From c8665318e6d866b96c1571f0879f4a47ab5c8b12 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 13 Oct 2010 15:17:20 -0500 Subject: [PATCH 001/343] binpac: Initial import of Bro's binpac subdirectory from SVN r7088. --- tools/binpac/TODO | 34 + tools/binpac/lib/Makefile.am | 8 + tools/binpac/lib/README | 3 + tools/binpac/lib/binpac.h.in | 142 ++ tools/binpac/lib/binpac_analyzer.h | 27 + tools/binpac/lib/binpac_buffer.cc | 465 +++++++ tools/binpac/lib/binpac_buffer.h | 148 +++ tools/binpac/lib/binpac_bytestring.cc | 24 + tools/binpac/lib/binpac_bytestring.h | 199 +++ tools/binpac/lib/binpac_exception.h | 112 ++ tools/binpac/lib/binpac_regex.cc | 0 tools/binpac/lib/binpac_regex.h | 43 + tools/binpac/patches/binpac-1.patch | 31 + tools/binpac/patches/binpac-2.patch | 97 ++ tools/binpac/patches/binpac-3.patch | 37 + tools/binpac/patches/binpac-4.patch | 12 + tools/binpac/patches/binpac-5.patch | 66 + tools/binpac/patches/binpac-6.patch | 28 + tools/binpac/patches/binpac-7.patch | 21 + tools/binpac/patches/binpac-8.patch | 190 +++ tools/binpac/patches/binpac-patch-doc.txt | 87 ++ .../patches/brosslbinpacanalyzerpatches.zip | Bin 0 -> 8025 bytes tools/binpac/patches/nadi-bittorrent.patch | 172 +++ tools/binpac/src/Makefile.am | 62 + tools/binpac/src/pac_action.cc | 119 ++ tools/binpac/src/pac_action.h | 74 ++ tools/binpac/src/pac_analyzer.cc | 358 ++++++ tools/binpac/src/pac_analyzer.h | 168 +++ tools/binpac/src/pac_array.cc | 700 ++++++++++ tools/binpac/src/pac_array.h | 92 ++ tools/binpac/src/pac_attr.cc | 57 + tools/binpac/src/pac_attr.h | 61 + tools/binpac/src/pac_btype.cc | 144 +++ tools/binpac/src/pac_btype.h | 52 + tools/binpac/src/pac_case.cc | 391 ++++++ tools/binpac/src/pac_case.h | 99 ++ tools/binpac/src/pac_cclass.h | 81 ++ tools/binpac/src/pac_common.h | 134 ++ tools/binpac/src/pac_conn.cc | 169 +++ tools/binpac/src/pac_conn.h | 34 + tools/binpac/src/pac_context.cc | 120 ++ tools/binpac/src/pac_context.h | 97 ++ tools/binpac/src/pac_cstr.cc | 127 ++ tools/binpac/src/pac_cstr.h | 23 + tools/binpac/src/pac_ctype.cc | 21 + tools/binpac/src/pac_ctype.h | 23 + tools/binpac/src/pac_datadep.cc | 76 ++ tools/binpac/src/pac_datadep.h | 71 + tools/binpac/src/pac_dataptr.cc | 66 + tools/binpac/src/pac_dataptr.h | 47 + tools/binpac/src/pac_dataunit.cc | 60 + tools/binpac/src/pac_dataunit.h | 49 + tools/binpac/src/pac_dbg.h | 14 + tools/binpac/src/pac_decl-inl.h | 6 + tools/binpac/src/pac_decl.cc | 191 +++ tools/binpac/src/pac_decl.h | 81 ++ tools/binpac/src/pac_embedded.cc | 82 ++ tools/binpac/src/pac_embedded.h | 42 + tools/binpac/src/pac_enum.cc | 70 + tools/binpac/src/pac_enum.h | 37 + tools/binpac/src/pac_exception.cc | 70 + tools/binpac/src/pac_exception.h | 97 ++ tools/binpac/src/pac_expr.cc | 1041 +++++++++++++++ tools/binpac/src/pac_expr.def | 34 + tools/binpac/src/pac_expr.h | 139 ++ tools/binpac/src/pac_externtype.def | 15 + tools/binpac/src/pac_exttype.cc | 76 ++ tools/binpac/src/pac_exttype.h | 47 + tools/binpac/src/pac_field.cc | 143 +++ tools/binpac/src/pac_field.h | 84 ++ tools/binpac/src/pac_flow.cc | 340 +++++ tools/binpac/src/pac_flow.h | 47 + tools/binpac/src/pac_func.cc | 123 ++ tools/binpac/src/pac_func.h | 68 + tools/binpac/src/pac_id.cc | 440 +++++++ tools/binpac/src/pac_id.h | 246 ++++ tools/binpac/src/pac_inputbuf.cc | 44 + tools/binpac/src/pac_inputbuf.h | 24 + tools/binpac/src/pac_let.cc | 167 +++ tools/binpac/src/pac_let.h | 48 + tools/binpac/src/pac_main.cc | 259 ++++ tools/binpac/src/pac_number.h | 21 + tools/binpac/src/pac_output.cc | 61 + tools/binpac/src/pac_output.h | 42 + tools/binpac/src/pac_param.cc | 70 + tools/binpac/src/pac_param.h | 48 + tools/binpac/src/pac_paramtype.cc | 289 +++++ tools/binpac/src/pac_paramtype.h | 62 + tools/binpac/src/pac_parse.yy | 1095 ++++++++++++++++ tools/binpac/src/pac_primitive.cc | 39 + tools/binpac/src/pac_primitive.h | 75 ++ tools/binpac/src/pac_record.cc | 680 ++++++++++ tools/binpac/src/pac_record.h | 169 +++ tools/binpac/src/pac_redef.cc | 173 +++ tools/binpac/src/pac_redef.h | 13 + tools/binpac/src/pac_regex.cc | 82 ++ tools/binpac/src/pac_regex.h | 41 + tools/binpac/src/pac_scan.ll | 356 ++++++ tools/binpac/src/pac_state.cc | 36 + tools/binpac/src/pac_state.h | 28 + tools/binpac/src/pac_strtype.cc | 425 ++++++ tools/binpac/src/pac_strtype.h | 82 ++ tools/binpac/src/pac_type.cc | 1137 +++++++++++++++++ tools/binpac/src/pac_type.def | 8 + tools/binpac/src/pac_type.h | 309 +++++ tools/binpac/src/pac_typedecl.cc | 409 ++++++ tools/binpac/src/pac_typedecl.h | 49 + tools/binpac/src/pac_utils.cc | 43 + tools/binpac/src/pac_utils.h | 17 + tools/binpac/src/pac_varfield.cc | 6 + tools/binpac/src/pac_varfield.h | 51 + tools/binpac/src/pac_withinput.cc | 80 ++ tools/binpac/src/pac_withinput.h | 38 + 113 files changed, 15630 insertions(+) create mode 100644 tools/binpac/TODO create mode 100644 tools/binpac/lib/Makefile.am create mode 100644 tools/binpac/lib/README create mode 100644 tools/binpac/lib/binpac.h.in create mode 100644 tools/binpac/lib/binpac_analyzer.h create mode 100644 tools/binpac/lib/binpac_buffer.cc create mode 100644 tools/binpac/lib/binpac_buffer.h create mode 100644 tools/binpac/lib/binpac_bytestring.cc create mode 100644 tools/binpac/lib/binpac_bytestring.h create mode 100644 tools/binpac/lib/binpac_exception.h create mode 100644 tools/binpac/lib/binpac_regex.cc create mode 100644 tools/binpac/lib/binpac_regex.h create mode 100644 tools/binpac/patches/binpac-1.patch create mode 100644 tools/binpac/patches/binpac-2.patch create mode 100644 tools/binpac/patches/binpac-3.patch create mode 100644 tools/binpac/patches/binpac-4.patch create mode 100644 tools/binpac/patches/binpac-5.patch create mode 100644 tools/binpac/patches/binpac-6.patch create mode 100644 tools/binpac/patches/binpac-7.patch create mode 100644 tools/binpac/patches/binpac-8.patch create mode 100644 tools/binpac/patches/binpac-patch-doc.txt create mode 100644 tools/binpac/patches/brosslbinpacanalyzerpatches.zip create mode 100644 tools/binpac/patches/nadi-bittorrent.patch create mode 100644 tools/binpac/src/Makefile.am create mode 100644 tools/binpac/src/pac_action.cc create mode 100644 tools/binpac/src/pac_action.h create mode 100644 tools/binpac/src/pac_analyzer.cc create mode 100644 tools/binpac/src/pac_analyzer.h create mode 100644 tools/binpac/src/pac_array.cc create mode 100644 tools/binpac/src/pac_array.h create mode 100644 tools/binpac/src/pac_attr.cc create mode 100644 tools/binpac/src/pac_attr.h create mode 100644 tools/binpac/src/pac_btype.cc create mode 100644 tools/binpac/src/pac_btype.h create mode 100644 tools/binpac/src/pac_case.cc create mode 100644 tools/binpac/src/pac_case.h create mode 100644 tools/binpac/src/pac_cclass.h create mode 100644 tools/binpac/src/pac_common.h create mode 100644 tools/binpac/src/pac_conn.cc create mode 100644 tools/binpac/src/pac_conn.h create mode 100644 tools/binpac/src/pac_context.cc create mode 100644 tools/binpac/src/pac_context.h create mode 100644 tools/binpac/src/pac_cstr.cc create mode 100644 tools/binpac/src/pac_cstr.h create mode 100644 tools/binpac/src/pac_ctype.cc create mode 100644 tools/binpac/src/pac_ctype.h create mode 100644 tools/binpac/src/pac_datadep.cc create mode 100644 tools/binpac/src/pac_datadep.h create mode 100644 tools/binpac/src/pac_dataptr.cc create mode 100644 tools/binpac/src/pac_dataptr.h create mode 100644 tools/binpac/src/pac_dataunit.cc create mode 100644 tools/binpac/src/pac_dataunit.h create mode 100644 tools/binpac/src/pac_dbg.h create mode 100644 tools/binpac/src/pac_decl-inl.h create mode 100644 tools/binpac/src/pac_decl.cc create mode 100644 tools/binpac/src/pac_decl.h create mode 100644 tools/binpac/src/pac_embedded.cc create mode 100644 tools/binpac/src/pac_embedded.h create mode 100644 tools/binpac/src/pac_enum.cc create mode 100644 tools/binpac/src/pac_enum.h create mode 100644 tools/binpac/src/pac_exception.cc create mode 100644 tools/binpac/src/pac_exception.h create mode 100644 tools/binpac/src/pac_expr.cc create mode 100644 tools/binpac/src/pac_expr.def create mode 100644 tools/binpac/src/pac_expr.h create mode 100644 tools/binpac/src/pac_externtype.def create mode 100644 tools/binpac/src/pac_exttype.cc create mode 100644 tools/binpac/src/pac_exttype.h create mode 100644 tools/binpac/src/pac_field.cc create mode 100644 tools/binpac/src/pac_field.h create mode 100644 tools/binpac/src/pac_flow.cc create mode 100644 tools/binpac/src/pac_flow.h create mode 100644 tools/binpac/src/pac_func.cc create mode 100644 tools/binpac/src/pac_func.h create mode 100644 tools/binpac/src/pac_id.cc create mode 100644 tools/binpac/src/pac_id.h create mode 100644 tools/binpac/src/pac_inputbuf.cc create mode 100644 tools/binpac/src/pac_inputbuf.h create mode 100644 tools/binpac/src/pac_let.cc create mode 100644 tools/binpac/src/pac_let.h create mode 100644 tools/binpac/src/pac_main.cc create mode 100644 tools/binpac/src/pac_number.h create mode 100644 tools/binpac/src/pac_output.cc create mode 100644 tools/binpac/src/pac_output.h create mode 100644 tools/binpac/src/pac_param.cc create mode 100644 tools/binpac/src/pac_param.h create mode 100644 tools/binpac/src/pac_paramtype.cc create mode 100644 tools/binpac/src/pac_paramtype.h create mode 100644 tools/binpac/src/pac_parse.yy create mode 100644 tools/binpac/src/pac_primitive.cc create mode 100644 tools/binpac/src/pac_primitive.h create mode 100644 tools/binpac/src/pac_record.cc create mode 100644 tools/binpac/src/pac_record.h create mode 100644 tools/binpac/src/pac_redef.cc create mode 100644 tools/binpac/src/pac_redef.h create mode 100644 tools/binpac/src/pac_regex.cc create mode 100644 tools/binpac/src/pac_regex.h create mode 100644 tools/binpac/src/pac_scan.ll create mode 100644 tools/binpac/src/pac_state.cc create mode 100644 tools/binpac/src/pac_state.h create mode 100644 tools/binpac/src/pac_strtype.cc create mode 100644 tools/binpac/src/pac_strtype.h create mode 100644 tools/binpac/src/pac_type.cc create mode 100644 tools/binpac/src/pac_type.def create mode 100644 tools/binpac/src/pac_type.h create mode 100644 tools/binpac/src/pac_typedecl.cc create mode 100644 tools/binpac/src/pac_typedecl.h create mode 100644 tools/binpac/src/pac_utils.cc create mode 100644 tools/binpac/src/pac_utils.h create mode 100644 tools/binpac/src/pac_varfield.cc create mode 100644 tools/binpac/src/pac_varfield.h create mode 100644 tools/binpac/src/pac_withinput.cc create mode 100644 tools/binpac/src/pac_withinput.h diff --git a/tools/binpac/TODO b/tools/binpac/TODO new file mode 100644 index 0000000000..4b2833f224 --- /dev/null +++ b/tools/binpac/TODO @@ -0,0 +1,34 @@ +Big features +* Variable context (xid, call in RPC)? -- no variable context +* Helpers +* Connection states and actions +* Case and analyzer redef +* &also withinput +* Explicit analyzer context (interface + instantiation) "withcontext" ++ Interface with C++ and Bro (events, extern, weird) ++ Incremental input ++ ASCII protocols ++ Reassembly +- Dealing with exceptions +- Dependency analysis to save parsing time on unused fields +- Performance measurement + +Small features +* Restructure the code: break up pac.{h,cc} +* ref counting (to keep certain structures) +* analyzer context as a parameter of class +* &autolength +* find a better name for "analyzer_context" ("analcxt", "context", "analyzer") $context +* &if +* &autolength (now &restofdata) +* Use vector<> instead of array<>? +* set end_of_data when &length = ... +- make the `default' case mandatory? +- &inline +- &warn and &check? (follow &if) +- typedef? + +Binpac 1 +- create a namespace for each .pac file +- type equivalence +- byteorder() for every type? diff --git a/tools/binpac/lib/Makefile.am b/tools/binpac/lib/Makefile.am new file mode 100644 index 0000000000..7ff8dca88f --- /dev/null +++ b/tools/binpac/lib/Makefile.am @@ -0,0 +1,8 @@ +## Process this file with automake to produce Makefile.in + +noinst_LIBRARIES = libbinpac.a + +libbinpac_a_SOURCES = \ + binpac_buffer.cc binpac_bytestring.cc \ + binpac.h binpac_analyzer.h binpac_buffer.h \ + binpac_bytestring.h binpac_exception.h binpac_regex.h diff --git a/tools/binpac/lib/README b/tools/binpac/lib/README new file mode 100644 index 0000000000..c57ca2ebab --- /dev/null +++ b/tools/binpac/lib/README @@ -0,0 +1,3 @@ +This directory contains a library needed by generated C++ code from +binpac. Note that the library is not needed by the binpac compiler +itself. diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in new file mode 100644 index 0000000000..920a699409 --- /dev/null +++ b/tools/binpac/lib/binpac.h.in @@ -0,0 +1,142 @@ +// $Id: binpac.h,v 1.1.4.2 2006/06/02 15:13:13 rpang Exp $ +// Do not edit binpac.h, edit binpac.h.in instead! + +#ifndef binpac_h +#define binpac_h + +#include + +@HOST_BIGENDIAN@ +#ifdef HOST_BIGENDIAN +# define HOST_BYTEORDER bigendian +#else +# define HOST_BYTEORDER littleendian +#endif + +#include +#include +#include +#include +#include + +#define BINPAC_ASSERT(x) assert(x) + +using namespace std; + +namespace binpac { + +const int bigendian = 0; +const int littleendian = 1; +const int unspecified_byteorder = -1; + +#ifndef pac_type_defs +#define pac_type_defs + +typedef char int8; +typedef short int16; +typedef long int32; +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef void *nullptr; +typedef void *voidptr; +typedef uint8 *byteptr; +typedef const uint8 *const_byteptr; +typedef const char *const_charptr; + +#if @SIZEOF_UNSIGNED_INT@ != 4 +#error "unexpected size of unsigned int" +#endif + +#endif /* pac_type_defs */ + +/* Handling byte order */ + +namespace { + +inline int16 pac_swap(int16 x) + { + return (x >> 8) | ((x & 0xff) << 8); + } + +inline uint16 pac_swap(uint16 x) + { + return (x >> 8) | ((x & 0xff) << 8); + } + +inline int32 pac_swap(int32 x) + { + return (x >> 24) | + ((x & 0xff0000) >> 8) | + ((x & 0xff00) << 8) | + ((x & 0xff) << 24); + } + +inline uint32 pac_swap(uint32 x) + { + return (x >> 24) | + ((x & 0xff0000) >> 8) | + ((x & 0xff00) << 8) | + ((x & 0xff) << 24); + } + +#define FixByteOrder(byteorder, x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap(x)) + +template +inline T UnMarshall(const u_char *data, int byteorder) + { + T result = 0; + for ( int i = 0; i < (int) sizeof(T); ++i ) + result = ( result << 8 ) | + data[byteorder == bigendian ? i : sizeof(T) - 1 - i]; + return result; + } + +inline const char* do_fmt(const char* format, va_list ap) + { + static char buf[1024]; + vsnprintf(buf, sizeof(buf), format, ap); + return buf; + } + +inline string strfmt(const char* format, ...) + { + va_list ap; + va_start(ap, format); + const char* r = do_fmt(format, ap); + va_end(ap); + return string(r); + } + +} // anonymous namespace + +#define binpac_fmt(x...) strfmt(x).c_str() + +class RefCount +{ +public: + RefCount() { count = 1; } + void Ref() { ++count; } + int Unref() { BINPAC_ASSERT(count > 0); return --count; } + +private: + int count; +}; + +namespace { + inline void Unref(RefCount *x) + { + if ( x && x->Unref() <= 0 ) + delete x; + } +} // anonymous namespace + +} // namespace binpac + +#include "binpac_analyzer.h" +#include "binpac_buffer.h" +#include "binpac_bytestring.h" +#include "binpac_exception.h" +#include "binpac_regex.h" + +#endif /* binpac_h */ diff --git a/tools/binpac/lib/binpac_analyzer.h b/tools/binpac/lib/binpac_analyzer.h new file mode 100644 index 0000000000..b9228da5de --- /dev/null +++ b/tools/binpac/lib/binpac_analyzer.h @@ -0,0 +1,27 @@ +#ifndef binpac_an_h +#define binpac_an_h + +namespace binpac { + +// TODO: Add the Done() function + +// The interface for a connection analyzer +class ConnectionAnalyzer { +public: + virtual ~ConnectionAnalyzer() {} + virtual void NewData(bool is_orig, + const u_char *begin_of_data, + const u_char *end_of_data) = 0; +}; + +// The interface for a flow analyzer +class FlowAnalyzer { +public: + virtual ~FlowAnalyzer() {} + virtual void NewData(const u_char *begin_of_data, + const u_char *end_of_data) = 0; +}; + +} // namespace binpac + +#endif // binpac_an_h diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc new file mode 100644 index 0000000000..1b12b58eab --- /dev/null +++ b/tools/binpac/lib/binpac_buffer.cc @@ -0,0 +1,465 @@ +#include +#include +#include // for memcpy + +#define binpac_regex_h + +#include "binpac.h" +#include "binpac_buffer.h" + +namespace binpac { + +extern double network_time(); + +namespace { + const u_char CR = '\r'; + const u_char LF = '\n'; +} + +FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) + { + buffer_length_ = 0; + buffer_ = 0; + + orig_data_begin_ = 0; + orig_data_end_ = 0; + + linebreak_style_ = linebreak_style; + ResetLineState(); + + mode_ = UNKNOWN_MODE; + frame_length_ = 0; + chunked_ = false; + + data_seq_at_orig_data_end_ = 0; + eof_ = false; + have_pending_request_ = false; + + buffer_n_ = 0; + + NewMessage(); + } + +FlowBuffer::~FlowBuffer() + { + if ( buffer_ ) + free(buffer_); + } + +void FlowBuffer::NewMessage() + { + BINPAC_ASSERT(frame_length_ >= 0); + + int bytes_to_advance = 0; + if ( buffer_n_ == 0 ) + { + switch ( mode_ ) + { + case LINE_MODE: + bytes_to_advance = (frame_length_ + + (linebreak_style_ == STRICT_CRLF ? + 2 : 1)); + break; + case FRAME_MODE: + bytes_to_advance = frame_length_; + break; + case UNKNOWN_MODE: + break; + } + } + + orig_data_begin_ += bytes_to_advance; + BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_); + + buffer_n_ = 0; + message_complete_ = false; + } + +void FlowBuffer::ResetLineState() + { + switch ( linebreak_style_ ) + { + case CR_OR_LF: + state_ = CR_OR_LF_0; + break; + case STRICT_CRLF: + state_ = STRICT_CRLF_0; + break; + default: + BINPAC_ASSERT(0); + break; + } + } + +void FlowBuffer::ExpandBuffer(int length) + { + if ( buffer_length_ >= length ) + return; + // So length > 0 + if ( length < 512 ) + length = 512; + + if ( length < buffer_length_ * 2 ) + length = buffer_length_ * 2; + + // Allocate a new buffer and copy the existing contents + buffer_length_ = length; + u_char *new_buf = (u_char *) realloc(buffer_, buffer_length_); + BINPAC_ASSERT(new_buf); +#if 0 + u_char* new_buf = new u_char[buffer_length_]; + if ( buffer_ && buffer_n_ > 0 ) + memcpy(new_buf, buffer_, buffer_n_); + delete [] buffer_; +#endif + buffer_ = new_buf; + } + +void FlowBuffer::NewLine() + { + FlowBuffer::NewMessage(); + mode_ = LINE_MODE; + frame_length_ = 0; + chunked_ = false; + have_pending_request_ = true; + if ( state_ == FRAME_0 ) + ResetLineState(); + MarkOrCopyLine(); + } + +void FlowBuffer::NewFrame(int frame_length, bool chunked) + { + FlowBuffer::NewMessage(); + mode_ = FRAME_MODE; + frame_length_ = frame_length; + chunked_ = chunked; + have_pending_request_ = true; + MarkOrCopyFrame(); + } + +void FlowBuffer::GrowFrame(int length) + { + BINPAC_ASSERT(frame_length_ >= 0); + if ( length <= frame_length_ ) + return; + BINPAC_ASSERT(! chunked_ || frame_length_ == 0); + mode_ = FRAME_MODE; + frame_length_ = length; + MarkOrCopyFrame(); + } + +void FlowBuffer::DiscardData() + { + mode_ = UNKNOWN_MODE; + message_complete_ = false; + have_pending_request_ = false; + orig_data_begin_ = orig_data_end_ = 0; + + buffer_n_ = 0; + frame_length_ = 0; + } + +void FlowBuffer::set_eof() + { + // fprintf(stderr, "EOF\n"); + eof_ = true; + if ( chunked_ ) + frame_length_ = orig_data_end_ - orig_data_begin_; + if ( frame_length_ < 0 ) + frame_length_ = 0; + } + +void FlowBuffer::NewData(const_byteptr begin, const_byteptr end) + { + BINPAC_ASSERT(begin <= end); + + ClearPreviousData(); + + BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || + orig_data_begin_ == orig_data_end_); + + orig_data_begin_ = begin; + orig_data_end_ = end; + data_seq_at_orig_data_end_ += (end - begin); + + MarkOrCopy(); + } + +void FlowBuffer::MarkOrCopy() + { + if ( ! message_complete_ ) + { + switch ( mode_ ) + { + case LINE_MODE: + MarkOrCopyLine(); + break; + + case FRAME_MODE: + MarkOrCopyFrame(); + break; + + default: + break; + } + } + } + +void FlowBuffer::ClearPreviousData() + { + // All previous data must have been processed or buffered already + if ( orig_data_begin_ < orig_data_end_ ) + { + BINPAC_ASSERT(buffer_n_ == 0); + if ( chunked_ ) + { + if ( frame_length_ > 0 ) + { + frame_length_ -= + (orig_data_end_ - orig_data_begin_); + } + orig_data_begin_ = orig_data_end_; + } + } + } + +void FlowBuffer::NewGap(int length) + { + ClearPreviousData(); + + if ( chunked_ && frame_length_ >= 0 ) + { + frame_length_ -= length; + if ( frame_length_ < 0 ) + frame_length_ = 0; + } + + orig_data_begin_ = orig_data_end_ = 0; + MarkOrCopy(); + } + +void FlowBuffer::MarkOrCopyLine() + { + switch ( linebreak_style_ ) + { + case CR_OR_LF: + MarkOrCopyLine_CR_OR_LF(); + break; + case STRICT_CRLF: + MarkOrCopyLine_STRICT_CRLF(); + break; + default: + BINPAC_ASSERT(0); + break; + } + } + +/* +Finite state automaton for CR_OR_LF: +(!--line is complete, *--add to buffer) + +CR_OR_LF_0: + CR: CR_OR_LF_1 ! + LF: CR_OR_LF_0 ! + .: CR_OR_LF_0 * + +CR_OR_LF_1: + CR: CR_OR_LF_1 ! + LF: CR_OR_LF_0 + .: CR_OR_LF_0 * +*/ + +void FlowBuffer::MarkOrCopyLine_CR_OR_LF() + { + if ( state_ == CR_OR_LF_1 && + orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF ) + { + state_ = CR_OR_LF_0; + ++orig_data_begin_; + } + + const_byteptr data; + for ( data = orig_data_begin_; data < orig_data_end_; ++data ) + { + switch ( *data ) + { + case CR: + state_ = CR_OR_LF_1; + goto found_end_of_line; + + case LF: + // state_ = CR_OR_LF_0; + goto found_end_of_line; + + default: + // state_ = CR_OR_LF_0; + break; + } + } + + AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); + return; + +found_end_of_line: + if ( buffer_n_ == 0 ) + { + frame_length_ = data - orig_data_begin_; + } + else + { + AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); + // But eliminate the last CR or LF + --buffer_n_; + } + message_complete_ = true; + +#if DEBUG_FLOW_BUFFER + fprintf(stderr, "%.6f Line complete: [%s]\n", + network_time(), + string((const char *) begin(), (const char *) end()).c_str()); +#endif + } + +/* +Finite state automaton and STRICT_CRLF: +(!--line is complete, *--add to buffer) + +STRICT_CRLF_0: + CR: STRICT_CRLF_1 * + LF: STRICT_CRLF_0 * + .: STRICT_CRLF_0 * + +STRICT_CRLF_1: + CR: STRICT_CRLF_1 * + LF: STRICT_CRLF_0 ! (--buffer_n_) + .: STRICT_CRLF_0 * +*/ + +void FlowBuffer::MarkOrCopyLine_STRICT_CRLF() + { + const_byteptr data; + for ( data = orig_data_begin_; data < orig_data_end_; ++data ) + { + switch ( *data ) + { + case CR: + state_ = STRICT_CRLF_1; + break; + + case LF: + if ( state_ == STRICT_CRLF_1 ) + { + state_ = STRICT_CRLF_0; + goto found_end_of_line; + } + break; + + default: + state_ = STRICT_CRLF_0; + break; + } + } + + AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); + return; + +found_end_of_line: + if ( buffer_n_ == 0 ) + { + frame_length_ = data - 1 - orig_data_begin_; + } + else + { + AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); + // Pop the preceding CR and LF from the buffer + buffer_n_ -= 2; + } + + message_complete_ = true; + +#if DEBUG_FLOW_BUFFER + fprintf(stderr, "%.6f Line complete: [%s]\n", + network_time(), + string((const char *) begin(), (const char *) end()).c_str()); +#endif + } + +// Invariants: +// +// When buffer_n_ == 0: +// Frame = [orig_data_begin_..(orig_data_begin_ + frame_length_)] +// +// When buffer_n_ > 0: +// Frame = [0..buffer_n_][orig_data_begin_..] + +void FlowBuffer::MarkOrCopyFrame() + { + if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && + orig_data_begin_ < orig_data_end_ ) + { + // Skip the lingering LF + if ( *orig_data_begin_ == LF ) + { + ++orig_data_begin_; + } + state_ = FRAME_0; + } + + if ( buffer_n_ == 0 ) + { + // If there is enough data + if ( frame_length_ >= 0 && + orig_data_end_ - orig_data_begin_ >= frame_length_ ) + { + // Do nothing except setting the message complete flag + message_complete_ = true; + } + else + { + if ( ! chunked_ ) + { + AppendToBuffer(orig_data_begin_, + orig_data_end_ - orig_data_begin_); + } + message_complete_ = false; + } + } + else + { + BINPAC_ASSERT(!chunked_); + int bytes_to_copy = orig_data_end_ - orig_data_begin_; + message_complete_ = false; + if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ ) + { + bytes_to_copy = frame_length_ - buffer_n_; + message_complete_ = true; + } + AppendToBuffer(orig_data_begin_, bytes_to_copy); + } + +#if DEBUG_FLOW_BUFFER + if ( message_complete_ ) + { + fprintf(stderr, "%.6f frame complete: [%s]\n", + network_time(), + string((const char *) begin(), + (const char *) end()).c_str()); + } +#endif + } + +void FlowBuffer::AppendToBuffer(const_byteptr data, int len) + { + if ( len <= 0 ) + return; + + BINPAC_ASSERT(! chunked_); + ExpandBuffer(buffer_n_ + len); + memcpy(buffer_ + buffer_n_, data, len); + buffer_n_ += len; + + orig_data_begin_ += len; + BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_); + } + +} // namespace binpac diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h new file mode 100644 index 0000000000..2eb197e7b9 --- /dev/null +++ b/tools/binpac/lib/binpac_buffer.h @@ -0,0 +1,148 @@ +#ifndef binpac_buffer_h +#define binpac_buffer_h + +#include +#include "binpac.h" + +namespace binpac { + +class FlowBuffer { +public: + enum LineBreakStyle { + CR_OR_LF, // CR or LF or CRLF + STRICT_CRLF, // CR followed by LF + CR_LF_NUL, // CR or LF or CR-LF or CR-NUL + }; + + FlowBuffer(LineBreakStyle linebreak_style = CR_OR_LF); + virtual ~FlowBuffer(); + + void NewData(const_byteptr begin, const_byteptr end); + void NewGap(int length); + + // Discard unprocessed data + void DiscardData(); + + // Whether there is enough data for the frame + bool ready() const{ return message_complete_ || mode_ == UNKNOWN_MODE; } + + inline const_byteptr begin() const + { + BINPAC_ASSERT(ready()); + return ( buffer_n_ == 0 ) ? + orig_data_begin_ : buffer_; + } + + inline const_byteptr end() const + { + BINPAC_ASSERT(ready()); + if ( buffer_n_ == 0 ) + { + BINPAC_ASSERT(frame_length_ >= 0); + const_byteptr end = orig_data_begin_ + frame_length_; + BINPAC_ASSERT(end <= orig_data_end_); + return end; + } + else + return buffer_ + buffer_n_; + } + + inline int data_length() const + { + if ( buffer_n_ > 0 ) + return buffer_n_; + + if ( frame_length_ < 0 || + orig_data_begin_ + frame_length_ > orig_data_end_ ) + return orig_data_end_ - orig_data_begin_; + else + return frame_length_; + } + + inline bool data_available() const + { + return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; + } + + void NewLine(); + // A negative frame_length represents a frame till EOF + void NewFrame(int frame_length, bool chunked_); + void GrowFrame(int new_frame_length); + + int data_seq() const + { + int data_seq_at_orig_data_begin = + data_seq_at_orig_data_end_ - + (orig_data_end_ - orig_data_begin_); + if ( buffer_n_ > 0 ) + return data_seq_at_orig_data_begin; + else + return data_seq_at_orig_data_begin + data_length(); + } + bool eof() const { return eof_; } + void set_eof(); + + bool have_pending_request() const { return have_pending_request_; } + +protected: + // Reset the buffer for a new message + void NewMessage(); + + void ClearPreviousData(); + + // Expand the buffer to at least bytes. If there + // are contents in the existing buffer, copy them to the new + // buffer. + void ExpandBuffer(int length); + + // Reset line state when transit from frame mode to line mode. + void ResetLineState(); + + void AppendToBuffer(const_byteptr data, int len); + + // MarkOrCopy{Line,Frame} sets message_complete_ and + // marks begin/end pointers if a line/frame is complete, + // otherwise it clears message_complete_ and copies all + // the original data to the buffer. + // + void MarkOrCopy(); + void MarkOrCopyLine(); + void MarkOrCopyFrame(); + + void MarkOrCopyLine_CR_OR_LF(); + void MarkOrCopyLine_STRICT_CRLF(); + + int buffer_n_; // number of bytes in the buffer + int buffer_length_; // size of the buffer + u_char *buffer_; + bool message_complete_; + int frame_length_; + bool chunked_; + const_byteptr orig_data_begin_, orig_data_end_; + + LineBreakStyle linebreak_style_; + + enum { + UNKNOWN_MODE, + LINE_MODE, + FRAME_MODE, + } mode_; + + enum { + CR_OR_LF_0, + CR_OR_LF_1, + STRICT_CRLF_0, + STRICT_CRLF_1, + FRAME_0, + } state_; + + int data_seq_at_orig_data_end_; + bool eof_; + bool have_pending_request_; +}; + +typedef FlowBuffer *flow_buffer_t; + +} // namespace binpac + +#endif // binpac_buffer_h diff --git a/tools/binpac/lib/binpac_bytestring.cc b/tools/binpac/lib/binpac_bytestring.cc new file mode 100644 index 0000000000..b74fe369b1 --- /dev/null +++ b/tools/binpac/lib/binpac_bytestring.cc @@ -0,0 +1,24 @@ +#define binpac_regex_h + +#include +#include "binpac_bytestring.h" + +namespace binpac +{ + +std::string std_string(bytestring const *s) + { + return std::string((const char *) s->begin(), (const char *) s->end()); + } + +int bytestring_to_int(bytestring const *s) + { + return atoi((const char *) s->begin()); + } + +double bytestring_to_double(bytestring const *s) + { + return atof((const char *) s->begin()); + } + +} // namespace binpac diff --git a/tools/binpac/lib/binpac_bytestring.h b/tools/binpac/lib/binpac_bytestring.h new file mode 100644 index 0000000000..13d1879aed --- /dev/null +++ b/tools/binpac/lib/binpac_bytestring.h @@ -0,0 +1,199 @@ +#ifndef binpac_bytestring_h +#define binpac_bytestring_h + +#include +#include +#include "binpac.h" + +namespace binpac +{ + +template class datastring; + +template +class const_datastring +{ +public: + const_datastring() + : begin_(0), end_(0) + { + } + + const_datastring(T const *data, int length) + : begin_(data), end_(data + length) + { + } + + const_datastring(const T *begin, const T *end) + : begin_(begin), end_(end) + { + } + + const_datastring(datastring const &s) + : begin_(s.begin()), end_(s.end()) + { + } + + void init(const T *data, int length) + { + begin_ = data; + end_ = data + length; + } + + T const *begin() const { return begin_; } + T const *end() const { return end_; } + int length() const { return end_ - begin_; } + + T const &operator[](int index) const + { + return begin()[index]; + } + + bool operator==(const_datastring const &s) + { + if ( length() != s.length() ) + return false; + return memcmp((const void *) begin(), (const void *) s.begin(), + sizeof(T) * length()) == 0; + } + + void set_begin(T const *begin) { begin_ = begin; } + void set_end(T const *end) { end_ = end; } + +private: + T const *begin_; + T const *end_; +}; + +typedef const_datastring const_bytestring; + +template +class datastring +{ +public: + datastring() + { + clear(); + } + + datastring(T *data, int len) + { + set(data, len); + } + + datastring(T const *begin, T const *end) + { + set_const(begin, end - begin); + } + + datastring(datastring const &x) + : data_(x.data()), length_(x.length()) + { + } + + explicit datastring(const_datastring const &x) + { + set_const(x.begin(), x.length()); + } + + datastring const &operator=(datastring const &x) + { + BINPAC_ASSERT(!data_); + set(x.data(), x.length()); + return *this; + } + + void init(T const *begin, int length) + { + BINPAC_ASSERT(!data_); + set_const(begin, length); + } + + void clear() + { + data_ = 0; length_ = 0; + } + + void free() + { + if ( data_ ) + delete [] data_; + clear(); + } + + void clone() + { + set_const(begin(), length()); + } + + datastring const &operator=(const_datastring const &x) + { + BINPAC_ASSERT(!data_); + set_const(x.begin(), x.length()); + return *this; + } + + T const &operator[](int index) const + { + return begin()[index]; + } + + T *data() const { return data_; } + int length() const { return length_; } + + T const *begin() const { return data_; } + T const *end() const { return data_ + length_; } + +private: + void set(T *data, int len) + { + data_ = data; + length_ = len; + } + + void set_const(T const *data, int len) + { + length_ = len; + data_ = new T[len + 1]; + memcpy(data_, data, sizeof(T) * len); + data_[len] = 0; + } + + T * data_; + int length_; +}; + +typedef datastring bytestring; + +inline const char *c_str(bytestring const &s) + { + return (const char *) s.begin(); + } + +inline std::string std_str(const_bytestring const &s) + { + return std::string((const char *) s.begin(), (const char *) s.end()); + } + +inline bool operator==(bytestring const &s1, const char *s2) + { + return strcmp(c_str(s1), s2) == 0; + } + +inline void get_pointers(const_bytestring const &s, + uint8 const **pbegin, uint8 const **pend) + { + *pbegin = s.begin(); + *pend = s.end(); + } + +inline void get_pointers(bytestring const *s, + uint8 const **pbegin, uint8 const **pend) + { + *pbegin = s->begin(); + *pend = s->end(); + } + +} // namespace binpac + +#endif // binpac_bytestring_h diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h new file mode 100644 index 0000000000..3feda3d69d --- /dev/null +++ b/tools/binpac/lib/binpac_exception.h @@ -0,0 +1,112 @@ +#ifndef binpac_exception_h +#define binpac_exception_h + +namespace binpac { + +class Exception +{ +public: + Exception(const char* m = 0) + : msg_("binpac exception: ") + { + if ( m ) + append(m); + // abort(); + } + + void append(string m) { msg_ += m; } + string msg() const { return msg_; } + const char* c_msg() const { return msg().c_str(); } + +protected: + string msg_; +}; + +class ExceptionOutOfBound : public Exception +{ +public: + ExceptionOutOfBound(const char* where, int len_needed, int len_given) + { + append(binpac_fmt("out_of_bound: %s: %d > %d", + where, len_needed, len_given)); + } +}; + +class ExceptionInvalidCase : public Exception +{ +public: + ExceptionInvalidCase(const char* location, + int index, + const char *expected) + : location_(location), + index_(index), + expected_(expected) + { + append(binpac_fmt("invalid case: %s: %d (%s)", + location, index, expected)); + } + +protected: + const char* location_; + int index_; + string expected_; +}; + +class ExceptionInvalidCaseIndex : public Exception +{ +public: + ExceptionInvalidCaseIndex(const char* location, + int index) + : location_(location), + index_(index) + { + append(binpac_fmt("invalid index for case: %s: %d", + location, index)); + } + +protected: + const char* location_; + int index_; +}; + +class ExceptionInvalidOffset : public Exception +{ +public: + ExceptionInvalidOffset(const char* location, + int min_offset, int offset) + : location_(location), + min_offset_(min_offset), offset_(offset) + { + append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", + location, min_offset, offset)); + } + +protected: + const char* location_; + int min_offset_, offset_; +}; + +class ExceptionStringMismatch : public Exception +{ +public: + ExceptionStringMismatch(const char* location, + const char *expected, const char *actual_data) + { + append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"", + location, expected, actual_data)); + } +}; + +class ExceptionInvalidStringLength : public Exception +{ +public: + ExceptionInvalidStringLength(const char* location, int len) + { + append(binpac_fmt("invalid length string: %s: %d", + location, len)); + } +}; + +} + +#endif // binpac_exception_h diff --git a/tools/binpac/lib/binpac_regex.cc b/tools/binpac/lib/binpac_regex.cc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h new file mode 100644 index 0000000000..b41e6dbb90 --- /dev/null +++ b/tools/binpac/lib/binpac_regex.h @@ -0,0 +1,43 @@ +#ifndef binpac_regex_h +#define binpac_regex_h + +#include "binpac.h" +#include "RE.h" + +class RE_Matcher; + +namespace binpac +{ + +class RegExMatcher { +public: + RegExMatcher(const char *pattern) + : pattern_(pattern) + { + re_matcher_ = 0; + } + + ~RegExMatcher() + { + delete re_matcher_; + } + + // Returns the length of longest match, or -1 on mismatch. + int MatchPrefix(const_byteptr data, int len) + { + if ( ! re_matcher_ ) + { + re_matcher_ = new RE_Matcher(pattern_.c_str()); + re_matcher_->Compile(); + } + return re_matcher_->MatchPrefix(data, len); + } + +private: + string pattern_; + RE_Matcher *re_matcher_; +}; + +} // namespace binpac + +#endif // binpac_regex_h diff --git a/tools/binpac/patches/binpac-1.patch b/tools/binpac/patches/binpac-1.patch new file mode 100644 index 0000000000..ade4e41065 --- /dev/null +++ b/tools/binpac/patches/binpac-1.patch @@ -0,0 +1,31 @@ +diff -urN bro-1.2.1-orig/src/binpac/pac_expr.cc bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc +--- bro-1.2.1-orig/src/binpac/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700 +@@ -776,6 +776,27 @@ + } + break; + ++ case EXPR_CALLARGS: ++ { ++ mhs = 0; ++ if ( args_ ) ++ for ( uint i = 0; i < args_->size(); ++i ) ++ mhs = mhs_max(mhs, args_->at(i)->MinimalHeaderSize(env)); ++ } ++ break; ++ case EXPR_CASE: ++ { ++ mhs = operand_[0]->MinimalHeaderSize(env); ++ for ( uint i = 0; i < cases_->size(); ++i ) ++ { ++ CaseExpr * ce = cases_->at(i); ++ if ( ce->index() ) ++ for ( uint j = 0; j < ce->index()->size(); ++j ) ++ mhs = mhs_max(mhs, ce->index()->at(j)->MinimalHeaderSize(env)); ++ mhs = mhs_max(mhs, ce->value()->MinimalHeaderSize(env)); ++ } ++ } ++ break; + default: + // Evaluate every operand by default + mhs = 0; diff --git a/tools/binpac/patches/binpac-2.patch b/tools/binpac/patches/binpac-2.patch new file mode 100644 index 0000000000..378c33027a --- /dev/null +++ b/tools/binpac/patches/binpac-2.patch @@ -0,0 +1,97 @@ +diff -urN bro-1.2.1-orig/src/binpac/pac_expr.cc bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc +--- bro-1.2.1-orig/src/binpac/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700 +@@ -245,6 +245,12 @@ + out_cc->println("%s %s;", + val_type->DataTypeStr().c_str(), + env->LValue(val_var)); ++ ++ // force evaluation of IDs appearing in case stmt ++ operand_[0]->ForceIDEval(out_cc, env); ++ foreach(i, CaseExprList, cases_) ++ (*i)->value()->ForceIDEval(out_cc, env); ++ + out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); + + out_cc->inc_indent(); +@@ -386,6 +392,49 @@ + } + } + ++void Expr::ForceIDEval(Output* out_cc, Env* env) ++ { ++ switch ( expr_type_ ) ++ { ++ case EXPR_NUM: ++ case EXPR_SIZEOF: ++ case EXPR_OFFSETOF: ++ break; ++ ++ case EXPR_ID: ++ if ( ! env->Evaluated(id_) ) ++ env->Evaluate(out_cc, id_); ++ break; ++ ++ case EXPR_MEMBER: ++ operand_[0]->ForceIDEval(out_cc, env); ++ break; ++ ++ case EXPR_CALLARGS: ++ { ++ foreach(i, ExprList, args_) ++ (*i)->ForceIDEval(out_cc, env); ++ } ++ break; ++ ++ case EXPR_CASE: ++ { ++ operand_[0]->ForceIDEval(out_cc, env); ++ foreach(i, CaseExprList, cases_) ++ (*i)->value()->ForceIDEval(out_cc, env); ++ } ++ break; ++ ++ default: ++ // Evaluate every operand by default ++ for ( int i = 0; i < 3; ++i ) ++ if ( operand_[i] ) ++ operand_[i]->ForceIDEval(out_cc, env); ++ break; ++ } ++ } ++ ++ + const char* Expr::EvalExpr(Output* out_cc, Env* env) + { + GenEval(out_cc, env); +diff -urN bro-1.2.1-orig/src/binpac/pac_expr.h bro-1.2.1-ssl-binpac/src/binpac/pac_expr.h +--- bro-1.2.1-orig/src/binpac/pac_expr.h 2006-07-26 15:02:39.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_expr.h 2007-05-04 14:16:31.624287000 -0700 +@@ -56,6 +56,11 @@ + // + const char *EvalExpr(Output *out, Env *env); + ++ // force evaulation of IDs contained in this expression; ++ // necessary with case expr and conditional let fields (&if) ++ // for correct parsing of fields ++ void ForceIDEval(Output *out_cc, Env *env); ++ + // Returns the set_* function of the expression. + // The expression must be of form ID or x.ID. + string SetFunc(Output *out, Env *env); +diff -urN bro-1.2.1-orig/src/binpac/pac_let.cc bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc +--- bro-1.2.1-orig/src/binpac/pac_let.cc 2006-07-26 15:02:39.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc 2007-05-04 15:32:09.695568000 -0700 +@@ -80,7 +80,12 @@ + if ( type_->attr_if_expr() ) + { + // A conditional field ++ + env->Evaluate(out_cc, type_->has_value_var()); ++ ++ // force evaluation of IDs contained in this expr ++ expr()->ForceIDEval(out_cc, env); ++ + out_cc->println("if ( %s )", + env->RValue(type_->has_value_var())); + out_cc->inc_indent(); diff --git a/tools/binpac/patches/binpac-3.patch b/tools/binpac/patches/binpac-3.patch new file mode 100644 index 0000000000..9832a245b6 --- /dev/null +++ b/tools/binpac/patches/binpac-3.patch @@ -0,0 +1,37 @@ +diff -urN bro-1.2.1-orig/src/binpac/pac_let.cc bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc +--- bro-1.2.1-orig/src/binpac/pac_let.cc 2006-07-26 15:02:39.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc 2007-05-04 15:32:09.695568000 -0700 +@@ -108,11 +108,6 @@ + void LetField::GenEval(Output* out_cc, Env* env) + { + GenParseCode(out_cc, env); +- if ( type_->attr_if_expr() ) +- { +- out_cc->println("BINPAC_ASSERT(%s);", +- env->RValue(type_->has_value_var())); +- } + } + + LetDecl::LetDecl(ID *id, Type *type, Expr *expr) +diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc +--- bro-1.2.1-orig/src/binpac/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 +@@ -316,9 +316,15 @@ + { + if ( DefineValueVar() ) + { +- out_h->println("%s %s const { return %s; }", +- DataTypeConstRefStr().c_str(), +- env->RValue(value_var()), lvalue()); ++ if ( attr_if_expr_ ) ++ out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }", ++ DataTypeConstRefStr().c_str(), ++ env->RValue(value_var()), ++ env->RValue(has_value_var()), lvalue()); ++ else ++ out_h->println("%s %s const { return %s; }", ++ DataTypeConstRefStr().c_str(), ++ env->RValue(value_var()), lvalue()); + } + + foreach (i, FieldList, fields_) diff --git a/tools/binpac/patches/binpac-4.patch b/tools/binpac/patches/binpac-4.patch new file mode 100644 index 0000000000..560fb4051b --- /dev/null +++ b/tools/binpac/patches/binpac-4.patch @@ -0,0 +1,12 @@ +diff -urN bro-1.2.1-orig/src/binpac/pac_record.cc bro-1.2.1-ssl-binpac/src/binpac/pac_record.cc +--- bro-1.2.1-orig/src/binpac/pac_record.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_record.cc 2007-05-08 16:13:33.373850000 -0700 +@@ -123,7 +123,7 @@ + void RecordType::DoGenParseCode(Output* out_cc, Env* env, + const DataPtr& data, int flags) + { +- if ( StaticSize(env) >= 0 ) ++ if ( !incremental_input() && StaticSize(env) >= 0 ) + GenBoundaryCheck(out_cc, env, data); + + if ( incremental_parsing() ) diff --git a/tools/binpac/patches/binpac-5.patch b/tools/binpac/patches/binpac-5.patch new file mode 100644 index 0000000000..ae31fa1711 --- /dev/null +++ b/tools/binpac/patches/binpac-5.patch @@ -0,0 +1,66 @@ +diff -urN bro-1.2.1-orig/src/binpac/pac_paramtype.cc bro-1.2.1-ssl-binpac/src/binpac/pac_paramtype.cc +--- bro-1.2.1-orig/src/binpac/pac_paramtype.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_paramtype.cc 2007-05-10 15:09:47.470104000 -0700 +@@ -208,7 +208,13 @@ + const char *parse_func; + string parse_params; + +- if ( ref_type->incremental_input() ) ++ if ( buffer_mode() == BUFFER_NOTHING ) ++ { ++ ASSERT(!ref_type->incremental_input()); ++ parse_func = kParseFuncWithoutBuffer; ++ parse_params = "0, 0"; ++ } ++ else if ( ref_type->incremental_input() ) + { + parse_func = kParseFuncWithBuffer; + parse_params = env->RValue(flow_buffer_id); +@@ -239,15 +245,24 @@ + + if ( incremental_input() ) + { +- ASSERT(parsing_complete_var()); +- out_cc->println("%s = %s;", +- env->LValue(parsing_complete_var()), +- call_parse_func.c_str()); +- +- // parsing_complete_var might have been already +- // evaluated when set to false +- if ( ! env->Evaluated(parsing_complete_var()) ) +- env->SetEvaluated(parsing_complete_var()); ++ if ( buffer_mode() == BUFFER_NOTHING ) ++ { ++ out_cc->println("%s;", call_parse_func.c_str()); ++ out_cc->println("%s = true;", ++ env->LValue(parsing_complete_var())); ++ } ++ else ++ { ++ ASSERT(parsing_complete_var()); ++ out_cc->println("%s = %s;", ++ env->LValue(parsing_complete_var()), ++ call_parse_func.c_str()); ++ ++ // parsing_complete_var might have been already ++ // evaluated when set to false ++ if ( ! env->Evaluated(parsing_complete_var()) ) ++ env->SetEvaluated(parsing_complete_var()); ++ } + } + else + { +diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc +--- bro-1.2.1-orig/src/binpac/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 +@@ -501,8 +501,8 @@ + + if ( buffer_mode() == BUFFER_NOTHING ) + { +- out_cc->println("%s = true;", +- env->LValue(parsing_complete_var())); ++ // this is the empty type ++ DoGenParseCode(out_cc, env, data, flags); + } + else if ( buffer_input() ) + { diff --git a/tools/binpac/patches/binpac-6.patch b/tools/binpac/patches/binpac-6.patch new file mode 100644 index 0000000000..fec16c1084 --- /dev/null +++ b/tools/binpac/patches/binpac-6.patch @@ -0,0 +1,28 @@ +diff -urN bro-1.2.1-orig/src/binpac/lib/binpac_buffer.h bro-1.2.1-ssl-binpac/src/binpac/lib/binpac_buffer.h +--- bro-1.2.1-orig/src/binpac/lib/binpac_buffer.h 2006-07-26 15:02:38.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/lib/binpac_buffer.h 2007-05-09 16:14:54.501656000 -0700 +@@ -59,6 +59,11 @@ + return frame_length_; + } + ++ inline bool data_available() const ++ { ++ return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; ++ } ++ + void NewLine(); + // A negative frame_length represents a frame till EOF + void NewFrame(int frame_length, bool chunked_); +diff -urN bro-1.2.1-orig/src/binpac/pac_flow.cc bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc +--- bro-1.2.1-orig/src/binpac/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700 +@@ -272,7 +272,8 @@ + env_->RValue(begin_of_data), + env_->RValue(end_of_data)); + +- out_cc->println("while ( true )"); ++ out_cc->println("while ( %s->data_available() )", ++ env_->LValue(flow_buffer_id)); + out_cc->inc_indent(); + out_cc->println("{"); + diff --git a/tools/binpac/patches/binpac-7.patch b/tools/binpac/patches/binpac-7.patch new file mode 100644 index 0000000000..263f00bf2c --- /dev/null +++ b/tools/binpac/patches/binpac-7.patch @@ -0,0 +1,21 @@ +diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc +--- bro-1.2.1-orig/src/binpac/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 +@@ -393,7 +393,7 @@ + break; + + case BUFFER_BY_LENGTH: +- if ( buffering_state_var_field_ ) ++ if ( env->GetDataType(buffering_state_id) ) + { + out_cc->println("if ( %s == 0 )", + env->RValue(buffering_state_id)); +@@ -421,7 +421,7 @@ + frame_buffer_arg.c_str(), + attr_chunked() ? "true" : "false"); + +- if ( buffering_state_var_field_ ) ++ if ( env->GetDataType(buffering_state_id) ) + { + out_cc->println("%s = 1;", + env->LValue(buffering_state_id)); diff --git a/tools/binpac/patches/binpac-8.patch b/tools/binpac/patches/binpac-8.patch new file mode 100644 index 0000000000..b69a1676dd --- /dev/null +++ b/tools/binpac/patches/binpac-8.patch @@ -0,0 +1,190 @@ +diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.cc +--- bro-1.2.1-orig/src/binpac/pac_analyzer.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.cc 2007-05-22 17:00:10.091531000 -0700 +@@ -26,8 +26,9 @@ + helpers_ = new AnalyzerHelperList(); + functions_ = new FunctionList(); + +- constructor_helper_ = 0; +- destructor_helper_ = 0; ++ constructor_helpers_ = new AnalyzerHelperList(); ++ destructor_helpers_ = new AnalyzerHelperList(); ++ eof_helpers_ = new AnalyzerHelperList(); + + SetAnalyzerContext(); + +@@ -41,6 +42,9 @@ + delete_list(AnalyzerHelperList, helpers_); + delete_list(FunctionList, functions_); + delete_list(ParamList, params_); ++ delete_list(AnalyzerHelperList, constructor_helpers_); ++ delete_list(AnalyzerHelperList, destructor_helpers_); ++ delete_list(AnalyzerHelperList, eof_helpers_); + } + + void AnalyzerDecl::AddElements(AnalyzerElementList *elemlist) +@@ -75,28 +79,20 @@ + AnalyzerHelper *helper_elem = + (AnalyzerHelper *) elem; + +- if ( helper_elem->helper_type() == +- AnalyzerHelper::INIT_CODE) +- { +- if ( constructor_helper_ ) +- { +- throw Exception(elem, +- "Repeated definition of %init code"); +- } +- constructor_helper_ = helper_elem; ++ switch ( helper_elem->helper_type() ) ++ { ++ case AnalyzerHelper::INIT_CODE: ++ constructor_helpers_->push_back(helper_elem); ++ break; ++ case AnalyzerHelper::CLEANUP_CODE: ++ destructor_helpers_->push_back(helper_elem); ++ break; ++ case AnalyzerHelper::EOF_CODE: ++ eof_helpers_->push_back(helper_elem); ++ break; ++ default: ++ helpers_->push_back(helper_elem); + } +- else if ( helper_elem->helper_type() == +- AnalyzerHelper::CLEANUP_CODE) +- { +- if ( destructor_helper_ ) +- { +- throw Exception(elem, +- "Repeated definition of %cleanup code"); +- } +- destructor_helper_ = helper_elem; +- } +- else +- helpers_->push_back(helper_elem); + } + break; + case AnalyzerElement::FUNCTION: +@@ -217,15 +213,19 @@ + void AnalyzerDecl::GenInitCode(Output *out_cc) + { + TypeDecl::GenInitCode(out_cc); +- if ( constructor_helper_ ) +- constructor_helper_->GenCode(0, out_cc, this); ++ foreach(i, AnalyzerHelperList, constructor_helpers_) ++ { ++ (*i)->GenCode(0, out_cc, this); ++ } + } + + void AnalyzerDecl::GenCleanUpCode(Output *out_cc) + { + TypeDecl::GenCleanUpCode(out_cc); +- if ( destructor_helper_ ) +- destructor_helper_->GenCode(0, out_cc, this); ++ foreach(i, AnalyzerHelperList, destructor_helpers_) ++ { ++ (*i)->GenCode(0, out_cc, this); ++ } + } + + void AnalyzerDecl::GenStateVarDecls(Output *out_h) +@@ -295,6 +295,7 @@ + break; + case INIT_CODE: + case CLEANUP_CODE: ++ case EOF_CODE: + out = out_cc; + break; + } +diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.h bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.h +--- bro-1.2.1-orig/src/binpac/pac_analyzer.h 2006-07-26 15:02:39.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.h 2007-05-22 16:32:08.397926000 -0700 +@@ -76,8 +76,9 @@ + AnalyzerHelperList *helpers_; + FunctionList *functions_; + +- AnalyzerHelper *constructor_helper_; +- AnalyzerHelper *destructor_helper_; ++ AnalyzerHelperList *constructor_helpers_; ++ AnalyzerHelperList *destructor_helpers_; ++ AnalyzerHelperList *eof_helpers_; + }; + + class AnalyzerElement : public Object +@@ -117,6 +118,7 @@ + MEMBER_DECLS, + INIT_CODE, + CLEANUP_CODE, ++ EOF_CODE, + }; + AnalyzerHelper(Type helper_type, EmbeddedCode *code) + : AnalyzerElement(HELPER), +diff -urN bro-1.2.1-orig/src/binpac/pac_conn.cc bro-1.2.1-ssl-binpac/src/binpac/pac_conn.cc +--- bro-1.2.1-orig/src/binpac/pac_conn.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_conn.cc 2007-05-22 16:42:35.406135000 -0700 +@@ -97,6 +97,12 @@ + out_cc->println("%s->%s();", + env_->LValue(downflow_id), + kFlowEOF); ++ ++ foreach(i, AnalyzerHelperList, eof_helpers_) ++ { ++ (*i)->GenCode(0, out_cc, this); ++ } ++ + out_cc->dec_indent(); + + out_cc->println("}"); +diff -urN bro-1.2.1-orig/src/binpac/pac_flow.cc bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc +--- bro-1.2.1-orig/src/binpac/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700 +@@ -151,6 +151,11 @@ + out_cc->inc_indent(); + out_cc->println("{"); + ++ foreach(i, AnalyzerHelperList, eof_helpers_) ++ { ++ (*i)->GenCode(0, out_cc, this); ++ } ++ + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) + { + out_cc->println("%s->set_eof();", +diff -urN bro-1.2.1-orig/src/binpac/pac_parse.yy bro-1.2.1-ssl-binpac/src/binpac/pac_parse.yy +--- bro-1.2.1-orig/src/binpac/pac_parse.yy 2006-10-12 14:13:12.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_parse.yy 2007-05-22 16:56:09.280526000 -0700 +@@ -22,7 +22,7 @@ + %token TOK_STATE TOK_ACTION TOK_WHEN TOK_HELPER + %token TOK_DATAUNIT TOK_FLOWDIR TOK_WITHCONTEXT + %token TOK_LPB_EXTERN TOK_LPB_HEADER TOK_LPB_CODE +-%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP ++%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP TOK_LPB_EOF + %token TOK_LPB TOK_RPB + %token TOK_EMBEDDED_ATOM TOK_EMBEDDED_STRING + %token TOK_PAC_VAL TOK_PAC_SET TOK_PAC_TYPE TOK_PAC_TYPEOF TOK_PAC_CONST_DEF +@@ -795,6 +795,10 @@ + { + $$ = new AnalyzerHelper(AnalyzerHelper::CLEANUP_CODE, $2); + } ++ | TOK_LPB_EOF embedded_code TOK_RPB ++ { ++ $$ = new AnalyzerHelper(AnalyzerHelper::EOF_CODE, $2); ++ } + | TOK_FLOWDIR '=' tok_id optargs ';' + { + $$ = new AnalyzerFlow((AnalyzerFlow::Direction) $1, $3, $4); +diff -urN bro-1.2.1-orig/src/binpac/pac_scan.ll bro-1.2.1-ssl-binpac/src/binpac/pac_scan.ll +--- bro-1.2.1-orig/src/binpac/pac_scan.ll 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/binpac/pac_scan.ll 2007-05-22 16:55:19.349644000 -0700 +@@ -96,6 +96,10 @@ + BEGIN(EC); + return TOK_LPB_MEMBER; + } ++"%eof{" { ++ BEGIN(EC); ++ return TOK_LPB_EOF; ++ } + "%{" { + BEGIN(EC); + return TOK_LPB; diff --git a/tools/binpac/patches/binpac-patch-doc.txt b/tools/binpac/patches/binpac-patch-doc.txt new file mode 100644 index 0000000000..052285eaea --- /dev/null +++ b/tools/binpac/patches/binpac-patch-doc.txt @@ -0,0 +1,87 @@ +binpac fixes +---------------- + +numbers of issues below correspond to the patch numbers + +(1) correct calculation of minimal header size in pac_expr.cc +- problem: EXPR_CALLARGS and EXPR_CASE not considered for the calculation + of minimal header size +- solution: added two cases in switch stmt of Expr::MinimalHeaderSize + for EXPR_CALLARGS and EXPR_CASE + + +(2) ensure parsing of fields first referenced in a case expression or + let field with an &if attribute +- problem: in cases where the if expression evaluates to false or the + proper case does not occur, fields get not parsed at all +- solution: force evaluation of all IDs referenced in a let field with + if attribute or a case expression before the body of the corresponding + switch stmt or the if stmt +- added public method Expr::ForceIDEval, properly called before + generating the code of a field with if attribute or the case expression + + +(3) properly assert the use of fields with an if attribute +- problem: the use of fields with an if attribute was not asserted in all + cases and asserted in the wrong way in some others due to the + corresponding BINPAC_ASSERT only called upon parsing the field +- solution: perform BINPAC_ASSERT upon calling the fields accessor + function +- moved BINPAC_ASSERT statement from LetField::GenEval to + Type::GenPubDecls + + +(4) incremental input with records with a non-negative StaticSize +- problem: incremental input with records with a StaticSize >= 0 + cannot be performed due to necessary length attribute, leading to + an invalid call of GenBoundaryCheck in RecordType::DoGenParseCode +- solution: added a check for incremental input in + RecordType::DoGenParseCode before calling GenBoundaryCheck + + +(5) empty type with incremental input +- problem: with an empty type and incremental input, although the + Parse function is created, it is never called, leading to problems, + if additional actions are to be performed when encountering that + empty type +- solution: generate call to Parse of empty type in Type::GenParseBuffer + + +(6) parsing loop in flow ParseBuffer (while(true)) +- problem: while(true) leads to problems after parsing of a type is + complete; at this time, it is unexpected that parsing continues, even + if no data is available in the flow buffer +- solution: check if data is available before starting a new parsing + cycle +- added a method data_available to FlowBuffer +- changed while(true) in FlowDecl::GenCodeFlowUnit to + while(flow_buffer_->data_available()) + + +(7) initialization of flow buffer in CaseType with bufferable fields + in cases +- problem: initialization of buffer occurs in every Parse call, + regardless if it was initialized before or not; initialization + is correct only on first such occurence +- solution: check to buffer_state is to be created always when + buffering_state_id is in environment in Type::GenBufferConfig +- changed condition from buffering_state_var_field_ to + env->GetDataType(buffering_state_id) + + +(8) allowing init and cleanup code to be redefined, as well as addition + of code to FlowEOF calls in analyzer and flow +- problem 1: when refining an analyzer or flow definition, additional + init and cleanup code was not allowed, if these were already defined + before; this leads to problems when adding new members, as these + cannot be initialized and destroyed properly +- solution: allow init and cleanup code to be specified more than once +- changed deifnitions and usage of constructor_helper and + destructor_helper to allow for lists of constructor and destructor + helpers (similar to member declarations) in pac_analyzer.h and + pac_analyzer.cc +- problem 2: in some cases, it is desirable to execute code when + encountering the end of the input stream, which is not possible in + binpac +- solution: added a %eof binpac primitive similar to %init, which adds + code to the FlowEOF function of an analyzer or a flow diff --git a/tools/binpac/patches/brosslbinpacanalyzerpatches.zip b/tools/binpac/patches/brosslbinpacanalyzerpatches.zip new file mode 100644 index 0000000000000000000000000000000000000000..4d89326f71cc03cdd85616c3ee943d8d09072b0b GIT binary patch literal 8025 zcma)>WmHw&`u1sQHr+^rfJk>Ejj-uZK)M??-6^^0?rx;JJ7m)h(kUqo^6EK`^VjFY zJD$0|toh+L#u{^8>yGON%E7|nKq3Bo?7_`kP=74+pYI0dHg@`kuUVPx^qmaN5|nim zdsuM1PQ3fQR!CM`c$3j-0OH@FBmMBP4HIjeH3LQY$g?*(m%X~l0d>Pm$JgnO6YY%@ z(Ue_s=P=@|y@~q7c$r8-Y}lB|;$#!%A4eukkD6Khv;Adbk(i;1J|hp@+LjK{=KFmL z|AwIH9KDb!j;hQI<_@H9seGpMC_OMx9_)i2J+FK{QG+_)VQ-VsZqkaj;7nYPuz#T6 z3bA4I1uU6709o#5RYfK-kAwnJnic$utt zu>ENg{7ICdZ!@8A2h^aJC*dcxgVvHHn>L=3ZNJ|c7wvd(VO3-)AD6*=K~5)zfwhou z8OVs3yq(ln4iOMvTld|-ixzKCuipZxF-16{Y|Zp!0=I3G^(kd1G)h zm{Qzh+E*2=ZtyUXwcaMh1tke8O$XYPO5&p~gnfF)OH5#sEn?EOn)V0}lzV}=rRzPB z1`P#u0Sg5M{5RLi_TOu*P`8fWk^t|@@o$LGTa&2m?>cI(tOt*n8umonZ#5FvgmIYs;C9g^9=OW2W_(*s; zb!xM(^F{0GDY$SR>TVqz+z3V1jD_a9A*Ia?tE}HD4?tb!7*;Njn%Aw5P+t~6{VWkT zuK3A1(>7@!l=Qjm15}d1!u zkZ4}dv5=RCzHxTnwc-jU^weiaB9Z8#Z!N#Dw_Ct_Gq2IjLyWAWPP}PG{SOVEQjKO0 zs|{39D<*yE$6=6h=#YD~QbmZmozh{oD(FRJ6}zwyr4=alCfW?*ix0v~sF9w8kE?dg zC`AelF_fI@vs&yJ+syWTW69^VNQEdOLNHqmd8_0gD^d{iF33R(U zZ%%wJOhyK0TXoBM16iN=+LgvHech}tTP8aq$ zY0fe!7h+uHg!3_9C4QiRJ!+MwP2?HZm7S}0^@}tf1{C;R!J&G?d4yKI%;tsb{aC<} z@7j=NqBm-9ZF{^FQP$LnJb;ThMZE{;qb{>9wRm5u#vmOXL|C@fu%dfY-Cwse9Hcm?^g<)gFIoqj1H#cQ*1t8f$|;0F zl&Z+lB&$Q{+YF@Pz^U*XWJ;1E9CxfEEGH7(@1Y?e`)s$MyO8`ENU^7a^uZ^ZvD>AR*9oU0Wp~vXo)KE)xEDY1% zSORcmfHrawCtUh|+Lx{@$P@6vcA_+K93BIjP#2FT?*{Rf3}Nv&_Tm)*w^mkFxO51+ zON?N)cCqx4GauYNbO**S*VzZ?#~rf=jmsHpIXoVqb`%7m(dB3XH6v^esldxI(-@pK zW^F99nh^;G8w^#dAaZt(LPKkSVeG?&2yPNtd)w8Amh1Gn2F-lUr{$gPZ{OaY*g3Le zB7~jGuMU1W!{IE>XwH0u{S_6CD`BXYentcdlz$l&*#8?9>Q&Dz^H>O;w4TGFyG6=A zPpUU+)34UI8?u1%NFUVF2P{SEk~MAOpH6T3m-r7F_)ow3v$DFmbwuBA>}Vn6SDtJ% zGkiL7jglJ)^C1pnAQZYZz^4;GR{D}3M@pRnaUg`0jz@Mgi+tOs zApyA_h>5aRbA(}2tFPmfp%)IjF$T(ZP~51Y%$4G@r|H(o3l>UY9+uV0D0UsSLi2s%o)K!$ZP&!C4IwOXEh+fV~Amg3Vky3mw$Ymae9a zhl8aVo0-o145WM5&F#NNlnnPwi(q})GjifdGjktd>R4#FIXT$2H!RMb^iK&{n)W+_#Dy?sBiJRkTLvJ-| zl9c(xQw{k7jI<$jO@*w2q;|NnG6ccT?E59WQ?I6YscR{R!Kp+55LY83$JqV8?-_OfZ`XCg-N*L93PV2;DZ=O{t?29G)zFoJ#d86&4JDzpqsnVs{{nGE4RMqxxwY-@U+%1YYGpmhVZL_D0F8Jt?n&-A$p%8E|oLQ zCnkJp;R72=(CR8^e9n5N{lzQNyK2a0jYGETHC%TROc@>AFXIYmPT!h)pK27yh>b~d z?|mHt2^>cqEsATnycpl_0tJd^$`(HA_db&AF{v;&cN&N#Aya5#2qO+1V7+IUE}vf0 zp!kMAX#M`vYtj`B>=itI1cGXgEAG1+*q7!8ZS;2^p=?WfDN_cq3>r3Bwgg}kk-zkW z$OctGSmOi&9|(frlgJ%I3AiLFoRF^Nq2J6wto03aGO=2AE_B)oMXgIawh!+&A`cDp z^*t(pE^>1D^vzSVU_R@T@>i6Ww4KNoI__2&17~?Q)VK~(b3~AM%7ib>QS{O(vGf_v z8L2VwmT0@VM-__tnvSa+iyT);W6uk3o-6UvrO`87^FD>UGn2Z7ywM1kB7Fe3@2Zbi zw(KFtn8dcb&`Z~f`_;wRD?@o3kNLexynt3U(7u1wxtT(?w#UG+wWMxTO<@$f2q>`9 zb-H5Vez#s8c6H`06u}zO`AgquaUwPOKeg?G_%HR%^laUUpsFJg%8`?rC$OWp@jRm}|eq zN(IaiHD|aKrY0$$x^ZgMq!*Txq)H|mx%i#%1<`&z^6(6VJeRoQY@u$DOrlC_f7E8O z!SW>g$Vl*@gyWS@JeWb1PT2+%i)*BnKT6$CEmv!LGL8Uj31bgEP68}gd7cSOgnF|O z5%u~Y7Y43f^Mj5UIz7**6fJ1#eQT_7XWI56UN)(=sZt{5SUAtW2gq+tewhd~w3TPq zgbgmDvvcWFz!96bxpK?Fd0$dtv8_tQ=xt_j(2o*XoX79wg0} z!G@ZMl7artaZJc!!Z?YYJc<-KGeJhp^iv#K6&D|+_)P4a&CPjj*Nab-B3IlDXlFaI@So&k0Yq#Opf{MDPM)#9mxv$X zAE20imK&q@5|(YPRhaM}<`au6D@4@rf?IMy`^O2BqNu2$kz(z@j?0Q+St84vaM07#i98PemC;;s|2 zs~!73TDQfrQz^6{Xnb7U^-+&AwyqP472_p{T zwjvtv5rZOKGaePFocrTcqa(Gdjx$zA%?j<-%PrPQl#Ain6`$CeYu$F@f){gAlw&XU z*w(`rST^vSXykIl5#4)g#P&@{XZ!uKedKb{q0=XC5Y;;+&d`7TsAWXQI$A$3<@Dbs zBA(xgNYmOeR~qoc%DZ2cq2wbRK9FORroJ*Z(z&t_b+P^7Ehd2?GaOUb_^!j<={$QI z4>@g9TAr+5ifM~!OV+_jHwX`fx;)@j3yPK@O^$5|=3c&8`tF4f z-!afr6Z^?~A-Gr&n@2x##My#*Bc)?R0}U|0w6dy_`m%wF{2MsITvv!0$8`pL%rfp< z39vD>vzn4B4R|>&KCv$5;hYMl{gKe3%Ll{j(bd;N?zqwpK(tTdc8iII6{At-wi$@2 zaSCho`MP}QydBjwg~JF8n`0vCgHv8Hgb|_1EE?{$Ut{m4m}dkbjx)DH@oA)xxc2&MJz+8i ztAzyFtNioAO}1KfB29x8*)2`%X^A#~q4y0bKl>Hp`^r*utM`uQu-CaP*zp_ynSC4_ zK>(+-#d&4VXxD;GbW;DquH6ouuL8D0Ow89c0+p?>Vm?aW((b5n48@T5}QYPI+8TGxq zy87%rT(?FWuIPT`K7LWd>}J*H`t4b{da)rFf`k?ANb))}$12oYQL5e6ecr9x<)Rff&X>scmC9FPF?0r) zSc9}$fFRi8B7_yo%GF}}Gi&`&XF-sD&4YbQ{6e|0T(b_==z8Q*V)#4T_ND%lDUMjG zMj(gGl=5WqoAcN97z_^NpHxcS-S|llw-!|+<4R|CXyB(xXEqCX*yG_kCKiZ$l|!mI zY#O4}Ekm7u@UbzKp{HhU6a~aJd`1c`|8}*YJVo)rmzqIhTZt)DYH|wc6)wI|`LwnJ zx?U{0%QiqvnFy&#rRYbCtHrpExi2d9mku2@PDGS9OGfx~jmtj6l*Ys7q-YM<-I=!* zQ^72zvBv4BJDFmK7!F5;!*;!DvTC$|qIW@>DRnlR1TiqO9~t}EPw=-pNEROECP$x; z7j}fyzB{yr+FW_JhwAQH>_;uds-2fF9y)tC(CLZ0n4_(ZTkKmG=Htqk0bpzD$@o@h z-0f+U%avt8_MLDI<5oS@H6`)ZTRIC^{-^#mcj)RDV&SHvoW0cq%rRl=NBr}jA;%}S zRuVIzSbg%@HPji#sy}kQ?()YYW4O{+&hja?*t`tQ$FPZtP-)xWdg-T>ntEhyt?^f0g*K<`}CZu3UUYBN)VOzm}p&N1$YE+8KQ%hD{PoQWQl)VP_5l!bA? zdjEWF@c|<_ra2e}Ik~aKv(^(OqY;8+ykd0y4bLAnSKn8aWak*&-l(gNzF*0hsLM^T zZ@j2THdDGAHxw+ko`6&i3`Ulf!u5D}C$Ac&1x%!{MK*R{FG=;~E|%_pDyQc~PS%$)zEJ{n|HoiNsz) znciP=s$Ph19es=yTsL#SE`N5b*wHmfT4Y=}kqn7&C-mt!9Jr!tmPxC6HF5rJzxew! z!OaqMjFi;H?lGLl**cLSQed2?C0I3Wi9%?XRu8+BVcfy1ygG(-&LHTOslpdUfF{}$ z%7sP@;UjKt+>ha-QR-JATMOK3q`c6DYTBfvGTF88o!4Z9r{6q2fDN{jpIB_H%UdlF1#&!?q z#n$7tz#_ePqYFMh5(P+byAs|P^!mzPP zMMr8||F!`Mdebzv9x(4qgeK_9R#2UU@v%(BS4gVbT)L8vcX-b9`>S1-s{oemykgf*(i! zz7S%(EcWT9C95(&?ZsktNPB=IwqQaA8m`k^QR>JJOl`G*sEKrH@>TzoTQc{+ZvP65JnVtlw-o0PcW2OqqSAh{#Gf_ zBk$FSuM*kl(AVC_d1{^(Td*O8YUHM-_i9B2Nm&{jhM6KLEDlK#48O^132O*83ynlY zKOrQM?(KJbt}Uax?yn3taNzkNSg89t1RiLVH*b5}m@_YW|27zZe9YaZxfUtp317)Y z&O;Xq40Yh%jTLIs*sM+zjmtaAk01D`?FD+ejnXW{ihA{oBi$B{*(RFu=$%! zNBST8+l2fl`)6bSH|vS|KlZo5^H28A{_}4Z{B!&Jn|~Vt|78Cx5dLOq0RLlu_pAS8 m|GfKOCB*-&F1-J-e-#u!IryJifr3K%`B47smMKVo?fxHiFH3{~ literal 0 HcmV?d00001 diff --git a/tools/binpac/patches/nadi-bittorrent.patch b/tools/binpac/patches/nadi-bittorrent.patch new file mode 100644 index 0000000000..1ce6cc0313 --- /dev/null +++ b/tools/binpac/patches/nadi-bittorrent.patch @@ -0,0 +1,172 @@ +Index: pac_type.h +=================================================================== +--- pac_type.h (revision 4130) ++++ pac_type.h (working copy) +@@ -78,12 +78,6 @@ + string EvalByteOrder(Output *out_cc, Env *env) const; + + virtual string EvalMember(const ID *member_id) const; +-#if 0 +- // member_env() is used for finding a member of the type. +- // Thus member_env() of a ParameterizedType should return +- // ReferredDataType()->env() +- // virtual Env *member_env() const; +-#endif + + // The variable defined by the type + const ID *value_var() const { return value_var_; } +@@ -223,6 +217,8 @@ + + virtual bool ByteOrderSensitive() const = 0; + ++ bool NeedsBufferingStateVar() const; ++ + void GenBufferingLoop(Output* out_cc, Env* env, int flags); + void GenParseBuffer(Output* out_cc, Env* env, int flags); + void GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags); +Index: lib/binpac_buffer.h +=================================================================== +--- lib/binpac_buffer.h (revision 4130) ++++ lib/binpac_buffer.h (working copy) +@@ -24,18 +24,18 @@ + void DiscardData(); + + // Whether there is enough data for the frame +- bool ready() const{ return message_complete_; } ++ bool ready() const{ return message_complete_ || mode_ == UNKNOWN_MODE; } + + inline const_byteptr begin() const + { +- BINPAC_ASSERT(message_complete_); ++ BINPAC_ASSERT(ready()); + return ( buffer_n_ == 0 ) ? + orig_data_begin_ : buffer_; + } + + inline const_byteptr end() const + { +- BINPAC_ASSERT(message_complete_); ++ BINPAC_ASSERT(ready()); + if ( buffer_n_ == 0 ) + { + BINPAC_ASSERT(frame_length_ >= 0); +Index: pac_type.cc +=================================================================== +--- pac_type.cc (revision 4130) ++++ pac_type.cc (working copy) +@@ -285,9 +285,8 @@ + parsing_complete_var, extern_type_bool->Clone()); + parsing_complete_var_field_->Prepare(env); + +- if ( ( buffer_mode() == BUFFER_BY_LENGTH || +- buffer_mode() == BUFFER_BY_LINE ) && +- ! env->GetDataType(buffering_state_id) ) ++ if ( NeedsBufferingStateVar() && ++ !env->GetDataType(buffering_state_id) ) + { + buffering_state_var_field_ = new PrivVarField( + buffering_state_id->clone(), +@@ -387,17 +386,17 @@ + break; + + case BUFFER_BY_LENGTH: +- if ( buffering_state_var_field_ ) +- { +- out_cc->println("if ( %s == 0 )", +- env->RValue(buffering_state_id)); +- out_cc->inc_indent(); +- out_cc->println("{"); +- } ++ if ( !NeedsBufferingStateVar() ) ++ break; + ++ ASSERT(env->GetDataType(buffering_state_id)); ++ out_cc->println("if ( %s == 0 )", ++ env->RValue(buffering_state_id)); ++ out_cc->inc_indent(); ++ out_cc->println("{"); ++ + if ( attr_length_expr_ ) + { +- // frame_buffer_arg = attr_length_expr_->EvalExpr(out_cc, env); + frame_buffer_arg = strfmt("%d", InitialBufferLength()); + } + else if ( attr_restofflow_ ) +@@ -407,7 +406,7 @@ + } + else + { +- frame_buffer_arg = strfmt("%d", InitialBufferLength()); ++ ASSERT(0); + } + + out_cc->println("%s->NewFrame(%s, %s);", +@@ -415,16 +414,14 @@ + frame_buffer_arg.c_str(), + attr_chunked() ? "true" : "false"); + +- if ( buffering_state_var_field_ ) +- { +- out_cc->println("%s = 1;", +- env->LValue(buffering_state_id)); +- out_cc->println("}"); +- out_cc->dec_indent(); +- } ++ out_cc->println("%s = 1;", ++ env->LValue(buffering_state_id)); ++ out_cc->println("}"); ++ out_cc->dec_indent(); + break; + + case BUFFER_BY_LINE: ++ ASSERT(env->GetDataType(buffering_state_id)); + out_cc->println("if ( %s == 0 )", + env->RValue(buffering_state_id)); + out_cc->inc_indent(); +@@ -890,6 +887,25 @@ + return ! attr_byteorder_expr() && ByteOrderSensitive(); + } + ++bool Type::NeedsBufferingStateVar() const ++ { ++ if ( !incremental_input() ) ++ return false; ++ switch ( buffer_mode() ) ++ { ++ case BUFFER_NOTHING: ++ case NOT_BUFFERABLE: ++ return false; ++ case BUFFER_BY_LINE: ++ return true; ++ case BUFFER_BY_LENGTH: ++ return ( attr_length_expr_ || attr_restofflow_ ); ++ default: ++ ASSERT(0); ++ return false; ++ } ++ } ++ + bool Type::DoTraverse(DataDepVisitor *visitor) + { + foreach (i, FieldList, fields_) +Index: pac_flow.cc +=================================================================== +--- pac_flow.cc (revision 4130) ++++ pac_flow.cc (working copy) +@@ -224,15 +224,13 @@ + out_cc->println("catch ( Exception const &e )"); + out_cc->inc_indent(); + out_cc->println("{"); +- out_cc->println("DEBUG_MSG(\"%%.6f binpac exception: %%s\\n\", network_time(), e.c_msg());"); + GenCleanUpCode(out_cc); + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) + { + out_cc->println("%s->DiscardData();", + env_->LValue(flow_buffer_id)); +- out_cc->println("BINPAC_ASSERT(!%s->ready());", +- env_->RValue(flow_buffer_id)); + } ++ out_cc->println("throw e;"); + out_cc->println("}"); + out_cc->dec_indent(); + diff --git a/tools/binpac/src/Makefile.am b/tools/binpac/src/Makefile.am new file mode 100644 index 0000000000..2dc2816c35 --- /dev/null +++ b/tools/binpac/src/Makefile.am @@ -0,0 +1,62 @@ +## Process this file with automake to produce Makefile.in + +AM_YFLAGS = -d -t -v +AM_CPPFLAGS = -W -Wall -Wno-unused + +noinst_PROGRAMS = binpac + +binpac_SOURCES = \ + pac_scan.ll pac_parse.yy \ + pac_action.cc \ + pac_analyzer.cc \ + pac_array.cc \ + pac_attr.cc \ + pac_btype.cc \ + pac_case.cc \ + pac_conn.cc \ + pac_context.cc \ + pac_cstr.cc \ + pac_datadep.cc \ + pac_dataptr.cc \ + pac_dataunit.cc \ + pac_decl.cc \ + pac_embedded.cc \ + pac_enum.cc \ + pac_expr.cc \ + pac_exttype.cc \ + pac_field.cc \ + pac_flow.cc \ + pac_func.cc \ + pac_id.cc \ + pac_inputbuf.cc \ + pac_let.cc \ + pac_param.cc \ + pac_paramtype.cc \ + pac_primitive.cc \ + pac_record.cc \ + pac_redef.cc \ + pac_regex.cc \ + pac_state.cc \ + pac_strtype.cc \ + pac_type.cc \ + pac_typedecl.cc \ + pac_withinput.cc \ + pac_output.cc pac_utils.cc pac_exception.cc \ + pac_main.cc \ + pac_action.h pac_analyzer.h pac_array.h pac_attr.h pac_btype.h \ + pac_case.h pac_cclass.h pac_common.h pac_conn.h pac_context.h \ + pac_cstr.h pac_ctype.h pac_datadep.h pac_dataptr.h pac_dataunit.h \ + pac_dbg.h pac_decl-inl.h pac_decl.h pac_embedded.h pac_enum.h \ + pac_exception.h pac_expr.h pac_exttype.h pac_field.h pac_flow.h \ + pac_func.h pac_id.h pac_inputbuf.h pac_let.h pac_number.h \ + pac_output.h pac_param.h pac_paramtype.h pac_parse.h pac_primitive.h \ + pac_record.h pac_redef.h pac_regex.h pac_state.h pac_strtype.h \ + pac_type.h pac_typedecl.h pac_utils.h pac_varfield.h pac_withinput.h + +EXTRA_DIST = pac_expr.def pac_type.def pac_externtype.def + +DISTCLEANFILES = pac_parse.cc pac_parse.h pac_scan.cc y.output + +# Manual rules below: + +pac_scan.o: pac_parse.h diff --git a/tools/binpac/src/pac_action.cc b/tools/binpac/src/pac_action.cc new file mode 100644 index 0000000000..0b1ac3574f --- /dev/null +++ b/tools/binpac/src/pac_action.cc @@ -0,0 +1,119 @@ +#include "pac_embedded.h" +#include "pac_exception.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_type.h" +#include "pac_typedecl.h" +#include "pac_utils.h" + +#include "pac_action.h" + +AnalyzerAction::AnalyzerAction(ID *action_id, + When when, + ActionParam *param, + EmbeddedCode *code) + : AnalyzerElement(ACTION), + action_id_(action_id), + when_(when), + param_(param), + code_(code), + analyzer_(0) + { + } + +AnalyzerAction::~AnalyzerAction() + { + delete action_id_; + delete param_; + delete code_; + } + +string AnalyzerAction::action_function() const + { + return strfmt("Action_%s", action_id_->Name()); + } + +void AnalyzerAction::InstallHook(AnalyzerDecl *analyzer) + { + ASSERT(0); + analyzer_ = analyzer; + // param_->MainDataType()->InstallAction(this); + } + +void AnalyzerAction::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl) + { + Env action_func_env(decl->env(), this); + action_func_env.AddID(param_->id(), + TEMP_VAR, + param_->DataType()); + action_func_env.SetEvaluated(param_->id()); + + string action_func_proto = + strfmt("%s(%s)", + action_function().c_str(), + ParamDecls(&action_func_env).c_str()); + + out_h->println("void %s;", action_func_proto.c_str()); + + out_cc->println("void %s::%s", + decl->class_name().c_str(), + action_func_proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + + code_->GenCode(out_cc, &action_func_env); + + out_cc->println(""); + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); + } + +string AnalyzerAction::ParamDecls(Env *env) const + { + return param_->DeclStr(env); + } + +Type *ActionParam::MainDataType() const + { + // Note: this is not equal to DataType() + Type *main_type = TypeDecl::LookUpType(type()->type_id()); + + if ( ! main_type ) + { + throw Exception(type()->type_id(), + "type not defined"); + } + + return main_type; + } + +Type *ActionParam::DataType() const + { + Type *main_type = MainDataType(); + + if ( ! type()->field_id() ) + { + return main_type; + } + else + { + Type *member_type = + main_type->MemberDataType(type()->field_id()); + if ( ! member_type ) + { + throw Exception(type()->field_id(), + fmt("cannot find member type for `%s.%s'", + type()->type_id()->Name(), + type()->field_id()->Name())); + } + return member_type; + } + } + +string ActionParam::DeclStr(Env *env) const + { + return strfmt("%s %s", + DataType()->DataTypeStr().c_str(), + env->LValue(id())); + } diff --git a/tools/binpac/src/pac_action.h b/tools/binpac/src/pac_action.h new file mode 100644 index 0000000000..df0828b823 --- /dev/null +++ b/tools/binpac/src/pac_action.h @@ -0,0 +1,74 @@ +#ifndef pac_action_h +#define pac_action_h + +// Classes representing analyzer actions. + +#include "pac_common.h" +#include "pac_analyzer.h" + +class AnalyzerAction : public AnalyzerElement +{ +public: + enum When { BEFORE, AFTER }; + + AnalyzerAction(ID *action_id, + When when, + ActionParam *param, + EmbeddedCode *code); + + ~AnalyzerAction(); + + When when() const { return when_; } + ActionParam *param() const { return param_; } + AnalyzerDecl *analyzer() const { return analyzer_; } + string action_function() const; + + // Generate function prototype and code for the action + void GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl); + + // Install the hook at the corresponding data type parsing + // function to invoke the action. + void InstallHook(AnalyzerDecl *analyzer); + +private: + string ParamDecls(Env *env) const; + + ID *action_id_; + When when_; + ActionParam *param_; + EmbeddedCode *code_; + AnalyzerDecl *analyzer_; +}; + +class ActionParam +{ +public: + ActionParam(const ID *id, ActionParamType *type) + : id_(id), type_(type) {} + + const ID *id() const { return id_; } + ActionParamType *type() const { return type_; } + + Type *MainDataType() const; + Type *DataType() const; + string DeclStr(Env *env) const; + +private: + const ID *id_; + ActionParamType *type_; +}; + +class ActionParamType +{ +public: + ActionParamType(const ID *type_id, const ID *field_id = 0) + : type_id_(type_id), field_id_(field_id) {} + + const ID *type_id() const { return type_id_; } + const ID *field_id() const { return field_id_; } + +protected: + const ID *type_id_, *field_id_; +}; + +#endif // pac_action_h diff --git a/tools/binpac/src/pac_analyzer.cc b/tools/binpac/src/pac_analyzer.cc new file mode 100644 index 0000000000..0c01190a9d --- /dev/null +++ b/tools/binpac/src/pac_analyzer.cc @@ -0,0 +1,358 @@ +#include "pac_action.h" +#include "pac_context.h" +#include "pac_embedded.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_flow.h" +#include "pac_func.h" +#include "pac_output.h" +#include "pac_param.h" +#include "pac_paramtype.h" +#include "pac_state.h" +#include "pac_type.h" +#include "pac_varfield.h" + +#include "pac_analyzer.h" + +AnalyzerDecl::AnalyzerDecl(ID *id, + DeclType decl_type, + ParamList *params) + : TypeDecl(id, params, new DummyType()) + { + decl_type_ = decl_type; + + statevars_ = new StateVarList(); + actions_ = new AnalyzerActionList(); + helpers_ = new AnalyzerHelperList(); + functions_ = new FunctionList(); + + constructor_helpers_ = new AnalyzerHelperList(); + destructor_helpers_ = new AnalyzerHelperList(); + eof_helpers_ = new AnalyzerHelperList(); + + SetAnalyzerContext(); + + env_ = 0; + } + +AnalyzerDecl::~AnalyzerDecl() + { + delete_list(StateVarList, statevars_); + delete_list(AnalyzerActionList, actions_); + delete_list(AnalyzerHelperList, helpers_); + delete_list(FunctionList, functions_); + delete_list(ParamList, params_); + delete_list(AnalyzerHelperList, constructor_helpers_); + delete_list(AnalyzerHelperList, destructor_helpers_); + delete_list(AnalyzerHelperList, eof_helpers_); + } + +void AnalyzerDecl::AddElements(AnalyzerElementList *elemlist) + { + ASSERT(! env_); + foreach(i, AnalyzerElementList, elemlist) + { + AnalyzerElement *elem = *i; + switch ( elem->type() ) + { + case AnalyzerElement::STATE: + { + ASSERT(0); + AnalyzerState *state_elem = + (AnalyzerState *) elem; + statevars_->insert( + statevars_->end(), + state_elem->statevars()->begin(), + state_elem->statevars()->end()); + } + break; + case AnalyzerElement::ACTION: + { + ASSERT(0); + AnalyzerAction *action_elem = + (AnalyzerAction *) elem; + actions_->push_back(action_elem); + } + break; + case AnalyzerElement::HELPER: + { + AnalyzerHelper *helper_elem = + (AnalyzerHelper *) elem; + + switch ( helper_elem->helper_type() ) + { + case AnalyzerHelper::INIT_CODE: + constructor_helpers_->push_back(helper_elem); + break; + case AnalyzerHelper::CLEANUP_CODE: + destructor_helpers_->push_back(helper_elem); + break; + case AnalyzerHelper::EOF_CODE: + eof_helpers_->push_back(helper_elem); + break; + default: + helpers_->push_back(helper_elem); + } + } + break; + case AnalyzerElement::FUNCTION: + { + AnalyzerFunction *func_elem = + (AnalyzerFunction *) elem; + Function *func = func_elem->function(); + func->set_analyzer_decl(this); + functions_->push_back(func); + } + break; + case AnalyzerElement::FLOW: + { + AnalyzerFlow *flow_elem = + (AnalyzerFlow *) elem; + ProcessFlowElement(flow_elem); + } + break; + case AnalyzerElement::DATAUNIT: + { + AnalyzerDataUnit *dataunit_elem = + (AnalyzerDataUnit *) elem; + ProcessDataUnitElement(dataunit_elem); + } + break; + } + } + } + +string AnalyzerDecl::class_name() const + { + return id_->Name(); + } + +void AnalyzerDecl::Prepare() + { + TypeDecl::Prepare(); + + ASSERT(statevars_->empty()); + ASSERT(actions_->empty()); + + foreach(i, FunctionList, functions_) + { + Function *function = *i; + function->Prepare(env_); + } + foreach(i, StateVarList, statevars_) + { + StateVar *statevar = *i; + env_->AddID(statevar->id(), STATE_VAR, statevar->type()); + } + foreach(i, AnalyzerActionList, actions_) + { + AnalyzerAction *action = *i; + action->InstallHook(this); + } + } + +void AnalyzerDecl::GenForwardDeclaration(Output* out_h) + { + out_h->println("class %s;", class_name().c_str()); + foreach(i, FunctionList, functions_) + { + Function *function = *i; + function->GenForwardDeclaration(out_h); + } + } + +void AnalyzerDecl::GenActions(Output *out_h, Output *out_cc) + { + foreach(i, AnalyzerActionList, actions_) + { + (*i)->GenCode(out_h, out_cc, this); + } + } + +void AnalyzerDecl::GenHelpers(Output *out_h, Output *out_cc) + { + foreach(i, AnalyzerHelperList, helpers_) + { + (*i)->GenCode(out_h, out_cc, this); + } + } + +void AnalyzerDecl::GenPubDecls(Output *out_h, Output *out_cc) + { + TypeDecl::GenPubDecls(out_h, out_cc); + + GenProcessFunc(out_h, out_cc); + GenGapFunc(out_h, out_cc); + GenEOFFunc(out_h, out_cc); + out_h->println(""); + + if ( ! functions_->empty() ) + { + out_h->println("// Functions"); + GenFunctions(out_h, out_cc); + out_h->println(""); + } + + // TODO: export public state variables + } + +void AnalyzerDecl::GenPrivDecls(Output *out_h, Output *out_cc) + { + TypeDecl::GenPrivDecls(out_h, out_cc); + + if ( ! helpers_->empty() ) + { + out_h->println(""); + out_h->println("// Additional members"); + GenHelpers(out_h, out_cc); + } + + // TODO: declare state variables + } + +void AnalyzerDecl::GenInitCode(Output *out_cc) + { + TypeDecl::GenInitCode(out_cc); + foreach(i, AnalyzerHelperList, constructor_helpers_) + { + (*i)->GenCode(0, out_cc, this); + } + } + +void AnalyzerDecl::GenCleanUpCode(Output *out_cc) + { + TypeDecl::GenCleanUpCode(out_cc); + foreach(i, AnalyzerHelperList, destructor_helpers_) + { + (*i)->GenCode(0, out_cc, this); + } + } + +void AnalyzerDecl::GenStateVarDecls(Output *out_h) + { + foreach(i, StateVarList, statevars_) + { + StateVar *var = *i; + var->GenDecl(out_h, env_); + } + } + +void AnalyzerDecl::GenStateVarSetFunctions(Output *out_h) + { + foreach(i, StateVarList, statevars_) + { + StateVar *var = *i; + var->GenSetFunction(out_h, env_); + } + } + +void AnalyzerDecl::GenStateVarInitCode(Output *out_cc) + { + foreach(i, StateVarList, statevars_) + { + StateVar *var = *i; + var->GenInitCode(out_cc, env_); + } + } + +void AnalyzerDecl::GenStateVarCleanUpCode(Output *out_cc) + { + foreach(i, StateVarList, statevars_) + { + StateVar *var = *i; + var->GenCleanUpCode(out_cc, env_); + } + } + +void AnalyzerDecl::GenFunctions(Output *out_h, Output *out_cc) + { + foreach(i, FunctionList, functions_) + { + Function *function = *i; + function->GenCode(out_h, out_cc); + } + } + +AnalyzerState::~AnalyzerState() + { + // Note: do not delete elements of statevars_, because they + // are referenced by the AnalyzerDecl. + delete statevars_; + } + +AnalyzerHelper::~AnalyzerHelper() + { + delete code_; + } + +void AnalyzerHelper::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl) + { + Output *out = 0; + switch ( helper_type_ ) + { + case MEMBER_DECLS: + out = out_h; + break; + case INIT_CODE: + case CLEANUP_CODE: + case EOF_CODE: + out = out_cc; + break; + } + ASSERT(out); + code()->GenCode(out, decl->env()); + } + +FlowField::FlowField(ID *flow_id, ParameterizedType *flow_type) + : Field(FLOW_FIELD, + TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, + flow_id, flow_type) + { + } + +void FlowField::GenInitCode(Output *out_cc, Env *env) + { + type_->GenPreParsing(out_cc, env); + } + +AnalyzerFlow::AnalyzerFlow(Direction dir, ID *type_id, ExprList *params) + : AnalyzerElement(FLOW), + dir_(dir), + type_id_(type_id) + { + if ( ! params ) + params = new ExprList(); + + // Add "this" to the list of params + params->insert(params->begin(), new Expr(this_id->clone())); + + ID *flow_id = ((dir == UP) ? upflow_id : downflow_id)->clone(); + + ParameterizedType *flow_type = new ParameterizedType(type_id_, params); + + flow_field_ = new FlowField(flow_id, flow_type); + + flow_decl_ = 0; + } + +AnalyzerFlow::~AnalyzerFlow() + { + delete flow_field_; + } + +FlowDecl *AnalyzerFlow::flow_decl() + { + DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name()); + if ( ! flow_decl_ ) + { + Decl *decl = Decl::LookUpDecl(type_id_); + if ( decl && decl->decl_type() == Decl::FLOW ) + flow_decl_ = static_cast(decl); + if ( ! flow_decl_ ) + { + throw Exception(this, + "cannot find the flow declaration"); + } + } + return flow_decl_; + } diff --git a/tools/binpac/src/pac_analyzer.h b/tools/binpac/src/pac_analyzer.h new file mode 100644 index 0000000000..a5fd5245aa --- /dev/null +++ b/tools/binpac/src/pac_analyzer.h @@ -0,0 +1,168 @@ +#ifndef pac_analyzer_h +#define pac_analyzer_h + +#include "pac_common.h" +#include "pac_field.h" +#include "pac_typedecl.h" + +class AnalyzerElement; +class AnalyzerState; +class AnalyzerAction; // defined in pac_action.h +class AnalyzerHelper; +class AnalyzerFlow; +class AnalyzerDataUnit; +class AnalyzerFunction; +class ConnDecl; +class FlowDecl; +typedef vector AnalyzerHelperList; +typedef vector FunctionList; + +class AnalyzerDecl : public TypeDecl +{ +public: + AnalyzerDecl(ID *id, DeclType decl_type, ParamList *params); + ~AnalyzerDecl(); + + void AddElements(AnalyzerElementList *elemlist); + + void Prepare(); + void GenForwardDeclaration(Output *out_h); + // void GenCode(Output *out_h, Output *out_cc); + + void GenInitCode(Output *out_cc); + void GenCleanUpCode(Output *out_cc); + + string class_name() const; + // string cookie_name() const; + +protected: + virtual void ProcessFlowElement(AnalyzerFlow *flow_elem) = 0; + virtual void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) = 0; + + // Generate public/private declarations for member functions and + // variables + void GenPubDecls(Output *out_h, Output *out_cc); + void GenPrivDecls(Output *out_h, Output *out_cc); + + // Generate the NewData() function + virtual void GenProcessFunc(Output *out_h, Output *out_cc) = 0; + + // Generate the NewGap() function + virtual void GenGapFunc(Output *out_h, Output *out_cc) = 0; + + // Generate the FlowEOF() function + virtual void GenEOFFunc(Output *out_h, Output *out_cc) = 0; + + // Generate the functions + void GenFunctions(Output *out_h, Output *out_cc); + + // Generate the action functions + void GenActions(Output *out_h, Output *out_cc); + + // Generate the helper code segments + void GenHelpers(Output *out_h, Output *out_cc); + + // Generate declarations for state variables and their set functions + void GenStateVarDecls(Output *out_h); + void GenStateVarSetFunctions(Output *out_h); + + // Generate code for initializing and cleaning up (including + // memory de-allocating) state variables + void GenStateVarInitCode(Output *out_cc); + void GenStateVarCleanUpCode(Output *out_cc); + + StateVarList *statevars_; + AnalyzerActionList *actions_; + AnalyzerHelperList *helpers_; + FunctionList *functions_; + + AnalyzerHelperList *constructor_helpers_; + AnalyzerHelperList *destructor_helpers_; + AnalyzerHelperList *eof_helpers_; +}; + +class AnalyzerElement : public Object +{ +public: + enum ElementType { STATE, ACTION, FUNCTION, HELPER, FLOW, DATAUNIT }; + AnalyzerElement(ElementType type) + : type_(type) {} + virtual ~AnalyzerElement() {} + + ElementType type() const { return type_; } + +private: + ElementType type_; +}; + +// A collection of variables representing analyzer states. +class AnalyzerState : public AnalyzerElement +{ +public: + AnalyzerState(StateVarList *statevars) + : AnalyzerElement(STATE), + statevars_(statevars) {} + ~AnalyzerState(); + + StateVarList *statevars() const { return statevars_; } + +private: + StateVarList *statevars_; +}; + +// A collection of embedded C++ code +class AnalyzerHelper : public AnalyzerElement +{ +public: + enum Type { + MEMBER_DECLS, + INIT_CODE, + CLEANUP_CODE, + EOF_CODE, + }; + AnalyzerHelper(Type helper_type, EmbeddedCode *code) + : AnalyzerElement(HELPER), + helper_type_(helper_type), + code_(code) {} + ~AnalyzerHelper(); + + Type helper_type() const { return helper_type_; } + + void GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl); + + EmbeddedCode *code() const { return code_; } + +private: + Type helper_type_; + EmbeddedCode *code_; +}; + +// The type and parameters of (uni-directional) flows of a connection. + +class FlowField : public Field +{ +public: + FlowField(ID *flow_id, ParameterizedType *flow_type); + void GenInitCode(Output *out, Env *env); +}; + +class AnalyzerFlow : public AnalyzerElement +{ +public: + enum Direction { UP, DOWN }; + AnalyzerFlow(Direction dir, ID *type_id, ExprList *params); + ~AnalyzerFlow(); + + Direction dir() const { return dir_; } + FlowField *flow_field() const { return flow_field_; } + + FlowDecl *flow_decl(); + +private: + Direction dir_; + ID *type_id_; + FlowField *flow_field_; + FlowDecl *flow_decl_; +}; + +#endif // pac_analyzer_h diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc new file mode 100644 index 0000000000..7477ba050b --- /dev/null +++ b/tools/binpac/src/pac_array.cc @@ -0,0 +1,700 @@ +#include "pac_attr.h" +#include "pac_dataptr.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_number.h" +#include "pac_output.h" +#include "pac_utils.h" +#include "pac_varfield.h" + +#include "pac_array.h" + +ArrayType::ArrayType(Type *elemtype, Expr *length) + : Type(ARRAY), elemtype_(elemtype), length_(length) + { + init(); + + switch ( elemtype_->tot() ) + { + case BUILTIN: + case PARAMETERIZED: + case STRING: + case EXTERN: + break; + + case ARRAY: + case CASE: + case DUMMY: + case EMPTY: + case RECORD: + case UNDEF: + ASSERT(0); + break; + } + } + +void ArrayType::init() + { + arraylength_var_field_ = 0; + elem_it_var_field_ = 0; + elem_var_field_ = 0; + elem_dataptr_var_field_ = 0; + elem_input_var_field_ = 0; + + elem_dataptr_until_expr_ = 0; + + end_of_array_loop_label_ = "@@@"; + + vector_str_ = strfmt("vector<%s>", elemtype_->DataTypeStr().c_str()); + + datatype_str_ = strfmt("%s *", vector_str_.c_str()); + + attr_generic_until_expr_ = 0; + attr_until_element_expr_ = 0; + attr_until_input_expr_ = 0; + } + +ArrayType::~ArrayType() + { + delete arraylength_var_field_; + delete elem_it_var_field_; + delete elem_var_field_; + delete elem_dataptr_var_field_; + delete elem_input_var_field_; + + delete elem_dataptr_until_expr_; + } + +Type *ArrayType::DoClone() const + { + Type *elemtype = elemtype_->Clone(); + if ( ! elemtype ) + return 0; + return new ArrayType(elemtype, length_); + } + +bool ArrayType::DefineValueVar() const + { + return true; + } + +string ArrayType::DataTypeStr() const + { + return datatype_str_; + } + +Type *ArrayType::ElementDataType() const + { + return elemtype_; + } + +string ArrayType::EvalElement(const string &array, const string &index) const + { + return strfmt("(*(%s))[%s]", array.c_str(), index.c_str()); + } + +const ID *ArrayType::arraylength_var() const + { + return arraylength_var_field_ ? arraylength_var_field_->id() : 0; + } + +const ID *ArrayType::elem_it_var() const + { + return elem_it_var_field_ ? elem_it_var_field_->id() : 0; + } + +const ID *ArrayType::elem_var() const + { + return elem_var_field_ ? elem_var_field_->id() : 0; + } + +const ID *ArrayType::elem_dataptr_var() const + { + return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : 0; + } + +const ID *ArrayType::elem_input_var() const + { + return elem_input_var_field_ ? elem_input_var_field_->id() : 0; + } + +void ArrayType::ProcessAttr(Attr *a) + { + Type::ProcessAttr(a); + + switch ( a->type() ) + { + case ATTR_RESTOFDATA: + { + if ( elemtype_->StaticSize(env()) != 1 ) + { + throw Exception(elemtype_, + "&restofdata can be applied" + " to only byte arrays"); + } + if ( length_ ) + { + throw Exception(length_, + "&restofdata cannot be applied" + " to arrays with specified length"); + } + attr_restofdata_ = true; + // As the array automatically extends to the end of + // data, we do not have to check boundary. + SetBoundaryChecked(); + } + break; + + case ATTR_RESTOFFLOW: + attr_restofflow_ = true; + // TODO: handle &restofflow + break; + + case ATTR_UNTIL: + { + bool ref_element = a->expr()->HasReference(element_macro_id); + bool ref_input = a->expr()->HasReference(input_macro_id); + if ( ref_element && ref_input ) + { + throw Exception(a->expr(), + "cannot reference both $element and $input " + "in the same &until---please separate them."); + } + + if ( ref_element ) + { + if ( attr_until_element_expr_ ) + { + throw Exception(a->expr(), + "multiple &until on $element"); + } + attr_until_element_expr_ = a->expr(); + } + else if ( ref_input ) + { + if ( attr_until_input_expr_ ) + { + throw Exception(a->expr(), + "multiple &until on $input"); + } + attr_until_input_expr_ = a->expr(); + } + else + { + if ( attr_generic_until_expr_ ) + { + throw Exception(a->expr(), + "multiple &until condition"); + } + attr_generic_until_expr_ = a->expr(); + } + } + break; + + default: + break; + } + } + +void ArrayType::Prepare(Env *env, int flags) + { + if ( flags & TO_BE_PARSED ) + { + ID *arraylength_var = new ID(fmt("%s__arraylength", value_var()->Name())); + ID *elem_var = new ID(fmt("%s__elem", value_var()->Name())); + ID *elem_it_var = new ID(fmt("%s__it", elem_var->Name())); + + elem_var_field_ = + new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_); + AddField(elem_var_field_); + + if ( incremental_parsing() ) + { + arraylength_var_field_ = + new PrivVarField(arraylength_var, extern_type_int->Clone()); + elem_it_var_field_ = + new PrivVarField(elem_it_var, extern_type_int->Clone()); + + AddField(arraylength_var_field_); + AddField(elem_it_var_field_); + } + else + { + arraylength_var_field_ = + new TempVarField(arraylength_var, extern_type_int->Clone()); + elem_it_var_field_ = + new TempVarField(elem_it_var, extern_type_int->Clone()); + + arraylength_var_field_->Prepare(env); + elem_it_var_field_->Prepare(env); + + // Add elem_dataptr_var only when not parsing incrementally + ID *elem_dataptr_var = + new ID(fmt("%s__dataptr", elem_var->Name())); + elem_dataptr_var_field_ = new TempVarField( + elem_dataptr_var, + extern_type_const_byteptr->Clone()); + elem_dataptr_var_field_->Prepare(env); + + // until(dataptr >= end_of_data) + elem_dataptr_until_expr_ = new Expr( + Expr::EXPR_GE, + new Expr(elem_dataptr_var->clone()), + new Expr(end_of_data->clone())); + } + + if ( attr_until_input_expr_ ) + { + elemtype_->SetUntilCheck(this); + } + + end_of_array_loop_label_ = strfmt("end_of_%s", value_var()->Name()); + } + + Type::Prepare(env, flags); + } + +void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) + { + if ( env->Evaluated(arraylength_var()) ) + return; + + if ( ! incremental_parsing() ) + { + arraylength_var_field_->GenTempDecls(out_cc, env); + arraylength_var_field_->GenInitCode(out_cc, env); + } + + if ( length_ ) + { + out_cc->println("%s = %s;", + env->LValue(arraylength_var()), + length_->EvalExpr(out_cc, env)); + + env->SetEvaluated(arraylength_var()); + + // Check for overlong array length. We cap it at the + // maximum data size as we won't store more elements. + out_cc->println("if ( t_begin_of_data + %s > t_end_of_data + 1 )", + env->LValue(arraylength_var())); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("%s = t_end_of_data - t_begin_of_data + 1;", + env->LValue(arraylength_var())); + out_cc->println("}"); + out_cc->dec_indent(); + + // Check negative array length + out_cc->println("if ( %s < 0 )", + env->LValue(arraylength_var())); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("%s = 0;", + env->LValue(arraylength_var())); + out_cc->println("}"); + out_cc->dec_indent(); + } + else if ( attr_restofdata_ ) + { + ASSERT(elemtype_->StaticSize(env) == 1); + out_cc->println("%s = (%s) - (%s);", + env->LValue(arraylength_var()), + env->RValue(end_of_data), + data.ptr_expr()); + env->SetEvaluated(arraylength_var()); + } + } + +void ArrayType::GenPubDecls(Output *out_h, Env *env) + { + Type::GenPubDecls(out_h, env); + + if ( declared_as_type() ) + { + out_h->println("int size() const { return %s ? %s->size() : 0; }", + env->RValue(value_var()), + env->RValue(value_var())); + out_h->println("%s operator[](int index) const { BINPAC_ASSERT(%s); return (*%s)[index]; }", + elemtype_->DataTypeConstRefStr().c_str(), + env->RValue(value_var()), + env->RValue(value_var())); + } + } + +void ArrayType::GenPrivDecls(Output *out_h, Env *env) + { + ASSERT(elem_var_field_->type() == elemtype_); + ASSERT(elemtype_->value_var()); + Type::GenPrivDecls(out_h, env); + } + +void ArrayType::GenInitCode(Output *out_cc, Env *env) + { + // Do not initiate the array here + // out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); + out_cc->println("%s = 0;", lvalue()); + + Type::GenInitCode(out_cc, env); + if ( incremental_parsing() ) + { + out_cc->println("%s = -1;", + env->LValue(elem_it_var())); + } + } + +void ArrayType::GenCleanUpCode(Output *out_cc, Env *env) + { + Type::GenCleanUpCode(out_cc, env); + if ( elemtype_->NeedsCleanUp() ) + { + if ( ! elem_var_field_ ) + { + ID *elem_var = new ID(fmt("%s__elem", value_var()->Name())); + elem_var_field_ = + new ParseVarField( + Field::NOT_CLASS_MEMBER, + elem_var, + elemtype_); + elem_var_field_->Prepare(env); + } + + out_cc->println("if ( %s )", env->RValue(value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + + out_cc->println("for ( int i = 0; i < (int) %s->size(); ++i )", + env->RValue(value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("%s %s = (*%s)[i];", + elemtype_->DataTypeStr().c_str(), + env->LValue(elem_var()), + lvalue()); + elemtype_->GenCleanUpCode(out_cc, env); + out_cc->println("}"); + out_cc->dec_indent(); + + out_cc->println("}"); + out_cc->dec_indent(); + } + out_cc->println("delete %s;", lvalue()); + } + +string ArrayType::GenArrayInit(Output *out_cc, Env *env, bool known_array_length) + { + string array_str; + + array_str = lvalue(); + if ( incremental_parsing() ) + { + out_cc->println("if ( %s < 0 )", + env->LValue(elem_it_var())); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("// Initialize only once"); + out_cc->println("%s = 0;", env->LValue(elem_it_var())); + } + + out_cc->println("%s = new %s;", + lvalue(), vector_str_.c_str()); + + if ( known_array_length ) + { + out_cc->println("%s->reserve(%s);", + lvalue(), env->RValue(arraylength_var())); + } + + if ( incremental_parsing() ) + { + out_cc->println("}"); + out_cc->dec_indent(); + } + + return array_str; + } + +void ArrayType::GenElementAssignment(Output *out_cc, Env *env, + string const &array_str, bool use_vector) + { + // Assign the element + if ( ! use_vector ) + { + out_cc->println("%s[%s] = %s;", + array_str.c_str(), + env->LValue(elem_it_var()), + env->LValue(elem_var())); + } + else + { + out_cc->println("%s->push_back(%s);", + array_str.c_str(), + env->LValue(elem_var())); + } + } + +void ArrayType::DoGenParseCode(Output *out_cc, Env *env, + const DataPtr& data, int flags) + { + GenArrayLength(out_cc, env, data); + + // Otherwise these variables are declared as member variables + if ( ! incremental_parsing() ) + { + // Declare and initialize temporary variables + elem_var_field_->GenInitCode(out_cc, env); + elem_it_var_field_->GenTempDecls(out_cc, env); + out_cc->println("%s = 0;", env->LValue(elem_it_var())); + env->SetEvaluated(elem_it_var()); + } + + /* + If the input length can be determined without parsing + individual elements, generate the boundary checking before + parsing (unless in the case of incremental parsing). + + There are two cases when the input length can be determined: + 1. The array has a static size; + 2. The array length can be computed before parsing and + each element is of constant size. + */ + + bool compute_size_var = false; + + if ( incremental_input() ) + { + // Do not compute size_var on incremental input + compute_size_var = false; + + if ( ! incremental_parsing() && + ( StaticSize(env) >= 0 || + ( env->Evaluated(arraylength_var()) && + elemtype_->StaticSize(env) >= 0 ) ) ) + { + GenBoundaryCheck(out_cc, env, data); + } + } + else + { + compute_size_var = AddSizeVar(out_cc, env); + } + + bool known_array_length = env->Evaluated(arraylength_var()); + string array_str = GenArrayInit(out_cc, env, known_array_length); + + bool use_vector = true; + + ASSERT(elem_it_var()); + + DataPtr elem_data(env, 0, 0); + + if ( elem_dataptr_var() ) + { + out_cc->println("const_byteptr %s = %s;", + env->LValue(elem_dataptr_var()), data.ptr_expr()); + env->SetEvaluated(elem_dataptr_var()); + + elem_data = DataPtr(env, elem_dataptr_var(), 0); + } + + string for_condition = known_array_length ? + strfmt("%s < %s", + env->LValue(elem_it_var()), + env->RValue(arraylength_var())) : + "/* forever */"; + + out_cc->println("for (; %s; ++%s)", + for_condition.c_str(), + env->LValue(elem_it_var())); + out_cc->inc_indent(); + out_cc->println("{"); + + if ( attr_generic_until_expr_ ) + GenUntilCheck(out_cc, env, attr_generic_until_expr_, true); + + if ( elem_dataptr_var() ) + GenUntilCheck(out_cc, env, elem_dataptr_until_expr_, false); + + elemtype_->GenPreParsing(out_cc, env); + elemtype_->GenParseCode(out_cc, env, elem_data, flags); + + if ( incremental_parsing() ) + { + out_cc->println("if ( ! %s )", + elemtype_->parsing_complete(env).c_str()); + out_cc->inc_indent(); + out_cc->println("goto %s;", kNeedMoreData); + out_cc->dec_indent(); + } + + GenElementAssignment(out_cc, env, array_str, use_vector); + + if ( elem_dataptr_var() ) + { + out_cc->println("%s += %s;", + env->LValue(elem_dataptr_var()), + elemtype_->DataSize(0, env, elem_data).c_str()); + out_cc->println("BINPAC_ASSERT(%s <= %s);", + env->RValue(elem_dataptr_var()), + env->RValue(end_of_data)); + } + + if ( attr_until_element_expr_ ) + GenUntilCheck(out_cc, env, attr_until_element_expr_, false); + + if ( elemtype_->IsPointerType() ) + out_cc->println("%s = 0;", env->LValue(elem_var())); + + out_cc->println("}"); + out_cc->dec_indent(); + + out_cc->dec_indent(); + out_cc->println("%s: ;", end_of_array_loop_label_.c_str()); + out_cc->inc_indent(); + + if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) ) + { + // Compute the data size + out_cc->println("%s = %s - (%s);", + env->LValue(size_var()), + env->RValue(elem_dataptr_var()), + data.ptr_expr()); + env->SetEvaluated(size_var()); + } + } + +void ArrayType::GenUntilInputCheck(Output *out_cc, Env *env) + { + ID *elem_input_var_id = new ID( + fmt("%s__elem_input", value_var()->Name())); + elem_input_var_field_ = new TempVarField( + elem_input_var_id, extern_type_const_bytestring->Clone()); + elem_input_var_field_->Prepare(env); + + out_cc->println("%s %s(%s, %s);", + extern_type_const_bytestring->DataTypeStr().c_str(), + env->LValue(elem_input_var()), + env->RValue(begin_of_data), + env->RValue(end_of_data)); + env->SetEvaluated(elem_input_var()); + + GenUntilCheck(out_cc, env, attr_until_input_expr_, true); + } + +void ArrayType::GenUntilCheck(Output *out_cc, Env *env, + Expr *until_expr, bool delete_elem) + { + ASSERT(until_expr); + + Env check_env(env, this); + check_env.AddMacro(element_macro_id, + new Expr(elem_var()->clone())); + if ( elem_input_var() ) + { + check_env.AddMacro(input_macro_id, + new Expr(elem_input_var()->clone())); + } + + out_cc->println("// Check &until(%s)", until_expr->orig()); + out_cc->println("if ( %s )", + until_expr->EvalExpr(out_cc, &check_env)); + out_cc->inc_indent(); + out_cc->println("{"); + if ( parsing_complete_var() ) + { + out_cc->println("%s = true;", + env->LValue(parsing_complete_var())); + } + + if ( elemtype_->IsPointerType() ) + { + if ( delete_elem ) + elemtype_->GenCleanUpCode(out_cc, env); + else + out_cc->println("%s = 0;", env->LValue(elem_var())); + } + + out_cc->println("goto %s;", end_of_array_loop_label_.c_str()); + out_cc->println("}"); + out_cc->dec_indent(); + } + +void ArrayType::GenDynamicSize(Output *out_cc, Env *env, + const DataPtr& data) + { + ASSERT(! incremental_input()); + DEBUG_MSG("Generating dynamic size for array `%s'\n", + value_var()->Name()); + + int elem_w = elemtype_->StaticSize(env); + if ( elem_w >= 0 && + ! attr_until_element_expr_ && + ! attr_until_input_expr_ && + ( length_ || attr_restofdata_ ) ) + { + // If the elements have a fixed size, + // we only need to compute the number of elements + bool compute_size_var = AddSizeVar(out_cc, env); + ASSERT(compute_size_var); + GenArrayLength(out_cc, env, data); + ASSERT(env->Evaluated(arraylength_var())); + out_cc->println("%s = %d * %s;", + env->LValue(size_var()), elem_w, env->RValue(arraylength_var())); + env->SetEvaluated(size_var()); + } + else + { + // Otherwise we need parse the array dynamically + GenParseCode(out_cc, env, data, 0); + } + } + +int ArrayType::StaticSize(Env *env) const + { + int num = 0; + + if ( ! length_ || ! length_->ConstFold(env, &num) ) + return -1; + + int elem_w = elemtype_->StaticSize(env); + if ( elem_w < 0 ) + return -1; + + DEBUG_MSG("static size of %s:%s = %d * %d\n", + decl_id()->Name(), lvalue(), elem_w, num); + + return num * elem_w; + } + +void ArrayType::SetBoundaryChecked() + { + Type::SetBoundaryChecked(); + elemtype_->SetBoundaryChecked(); + } + +void ArrayType::DoMarkIncrementalInput() + { + elemtype_->MarkIncrementalInput(); + } + +bool ArrayType::RequiresAnalyzerContext() + { + return Type::RequiresAnalyzerContext() || + ( length_ && length_->RequiresAnalyzerContext() ) || + elemtype_->RequiresAnalyzerContext(); + } + +bool ArrayType::DoTraverse(DataDepVisitor *visitor) + { + if ( ! Type::DoTraverse(visitor) ) + return false; + + if ( length_ && ! length_->Traverse(visitor) ) + return false; + + if ( ! elemtype_->Traverse(visitor) ) + return false; + + return true; + } diff --git a/tools/binpac/src/pac_array.h b/tools/binpac/src/pac_array.h new file mode 100644 index 0000000000..022ef2ea4a --- /dev/null +++ b/tools/binpac/src/pac_array.h @@ -0,0 +1,92 @@ +#ifndef pac_array_h +#define pac_array_h + +#include "pac_common.h" +#include "pac_type.h" + +// Fixed-length array and variable length sequence with an ending pattern + +class ArrayType : public Type +{ +public: + ArrayType(Type *arg_elemtype, Expr *arg_length = 0); + ~ArrayType(); + + bool DefineValueVar() const; + string DataTypeStr() const; + string DefaultValue() const { return "0"; } + Type *ElementDataType() const; + + string EvalElement(const string &array, const string &index) const; + + void ProcessAttr(Attr *a); + + void Prepare(Env *env, int flags); + + void GenPubDecls(Output *out, Env *env); + void GenPrivDecls(Output *out, Env *env); + + void GenInitCode(Output *out, Env *env); + void GenCleanUpCode(Output *out, Env *env); + + int StaticSize(Env *env) const; + + void SetBoundaryChecked(); + void GenUntilInputCheck(Output *out_cc, Env *env); + + bool IsPointerType() const { return true; } + +protected: + void init(); + + void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); + void GenDynamicSize(Output *out, Env *env, const DataPtr& data); + void GenArrayLength(Output *out_cc, Env *env, const DataPtr& data); + string GenArrayInit(Output *out_cc, Env *env, bool known_array_length); + void GenElementAssignment(Output *out_cc, Env *env, + string const &array_str, bool use_vector); + void GenUntilCheck(Output *out_cc, Env *env, + Expr *until_condition, bool delete_elem); + + bool ByteOrderSensitive() const + { + return elemtype_->RequiresByteOrder(); + } + bool RequiresAnalyzerContext(); + + Type *DoClone() const; + + void DoMarkIncrementalInput(); + + const ID *arraylength_var() const; + const ID *elem_it_var() const; + const ID *elem_var() const; + const ID *elem_dataptr_var() const; + const ID *elem_input_var() const; + +protected: + bool DoTraverse(DataDepVisitor *visitor); + +private: + Type *elemtype_; + Expr *length_; + + string vector_str_; + string datatype_str_; + string end_of_array_loop_label_; + + Field *arraylength_var_field_; + Field *elem_it_var_field_; + Field *elem_var_field_; + Field *elem_dataptr_var_field_; + Field *elem_input_var_field_; + + // This does not come from &until, but is internally generated + Expr *elem_dataptr_until_expr_; + + Expr *attr_generic_until_expr_; + Expr *attr_until_element_expr_; + Expr *attr_until_input_expr_; +}; + +#endif // pac_array_h diff --git a/tools/binpac/src/pac_attr.cc b/tools/binpac/src/pac_attr.cc new file mode 100644 index 0000000000..cfd6263be6 --- /dev/null +++ b/tools/binpac/src/pac_attr.cc @@ -0,0 +1,57 @@ +#include "pac_attr.h" +#include "pac_expr.h" + +bool Attr::DoTraverse(DataDepVisitor *visitor) + { + if ( expr_ && ! expr_->Traverse(visitor) ) + return false; + return true; + } + +bool Attr::RequiresAnalyzerContext() const + { + return (expr_ && expr_->RequiresAnalyzerContext()); + } + +void Attr::init() + { + expr_ = 0; + seqend_ = 0; + } + +Attr::Attr(AttrType type) + : DataDepElement(DataDepElement::ATTR) + { + type_ = type; + init(); + } + +Attr::Attr(AttrType type, Expr *expr) + : DataDepElement(DataDepElement::ATTR) + { + type_ = type; + init(); + expr_ = expr; + } + +Attr::Attr(AttrType type, ExprList *exprlist) + : DataDepElement(DataDepElement::ATTR) + { + type_ = type; + init(); + expr_ = new Expr(exprlist); + } + +Attr::Attr(AttrType type, SeqEnd *seqend) + : DataDepElement(DataDepElement::ATTR) + { + type_ = type; + init(); + seqend_ = seqend; + } + +LetAttr::LetAttr(FieldList *letfields) + : Attr(ATTR_LET) + { + letfields_ = letfields; + } diff --git a/tools/binpac/src/pac_attr.h b/tools/binpac/src/pac_attr.h new file mode 100644 index 0000000000..67bdbedc8d --- /dev/null +++ b/tools/binpac/src/pac_attr.h @@ -0,0 +1,61 @@ +#ifndef pac_attr_h +#define pac_attr_h + +#include "pac_common.h" +#include "pac_datadep.h" + +enum AttrType { + ATTR_BYTEORDER, + ATTR_CHECK, + ATTR_CHUNKED, + ATTR_EXPORTSOURCEDATA, + ATTR_IF, + ATTR_LENGTH, + ATTR_LET, + ATTR_LINEBREAKER, + ATTR_MULTILINE, + ATTR_ONELINE, + ATTR_REFCOUNT, + ATTR_REQUIRES, + ATTR_RESTOFDATA, + ATTR_RESTOFFLOW, + ATTR_TRANSIENT, + ATTR_UNTIL, +}; + +class Attr : public Object, public DataDepElement +{ +public: + Attr(AttrType type); + Attr(AttrType type, Expr *expr); + Attr(AttrType type, ExprList *exprlist); + Attr(AttrType type, SeqEnd *seqend); + + AttrType type() const { return type_; } + Expr *expr() const { return expr_; } + SeqEnd *seqend() const { return seqend_; } + + bool RequiresAnalyzerContext() const; + +protected: + bool DoTraverse(DataDepVisitor *visitor); + +protected: + void init(); + + AttrType type_; + Expr *expr_; + SeqEnd *seqend_; +}; + +class LetAttr : public Attr +{ +public: + LetAttr(FieldList *letfields); + FieldList *letfields() const { return letfields_; } + +private: + FieldList *letfields_; +}; + +#endif // pac_attr_h diff --git a/tools/binpac/src/pac_btype.cc b/tools/binpac/src/pac_btype.cc new file mode 100644 index 0000000000..a7df6f7bf3 --- /dev/null +++ b/tools/binpac/src/pac_btype.cc @@ -0,0 +1,144 @@ +#include "pac_btype.h" +#include "pac_dataptr.h" +#include "pac_id.h" +#include "pac_output.h" + +Type *BuiltInType::DoClone() const + { + return new BuiltInType(bit_type()); + } + +bool BuiltInType::IsNumericType() const + { + BITType t = bit_type(); + return (t == INT8 || t == INT16 || t == INT32 || + t == UINT8 || t == UINT16 || t == UINT32); + } + +bool BuiltInType::CompatibleBuiltInTypes(BuiltInType *type1, + BuiltInType *type2) + { + return type1->IsNumericType() && type2->IsNumericType(); + } + +static const char* basic_pactype_name[] = { +# define TYPE_DEF(name, pactype, ctype, size) pactype, +# include "pac_type.def" +# undef TYPE_DEF + 0, +}; + +void BuiltInType::static_init() + { + for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type ) + { + Type::AddPredefinedType( + basic_pactype_name[bit_type], + new BuiltInType((BITType) bit_type)); + } + } + +int BuiltInType::LookUpByName(const char* name) + { + ASSERT(0); + for ( int i = 0; basic_pactype_name[i]; ++i ) + if ( strcmp(basic_pactype_name[i], name) == 0 ) + return i; + return -1; + } + +static const char* basic_ctype_name[] = { +# define TYPE_DEF(name, pactype, ctype, size) ctype, +# include "pac_type.def" +# undef TYPE_DEF + 0, +}; + +bool BuiltInType::DefineValueVar() const + { + return bit_type_ != EMPTY; + } + +string BuiltInType::DataTypeStr() const + { + return basic_ctype_name[bit_type_]; + } + +int BuiltInType::StaticSize(Env* /* env */) const + { + static const size_t basic_type_size[] = + { +# define TYPE_DEF(name, pactype, ctype, size) size, +# include "pac_type.def" +# undef TYPE_DEF + }; + + return basic_type_size[bit_type_]; + } + +void BuiltInType::DoMarkIncrementalInput() + { + if ( bit_type_ == EMPTY ) + return; + Type::DoMarkIncrementalInput(); + } + +void BuiltInType::GenInitCode(Output* out_cc, Env* env) + { + if ( bit_type_ != EMPTY ) + out_cc->println("%s = 0;", env->LValue(value_var())); + Type::GenInitCode(out_cc, env); + } + +void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) + { + /* should never be called */ + ASSERT(0); + } + +void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, + const DataPtr& data, int flags) + { + if ( bit_type_ == EMPTY ) + return; + + // There is no need to generate the size variable + // out_cc->println("%s = sizeof(%s);", size_var(), DataTypeStr().c_str()); + + GenBoundaryCheck(out_cc, env, data); + + if ( anonymous_value_var() ) + return; + + switch ( bit_type_ ) + { + case EMPTY: + // do nothing + break; + + case INT8: + case UINT8: + out_cc->println("%s = *((%s const *) (%s));", + lvalue(), DataTypeStr().c_str(), data.ptr_expr()); + break; + case INT16: + case UINT16: + case INT32: + case UINT32: +#if 0 + out_cc->println("%s = UnMarshall<%s>(%s, %s);", + lvalue(), + DataTypeStr().c_str(), + data.ptr_expr(), + EvalByteOrder(out_cc, env).c_str()); +#else + out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", + lvalue(), + EvalByteOrder(out_cc, env).c_str(), + DataTypeStr().c_str(), + data.ptr_expr()); +#endif + break; + } + } + diff --git a/tools/binpac/src/pac_btype.h b/tools/binpac/src/pac_btype.h new file mode 100644 index 0000000000..4bdbf9390b --- /dev/null +++ b/tools/binpac/src/pac_btype.h @@ -0,0 +1,52 @@ +#ifndef pac_btype_h +#define pac_btype_h + +#include "pac_type.h" + +class BuiltInType : public Type +{ +public: + enum BITType { +# define TYPE_DEF(name, pactype, ctype, size) name, +# include "pac_type.def" +# undef TYPE_DEF + }; + + static int LookUpByName(const char *name); + + BuiltInType(BITType bit_type) + : Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN), + bit_type_(bit_type) {} + + BITType bit_type() const { return bit_type_; } + + bool IsNumericType() const; + + bool DefineValueVar() const; + string DataTypeStr() const; + string DefaultValue() const { return "0"; } + + int StaticSize(Env *env) const; + + bool IsPointerType() const { return false; } + + bool ByteOrderSensitive() const { return StaticSize(0) >= 2; } + + void GenInitCode(Output *out_cc, Env *env); + + void DoMarkIncrementalInput(); + +protected: + void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); + void GenDynamicSize(Output *out, Env *env, const DataPtr& data); + Type *DoClone() const; + + BITType bit_type_; + +public: + static void static_init(); + static bool CompatibleBuiltInTypes(BuiltInType *type1, + BuiltInType *type2); +}; + +#endif // pac_btype_h diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc new file mode 100644 index 0000000000..b809d61b6e --- /dev/null +++ b/tools/binpac/src/pac_case.cc @@ -0,0 +1,391 @@ +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_typedecl.h" +#include "pac_utils.h" + +#include "pac_case.h" + +CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) + : Type(CASE), index_expr_(index_expr), cases_(cases) + { + index_var_ = 0; + foreach(i, CaseFieldList, cases_) + AddField(*i); + } + +CaseType::~CaseType() + { + delete index_var_; + delete index_expr_; + delete cases_; + } + +void CaseType::AddCaseField(CaseField *f) + { + // All fields must be added before Prepare() + ASSERT(!env()); + + AddField(f); + cases_->push_back(f); + } + +bool CaseType::DefineValueVar() const + { + return false; + } + +string CaseType::DataTypeStr() const + { + ASSERT(type_decl()); + return strfmt("%s *", type_decl()->class_name().c_str()); + } + +Type *CaseType::ValueType() const + { + foreach (i, CaseFieldList, cases_) + { + CaseField *c = *i; + return c->type(); + } + ASSERT(0); + return 0; + } + +string CaseType::DefaultValue() const + { + return ValueType()->DefaultValue(); + } + +void CaseType::Prepare(Env* env, int flags) + { + ASSERT(flags & TO_BE_PARSED); + + index_var_ = new ID(fmt("%s_case_index", value_var()->Name())); + env->AddID(index_var_, MEMBER_VAR, extern_type_int); + + // Sort the cases_ to put the default case at the end of the list + CaseFieldList::iterator default_case_it = + cases_->end(); // to avoid warning + CaseField *default_case = 0; + + foreach (i, CaseFieldList, cases_) + { + CaseField *c = *i; + if ( ! c->index() ) + { + if ( default_case ) + throw Exception(c, "duplicate default case"); + default_case_it = i; + default_case = c; + } + } + if ( default_case ) + { + cases_->erase(default_case_it); + cases_->push_back(default_case); + } + + foreach (i, CaseFieldList, cases_) + { + CaseField *c = *i; + c->set_index_var(index_var_); + c->set_case_type(this); + } + + Type::Prepare(env, flags); + } + +void CaseType::GenPrivDecls(Output* out_h, Env* env) + { + out_h->println("int %s;", env->LValue(index_var_)); + Type::GenPrivDecls(out_h, env); + } + +void CaseType::GenPubDecls(Output* out_h, Env* env) + { + out_h->println("int %s const { return %s; }", + env->RValue(index_var_), env->LValue(index_var_)); + Type::GenPubDecls(out_h, env); + } + +void CaseType::GenInitCode(Output* out_cc, Env* env) + { + out_cc->println("%s = -1;", env->LValue(index_var_)); + Type::GenInitCode(out_cc, env); + } + +void CaseType::GenCleanUpCode(Output* out_cc, Env* env) + { + Type::GenCleanUpCode(out_cc, env); + + env->set_in_branch(true); + out_cc->println("switch ( %s )", env->RValue(index_var_)); + out_cc->inc_indent(); + out_cc->println("{"); + foreach (i, CaseFieldList, cases_) + { + CaseField *c = *i; + c->GenCleanUpCode(out_cc, env); + } + out_cc->println("}"); + out_cc->dec_indent(); + env->set_in_branch(false); + } + +void CaseType::DoGenParseCode(Output* out_cc, Env* env, + const DataPtr& data, int flags) + { + if ( StaticSize(env) >= 0 ) + GenBoundaryCheck(out_cc, env, data); + + bool compute_size_var = false; + + if ( ! incremental_input() ) + compute_size_var = AddSizeVar(out_cc, env); + + out_cc->println("%s = %s;", + env->LValue(index_var_), index_expr_->EvalExpr(out_cc, env)); + env->SetEvaluated(index_var_); + + env->set_in_branch(true); + out_cc->println("switch ( %s )", env->RValue(index_var_)); + out_cc->inc_indent(); + out_cc->println("{"); + bool has_default_case = false; + foreach (i, CaseFieldList, cases_) + { + CaseField *c = *i; + c->GenParseCode(out_cc, env, data, + compute_size_var ? size_var() : 0); + if ( c->IsDefaultCase() ) + has_default_case = true; + } + + if ( ! has_default_case ) + { + out_cc->println("default:"); + out_cc->inc_indent(); + out_cc->println("throw ExceptionInvalidCaseIndex(\"%s\", %s);", + decl_id()->Name(), env->RValue(index_var_)); + out_cc->println("break;"); + out_cc->dec_indent(); + } + out_cc->println("}"); + out_cc->dec_indent(); + env->set_in_branch(false); + + if ( compute_size_var ) + env->SetEvaluated(size_var()); + } + +void CaseType::GenDynamicSize(Output* out_cc, Env* env, + const DataPtr& data) + { + GenParseCode(out_cc, env, data, 0); + } + +int CaseType::StaticSize(Env* env) const + { + int static_w = -1; + foreach (i, CaseFieldList, cases_) + { + CaseField *c = *i; + int w = c->StaticSize(env); + if ( w < 0 || ( static_w >= 0 && w != static_w ) ) + return -1; + static_w = w; + } + return static_w; + } + +void CaseType::SetBoundaryChecked() + { + Type::SetBoundaryChecked(); + foreach (i, CaseFieldList, cases_) + { + CaseField *c = *i; + c->SetBoundaryChecked(); + } + } + +void CaseType::DoMarkIncrementalInput() + { + foreach (i, CaseFieldList, cases_) + { + CaseField *c = *i; + c->type()->MarkIncrementalInput(); + } + } + +bool CaseType::ByteOrderSensitive() const + { + foreach (i, CaseFieldList, cases_) + { + CaseField *c = *i; + if ( c->RequiresByteOrder() ) + return true; + } + return false; + } + +CaseField::CaseField(ExprList* index, ID* id, Type* type) + : Field(CASE_FIELD, + TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, + id, type), + index_(index) + { + ASSERT(type_); + type_->set_value_var(id, MEMBER_VAR); + case_type_ = 0; + } + +CaseField::~CaseField() + { + delete_list(ExprList, index_); + } + +void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env) + { + if ( index_list ) + { + foreach(i, ExprList, index_list) + { + Expr *index_expr = *i; + int index_const; + + if ( ! index_expr->ConstFold(env, &index_const) ) + throw ExceptionNonConstExpr(index_expr); + out_cc->println("case %d:", index_const); + } + } + else + { + out_cc->println("default:"); + } + } + +void CaseField::Prepare(Env* env) + { + ASSERT(index_var_); + Field::Prepare(env); + } + +void CaseField::GenPubDecls(Output* out_h, Env* env) + { + if ( ! ((flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER)) ) + return; + + // Skip type "empty" + if ( type_->DataTypeStr().empty() ) + return; + + out_h->println("%s %s const", + type_->DataTypeConstRefStr().c_str(), env->RValue(id_)); + + out_h->inc_indent(); + out_h->println("{"); + + if ( ! index_ ) + out_h->println("return %s;", lvalue()); + else + { + out_h->println("switch ( %s )", env->RValue(index_var_)); + out_h->inc_indent(); + out_h->println("{"); + GenCaseStr(index_, out_h, env); + out_h->inc_indent(); + out_h->println("break; // OK"); + out_h->dec_indent(); + + out_h->println("default:"); + out_h->inc_indent(); + out_h->println("throw ExceptionInvalidCase(\"%s\", %s, \"%s\");", + id_->LocName(), + env->RValue(index_var_), + OrigExprList(index_).c_str()); + out_h->println("break;"); + out_h->dec_indent(); + + out_h->println("}"); + out_h->dec_indent(); + + out_h->println("return %s;", lvalue()); + } + + out_h->println("}"); + out_h->dec_indent(); + } + +void CaseField::GenInitCode(Output* out_cc, Env* env) + { + // GenCaseStr(index_, out_cc, env); + // out_cc->inc_indent(); + // out_cc->println("{"); + // out_cc->println("// Initialize \"%s\"", id_->Name()); + type_->GenInitCode(out_cc, env); + // out_cc->println("}"); + // out_cc->println("break;"); + // out_cc->dec_indent(); + } + +void CaseField::GenCleanUpCode(Output* out_cc, Env* env) + { + GenCaseStr(index_, out_cc, env); + out_cc->inc_indent(); + out_cc->println("// Clean up \"%s\"", id_->Name()); + out_cc->println("{"); + if ( ! anonymous_field() ) + type_->GenCleanUpCode(out_cc, env); + out_cc->println("}"); + out_cc->println("break;"); + out_cc->dec_indent(); + } + +void CaseField::GenParseCode(Output* out_cc, Env* env, + const DataPtr& data, const ID* size_var) + { + GenCaseStr(index_, out_cc, env); + out_cc->inc_indent(); + out_cc->println("// Parse \"%s\"", id_->Name()); + out_cc->println("{"); + + { + Env case_env(env, this); + Env *env = &case_env; + + type_->GenPreParsing(out_cc, env); + type_->GenParseCode(out_cc, env, data, 0); + if ( size_var ) + { + out_cc->println("%s = %s;", + env->LValue(size_var), + type_->DataSize(out_cc, env, data).c_str()); + } + if ( type_->incremental_input() ) + { + ASSERT(case_type()->parsing_complete_var()); + out_cc->println("%s = %s;", + env->LValue(case_type()->parsing_complete_var()), + env->RValue(type_->parsing_complete_var())); + } + out_cc->println("}"); + } + + out_cc->println("break;"); + out_cc->dec_indent(); + } + +bool CaseField::DoTraverse(DataDepVisitor *visitor) + { + return Field::DoTraverse(visitor) && + type()->Traverse(visitor); + } + +bool CaseField::RequiresAnalyzerContext() const + { + return Field::RequiresAnalyzerContext() || + type()->RequiresAnalyzerContext(); + } diff --git a/tools/binpac/src/pac_case.h b/tools/binpac/src/pac_case.h new file mode 100644 index 0000000000..c9e416cfe1 --- /dev/null +++ b/tools/binpac/src/pac_case.h @@ -0,0 +1,99 @@ +#ifndef pac_case_h +#define pac_case_h + +#include "pac_common.h" +#include "pac_field.h" +#include "pac_id.h" +#include "pac_type.h" + +class CaseType : public Type +{ +public: + CaseType(Expr *index, CaseFieldList *cases); + ~CaseType(); + + void AddCaseField(CaseField *f); + + bool DefineValueVar() const; + string DataTypeStr() const; + string DefaultValue() const; + + void Prepare(Env *env, int flags); + + void GenPubDecls(Output *out, Env *env); + void GenPrivDecls(Output *out, Env *env); + + void GenInitCode(Output *out, Env *env); + void GenCleanUpCode(Output *out, Env *env); + + int StaticSize(Env *env) const; + + void SetBoundaryChecked(); + + Type *ValueType() const; + + bool IsPointerType() const { return ValueType()->IsPointerType(); } + +protected: + void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); + void GenDynamicSize(Output *out, Env *env, const DataPtr& data); + Type *DoClone() const { return 0; } + void DoMarkIncrementalInput(); + + bool ByteOrderSensitive() const; + + Expr *index_expr_; + ID *index_var_; + CaseFieldList *cases_; + + typedef map member_map_t; + member_map_t member_map_; +}; + +class CaseField : public Field +{ +public: + CaseField(ExprList *index, ID *id, Type *type); + ~CaseField(); + + CaseType *case_type() const { return case_type_; } + void set_case_type(CaseType *t) { case_type_ = t; } + + ExprList *index() const { return index_; } + + const char *lvalue() const { return type_->lvalue(); } + + const char *CaseStr(Env *env); + void set_index_var(const ID *var) { index_var_ = var; } + + void Prepare(Env *env); + + void GenPubDecls(Output *out, Env *env); + + void GenInitCode(Output *out, Env *env); + void GenCleanUpCode(Output *out, Env *env); + void GenParseCode(Output *out, Env *env, + const DataPtr& data, const ID *size_var); + + int StaticSize(Env *env) const { return type_->StaticSize(env); } + + bool IsDefaultCase() const { return ! index_; } + void SetBoundaryChecked() { type_->SetBoundaryChecked(); } + + bool RequiresByteOrder() const { return type_->RequiresByteOrder(); } + bool RequiresAnalyzerContext() const; + +protected: + bool DoTraverse(DataDepVisitor *visitor); + +protected: + CaseType *case_type_; + ExprList *index_; + const ID *index_var_; +}; + +// Generate a list of "case X:" lines from index_list. Each index +// expression must be constant foldable. +void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env); + +#endif // pac_case_h diff --git a/tools/binpac/src/pac_cclass.h b/tools/binpac/src/pac_cclass.h new file mode 100644 index 0000000000..87a7595996 --- /dev/null +++ b/tools/binpac/src/pac_cclass.h @@ -0,0 +1,81 @@ +#ifndef pac_cclass_h +#define pac_cclass_h + +class CClass; +class CClassMember; +class CClassMethod; +class CType; +class CVariable; + +typedef vector CClassMemberList; +typedef vector CClassMethodList; +typedef vector CVariableList; + +#include "pac_common.h" + +// Represents a C++ class. +// +// For now we adopt a simple model: +// +// 1. All members have a protected member variable "name_" and a +// public constant access method "name()". +// +// 2. All methods are public. +// +// 3. We do not check repeated names. + +class CClass +{ +public: + CClass(const string &class_name); + + void AddMember(CClassMember *member); + void AddMethod(CClassMember *method); + + void GenForwardDeclaration(Output *out_h); + void GenCode(Output *out_h, Output *out_cc); + +protected: + string class_name_; + CClassMemberList *members_; + CClassMethodList *methods_; +}; + +class CVariable +{ +public: + CClassMember(const string &name, CType *type); + + string name() const { return name_; } + CType *type() const { return type_; } + +protected: + string name_; + CType *type_; +}; + +class CClassMember +{ +public: + CClassMember(CVariable *var); + void GenCode(Output *out_h, Output *out_cc); + + string decl() const; + +protected: + CVariable *var_; +}; + +class CClassMethod +{ +public: + CClassMethod(CVariable *var, CVariableList *params); + + string decl() const; + +protected: + CVariable *var_; + CVariableList *params_; +}; + +#endif // pac_cclass_h diff --git a/tools/binpac/src/pac_common.h b/tools/binpac/src/pac_common.h new file mode 100644 index 0000000000..81e59c184e --- /dev/null +++ b/tools/binpac/src/pac_common.h @@ -0,0 +1,134 @@ +#ifndef pac_common_h +#define pac_common_h + +#include "pac_utils.h" + +#include + +#include +#include +#include + +using namespace std; + +extern bool FLAGS_pac_debug; +extern vector FLAGS_include_directories; +extern string input_filename; +extern int line_number; + +// Definition of class Object, which is the base class for all objects +// representing language elements -- identifiers, types, expressions, +// etc. + +class Object +{ +public: + Object() + { + filename = input_filename; + line_num = line_number; + location = strfmt("%s:%d", filename.c_str(), line_number); + } + + ~Object() + { + } + + const char* Location() const { return location.c_str(); } + +protected: + string filename; + int line_num; + string location; +}; + +class ActionParam; +class ActionParamType; +class AnalyzerAction; +class AnalyzerContextDecl; +class AnalyzerDecl; +class AnalyzerElement; +class ArrayType; +class Attr; +class CClass; +class CType; +class ConstString; +class CaseExpr; +class CaseField; +class ContextField; +class DataPtr; +class Decl; +class EmbeddedCode; +class Enum; +class Env; +class ExternType; +class Expr; +class Field; +class Function; +class InputBuffer; +class LetDef; +class LetField; +class ID; +class Number; +class Output; +class PacPrimitive; +class Param; +class ParameterizedType; +class RecordType; +class RecordField; +class RecordDataField; +class RecordPaddingField; +class RegEx; +class SeqEnd; +class StateVar; +class Type; +class TypeDecl; +class WithInputField; + +// The ID of the current declaration. +extern const ID* current_decl_id; + +typedef vector ActionParamList; +typedef vector AnalyzerActionList; +typedef vector AnalyzerElementList; +typedef vector AttrList; +typedef vector CaseExprList; +typedef vector CaseFieldList; +typedef vector ContextFieldList; +typedef vector DeclList; +typedef vector EnumList; +typedef vector ExprList; +typedef vector FieldList; +typedef vector LetFieldList; +typedef vector NumList; +typedef vector ParamList; +typedef vector RecordFieldList; +typedef vector StateVarList; + +#define foreach(i, ct, pc) \ + if ( pc ) \ + for ( ct::iterator i = (pc)->begin(); i != (pc)->end(); ++i ) + +#define delete_list(ct, pc) \ + { \ + foreach(delete_list_i, ct, pc) \ + delete *delete_list_i; \ + delete pc; \ + pc = 0; \ + } + +// Constants +const char * const kComputeFrameLength = "compute_frame_length"; +const char * const kFlowBufferClass = "FlowBuffer"; +const char * const kFlowBufferVar = "flow_buffer"; +const char * const kFlowEOF = "FlowEOF"; +const char * const kFlowGap = "NewGap"; +const char * const kInitialBufferLengthFunc = "initial_buffer_length"; +const char * const kNeedMoreData = "need_more_data"; +const char * const kNewData = "NewData"; +const char * const kParseFuncWithBuffer = "ParseBuffer"; +const char * const kParseFuncWithoutBuffer = "Parse"; +const char * const kRefCountClass = "binpac::RefCount"; +const char * const kTypeWithLengthClass = "binpac::TypeWithLength"; + +#endif // pac_common_h diff --git a/tools/binpac/src/pac_conn.cc b/tools/binpac/src/pac_conn.cc new file mode 100644 index 0000000000..d9159cae5a --- /dev/null +++ b/tools/binpac/src/pac_conn.cc @@ -0,0 +1,169 @@ +#include "pac_analyzer.h" +#include "pac_dataunit.h" +#include "pac_embedded.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_flow.h" +#include "pac_output.h" +#include "pac_paramtype.h" +#include "pac_type.h" + +#include "pac_conn.h" + +ConnDecl::ConnDecl(ID *conn_id, + ParamList *params, + AnalyzerElementList *elemlist) + : AnalyzerDecl(conn_id, CONN, params) + { + flows_[0] = flows_[1] = 0; + AddElements(elemlist); + data_type_ = new ParameterizedType(conn_id->clone(), 0); + } + +ConnDecl::~ConnDecl() + { + delete flows_[0]; + delete flows_[1]; + } + +void ConnDecl::AddBaseClass(vector *base_classes) const + { + base_classes->push_back("binpac::ConnectionAnalyzer"); + } + +void ConnDecl::ProcessFlowElement(AnalyzerFlow *flow_elem) + { + int flow_index; + + if ( flow_elem->dir() == AnalyzerFlow::UP ) + flow_index = 0; + else + flow_index = 1; + + if ( flows_[flow_index] ) + { + throw Exception(flow_elem, + fmt("%sflow already defined", + flow_index == 0 ? "up" : "down")); + } + + flows_[flow_index] = flow_elem; + type_->AddField(flow_elem->flow_field()); + } + +void ConnDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) + { + throw Exception( + dataunit_elem, + "dataunit should be defined in only a flow declaration"); + } + +void ConnDecl::Prepare() + { + AnalyzerDecl::Prepare(); + + flows_[0]->flow_decl()->set_conn_decl(this); + flows_[1]->flow_decl()->set_conn_decl(this); + } + +void ConnDecl::GenPubDecls(Output *out_h, Output *out_cc) + { + AnalyzerDecl::GenPubDecls(out_h, out_cc); + } + +void ConnDecl::GenPrivDecls(Output *out_h, Output *out_cc) + { + AnalyzerDecl::GenPrivDecls(out_h, out_cc); + } + +void ConnDecl::GenEOFFunc(Output *out_h, Output *out_cc) + { + string proto = strfmt("%s(bool is_orig)", kFlowEOF); + + out_h->println("void %s;", proto.c_str()); + + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + + out_cc->println("if ( is_orig )"); + out_cc->inc_indent(); + out_cc->println("%s->%s();", + env_->LValue(upflow_id), + kFlowEOF); + out_cc->dec_indent(); + out_cc->println("else"); + out_cc->inc_indent(); + out_cc->println("%s->%s();", + env_->LValue(downflow_id), + kFlowEOF); + + foreach(i, AnalyzerHelperList, eof_helpers_) + { + (*i)->GenCode(0, out_cc, this); + } + + out_cc->dec_indent(); + + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); + } + +void ConnDecl::GenGapFunc(Output *out_h, Output *out_cc) + { + string proto = strfmt("%s(bool is_orig, int gap_length)", kFlowGap); + + out_h->println("void %s;", proto.c_str()); + + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + + out_cc->println("if ( is_orig )"); + out_cc->inc_indent(); + out_cc->println("%s->%s(gap_length);", + env_->LValue(upflow_id), + kFlowGap); + out_cc->dec_indent(); + out_cc->println("else"); + out_cc->inc_indent(); + out_cc->println("%s->%s(gap_length);", + env_->LValue(downflow_id), + kFlowGap); + out_cc->dec_indent(); + + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); + } + +void ConnDecl::GenProcessFunc(Output *out_h, Output *out_cc) + { + string proto = + strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)", + kNewData); + + out_h->println("void %s;", proto.c_str()); + + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + + out_cc->println("if ( is_orig )"); + out_cc->inc_indent(); + out_cc->println("%s->%s(begin, end);", + env_->LValue(upflow_id), + kNewData); + out_cc->dec_indent(); + out_cc->println("else"); + out_cc->inc_indent(); + out_cc->println("%s->%s(begin, end);", + env_->LValue(downflow_id), + kNewData); + out_cc->dec_indent(); + + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); + } diff --git a/tools/binpac/src/pac_conn.h b/tools/binpac/src/pac_conn.h new file mode 100644 index 0000000000..0247bf7f7b --- /dev/null +++ b/tools/binpac/src/pac_conn.h @@ -0,0 +1,34 @@ +#ifndef pac_conn_h +#define pac_conn_h + +#include "pac_decl.h" +#include "pac_analyzer.h" + +class ConnDecl : public AnalyzerDecl +{ +public: + ConnDecl(ID *conn_id, ParamList *params, AnalyzerElementList *elemlist); + ~ConnDecl(); + + void Prepare(); + + Type* DataType() const { return data_type_; } + +protected: + void AddBaseClass(vector *base_classes) const; + + void GenProcessFunc(Output *out_h, Output *out_cc); + void GenGapFunc(Output *out_h, Output *out_cc); + void GenEOFFunc(Output *out_h, Output *out_cc); + + void GenPubDecls(Output *out_h, Output *out_cc); + void GenPrivDecls(Output *out_h, Output *out_cc); + + void ProcessFlowElement(AnalyzerFlow *flow_elem); + void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem); + + AnalyzerFlow *flows_[2]; + Type *data_type_; +}; + +#endif // pac_conn_h diff --git a/tools/binpac/src/pac_context.cc b/tools/binpac/src/pac_context.cc new file mode 100644 index 0000000000..94e4c4ce47 --- /dev/null +++ b/tools/binpac/src/pac_context.cc @@ -0,0 +1,120 @@ +#include "pac_analyzer.h" +#include "pac_exception.h" +#include "pac_exttype.h" +#include "pac_flow.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_param.h" +#include "pac_paramtype.h" +#include "pac_type.h" +#include "pac_utils.h" + +#include "pac_context.h" + +ContextField::ContextField(ID *id, Type *type) + : Field(CONTEXT_FIELD, + TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, + id, type) + { + } + +AnalyzerContextDecl *AnalyzerContextDecl::current_analyzer_context_ = 0; + +namespace { + ParamList *ContextFieldsToParams(ContextFieldList *context_fields) + { + // Convert context fields to parameters + ParamList *params = new ParamList(); + foreach(i, ContextFieldList, context_fields) + { + ContextField *f = *i; + params->push_back( + new Param(f->id()->clone(), + f->type())); + } + return params; + } +} // namespace private + +AnalyzerContextDecl::AnalyzerContextDecl( + ID *id, + ContextFieldList *context_fields) + : TypeDecl(new ID(fmt("Context%s", id->Name())), + ContextFieldsToParams(context_fields), + new DummyType()) + { + context_name_id_ = id; + if ( current_analyzer_context_ != 0 ) + { + throw Exception(this, + fmt("multiple declaration of analyzer context; " + "the previous one is `%s'", + current_analyzer_context_->id()->Name())); + } + else + current_analyzer_context_ = this; + + context_fields_ = context_fields; + + param_type_ = new ParameterizedType(id_->clone(), 0); + + flow_buffer_added_ = false; + + DEBUG_MSG("Context type: %s\n", param_type()->class_name().c_str()); + } + +AnalyzerContextDecl::~AnalyzerContextDecl() + { + delete context_name_id_; + delete_list(ContextFieldList, context_fields_); + } + +void AnalyzerContextDecl::GenForwardDeclaration(Output *out_h) + { + GenNamespaceBegin(out_h); + TypeDecl::GenForwardDeclaration(out_h); + } + +void AnalyzerContextDecl::GenCode(Output *out_h, Output *out_cc) + { + GenNamespaceBegin(out_h); + GenNamespaceBegin(out_cc); + TypeDecl::GenCode(out_h, out_cc); + } + +void AnalyzerContextDecl::GenNamespaceBegin(Output *out) const + { + out->println("namespace %s {", context_name_id()->Name()); + } + +void AnalyzerContextDecl::GenNamespaceEnd(Output *out) const + { + out->println("} // namespace %s", context_name_id()->Name()); + } + +void AnalyzerContextDecl::AddFlowBuffer() + { + if ( flow_buffer_added_ ) + return; + + AddParam(new Param( + new ID(kFlowBufferVar), + FlowDecl::flow_buffer_type()->Clone())); + + flow_buffer_added_ = true; + } + +string AnalyzerContextDecl::mb_buffer(Env *env) + { + // A hack. The orthodox way would be to build an Expr of + // context.flow_buffer_var, and then EvalExpr. + return fmt("%s->%s()", + env->RValue(analyzer_context_id), + kFlowBufferVar); + } + +Type *DummyType::DoClone() const + { + // Fields will be copied in Type::Clone(). + return new DummyType(); + } diff --git a/tools/binpac/src/pac_context.h b/tools/binpac/src/pac_context.h new file mode 100644 index 0000000000..29704e0b8d --- /dev/null +++ b/tools/binpac/src/pac_context.h @@ -0,0 +1,97 @@ +#ifndef pac_context_h +#define pac_context_h + +#include "pac_common.h" +#include "pac_field.h" +#include "pac_type.h" +#include "pac_typedecl.h" + +// AnalyzerContext represents a cookie that an analyzer gives to +// parse functions of various message types. The cookie is parsed +// to every parse function (if necessary) as parameter 'binpac_context'. +// +// The members of the cookie is declared through 'analyzer' declarations, +// such as in: +// +// analyzer SunRPC withcontext { +// connection: RPC_Conn; +// flow: RPC_Flow; +// }; +// +// The cookie usually contains the connection and flow in which +// the message appears, and the context information can be +// accessed as members of the cookie, such as +// ``binpac_context.connection''. + +class ContextField : public Field +{ +public: + ContextField(ID *id, Type *type); +}; + +class AnalyzerContextDecl : public TypeDecl +{ +public: + AnalyzerContextDecl(ID *id, ContextFieldList *context_fields); + ~AnalyzerContextDecl(); + + void AddFlowBuffer(); + + const ID *context_name_id() const { return context_name_id_; } + + // The type of analyzer context as a parameter + ParameterizedType *param_type() const { return param_type_; } + + void GenForwardDeclaration(Output *out_h); + void GenCode(Output *out_h, Output *out_cc); + + void GenNamespaceBegin(Output *out) const; + void GenNamespaceEnd(Output *out) const; + +private: + ID *context_name_id_; + ContextFieldList *context_fields_; + ParameterizedType *param_type_; + bool flow_buffer_added_; + +// static members +public: + static AnalyzerContextDecl *current_analyzer_context() + { + return current_analyzer_context_; + } + + static string mb_buffer(Env *env); + +private: + static AnalyzerContextDecl *current_analyzer_context_; +}; + +class DummyType : public Type +{ +public: + DummyType() : Type(DUMMY) {} + + bool DefineValueVar() const { return false; } + string DataTypeStr() const { ASSERT(0); return ""; } + + int StaticSize(Env* env) const { ASSERT(0); return -1; } + + bool ByteOrderSensitive() const { return false; } + + bool IsPointerType() const { ASSERT(0); return false; } + + void DoGenParseCode(Output* out, Env* env, + const DataPtr& data, int flags) + { ASSERT(0); } + + // Generate code for computing the dynamic size of the type + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) + { ASSERT(0); } + +protected: + Type *DoClone() const; + void DoMarkIncrementalInput() { ASSERT(0); } +}; + +#endif // pac_context_h diff --git a/tools/binpac/src/pac_cstr.cc b/tools/binpac/src/pac_cstr.cc new file mode 100644 index 0000000000..2d41bf7d1b --- /dev/null +++ b/tools/binpac/src/pac_cstr.cc @@ -0,0 +1,127 @@ +#include "pac_cstr.h" +#include "pac_dbg.h" +#include "pac_exception.h" + +namespace { + +class EscapeException +{ +public: + explicit EscapeException(const string &s) + { + msg_ = s; + } + + const string &msg() const { return msg_; } + +private: + string msg_; +}; + +// Copied from util.cc of Bro +int expand_escape(const char*& s) + { + switch ( *(s++) ) { + case 'b': return '\b'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'a': return '\a'; + case 'v': return '\v'; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + { // \{1,3} + --s; // put back the first octal digit + const char* start = s; + + // Don't increment inside loop control + // because if isdigit() is a macro it might + // expand into multiple increments ... + + // Here we define a maximum length for escape sequence + // to allow easy handling of string like: "^H0" as + // "\0100". + + for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s); ++s, ++len) + ; + + int result; + if ( sscanf(start, "%3o", &result) != 1 ) + { + throw EscapeException(fmt("bad octal escape: \"%s", start)); + result = 0; + } + + return result; + } + + case 'x': + { /* \x */ + const char* start = s; + + // Look at most 2 characters, so that "\x0ddir" -> "^Mdir". + for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s); + ++s, ++len) + ; + + int result; + if ( sscanf(start, "%2x", &result) != 1 ) + { + throw EscapeException(fmt("bad hexadecimal escape: \"%s", start)); + result = 0; + } + + return result; + } + + default: + return s[-1]; + } + } + +} // private namespace + +ConstString::ConstString(const string &s) + : str_(s) + { + // Copied from scan.l of Bro + try + { + const char* text = str_.c_str(); + int len = strlen(text) + 1; + int i = 0; + + char* s = new char[len]; + + // Skip leading quote. + for ( ++text; *text; ++text ) + { + if ( *text == '\\' ) + { + ++text; // skip '\' + s[i++] = expand_escape(text); + --text; // point to end of sequence + } + else + { + s[i++] = *text; + } + } + ASSERT(i < len); + + // Get rid of trailing quote. + ASSERT(s[i-1] == '"'); + s[i-1] = '\0'; + + unescaped_ = s; + delete [] s; + } + catch(EscapeException const &e) + { + // Throw again with the object + throw Exception(this, e.msg().c_str()); + } + } + diff --git a/tools/binpac/src/pac_cstr.h b/tools/binpac/src/pac_cstr.h new file mode 100644 index 0000000000..d1faaf7604 --- /dev/null +++ b/tools/binpac/src/pac_cstr.h @@ -0,0 +1,23 @@ +#ifndef pac_cstr_h +#define pac_cstr_h + +#include "pac_common.h" + +class ConstString : public Object +{ +public: + ConstString(const string &s); + + // The string in its escaped form, with surrounding '"'s + const string &str() const { return str_; } + const char *c_str() const { return str_.c_str(); } + + // The unescaped string, without surrounding '"'s + const string &unescaped() const { return unescaped_; } + +private: + string str_; + string unescaped_; +}; + +#endif // pac_cstr_h diff --git a/tools/binpac/src/pac_ctype.cc b/tools/binpac/src/pac_ctype.cc new file mode 100644 index 0000000000..cfde2f461b --- /dev/null +++ b/tools/binpac/src/pac_ctype.cc @@ -0,0 +1,21 @@ +#include "pac_ctype.h" + +string CType::DeclareInstance(const string &var) const + { + return strfmt("%s %s", name().c_str(), var.c_str()); + } + +string CType::DeclareConstReference(const string &var) const + { + return strfmt("%s const &%s", name().c_str(), var.c_str()); + } + +string CType::DeclareConstPointer(const string &var) const + { + return strfmt("%s const *%s", name().c_str(), var.c_str()); + } + +string CType::DeclarePointer(const string &var) const + { + return strfmt("%s *%s", name().c_str(), var.c_str()); + } diff --git a/tools/binpac/src/pac_ctype.h b/tools/binpac/src/pac_ctype.h new file mode 100644 index 0000000000..aebbc34d6a --- /dev/null +++ b/tools/binpac/src/pac_ctype.h @@ -0,0 +1,23 @@ +#ifndef pac_ctype_h +#define pac_ctype_h + +#include "pac_common.h" + +// Represents a C++ type +class CType +{ +public: + CType(const string &name); + + string name() const { return name_; } + + string DeclareInstance(const string &var) const; + string DeclareConstReference(const string &var) const; + string DeclareConstPointer(const string &var) const; + string DeclarePointer(const string &var) const; + +protected: + string name_; +}; + +#endif // pac_ctype_h diff --git a/tools/binpac/src/pac_datadep.cc b/tools/binpac/src/pac_datadep.cc new file mode 100644 index 0000000000..8c43e0e106 --- /dev/null +++ b/tools/binpac/src/pac_datadep.cc @@ -0,0 +1,76 @@ +#include "pac_datadep.h" +#include "pac_expr.h" +#include "pac_id.h" +#include "pac_type.h" + +DataDepElement::DataDepElement(DDE_Type type) + : dde_type_(type), in_traversal(false) + { + } + +bool DataDepElement::Traverse(DataDepVisitor *visitor) + { + // Avoid infinite loop + if ( in_traversal ) + return true; + if ( ! visitor->PreProcess(this) ) + return false; + + in_traversal = true; + bool cont = DoTraverse(visitor); + in_traversal = false; + + if ( ! cont ) + return false; + if ( ! visitor->PostProcess(this) ) + return false; + return true; + } + +Expr *DataDepElement::expr() + { + return static_cast(this); + } + +Type *DataDepElement::type() + { + return static_cast(this); + } + +bool RequiresAnalyzerContext::PreProcess(DataDepElement *element) + { + switch ( element->dde_type() ) + { + case DataDepElement::EXPR: + ProcessExpr(element->expr()); + break; + default: + break; + } + + // Continue traversal until we know the answer is 'yes' + return ! requires_analyzer_context_; + } + +bool RequiresAnalyzerContext::PostProcess(DataDepElement *element) + { + return ! requires_analyzer_context_; + } + +void RequiresAnalyzerContext::ProcessExpr(Expr *expr) + { + if ( expr->expr_type() == Expr::EXPR_ID ) + { + requires_analyzer_context_ = + (requires_analyzer_context_ || + *expr->id() == *analyzer_context_id || + *expr->id() == *context_macro_id); + } + } + +bool RequiresAnalyzerContext::compute(DataDepElement *element) + { + RequiresAnalyzerContext visitor; + element->Traverse(&visitor); + return visitor.requires_analyzer_context_; + } diff --git a/tools/binpac/src/pac_datadep.h b/tools/binpac/src/pac_datadep.h new file mode 100644 index 0000000000..a45053fb01 --- /dev/null +++ b/tools/binpac/src/pac_datadep.h @@ -0,0 +1,71 @@ +#ifndef pac_datadep_h +#define pac_datadep_h + +// To provide a way to traverse through the data dependency graph. +// That is, to evaluate X, what must be evaluated. + +#include "pac_common.h" +#include "pac_dbg.h" + +class DataDepVisitor; + +class DataDepElement { +public: + enum DDE_Type { + ATTR, + CASEEXPR, + EXPR, + FIELD, + INPUT_BUFFER, + PARAM, + TYPE, + }; + + DataDepElement(DDE_Type type); + virtual ~DataDepElement() {} + + // Returns whether to continue traversal + bool Traverse(DataDepVisitor *visitor); + + // Returns whether to continue traversal + virtual bool DoTraverse(DataDepVisitor *visitor) = 0; + + DDE_Type dde_type() const { return dde_type_; } + Expr *expr(); + Type *type(); + +protected: + DDE_Type dde_type_; + bool in_traversal; +}; + +class DataDepVisitor { +public: + virtual ~DataDepVisitor() {} + // Returns whether to continue traversal + virtual bool PreProcess(DataDepElement *element) = 0; + virtual bool PostProcess(DataDepElement *element) = 0; +}; + +class RequiresAnalyzerContext : public DataDepVisitor { +public: + RequiresAnalyzerContext() : requires_analyzer_context_(false) {} + + // Returns whether to continue traversal + bool PreProcess(DataDepElement *element); + bool PostProcess(DataDepElement *element); + + bool requires_analyzer_context() const + { + return requires_analyzer_context_; + } + + static bool compute(DataDepElement *element); + +protected: + void ProcessExpr(Expr *expr); + + bool requires_analyzer_context_; +}; + +#endif // pac_datadep_h diff --git a/tools/binpac/src/pac_dataptr.cc b/tools/binpac/src/pac_dataptr.cc new file mode 100644 index 0000000000..beac6997cb --- /dev/null +++ b/tools/binpac/src/pac_dataptr.cc @@ -0,0 +1,66 @@ +#include "pac_exception.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_utils.h" + +#include "pac_dataptr.h" + +DataPtr::DataPtr(Env* env, const ID* id, const int offset) + : id_(id), offset_(offset) + { + if ( id_ ) + { + if ( ! env->Evaluated(id_) ) + throw ExceptionIDNotEvaluated(id_); + + if ( offset_ == 0 ) + ptr_expr_ = strfmt("%s", env->RValue(id_)); + else + ptr_expr_ = strfmt("(%s + %d)", env->RValue(id_), offset_); + } + else + ptr_expr_ = "(null id)"; + } + +int DataPtr::AbsOffset(const ID* base_ptr) const + { + return ( id() == base_ptr ) ? offset() : -1; + } + +char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const + { + if ( AbsOffset(base_ptr) >= 0 ) + return nfmt("%d", offset()); + else + return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr)); + } + +void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, + const char* data_size, const char* data_name) const + { + ASSERT(id_); + + out_cc->println("// Checking out-of-bound for \"%s\"", data_name); + out_cc->println("if ( %s + (%s) > %s )", + ptr_expr(), + data_size, + env->RValue(end_of_data)); + + out_cc->inc_indent(); + out_cc->println("{"); + + char* data_offset = AbsOffsetExpr(env, begin_of_data); + + out_cc->println("// Handle out-of-bound condition"); + out_cc->println("throw ExceptionOutOfBound(\"%s\",", data_name); + out_cc->println(" (%s) + (%s), ", + data_offset, data_size); + out_cc->println(" (%s) - (%s));", + env->RValue(end_of_data), env->RValue(begin_of_data)); + + delete [] data_offset; + + out_cc->println("}"); + out_cc->dec_indent(); + } + diff --git a/tools/binpac/src/pac_dataptr.h b/tools/binpac/src/pac_dataptr.h new file mode 100644 index 0000000000..602843ff56 --- /dev/null +++ b/tools/binpac/src/pac_dataptr.h @@ -0,0 +1,47 @@ +#ifndef pac_dataptr_h +#define pac_dataptr_h + +#include +#include "pac_common.h" + +// A data pointer is represented by an data pointer variable +// plus a constant offset. + +class DataPtr +{ +public: + DataPtr(Env* env, const ID* arg_id, const int arg_off); + + DataPtr const &operator=(DataPtr const &x) + { + id_ = x.id(); + offset_ = x.offset(); + ptr_expr_ = x.ptr_expr(); + + return *this; + } + + const ID* id() const { return id_; } + int offset() const { return offset_; } + + const char* ptr_expr() const + { + ASSERT(id_); + return ptr_expr_.c_str(); + } + + int AbsOffset(const ID* base_ptr) const; + char* AbsOffsetExpr(Env* env, const ID* base_ptr) const; + + void GenBoundaryCheck(Output* out, + Env* env, + const char* data_size, + const char* data_name) const; + +protected: + const ID* id_; + int offset_; + string ptr_expr_; +}; + +#endif // pac_dataptr_h diff --git a/tools/binpac/src/pac_dataunit.cc b/tools/binpac/src/pac_dataunit.cc new file mode 100644 index 0000000000..2b7218963d --- /dev/null +++ b/tools/binpac/src/pac_dataunit.cc @@ -0,0 +1,60 @@ +#include "pac_context.h" +#include "pac_dataunit.h" +#include "pac_output.h" +#include "pac_paramtype.h" +#include "pac_varfield.h" + +AnalyzerDataUnit::AnalyzerDataUnit( + DataUnitType type, + ID *id, + ExprList *type_params, + ExprList *context_params) + : AnalyzerElement(DATAUNIT), + type_(type), + id_(id), + type_params_(type_params), + context_params_(context_params) + { + data_type_ = new ParameterizedType(id_, type_params_); + context_type_ = new ParameterizedType( + AnalyzerContextDecl::current_analyzer_context()->id()->clone(), + context_params_); + + dataunit_var_field_ = new ParseVarField( + Field::CLASS_MEMBER, + dataunit_id->clone(), + data_type()); + context_var_field_ = new PrivVarField( + analyzer_context_id->clone(), + context_type()); + } + +AnalyzerDataUnit::~AnalyzerDataUnit() + { + delete dataunit_var_field_; + delete context_var_field_; + } + +void AnalyzerDataUnit::Prepare(Env *env) + { + dataunit_var_field_->Prepare(env); + context_var_field_->Prepare(env); + } + +void AnalyzerDataUnit::GenNewDataUnit(Output *out_cc, Env *env) + { + out_cc->println("%s = new %s(%s);", + env->LValue(dataunit_id), + data_type()->class_name().c_str(), + data_type()->EvalParameters(out_cc, env).c_str()); + } + +void AnalyzerDataUnit::GenNewContext(Output *out_cc, Env *env) + { + out_cc->println("%s = new %s(%s);", + env->LValue(analyzer_context_id), + context_type()->class_name().c_str(), + context_type()->EvalParameters(out_cc, env).c_str()); + env->SetEvaluated(analyzer_context_id); + } + diff --git a/tools/binpac/src/pac_dataunit.h b/tools/binpac/src/pac_dataunit.h new file mode 100644 index 0000000000..eb76378afa --- /dev/null +++ b/tools/binpac/src/pac_dataunit.h @@ -0,0 +1,49 @@ +#ifndef pac_dataunit_h +#define pac_dataunit_h + +#include "pac_analyzer.h" + +// The type and parameters of input data unit of a flow. For instance, the +// data unit of a DCE/RPC flow is DCE_RPC_PDU. + +class AnalyzerDataUnit : public AnalyzerElement +{ +public: + enum DataUnitType { DATAGRAM, FLOWUNIT }; + AnalyzerDataUnit( + DataUnitType type, + ID *id, + ExprList *type_params, + ExprList *context_params); + ~AnalyzerDataUnit(); + + void Prepare(Env *env); + + // Initializes dataunit_id + void GenNewDataUnit(Output *out_cc, Env *env); + // Initializes analyzer_context_id + void GenNewContext(Output *out_cc, Env *env); + + DataUnitType type() const { return type_; } + const ID *id() const { return id_; } + ExprList *type_params() const { return type_params_; } + ExprList *context_params() const { return context_params_; } + + ParameterizedType *data_type() const { return data_type_; } + ParameterizedType *context_type() const { return context_type_; } + + Field *dataunit_var_field() const { return dataunit_var_field_; } + Field *context_var_field() const { return context_var_field_; } + +private: + DataUnitType type_; + ID *id_; + ExprList *type_params_; + ExprList *context_params_; + ParameterizedType *data_type_; + ParameterizedType *context_type_; + Field *dataunit_var_field_; + Field *context_var_field_; +}; + +#endif // pac_dataunit_h diff --git a/tools/binpac/src/pac_dbg.h b/tools/binpac/src/pac_dbg.h new file mode 100644 index 0000000000..bcd87639fb --- /dev/null +++ b/tools/binpac/src/pac_dbg.h @@ -0,0 +1,14 @@ +/* $Id: pac_dbg.h 3265 2006-06-09 21:16:12Z rpang $ */ + +#ifndef pac_dbg_h +#define pac_dbg_h + +#include +#include + +extern bool FLAGS_pac_debug; + +#define ASSERT(x) assert(x) +#define DEBUG_MSG(x...) if ( FLAGS_pac_debug ) fprintf(stderr, x) + +#endif /* pac_dbg_h */ diff --git a/tools/binpac/src/pac_decl-inl.h b/tools/binpac/src/pac_decl-inl.h new file mode 100644 index 0000000000..97c369fa9f --- /dev/null +++ b/tools/binpac/src/pac_decl-inl.h @@ -0,0 +1,6 @@ +#ifndef pac_decl_inl_h +#define pac_decl_inl_h + +#include "pac_id.h" + +#endif // pac_decl_inl_h diff --git a/tools/binpac/src/pac_decl.cc b/tools/binpac/src/pac_decl.cc new file mode 100644 index 0000000000..3c3ae95aa9 --- /dev/null +++ b/tools/binpac/src/pac_decl.cc @@ -0,0 +1,191 @@ +#include "pac_attr.h" +#include "pac_context.h" +#include "pac_dataptr.h" +#include "pac_embedded.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_param.h" +#include "pac_record.h" +#include "pac_type.h" +#include "pac_utils.h" + +#include "pac_decl.h" + +DeclList *Decl::decl_list_ = 0; +Decl::DeclMap Decl::decl_map_; + +Decl::Decl(ID* id, DeclType decl_type) + : id_(id), decl_type_(decl_type), attrlist_(0) + { + decl_map_[id_] = this; + if ( ! decl_list_ ) + decl_list_ = new DeclList(); + decl_list_->push_back(this); + + DEBUG_MSG("Finished Decl %s\n", id_->Name()); + + analyzer_context_ = 0; + } + +Decl::~Decl() + { + delete id_; + delete_list(AttrList, attrlist_); + } + +void Decl::AddAttrs(AttrList* attrs) + { + if ( ! attrs ) + return; + if ( ! attrlist_ ) + attrlist_ = new AttrList(); + foreach ( i, AttrList, attrs ) + { + attrlist_->push_back(*i); + ProcessAttr(*i); + } + } + +void Decl::ProcessAttr(Attr *attr) + { + throw Exception(attr, "unhandled attribute"); + } + +void Decl::SetAnalyzerContext() + { + analyzer_context_ = + AnalyzerContextDecl::current_analyzer_context(); + if ( ! analyzer_context_ ) + { + throw Exception(this, + "analyzer context not defined"); + } + } + +void Decl::ProcessDecls(Output *out_h, Output *out_cc) + { + if ( ! decl_list_ ) + return; + + foreach(i, DeclList, decl_list_) + { + Decl *decl = *i; + current_decl_id = decl->id(); + decl->Prepare(); + } + + foreach(i, DeclList, decl_list_) + { + Decl *decl = *i; + current_decl_id = decl->id(); + decl->GenExternDeclaration(out_h); + } + + out_h->println("namespace binpac {\n"); + out_cc->println("namespace binpac {\n"); + + AnalyzerContextDecl *analyzer_context = + AnalyzerContextDecl::current_analyzer_context(); + + foreach(i, DeclList, decl_list_) + { + Decl *decl = *i; + current_decl_id = decl->id(); + decl->GenForwardDeclaration(out_h); + } + + if ( analyzer_context ) + analyzer_context->GenNamespaceEnd(out_h); + + out_h->println(""); + + foreach(i, DeclList, decl_list_) + { + Decl *decl = *i; + current_decl_id = decl->id(); + decl->GenCode(out_h, out_cc); + } + + if ( analyzer_context ) + { + analyzer_context->GenNamespaceEnd(out_h); + analyzer_context->GenNamespaceEnd(out_cc); + } + + out_h->println("} // namespace binpac"); + out_cc->println("} // namespace binpac"); + } + +Decl* Decl::LookUpDecl(const ID* id) + { + DeclMap::iterator it = decl_map_.find(id); + if ( it == decl_map_.end() ) + return 0; + return it->second; + } + +int HelperDecl::helper_id_seq = 0; + +HelperDecl::HelperDecl(HelperType helper_type, + ID* context_id, + EmbeddedCode* code) + : Decl(new ID(fmt("helper_%d", ++helper_id_seq)), HELPER), + helper_type_(helper_type), + context_id_(context_id), + code_(code) + { + } + +HelperDecl::~HelperDecl() + { + delete context_id_; + delete code_; + } + +void HelperDecl::Prepare() + { + // Do nothing + } + +void HelperDecl::GenExternDeclaration(Output *out_h) + { + if ( helper_type_ == EXTERN ) + code_->GenCode(out_h, global_env()); + } + +void HelperDecl::GenCode(Output *out_h, Output *out_cc) + { + Env *env = global_env(); + +#if 0 + if ( context_id_ ) + { + Decl *decl = Decl::LookUpDecl(context_id_); + if ( ! decl ) + { + throw Exception(context_id_, + fmt("cannot find declaration for %s", + context_id_->Name())); + } + env = decl->env(); + if ( ! env ) + { + throw Exception(context_id_, + fmt("not a type or analyzer: %s", + context_id_->Name())); + } + } +#endif + + if ( helper_type_ == HEADER ) + code_->GenCode(out_h, env); + else if ( helper_type_ == CODE ) + code_->GenCode(out_cc, env); + else if ( helper_type_ == EXTERN ) + ; // do nothing + else + ASSERT(0); + } diff --git a/tools/binpac/src/pac_decl.h b/tools/binpac/src/pac_decl.h new file mode 100644 index 0000000000..6151022d20 --- /dev/null +++ b/tools/binpac/src/pac_decl.h @@ -0,0 +1,81 @@ +#ifndef pac_decl_h +#define pac_decl_h + +#include "pac_common.h" +#include "pac_id.h" + +class Decl : public Object +{ +public: + // Note: ANALYZER is not for AnalyzerDecl (which is an + // abstract class) , but for AnalyzerContextDecl. + enum DeclType { ENUM, LET, TYPE, FUNC, CONN, FLOW, ANALYZER, HELPER, REGEX }; + + Decl(ID *id, DeclType decl_type); + virtual ~Decl(); + + const ID *id() const { return id_; } + DeclType decl_type() const { return decl_type_; } + AnalyzerContextDecl *analyzer_context() const + { return analyzer_context_; } + + // NULL except for TypeDecl or AnalyzerDecl + virtual Env *env() const { return 0; } + + virtual void Prepare() = 0; + + // Generate declarations out of the "binpac" namespace + virtual void GenExternDeclaration(Output *out_h) { /* do nothing */ } + + // Generate declarations before definition of classes + virtual void GenForwardDeclaration(Output *out_h) = 0; + + virtual void GenCode(Output *out_h, Output *out_cc) = 0; + + void TakeExprList(); + void AddAttrs(AttrList *attrlist); + void SetAnalyzerContext(); + +protected: + virtual void ProcessAttr(Attr *a); + + ID *id_; + DeclType decl_type_; + AttrList *attrlist_; + ExprList *expr_list_; + AnalyzerContextDecl *analyzer_context_; + +public: + static void ProcessDecls(Output *out_h, Output *out_cc); + static Decl *LookUpDecl(const ID *id); + +private: + static DeclList *decl_list_; + typedef map DeclMap; + static DeclMap decl_map_; +}; + +class HelperDecl : public Decl +{ +public: + enum HelperType { + HEADER, CODE, EXTERN, + }; + HelperDecl(HelperType type, ID *context_id, EmbeddedCode *code); + ~HelperDecl(); + + void Prepare(); + void GenExternDeclaration(Output *out_h); + void GenForwardDeclaration(Output *out_h) { /* do nothing */ } + void GenCode(Output *out_h, Output *out_cc); + +private: + HelperType helper_type_; + ID *context_id_; + ID *helper_id_; + EmbeddedCode *code_; + + static int helper_id_seq; +}; + +#endif // pac_decl_h diff --git a/tools/binpac/src/pac_embedded.cc b/tools/binpac/src/pac_embedded.cc new file mode 100644 index 0000000000..aca2d03a19 --- /dev/null +++ b/tools/binpac/src/pac_embedded.cc @@ -0,0 +1,82 @@ +#include "pac_id.h" +#include "pac_primitive.h" +#include "pac_output.h" + +#include "pac_embedded.h" + +EmbeddedCodeSegment::EmbeddedCodeSegment(const string &s) + : s_(s), primitive_(0) + { + } + +EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive *primitive) + : s_(""), primitive_(primitive) + { + } + +EmbeddedCodeSegment::~EmbeddedCodeSegment() + { + delete primitive_; + } + +string EmbeddedCodeSegment::ToCode(Env *env) + { + if ( primitive_ && s_.empty() ) + s_ = primitive_->ToCode(env); + return s_; + } + +EmbeddedCode::EmbeddedCode() + { + segments_ = new EmbeddedCodeSegmentList(); + } + +EmbeddedCode::~EmbeddedCode() + { + delete_list(EmbeddedCodeSegmentList, segments_); + } + +void EmbeddedCode::Append(int atom) + { + current_segment_ += static_cast(atom); + } + +void EmbeddedCode::Append(const char *str) + { + current_segment_ += str; + } + +void EmbeddedCode::Append(PacPrimitive *primitive) + { + if ( ! current_segment_.empty() ) + { + segments_->push_back(new EmbeddedCodeSegment(current_segment_)); + current_segment_ = ""; + } + segments_->push_back(new EmbeddedCodeSegment(primitive)); + } + +void EmbeddedCode::GenCode(Output *out, Env *env) + { + if ( ! current_segment_.empty() ) + { + segments_->push_back(new EmbeddedCodeSegment(current_segment_)); + current_segment_ = ""; + } + + // TODO: return to the generated file after embedded code + // out->print("#line %d \"%s\"\n", line_num, filename.c_str()); + + // Allow use of RValue for undefined ID, in which case the + // ID's name is used as its RValue + env->set_allow_undefined_id(true); + + foreach(i, EmbeddedCodeSegmentList, segments_) + { + EmbeddedCodeSegment *segment = *i; + out->print("%s", segment->ToCode(env).c_str()); + } + + env->set_allow_undefined_id(false); + out->print("\n"); + } diff --git a/tools/binpac/src/pac_embedded.h b/tools/binpac/src/pac_embedded.h new file mode 100644 index 0000000000..b84de746e1 --- /dev/null +++ b/tools/binpac/src/pac_embedded.h @@ -0,0 +1,42 @@ +#ifndef pac_embedded_h +#define pac_embedded_h + +#include "pac_common.h" + +class EmbeddedCodeSegment +{ +public: + explicit EmbeddedCodeSegment(const string &s); + explicit EmbeddedCodeSegment(PacPrimitive *primitive); + ~EmbeddedCodeSegment(); + + string ToCode(Env *env); + +private: + string s_; + PacPrimitive *primitive_; +}; + +typedef vector EmbeddedCodeSegmentList; + +class EmbeddedCode : public Object +{ +public: + EmbeddedCode(); + ~EmbeddedCode(); + + // Append a character + void Append(int atom); + void Append(const char *str); + + // Append a PAC primitive + void Append(PacPrimitive *primitive); + + void GenCode(Output *out, Env *env); + +private: + string current_segment_; + EmbeddedCodeSegmentList *segments_; +}; + +#endif // pac_embedded_h diff --git a/tools/binpac/src/pac_enum.cc b/tools/binpac/src/pac_enum.cc new file mode 100644 index 0000000000..deb1711bc6 --- /dev/null +++ b/tools/binpac/src/pac_enum.cc @@ -0,0 +1,70 @@ +#include "pac_exception.h" +#include "pac_enum.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_output.h" +#include "pac_typedecl.h" + +Enum::Enum(ID* id, Expr* expr) + : id_(id), expr_(expr) + { + } + +Enum::~Enum() + { + delete id_; + delete expr_; + } + +void Enum::GenHeader(Output* out_h, int *pval) + { + ASSERT(pval); + if ( expr_ ) + { + if ( ! expr_->ConstFold(global_env(), pval) ) + throw ExceptionNonConstExpr(expr_); + out_h->println("%s = %d,", id_->Name(), *pval); + } + else + out_h->println("%s,", id_->Name()); + global_env()->AddConstID(id_, *pval); + } + +EnumDecl::EnumDecl(ID *id, EnumList *enumlist) + : Decl(id, ENUM), enumlist_(enumlist) + { + ID *type_id = id->clone(); + datatype_ = new ExternType(type_id, ExternType::NUMBER); + extern_typedecl_ = new TypeDecl(type_id, 0, datatype_); + } + +EnumDecl::~EnumDecl() + { + delete_list(EnumList, enumlist_); + delete extern_typedecl_; + } + +void EnumDecl::Prepare() + { + // Do nothing + } + +void EnumDecl::GenForwardDeclaration(Output *out_h) + { + out_h->println("enum %s {", id_->Name()); + out_h->inc_indent(); + int c = 0; + foreach(i, EnumList, enumlist_) + { + (*i)->GenHeader(out_h, &c); + ++c; + } + out_h->dec_indent(); + out_h->println("};"); + } + +void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */) + { + // Do nothing + } + diff --git a/tools/binpac/src/pac_enum.h b/tools/binpac/src/pac_enum.h new file mode 100644 index 0000000000..6b255912b6 --- /dev/null +++ b/tools/binpac/src/pac_enum.h @@ -0,0 +1,37 @@ +#ifndef pac_enum_h +#define pac_enum_h + +#include "pac_decl.h" + +class Enum +{ +public: + Enum(ID *id, Expr *expr = 0); + ~Enum(); + + void GenHeader(Output *out_h, int *pval); + +private: + ID *id_; + Expr *expr_; +}; + +class EnumDecl : public Decl +{ +public: + EnumDecl(ID *id, EnumList *enumlist); + ~EnumDecl(); + + Type *DataType() const { return datatype_; } + + void Prepare(); + void GenForwardDeclaration(Output *out_h); + void GenCode(Output *out_h, Output *out_cc); + +private: + EnumList *enumlist_; + Type *datatype_; + TypeDecl *extern_typedecl_; +}; + +#endif // pac_enum_h diff --git a/tools/binpac/src/pac_exception.cc b/tools/binpac/src/pac_exception.cc new file mode 100644 index 0000000000..462ef8e18f --- /dev/null +++ b/tools/binpac/src/pac_exception.cc @@ -0,0 +1,70 @@ +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_id.h" +#include "pac_utils.h" + +Exception::Exception(const Object* o, const char* msg) + { + if ( o ) + { + msg_ = o->Location(); + msg_ += ": error : "; + } + if ( msg ) + msg_ += msg; + if ( FLAGS_pac_debug ) + { + DEBUG_MSG("Exception: %s\n", msg_.c_str()); + abort(); + } + } + +ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) + : Exception(id), id_(id) + { + append(fmt("`%s' undeclared", id_->Name())); + } + +ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) + : Exception(id), id_(id) + { + append(fmt("`%s' redefined", id_->Name())); + } + +ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) + : Exception(id), id_(id) + { + append(fmt("ID `%s' not evaluated before used", id->Name())); + } + +ExceptionIDNotField::ExceptionIDNotField(const ID* id) + : Exception(id), id_(id) + { + append(fmt("ID `%s' is not a field", id_->Name())); + } + +ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id, + const ID *member_id) + : Exception(member_id), type_id_(type_id), member_id_(member_id) + { + append(fmt("type %s does not have member `%s'", + type_id_->Name(), member_id_->Name())); + } + +ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) + : Exception(id), id_(id) + { + append(fmt("cyclic dependence through `%s'", id_->Name())); + } + +ExceptionPaddingError::ExceptionPaddingError(const Object* o, const char* msg) + : Exception(o) + { + append(msg); + } + +ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) + : Exception(expr) + { + append(fmt("Expression `%s' is not constant", expr->orig())); + } diff --git a/tools/binpac/src/pac_exception.h b/tools/binpac/src/pac_exception.h new file mode 100644 index 0000000000..7653ffeacc --- /dev/null +++ b/tools/binpac/src/pac_exception.h @@ -0,0 +1,97 @@ +// $Id: pac_exception.h 3225 2006-06-08 00:00:01Z vern $ + +#ifndef pac_exception_h +#define pac_exception_h + +#include +using namespace std; + +#include "pac_common.h" + +class Exception +{ +public: + Exception(const Object* o, const char* msg = 0); + + const char* msg() const { return msg_.c_str(); } + void append(const char* s) { msg_ += s; } + +private: + string msg_; +}; + +class ExceptionIDNotFound : public Exception +{ +public: + ExceptionIDNotFound(const ID* id); + const ID* id() const { return id_; } + +private: + const ID* id_; +}; + +class ExceptionIDRedefinition : public Exception +{ +public: + ExceptionIDRedefinition(const ID* id); + const ID* id() const { return id_; } + +private: + const ID* id_; +}; + +class ExceptionIDNotEvaluated : public Exception +{ +public: + ExceptionIDNotEvaluated(const ID* id); + const ID* id() const { return id_; } + +private: + const ID* id_; +}; + +class ExceptionCyclicDependence : public Exception +{ +public: + ExceptionCyclicDependence(const ID* id); + const ID* id() const { return id_; } + +private: + const ID* id_; +}; + +class ExceptionPaddingError : public Exception +{ +public: + ExceptionPaddingError(const Object* o, const char* msg); +}; + +class ExceptionIDNotField : public Exception +{ +public: + ExceptionIDNotField(const ID* id); + const ID* id() const { return id_; } + +private: + const ID* id_; +}; + +class ExceptionMemberNotFound : public Exception +{ +public: + ExceptionMemberNotFound(const ID* type_id, const ID *member_id); + +private: + const ID *type_id_, *member_id_; +}; + +class ExceptionNonConstExpr : public Exception +{ +public: + ExceptionNonConstExpr(const Expr* expr); + +private: + const Expr *expr; +}; + +#endif /* pac_exception_h */ diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc new file mode 100644 index 0000000000..02303bc953 --- /dev/null +++ b/tools/binpac/src/pac_expr.cc @@ -0,0 +1,1041 @@ +#include "pac_case.h" +#include "pac_cstr.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_number.h" +#include "pac_output.h" +#include "pac_record.h" +#include "pac_regex.h" +#include "pac_strtype.h" +#include "pac_typedecl.h" +#include "pac_utils.h" + +string OrigExprList(ExprList *list) + { + bool first = true; + string str; + foreach(i, ExprList, list) + { + Expr *expr = *i; + if ( first ) + first = false; + else + str += ", "; + str += expr->orig(); + } + return str; + } + +string EvalExprList(ExprList *exprlist, Output *out, Env *env) + { + string val_list(""); + bool first = true; + + foreach(i, ExprList, exprlist) + { + if ( ! first ) + val_list += ", "; + val_list += (*i)->EvalExpr(out, env); + first = false; + } + + return val_list; + } + +static const char* expr_fmt[] = +{ +# define EXPR_DEF(type, num_op, fmt) fmt, +# include "pac_expr.def" +# undef EXPR_DEF +}; + +void Expr::init() + { + id_ = 0; + num_ = 0; + cstr_ = 0; + regex_ = 0; + num_operands_ = 0; + operand_[0] = 0; + operand_[1] = 0; + operand_[2] = 0; + args_ = 0; + cases_ = 0; + } + +Expr::Expr(ID* arg_id) + : DataDepElement(EXPR) + { + init(); + expr_type_ = EXPR_ID; + id_ = arg_id; + num_operands_ = 0; + orig_ = fmt("%s", id_->Name()); + } + +Expr::Expr(Number* arg_num) + : DataDepElement(EXPR) + { + init(); + expr_type_ = EXPR_NUM; + num_ = arg_num; + num_operands_ = 0; + orig_ = fmt("((int) %s)", num_->Str()); + } + +Expr::Expr(ConstString *cstr) + : DataDepElement(EXPR) + { + init(); + expr_type_ = EXPR_CSTR; + cstr_ = cstr; + num_operands_ = 0; + orig_ = cstr_->str(); + } + +Expr::Expr(RegEx *regex) + : DataDepElement(EXPR) + { + init(); + expr_type_ = EXPR_REGEX; + regex_ = regex; + num_operands_ = 0; + orig_ = fmt("/%s/", regex_->str().c_str()); + } + +Expr::Expr(ExprType arg_type, Expr* op1) + : DataDepElement(EXPR) + { + init(); + expr_type_ = arg_type; + num_operands_ = 1; + operand_[0] = op1; + orig_ = fmt(expr_fmt[expr_type_], op1->orig()); + } + +Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) + : DataDepElement(EXPR) + { + init(); + expr_type_ = arg_type; + num_operands_ = 2; + operand_[0] = op1; + operand_[1] = op2; + operand_[2] = 0; + orig_ = fmt(expr_fmt[expr_type_], op1->orig(), op2->orig()); + } + +Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) + : DataDepElement(EXPR) + { + init(); + expr_type_ = arg_type; + num_operands_ = 3; + operand_[0] = op1; + operand_[1] = op2; + operand_[2] = op3; + orig_ = fmt(expr_fmt[expr_type_], op1->orig(), op2->orig(), op3->orig()); + } + +Expr::Expr(ExprList *args) + : DataDepElement(EXPR) + { + init(); + expr_type_ = EXPR_CALLARGS; + num_operands_ = -1; + args_ = args; + + orig_ = OrigExprList(args_); + } + +Expr::Expr(Expr *index, CaseExprList *cases) + : DataDepElement(EXPR) + { + init(); + expr_type_ = EXPR_CASE; + num_operands_ = -1; + operand_[0] = index; + cases_ = cases; + + orig_ = strfmt("case %s of { ", index->orig()); + foreach(i, CaseExprList, cases_) + { + CaseExpr *c = *i; + orig_ += strfmt("%s => %s; ", + OrigExprList(c->index()).c_str(), + c->value()->orig()); + } + orig_ += "}"; + } + +Expr::~Expr() + { + delete id_; + delete operand_[0]; + delete operand_[1]; + delete operand_[2]; + delete_list(ExprList, args_); + delete_list(CaseExprList, cases_); + } + +void Expr::AddCaseExpr(CaseExpr *case_expr) + { + ASSERT(str_.empty()); + ASSERT(expr_type_ == EXPR_CASE); + ASSERT(cases_); + cases_->push_back(case_expr); + } + +void Expr::GenStrFromFormat(Env *env) + { + // The format != "@custom@" + ASSERT(*expr_fmt[expr_type_] != '@'); + + switch ( num_operands_ ) + { + case 1: + str_ = fmt(expr_fmt[expr_type_], + operand_[0]->str()); + break; + case 2: + str_ = fmt(expr_fmt[expr_type_], + operand_[0]->str(), + operand_[1]->str()); + break; + case 3: + str_ = fmt(expr_fmt[expr_type_], + operand_[0]->str(), + operand_[1]->str(), + operand_[2]->str()); + break; + default: + DEBUG_MSG("num_operands_ = %d, orig = %s\n", num_operands_, orig()); + ASSERT(0); + break; + } + } + +namespace { + + RecordField *GetRecordField(const ID *id, Env *env) + { + Field* field = env->GetField(id); + ASSERT(field); + if ( field->tof() != RECORD_FIELD && + field->tof() != PADDING_FIELD ) + throw Exception(id, "not a record field"); + RecordField *r = static_cast(field); + ASSERT(r); + return r; + } + +} // private namespace + +void Expr::GenCaseEval(Output *out_cc, Env *env) + { + ASSERT(expr_type_ == EXPR_CASE); + ASSERT(operand_[0]); + ASSERT(cases_); + + Type *val_type = DataType(env); + ID *val_var = env->AddTempID(val_type); + + out_cc->println("%s %s;", + val_type->DataTypeStr().c_str(), + env->LValue(val_var)); + + // force evaluation of IDs appearing in case stmt + operand_[0]->ForceIDEval(out_cc, env); + foreach(i, CaseExprList, cases_) + (*i)->value()->ForceIDEval(out_cc, env); + + out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); + + out_cc->inc_indent(); + out_cc->println("{"); + + CaseExpr *default_case = 0; + foreach(i, CaseExprList, cases_) + { + CaseExpr *c = *i; + ExprList *index = c->index(); + if ( ! index ) + { + if ( default_case ) + throw Exception(c, "duplicate default cases"); + default_case = c; + } + else + { + GenCaseStr(index, out_cc, env); + out_cc->inc_indent(); + out_cc->println("%s = %s;", + env->LValue(val_var), + c->value()->EvalExpr(out_cc, env)); + out_cc->println("break;"); + out_cc->dec_indent(); + } + } + + // Generate the default case after all other cases + GenCaseStr(0, out_cc, env); + out_cc->inc_indent(); + if ( default_case ) + { + out_cc->println("%s = %s;", + env->LValue(val_var), + default_case->value()->EvalExpr(out_cc, env)); + } + else + { + out_cc->println("throw ExceptionInvalidCaseIndex(\"%s\", %s);", + Location(), operand_[0]->EvalExpr(out_cc, env)); + } + out_cc->println("break;"); + out_cc->dec_indent(); + + out_cc->println("}"); + out_cc->dec_indent(); + + env->SetEvaluated(val_var); + str_ = env->RValue(val_var); + } + +void Expr::GenEval(Output* out_cc, Env* env) + { + switch ( expr_type_ ) + { + case EXPR_NUM: + str_ = num_->Str(); + break; + + case EXPR_ID: + if ( ! env->Evaluated(id_) ) + env->Evaluate(out_cc, id_); + str_ = env->RValue(id_); + break; + + case EXPR_MEMBER: + { + /* + For member expressions such X.Y, evaluating + X only is sufficient. (Actually trying to + evaluate Y will lead to error because Y is + not defined in the current environment.) + */ + operand_[0]->GenEval(out_cc, env); + + Type *ty0 = operand_[0]->DataType(env); + + str_ = fmt("%s%s", + operand_[0]->EvalExpr(out_cc, env), + ty0 ? + ty0->EvalMember(operand_[1]->id()).c_str() : + fmt("->%s()", operand_[1]->id()->Name())); + } + break; + + case EXPR_SUBSCRIPT: + { + operand_[0]->GenEval(out_cc, env); + operand_[1]->GenEval(out_cc, env); + + string v0 = operand_[0]->EvalExpr(out_cc, env); + string v1 = operand_[1]->EvalExpr(out_cc, env); + + Type *ty0 = operand_[0]->DataType(env); + if ( ty0 ) + str_ = ty0->EvalElement(v0, v1); + else + str_ = fmt("%s[%s]", v0.c_str(), v1.c_str()); + } + break; + + case EXPR_SIZEOF: + { + const ID *id = operand_[0]->id(); + RecordField *rf; + Type *ty; + + try + { + if ( (rf = GetRecordField(id, env)) != 0 ) + { + str_ = fmt("%s", rf->FieldSize(out_cc, env)); + } + } + catch ( ExceptionIDNotFound &e ) + { + if ( (ty = TypeDecl::LookUpType(id)) != 0 ) + { + int ty_size = ty->StaticSize(global_env()); + if ( ty_size >= 0 ) + str_ = fmt("%d", ty_size); + else + throw Exception(id, "unknown size"); + } + else + throw Exception(id, "not a record field or type"); + } + } + break; + + case EXPR_OFFSETOF: + { + const ID *id = operand_[0]->id(); + RecordField *rf = GetRecordField(id, env); + str_ = fmt("%s", rf->FieldOffset(out_cc, env)); + } + break; + + case EXPR_CALLARGS: + str_ = EvalExprList(args_, out_cc, env); + break; + + case EXPR_CASE: + GenCaseEval(out_cc, env); + break; + + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) + if ( operand_[i] ) + operand_[i]->GenEval(out_cc, env); + GenStrFromFormat(env); + break; + } + } + +void Expr::ForceIDEval(Output* out_cc, Env* env) + { + switch ( expr_type_ ) + { + case EXPR_NUM: + case EXPR_SIZEOF: + case EXPR_OFFSETOF: + break; + + case EXPR_ID: + if ( ! env->Evaluated(id_) ) + env->Evaluate(out_cc, id_); + break; + + case EXPR_MEMBER: + operand_[0]->ForceIDEval(out_cc, env); + break; + + case EXPR_CALLARGS: + { + foreach(i, ExprList, args_) + (*i)->ForceIDEval(out_cc, env); + } + break; + + case EXPR_CASE: + { + operand_[0]->ForceIDEval(out_cc, env); + foreach(i, CaseExprList, cases_) + (*i)->value()->ForceIDEval(out_cc, env); + } + break; + + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) + if ( operand_[i] ) + operand_[i]->ForceIDEval(out_cc, env); + break; + } + } + + +const char* Expr::EvalExpr(Output* out_cc, Env* env) + { + GenEval(out_cc, env); + return str(); + } + +Type *Expr::DataType(Env *env) const + { + Type *data_type; + + switch ( expr_type_ ) + { + case EXPR_ID: + data_type = env->GetDataType(id_); + break; + + case EXPR_MEMBER: + { + // Get type of the parent + Type *parent_type = operand_[0]->DataType(env); + if ( ! parent_type ) + return 0; + data_type = parent_type->MemberDataType(operand_[1]->id()); + } + break; + + case EXPR_SUBSCRIPT: + { + // Get type of the parent + Type *parent_type = operand_[0]->DataType(env); + data_type = parent_type->ElementDataType(); + } + break; + + case EXPR_PAREN: + data_type = operand_[0]->DataType(env); + break; + + case EXPR_COND: + { + Type *type1 = operand_[1]->DataType(env); + Type *type2 = operand_[2]->DataType(env); + if ( ! Type::CompatibleTypes(type1, type2) ) + { + throw Exception(this, + fmt("type mismatch: %s vs %s", + type1->DataTypeStr().c_str(), + type2->DataTypeStr().c_str())); + } + data_type = type1; + } + break; + + case EXPR_CALL: + data_type = operand_[0]->DataType(env); + break; + + case EXPR_CASE: + { + if ( cases_ && ! cases_->empty() ) + { + Type *type1 = + cases_->front()->value()->DataType(env); + foreach(i, CaseExprList, cases_) + { + Type *type2 = + (*i)->value()->DataType(env); + if ( ! Type::CompatibleTypes(type1, type2) ) + { + throw Exception(this, + fmt("type mismatch: %s vs %s", + type1->DataTypeStr().c_str(), + type2->DataTypeStr().c_str())); + } + if ( type1 == extern_type_nullptr ) + type1 = type2; + } + data_type = type1; + } + else + data_type = 0; + } + break; + + case EXPR_NUM: + case EXPR_SIZEOF: + case EXPR_OFFSETOF: + case EXPR_NEG: + case EXPR_PLUS: + case EXPR_MINUS: + case EXPR_TIMES: + case EXPR_DIV: + case EXPR_MOD: + case EXPR_BITNOT: + case EXPR_BITAND: + case EXPR_BITOR: + case EXPR_BITXOR: + case EXPR_LSHIFT: + case EXPR_RSHIFT: + case EXPR_EQUAL: + case EXPR_GE: + case EXPR_LE: + case EXPR_GT: + case EXPR_LT: + case EXPR_NOT: + case EXPR_AND: + case EXPR_OR: + data_type = extern_type_int; + break; + + default: + data_type = 0; + break; + } + + return data_type; + } + +string Expr::DataTypeStr(Env *env) const + { + Type *type = DataType(env); + + if ( ! type ) + { + throw Exception(this, + fmt("cannot find data type for expression `%s'", + orig())); + } + + return type->DataTypeStr(); + } + +string Expr::SetFunc(Output *out, Env *env) + { + switch ( expr_type_ ) + { + case EXPR_ID: + return set_function(id_); + case EXPR_MEMBER: + { + // Evaluate the parent + string parent_val(operand_[0]->EvalExpr(out, env)); + return parent_val + + "->" + + set_function(operand_[1]->id()); + } + break; + default: + throw Exception(this, + fmt("cannot generate set function " + "for expression `%s'", orig())); + break; + } + } + +bool Expr::ConstFold(Env* env, int* pn) const + { + switch ( expr_type_ ) + { + case EXPR_NUM: + *pn = num_->Num(); + return true; + case EXPR_ID: + return env->GetConstant(id_, pn); + default: + // ### FIXME: folding consts + return false; + } + } + +// TODO: build a generic data dependency extraction process +namespace { + + // Maximum of two minimal header sizes + int mhs_max(int h1, int h2) + { + if ( h1 < 0 || h2 < 0 ) + return -1; + else + { + // return max(h1, h2); + return h1 > h2 ? h1 : h2; + } + } + + // MHS required to evaluate the field + int mhs_letfield(Env* env, LetField* field) + { + return field->expr()->MinimalHeaderSize(env); + } + + int mhs_recordfield(Env* env, RecordField* field) + { + int offset = field->static_offset(); + if ( offset < 0 ) // offset cannot be statically determined + return -1; + int size = field->StaticSize(env, offset); + if ( size < 0 ) // size cannot be statically determined + return -1; + return offset + size; + } + + int mhs_casefield(Env* env, CaseField* field) + { + // TODO: deal with the index + int size = field->StaticSize(env); + if ( size < 0 ) // size cannot be statically determined + return -1; + return size; + } + + int mhs_field(Env* env, Field* field) + { + int mhs = -1; + switch ( field->tof() ) + { + case LET_FIELD: + { + LetField *f = + static_cast(field); + ASSERT(f); + mhs = mhs_letfield(env, f); + } + break; + + case CONTEXT_FIELD: + case FLOW_FIELD: + ASSERT(0); + break; + + case PARAM_FIELD: + mhs = 0; + break; + + case RECORD_FIELD: + case PADDING_FIELD: + { + RecordField *f = + static_cast(field); + ASSERT(f); + mhs = mhs_recordfield(env, f); + } + break; + + case CASE_FIELD: + { + CaseField *f = + static_cast(field); + ASSERT(f); + mhs = mhs_casefield(env, f); + } + break; + + case PARSE_VAR_FIELD: + case PRIV_VAR_FIELD: + case PUB_VAR_FIELD: + case TEMP_VAR_FIELD: + mhs = 0; + break; + + case WITHINPUT_FIELD: + { + // ### TODO: fix this + mhs = -1; + } + break; + } + return mhs; + } + + int mhs_id(Env *env, const ID *id) + { + int mhs = -1; + switch ( env->GetIDType(id) ) + { + case CONST: + case GLOBAL_VAR: + case TEMP_VAR: + case STATE_VAR: + case FUNC_ID: + case FUNC_PARAM: + mhs = 0; + break; + case MEMBER_VAR: + case PRIV_MEMBER_VAR: + { + Field* field = env->GetField(id); + if ( ! field ) + throw ExceptionIDNotField(id); + mhs = mhs_field(env, field); + } + break; + case UNION_VAR: + // TODO: deal with UNION_VAR + mhs = -1; + break; + case MACRO: + { + Expr *e = env->GetMacro(id); + mhs = e->MinimalHeaderSize(env); + } + break; + } + return mhs; + } +} + +int Expr::MinimalHeaderSize(Env *env) + { + int mhs; + + switch ( expr_type_ ) + { + case EXPR_NUM: + // Zero byte is required + mhs = 0; + break; + + case EXPR_ID: + mhs = mhs_id(env, id_); + break; + + case EXPR_MEMBER: + // TODO: this is not a tight bound because + // one actually does not have to parse the + // whole record to compute one particular + // field. + mhs = operand_[0]->MinimalHeaderSize(env); + break; + + case EXPR_SUBSCRIPT: + { + int index; + Type *array_type = operand_[0]->DataType(env); + Type *elem_type = array_type->ElementDataType(); + int elem_size = elem_type->StaticSize(env); + if ( elem_size >= 0 && + operand_[1]->ConstFold(env, &index) ) + { + mhs = elem_size * index; + } + else + { + mhs = -1; + } + } + + case EXPR_SIZEOF: + { + const ID* id = operand_[0]->id(); + ASSERT(id); + RecordField *rf; + Type *ty; + + if ( (rf = GetRecordField(id, env)) != 0 ) + { + if ( rf->StaticSize(env, -1) >= 0 ) + mhs = 0; + else + mhs = mhs_recordfield(env, rf); + } + + else if ( (ty = TypeDecl::LookUpType(id)) != 0 ) + { + mhs = 0; + } + + else + throw Exception(id, "not a record field or type"); + } + break; + + case EXPR_OFFSETOF: + { + const ID* id = operand_[0]->id(); + ASSERT(id); + RecordField *field = GetRecordField(id, env); + + mhs = field->static_offset(); + if ( mhs < 0 ) + { + mhs = 0; + // Take the MHS of the preceding (non-let) field + RecordField* prev_field = field->prev(); + ASSERT(prev_field); + mhs = mhs_recordfield(env, prev_field); + } + } + break; + + case EXPR_CALLARGS: + { + mhs = 0; + if ( args_ ) + for ( unsigned int i = 0; i < args_->size(); ++i ) + mhs = mhs_max(mhs, (*args_)[i]->MinimalHeaderSize(env)); + } + break; + case EXPR_CASE: + { + mhs = operand_[0]->MinimalHeaderSize(env); + for ( unsigned int i = 0; i < cases_->size(); ++i ) + { + CaseExpr * ce = (*cases_)[i]; + if ( ce->index() ) + for ( unsigned int j = 0; j < ce->index()->size(); ++j ) + mhs = mhs_max(mhs, (*ce->index())[j]->MinimalHeaderSize(env)); + mhs = mhs_max(mhs, ce->value()->MinimalHeaderSize(env)); + } + } + break; + default: + // Evaluate every operand by default + mhs = 0; + for ( int i = 0; i < 3; ++i ) + if ( operand_[i] ) + mhs = mhs_max(mhs, operand_[i]->MinimalHeaderSize(env)); + break; + } + + return mhs; + } + +bool Expr::HasReference(const ID *id) const + { + switch ( expr_type_ ) + { + case EXPR_ID: + return *id == *id_; + + case EXPR_MEMBER: + return operand_[0]->HasReference(id); + + case EXPR_CALLARGS: + { + foreach(i, ExprList, args_) + if ( (*i)->HasReference(id) ) + return true; + } + return false; + + case EXPR_CASE: + { + foreach(i, CaseExprList, cases_) + if ( (*i)->HasReference(id) ) + return true; + } + return false; + + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) + { + if ( operand_[i] && + operand_[i]->HasReference(id) ) + { + return true; + } + } + return false; + } + } + +bool Expr::DoTraverse(DataDepVisitor *visitor) + { + switch ( expr_type_ ) + { + case EXPR_ID: + break; + + case EXPR_MEMBER: + /* + For member expressions such X.Y, evaluating + X only is sufficient. (Actually trying to + evaluate Y will lead to error because Y is + not defined in the current environment.) + */ + if ( ! operand_[0]->Traverse(visitor) ) + return false; + break; + + case EXPR_CALLARGS: + { + foreach(i, ExprList, args_) + if ( ! (*i)->Traverse(visitor) ) + return false; + } + break; + + case EXPR_CASE: + { + foreach(i, CaseExprList, cases_) + if ( ! (*i)->Traverse(visitor) ) + return false; + } + break; + + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) + { + if ( operand_[i] && + ! operand_[i]->Traverse(visitor) ) + { + return false; + } + } + break; + } + + return true; + } + +bool Expr::RequiresAnalyzerContext() const + { + switch ( expr_type_ ) + { + case EXPR_ID: + return *id_ == *analyzer_context_id; + + case EXPR_MEMBER: + /* + For member expressions such X.Y, evaluating + X only is sufficient. (Actually trying to + evaluate Y will lead to error because Y is + not defined in the current environment.) + */ + return operand_[0]->RequiresAnalyzerContext(); + + case EXPR_CALLARGS: + { + foreach(i, ExprList, args_) + if ( (*i)->RequiresAnalyzerContext() ) + return true; + } + return false; + + case EXPR_CASE: + { + foreach(i, CaseExprList, cases_) + if ( (*i)->RequiresAnalyzerContext() ) + return true; + } + return false; + + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) + if ( operand_[i] && + operand_[i]->RequiresAnalyzerContext() ) + { + DEBUG_MSG("'%s' requires analyzer context\n", operand_[i]->orig()); + return true; + } + return false; + } + } + +CaseExpr::CaseExpr(ExprList *index, Expr *value) + : DataDepElement(DataDepElement::CASEEXPR), + index_(index), value_(value) + { + } + +CaseExpr::~CaseExpr() + { + delete_list(ExprList, index_); + delete value_; + } + +bool CaseExpr::DoTraverse(DataDepVisitor *visitor) + { + foreach(i, ExprList, index_) + if ( ! (*i)->Traverse(visitor) ) + return false; + return value_->Traverse(visitor); + } + +bool CaseExpr::HasReference(const ID *id) const + { + return value_->HasReference(id); + } + +bool CaseExpr::RequiresAnalyzerContext() const + { + // index_ should evaluate to constants + return value_->RequiresAnalyzerContext(); + } diff --git a/tools/binpac/src/pac_expr.def b/tools/binpac/src/pac_expr.def new file mode 100644 index 0000000000..d7c0319522 --- /dev/null +++ b/tools/binpac/src/pac_expr.def @@ -0,0 +1,34 @@ +EXPR_DEF(EXPR_ID, 0, "%s") +EXPR_DEF(EXPR_NUM, 0, "%s") +EXPR_DEF(EXPR_CSTR, 0, "%s") +EXPR_DEF(EXPR_REGEX, 0, "REGEX(%s)") +EXPR_DEF(EXPR_SUBSCRIPT, 2, "@element@(%s[%s])") +EXPR_DEF(EXPR_MEMBER, 2, "@%s->%s@") +EXPR_DEF(EXPR_PAREN, 1, " ( %s ) ") +EXPR_DEF(EXPR_CALL, 1, "%s(%s)") +EXPR_DEF(EXPR_CALLARGS, -1, "@custom@") +EXPR_DEF(EXPR_SIZEOF, 1, "@sizeof(%s)@") +EXPR_DEF(EXPR_OFFSETOF, 1, "@offsetof(%s)@") +EXPR_DEF(EXPR_NEG, 1, "-%s") +EXPR_DEF(EXPR_PLUS, 2, "%s + %s") +EXPR_DEF(EXPR_MINUS, 2, "%s - %s") +EXPR_DEF(EXPR_TIMES, 2, "%s * %s") +EXPR_DEF(EXPR_DIV, 2, "%s / %s") +EXPR_DEF(EXPR_MOD, 2, "%s %% %s") +EXPR_DEF(EXPR_BITNOT, 1, "~%s") +EXPR_DEF(EXPR_BITAND, 2, "%s & %s") +EXPR_DEF(EXPR_BITOR, 2, "%s | %s") +EXPR_DEF(EXPR_BITXOR, 2, "%s ^ %s") +EXPR_DEF(EXPR_LSHIFT, 2, "%s << %s") +EXPR_DEF(EXPR_RSHIFT, 2, "%s >> %s") +EXPR_DEF(EXPR_EQUAL, 2, "%s == %s") +EXPR_DEF(EXPR_NEQ, 2, "%s != %s") +EXPR_DEF(EXPR_GE, 2, "%s >= %s") +EXPR_DEF(EXPR_LE, 2, "%s <= %s") +EXPR_DEF(EXPR_GT, 2, "%s > %s") +EXPR_DEF(EXPR_LT, 2, "%s < %s") +EXPR_DEF(EXPR_NOT, 1, "! %s") +EXPR_DEF(EXPR_AND, 2, "%s && %s") +EXPR_DEF(EXPR_OR, 2, "%s || %s") +EXPR_DEF(EXPR_COND, 3, "%s ? %s : %s") +EXPR_DEF(EXPR_CASE, -1, "@custom@") diff --git a/tools/binpac/src/pac_expr.h b/tools/binpac/src/pac_expr.h new file mode 100644 index 0000000000..be1e70c6ea --- /dev/null +++ b/tools/binpac/src/pac_expr.h @@ -0,0 +1,139 @@ +#ifndef pac_expr_h +#define pac_expr_h + +#include "pac_common.h" +#include "pac_datadep.h" + +class CaseExpr; + +class Expr : public Object, public DataDepElement +{ +public: + enum ExprType { +# define EXPR_DEF(type, x, y) type, +# include "pac_expr.def" +# undef EXPR_DEF + }; + + void init(); + + Expr(ID *id); + Expr(Number *num); + Expr(ConstString *s); + Expr(RegEx *regex); + Expr(ExprList *args); // for EXPR_CALLARGS + Expr(Expr *index, CaseExprList *cases); + + Expr(ExprType type, Expr *op1); + Expr(ExprType type, Expr *op1, Expr *op2); + Expr(ExprType type, Expr *op1, Expr *op2, Expr *op3); + + virtual ~Expr(); + + const char *orig() const { return orig_.c_str(); } + const ID *id() const { return id_; } + const char *str() const { return str_.c_str(); } + ExprType expr_type() const { return expr_type_; } + + void AddCaseExpr(CaseExpr *case_expr); + + // Returns the data "type" of the expression. Here we only + // do a serious job for the EXPR_MEMBER and EXPR_SUBSCRIPT + // operators. For arithmetic operations, we fall back + // to "int". + Type *DataType(Env *env) const; + string DataTypeStr(Env *env) const; + + // Note: EvalExpr() may generate C++ statements in order to evaluate + // variables in the expression, so the following is wrong: + // + // out->print("int x = "); + // out->println("%s", expr->EvalExpr(out, env)); + // + // While putting them together is right: + // + // out->println("int x = %s", expr->EvalExpr(out, env)); + // + const char *EvalExpr(Output *out, Env *env); + + // force evaulation of IDs contained in this expression; + // necessary with case expr and conditional let fields (&if) + // for correct parsing of fields + void ForceIDEval(Output *out_cc, Env *env); + + // Returns the set_* function of the expression. + // The expression must be of form ID or x.ID. + string SetFunc(Output *out, Env *env); + + // Returns true if the expression folds to an integer + // constant with env, and puts the constant in *pn. + // + bool ConstFold(Env *env, int *pn) const; + + // Whether id is referenced in the expression + bool HasReference(const ID *id) const; + + // Suppose the data for type might be incomplete, what is + // the minimal number of bytes from data head required to + // compute the expression? For example, how many bytes of frame + // header do we need to determine the length of the frame? + // + // The parameter points to the Env of a type. + // + // Returns -1 if the number is not a constant. + // + int MinimalHeaderSize(Env *env); + + // Whether evaluation of the expression requires the analyzer context + bool RequiresAnalyzerContext() const; + +protected: + bool DoTraverse(DataDepVisitor *visitor); + +private: + ExprType expr_type_; + + int num_operands_; + Expr *operand_[3]; + + ID *id_; // EXPR_ID + Number *num_; // EXPR_NUM + ConstString *cstr_; // EXPR_CSTR + RegEx *regex_; // EXPR_REGEX + ExprList *args_; // EXPR_CALLARGS + CaseExprList *cases_; // EXPR_CASE + + string str_; // value string + string orig_; // original string for debugging info + + void GenStrFromFormat(Env *env); + void GenEval(Output *out, Env *env); + void GenCaseEval(Output *out_cc, Env *env); +}; + +string OrigExprList(ExprList *exprlist); +string EvalExprList(ExprList *exprlist, Output *out, Env *env); + +// An entry of the case expression, consisting of one or more constant +// expressions for the case index and a value expression. +class CaseExpr : public Object, public DataDepElement +{ +public: + CaseExpr(ExprList *index, Expr *value); + virtual ~CaseExpr(); + + ExprList *index() const { return index_; } + Expr *value() const { return value_; } + + bool HasReference(const ID *id) const; + bool RequiresAnalyzerContext() const; + +protected: + bool DoTraverse(DataDepVisitor *visitor); + +private: + ExprList *index_; + Expr *value_; +}; + +#endif // pac_expr_h diff --git a/tools/binpac/src/pac_externtype.def b/tools/binpac/src/pac_externtype.def new file mode 100644 index 0000000000..aeac5a51b0 --- /dev/null +++ b/tools/binpac/src/pac_externtype.def @@ -0,0 +1,15 @@ +EXTERNTYPE(bool, bool, NUMBER) +EXTERNTYPE(int, int, NUMBER) +EXTERNTYPE(double, double, NUMBER) +EXTERNTYPE(string, string, PLAIN) +EXTERNTYPE(void, void, PLAIN) +EXTERNTYPE(voidptr, void, POINTER) +EXTERNTYPE(nullptr, nullptr, PLAIN) +EXTERNTYPE(bytearray, bytearray, PLAIN) +EXTERNTYPE(const_charptr, const_charptr, PLAIN) +EXTERNTYPE(const_byteptr, const_byteptr, PLAIN) +// EXTERNTYPE(const_byteseg, const_byteseg, PLAIN) +EXTERNTYPE(const_bytestring, const_bytestring, PLAIN) +// EXTERNTYPE(bytestring, bytestring, PLAIN) +EXTERNTYPE(re_matcher, re_matcher, PLAIN) +EXTERNTYPE(flowbuffer, FlowBuffer, POINTER) diff --git a/tools/binpac/src/pac_exttype.cc b/tools/binpac/src/pac_exttype.cc new file mode 100644 index 0000000000..659d4cdc5e --- /dev/null +++ b/tools/binpac/src/pac_exttype.cc @@ -0,0 +1,76 @@ +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_decl.h" + +bool ExternType::DefineValueVar() const + { + return true; + } + +string ExternType::DataTypeStr() const + { + switch ( ext_type_ ) + { + case PLAIN: + case NUMBER: + return id_->Name(); + case POINTER: + return string(id_->Name()) + " *"; + default: + ASSERT(0); + return ""; + } + } + +int ExternType::StaticSize(Env* env) const + { + ASSERT(0); + return -1; + } + +bool ExternType::ByteOrderSensitive() const + { + return false; + } + +string ExternType::EvalMember(const ID *member_id) const + { + return strfmt("%s%s", + ext_type_ == POINTER ? "->" : ".", + member_id->Name()); + } + +void ExternType::DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) + { + ASSERT(0); + } + +void ExternType::GenDynamicSize(Output* out, Env* env, const DataPtr& data) + { + ASSERT(0); + } + +Type *ExternType::DoClone() const + { + return new ExternType(id_->clone(), ext_type_); + } + +// Definitions of pre-defined external types + +#define EXTERNTYPE(name, ctype, exttype) ExternType *extern_type_##name = 0; +#include "pac_externtype.def" +#undef EXTERNTYPE + +void ExternType::static_init() + { + ID *id; + // TypeDecl *decl; + // decl = new TypeDecl(id, 0, extern_type_##name); + +#define EXTERNTYPE(name, ctype, exttype) \ + id = new ID(#ctype); \ + extern_type_##name = new ExternType(id, ExternType::exttype); \ + Type::AddPredefinedType(#name, extern_type_##name); +#include "pac_externtype.def" +#undef EXTERNTYPE + } diff --git a/tools/binpac/src/pac_exttype.h b/tools/binpac/src/pac_exttype.h new file mode 100644 index 0000000000..6d81608195 --- /dev/null +++ b/tools/binpac/src/pac_exttype.h @@ -0,0 +1,47 @@ +#ifndef pac_exttype_h +#define pac_exttype_h + +#include "pac_type.h" + +// ExternType represent external C++ types that are not defined in +// PAC specification (therefore they cannot appear in data layout +// spefication, e.g., in a record field). The type name is copied +// literally to the compiled code. + +class ExternType : public Type +{ +public: + enum EXTType { PLAIN, NUMBER, POINTER }; + ExternType(const ID *id, EXTType ext_type) + : Type(EXTERN), + id_(id), + ext_type_(ext_type) {} + + bool DefineValueVar() const; + string DataTypeStr() const; + int StaticSize(Env *env) const; + bool ByteOrderSensitive() const; + + string EvalMember(const ID *member_id) const; + bool IsNumericType() const { return ext_type_ == NUMBER; } + bool IsPointerType() const { return ext_type_ == POINTER; } + +protected: + void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); + void GenDynamicSize(Output *out, Env *env, const DataPtr& data); + + Type *DoClone() const; + +private: + const ID *id_; + EXTType ext_type_; + +public: + static void static_init(); +}; + +#define EXTERNTYPE(name, ctype, exttype) extern ExternType *extern_type_##name; +#include "pac_externtype.def" +#undef EXTERNTYPE + +#endif // pac_exttype_h diff --git a/tools/binpac/src/pac_field.cc b/tools/binpac/src/pac_field.cc new file mode 100644 index 0000000000..0ee70e4b28 --- /dev/null +++ b/tools/binpac/src/pac_field.cc @@ -0,0 +1,143 @@ +#include "pac_attr.h" +#include "pac_common.h" +#include "pac_exception.h" +#include "pac_field.h" +#include "pac_id.h" +#include "pac_type.h" + +Field::Field(FieldType tof, int flags, ID *id, Type *type) + : DataDepElement(DataDepElement::FIELD), + tof_(tof), flags_(flags), id_(id), type_(type) + { + decl_id_ = current_decl_id; + field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name()); + attrs_ = 0; + } + +Field::~Field() + { + delete id_; + delete type_; + delete_list(AttrList, attrs_); + } + +void Field::AddAttr(AttrList* attrs) + { + if ( ! attrs_ ) + { + attrs_ = attrs; + } + else + { + attrs_->insert(attrs_->end(), attrs->begin(), attrs->end()); + delete attrs; + } + + foreach(i, AttrList, attrs) + ProcessAttr(*i); + } + +void Field::ProcessAttr(Attr *a) + { + switch ( a->type() ) + { + case ATTR_IF: + if ( tof() != LET_FIELD && + tof() != WITHINPUT_FIELD ) + { + throw Exception(a, + "&if can only be applied to a " + "let field"); + } + break; + default: + break; + } + + if ( type_ ) + type_->ProcessAttr(a); + } + +bool Field::anonymous_field() const + { + return type_ && type_->anonymous_value_var(); + } + +int Field::ValueVarType() const + { + if ( flags_ & CLASS_MEMBER ) + return (flags_ & PUBLIC_READABLE) ? MEMBER_VAR : PRIV_MEMBER_VAR; + else + return TEMP_VAR; + } + +void Field::Prepare(Env *env) + { + if ( type_ ) + { + if ( anonymous_field() ) + flags_ &= ~(CLASS_MEMBER | PUBLIC_READABLE); + if ( ! type_->persistent() ) + flags_ &= (~PUBLIC_READABLE); + + type_->set_value_var(id(), ValueVarType()); + type_->Prepare(env, + flags_ & TYPE_TO_BE_PARSED ? + Type::TO_BE_PARSED : 0); + env->SetField(id(), this); + } + } + +void Field::GenPubDecls(Output* out_h, Env* env) + { + if ( type_ && (flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER) ) + type_->GenPubDecls(out_h, env); + } + +void Field::GenPrivDecls(Output* out_h, Env* env) + { + // Generate private declaration only if it is a class member + if ( type_ && (flags_ & CLASS_MEMBER) ) + type_->GenPrivDecls(out_h, env); + } + +void Field::GenTempDecls(Output* out_h, Env* env) + { + // Generate temp field + if ( type_ && !(flags_ & CLASS_MEMBER) ) + type_->GenPrivDecls(out_h, env); + } + +void Field::GenInitCode(Output* out_cc, Env* env) + { + if ( type_ && ! anonymous_field() ) + type_->GenInitCode(out_cc, env); + } + +void Field::GenCleanUpCode(Output* out_cc, Env* env) + { + if ( type_ && ! anonymous_field() ) + type_->GenCleanUpCode(out_cc, env); + } + +bool Field::DoTraverse(DataDepVisitor *visitor) + { + // Check parameterized type + if ( type_ && ! type_->Traverse(visitor) ) + return false; + foreach(i, AttrList, attrs_) + if ( ! (*i)->Traverse(visitor) ) + return false; + return true; + } + +bool Field::RequiresAnalyzerContext() const + { + // Check parameterized type + if ( type_ && type_->RequiresAnalyzerContext() ) + return true; + foreach(i, AttrList, attrs_) + if ( (*i)->RequiresAnalyzerContext() ) + return true; + return false; + } diff --git a/tools/binpac/src/pac_field.h b/tools/binpac/src/pac_field.h new file mode 100644 index 0000000000..169c8110ec --- /dev/null +++ b/tools/binpac/src/pac_field.h @@ -0,0 +1,84 @@ +#ifndef pac_field_h +#define pac_field_h + +#include "pac_common.h" +#include "pac_datadep.h" + +// A "field" is a member of class. + +enum FieldType { + CASE_FIELD, + CONTEXT_FIELD, + FLOW_FIELD, + LET_FIELD, + PADDING_FIELD, + PARAM_FIELD, + RECORD_FIELD, + PARSE_VAR_FIELD, + PRIV_VAR_FIELD, + PUB_VAR_FIELD, + TEMP_VAR_FIELD, + WITHINPUT_FIELD, +}; + +class Field : public Object, public DataDepElement +{ +public: + Field(FieldType tof, int flags, ID *id, Type *type); + // Field flags + + // Whether the field will be evaluated by calling the Parse() + // function of the type + static const int TYPE_TO_BE_PARSED = 1; + static const int TYPE_NOT_TO_BE_PARSED = 0; + + // Whether the field is a member of the class or a temp + // variable + static const int CLASS_MEMBER = 2; + static const int NOT_CLASS_MEMBER = 0; + + // Whether the field is public readable + static const int PUBLIC_READABLE = 4; + static const int NOT_PUBLIC_READABLE = 0; + + virtual ~Field(); + + FieldType tof() const { return tof_; } + const ID* id() const { return id_; } + Type *type() const { return type_; } + const ID* decl_id() const { return decl_id_; } + + bool anonymous_field() const; + + void AddAttr(AttrList* attrs); + + // The field interface + virtual void ProcessAttr(Attr *attr); + virtual void Prepare(Env* env); + + virtual void GenPubDecls(Output* out, Env* env); + virtual void GenPrivDecls(Output* out, Env* env); + virtual void GenTempDecls(Output* out, Env* env); + + virtual void GenInitCode(Output* out, Env* env); + virtual void GenCleanUpCode(Output* out, Env* env); + + virtual bool RequiresAnalyzerContext() const; + +protected: + int ValueVarType() const; + bool ToBeParsed() const; + + bool DoTraverse(DataDepVisitor *visitor); + +protected: + FieldType tof_; + int flags_; + ID* id_; + Type *type_; + const ID* decl_id_; + string field_id_str_; + AttrList* attrs_; +}; + +#endif // pac_field_h diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc new file mode 100644 index 0000000000..adf574e879 --- /dev/null +++ b/tools/binpac/src/pac_flow.cc @@ -0,0 +1,340 @@ +#include "pac_analyzer.h" +#include "pac_conn.h" +#include "pac_context.h" +#include "pac_dataptr.h" +#include "pac_dataunit.h" +#include "pac_embedded.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_flow.h" +#include "pac_output.h" +#include "pac_param.h" +#include "pac_paramtype.h" +#include "pac_type.h" +#include "pac_varfield.h" + + +FlowDecl::FlowDecl(ID *id, + ParamList *params, + AnalyzerElementList *elemlist) + : AnalyzerDecl(id, FLOW, params) + { + dataunit_ = 0; + conn_decl_ = 0; + flow_buffer_var_field_ = 0; + AddElements(elemlist); + } + +FlowDecl::~FlowDecl() + { + delete flow_buffer_var_field_; + delete dataunit_; + } + +ParameterizedType *FlowDecl::flow_buffer_type_ = 0; + +ParameterizedType *FlowDecl::flow_buffer_type() + { + if ( ! flow_buffer_type_ ) + { + flow_buffer_type_ = new ParameterizedType(new ID(kFlowBufferClass), 0); + } + return flow_buffer_type_; + } + +void FlowDecl::AddBaseClass(vector *base_classes) const + { + base_classes->push_back("binpac::FlowAnalyzer"); + } + +void FlowDecl::ProcessFlowElement(AnalyzerFlow *flow_elem) + { + throw Exception( + flow_elem, + "flow should be defined in only a connection declaration"); + } + +void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) + { + if ( dataunit_ ) + { + throw Exception(dataunit_elem, + "dataunit already defined"); + } + dataunit_ = dataunit_elem; + + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) + { + dataunit_->data_type()->MarkIncrementalInput(); + + flow_buffer_var_field_ = new PrivVarField( + flow_buffer_id->clone(), + FlowDecl::flow_buffer_type()->Clone()); + type_->AddField(flow_buffer_var_field_); + + ASSERT(AnalyzerContextDecl::current_analyzer_context()); + AnalyzerContextDecl::current_analyzer_context()->AddFlowBuffer(); + + // Add an argument to the context initiation + dataunit_->context_type()->AddParamArg( + new Expr(flow_buffer_var_field_->id()->clone())); + } + } + +void FlowDecl::Prepare() + { + // Add the connection parameter + if ( ! conn_decl_ ) + { + throw Exception(this, + "no connection is not declared for the flow"); + } + + if ( ! params_ ) + params_ = new ParamList(); + + params_->insert(params_->begin(), + new Param(connection_id->clone(), + conn_decl_->DataType())); + + AnalyzerDecl::Prepare(); + + dataunit_->Prepare(env_); + } + +void FlowDecl::GenPubDecls(Output *out_h, Output *out_cc) + { + AnalyzerDecl::GenPubDecls(out_h, out_cc); + } + +void FlowDecl::GenPrivDecls(Output *out_h, Output *out_cc) + { + // Declare the data unit + dataunit_->dataunit_var_field()->GenPrivDecls(out_h, env_); + + // Declare the analyzer context + dataunit_->context_var_field()->GenPrivDecls(out_h, env_); + + AnalyzerDecl::GenPrivDecls(out_h, out_cc); + } + +void FlowDecl::GenInitCode(Output *out_cc) + { + AnalyzerDecl::GenInitCode(out_cc); + + out_cc->println("%s = 0;", + env_->LValue(dataunit_id)); + out_cc->println("%s = 0;", + env_->LValue(analyzer_context_id)); + + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) + { + flow_buffer_var_field_->type()->GenPreParsing(out_cc, env_); + env_->SetEvaluated(flow_buffer_var_field_->id()); + } + } + +void FlowDecl::GenCleanUpCode(Output *out_cc) + { + GenDeleteDataUnit(out_cc); + AnalyzerDecl::GenCleanUpCode(out_cc); + } + +void FlowDecl::GenEOFFunc(Output *out_h, Output *out_cc) + { + string proto = strfmt("%s()", kFlowEOF); + + out_h->println("void %s;", proto.c_str()); + + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + + foreach(i, AnalyzerHelperList, eof_helpers_) + { + (*i)->GenCode(0, out_cc, this); + } + + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) + { + out_cc->println("%s->set_eof();", + env_->LValue(flow_buffer_id)); + out_cc->println("%s(0, 0);", kNewData); + } + + out_cc->println("}"); + out_cc->dec_indent(); + } + +void FlowDecl::GenGapFunc(Output *out_h, Output *out_cc) + { + string proto = strfmt("%s(int gap_length)", kFlowGap); + + out_h->println("void %s;", proto.c_str()); + + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) + { + out_cc->println("%s->NewGap(gap_length);", + env_->LValue(flow_buffer_id)); + } + + out_cc->println("}"); + out_cc->dec_indent(); + } + +void FlowDecl::GenProcessFunc(Output *out_h, Output *out_cc) + { + env_->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); + env_->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); + + string proto = + strfmt("%s(const_byteptr %s, const_byteptr %s)", + kNewData, + env_->LValue(begin_of_data), + env_->LValue(end_of_data)); + + out_h->println("void %s;", proto.c_str()); + + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + + out_cc->println("try"); + out_cc->inc_indent(); + out_cc->println("{"); + + env_->SetEvaluated(begin_of_data); + env_->SetEvaluated(end_of_data); + + switch ( dataunit_->type() ) + { + case AnalyzerDataUnit::DATAGRAM: + GenCodeDatagram(out_cc); + break; + case AnalyzerDataUnit::FLOWUNIT: + GenCodeFlowUnit(out_cc); + break; + default: + ASSERT(0); + } + + out_cc->println("}"); + out_cc->dec_indent(); + + out_cc->println("catch ( Exception const &e )"); + out_cc->inc_indent(); + out_cc->println("{"); + GenCleanUpCode(out_cc); + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) + { + out_cc->println("%s->DiscardData();", + env_->LValue(flow_buffer_id)); + } + out_cc->println("throw e;"); + out_cc->println("}"); + out_cc->dec_indent(); + + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); + } + +void FlowDecl::GenNewDataUnit(Output *out_cc) + { + Type *unit_datatype = dataunit_->data_type(); + // dataunit_->data_type()->GenPreParsing(out_cc, env_); + dataunit_->GenNewDataUnit(out_cc, env_); + if ( unit_datatype->buffer_input() && + unit_datatype->buffer_mode() == Type::BUFFER_BY_LENGTH ) + { + out_cc->println("%s->NewFrame(0, false);", + env_->LValue(flow_buffer_id)); + } + dataunit_->GenNewContext(out_cc, env_); + } + +void FlowDecl::GenDeleteDataUnit(Output *out_cc) + { + // Do not just delete dataunit, because we may just want to Unref it. + // out_cc->println("delete %s;", env_->LValue(dataunit_id)); + dataunit_->data_type()->GenCleanUpCode(out_cc, env_); + dataunit_->context_type()->GenCleanUpCode(out_cc, env_); + } + +void FlowDecl::GenCodeFlowUnit(Output *out_cc) + { + Type *unit_datatype = dataunit_->data_type(); + + out_cc->println("%s->NewData(%s, %s);", + env_->LValue(flow_buffer_id), + env_->RValue(begin_of_data), + env_->RValue(end_of_data)); + + out_cc->println("while ( %s->data_available() && ", + env_->LValue(flow_buffer_id)); + out_cc->inc_indent(); + out_cc->println("( !%s->have_pending_request() || %s->ready() ) )", + env_->LValue(flow_buffer_id), env_->LValue(flow_buffer_id)); + out_cc->println("{"); + + // Generate a new dataunit if necessary + out_cc->println("if ( ! %s )", env_->LValue(dataunit_id)); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("BINPAC_ASSERT(!%s);", + env_->LValue(analyzer_context_id)); + GenNewDataUnit(out_cc); + out_cc->println("}"); + out_cc->dec_indent(); + + DataPtr data(env_, 0, 0); + unit_datatype->GenParseCode(out_cc, env_, data, 0); + + out_cc->println("if ( %s )", + unit_datatype->parsing_complete(env_).c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("// Clean up the flow unit after parsing"); + GenDeleteDataUnit(out_cc); + // out_cc->println("BINPAC_ASSERT(%s == 0);", env_->LValue(dataunit_id)); + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println("else"); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("// Resume upon next input segment"); + out_cc->println("BINPAC_ASSERT(!%s->ready());", + env_->RValue(flow_buffer_id)); + out_cc->println("break;"); + out_cc->println("}"); + out_cc->dec_indent(); + + out_cc->println("}"); + out_cc->dec_indent(); + } + +void FlowDecl::GenCodeDatagram(Output *out_cc) + { + Type *unit_datatype = dataunit_->data_type(); + GenNewDataUnit(out_cc); + + string parse_params = strfmt("%s, %s", + env_->RValue(begin_of_data), + env_->RValue(end_of_data)); + + if ( RequiresAnalyzerContext::compute(unit_datatype) ) + { + parse_params += ", "; + parse_params += env_->RValue(analyzer_context_id); + } + + DataPtr dataptr(env_, begin_of_data, 0); + unit_datatype->GenParseCode(out_cc, env_, dataptr, 0); + + GenDeleteDataUnit(out_cc); + } diff --git a/tools/binpac/src/pac_flow.h b/tools/binpac/src/pac_flow.h new file mode 100644 index 0000000000..652f206992 --- /dev/null +++ b/tools/binpac/src/pac_flow.h @@ -0,0 +1,47 @@ +#ifndef pac_flow_h +#define pac_flow_h + +#include "pac_analyzer.h" + +class FlowDecl : public AnalyzerDecl +{ +public: + FlowDecl(ID *flow_id, ParamList *params, AnalyzerElementList *elemlist); + ~FlowDecl(); + + void Prepare(); + + void set_conn_decl(ConnDecl *c) { conn_decl_ = c; } + + static ParameterizedType *flow_buffer_type(); + +protected: + void AddBaseClass(vector *base_classes) const; + + void GenInitCode(Output *out_cc); + void GenCleanUpCode(Output *out_cc); + void GenProcessFunc(Output *out_h, Output *out_cc); + void GenEOFFunc(Output *out_h, Output *out_cc); + void GenGapFunc(Output *out_h, Output *out_cc); + + void GenPubDecls(Output *out_h, Output *out_cc); + void GenPrivDecls(Output *out_h, Output *out_cc); + + void ProcessFlowElement(AnalyzerFlow *flow_elem); + void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem); + +private: + void GenNewDataUnit(Output *out_cc); + void GenDeleteDataUnit(Output *out_cc); + void GenCodeFlowUnit(Output *out_cc); + void GenCodeDatagram(Output *out_cc); + + AnalyzerDataUnit *dataunit_; + ConnDecl *conn_decl_; + + Field *flow_buffer_var_field_; + + static ParameterizedType *flow_buffer_type_; +}; + +#endif // pac_flow_h diff --git a/tools/binpac/src/pac_func.cc b/tools/binpac/src/pac_func.cc new file mode 100644 index 0000000000..8bde6e10f6 --- /dev/null +++ b/tools/binpac/src/pac_func.cc @@ -0,0 +1,123 @@ +#include "pac_embedded.h" +#include "pac_expr.h" +#include "pac_func.h" +#include "pac_output.h" +#include "pac_param.h" +#include "pac_type.h" + +Function::Function(ID *id, Type *type, ParamList *params) + : id_(id), type_(type), params_(params), expr_(0), code_(0) + { + analyzer_decl_ = 0; + env_ = 0; + } + +Function::~Function() + { + delete id_; + delete type_; + delete_list(ParamList, params_); + delete env_; + delete expr_; + delete code_; + } + +void Function::Prepare(Env *env) + { + env->AddID(id_, FUNC_ID, type_); + env->SetEvaluated(id_); + + env_ = new Env(env, this); + + foreach(i, ParamList, params_) + { + Param *p = *i; + env_->AddID(p->id(), FUNC_PARAM, p->type()); + env_->SetEvaluated(p->id()); + } + } + +void Function::GenForwardDeclaration(Output* out_h) + { + // Do nothing + } + +void Function::GenCode(Output* out_h, Output* out_cc) + { + out_h->println("%s %s(%s);", + type_->DataTypeStr().c_str(), + id_->Name(), + ParamDecls(params_).c_str()); + + string class_str = ""; + if ( analyzer_decl_ ) + class_str = strfmt("%s::", analyzer_decl_->id()->Name()); + + string proto_str = strfmt("%s %s%s(%s)", + type_->DataTypeStr().c_str(), + class_str.c_str(), + id_->Name(), + ParamDecls(params_).c_str()); + + ASSERT(!(expr_ && code_)); + + if ( expr_ ) + { + out_cc->println("%s", proto_str.c_str()); + + out_cc->inc_indent(); + out_cc->println("{"); + + out_cc->println("return static_cast<%s>(%s);", + type_->DataTypeStr().c_str(), + expr_->EvalExpr(out_cc, env_)); + + out_cc->println("}"); + out_cc->dec_indent(); + } + + else if ( code_ ) + { + out_cc->println("%s", proto_str.c_str()); + + out_cc->inc_indent(); + out_cc->println("{"); + + code_->GenCode(out_cc, env_); + + out_cc->println("}"); + out_cc->dec_indent(); + } + + out_cc->println(""); + } + +FuncDecl::FuncDecl(Function *function) + : Decl(function->id()->clone(), FUNC), function_(function) + { + function_->Prepare(global_env()); + } + +FuncDecl::~FuncDecl() + { + delete function_; + } + +void FuncDecl::Prepare() + { + } + +void FuncDecl::GenForwardDeclaration(Output *out_h) + { + function_->GenForwardDeclaration(out_h); + } + +void FuncDecl::GenCode(Output *out_h, Output *out_cc) + { + function_->GenCode(out_h, out_cc); + } + +AnalyzerFunction::AnalyzerFunction(Function *function) + : AnalyzerElement(FUNCTION), function_(function) + { + } diff --git a/tools/binpac/src/pac_func.h b/tools/binpac/src/pac_func.h new file mode 100644 index 0000000000..df862323bb --- /dev/null +++ b/tools/binpac/src/pac_func.h @@ -0,0 +1,68 @@ +#ifndef pac_func_h +#define pac_func_h + +#include "pac_decl.h" +#include "pac_analyzer.h" + +class Function : public Object +{ +public: + Function(ID *id, Type *type, ParamList *params); + ~Function(); + + ID *id() const { return id_; } + + AnalyzerDecl *analyzer_decl() const { return analyzer_decl_; } + void set_analyzer_decl(AnalyzerDecl *decl) { analyzer_decl_ = decl; } + + Expr *expr() const { return expr_; } + void set_expr(Expr *expr) { expr_ = expr; } + + EmbeddedCode *code() const { return code_; } + void set_code(EmbeddedCode *code) { code_ = code; } + + void Prepare(Env *env); + void GenForwardDeclaration(Output *out_h); + void GenCode(Output *out_h, Output *out_cc); + +private: + Env *env_; + + ID *id_; + Type *type_; + ParamList *params_; + + AnalyzerDecl *analyzer_decl_; + + Expr *expr_; + EmbeddedCode *code_; +}; + +class FuncDecl : public Decl +{ +public: + FuncDecl(Function *function); + ~FuncDecl(); + + Function *function() const { return function_; } + + void Prepare(); + void GenForwardDeclaration(Output *out_h); + void GenCode(Output *out_h, Output *out_cc); + +private: + Function *function_; +}; + +class AnalyzerFunction : public AnalyzerElement +{ +public: + AnalyzerFunction(Function *function); + + Function *function() const { return function_; } + +private: + Function *function_; +}; + +#endif // pac_func_h diff --git a/tools/binpac/src/pac_id.cc b/tools/binpac/src/pac_id.cc new file mode 100644 index 0000000000..5eb7a0d985 --- /dev/null +++ b/tools/binpac/src/pac_id.cc @@ -0,0 +1,440 @@ +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_field.h" +#include "pac_id.h" +#include "pac_type.h" +#include "pac_utils.h" + +const ID *default_value_var = 0; +const ID *null_id = 0; +const ID *null_byteseg_id = 0; +const ID *null_decl_id = 0; +const ID *begin_of_data = 0; +const ID *end_of_data = 0; +const ID *len_of_data = 0; +const ID *byteorder_id = 0; +const ID *bigendian_id = 0; +const ID *littleendian_id = 0; +const ID *unspecified_byteorder_id = 0; +const ID *const_true_id = 0; +const ID *const_false_id = 0; +const ID *analyzer_context_id = 0; +const ID *context_macro_id = 0; +const ID *this_id = 0; +const ID *sourcedata_id = 0; +const ID *connection_id = 0; +const ID *upflow_id = 0; +const ID *downflow_id = 0; +const ID *dataunit_id = 0; +const ID *flow_buffer_id = 0; +const ID *element_macro_id = 0; +const ID *input_macro_id = 0; +const ID *cxt_connection_id = 0; +const ID *cxt_flow_id = 0; +const ID *parsing_state_id = 0; +const ID *buffering_state_id = 0; + +int ID::anonymous_id_seq = 0; + +ID *ID::NewAnonymousID(const string &prefix) + { + ID *id = new ID(fmt("%s%03d", prefix.c_str(), ++anonymous_id_seq)); + id->anonymous_id_ = true; + return id; + } + +IDRecord::IDRecord(Env *arg_env, const ID* arg_id, IDType arg_id_type) + : env(arg_env), id(arg_id), id_type(arg_id_type) + { + eval = 0; + evaluated = in_evaluation = false; + setfunc = ""; // except for STATE_VAR + switch (id_type) + { + case MEMBER_VAR: + rvalue = strfmt("%s()", id->Name()); + lvalue = strfmt("%s_", id->Name()); + break; + case PRIV_MEMBER_VAR: + rvalue = strfmt("%s_", id->Name()); + lvalue = strfmt("%s_", id->Name()); + break; + case UNION_VAR: + rvalue = strfmt("%s()", id->Name()); + lvalue = strfmt("%s_", id->Name()); + break; + case CONST: + case GLOBAL_VAR: + rvalue = strfmt("%s", id->Name()); + lvalue = strfmt("%s", id->Name()); + break; + case TEMP_VAR: + rvalue = strfmt("t_%s", id->Name()); + lvalue = strfmt("t_%s", id->Name()); + break; + case STATE_VAR: + rvalue = strfmt("%s()", id->Name()); + lvalue = strfmt("%s_", id->Name()); + break; + case MACRO: + rvalue = "@MACRO@"; + lvalue = "@MACRO@"; + break; + case FUNC_ID: + rvalue = strfmt("%s", id->Name()); + lvalue = "@FUNC_ID@"; + break; + case FUNC_PARAM: + rvalue = strfmt("%s", id->Name()); + lvalue = "@FUNC_PARAM@"; + break; + } + field = 0; + constant_set = false; + } + +IDRecord::~IDRecord() + { + } + +void IDRecord::SetConstant(int c) + { + ASSERT(id_type == CONST); + constant_set = true; + constant = c; + } + +bool IDRecord::GetConstant(int *pc) const + { + if ( constant_set ) + *pc = constant; + return constant_set; + } + +void IDRecord::SetMacro(Expr *e) + { + ASSERT(id_type == MACRO); + macro = e; + } + +Expr *IDRecord::GetMacro() const + { + ASSERT(id_type == MACRO); + return macro; + } + +void IDRecord::SetEvaluated(bool v) + { + if ( v ) + ASSERT(! evaluated); + evaluated = v; + } + +void IDRecord::Evaluate(Output* out, Env* env) + { + if ( evaluated ) + return; + + if ( ! out ) + throw ExceptionIDNotEvaluated(id); + + if ( ! eval ) + throw Exception(id, "no evaluation method"); + + if ( in_evaluation ) + throw ExceptionCyclicDependence(id); + + in_evaluation = true; + eval->GenEval(out, env); + in_evaluation = false; + + evaluated = true; + } + +const char* IDRecord::RValue() const + { + if ( id_type == MACRO ) + return macro->EvalExpr(0, env); + + if ( id_type == TEMP_VAR && ! evaluated ) + throw ExceptionIDNotEvaluated(id); + + return rvalue.c_str(); + } + +const char* IDRecord::LValue() const + { + ASSERT(id_type != MACRO && id_type != FUNC_ID); + return lvalue.c_str(); + } + +Env::Env(Env* parent_env, Object* context_object) + : parent(parent_env), context_object_(context_object) + { + allow_undefined_id_ = false; + in_branch_ = false; + } + +Env::~Env() + { + for ( id_map_t::iterator it = id_map.begin(); it != id_map.end(); ++it ) + { + delete it->second; + it->second = 0; + } + } + +void Env::AddID(const ID* id, IDType id_type, Type *data_type) + { + DEBUG_MSG("To add ID `%s'...\n", id->Name()); + id_map_t::iterator it = id_map.find(id); + if ( it != id_map.end() ) + { + DEBUG_MSG("Duplicate definition: `%s'\n", it->first->Name()); + throw ExceptionIDRedefinition(id); + } + id_map[id] = new IDRecord(this, id, id_type); + // TODO: figure out when data_type must be non-NULL + // ASSERT(data_type); + SetDataType(id, data_type); + } + +void Env::AddConstID(const ID* id, const int c, Type *type) + { + if ( ! type ) + type = extern_type_int; + AddID(id, CONST, type); + SetConstant(id, c); + SetEvaluated(id); // a constant is always evaluated + } + +void Env::AddMacro(const ID *id, Expr *macro) + { + AddID(id, MACRO, macro->DataType(this)); + SetMacro(id, macro); + SetEvaluated(id); + } + +ID *Env::AddTempID(Type *type) + { + ID *id = ID::NewAnonymousID("t_var_"); + AddID(id, TEMP_VAR, type); + return id; + } + +IDRecord* Env::lookup(const ID* id, bool recursive, bool raise_exception) const + { + ASSERT(id); + + id_map_t::const_iterator it = id_map.find(id); + if ( it != id_map.end() ) + return it->second; + + if ( recursive && parent ) + return parent->lookup(id, recursive, raise_exception); + + if ( raise_exception ) + throw ExceptionIDNotFound(id); + else + return 0; + } + +IDType Env::GetIDType(const ID* id) const + { + return lookup(id, true, true)->GetType(); + } + +const char* Env::RValue(const ID* id) const + { + IDRecord *r = lookup(id, true, false); + if ( r ) + return r->RValue(); + else + { + if ( allow_undefined_id() ) + return id->Name(); + else + throw ExceptionIDNotFound(id); + } + } + +const char* Env::LValue(const ID* id) const + { + return lookup(id, true, true)->LValue(); + } + +void Env::SetEvalMethod(const ID* id, Evaluatable* eval) + { + lookup(id, true, true)->SetEvalMethod(eval); + } + +void Env::Evaluate(Output* out, const ID* id) + { + IDRecord *r = lookup(id, true, !allow_undefined_id()); + if ( r ) + r->Evaluate(out, this); + } + +bool Env::Evaluated(const ID* id) const + { + IDRecord *r = lookup(id, true, !allow_undefined_id()); + if ( r ) + return r->Evaluated(); + else + // Assume undefined variables are already evaluated + return true; + } + +void Env::SetEvaluated(const ID* id, bool v) + { + if ( in_branch() ) + { + Field *f = GetField(id); + if (f && f->tof() == LET_FIELD) + { + throw Exception( + context_object_, + fmt("INTERNAL ERROR: " + "evaluating let field '%s' in a branch! " + "To work around this problem, " + "add '&requires(%s)' to the case type. " + "Sorry for the inconvenience.\n", + id->Name(), + id->Name())); + ASSERT(0); + } + } + + IDRecord *r = lookup(id, false, false); + if ( r ) + r->SetEvaluated(v); + else if ( parent ) + parent->SetEvaluated(id, v); + else + throw ExceptionIDNotFound(id); + } + +void Env::SetField(const ID* id, Field* field) + { + lookup(id, false, true)->SetField(field); + } + +Field* Env::GetField(const ID* id) const + { + return lookup(id, true, true)->GetField(); + } + +void Env::SetDataType(const ID* id, Type* type) + { + lookup(id, true, true)->SetDataType(type); + } + +Type* Env::GetDataType(const ID* id) const + { + IDRecord *r = lookup(id, true, false); + if ( r ) + return r->GetDataType(); + else + return 0; + } + +string Env::DataTypeStr(const ID *id) const + { + Type *type = GetDataType(id); + if ( ! type ) + throw Exception(id, "data type not defined"); + return type->DataTypeStr(); + } + +void Env::SetConstant(const ID* id, int constant) + { + lookup(id, false, true)->SetConstant(constant); + } + +bool Env::GetConstant(const ID* id, int* pc) const + { + ASSERT(pc); + // lookup without raising exception + IDRecord* r = lookup(id, true, false); + if ( r ) + return r->GetConstant(pc); + else + return false; + } + +void Env::SetMacro(const ID* id, Expr *macro) + { + lookup(id, true, true)->SetMacro(macro); + } + +Expr* Env::GetMacro(const ID* id) const + { + return lookup(id, true, true)->GetMacro(); + } + +void init_builtin_identifiers() + { + default_value_var = new ID("val"); + null_id = new ID("NULL"); + null_byteseg_id = new ID("null_byteseg"); + begin_of_data = new ID("begin_of_data"); + end_of_data = new ID("end_of_data"); + len_of_data = new ID("length_of_data"); + byteorder_id = new ID("byteorder"); + bigendian_id = new ID("bigendian"); + littleendian_id = new ID("littleendian"); + unspecified_byteorder_id = new ID("unspecified_byteorder"); + const_true_id = new ID("true"); + const_false_id = new ID("false"); + analyzer_context_id = new ID("context"); + this_id = new ID("this"); + sourcedata_id = new ID("sourcedata"); + connection_id = new ID("connection"); + upflow_id = new ID("upflow"); + downflow_id = new ID("downflow"); + dataunit_id = new ID("dataunit"); + flow_buffer_id = new ID("flow_buffer"); + element_macro_id = new ID("$element"); + input_macro_id = new ID("$input"); + context_macro_id = new ID("$context"); + parsing_state_id = new ID("parsing_state"); + buffering_state_id = new ID("buffering_state"); + + null_decl_id = new ID(""); + current_decl_id = null_decl_id; + } + +Env* global_env() + { + static Env *the_global_env = 0; + + if ( ! the_global_env ) + { + the_global_env = new Env(0, 0); + + // These two are defined in binpac.h, so we do not need to + // generate code for them. + the_global_env->AddConstID(bigendian_id, 0); + the_global_env->AddConstID(littleendian_id, 1); + the_global_env->AddConstID(unspecified_byteorder_id, -1); + the_global_env->AddConstID(const_false_id, 0); + the_global_env->AddConstID(const_true_id, 1); + // A hack for ID "this" + the_global_env->AddConstID(this_id, 0); + the_global_env->AddConstID(null_id, 0, extern_type_nullptr); + +#if 0 + the_global_env->AddID(null_byteseg_id, + GLOBAL_VAR, + extern_type_const_byteseg); +#endif + } + + return the_global_env; + } + +string set_function(const ID *id) + { + return strfmt("set_%s", id->Name()); + } diff --git a/tools/binpac/src/pac_id.h b/tools/binpac/src/pac_id.h new file mode 100644 index 0000000000..6ac89687d4 --- /dev/null +++ b/tools/binpac/src/pac_id.h @@ -0,0 +1,246 @@ +#ifndef pac_id_h +#define pac_id_h + +#include +#include +using namespace std; + +#include "pac_common.h" +#include "pac_dbg.h" +#include "pac_utils.h" + +// Classes handling identifiers. +// +// ID -- name and location of definition of an ID +// +// IDRecord -- association of an ID, its definition type (const, global, temp, +// member, or union member), and its evaluation method. +// +// Evaluatable -- interface for a variable or a field that needs be evaluated +// before referenced. +// +// Env -- a mapping from ID names to their L/R-value expressions and evaluation +// methods. + +enum IDType { + CONST, + GLOBAL_VAR, + TEMP_VAR, + MEMBER_VAR, + PRIV_MEMBER_VAR, + UNION_VAR, + STATE_VAR, + MACRO, + FUNC_ID, + FUNC_PARAM, +}; + +class ID; +class IDRecord; +class Env; +class Evaluatable; + +class ID : public Object +{ +public: + ID(const char *arg_name) + : name(arg_name), anonymous_id_(false) + { + locname = nfmt("%s:%s", Location(), Name()); + } + ~ID() + { + delete locname; + } + + bool operator==(ID const &x) const { return name == x.Name(); } + + const char *Name() const { return name.c_str(); } + const char *LocName() const { return locname; } + bool is_anonymous() const { return anonymous_id_; } + + ID *clone() const { return new ID(Name()); } + +protected: + string name; + bool anonymous_id_; + char *locname; + friend class ID_ptr_cmp; + +public: + static ID *NewAnonymousID(const string &prefix); +private: + static int anonymous_id_seq; +}; + +// A comparison operator for pointers to ID's. +class ID_ptr_cmp +{ +public: + bool operator()(const ID *const & id1, const ID *const & id2) const + { + ASSERT(id1); + ASSERT(id2); + return id1->name < id2->name; + } +}; + +class IDRecord +{ +public: + IDRecord(Env *env, const ID *id, IDType id_type); + ~IDRecord(); + + IDType GetType() const { return id_type; } + + void SetDataType(Type *type) { data_type = type; } + Type *GetDataType() const { return data_type; } + + void SetEvalMethod(Evaluatable *arg_eval) { eval = arg_eval; } + void Evaluate(Output *out, Env *env); + void SetEvaluated(bool v); + bool Evaluated() const { return evaluated; } + + void SetField(Field *f) { field = f; } + Field *GetField() const { return field; } + + void SetConstant(int c); + bool GetConstant(int *pc) const; + + void SetMacro(Expr *expr); + Expr *GetMacro() const; + + const char * RValue() const; + const char * LValue() const; + +protected: + Env *env; + const ID *id; + IDType id_type; + + string rvalue; + string lvalue; + string setfunc; + + Type *data_type; + + Field *field; + + int constant; + bool constant_set; + + Expr *macro; + + bool evaluated; + bool in_evaluation; // to detect cyclic dependence + Evaluatable *eval; +}; + +class Evaluatable +{ +public: + virtual ~Evaluatable() {} + virtual void GenEval(Output *out, Env *env) = 0; +}; + +class Env +{ +public: + Env(Env *parent_env, Object *context_object); + ~Env(); + + bool allow_undefined_id() const { return allow_undefined_id_; } + void set_allow_undefined_id(bool x) { allow_undefined_id_ = x; } + + bool in_branch() const { return in_branch_; } + void set_in_branch(bool x) { in_branch_ = x; } + + void AddID(const ID *id, IDType id_type, Type *type); + void AddConstID(const ID *id, const int c, Type *type = 0); + void AddMacro(const ID *id, Expr *expr); + + // Generate a temp ID with a unique name + ID *AddTempID(Type *type); + + IDType GetIDType(const ID *id) const; + const char * RValue(const ID *id) const; + const char * LValue(const ID *id) const; + // const char *SetFunc(const ID *id) const; + + // Set evaluation method for the ID + void SetEvalMethod(const ID *id, Evaluatable *eval); + + // Evaluate the ID according to the evaluation method. It + // assumes the ID has an evaluation emthod. It does nothing + // if the ID has already been evaluated. + void Evaluate(Output *out, const ID *id); + + // Whether the ID has already been evaluated. + bool Evaluated(const ID *id) const; + + // Set the ID as evaluated (or not). + void SetEvaluated(const ID *id, bool v = true); + + void SetField(const ID *id, Field *field); + Field *GetField(const ID *id) const; + + bool GetConstant(const ID *id, int *pc) const; + + Expr *GetMacro(const ID *id) const; + + Type *GetDataType(const ID *id) const; + + string DataTypeStr(const ID *id) const; + +protected: + IDRecord *lookup(const ID *id, + bool recursive, + bool raise_exception) const; + + void SetDataType(const ID *id, Type *type); + void SetConstant(const ID *id, int constant); + void SetMacro(const ID *id, Expr *macro); + +private: + Env *parent; + Object *context_object_; + typedef map id_map_t; + id_map_t id_map; + bool allow_undefined_id_; + bool in_branch_; +}; + +extern const ID *default_value_var; +extern const ID *null_id; +extern const ID *null_byteseg_id; +extern const ID *begin_of_data; +extern const ID *end_of_data; +extern const ID *len_of_data; +extern const ID *byteorder_id; +extern const ID *bigendian_id; +extern const ID *littleendian_id; +extern const ID *unspecified_byteorder_id; +extern const ID *analyzer_context_id; +extern const ID *context_macro_id; +extern const ID *this_id; +extern const ID *sourcedata_id; +// extern const ID *sourcedata_begin_id; +// extern const ID *sourcedata_end_id; +extern const ID *connection_id; +extern const ID *upflow_id; +extern const ID *downflow_id; +extern const ID *dataunit_id; +extern const ID *flow_buffer_id; +extern const ID *element_macro_id; +extern const ID *cxt_connection_id; +extern const ID *cxt_flow_id; +extern const ID *input_macro_id; +extern const ID *parsing_state_id; +extern const ID *buffering_state_id; + +extern void init_builtin_identifiers(); +extern Env *global_env(); + +extern string set_function(const ID *id); + +#endif // pac_id_h diff --git a/tools/binpac/src/pac_inputbuf.cc b/tools/binpac/src/pac_inputbuf.cc new file mode 100644 index 0000000000..1974860693 --- /dev/null +++ b/tools/binpac/src/pac_inputbuf.cc @@ -0,0 +1,44 @@ +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_inputbuf.h" +#include "pac_output.h" +#include "pac_type.h" + +InputBuffer::InputBuffer(Expr *expr) + : DataDepElement(INPUT_BUFFER), expr_(expr) + { + } + +bool InputBuffer::DoTraverse(DataDepVisitor *visitor) + { + if ( expr_ && ! expr_->Traverse(visitor) ) + return false; + return true; + } + +bool InputBuffer::RequiresAnalyzerContext() const + { + return expr_->RequiresAnalyzerContext(); + } + +DataPtr InputBuffer::GenDataBeginEnd(Output *out_cc, Env *env) + { + env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); + env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); + + out_cc->println("%s %s, %s;", + extern_type_const_byteptr->DataTypeStr().c_str(), + env->LValue(begin_of_data), + env->LValue(end_of_data)); + + out_cc->println("get_pointers(%s, &%s, &%s);", + expr_->EvalExpr(out_cc, env), + env->LValue(begin_of_data), + env->LValue(end_of_data)); + + env->SetEvaluated(begin_of_data); + env->SetEvaluated(end_of_data); + + return DataPtr(env, begin_of_data, 0); + } diff --git a/tools/binpac/src/pac_inputbuf.h b/tools/binpac/src/pac_inputbuf.h new file mode 100644 index 0000000000..f03a5193ab --- /dev/null +++ b/tools/binpac/src/pac_inputbuf.h @@ -0,0 +1,24 @@ +#ifndef pac_inputbuf_h +#define pac_inputbuf_h + +#include "pac_datadep.h" +#include "pac_dataptr.h" + +class Expr; + +class InputBuffer : public Object, public DataDepElement +{ +public: + InputBuffer(Expr *expr); + + bool RequiresAnalyzerContext() const; + DataPtr GenDataBeginEnd(Output *out_cc, Env *env); + +protected: + bool DoTraverse(DataDepVisitor *visitor); + +private: + Expr *expr_; +}; + +#endif // pac_inputbuf_h diff --git a/tools/binpac/src/pac_let.cc b/tools/binpac/src/pac_let.cc new file mode 100644 index 0000000000..ebd7caef90 --- /dev/null +++ b/tools/binpac/src/pac_let.cc @@ -0,0 +1,167 @@ +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_let.h" +#include "pac_output.h" +#include "pac_type.h" + +namespace { + +void GenLetEval(const ID *id, Expr *expr, string prefix, Output* out, Env* env) + { + if ( expr ) + { + } + } + +} // private namespace + +LetField::LetField(ID* id, Type *type, Expr* expr) + : Field(LET_FIELD, + TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, + id, type), + expr_(expr) + { + ASSERT(expr_); + } + +LetField::~LetField() + { + delete expr_; + } + +bool LetField::DoTraverse(DataDepVisitor *visitor) + { + return Field::DoTraverse(visitor) && + expr()->Traverse(visitor); + } + +bool LetField::RequiresAnalyzerContext() const + { + return Field::RequiresAnalyzerContext() || + (expr() && expr()->RequiresAnalyzerContext()); + } + +void LetField::Prepare(Env* env) + { + if ( ! type_ ) + { + ASSERT(expr_); + type_ = expr_->DataType(env); + if ( type_ ) + type_ = type_->Clone(); + else + type_ = extern_type_int->Clone(); + + foreach(i, AttrList, attrs_) + ProcessAttr(*i); + } + + Field::Prepare(env); + env->SetEvalMethod(id_, this); + } + +void LetField::GenInitCode(Output* out_cc, Env* env) + { + int v; + if ( expr_ && expr_->ConstFold(env, &v) ) + { + DEBUG_MSG("Folding const for `%s'\n", id_->Name()); + GenEval(out_cc, env); + } + else + type_->GenInitCode(out_cc, env); + } + +void LetField::GenParseCode(Output* out_cc, Env* env) + { + if ( env->Evaluated(id_) ) + return; + + if ( type_->attr_if_expr() ) + { + // A conditional field + + env->Evaluate(out_cc, type_->has_value_var()); + + // force evaluation of IDs contained in this expr + expr()->ForceIDEval(out_cc, env); + + out_cc->println("if ( %s )", + env->RValue(type_->has_value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + } + + out_cc->println("%s = %s;", + env->LValue(id_), + expr()->EvalExpr(out_cc, env)); + if ( ! env->Evaluated(id_) ) + env->SetEvaluated(id_); + + if ( type_->attr_if_expr() ) + { + out_cc->println("}"); + out_cc->dec_indent(); + } + } + +void LetField::GenEval(Output* out_cc, Env* env) + { + GenParseCode(out_cc, env); + } + +LetDecl::LetDecl(ID *id, Type *type, Expr *expr) + : Decl(id, LET), type_(type), expr_(expr) + { + if ( ! type_ ) + { + ASSERT(expr_); + type_ = expr_->DataType(global_env()); + if ( type_ ) + type_ = type_->Clone(); + else + type_ = extern_type_int->Clone(); + } + + Env *env = global_env(); + int c; + if ( expr_ && expr_->ConstFold(env, &c) ) + env->AddConstID(id_, c); + else + env->AddID(id_, GLOBAL_VAR, type_); + } + +LetDecl::~LetDecl() + { + delete id_; + delete type_; + delete expr_; + } + +void LetDecl::Prepare() + { + } + +void LetDecl::GenForwardDeclaration(Output* out_h) + { + } + +void LetDecl::GenCode(Output * out_h, Output *out_cc) + { + out_h->println("extern %s const %s;", + type_->DataTypeStr().c_str(), + global_env()->RValue(id_)); + GenEval(out_cc, global_env()); + } + +void LetDecl::GenEval(Output *out_cc, Env * /* env */) + { + Env *env = global_env(); + out_cc->println("%s %s = %s;", + fmt("%s const", type_->DataTypeStr().c_str()), + env->LValue(id_), + expr_->EvalExpr(out_cc, env)); + + if ( ! env->Evaluated(id_) ) + env->SetEvaluated(id_); + } diff --git a/tools/binpac/src/pac_let.h b/tools/binpac/src/pac_let.h new file mode 100644 index 0000000000..aba8128511 --- /dev/null +++ b/tools/binpac/src/pac_let.h @@ -0,0 +1,48 @@ +#ifndef pac_let_h +#define pac_let_h + +#include "pac_decl.h" +#include "pac_field.h" + +class LetField : public Field, Evaluatable +{ +public: + LetField(ID* arg_id, Type *type, Expr* arg_expr); + ~LetField(); + + Expr *expr() const { return expr_; } + + void Prepare(Env* env); + + void GenInitCode(Output* out, Env* env); + void GenParseCode(Output* out, Env* env); + void GenEval(Output* out, Env* env); + + bool RequiresAnalyzerContext() const; + +protected: + bool DoTraverse(DataDepVisitor *visitor); + +protected: + Expr* expr_; +}; + +class LetDecl : public Decl, Evaluatable +{ +public: + LetDecl(ID *id, Type *type, Expr *expr); + ~LetDecl(); + + Expr *expr() const { return expr_; } + + void Prepare(); + void GenForwardDeclaration(Output *out_h); + void GenCode(Output *out_h, Output *out_cc); + void GenEval(Output* out, Env* env); + +private: + Type *type_; + Expr *expr_; +}; + +#endif // pac_let_h diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc new file mode 100644 index 0000000000..7c98e526fa --- /dev/null +++ b/tools/binpac/src/pac_main.cc @@ -0,0 +1,259 @@ +// $Id: pac_main.cc 3320 2006-06-20 21:19:33Z rpang $ + +#include +#include + +#include "pac_common.h" +#include "pac_decl.h" +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_parse.h" +#include "pac_type.h" +#include "pac_utils.h" +#include "pac_exception.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +extern int yydebug; +extern int yyparse(); +extern void switch_to_file(FILE* fp_input); +string input_filename; + +bool FLAGS_pac_debug = false; +string FLAGS_output_directory; +vector FLAGS_include_directories; + +Output* header_output = 0; +Output* source_output = 0; + +void add_to_include_directories(string dirs) + { + unsigned int dir_begin = 0, dir_end; + while ( dir_begin < dirs.length() ) + { + for ( dir_end = dir_begin; dir_end < dirs.length(); ++dir_end) + if ( dirs[dir_end] == ':' ) + break; + + string dir = dirs.substr(dir_begin, dir_end - dir_begin); + + // Add a trailing '/' if necessary + if ( dir.length() > 0 && *(dir.end() - 1) != '/' ) + dir += '/'; + + FLAGS_include_directories.push_back(dir); + dir_begin = dir_end + 1; + } + } + +void pac_init() + { + init_builtin_identifiers(); + Type::init(); + } + +void insert_comments(Output* out, const char* source_filename) + { + out->println("// This file is automatically generated from %s.\n", + source_filename); + } + +void insert_basictype_defs(Output* out) + { + out->println("#ifndef pac_type_defs"); + out->println("#define pac_type_defs"); + out->println(""); + out->println("typedef char int8;"); + out->println("typedef short int16;"); + out->println("typedef long int32;"); + out->println("typedef unsigned char uint8;"); + out->println("typedef unsigned short uint16;"); + out->println("typedef unsigned long uint32;"); + out->println(""); + out->println("#endif /* pac_type_defs */"); + out->println(""); + } + +void insert_byteorder_macros(Output* out) + { + out->println("#define FixByteOrder16(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap16(x))"); + out->println("#define FixByteOrder32(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap32(x))"); + out->println(""); + } + +const char* to_id(const char* s) + { + static char t[1024]; + int i; + for ( i = 0; s[i] && i < (int) sizeof(t) - 1; ++i ) + t[i] = isalnum(s[i]) ? s[i] : '_'; + if ( isdigit(t[0]) ) + t[0] = '_'; + t[i] = '\0'; + return t; + } + +int compile(const char* filename) + { + FILE* fp_input = fopen(filename, "r"); + if ( ! fp_input ) + { + perror(fmt("Error in opening %s", filename)); + return -1; + } + input_filename = filename; + + string basename; + + if ( ! FLAGS_output_directory.empty() ) + { + // Strip leading directories of filename + const char *last_slash = strrchr(filename, '/'); + if ( last_slash ) + basename = last_slash + 1; + else + basename = filename; + basename = FLAGS_output_directory + "/" + basename; + } + else + basename = filename; + + // If the file name ends with ".pac" + if ( basename.length() > 4 && + basename.substr(basename.length() - 4) == ".pac" ) + { + basename = basename.substr(0, basename.length() - 4); + } + + basename += "_pac"; + + DEBUG_MSG("Output file: %s.{h,cc}\n", basename.c_str()); + + int ret = 0; + + try + { + switch_to_file(fp_input); + if ( yyparse() ) + return 1; + + Output out_h(fmt("%s.h", basename.c_str())); + Output out_cc(fmt("%s.cc", basename.c_str())); + + header_output = &out_h; + source_output = &out_cc; + + insert_comments(&out_h, filename); + insert_comments(&out_cc, filename); + + const char* filename_id = to_id(filename); + + out_h.println("#ifndef %s_h", filename_id); + out_h.println("#define %s_h", filename_id); + out_h.println(""); + out_h.println("#include "); + out_h.println(""); + out_h.println("#include \"binpac.h\""); + out_h.println(""); + + out_cc.println("#include \"%s.h\"\n", basename.c_str()); + + Decl::ProcessDecls(&out_h, &out_cc); + + out_h.println("#endif /* %s_h */", filename_id); + } + catch ( OutputException& e ) + { + fprintf(stderr, "Error in compiling %s: %s\n", + filename, e.errmsg()); + ret = 1; + } + catch ( Exception& e ) + { + fprintf(stderr, "%s\n", e.msg()); + exit(1); + } + + header_output = 0; + source_output = 0; + input_filename = ""; + fclose(fp_input); + + return ret; + } + +void usage() + { +#ifdef VERSION + fprintf(stderr, "binpac version %s\n", VERSION); +#endif + fprintf(stderr, "usage: binpac [options] \n"); + fprintf(stderr, " | pac-language input files\n"); + fprintf(stderr, " -d | use given directory for compiler output\n"); + fprintf(stderr, " -D | enable debugging output\n"); + fprintf(stderr, " -h | show command line help\n"); + fprintf(stderr, " -I | include in input file search path\n"); + exit(1); + } + +int main(int argc, char* argv[]) + { +#ifdef HAVE_MALLOC_OPTIONS + extern char *malloc_options; +#endif + int o; + while ( (o = getopt(argc, argv, "DI:d:h")) != -1 ) + { + switch(o) + { + case 'D': + yydebug = 1; + FLAGS_pac_debug = true; +#ifdef HAVE_MALLOC_OPTIONS + malloc_options = "A"; +#endif + break; + + case 'I': + // Add to FLAGS_include_directories + add_to_include_directories(optarg); + break; + + case 'd': + FLAGS_output_directory = optarg; + break; + + case 'h': + usage(); + break; + } + } + + // Strip the trailing '/'s + while ( ! FLAGS_output_directory.empty() && + *(FLAGS_output_directory.end() - 1) == '/' ) + { + FLAGS_output_directory.erase(FLAGS_output_directory.end()-1); + } + + // Add the current directory to FLAGS_include_directories + add_to_include_directories("."); + + pac_init(); + + argc -= optind; + argv += optind; + if ( argc == 0 ) + compile("-"); + + int ret = 0; + for ( int i = 0; i < argc; ++i ) + if ( compile(argv[i]) ) + ret = 1; + + return ret; + } + diff --git a/tools/binpac/src/pac_number.h b/tools/binpac/src/pac_number.h new file mode 100644 index 0000000000..f923068700 --- /dev/null +++ b/tools/binpac/src/pac_number.h @@ -0,0 +1,21 @@ +#ifndef pac_number_h +#define pac_number_h + +#include "pac_common.h" + +class Number : public Object +{ +public: + Number(int arg_n) + : s(fmt("%d", arg_n)), n(arg_n) {} + Number(const char* arg_s, int arg_n) + : s(arg_s), n(arg_n) {} + const char* Str() const { return s.c_str(); } + int Num() const { return n; } + +protected: + const string s; + const int n; +}; + +#endif // pac_number_h diff --git a/tools/binpac/src/pac_output.cc b/tools/binpac/src/pac_output.cc new file mode 100644 index 0000000000..404b4422cc --- /dev/null +++ b/tools/binpac/src/pac_output.cc @@ -0,0 +1,61 @@ +// $Id: pac_output.cc 3225 2006-06-08 00:00:01Z vern $ + +#include +#include +#include +#include + +#include "pac_utils.h" +#include "pac_output.h" + +OutputException::OutputException(const char* arg_msg) + { + msg = arg_msg; + } + +OutputException::~OutputException() + { + } + +Output::Output(const char* filename) + { + fp = fopen(filename, "w"); + if ( ! fp ) + throw OutputException(strerror(errno)); + indent_ = 0; + } + +Output::~Output() + { + if ( fp ) + fclose(fp); + } + +int Output::print(const char* fmt, va_list ap) + { + int r = vfprintf(fp, fmt, ap); + if ( r == -1 ) + throw OutputException(strerror(errno)); + return r; + } + +int Output::print(const char* fmt, ...) + { + va_list ap; + va_start(ap, fmt); + return print(fmt, ap); + } + +int Output::println(const char* fmt, ...) + { + for ( int i = 0; i < indent(); ++i ) + fprintf(fp, "\t"); + + int r; + va_list ap; + va_start(ap, fmt); + r = print(fmt, ap); + + fprintf(fp, "\n"); + return r; + } diff --git a/tools/binpac/src/pac_output.h b/tools/binpac/src/pac_output.h new file mode 100644 index 0000000000..9911f3a2b4 --- /dev/null +++ b/tools/binpac/src/pac_output.h @@ -0,0 +1,42 @@ +// $Id: pac_output.h 3225 2006-06-08 00:00:01Z vern $ + +#ifndef pac_output_h +#define pac_output_h + +#include +#include +#include + +using namespace std; + +class OutputException { +public: + OutputException(const char* arg_msg); + ~OutputException(); + const char* errmsg() const { return msg.c_str(); } + +protected: + string msg; +}; + +class Output { +public: + Output(const char *filename); + ~Output(); + + int println(const char* fmt, ...); + int print(const char* fmt, ...); + + int indent() const { return indent_; } + + void inc_indent() { ++indent_; } + void dec_indent() { --indent_; } + +protected: + int print(const char* fmt, va_list ap); + + FILE* fp; + int indent_; +}; + +#endif /* pac_output_h */ diff --git a/tools/binpac/src/pac_param.cc b/tools/binpac/src/pac_param.cc new file mode 100644 index 0000000000..21e452ee05 --- /dev/null +++ b/tools/binpac/src/pac_param.cc @@ -0,0 +1,70 @@ +#include "pac_decl.h" +#include "pac_exttype.h" +#include "pac_field.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_type.h" +#include "pac_utils.h" + +#include "pac_param.h" + +Param::Param(ID* id, Type *type) + : id_(id), type_(type) + { + if ( ! type_ ) + type_ = extern_type_int->Clone(); + + decl_str_ = strfmt("%s %s", + type_->DataTypeConstRefStr().c_str(), + id_->Name()); + + param_field_ = new ParamField(this); + } + +Param::~Param() + { + } + +const string &Param::decl_str() const + { + ASSERT(!decl_str_.empty()); + return decl_str_; + } + +string ParamDecls(ParamList *params) + { + string param_decls; + + int first = 1; + foreach (i, ParamList, params) + { + Param* p = *i; + const char* decl_str = p->decl_str().c_str(); + if ( first ) + first = 0; + else + param_decls += ", "; + param_decls += decl_str; + } + return param_decls; + } + +ParamField::ParamField(const Param *param) + : Field(PARAM_FIELD, + TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, + param->id(), + param->type()) + { + } + +void ParamField::GenInitCode(Output *out_cc, Env *env) + { + out_cc->println("%s = %s;", + env->LValue(id()), id()->Name()); + env->SetEvaluated(id()); + } + +void ParamField::GenCleanUpCode(Output* out_cc, Env* env) + { + // Do nothing + } diff --git a/tools/binpac/src/pac_param.h b/tools/binpac/src/pac_param.h new file mode 100644 index 0000000000..5efc60fd3a --- /dev/null +++ b/tools/binpac/src/pac_param.h @@ -0,0 +1,48 @@ +#ifndef pac_param_h +#define pac_param_h + +#include "pac_common.h" +#include "pac_field.h" + +class Param : public Object +{ +public: + Param(ID* id, Type* type); + ~Param(); + + ID *id() const { return id_; } + Type *type() const { return type_; } + const string & decl_str() const; + Field *param_field() const { return param_field_; } + +private: + ID* id_; + Type* type_; + string decl_str_; + Field *param_field_; +}; + +class ParamField : public Field +{ +public: + ParamField(const Param *param); + + void GenInitCode(Output *out, Env *env); + void GenCleanUpCode(Output* out, Env* env); +}; + +// Returns the string with a list of param declarations separated by ','. +string ParamDecls(ParamList *params); + +#if 0 +// Generate assignments to parameters, in the form of "%s_ = %s;" % (id, id). +void GenParamAssignments(ParamList *params, Output *out_cc, Env *env); + +// Generate public access methods to parameter members. +void GenParamPubDecls(ParamList *params, Output *out_h, Env *env); + +// Generate private definitions of parameter members. +void GenParamPrivDecls(ParamList *params, Output *out_h, Env *env); +#endif + +#endif // pac_param_h diff --git a/tools/binpac/src/pac_paramtype.cc b/tools/binpac/src/pac_paramtype.cc new file mode 100644 index 0000000000..96e79735a3 --- /dev/null +++ b/tools/binpac/src/pac_paramtype.cc @@ -0,0 +1,289 @@ +#include "pac_context.h" +#include "pac_dataptr.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_output.h" +#include "pac_paramtype.h" +#include "pac_typedecl.h" + +ParameterizedType::ParameterizedType(ID* type_id, ExprList* args) + : Type(PARAMETERIZED), type_id_(type_id), args_(args) + { + checking_requires_analyzer_context_ = false; + } + +ParameterizedType::~ParameterizedType() + { + } + +string ParameterizedType::EvalMember(const ID *member_id) const + { + Type *ty = ReferredDataType(true); + return strfmt("->%s", ty->env()->RValue(member_id)); + } + +string ParameterizedType::class_name() const + { + return type_id_->Name(); + } + +Type *ParameterizedType::DoClone() const + { + return new ParameterizedType(type_id_->clone(), args_); + } + +void ParameterizedType::AddParamArg(Expr *arg) + { + args_->push_back(arg); + } + +bool ParameterizedType::DefineValueVar() const + { + return true; + } + +string ParameterizedType::DataTypeStr() const + { + return strfmt("%s *", type_id_->Name()); + } + +Type *ParameterizedType::MemberDataType(const ID *member_id) const + { + Type *ref_type = TypeDecl::LookUpType(type_id_); + if ( ! ref_type ) + return 0; + return ref_type->MemberDataType(member_id); + } + +Type *ParameterizedType::ReferredDataType(bool throw_exception) const + { + Type* type = TypeDecl::LookUpType(type_id_); + if ( ! type ) + { + DEBUG_MSG("WARNING: cannot find referenced type for %s\n", + type_id_->Name()); + if ( throw_exception ) + throw ExceptionIDNotFound(type_id_); + } + return type; + } + +int ParameterizedType::StaticSize(Env* env) const + { + return ReferredDataType(true)->StaticSize(env); + } + +void ParameterizedType::DoMarkIncrementalInput() + { + Type *ty = ReferredDataType(true); + + ty->MarkIncrementalInput(); + + buffer_input_ = ty->buffer_input(); + incremental_parsing_ = ty->incremental_parsing(); + } + +Type::BufferMode ParameterizedType::buffer_mode() const + { + // Note that the precedence is on attributes (&oneline or &length) + // specified on the parameterized type directly than on the type + // declaration. + // + // If both &oneline and &length are specified at the same place, + // use &length. + // + BufferMode mode = Type::buffer_mode(); + Type *ty = ReferredDataType(true); + + if ( mode != NOT_BUFFERABLE ) + return mode; + else if ( ty->BufferableByLength() ) + return BUFFER_BY_LENGTH; + else if ( ty->BufferableByLine() ) + return BUFFER_BY_LINE; + + return NOT_BUFFERABLE; + } + +bool ParameterizedType::ByteOrderSensitive() const + { + return ReferredDataType(true)->RequiresByteOrder(); + } + +bool ParameterizedType::DoTraverse(DataDepVisitor *visitor) + { + if ( ! Type::DoTraverse(visitor) ) + return false; + + foreach(i, ExprList, args_) + if ( ! (*i)->Traverse(visitor) ) + return false; + + Type *ty = ReferredDataType(false); + if ( ty && ! ty->Traverse(visitor) ) + return false; + + return true; + } + +bool ParameterizedType::RequiresAnalyzerContext() + { + if ( checking_requires_analyzer_context_ ) + return false; + checking_requires_analyzer_context_ = true; + + bool ret = false; + // If any argument expression refers to analyzer context + foreach(i, ExprList, args_) + if ( (*i)->RequiresAnalyzerContext() ) + { + ret = true; + break; + } + ret = ret || + Type::RequiresAnalyzerContext(); + + if ( ! ret ) + { + Type *ty = ReferredDataType(false); + if ( ty ) + ret = ty->RequiresAnalyzerContext(); + } + + checking_requires_analyzer_context_ = false; + return ret; + } + +void ParameterizedType::GenInitCode(Output* out_cc, Env* env) + { + ASSERT(persistent()); + out_cc->println("%s = 0;", env->LValue(value_var())); + Type::GenInitCode(out_cc, env); + } + +void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env) + { + Type *ty = ReferredDataType(false); + if ( ty && ty->attr_refcount() ) + out_cc->println("Unref(%s);", lvalue()); + else + out_cc->println("delete %s;", lvalue()); + out_cc->println("%s = 0;", lvalue()); + Type::GenCleanUpCode(out_cc, env); + } + +string ParameterizedType::EvalParameters(Output* out_cc, Env *env) const + { + string arg_str; + + int first = 1; + foreach (i, ExprList, args_) + { + Expr* e = *i; + if ( first ) + first = 0; + else + arg_str += ", "; + arg_str += e->EvalExpr(out_cc, env); + } + + return arg_str; + } + +void ParameterizedType::GenNewInstance(Output *out_cc, Env *env) + { + out_cc->println("%s = new %s(%s);", + lvalue(), + type_id_->Name(), + EvalParameters(out_cc, env).c_str()); + } + +void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, + const DataPtr& data, int flags) + { + DEBUG_MSG("DoGenParseCode for %s\n", type_id_->Name()); + + Type *ref_type = ReferredDataType(true); + + const char *parse_func; + string parse_params; + + if ( buffer_mode() == BUFFER_NOTHING ) + { + ASSERT(!ref_type->incremental_input()); + parse_func = kParseFuncWithoutBuffer; + parse_params = "0, 0"; + } + else if ( ref_type->incremental_input() ) + { + parse_func = kParseFuncWithBuffer; + parse_params = env->RValue(flow_buffer_id); + } + else + { + parse_func = kParseFuncWithoutBuffer; + parse_params = strfmt("%s, %s", + data.ptr_expr(), + env->RValue(end_of_data)); + } + + if ( RequiresAnalyzerContext::compute(ref_type) ) + { + parse_params += strfmt(", %s", env->RValue(analyzer_context_id)); + } + + if ( ref_type->RequiresByteOrder() ) + { + env->Evaluate(out_cc, byteorder_id); + parse_params += strfmt(", %s", env->RValue(byteorder_id)); + } + + string call_parse_func = strfmt("%s->%s(%s)", + lvalue(), // parse() needs an LValue + parse_func, + parse_params.c_str()); + + if ( incremental_input() ) + { + if ( buffer_mode() == BUFFER_NOTHING ) + { + out_cc->println("%s;", call_parse_func.c_str()); + out_cc->println("%s = true;", + env->LValue(parsing_complete_var())); + } + else + { + ASSERT(parsing_complete_var()); + out_cc->println("%s = %s;", + env->LValue(parsing_complete_var()), + call_parse_func.c_str()); + + // parsing_complete_var might have been already + // evaluated when set to false + if ( ! env->Evaluated(parsing_complete_var()) ) + env->SetEvaluated(parsing_complete_var()); + } + } + else + { + if ( AddSizeVar(out_cc, env) ) + { + out_cc->println("%s = %s;", + env->LValue(size_var()), + call_parse_func.c_str()); + env->SetEvaluated(size_var()); + } + else + { + out_cc->println("%s;", + call_parse_func.c_str()); + } + } + } + +void ParameterizedType::GenDynamicSize(Output* out_cc, Env* env, + const DataPtr& data) + { + GenParseCode(out_cc, env, data, 0); + } + diff --git a/tools/binpac/src/pac_paramtype.h b/tools/binpac/src/pac_paramtype.h new file mode 100644 index 0000000000..4a2ef4e1d7 --- /dev/null +++ b/tools/binpac/src/pac_paramtype.h @@ -0,0 +1,62 @@ +#ifndef pac_paramtype_h +#define pac_paramtype_h + +#include "pac_type.h" + +// An instantiated type: ID + expression list +class ParameterizedType : public Type +{ +public: + ParameterizedType(ID *type_id, ExprList *args); + ~ParameterizedType(); + + Type *clone() const; + + string EvalMember(const ID *member_id) const; + // Env *member_env() const; + + void AddParamArg(Expr *arg); + + bool DefineValueVar() const; + string DataTypeStr() const; + string DefaultValue() const { return "0"; } + Type *MemberDataType(const ID *member_id) const; + + // "throw_exception" specifies whether to throw an exception + // if the referred data type is not found + Type *ReferredDataType(bool throw_exception) const; + + void GenCleanUpCode(Output *out, Env *env); + + int StaticSize(Env *env) const; + + bool IsPointerType() const { return true; } + + bool ByteOrderSensitive() const; + bool RequiresAnalyzerContext(); + + void GenInitCode(Output *out_cc, Env *env); + + string class_name() const; + string EvalParameters(Output *out_cc, Env *env) const; + + BufferMode buffer_mode() const; + +protected: + void GenNewInstance(Output *out, Env *env); + + bool DoTraverse(DataDepVisitor *visitor); + Type *DoClone() const; + void DoMarkIncrementalInput(); + +private: + ID *type_id_; + ExprList *args_; + char *data_type_; + bool checking_requires_analyzer_context_; + + void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); + void GenDynamicSize(Output *out, Env *env, const DataPtr& data); +}; + +#endif // pac_paramtype_h diff --git a/tools/binpac/src/pac_parse.yy b/tools/binpac/src/pac_parse.yy new file mode 100644 index 0000000000..3d7f9a328f --- /dev/null +++ b/tools/binpac/src/pac_parse.yy @@ -0,0 +1,1095 @@ +/* $Id: pac_parse.yy 3225 2006-06-08 00:00:01Z vern $ */ + +%token TOK_TYPE TOK_RECORD TOK_CASE TOK_ENUM TOK_LET TOK_FUNCTION +%token TOK_REFINE TOK_CASEFUNC TOK_CASETYPE TOK_TYPEATTR +%token TOK_HELPERHEADER TOK_HELPERCODE +%token TOK_RIGHTARROW TOK_DEFAULT TOK_OF +%token TOK_PADDING TOK_TO TOK_ALIGN +%token TOK_WITHINPUT +%token TOK_INT8 TOK_INT16 TOK_INT32 +%token TOK_UINT8 TOK_UINT16 TOK_UINT32 +%token TOK_ID TOK_NUMBER TOK_REGEX TOK_STRING +%token TOK_BEGIN_RE TOK_END_RE +%token TOK_ATTR_ALSO +%token TOK_ATTR_BYTEORDER TOK_ATTR_CHECK TOK_ATTR_CHUNKED +%token TOK_ATTR_EXPORTSOURCEDATA TOK_ATTR_IF +%token TOK_ATTR_LENGTH TOK_ATTR_LET +%token TOK_ATTR_LINEBREAKER TOK_ATTR_MULTILINE TOK_ATTR_ONELINE +%token TOK_ATTR_REFCOUNT TOK_ATTR_REQUIRES +%token TOK_ATTR_RESTOFDATA TOK_ATTR_RESTOFFLOW +%token TOK_ATTR_TRANSIENT TOK_ATTR_UNTIL +%token TOK_ANALYZER TOK_CONNECTION TOK_FLOW +%token TOK_STATE TOK_ACTION TOK_WHEN TOK_HELPER +%token TOK_DATAUNIT TOK_FLOWDIR TOK_WITHCONTEXT +%token TOK_LPB_EXTERN TOK_LPB_HEADER TOK_LPB_CODE +%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP TOK_LPB_EOF +%token TOK_LPB TOK_RPB +%token TOK_EMBEDDED_ATOM TOK_EMBEDDED_STRING +%token TOK_PAC_VAL TOK_PAC_SET TOK_PAC_TYPE TOK_PAC_TYPEOF TOK_PAC_CONST_DEF +%token TOK_END_PAC +%token TOK_EXTERN + +%nonassoc '=' TOK_PLUSEQ +%left ';' +%left ',' +%left '?' ':' +%left TOK_OR +%left TOK_AND +%nonassoc TOK_EQUAL TOK_NEQ TOK_LE TOK_GE '<' '>' +%left '&' '|' '^' +%left TOK_LSHIFT TOK_RSHIFT +%left '+' '-' +%left '*' '/' '%' +%right '~' '!' +%right TOK_SIZEOF TOK_OFFSETOF +%right '(' ')' '[' ']' +%left '.' + +%type actionparam +%type actionparamtype +%type sah +%type sahlist conn flow +%type attr +%type optattrs attrlist +%type caseexpr +%type caseexprlist +%type casefield casefield0 +%type casefieldlist +%type contextfield +%type analyzercontext contextfieldlist +%type decl decl_with_attr decl_without_attr +%type embedded_code +%type enumlist enumlist1 +%type enumitem +%type expr caseindex optinit optlinebreaker +%type exprlist optexprlist optargs +%type withinputfield letfield +%type letfieldlist +%type funcproto function +%type TOK_ID tok_id optfieldid +%type input +%type TOK_NUMBER +%type embedded_pac_primitive +%type param +%type optparams paramlist +%type recordfield recordfield0 padding +%type recordfieldlist +%type regex +%type statevar +%type statevarlist +%type TOK_EMBEDDED_STRING TOK_STRING TOK_REGEX +%type cstr +%type type type3 type2 type1 opttype +%type TOK_EMBEDDED_ATOM TOK_WHEN TOK_FLOWDIR TOK_DATAUNIT + +%{ + +#include "pac_action.h" +#include "pac_analyzer.h" +#include "pac_array.h" +#include "pac_attr.h" +#include "pac_case.h" +#include "pac_common.h" +#include "pac_conn.h" +#include "pac_context.h" +#include "pac_cstr.h" +#include "pac_dataptr.h" +#include "pac_dataunit.h" +#include "pac_dbg.h" +#include "pac_decl.h" +#include "pac_embedded.h" +#include "pac_enum.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_flow.h" +#include "pac_func.h" +#include "pac_id.h" +#include "pac_inputbuf.h" +#include "pac_let.h" +#include "pac_output.h" +#include "pac_param.h" +#include "pac_paramtype.h" +#include "pac_primitive.h" +#include "pac_record.h" +#include "pac_redef.h" +#include "pac_regex.h" +#include "pac_state.h" +#include "pac_strtype.h" +#include "pac_type.h" +#include "pac_utils.h" +#include "pac_withinput.h" + +extern int yyerror(const char msg[]); +extern int yylex(); +extern int yychar; +extern char* yytext; +extern int yyleng; +extern void begin_RE(); +extern void end_RE(); + +extern string input_filename; +extern int line_number; +extern Output* header_output; +extern Output* source_output; + +%} + +%union { + ActionParam *actionparam; + ActionParamType *actionparamtype; + AnalyzerElement *aelem; + AnalyzerElementList *aelemlist; + Attr *attr; + AttrList *attrlist; + ConstString *cstr; + CaseExpr *caseexpr; + CaseExprList *caseexprlist; + CaseField *casefield; + CaseFieldList *casefieldlist; + ContextField *contextfield; + ContextFieldList *contextfieldlist; + Decl *decl; + EmbeddedCode *embedded_code; + Enum *enumitem; + EnumList *enumlist; + Expr *expr; + ExprList *exprlist; + Field *field; + FieldList *fieldlist; + Function *function; + ID *id; + InputBuffer *input; + LetFieldList *letfieldlist; + LetField *letfield; + Number *num; + PacPrimitive *pacprimitive; + Param *param; + ParamList *paramlist; + RecordFieldList *recordfieldlist; + RecordField *recordfield; + RegEx *regex; + StateVar *statevar; + StateVarList *statevarlist; + const char *str; + Type *type; + int val; +} + +%% + +decls : /* empty */ + { + // Put initialization here + } + | decls decl optsemicolon + { + } + ; + +decl : decl_with_attr optattrs + { + $$ = $1; + $1->AddAttrs($2); + } + | decl_without_attr + { + $$ = $1; + } + ; + +decl_with_attr : TOK_TYPE tok_id { current_decl_id = $2; } optparams '=' type + { + TypeDecl* decl = new TypeDecl($2, $4, $6); + $$ = decl; + } + | TOK_LET tok_id { current_decl_id = $2; } opttype optinit + { + $$ = new LetDecl($2, $4, $5); + } + | TOK_FUNCTION function + { + current_decl_id = $2->id(); + $$ = new FuncDecl($2); + } + | TOK_ENUM tok_id { current_decl_id = $2; } '{' enumlist '}' + { + $$ = new EnumDecl($2, $5); + } + | TOK_EXTERN TOK_TYPE tok_id { current_decl_id = $3; } + { + Type *extern_type = new ExternType($3, ExternType::PLAIN); + $$ = new TypeDecl($3, 0, extern_type); + } + | TOK_ANALYZER tok_id { current_decl_id = $2; } TOK_WITHCONTEXT analyzercontext + { + $$ = new AnalyzerContextDecl($2, $5); + } + | TOK_ANALYZER tok_id { current_decl_id = $2; } optparams '{' conn '}' + { + $$ = new ConnDecl($2, $4, $6); + } + | TOK_CONNECTION tok_id { current_decl_id = $2; } optparams '{' conn '}' + { + $$ = new ConnDecl($2, $4, $6); + } + | TOK_FLOW tok_id { current_decl_id = $2; } optparams '{' flow '}' + { + $$ = new FlowDecl($2, $4, $6); + } + | TOK_REFINE TOK_CASETYPE tok_id TOK_PLUSEQ '{' casefieldlist '}' + { + $$ = ProcessCaseTypeRedef($3, $6); + } + | TOK_REFINE TOK_CASEFUNC tok_id TOK_PLUSEQ '{' caseexprlist '}' + { + $$ = ProcessCaseExprRedef($3, $6); + } + | TOK_REFINE TOK_ANALYZER tok_id TOK_PLUSEQ '{' sahlist '}' + { + $$ = ProcessAnalyzerRedef($3, Decl::CONN, $6); + } + | TOK_REFINE TOK_CONNECTION tok_id TOK_PLUSEQ '{' sahlist '}' + { + $$ = ProcessAnalyzerRedef($3, Decl::CONN, $6); + } + | TOK_REFINE TOK_FLOW tok_id TOK_PLUSEQ '{' sahlist '}' + { + $$ = ProcessAnalyzerRedef($3, Decl::FLOW, $6); + } + ; + +decl_without_attr: TOK_LPB_HEADER embedded_code TOK_RPB + { + $$ = new HelperDecl(HelperDecl::HEADER, 0, $2); + } + | TOK_LPB_CODE embedded_code TOK_RPB + { + $$ = new HelperDecl(HelperDecl::CODE, 0, $2); + } + | TOK_LPB_EXTERN embedded_code TOK_RPB + { + $$ = new HelperDecl(HelperDecl::EXTERN, 0, $2); + } + | TOK_REFINE TOK_TYPEATTR tok_id TOK_PLUSEQ attrlist + { + $$ = ProcessTypeAttrRedef($3, $5); + } + ; + +optsemicolon : /* nothing */ + | ';' + ; + +tok_id : TOK_ID + { + $$ = $1; + } + | TOK_CONNECTION + { + $$ = new ID("connection"); + } + | TOK_ANALYZER + { + $$ = new ID("analyzer"); + } + | TOK_FLOW + { + $$ = new ID("flow"); + } + | TOK_FUNCTION + { + $$ = new ID("function"); + } + | TOK_TYPE + { + $$ = new ID("type"); + } + ; + +analyzercontext : '{' contextfieldlist '}' + { + $$ = $2; + } + ; + +contextfieldlist: contextfieldlist contextfield ';' + { + $1->push_back($2); + $$ = $1; + } + | /* nothing */ + { + $$ = new ContextFieldList(); + } + ; + +contextfield : tok_id ':' type1 + { + $$ = new ContextField($1, $3); + } + ; + +funcproto : tok_id '(' paramlist ')' ':' type2 + { + $$ = new Function($1, $6, $3); + } + ; + +function : funcproto '=' expr + { + $1->set_expr($3); + $$ = $1; + } + | funcproto TOK_LPB embedded_code TOK_RPB + { + $1->set_code($3); + $$ = $1; + } + | funcproto ';' + { + $$ = $1; + } + ; + +optparams : '(' paramlist ')' + { + $$ = $2; + } + | /* empty */ + { + $$ = 0; + } + ; + +paramlist : paramlist ',' param + { + $1->push_back($3); + $$ = $1; + } + | param + { + $$ = new ParamList(); + $$->push_back($1); + } + | /* empty */ + { + $$ = new ParamList(); + } + ; + +param : tok_id ':' type2 + { + $$ = new Param($1, $3); + } + ; + +optinit : /* nothing */ + { + $$ = 0; + } + | '=' expr + { + $$ = $2; + } + ; + +opttype : /* nothing */ + { + $$ = 0; + } + | ':' type2 + { + $$ = $2; + } + ; + +type : type3 + { + $$ = $1; + } + ; + +/* type3 is for record or type2 */ +type3 : type2 + { + $$ = $1; + } + | TOK_RECORD '{' recordfieldlist '}' + { + $$ = new RecordType($3); + } + ; + +/* type2 is for array or case or type1 */ +type2 : type1 + { + $$ = $1; + } + | type1 '[' expr ']' + { + $$ = new ArrayType($1, $3); + } + | type1 '[' ']' + { + $$ = new ArrayType($1); + } + | TOK_CASE caseindex TOK_OF '{' casefieldlist '}' + { + $$ = new CaseType($2, $5); + } + ; + +/* type1 is for built-in, parameterized, or string types */ +type1 : tok_id + { + $$ = Type::LookUpByID($1); + } + | tok_id '(' exprlist ')' + { + $$ = new ParameterizedType($1, $3); + } + | regex + { + $$ = new StringType($1); + } + | cstr + { + $$ = new StringType($1); + } + ; + +recordfieldlist : recordfieldlist recordfield ';' + { + $1->push_back($2); + $$ = $1; + } + | /* empty */ + { + $$ = new RecordFieldList(); + } + ; + +recordfield : recordfield0 optattrs + { + $1->AddAttr($2); + $$ = $1; + } + ; + +recordfield0 : optfieldid type2 + { + $$ = new RecordDataField($1, $2); + } + | padding + { + $$ = $1; + } + ; + +padding : optfieldid TOK_PADDING '[' expr ']' + { + $$ = new RecordPaddingField( + $1, PAD_BY_LENGTH, $4); + } + | optfieldid TOK_PADDING TOK_TO expr + { + $$ = new RecordPaddingField( + $1, PAD_TO_OFFSET, $4); + } + | optfieldid TOK_PADDING TOK_ALIGN expr + { + $$ = new RecordPaddingField( + $1, PAD_TO_NEXT_WORD, $4); + } + ; + +optfieldid : tok_id ':' + { + $$ = $1; + } + | ':' + { + $$ = ID::NewAnonymousID("anonymous_field_"); + } + ; + +caseindex : expr + { + $$ = $1; + } + ; + +casefieldlist : casefieldlist casefield ';' + { + $1->push_back($2); + $$ = $1; + } + | /* empty */ + { + $$ = new CaseFieldList(); + } + ; + +casefield : casefield0 optattrs + { + $1->AddAttr($2); + $$ = $1; + } + ; + +casefield0 : exprlist TOK_RIGHTARROW tok_id ':' type2 + { + $$ = new CaseField($1, $3, $5); + } + | TOK_DEFAULT TOK_RIGHTARROW tok_id ':' type2 + { + $$ = new CaseField(0, $3, $5); + } + ; + +optexprlist : /* nothing */ + { + $$ = 0; + } + | exprlist + { + $$ = $1; + } + ; + +exprlist : exprlist ',' expr + { + $1->push_back($3); + $$ = $1; + } + | expr + { + $$ = new ExprList(); + $$->push_back($1); + } + ; + +expr : tok_id + { + $$ = new Expr($1); + } + | TOK_NUMBER + { + $$ = new Expr($1); + } + | expr '[' expr ']' + { + $$ = new Expr(Expr::EXPR_SUBSCRIPT, $1, $3); + } + | expr '.' tok_id + { + $$ = new Expr(Expr::EXPR_MEMBER, $1, new Expr($3)); + } + | TOK_SIZEOF '(' tok_id ')' + { + $$ = new Expr(Expr::EXPR_SIZEOF, new Expr($3)); + } + | TOK_OFFSETOF '(' tok_id ')' + { + $$ = new Expr(Expr::EXPR_OFFSETOF, new Expr($3)); + } + | '(' expr ')' + { + $$ = new Expr(Expr::EXPR_PAREN, $2); + } + | expr '(' optexprlist ')' + { + $$ = new Expr(Expr::EXPR_CALL, + $1, + new Expr($3)); + } + | '-' expr + { + $$ = new Expr(Expr::EXPR_NEG, $2); + } + | expr '+' expr + { + $$ = new Expr(Expr::EXPR_PLUS, $1, $3); + } + | expr '-' expr + { + $$ = new Expr(Expr::EXPR_MINUS, $1, $3); + } + | expr '*' expr + { + $$ = new Expr(Expr::EXPR_TIMES, $1, $3); + } + | expr '/' expr + { + $$ = new Expr(Expr::EXPR_DIV, $1, $3); + } + | expr '%' expr + { + $$ = new Expr(Expr::EXPR_MOD, $1, $3); + } + | '~' expr + { + $$ = new Expr(Expr::EXPR_BITNOT, $2); + } + | expr '&' expr + { + $$ = new Expr(Expr::EXPR_BITAND, $1, $3); + } + | expr '|' expr + { + $$ = new Expr(Expr::EXPR_BITOR, $1, $3); + } + | expr '^' expr + { + $$ = new Expr(Expr::EXPR_BITXOR, $1, $3); + } + | expr TOK_LSHIFT expr + { + $$ = new Expr(Expr::EXPR_LSHIFT, $1, $3); + } + | expr TOK_RSHIFT expr + { + $$ = new Expr(Expr::EXPR_RSHIFT, $1, $3); + } + | expr TOK_EQUAL expr + { + $$ = new Expr(Expr::EXPR_EQUAL, $1, $3); + } + | expr TOK_NEQ expr + { + $$ = new Expr(Expr::EXPR_NEQ, $1, $3); + } + | expr TOK_GE expr + { + $$ = new Expr(Expr::EXPR_GE, $1, $3); + } + | expr TOK_LE expr + { + $$ = new Expr(Expr::EXPR_LE, $1, $3); + } + | expr '>' expr + { + $$ = new Expr(Expr::EXPR_GT, $1, $3); + } + | expr '<' expr + { + $$ = new Expr(Expr::EXPR_LT, $1, $3); + } + | '!' expr + { + $$ = new Expr(Expr::EXPR_NOT, $2); + } + | expr TOK_AND expr + { + $$ = new Expr(Expr::EXPR_AND, $1, $3); + } + | expr TOK_OR expr + { + $$ = new Expr(Expr::EXPR_OR, $1, $3); + } + | expr '?' expr ':' expr + { + $$ = new Expr(Expr::EXPR_COND, $1, $3, $5); + } + | TOK_CASE expr TOK_OF '{' caseexprlist '}' + { + $$ = new Expr($2, $5); + } + | cstr + { + $$ = new Expr($1); + } + | regex + { + $$ = new Expr($1); + } + ; + +cstr : TOK_STRING + { + $$ = new ConstString($1); + } + ; + +regex : TOK_BEGIN_RE TOK_REGEX TOK_END_RE + { + $$ = new RegEx($2); + } + ; + +caseexprlist : /* nothing */ + { + $$ = new CaseExprList(); + } + | caseexprlist caseexpr ';' + { + $1->push_back($2); + $$ = $1; + } + ; + +caseexpr : exprlist TOK_RIGHTARROW expr + { + $$ = new CaseExpr($1, $3); + } + | TOK_DEFAULT TOK_RIGHTARROW expr + { + $$ = new CaseExpr(0, $3); + } + ; + +enumlist : enumlist1 + { + $$ = $1; + } + | enumlist1 ',' + { + $$ = $1; + } + ; + +enumlist1 : enumlist1 ',' enumitem + { + $1->push_back($3); + $$ = $1; + } + | enumitem + { + $$ = new EnumList(); + $$->push_back($1); + } + ; + +enumitem : tok_id + { + $$ = new Enum($1); + } + | tok_id '=' expr + { + $$ = new Enum($1, $3); + } + ; + +conn : sahlist + { + $$ = $1; + } + ; + +flow : sahlist + { + $$ = $1; + } + ; + +/* State-Action-Helper List */ +sahlist : /* empty */ + { + $$ = new AnalyzerElementList(); + } + | sahlist sah + { + $1->push_back($2); + $$ = $1; + } + ; + +sah : TOK_LPB_MEMBER embedded_code TOK_RPB + { + $$ = new AnalyzerHelper(AnalyzerHelper::MEMBER_DECLS, $2); + } + | TOK_LPB_INIT embedded_code TOK_RPB + { + $$ = new AnalyzerHelper(AnalyzerHelper::INIT_CODE, $2); + } + | TOK_LPB_CLEANUP embedded_code TOK_RPB + { + $$ = new AnalyzerHelper(AnalyzerHelper::CLEANUP_CODE, $2); + } + | TOK_LPB_EOF embedded_code TOK_RPB + { + $$ = new AnalyzerHelper(AnalyzerHelper::EOF_CODE, $2); + } + | TOK_FLOWDIR '=' tok_id optargs ';' + { + $$ = new AnalyzerFlow((AnalyzerFlow::Direction) $1, $3, $4); + } + | TOK_DATAUNIT '=' tok_id optargs TOK_WITHCONTEXT '(' optexprlist ')' ';' + { + $$ = new AnalyzerDataUnit( + (AnalyzerDataUnit::DataUnitType) $1, + $3, + $4, + $7); + } + | TOK_FUNCTION function + { + $$ = new AnalyzerFunction($2); + } + | TOK_STATE '{' statevarlist '}' + { + $$ = new AnalyzerState($3); + } + | TOK_ACTION tok_id TOK_WHEN '(' actionparam ')' TOK_LPB embedded_code TOK_RPB + { + $$ = new AnalyzerAction($2, (AnalyzerAction::When) $3, $5, $8); + } + ; + +statevarlist : /* empty */ + { + $$ = new StateVarList(); + } + | statevarlist statevar ';' + { + $1->push_back($2); + $$ = $1; + } + ; + +statevar : tok_id ':' type1 + { + $$ = new StateVar($1, $3); + } + ; + +actionparam : tok_id TOK_LE actionparamtype + { + $$ = new ActionParam($1, $3); + } + ; + +actionparamtype : tok_id + { + $$ = new ActionParamType($1); + } + | tok_id '.' tok_id + { + $$ = new ActionParamType($1, $3); + } + ; + +embedded_code : /* empty */ + { + $$ = new EmbeddedCode(); + } + | embedded_code TOK_EMBEDDED_ATOM + { + $1->Append($2); + $$ = $1; + } + | embedded_code TOK_EMBEDDED_STRING + { + $1->Append($2); + $$ = $1; + } + | embedded_code embedded_pac_primitive + { + $1->Append($2); + $$ = $1; + } + ; + +embedded_pac_primitive: TOK_PAC_VAL expr TOK_END_PAC + { + $$ = new PPVal($2); + } + | TOK_PAC_SET expr TOK_END_PAC + { + $$ = new PPSet($2); + } + | TOK_PAC_TYPE expr TOK_END_PAC + { + $$ = new PPType($2); + } + | TOK_PAC_CONST_DEF tok_id '=' expr TOK_END_PAC + { + $$ = new PPConstDef($2, $4); + } + ; + +optargs : /* empty */ + { + $$ = 0; + } + | '(' optexprlist ')' + { + $$ = $2; + } + ; + +letfieldlist : letfieldlist letfield ';' + { + $1->push_back($2); + $$ = $1; + } + | letfieldlist withinputfield ';' + { + $1->push_back($2); + $$ = $1; + } + | /* empty */ + { + $$ = new FieldList(); + } + ; + +letfield : tok_id opttype optinit optattrs + { + $$ = new LetField($1, $2, $3); + $$->AddAttr($4); + } + ; + +withinputfield : tok_id ':' type1 TOK_WITHINPUT input optattrs + { + $$ = new WithInputField($1, $3, $5); + $$->AddAttr($6); + } + ; + +/* There can be other forms of input */ +input : expr + { + $$ = new InputBuffer($1); + } + ; + +optattrs : /* empty */ + { + $$ = 0; + } + | attrlist + { + $$ = $1; + } + ; + +attrlist : attrlist optcomma attr + { + if ( $3 ) + $1->push_back($3); + $$ = $1; + } + | attr + { + $$ = new AttrList(); + if ( $1 ) + $$->push_back($1); + } + ; + +optcomma : /* nothing */ + | ',' + ; + +attr : TOK_ATTR_BYTEORDER '=' expr + { + $$ = new Attr(ATTR_BYTEORDER, $3); + } + | TOK_ATTR_CHECK expr + { + $$ = new Attr(ATTR_CHECK, $2); + } + | TOK_ATTR_CHUNKED + { + $$ = new Attr(ATTR_CHUNKED); + } + | TOK_ATTR_EXPORTSOURCEDATA + { + $$ = new Attr(ATTR_EXPORTSOURCEDATA); + } + | TOK_ATTR_IF expr + { + $$ = new Attr(ATTR_IF, $2); + } + | TOK_ATTR_LENGTH '=' expr + { + $$ = new Attr(ATTR_LENGTH, $3); + } + | TOK_ATTR_LET '{' letfieldlist '}' + { + $$ = new LetAttr($3); + } + | TOK_ATTR_LINEBREAKER '=' expr + { + $$ = new Attr(ATTR_LINEBREAKER, $3); + } + | TOK_ATTR_MULTILINE '(' expr ')' + { + $$ = new Attr(ATTR_MULTILINE, $3); + } + | TOK_ATTR_ONELINE optlinebreaker + { + $$ = new Attr(ATTR_ONELINE, $2); + } + | TOK_ATTR_REFCOUNT + { + $$ = new Attr(ATTR_REFCOUNT); + } + | TOK_ATTR_REQUIRES '(' optexprlist ')' + { + $$ = new Attr(ATTR_REQUIRES, $3); + } + | TOK_ATTR_RESTOFDATA + { + $$ = new Attr(ATTR_RESTOFDATA); + } + | TOK_ATTR_RESTOFFLOW + { + $$ = new Attr(ATTR_RESTOFFLOW); + } + | TOK_ATTR_TRANSIENT + { + $$ = new Attr(ATTR_TRANSIENT); + } + | TOK_ATTR_UNTIL expr + { + $$ = new Attr(ATTR_UNTIL, $2); + } + ; + +optlinebreaker : /* nothing */ + { + $$ = 0; + } + | '(' expr ')' + { + $$ = $2; + } + ; + +%% + +const ID* current_decl_id = 0; + +int yyerror(const char msg[]) + { + char* msgbuf = + new char[strlen(msg) + yyleng + 64]; + + if ( ! yychar || ! yytext || yytext[0] == '\0' ) + sprintf(msgbuf, "%s, at end of file", msg); + + else if ( yytext[0] == '\n' ) + sprintf(msgbuf, "%s, on previous line", msg); + + else + sprintf(msgbuf, "%s, at or near \"%s\"", msg, yytext); + + /* + extern int column; + sprintf(msgbuf, "%*s\n%*s\n", column, "^", column, msg); + */ + + if ( ! input_filename.empty() ) + fprintf(stderr, "%s:%d: ", input_filename.c_str(), line_number); + else + fprintf(stderr, "line %d: ", line_number); + fprintf(stderr, "%s", msgbuf); + fprintf(stderr, " (yychar=%d)", yychar); + fprintf(stderr, "\n"); + + return 0; + } diff --git a/tools/binpac/src/pac_primitive.cc b/tools/binpac/src/pac_primitive.cc new file mode 100644 index 0000000000..c4893a63ed --- /dev/null +++ b/tools/binpac/src/pac_primitive.cc @@ -0,0 +1,39 @@ +#include "pac_dbg.h" +#include "pac_expr.h" +#include "pac_id.h" +#include "pac_primitive.h" +#include "pac_type.h" + +string PPVal::ToCode(Env *env) + { + ASSERT(expr_); + return string(expr_->EvalExpr(0, env)); + } + +string PPSet::ToCode(Env *env) + { + ASSERT(expr_); + return expr_->SetFunc(0, env); + } + +string PPType::ToCode(Env *env) + { + Type *type = expr_->DataType(env); + if ( ! type ) + { + } + return type->DataTypeStr(); + } + +string PPConstDef::ToCode(Env *env) + { + Type *type = expr_->DataType(env); + env->AddID(id_, TEMP_VAR, type); + env->SetEvaluated(id_); + + string type_str = type->DataTypeStr(); + return strfmt("%s %s = %s", + type_str.c_str(), + env->LValue(id_), + expr_->EvalExpr(0, env)); + } diff --git a/tools/binpac/src/pac_primitive.h b/tools/binpac/src/pac_primitive.h new file mode 100644 index 0000000000..47d06a1e72 --- /dev/null +++ b/tools/binpac/src/pac_primitive.h @@ -0,0 +1,75 @@ +#ifndef pac_primitive_h +#define pac_primitive_h + +#include "pac_common.h" + +class PacPrimitive +{ +public: + enum PrimitiveType { VAL, SET, TYPE, CONST_DEF }; + + explicit PacPrimitive(PrimitiveType type) : type_(type) {} + virtual ~PacPrimitive() {} + + PrimitiveType type() const { return type(); } + + virtual string ToCode(Env *env) = 0; + +private: + PrimitiveType type_; +}; + +class PPVal : public PacPrimitive +{ +public: + PPVal(Expr *expr) : PacPrimitive(VAL), expr_(expr) {} + Expr *expr() const { return expr_; } + + string ToCode(Env *env); + +private: + Expr *expr_; +}; + +class PPSet : public PacPrimitive +{ +public: + PPSet(Expr *expr) : PacPrimitive(SET), expr_(expr) {} + Expr *expr() const { return expr_; } + + string ToCode(Env *env); + +private: + Expr *expr_; +}; + +class PPType : public PacPrimitive +{ +public: + PPType(Expr *expr) : PacPrimitive(TYPE), expr_(expr) {} + Expr *expr() const { return expr_; } + + string ToCode(Env *env); + +private: + Expr *expr_; +}; + +class PPConstDef : public PacPrimitive +{ +public: + PPConstDef(const ID *id, Expr *expr) + : PacPrimitive(CONST_DEF), + id_(id), + expr_(expr) {} + const ID *id() const { return id_; } + Expr *expr() const { return expr_; } + + string ToCode(Env *env); + +private: + const ID *id_; + Expr *expr_; +}; + +#endif // pac_primitive_h diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc new file mode 100644 index 0000000000..9875195033 --- /dev/null +++ b/tools/binpac/src/pac_record.cc @@ -0,0 +1,680 @@ +#include "pac_attr.h" +#include "pac_dataptr.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_field.h" +#include "pac_output.h" +#include "pac_record.h" +#include "pac_type.h" +#include "pac_typedecl.h" +#include "pac_utils.h" +#include "pac_varfield.h" + + +RecordType::RecordType(RecordFieldList* record_fields) + : Type(RECORD) + { + // Here we assume that the type is a standalone type. + value_var_ = 0; + + // Put all fields in fields_ + foreach (i, RecordFieldList, record_fields) + AddField(*i); + + // Put RecordField's in record_fields_ + record_fields_ = record_fields; + + parsing_dataptr_var_field_ = 0; + } + +RecordType::~RecordType() + { + // Do not delete_list(RecordFieldList, record_fields_) + // because the fields are also in fields_. + delete record_fields_; + delete parsing_dataptr_var_field_; + } + +const ID *RecordType::parsing_dataptr_var() const + { + return parsing_dataptr_var_field_ ? + parsing_dataptr_var_field_->id() : 0; + } + +bool RecordType::DefineValueVar() const + { + return false; + } + +string RecordType::DataTypeStr() const + { + ASSERT(type_decl()); + return strfmt("%s *", type_decl()->class_name().c_str()); + } + +void RecordType::Prepare(Env* env, int flags) + { + ASSERT(flags & TO_BE_PARSED); + + RecordField *prev = 0; + int offset = 0; + int seq = 0; + foreach (i, RecordFieldList, record_fields_) + { + RecordField *f = *i; + f->set_record_type(this); + f->set_prev(prev); + if ( prev ) + prev->set_next(f); + prev = f; + if ( offset >= 0 ) + { + f->set_static_offset(offset); + int w = f->StaticSize(env, offset); + if ( w < 0 ) + offset = -1; + else + offset += w; + } + ++seq; + f->set_parsing_state_seq(seq); + } + + if ( incremental_parsing() ) + { +#if 0 + ASSERT(! parsing_state_var_field_); + ID *parsing_state_var_id = new ID("parsing_state"); + parsing_state_var_field_ = new PrivVarField( + parsing_state_var_id, extern_type_int->Clone()); + AddField(parsing_state_var_field_); + + ID *parsing_dataptr_var_id = new ID("parsing_dataptr"); + parsing_dataptr_var_field_ = new TempVarField( + parsing_dataptr_var_id, extern_type_const_byteptr->Clone()); + parsing_dataptr_var_field_->Prepare(env); +#endif + } + + Type::Prepare(env, flags); + } + +void RecordType::GenPubDecls(Output* out_h, Env* env) + { + Type::GenPubDecls(out_h, env); + } + +void RecordType::GenPrivDecls(Output* out_h, Env* env) + { + Type::GenPrivDecls(out_h, env); + } + +void RecordType::GenInitCode(Output* out_cc, Env* env) + { + Type::GenInitCode(out_cc, env); + } + +void RecordType::GenCleanUpCode(Output* out_cc, Env* env) + { + Type::GenCleanUpCode(out_cc, env); + } + +void RecordType::DoGenParseCode(Output* out_cc, Env* env, + const DataPtr& data, int flags) + { + if ( !incremental_input() && StaticSize(env) >= 0 ) + GenBoundaryCheck(out_cc, env, data); + + if ( incremental_parsing() ) + { + out_cc->println("switch ( %s ) {", + env->LValue(parsing_state_id)); + + out_cc->println("case 0:"); + out_cc->inc_indent(); + foreach (i, RecordFieldList, record_fields_) + { + RecordField *f = *i; + f->GenParseCode(out_cc, env); + out_cc->println(""); + } + out_cc->println(""); + out_cc->println("%s = true;", + env->LValue(parsing_complete_var())); + out_cc->dec_indent(); + out_cc->println("}"); + } + else + { + ASSERT( data.id() == begin_of_data && + data.offset() == 0 ); + foreach (i, RecordFieldList, record_fields_) + { + RecordField *f = *i; + f->GenParseCode(out_cc, env); + out_cc->println(""); + } + if ( incremental_input() ) + { + ASSERT(parsing_complete_var()); + out_cc->println("%s = true;", + env->LValue(parsing_complete_var())); + } + } + + if ( ! incremental_input() && AddSizeVar(out_cc, env) ) + { + const DataPtr& end_of_record_dataptr = + record_fields_->back()->getFieldEnd(out_cc, env); + + out_cc->println("%s = %s - %s;", + env->LValue(size_var()), + end_of_record_dataptr.ptr_expr(), + env->RValue(begin_of_data)); + env->SetEvaluated(size_var()); + } + + if ( ! boundary_checked() ) + { + RecordField *last_field = record_fields_->back(); + if ( ! last_field->BoundaryChecked() ) + GenBoundaryCheck(out_cc, env, data); + } + } + +void RecordType::GenDynamicSize(Output* out_cc, Env* env, + const DataPtr& data) + { + GenParseCode(out_cc, env, data, 0); + } + +int RecordType::StaticSize(Env* env) const + { + int tot_w = 0; + foreach (i, RecordFieldList, record_fields_) + { + RecordField *f = *i; + int w = f->StaticSize(env, tot_w); + if ( w < 0 ) + return -1; + tot_w += w; + } + return tot_w; + } + +void RecordType::SetBoundaryChecked() + { + Type::SetBoundaryChecked(); + foreach (i, RecordFieldList, record_fields_) + { + RecordField *f = *i; + f->SetBoundaryChecked(); + } + } + +void RecordType::DoMarkIncrementalInput() + { + foreach (i, RecordFieldList, record_fields_) + { + RecordField *f = *i; + f->type()->MarkIncrementalInput(); + } + } + +bool RecordType::DoTraverse(DataDepVisitor *visitor) + { + return Type::DoTraverse(visitor); + } + +bool RecordType::ByteOrderSensitive() const + { + foreach (i, RecordFieldList, record_fields_) + { + RecordField *f = *i; + if ( f->RequiresByteOrder() ) + return true; + } + return false; + } + +RecordField::RecordField(FieldType tof, ID *id, Type *type) + : Field(tof, + TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, + id, type) + { + begin_of_field_dataptr = 0; + end_of_field_dataptr = 0; + field_size_expr = 0; + field_offset_expr = 0; + end_of_field_dataptr_var = 0; + record_type_ = 0; + prev_ = 0; + next_ = 0; + static_offset_ = -1; + boundary_checked_ = false; + } + +RecordField::~RecordField() + { + delete begin_of_field_dataptr; + delete end_of_field_dataptr; + delete [] field_size_expr; + delete [] field_offset_expr; + delete end_of_field_dataptr_var; + } + +const DataPtr& RecordField::getFieldBegin(Output* out_cc, Env* env) + { + if ( prev() ) + return prev()->getFieldEnd(out_cc, env); + else + { + // The first field + if ( ! begin_of_field_dataptr ) + { + begin_of_field_dataptr = + new DataPtr(env, begin_of_data, 0); + } + return *begin_of_field_dataptr; + } + } + +const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) + { + if ( end_of_field_dataptr ) + return *end_of_field_dataptr; + + const DataPtr& begin_ptr = getFieldBegin(out_cc, env); + + if ( record_type()->incremental_parsing() ) + { + ASSERT(0); + if ( ! end_of_field_dataptr ) + { + const ID *dataptr_var = + record_type()->parsing_dataptr_var(); + ASSERT(dataptr_var); + + end_of_field_dataptr = + new DataPtr(env, dataptr_var, 0); + } + } + else + { + int field_offset; + if ( begin_ptr.id() == begin_of_data ) + field_offset = begin_ptr.offset(); + else + field_offset = -1; // unknown + + int field_size = StaticSize(env, field_offset); + if ( field_size >= 0 ) // can be statically determinted + { + end_of_field_dataptr = new DataPtr( + env, + begin_ptr.id(), + begin_ptr.offset() + field_size); + } + else + { + // If not, we add a variable for the offset after the field + end_of_field_dataptr_var = new ID( + fmt("dataptr_after_%s", id()->Name())); + env->AddID(end_of_field_dataptr_var, + TEMP_VAR, + extern_type_const_byteptr); + + GenFieldEnd(out_cc, env, begin_ptr); + + end_of_field_dataptr = new DataPtr( + env, + end_of_field_dataptr_var, + 0); + } + } + + return *end_of_field_dataptr; + } + +const char* RecordField::FieldSize(Output* out_cc, Env* env) + { + if ( field_size_expr ) + return field_size_expr; + + const DataPtr& begin = getFieldBegin(out_cc, env); + const DataPtr& end = getFieldEnd(out_cc, env); + if ( begin.id() == end.id() ) + field_size_expr = nfmt("%d", end.offset() - begin.offset()); + else + field_size_expr = nfmt("(%s - %s)", end.ptr_expr(), begin.ptr_expr()); + return field_size_expr; + } + +const char* RecordField::FieldOffset(Output* out_cc, Env* env) + { + if ( field_offset_expr ) + return field_offset_expr; + + const DataPtr& begin = getFieldBegin(out_cc, env); + if ( begin.id() == begin_of_data ) + field_offset_expr = nfmt("%d", begin.offset()); + else + field_offset_expr = nfmt("(%s - %s)", + begin.ptr_expr(), env->RValue(begin_of_data)); + return field_offset_expr; + } + +// The reasoning behind AttemptBoundaryCheck is: "If my next field +// can check its boundary, then I don't have to check mine, and it +// will save me a boundary-check." +bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env) + { + if ( boundary_checked_ ) + return true; + + // If I do not even know my size till I parse the data, my + // next field won't be able to check its boundary now. + + const DataPtr& begin = getFieldBegin(out_cc, env); + if ( StaticSize(env, begin.AbsOffset(begin_of_data)) < 0 ) + return false; + + // Now we ask the next field to check its boundary. + if ( next() && next()->AttemptBoundaryCheck(out_cc, env) ) + { + // If it works, we are all set + SetBoundaryChecked(); + return true; + } + else + // If it fails, then I can still try to do it by myself + return GenBoundaryCheck(out_cc, env); + } + +RecordDataField::RecordDataField(ID* id, Type* type) + : RecordField(RECORD_FIELD, id, type) + { + ASSERT(type_); + } + +RecordDataField::~RecordDataField() + { + } + +void RecordDataField::Prepare(Env* env) + { + Field::Prepare(env); + env->SetEvalMethod(id_, this); + env->SetField(id_, this); + } + +void RecordDataField::GenParseCode(Output* out_cc, Env* env) + { + if ( env->Evaluated(id()) ) + return; + + // Always evaluate record fields in order if parsing + // is incremental. + if ( record_type()->incremental_parsing() && prev() ) + prev()->GenParseCode(out_cc, env); + + DataPtr data(env, 0, 0); + if ( ! record_type()->incremental_parsing() ) + { + data = getFieldBegin(out_cc, env); + AttemptBoundaryCheck(out_cc, env); + } + + out_cc->println("// Parse \"%s\"", id_->Name()); +#if 0 + out_cc->println("DEBUG_MSG(\"%%.6f Parse %s\\n\", network_time());", + id_->Name()); +#endif + type_->GenPreParsing(out_cc, env); + if ( type_->incremental_input() ) + { + // The enclosing record type must be incrementally parsed + out_cc->println("%s = %d;", + env->LValue(parsing_state_id), + parsing_state_seq()); + out_cc->dec_indent(); + out_cc->println("case %d:", parsing_state_seq()); + out_cc->inc_indent(); + out_cc->println("{"); + } + + type_->GenParseCode(out_cc, env, data, 0); + + if ( record_type()->incremental_parsing() ) + { + ASSERT(type_->incremental_input()); + + out_cc->println("if ( ! (%s) )", + type_->parsing_complete(env).c_str()); + out_cc->inc_indent(); + out_cc->println("goto %s;", kNeedMoreData); + out_cc->dec_indent(); + } + + if ( record_type()->incremental_parsing() ) + { +#if 0 + const ID *dataptr_var = + record_type()->parsing_dataptr_var(); + ASSERT(dataptr_var); + out_cc->println("%s += (%s);", + env->LValue(dataptr_var), + type_->DataSize(out_cc, env, data).c_str()); +#endif + out_cc->println("}"); + } + + SetBoundaryChecked(); + } + +void RecordDataField::GenEval(Output* out_cc, Env* env) + { + GenParseCode(out_cc, env); + } + +void RecordDataField::GenFieldEnd(Output* out_cc, Env* env, + const DataPtr& field_begin) + { + out_cc->println("const_byteptr const %s = %s + (%s);", + env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr(), + type_->DataSize(out_cc, env, field_begin).c_str()); + env->SetEvaluated(end_of_field_dataptr_var); + + out_cc->println("BINPAC_ASSERT(%s <= %s);", + env->RValue(end_of_field_dataptr_var), + env->RValue(end_of_data)); + } + +void RecordDataField::SetBoundaryChecked() + { + RecordField::SetBoundaryChecked(); + type_->SetBoundaryChecked(); + } + +bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env) + { + if ( boundary_checked_ ) + return true; + + type_->GenBoundaryCheck(out_cc, env, getFieldBegin(out_cc, env)); + + SetBoundaryChecked(); + return true; + } + +bool RecordDataField::DoTraverse(DataDepVisitor *visitor) + { + return Field::DoTraverse(visitor); + } + +bool RecordDataField::RequiresAnalyzerContext() const + { + return Field::RequiresAnalyzerContext() || + type()->RequiresAnalyzerContext(); + } + +RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr) + : RecordField(PADDING_FIELD, id, 0), ptype_(ptype), expr_(expr) + { + wordsize_ = -1; + } + +RecordPaddingField::~RecordPaddingField() + { + } + +void RecordPaddingField::Prepare(Env* env) + { + Field::Prepare(env); + if ( ptype_ == PAD_TO_NEXT_WORD ) + { + if ( ! expr_->ConstFold(env, &wordsize_) ) + throw ExceptionPaddingError(this, + fmt("padding word size not a constant")); + } + } + +void RecordPaddingField::GenParseCode(Output* out_cc, Env* env) + { + // Always evaluate record fields in order if parsing + // is incremental. + if ( record_type()->incremental_parsing() && prev() ) + prev()->GenParseCode(out_cc, env); + } + +int RecordPaddingField::StaticSize(Env* env, int offset) const + { + int length; + int target_offset; + int offset_in_word; + + switch ( ptype_ ) + { + case PAD_BY_LENGTH: + return expr_->ConstFold(env, &length) ? length : -1; + + case PAD_TO_OFFSET: + // If the current offset cannot be statically + // determined, we need to Generate code to + // check the offset + if ( offset == -1 ) + return -1; + + if ( ! expr_->ConstFold(env, &target_offset) ) + return -1; + + // If both the current and target offsets + // can be statically computed, we can get its + // static size + if ( offset > target_offset ) + throw ExceptionPaddingError( + this, + fmt("current offset = %d, " + "target offset = %d", + offset, target_offset)); + return target_offset - offset; + + case PAD_TO_NEXT_WORD: + if ( offset == -1 || wordsize_ == -1 ) + return -1; + + offset_in_word = offset % wordsize_; + return ( offset_in_word == 0 ) ? + 0 : wordsize_ - offset_in_word; + } + + return -1; + } + +void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin) + { + ASSERT(! env->Evaluated(end_of_field_dataptr_var)); + + char* padding_var; + switch ( ptype_ ) + { + case PAD_BY_LENGTH: + out_cc->println("const_byteptr const %s = %s + (%s);", + env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr(), + expr_->EvalExpr(out_cc, env)); + break; + + case PAD_TO_OFFSET: + out_cc->println("const_byteptr %s = %s + (%s);", + env->LValue(end_of_field_dataptr_var), + env->RValue(begin_of_data), + expr_->EvalExpr(out_cc, env)); + out_cc->println("if ( %s < %s )", + env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr()); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("// throw ExceptionInvalidOffset(\"%s\", %s - %s, %s);", + id_->LocName(), + field_begin.ptr_expr(), + env->RValue(begin_of_data), + expr_->EvalExpr(out_cc, env)); + out_cc->println("%s = %s;", + env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr()); + out_cc->println("}"); + out_cc->dec_indent(); + break; + + case PAD_TO_NEXT_WORD: + padding_var = nfmt("%s__size", id()->Name()); + out_cc->println("int %s = (%s - %s) %% %d;", + padding_var, + field_begin.ptr_expr(), + env->RValue(begin_of_data), + wordsize_); + out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", + padding_var, + padding_var, + wordsize_, + padding_var); + out_cc->println("const_byteptr const %s = %s + %s;", + env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr(), + padding_var); + delete [] padding_var; + break; + } + + env->SetEvaluated(end_of_field_dataptr_var); + } + +bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env) + { + if ( boundary_checked_ ) + return true; + + const DataPtr& begin = getFieldBegin(out_cc, env); + + char* size; + int ss = StaticSize(env, begin.AbsOffset(begin_of_data)); + ASSERT ( ss >= 0 ); + size = nfmt("%d", ss); + + begin.GenBoundaryCheck(out_cc, env, size, field_id_str_.c_str()); + + delete [] size; + + SetBoundaryChecked(); + return true; + } + +bool RecordPaddingField::DoTraverse(DataDepVisitor *visitor) + { + return Field::DoTraverse(visitor) && + (! expr_ || expr_->Traverse(visitor)); + } + diff --git a/tools/binpac/src/pac_record.h b/tools/binpac/src/pac_record.h new file mode 100644 index 0000000000..04daa3a9f4 --- /dev/null +++ b/tools/binpac/src/pac_record.h @@ -0,0 +1,169 @@ +#ifndef pac_record_h +#define pac_record_h + +#include "pac_common.h" +#include "pac_field.h" +#include "pac_id.h" +#include "pac_let.h" +#include "pac_type.h" + +class RecordType : public Type +{ +public: + RecordType(RecordFieldList* fields); + ~RecordType(); + + bool DefineValueVar() const; + string DataTypeStr() const; + + void Prepare(Env* env, int flags); + + void GenPubDecls(Output* out, Env* env); + void GenPrivDecls(Output* out, Env* env); + + void GenInitCode(Output* out, Env* env); + void GenCleanUpCode(Output* out, Env* env); + + int StaticSize(Env* env) const; + + void SetBoundaryChecked(); + + const ID *parsing_dataptr_var() const; + + bool IsPointerType() const { ASSERT(0); return false; } + +protected: + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); + void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + + Type *DoClone() const { return 0; } + + void DoMarkIncrementalInput(); + + bool DoTraverse(DataDepVisitor *visitor); + bool ByteOrderSensitive() const; + +private: + Field *parsing_dataptr_var_field_; + RecordFieldList* record_fields_; +}; + +// A data field of a record type. A RecordField corresponds to a +// segment of input data, and therefore RecordField's are ordered---each +// of them has a known previous and next field. + +class RecordField : public Field +{ +public: + RecordField(FieldType tof, ID* id, Type *type); + ~RecordField(); + + RecordType *record_type() const { return record_type_; } + void set_record_type(RecordType* ty) { record_type_ = ty; } + + virtual void GenParseCode(Output* out, Env* env) = 0; + + RecordField* prev() const { return prev_; } + RecordField* next() const { return next_; } + void set_prev(RecordField* f) { prev_ = f; } + void set_next(RecordField* f) { next_ = f; } + + int static_offset() const { return static_offset_; } + void set_static_offset(int offset) { static_offset_ = offset; } + + int parsing_state_seq() const { return parsing_state_seq_; } + void set_parsing_state_seq(int x) { parsing_state_seq_ = x; } + + virtual int StaticSize(Env* env, int offset) const = 0; + const char* FieldSize(Output* out, Env* env); + const char* FieldOffset(Output* out, Env* env); + + virtual bool BoundaryChecked() const { return boundary_checked_; } + virtual void SetBoundaryChecked() { boundary_checked_ = true; } + + virtual bool RequiresByteOrder() const = 0; + + friend class RecordType; + +protected: + RecordType* record_type_; + RecordField* prev_; + RecordField* next_; + bool boundary_checked_; + int static_offset_; + int parsing_state_seq_; + + DataPtr* begin_of_field_dataptr; + DataPtr* end_of_field_dataptr; + char* field_size_expr; + char* field_offset_expr; + ID* end_of_field_dataptr_var; + + const DataPtr& getFieldBegin(Output* out_cc, Env* env); + const DataPtr& getFieldEnd(Output* out_cc, Env* env); + virtual void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) = 0; + + bool AttemptBoundaryCheck(Output* out_cc, Env* env); + virtual bool GenBoundaryCheck(Output* out_cc, Env* env) = 0; +}; + +class RecordDataField : public RecordField, public Evaluatable +{ +public: + RecordDataField(ID* arg_id, Type* arg_type); + ~RecordDataField(); + + // Instantiates abstract class Field + void Prepare(Env* env); + void GenParseCode(Output* out, Env* env); + + // Instantiates abstract class Evaluatable + void GenEval(Output* out, Env* env); + + int StaticSize(Env* env, int) const { return type()->StaticSize(env); } + + void SetBoundaryChecked(); + + bool RequiresByteOrder() const + { return type()->RequiresByteOrder(); } + bool RequiresAnalyzerContext() const; + +protected: + void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); + bool GenBoundaryCheck(Output* out_cc, Env* env); + bool DoTraverse(DataDepVisitor *visitor); +}; + +enum PaddingType { PAD_BY_LENGTH, PAD_TO_OFFSET, PAD_TO_NEXT_WORD }; + +class RecordPaddingField : public RecordField +{ +public: + RecordPaddingField(ID* id, PaddingType ptype, Expr* expr); + ~RecordPaddingField(); + + void Prepare(Env* env); + + void GenPubDecls(Output* out, Env* env) { /* nothing */ } + void GenPrivDecls(Output* out, Env* env) { /* nothing */ } + + void GenInitCode(Output* out, Env* env) { /* nothing */ } + void GenCleanUpCode(Output* out, Env* env) { /* nothing */ } + void GenParseCode(Output* out, Env* env); + + int StaticSize(Env* env, int offset) const; + + bool RequiresByteOrder() const { return false; } + +protected: + void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); + bool GenBoundaryCheck(Output* out_cc, Env* env); + bool DoTraverse(DataDepVisitor *visitor); + +private: + PaddingType ptype_; + Expr* expr_; + int wordsize_; +}; + +#endif // pac_record_h diff --git a/tools/binpac/src/pac_redef.cc b/tools/binpac/src/pac_redef.cc new file mode 100644 index 0000000000..9f09b457bd --- /dev/null +++ b/tools/binpac/src/pac_redef.cc @@ -0,0 +1,173 @@ +#include "pac_analyzer.h" +#include "pac_case.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_func.h" +#include "pac_record.h" +#include "pac_redef.h" +#include "pac_type.h" +#include "pac_typedecl.h" + +namespace { + +Decl *find_decl(const ID *id) + { + Decl *decl = Decl::LookUpDecl(id); + if ( ! decl ) + { + throw Exception(id, + fmt("cannot find declaration for %s", + id->Name())); + } + + return decl; + } + +} + +Decl *ProcessTypeRedef(const ID *id, FieldList *fieldlist) + { + Decl *decl = find_decl(id); + + if ( decl->decl_type() != Decl::TYPE ) + { + throw Exception(id, + fmt("not a type declaration: %s", + id->Name())); + } + + TypeDecl *type_decl = static_cast(decl); + ASSERT(type_decl); + Type *type = type_decl->type(); + + foreach(i, FieldList, fieldlist) + { + Field *f = *i; + + // One cannot change data layout in 'redef'. + // Only 'let' or 'action' can be added + if ( f->tof() == LET_FIELD || + f->tof() == WITHINPUT_FIELD ) + { + type->AddField(f); + } + else if ( f->tof() == RECORD_FIELD || + f->tof() == PADDING_FIELD ) + { + throw Exception(f, + "cannot change data layout in redef"); + } + else if ( f->tof() == CASE_FIELD ) + { + throw Exception(f, + "use 'redef case' adding cases"); + } + } + + return decl; + } + +Decl *ProcessCaseTypeRedef(const ID *id, CaseFieldList *casefieldlist) + { + Decl *decl = find_decl(id); + + if ( decl->decl_type() != Decl::TYPE ) + { + throw Exception(id, + fmt("not a type declaration: %s", + id->Name())); + } + + TypeDecl *type_decl = static_cast(decl); + ASSERT(type_decl); + + Type *type = type_decl->type(); + if ( type->tot() != Type::CASE ) + { + throw Exception(id, + fmt("not a case type: %s", + id->Name())); + } + + CaseType *casetype = static_cast(type); + ASSERT(casetype); + + foreach(i, CaseFieldList, casefieldlist) + { + CaseField *f = *i; + casetype->AddCaseField(f); + } + + return decl; + } + +Decl *ProcessCaseExprRedef(const ID *id, CaseExprList *caseexprlist) + { + Decl *decl = find_decl(id); + + if ( decl->decl_type() != Decl::FUNC ) + { + throw Exception(id, + fmt("not a function declaration: %s", + id->Name())); + } + + FuncDecl *func_decl = static_cast(decl); + ASSERT(func_decl); + + Expr *expr = func_decl->function()->expr(); + if ( ! expr ||expr->expr_type() != Expr::EXPR_CASE ) + { + throw Exception(id, + fmt("function not defined by a case expression: %s", + id->Name())); + } + + foreach(i, CaseExprList, caseexprlist) + { + CaseExpr *e = *i; + expr->AddCaseExpr(e); + } + + return decl; + } + +Decl *ProcessAnalyzerRedef(const ID *id, + Decl::DeclType decl_type, + AnalyzerElementList *elements) + { + Decl *decl = find_decl(id); + + if ( decl->decl_type() != decl_type ) + { + throw Exception(id, + fmt("not a connection/flow declaration: %s", + id->Name())); + } + + AnalyzerDecl *analyzer_decl = static_cast(decl); + ASSERT(analyzer_decl); + + analyzer_decl->AddElements(elements); + + return decl; + } + +Decl *ProcessTypeAttrRedef(const ID *id, AttrList *attrlist) + { + Decl *decl = find_decl(id); + + if ( decl->decl_type() != Decl::TYPE ) + { + throw Exception(id, + fmt("not a type declaration: %s", + id->Name())); + } + + TypeDecl *type_decl = static_cast(decl); + ASSERT(type_decl); + + type_decl->AddAttrs(attrlist); + + return decl; + } diff --git a/tools/binpac/src/pac_redef.h b/tools/binpac/src/pac_redef.h new file mode 100644 index 0000000000..9a9c3030c4 --- /dev/null +++ b/tools/binpac/src/pac_redef.h @@ -0,0 +1,13 @@ +#ifndef pac_redef_h +#define pac_redef_h + +#include "pac_decl.h" + +Decl *ProcessCaseTypeRedef(const ID *id, CaseFieldList *casefieldlist); +Decl *ProcessCaseExprRedef(const ID *id, CaseExprList *caseexprlist); +Decl *ProcessAnalyzerRedef(const ID *id, + Decl::DeclType decl_type, + AnalyzerElementList *elements); +Decl *ProcessTypeAttrRedef(const ID *id, AttrList *attrlist); + +#endif // pac_redef_h diff --git a/tools/binpac/src/pac_regex.cc b/tools/binpac/src/pac_regex.cc new file mode 100644 index 0000000000..6265c02876 --- /dev/null +++ b/tools/binpac/src/pac_regex.cc @@ -0,0 +1,82 @@ +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_regex.h" +#include "pac_type.h" + +// Depends on the regular expression library we are using +const char *RegEx::kREMatcherType = "RegExMatcher"; +const char *RegEx::kMatchPrefix = "MatchPrefix"; + +string escape_char(const string &s) + { + char buf[s.length() * 2 + 1]; + int j = 0; + for ( int i = 0; i < (int) s.length(); ++i ) + { + if ( s[i] == '\\' ) + { + if ( i + 1 < (int) s.length() ) + { + buf[j++] = '\\'; + if ( s[i+1] == '/' ) + buf[j-1] = s[++i]; + else if ( s[i+1] == '/' || s[i+1] == '\\' || s[i+1] == '"' ) + buf[j++] = s[++i]; + else + buf[j++] = '\\'; + } + } + else if ( s[i] == '"' ) + { + buf[j++] = '\\'; + buf[j++] = '"'; + } + else + { + buf[j++] = s[i]; + } + } + + buf[j++] = '\0'; + + return string(buf); + } + +RegEx::RegEx(const string &s) + { + str_ = escape_char(s); + string prefix = strfmt("%s_re_", current_decl_id->Name()); + matcher_id_ = ID::NewAnonymousID(prefix); + decl_ = new RegExDecl(this); + } + +RegEx::~RegEx() + { + } + +RegExDecl::RegExDecl(RegEx *regex) + : Decl(regex->matcher_id(), REGEX) + { + regex_ = regex; + } + +void RegExDecl::Prepare() + { + global_env()->AddID(id(), GLOBAL_VAR, extern_type_re_matcher); + } + +void RegExDecl::GenForwardDeclaration(Output *out_h) + { + out_h->println("extern %s %s;\n", + RegEx::kREMatcherType, + global_env()->LValue(regex_->matcher_id())); + } + +void RegExDecl::GenCode(Output *out_h, Output *out_cc) + { + out_cc->println("%s %s(\"%s\");\n", + RegEx::kREMatcherType, + global_env()->LValue(regex_->matcher_id()), + regex_->str().c_str()); + } diff --git a/tools/binpac/src/pac_regex.h b/tools/binpac/src/pac_regex.h new file mode 100644 index 0000000000..47c601b729 --- /dev/null +++ b/tools/binpac/src/pac_regex.h @@ -0,0 +1,41 @@ +#ifndef pac_regex_h +#define pac_regex_h + +#include "pac_common.h" +#include "pac_decl.h" + +class RegExDecl; + +class RegEx : public Object +{ +public: + RegEx(const string &str); + ~RegEx(); + + const string &str() const { return str_; } + ID *matcher_id() const { return matcher_id_; } + +private: + string str_; + ID *matcher_id_; + RegExDecl *decl_; + +public: + static const char *kREMatcherType; + static const char *kMatchPrefix; +}; + +class RegExDecl : public Decl +{ +public: + RegExDecl(RegEx *regex); + + void Prepare(); + void GenForwardDeclaration(Output *out_h); + void GenCode(Output *out_h, Output *out_cc); + +private: + RegEx *regex_; +}; + +#endif // pac_regex_h diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll new file mode 100644 index 0000000000..ec435ea4ea --- /dev/null +++ b/tools/binpac/src/pac_scan.ll @@ -0,0 +1,356 @@ +%{ +// $Id: pac_scan.ll 3361 2006-07-06 18:06:49Z rpang $ + +#include "pac_action.h" +#include "pac_array.h" +#include "pac_attr.h" +#include "pac_case.h" +#include "pac_common.h" +#include "pac_conn.h" +#include "pac_dataptr.h" +#include "pac_dataunit.h" +#include "pac_dbg.h" +#include "pac_decl.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_flow.h" +#include "pac_id.h" +#include "pac_number.h" +#include "pac_output.h" +#include "pac_param.h" +#include "pac_parse.h" +#include "pac_record.h" +#include "pac_type.h" +#include "pac_utils.h" + +int line_number = 1; + +int begin_pac_primitive(int tok); +int end_pac_primitive(); + +int string_token(int tok) + { + yylval.str = copy_string(yytext); + return tok; + } + +int char_token(int tok) + { + yylval.val = yytext[0]; + return tok; + } + +void include_file(const char *filename); + +%} + +/* EC -- embedded code state */ +/* PP -- PAC primitive state */ +/* INCL -- @include line */ + +%s EC INCL PP RE + +WS [ \t]+ +ID [A-Za-z_][A-Za-z_0-9]* +D [0-9]+ +HEX [0-9a-fA-F]+ +FILE [A-Za-z._0-9\-]+ +ESCSEQ (\\([^\n]|[0-7]{3}|x[[:xdigit:]]{2})) + +%option nounput + +%% + +"%include" { + BEGIN(INCL); + } + +{WS} /* skip whitespace */ + +{FILE} { + BEGIN(INITIAL); + include_file(yytext); + } + +"%extern{" { + BEGIN(EC); + return TOK_LPB_EXTERN; + } +"%header{" { + BEGIN(EC); + return TOK_LPB_HEADER; + } +"%code{" { + BEGIN(EC); + return TOK_LPB_CODE; + } +"%init{" { + BEGIN(EC); + return TOK_LPB_INIT; + } +"%cleanup{" { + BEGIN(EC); + return TOK_LPB_CLEANUP; + } +"%member{" { + BEGIN(EC); + return TOK_LPB_MEMBER; + } +"%eof{" { + BEGIN(EC); + return TOK_LPB_EOF; + } +"%{" { + BEGIN(EC); + return TOK_LPB; + } +"%}" { + BEGIN(INITIAL); + return TOK_RPB; + } + +"${" return begin_pac_primitive(TOK_PAC_VAL); +"$set{" return begin_pac_primitive(TOK_PAC_SET); +"$type{" return begin_pac_primitive(TOK_PAC_TYPE); +"$typeof{" return begin_pac_primitive(TOK_PAC_TYPEOF); +"$const_def{" return begin_pac_primitive(TOK_PAC_CONST_DEF); + +"//".* return string_token(TOK_EMBEDDED_STRING); +. return char_token(TOK_EMBEDDED_ATOM); +\n { ++line_number; return char_token(TOK_EMBEDDED_ATOM); } + +"}" return end_pac_primitive(); + +\n ++line_number; +#.* /* eat comments */ +{WS} /* eat whitespace */ + +"RE/" { + BEGIN(RE); + return TOK_BEGIN_RE; + } + +([^/\\\n]|{ESCSEQ})+ return string_token(TOK_REGEX); + +"/" { + BEGIN(INITIAL); + return TOK_END_RE; + } + +[\\\n] return yytext[0]; + +analyzer return TOK_ANALYZER; +enum return TOK_ENUM; +extern return TOK_EXTERN; +flow return TOK_FLOW; +function return TOK_FUNCTION; +let return TOK_LET; +refine return TOK_REFINE; +type return TOK_TYPE; + +align return TOK_ALIGN; +case return TOK_CASE; +casefunc return TOK_CASEFUNC; +casetype return TOK_CASETYPE; +connection return TOK_CONNECTION; +datagram { + yylval.val = AnalyzerDataUnit::DATAGRAM; + return TOK_DATAUNIT; + } +default return TOK_DEFAULT; +downflow { + yylval.val = AnalyzerFlow::DOWN; + return TOK_FLOWDIR; + } +flowunit { + yylval.val = AnalyzerDataUnit::FLOWUNIT; + return TOK_DATAUNIT; + } +of return TOK_OF; +offsetof return TOK_OFFSETOF; +padding return TOK_PADDING; +record return TOK_RECORD; +sizeof return TOK_SIZEOF; +to return TOK_TO; +typeattr return TOK_TYPEATTR; +upflow { + yylval.val = AnalyzerFlow::UP; + return TOK_FLOWDIR; + } +withcontext return TOK_WITHCONTEXT; +withinput return TOK_WITHINPUT; + +&also return TOK_ATTR_ALSO; +&byteorder return TOK_ATTR_BYTEORDER; +&check return TOK_ATTR_CHECK; +&chunked return TOK_ATTR_CHUNKED; +&exportsourcedata return TOK_ATTR_EXPORTSOURCEDATA; +&if return TOK_ATTR_IF; +&length return TOK_ATTR_LENGTH; +&let return TOK_ATTR_LET; +&linebreaker return TOK_ATTR_LINEBREAKER; +&oneline return TOK_ATTR_ONELINE; +&refcount return TOK_ATTR_REFCOUNT; +&requires return TOK_ATTR_REQUIRES; +&restofdata return TOK_ATTR_RESTOFDATA; +&restofflow return TOK_ATTR_RESTOFFLOW; +&transient return TOK_ATTR_TRANSIENT; +&until return TOK_ATTR_UNTIL; + +"0x"{HEX} { + int n; + sscanf(yytext + 2, "%x", &n); + yylval.num = new Number(yytext, n); + return TOK_NUMBER; + } + +{D} { + int n; + sscanf(yytext, "%d", &n); + yylval.num = new Number(yytext, n); + return TOK_NUMBER; + } + +{ID} { + yylval.id = new ID(yytext); + return TOK_ID; + } + +"$"{ID} { + yylval.id = new ID(yytext); + return TOK_ID; + } + +\"([^\\\n\"]|{ESCSEQ})*\" return string_token(TOK_STRING); + +"==" return TOK_EQUAL; +"!=" return TOK_NEQ; +">=" return TOK_GE; +"<=" return TOK_LE; +"<<" return TOK_LSHIFT; +">>" return TOK_RSHIFT; +"&&" return TOK_AND; +"||" return TOK_OR; +"+=" return TOK_PLUSEQ; +"->" return TOK_RIGHTARROW; + +[\.!%*/+\-&|\^,:;<=>?()\[\]{}~] return yytext[0]; + +%% + +void begin_RE() + { + BEGIN(RE); + } + +void end_RE() + { + BEGIN(INITIAL); + } + +// The DECL state is deprecated +void begin_decl() + { + // BEGIN(DECL); + } + +void end_decl() + { + // BEGIN(INITIAL); + } + +int begin_pac_primitive(int tok) + { + BEGIN(PP); + return tok; + } + +int end_pac_primitive() + { + BEGIN(EC); + return TOK_END_PAC; + } + +const int MAX_INCLUDE_DEPTH = 100; + +struct IncludeState { + YY_BUFFER_STATE yystate; + string input_filename; + int line_number; +}; + +IncludeState include_stack[MAX_INCLUDE_DEPTH]; +int include_stack_ptr = 0; + +void switch_to_file(FILE *fp) + { + yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + } + +void switch_to_file(const char *filename) + { + if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) + { + fprintf( stderr, "Includes nested too deeply" ); + exit( 1 ); + } + + IncludeState state = + { YY_CURRENT_BUFFER, input_filename, line_number }; + include_stack[include_stack_ptr++] = state; + + FILE *fp = fopen(filename, "r"); + + if ( ! fp ) + { + fprintf(stderr, "%s:%d: error: cannot include file \"%s\"\n", + input_filename.c_str(), line_number,filename); + --include_stack_ptr; + return; + } + + yyin = fp; + input_filename = string(filename); + line_number = 1; + switch_to_file(yyin); + fprintf(stderr, "switching to file %s\n", input_filename.c_str()); + } + +void include_file(const char *filename) + { + ASSERT(filename); + + string full_filename; + if ( filename[0] == '/' || filename[0] == '.' ) + full_filename = filename; + else + { + int i; + for ( i = 0; i < (int) FLAGS_include_directories.size(); ++i ) + { + full_filename = FLAGS_include_directories[i] + filename; + DEBUG_MSG("Try include file: \"%s\"\n", + full_filename.c_str()); + if ( access(full_filename.c_str(), R_OK) == 0 ) + break; + } + if ( i >= (int) FLAGS_include_directories.size() ) + full_filename = filename; + } + + switch_to_file(full_filename.c_str()); + } + +int yywrap() + { + yy_delete_buffer(YY_CURRENT_BUFFER); + --include_stack_ptr; + if ( include_stack_ptr < 0 ) + return 1; + + IncludeState state = include_stack[include_stack_ptr]; + yy_switch_to_buffer(state.yystate); + input_filename = state.input_filename; + line_number = state.line_number; + return 0; + } diff --git a/tools/binpac/src/pac_state.cc b/tools/binpac/src/pac_state.cc new file mode 100644 index 0000000000..83ee974391 --- /dev/null +++ b/tools/binpac/src/pac_state.cc @@ -0,0 +1,36 @@ +#include "pac_id.h" +#include "pac_output.h" +#include "pac_type.h" + +#include "pac_state.h" + +void StateVar::GenDecl(Output *out_h, Env *env) + { + out_h->println("%s %s;", + type_->DataTypeStr().c_str(), + env->LValue(id_)); + } + +void StateVar::GenAccessFunction(Output *out_h, Env *env) + { + out_h->println("%s %s const { return %s; }", + type_->DataTypeConstRefStr().c_str(), + env->RValue(id_), + env->LValue(id_)); + } + +void StateVar::GenSetFunction(Output *out_h, Env *env) + { + out_h->println("void %s(%s x) { %s = x; }", + set_function(id_).c_str(), + type_->DataTypeConstRefStr().c_str(), + env->LValue(id_)); + } + +void StateVar::GenInitCode(Output *out_cc, Env *env) + { + } + +void StateVar::GenCleanUpCode(Output *out_cc, Env *env) + { + } diff --git a/tools/binpac/src/pac_state.h b/tools/binpac/src/pac_state.h new file mode 100644 index 0000000000..82bb580f47 --- /dev/null +++ b/tools/binpac/src/pac_state.h @@ -0,0 +1,28 @@ +#ifndef pac_state_h +#define pac_state_h + +// Classes representing analyzer states. + +#include "pac_common.h" + +class StateVar +{ +public: + StateVar(ID *id, Type *type) + : id_(id), type_(type) {} + + const ID *id() const { return id_; } + Type *type() const { return type_; } + + void GenDecl(Output *out_h, Env *env); + void GenAccessFunction(Output *out_h, Env *env); + void GenSetFunction(Output *out_h, Env *env); + void GenInitCode(Output *out_cc, Env *env); + void GenCleanUpCode(Output *out_cc, Env *env); + +private: + ID *id_; + Type *type_; +}; + +#endif // pac_state_h diff --git a/tools/binpac/src/pac_strtype.cc b/tools/binpac/src/pac_strtype.cc new file mode 100644 index 0000000000..48e1eb5ad0 --- /dev/null +++ b/tools/binpac/src/pac_strtype.cc @@ -0,0 +1,425 @@ +#include "pac_attr.h" +#include "pac_btype.h" +#include "pac_cstr.h" +#include "pac_dataptr.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_regex.h" +#include "pac_strtype.h" +#include "pac_varfield.h" + +const char *StringType::kStringTypeName = "bytestring"; +const char *StringType::kConstStringTypeName = "const_bytestring"; + +StringType::StringType(StringTypeEnum anystr) + : Type(STRING), type_(ANYSTR), str_(0), regex_(0) + { + ASSERT(anystr == ANYSTR); + init(); + } + +StringType::StringType(ConstString *str) + : Type(STRING), type_(CSTR), str_(str), regex_(0) + { + init(); + } + +StringType::StringType(RegEx *regex) + : Type(STRING), type_(REGEX), str_(0), regex_(regex) + { + ASSERT(regex_); + init(); + } + +void StringType::init() + { + string_length_var_field_ = 0; + elem_datatype_ = new BuiltInType(BuiltInType::UINT8); + } + +StringType::~StringType() + { + // TODO: Unref for Objects + // Question: why Unref? + // + // Unref(str_); + // Unref(regex_); + + delete string_length_var_field_; + delete elem_datatype_; + } + +Type *StringType::DoClone() const + { + StringType *clone; + + switch ( type_ ) + { + case ANYSTR: + clone = new StringType(ANYSTR); + break; + case CSTR: + clone = new StringType(str_); + break; + case REGEX: + clone = new StringType(regex_); + break; + default: + ASSERT(0); + return 0; + } + + return clone; + } + +bool StringType::DefineValueVar() const + { + return true; + } + +string StringType::DataTypeStr() const + { + return strfmt("%s", + persistent() ? kStringTypeName : kConstStringTypeName); + } + +Type *StringType::ElementDataType() const + { + return elem_datatype_; + } + +void StringType::ProcessAttr(Attr *a) + { + Type::ProcessAttr(a); + + switch ( a->type() ) + { + case ATTR_CHUNKED: + { + if ( type_ != ANYSTR ) + { + throw Exception(a, + "&chunked can be applied" + " to only type bytestring"); + } + attr_chunked_ = true; + SetBoundaryChecked(); + } + break; + + case ATTR_RESTOFDATA: + { + if ( type_ != ANYSTR ) + { + throw Exception(a, + "&restofdata can be applied" + " to only type bytestring"); + } + attr_restofdata_ = true; + // As the string automatically extends to the end of + // data, we do not have to check boundary. + SetBoundaryChecked(); + } + break; + + case ATTR_RESTOFFLOW: + { + if ( type_ != ANYSTR ) + { + throw Exception(a, + "&restofflow can be applied" + " to only type bytestring"); + } + attr_restofflow_ = true; + // As the string automatically extends to the end of + // flow, we do not have to check boundary. + SetBoundaryChecked(); + } + break; + + default: + break; + } + } + +void StringType::Prepare(Env* env, int flags) + { + if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 ) + { + ID *string_length_var = new ID(fmt("%s_string_length", + value_var() ? value_var()->Name() : "val")); + string_length_var_field_ = new TempVarField( + string_length_var, extern_type_int->Clone()); + string_length_var_field_->Prepare(env); + } + Type::Prepare(env, flags); + } + +void StringType::GenPubDecls(Output* out_h, Env* env) + { + Type::GenPubDecls(out_h, env); + } + +void StringType::GenPrivDecls(Output* out_h, Env* env) + { + Type::GenPrivDecls(out_h, env); + } + +void StringType::GenInitCode(Output* out_cc, Env* env) + { + Type::GenInitCode(out_cc, env); + } + +void StringType::GenCleanUpCode(Output* out_cc, Env* env) + { + Type::GenCleanUpCode(out_cc, env); + if ( persistent() ) + out_cc->println("%s.free();", env->LValue(value_var())); + } + +void StringType::DoMarkIncrementalInput() + { + if ( attr_restofflow_ ) + { + // Do nothing + ASSERT(type_ == ANYSTR); + } + else + { + Type::DoMarkIncrementalInput(); + } + } + +int StringType::StaticSize(Env* env) const + { + switch ( type_ ) + { + case CSTR: + // Use length of the unescaped string + return str_->unescaped().length(); + case REGEX: + // TODO: static size for a regular expression? + case ANYSTR: + return -1; + + default: + ASSERT(0); + return -1; + } + } + +const ID *StringType::string_length_var() const + { + return string_length_var_field_ ? string_length_var_field_->id() : 0; + } + +void StringType::GenDynamicSize(Output* out_cc, Env* env, + const DataPtr& data) + { + ASSERT(StaticSize(env) < 0); + DEBUG_MSG("Generating dynamic size for string `%s'\n", + value_var()->Name()); + + if ( env->Evaluated(string_length_var()) ) + return; + + string_length_var_field_->GenTempDecls(out_cc, env); + + switch ( type_ ) + { + case ANYSTR: + GenDynamicSizeAnyStr(out_cc, env, data); + break; + case CSTR: + ASSERT(0); + break; + case REGEX: + // TODO: static size for a regular expression? + GenDynamicSizeRegEx(out_cc, env, data); + break; + } + + if ( ! incremental_input() && AddSizeVar(out_cc, env) ) + { + out_cc->println("%s = %s;", + env->LValue(size_var()), + env->RValue(string_length_var())); + env->SetEvaluated(size_var()); + } + } + +string StringType::GenStringSize(Output* out_cc, Env* env, + const DataPtr& data) + { + int static_size = StaticSize(env); + if ( static_size >= 0 ) + return strfmt("%d", static_size); + GenDynamicSize(out_cc, env, data); + return env->RValue(string_length_var()); + } + +void StringType::DoGenParseCode(Output* out_cc, Env* env, + const DataPtr& data, int flags) + { + string str_size = GenStringSize(out_cc, env, data); + + // Generate additional checking + switch ( type_ ) + { + case CSTR: + GenCheckingCStr(out_cc, env, data, str_size); + break; + case REGEX: + case ANYSTR: + break; + } + + if ( ! anonymous_value_var() ) + { + // Set the value variable + out_cc->println("// check for negative sizes"); + out_cc->println("if ( %s < 0 )", + str_size.c_str()); + out_cc->println("throw ExceptionInvalidStringLength(\"%s\", %s);", + Location(), str_size.c_str()); + out_cc->println("%s.init(%s, %s);", + env->LValue(value_var()), + data.ptr_expr(), + str_size.c_str()); + } + + if ( parsing_complete_var() ) + { + out_cc->println("%s = true;", + env->LValue(parsing_complete_var())); + } + } + +void StringType::GenStringMismatch(Output* out_cc, Env* env, + const DataPtr& data, const char *pattern) + { + out_cc->println("throw ExceptionStringMismatch(\"%s\", %s, %s);", + Location(), + pattern, + fmt("string((const char *) (%s), (const char *) %s).c_str()", + data.ptr_expr(), + env->RValue(end_of_data))); + } + +void StringType::GenCheckingCStr(Output* out_cc, Env* env, + const DataPtr& data, const string &str_size) + { + // TODO: extend it for dynamic strings + ASSERT(type_ == CSTR); + + GenBoundaryCheck(out_cc, env, data); + + string str_val = str_->str(); + + // Compare the string and report error on mismatch + out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", + data.ptr_expr(), + str_val.c_str(), + str_size.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + GenStringMismatch(out_cc, env, data, str_val.c_str()); + out_cc->println("}"); + out_cc->dec_indent(); + } + +void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, + const DataPtr& data) + { + // string_length_var = + // matcher.match_prefix( + // begin, + // end); + + out_cc->println("%s = ", + env->LValue(string_length_var())); + out_cc->inc_indent(); + + out_cc->println("%s.%s(", + env->RValue(regex_->matcher_id()), + RegEx::kMatchPrefix); + + out_cc->inc_indent(); + out_cc->println("%s,", + data.ptr_expr()); + out_cc->println("%s - %s);", + env->RValue(end_of_data), + data.ptr_expr()); + + out_cc->dec_indent(); + out_cc->dec_indent(); + + env->SetEvaluated(string_length_var()); + + out_cc->println("if ( %s < 0 )", + env->RValue(string_length_var())); + out_cc->inc_indent(); + out_cc->println("{"); + GenStringMismatch(out_cc, env, data, + fmt("\"%s\"", regex_->str().c_str())); + out_cc->println("}"); + out_cc->dec_indent(); + } + +void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, + const DataPtr& data) + { + ASSERT(type_ == ANYSTR); + + if ( attr_restofdata_ || attr_oneline_ ) + { + out_cc->println("%s = (%s) - (%s);", + env->LValue(string_length_var()), + env->RValue(end_of_data), + data.ptr_expr()); + } + else if ( attr_restofflow_ ) + { + out_cc->println("%s = (%s) - (%s);", + env->LValue(string_length_var()), + env->RValue(end_of_data), + data.ptr_expr()); + } + else if ( attr_length_expr_ ) + { + out_cc->println("%s = %s;", + env->LValue(string_length_var()), + attr_length_expr_->EvalExpr(out_cc, env)); + } + else + { + throw Exception(this, + "cannot determine length of bytestring"); + } + + env->SetEvaluated(string_length_var()); + } + +bool StringType::DoTraverse(DataDepVisitor *visitor) + { + if ( ! Type::DoTraverse(visitor) ) + return false; + + switch ( type_ ) + { + case ANYSTR: + case CSTR: + case REGEX: + break; + } + + return true; + } + +void StringType::static_init() + { + Type::AddPredefinedType("bytestring", new StringType(ANYSTR)); + } diff --git a/tools/binpac/src/pac_strtype.h b/tools/binpac/src/pac_strtype.h new file mode 100644 index 0000000000..55b35e54ab --- /dev/null +++ b/tools/binpac/src/pac_strtype.h @@ -0,0 +1,82 @@ +#ifndef pac_strtype_h +#define pac_strtype_h + +#include "pac_type.h" + +// TODO: question: shall we merge it with ArrayType? +class StringType : public Type +{ +public: + enum StringTypeEnum { CSTR, REGEX, ANYSTR }; + + explicit StringType(StringTypeEnum anystr); + explicit StringType(ConstString *str); + explicit StringType(RegEx *regex); + ~StringType(); + + bool DefineValueVar() const; + string DataTypeStr() const; + string DefaultValue() const { return "0"; } + Type *ElementDataType() const; + + void Prepare(Env* env, int flags); + + void GenPubDecls(Output* out, Env* env); + void GenPrivDecls(Output* out, Env* env); + + void GenInitCode(Output* out, Env* env); + void GenCleanUpCode(Output* out, Env* env); + + void DoMarkIncrementalInput(); + + int StaticSize(Env* env) const; + + bool IsPointerType() const { return false; } + + void ProcessAttr(Attr *a); + +protected: + void init(); + + // Generate computation of size of the string and returns the string + // representing a constant integer or name of the length variable. + string GenStringSize(Output* out_cc, Env* env, const DataPtr& data); + + // Generate a string mismatch exception + void GenStringMismatch(Output* out_cc, Env* env, + const DataPtr& data, const char *pattern); + + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); + + void GenCheckingCStr(Output* out, Env* env, + const DataPtr& data, const string &str_size); + + void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + void GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data); + void GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data); + + Type *DoClone() const; + + // TODO: insensitive towards byte order till we support unicode + bool ByteOrderSensitive() const { return false; } + +protected: + bool DoTraverse(DataDepVisitor *visitor); + +private: + const ID *string_length_var() const; + + StringTypeEnum type_; + ConstString *str_; + RegEx *regex_; + Field *string_length_var_field_; + Type *elem_datatype_; + +public: + static void static_init(); +private: + static const char *kStringTypeName; + static const char *kConstStringTypeName; +}; + +#endif // pac_strtype_h diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc new file mode 100644 index 0000000000..a30295aa0e --- /dev/null +++ b/tools/binpac/src/pac_type.cc @@ -0,0 +1,1137 @@ +#include "pac_action.h" +#include "pac_array.h" +#include "pac_attr.h" +#include "pac_btype.h" +#include "pac_context.h" +#include "pac_dataptr.h" +#include "pac_decl.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_field.h" +#include "pac_id.h" +#include "pac_let.h" +#include "pac_output.h" +#include "pac_paramtype.h" +#include "pac_strtype.h" +#include "pac_type.h" +#include "pac_utils.h" +#include "pac_varfield.h" +#include "pac_withinput.h" + + +Type::type_map_t Type::type_map_; + +Type::Type(TypeType tot) + : DataDepElement(DataDepElement::TYPE), tot_(tot) + { + type_decl_ = 0; + type_decl_id_ = current_decl_id; + declared_as_type_ = false; + env_ = 0; + value_var_ = default_value_var; + ASSERT(value_var_); + value_var_type_ = MEMBER_VAR; + anonymous_value_var_ = false; + size_var_field_ = 0; + size_expr_ = 0; + boundary_checked_ = false; + parsing_complete_var_field_ = 0; + parsing_state_var_field_ = 0; + buffering_state_var_field_ = 0; + has_value_field_ = 0; + + array_until_input_ = 0; + + incremental_input_ = false; + buffer_input_ = false; + incremental_parsing_ = false; + + fields_ = new FieldList(); + + attrs_ = new AttrList(); + attr_byteorder_expr_ = 0; + attr_checks_ = new ExprList(); + attr_chunked_ = false; + attr_exportsourcedata_ = false; + attr_if_expr_ = 0; + attr_length_expr_ = 0; + attr_letfields_ = 0; + attr_multiline_end_ = 0; + attr_oneline_ = false; + attr_refcount_ = false; + attr_requires_ = 0; + attr_restofdata_ = false; + attr_restofflow_ = false; + attr_transient_ = false; + } + +Type::~Type() + { + delete size_var_field_; + delete parsing_complete_var_field_; + delete parsing_state_var_field_; + delete buffering_state_var_field_; + delete has_value_field_; + delete [] size_expr_; + delete_list(FieldList, fields_); + delete attrs_; + delete attr_byteorder_expr_; + delete attr_if_expr_; + delete attr_length_expr_; + delete_list(ExprList, attr_checks_); + delete attr_requires_; + } + +Type *Type::Clone() const + { + Type *clone = DoClone(); + if ( clone ) + { + foreach(i, FieldList, fields_) + { + Field *f = *i; + clone->AddField(f); + } + + foreach(i, AttrList, attrs_) + { + Attr *a = *i; + clone->ProcessAttr(a); + } + } + return clone; + } + +string Type::EvalMember(const ID *member_id) const + { + ASSERT(0); + return "@@@"; + } + +string Type::EvalElement(const string &array, const string &index) const + { + return strfmt("%s[%s]", array.c_str(), index.c_str()); + } + +const ID *Type::decl_id() const + { + return type_decl_id_; + } + +void Type::set_type_decl(const TypeDecl *decl, bool declared_as_type) + { + type_decl_ = decl; + type_decl_id_ = decl->id(); + declared_as_type_ = declared_as_type; + } + +void Type::set_value_var(const ID* arg_id, int arg_id_type) + { + value_var_ = arg_id; + value_var_type_ = arg_id_type; + + if ( value_var_ ) + anonymous_value_var_ = value_var_->is_anonymous(); + } + +const ID *Type::size_var() const + { + return size_var_field_ ? size_var_field_->id() : 0; + } + +void Type::AddField(Field *f) + { + ASSERT(f); + fields_->push_back(f); + } + +void Type::ProcessAttr(Attr* a) + { + switch ( a->type() ) + { + case ATTR_BYTEORDER: + attr_byteorder_expr_ = a->expr(); + break; + + case ATTR_CHECK: + attr_checks_->push_back(a->expr()); + break; + + case ATTR_EXPORTSOURCEDATA: + attr_exportsourcedata_ = true; + break; + + case ATTR_LENGTH: + attr_length_expr_ = a->expr(); + break; + + case ATTR_IF: + attr_if_expr_ = a->expr(); + break; + + case ATTR_LET: + { + LetAttr *letattr = static_cast(a); + if ( ! attr_letfields_ ) + attr_letfields_ = letattr->letfields(); + else + { + // Append to attr_letfields_ + attr_letfields_->insert( + attr_letfields_->end(), + letattr->letfields()->begin(), + letattr->letfields()->end()); + } + } + break; + + case ATTR_LINEBREAKER: + ASSERT(0); + break; + + case ATTR_MULTILINE: + attr_multiline_end_ = a->expr(); + break; + + case ATTR_ONELINE: + attr_oneline_ = true; + break; + + case ATTR_REFCOUNT: + attr_refcount_ = true; + break; + + case ATTR_REQUIRES: + attr_requires_ = a->expr(); + break; + + case ATTR_TRANSIENT: + attr_transient_ = true; + break; + + case ATTR_CHUNKED: + case ATTR_UNTIL: + case ATTR_RESTOFDATA: + case ATTR_RESTOFFLOW: + // Ignore + // ... these are processed by { + // {ArrayType, StringType}::ProcessAttr + break; + } + + attrs_->push_back(a); + } + +string Type::EvalByteOrder(Output *out_cc, Env *env) const + { + // If &byteorder is specified for a field, rather + // than a type declaration, we do not add a byteorder variable + // to the class, but instead evaluate it directly. + if ( attr_byteorder_expr() && ! declared_as_type() ) + return attr_byteorder_expr()->EvalExpr(out_cc, global_env()); + env->Evaluate(out_cc, byteorder_id); + return env->RValue(byteorder_id); + } + +void Type::Prepare(Env* env, int flags) + { + env_ = env; + ASSERT(env_); + + // The name of the value variable + if ( value_var() ) + { + data_id_str_ = strfmt("%s:%s", + decl_id()->Name(), value_var()->Name()); + } + else + { + data_id_str_ = strfmt("%s", decl_id()->Name()); + } + + if ( value_var() ) + { + env_->AddID(value_var(), + static_cast(value_var_type_), + this); + lvalue_ = strfmt("%s", env_->LValue(value_var())); + } + + foreach(i, FieldList, attr_letfields_) + { + AddField(*i); + } + + if ( attr_exportsourcedata_ ) + { + ASSERT(flags & TO_BE_PARSED); + AddField(new PubVarField(sourcedata_id->clone(), + extern_type_const_bytestring->Clone())); + } + + // An optional field + if ( attr_if_expr() ) + { + ASSERT(value_var()); + ID *has_value_id = new ID(fmt("has_%s", value_var()->Name())); + has_value_field_ = new LetField(has_value_id, + extern_type_bool->Clone(), + attr_if_expr()); + AddField(has_value_field_); + } + + if ( incremental_input() ) + { + ASSERT(flags & TO_BE_PARSED); + ID *parsing_complete_var = + new ID(fmt("%s_parsing_complete", + value_var() ? value_var()->Name() : "val")); + DEBUG_MSG("Adding parsing complete var: %s\n", + parsing_complete_var->Name()); + parsing_complete_var_field_ = new TempVarField( + parsing_complete_var, extern_type_bool->Clone()); + parsing_complete_var_field_->Prepare(env); + + if ( NeedsBufferingStateVar() && + ! env->GetDataType(buffering_state_id) ) + { + buffering_state_var_field_ = new PrivVarField( + buffering_state_id->clone(), + extern_type_int->Clone()); + AddField(buffering_state_var_field_); + } + + if ( incremental_parsing() && tot_ == RECORD ) + { + ASSERT(! parsing_state_var_field_); + parsing_state_var_field_ = new PrivVarField( + parsing_state_id->clone(), + extern_type_int->Clone()); + AddField(parsing_state_var_field_); + } + } + + foreach (i, FieldList, fields_) + { + Field *f = *i; + f->Prepare(env); + } + } + +void Type::GenPubDecls(Output* out_h, Env* env) + { + if ( DefineValueVar() ) + { + if ( attr_if_expr_ ) + out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }", + DataTypeConstRefStr().c_str(), + env->RValue(value_var()), + env->RValue(has_value_var()), lvalue()); + else + out_h->println("%s %s const { return %s; }", + DataTypeConstRefStr().c_str(), + env->RValue(value_var()), lvalue()); + } + + foreach (i, FieldList, fields_) + { + Field *f = *i; + f->GenPubDecls(out_h, env); + } + } + +void Type::GenPrivDecls(Output* out_h, Env* env) + { + if ( DefineValueVar() ) + { + out_h->println("%s %s;", + DataTypeStr().c_str(), + env->LValue(value_var())); + } + + foreach (i, FieldList, fields_) + { + Field *f = *i; + f->GenPrivDecls(out_h, env); + } + } + +void Type::GenInitCode(Output* out_cc, Env* env) + { + foreach (i, FieldList, fields_) + { + Field *f = *i; + f->GenInitCode(out_cc, env); + } + + if ( parsing_state_var_field_ ) + { + out_cc->println("%s = 0;", + env->LValue(parsing_state_var_field_->id())); + } + + if ( buffering_state_var_field_ ) + { + out_cc->println("%s = 0;", + env->LValue(buffering_state_var_field_->id())); + } + } + +void Type::GenCleanUpCode(Output* out_cc, Env* env) + { + foreach (i, FieldList, fields_) + { + Field *f = *i; + if ( f->tof() != CASE_FIELD ) + f->GenCleanUpCode(out_cc, env); + } + } + +void Type::GenBufferConfiguration(Output *out_cc, Env *env) + { + ASSERT(buffer_input()); + + string frame_buffer_arg; + + switch ( buffer_mode() ) + { + case BUFFER_NOTHING: + break; + + case BUFFER_BY_LENGTH: + if ( ! NeedsBufferingStateVar() ) + break; + + if ( buffering_state_var_field_ ) + { + out_cc->println("if ( %s == 0 )", + env->RValue(buffering_state_id)); + out_cc->inc_indent(); + out_cc->println("{"); + } + + if ( attr_length_expr_ ) + { + // frame_buffer_arg = attr_length_expr_->EvalExpr(out_cc, env); + frame_buffer_arg = strfmt("%d", InitialBufferLength()); + } + else if ( attr_restofflow_ ) + { + ASSERT(attr_chunked()); + frame_buffer_arg = "-1"; + } + else + { + ASSERT(0); + } + + out_cc->println("%s->NewFrame(%s, %s);", + env->LValue(flow_buffer_id), + frame_buffer_arg.c_str(), + attr_chunked() ? "true" : "false"); + + if ( buffering_state_var_field_ ) + { + out_cc->println("%s = 1;", + env->LValue(buffering_state_id)); + out_cc->println("}"); + out_cc->dec_indent(); + } + break; + + case BUFFER_BY_LINE: + out_cc->println("if ( %s == 0 )", + env->RValue(buffering_state_id)); + out_cc->inc_indent(); + out_cc->println("{"); + + out_cc->println("%s->NewLine();", + env->LValue(flow_buffer_id)); + + out_cc->println("%s = 1;", + env->LValue(buffering_state_id)); + out_cc->println("}"); + out_cc->dec_indent(); + break; + + default: + ASSERT(0); + break; + } + } + +void Type::GenPreParsing(Output *out_cc, Env *env) + { + if ( incremental_input() && IsPointerType() ) + { + out_cc->println("if ( ! %s )", env->LValue(value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + GenNewInstance(out_cc, env); + out_cc->println("}"); + out_cc->dec_indent(); + } + else + GenNewInstance(out_cc, env); + + if ( buffer_input() ) + { + GenBufferConfiguration(out_cc, env); + } + } + +// Wrappers around DoGenParseCode, which does the real job +void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) + { + if ( value_var() && env->Evaluated(value_var()) ) + return; + + DEBUG_MSG("GenParseCode for %s\n", data_id_str_.c_str()); + + if ( attr_if_expr() ) + { + ASSERT(has_value_var()); + ASSERT(env->Evaluated(has_value_var())); + } + + if ( value_var() && anonymous_value_var() ) + { + GenPrivDecls(out_cc, env); + GenInitCode(out_cc, env); + } + + if ( incremental_input() ) + { + parsing_complete_var_field_->GenTempDecls(out_cc, env); + + out_cc->println("%s = false;", + env->LValue(parsing_complete_var())); + env->SetEvaluated(parsing_complete_var()); + + if ( buffer_mode() == BUFFER_NOTHING ) + { + out_cc->println("%s = true;", + env->LValue(parsing_complete_var())); + } + else if ( buffer_input() ) + { + if ( declared_as_type() ) + GenParseBuffer(out_cc, env, flags); + else + GenBufferingLoop(out_cc, env, flags); + } + else + GenParseCode2(out_cc, env, data, flags); + } + else + { + if ( attr_length_expr_) + { + EvalLengthExpr(out_cc, env); + + GenBoundaryCheck(out_cc, env, data); + + out_cc->println("{"); + out_cc->println("// Setting %s with &length", + env->RValue(end_of_data)); + out_cc->println("%s %s = %s + %s;", + extern_type_const_byteptr->DataTypeStr().c_str(), + env->LValue(end_of_data), + data.ptr_expr(), + EvalLengthExpr(out_cc, env).c_str()); + + GenParseCode2(out_cc, env, data, flags); + + out_cc->println("}"); + } + else + { + GenParseCode2(out_cc, env, data, flags); + } + } + } + +void Type::GenBufferingLoop(Output* out_cc, Env* env, int flags) + { + out_cc->println("while ( ! %s && %s->ready() )", + env->LValue(parsing_complete_var()), + env->LValue(flow_buffer_id)); + + out_cc->inc_indent(); + out_cc->println("{"); + + Env buffer_env(env, this); + GenParseBuffer(out_cc, &buffer_env, flags); + + out_cc->println("}"); + out_cc->dec_indent(); + } + +void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) + { + ASSERT(incremental_input()); + + const ID *data_begin; + + if ( ! incremental_parsing() ) + { + env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); + env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); + + out_cc->println("%s %s = %s->begin();", + env->DataTypeStr(begin_of_data).c_str(), + env->LValue(begin_of_data), + env->RValue(flow_buffer_id)); + + out_cc->println("%s %s = %s->end();", + env->DataTypeStr(end_of_data).c_str(), + env->LValue(end_of_data), + env->RValue(flow_buffer_id)); + + env->SetEvaluated(begin_of_data); + env->SetEvaluated(end_of_data); + + data_begin = begin_of_data; + } + else + data_begin = 0; + + if ( array_until_input_ ) + { + if ( incremental_parsing() ) + { + throw Exception(this, + "cannot handle &until($input...) " + "for incrementally parsed type"); + } + array_until_input_->GenUntilInputCheck(out_cc, env); + } + + DataPtr data(env, data_begin, 0); + + if ( attr_length_expr() ) + { + ASSERT(buffer_mode() == BUFFER_BY_LENGTH); + out_cc->println("switch ( %s )", + env->LValue(buffering_state_id)); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("case 0:"); + out_cc->inc_indent(); + GenBufferConfiguration(out_cc, env); + out_cc->println("%s = 1;", env->LValue(buffering_state_id)); + out_cc->println("break;"); + out_cc->dec_indent(); + + out_cc->println("case 1:"); + out_cc->inc_indent(); + + out_cc->println("{"); + + out_cc->println("%s = 2;", env->LValue(buffering_state_id)); + + Env frame_length_env(env, this); + out_cc->println("%s->GrowFrame(%s);", + env->LValue(flow_buffer_id), + attr_length_expr_->EvalExpr(out_cc, &frame_length_env)); + out_cc->println("}"); + out_cc->println("break;"); + + out_cc->dec_indent(); + out_cc->println("case 2:"); + out_cc->inc_indent(); + + out_cc->println("BINPAC_ASSERT(%s->ready());", + env->RValue(flow_buffer_id)); + out_cc->println("if ( %s->ready() )", + env->RValue(flow_buffer_id)); + out_cc->inc_indent(); + out_cc->println("{"); + + Env parse_env(env, this); + GenParseCode2(out_cc, &parse_env, data, 0); + + out_cc->println("BINPAC_ASSERT(%s);", + parsing_complete(env).c_str()); + out_cc->println("%s = 0;", + env->LValue(buffering_state_id)); + out_cc->println("}"); + out_cc->dec_indent(); + + out_cc->println("break;"); + + out_cc->dec_indent(); + out_cc->println("default:"); + out_cc->inc_indent(); + + out_cc->println("BINPAC_ASSERT(%s <= 2);", + env->LValue(buffering_state_id)); + out_cc->println("break;"); + + out_cc->dec_indent(); + out_cc->println("}"); + out_cc->dec_indent(); + } + else if ( attr_restofflow_ ) + { + out_cc->println("BINPAC_ASSERT(%s->eof());", + env->RValue(flow_buffer_id)); + GenParseCode2(out_cc, env, data, 0); + } + else if ( buffer_mode() == BUFFER_BY_LINE ) + { + GenParseCode2(out_cc, env, data, 0); + out_cc->println("%s = 0;", env->LValue(buffering_state_id)); + } + else + GenParseCode2(out_cc, env, data, 0); + } + +void Type::GenParseCode2(Output* out_cc, Env* env, + const DataPtr& data, int flags) + { + DEBUG_MSG("GenParseCode2 for %s\n", data_id_str_.c_str()); + + if ( attr_exportsourcedata_ ) + { + if ( incremental_parsing() ) + { + throw Exception(this, + "cannot export raw data for incrementally parsed types"); + } + + out_cc->println("%s = const_bytestring(%s, %s);", + env->LValue(sourcedata_id), + data.ptr_expr(), + env->RValue(end_of_data)); + env->SetEvaluated(sourcedata_id); + + GenParseCode3(out_cc, env, data, flags); + + string datasize_str = DataSize(out_cc, env, data); + out_cc->println("%s.set_end(%s + %s);", + env->LValue(sourcedata_id), + data.ptr_expr(), + datasize_str.c_str()); + } + else + { + GenParseCode3(out_cc, env, data, flags); + } + } + +void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags) + { + if ( attr_requires_ ) + attr_requires_->EvalExpr(out_cc, env); + + foreach(i, FieldList, fields_) + { + Field *f = *i; + f->GenTempDecls(out_cc, env); + } + + DoGenParseCode(out_cc, env, data, flags); + + if ( incremental_input() ) + { + out_cc->println("if ( %s )", parsing_complete(env).c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + } + + out_cc->println("// Evaluate 'let' and 'withinput' fields"); + foreach(i, FieldList, fields_) + { + Field *f = *i; + if ( f->tof() == LET_FIELD ) + { + LetField *lf = static_cast(f); + lf->GenParseCode(out_cc, env); + } + else if ( f->tof() == WITHINPUT_FIELD ) + { + WithInputField *af = static_cast(f); + af->GenParseCode(out_cc, env); + } + } + + if ( value_var() && anonymous_value_var() ) + { + GenCleanUpCode(out_cc, env); + } + + if ( incremental_input() ) + { + out_cc->println("}"); + out_cc->dec_indent(); + } + + if ( value_var() ) + env->SetEvaluated(value_var()); + + if ( size_var() ) + ASSERT(env->Evaluated(size_var())); + } + +Type *Type::MemberDataType(const ID *member_id) const + { + DEBUG_MSG("MemberDataType: %s::%s\n", type_decl_id_->Name(), member_id->Name()); + ASSERT(env_); + env_->set_allow_undefined_id(true); + Type *t = env_->GetDataType(member_id); + env_->set_allow_undefined_id(false); + return t; + } + +Type *Type::ElementDataType() const + { + return 0; + } + +// Returns false if it is not necessary to add size_var +// (it is already added or the type has a fixed size). +bool Type::AddSizeVar(Output* out_cc, Env* env) + { + if ( size_var() ) + { + DEBUG_MSG("size var `%s' already added\n", size_var()->Name()); + ASSERT(env->Evaluated(size_var())); + return false; + } + + if ( StaticSize(env) >= 0 ) + return false; + + ASSERT(! incremental_input()); + + ID *size_var_id = new ID(fmt("%s__size", + value_var() ? value_var()->Name() : decl_id()->Name())); + + DEBUG_MSG("adding size var `%s' to env %p\n", size_var_id->Name(), env); + + size_var_field_ = new TempVarField( + size_var_id, extern_type_int->Clone()); + size_var_field_->Prepare(env); + size_var_field_->GenTempDecls(out_cc, env); + + return true; + } + +string Type::EvalLengthExpr(Output* out_cc, Env* env) + { + ASSERT(!incremental_input()); + ASSERT(attr_length_expr_); + int static_length; + if ( attr_length_expr_->ConstFold(env, &static_length) ) + return strfmt("%d", static_length); + // How do we make sure size_var is evaluated with attr_length_expr_? + if ( AddSizeVar(out_cc, env) ) + { + out_cc->println("%s = %s;", + env->LValue(size_var()), + attr_length_expr_->EvalExpr(out_cc, env)); + env->SetEvaluated(size_var()); + } + return env->RValue(size_var()); + } + +string Type::DataSize(Output* out_cc, Env* env, const DataPtr& data) + { + if ( attr_length_expr_ ) + return EvalLengthExpr(out_cc, env); + + int ss = StaticSize(env); + if ( ss >= 0 ) + { + return strfmt("%d", ss); + } + else + { + if ( ! size_var() || ! env->Evaluated(size_var()) ) + { + ASSERT(out_cc != 0); + GenDynamicSize(out_cc, env, data); + ASSERT(size_var()); + } + return env->RValue(size_var()); + } + } + +void Type::GenBoundaryCheck(Output* out_cc, Env* env, + const DataPtr& data) + { + if ( boundary_checked() ) + return; + + data.GenBoundaryCheck(out_cc, env, + DataSize(out_cc, env, data).c_str(), + data_id_str_.c_str()); + + SetBoundaryChecked(); + } + +bool Type::NeedsCleanUp() const + { + switch ( tot_ ) + { + case EMPTY: + case BUILTIN: + return false; + case ARRAY: + case PARAMETERIZED: + case STRING: + return true; + default: + ASSERT(0); + return true; + } + return true; + } + +bool Type::RequiresByteOrder() const + { + return ! attr_byteorder_expr() && ByteOrderSensitive(); + } + +bool Type::NeedsBufferingStateVar() const + { + if ( !incremental_input() ) + return false; + switch ( buffer_mode() ) + { + case BUFFER_NOTHING: + case NOT_BUFFERABLE: + return false; + case BUFFER_BY_LINE: + return true; + case BUFFER_BY_LENGTH: + return ( attr_length_expr_ || attr_restofflow_ ); + default: + ASSERT(0); + return false; + } + } + +bool Type::DoTraverse(DataDepVisitor *visitor) + { + foreach (i, FieldList, fields_) + { + if ( ! (*i)->Traverse(visitor) ) + return false; + } + + foreach(i, AttrList, attrs_) + { + if ( ! (*i)->Traverse(visitor) ) + return false; + } + + return true; + } + +bool Type::RequiresAnalyzerContext() + { + ASSERT(0); + + if ( buffer_input() ) + return true; + + foreach (i, FieldList, fields_) + { + Field *f = *i; + if ( f->RequiresAnalyzerContext() ) + return true; + } + + foreach(i, AttrList, attrs_) + if ( (*i)->RequiresAnalyzerContext() ) + return true; + + return false; + } + +bool Type::IsEmptyType() const + { + return ( StaticSize(global_env()) == 0 ); + } + +void Type::MarkIncrementalInput() + { + DEBUG_MSG("Handle incremental input for %s.%s\n", + decl_id()->Name(), + value_var() ? value_var()->Name() : "*"); + + incremental_input_ = true; + if ( Bufferable() ) + buffer_input_ = true; + else + { + incremental_parsing_ = true; + DoMarkIncrementalInput(); + } + } + +void Type::DoMarkIncrementalInput() + { + throw Exception(this, "cannot handle incremental input"); + } + +bool Type::BufferableByLength() const + { + // If the input is an "frame buffer" with specified length + return attr_length_expr_ || attr_restofflow_; + } + +bool Type::BufferableByLine() const + { + // If the input is an ASCII line; + return attr_oneline_; + } + +bool Type::Bufferable() const + { + // If the input is an ASCII line or an "frame buffer" + return IsEmptyType() || BufferableByLength() || BufferableByLine(); + } + +Type::BufferMode Type::buffer_mode() const + { + if ( IsEmptyType() ) + return BUFFER_NOTHING; + else if ( BufferableByLength() ) + return BUFFER_BY_LENGTH; + else if ( BufferableByLine() ) + return BUFFER_BY_LINE; + return NOT_BUFFERABLE; + } + +const ID *Type::parsing_complete_var() const + { + if ( parsing_complete_var_field_ ) + return parsing_complete_var_field_->id(); + else + return 0; + } + +string Type::parsing_complete(Env *env) const + { + ASSERT(parsing_complete_var()); + return env->RValue(parsing_complete_var()); + } + +const ID *Type::has_value_var() const + { + if ( has_value_field_ ) + return has_value_field_->id(); + else + return 0; + } + +int Type::InitialBufferLength() const + { + if ( ! attr_length_expr_ ) + return 0; + return attr_length_expr_->MinimalHeaderSize(env()); + } + +bool Type::CompatibleTypes(Type *type1, Type *type2) + { + // If we cannot deduce one of the data types, assume that + // they are compatible. + if ( ! type1 || ! type2 ) + return true; + + // We do not have enough information about extern types + if ( type1->tot() == EXTERN || type2->tot() == EXTERN ) + return true; + + if ( type1->tot() != type2->tot() ) + { + if ( type1->IsNumericType() && type2->IsNumericType() ) + return true; + else + return false; + } + + switch( type1->tot() ) + { + case UNDEF: + case EMPTY: + return true; + case BUILTIN: + { + BuiltInType *t1 = + static_cast(type1); + BuiltInType *t2 = + static_cast(type2); + return BuiltInType::CompatibleBuiltInTypes(t1, t2); + } + + case PARAMETERIZED: + case RECORD: + case CASE: + case EXTERN: + return type1->DataTypeStr() == type2->DataTypeStr(); + break; + + case ARRAY: + { + ArrayType *t1 = + static_cast(type1); + ArrayType *t2 = + static_cast(type2); + return CompatibleTypes(t1->ElementDataType(), + t2->ElementDataType()); + } + + default: + ASSERT(0); + return false; + } + } + +Type *Type::LookUpByID(ID *id) + { + // 1. Is it a pre-defined type? + string name = id->Name(); + if ( type_map_.find(name) != type_map_.end() ) + { + return type_map_[name]->Clone(); + } + + // 2. Is it a simple declared type? + Type *type = TypeDecl::LookUpType(id); + if ( type ) + { + // Note: as a Type is always associated with a variable, + // return a clone. + switch ( type->tot() ) + { + case Type::BUILTIN: + case Type::EXTERN: + case Type::STRING: + return type->Clone(); + + case Type::ARRAY: + default: + break; + } + } + + return new ParameterizedType(id, 0); + } + +void Type::AddPredefinedType(const string &type_name, Type *type) + { + ASSERT(type_map_.find(type_name) == type_map_.end()); + type_map_[type_name] = type; + } + +void Type::init() + { + BuiltInType::static_init(); + ExternType::static_init(); + StringType::static_init(); + } diff --git a/tools/binpac/src/pac_type.def b/tools/binpac/src/pac_type.def new file mode 100644 index 0000000000..62939ec671 --- /dev/null +++ b/tools/binpac/src/pac_type.def @@ -0,0 +1,8 @@ +// TYPEDEF(type_id, pac_type, c_type, size) +TYPE_DEF(INT8, "int8", "int8", 1) +TYPE_DEF(INT16, "int16", "int16", 2) +TYPE_DEF(INT32, "int32", "int32", 4) +TYPE_DEF(UINT8, "uint8", "uint8", 1) +TYPE_DEF(UINT16, "uint16", "uint16", 2) +TYPE_DEF(UINT32, "uint32", "uint32", 4) +TYPE_DEF(EMPTY, "empty", "", 0) diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h new file mode 100644 index 0000000000..08252cf637 --- /dev/null +++ b/tools/binpac/src/pac_type.h @@ -0,0 +1,309 @@ +#ifndef pac_type_h +#define pac_type_h + +#include +using namespace std; + +#include "pac_common.h" +#include "pac_datadep.h" +#include "pac_dbg.h" + +class Type : public Object, public DataDepElement +{ +public: + enum TypeType { + UNDEF = -1, + EMPTY, + BUILTIN, + PARAMETERIZED, + RECORD, + CASE, + ARRAY, + STRING, + EXTERN, + DUMMY, + }; + + explicit Type(TypeType tot); + virtual ~Type(); + + Type *Clone() const; + + // Type of type + TypeType tot() const { return tot_; } + + //////////////////////////////////////// + // Code generation + virtual void Prepare(Env *env, int flags); + + // Flag(s) for Prepare() + static const int TO_BE_PARSED = 1; + + virtual void GenPubDecls(Output *out, Env *env); + virtual void GenPrivDecls(Output *out, Env *env); + + virtual void GenInitCode(Output *out, Env *env); + virtual void GenCleanUpCode(Output *out, Env *env); + + void GenPreParsing(Output *out, Env *env); + void GenParseCode(Output *out, Env *env, const DataPtr& data, int flags); + + //////////////////////////////////////// + // TODO: organize the various methods below + + // The LValue string of the variable defined by the type. + // For example, if the type defines a record field, the + // lvalue is the member variable corresponding to the field; + // if the type appears in a type decl, then the lvalue is the + // default value var. + // + const char *lvalue() const { return lvalue_.c_str(); } + + // The TypeDecl that defined the type. + // + const TypeDecl *type_decl() const { return type_decl_; } + void set_type_decl(const TypeDecl *decl, bool declared_as_type); + + // Returns whether the type appears in a type declaration + // (true) or as type specification of a field (false). + // + bool declared_as_type() const { return declared_as_type_; } + + // The ID of the decl in which the type appear. + // + const ID *decl_id() const; + + Env *env() const { return env_; } + + string EvalByteOrder(Output *out_cc, Env *env) const; + + virtual string EvalMember(const ID *member_id) const; + virtual string EvalElement(const string &array, + const string &index) const; + + // The variable defined by the type + const ID *value_var() const { return value_var_; } + void set_value_var(const ID *arg_id, int arg_id_type); + + bool anonymous_value_var() const { return anonymous_value_var_; } + + const ID *size_var() const; + + // Adds a variable to env to represent the size of this type. + // Returns false if we do not need a size variable (because + // the type has a static size) or the size variable is already added. + bool AddSizeVar(Output *out, Env *env); + + const ID *parsing_state_var() const; + + const ID *has_value_var() const; + + void AddField(Field *f); + + void AddCheck(Expr *expr) { /* TODO */ } + + virtual bool DefineValueVar() const = 0; + + // Returns C++ datatype string + virtual string DataTypeStr() const = 0; + + // Returns const reference of the C++ data type (unless the type + // is numeric or pointer) + string DataTypeConstRefStr() const + { + string data_type = DataTypeStr(); + if ( ! IsPointerType() && ! IsNumericType() ) + data_type += " const &"; + return data_type; + } + + // Returns a default value for the type + virtual string DefaultValue() const + { + ASSERT(0); return "@@@"; + } + + // Returns the data type of the member field/case + virtual Type *MemberDataType(const ID *member_id) const; + + // Returns the data type of the element type of an array + virtual Type *ElementDataType() const; + + // Whether the type needs clean-up at deallocation. + bool NeedsCleanUp() const; + + // Whether byte order must be determined before parsing the type. + bool RequiresByteOrder() const; + + // Whether class of the type requires a parameter of analyzer context. + virtual bool RequiresAnalyzerContext(); + + virtual bool IsPointerType() const = 0; + virtual bool IsNumericType() const { return false; } + bool IsEmptyType() const; + + //////////////////////////////////////// + // Attributes + virtual void ProcessAttr(Attr *a); + + bool attr_chunked() const { return attr_chunked_; } + Expr *attr_byteorder_expr() const { return attr_byteorder_expr_; } + Expr *attr_if_expr() const { return attr_if_expr_; } + // TODO: generate the length expression automatically. + Expr *attr_length_expr() const { return attr_length_expr_; } + bool attr_refcount() const { return attr_refcount_; } + bool attr_transient() const { return attr_transient_; } + + // Whether the value remains valid outside the parse function + bool persistent() const + { + return ! attr_transient() && ! attr_chunked(); + } + + void SetUntilCheck(ArrayType *t) { array_until_input_ = t; } + + //////////////////////////////////////// + // Size and boundary checking + virtual int StaticSize(Env *env) const = 0; + string DataSize(Output *out, Env *env, const DataPtr& data); + + bool boundary_checked() const { return boundary_checked_; } + virtual void SetBoundaryChecked() { boundary_checked_ = true; } + void GenBoundaryCheck(Output *out, Env *env, const DataPtr& data); + + //////////////////////////////////////// + // Handling incremental input + // + // There are two ways to handle incremental input: (1) to + // buffer the input before parsing; (2) to parse incrementally. + // + // The type must be "bufferable" for (1). While for (2), + // each member of the type must be able to handle incremental + // input. + + void MarkIncrementalInput(); + virtual void DoMarkIncrementalInput(); + + // Whether the type may receive incremental input + bool incremental_input() const { return incremental_input_; } + + // Whether parsing should also be incremental + bool incremental_parsing() const { return incremental_parsing_; } + + // Whether we should buffer the input + bool buffer_input() const { return buffer_input_; } + + // Whether parsing of the type is completed + const ID *parsing_complete_var() const; + string parsing_complete(Env *env) const; + + // Whether the input is bufferable + bool Bufferable() const; + bool BufferableByLength() const; + bool BufferableByLine() const; + + enum BufferMode { + NOT_BUFFERABLE, + BUFFER_NOTHING, // for type "empty" + BUFFER_BY_LENGTH, + BUFFER_BY_LINE, + }; + virtual BufferMode buffer_mode() const; + + void GenBufferConfiguration(Output *out, Env *env); + + int InitialBufferLength() const; + +protected: + virtual void GenNewInstance(Output *out, Env *env) {} + + virtual bool ByteOrderSensitive() const = 0; + + bool NeedsBufferingStateVar() const; + + void GenBufferingLoop(Output* out_cc, Env* env, int flags); + void GenParseBuffer(Output* out_cc, Env* env, int flags); + void GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags); + void GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags); + + virtual void DoGenParseCode(Output *out, Env *env, + const DataPtr& data, + int flags) = 0; + + string EvalLengthExpr(Output* out_cc, Env* env); + + // Generate code for computing the dynamic size of the type + virtual void GenDynamicSize(Output *out, Env *env, + const DataPtr& data) = 0; + + bool DoTraverse(DataDepVisitor *visitor); + + virtual Type *DoClone() const = 0; + +protected: + TypeType tot_; + const TypeDecl *type_decl_; + bool declared_as_type_; + const ID *type_decl_id_; + Env *env_; + + const ID *value_var_; + bool anonymous_value_var_; // whether the ID is anonymous + + string data_id_str_; + int value_var_type_; + Field *size_var_field_; + char *size_expr_; + bool boundary_checked_; + string lvalue_; + FieldList *fields_; + + bool incremental_input_; + bool incremental_parsing_; + bool buffer_input_; + + // A boolean variable on whether parsing of the type is completed + Field *parsing_complete_var_field_; + + // An integer variable holding the parsing state + Field *parsing_state_var_field_; + + Field *buffering_state_var_field_; + + // The array type with &until($input...) condition, if + // "this" is the element type + ArrayType *array_until_input_; + + // A "has_*" member var for fields with &if + LetField *has_value_field_; + + // Attributes + AttrList *attrs_; + + Expr *attr_byteorder_expr_; + ExprList *attr_checks_; + bool attr_chunked_; + bool attr_exportsourcedata_; + Expr *attr_if_expr_; + Expr *attr_length_expr_; + FieldList *attr_letfields_; + Expr *attr_multiline_end_; + bool attr_oneline_; + bool attr_refcount_; + Expr *attr_requires_; + bool attr_restofdata_; + bool attr_restofflow_; + bool attr_transient_; + +public: + static void init(); + static bool CompatibleTypes(Type *type1, Type *type2); + static void AddPredefinedType(const string &type_name, Type *type); + static Type *LookUpByID(ID *id); + +protected: + typedef map type_map_t; + static type_map_t type_map_; +}; + +#endif // pac_type_h diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc new file mode 100644 index 0000000000..c989869d20 --- /dev/null +++ b/tools/binpac/src/pac_typedecl.cc @@ -0,0 +1,409 @@ +#include "pac_attr.h" +#include "pac_context.h" +#include "pac_dataptr.h" +#include "pac_embedded.h" +#include "pac_enum.h" +#include "pac_exception.h" +#include "pac_expr.h" +#include "pac_exttype.h" +#include "pac_id.h" +#include "pac_output.h" +#include "pac_param.h" +#include "pac_paramtype.h" +#include "pac_record.h" +#include "pac_type.h" +#include "pac_typedecl.h" +#include "pac_utils.h" + +TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type) + : Decl(id, TYPE), params_(params), type_(type) + { + env_ = 0; + type_->set_type_decl(this, true); + } + +TypeDecl::~TypeDecl() + { + delete env_; + delete type_; + + delete_list(ParamList, params_); + } + +void TypeDecl::ProcessAttr(Attr* a) + { + type_->ProcessAttr(a); + } + +void TypeDecl::AddParam(Param *param) + { + // Cannot work after Prepare() + ASSERT(! env_); + params_->push_back(param); + } + +void TypeDecl::Prepare() + { + DEBUG_MSG("Preparing type %s\n", id()->Name()); + + if ( type_->tot() != Type::EXTERN && type_->tot() != Type::DUMMY ) + SetAnalyzerContext(); + + // As a type ID can be used in the same way function is, add the + // id as a FUNC_ID and set it as evaluated. + global_env()->AddID(id(), FUNC_ID, type_); + global_env()->SetEvaluated(id()); + + env_ = new Env(global_env(), this); + + foreach (i, ParamList, params_) + { + Param* p = *i; + // p->Prepare(env_); + type_->AddField(p->param_field()); + } + + if ( type_->attr_byteorder_expr() ) + { + DEBUG_MSG("Adding byteorder field to %s\n", + id()->Name()); + type_->AddField(new LetField(byteorder_id->clone(), + extern_type_int, + type_->attr_byteorder_expr())); + } + + type_->Prepare(env_, Type::TO_BE_PARSED); + } + +string TypeDecl::class_name() const + { + return id_->Name(); + } + +void TypeDecl::GenForwardDeclaration(Output* out_h) + { + // Do not generate declaration for external types + if ( type_->tot() == Type::EXTERN ) + return; + out_h->println("class %s;", class_name().c_str()); + } + +void TypeDecl::GenCode(Output* out_h, Output* out_cc) + { + // Do not generate code for external types + if ( type_->tot() == Type::EXTERN || type_->tot() == Type::STRING ) + return; + + fprintf(stderr, "Generating code for %s\n", class_name().c_str()); + + if ( RequiresAnalyzerContext::compute(type_) ) + { + DEBUG_MSG("%s requires analyzer context\n", + id()->Name()); + Type *param_type = analyzer_context()->param_type(); + env_->AddID(analyzer_context_id, TEMP_VAR, param_type); + env_->SetEvaluated(analyzer_context_id); + env_->AddMacro(context_macro_id, + new Expr(analyzer_context_id->clone())); + } + + // Add parameter "byteorder" + if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) + { + env_->AddID(byteorder_id, TEMP_VAR, extern_type_int); + env_->SetEvaluated(byteorder_id); + } + + vector base_classes; + + AddBaseClass(&base_classes); + + if ( type_->attr_refcount() ) + base_classes.push_back(kRefCountClass); + + // The first line of class definition + out_h->println(""); + out_h->print("class %s", class_name().c_str()); + bool first = true; + foreach(i, vector, &base_classes) + { + if ( first ) + { + out_h->print(" : public %s", i->c_str()); + first = false; + } + else + out_h->print(", public %s", i->c_str()); + } + out_h->print("\n"); + + // Public members + out_h->println("{"); + out_h->println("public:"); + out_h->inc_indent(); + + GenConstructorFunc(out_h, out_cc); + GenDestructorFunc(out_h, out_cc); + + if ( type_->attr_length_expr() ) + GenInitialBufferLengthFunc(out_h, out_cc); + + GenParseFunc(out_h, out_cc); + + out_h->println(""); + out_h->println("// Member access functions"); + type_->GenPubDecls(out_h, env_); + out_h->println(""); + + GenPubDecls(out_h, out_cc); + + out_h->dec_indent(); + out_h->println("protected:"); + out_h->inc_indent(); + + GenPrivDecls(out_h, out_cc); + type_->GenPrivDecls(out_h, env_); + + out_h->dec_indent(); + out_h->println("};\n"); + } + +void TypeDecl::GenPubDecls(Output* out_h, Output *out_cc) + { + // GenParamPubDecls(params_, out_h, env_); + } + +void TypeDecl::GenPrivDecls(Output* out_h, Output *out_cc) + { + // GenParamPrivDecls(params_, out_h, env_); + } + +void TypeDecl::GenInitCode(Output *out_cc) + { + } + +void TypeDecl::GenCleanUpCode(Output *out_cc) + { + } + +void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc) + { + string params_str = ParamDecls(params_); + + string proto = + strfmt("%s(%s)", class_name().c_str(), params_str.c_str()); + + out_h->println("%s;", proto.c_str()); + + out_cc->println("%s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + + out_cc->println("{"); + + // GenParamAssignments(params_, out_cc, env_); + + type_->GenInitCode(out_cc, env_); + GenInitCode(out_cc); + + out_cc->println("}\n"); + out_cc->dec_indent(); + } + +void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) + { + string proto = strfmt("~%s()", class_name().c_str()); + + out_h->println("%s;", proto.c_str()); + + out_cc->println("%s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + + GenCleanUpCode(out_cc); + type_->GenCleanUpCode(out_cc, env_); + + out_cc->println("}\n"); + out_cc->dec_indent(); + } + +string TypeDecl::ParseFuncPrototype(Env* env) + { + const char *func_name = 0; + const char *return_type = 0; + string params; + + if ( type_->incremental_input() ) + { + func_name = kParseFuncWithBuffer; + return_type = "bool"; + params = strfmt("flow_buffer_t %s", + env->LValue(flow_buffer_id)); + } + else + { + func_name = kParseFuncWithoutBuffer; + return_type = "int"; + params = strfmt("const_byteptr const %s, const_byteptr const %s", + env->LValue(begin_of_data), + env->LValue(end_of_data)); + } + + if ( RequiresAnalyzerContext::compute(type_) ) + { + Type *param_type = analyzer_context()->param_type(); + params += fmt(", %s %s", + param_type->DataTypeConstRefStr().c_str(), + env->LValue(analyzer_context_id)); + } + + // Add parameter "byteorder" + if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) + { + params += fmt(", int %s", env->LValue(byteorder_id)); + } + + // Returns " %s()%s". + return strfmt("%s %%s%s(%s)%%s", + return_type, func_name, params.c_str()); + } + +void TypeDecl::GenParsingEnd(Output *out_cc, Env *env, const DataPtr &data) + { + string ret_val_0, ret_val_1; + + if ( type_->incremental_input() ) + { + ret_val_0 = type_->parsing_complete(env).c_str(); + ret_val_1 = "false"; + } + else + { + ret_val_0 = type_->DataSize(0, env, data).c_str(); + ret_val_1 = "@@@"; + + out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", + env->RValue(begin_of_data), + ret_val_0.c_str(), + env->RValue(end_of_data)); + } + + if ( type_->incremental_parsing() && + ( type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY ) ) + { + // In which case parsing may jump to label + // "need_more_data" ... + out_cc->println("BINPAC_ASSERT(%s);", + type_->parsing_complete(env).c_str()); + out_cc->println("return %s;", ret_val_0.c_str()); + + out_cc->println(""); + out_cc->dec_indent(); + out_cc->println("%s:", kNeedMoreData); + out_cc->inc_indent(); + out_cc->println("BINPAC_ASSERT(!(%s));", + type_->parsing_complete(env).c_str()); + out_cc->println("return %s;", ret_val_1.c_str()); + } + else if ( type_->incremental_input() ) + { + out_cc->println("return %s;", ret_val_0.c_str()); + } + else + { + out_cc->println("return %s;", ret_val_0.c_str()); + } + } + +void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) + { + if ( type_->tot() == Type::DUMMY ) + return; + + // Env within the parse function + Env p_func_env(env_, this); + Env *env = &p_func_env; + + if ( type_->incremental_input() ) + { + env->AddID(flow_buffer_id, TEMP_VAR, extern_type_flowbuffer); + env->SetEvaluated(flow_buffer_id); + } + else + { + env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); + env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); + + env->SetEvaluated(begin_of_data); + env->SetEvaluated(end_of_data); + } + + string proto; + proto = ParseFuncPrototype(env); + +#if 0 + if ( func_type == PARSE ) + { + out_h->println("// 1. If the message is completely parsed, returns number of"); + out_h->println("// input bytes parsed."); + out_h->println("// 2. If the input is not complete but the type supports"); + out_h->println("// incremental input, returns number of input bytes + 1"); + out_h->println("// (%s - %s + 1).", + env->LValue(end_of_data), + env->LValue(begin_of_data)); + out_h->println("// 3. An exception will be thrown on error."); + } +#endif + + out_h->println(proto.c_str(), "", ";"); + + out_cc->println(proto.c_str(), fmt("%s::", class_name().c_str()), ""); + out_cc->inc_indent(); + out_cc->println("{"); + + DataPtr data(env, 0, 0); + + if ( ! type_->incremental_input() ) + data = DataPtr(env, begin_of_data, 0); + type_->GenParseCode(out_cc, env, data, 0); + GenParsingEnd(out_cc, env, data); + + out_cc->println("}\n"); + out_cc->dec_indent(); + } + +void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc) + { + string func(kInitialBufferLengthFunc); + + int init_buffer_length = type_->InitialBufferLength(); + + if ( init_buffer_length < 0 ) // cannot be statically determined + { + throw Exception(type()->attr_length_expr(), + fmt("cannot determine initial buffer length" + " for type %s", id_->Name())); + } + + out_h->println("int %s() const { return %d; }", + func.c_str(), + init_buffer_length); + } + +Type* TypeDecl::LookUpType(const ID *id) + { + Decl *decl = LookUpDecl(id); + if ( ! decl ) + return 0; + switch ( decl->decl_type() ) + { + case TYPE: + case CONN: + case FLOW: + return static_cast(decl)->type(); + case ENUM: + return static_cast(decl)->DataType(); + default: + return 0; + } + } + diff --git a/tools/binpac/src/pac_typedecl.h b/tools/binpac/src/pac_typedecl.h new file mode 100644 index 0000000000..37631af18e --- /dev/null +++ b/tools/binpac/src/pac_typedecl.h @@ -0,0 +1,49 @@ +#ifndef pac_typedecl_h +#define pac_typedecl_h + +#include "pac_decl.h" + +class TypeDecl : public Decl +{ +public: + TypeDecl(ID *arg_id, ParamList *arg_params, Type *arg_type); + ~TypeDecl(); + void Prepare(); + void GenForwardDeclaration(Output *out_h); + void GenCode(Output *out_h, Output *out_cc); + + Env *env() const { return env_; } + Type *type() const { return type_; } + string class_name() const; + static Type *LookUpType(const ID *id); + +protected: + void AddParam(Param *param); + virtual void AddBaseClass(vector *base_classes) const {} + void ProcessAttr(Attr *a); + + virtual void GenPubDecls(Output *out_h, Output *out_cc); + virtual void GenPrivDecls(Output *out_h, Output *out_cc); + virtual void GenInitCode(Output *out_cc); + virtual void GenCleanUpCode(Output *out_cc); + + void GenConstructorFunc(Output *out_h, Output *out_cc); + void GenDestructorFunc(Output *out_h, Output *out_cc); + + string ParseFuncPrototype(Env* env); + void GenParseFunc(Output *out_h, Output *out_cc); + + void GenParsingEnd(Output *out_cc, Env *env, const DataPtr &data); + + void GenInitialBufferLengthFunc(Output *out_h, Output *out_cc); + +protected: + Env *env_; + + ParamList *params_; + Type *type_; + + bool inherits_frame_buffer_; +}; + +#endif // pac_typedecl_h diff --git a/tools/binpac/src/pac_utils.cc b/tools/binpac/src/pac_utils.cc new file mode 100644 index 0000000000..a9118fc256 --- /dev/null +++ b/tools/binpac/src/pac_utils.cc @@ -0,0 +1,43 @@ +// $Id: pac_utils.cc 3225 2006-06-08 00:00:01Z vern $ + +#include +#include +#include + +#include "pac_utils.h" + +char* copy_string(const char* s) + { + char* c = new char[strlen(s)+1]; + strcpy(c, s); + return c; + } + +namespace { + +const char* do_fmt(const char* format, va_list ap) + { + static char buf[1024]; + vsnprintf(buf, sizeof(buf), format, ap); + return buf; + } + +} + +string strfmt(const char* format, ...) + { + va_list ap; + va_start(ap, format); + const char* r = do_fmt(format, ap); + va_end(ap); + return string(r); + } + +char* nfmt(const char* format, ...) + { + va_list ap; + va_start(ap, format); + const char* r = do_fmt(format, ap); + va_end(ap); + return copy_string(r); + } diff --git a/tools/binpac/src/pac_utils.h b/tools/binpac/src/pac_utils.h new file mode 100644 index 0000000000..deef850245 --- /dev/null +++ b/tools/binpac/src/pac_utils.h @@ -0,0 +1,17 @@ +// $Id: pac_utils.h 3225 2006-06-08 00:00:01Z vern $ + +#ifndef pac_utils_h +#define pac_utils_h + +#include +#include +using namespace std; + +char* copy_string(const char* s); +string strfmt(const char* fmt, ...); +char* nfmt(const char* fmt, ...); + +// const char* fmt(const char* fmt, ...); +#define fmt(x...) strfmt(x).c_str() + +#endif /* pac_utils_h */ diff --git a/tools/binpac/src/pac_varfield.cc b/tools/binpac/src/pac_varfield.cc new file mode 100644 index 0000000000..76f36910f6 --- /dev/null +++ b/tools/binpac/src/pac_varfield.cc @@ -0,0 +1,6 @@ +#include "pac_varfield.h" + +void PrivVarField::Prepare(Env *env) + { + Field::Prepare(env); + } diff --git a/tools/binpac/src/pac_varfield.h b/tools/binpac/src/pac_varfield.h new file mode 100644 index 0000000000..8fea8879f9 --- /dev/null +++ b/tools/binpac/src/pac_varfield.h @@ -0,0 +1,51 @@ +#ifndef pac_varfield_h +#define pac_varfield_h + +#include "pac_field.h" + +// A private variable evaluated with parsing +class ParseVarField : public Field +{ +public: + ParseVarField(int is_class_member, ID* id, Type *type) + : Field(PARSE_VAR_FIELD, + TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, + id, type) {} + void GenPubDecls(Output* out, Env* env) { /* do nothing */ } +}; + +// A public variable +class PubVarField : public Field +{ +public: + PubVarField(ID* id, Type *type) + : Field(PUB_VAR_FIELD, + TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, + id, type) {} + ~PubVarField() {} +}; + +// A private variable +class PrivVarField : public Field +{ +public: + PrivVarField(ID* id, Type *type) + : Field(PRIV_VAR_FIELD, + TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, + id, type) {} + ~PrivVarField() {} + + void GenPubDecls(Output* out, Env* env) { /* do nothing */ } +}; + +class TempVarField : public Field +{ +public: + TempVarField(ID* id, Type *type) + : Field(TEMP_VAR_FIELD, + TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, + id, type) {} + ~TempVarField() {} +}; + +#endif // pac_varfield_h diff --git a/tools/binpac/src/pac_withinput.cc b/tools/binpac/src/pac_withinput.cc new file mode 100644 index 0000000000..8c39053046 --- /dev/null +++ b/tools/binpac/src/pac_withinput.cc @@ -0,0 +1,80 @@ +#include "pac_withinput.h" +#include "pac_dataptr.h" +#include "pac_expr.h" +#include "pac_inputbuf.h" +#include "pac_output.h" +#include "pac_type.h" + +WithInputField::WithInputField(ID* id, Type *type, InputBuffer* input) + : Field(WITHINPUT_FIELD, + TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, + id, type), + input_(input) + { + ASSERT(type_); + ASSERT(input_); + } + +WithInputField::~WithInputField() + { + delete input_; + } + +bool WithInputField::DoTraverse(DataDepVisitor *visitor) + { + return Field::DoTraverse(visitor) && + input()->Traverse(visitor); + } + +bool WithInputField::RequiresAnalyzerContext() const + { + return Field::RequiresAnalyzerContext() || + (input() && input()->RequiresAnalyzerContext()); + } + +void WithInputField::Prepare(Env* env) + { + Field::Prepare(env); + env->SetEvalMethod(id_, this); + } + +void WithInputField::GenEval(Output* out_cc, Env* env) + { + GenParseCode(out_cc, env); + if ( type_->attr_if_expr() ) + { + out_cc->println("BINPAC_ASSERT(%s);", + env->RValue(type_->has_value_var())); + } + } + +void WithInputField::GenParseCode(Output* out_cc, Env* env) + { + out_cc->println("// Parse \"%s\"", id_->Name()); + if ( type_->attr_if_expr() ) + { + // A conditional field + env->Evaluate(out_cc, type_->has_value_var()); + out_cc->println("if ( %s )", + env->RValue(type_->has_value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + } + else + out_cc->println("{"); + + Env field_env(env, this); + ASSERT(! type_->incremental_input()); + type_->GenPreParsing(out_cc, &field_env); + type_->GenParseCode(out_cc, &field_env, + input()->GenDataBeginEnd(out_cc, &field_env), + 0); + + if ( type_->attr_if_expr() ) + { + out_cc->println("}"); + out_cc->dec_indent(); + } + else + out_cc->println("}"); + } diff --git a/tools/binpac/src/pac_withinput.h b/tools/binpac/src/pac_withinput.h new file mode 100644 index 0000000000..18b086d61a --- /dev/null +++ b/tools/binpac/src/pac_withinput.h @@ -0,0 +1,38 @@ +#ifndef pac_withinput_h +#define pac_withinput_h + +#include "pac_datadep.h" +#include "pac_decl.h" +#include "pac_field.h" + +class WithInputField : public Field, public Evaluatable +{ +public: + WithInputField(ID* id, Type *type, InputBuffer* input); + virtual ~WithInputField(); + + InputBuffer *input() const { return input_; } + + void Prepare(Env* env); + + // void GenPubDecls(Output* out, Env* env); + // void GenPrivDecls(Output* out, Env* env); + + // void GenInitCode(Output* out, Env* env); + // void GenCleanUpCode(Output* out, Env* env); + + void GenParseCode(Output* out, Env* env); + + // Instantiate the Evaluatable interface + void GenEval(Output* out, Env* env); + + bool RequiresAnalyzerContext() const; + +protected: + bool DoTraverse(DataDepVisitor *visitor); + +protected: + InputBuffer *input_; +}; + +#endif // pac_withinput_h From 65668d3ea655fb1358657c438f387dc0ef336a1b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 14 Oct 2010 10:17:55 -0500 Subject: [PATCH 002/343] binpac: Initial, working CMake build added. --- tools/binpac/CMakeLists.txt | 63 ++++++++++++++++++++ tools/binpac/lib/CMakeLists.txt | 24 ++++++++ tools/binpac/lib/binpac.h.in | 2 +- tools/binpac/src/CMakeLists.txt | 101 ++++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 tools/binpac/CMakeLists.txt create mode 100644 tools/binpac/lib/CMakeLists.txt create mode 100644 tools/binpac/src/CMakeLists.txt diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt new file mode 100644 index 0000000000..a64686b3a8 --- /dev/null +++ b/tools/binpac/CMakeLists.txt @@ -0,0 +1,63 @@ +## +## CMake Configuration +## + +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) + +# Prohibit in-source builds. +string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" source_build) +if (source_build) + message(FATAL_ERROR "In-source builds are not allowed\n." + "Please create a separate build directory and invoke cmake from there.") +endif () + +# If the build configuration file does not exist, copy it over. +set(build_config BuildOptions.cmake) +find_file(build_config_file + NAMES BuildOptions.cmake + PATHS ${CMAKE_BINARY_DIR} + DOC "Build configuration" + NO_DEFAULT_PATH + ) +if (NOT build_config_file) + message("No build configuration found, using default.") + configure_file(${CMAKE_SOURCE_DIR}/${build_config} + ${CMAKE_BINARY_DIR}/${build_config} + ) +endif () +mark_as_advanced(build_config_file) + +include(${CMAKE_BINARY_DIR}/${build_config}) + +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/) + +## +## Project Configuration +## + +project(BinPAC) + +include(CheckIncludeFiles) +check_include_files(inttypes.h HAVE_INTTYPES_H) +check_include_files(memory.h HAVE_MEMORY_H) +check_include_files(stdint.h HAVE_STDINT_H) +check_include_files(stdlib.h HAVE_STDLIB_H) +check_include_files(strings.h HAVE_STRINGS_H) +check_include_files(string.h HAVE_STRING_H) +check_include_files(sys/stat.h HAVE_SYS_STAT_H) +check_include_files(sys/types.h HAVE_SYS_TYPES_H) +check_include_files(unistd.h HAVE_UNISTD_H) + +include(TestBigEndian) +test_big_endian(WORDS_BIGENDIAN) + +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) + +add_subdirectory(lib) +add_subdirectory(src) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt new file mode 100644 index 0000000000..f571fed48d --- /dev/null +++ b/tools/binpac/lib/CMakeLists.txt @@ -0,0 +1,24 @@ +include(TestBigEndian) +test_big_endian(HOST_BIGENDIAN) + +include(CheckTypeSize) +check_type_size("unsigned int" SIZEOF_UNSIGNED_INT) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/binpac.h.in + ${CMAKE_CURRENT_BINARY_DIR}/binpac.h) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) + +set(binpac_LIB_SRCS + binpac_buffer.cc + binpac_bytestring.cc + binpac.h + binpac_analyzer.h + binpac_buffer.h + binpac_bytestring.h + binpac_exception.h + binpac_regex.h +) + +add_library(binpac_lib STATIC ${binpac_LIB_SRCS}) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index 920a699409..c7e8eac515 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -6,7 +6,7 @@ #include -@HOST_BIGENDIAN@ +#cmakedefine HOST_BIGENDIAN #ifdef HOST_BIGENDIAN # define HOST_BYTEORDER bigendian #else diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt new file mode 100644 index 0000000000..f4a7ad9cc6 --- /dev/null +++ b/tools/binpac/src/CMakeLists.txt @@ -0,0 +1,101 @@ +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) + +bison_target(PACParser pac_parse.yy ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.cc + COMPILE_FLAGS "-t" HEADER ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.h) +flex_target(PACScanner pac_scan.ll ${CMAKE_CURRENT_BINARY_DIR}/pac_scan.cc) +add_flex_bison_dependency(PACScanner PACParser) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) + +set(binpac_SRCS + ${BISON_PACParser_OUTPUTS} + ${FLEX_PACScanner_OUTPUTS} + pac_action.cc + pac_analyzer.cc + pac_array.cc + pac_attr.cc + pac_btype.cc + pac_case.cc + pac_conn.cc + pac_context.cc + pac_cstr.cc + pac_datadep.cc + pac_dataptr.cc + pac_dataunit.cc + pac_decl.cc + pac_embedded.cc + pac_enum.cc + pac_expr.cc + pac_exttype.cc + pac_field.cc + pac_flow.cc + pac_func.cc + pac_id.cc + pac_inputbuf.cc + pac_let.cc + pac_param.cc + pac_paramtype.cc + pac_primitive.cc + pac_record.cc + pac_redef.cc + pac_regex.cc + pac_state.cc + pac_strtype.cc + pac_type.cc + pac_typedecl.cc + pac_withinput.cc + pac_output.cc + pac_utils.cc + pac_exception.cc + pac_main.cc + pac_action.h + pac_analyzer.h + pac_array.h + pac_attr.h + pac_btype.h + pac_case.h + pac_cclass.h + pac_common.h + pac_conn.h + pac_context.h + pac_cstr.h + pac_ctype.h + pac_datadep.h + pac_dataptr.h + pac_dataunit.h + pac_dbg.h + pac_decl-inl.h + pac_decl.h + pac_embedded.h + pac_enum.h + pac_exception.h + pac_expr.h + pac_exttype.h + pac_field.h + pac_flow.h + pac_func.h + pac_id.h + pac_inputbuf.h + pac_let.h + pac_number.h + pac_output.h + pac_param.h + pac_paramtype.h + pac_primitive.h + pac_record.h + pac_redef.h + pac_regex.h + pac_state.h + pac_strtype.h + pac_type.h + pac_typedecl.h + pac_utils.h + pac_varfield.h + pac_withinput.h +) + +add_executable(binpac ${binpac_SRCS}) + +target_link_libraries(binpac) From 73a67f0ae38dae19d85cc3605ec502b21e99b688 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 18 Oct 2010 12:42:43 -0500 Subject: [PATCH 003/343] binpac: Removed unnecessary subdir for custom CMake modules. --- tools/binpac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index a64686b3a8..b946e70d44 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -29,7 +29,7 @@ mark_as_advanced(build_config_file) include(${CMAKE_BINARY_DIR}/${build_config}) -set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/) +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) ## ## Project Configuration From 677ae822030493a6419dfcdef81b6fdd2f293255 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 18 Oct 2010 12:55:55 -0500 Subject: [PATCH 004/343] binpac: Changes to the config.h generation. - Renamed VERSION preprocessor definition to not conflict with Bro's. - Removed check for HAVE_CONFIG_H; config.h will always be generated in the binpac build directory, but if a parent directory has generated a config.h and added that to compiler include search paths via include_directories(), then that one should be used -- include_directories() appends paths by default and the parent CMakeLists.txt will have called it first. --- tools/binpac/CMakeLists.txt | 3 +-- tools/binpac/src/pac_main.cc | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index b946e70d44..bfc7fe95e5 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -56,8 +56,7 @@ file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_subdirectory(lib) add_subdirectory(src) diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index 7c98e526fa..6b6fe64a63 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -13,9 +13,7 @@ #include "pac_utils.h" #include "pac_exception.h" -#ifdef HAVE_CONFIG_H #include "config.h" -#endif extern int yydebug; extern int yyparse(); @@ -187,8 +185,8 @@ int compile(const char* filename) void usage() { -#ifdef VERSION - fprintf(stderr, "binpac version %s\n", VERSION); +#ifdef BINPAC_VERSION + fprintf(stderr, "binpac version %s\n", BINPAC_VERSION); #endif fprintf(stderr, "usage: binpac [options] \n"); fprintf(stderr, " | pac-language input files\n"); From 9d7d6f88682e6f61ac8903bd70231598840e3261 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 19 Oct 2010 16:28:38 -0500 Subject: [PATCH 005/343] binpac: Two small changes: - Moved find_package() calls up to top directory so failure can occur right away if any dependencies are missing - Got rid of a bunch of header checks and preprocessor definitions that aren't ever used; not sure why I had them there in the first place --- tools/binpac/CMakeLists.txt | 15 ++------------- tools/binpac/src/CMakeLists.txt | 3 --- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index bfc7fe95e5..232d590cac 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -37,19 +37,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) project(BinPAC) -include(CheckIncludeFiles) -check_include_files(inttypes.h HAVE_INTTYPES_H) -check_include_files(memory.h HAVE_MEMORY_H) -check_include_files(stdint.h HAVE_STDINT_H) -check_include_files(stdlib.h HAVE_STDLIB_H) -check_include_files(strings.h HAVE_STRINGS_H) -check_include_files(string.h HAVE_STRING_H) -check_include_files(sys/stat.h HAVE_SYS_STAT_H) -check_include_files(sys/types.h HAVE_SYS_TYPES_H) -check_include_files(unistd.h HAVE_UNISTD_H) - -include(TestBigEndian) -test_big_endian(WORDS_BIGENDIAN) +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index f4a7ad9cc6..e1332427ac 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -1,6 +1,3 @@ -find_package(FLEX REQUIRED) -find_package(BISON REQUIRED) - bison_target(PACParser pac_parse.yy ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.cc COMPILE_FLAGS "-t" HEADER ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.h) flex_target(PACScanner pac_scan.ll ${CMAKE_CURRENT_BINARY_DIR}/pac_scan.cc) From 0944e3619cc0fb12578d2e0e7e3f32aed07b36df Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 20 Oct 2010 12:38:13 -0500 Subject: [PATCH 006/343] binpac: Added bison flag for verbose output. --- tools/binpac/src/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index e1332427ac..5d28c5cc30 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -1,5 +1,7 @@ bison_target(PACParser pac_parse.yy ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.cc - COMPILE_FLAGS "-t" HEADER ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.h) + HEADER ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.h + VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.output + COMPILE_FLAGS "--debug") flex_target(PACScanner pac_scan.ll ${CMAKE_CURRENT_BINARY_DIR}/pac_scan.cc) add_flex_bison_dependency(PACScanner PACParser) From 4644605860a6065dd2c61db145fdc725a5c74ceb Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 20 Oct 2010 13:17:59 -0500 Subject: [PATCH 007/343] binpac: Added debug/release mode compiler flags and build summary output. --- tools/binpac/CMakeLists.txt | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 232d590cac..3d59e02e86 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -37,9 +37,30 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) project(BinPAC) +set(CMAKE_C_FLAGS "-W -Wall -Wno-unused") +set(CMAKE_CXX_FLAGS "-W -Wall -Wno-unused") + +if (ENABLE_DEBUG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") +endif () + +if (ENABLE_RELEASE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") +endif () + +## +## Dependency Configuration +## + find_package(FLEX REQUIRED) find_package(BISON REQUIRED) +## +## Configuration Checks/Tests +## + file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in @@ -47,5 +68,26 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in include_directories(${CMAKE_CURRENT_BINARY_DIR}) +## +## Recuse on sub-directories +## + add_subdirectory(lib) add_subdirectory(src) + +## +## Build Summary +## + +message( + "\n==================| BinPAC Build Summary |====================" + "\n" + "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nDebug mode: ${ENABLE_DEBUG}" + "\nRelease mode: ${ENABLE_RELEASE}" + "\n" + "\nCFLAGS: ${CMAKE_C_FLAGS}" + "\nCXXFLAGS: ${CMAKE_CXX_FLAGS}" + "\n" + "\n================================================================\n" +) From 47c64d7feda9c1e4ba22fd643146f69390c0d920 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 21 Oct 2010 10:06:59 -0500 Subject: [PATCH 008/343] binpac: Changes to add an install target. --- tools/binpac/lib/CMakeLists.txt | 8 ++++++-- tools/binpac/src/CMakeLists.txt | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index f571fed48d..f7ed65f2c8 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -10,7 +10,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/binpac.h.in include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) -set(binpac_LIB_SRCS +set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc binpac.h @@ -21,4 +21,8 @@ set(binpac_LIB_SRCS binpac_regex.h ) -add_library(binpac_lib STATIC ${binpac_LIB_SRCS}) +add_library(binpac_lib STATIC ${binpac_lib_SRCS}) + +set_target_properties(binpac_lib PROPERTIES OUTPUT_NAME binpac) + +install(TARGETS binpac_lib DESTINATION lib) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 5d28c5cc30..bbaedaf53f 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -97,4 +97,4 @@ set(binpac_SRCS add_executable(binpac ${binpac_SRCS}) -target_link_libraries(binpac) +install(TARGETS binpac DESTINATION bin) From 92f936fdb83482e6d2edc0280bee089cfc9b9771 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 21 Oct 2010 12:45:51 -0500 Subject: [PATCH 009/343] binpac: Added headers to install target. Also set some convenience variables that mimic what a FindBinPAC module would set. These could be used by a superproject that wants to decide whether to use an existing BinPAC installation or (re)build from source. --- tools/binpac/CMakeLists.txt | 8 +++++++- tools/binpac/lib/CMakeLists.txt | 27 +++++++++++++++++++++++++-- tools/binpac/src/CMakeLists.txt | 9 ++++++++- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 3d59e02e86..bf8c2fe233 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -79,10 +79,16 @@ add_subdirectory(src) ## Build Summary ## +if (BinPAC_SKIP_INSTALL) + set(binpac_install_summary "Install skipped") +else () + set(binpac_install_summary "${CMAKE_INSTALL_PREFIX}") +endif () + message( "\n==================| BinPAC Build Summary |====================" "\n" - "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nInstall prefix: ${binpac_install_summary}" "\nDebug mode: ${ENABLE_DEBUG}" "\nRelease mode: ${ENABLE_RELEASE}" "\n" diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index f7ed65f2c8..996bbf1c18 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -13,7 +13,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc - binpac.h + ${CMAKE_CURRENT_BINARY_DIR}/binpac.h binpac_analyzer.h binpac_buffer.h binpac_bytestring.h @@ -25,4 +25,27 @@ add_library(binpac_lib STATIC ${binpac_lib_SRCS}) set_target_properties(binpac_lib PROPERTIES OUTPUT_NAME binpac) -install(TARGETS binpac_lib DESTINATION lib) +if (NOT BinPAC_SKIP_INSTALL) + install(TARGETS binpac_lib DESTINATION lib) + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/binpac.h + binpac_analyzer.h + binpac_buffer.h + binpac_bytestring.h + binpac_exception.h + binpac_regex.h + DESTINATION + include + ) +endif () + +# This is set to assist superprojects that want to build BinPac +# from source and rely on it as a target +set(BinPAC_LIBRARY binpac_lib + CACHE STRING "BinPAC static library" FORCE +) + +set(BinPAC_INCLUDE_DIR + ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + CACHE STRING "BinPAC header directories" FORCE +) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index bbaedaf53f..5e9881138c 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -97,4 +97,11 @@ set(binpac_SRCS add_executable(binpac ${binpac_SRCS}) -install(TARGETS binpac DESTINATION bin) +if (NOT BinPAC_SKIP_INSTALL) + install(TARGETS binpac DESTINATION bin) +endif () + +# This is set to assist superprojects that want to build BinPac +# from source and rely on it as a target +set(BinPAC_EXE binpac + CACHE STRING "BinPAC executable" FORCE) From a05eb8b150fa87d5c18b9c723efb102d04dc5615 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 26 Oct 2010 16:26:22 -0500 Subject: [PATCH 010/343] binpac: Added configure script to wrap cmake functionality --- tools/binpac/CMakeLists.txt | 60 +++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index bf8c2fe233..8e56a8e411 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -7,27 +7,24 @@ cmake_minimum_required(VERSION 2.8 FATAL_ERROR) # Prohibit in-source builds. string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" source_build) if (source_build) - message(FATAL_ERROR "In-source builds are not allowed\n." - "Please create a separate build directory and invoke cmake from there.") + message(FATAL_ERROR "In-source builds are not allowed. Please use " + "./configure to choose a build directory and " + "initialize the build configuration.") endif () -# If the build configuration file does not exist, copy it over. -set(build_config BuildOptions.cmake) -find_file(build_config_file +find_file(build_options_file NAMES BuildOptions.cmake PATHS ${CMAKE_BINARY_DIR} - DOC "Build configuration" + DOC "Build Options" NO_DEFAULT_PATH ) -if (NOT build_config_file) - message("No build configuration found, using default.") - configure_file(${CMAKE_SOURCE_DIR}/${build_config} - ${CMAKE_BINARY_DIR}/${build_config} - ) +if (NOT build_options_file) + message(FATAL_ERROR "Build options file not found, please use " + "${CMAKE_SOURCE_DIR}/configure to generate one.") endif () mark_as_advanced(build_config_file) -include(${CMAKE_BINARY_DIR}/${build_config}) +include(${build_options_file}) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) @@ -37,17 +34,27 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) project(BinPAC) -set(CMAKE_C_FLAGS "-W -Wall -Wno-unused") -set(CMAKE_CXX_FLAGS "-W -Wall -Wno-unused") - -if (ENABLE_DEBUG) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") +if (ENABLE_DEBUG AND ENABLE_RELEASE) + set(CMAKE_BUILD_TYPE RelWithDebInfo) +elseif (ENABLE_DEBUG AND NOT ENABLE_RELEASE) + set(CMAKE_BUILD_TYPE Debug) +elseif (NOT ENABLE_DEBUG AND ENABLE_RELEASE) + set(CMAKE_BUILD_TYPE Release) endif () -if (ENABLE_RELEASE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") +# don't set extra compile flags again if already declared in this scope +# (i.e. this project is included from Bro) +if (NOT EXTRA_COMPILE_FLAGS) + set(EXTRA_COMPILE_FLAGS "-Wall -Wno-unused") + + if (ENABLE_DEBUG) + set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DDEBUG") + endif () + + # Compiler flags may already exist in CMake cache (e.g. when specifying + # CFLAGS environment variable before running cmake for the the first time) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_COMPILE_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_COMPILE_FLAGS}") endif () ## @@ -85,6 +92,10 @@ else () set(binpac_install_summary "${CMAKE_INSTALL_PREFIX}") endif () +if (CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) +endif () + message( "\n==================| BinPAC Build Summary |====================" "\n" @@ -92,8 +103,11 @@ message( "\nDebug mode: ${ENABLE_DEBUG}" "\nRelease mode: ${ENABLE_RELEASE}" "\n" - "\nCFLAGS: ${CMAKE_C_FLAGS}" - "\nCXXFLAGS: ${CMAKE_CXX_FLAGS}" + "\nCC: ${CMAKE_C_COMPILER}" + "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" + "\nCXX: ${CMAKE_CXX_COMPILER}" + "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" + "\nCPP: ${CMAKE_CXX_COMPILER}" "\n" "\n================================================================\n" ) From 32db4e4447ecf3d3bf10c887988535190c89a32a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 26 Oct 2010 17:09:27 -0500 Subject: [PATCH 011/343] binpac: CMake module path adjustment. To allow inclusion from a superproject. --- tools/binpac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 8e56a8e411..800c575464 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -26,7 +26,7 @@ mark_as_advanced(build_config_file) include(${build_options_file}) -set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) ## ## Project Configuration From 8366dd6bcb1c343c86c909069acf46af7bc11882 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 2 Nov 2010 10:57:24 -0500 Subject: [PATCH 012/343] binpac: Minor style changes. --- tools/binpac/CMakeLists.txt | 31 ++++++++++++------------------- tools/binpac/lib/CMakeLists.txt | 18 ++++++++---------- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 800c575464..3b567b2fc1 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,12 +1,10 @@ -## +######################################################################## ## CMake Configuration -## cmake_minimum_required(VERSION 2.8 FATAL_ERROR) # Prohibit in-source builds. -string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" source_build) -if (source_build) +if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message(FATAL_ERROR "In-source builds are not allowed. Please use " "./configure to choose a build directory and " "initialize the build configuration.") @@ -28,12 +26,13 @@ include(${build_options_file}) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) -## -## Project Configuration -## +######################################################################## +## Project/Build Configuration project(BinPAC) +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) + if (ENABLE_DEBUG AND ENABLE_RELEASE) set(CMAKE_BUILD_TYPE RelWithDebInfo) elseif (ENABLE_DEBUG AND NOT ENABLE_RELEASE) @@ -57,34 +56,28 @@ if (NOT EXTRA_COMPILE_FLAGS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_COMPILE_FLAGS}") endif () -## +######################################################################## ## Dependency Configuration -## find_package(FLEX REQUIRED) find_package(BISON REQUIRED) -## -## Configuration Checks/Tests -## - -file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) +######################################################################## +## System Introspection configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) include_directories(${CMAKE_CURRENT_BINARY_DIR}) -## -## Recuse on sub-directories -## +######################################################################## +## Recurse on sub-directories add_subdirectory(lib) add_subdirectory(src) -## +######################################################################## ## Build Summary -## if (BinPAC_SKIP_INSTALL) set(binpac_install_summary "Install skipped") diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index 996bbf1c18..4eba7e2f61 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -9,10 +9,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/binpac.h.in include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) - -set(binpac_lib_SRCS - binpac_buffer.cc - binpac_bytestring.cc +set(binpac_headers ${CMAKE_CURRENT_BINARY_DIR}/binpac.h binpac_analyzer.h binpac_buffer.h @@ -21,6 +18,12 @@ set(binpac_lib_SRCS binpac_regex.h ) +set(binpac_lib_SRCS + binpac_buffer.cc + binpac_bytestring.cc + ${binpac_headers} +) + add_library(binpac_lib STATIC ${binpac_lib_SRCS}) set_target_properties(binpac_lib PROPERTIES OUTPUT_NAME binpac) @@ -28,12 +31,7 @@ set_target_properties(binpac_lib PROPERTIES OUTPUT_NAME binpac) if (NOT BinPAC_SKIP_INSTALL) install(TARGETS binpac_lib DESTINATION lib) install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/binpac.h - binpac_analyzer.h - binpac_buffer.h - binpac_bytestring.h - binpac_exception.h - binpac_regex.h + ${binpac_headers} DESTINATION include ) From 6b1b6b178a2f7a9b1157608731da3dae44dd50be Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 2 Nov 2010 13:03:44 -0500 Subject: [PATCH 013/343] binpac: configure now writes directly to CMakeCache.txt The intermediate BuildOptions.cmake file is no longer needed. --- tools/binpac/CMakeLists.txt | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 3b567b2fc1..7e01686c1d 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -10,20 +10,6 @@ if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") "initialize the build configuration.") endif () -find_file(build_options_file - NAMES BuildOptions.cmake - PATHS ${CMAKE_BINARY_DIR} - DOC "Build Options" - NO_DEFAULT_PATH - ) -if (NOT build_options_file) - message(FATAL_ERROR "Build options file not found, please use " - "${CMAKE_SOURCE_DIR}/configure to generate one.") -endif () -mark_as_advanced(build_config_file) - -include(${build_options_file}) - set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) ######################################################################## From 173c3784abc991a9456f1e7b8779ca8843e7d7e4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Sat, 13 Nov 2010 20:09:47 -0600 Subject: [PATCH 014/343] binpac: Prepend build dir to search path. This avoids inclusion of conflicting superproject config.h. --- tools/binpac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 7e01686c1d..fb5f5b49ff 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -54,7 +54,7 @@ find_package(BISON REQUIRED) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) +include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) ######################################################################## ## Recurse on sub-directories From 32423cf27bf3a14520e896bd5e1d924fedee86dc Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 17 Nov 2010 19:14:47 -0600 Subject: [PATCH 015/343] binpac: Customizable error messages for missing prereqs. Adds the FindRequiredPackage() macro that wraps the functionality of the standard find_package() macro. --- tools/binpac/CMakeLists.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index fb5f5b49ff..ead7550646 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -45,8 +45,17 @@ endif () ######################################################################## ## Dependency Configuration -find_package(FLEX REQUIRED) -find_package(BISON REQUIRED) +include(FindRequiredPackage) + +FindRequiredPackage(FLEX) +FindRequiredPackage(BISON) + +if (MISSING_PREREQS) + foreach (prereq ${MISSING_PREREQ_DESCS}) + message(SEND_ERROR ${prereq}) + endforeach () + message(FATAL_ERROR "Configuration aborted due to missing prerequisites") +endif () ######################################################################## ## System Introspection From ed7e697d35ad828a4b0472565a8b0987bb08e137 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 18 Nov 2010 11:33:51 -0600 Subject: [PATCH 016/343] binpac: Changed default CMAKE_BUILD_TYPE to RelWithDebInfo The --enable-debug option of the configure wrapper changes it to Debug. Removed --enable-release option of the configure wrapper. --- tools/binpac/CMakeLists.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index ead7550646..6f5a3076ab 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -19,12 +19,10 @@ project(BinPAC) file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) -if (ENABLE_DEBUG AND ENABLE_RELEASE) - set(CMAKE_BUILD_TYPE RelWithDebInfo) -elseif (ENABLE_DEBUG AND NOT ENABLE_RELEASE) +if (ENABLE_DEBUG) set(CMAKE_BUILD_TYPE Debug) -elseif (NOT ENABLE_DEBUG AND ENABLE_RELEASE) - set(CMAKE_BUILD_TYPE Release) +else () + set(CMAKE_BUILD_TYPE RelWithDebInfo) endif () # don't set extra compile flags again if already declared in this scope @@ -89,7 +87,6 @@ message( "\n" "\nInstall prefix: ${binpac_install_summary}" "\nDebug mode: ${ENABLE_DEBUG}" - "\nRelease mode: ${ENABLE_RELEASE}" "\n" "\nCC: ${CMAKE_C_COMPILER}" "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" From aacc6ee0435d3cb65ee89b1dcbdd40fd104a7ff2 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Sat, 20 Nov 2010 11:42:57 -0600 Subject: [PATCH 017/343] binpac: Added uninstall target --- tools/binpac/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 6f5a3076ab..2009a444e8 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -12,6 +12,14 @@ endif () set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +# uninstall target +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + @ONLY) + +add_custom_target(uninstall COMMAND + ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) + ######################################################################## ## Project/Build Configuration From 67e5bc71982f079efffe70319964b5b88b861882 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Sat, 20 Nov 2010 12:15:17 -0600 Subject: [PATCH 018/343] binpac: Made uninstall target cooperate with other projects --- tools/binpac/CMakeLists.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 2009a444e8..d969ddc49e 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,3 +1,5 @@ +project(BinPAC) + ######################################################################## ## CMake Configuration @@ -12,19 +14,19 @@ endif () set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) -# uninstall target -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - @ONLY) +if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") + # uninstall target + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + @ONLY) -add_custom_target(uninstall COMMAND - ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) + add_custom_target(uninstall COMMAND + ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +endif () ######################################################################## ## Project/Build Configuration -project(BinPAC) - file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) if (ENABLE_DEBUG) From 71cc7e9d5b170bc906ac8b66a5891d3974634b3f Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 26 Nov 2010 16:30:52 -0800 Subject: [PATCH 019/343] binpac: Cleaning up. --- tools/binpac/lib/Makefile.am | 8 ----- tools/binpac/src/Makefile.am | 62 ------------------------------------ 2 files changed, 70 deletions(-) delete mode 100644 tools/binpac/lib/Makefile.am delete mode 100644 tools/binpac/src/Makefile.am diff --git a/tools/binpac/lib/Makefile.am b/tools/binpac/lib/Makefile.am deleted file mode 100644 index 7ff8dca88f..0000000000 --- a/tools/binpac/lib/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -## Process this file with automake to produce Makefile.in - -noinst_LIBRARIES = libbinpac.a - -libbinpac_a_SOURCES = \ - binpac_buffer.cc binpac_bytestring.cc \ - binpac.h binpac_analyzer.h binpac_buffer.h \ - binpac_bytestring.h binpac_exception.h binpac_regex.h diff --git a/tools/binpac/src/Makefile.am b/tools/binpac/src/Makefile.am deleted file mode 100644 index 2dc2816c35..0000000000 --- a/tools/binpac/src/Makefile.am +++ /dev/null @@ -1,62 +0,0 @@ -## Process this file with automake to produce Makefile.in - -AM_YFLAGS = -d -t -v -AM_CPPFLAGS = -W -Wall -Wno-unused - -noinst_PROGRAMS = binpac - -binpac_SOURCES = \ - pac_scan.ll pac_parse.yy \ - pac_action.cc \ - pac_analyzer.cc \ - pac_array.cc \ - pac_attr.cc \ - pac_btype.cc \ - pac_case.cc \ - pac_conn.cc \ - pac_context.cc \ - pac_cstr.cc \ - pac_datadep.cc \ - pac_dataptr.cc \ - pac_dataunit.cc \ - pac_decl.cc \ - pac_embedded.cc \ - pac_enum.cc \ - pac_expr.cc \ - pac_exttype.cc \ - pac_field.cc \ - pac_flow.cc \ - pac_func.cc \ - pac_id.cc \ - pac_inputbuf.cc \ - pac_let.cc \ - pac_param.cc \ - pac_paramtype.cc \ - pac_primitive.cc \ - pac_record.cc \ - pac_redef.cc \ - pac_regex.cc \ - pac_state.cc \ - pac_strtype.cc \ - pac_type.cc \ - pac_typedecl.cc \ - pac_withinput.cc \ - pac_output.cc pac_utils.cc pac_exception.cc \ - pac_main.cc \ - pac_action.h pac_analyzer.h pac_array.h pac_attr.h pac_btype.h \ - pac_case.h pac_cclass.h pac_common.h pac_conn.h pac_context.h \ - pac_cstr.h pac_ctype.h pac_datadep.h pac_dataptr.h pac_dataunit.h \ - pac_dbg.h pac_decl-inl.h pac_decl.h pac_embedded.h pac_enum.h \ - pac_exception.h pac_expr.h pac_exttype.h pac_field.h pac_flow.h \ - pac_func.h pac_id.h pac_inputbuf.h pac_let.h pac_number.h \ - pac_output.h pac_param.h pac_paramtype.h pac_parse.h pac_primitive.h \ - pac_record.h pac_redef.h pac_regex.h pac_state.h pac_strtype.h \ - pac_type.h pac_typedecl.h pac_utils.h pac_varfield.h pac_withinput.h - -EXTRA_DIST = pac_expr.def pac_type.def pac_externtype.def - -DISTCLEANFILES = pac_parse.cc pac_parse.h pac_scan.cc y.output - -# Manual rules below: - -pac_scan.o: pac_parse.h From 4dd640d0f78e9dccbea66e9fd6ac42d1c659148a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 30 Nov 2010 13:18:21 -0600 Subject: [PATCH 020/343] binpac: CMake 2.6 compatibility changes --- tools/binpac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index d969ddc49e..6f1e549207 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -3,7 +3,7 @@ project(BinPAC) ######################################################################## ## CMake Configuration -cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +cmake_minimum_required(VERSION 2.6 FATAL_ERROR) # Prohibit in-source builds. if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") From 2260d6c60e7eaf9a8550f2e002064ba4df187f86 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 11 Jan 2011 16:03:49 -0600 Subject: [PATCH 021/343] binpac: Add warning when building and installing are done by different users --- tools/binpac/CMakeLists.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 6f1e549207..cc255c9a01 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -106,3 +106,17 @@ message( "\n" "\n================================================================\n" ) + +######################################################################## +## Show warning when installing user is different from the one that configured + +install(CODE " + if (NOT $ENV{USER} STREQUAL \$ENV{USER}) + message(STATUS \"ATTENTION: Install is being performed by user \" + \"'\$ENV{USER}', but the build directory was configured by \" + \"user '$ENV{USER}'. This may result in a permissions error \" + \"when writing the install manifest, but you can ignore it \" + \"and consider the installation as successful if you don't \" + \"care about the install manifest.\") + endif () +") From c2dbefab17c0d60ed6c02c29d584acda55147d01 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 19 Jan 2011 14:54:59 -0600 Subject: [PATCH 022/343] binpac: MacPorts & Fink paths now prepended to default search prefixes --- tools/binpac/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index cc255c9a01..09cc538e5e 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -53,6 +53,7 @@ endif () ######################################################################## ## Dependency Configuration +include(MacDependencyPaths) include(FindRequiredPackage) FindRequiredPackage(FLEX) From 1a15b968e652868c8d7476cb8e38031920ca593f Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Thu, 20 Jan 2011 15:34:39 -0500 Subject: [PATCH 023/343] binpac: Added an option to quiet the status output from binpac. This adds the -q command line flag to quiet the output. It also fixes a small compiler warning. --- tools/binpac/src/pac_common.h | 1 + tools/binpac/src/pac_main.cc | 8 +++++++- tools/binpac/src/pac_scan.ll | 3 ++- tools/binpac/src/pac_typedecl.cc | 6 ++++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/binpac/src/pac_common.h b/tools/binpac/src/pac_common.h index 81e59c184e..079e14ac1f 100644 --- a/tools/binpac/src/pac_common.h +++ b/tools/binpac/src/pac_common.h @@ -12,6 +12,7 @@ using namespace std; extern bool FLAGS_pac_debug; +extern bool FLAGS_quiet; extern vector FLAGS_include_directories; extern string input_filename; extern int line_number; diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index 6b6fe64a63..68405effef 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -21,6 +21,7 @@ extern void switch_to_file(FILE* fp_input); string input_filename; bool FLAGS_pac_debug = false; +bool FLAGS_quiet = false; string FLAGS_output_directory; vector FLAGS_include_directories; @@ -192,6 +193,7 @@ void usage() fprintf(stderr, " | pac-language input files\n"); fprintf(stderr, " -d | use given directory for compiler output\n"); fprintf(stderr, " -D | enable debugging output\n"); + fprintf(stderr, " -q | stay quiet\n"); fprintf(stderr, " -h | show command line help\n"); fprintf(stderr, " -I | include in input file search path\n"); exit(1); @@ -203,7 +205,7 @@ int main(int argc, char* argv[]) extern char *malloc_options; #endif int o; - while ( (o = getopt(argc, argv, "DI:d:h")) != -1 ) + while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 ) { switch(o) { @@ -214,6 +216,10 @@ int main(int argc, char* argv[]) malloc_options = "A"; #endif break; + + case 'q': + FLAGS_quiet = true; + break; case 'I': // Add to FLAGS_include_directories diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index ec435ea4ea..79743b540c 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -313,7 +313,8 @@ void switch_to_file(const char *filename) input_filename = string(filename); line_number = 1; switch_to_file(yyin); - fprintf(stderr, "switching to file %s\n", input_filename.c_str()); + if ( !FLAGS_quiet ) + fprintf(stderr, "switching to file %s\n", input_filename.c_str()); } void include_file(const char *filename) diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc index c989869d20..35d52a098e 100644 --- a/tools/binpac/src/pac_typedecl.cc +++ b/tools/binpac/src/pac_typedecl.cc @@ -94,7 +94,8 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc) if ( type_->tot() == Type::EXTERN || type_->tot() == Type::STRING ) return; - fprintf(stderr, "Generating code for %s\n", class_name().c_str()); + if ( !FLAGS_quiet ) + fprintf(stderr, "Generating code for %s\n", class_name().c_str()); if ( RequiresAnalyzerContext::compute(type_) ) { @@ -125,7 +126,8 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc) out_h->println(""); out_h->print("class %s", class_name().c_str()); bool first = true; - foreach(i, vector, &base_classes) + vector::iterator i; + for ( i = (&base_classes)->begin(); i != (&base_classes)->end(); ++i ) { if ( first ) { From e7e2ee38e75ea3cf5a835aee9c01f397775c6cdd Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 9 Mar 2011 11:47:28 -0600 Subject: [PATCH 024/343] binpac: Add explicit CMake check for compiler --- tools/binpac/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 09cc538e5e..3f7ee54de1 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,4 +1,12 @@ -project(BinPAC) +project(BinPAC C CXX) + +if (NOT CMAKE_C_COMPILER) + message(FATAL_ERROR "Could not find prerequisite C compiler") +endif () + +if (NOT CMAKE_CXX_COMPILER) + message(FATAL_ERROR "Could not find prerequisite C++ compiler") +endif () ######################################################################## ## CMake Configuration From d41a2def5a06d562ba7f4d6d50aebd1929532fce Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 11 Apr 2011 08:22:16 -0700 Subject: [PATCH 025/343] binpac: Fixing crash with undefined case expressions. Found by Emmanuele Zambon. --- tools/binpac/src/pac_expr.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index 02303bc953..2047d2269d 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -242,6 +242,11 @@ void Expr::GenCaseEval(Output *out_cc, Env *env) Type *val_type = DataType(env); ID *val_var = env->AddTempID(val_type); + // DataType(env) can return a null pointer if an enum value is not + // defined. + if ( ! val_type ) + throw Exception(this, "undefined case value"); + out_cc->println("%s %s;", val_type->DataTypeStr().c_str(), env->LValue(val_var)); From 50f5a913c3cccbdd2fcb80757b64619e1c01b004 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 12 Apr 2011 11:45:56 -0500 Subject: [PATCH 026/343] binpac: Adding files to CMake build targets so they show up in generated IDE projects. This addresses #413. --- tools/binpac/lib/CMakeLists.txt | 1 + tools/binpac/src/CMakeLists.txt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index 4eba7e2f61..bac8a2bebe 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -10,6 +10,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/binpac.h.in include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) set(binpac_headers + binpac.h.in ${CMAKE_CURRENT_BINARY_DIR}/binpac.h binpac_analyzer.h binpac_buffer.h diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 5e9881138c..127a6b90a3 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -9,6 +9,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) set(binpac_SRCS + ${BISON_PACParser_INPUT} + ${FLEX_PACScanner_INPUT} ${BISON_PACParser_OUTPUTS} ${FLEX_PACScanner_OUTPUTS} pac_action.cc From 1d6cea8c52068f9b9dd1fb7a847778bfcfd892f6 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 27 Jan 2012 22:32:50 -0500 Subject: [PATCH 027/343] binpac: Adding int64 and uint64 types to binpac. --- tools/binpac/lib/binpac.h.in | 33 ++++++++++++++++++++++++++++++--- tools/binpac/src/pac_btype.cc | 6 ++++-- tools/binpac/src/pac_main.cc | 5 +++++ tools/binpac/src/pac_parse.yy | 4 ++-- tools/binpac/src/pac_type.def | 2 ++ 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index c7e8eac515..eaef8e7fcd 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -35,9 +35,11 @@ const int unspecified_byteorder = -1; typedef char int8; typedef short int16; typedef long int32; -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; +typedef long long int64; +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef unsigned long long uint64; typedef void *nullptr; typedef void *voidptr; typedef uint8 *byteptr; @@ -80,6 +82,31 @@ inline uint32 pac_swap(uint32 x) ((x & 0xff) << 24); } +inline int64 pac_swap(int64 x) + { + return (x >> 56) | + ((x & 0xff000000000000) >> 40) | + ((x & 0xff0000000000) >> 24) | + ((x & 0xff00000000) >> 8) | + ((x & 0xff000000) << 8) | + ((x & 0xff0000) << 24) | + ((x & 0xff00) << 40) | + ((x & 0xff) << 56); + } + +inline uint64 pac_swap(uint64 x) + { + return (x >> 56) | + ((x & 0xff000000000000) >> 40) | + ((x & 0xff0000000000) >> 24) | + ((x & 0xff00000000) >> 8) | + ((x & 0xff000000) << 8) | + ((x & 0xff0000) << 24) | + ((x & 0xff00) << 40) | + ((x & 0xff) << 56); + } + + #define FixByteOrder(byteorder, x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap(x)) template diff --git a/tools/binpac/src/pac_btype.cc b/tools/binpac/src/pac_btype.cc index a7df6f7bf3..c565932d24 100644 --- a/tools/binpac/src/pac_btype.cc +++ b/tools/binpac/src/pac_btype.cc @@ -11,8 +11,8 @@ Type *BuiltInType::DoClone() const bool BuiltInType::IsNumericType() const { BITType t = bit_type(); - return (t == INT8 || t == INT16 || t == INT32 || - t == UINT8 || t == UINT16 || t == UINT32); + return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || + t == UINT8 || t == UINT16 || t == UINT32 || t == UINT64); } bool BuiltInType::CompatibleBuiltInTypes(BuiltInType *type1, @@ -125,6 +125,8 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, case UINT16: case INT32: case UINT32: + case INT64: + case UINT64: #if 0 out_cc->println("%s = UnMarshall<%s>(%s, %s);", lvalue(), diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index 68405effef..e104a86952 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -68,9 +68,13 @@ void insert_basictype_defs(Output* out) out->println("typedef char int8;"); out->println("typedef short int16;"); out->println("typedef long int32;"); + out->println("typedef long long int64;"); + out->println("typedef unsigned char uint8;"); out->println("typedef unsigned short uint16;"); out->println("typedef unsigned long uint32;"); + out->println("typedef unsigned long long uint64;"); + out->println(""); out->println("#endif /* pac_type_defs */"); out->println(""); @@ -80,6 +84,7 @@ void insert_byteorder_macros(Output* out) { out->println("#define FixByteOrder16(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap16(x))"); out->println("#define FixByteOrder32(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap32(x))"); + out->println("#define FixByteOrder64(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap64(x))"); out->println(""); } diff --git a/tools/binpac/src/pac_parse.yy b/tools/binpac/src/pac_parse.yy index 3d7f9a328f..d29e361910 100644 --- a/tools/binpac/src/pac_parse.yy +++ b/tools/binpac/src/pac_parse.yy @@ -6,8 +6,8 @@ %token TOK_RIGHTARROW TOK_DEFAULT TOK_OF %token TOK_PADDING TOK_TO TOK_ALIGN %token TOK_WITHINPUT -%token TOK_INT8 TOK_INT16 TOK_INT32 -%token TOK_UINT8 TOK_UINT16 TOK_UINT32 +%token TOK_INT8 TOK_INT16 TOK_INT32 TOK_INT64 +%token TOK_UINT8 TOK_UINT16 TOK_UINT32 TOK_UINT64 %token TOK_ID TOK_NUMBER TOK_REGEX TOK_STRING %token TOK_BEGIN_RE TOK_END_RE %token TOK_ATTR_ALSO diff --git a/tools/binpac/src/pac_type.def b/tools/binpac/src/pac_type.def index 62939ec671..a34c3547c2 100644 --- a/tools/binpac/src/pac_type.def +++ b/tools/binpac/src/pac_type.def @@ -2,7 +2,9 @@ TYPE_DEF(INT8, "int8", "int8", 1) TYPE_DEF(INT16, "int16", "int16", 2) TYPE_DEF(INT32, "int32", "int32", 4) +TYPE_DEF(INT64, "int64", "int64", 8) TYPE_DEF(UINT8, "uint8", "uint8", 1) TYPE_DEF(UINT16, "uint16", "uint16", 2) TYPE_DEF(UINT32, "uint32", "uint32", 4) +TYPE_DEF(UINT64, "uint64", "uint64", 8) TYPE_DEF(EMPTY, "empty", "", 0) From 77e4315a57cde4854d69b2f0129c0fde8a6bf446 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 8 Aug 2011 16:13:53 -0700 Subject: [PATCH 028/343] binpac: Fixing compiler warning --- tools/binpac/lib/binpac.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index eaef8e7fcd..16af8a18c5 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -40,7 +40,7 @@ typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; typedef unsigned long long uint64; -typedef void *nullptr; +typedef void *nulptr; typedef void *voidptr; typedef uint8 *byteptr; typedef const uint8 *const_byteptr; From a4f05185d67b3fcee0842132d8ab4a38310dd911 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 9 Aug 2011 13:33:58 -0500 Subject: [PATCH 029/343] binpac: Workaround for FreeBSD CMake port missing debug flags --- tools/binpac/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 3f7ee54de1..78da36410b 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -49,7 +49,8 @@ if (NOT EXTRA_COMPILE_FLAGS) set(EXTRA_COMPILE_FLAGS "-Wall -Wno-unused") if (ENABLE_DEBUG) - set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DDEBUG") + # manual add of -g works around its omission in FreeBSD's CMake port + set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -g -DDEBUG") endif () # Compiler flags may already exist in CMake cache (e.g. when specifying From 3841c68d87055a7024f4fe477dd883b5a8371699 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 2 Sep 2011 11:16:03 -0500 Subject: [PATCH 030/343] binpac: Install binaries with an RPATH --- tools/binpac/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 78da36410b..d4cd6e38dd 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -32,6 +32,14 @@ if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) endif () +# Keep RPATH upon installing so that user doesn't have to ensure the linker +# can find internal/private libraries or libraries external to the build +# directory that were explicitly linked against +if (NOT BINARY_PACKAGING_MODE) + SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +endif () + ######################################################################## ## Project/Build Configuration From 969998d1483e04745281488170f98bb364a0ee22 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 4 Aug 2011 15:11:10 -0500 Subject: [PATCH 031/343] binpac: Remove $Id$ tags --- tools/binpac/lib/binpac.h.in | 1 - tools/binpac/src/pac_dbg.h | 2 -- tools/binpac/src/pac_exception.h | 2 -- tools/binpac/src/pac_main.cc | 2 -- tools/binpac/src/pac_output.cc | 2 -- tools/binpac/src/pac_output.h | 2 -- tools/binpac/src/pac_parse.yy | 2 -- tools/binpac/src/pac_scan.ll | 2 -- tools/binpac/src/pac_utils.cc | 2 -- tools/binpac/src/pac_utils.h | 2 -- 10 files changed, 19 deletions(-) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index 16af8a18c5..051eede652 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -1,4 +1,3 @@ -// $Id: binpac.h,v 1.1.4.2 2006/06/02 15:13:13 rpang Exp $ // Do not edit binpac.h, edit binpac.h.in instead! #ifndef binpac_h diff --git a/tools/binpac/src/pac_dbg.h b/tools/binpac/src/pac_dbg.h index bcd87639fb..e24fdfcd9a 100644 --- a/tools/binpac/src/pac_dbg.h +++ b/tools/binpac/src/pac_dbg.h @@ -1,5 +1,3 @@ -/* $Id: pac_dbg.h 3265 2006-06-09 21:16:12Z rpang $ */ - #ifndef pac_dbg_h #define pac_dbg_h diff --git a/tools/binpac/src/pac_exception.h b/tools/binpac/src/pac_exception.h index 7653ffeacc..5508e75537 100644 --- a/tools/binpac/src/pac_exception.h +++ b/tools/binpac/src/pac_exception.h @@ -1,5 +1,3 @@ -// $Id: pac_exception.h 3225 2006-06-08 00:00:01Z vern $ - #ifndef pac_exception_h #define pac_exception_h diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index e104a86952..efb414fa7d 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -1,5 +1,3 @@ -// $Id: pac_main.cc 3320 2006-06-20 21:19:33Z rpang $ - #include #include diff --git a/tools/binpac/src/pac_output.cc b/tools/binpac/src/pac_output.cc index 404b4422cc..99af4bd400 100644 --- a/tools/binpac/src/pac_output.cc +++ b/tools/binpac/src/pac_output.cc @@ -1,5 +1,3 @@ -// $Id: pac_output.cc 3225 2006-06-08 00:00:01Z vern $ - #include #include #include diff --git a/tools/binpac/src/pac_output.h b/tools/binpac/src/pac_output.h index 9911f3a2b4..b9d99a7dc5 100644 --- a/tools/binpac/src/pac_output.h +++ b/tools/binpac/src/pac_output.h @@ -1,5 +1,3 @@ -// $Id: pac_output.h 3225 2006-06-08 00:00:01Z vern $ - #ifndef pac_output_h #define pac_output_h diff --git a/tools/binpac/src/pac_parse.yy b/tools/binpac/src/pac_parse.yy index d29e361910..58d66b8808 100644 --- a/tools/binpac/src/pac_parse.yy +++ b/tools/binpac/src/pac_parse.yy @@ -1,5 +1,3 @@ -/* $Id: pac_parse.yy 3225 2006-06-08 00:00:01Z vern $ */ - %token TOK_TYPE TOK_RECORD TOK_CASE TOK_ENUM TOK_LET TOK_FUNCTION %token TOK_REFINE TOK_CASEFUNC TOK_CASETYPE TOK_TYPEATTR %token TOK_HELPERHEADER TOK_HELPERCODE diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index 79743b540c..3961a28f3b 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -1,6 +1,4 @@ %{ -// $Id: pac_scan.ll 3361 2006-07-06 18:06:49Z rpang $ - #include "pac_action.h" #include "pac_array.h" #include "pac_attr.h" diff --git a/tools/binpac/src/pac_utils.cc b/tools/binpac/src/pac_utils.cc index a9118fc256..ac32edbad7 100644 --- a/tools/binpac/src/pac_utils.cc +++ b/tools/binpac/src/pac_utils.cc @@ -1,5 +1,3 @@ -// $Id: pac_utils.cc 3225 2006-06-08 00:00:01Z vern $ - #include #include #include diff --git a/tools/binpac/src/pac_utils.h b/tools/binpac/src/pac_utils.h index deef850245..37898e4070 100644 --- a/tools/binpac/src/pac_utils.h +++ b/tools/binpac/src/pac_utils.h @@ -1,5 +1,3 @@ -// $Id: pac_utils.h 3225 2006-06-08 00:00:01Z vern $ - #ifndef pac_utils_h #define pac_utils_h From 5db7ba405044076aacc63557ea7b044438ad5786 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 20 Sep 2011 09:48:32 -0500 Subject: [PATCH 032/343] binpac: Update to use cmake submodule --- tools/binpac/CMakeLists.txt | 80 +------------------------------------ 1 file changed, 2 insertions(+), 78 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index d4cd6e38dd..de5768d165 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,76 +1,12 @@ project(BinPAC C CXX) - -if (NOT CMAKE_C_COMPILER) - message(FATAL_ERROR "Could not find prerequisite C compiler") -endif () - -if (NOT CMAKE_CXX_COMPILER) - message(FATAL_ERROR "Could not find prerequisite C++ compiler") -endif () - -######################################################################## -## CMake Configuration - cmake_minimum_required(VERSION 2.6 FATAL_ERROR) - -# Prohibit in-source builds. -if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") - message(FATAL_ERROR "In-source builds are not allowed. Please use " - "./configure to choose a build directory and " - "initialize the build configuration.") -endif () - -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) - -if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") - # uninstall target - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - @ONLY) - - add_custom_target(uninstall COMMAND - ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) -endif () - -# Keep RPATH upon installing so that user doesn't have to ensure the linker -# can find internal/private libraries or libraries external to the build -# directory that were explicitly linked against -if (NOT BINARY_PACKAGING_MODE) - SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) - SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -endif () - -######################################################################## -## Project/Build Configuration +include(cmake/CommonCMakeConfig.cmake) file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) -if (ENABLE_DEBUG) - set(CMAKE_BUILD_TYPE Debug) -else () - set(CMAKE_BUILD_TYPE RelWithDebInfo) -endif () - -# don't set extra compile flags again if already declared in this scope -# (i.e. this project is included from Bro) -if (NOT EXTRA_COMPILE_FLAGS) - set(EXTRA_COMPILE_FLAGS "-Wall -Wno-unused") - - if (ENABLE_DEBUG) - # manual add of -g works around its omission in FreeBSD's CMake port - set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -g -DDEBUG") - endif () - - # Compiler flags may already exist in CMake cache (e.g. when specifying - # CFLAGS environment variable before running cmake for the the first time) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_COMPILE_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_COMPILE_FLAGS}") -endif () - ######################################################################## ## Dependency Configuration -include(MacDependencyPaths) include(FindRequiredPackage) FindRequiredPackage(FLEX) @@ -125,16 +61,4 @@ message( "\n================================================================\n" ) -######################################################################## -## Show warning when installing user is different from the one that configured - -install(CODE " - if (NOT $ENV{USER} STREQUAL \$ENV{USER}) - message(STATUS \"ATTENTION: Install is being performed by user \" - \"'\$ENV{USER}', but the build directory was configured by \" - \"user '$ENV{USER}'. This may result in a permissions error \" - \"when writing the install manifest, but you can ignore it \" - \"and consider the installation as successful if you don't \" - \"care about the install manifest.\") - endif () -") +include(UserChangedWarning) From 092d049f8ee958b3475b9486fb2a65bb743e9a66 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 22 Sep 2011 21:19:16 -0700 Subject: [PATCH 033/343] binpac: Arrays now suport the &transient attribute. If set, parsed elements won't actually be added to the array, and read access to the array aren't permitted. This is helpful to save memory in the case of large arrays for which elements don't need (or can't) be buffered. --- tools/binpac/src/pac_array.cc | 145 ++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 66 deletions(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 7477ba050b..1d38011780 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -92,6 +92,9 @@ Type *ArrayType::ElementDataType() const string ArrayType::EvalElement(const string &array, const string &index) const { + if ( attr_transient_ ) + throw Exception(this, "cannot access element in &transient array"); + return strfmt("(*(%s))[%s]", array.c_str(), index.c_str()); } @@ -130,18 +133,18 @@ void ArrayType::ProcessAttr(Attr *a) { if ( elemtype_->StaticSize(env()) != 1 ) { - throw Exception(elemtype_, + throw Exception(elemtype_, "&restofdata can be applied" " to only byte arrays"); } if ( length_ ) { - throw Exception(length_, + throw Exception(length_, "&restofdata cannot be applied" " to arrays with specified length"); } attr_restofdata_ = true; - // As the array automatically extends to the end of + // As the array automatically extends to the end of // data, we do not have to check boundary. SetBoundaryChecked(); } @@ -158,7 +161,7 @@ void ArrayType::ProcessAttr(Attr *a) bool ref_input = a->expr()->HasReference(input_macro_id); if ( ref_element && ref_input ) { - throw Exception(a->expr(), + throw Exception(a->expr(), "cannot reference both $element and $input " "in the same &until---please separate them."); } @@ -167,7 +170,7 @@ void ArrayType::ProcessAttr(Attr *a) { if ( attr_until_element_expr_ ) { - throw Exception(a->expr(), + throw Exception(a->expr(), "multiple &until on $element"); } attr_until_element_expr_ = a->expr(); @@ -176,7 +179,7 @@ void ArrayType::ProcessAttr(Attr *a) { if ( attr_until_input_expr_ ) { - throw Exception(a->expr(), + throw Exception(a->expr(), "multiple &until on $input"); } attr_until_input_expr_ = a->expr(); @@ -185,7 +188,7 @@ void ArrayType::ProcessAttr(Attr *a) { if ( attr_generic_until_expr_ ) { - throw Exception(a->expr(), + throw Exception(a->expr(), "multiple &until condition"); } attr_generic_until_expr_ = a->expr(); @@ -206,15 +209,15 @@ void ArrayType::Prepare(Env *env, int flags) ID *elem_var = new ID(fmt("%s__elem", value_var()->Name())); ID *elem_it_var = new ID(fmt("%s__it", elem_var->Name())); - elem_var_field_ = + elem_var_field_ = new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_); AddField(elem_var_field_); if ( incremental_parsing() ) { - arraylength_var_field_ = + arraylength_var_field_ = new PrivVarField(arraylength_var, extern_type_int->Clone()); - elem_it_var_field_ = + elem_it_var_field_ = new PrivVarField(elem_it_var, extern_type_int->Clone()); AddField(arraylength_var_field_); @@ -222,25 +225,25 @@ void ArrayType::Prepare(Env *env, int flags) } else { - arraylength_var_field_ = + arraylength_var_field_ = new TempVarField(arraylength_var, extern_type_int->Clone()); - elem_it_var_field_ = + elem_it_var_field_ = new TempVarField(elem_it_var, extern_type_int->Clone()); arraylength_var_field_->Prepare(env); elem_it_var_field_->Prepare(env); // Add elem_dataptr_var only when not parsing incrementally - ID *elem_dataptr_var = + ID *elem_dataptr_var = new ID(fmt("%s__dataptr", elem_var->Name())); elem_dataptr_var_field_ = new TempVarField( - elem_dataptr_var, + elem_dataptr_var, extern_type_const_byteptr->Clone()); elem_dataptr_var_field_->Prepare(env); // until(dataptr >= end_of_data) elem_dataptr_until_expr_ = new Expr( - Expr::EXPR_GE, + Expr::EXPR_GE, new Expr(elem_dataptr_var->clone()), new Expr(end_of_data->clone())); } @@ -269,8 +272,8 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) if ( length_ ) { - out_cc->println("%s = %s;", - env->LValue(arraylength_var()), + out_cc->println("%s = %s;", + env->LValue(arraylength_var()), length_->EvalExpr(out_cc, env)); env->SetEvaluated(arraylength_var()); @@ -285,22 +288,22 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) env->LValue(arraylength_var())); out_cc->println("}"); out_cc->dec_indent(); - + // Check negative array length out_cc->println("if ( %s < 0 )", - env->LValue(arraylength_var())); + env->LValue(arraylength_var())); out_cc->inc_indent(); out_cc->println("{"); out_cc->println("%s = 0;", - env->LValue(arraylength_var())); + env->LValue(arraylength_var())); out_cc->println("}"); out_cc->dec_indent(); } else if ( attr_restofdata_ ) { ASSERT(elemtype_->StaticSize(env) == 1); - out_cc->println("%s = (%s) - (%s);", - env->LValue(arraylength_var()), + out_cc->println("%s = (%s) - (%s);", + env->LValue(arraylength_var()), env->RValue(end_of_data), data.ptr_expr()); env->SetEvaluated(arraylength_var()); @@ -313,6 +316,9 @@ void ArrayType::GenPubDecls(Output *out_h, Env *env) if ( declared_as_type() ) { + if ( attr_transient_ ) + throw Exception(this, "cannot access element in &transient array"); + out_h->println("int size() const { return %s ? %s->size() : 0; }", env->RValue(value_var()), env->RValue(value_var())); @@ -339,7 +345,7 @@ void ArrayType::GenInitCode(Output *out_cc, Env *env) Type::GenInitCode(out_cc, env); if ( incremental_parsing() ) { - out_cc->println("%s = -1;", + out_cc->println("%s = -1;", env->LValue(elem_it_var())); } } @@ -352,10 +358,10 @@ void ArrayType::GenCleanUpCode(Output *out_cc, Env *env) if ( ! elem_var_field_ ) { ID *elem_var = new ID(fmt("%s__elem", value_var()->Name())); - elem_var_field_ = + elem_var_field_ = new ParseVarField( - Field::NOT_CLASS_MEMBER, - elem_var, + Field::NOT_CLASS_MEMBER, + elem_var, elemtype_); elem_var_field_->Prepare(env); } @@ -368,9 +374,9 @@ void ArrayType::GenCleanUpCode(Output *out_cc, Env *env) env->RValue(value_var())); out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("%s %s = (*%s)[i];", - elemtype_->DataTypeStr().c_str(), - env->LValue(elem_var()), + out_cc->println("%s %s = (*%s)[i];", + elemtype_->DataTypeStr().c_str(), + env->LValue(elem_var()), lvalue()); elemtype_->GenCleanUpCode(out_cc, env); out_cc->println("}"); @@ -389,7 +395,7 @@ string ArrayType::GenArrayInit(Output *out_cc, Env *env, bool known_array_length array_str = lvalue(); if ( incremental_parsing() ) { - out_cc->println("if ( %s < 0 )", + out_cc->println("if ( %s < 0 )", env->LValue(elem_it_var())); out_cc->inc_indent(); out_cc->println("{"); @@ -397,12 +403,12 @@ string ArrayType::GenArrayInit(Output *out_cc, Env *env, bool known_array_length out_cc->println("%s = 0;", env->LValue(elem_it_var())); } - out_cc->println("%s = new %s;", + out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); if ( known_array_length ) { - out_cc->println("%s->reserve(%s);", + out_cc->println("%s->reserve(%s);", lvalue(), env->RValue(arraylength_var())); } @@ -418,23 +424,30 @@ string ArrayType::GenArrayInit(Output *out_cc, Env *env, bool known_array_length void ArrayType::GenElementAssignment(Output *out_cc, Env *env, string const &array_str, bool use_vector) { + if ( attr_transient_ ) + { + // Just discard. + out_cc->println("delete %s;", env->LValue(elem_var())); + return; + } + // Assign the element if ( ! use_vector ) { - out_cc->println("%s[%s] = %s;", - array_str.c_str(), - env->LValue(elem_it_var()), + out_cc->println("%s[%s] = %s;", + array_str.c_str(), + env->LValue(elem_it_var()), env->LValue(elem_var())); } else { - out_cc->println("%s->push_back(%s);", - array_str.c_str(), + out_cc->println("%s->push_back(%s);", + array_str.c_str(), env->LValue(elem_var())); } } -void ArrayType::DoGenParseCode(Output *out_cc, Env *env, +void ArrayType::DoGenParseCode(Output *out_cc, Env *env, const DataPtr& data, int flags) { GenArrayLength(out_cc, env, data); @@ -466,10 +479,10 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, { // Do not compute size_var on incremental input compute_size_var = false; - + if ( ! incremental_parsing() && ( StaticSize(env) >= 0 || - ( env->Evaluated(arraylength_var()) && + ( env->Evaluated(arraylength_var()) && elemtype_->StaticSize(env) >= 0 ) ) ) { GenBoundaryCheck(out_cc, env, data); @@ -491,7 +504,7 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, if ( elem_dataptr_var() ) { - out_cc->println("const_byteptr %s = %s;", + out_cc->println("const_byteptr %s = %s;", env->LValue(elem_dataptr_var()), data.ptr_expr()); env->SetEvaluated(elem_dataptr_var()); @@ -499,13 +512,13 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, } string for_condition = known_array_length ? - strfmt("%s < %s", - env->LValue(elem_it_var()), + strfmt("%s < %s", + env->LValue(elem_it_var()), env->RValue(arraylength_var())) : "/* forever */"; - out_cc->println("for (; %s; ++%s)", - for_condition.c_str(), + out_cc->println("for (; %s; ++%s)", + for_condition.c_str(), env->LValue(elem_it_var())); out_cc->inc_indent(); out_cc->println("{"); @@ -515,13 +528,13 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, if ( elem_dataptr_var() ) GenUntilCheck(out_cc, env, elem_dataptr_until_expr_, false); - + elemtype_->GenPreParsing(out_cc, env); elemtype_->GenParseCode(out_cc, env, elem_data, flags); - if ( incremental_parsing() ) + if ( incremental_parsing() ) { - out_cc->println("if ( ! %s )", + out_cc->println("if ( ! %s )", elemtype_->parsing_complete(env).c_str()); out_cc->inc_indent(); out_cc->println("goto %s;", kNeedMoreData); @@ -532,11 +545,11 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, if ( elem_dataptr_var() ) { - out_cc->println("%s += %s;", - env->LValue(elem_dataptr_var()), + out_cc->println("%s += %s;", + env->LValue(elem_dataptr_var()), elemtype_->DataSize(0, env, elem_data).c_str()); out_cc->println("BINPAC_ASSERT(%s <= %s);", - env->RValue(elem_dataptr_var()), + env->RValue(elem_dataptr_var()), env->RValue(end_of_data)); } @@ -556,7 +569,7 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) ) { // Compute the data size - out_cc->println("%s = %s - (%s);", + out_cc->println("%s = %s - (%s);", env->LValue(size_var()), env->RValue(elem_dataptr_var()), data.ptr_expr()); @@ -572,7 +585,7 @@ void ArrayType::GenUntilInputCheck(Output *out_cc, Env *env) elem_input_var_id, extern_type_const_bytestring->Clone()); elem_input_var_field_->Prepare(env); - out_cc->println("%s %s(%s, %s);", + out_cc->println("%s %s(%s, %s);", extern_type_const_bytestring->DataTypeStr().c_str(), env->LValue(elem_input_var()), env->RValue(begin_of_data), @@ -582,22 +595,22 @@ void ArrayType::GenUntilInputCheck(Output *out_cc, Env *env) GenUntilCheck(out_cc, env, attr_until_input_expr_, true); } -void ArrayType::GenUntilCheck(Output *out_cc, Env *env, +void ArrayType::GenUntilCheck(Output *out_cc, Env *env, Expr *until_expr, bool delete_elem) { ASSERT(until_expr); Env check_env(env, this); - check_env.AddMacro(element_macro_id, + check_env.AddMacro(element_macro_id, new Expr(elem_var()->clone())); if ( elem_input_var() ) { - check_env.AddMacro(input_macro_id, + check_env.AddMacro(input_macro_id, new Expr(elem_input_var()->clone())); } out_cc->println("// Check &until(%s)", until_expr->orig()); - out_cc->println("if ( %s )", + out_cc->println("if ( %s )", until_expr->EvalExpr(out_cc, &check_env)); out_cc->inc_indent(); out_cc->println("{"); @@ -624,12 +637,12 @@ void ArrayType::GenDynamicSize(Output *out_cc, Env *env, const DataPtr& data) { ASSERT(! incremental_input()); - DEBUG_MSG("Generating dynamic size for array `%s'\n", + DEBUG_MSG("Generating dynamic size for array `%s'\n", value_var()->Name()); int elem_w = elemtype_->StaticSize(env); if ( elem_w >= 0 && - ! attr_until_element_expr_ && + ! attr_until_element_expr_ && ! attr_until_input_expr_ && ( length_ || attr_restofdata_ ) ) { @@ -661,7 +674,7 @@ int ArrayType::StaticSize(Env *env) const if ( elem_w < 0 ) return -1; - DEBUG_MSG("static size of %s:%s = %d * %d\n", + DEBUG_MSG("static size of %s:%s = %d * %d\n", decl_id()->Name(), lvalue(), elem_w, num); return num * elem_w; @@ -675,18 +688,18 @@ void ArrayType::SetBoundaryChecked() void ArrayType::DoMarkIncrementalInput() { - elemtype_->MarkIncrementalInput(); + elemtype_->MarkIncrementalInput(); } bool ArrayType::RequiresAnalyzerContext() - { + { return Type::RequiresAnalyzerContext() || - ( length_ && length_->RequiresAnalyzerContext() ) || - elemtype_->RequiresAnalyzerContext(); + ( length_ && length_->RequiresAnalyzerContext() ) || + elemtype_->RequiresAnalyzerContext(); } bool ArrayType::DoTraverse(DataDepVisitor *visitor) - { + { if ( ! Type::DoTraverse(visitor) ) return false; @@ -694,7 +707,7 @@ bool ArrayType::DoTraverse(DataDepVisitor *visitor) return false; if ( ! elemtype_->Traverse(visitor) ) - return false; + return false; return true; } From fccf3a73403921a5ef22dc07431c694dcaf45a53 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 14 Oct 2011 12:12:33 -0700 Subject: [PATCH 034/343] binpac: Distribution cleanup. --- tools/binpac/patches/README | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tools/binpac/patches/README diff --git a/tools/binpac/patches/README b/tools/binpac/patches/README new file mode 100644 index 0000000000..1d3b116566 --- /dev/null +++ b/tools/binpac/patches/README @@ -0,0 +1,2 @@ +Note: It's unclear which of these patches have in fact already been +applied. We should figure that out ... From bf2184bb0fa26c5cf6986643adba8136ca8db22e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 24 Feb 2012 13:10:59 -0600 Subject: [PATCH 035/343] binpac: Raise minimum required CMake version to 2.6.3 --- tools/binpac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index de5768d165..17574e8a4e 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,5 +1,5 @@ project(BinPAC C CXX) -cmake_minimum_required(VERSION 2.6 FATAL_ERROR) +cmake_minimum_required(VERSION 2.6.3 FATAL_ERROR) include(cmake/CommonCMakeConfig.cmake) file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) From 8cf0be6d0fe55ca193b4dccfa506aae4e4825019 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 17 Apr 2012 11:21:57 -0500 Subject: [PATCH 036/343] binpac: Change binpac.h integral typedefs and reimplement 64-bit pac_swap(). Integer types now use , and the 64-bit byte-swapping function uses a union approach instead of masking/bit-shifting. Addresses #761. --- tools/binpac/lib/binpac.h.in | 62 ++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index 051eede652..8d7c137d7b 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -17,6 +17,7 @@ #include #include #include +#include #define BINPAC_ASSERT(x) assert(x) @@ -31,14 +32,14 @@ const int unspecified_byteorder = -1; #ifndef pac_type_defs #define pac_type_defs -typedef char int8; -typedef short int16; -typedef long int32; -typedef long long int64; -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; -typedef unsigned long long uint64; +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; typedef void *nulptr; typedef void *voidptr; typedef uint8 *byteptr; @@ -81,30 +82,37 @@ inline uint32 pac_swap(uint32 x) ((x & 0xff) << 24); } -inline int64 pac_swap(int64 x) +inline int64 pac_swap(int64 i) { - return (x >> 56) | - ((x & 0xff000000000000) >> 40) | - ((x & 0xff0000000000) >> 24) | - ((x & 0xff00000000) >> 8) | - ((x & 0xff000000) << 8) | - ((x & 0xff0000) << 24) | - ((x & 0xff00) << 40) | - ((x & 0xff) << 56); + unsigned char c; + union { + uint64 i; + unsigned char c[8]; + } x; + + x.i = i; + c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; + c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; + c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; + c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; + return x.i; } -inline uint64 pac_swap(uint64 x) +inline uint64 pac_swap(uint64 i) { - return (x >> 56) | - ((x & 0xff000000000000) >> 40) | - ((x & 0xff0000000000) >> 24) | - ((x & 0xff00000000) >> 8) | - ((x & 0xff000000) << 8) | - ((x & 0xff0000) << 24) | - ((x & 0xff00) << 40) | - ((x & 0xff) << 56); - } + unsigned char c; + union { + uint64 i; + unsigned char c[8]; + } x; + x.i = i; + c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; + c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; + c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; + c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; + return x.i; + } #define FixByteOrder(byteorder, x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap(x)) From 6c70f7851be86e92932f705adedd7caa758b2b75 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 24 Jul 2012 09:00:12 -0700 Subject: [PATCH 037/343] binpac: Silence warning for generated code when compiling with clang. --- tools/binpac/src/pac_main.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index efb414fa7d..adb8d0eb51 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -161,6 +161,12 @@ int compile(const char* filename) out_h.println("#include \"binpac.h\""); out_h.println(""); + out_cc.println(""); + out_cc.println("#ifdef __clang__"); + out_cc.println("#pragma clang diagnostic ignored \"-Wparentheses-equality\""); + out_cc.println("#endif"); + out_cc.println(""); + out_cc.println("#include \"%s.h\"\n", basename.c_str()); Decl::ProcessDecls(&out_h, &out_cc); From 14e3d5a1a3a7911f479975149d51ff428572ee24 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 12 Nov 2012 11:44:14 -0600 Subject: [PATCH 038/343] binpac: Add scoping to usages of binpac::Exception classes in generated code. This allows analyzers to define their own types of the same name without mistakingly overshadowing the usages of binpac::Exception and its derived types in the generated parser code. --- tools/binpac/src/pac_case.cc | 11 ++++++----- tools/binpac/src/pac_dataptr.cc | 2 +- tools/binpac/src/pac_expr.cc | 2 +- tools/binpac/src/pac_flow.cc | 2 +- tools/binpac/src/pac_record.cc | 2 +- tools/binpac/src/pac_strtype.cc | 5 +++-- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index b809d61b6e..90352a6333 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -168,7 +168,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, { out_cc->println("default:"); out_cc->inc_indent(); - out_cc->println("throw ExceptionInvalidCaseIndex(\"%s\", %s);", + out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", %s);", decl_id()->Name(), env->RValue(index_var_)); out_cc->println("break;"); out_cc->dec_indent(); @@ -302,10 +302,11 @@ void CaseField::GenPubDecls(Output* out_h, Env* env) out_h->println("default:"); out_h->inc_indent(); - out_h->println("throw ExceptionInvalidCase(\"%s\", %s, \"%s\");", - id_->LocName(), - env->RValue(index_var_), - OrigExprList(index_).c_str()); + out_h->println( + "throw binpac::ExceptionInvalidCase(\"%s\", %s, \"%s\");", + id_->LocName(), + env->RValue(index_var_), + OrigExprList(index_).c_str()); out_h->println("break;"); out_h->dec_indent(); diff --git a/tools/binpac/src/pac_dataptr.cc b/tools/binpac/src/pac_dataptr.cc index beac6997cb..44c497efea 100644 --- a/tools/binpac/src/pac_dataptr.cc +++ b/tools/binpac/src/pac_dataptr.cc @@ -52,7 +52,7 @@ void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, char* data_offset = AbsOffsetExpr(env, begin_of_data); out_cc->println("// Handle out-of-bound condition"); - out_cc->println("throw ExceptionOutOfBound(\"%s\",", data_name); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_name); out_cc->println(" (%s) + (%s), ", data_offset, data_size); out_cc->println(" (%s) - (%s));", diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index 2047d2269d..7b25ce5aaa 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -295,7 +295,7 @@ void Expr::GenCaseEval(Output *out_cc, Env *env) } else { - out_cc->println("throw ExceptionInvalidCaseIndex(\"%s\", %s);", + out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", %s);", Location(), operand_[0]->EvalExpr(out_cc, env)); } out_cc->println("break;"); diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index adf574e879..f7710a9c0c 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -226,7 +226,7 @@ void FlowDecl::GenProcessFunc(Output *out_h, Output *out_cc) out_cc->println("}"); out_cc->dec_indent(); - out_cc->println("catch ( Exception const &e )"); + out_cc->println("catch ( binpac::Exception const &e )"); out_cc->inc_indent(); out_cc->println("{"); GenCleanUpCode(out_cc); diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index 9875195033..fdfc6a7977 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -617,7 +617,7 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi field_begin.ptr_expr()); out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("// throw ExceptionInvalidOffset(\"%s\", %s - %s, %s);", + out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);", id_->LocName(), field_begin.ptr_expr(), env->RValue(begin_of_data), diff --git a/tools/binpac/src/pac_strtype.cc b/tools/binpac/src/pac_strtype.cc index 48e1eb5ad0..ebb9df4803 100644 --- a/tools/binpac/src/pac_strtype.cc +++ b/tools/binpac/src/pac_strtype.cc @@ -283,7 +283,8 @@ void StringType::DoGenParseCode(Output* out_cc, Env* env, out_cc->println("// check for negative sizes"); out_cc->println("if ( %s < 0 )", str_size.c_str()); - out_cc->println("throw ExceptionInvalidStringLength(\"%s\", %s);", + out_cc->println( + "throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), str_size.c_str()); out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), @@ -301,7 +302,7 @@ void StringType::DoGenParseCode(Output* out_cc, Env* env, void StringType::GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, const char *pattern) { - out_cc->println("throw ExceptionStringMismatch(\"%s\", %s, %s);", + out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", Location(), pattern, fmt("string((const char *) (%s), (const char *) %s).c_str()", From ce2b56751b469c25ddb54fe9485d9dfa2b1afd55 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 24 Apr 2013 15:25:59 -0500 Subject: [PATCH 039/343] binpac: Fix an exception slicing issue in binpac generated cleanup code. Switch to using a no-argument throw to preserve the dynamic type of the binpac exception. Otherwise, the exception is "sliced" and can only be subsequently handled as binpac::Exception and not a derived type. --- tools/binpac/src/pac_flow.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index f7710a9c0c..c92a8c93cc 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -235,7 +235,7 @@ void FlowDecl::GenProcessFunc(Output *out_h, Output *out_cc) out_cc->println("%s->DiscardData();", env_->LValue(flow_buffer_id)); } - out_cc->println("throw e;"); + out_cc->println("throw;"); out_cc->println("}"); out_cc->dec_indent(); From 61cc83affaeb7c757ecd4905d64f7cb9c7116b4b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 24 Jul 2013 18:32:09 -0700 Subject: [PATCH 040/343] binpac: Adding an interface to manually control the buffering for generated parsers. This consists of two parts: 1. The generated Flow classes expose their flow buffers via a new method flow_buffer(). 2. Flow buffers get two new methods: // Interface for delayed parsing. Sometimes BinPAC doesn't get the // buffering right and then one can use these to feed parts // individually and assemble them internally. After calling // FinishBuffer(), one can send the uppper-layer flow an FlowEOF() // to trigger parsing. void BufferData(const_byteptr data, const_byteptr end); void FinishBuffer(); --- tools/binpac/lib/binpac_buffer.cc | 13 +++++++++++++ tools/binpac/lib/binpac_buffer.h | 10 +++++++++- tools/binpac/src/pac_flow.cc | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index 1b12b58eab..b0fc4dfbce 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -137,6 +137,19 @@ void FlowBuffer::NewFrame(int frame_length, bool chunked) MarkOrCopyFrame(); } +void FlowBuffer::BufferData(const_byteptr data, const_byteptr end) + { + mode_ = FRAME_MODE; + frame_length_ += (end - data); + MarkOrCopyFrame(); + NewData(data, end); + } + +void FlowBuffer::FinishBuffer() + { + message_complete_ = true; + } + void FlowBuffer::GrowFrame(int length) { BINPAC_ASSERT(frame_length_ >= 0); diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h index 2eb197e7b9..ca39a6af15 100644 --- a/tools/binpac/lib/binpac_buffer.h +++ b/tools/binpac/lib/binpac_buffer.h @@ -8,7 +8,7 @@ namespace binpac { class FlowBuffer { public: - enum LineBreakStyle { + enum LineBreakStyle { CR_OR_LF, // CR or LF or CRLF STRICT_CRLF, // CR followed by LF CR_LF_NUL, // CR or LF or CR-LF or CR-NUL @@ -20,6 +20,14 @@ public: void NewData(const_byteptr begin, const_byteptr end); void NewGap(int length); + // Interface for delayed parsing. Sometimes BinPAC doesn't get the + // buffering right and then one can use these to feed parts + // individually and assemble them internally. After calling + // FinishBuffer(), one can send the uppper-layer flow an FlowEOF() to + // trigger parsing. + void BufferData(const_byteptr data, const_byteptr end); + void FinishBuffer(); + // Discard unprocessed data void DiscardData(); diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index c92a8c93cc..1a93b4b99f 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -68,7 +68,7 @@ void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) { dataunit_->data_type()->MarkIncrementalInput(); - flow_buffer_var_field_ = new PrivVarField( + flow_buffer_var_field_ = new PubVarField( flow_buffer_id->clone(), FlowDecl::flow_buffer_type()->Clone()); type_->AddField(flow_buffer_var_field_); From 871541e636933d9738fc561280f56d2160fbc94e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 10 Sep 2013 10:58:54 -0500 Subject: [PATCH 041/343] binpac: Fix double-free. The field is deleted by a base class dtor. --- tools/binpac/src/pac_let.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/binpac/src/pac_let.cc b/tools/binpac/src/pac_let.cc index ebd7caef90..fba5f1cfc8 100644 --- a/tools/binpac/src/pac_let.cc +++ b/tools/binpac/src/pac_let.cc @@ -133,7 +133,6 @@ LetDecl::LetDecl(ID *id, Type *type, Expr *expr) LetDecl::~LetDecl() { - delete id_; delete type_; delete expr_; } From cb524c2fde48134f18292fbf8483f4043f9e6379 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 10 Sep 2013 11:02:00 -0500 Subject: [PATCH 042/343] binpac: Fix two use-after-free bugs. --- tools/binpac/lib/binpac_exception.h | 2 +- tools/binpac/src/pac_field.cc | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h index 3feda3d69d..6debf54466 100644 --- a/tools/binpac/lib/binpac_exception.h +++ b/tools/binpac/lib/binpac_exception.h @@ -16,7 +16,7 @@ public: void append(string m) { msg_ += m; } string msg() const { return msg_; } - const char* c_msg() const { return msg().c_str(); } + const char* c_msg() const { return msg_.c_str(); } protected: string msg_; diff --git a/tools/binpac/src/pac_field.cc b/tools/binpac/src/pac_field.cc index 0ee70e4b28..7b7b337b1a 100644 --- a/tools/binpac/src/pac_field.cc +++ b/tools/binpac/src/pac_field.cc @@ -23,6 +23,8 @@ Field::~Field() void Field::AddAttr(AttrList* attrs) { + bool delete_attrs = false; + if ( ! attrs_ ) { attrs_ = attrs; @@ -30,11 +32,14 @@ void Field::AddAttr(AttrList* attrs) else { attrs_->insert(attrs_->end(), attrs->begin(), attrs->end()); - delete attrs; + delete_attrs = true; } foreach(i, AttrList, attrs) ProcessAttr(*i); + + if ( delete_attrs ) + delete attrs; } void Field::ProcessAttr(Attr *a) From 5e0f604418897975c1f45b46a3987bd0b0c831e4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 10 Sep 2013 11:30:13 -0500 Subject: [PATCH 043/343] binpac: Add missing va_end()'s to match va_start()'s. Probably not an issue on most implementations, but undefined behavior is scary and it's easy to fix. --- tools/binpac/src/pac_output.cc | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/tools/binpac/src/pac_output.cc b/tools/binpac/src/pac_output.cc index 99af4bd400..32875bdee6 100644 --- a/tools/binpac/src/pac_output.cc +++ b/tools/binpac/src/pac_output.cc @@ -41,7 +41,21 @@ int Output::print(const char* fmt, ...) { va_list ap; va_start(ap, fmt); - return print(fmt, ap); + int r = -1; + + try + { + r = print(fmt, ap); + } + + catch ( ... ) + { + va_end(ap); + throw; + } + + va_end(ap); + return r; } int Output::println(const char* fmt, ...) @@ -49,11 +63,22 @@ int Output::println(const char* fmt, ...) for ( int i = 0; i < indent(); ++i ) fprintf(fp, "\t"); - int r; va_list ap; va_start(ap, fmt); - r = print(fmt, ap); + int r = -1; + try + { + r = print(fmt, ap); + } + + catch ( ... ) + { + va_end(ap); + throw; + } + + va_end(ap); fprintf(fp, "\n"); return r; } From 8136abafef4872706d64b692ef0929d550c4ff86 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 10 Sep 2013 11:35:08 -0500 Subject: [PATCH 044/343] binpac: Remove unreachable code. --- tools/binpac/src/pac_cstr.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/binpac/src/pac_cstr.cc b/tools/binpac/src/pac_cstr.cc index 2d41bf7d1b..fb6db4b0b9 100644 --- a/tools/binpac/src/pac_cstr.cc +++ b/tools/binpac/src/pac_cstr.cc @@ -49,10 +49,7 @@ int expand_escape(const char*& s) int result; if ( sscanf(start, "%3o", &result) != 1 ) - { throw EscapeException(fmt("bad octal escape: \"%s", start)); - result = 0; - } return result; } @@ -68,10 +65,7 @@ int expand_escape(const char*& s) int result; if ( sscanf(start, "%2x", &result) != 1 ) - { throw EscapeException(fmt("bad hexadecimal escape: \"%s", start)); - result = 0; - } return result; } From 4d7de63ef00676b22d1a92cc037be1df4a6f59fe Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 10 Sep 2013 12:02:07 -0500 Subject: [PATCH 045/343] binpac: Add missing break to switch statement case. --- tools/binpac/src/pac_expr.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index 7b25ce5aaa..df499f7cef 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -802,6 +802,7 @@ int Expr::MinimalHeaderSize(Env *env) mhs = -1; } } + break; case EXPR_SIZEOF: { From 13e14768dafb1a180aad94e856103fafac510054 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 19 Sep 2013 12:33:57 -0500 Subject: [PATCH 046/343] binpac: Add virtual dtor to RefCount base class. The code generated for types w/ &refcount will subclass RefCount and Unref definitely deletes via a pointer to that base class so it needs a virtual dtor. --- tools/binpac/lib/binpac.h.in | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index 8d7c137d7b..f5c6e152c7 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -150,6 +150,7 @@ class RefCount { public: RefCount() { count = 1; } + virtual ~RefCount() {} void Ref() { ++count; } int Unref() { BINPAC_ASSERT(count > 0); return --count; } From 201b43f3bee9d9f5565467f2fa6fc78b9942df6d Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 25 Sep 2013 15:03:43 -0500 Subject: [PATCH 047/343] binpac: Optimize negative string length check. Strings with a constant &length expression can be checked for negative length values while generating the parser instead of in the parser itself (which likely just ends up being dead code). --- tools/binpac/src/pac_strtype.cc | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tools/binpac/src/pac_strtype.cc b/tools/binpac/src/pac_strtype.cc index ebb9df4803..2a80c005d7 100644 --- a/tools/binpac/src/pac_strtype.cc +++ b/tools/binpac/src/pac_strtype.cc @@ -280,12 +280,26 @@ void StringType::DoGenParseCode(Output* out_cc, Env* env, if ( ! anonymous_value_var() ) { // Set the value variable - out_cc->println("// check for negative sizes"); - out_cc->println("if ( %s < 0 )", - str_size.c_str()); - out_cc->println( - "throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", - Location(), str_size.c_str()); + + int len; + + if ( type_ == ANYSTR && attr_length_expr_ && + attr_length_expr_->ConstFold(env, &len) ) + { + // can check for a negative length now + if ( len < 0 ) + throw Exception(this, "negative &length on string"); + } + else + { + out_cc->println("// check for negative sizes"); + out_cc->println("if ( %s < 0 )", + str_size.c_str()); + out_cc->println( + "throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", + Location(), str_size.c_str()); + } + out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), data.ptr_expr(), From 81bf65e148bda592fdda4de32fe566dcb04e2cb5 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 25 Sep 2013 17:03:06 -0500 Subject: [PATCH 048/343] binpac: Generate initialization code for external types. Numeric/pointer types can be initialized to 0. --- tools/binpac/src/pac_exttype.cc | 8 ++++++++ tools/binpac/src/pac_exttype.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/tools/binpac/src/pac_exttype.cc b/tools/binpac/src/pac_exttype.cc index 659d4cdc5e..65c89245f9 100644 --- a/tools/binpac/src/pac_exttype.cc +++ b/tools/binpac/src/pac_exttype.cc @@ -1,6 +1,7 @@ #include "pac_exttype.h" #include "pac_id.h" #include "pac_decl.h" +#include "pac_output.h" bool ExternType::DefineValueVar() const { @@ -40,6 +41,13 @@ string ExternType::EvalMember(const ID *member_id) const member_id->Name()); } +void ExternType::GenInitCode(Output* out_cc, Env* env) + { + if ( IsNumericType() || IsPointerType() ) + out_cc->println("%s = 0;", env->LValue(value_var())); + Type::GenInitCode(out_cc, env); + } + void ExternType::DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) { ASSERT(0); diff --git a/tools/binpac/src/pac_exttype.h b/tools/binpac/src/pac_exttype.h index 6d81608195..a15ff6342e 100644 --- a/tools/binpac/src/pac_exttype.h +++ b/tools/binpac/src/pac_exttype.h @@ -26,6 +26,8 @@ public: bool IsNumericType() const { return ext_type_ == NUMBER; } bool IsPointerType() const { return ext_type_ == POINTER; } + void GenInitCode(Output *out_cc, Env *env); + protected: void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); void GenDynamicSize(Output *out, Env *env, const DataPtr& data); From a5fb8e3787245862c39c4dbdf028f62eb27ab9b1 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 27 Sep 2013 10:03:49 -0500 Subject: [PATCH 049/343] binpac: Fix uninitialized (or unused) fields. --- tools/binpac/src/pac_case.cc | 1 + tools/binpac/src/pac_decl.h | 2 -- tools/binpac/src/pac_exception.cc | 2 +- tools/binpac/src/pac_id.cc | 4 +++- tools/binpac/src/pac_paramtype.h | 1 - tools/binpac/src/pac_record.cc | 1 + tools/binpac/src/pac_typedecl.h | 2 -- 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index 90352a6333..42ef5fd15f 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -240,6 +240,7 @@ CaseField::CaseField(ExprList* index, ID* id, Type* type) ASSERT(type_); type_->set_value_var(id, MEMBER_VAR); case_type_ = 0; + index_var_ = 0; } CaseField::~CaseField() diff --git a/tools/binpac/src/pac_decl.h b/tools/binpac/src/pac_decl.h index 6151022d20..fc82f8ce34 100644 --- a/tools/binpac/src/pac_decl.h +++ b/tools/binpac/src/pac_decl.h @@ -42,7 +42,6 @@ protected: ID *id_; DeclType decl_type_; AttrList *attrlist_; - ExprList *expr_list_; AnalyzerContextDecl *analyzer_context_; public: @@ -72,7 +71,6 @@ public: private: HelperType helper_type_; ID *context_id_; - ID *helper_id_; EmbeddedCode *code_; static int helper_id_seq; diff --git a/tools/binpac/src/pac_exception.cc b/tools/binpac/src/pac_exception.cc index 462ef8e18f..b614c2a6f6 100644 --- a/tools/binpac/src/pac_exception.cc +++ b/tools/binpac/src/pac_exception.cc @@ -64,7 +64,7 @@ ExceptionPaddingError::ExceptionPaddingError(const Object* o, const char* msg) } ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) - : Exception(expr) + : Exception(expr), expr(expr) { append(fmt("Expression `%s' is not constant", expr->orig())); } diff --git a/tools/binpac/src/pac_id.cc b/tools/binpac/src/pac_id.cc index 5eb7a0d985..b8431e6f0a 100644 --- a/tools/binpac/src/pac_id.cc +++ b/tools/binpac/src/pac_id.cc @@ -90,8 +90,10 @@ IDRecord::IDRecord(Env *arg_env, const ID* arg_id, IDType arg_id_type) lvalue = "@FUNC_PARAM@"; break; } + data_type = 0; field = 0; - constant_set = false; + constant = constant_set = false; + macro = 0; } IDRecord::~IDRecord() diff --git a/tools/binpac/src/pac_paramtype.h b/tools/binpac/src/pac_paramtype.h index 4a2ef4e1d7..743af1cad6 100644 --- a/tools/binpac/src/pac_paramtype.h +++ b/tools/binpac/src/pac_paramtype.h @@ -52,7 +52,6 @@ protected: private: ID *type_id_; ExprList *args_; - char *data_type_; bool checking_requires_analyzer_context_; void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index fdfc6a7977..b474d9c83a 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -252,6 +252,7 @@ RecordField::RecordField(FieldType tof, ID *id, Type *type) prev_ = 0; next_ = 0; static_offset_ = -1; + parsing_state_seq_ = 0; boundary_checked_ = false; } diff --git a/tools/binpac/src/pac_typedecl.h b/tools/binpac/src/pac_typedecl.h index 37631af18e..2aea7ad183 100644 --- a/tools/binpac/src/pac_typedecl.h +++ b/tools/binpac/src/pac_typedecl.h @@ -42,8 +42,6 @@ protected: ParamList *params_; Type *type_; - - bool inherits_frame_buffer_; }; #endif // pac_typedecl_h From 498a5314ed04db64884fe2a591f95e8f45ae944b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 18 Feb 2014 15:42:36 -0600 Subject: [PATCH 050/343] binpac: Request format macros from inttypes.h explicitly. This helps ensure the availability of PRI* macros from .pac files, which cannot create this definition themselves since the inclusion of binpac.h is hardcoded to be placed very early in the generated code and already includes inttypes.h itself. --- tools/binpac/lib/binpac.h.in | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index f5c6e152c7..4e78b7b830 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -17,6 +17,13 @@ #include #include #include + +// Expose C99 functionality from inttypes.h, which would otherwise not be +// available in C++. +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif + #include #define BINPAC_ASSERT(x) assert(x) From 434f147932624bc3817e4bbcf8e901cd3d7867ff Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 31 Oct 2014 17:42:21 -0700 Subject: [PATCH 051/343] binpac: Adding a new binpac::init() function that must be called by the host before anything else. Internally, this function compiles all regular expressions, avoiding to that inside the regexp constructore. The code is a bit hackish due to the way the regexp code depends on the Bro header. --- tools/binpac/lib/CMakeLists.txt | 1 + tools/binpac/lib/binpac_regex.cc | 10 +++++++ tools/binpac/lib/binpac_regex.h | 45 +++++++++++++++++++++++++++----- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index bac8a2bebe..b4179e702c 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -22,6 +22,7 @@ set(binpac_headers set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc + binpac_regex.cc ${binpac_headers} ) diff --git a/tools/binpac/lib/binpac_regex.cc b/tools/binpac/lib/binpac_regex.cc index e69de29bb2..6f276c3462 100644 --- a/tools/binpac/lib/binpac_regex.cc +++ b/tools/binpac/lib/binpac_regex.cc @@ -0,0 +1,10 @@ + +#include + +class RE_Matcher; + +namespace binpac { + +std::vector* uncompiled_re_matchers = 0; + +} diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index b41e6dbb90..d27083877b 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -9,12 +9,19 @@ class RE_Matcher; namespace binpac { +// Internal vector recording not yet compiled matchers. +extern std::vector* uncompiled_re_matchers; + class RegExMatcher { public: RegExMatcher(const char *pattern) : pattern_(pattern) { - re_matcher_ = 0; + if ( ! uncompiled_re_matchers ) + uncompiled_re_matchers = new std::vector; + + re_matcher_ = new RE_Matcher(pattern_.c_str()); + uncompiled_re_matchers->push_back(re_matcher_); } ~RegExMatcher() @@ -25,19 +32,45 @@ public: // Returns the length of longest match, or -1 on mismatch. int MatchPrefix(const_byteptr data, int len) { - if ( ! re_matcher_ ) - { - re_matcher_ = new RE_Matcher(pattern_.c_str()); - re_matcher_->Compile(); - } return re_matcher_->MatchPrefix(data, len); } private: + friend void ::binpac::init(); + + // Function, and state, for compiling matchers. + static void init(); + string pattern_; RE_Matcher *re_matcher_; }; +inline void RegExMatcher::init() + { + if ( ! uncompiled_re_matchers ) + return; + + for ( size_t i = 0; i < uncompiled_re_matchers->size(); ++i ) + { + if ( ! (*uncompiled_re_matchers)[i]->Compile() ) + { + fprintf(stderr, "binpac: cannot compile regular expression\n"); + exit(1); + } + } + + uncompiled_re_matchers->clear(); + } + +// Must be called before any binpac functionality is used. +// +// Note, this must be defined here, and inline, because the RE functionality +// can only be used when compiling from inside Bro. +inline void init() + { + RegExMatcher::init(); + } + } // namespace binpac #endif // binpac_regex_h From db1c70b32e5b3285b4cbac45988ad8316a23d6d1 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 3 Nov 2014 10:05:17 -0600 Subject: [PATCH 052/343] binpac: Separate declaration of binpac::init from definition. When friend'ing a global function via qualified-id, Clang complains if it's not been previously declared. --- tools/binpac/lib/binpac_regex.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index d27083877b..49d58e4c0a 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -9,6 +9,12 @@ class RE_Matcher; namespace binpac { +// Must be called before any binpac functionality is used. +// +// Note, this must be declared/defined here, and inline, because the RE +// functionality can only be used when compiling from inside Bro. +inline void init(); + // Internal vector recording not yet compiled matchers. extern std::vector* uncompiled_re_matchers; @@ -62,10 +68,6 @@ inline void RegExMatcher::init() uncompiled_re_matchers->clear(); } -// Must be called before any binpac functionality is used. -// -// Note, this must be defined here, and inline, because the RE functionality -// can only be used when compiling from inside Bro. inline void init() { RegExMatcher::init(); From 8648820497b3e3c0159e4e32befdddad31266a27 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 23 Jan 2015 09:56:59 -0600 Subject: [PATCH 053/343] binpac: Fix potential out-of-bounds memory reads in generated code. Field lengths derived from other data in the input could potentially lead to reading from outside the bounds of the input buffer. Reported by John Villamil and Chris Rohlf - Yahoo Paranoids --- tools/binpac/src/pac_dataptr.cc | 7 ++++-- tools/binpac/src/pac_record.cc | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/tools/binpac/src/pac_dataptr.cc b/tools/binpac/src/pac_dataptr.cc index 44c497efea..08071b1cf8 100644 --- a/tools/binpac/src/pac_dataptr.cc +++ b/tools/binpac/src/pac_dataptr.cc @@ -41,10 +41,13 @@ void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, ASSERT(id_); out_cc->println("// Checking out-of-bound for \"%s\"", data_name); - out_cc->println("if ( %s + (%s) > %s )", + out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", ptr_expr(), data_size, - env->RValue(end_of_data)); + env->RValue(end_of_data), + ptr_expr(), + data_size, + ptr_expr()); out_cc->inc_indent(); out_cc->println("{"); diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index b474d9c83a..cdffd70ef9 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -602,10 +602,37 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi switch ( ptype_ ) { case PAD_BY_LENGTH: + out_cc->println("if ( (%s) < 0 ) // check for negative pad length", + expr_->EvalExpr(out_cc, env)); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", + Location(), expr_->EvalExpr(out_cc, env)); + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); + out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(), expr_->EvalExpr(out_cc, env)); + + out_cc->println("// Checking out-of-bound padding for \"%s\"", field_id_str_.c_str()); + out_cc->println("if ( %s > %s || %s < %s )", + env->LValue(end_of_field_dataptr_var), + env->RValue(end_of_data), + env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr()); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); + out_cc->println(" (%s), ", + expr_->EvalExpr(out_cc, env)); + out_cc->println(" (%s) - (%s));", + env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var)); + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); break; case PAD_TO_OFFSET: @@ -628,6 +655,18 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi field_begin.ptr_expr()); out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("if ( %s > %s )", + env->LValue(end_of_field_dataptr_var), + env->RValue(end_of_data)); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); + out_cc->println(" (%s), ", + expr_->EvalExpr(out_cc, env)); + out_cc->println(" (%s) - (%s));", + env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var)); + out_cc->println("}"); + out_cc->dec_indent(); break; case PAD_TO_NEXT_WORD: From ded5abb01eb014ef727e03e6edf8ca68974a36d1 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 31 Mar 2015 13:48:15 -0500 Subject: [PATCH 054/343] binpac: BIT-1361: Improve boundary checks of records that use &length Specifying &length on a record no longer skips generating boundary checks for individual fields. E.g. a record field that specifies a &length that extends beyond the &length of the record containing it should throw binpac::ExceptionOutOfBound, the usual way of handling out-of-bounds conditions. --- tools/binpac/src/pac_record.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index cdffd70ef9..2cd888742a 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -206,6 +206,13 @@ int RecordType::StaticSize(Env* env) const void RecordType::SetBoundaryChecked() { Type::SetBoundaryChecked(); + + if ( StaticSize(env()) < 0 || attr_length_expr_ ) + // Don't assume sufficient bounds checking has been done on fields + // if the record is of variable size or if its size is set from &length + // (whose value is not necessarily trustworthy). + return; + foreach (i, RecordFieldList, record_fields_) { RecordField *f = *i; From ae200429438421bbd08a80ef2075fa1ee2d6a2b5 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 21 Apr 2015 13:11:24 -0500 Subject: [PATCH 055/343] binpac: BIT-1343: fix %include to work with relative paths --- tools/binpac/src/pac_scan.ll | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index 3961a28f3b..95e2475c21 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -20,6 +20,7 @@ #include "pac_record.h" #include "pac_type.h" #include "pac_utils.h" +#include int line_number = 1; @@ -52,7 +53,7 @@ WS [ \t]+ ID [A-Za-z_][A-Za-z_0-9]* D [0-9]+ HEX [0-9a-fA-F]+ -FILE [A-Za-z._0-9\-]+ +FILE [^ \t\n]+ ESCSEQ (\\([^\n]|[0-7]{3}|x[[:xdigit:]]{2})) %option nounput @@ -320,8 +321,27 @@ void include_file(const char *filename) ASSERT(filename); string full_filename; - if ( filename[0] == '/' || filename[0] == '.' ) + if ( filename[0] == '/' ) full_filename = filename; + else if ( filename[0] == '.' ) + { + char* tmp = new char[strlen(input_filename.c_str()) + 1]; + strcpy(tmp, input_filename.c_str()); + char* dir = dirname(tmp); + + if ( dir ) + full_filename = string(dir) + "/" + filename; + else + { + fprintf(stderr, "%s:%d error: cannot include file \"%s\": %s\n", + input_filename.c_str(), line_number, filename, + strerror(errno)); + delete [] tmp; + return; + } + + delete [] tmp; + } else { int i; From e3e4453dac1d84d20511919e4d106607a494fe68 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 21 Apr 2015 20:11:06 -0700 Subject: [PATCH 056/343] binpac: Adding missing include. --- tools/binpac/src/pac_scan.ll | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index 95e2475c21..0324ef0aa8 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -21,6 +21,7 @@ #include "pac_type.h" #include "pac_utils.h" #include +#include int line_number = 1; From a9d294528db9f983e6e62e3bb8d86f98a10bb17f Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Sat, 16 Jan 2016 23:52:01 -0500 Subject: [PATCH 057/343] binpac: Fixed compiler complaining about recursive function. --- tools/binpac/src/pac_primitive.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_primitive.h b/tools/binpac/src/pac_primitive.h index 47d06a1e72..fb44e2009c 100644 --- a/tools/binpac/src/pac_primitive.h +++ b/tools/binpac/src/pac_primitive.h @@ -11,7 +11,7 @@ public: explicit PacPrimitive(PrimitiveType type) : type_(type) {} virtual ~PacPrimitive() {} - PrimitiveType type() const { return type(); } + PrimitiveType type() const { return type_; } virtual string ToCode(Env *env) = 0; From dc49b0343f91f9a7d85bd4d30f02c103c1a52a72 Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Fri, 6 May 2016 15:07:05 -0500 Subject: [PATCH 058/343] binpac: Add a comment in the generated C++ code for fall through in switch A common BinPAC construct for parsing records is a switch statement, with no breaks between the cases, as control is expected to fall through. Coverity raises an error about this; this commit should fix that. --- tools/binpac/src/pac_record.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index 2cd888742a..41a717653d 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -446,6 +446,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) out_cc->println("%s = %d;", env->LValue(parsing_state_id), parsing_state_seq()); + out_cc->println("/* fall through */"); out_cc->dec_indent(); out_cc->println("case %d:", parsing_state_seq()); out_cc->inc_indent(); From d73e3485c138745a28433118bc0177f344d87521 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 23 May 2016 08:25:49 -0700 Subject: [PATCH 059/343] binpac: Fixing Coverity warning. --- tools/binpac/lib/binpac_buffer.cc | 37 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index b0fc4dfbce..ebc951a575 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -51,13 +51,13 @@ void FlowBuffer::NewMessage() BINPAC_ASSERT(frame_length_ >= 0); int bytes_to_advance = 0; - if ( buffer_n_ == 0 ) + if ( buffer_n_ == 0 ) { - switch ( mode_ ) + switch ( mode_ ) { case LINE_MODE: - bytes_to_advance = (frame_length_ + - (linebreak_style_ == STRICT_CRLF ? + bytes_to_advance = (frame_length_ + + (linebreak_style_ == STRICT_CRLF ? 2 : 1)); break; case FRAME_MODE: @@ -98,7 +98,7 @@ void FlowBuffer::ExpandBuffer(int length) // So length > 0 if ( length < 512 ) length = 512; - + if ( length < buffer_length_ * 2 ) length = buffer_length_ * 2; @@ -188,7 +188,7 @@ void FlowBuffer::NewData(const_byteptr begin, const_byteptr end) ClearPreviousData(); - BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || + BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || orig_data_begin_ == orig_data_end_); orig_data_begin_ = begin; @@ -202,7 +202,7 @@ void FlowBuffer::MarkOrCopy() { if ( ! message_complete_ ) { - switch ( mode_ ) + switch ( mode_ ) { case LINE_MODE: MarkOrCopyLine(); @@ -211,7 +211,7 @@ void FlowBuffer::MarkOrCopy() case FRAME_MODE: MarkOrCopyFrame(); break; - + default: break; } @@ -228,7 +228,7 @@ void FlowBuffer::ClearPreviousData() { if ( frame_length_ > 0 ) { - frame_length_ -= + frame_length_ -= (orig_data_end_ - orig_data_begin_); } orig_data_begin_ = orig_data_end_; @@ -284,7 +284,10 @@ CR_OR_LF_1: void FlowBuffer::MarkOrCopyLine_CR_OR_LF() { - if ( state_ == CR_OR_LF_1 && + if ( ! (orig_data_begin_ && orig_data_end_) ) + return; + + if ( state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF ) { state_ = CR_OR_LF_0; @@ -398,16 +401,16 @@ found_end_of_line: } // Invariants: -// +// // When buffer_n_ == 0: // Frame = [orig_data_begin_..(orig_data_begin_ + frame_length_)] -// +// // When buffer_n_ > 0: // Frame = [0..buffer_n_][orig_data_begin_..] void FlowBuffer::MarkOrCopyFrame() { - if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && + if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ ) { // Skip the lingering LF @@ -427,11 +430,11 @@ void FlowBuffer::MarkOrCopyFrame() // Do nothing except setting the message complete flag message_complete_ = true; } - else + else { if ( ! chunked_ ) { - AppendToBuffer(orig_data_begin_, + AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); } message_complete_ = false; @@ -442,7 +445,7 @@ void FlowBuffer::MarkOrCopyFrame() BINPAC_ASSERT(!chunked_); int bytes_to_copy = orig_data_end_ - orig_data_begin_; message_complete_ = false; - if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ ) + if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ ) { bytes_to_copy = frame_length_ - buffer_n_; message_complete_ = true; @@ -455,7 +458,7 @@ void FlowBuffer::MarkOrCopyFrame() { fprintf(stderr, "%.6f frame complete: [%s]\n", network_time(), - string((const char *) begin(), + string((const char *) begin(), (const char *) end()).c_str()); } #endif From f1239143cb73f2fc8ef9bb0481240164cecf1eaa Mon Sep 17 00:00:00 2001 From: Bartolo Otrit Date: Sat, 4 Jun 2016 16:08:05 +0300 Subject: [PATCH 060/343] binpac: Bug fix of pac_swap function with int32 type of argument. How to reproduce: >>>code int32 n = 0xF71B0000; int32 n1 = pac_swap(n); code<<< n1 becomes 0xFFFFFFF7 instead of 0x00001BF7 Reason: Undefined behaviour after bit shift operation because of negative value of the argument. See C++ standard (2011) 5.8.2 (Shift operators). --- tools/binpac/lib/binpac.h.in | 65 ++++++++++++++---------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index 4e78b7b830..63651e22ce 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -63,62 +63,47 @@ typedef const char *const_charptr; namespace { -inline int16 pac_swap(int16 x) +inline uint16 pac_swap(const uint16 x) { return (x >> 8) | ((x & 0xff) << 8); } -inline uint16 pac_swap(uint16 x) +inline int16 pac_swap(const int16 x) { - return (x >> 8) | ((x & 0xff) << 8); + uint16 (*p)(const uint16) = &pac_swap; + return (*p)(x); } -inline int32 pac_swap(int32 x) +inline uint32 pac_swap(const uint32 x) { - return (x >> 24) | - ((x & 0xff0000) >> 8) | - ((x & 0xff00) << 8) | - ((x & 0xff) << 24); + return (x >> 24) | + ((x & 0xff0000) >> 8) | + ((x & 0xff00) << 8) | + ((x & 0xff) << 24); } -inline uint32 pac_swap(uint32 x) +inline int32 pac_swap(const int32 x) { - return (x >> 24) | - ((x & 0xff0000) >> 8) | - ((x & 0xff00) << 8) | - ((x & 0xff) << 24); + uint32 (*p)(const uint32) = &pac_swap; + return (*p)(x); } -inline int64 pac_swap(int64 i) +inline uint64 pac_swap(const uint64 x) { - unsigned char c; - union { - uint64 i; - unsigned char c[8]; - } x; - - x.i = i; - c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; - c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; - c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; - c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; - return x.i; + return x >> 56 | + (x & 0xff000000000000) >> 40 | + (x & 0xff0000000000) >> 24 | + (x & 0xff00000000) >> 8 | + (x & 0xff000000) << 8 | + (x & 0xff0000) << 24 | + (x & 0xff00) << 40 | + (x & 0xff) << 56; } - -inline uint64 pac_swap(uint64 i) + +inline int64 pac_swap(const int64 x) { - unsigned char c; - union { - uint64 i; - unsigned char c[8]; - } x; - - x.i = i; - c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; - c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; - c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; - c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; - return x.i; + uint64 (*p)(const uint64) = &pac_swap; + return (*p)(x); } #define FixByteOrder(byteorder, x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap(x)) From ffe92f487fdad55e1a788ef77ae6addce02c878b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bryon=20Gloden=2C=20CISSP=C2=AE?= Date: Mon, 1 Aug 2016 13:51:30 -0400 Subject: [PATCH 061/343] binpac: Update pac_parse.yy (error) Memory leak: msgbug Found by https://github.com/bryongloden/cppcheck --- tools/binpac/src/pac_parse.yy | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/src/pac_parse.yy b/tools/binpac/src/pac_parse.yy index 58d66b8808..5bf3c96434 100644 --- a/tools/binpac/src/pac_parse.yy +++ b/tools/binpac/src/pac_parse.yy @@ -1089,5 +1089,6 @@ int yyerror(const char msg[]) fprintf(stderr, " (yychar=%d)", yychar); fprintf(stderr, "\n"); + delete[] msgbuf; return 0; } From e4c168836e2a1c0b4f0908552dd4718064085a70 Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Wed, 30 Nov 2016 10:18:23 -0800 Subject: [PATCH 062/343] binpac: Allow more than one &require attribute on a field. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by François Pennaneach . BIT-1753 #close --- tools/binpac/src/pac_type.cc | 13 ++++++++----- tools/binpac/src/pac_type.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index a30295aa0e..4023da920d 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -60,7 +60,7 @@ Type::Type(TypeType tot) attr_multiline_end_ = 0; attr_oneline_ = false; attr_refcount_ = false; - attr_requires_ = 0; + attr_requires_ = new ExprList(); attr_restofdata_ = false; attr_restofflow_ = false; attr_transient_ = false; @@ -80,7 +80,7 @@ Type::~Type() delete attr_if_expr_; delete attr_length_expr_; delete_list(ExprList, attr_checks_); - delete attr_requires_; + delete_list(ExprList, attr_requires_); } Type *Type::Clone() const @@ -203,7 +203,7 @@ void Type::ProcessAttr(Attr* a) break; case ATTR_REQUIRES: - attr_requires_ = a->expr(); + attr_requires_->push_back(a->expr()); break; case ATTR_TRANSIENT: @@ -723,8 +723,11 @@ void Type::GenParseCode2(Output* out_cc, Env* env, void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags) { - if ( attr_requires_ ) - attr_requires_->EvalExpr(out_cc, env); + foreach(i, ExprList, attr_requires_) + { + Expr *req = *i; + req->EvalExpr(out_cc, env); + } foreach(i, FieldList, fields_) { diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index 08252cf637..6e9f548600 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -290,7 +290,7 @@ protected: Expr *attr_multiline_end_; bool attr_oneline_; bool attr_refcount_; - Expr *attr_requires_; + ExprList *attr_requires_; bool attr_restofdata_; bool attr_restofflow_; bool attr_transient_; From 827d1ff11eaf5019fb4bf292d72cd1e19781b878 Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Tue, 13 Feb 2018 09:27:42 -0800 Subject: [PATCH 063/343] binpac: Fix integer overflow in binpac generated code. The issue is that t_begin_of_data + %s can sometimes overflow. Bug reported and patch proposed by Philippe Antoine from Catena cyber. --- tools/binpac/src/pac_array.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 1d38011780..eb03dd5597 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -280,8 +280,8 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) // Check for overlong array length. We cap it at the // maximum data size as we won't store more elements. - out_cc->println("if ( t_begin_of_data + %s > t_end_of_data + 1 )", - env->LValue(arraylength_var())); + out_cc->println("if ( t_begin_of_data + %s > t_end_of_data + 1 || t_begin_of_data + %s < t_begin_of_data )", + env->LValue(arraylength_var()), env->LValue(arraylength_var())); out_cc->inc_indent(); out_cc->println("{"); out_cc->println("%s = t_end_of_data - t_begin_of_data + 1;", From 5cfbefca7c8c3588f4df4ecedaeb43c8ddb5eb10 Mon Sep 17 00:00:00 2001 From: giralt Date: Thu, 5 Apr 2018 19:19:58 +0200 Subject: [PATCH 064/343] binpac: Extends BinPAC to support arbitrary line breakers via &linebreaker attribute This feature is needed to run the FIX ASCII analyzer: https://github.com/reservoirlabs/fix-ascii --- tools/binpac/lib/binpac_buffer.cc | 54 +++++++++++++++++++++++++++++++ tools/binpac/lib/binpac_buffer.h | 6 ++++ tools/binpac/src/pac_type.cc | 23 +++++++++++-- tools/binpac/src/pac_type.h | 3 ++ 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index ebc951a575..61ad8d9ea3 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -25,6 +25,7 @@ FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) orig_data_end_ = 0; linebreak_style_ = linebreak_style; + linebreak_style_default = linebreak_style; ResetLineState(); mode_ = UNKNOWN_MODE; @@ -85,6 +86,8 @@ void FlowBuffer::ResetLineState() case STRICT_CRLF: state_ = STRICT_CRLF_0; break; + case LINE_BREAKER: + break; // Nothing to reset default: BINPAC_ASSERT(0); break; @@ -115,6 +118,18 @@ void FlowBuffer::ExpandBuffer(int length) buffer_ = new_buf; } +void FlowBuffer::SetLineBreaker(u_char *lbreaker) + { + linebreaker_ = *lbreaker; + linebreak_style_default = linebreak_style_; + linebreak_style_ = LINE_BREAKER; + } + +void FlowBuffer::UnsetLineBreaker() + { + linebreak_style_ = linebreak_style_default; + } + void FlowBuffer::NewLine() { FlowBuffer::NewMessage(); @@ -261,6 +276,9 @@ void FlowBuffer::MarkOrCopyLine() case STRICT_CRLF: MarkOrCopyLine_STRICT_CRLF(); break; + case LINE_BREAKER: + MarkOrCopyLine_LINEBREAK(); + break; default: BINPAC_ASSERT(0); break; @@ -400,6 +418,42 @@ found_end_of_line: #endif } +void FlowBuffer::MarkOrCopyLine_LINEBREAK() + { + if ( ! (orig_data_begin_ && orig_data_end_) ) + return; + + const_byteptr data; + for ( data = orig_data_begin_; data < orig_data_end_; ++data ) + { + if ( *data == linebreaker_ ) + goto found_end_of_line; + } + + AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); + return; + +found_end_of_line: + if ( buffer_n_ == 0 ) + { + frame_length_ = data - orig_data_begin_; + } + else + { + AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); + // But eliminate the last CR or LF + --buffer_n_; + } + message_complete_ = true; + +#if DEBUG_FLOW_BUFFER + fprintf(stderr, "%.6f Line complete: [%s]\n", + network_time(), + string((const char *) begin(), (const char *) end()).c_str()); +#endif + } + + // Invariants: // // When buffer_n_ == 0: diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h index ca39a6af15..dda80c8785 100644 --- a/tools/binpac/lib/binpac_buffer.h +++ b/tools/binpac/lib/binpac_buffer.h @@ -12,6 +12,7 @@ public: CR_OR_LF, // CR or LF or CRLF STRICT_CRLF, // CR followed by LF CR_LF_NUL, // CR or LF or CR-LF or CR-NUL + LINE_BREAKER, // User specified linebreaker }; FlowBuffer(LineBreakStyle linebreak_style = CR_OR_LF); @@ -72,6 +73,8 @@ public: return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; } + void SetLineBreaker(u_char *lbreaker); + void UnsetLineBreaker(); void NewLine(); // A negative frame_length represents a frame till EOF void NewFrame(int frame_length, bool chunked_); @@ -119,6 +122,7 @@ protected: void MarkOrCopyLine_CR_OR_LF(); void MarkOrCopyLine_STRICT_CRLF(); + void MarkOrCopyLine_LINEBREAK(); int buffer_n_; // number of bytes in the buffer int buffer_length_; // size of the buffer @@ -129,6 +133,8 @@ protected: const_byteptr orig_data_begin_, orig_data_end_; LineBreakStyle linebreak_style_; + LineBreakStyle linebreak_style_default; + u_char linebreaker_; enum { UNKNOWN_MODE, diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index 4023da920d..6c5adead08 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -58,6 +58,7 @@ Type::Type(TypeType tot) attr_length_expr_ = 0; attr_letfields_ = 0; attr_multiline_end_ = 0; + attr_linebreaker_ = 0; attr_oneline_ = false; attr_refcount_ = false; attr_requires_ = new ExprList(); @@ -187,7 +188,9 @@ void Type::ProcessAttr(Attr* a) break; case ATTR_LINEBREAKER: - ASSERT(0); + if (strlen(a->expr()->orig()) != 6 ) + throw Exception(this, "invalid line breaker length, must be a single ASCII character. (Ex: \"\\001\".)"); + attr_linebreaker_ = a->expr(); break; case ATTR_MULTILINE: @@ -445,7 +448,12 @@ void Type::GenBufferConfiguration(Output *out_cc, Env *env) env->RValue(buffering_state_id)); out_cc->inc_indent(); out_cc->println("{"); - + if(BufferableWithLineBreaker()) + out_cc->println("%s->SetLineBreaker((u_char*)%s);", + env->LValue(flow_buffer_id), LineBreaker()->orig()); + else + out_cc->println("%s->UnsetLineBreaker();", + env->LValue(flow_buffer_id)); out_cc->println("%s->NewLine();", env->LValue(flow_buffer_id)); @@ -999,6 +1007,17 @@ bool Type::Bufferable() const return IsEmptyType() || BufferableByLength() || BufferableByLine(); } +bool Type::BufferableWithLineBreaker() const + { + // If the input is an ASCII line with a given linebreaker; + return attr_linebreaker_ != 0; + } + +Expr* Type::LineBreaker() const + { + return attr_linebreaker_; + } + Type::BufferMode Type::buffer_mode() const { if ( IsEmptyType() ) diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index 6e9f548600..6590a94a5a 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -201,6 +201,8 @@ public: bool Bufferable() const; bool BufferableByLength() const; bool BufferableByLine() const; + bool BufferableWithLineBreaker() const; + Expr* LineBreaker() const; enum BufferMode { NOT_BUFFERABLE, @@ -288,6 +290,7 @@ protected: Expr *attr_length_expr_; FieldList *attr_letfields_; Expr *attr_multiline_end_; + Expr *attr_linebreaker_; bool attr_oneline_; bool attr_refcount_; ExprList *attr_requires_; From 0b84838465b6b448a38c0ac5788ee2a2d2955171 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 24 Apr 2018 13:01:53 -0500 Subject: [PATCH 065/343] binpac: Fix an uninitialized member warning --- tools/binpac/lib/binpac_buffer.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index 61ad8d9ea3..f02ef83da1 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -26,6 +26,7 @@ FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) linebreak_style_ = linebreak_style; linebreak_style_default = linebreak_style; + linebreaker_ = 0; ResetLineState(); mode_ = UNKNOWN_MODE; From 0ecf7755ea0aaebcb96355630ef8b32185a789e6 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 18 Apr 2018 18:07:59 -0500 Subject: [PATCH 066/343] binpac: BIT-1914: Implement &check Patch submitted by Antoine --- tools/binpac/lib/binpac_exception.h | 9 +++++++++ tools/binpac/src/pac_type.cc | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h index 6debf54466..328f8c696d 100644 --- a/tools/binpac/lib/binpac_exception.h +++ b/tools/binpac/lib/binpac_exception.h @@ -22,6 +22,15 @@ protected: string msg_; }; +class ExceptionCheckViolation : public Exception +{ +public: + ExceptionCheckViolation(const char* where) + { + append(binpac_fmt("check violation : %s", where)); + } +}; + class ExceptionOutOfBound : public Exception { public: diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index 6c5adead08..5f06b2b760 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -784,6 +784,20 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag if ( size_var() ) ASSERT(env->Evaluated(size_var())); + + foreach(i, ExprList, attr_checks_) + { + Expr* check = *i; + const char* check_expr = check->EvalExpr(out_cc, env); + out_cc->println("// Evaluate '&check' attribute"); + out_cc->println("if (!%s)", check_expr); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("throw binpac::ExceptionCheckViolation(\"%s\");", data_id_str_.c_str()); + out_cc->println("}"); + out_cc->dec_indent(); + } + } Type *Type::MemberDataType(const ID *member_id) const From 8a1c8db02e863fb4548676f50e0e37c23563e51c Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 19 Apr 2018 14:05:08 -0500 Subject: [PATCH 067/343] binpac: BIT-1914: move &check implementation to new &enforce attribute &check returns to being a no-op to avoid unintentionally breaking existing code. --- tools/binpac/lib/binpac_exception.h | 6 +++--- tools/binpac/src/pac_attr.h | 1 + tools/binpac/src/pac_parse.yy | 6 +++++- tools/binpac/src/pac_scan.ll | 1 + tools/binpac/src/pac_type.cc | 18 ++++++++++++------ tools/binpac/src/pac_type.h | 1 + 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h index 328f8c696d..4a4ae40e31 100644 --- a/tools/binpac/lib/binpac_exception.h +++ b/tools/binpac/lib/binpac_exception.h @@ -22,12 +22,12 @@ protected: string msg_; }; -class ExceptionCheckViolation : public Exception +class ExceptionEnforceViolation : public Exception { public: - ExceptionCheckViolation(const char* where) + ExceptionEnforceViolation(const char* where) { - append(binpac_fmt("check violation : %s", where)); + append(binpac_fmt("&enforce violation : %s", where)); } }; diff --git a/tools/binpac/src/pac_attr.h b/tools/binpac/src/pac_attr.h index 67bdbedc8d..85d7f19afb 100644 --- a/tools/binpac/src/pac_attr.h +++ b/tools/binpac/src/pac_attr.h @@ -8,6 +8,7 @@ enum AttrType { ATTR_BYTEORDER, ATTR_CHECK, ATTR_CHUNKED, + ATTR_ENFORCE, ATTR_EXPORTSOURCEDATA, ATTR_IF, ATTR_LENGTH, diff --git a/tools/binpac/src/pac_parse.yy b/tools/binpac/src/pac_parse.yy index 5bf3c96434..178af0604e 100644 --- a/tools/binpac/src/pac_parse.yy +++ b/tools/binpac/src/pac_parse.yy @@ -9,7 +9,7 @@ %token TOK_ID TOK_NUMBER TOK_REGEX TOK_STRING %token TOK_BEGIN_RE TOK_END_RE %token TOK_ATTR_ALSO -%token TOK_ATTR_BYTEORDER TOK_ATTR_CHECK TOK_ATTR_CHUNKED +%token TOK_ATTR_BYTEORDER TOK_ATTR_CHECK TOK_ATTR_CHUNKED TOK_ATTR_ENFORCE %token TOK_ATTR_EXPORTSOURCEDATA TOK_ATTR_IF %token TOK_ATTR_LENGTH TOK_ATTR_LET %token TOK_ATTR_LINEBREAKER TOK_ATTR_MULTILINE TOK_ATTR_ONELINE @@ -994,6 +994,10 @@ attr : TOK_ATTR_BYTEORDER '=' expr { $$ = new Attr(ATTR_CHUNKED); } + | TOK_ATTR_ENFORCE expr + { + $$ = new Attr(ATTR_ENFORCE, $2); + } | TOK_ATTR_EXPORTSOURCEDATA { $$ = new Attr(ATTR_EXPORTSOURCEDATA); diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index 0324ef0aa8..f5dab77c64 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -184,6 +184,7 @@ ESCSEQ (\\([^\n]|[0-7]{3}|x[[:xdigit:]]{2})) &byteorder return TOK_ATTR_BYTEORDER; &check return TOK_ATTR_CHECK; &chunked return TOK_ATTR_CHUNKED; +&enforce return TOK_ATTR_ENFORCE; &exportsourcedata return TOK_ATTR_EXPORTSOURCEDATA; &if return TOK_ATTR_IF; &length return TOK_ATTR_LENGTH; diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index 5f06b2b760..044a5305d1 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -52,6 +52,7 @@ Type::Type(TypeType tot) attrs_ = new AttrList(); attr_byteorder_expr_ = 0; attr_checks_ = new ExprList(); + attr_enforces_ = new ExprList(); attr_chunked_ = false; attr_exportsourcedata_ = false; attr_if_expr_ = 0; @@ -81,6 +82,7 @@ Type::~Type() delete attr_if_expr_; delete attr_length_expr_; delete_list(ExprList, attr_checks_); + delete_list(ExprList, attr_enforces_); delete_list(ExprList, attr_requires_); } @@ -159,6 +161,10 @@ void Type::ProcessAttr(Attr* a) attr_checks_->push_back(a->expr()); break; + case ATTR_ENFORCE: + attr_enforces_->push_back(a->expr()); + break; + case ATTR_EXPORTSOURCEDATA: attr_exportsourcedata_ = true; break; @@ -785,15 +791,15 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag if ( size_var() ) ASSERT(env->Evaluated(size_var())); - foreach(i, ExprList, attr_checks_) + foreach(i, ExprList, attr_enforces_) { - Expr* check = *i; - const char* check_expr = check->EvalExpr(out_cc, env); - out_cc->println("// Evaluate '&check' attribute"); - out_cc->println("if (!%s)", check_expr); + Expr* enforce = *i; + const char* enforce_expr = enforce->EvalExpr(out_cc, env); + out_cc->println("// Evaluate '&enforce' attribute"); + out_cc->println("if (!%s)", enforce_expr); out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("throw binpac::ExceptionCheckViolation(\"%s\");", data_id_str_.c_str()); + out_cc->println("throw binpac::ExceptionEnforceViolation(\"%s\");", data_id_str_.c_str()); out_cc->println("}"); out_cc->dec_indent(); } diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index 6590a94a5a..2de0a6fc76 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -284,6 +284,7 @@ protected: Expr *attr_byteorder_expr_; ExprList *attr_checks_; + ExprList *attr_enforces_; bool attr_chunked_; bool attr_exportsourcedata_; Expr *attr_if_expr_; From 39547dccecab98fd8727e3e9f3df6b523e011d7a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 19 Apr 2018 17:10:52 -0500 Subject: [PATCH 068/343] binpac: BIT-1914: emit deprecation warning for &check usages --- tools/binpac/src/pac_scan.ll | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index f5dab77c64..8ffd90fd1a 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -182,7 +182,12 @@ ESCSEQ (\\([^\n]|[0-7]{3}|x[[:xdigit:]]{2})) &also return TOK_ATTR_ALSO; &byteorder return TOK_ATTR_BYTEORDER; -&check return TOK_ATTR_CHECK; +&check { + fprintf(stderr, + "warning in %s:%d: &check is a deprecated no-op, use &enforce\n", + input_filename.c_str(), line_number); + return TOK_ATTR_CHECK; + } &chunked return TOK_ATTR_CHUNKED; &enforce return TOK_ATTR_ENFORCE; &exportsourcedata return TOK_ATTR_EXPORTSOURCEDATA; From 9c61eefe0d717c525dbcbda3a5b3ffb51acc1687 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 18 May 2018 09:13:17 -0500 Subject: [PATCH 069/343] binpac: BIT-1829: fix &length suppressing boundary checks for array elements It should only suppress the parsing-loop boundary check in the case where array elaments are a single byte in length and thus covered by the boundary check (generated as a result of &length) that is placed before the parsing-loop. --- tools/binpac/src/pac_array.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index eb03dd5597..7017389df9 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -683,6 +683,17 @@ int ArrayType::StaticSize(Env *env) const void ArrayType::SetBoundaryChecked() { Type::SetBoundaryChecked(); + + if ( attr_length_expr_ ) + { + // When using &length on an array, only treat its elements as + // already-bounds-checked if they are a single byte in length. + if ( elemtype_->StaticSize(env()) == 1 ) + elemtype_->SetBoundaryChecked(); + + return; + } + elemtype_->SetBoundaryChecked(); } From d6fc439c21038718bcffdf317ddd17cd87f3ee1e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 18 May 2018 10:00:35 -0500 Subject: [PATCH 070/343] binpac: GH-4: fix premature loop termination when parsing known-length arrays For arrays with a length expression (e.g. uint16[size] instead of uint16[]), the parsing loop would consider reaching the end of the data buffer as a successful loop termination condition even if it's not yet parsed the required number of elements. Now, for such arrays, the loop will only terminate based on the loop counter (derived from the length expression) or else it will throw an OOB exception when trying to parse an element and finding not enough data in the buffer. Credit to Tomas Bortoli for reporting the problem and proposing patches. --- tools/binpac/src/pac_array.cc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 7017389df9..71736b1a49 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -527,7 +527,22 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, GenUntilCheck(out_cc, env, attr_generic_until_expr_, true); if ( elem_dataptr_var() ) - GenUntilCheck(out_cc, env, elem_dataptr_until_expr_, false); + { + if ( length_ ) + { + // Array has a known-length expression like uint16[4] vs. uint16[]. + // Here, arriving at the end of the data buffer should not be a + // valid loop-termination condition (which is what the + // GenUntilCheck() call produces). Instead, rely on the loop + // counter to terminate iteration or else the parsing code + // generated for each element should throw an OOB exception if + // there's insufficient data in the buffer. + } + else + { + GenUntilCheck(out_cc, env, elem_dataptr_until_expr_, false); + } + } elemtype_->GenPreParsing(out_cc, env); elemtype_->GenParseCode(out_cc, env, elem_data, flags); From 0a05aa92fc2c97e89a208fe27c4d8ee0a590bc80 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 18 May 2018 10:31:54 -0500 Subject: [PATCH 071/343] binpac: Improve parsing of known-length, static-size arrays In this case, the bounds checking for individual elements can be optimized out of the parsing-loop in favor of a single, array-wide bounds check beforehand. --- tools/binpac/src/pac_array.cc | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 71736b1a49..1f2bacc5d5 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -280,6 +280,12 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) // Check for overlong array length. We cap it at the // maximum data size as we won't store more elements. + // e.g. this helps prevent user-controlled length fields + // from causing an excessive memory-allocation (for + // the array we'll be parsing into) unless they actually + // sent enough data to go along with it. Note that this check + // is *not* looking for whether the contents of the array will + // extend past the end of the data buffer. out_cc->println("if ( t_begin_of_data + %s > t_end_of_data + 1 || t_begin_of_data + %s < t_begin_of_data )", env->LValue(arraylength_var()), env->LValue(arraylength_var())); out_cc->inc_indent(); @@ -298,6 +304,28 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) env->LValue(arraylength_var())); out_cc->println("}"); out_cc->dec_indent(); + + if ( elemtype_->StaticSize(env) != -1 ) + { + // Boundary check the entire array if elements have static size. + string array_size = strfmt("((%d) * (%s))", + elemtype_->StaticSize(env), + env->RValue(arraylength_var())); + out_cc->println("// Check bounds for static-size array: %s", + data_id_str_.c_str()); + out_cc->println("if ( t_begin_of_data + %s > t_end_of_data || " + "t_begin_of_data + %s < t_begin_of_data )", + array_size.c_str(), array_size.c_str()); + out_cc->inc_indent(); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", + data_id_str_.c_str()); + out_cc->println(" %s, (%s) - (%s));", + array_size.c_str(), + env->RValue(end_of_data), + env->RValue(begin_of_data)); + out_cc->dec_indent(); + elemtype_->SetBoundaryChecked(); + } } else if ( attr_restofdata_ ) { From 5a688c2730c301e28f24aed38055b50959de9bd5 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 17 May 2018 15:51:49 -0500 Subject: [PATCH 072/343] binpac: Migrate fmt() usage to strfmt() The former is easy to misuse by accidentally storing the contents of the temporary string return value and accessing it later. There's also potential pitfalls in changing it to return a pointer into a static buffer, so instead start using strfmt() uniformly across the codebase and change some methods to use strings instead of char*. --- tools/binpac/src/pac_action.cc | 2 +- tools/binpac/src/pac_array.cc | 12 +++---- tools/binpac/src/pac_case.cc | 2 +- tools/binpac/src/pac_conn.cc | 2 +- tools/binpac/src/pac_context.cc | 6 ++-- tools/binpac/src/pac_cstr.cc | 4 +-- tools/binpac/src/pac_decl.cc | 2 +- tools/binpac/src/pac_exception.cc | 25 ++++++++------- tools/binpac/src/pac_exception.h | 6 ++-- tools/binpac/src/pac_expr.cc | 52 ++++++++++++++++++------------- tools/binpac/src/pac_id.cc | 4 +-- tools/binpac/src/pac_id.h | 2 +- tools/binpac/src/pac_let.cc | 3 +- tools/binpac/src/pac_main.cc | 7 +++-- tools/binpac/src/pac_number.h | 2 +- tools/binpac/src/pac_output.cc | 4 +-- tools/binpac/src/pac_output.h | 2 +- tools/binpac/src/pac_record.cc | 6 ++-- tools/binpac/src/pac_redef.cc | 16 +++++----- tools/binpac/src/pac_strtype.cc | 20 ++++++------ tools/binpac/src/pac_strtype.h | 2 +- tools/binpac/src/pac_type.cc | 6 ++-- tools/binpac/src/pac_typedecl.cc | 9 +++--- tools/binpac/src/pac_utils.h | 3 -- 24 files changed, 105 insertions(+), 94 deletions(-) diff --git a/tools/binpac/src/pac_action.cc b/tools/binpac/src/pac_action.cc index 0b1ac3574f..ca9f72d96e 100644 --- a/tools/binpac/src/pac_action.cc +++ b/tools/binpac/src/pac_action.cc @@ -103,7 +103,7 @@ Type *ActionParam::DataType() const if ( ! member_type ) { throw Exception(type()->field_id(), - fmt("cannot find member type for `%s.%s'", + strfmt("cannot find member type for `%s.%s'", type()->type_id()->Name(), type()->field_id()->Name())); } diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 1f2bacc5d5..05eefdeb6c 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -205,9 +205,9 @@ void ArrayType::Prepare(Env *env, int flags) { if ( flags & TO_BE_PARSED ) { - ID *arraylength_var = new ID(fmt("%s__arraylength", value_var()->Name())); - ID *elem_var = new ID(fmt("%s__elem", value_var()->Name())); - ID *elem_it_var = new ID(fmt("%s__it", elem_var->Name())); + ID *arraylength_var = new ID(strfmt("%s__arraylength", value_var()->Name())); + ID *elem_var = new ID(strfmt("%s__elem", value_var()->Name())); + ID *elem_it_var = new ID(strfmt("%s__it", elem_var->Name())); elem_var_field_ = new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_); @@ -235,7 +235,7 @@ void ArrayType::Prepare(Env *env, int flags) // Add elem_dataptr_var only when not parsing incrementally ID *elem_dataptr_var = - new ID(fmt("%s__dataptr", elem_var->Name())); + new ID(strfmt("%s__dataptr", elem_var->Name())); elem_dataptr_var_field_ = new TempVarField( elem_dataptr_var, extern_type_const_byteptr->Clone()); @@ -385,7 +385,7 @@ void ArrayType::GenCleanUpCode(Output *out_cc, Env *env) { if ( ! elem_var_field_ ) { - ID *elem_var = new ID(fmt("%s__elem", value_var()->Name())); + ID *elem_var = new ID(strfmt("%s__elem", value_var()->Name())); elem_var_field_ = new ParseVarField( Field::NOT_CLASS_MEMBER, @@ -623,7 +623,7 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, void ArrayType::GenUntilInputCheck(Output *out_cc, Env *env) { ID *elem_input_var_id = new ID( - fmt("%s__elem_input", value_var()->Name())); + strfmt("%s__elem_input", value_var()->Name())); elem_input_var_field_ = new TempVarField( elem_input_var_id, extern_type_const_bytestring->Clone()); elem_input_var_field_->Prepare(env); diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index 42ef5fd15f..1e501fc301 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -63,7 +63,7 @@ void CaseType::Prepare(Env* env, int flags) { ASSERT(flags & TO_BE_PARSED); - index_var_ = new ID(fmt("%s_case_index", value_var()->Name())); + index_var_ = new ID(strfmt("%s_case_index", value_var()->Name())); env->AddID(index_var_, MEMBER_VAR, extern_type_int); // Sort the cases_ to put the default case at the end of the list diff --git a/tools/binpac/src/pac_conn.cc b/tools/binpac/src/pac_conn.cc index d9159cae5a..5e2542e483 100644 --- a/tools/binpac/src/pac_conn.cc +++ b/tools/binpac/src/pac_conn.cc @@ -43,7 +43,7 @@ void ConnDecl::ProcessFlowElement(AnalyzerFlow *flow_elem) if ( flows_[flow_index] ) { throw Exception(flow_elem, - fmt("%sflow already defined", + strfmt("%sflow already defined", flow_index == 0 ? "up" : "down")); } diff --git a/tools/binpac/src/pac_context.cc b/tools/binpac/src/pac_context.cc index 94e4c4ce47..abf3c73a3c 100644 --- a/tools/binpac/src/pac_context.cc +++ b/tools/binpac/src/pac_context.cc @@ -39,7 +39,7 @@ namespace { AnalyzerContextDecl::AnalyzerContextDecl( ID *id, ContextFieldList *context_fields) - : TypeDecl(new ID(fmt("Context%s", id->Name())), + : TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields), new DummyType()) { @@ -47,7 +47,7 @@ AnalyzerContextDecl::AnalyzerContextDecl( if ( current_analyzer_context_ != 0 ) { throw Exception(this, - fmt("multiple declaration of analyzer context; " + strfmt("multiple declaration of analyzer context; " "the previous one is `%s'", current_analyzer_context_->id()->Name())); } @@ -108,7 +108,7 @@ string AnalyzerContextDecl::mb_buffer(Env *env) { // A hack. The orthodox way would be to build an Expr of // context.flow_buffer_var, and then EvalExpr. - return fmt("%s->%s()", + return strfmt("%s->%s()", env->RValue(analyzer_context_id), kFlowBufferVar); } diff --git a/tools/binpac/src/pac_cstr.cc b/tools/binpac/src/pac_cstr.cc index fb6db4b0b9..45e0b78f5e 100644 --- a/tools/binpac/src/pac_cstr.cc +++ b/tools/binpac/src/pac_cstr.cc @@ -49,7 +49,7 @@ int expand_escape(const char*& s) int result; if ( sscanf(start, "%3o", &result) != 1 ) - throw EscapeException(fmt("bad octal escape: \"%s", start)); + throw EscapeException(strfmt("bad octal escape: \"%s", start)); return result; } @@ -65,7 +65,7 @@ int expand_escape(const char*& s) int result; if ( sscanf(start, "%2x", &result) != 1 ) - throw EscapeException(fmt("bad hexadecimal escape: \"%s", start)); + throw EscapeException(strfmt("bad hexadecimal escape: \"%s", start)); return result; } diff --git a/tools/binpac/src/pac_decl.cc b/tools/binpac/src/pac_decl.cc index 3c3ae95aa9..0bf371ce31 100644 --- a/tools/binpac/src/pac_decl.cc +++ b/tools/binpac/src/pac_decl.cc @@ -132,7 +132,7 @@ int HelperDecl::helper_id_seq = 0; HelperDecl::HelperDecl(HelperType helper_type, ID* context_id, EmbeddedCode* code) - : Decl(new ID(fmt("helper_%d", ++helper_id_seq)), HELPER), + : Decl(new ID(strfmt("helper_%d", ++helper_id_seq)), HELPER), helper_type_(helper_type), context_id_(context_id), code_(code) diff --git a/tools/binpac/src/pac_exception.cc b/tools/binpac/src/pac_exception.cc index b614c2a6f6..e9648495fd 100644 --- a/tools/binpac/src/pac_exception.cc +++ b/tools/binpac/src/pac_exception.cc @@ -3,15 +3,16 @@ #include "pac_id.h" #include "pac_utils.h" -Exception::Exception(const Object* o, const char* msg) +Exception::Exception(const Object* o, string msg) { if ( o ) { msg_ = o->Location(); msg_ += ": error : "; } - if ( msg ) - msg_ += msg; + + msg_ += msg; + if ( FLAGS_pac_debug ) { DEBUG_MSG("Exception: %s\n", msg_.c_str()); @@ -22,49 +23,49 @@ Exception::Exception(const Object* o, const char* msg) ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) : Exception(id), id_(id) { - append(fmt("`%s' undeclared", id_->Name())); + append(strfmt("`%s' undeclared", id_->Name())); } ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) : Exception(id), id_(id) { - append(fmt("`%s' redefined", id_->Name())); + append(strfmt("`%s' redefined", id_->Name())); } ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) : Exception(id), id_(id) { - append(fmt("ID `%s' not evaluated before used", id->Name())); + append(strfmt("ID `%s' not evaluated before used", id->Name())); } ExceptionIDNotField::ExceptionIDNotField(const ID* id) : Exception(id), id_(id) { - append(fmt("ID `%s' is not a field", id_->Name())); + append(strfmt("ID `%s' is not a field", id_->Name())); } ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id, const ID *member_id) : Exception(member_id), type_id_(type_id), member_id_(member_id) { - append(fmt("type %s does not have member `%s'", + append(strfmt("type %s does not have member `%s'", type_id_->Name(), member_id_->Name())); } ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) : Exception(id), id_(id) { - append(fmt("cyclic dependence through `%s'", id_->Name())); + append(strfmt("cyclic dependence through `%s'", id_->Name())); } -ExceptionPaddingError::ExceptionPaddingError(const Object* o, const char* msg) +ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) : Exception(o) { - append(msg); + append(msg.c_str()); } ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) : Exception(expr), expr(expr) { - append(fmt("Expression `%s' is not constant", expr->orig())); + append(strfmt("Expression `%s' is not constant", expr->orig())); } diff --git a/tools/binpac/src/pac_exception.h b/tools/binpac/src/pac_exception.h index 5508e75537..5920af0d54 100644 --- a/tools/binpac/src/pac_exception.h +++ b/tools/binpac/src/pac_exception.h @@ -9,10 +9,10 @@ using namespace std; class Exception { public: - Exception(const Object* o, const char* msg = 0); + Exception(const Object* o, string msg = ""); const char* msg() const { return msg_.c_str(); } - void append(const char* s) { msg_ += s; } + void append(string s) { msg_ += s; } private: string msg_; @@ -61,7 +61,7 @@ private: class ExceptionPaddingError : public Exception { public: - ExceptionPaddingError(const Object* o, const char* msg); + ExceptionPaddingError(const Object* o, string msg); }; class ExceptionIDNotField : public Exception diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index df499f7cef..3f74aa8e3f 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -72,7 +72,7 @@ Expr::Expr(ID* arg_id) expr_type_ = EXPR_ID; id_ = arg_id; num_operands_ = 0; - orig_ = fmt("%s", id_->Name()); + orig_ = strfmt("%s", id_->Name()); } Expr::Expr(Number* arg_num) @@ -82,7 +82,7 @@ Expr::Expr(Number* arg_num) expr_type_ = EXPR_NUM; num_ = arg_num; num_operands_ = 0; - orig_ = fmt("((int) %s)", num_->Str()); + orig_ = strfmt("((int) %s)", num_->Str()); } Expr::Expr(ConstString *cstr) @@ -102,7 +102,7 @@ Expr::Expr(RegEx *regex) expr_type_ = EXPR_REGEX; regex_ = regex; num_operands_ = 0; - orig_ = fmt("/%s/", regex_->str().c_str()); + orig_ = strfmt("/%s/", regex_->str().c_str()); } Expr::Expr(ExprType arg_type, Expr* op1) @@ -112,7 +112,7 @@ Expr::Expr(ExprType arg_type, Expr* op1) expr_type_ = arg_type; num_operands_ = 1; operand_[0] = op1; - orig_ = fmt(expr_fmt[expr_type_], op1->orig()); + orig_ = strfmt(expr_fmt[expr_type_], op1->orig()); } Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) @@ -124,7 +124,7 @@ Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) operand_[0] = op1; operand_[1] = op2; operand_[2] = 0; - orig_ = fmt(expr_fmt[expr_type_], op1->orig(), op2->orig()); + orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig()); } Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) @@ -136,7 +136,7 @@ Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) operand_[0] = op1; operand_[1] = op2; operand_[2] = op3; - orig_ = fmt(expr_fmt[expr_type_], op1->orig(), op2->orig(), op3->orig()); + orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig(), op3->orig()); } Expr::Expr(ExprList *args) @@ -196,16 +196,16 @@ void Expr::GenStrFromFormat(Env *env) switch ( num_operands_ ) { case 1: - str_ = fmt(expr_fmt[expr_type_], + str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str()); break; case 2: - str_ = fmt(expr_fmt[expr_type_], + str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str()); break; case 3: - str_ = fmt(expr_fmt[expr_type_], + str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str(), operand_[2]->str()); @@ -334,11 +334,19 @@ void Expr::GenEval(Output* out_cc, Env* env) Type *ty0 = operand_[0]->DataType(env); - str_ = fmt("%s%s", - operand_[0]->EvalExpr(out_cc, env), - ty0 ? - ty0->EvalMember(operand_[1]->id()).c_str() : - fmt("->%s()", operand_[1]->id()->Name())); + if ( ty0 ) + { + str_ = strfmt("%s%s", + operand_[0]->EvalExpr(out_cc, env), + ty0->EvalMember(operand_[1]->id()).c_str()); + } + else + { + string tmp = strfmt("->%s()", operand_[1]->id()->Name()); + str_ = strfmt("%s%s", + operand_[0]->EvalExpr(out_cc, env), + tmp.c_str()); + } } break; @@ -354,7 +362,7 @@ void Expr::GenEval(Output* out_cc, Env* env) if ( ty0 ) str_ = ty0->EvalElement(v0, v1); else - str_ = fmt("%s[%s]", v0.c_str(), v1.c_str()); + str_ = strfmt("%s[%s]", v0.c_str(), v1.c_str()); } break; @@ -368,7 +376,7 @@ void Expr::GenEval(Output* out_cc, Env* env) { if ( (rf = GetRecordField(id, env)) != 0 ) { - str_ = fmt("%s", rf->FieldSize(out_cc, env)); + str_ = strfmt("%s", rf->FieldSize(out_cc, env)); } } catch ( ExceptionIDNotFound &e ) @@ -377,7 +385,7 @@ void Expr::GenEval(Output* out_cc, Env* env) { int ty_size = ty->StaticSize(global_env()); if ( ty_size >= 0 ) - str_ = fmt("%d", ty_size); + str_ = strfmt("%d", ty_size); else throw Exception(id, "unknown size"); } @@ -391,7 +399,7 @@ void Expr::GenEval(Output* out_cc, Env* env) { const ID *id = operand_[0]->id(); RecordField *rf = GetRecordField(id, env); - str_ = fmt("%s", rf->FieldOffset(out_cc, env)); + str_ = strfmt("%s", rf->FieldOffset(out_cc, env)); } break; @@ -501,7 +509,7 @@ Type *Expr::DataType(Env *env) const if ( ! Type::CompatibleTypes(type1, type2) ) { throw Exception(this, - fmt("type mismatch: %s vs %s", + strfmt("type mismatch: %s vs %s", type1->DataTypeStr().c_str(), type2->DataTypeStr().c_str())); } @@ -526,7 +534,7 @@ Type *Expr::DataType(Env *env) const if ( ! Type::CompatibleTypes(type1, type2) ) { throw Exception(this, - fmt("type mismatch: %s vs %s", + strfmt("type mismatch: %s vs %s", type1->DataTypeStr().c_str(), type2->DataTypeStr().c_str())); } @@ -581,7 +589,7 @@ string Expr::DataTypeStr(Env *env) const if ( ! type ) { throw Exception(this, - fmt("cannot find data type for expression `%s'", + strfmt("cannot find data type for expression `%s'", orig())); } @@ -605,7 +613,7 @@ string Expr::SetFunc(Output *out, Env *env) break; default: throw Exception(this, - fmt("cannot generate set function " + strfmt("cannot generate set function " "for expression `%s'", orig())); break; } diff --git a/tools/binpac/src/pac_id.cc b/tools/binpac/src/pac_id.cc index b8431e6f0a..447348e978 100644 --- a/tools/binpac/src/pac_id.cc +++ b/tools/binpac/src/pac_id.cc @@ -39,7 +39,7 @@ int ID::anonymous_id_seq = 0; ID *ID::NewAnonymousID(const string &prefix) { - ID *id = new ID(fmt("%s%03d", prefix.c_str(), ++anonymous_id_seq)); + ID *id = new ID(strfmt("%s%03d", prefix.c_str(), ++anonymous_id_seq)); id->anonymous_id_ = true; return id; } @@ -297,7 +297,7 @@ void Env::SetEvaluated(const ID* id, bool v) { throw Exception( context_object_, - fmt("INTERNAL ERROR: " + strfmt("INTERNAL ERROR: " "evaluating let field '%s' in a branch! " "To work around this problem, " "add '&requires(%s)' to the case type. " diff --git a/tools/binpac/src/pac_id.h b/tools/binpac/src/pac_id.h index 6ac89687d4..06ffeb9f63 100644 --- a/tools/binpac/src/pac_id.h +++ b/tools/binpac/src/pac_id.h @@ -43,7 +43,7 @@ class Evaluatable; class ID : public Object { public: - ID(const char *arg_name) + ID(string arg_name) : name(arg_name), anonymous_id_(false) { locname = nfmt("%s:%s", Location(), Name()); diff --git a/tools/binpac/src/pac_let.cc b/tools/binpac/src/pac_let.cc index fba5f1cfc8..c850784554 100644 --- a/tools/binpac/src/pac_let.cc +++ b/tools/binpac/src/pac_let.cc @@ -156,8 +156,9 @@ void LetDecl::GenCode(Output * out_h, Output *out_cc) void LetDecl::GenEval(Output *out_cc, Env * /* env */) { Env *env = global_env(); + string tmp = strfmt("%s const", type_->DataTypeStr().c_str()); out_cc->println("%s %s = %s;", - fmt("%s const", type_->DataTypeStr().c_str()), + tmp.c_str(), env->LValue(id_), expr_->EvalExpr(out_cc, env)); diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index adb8d0eb51..0dbb43342e 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -103,7 +103,8 @@ int compile(const char* filename) FILE* fp_input = fopen(filename, "r"); if ( ! fp_input ) { - perror(fmt("Error in opening %s", filename)); + string tmp = strfmt("Error in opening %s", filename); + perror(tmp.c_str()); return -1; } input_filename = filename; @@ -142,8 +143,8 @@ int compile(const char* filename) if ( yyparse() ) return 1; - Output out_h(fmt("%s.h", basename.c_str())); - Output out_cc(fmt("%s.cc", basename.c_str())); + Output out_h(strfmt("%s.h", basename.c_str())); + Output out_cc(strfmt("%s.cc", basename.c_str())); header_output = &out_h; source_output = &out_cc; diff --git a/tools/binpac/src/pac_number.h b/tools/binpac/src/pac_number.h index f923068700..f74b206417 100644 --- a/tools/binpac/src/pac_number.h +++ b/tools/binpac/src/pac_number.h @@ -7,7 +7,7 @@ class Number : public Object { public: Number(int arg_n) - : s(fmt("%d", arg_n)), n(arg_n) {} + : s(strfmt("%d", arg_n)), n(arg_n) {} Number(const char* arg_s, int arg_n) : s(arg_s), n(arg_n) {} const char* Str() const { return s.c_str(); } diff --git a/tools/binpac/src/pac_output.cc b/tools/binpac/src/pac_output.cc index 32875bdee6..aec1e92dfc 100644 --- a/tools/binpac/src/pac_output.cc +++ b/tools/binpac/src/pac_output.cc @@ -15,9 +15,9 @@ OutputException::~OutputException() { } -Output::Output(const char* filename) +Output::Output(string filename) { - fp = fopen(filename, "w"); + fp = fopen(filename.c_str(), "w"); if ( ! fp ) throw OutputException(strerror(errno)); indent_ = 0; diff --git a/tools/binpac/src/pac_output.h b/tools/binpac/src/pac_output.h index b9d99a7dc5..26cfd72667 100644 --- a/tools/binpac/src/pac_output.h +++ b/tools/binpac/src/pac_output.h @@ -19,7 +19,7 @@ protected: class Output { public: - Output(const char *filename); + Output(string filename); ~Output(); int println(const char* fmt, ...); diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index 41a717653d..813f201b8b 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -328,7 +328,7 @@ const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) { // If not, we add a variable for the offset after the field end_of_field_dataptr_var = new ID( - fmt("dataptr_after_%s", id()->Name())); + strfmt("dataptr_after_%s", id()->Name())); env->AddID(end_of_field_dataptr_var, TEMP_VAR, extern_type_const_byteptr); @@ -546,7 +546,7 @@ void RecordPaddingField::Prepare(Env* env) { if ( ! expr_->ConstFold(env, &wordsize_) ) throw ExceptionPaddingError(this, - fmt("padding word size not a constant")); + strfmt("padding word size not a constant")); } } @@ -585,7 +585,7 @@ int RecordPaddingField::StaticSize(Env* env, int offset) const if ( offset > target_offset ) throw ExceptionPaddingError( this, - fmt("current offset = %d, " + strfmt("current offset = %d, " "target offset = %d", offset, target_offset)); return target_offset - offset; diff --git a/tools/binpac/src/pac_redef.cc b/tools/binpac/src/pac_redef.cc index 9f09b457bd..260a9ce621 100644 --- a/tools/binpac/src/pac_redef.cc +++ b/tools/binpac/src/pac_redef.cc @@ -16,7 +16,7 @@ Decl *find_decl(const ID *id) if ( ! decl ) { throw Exception(id, - fmt("cannot find declaration for %s", + strfmt("cannot find declaration for %s", id->Name())); } @@ -32,7 +32,7 @@ Decl *ProcessTypeRedef(const ID *id, FieldList *fieldlist) if ( decl->decl_type() != Decl::TYPE ) { throw Exception(id, - fmt("not a type declaration: %s", + strfmt("not a type declaration: %s", id->Name())); } @@ -74,7 +74,7 @@ Decl *ProcessCaseTypeRedef(const ID *id, CaseFieldList *casefieldlist) if ( decl->decl_type() != Decl::TYPE ) { throw Exception(id, - fmt("not a type declaration: %s", + strfmt("not a type declaration: %s", id->Name())); } @@ -85,7 +85,7 @@ Decl *ProcessCaseTypeRedef(const ID *id, CaseFieldList *casefieldlist) if ( type->tot() != Type::CASE ) { throw Exception(id, - fmt("not a case type: %s", + strfmt("not a case type: %s", id->Name())); } @@ -108,7 +108,7 @@ Decl *ProcessCaseExprRedef(const ID *id, CaseExprList *caseexprlist) if ( decl->decl_type() != Decl::FUNC ) { throw Exception(id, - fmt("not a function declaration: %s", + strfmt("not a function declaration: %s", id->Name())); } @@ -119,7 +119,7 @@ Decl *ProcessCaseExprRedef(const ID *id, CaseExprList *caseexprlist) if ( ! expr ||expr->expr_type() != Expr::EXPR_CASE ) { throw Exception(id, - fmt("function not defined by a case expression: %s", + strfmt("function not defined by a case expression: %s", id->Name())); } @@ -141,7 +141,7 @@ Decl *ProcessAnalyzerRedef(const ID *id, if ( decl->decl_type() != decl_type ) { throw Exception(id, - fmt("not a connection/flow declaration: %s", + strfmt("not a connection/flow declaration: %s", id->Name())); } @@ -160,7 +160,7 @@ Decl *ProcessTypeAttrRedef(const ID *id, AttrList *attrlist) if ( decl->decl_type() != Decl::TYPE ) { throw Exception(id, - fmt("not a type declaration: %s", + strfmt("not a type declaration: %s", id->Name())); } diff --git a/tools/binpac/src/pac_strtype.cc b/tools/binpac/src/pac_strtype.cc index 2a80c005d7..1dc7832c5a 100644 --- a/tools/binpac/src/pac_strtype.cc +++ b/tools/binpac/src/pac_strtype.cc @@ -149,7 +149,7 @@ void StringType::Prepare(Env* env, int flags) { if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 ) { - ID *string_length_var = new ID(fmt("%s_string_length", + ID *string_length_var = new ID(strfmt("%s_string_length", value_var() ? value_var()->Name() : "val")); string_length_var_field_ = new TempVarField( string_length_var, extern_type_int->Clone()); @@ -314,14 +314,16 @@ void StringType::DoGenParseCode(Output* out_cc, Env* env, } void StringType::GenStringMismatch(Output* out_cc, Env* env, - const DataPtr& data, const char *pattern) + const DataPtr& data, string pattern) { + string tmp = + strfmt("string((const char *) (%s), (const char *) %s).c_str()", + data.ptr_expr(), + env->RValue(end_of_data)); out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", Location(), - pattern, - fmt("string((const char *) (%s), (const char *) %s).c_str()", - data.ptr_expr(), - env->RValue(end_of_data))); + pattern.c_str(), + tmp.c_str()); } void StringType::GenCheckingCStr(Output* out_cc, Env* env, @@ -341,7 +343,7 @@ void StringType::GenCheckingCStr(Output* out_cc, Env* env, str_size.c_str()); out_cc->inc_indent(); out_cc->println("{"); - GenStringMismatch(out_cc, env, data, str_val.c_str()); + GenStringMismatch(out_cc, env, data, str_val); out_cc->println("}"); out_cc->dec_indent(); } @@ -378,8 +380,8 @@ void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, env->RValue(string_length_var())); out_cc->inc_indent(); out_cc->println("{"); - GenStringMismatch(out_cc, env, data, - fmt("\"%s\"", regex_->str().c_str())); + string tmp = strfmt("\"%s\"", regex_->str().c_str()); + GenStringMismatch(out_cc, env, data, tmp); out_cc->println("}"); out_cc->dec_indent(); } diff --git a/tools/binpac/src/pac_strtype.h b/tools/binpac/src/pac_strtype.h index 55b35e54ab..81520d7b7c 100644 --- a/tools/binpac/src/pac_strtype.h +++ b/tools/binpac/src/pac_strtype.h @@ -44,7 +44,7 @@ protected: // Generate a string mismatch exception void GenStringMismatch(Output* out_cc, Env* env, - const DataPtr& data, const char *pattern); + const DataPtr& data, string pattern); void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index 044a5305d1..aa338aa285 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -283,7 +283,7 @@ void Type::Prepare(Env* env, int flags) if ( attr_if_expr() ) { ASSERT(value_var()); - ID *has_value_id = new ID(fmt("has_%s", value_var()->Name())); + ID *has_value_id = new ID(strfmt("has_%s", value_var()->Name())); has_value_field_ = new LetField(has_value_id, extern_type_bool->Clone(), attr_if_expr()); @@ -294,7 +294,7 @@ void Type::Prepare(Env* env, int flags) { ASSERT(flags & TO_BE_PARSED); ID *parsing_complete_var = - new ID(fmt("%s_parsing_complete", + new ID(strfmt("%s_parsing_complete", value_var() ? value_var()->Name() : "val")); DEBUG_MSG("Adding parsing complete var: %s\n", parsing_complete_var->Name()); @@ -837,7 +837,7 @@ bool Type::AddSizeVar(Output* out_cc, Env* env) ASSERT(! incremental_input()); - ID *size_var_id = new ID(fmt("%s__size", + ID *size_var_id = new ID(strfmt("%s__size", value_var() ? value_var()->Name() : decl_id()->Name())); DEBUG_MSG("adding size var `%s' to env %p\n", size_var_id->Name(), env); diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc index 35d52a098e..a26b2f7ab6 100644 --- a/tools/binpac/src/pac_typedecl.cc +++ b/tools/binpac/src/pac_typedecl.cc @@ -253,7 +253,7 @@ string TypeDecl::ParseFuncPrototype(Env* env) if ( RequiresAnalyzerContext::compute(type_) ) { Type *param_type = analyzer_context()->param_type(); - params += fmt(", %s %s", + params += strfmt(", %s %s", param_type->DataTypeConstRefStr().c_str(), env->LValue(analyzer_context_id)); } @@ -261,7 +261,7 @@ string TypeDecl::ParseFuncPrototype(Env* env) // Add parameter "byteorder" if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) { - params += fmt(", int %s", env->LValue(byteorder_id)); + params += strfmt(", int %s", env->LValue(byteorder_id)); } // Returns " %s()%s". @@ -358,7 +358,8 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) out_h->println(proto.c_str(), "", ";"); - out_cc->println(proto.c_str(), fmt("%s::", class_name().c_str()), ""); + string tmp = strfmt("%s::", class_name().c_str()); + out_cc->println(proto.c_str(), tmp.c_str(), ""); out_cc->inc_indent(); out_cc->println("{"); @@ -382,7 +383,7 @@ void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc) if ( init_buffer_length < 0 ) // cannot be statically determined { throw Exception(type()->attr_length_expr(), - fmt("cannot determine initial buffer length" + strfmt("cannot determine initial buffer length" " for type %s", id_->Name())); } diff --git a/tools/binpac/src/pac_utils.h b/tools/binpac/src/pac_utils.h index 37898e4070..ec70e6be8b 100644 --- a/tools/binpac/src/pac_utils.h +++ b/tools/binpac/src/pac_utils.h @@ -9,7 +9,4 @@ char* copy_string(const char* s); string strfmt(const char* fmt, ...); char* nfmt(const char* fmt, ...); -// const char* fmt(const char* fmt, ...); -#define fmt(x...) strfmt(x).c_str() - #endif /* pac_utils_h */ From 455e2fbac522b1ec74fccfa9f9b40027e3aa094e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 22 May 2018 12:33:23 -0500 Subject: [PATCH 073/343] binpac: BIT-1829: throw exceptions for excessive array sizes For arrays with unknown element size, it used to cap the array length to be the maximum it could be for the given input buffer, assuming 1-byte elements. An exception is instead now raised for cases where the maximum array size (number of elements) exceeds what's possibly in the buffer. Using an exception versus capping the length may help prevent protocol analyzers from unintentionally accessing array indices that were not actually parsed even if the evauluated-length-expression for that given array implies it may have been. --- tools/binpac/src/pac_array.cc | 65 ++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 05eefdeb6c..27c43b221b 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -278,23 +278,6 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) env->SetEvaluated(arraylength_var()); - // Check for overlong array length. We cap it at the - // maximum data size as we won't store more elements. - // e.g. this helps prevent user-controlled length fields - // from causing an excessive memory-allocation (for - // the array we'll be parsing into) unless they actually - // sent enough data to go along with it. Note that this check - // is *not* looking for whether the contents of the array will - // extend past the end of the data buffer. - out_cc->println("if ( t_begin_of_data + %s > t_end_of_data + 1 || t_begin_of_data + %s < t_begin_of_data )", - env->LValue(arraylength_var()), env->LValue(arraylength_var())); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("%s = t_end_of_data - t_begin_of_data + 1;", - env->LValue(arraylength_var())); - out_cc->println("}"); - out_cc->dec_indent(); - // Check negative array length out_cc->println("if ( %s < 0 )", env->LValue(arraylength_var())); @@ -305,27 +288,45 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) out_cc->println("}"); out_cc->dec_indent(); - if ( elemtype_->StaticSize(env) != -1 ) + string array_size; + + if ( elemtype_->StaticSize(env) == -1 ) + { + // Check for overlong array quantity. We cap it at the maximum + // array size (assume 1-byte elements * array length) as we can't + // possibly store more elements. e.g. this helps prevent + // user-controlled length fields from causing an excessive + // iteration and/or memory-allocation (for the array we'll be + // parsing into) unless they actually sent enough data to go along + // with it. Note that this check is *not* looking for whether the + // contents of the array will extend past the end of the data + // buffer. + out_cc->println("// Check array element quantity: %s", + data_id_str_.c_str()); + array_size = strfmt("(%s)", env->RValue(arraylength_var())); + } + else { // Boundary check the entire array if elements have static size. - string array_size = strfmt("((%d) * (%s))", - elemtype_->StaticSize(env), - env->RValue(arraylength_var())); out_cc->println("// Check bounds for static-size array: %s", data_id_str_.c_str()); - out_cc->println("if ( t_begin_of_data + %s > t_end_of_data || " - "t_begin_of_data + %s < t_begin_of_data )", - array_size.c_str(), array_size.c_str()); - out_cc->inc_indent(); - out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", - data_id_str_.c_str()); - out_cc->println(" %s, (%s) - (%s));", - array_size.c_str(), - env->RValue(end_of_data), - env->RValue(begin_of_data)); - out_cc->dec_indent(); elemtype_->SetBoundaryChecked(); + array_size = strfmt("((%d) * (%s))", + elemtype_->StaticSize(env), + env->RValue(arraylength_var())); } + + out_cc->println("if ( t_begin_of_data + %s > t_end_of_data || " + "t_begin_of_data + %s < t_begin_of_data )", + array_size.c_str(), array_size.c_str()); + out_cc->inc_indent(); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", + data_id_str_.c_str()); + out_cc->println(" %s, (%s) - (%s));", + array_size.c_str(), + env->RValue(end_of_data), + env->RValue(begin_of_data)); + out_cc->dec_indent(); } else if ( attr_restofdata_ ) { From 465fd6bd56d6fd2b98acb267d19e39d13b65b60d Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 22 May 2018 13:18:20 -0500 Subject: [PATCH 074/343] binpac: BIT-1829: throw exceptions for negative array length expressions --- tools/binpac/src/pac_array.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 27c43b221b..a878918d52 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -283,8 +283,12 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) env->LValue(arraylength_var())); out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("%s = 0;", - env->LValue(arraylength_var())); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", + data_id_str_.c_str()); + out_cc->println(" %s, (%s) - (%s));", + env->LValue(arraylength_var()), + env->RValue(end_of_data), + env->RValue(begin_of_data)); out_cc->println("}"); out_cc->dec_indent(); From c149922d64585093a8a5d15e8adcab749068cf8a Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 23 Jul 2018 18:09:26 +0000 Subject: [PATCH 075/343] binpac: Fix compiler warning. --- tools/binpac/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 127a6b90a3..dd54dda9f3 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -4,6 +4,7 @@ bison_target(PACParser pac_parse.yy ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.cc COMPILE_FLAGS "--debug") flex_target(PACScanner pac_scan.ll ${CMAKE_CURRENT_BINARY_DIR}/pac_scan.cc) add_flex_bison_dependency(PACScanner PACParser) +set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) From 9bb3a9459540e752735e9f4cda53ade760cc5d8d Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 13 Jul 2018 10:10:47 -0500 Subject: [PATCH 076/343] binpac: Don't install binpac.h.in --- tools/binpac/lib/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index b4179e702c..e026e8f4e9 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -10,7 +10,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/binpac.h.in include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) set(binpac_headers - binpac.h.in ${CMAKE_CURRENT_BINARY_DIR}/binpac.h binpac_analyzer.h binpac_buffer.h From eea32ada6da84b3ebaa6200bfb0d866cf41cdbbf Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 13 Jul 2018 10:11:28 -0500 Subject: [PATCH 077/343] binpac: Remove "installation skip" code paths --- tools/binpac/CMakeLists.txt | 8 +------- tools/binpac/lib/CMakeLists.txt | 10 ++-------- tools/binpac/src/CMakeLists.txt | 4 +--- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 17574e8a4e..dab67860dc 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -36,12 +36,6 @@ add_subdirectory(src) ######################################################################## ## Build Summary -if (BinPAC_SKIP_INSTALL) - set(binpac_install_summary "Install skipped") -else () - set(binpac_install_summary "${CMAKE_INSTALL_PREFIX}") -endif () - if (CMAKE_BUILD_TYPE) string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) endif () @@ -49,7 +43,7 @@ endif () message( "\n==================| BinPAC Build Summary |====================" "\n" - "\nInstall prefix: ${binpac_install_summary}" + "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" "\nDebug mode: ${ENABLE_DEBUG}" "\n" "\nCC: ${CMAKE_C_COMPILER}" diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index e026e8f4e9..77fd64979c 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -29,14 +29,8 @@ add_library(binpac_lib STATIC ${binpac_lib_SRCS}) set_target_properties(binpac_lib PROPERTIES OUTPUT_NAME binpac) -if (NOT BinPAC_SKIP_INSTALL) - install(TARGETS binpac_lib DESTINATION lib) - install(FILES - ${binpac_headers} - DESTINATION - include - ) -endif () +install(TARGETS binpac_lib DESTINATION lib) +install(FILES ${binpac_headers} DESTINATION include) # This is set to assist superprojects that want to build BinPac # from source and rely on it as a target diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index dd54dda9f3..57b5482111 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -100,9 +100,7 @@ set(binpac_SRCS add_executable(binpac ${binpac_SRCS}) -if (NOT BinPAC_SKIP_INSTALL) - install(TARGETS binpac DESTINATION bin) -endif () +install(TARGETS binpac DESTINATION bin) # This is set to assist superprojects that want to build BinPac # from source and rely on it as a target From 721ea63a3388474e318cc1517b8c5d835f48b241 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 24 Jul 2018 16:33:58 -0500 Subject: [PATCH 078/343] binpac: Install headers to alternate path as part of Bro sub-project --- tools/binpac/lib/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index 77fd64979c..89d9300039 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -30,7 +30,13 @@ add_library(binpac_lib STATIC ${binpac_lib_SRCS}) set_target_properties(binpac_lib PROPERTIES OUTPUT_NAME binpac) install(TARGETS binpac_lib DESTINATION lib) -install(FILES ${binpac_headers} DESTINATION include) + +if ( BRO_ROOT_DIR ) + # Installed in binpac subdir just for organization purposes. + install(FILES ${binpac_headers} DESTINATION include/binpac) +else () + install(FILES ${binpac_headers} DESTINATION include) +endif () # This is set to assist superprojects that want to build BinPac # from source and rely on it as a target From de87adf3988d910fa6f765f80ee473fda1f35347 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 1 Aug 2018 11:22:52 -0500 Subject: [PATCH 079/343] binpac: Update BinPAC_EXE CMake variable to be a full path --- tools/binpac/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 57b5482111..7ae99e4414 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -104,5 +104,5 @@ install(TARGETS binpac DESTINATION bin) # This is set to assist superprojects that want to build BinPac # from source and rely on it as a target -set(BinPAC_EXE binpac +set(BinPAC_EXE ${CMAKE_CURRENT_BINARY_DIR}/binpac CACHE STRING "BinPAC executable" FORCE) From 46e2490cb0ebfa2ab96798d0b5417613f42ca4f7 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 28 Aug 2018 10:23:24 -0500 Subject: [PATCH 080/343] binpac: Fix array bounds checking For arrays that are fields within a record, the bounds check was based on a pointer to the start of the record rather than the start of the array field. --- tools/binpac/src/pac_array.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index a878918d52..fc07e77517 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -320,16 +320,18 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) env->RValue(arraylength_var())); } - out_cc->println("if ( t_begin_of_data + %s > t_end_of_data || " - "t_begin_of_data + %s < t_begin_of_data )", - array_size.c_str(), array_size.c_str()); + const char* array_ptr_expr = data.ptr_expr(); + + out_cc->println("if ( %s + %s > %s || %s + %s < %s )", + array_ptr_expr, array_size.c_str(), env->RValue(end_of_data), + array_ptr_expr, array_size.c_str(), array_ptr_expr); out_cc->inc_indent(); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); out_cc->println(" %s, (%s) - (%s));", array_size.c_str(), env->RValue(end_of_data), - env->RValue(begin_of_data)); + array_ptr_expr); out_cc->dec_indent(); } else if ( attr_restofdata_ ) From 1d750aa164ffd58864ae7c3f3acaabfabda39ed8 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 30 Nov 2018 19:22:15 -0600 Subject: [PATCH 081/343] binpac: Replace u_char usages with unsigned char Improve Alpine (musl) support by not relying on the (technically) non-standard u_char typedef. --- tools/binpac/lib/binpac.h.in | 2 +- tools/binpac/lib/binpac_analyzer.h | 8 ++++---- tools/binpac/lib/binpac_buffer.cc | 10 +++++----- tools/binpac/lib/binpac_buffer.h | 6 +++--- tools/binpac/src/pac_type.cc | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index 63651e22ce..b106df9f09 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -109,7 +109,7 @@ inline int64 pac_swap(const int64 x) #define FixByteOrder(byteorder, x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap(x)) template -inline T UnMarshall(const u_char *data, int byteorder) +inline T UnMarshall(const unsigned char *data, int byteorder) { T result = 0; for ( int i = 0; i < (int) sizeof(T); ++i ) diff --git a/tools/binpac/lib/binpac_analyzer.h b/tools/binpac/lib/binpac_analyzer.h index b9228da5de..690092de1b 100644 --- a/tools/binpac/lib/binpac_analyzer.h +++ b/tools/binpac/lib/binpac_analyzer.h @@ -10,16 +10,16 @@ class ConnectionAnalyzer { public: virtual ~ConnectionAnalyzer() {} virtual void NewData(bool is_orig, - const u_char *begin_of_data, - const u_char *end_of_data) = 0; + const unsigned char* begin_of_data, + const unsigned char* end_of_data) = 0; }; // The interface for a flow analyzer class FlowAnalyzer { public: virtual ~FlowAnalyzer() {} - virtual void NewData(const u_char *begin_of_data, - const u_char *end_of_data) = 0; + virtual void NewData(const unsigned char* begin_of_data, + const unsigned char* end_of_data) = 0; }; } // namespace binpac diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index f02ef83da1..fe271fd181 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -12,8 +12,8 @@ namespace binpac { extern double network_time(); namespace { - const u_char CR = '\r'; - const u_char LF = '\n'; + const unsigned char CR = '\r'; + const unsigned char LF = '\n'; } FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) @@ -108,10 +108,10 @@ void FlowBuffer::ExpandBuffer(int length) // Allocate a new buffer and copy the existing contents buffer_length_ = length; - u_char *new_buf = (u_char *) realloc(buffer_, buffer_length_); + unsigned char* new_buf = (unsigned char *) realloc(buffer_, buffer_length_); BINPAC_ASSERT(new_buf); #if 0 - u_char* new_buf = new u_char[buffer_length_]; + unsigned char* new_buf = new unsigned char[buffer_length_]; if ( buffer_ && buffer_n_ > 0 ) memcpy(new_buf, buffer_, buffer_n_); delete [] buffer_; @@ -119,7 +119,7 @@ void FlowBuffer::ExpandBuffer(int length) buffer_ = new_buf; } -void FlowBuffer::SetLineBreaker(u_char *lbreaker) +void FlowBuffer::SetLineBreaker(unsigned char* lbreaker) { linebreaker_ = *lbreaker; linebreak_style_default = linebreak_style_; diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h index dda80c8785..a2902daf02 100644 --- a/tools/binpac/lib/binpac_buffer.h +++ b/tools/binpac/lib/binpac_buffer.h @@ -73,7 +73,7 @@ public: return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; } - void SetLineBreaker(u_char *lbreaker); + void SetLineBreaker(unsigned char* lbreaker); void UnsetLineBreaker(); void NewLine(); // A negative frame_length represents a frame till EOF @@ -126,7 +126,7 @@ protected: int buffer_n_; // number of bytes in the buffer int buffer_length_; // size of the buffer - u_char *buffer_; + unsigned char* buffer_; bool message_complete_; int frame_length_; bool chunked_; @@ -134,7 +134,7 @@ protected: LineBreakStyle linebreak_style_; LineBreakStyle linebreak_style_default; - u_char linebreaker_; + unsigned char linebreaker_; enum { UNKNOWN_MODE, diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index aa338aa285..d4d9119c26 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -454,8 +454,8 @@ void Type::GenBufferConfiguration(Output *out_cc, Env *env) env->RValue(buffering_state_id)); out_cc->inc_indent(); out_cc->println("{"); - if(BufferableWithLineBreaker()) - out_cc->println("%s->SetLineBreaker((u_char*)%s);", + if ( BufferableWithLineBreaker() ) + out_cc->println("%s->SetLineBreaker((unsigned char*)%s);", env->LValue(flow_buffer_id), LineBreaker()->orig()); else out_cc->println("%s->UnsetLineBreaker();", From 2da5fecc16f11e3bb37bcc233255bab1f287a90f Mon Sep 17 00:00:00 2001 From: Derek Ditch Date: Wed, 13 Feb 2019 21:04:35 -0600 Subject: [PATCH 082/343] binpac: Set installdirs using GNUInstallDirs module in CMake --- tools/binpac/CMakeLists.txt | 3 +++ tools/binpac/lib/CMakeLists.txt | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index dab67860dc..25fccc98c0 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -4,6 +4,9 @@ include(cmake/CommonCMakeConfig.cmake) file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) +# Set default install paths +include(GNUInstallDirs) + ######################################################################## ## Dependency Configuration diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index 89d9300039..ed338b42b2 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -29,13 +29,13 @@ add_library(binpac_lib STATIC ${binpac_lib_SRCS}) set_target_properties(binpac_lib PROPERTIES OUTPUT_NAME binpac) -install(TARGETS binpac_lib DESTINATION lib) +install(TARGETS binpac_lib DESTINATION ${CMAKE_INSTALL_LIBDIR}) if ( BRO_ROOT_DIR ) # Installed in binpac subdir just for organization purposes. - install(FILES ${binpac_headers} DESTINATION include/binpac) + install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/binpac) else () - install(FILES ${binpac_headers} DESTINATION include) + install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) endif () # This is set to assist superprojects that want to build BinPac From 7bb1a148afc22b6ed9a7817f32f24465e911f9a6 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 15 Feb 2019 15:24:38 -0600 Subject: [PATCH 083/343] binpac: Bump minimum CMake version to 2.8.12 --- tools/binpac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 25fccc98c0..ef9a0c9edf 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,5 +1,5 @@ project(BinPAC C CXX) -cmake_minimum_required(VERSION 2.6.3 FATAL_ERROR) +cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) include(cmake/CommonCMakeConfig.cmake) file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) From 7e6e24a4d8e9ed52b2f8914649352c736213dee3 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 18 Mar 2019 13:49:52 -0700 Subject: [PATCH 084/343] binpac: Build binpac shared lib instead of static by default Related to https://github.com/zeek/zeek/issues/307 --- tools/binpac/CMakeLists.txt | 32 +++++++++++++++++++++++++++++++- tools/binpac/lib/CMakeLists.txt | 26 +++++++++++++++++++------- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index ef9a0c9edf..7ededcf5fc 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -3,6 +3,20 @@ cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) include(cmake/CommonCMakeConfig.cmake) file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) +string(REPLACE "." " " _version_numbers ${BINPAC_VERSION}) +separate_arguments(_version_numbers) +list(GET _version_numbers 0 BINPAC_VERSION_MAJOR) +list(GET _version_numbers 1 BINPAC_VERSION_MINOR) + +# The SO number shall increase only if binary interface changes. +set(BINPAC_SOVERSION 0) + +set(ENABLE_SHARED true) + +if ( ENABLE_STATIC_ONLY ) + set(ENABLE_STATIC true) + set(ENABLE_SHARED false) +endif () # Set default install paths include(GNUInstallDirs) @@ -43,11 +57,27 @@ if (CMAKE_BUILD_TYPE) string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) endif () +macro(display test desc summary) + if ( ${test} ) + set(${summary} ${desc}) + else () + set(${summary} no) + endif() +endmacro() + +display(ENABLE_SHARED yes shared_summary) +display(ENABLE_STATIC yes static_summary) + message( "\n==================| BinPAC Build Summary |====================" + "\nVersion: ${BINPAC_VERSION}" + "\nSO version: ${BINPAC_SOVERSION}" "\n" - "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nBuild Type: ${CMAKE_BUILD_TYPE}" "\nDebug mode: ${ENABLE_DEBUG}" + "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nShared libs: ${shared_summary}" + "\nStatic libs: ${static_summary}" "\n" "\nCC: ${CMAKE_C_COMPILER}" "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index ed338b42b2..17a7e0d8b2 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -25,11 +25,21 @@ set(binpac_lib_SRCS ${binpac_headers} ) -add_library(binpac_lib STATIC ${binpac_lib_SRCS}) +if ( ENABLE_SHARED ) + add_library(binpac_lib SHARED ${binpac_lib_SRCS}) + set_target_properties(binpac_lib PROPERTIES + SOVERSION ${BINPAC_SOVERSION} + VERSION ${BINPAC_VERSION_MAJOR}.${BINPAC_VERSION_MINOR} + MACOSX_RPATH true + OUTPUT_NAME binpac) + install(TARGETS binpac_lib DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif () -set_target_properties(binpac_lib PROPERTIES OUTPUT_NAME binpac) - -install(TARGETS binpac_lib DESTINATION ${CMAKE_INSTALL_LIBDIR}) +if ( ENABLE_STATIC ) + add_library(binpac_static STATIC ${binpac_lib_SRCS}) + set_target_properties(binpac_static PROPERTIES OUTPUT_NAME binpac) + install(TARGETS binpac_static DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif () if ( BRO_ROOT_DIR ) # Installed in binpac subdir just for organization purposes. @@ -40,9 +50,11 @@ endif () # This is set to assist superprojects that want to build BinPac # from source and rely on it as a target -set(BinPAC_LIBRARY binpac_lib - CACHE STRING "BinPAC static library" FORCE -) +if ( ENABLE_SHARED ) + set(BinPAC_LIBRARY binpac_lib CACHE STRING "BinPAC library" FORCE) +else () + set(BinPAC_LIBRARY binpac_static CACHE STRING "BinPAC library" FORCE) +endif () set(BinPAC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} From b4b229acf7791ad51c311ac003fe3f5e00ad5444 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 5 Apr 2019 12:21:42 -0700 Subject: [PATCH 085/343] binpac: Add FlowBuffer policy mechanisms This allows for tunability of the following behaviors: * Minimum flowbuffer capacity to use when parsing a new unit * Threshold at which flowbuffer capacity is contracted back to the minimum after parsing a complete unit and before parsing the next * Maximum flowbuffer capacity to allow when parsing a given unit Failed flowbuffer allocations due to reaching maximum capacity or any other reason now throw ExceptionFlowBufferAlloc. --- tools/binpac/lib/binpac_buffer.cc | 49 +++++++++++++++++++++++------ tools/binpac/lib/binpac_buffer.h | 18 +++++++++++ tools/binpac/lib/binpac_exception.h | 9 ++++++ tools/binpac/lib/binpac_regex.h | 10 ++++-- 4 files changed, 73 insertions(+), 13 deletions(-) diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index fe271fd181..6440ef2c25 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -16,6 +16,15 @@ namespace { const unsigned char LF = '\n'; } +binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = { + // max_capacity + 10 * 1024 * 1024, + // min_capacity + 512, + // contract_threshold + 2 * 1024 * 1024, +}; + FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) { buffer_length_ = 0; @@ -75,6 +84,7 @@ void FlowBuffer::NewMessage() buffer_n_ = 0; message_complete_ = false; + ContractBuffer(); } void FlowBuffer::ResetLineState() @@ -99,23 +109,41 @@ void FlowBuffer::ExpandBuffer(int length) { if ( buffer_length_ >= length ) return; - // So length > 0 - if ( length < 512 ) - length = 512; + + if ( length < policy.min_capacity ) + length = policy.min_capacity; if ( length < buffer_length_ * 2 ) length = buffer_length_ * 2; + if ( length > policy.max_capacity ) + { + std::string reason = strfmt("expand past max capacity %d/%zu", + length, policy.max_capacity); + throw ExceptionFlowBufferAlloc(reason.c_str()); + } + // Allocate a new buffer and copy the existing contents buffer_length_ = length; unsigned char* new_buf = (unsigned char *) realloc(buffer_, buffer_length_); - BINPAC_ASSERT(new_buf); -#if 0 - unsigned char* new_buf = new unsigned char[buffer_length_]; - if ( buffer_ && buffer_n_ > 0 ) - memcpy(new_buf, buffer_, buffer_n_); - delete [] buffer_; -#endif + + if ( ! new_buf ) + throw ExceptionFlowBufferAlloc("expand realloc OOM"); + + buffer_ = new_buf; + } + +void FlowBuffer::ContractBuffer() + { + if ( buffer_length_ < policy.contract_threshold ) + return; + + buffer_length_ = policy.min_capacity; + unsigned char* new_buf = (unsigned char *) realloc(buffer_, buffer_length_); + + if ( ! new_buf ) + throw ExceptionFlowBufferAlloc("contract realloc OOM"); + buffer_ = new_buf; } @@ -186,6 +214,7 @@ void FlowBuffer::DiscardData() buffer_n_ = 0; frame_length_ = 0; + ContractBuffer(); } void FlowBuffer::set_eof() diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h index a2902daf02..ef37082924 100644 --- a/tools/binpac/lib/binpac_buffer.h +++ b/tools/binpac/lib/binpac_buffer.h @@ -8,6 +8,12 @@ namespace binpac { class FlowBuffer { public: + struct Policy { + int max_capacity; + int min_capacity; + int contract_threshold; + }; + enum LineBreakStyle { CR_OR_LF, // CR or LF or CRLF STRICT_CRLF, // CR followed by LF @@ -95,6 +101,9 @@ public: bool have_pending_request() const { return have_pending_request_; } + static void init(Policy p) + { policy = p; } + protected: // Reset the buffer for a new message void NewMessage(); @@ -106,6 +115,13 @@ protected: // buffer. void ExpandBuffer(int length); + // Contract the buffer to some minimum capacity. + // Existing contents in the buffer are preserved (but only usage + // at the time of creation this function is when the contents + // are being discarded due to parsing exception or have already been + // copied out after parsing a complete unit). + void ContractBuffer(); + // Reset line state when transit from frame mode to line mode. void ResetLineState(); @@ -153,6 +169,8 @@ protected: int data_seq_at_orig_data_end_; bool eof_; bool have_pending_request_; + + static Policy policy; }; typedef FlowBuffer *flow_buffer_t; diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h index 4a4ae40e31..07960f6248 100644 --- a/tools/binpac/lib/binpac_exception.h +++ b/tools/binpac/lib/binpac_exception.h @@ -116,6 +116,15 @@ public: } }; +class ExceptionFlowBufferAlloc : public Exception +{ +public: + ExceptionFlowBufferAlloc(const char* reason) + { + append(binpac_fmt("flowbuffer allocation failed: %s", reason)); + } +}; + } #endif // binpac_exception_h diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index 49d58e4c0a..52c4d1e85e 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -13,7 +13,8 @@ namespace binpac // // Note, this must be declared/defined here, and inline, because the RE // functionality can only be used when compiling from inside Bro. -inline void init(); +// A copy is made of any FlowBuffer policy struct data passed. +inline void init(FlowBuffer::Policy* fbp = 0); // Internal vector recording not yet compiled matchers. extern std::vector* uncompiled_re_matchers; @@ -42,7 +43,7 @@ public: } private: - friend void ::binpac::init(); + friend void ::binpac::init(FlowBuffer::Policy*); // Function, and state, for compiling matchers. static void init(); @@ -68,9 +69,12 @@ inline void RegExMatcher::init() uncompiled_re_matchers->clear(); } -inline void init() +inline void init(FlowBuffer::Policy* fbp) { RegExMatcher::init(); + + if ( fbp ) + FlowBuffer::init(*fbp); } } // namespace binpac From 21cf20fc6f985a7bdbfacf0320ad2e7438a66da6 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 16 May 2019 08:44:42 -0700 Subject: [PATCH 086/343] binpac: Improve storage type used for case-type index The type used to store the index for a case-type now tracks the type of the index expression rather than always using an "int". The case fields also now have some checking done at code-gen-time to ensure the constants used for cases does not exceed the numeric limit of the type used in the case's index expression. Then, assuming, it looks safe, the C++ case labels are generated with casts to the type of the Binpac case's index expression to ensure compilers accept it (since all Binpac numbers use "int" for storage/printing internally). --- tools/binpac/lib/binpac_exception.h | 15 +++-- tools/binpac/src/pac_case.cc | 100 +++++++++++++++++++++++++--- tools/binpac/src/pac_case.h | 4 +- tools/binpac/src/pac_exception.cc | 12 ++++ tools/binpac/src/pac_exception.h | 18 +++++ tools/binpac/src/pac_expr.cc | 7 +- tools/binpac/src/pac_let.cc | 2 +- 7 files changed, 137 insertions(+), 21 deletions(-) diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h index 07960f6248..cdbfd70405 100644 --- a/tools/binpac/lib/binpac_exception.h +++ b/tools/binpac/lib/binpac_exception.h @@ -1,6 +1,9 @@ #ifndef binpac_exception_h #define binpac_exception_h +#include +#include + namespace binpac { class Exception @@ -45,19 +48,19 @@ class ExceptionInvalidCase : public Exception { public: ExceptionInvalidCase(const char* location, - int index, + int64_t index, const char *expected) : location_(location), index_(index), expected_(expected) { - append(binpac_fmt("invalid case: %s: %d (%s)", + append(binpac_fmt("invalid case: %s: %" PRIi64 " (%s)", location, index, expected)); } protected: const char* location_; - int index_; + int64_t index_; string expected_; }; @@ -65,17 +68,17 @@ class ExceptionInvalidCaseIndex : public Exception { public: ExceptionInvalidCaseIndex(const char* location, - int index) + int64_t index) : location_(location), index_(index) { - append(binpac_fmt("invalid index for case: %s: %d", + append(binpac_fmt("invalid index for case: %s: %" PRIi64, location, index)); } protected: const char* location_; - int index_; + int64_t index_; }; class ExceptionInvalidOffset : public Exception diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index 1e501fc301..95cb3524b5 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -5,9 +5,13 @@ #include "pac_output.h" #include "pac_typedecl.h" #include "pac_utils.h" +#include "pac_btype.h" #include "pac_case.h" +#include +#include + CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) : Type(CASE), index_expr_(index_expr), cases_(cases) { @@ -64,7 +68,9 @@ void CaseType::Prepare(Env* env, int flags) ASSERT(flags & TO_BE_PARSED); index_var_ = new ID(strfmt("%s_case_index", value_var()->Name())); - env->AddID(index_var_, MEMBER_VAR, extern_type_int); + // Unable to get the type for index_var_ at this moment, but we'll + // generate the right type based on index_expr_ later. + env->AddID(index_var_, MEMBER_VAR, 0); // Sort the cases_ to put the default case at the end of the list CaseFieldList::iterator default_case_it = @@ -100,13 +106,25 @@ void CaseType::Prepare(Env* env, int flags) void CaseType::GenPrivDecls(Output* out_h, Env* env) { - out_h->println("int %s;", env->LValue(index_var_)); + Type* t = index_expr_->DataType(env); + + if ( t->tot() != Type::BUILTIN ) + // It's a Type::EXTERN with a C++ type of "int", "bool", or "enum", + // any of which will convert consistently using an int as storage type. + t = extern_type_int; + + out_h->println("%s %s;", t->DataTypeStr().c_str(), env->LValue(index_var_)); Type::GenPrivDecls(out_h, env); } void CaseType::GenPubDecls(Output* out_h, Env* env) { - out_h->println("int %s const { return %s; }", + Type* t = index_expr_->DataType(env); + + if ( t->tot() != Type::BUILTIN ) + t = extern_type_int; + + out_h->println("%s %s const { return %s; }", t->DataTypeStr().c_str(), env->RValue(index_var_), env->LValue(index_var_)); Type::GenPubDecls(out_h, env); } @@ -168,7 +186,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, { out_cc->println("default:"); out_cc->inc_indent(); - out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", %s);", + out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", decl_id()->Name(), env->RValue(index_var_)); out_cc->println("break;"); out_cc->dec_indent(); @@ -248,18 +266,80 @@ CaseField::~CaseField() delete_list(ExprList, index_); } -void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env) +void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env, Type* switch_type) { if ( index_list ) { foreach(i, ExprList, index_list) { Expr *index_expr = *i; + + Type* case_type = index_expr->DataType(env); + + if ( case_type->tot() == Type::BUILTIN && case_type->StaticSize(env) > 4 ) + throw ExceptionInvalidCaseSizeExpr(index_expr); + int index_const; if ( ! index_expr->ConstFold(env, &index_const) ) throw ExceptionNonConstExpr(index_expr); - out_cc->println("case %d:", index_const); + + // External C++ types like "int", "bool", "enum" + // all use "int" type internally by default. + int case_type_width = 4; + int switch_type_width = 4; + + if ( switch_type->tot() == Type::BUILTIN ) + switch_type_width = switch_type->StaticSize(env); + + if ( case_type->tot() == Type::BUILTIN ) + case_type_width = case_type->StaticSize(env); + + if ( case_type_width > switch_type_width ) + { + BuiltInType* st = (BuiltInType*)switch_type; + + if ( switch_type_width == 1 ) + { + if ( st->bit_type() == BuiltInType::INT8 ) + { + if ( index_const < std::numeric_limits::min() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + if ( index_const > std::numeric_limits::max() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + } + else + { + if ( index_const < std::numeric_limits::min() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + if ( index_const > std::numeric_limits::max() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + } + } + else if ( switch_type_width == 2 ) + { + if ( st->bit_type() == BuiltInType::INT16 ) + { + if ( index_const < std::numeric_limits::min() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + if ( index_const > std::numeric_limits::max() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + } + else + { + if ( index_const < std::numeric_limits::min() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + if ( index_const > std::numeric_limits::max() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + } + } + } + + // We're always using "int" for storage, so ok to just + // cast into the type used by the switch statement since + // some unsafe stuff is already checked above. + out_cc->println("case ((%s) %d):", + switch_type->DataTypeStr().c_str(), index_const); } } else @@ -296,7 +376,7 @@ void CaseField::GenPubDecls(Output* out_h, Env* env) out_h->println("switch ( %s )", env->RValue(index_var_)); out_h->inc_indent(); out_h->println("{"); - GenCaseStr(index_, out_h, env); + GenCaseStr(index_, out_h, env, case_type()->IndexExpr()->DataType(env)); out_h->inc_indent(); out_h->println("break; // OK"); out_h->dec_indent(); @@ -304,7 +384,7 @@ void CaseField::GenPubDecls(Output* out_h, Env* env) out_h->println("default:"); out_h->inc_indent(); out_h->println( - "throw binpac::ExceptionInvalidCase(\"%s\", %s, \"%s\");", + "throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");", id_->LocName(), env->RValue(index_var_), OrigExprList(index_).c_str()); @@ -335,7 +415,7 @@ void CaseField::GenInitCode(Output* out_cc, Env* env) void CaseField::GenCleanUpCode(Output* out_cc, Env* env) { - GenCaseStr(index_, out_cc, env); + GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); out_cc->inc_indent(); out_cc->println("// Clean up \"%s\"", id_->Name()); out_cc->println("{"); @@ -349,7 +429,7 @@ void CaseField::GenCleanUpCode(Output* out_cc, Env* env) void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, const ID* size_var) { - GenCaseStr(index_, out_cc, env); + GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); out_cc->inc_indent(); out_cc->println("// Parse \"%s\"", id_->Name()); out_cc->println("{"); diff --git a/tools/binpac/src/pac_case.h b/tools/binpac/src/pac_case.h index c9e416cfe1..7e7bb482ce 100644 --- a/tools/binpac/src/pac_case.h +++ b/tools/binpac/src/pac_case.h @@ -32,6 +32,8 @@ public: Type *ValueType() const; + Expr* IndexExpr() const { return index_expr_; } + bool IsPointerType() const { return ValueType()->IsPointerType(); } protected: @@ -94,6 +96,6 @@ protected: // Generate a list of "case X:" lines from index_list. Each index // expression must be constant foldable. -void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env); +void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env, Type* switch_type); #endif // pac_case_h diff --git a/tools/binpac/src/pac_exception.cc b/tools/binpac/src/pac_exception.cc index e9648495fd..64ad6663d9 100644 --- a/tools/binpac/src/pac_exception.cc +++ b/tools/binpac/src/pac_exception.cc @@ -69,3 +69,15 @@ ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) { append(strfmt("Expression `%s' is not constant", expr->orig())); } + +ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr) + : Exception(expr), expr(expr) + { + append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index", expr->orig())); + } + +ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr) + : Exception(expr), expr(expr) + { + append(strfmt("Expression `%s' as a case index is outside the numeric limit of the type used for the switch expression", expr->orig())); + } diff --git a/tools/binpac/src/pac_exception.h b/tools/binpac/src/pac_exception.h index 5920af0d54..c3320cf98e 100644 --- a/tools/binpac/src/pac_exception.h +++ b/tools/binpac/src/pac_exception.h @@ -92,4 +92,22 @@ private: const Expr *expr; }; +class ExceptionInvalidCaseSizeExpr : public Exception +{ +public: + ExceptionInvalidCaseSizeExpr(const Expr* expr); + +private: + const Expr *expr; +}; + +class ExceptionInvalidCaseLimitExpr : public Exception +{ +public: + ExceptionInvalidCaseLimitExpr(const Expr* expr); + +private: + const Expr *expr; +}; + #endif /* pac_exception_h */ diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index 3f74aa8e3f..4062525a57 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -257,6 +257,7 @@ void Expr::GenCaseEval(Output *out_cc, Env *env) (*i)->value()->ForceIDEval(out_cc, env); out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); + Type* switch_type = operand_[0]->DataType(env); out_cc->inc_indent(); out_cc->println("{"); @@ -274,7 +275,7 @@ void Expr::GenCaseEval(Output *out_cc, Env *env) } else { - GenCaseStr(index, out_cc, env); + GenCaseStr(index, out_cc, env, switch_type); out_cc->inc_indent(); out_cc->println("%s = %s;", env->LValue(val_var), @@ -285,7 +286,7 @@ void Expr::GenCaseEval(Output *out_cc, Env *env) } // Generate the default case after all other cases - GenCaseStr(0, out_cc, env); + GenCaseStr(0, out_cc, env, switch_type); out_cc->inc_indent(); if ( default_case ) { @@ -295,7 +296,7 @@ void Expr::GenCaseEval(Output *out_cc, Env *env) } else { - out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", %s);", + out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", Location(), operand_[0]->EvalExpr(out_cc, env)); } out_cc->println("break;"); diff --git a/tools/binpac/src/pac_let.cc b/tools/binpac/src/pac_let.cc index c850784554..06dd0416ce 100644 --- a/tools/binpac/src/pac_let.cc +++ b/tools/binpac/src/pac_let.cc @@ -126,7 +126,7 @@ LetDecl::LetDecl(ID *id, Type *type, Expr *expr) Env *env = global_env(); int c; if ( expr_ && expr_->ConstFold(env, &c) ) - env->AddConstID(id_, c); + env->AddConstID(id_, c, type); else env->AddID(id_, GLOBAL_VAR, type_); } From 533d823514f67e73a11e9dc3fd0e8ebc2e7e07fd Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 20 May 2019 13:21:24 -0700 Subject: [PATCH 087/343] binpac: Fix C++11 compatibility issue for older compilers --- tools/binpac/src/pac_case.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index 95cb3524b5..ffe22581a5 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -10,7 +10,7 @@ #include "pac_case.h" #include -#include +#include CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) : Type(CASE), index_expr_(index_expr), cases_(cases) From 078722fc8d60ebc4c6db5e4fbc5e43579be230aa Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 16 May 2019 23:55:02 -0500 Subject: [PATCH 088/343] binpac: Rename Bro to Zeek --- tools/binpac/TODO | 2 +- tools/binpac/lib/binpac_regex.h | 2 +- tools/binpac/src/pac_cstr.cc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/binpac/TODO b/tools/binpac/TODO index 4b2833f224..497485d48f 100644 --- a/tools/binpac/TODO +++ b/tools/binpac/TODO @@ -5,7 +5,7 @@ Big features * Case and analyzer redef * &also withinput * Explicit analyzer context (interface + instantiation) "withcontext" -+ Interface with C++ and Bro (events, extern, weird) ++ Interface with C++ and Zeek (events, extern, weird) + Incremental input + ASCII protocols + Reassembly diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index 52c4d1e85e..53981e8661 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -12,7 +12,7 @@ namespace binpac // Must be called before any binpac functionality is used. // // Note, this must be declared/defined here, and inline, because the RE -// functionality can only be used when compiling from inside Bro. +// functionality can only be used when compiling from inside Zeek. // A copy is made of any FlowBuffer policy struct data passed. inline void init(FlowBuffer::Policy* fbp = 0); diff --git a/tools/binpac/src/pac_cstr.cc b/tools/binpac/src/pac_cstr.cc index 45e0b78f5e..4ff3d1e6be 100644 --- a/tools/binpac/src/pac_cstr.cc +++ b/tools/binpac/src/pac_cstr.cc @@ -18,7 +18,7 @@ private: string msg_; }; -// Copied from util.cc of Bro +// Copied from util.cc of Zeek int expand_escape(const char*& s) { switch ( *(s++) ) { @@ -80,7 +80,7 @@ int expand_escape(const char*& s) ConstString::ConstString(const string &s) : str_(s) { - // Copied from scan.l of Bro + // Copied from scan.l of Zeek try { const char* text = str_.c_str(); From 219dbd0fa3fbdb58c0203646046b7be99bf38213 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Sun, 19 May 2019 14:02:33 -0500 Subject: [PATCH 089/343] binpac: More Bro to Zeek renaming --- tools/binpac/lib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index 17a7e0d8b2..d79b3f38b1 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -41,7 +41,7 @@ if ( ENABLE_STATIC ) install(TARGETS binpac_static DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif () -if ( BRO_ROOT_DIR ) +if ( ZEEK_ROOT_DIR ) # Installed in binpac subdir just for organization purposes. install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/binpac) else () From 7632c69566b8e1aabbf24e265d6403777e882d05 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 1 Jul 2019 10:33:44 -0700 Subject: [PATCH 090/343] binpac: Fix a printf format specifier --- tools/binpac/lib/binpac_buffer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index 6440ef2c25..6bf154aea7 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -118,7 +118,7 @@ void FlowBuffer::ExpandBuffer(int length) if ( length > policy.max_capacity ) { - std::string reason = strfmt("expand past max capacity %d/%zu", + std::string reason = strfmt("expand past max capacity %d/%d", length, policy.max_capacity); throw ExceptionFlowBufferAlloc(reason.c_str()); } From ef933c9e76308a59f5a1a8f02d29016327be2a37 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 26 Jun 2019 23:31:59 -0700 Subject: [PATCH 091/343] binpac: Fix signed integer overflow in array bounds checks Array lengths use signed integer storage, so multiplication of that by the element size for purpose of bounds checking against available data may produce a signed integer overlow, which is undefined behavior. --- tools/binpac/src/pac_array.cc | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index fc07e77517..16d961d80b 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -292,7 +292,7 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) out_cc->println("}"); out_cc->dec_indent(); - string array_size; + int element_size; if ( elemtype_->StaticSize(env) == -1 ) { @@ -307,7 +307,7 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) // buffer. out_cc->println("// Check array element quantity: %s", data_id_str_.c_str()); - array_size = strfmt("(%s)", env->RValue(arraylength_var())); + element_size = 1; } else { @@ -315,21 +315,34 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) out_cc->println("// Check bounds for static-size array: %s", data_id_str_.c_str()); elemtype_->SetBoundaryChecked(); - array_size = strfmt("((%d) * (%s))", - elemtype_->StaticSize(env), - env->RValue(arraylength_var())); + element_size = elemtype_->StaticSize(env); + + if ( element_size == 0 ) + { + // If we know we have an array of empty elements, probably + // better to structure the parser as just a single empty + // field to avoid DoS vulnerability of allocating + // arbitrary number of empty records (i.e. cheap for them, + // but costly for us unless we have special optimization + // for this scenario to forgo the usual allocation). + throw Exception(this, "using an array of known-to-be-empty elements is possibly a bad idea"); + } } const char* array_ptr_expr = data.ptr_expr(); + string max_elements_available = strfmt("((%s - %s) / %d)", + env->RValue(end_of_data), + array_ptr_expr, + element_size); - out_cc->println("if ( %s + %s > %s || %s + %s < %s )", - array_ptr_expr, array_size.c_str(), env->RValue(end_of_data), - array_ptr_expr, array_size.c_str(), array_ptr_expr); + out_cc->println("if ( %s > %s )", + env->RValue(arraylength_var()), + max_elements_available.c_str()); out_cc->inc_indent(); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); out_cc->println(" %s, (%s) - (%s));", - array_size.c_str(), + env->RValue(arraylength_var()), env->RValue(end_of_data), array_ptr_expr); out_cc->dec_indent(); From 8b4b74e54afa542c503bf9bc384e7a45ab1e16e3 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 28 Oct 2019 17:59:21 -0700 Subject: [PATCH 092/343] binpac: Move CMake project() after cmake_minimum_required() --- tools/binpac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 7ededcf5fc..46f70a27ac 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,5 +1,5 @@ -project(BinPAC C CXX) cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) +project(BinPAC C CXX) include(cmake/CommonCMakeConfig.cmake) file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) From 3cba237e843f745ec29a7f092cd3409c8ee34ab6 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 6 Nov 2019 22:23:55 -0800 Subject: [PATCH 093/343] binpac: Fix shared library versioning to agree with OpenBSD expectations OpenBSD shared library names are like "libfoo.so.major.minor" and binpac was previously letting the post-release number into the name like "libbinpac.so.0.54-7", which isn't compatible with that scheme. Related to https://github.com/zeek/zeek/issues/649 --- tools/binpac/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 46f70a27ac..3d0c01e405 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -7,6 +7,7 @@ string(REPLACE "." " " _version_numbers ${BINPAC_VERSION}) separate_arguments(_version_numbers) list(GET _version_numbers 0 BINPAC_VERSION_MAJOR) list(GET _version_numbers 1 BINPAC_VERSION_MINOR) +string(REGEX REPLACE "-[0-9]*$" "" BINPAC_VERSION_MINOR ${BINPAC_VERSION_MINOR}) # The SO number shall increase only if binary interface changes. set(BINPAC_SOVERSION 0) From b2ef28c2e7aeeb667347af642a2ccb2f83f07842 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 15 Nov 2019 17:45:29 -0800 Subject: [PATCH 094/343] binpac: Fix Zeek build for multi-config CMake generators (e.g. Xcode) --- tools/binpac/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 7ae99e4414..dcadb8b797 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -104,5 +104,5 @@ install(TARGETS binpac DESTINATION bin) # This is set to assist superprojects that want to build BinPac # from source and rely on it as a target -set(BinPAC_EXE ${CMAKE_CURRENT_BINARY_DIR}/binpac +set(BinPAC_EXE ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/binpac CACHE STRING "BinPAC executable" FORCE) From 3aad9c74c32a100638d29e0c09246382cd30072f Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 19 Dec 2019 12:26:15 -0800 Subject: [PATCH 095/343] binpac: Disable LeakSanitizer https://github.com/zeek/zeek/issues/699 --- tools/binpac/src/pac_main.cc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index 0dbb43342e..951929fa4e 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -209,8 +209,30 @@ void usage() exit(1); } +// GCC uses __SANITIZE_ADDRESS__, Clang uses __has_feature +#if defined(__SANITIZE_ADDRESS__) + #define USING_ASAN +#endif + +#if defined(__has_feature) + #if __has_feature(address_sanitizer) + #define USING_ASAN + #endif +#endif + +#if defined(USING_ASAN) + #include +#endif + int main(int argc, char* argv[]) { + #if defined(USING_ASAN) + // We generally do not care at all if binpac is leaking and other + // projects that use it, like Zeek, only have their build tripped up + // by the default behavior of LSAN to treat leaks as errors. + __lsan_disable(); + #endif + #ifdef HAVE_MALLOC_OPTIONS extern char *malloc_options; #endif From db7c3d7c5c54c878a5a055c67117220bbefccf81 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 19 Mar 2020 21:33:28 -0700 Subject: [PATCH 096/343] binpac: Fix incorrect boundary checks in flowbuffer frame length parsing Incremental flowbuffer parsing sought to first parse the "minimum header length" required to get the full frame length, possibly from a record field, but generating the logic to parse that field could greedily bundle in additional boundary-checks for all subsequent fields of known-size. E.g. for flowunit parsing of this: type HDR = record { version: uint8; reserved: uint8; len: uint16; } &byteorder=bigendian; type FOO_PDU(is_orig: bool) = record { hdr: HDR; plen: uint8; ptype: uint8; something: bytestring &restofdata; } &byteorder=bigendian, &length=hdr.len; The flowbuffer was correctly seeking to buffer 4 bytes and parse the "hdr.len" field, but the generated parsing logic for "hdr.len" included a boundary check all the way up to include "plen" and "ptype". This causes out-of-bounds exceptions to be thrown for inputs that should actually be possible to incrementally parse via flowbuffer. --- tools/binpac/src/pac_record.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index 813f201b8b..50f850fba5 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -431,7 +431,13 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) if ( ! record_type()->incremental_parsing() ) { data = getFieldBegin(out_cc, env); - AttemptBoundaryCheck(out_cc, env); + + Expr* len_expr = record_type()->attr_length_expr(); + int len; + + if ( ! record_type()->buffer_input() || + (len_expr && len_expr->ConstFold(env, &len)) ) + AttemptBoundaryCheck(out_cc, env); } out_cc->println("// Parse \"%s\"", id_->Name()); From 9de6212ddaafe9c9509a0e26429c6d83ffad5d38 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 15 Apr 2020 16:23:11 -0700 Subject: [PATCH 097/343] binpac: Remove use of Variable-Length-Arrays Related to https://github.com/zeek/zeek/issues/895 --- tools/binpac/src/pac_regex.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/binpac/src/pac_regex.cc b/tools/binpac/src/pac_regex.cc index 6265c02876..1d01556bd6 100644 --- a/tools/binpac/src/pac_regex.cc +++ b/tools/binpac/src/pac_regex.cc @@ -10,7 +10,7 @@ const char *RegEx::kMatchPrefix = "MatchPrefix"; string escape_char(const string &s) { - char buf[s.length() * 2 + 1]; + char* buf = new char[s.length() * 2 + 1]; int j = 0; for ( int i = 0; i < (int) s.length(); ++i ) { @@ -40,7 +40,9 @@ string escape_char(const string &s) buf[j++] = '\0'; - return string(buf); + string rval = buf; + delete [] buf; + return rval; } RegEx::RegEx(const string &s) From a7f14ed423bdce6eb2ebd21ea9b7b3dfacde1a56 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 15 Jun 2020 18:34:42 -0700 Subject: [PATCH 098/343] binpac: Allow namespaced names as typenames for function return values --- tools/binpac/src/pac_scan.ll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index 8ffd90fd1a..7eab510cee 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -222,6 +222,11 @@ ESCSEQ (\\([^\n]|[0-7]{3}|x[[:xdigit:]]{2})) return TOK_ID; } +{ID}::{ID} { + yylval.id = new ID(yytext); + return TOK_ID; + } + "$"{ID} { yylval.id = new ID(yytext); return TOK_ID; From cd7a2e97836e48b854e42e553dcf21ee3c1fdde0 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 2 Jul 2020 10:25:32 -0700 Subject: [PATCH 099/343] binpac: Squash two rules into one with a wildcard --- tools/binpac/src/pac_scan.ll | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index 7eab510cee..7917fa98a1 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -217,12 +217,7 @@ ESCSEQ (\\([^\n]|[0-7]{3}|x[[:xdigit:]]{2})) return TOK_NUMBER; } -{ID} { - yylval.id = new ID(yytext); - return TOK_ID; - } - -{ID}::{ID} { +{ID}(::{ID})* { yylval.id = new ID(yytext); return TOK_ID; } From f1d7d0c80dd1068145b1af673ce50104b4568145 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 17 Jul 2020 15:18:46 -0700 Subject: [PATCH 100/343] binpac: Move RE_Matcher to zeek namespace --- tools/binpac/lib/binpac_regex.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index 53981e8661..f0f36cada5 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -4,7 +4,7 @@ #include "binpac.h" #include "RE.h" -class RE_Matcher; +ZEEK_FORWARD_DECLARE_NAMESPACED(RE_Matcher, zeek); namespace binpac { @@ -17,7 +17,7 @@ namespace binpac inline void init(FlowBuffer::Policy* fbp = 0); // Internal vector recording not yet compiled matchers. -extern std::vector* uncompiled_re_matchers; +extern std::vector* uncompiled_re_matchers; class RegExMatcher { public: @@ -25,9 +25,9 @@ public: : pattern_(pattern) { if ( ! uncompiled_re_matchers ) - uncompiled_re_matchers = new std::vector; + uncompiled_re_matchers = new std::vector; - re_matcher_ = new RE_Matcher(pattern_.c_str()); + re_matcher_ = new zeek::RE_Matcher(pattern_.c_str()); uncompiled_re_matchers->push_back(re_matcher_); } @@ -49,7 +49,7 @@ private: static void init(); string pattern_; - RE_Matcher *re_matcher_; + zeek::RE_Matcher *re_matcher_; }; inline void RegExMatcher::init() From 11b6feb18bbf3c226e31cbc915ad47542fc1d83b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 1 Dec 2020 21:50:54 -0800 Subject: [PATCH 101/343] binpac: Update minimum required CMake to 3.5 --- tools/binpac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 3d0c01e405..2c4ee58a09 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(BinPAC C CXX) include(cmake/CommonCMakeConfig.cmake) From c5fe0eaa17c8f76f792da1cb93ae810e562d768f Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 1 Dec 2020 17:04:45 -0800 Subject: [PATCH 102/343] binpac: GH-14: Use larger temporary storage for evaluating case-expressions For example: inum: uint32 = case (ed & 0x0f) of { 0x00 -> n_8; # n_8 is a uint8 0x01 -> n_16; # n_16 is a uint16 0x02 -> n_32; # n_32 is a uint32 default -> 0; }; Previously, the temporary storage used for evaluating the case-expression was based on whatever type the first case yields, which is a uint8 in the above example. That behavior can lead to a narrowing conversion whenever the 0x01 or 0x02 cases occur. The new behavior is to base the temporary storage's type on the largest numeric type that the case-expression can yield, which is uint32 in the above example. --- tools/binpac/src/pac_expr.cc | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index 4062525a57..066f279ecd 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -528,6 +528,8 @@ Type *Expr::DataType(Env *env) const { Type *type1 = cases_->front()->value()->DataType(env); + Type* numeric_with_largest_width = 0; + foreach(i, CaseExprList, cases_) { Type *type2 = @@ -541,8 +543,34 @@ Type *Expr::DataType(Env *env) const } if ( type1 == extern_type_nullptr ) type1 = type2; + + if ( type2 && type2->IsNumericType() ) + { + if ( numeric_with_largest_width ) + { + int largest; + int contender; + + // External C++ types like "int", "bool", "enum" use "int" + // storage internally. + if ( numeric_with_largest_width->tot() == Type::EXTERN ) + largest = sizeof(int); + else + largest = numeric_with_largest_width->StaticSize(env); + + if ( type2->tot() == Type::EXTERN ) + contender = sizeof(int); + else + contender = type2->StaticSize(env); + + if ( contender > largest ) + numeric_with_largest_width = type2; + } + else + numeric_with_largest_width = type2; + } } - data_type = type1; + data_type = numeric_with_largest_width ? numeric_with_largest_width : type1; } else data_type = 0; From b1101e6e162fc3890299e1b6d84e5f2cfff23d58 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 8 Feb 2021 15:38:39 -0800 Subject: [PATCH 103/343] binpac: Fix #include of RE.h to use zeek/RE.h --- tools/binpac/lib/binpac_regex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index f0f36cada5..404166c3c8 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -2,7 +2,7 @@ #define binpac_regex_h #include "binpac.h" -#include "RE.h" +#include "zeek/RE.h" ZEEK_FORWARD_DECLARE_NAMESPACED(RE_Matcher, zeek); From 5d75f8ed6cc160dcb86aa1c28da3864a545844e4 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 1 Feb 2021 18:03:59 -0700 Subject: [PATCH 104/343] binpac: Remove usage of ZEEK_FORWARD_DECLARE_NAMESPACED macro --- tools/binpac/lib/binpac_regex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index 404166c3c8..7c742966a7 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -4,7 +4,7 @@ #include "binpac.h" #include "zeek/RE.h" -ZEEK_FORWARD_DECLARE_NAMESPACED(RE_Matcher, zeek); +namespace zeek { class RE_Matcher; } namespace binpac { From f365c253a7dccd5bcbe06329e25e500b5b8856da Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 3 Mar 2021 09:36:47 -0700 Subject: [PATCH 105/343] binpac: Fix LGTM findings --- tools/binpac/src/pac_attr.cc | 8 ++++++++ tools/binpac/src/pac_attr.h | 3 +++ tools/binpac/src/pac_case.cc | 17 ++++++++--------- tools/binpac/src/pac_conn.cc | 1 + tools/binpac/src/pac_context.cc | 1 + tools/binpac/src/pac_cstr.cc | 14 +++++++------- tools/binpac/src/pac_dataptr.h | 1 + tools/binpac/src/pac_id.h | 2 +- tools/binpac/src/pac_let.cc | 3 --- tools/binpac/src/pac_primitive.cc | 3 --- 10 files changed, 30 insertions(+), 23 deletions(-) diff --git a/tools/binpac/src/pac_attr.cc b/tools/binpac/src/pac_attr.cc index cfd6263be6..56396c4303 100644 --- a/tools/binpac/src/pac_attr.cc +++ b/tools/binpac/src/pac_attr.cc @@ -17,6 +17,7 @@ void Attr::init() { expr_ = 0; seqend_ = 0; + delete_expr_ = false; } Attr::Attr(AttrType type) @@ -40,6 +41,7 @@ Attr::Attr(AttrType type, ExprList *exprlist) type_ = type; init(); expr_ = new Expr(exprlist); + delete_expr_ = true; } Attr::Attr(AttrType type, SeqEnd *seqend) @@ -50,6 +52,12 @@ Attr::Attr(AttrType type, SeqEnd *seqend) seqend_ = seqend; } +Attr::~Attr() + { + if ( delete_expr_ ) + delete expr_; + } + LetAttr::LetAttr(FieldList *letfields) : Attr(ATTR_LET) { diff --git a/tools/binpac/src/pac_attr.h b/tools/binpac/src/pac_attr.h index 85d7f19afb..87479df77c 100644 --- a/tools/binpac/src/pac_attr.h +++ b/tools/binpac/src/pac_attr.h @@ -32,6 +32,8 @@ public: Attr(AttrType type, ExprList *exprlist); Attr(AttrType type, SeqEnd *seqend); + virtual ~Attr(); + AttrType type() const { return type_; } Expr *expr() const { return expr_; } SeqEnd *seqend() const { return seqend_; } @@ -47,6 +49,7 @@ protected: AttrType type_; Expr *expr_; SeqEnd *seqend_; + bool delete_expr_; }; class LetAttr : public Attr diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index ffe22581a5..a2d326113c 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -436,22 +436,21 @@ void CaseField::GenParseCode(Output* out_cc, Env* env, { Env case_env(env, this); - Env *env = &case_env; - type_->GenPreParsing(out_cc, env); - type_->GenParseCode(out_cc, env, data, 0); + type_->GenPreParsing(out_cc, &case_env); + type_->GenParseCode(out_cc, &case_env, data, 0); if ( size_var ) { - out_cc->println("%s = %s;", - env->LValue(size_var), - type_->DataSize(out_cc, env, data).c_str()); + out_cc->println("%s = %s;", + case_env.LValue(size_var), + type_->DataSize(out_cc, &case_env, data).c_str()); } if ( type_->incremental_input() ) { ASSERT(case_type()->parsing_complete_var()); - out_cc->println("%s = %s;", - env->LValue(case_type()->parsing_complete_var()), - env->RValue(type_->parsing_complete_var())); + out_cc->println("%s = %s;", + case_env.LValue(case_type()->parsing_complete_var()), + case_env.RValue(type_->parsing_complete_var())); } out_cc->println("}"); } diff --git a/tools/binpac/src/pac_conn.cc b/tools/binpac/src/pac_conn.cc index 5e2542e483..e30608f5c1 100644 --- a/tools/binpac/src/pac_conn.cc +++ b/tools/binpac/src/pac_conn.cc @@ -24,6 +24,7 @@ ConnDecl::~ConnDecl() { delete flows_[0]; delete flows_[1]; + delete data_type_; } void ConnDecl::AddBaseClass(vector *base_classes) const diff --git a/tools/binpac/src/pac_context.cc b/tools/binpac/src/pac_context.cc index abf3c73a3c..8f9271beb2 100644 --- a/tools/binpac/src/pac_context.cc +++ b/tools/binpac/src/pac_context.cc @@ -66,6 +66,7 @@ AnalyzerContextDecl::AnalyzerContextDecl( AnalyzerContextDecl::~AnalyzerContextDecl() { delete context_name_id_; + delete param_type_; delete_list(ContextFieldList, context_fields_); } diff --git a/tools/binpac/src/pac_cstr.cc b/tools/binpac/src/pac_cstr.cc index 4ff3d1e6be..6e0eb027e0 100644 --- a/tools/binpac/src/pac_cstr.cc +++ b/tools/binpac/src/pac_cstr.cc @@ -87,7 +87,7 @@ ConstString::ConstString(const string &s) int len = strlen(text) + 1; int i = 0; - char* s = new char[len]; + char* new_s = new char[len]; // Skip leading quote. for ( ++text; *text; ++text ) @@ -95,22 +95,22 @@ ConstString::ConstString(const string &s) if ( *text == '\\' ) { ++text; // skip '\' - s[i++] = expand_escape(text); + new_s[i++] = expand_escape(text); --text; // point to end of sequence } else { - s[i++] = *text; + new_s[i++] = *text; } } ASSERT(i < len); // Get rid of trailing quote. - ASSERT(s[i-1] == '"'); - s[i-1] = '\0'; + ASSERT(new_s[i-1] == '"'); + new_s[i-1] = '\0'; - unescaped_ = s; - delete [] s; + unescaped_ = new_s; + delete [] new_s; } catch(EscapeException const &e) { diff --git a/tools/binpac/src/pac_dataptr.h b/tools/binpac/src/pac_dataptr.h index 602843ff56..981707c9e9 100644 --- a/tools/binpac/src/pac_dataptr.h +++ b/tools/binpac/src/pac_dataptr.h @@ -11,6 +11,7 @@ class DataPtr { public: DataPtr(Env* env, const ID* arg_id, const int arg_off); + DataPtr(DataPtr const& x) { *this = x; } DataPtr const &operator=(DataPtr const &x) { diff --git a/tools/binpac/src/pac_id.h b/tools/binpac/src/pac_id.h index 06ffeb9f63..fc70f9531d 100644 --- a/tools/binpac/src/pac_id.h +++ b/tools/binpac/src/pac_id.h @@ -50,7 +50,7 @@ public: } ~ID() { - delete locname; + delete [] locname; } bool operator==(ID const &x) const { return name == x.Name(); } diff --git a/tools/binpac/src/pac_let.cc b/tools/binpac/src/pac_let.cc index 06dd0416ce..0801f18a3b 100644 --- a/tools/binpac/src/pac_let.cc +++ b/tools/binpac/src/pac_let.cc @@ -8,9 +8,6 @@ namespace { void GenLetEval(const ID *id, Expr *expr, string prefix, Output* out, Env* env) { - if ( expr ) - { - } } } // private namespace diff --git a/tools/binpac/src/pac_primitive.cc b/tools/binpac/src/pac_primitive.cc index c4893a63ed..5e6d01ac61 100644 --- a/tools/binpac/src/pac_primitive.cc +++ b/tools/binpac/src/pac_primitive.cc @@ -19,9 +19,6 @@ string PPSet::ToCode(Env *env) string PPType::ToCode(Env *env) { Type *type = expr_->DataType(env); - if ( ! type ) - { - } return type->DataTypeStr(); } From 508e78ebe98540c0f0ff1b87bfa6d605efb43ddf Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 12 Mar 2021 12:08:10 -0800 Subject: [PATCH 106/343] binpac: Prevent use of LeakSanitizer on FreeBSD --- tools/binpac/src/pac_main.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index 951929fa4e..148ee3ee0b 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -220,18 +220,20 @@ void usage() #endif #endif -#if defined(USING_ASAN) +// FreeBSD doesn't support LeakSanitizer +#if defined(USING_ASAN) && !defined(__FreeBSD__) #include + #define BINPAC_LSAN_DISABLE(x) __lsan_disable(x) +#else + #define BINPAC_LSAN_DISABLE(x) #endif int main(int argc, char* argv[]) { - #if defined(USING_ASAN) // We generally do not care at all if binpac is leaking and other // projects that use it, like Zeek, only have their build tripped up // by the default behavior of LSAN to treat leaks as errors. - __lsan_disable(); - #endif + BINPAC_LSAN_DISABLE(); #ifdef HAVE_MALLOC_OPTIONS extern char *malloc_options; From 024b4ff8f373ef4d131294bc8deb57bc375a7b0a Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 28 Jun 2021 13:03:36 +0000 Subject: [PATCH 107/343] binpac: Updates for building Zeek as a submodule --- tools/binpac/CMakeLists.txt | 6 +++--- tools/binpac/src/CMakeLists.txt | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 2c4ee58a09..0960a0a410 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -40,10 +40,10 @@ endif () ######################################################################## ## System Introspection -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in - ${CMAKE_CURRENT_BINARY_DIR}/config.h) +configure_file(${PROJECT_SOURCE_DIR}/config.h.in + ${PROJECT_BINARY_DIR}/config.h) -include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) +include_directories(BEFORE ${PROJECT_BINARY_DIR}) ######################################################################## ## Recurse on sub-directories diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index dcadb8b797..b04144cd64 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -1,13 +1,13 @@ -bison_target(PACParser pac_parse.yy ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.cc - HEADER ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.h - VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.output +bison_target(PACParser pac_parse.yy ${BinPAC_BINARY_DIR}/src/pac_parse.cc + HEADER ${BinPAC_BINARY_DIR}/src/pac_parse.h + VERBOSE ${BinPAC_BINARY_DIR}/src/pac_parse.output COMPILE_FLAGS "--debug") -flex_target(PACScanner pac_scan.ll ${CMAKE_CURRENT_BINARY_DIR}/pac_scan.cc) +flex_target(PACScanner pac_scan.ll ${BinPAC_BINARY_DIR}/pac_scan.cc) add_flex_bison_dependency(PACScanner PACParser) set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${PROJECT_SOURCE_DIR}/src + ${PROJECT_BINARY_DIR}/src) set(binpac_SRCS ${BISON_PACParser_INPUT} @@ -104,5 +104,5 @@ install(TARGETS binpac DESTINATION bin) # This is set to assist superprojects that want to build BinPac # from source and rely on it as a target -set(BinPAC_EXE ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/binpac +set(BinPAC_EXE ${BinPAC_BINARY_DIR}/${CMAKE_CFG_INTDIR}/binpac CACHE STRING "BinPAC executable" FORCE) From c01015234068a815315fd3768438c1c968ae90d8 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 28 Jun 2021 13:23:09 +0000 Subject: [PATCH 108/343] binpac: CMAKE_CFG_INTDIR is no longer necessary. CMake documentation says that CMAKE_CFG_INTDIR is no longer necessary to find the right binary for the configuration and is in fact deprecated in recent versions of CMake. --- tools/binpac/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index b04144cd64..54ceb335c8 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -104,5 +104,5 @@ install(TARGETS binpac DESTINATION bin) # This is set to assist superprojects that want to build BinPac # from source and rely on it as a target -set(BinPAC_EXE ${BinPAC_BINARY_DIR}/${CMAKE_CFG_INTDIR}/binpac +set(BinPAC_EXE binpac CACHE STRING "BinPAC executable" FORCE) From 6034744a0c071a12f439fea23131faee3450396e Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 29 Jun 2022 12:51:06 -0700 Subject: [PATCH 109/343] binpac: Rename files in patches to match current directory structure --- tools/binpac/patches/binpac-1.patch | 10 +-- tools/binpac/patches/binpac-2.patch | 32 ++++----- tools/binpac/patches/binpac-3.patch | 26 ++++---- tools/binpac/patches/binpac-4.patch | 12 ++-- tools/binpac/patches/binpac-5.patch | 22 +++---- tools/binpac/patches/binpac-6.patch | 21 +++--- tools/binpac/patches/binpac-7.patch | 10 +-- tools/binpac/patches/binpac-8.patch | 76 +++++++++++----------- tools/binpac/patches/nadi-bittorrent.patch | 57 ++++++++-------- 9 files changed, 132 insertions(+), 134 deletions(-) diff --git a/tools/binpac/patches/binpac-1.patch b/tools/binpac/patches/binpac-1.patch index ade4e41065..20ad9e3e3c 100644 --- a/tools/binpac/patches/binpac-1.patch +++ b/tools/binpac/patches/binpac-1.patch @@ -1,10 +1,10 @@ -diff -urN bro-1.2.1-orig/src/binpac/pac_expr.cc bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc ---- bro-1.2.1-orig/src/binpac/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700 -@@ -776,6 +776,27 @@ +diff -urN bro-1.2.1-orig/src/pac_expr.cc bro-1.2.1-ssl-binpac/src/pac_expr.cc +--- bro-1.2.1-orig/src/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700 +@@ -776,2 +776,2 @@ } break; - + + case EXPR_CALLARGS: + { + mhs = 0; diff --git a/tools/binpac/patches/binpac-2.patch b/tools/binpac/patches/binpac-2.patch index 378c33027a..fe946740c2 100644 --- a/tools/binpac/patches/binpac-2.patch +++ b/tools/binpac/patches/binpac-2.patch @@ -1,9 +1,9 @@ -diff -urN bro-1.2.1-orig/src/binpac/pac_expr.cc bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc ---- bro-1.2.1-orig/src/binpac/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700 +diff -urN bro-1.2.1-orig/src/pac_expr.cc bro-1.2.1-ssl-binpac/src/pac_expr.cc +--- bro-1.2.1-orig/src/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700 @@ -245,6 +245,12 @@ - out_cc->println("%s %s;", - val_type->DataTypeStr().c_str(), + out_cc->println("%s %s;", + val_type->DataTypeStr().c_str(), env->LValue(val_var)); + + // force evaluation of IDs appearing in case stmt @@ -12,12 +12,12 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_expr.cc bro-1.2.1-ssl-binpac/src/binpac/ + (*i)->value()->ForceIDEval(out_cc, env); + out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); - + out_cc->inc_indent(); @@ -386,6 +392,49 @@ } } - + +void Expr::ForceIDEval(Output* out_cc, Env* env) + { + switch ( expr_type_ ) @@ -64,24 +64,24 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_expr.cc bro-1.2.1-ssl-binpac/src/binpac/ const char* Expr::EvalExpr(Output* out_cc, Env* env) { GenEval(out_cc, env); -diff -urN bro-1.2.1-orig/src/binpac/pac_expr.h bro-1.2.1-ssl-binpac/src/binpac/pac_expr.h ---- bro-1.2.1-orig/src/binpac/pac_expr.h 2006-07-26 15:02:39.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_expr.h 2007-05-04 14:16:31.624287000 -0700 +diff -urN bro-1.2.1-orig/src/pac_expr.h bro-1.2.1-ssl-binpac/src/pac_expr.h +--- bro-1.2.1-orig/src/pac_expr.h 2006-07-26 15:02:39.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_expr.h 2007-05-04 14:16:31.624287000 -0700 @@ -56,6 +56,11 @@ // const char *EvalExpr(Output *out, Env *env); - + + // force evaulation of IDs contained in this expression; + // necessary with case expr and conditional let fields (&if) + // for correct parsing of fields + void ForceIDEval(Output *out_cc, Env *env); + - // Returns the set_* function of the expression. + // Returns the set_* function of the expression. // The expression must be of form ID or x.ID. string SetFunc(Output *out, Env *env); -diff -urN bro-1.2.1-orig/src/binpac/pac_let.cc bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc ---- bro-1.2.1-orig/src/binpac/pac_let.cc 2006-07-26 15:02:39.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc 2007-05-04 15:32:09.695568000 -0700 +diff -urN bro-1.2.1-orig/src/pac_let.cc bro-1.2.1-ssl-binpac/src/pac_let.cc +--- bro-1.2.1-orig/src/pac_let.cc 2006-07-26 15:02:39.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_let.cc 2007-05-04 15:32:09.695568000 -0700 @@ -80,7 +80,12 @@ if ( type_->attr_if_expr() ) { @@ -92,6 +92,6 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_let.cc bro-1.2.1-ssl-binpac/src/binpac/p + // force evaluation of IDs contained in this expr + expr()->ForceIDEval(out_cc, env); + - out_cc->println("if ( %s )", + out_cc->println("if ( %s )", env->RValue(type_->has_value_var())); out_cc->inc_indent(); diff --git a/tools/binpac/patches/binpac-3.patch b/tools/binpac/patches/binpac-3.patch index 9832a245b6..5b520d5e09 100644 --- a/tools/binpac/patches/binpac-3.patch +++ b/tools/binpac/patches/binpac-3.patch @@ -1,37 +1,37 @@ -diff -urN bro-1.2.1-orig/src/binpac/pac_let.cc bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc ---- bro-1.2.1-orig/src/binpac/pac_let.cc 2006-07-26 15:02:39.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc 2007-05-04 15:32:09.695568000 -0700 +diff -urN bro-1.2.1-orig/src/pac_let.cc bro-1.2.1-ssl-binpac/src/pac_let.cc +--- bro-1.2.1-orig/src/pac_let.cc 2006-07-26 15:02:39.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_let.cc 2007-05-04 15:32:09.695568000 -0700 @@ -108,11 +108,6 @@ void LetField::GenEval(Output* out_cc, Env* env) { GenParseCode(out_cc, env); - if ( type_->attr_if_expr() ) - { -- out_cc->println("BINPAC_ASSERT(%s);", +- out_cc->println("BINPAC_ASSERT(%s);", - env->RValue(type_->has_value_var())); - } } - + LetDecl::LetDecl(ID *id, Type *type, Expr *expr) -diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc ---- bro-1.2.1-orig/src/binpac/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 +diff -urN bro-1.2.1-orig/src/pac_type.cc bro-1.2.1-ssl-binpac/src/pac_type.cc +--- bro-1.2.1-orig/src/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 @@ -316,9 +316,15 @@ { if ( DefineValueVar() ) { -- out_h->println("%s %s const { return %s; }", -- DataTypeConstRefStr().c_str(), +- out_h->println("%s %s const { return %s; }", +- DataTypeConstRefStr().c_str(), - env->RValue(value_var()), lvalue()); + if ( attr_if_expr_ ) + out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }", -+ DataTypeConstRefStr().c_str(), ++ DataTypeConstRefStr().c_str(), + env->RValue(value_var()), + env->RValue(has_value_var()), lvalue()); + else + out_h->println("%s %s const { return %s; }", -+ DataTypeConstRefStr().c_str(), ++ DataTypeConstRefStr().c_str(), + env->RValue(value_var()), lvalue()); } - + foreach (i, FieldList, fields_) diff --git a/tools/binpac/patches/binpac-4.patch b/tools/binpac/patches/binpac-4.patch index 560fb4051b..feb644fba3 100644 --- a/tools/binpac/patches/binpac-4.patch +++ b/tools/binpac/patches/binpac-4.patch @@ -1,12 +1,12 @@ -diff -urN bro-1.2.1-orig/src/binpac/pac_record.cc bro-1.2.1-ssl-binpac/src/binpac/pac_record.cc ---- bro-1.2.1-orig/src/binpac/pac_record.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_record.cc 2007-05-08 16:13:33.373850000 -0700 -@@ -123,7 +123,7 @@ - void RecordType::DoGenParseCode(Output* out_cc, Env* env, +diff -urN bro-1.2.1-orig/src/pac_record.cc bro-1.2.1-ssl-binpac/src/pac_record.cc +--- bro-1.2.1-orig/src/pac_record.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_record.cc 2007-05-08 16:13:33.373850000 -0700 +@@ -123,5 +123,5 @@ + void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { - if ( StaticSize(env) >= 0 ) + if ( !incremental_input() && StaticSize(env) >= 0 ) GenBoundaryCheck(out_cc, env, data); - + if ( incremental_parsing() ) diff --git a/tools/binpac/patches/binpac-5.patch b/tools/binpac/patches/binpac-5.patch index ae31fa1711..180c9fedf1 100644 --- a/tools/binpac/patches/binpac-5.patch +++ b/tools/binpac/patches/binpac-5.patch @@ -1,10 +1,10 @@ -diff -urN bro-1.2.1-orig/src/binpac/pac_paramtype.cc bro-1.2.1-ssl-binpac/src/binpac/pac_paramtype.cc ---- bro-1.2.1-orig/src/binpac/pac_paramtype.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_paramtype.cc 2007-05-10 15:09:47.470104000 -0700 +diff -urN bro-1.2.1-orig/src/pac_paramtype.cc bro-1.2.1-ssl-binpac/src/pac_paramtype.cc +--- bro-1.2.1-orig/src/pac_paramtype.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_paramtype.cc 2007-05-10 15:09:47.470104000 -0700 @@ -208,7 +208,13 @@ const char *parse_func; string parse_params; - + - if ( ref_type->incremental_input() ) + if ( buffer_mode() == BUFFER_NOTHING ) + { @@ -17,7 +17,7 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_paramtype.cc bro-1.2.1-ssl-binpac/src/bi parse_func = kParseFuncWithBuffer; parse_params = env->RValue(flow_buffer_id); @@ -239,15 +245,24 @@ - + if ( incremental_input() ) { - ASSERT(parsing_complete_var()); @@ -32,7 +32,7 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_paramtype.cc bro-1.2.1-ssl-binpac/src/bi + if ( buffer_mode() == BUFFER_NOTHING ) + { + out_cc->println("%s;", call_parse_func.c_str()); -+ out_cc->println("%s = true;", ++ out_cc->println("%s = true;", + env->LValue(parsing_complete_var())); + } + else @@ -50,14 +50,14 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_paramtype.cc bro-1.2.1-ssl-binpac/src/bi } else { -diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc ---- bro-1.2.1-orig/src/binpac/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 +diff -urN bro-1.2.1-orig/src/pac_type.cc bro-1.2.1-ssl-binpac/src/pac_type.cc +--- bro-1.2.1-orig/src/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 @@ -501,8 +501,8 @@ - + if ( buffer_mode() == BUFFER_NOTHING ) { -- out_cc->println("%s = true;", +- out_cc->println("%s = true;", - env->LValue(parsing_complete_var())); + // this is the empty type + DoGenParseCode(out_cc, env, data, flags); diff --git a/tools/binpac/patches/binpac-6.patch b/tools/binpac/patches/binpac-6.patch index fec16c1084..9b13a1cef5 100644 --- a/tools/binpac/patches/binpac-6.patch +++ b/tools/binpac/patches/binpac-6.patch @@ -1,10 +1,10 @@ -diff -urN bro-1.2.1-orig/src/binpac/lib/binpac_buffer.h bro-1.2.1-ssl-binpac/src/binpac/lib/binpac_buffer.h ---- bro-1.2.1-orig/src/binpac/lib/binpac_buffer.h 2006-07-26 15:02:38.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/lib/binpac_buffer.h 2007-05-09 16:14:54.501656000 -0700 +diff -urN bro-1.2.1-orig/src/lib/binpac_buffer.h bro-1.2.1-ssl-binpac/src/lib/binpac_buffer.h +--- bro-1.2.1-orig/src/lib/binpac_buffer.h 2006-07-26 15:02:38.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/lib/binpac_buffer.h 2007-05-09 16:14:54.501656000 -0700 @@ -59,6 +59,11 @@ return frame_length_; } - + + inline bool data_available() const + { + return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; @@ -13,16 +13,15 @@ diff -urN bro-1.2.1-orig/src/binpac/lib/binpac_buffer.h bro-1.2.1-ssl-binpac/src void NewLine(); // A negative frame_length represents a frame till EOF void NewFrame(int frame_length, bool chunked_); -diff -urN bro-1.2.1-orig/src/binpac/pac_flow.cc bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc ---- bro-1.2.1-orig/src/binpac/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700 +diff -urN bro-1.2.1-orig/src/pac_flow.cc bro-1.2.1-ssl-binpac/src/pac_flow.cc +--- bro-1.2.1-orig/src/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700 @@ -272,7 +272,8 @@ - env_->RValue(begin_of_data), - env_->RValue(end_of_data)); - + env_->RValue(begin_of_data), + env_->RValue(end_of_data)); + - out_cc->println("while ( true )"); + out_cc->println("while ( %s->data_available() )", + env_->LValue(flow_buffer_id)); out_cc->inc_indent(); out_cc->println("{"); - diff --git a/tools/binpac/patches/binpac-7.patch b/tools/binpac/patches/binpac-7.patch index 263f00bf2c..96b79f2e10 100644 --- a/tools/binpac/patches/binpac-7.patch +++ b/tools/binpac/patches/binpac-7.patch @@ -1,9 +1,9 @@ -diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc ---- bro-1.2.1-orig/src/binpac/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 +diff -urN bro-1.2.1-orig/src/pac_type.cc bro-1.2.1-ssl-binpac/src/pac_type.cc +--- bro-1.2.1-orig/src/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 @@ -393,7 +393,7 @@ break; - + case BUFFER_BY_LENGTH: - if ( buffering_state_var_field_ ) + if ( env->GetDataType(buffering_state_id) ) @@ -13,7 +13,7 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/ @@ -421,7 +421,7 @@ frame_buffer_arg.c_str(), attr_chunked() ? "true" : "false"); - + - if ( buffering_state_var_field_ ) + if ( env->GetDataType(buffering_state_id) ) { diff --git a/tools/binpac/patches/binpac-8.patch b/tools/binpac/patches/binpac-8.patch index b69a1676dd..f452027725 100644 --- a/tools/binpac/patches/binpac-8.patch +++ b/tools/binpac/patches/binpac-8.patch @@ -1,18 +1,18 @@ -diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.cc ---- bro-1.2.1-orig/src/binpac/pac_analyzer.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.cc 2007-05-22 17:00:10.091531000 -0700 +diff -urN bro-1.2.1-orig/src/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/pac_analyzer.cc +--- bro-1.2.1-orig/src/pac_analyzer.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_analyzer.cc 2007-05-22 17:00:10.091531000 -0700 @@ -26,8 +26,9 @@ helpers_ = new AnalyzerHelperList(); functions_ = new FunctionList(); - + - constructor_helper_ = 0; - destructor_helper_ = 0; + constructor_helpers_ = new AnalyzerHelperList(); + destructor_helpers_ = new AnalyzerHelperList(); + eof_helpers_ = new AnalyzerHelperList(); - + SetAnalyzerContext(); - + @@ -41,6 +42,9 @@ delete_list(AnalyzerHelperList, helpers_); delete_list(FunctionList, functions_); @@ -21,13 +21,13 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/bin + delete_list(AnalyzerHelperList, destructor_helpers_); + delete_list(AnalyzerHelperList, eof_helpers_); } - + void AnalyzerDecl::AddElements(AnalyzerElementList *elemlist) @@ -75,28 +79,20 @@ - AnalyzerHelper *helper_elem = + AnalyzerHelper *helper_elem = (AnalyzerHelper *) elem; - -- if ( helper_elem->helper_type() == + +- if ( helper_elem->helper_type() == - AnalyzerHelper::INIT_CODE) - { - if ( constructor_helper_ ) @@ -50,7 +50,7 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/bin + default: + helpers_->push_back(helper_elem); } -- else if ( helper_elem->helper_type() == +- else if ( helper_elem->helper_type() == - AnalyzerHelper::CLEANUP_CODE) - { - if ( destructor_helper_ ) @@ -76,7 +76,7 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/bin + (*i)->GenCode(0, out_cc, this); + } } - + void AnalyzerDecl::GenCleanUpCode(Output *out_cc) { TypeDecl::GenCleanUpCode(out_cc); @@ -87,7 +87,7 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/bin + (*i)->GenCode(0, out_cc, this); + } } - + void AnalyzerDecl::GenStateVarDecls(Output *out_h) @@ -295,6 +295,7 @@ break; @@ -97,20 +97,20 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/bin out = out_cc; break; } -diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.h bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.h ---- bro-1.2.1-orig/src/binpac/pac_analyzer.h 2006-07-26 15:02:39.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.h 2007-05-22 16:32:08.397926000 -0700 +diff -urN bro-1.2.1-orig/src/pac_analyzer.h bro-1.2.1-ssl-binpac/src/pac_analyzer.h +--- bro-1.2.1-orig/src/pac_analyzer.h 2006-07-26 15:02:39.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_analyzer.h 2007-05-22 16:32:08.397926000 -0700 @@ -76,8 +76,9 @@ AnalyzerHelperList *helpers_; FunctionList *functions_; - + - AnalyzerHelper *constructor_helper_; - AnalyzerHelper *destructor_helper_; + AnalyzerHelperList *constructor_helpers_; + AnalyzerHelperList *destructor_helpers_; + AnalyzerHelperList *eof_helpers_; }; - + class AnalyzerElement : public Object @@ -117,6 +118,7 @@ MEMBER_DECLS, @@ -120,9 +120,9 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.h bro-1.2.1-ssl-binpac/src/binp }; AnalyzerHelper(Type helper_type, EmbeddedCode *code) : AnalyzerElement(HELPER), -diff -urN bro-1.2.1-orig/src/binpac/pac_conn.cc bro-1.2.1-ssl-binpac/src/binpac/pac_conn.cc ---- bro-1.2.1-orig/src/binpac/pac_conn.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_conn.cc 2007-05-22 16:42:35.406135000 -0700 +diff -urN bro-1.2.1-orig/src/pac_conn.cc bro-1.2.1-ssl-binpac/src/pac_conn.cc +--- bro-1.2.1-orig/src/pac_conn.cc 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_conn.cc 2007-05-22 16:42:35.406135000 -0700 @@ -97,6 +97,12 @@ out_cc->println("%s->%s();", env_->LValue(downflow_id), @@ -134,15 +134,15 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_conn.cc bro-1.2.1-ssl-binpac/src/binpac/ + } + out_cc->dec_indent(); - + out_cc->println("}"); -diff -urN bro-1.2.1-orig/src/binpac/pac_flow.cc bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc ---- bro-1.2.1-orig/src/binpac/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700 +diff -urN bro-1.2.1-orig/src/pac_flow.cc bro-1.2.1-ssl-binpac/src/pac_flow.cc +--- bro-1.2.1-orig/src/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700 @@ -151,6 +151,11 @@ out_cc->inc_indent(); out_cc->println("{"); - + + foreach(i, AnalyzerHelperList, eof_helpers_) + { + (*i)->GenCode(0, out_cc, this); @@ -150,19 +150,19 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_flow.cc bro-1.2.1-ssl-binpac/src/binpac/ + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { - out_cc->println("%s->set_eof();", -diff -urN bro-1.2.1-orig/src/binpac/pac_parse.yy bro-1.2.1-ssl-binpac/src/binpac/pac_parse.yy ---- bro-1.2.1-orig/src/binpac/pac_parse.yy 2006-10-12 14:13:12.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_parse.yy 2007-05-22 16:56:09.280526000 -0700 + out_cc->println("%s->set_eof();", +diff -urN bro-1.2.1-orig/src/pac_parse.yy bro-1.2.1-ssl-binpac/src/pac_parse.yy +--- bro-1.2.1-orig/src/pac_parse.yy 2006-10-12 14:13:12.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_parse.yy 2007-05-22 16:56:09.280526000 -0700 @@ -22,7 +22,7 @@ - %token TOK_STATE TOK_ACTION TOK_WHEN TOK_HELPER + %token TOK_STATE TOK_ACTION TOK_WHEN TOK_HELPER %token TOK_DATAUNIT TOK_FLOWDIR TOK_WITHCONTEXT - %token TOK_LPB_EXTERN TOK_LPB_HEADER TOK_LPB_CODE --%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP + %token TOK_LPB_EXTERN TOK_LPB_HEADER TOK_LPB_CODE +-%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP +%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP TOK_LPB_EOF - %token TOK_LPB TOK_RPB + %token TOK_LPB TOK_RPB %token TOK_EMBEDDED_ATOM TOK_EMBEDDED_STRING - %token TOK_PAC_VAL TOK_PAC_SET TOK_PAC_TYPE TOK_PAC_TYPEOF TOK_PAC_CONST_DEF + %token TOK_PAC_VAL TOK_PAC_SET TOK_PAC_TYPE TOK_PAC_TYPEOF TOK_PAC_CONST_DEF @@ -795,6 +795,10 @@ { $$ = new AnalyzerHelper(AnalyzerHelper::CLEANUP_CODE, $2); @@ -174,9 +174,9 @@ diff -urN bro-1.2.1-orig/src/binpac/pac_parse.yy bro-1.2.1-ssl-binpac/src/binpac | TOK_FLOWDIR '=' tok_id optargs ';' { $$ = new AnalyzerFlow((AnalyzerFlow::Direction) $1, $3, $4); -diff -urN bro-1.2.1-orig/src/binpac/pac_scan.ll bro-1.2.1-ssl-binpac/src/binpac/pac_scan.ll ---- bro-1.2.1-orig/src/binpac/pac_scan.ll 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/binpac/pac_scan.ll 2007-05-22 16:55:19.349644000 -0700 +diff -urN bro-1.2.1-orig/src/pac_scan.ll bro-1.2.1-ssl-binpac/src/pac_scan.ll +--- bro-1.2.1-orig/src/pac_scan.ll 2006-07-26 15:02:40.000000000 -0700 ++++ bro-1.2.1-ssl-binpac/src/pac_scan.ll 2007-05-22 16:55:19.349644000 -0700 @@ -96,6 +96,10 @@ BEGIN(EC); return TOK_LPB_MEMBER; diff --git a/tools/binpac/patches/nadi-bittorrent.patch b/tools/binpac/patches/nadi-bittorrent.patch index 1ce6cc0313..de0b68311f 100644 --- a/tools/binpac/patches/nadi-bittorrent.patch +++ b/tools/binpac/patches/nadi-bittorrent.patch @@ -1,24 +1,24 @@ -Index: pac_type.h +Index: src/pac_type.h =================================================================== ---- pac_type.h (revision 4130) -+++ pac_type.h (working copy) +--- src/pac_type.h (revision 4130) ++++ src/pac_type.h (working copy) @@ -78,12 +78,6 @@ string EvalByteOrder(Output *out_cc, Env *env) const; - + virtual string EvalMember(const ID *member_id) const; -#if 0 - // member_env() is used for finding a member of the type. -- // Thus member_env() of a ParameterizedType should return +- // Thus member_env() of a ParameterizedType should return - // ReferredDataType()->env() - // virtual Env *member_env() const; -#endif - + // The variable defined by the type const ID *value_var() const { return value_var_; } @@ -223,6 +217,8 @@ - + virtual bool ByteOrderSensitive() const = 0; - + + bool NeedsBufferingStateVar() const; + void GenBufferingLoop(Output* out_cc, Env* env, int flags); @@ -30,19 +30,19 @@ Index: lib/binpac_buffer.h +++ lib/binpac_buffer.h (working copy) @@ -24,18 +24,18 @@ void DiscardData(); - + // Whether there is enough data for the frame - bool ready() const{ return message_complete_; } + bool ready() const{ return message_complete_ || mode_ == UNKNOWN_MODE; } - + inline const_byteptr begin() const { - BINPAC_ASSERT(message_complete_); + BINPAC_ASSERT(ready()); - return ( buffer_n_ == 0 ) ? + return ( buffer_n_ == 0 ) ? orig_data_begin_ : buffer_; } - + inline const_byteptr end() const { - BINPAC_ASSERT(message_complete_); @@ -50,25 +50,25 @@ Index: lib/binpac_buffer.h if ( buffer_n_ == 0 ) { BINPAC_ASSERT(frame_length_ >= 0); -Index: pac_type.cc +Index: src/pac_type.cc =================================================================== ---- pac_type.cc (revision 4130) -+++ pac_type.cc (working copy) +--- src/pac_type.cc (revision 4130) ++++ src/pac_type.cc (working copy) @@ -285,9 +285,8 @@ parsing_complete_var, extern_type_bool->Clone()); parsing_complete_var_field_->Prepare(env); - + - if ( ( buffer_mode() == BUFFER_BY_LENGTH || - buffer_mode() == BUFFER_BY_LINE ) && - ! env->GetDataType(buffering_state_id) ) -+ if ( NeedsBufferingStateVar() && ++ if ( NeedsBufferingStateVar() && + !env->GetDataType(buffering_state_id) ) { buffering_state_var_field_ = new PrivVarField( - buffering_state_id->clone(), + buffering_state_id->clone(), @@ -387,17 +386,17 @@ break; - + case BUFFER_BY_LENGTH: - if ( buffering_state_var_field_ ) - { @@ -79,7 +79,7 @@ Index: pac_type.cc - } + if ( !NeedsBufferingStateVar() ) + break; - + + ASSERT(env->GetDataType(buffering_state_id)); + out_cc->println("if ( %s == 0 )", + env->RValue(buffering_state_id)); @@ -99,12 +99,12 @@ Index: pac_type.cc - frame_buffer_arg = strfmt("%d", InitialBufferLength()); + ASSERT(0); } - + out_cc->println("%s->NewFrame(%s, %s);", @@ -415,16 +414,14 @@ frame_buffer_arg.c_str(), attr_chunked() ? "true" : "false"); - + - if ( buffering_state_var_field_ ) - { - out_cc->println("%s = 1;", @@ -117,16 +117,16 @@ Index: pac_type.cc + out_cc->println("}"); + out_cc->dec_indent(); break; - + case BUFFER_BY_LINE: + ASSERT(env->GetDataType(buffering_state_id)); out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); out_cc->inc_indent(); @@ -890,6 +887,25 @@ - return ! attr_byteorder_expr() && ByteOrderSensitive(); + return ! attr_byteorder_expr() && ByteOrderSensitive(); } - + +bool Type::NeedsBufferingStateVar() const + { + if ( !incremental_input() ) @@ -149,10 +149,10 @@ Index: pac_type.cc bool Type::DoTraverse(DataDepVisitor *visitor) { foreach (i, FieldList, fields_) -Index: pac_flow.cc +Index: src/pac_flow.cc =================================================================== ---- pac_flow.cc (revision 4130) -+++ pac_flow.cc (working copy) +--- src/pac_flow.cc (revision 4130) ++++ src/pac_flow.cc (working copy) @@ -224,15 +224,13 @@ out_cc->println("catch ( Exception const &e )"); out_cc->inc_indent(); @@ -169,4 +169,3 @@ Index: pac_flow.cc + out_cc->println("throw e;"); out_cc->println("}"); out_cc->dec_indent(); - From 090ac0a6e08afbcc0992ec7552c17e8bee467942 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 29 Jun 2022 12:48:50 -0700 Subject: [PATCH 110/343] binpac: Remove already-applied binpac-* patches --- tools/binpac/patches/binpac-1.patch | 31 --- tools/binpac/patches/binpac-2.patch | 97 --------- tools/binpac/patches/binpac-3.patch | 37 ---- tools/binpac/patches/binpac-4.patch | 12 -- tools/binpac/patches/binpac-6.patch | 27 --- tools/binpac/patches/binpac-8.patch | 190 ------------------ .../patches/brosslbinpacanalyzerpatches.zip | Bin 8025 -> 0 bytes 7 files changed, 394 deletions(-) delete mode 100644 tools/binpac/patches/binpac-1.patch delete mode 100644 tools/binpac/patches/binpac-2.patch delete mode 100644 tools/binpac/patches/binpac-3.patch delete mode 100644 tools/binpac/patches/binpac-4.patch delete mode 100644 tools/binpac/patches/binpac-6.patch delete mode 100644 tools/binpac/patches/binpac-8.patch delete mode 100644 tools/binpac/patches/brosslbinpacanalyzerpatches.zip diff --git a/tools/binpac/patches/binpac-1.patch b/tools/binpac/patches/binpac-1.patch deleted file mode 100644 index 20ad9e3e3c..0000000000 --- a/tools/binpac/patches/binpac-1.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff -urN bro-1.2.1-orig/src/pac_expr.cc bro-1.2.1-ssl-binpac/src/pac_expr.cc ---- bro-1.2.1-orig/src/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700 -@@ -776,2 +776,2 @@ - } - break; - -+ case EXPR_CALLARGS: -+ { -+ mhs = 0; -+ if ( args_ ) -+ for ( uint i = 0; i < args_->size(); ++i ) -+ mhs = mhs_max(mhs, args_->at(i)->MinimalHeaderSize(env)); -+ } -+ break; -+ case EXPR_CASE: -+ { -+ mhs = operand_[0]->MinimalHeaderSize(env); -+ for ( uint i = 0; i < cases_->size(); ++i ) -+ { -+ CaseExpr * ce = cases_->at(i); -+ if ( ce->index() ) -+ for ( uint j = 0; j < ce->index()->size(); ++j ) -+ mhs = mhs_max(mhs, ce->index()->at(j)->MinimalHeaderSize(env)); -+ mhs = mhs_max(mhs, ce->value()->MinimalHeaderSize(env)); -+ } -+ } -+ break; - default: - // Evaluate every operand by default - mhs = 0; diff --git a/tools/binpac/patches/binpac-2.patch b/tools/binpac/patches/binpac-2.patch deleted file mode 100644 index fe946740c2..0000000000 --- a/tools/binpac/patches/binpac-2.patch +++ /dev/null @@ -1,97 +0,0 @@ -diff -urN bro-1.2.1-orig/src/pac_expr.cc bro-1.2.1-ssl-binpac/src/pac_expr.cc ---- bro-1.2.1-orig/src/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700 -@@ -245,6 +245,12 @@ - out_cc->println("%s %s;", - val_type->DataTypeStr().c_str(), - env->LValue(val_var)); -+ -+ // force evaluation of IDs appearing in case stmt -+ operand_[0]->ForceIDEval(out_cc, env); -+ foreach(i, CaseExprList, cases_) -+ (*i)->value()->ForceIDEval(out_cc, env); -+ - out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); - - out_cc->inc_indent(); -@@ -386,6 +392,49 @@ - } - } - -+void Expr::ForceIDEval(Output* out_cc, Env* env) -+ { -+ switch ( expr_type_ ) -+ { -+ case EXPR_NUM: -+ case EXPR_SIZEOF: -+ case EXPR_OFFSETOF: -+ break; -+ -+ case EXPR_ID: -+ if ( ! env->Evaluated(id_) ) -+ env->Evaluate(out_cc, id_); -+ break; -+ -+ case EXPR_MEMBER: -+ operand_[0]->ForceIDEval(out_cc, env); -+ break; -+ -+ case EXPR_CALLARGS: -+ { -+ foreach(i, ExprList, args_) -+ (*i)->ForceIDEval(out_cc, env); -+ } -+ break; -+ -+ case EXPR_CASE: -+ { -+ operand_[0]->ForceIDEval(out_cc, env); -+ foreach(i, CaseExprList, cases_) -+ (*i)->value()->ForceIDEval(out_cc, env); -+ } -+ break; -+ -+ default: -+ // Evaluate every operand by default -+ for ( int i = 0; i < 3; ++i ) -+ if ( operand_[i] ) -+ operand_[i]->ForceIDEval(out_cc, env); -+ break; -+ } -+ } -+ -+ - const char* Expr::EvalExpr(Output* out_cc, Env* env) - { - GenEval(out_cc, env); -diff -urN bro-1.2.1-orig/src/pac_expr.h bro-1.2.1-ssl-binpac/src/pac_expr.h ---- bro-1.2.1-orig/src/pac_expr.h 2006-07-26 15:02:39.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_expr.h 2007-05-04 14:16:31.624287000 -0700 -@@ -56,6 +56,11 @@ - // - const char *EvalExpr(Output *out, Env *env); - -+ // force evaulation of IDs contained in this expression; -+ // necessary with case expr and conditional let fields (&if) -+ // for correct parsing of fields -+ void ForceIDEval(Output *out_cc, Env *env); -+ - // Returns the set_* function of the expression. - // The expression must be of form ID or x.ID. - string SetFunc(Output *out, Env *env); -diff -urN bro-1.2.1-orig/src/pac_let.cc bro-1.2.1-ssl-binpac/src/pac_let.cc ---- bro-1.2.1-orig/src/pac_let.cc 2006-07-26 15:02:39.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_let.cc 2007-05-04 15:32:09.695568000 -0700 -@@ -80,7 +80,12 @@ - if ( type_->attr_if_expr() ) - { - // A conditional field -+ - env->Evaluate(out_cc, type_->has_value_var()); -+ -+ // force evaluation of IDs contained in this expr -+ expr()->ForceIDEval(out_cc, env); -+ - out_cc->println("if ( %s )", - env->RValue(type_->has_value_var())); - out_cc->inc_indent(); diff --git a/tools/binpac/patches/binpac-3.patch b/tools/binpac/patches/binpac-3.patch deleted file mode 100644 index 5b520d5e09..0000000000 --- a/tools/binpac/patches/binpac-3.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff -urN bro-1.2.1-orig/src/pac_let.cc bro-1.2.1-ssl-binpac/src/pac_let.cc ---- bro-1.2.1-orig/src/pac_let.cc 2006-07-26 15:02:39.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_let.cc 2007-05-04 15:32:09.695568000 -0700 -@@ -108,11 +108,6 @@ - void LetField::GenEval(Output* out_cc, Env* env) - { - GenParseCode(out_cc, env); -- if ( type_->attr_if_expr() ) -- { -- out_cc->println("BINPAC_ASSERT(%s);", -- env->RValue(type_->has_value_var())); -- } - } - - LetDecl::LetDecl(ID *id, Type *type, Expr *expr) -diff -urN bro-1.2.1-orig/src/pac_type.cc bro-1.2.1-ssl-binpac/src/pac_type.cc ---- bro-1.2.1-orig/src/pac_type.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_type.cc 2007-05-24 10:56:42.140658000 -0700 -@@ -316,9 +316,15 @@ - { - if ( DefineValueVar() ) - { -- out_h->println("%s %s const { return %s; }", -- DataTypeConstRefStr().c_str(), -- env->RValue(value_var()), lvalue()); -+ if ( attr_if_expr_ ) -+ out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }", -+ DataTypeConstRefStr().c_str(), -+ env->RValue(value_var()), -+ env->RValue(has_value_var()), lvalue()); -+ else -+ out_h->println("%s %s const { return %s; }", -+ DataTypeConstRefStr().c_str(), -+ env->RValue(value_var()), lvalue()); - } - - foreach (i, FieldList, fields_) diff --git a/tools/binpac/patches/binpac-4.patch b/tools/binpac/patches/binpac-4.patch deleted file mode 100644 index feb644fba3..0000000000 --- a/tools/binpac/patches/binpac-4.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -urN bro-1.2.1-orig/src/pac_record.cc bro-1.2.1-ssl-binpac/src/pac_record.cc ---- bro-1.2.1-orig/src/pac_record.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_record.cc 2007-05-08 16:13:33.373850000 -0700 -@@ -123,5 +123,5 @@ - void RecordType::DoGenParseCode(Output* out_cc, Env* env, - const DataPtr& data, int flags) - { -- if ( StaticSize(env) >= 0 ) -+ if ( !incremental_input() && StaticSize(env) >= 0 ) - GenBoundaryCheck(out_cc, env, data); - - if ( incremental_parsing() ) diff --git a/tools/binpac/patches/binpac-6.patch b/tools/binpac/patches/binpac-6.patch deleted file mode 100644 index 9b13a1cef5..0000000000 --- a/tools/binpac/patches/binpac-6.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff -urN bro-1.2.1-orig/src/lib/binpac_buffer.h bro-1.2.1-ssl-binpac/src/lib/binpac_buffer.h ---- bro-1.2.1-orig/src/lib/binpac_buffer.h 2006-07-26 15:02:38.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/lib/binpac_buffer.h 2007-05-09 16:14:54.501656000 -0700 -@@ -59,6 +59,11 @@ - return frame_length_; - } - -+ inline bool data_available() const -+ { -+ return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; -+ } -+ - void NewLine(); - // A negative frame_length represents a frame till EOF - void NewFrame(int frame_length, bool chunked_); -diff -urN bro-1.2.1-orig/src/pac_flow.cc bro-1.2.1-ssl-binpac/src/pac_flow.cc ---- bro-1.2.1-orig/src/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700 -@@ -272,7 +272,8 @@ - env_->RValue(begin_of_data), - env_->RValue(end_of_data)); - -- out_cc->println("while ( true )"); -+ out_cc->println("while ( %s->data_available() )", -+ env_->LValue(flow_buffer_id)); - out_cc->inc_indent(); - out_cc->println("{"); diff --git a/tools/binpac/patches/binpac-8.patch b/tools/binpac/patches/binpac-8.patch deleted file mode 100644 index f452027725..0000000000 --- a/tools/binpac/patches/binpac-8.patch +++ /dev/null @@ -1,190 +0,0 @@ -diff -urN bro-1.2.1-orig/src/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/pac_analyzer.cc ---- bro-1.2.1-orig/src/pac_analyzer.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_analyzer.cc 2007-05-22 17:00:10.091531000 -0700 -@@ -26,8 +26,9 @@ - helpers_ = new AnalyzerHelperList(); - functions_ = new FunctionList(); - -- constructor_helper_ = 0; -- destructor_helper_ = 0; -+ constructor_helpers_ = new AnalyzerHelperList(); -+ destructor_helpers_ = new AnalyzerHelperList(); -+ eof_helpers_ = new AnalyzerHelperList(); - - SetAnalyzerContext(); - -@@ -41,6 +42,9 @@ - delete_list(AnalyzerHelperList, helpers_); - delete_list(FunctionList, functions_); - delete_list(ParamList, params_); -+ delete_list(AnalyzerHelperList, constructor_helpers_); -+ delete_list(AnalyzerHelperList, destructor_helpers_); -+ delete_list(AnalyzerHelperList, eof_helpers_); - } - - void AnalyzerDecl::AddElements(AnalyzerElementList *elemlist) -@@ -75,28 +79,20 @@ - AnalyzerHelper *helper_elem = - (AnalyzerHelper *) elem; - -- if ( helper_elem->helper_type() == -- AnalyzerHelper::INIT_CODE) -- { -- if ( constructor_helper_ ) -- { -- throw Exception(elem, -- "Repeated definition of %init code"); -- } -- constructor_helper_ = helper_elem; -+ switch ( helper_elem->helper_type() ) -+ { -+ case AnalyzerHelper::INIT_CODE: -+ constructor_helpers_->push_back(helper_elem); -+ break; -+ case AnalyzerHelper::CLEANUP_CODE: -+ destructor_helpers_->push_back(helper_elem); -+ break; -+ case AnalyzerHelper::EOF_CODE: -+ eof_helpers_->push_back(helper_elem); -+ break; -+ default: -+ helpers_->push_back(helper_elem); - } -- else if ( helper_elem->helper_type() == -- AnalyzerHelper::CLEANUP_CODE) -- { -- if ( destructor_helper_ ) -- { -- throw Exception(elem, -- "Repeated definition of %cleanup code"); -- } -- destructor_helper_ = helper_elem; -- } -- else -- helpers_->push_back(helper_elem); - } - break; - case AnalyzerElement::FUNCTION: -@@ -217,15 +213,19 @@ - void AnalyzerDecl::GenInitCode(Output *out_cc) - { - TypeDecl::GenInitCode(out_cc); -- if ( constructor_helper_ ) -- constructor_helper_->GenCode(0, out_cc, this); -+ foreach(i, AnalyzerHelperList, constructor_helpers_) -+ { -+ (*i)->GenCode(0, out_cc, this); -+ } - } - - void AnalyzerDecl::GenCleanUpCode(Output *out_cc) - { - TypeDecl::GenCleanUpCode(out_cc); -- if ( destructor_helper_ ) -- destructor_helper_->GenCode(0, out_cc, this); -+ foreach(i, AnalyzerHelperList, destructor_helpers_) -+ { -+ (*i)->GenCode(0, out_cc, this); -+ } - } - - void AnalyzerDecl::GenStateVarDecls(Output *out_h) -@@ -295,6 +295,7 @@ - break; - case INIT_CODE: - case CLEANUP_CODE: -+ case EOF_CODE: - out = out_cc; - break; - } -diff -urN bro-1.2.1-orig/src/pac_analyzer.h bro-1.2.1-ssl-binpac/src/pac_analyzer.h ---- bro-1.2.1-orig/src/pac_analyzer.h 2006-07-26 15:02:39.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_analyzer.h 2007-05-22 16:32:08.397926000 -0700 -@@ -76,8 +76,9 @@ - AnalyzerHelperList *helpers_; - FunctionList *functions_; - -- AnalyzerHelper *constructor_helper_; -- AnalyzerHelper *destructor_helper_; -+ AnalyzerHelperList *constructor_helpers_; -+ AnalyzerHelperList *destructor_helpers_; -+ AnalyzerHelperList *eof_helpers_; - }; - - class AnalyzerElement : public Object -@@ -117,6 +118,7 @@ - MEMBER_DECLS, - INIT_CODE, - CLEANUP_CODE, -+ EOF_CODE, - }; - AnalyzerHelper(Type helper_type, EmbeddedCode *code) - : AnalyzerElement(HELPER), -diff -urN bro-1.2.1-orig/src/pac_conn.cc bro-1.2.1-ssl-binpac/src/pac_conn.cc ---- bro-1.2.1-orig/src/pac_conn.cc 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_conn.cc 2007-05-22 16:42:35.406135000 -0700 -@@ -97,6 +97,12 @@ - out_cc->println("%s->%s();", - env_->LValue(downflow_id), - kFlowEOF); -+ -+ foreach(i, AnalyzerHelperList, eof_helpers_) -+ { -+ (*i)->GenCode(0, out_cc, this); -+ } -+ - out_cc->dec_indent(); - - out_cc->println("}"); -diff -urN bro-1.2.1-orig/src/pac_flow.cc bro-1.2.1-ssl-binpac/src/pac_flow.cc ---- bro-1.2.1-orig/src/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700 -@@ -151,6 +151,11 @@ - out_cc->inc_indent(); - out_cc->println("{"); - -+ foreach(i, AnalyzerHelperList, eof_helpers_) -+ { -+ (*i)->GenCode(0, out_cc, this); -+ } -+ - if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) - { - out_cc->println("%s->set_eof();", -diff -urN bro-1.2.1-orig/src/pac_parse.yy bro-1.2.1-ssl-binpac/src/pac_parse.yy ---- bro-1.2.1-orig/src/pac_parse.yy 2006-10-12 14:13:12.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_parse.yy 2007-05-22 16:56:09.280526000 -0700 -@@ -22,7 +22,7 @@ - %token TOK_STATE TOK_ACTION TOK_WHEN TOK_HELPER - %token TOK_DATAUNIT TOK_FLOWDIR TOK_WITHCONTEXT - %token TOK_LPB_EXTERN TOK_LPB_HEADER TOK_LPB_CODE --%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP -+%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP TOK_LPB_EOF - %token TOK_LPB TOK_RPB - %token TOK_EMBEDDED_ATOM TOK_EMBEDDED_STRING - %token TOK_PAC_VAL TOK_PAC_SET TOK_PAC_TYPE TOK_PAC_TYPEOF TOK_PAC_CONST_DEF -@@ -795,6 +795,10 @@ - { - $$ = new AnalyzerHelper(AnalyzerHelper::CLEANUP_CODE, $2); - } -+ | TOK_LPB_EOF embedded_code TOK_RPB -+ { -+ $$ = new AnalyzerHelper(AnalyzerHelper::EOF_CODE, $2); -+ } - | TOK_FLOWDIR '=' tok_id optargs ';' - { - $$ = new AnalyzerFlow((AnalyzerFlow::Direction) $1, $3, $4); -diff -urN bro-1.2.1-orig/src/pac_scan.ll bro-1.2.1-ssl-binpac/src/pac_scan.ll ---- bro-1.2.1-orig/src/pac_scan.ll 2006-07-26 15:02:40.000000000 -0700 -+++ bro-1.2.1-ssl-binpac/src/pac_scan.ll 2007-05-22 16:55:19.349644000 -0700 -@@ -96,6 +96,10 @@ - BEGIN(EC); - return TOK_LPB_MEMBER; - } -+"%eof{" { -+ BEGIN(EC); -+ return TOK_LPB_EOF; -+ } - "%{" { - BEGIN(EC); - return TOK_LPB; diff --git a/tools/binpac/patches/brosslbinpacanalyzerpatches.zip b/tools/binpac/patches/brosslbinpacanalyzerpatches.zip deleted file mode 100644 index 4d89326f71cc03cdd85616c3ee943d8d09072b0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8025 zcma)>WmHw&`u1sQHr+^rfJk>Ejj-uZK)M??-6^^0?rx;JJ7m)h(kUqo^6EK`^VjFY zJD$0|toh+L#u{^8>yGON%E7|nKq3Bo?7_`kP=74+pYI0dHg@`kuUVPx^qmaN5|nim zdsuM1PQ3fQR!CM`c$3j-0OH@FBmMBP4HIjeH3LQY$g?*(m%X~l0d>Pm$JgnO6YY%@ z(Ue_s=P=@|y@~q7c$r8-Y}lB|;$#!%A4eukkD6Khv;Adbk(i;1J|hp@+LjK{=KFmL z|AwIH9KDb!j;hQI<_@H9seGpMC_OMx9_)i2J+FK{QG+_)VQ-VsZqkaj;7nYPuz#T6 z3bA4I1uU6709o#5RYfK-kAwnJnic$utt zu>ENg{7ICdZ!@8A2h^aJC*dcxgVvHHn>L=3ZNJ|c7wvd(VO3-)AD6*=K~5)zfwhou z8OVs3yq(ln4iOMvTld|-ixzKCuipZxF-16{Y|Zp!0=I3G^(kd1G)h zm{Qzh+E*2=ZtyUXwcaMh1tke8O$XYPO5&p~gnfF)OH5#sEn?EOn)V0}lzV}=rRzPB z1`P#u0Sg5M{5RLi_TOu*P`8fWk^t|@@o$LGTa&2m?>cI(tOt*n8umonZ#5FvgmIYs;C9g^9=OW2W_(*s; zb!xM(^F{0GDY$SR>TVqz+z3V1jD_a9A*Ia?tE}HD4?tb!7*;Njn%Aw5P+t~6{VWkT zuK3A1(>7@!l=Qjm15}d1!u zkZ4}dv5=RCzHxTnwc-jU^weiaB9Z8#Z!N#Dw_Ct_Gq2IjLyWAWPP}PG{SOVEQjKO0 zs|{39D<*yE$6=6h=#YD~QbmZmozh{oD(FRJ6}zwyr4=alCfW?*ix0v~sF9w8kE?dg zC`AelF_fI@vs&yJ+syWTW69^VNQEdOLNHqmd8_0gD^d{iF33R(U zZ%%wJOhyK0TXoBM16iN=+LgvHech}tTP8aq$ zY0fe!7h+uHg!3_9C4QiRJ!+MwP2?HZm7S}0^@}tf1{C;R!J&G?d4yKI%;tsb{aC<} z@7j=NqBm-9ZF{^FQP$LnJb;ThMZE{;qb{>9wRm5u#vmOXL|C@fu%dfY-Cwse9Hcm?^g<)gFIoqj1H#cQ*1t8f$|;0F zl&Z+lB&$Q{+YF@Pz^U*XWJ;1E9CxfEEGH7(@1Y?e`)s$MyO8`ENU^7a^uZ^ZvD>AR*9oU0Wp~vXo)KE)xEDY1% zSORcmfHrawCtUh|+Lx{@$P@6vcA_+K93BIjP#2FT?*{Rf3}Nv&_Tm)*w^mkFxO51+ zON?N)cCqx4GauYNbO**S*VzZ?#~rf=jmsHpIXoVqb`%7m(dB3XH6v^esldxI(-@pK zW^F99nh^;G8w^#dAaZt(LPKkSVeG?&2yPNtd)w8Amh1Gn2F-lUr{$gPZ{OaY*g3Le zB7~jGuMU1W!{IE>XwH0u{S_6CD`BXYentcdlz$l&*#8?9>Q&Dz^H>O;w4TGFyG6=A zPpUU+)34UI8?u1%NFUVF2P{SEk~MAOpH6T3m-r7F_)ow3v$DFmbwuBA>}Vn6SDtJ% zGkiL7jglJ)^C1pnAQZYZz^4;GR{D}3M@pRnaUg`0jz@Mgi+tOs zApyA_h>5aRbA(}2tFPmfp%)IjF$T(ZP~51Y%$4G@r|H(o3l>UY9+uV0D0UsSLi2s%o)K!$ZP&!C4IwOXEh+fV~Amg3Vky3mw$Ymae9a zhl8aVo0-o145WM5&F#NNlnnPwi(q})GjifdGjktd>R4#FIXT$2H!RMb^iK&{n)W+_#Dy?sBiJRkTLvJ-| zl9c(xQw{k7jI<$jO@*w2q;|NnG6ccT?E59WQ?I6YscR{R!Kp+55LY83$JqV8?-_OfZ`XCg-N*L93PV2;DZ=O{t?29G)zFoJ#d86&4JDzpqsnVs{{nGE4RMqxxwY-@U+%1YYGpmhVZL_D0F8Jt?n&-A$p%8E|oLQ zCnkJp;R72=(CR8^e9n5N{lzQNyK2a0jYGETHC%TROc@>AFXIYmPT!h)pK27yh>b~d z?|mHt2^>cqEsATnycpl_0tJd^$`(HA_db&AF{v;&cN&N#Aya5#2qO+1V7+IUE}vf0 zp!kMAX#M`vYtj`B>=itI1cGXgEAG1+*q7!8ZS;2^p=?WfDN_cq3>r3Bwgg}kk-zkW z$OctGSmOi&9|(frlgJ%I3AiLFoRF^Nq2J6wto03aGO=2AE_B)oMXgIawh!+&A`cDp z^*t(pE^>1D^vzSVU_R@T@>i6Ww4KNoI__2&17~?Q)VK~(b3~AM%7ib>QS{O(vGf_v z8L2VwmT0@VM-__tnvSa+iyT);W6uk3o-6UvrO`87^FD>UGn2Z7ywM1kB7Fe3@2Zbi zw(KFtn8dcb&`Z~f`_;wRD?@o3kNLexynt3U(7u1wxtT(?w#UG+wWMxTO<@$f2q>`9 zb-H5Vez#s8c6H`06u}zO`AgquaUwPOKeg?G_%HR%^laUUpsFJg%8`?rC$OWp@jRm}|eq zN(IaiHD|aKrY0$$x^ZgMq!*Txq)H|mx%i#%1<`&z^6(6VJeRoQY@u$DOrlC_f7E8O z!SW>g$Vl*@gyWS@JeWb1PT2+%i)*BnKT6$CEmv!LGL8Uj31bgEP68}gd7cSOgnF|O z5%u~Y7Y43f^Mj5UIz7**6fJ1#eQT_7XWI56UN)(=sZt{5SUAtW2gq+tewhd~w3TPq zgbgmDvvcWFz!96bxpK?Fd0$dtv8_tQ=xt_j(2o*XoX79wg0} z!G@ZMl7artaZJc!!Z?YYJc<-KGeJhp^iv#K6&D|+_)P4a&CPjj*Nab-B3IlDXlFaI@So&k0Yq#Opf{MDPM)#9mxv$X zAE20imK&q@5|(YPRhaM}<`au6D@4@rf?IMy`^O2BqNu2$kz(z@j?0Q+St84vaM07#i98PemC;;s|2 zs~!73TDQfrQz^6{Xnb7U^-+&AwyqP472_p{T zwjvtv5rZOKGaePFocrTcqa(Gdjx$zA%?j<-%PrPQl#Ain6`$CeYu$F@f){gAlw&XU z*w(`rST^vSXykIl5#4)g#P&@{XZ!uKedKb{q0=XC5Y;;+&d`7TsAWXQI$A$3<@Dbs zBA(xgNYmOeR~qoc%DZ2cq2wbRK9FORroJ*Z(z&t_b+P^7Ehd2?GaOUb_^!j<={$QI z4>@g9TAr+5ifM~!OV+_jHwX`fx;)@j3yPK@O^$5|=3c&8`tF4f z-!afr6Z^?~A-Gr&n@2x##My#*Bc)?R0}U|0w6dy_`m%wF{2MsITvv!0$8`pL%rfp< z39vD>vzn4B4R|>&KCv$5;hYMl{gKe3%Ll{j(bd;N?zqwpK(tTdc8iII6{At-wi$@2 zaSCho`MP}QydBjwg~JF8n`0vCgHv8Hgb|_1EE?{$Ut{m4m}dkbjx)DH@oA)xxc2&MJz+8i ztAzyFtNioAO}1KfB29x8*)2`%X^A#~q4y0bKl>Hp`^r*utM`uQu-CaP*zp_ynSC4_ zK>(+-#d&4VXxD;GbW;DquH6ouuL8D0Ow89c0+p?>Vm?aW((b5n48@T5}QYPI+8TGxq zy87%rT(?FWuIPT`K7LWd>}J*H`t4b{da)rFf`k?ANb))}$12oYQL5e6ecr9x<)Rff&X>scmC9FPF?0r) zSc9}$fFRi8B7_yo%GF}}Gi&`&XF-sD&4YbQ{6e|0T(b_==z8Q*V)#4T_ND%lDUMjG zMj(gGl=5WqoAcN97z_^NpHxcS-S|llw-!|+<4R|CXyB(xXEqCX*yG_kCKiZ$l|!mI zY#O4}Ekm7u@UbzKp{HhU6a~aJd`1c`|8}*YJVo)rmzqIhTZt)DYH|wc6)wI|`LwnJ zx?U{0%QiqvnFy&#rRYbCtHrpExi2d9mku2@PDGS9OGfx~jmtj6l*Ys7q-YM<-I=!* zQ^72zvBv4BJDFmK7!F5;!*;!DvTC$|qIW@>DRnlR1TiqO9~t}EPw=-pNEROECP$x; z7j}fyzB{yr+FW_JhwAQH>_;uds-2fF9y)tC(CLZ0n4_(ZTkKmG=Htqk0bpzD$@o@h z-0f+U%avt8_MLDI<5oS@H6`)ZTRIC^{-^#mcj)RDV&SHvoW0cq%rRl=NBr}jA;%}S zRuVIzSbg%@HPji#sy}kQ?()YYW4O{+&hja?*t`tQ$FPZtP-)xWdg-T>ntEhyt?^f0g*K<`}CZu3UUYBN)VOzm}p&N1$YE+8KQ%hD{PoQWQl)VP_5l!bA? zdjEWF@c|<_ra2e}Ik~aKv(^(OqY;8+ykd0y4bLAnSKn8aWak*&-l(gNzF*0hsLM^T zZ@j2THdDGAHxw+ko`6&i3`Ulf!u5D}C$Ac&1x%!{MK*R{FG=;~E|%_pDyQc~PS%$)zEJ{n|HoiNsz) znciP=s$Ph19es=yTsL#SE`N5b*wHmfT4Y=}kqn7&C-mt!9Jr!tmPxC6HF5rJzxew! z!OaqMjFi;H?lGLl**cLSQed2?C0I3Wi9%?XRu8+BVcfy1ygG(-&LHTOslpdUfF{}$ z%7sP@;UjKt+>ha-QR-JATMOK3q`c6DYTBfvGTF88o!4Z9r{6q2fDN{jpIB_H%UdlF1#&!?q z#n$7tz#_ePqYFMh5(P+byAs|P^!mzPP zMMr8||F!`Mdebzv9x(4qgeK_9R#2UU@v%(BS4gVbT)L8vcX-b9`>S1-s{oemykgf*(i! zz7S%(EcWT9C95(&?ZsktNPB=IwqQaA8m`k^QR>JJOl`G*sEKrH@>TzoTQc{+ZvP65JnVtlw-o0PcW2OqqSAh{#Gf_ zBk$FSuM*kl(AVC_d1{^(Td*O8YUHM-_i9B2Nm&{jhM6KLEDlK#48O^132O*83ynlY zKOrQM?(KJbt}Uax?yn3taNzkNSg89t1RiLVH*b5}m@_YW|27zZe9YaZxfUtp317)Y z&O;Xq40Yh%jTLIs*sM+zjmtaAk01D`?FD+ejnXW{ihA{oBi$B{*(RFu=$%! zNBST8+l2fl`)6bSH|vS|KlZo5^H28A{_}4Z{B!&Jn|~Vt|78Cx5dLOq0RLlu_pAS8 m|GfKOCB*-&F1-J-e-#u!IryJifr3K%`B47smMKVo?fxHiFH3{~ From 090325df40c320353eff3d96de07ff6e69764288 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 7 Jul 2022 11:49:24 -0700 Subject: [PATCH 111/343] binpac: Add pre-commit hooks and run clang-format on everything --- tools/binpac/lib/binpac_analyzer.h | 27 +- tools/binpac/lib/binpac_buffer.cc | 97 ++--- tools/binpac/lib/binpac_buffer.h | 91 +++-- tools/binpac/lib/binpac_bytestring.cc | 21 +- tools/binpac/lib/binpac_bytestring.h | 153 +++---- tools/binpac/lib/binpac_exception.h | 95 ++--- tools/binpac/lib/binpac_regex.cc | 5 +- tools/binpac/lib/binpac_regex.h | 34 +- tools/binpac/src/pac_action.cc | 62 +-- tools/binpac/src/pac_action.h | 74 ++-- tools/binpac/src/pac_analyzer.cc | 151 ++++--- tools/binpac/src/pac_analyzer.h | 156 +++---- tools/binpac/src/pac_array.cc | 315 ++++++--------- tools/binpac/src/pac_array.h | 87 ++-- tools/binpac/src/pac_attr.cc | 18 +- tools/binpac/src/pac_attr.h | 49 +-- tools/binpac/src/pac_btype.cc | 55 ++- tools/binpac/src/pac_btype.h | 43 +- tools/binpac/src/pac_case.cc | 138 +++---- tools/binpac/src/pac_case.h | 87 ++-- tools/binpac/src/pac_cclass.h | 62 +-- tools/binpac/src/pac_common.h | 95 +++-- tools/binpac/src/pac_conn.cc | 71 ++-- tools/binpac/src/pac_conn.h | 32 +- tools/binpac/src/pac_context.cc | 73 ++-- tools/binpac/src/pac_context.h | 92 +++-- tools/binpac/src/pac_cstr.cc | 138 ++++--- tools/binpac/src/pac_cstr.h | 14 +- tools/binpac/src/pac_ctype.cc | 8 +- tools/binpac/src/pac_ctype.h | 18 +- tools/binpac/src/pac_datadep.cc | 45 +-- tools/binpac/src/pac_datadep.h | 53 +-- tools/binpac/src/pac_dataptr.cc | 37 +- tools/binpac/src/pac_dataptr.h | 24 +- tools/binpac/src/pac_dataunit.cc | 49 +-- tools/binpac/src/pac_dataunit.h | 52 +-- tools/binpac/src/pac_dbg.h | 6 +- tools/binpac/src/pac_decl-inl.h | 2 +- tools/binpac/src/pac_decl.cc | 56 ++- tools/binpac/src/pac_decl.h | 83 ++-- tools/binpac/src/pac_embedded.cc | 33 +- tools/binpac/src/pac_embedded.h | 28 +- tools/binpac/src/pac_enum.cc | 34 +- tools/binpac/src/pac_enum.h | 30 +- tools/binpac/src/pac_exception.cc | 37 +- tools/binpac/src/pac_exception.h | 56 +-- tools/binpac/src/pac_expr.cc | 558 ++++++++++++-------------- tools/binpac/src/pac_expr.h | 115 +++--- tools/binpac/src/pac_exttype.cc | 27 +- tools/binpac/src/pac_exttype.h | 38 +- tools/binpac/src/pac_field.cc | 34 +- tools/binpac/src/pac_field.h | 37 +- tools/binpac/src/pac_flow.cc | 134 +++---- tools/binpac/src/pac_flow.h | 48 +-- tools/binpac/src/pac_func.cc | 46 +-- tools/binpac/src/pac_func.h | 66 +-- tools/binpac/src/pac_id.cc | 134 +++---- tools/binpac/src/pac_id.h | 216 +++++----- tools/binpac/src/pac_inputbuf.cc | 24 +- tools/binpac/src/pac_inputbuf.h | 12 +- tools/binpac/src/pac_let.cc | 75 ++-- tools/binpac/src/pac_let.h | 28 +- tools/binpac/src/pac_main.cc | 48 +-- tools/binpac/src/pac_number.h | 16 +- tools/binpac/src/pac_output.cc | 9 +- tools/binpac/src/pac_output.h | 12 +- tools/binpac/src/pac_param.cc | 56 ++- tools/binpac/src/pac_param.h | 28 +- tools/binpac/src/pac_paramtype.cc | 112 +++--- tools/binpac/src/pac_paramtype.h | 44 +- tools/binpac/src/pac_primitive.cc | 20 +- tools/binpac/src/pac_primitive.h | 77 ++-- tools/binpac/src/pac_record.cc | 272 +++++-------- tools/binpac/src/pac_record.h | 98 +++-- tools/binpac/src/pac_redef.cc | 114 +++--- tools/binpac/src/pac_redef.h | 12 +- tools/binpac/src/pac_regex.cc | 45 +-- tools/binpac/src/pac_regex.h | 32 +- tools/binpac/src/pac_state.cc | 34 +- tools/binpac/src/pac_state.h | 27 +- tools/binpac/src/pac_strtype.cc | 167 +++----- tools/binpac/src/pac_strtype.h | 56 +-- tools/binpac/src/pac_type.cc | 387 ++++++++---------- tools/binpac/src/pac_type.h | 214 +++++----- tools/binpac/src/pac_typedecl.cc | 105 ++--- tools/binpac/src/pac_typedecl.h | 48 +-- tools/binpac/src/pac_utils.cc | 25 +- tools/binpac/src/pac_varfield.cc | 2 +- tools/binpac/src/pac_varfield.h | 66 +-- tools/binpac/src/pac_withinput.cc | 33 +- tools/binpac/src/pac_withinput.h | 14 +- 91 files changed, 3086 insertions(+), 3665 deletions(-) diff --git a/tools/binpac/lib/binpac_analyzer.h b/tools/binpac/lib/binpac_analyzer.h index 690092de1b..c49fe22f20 100644 --- a/tools/binpac/lib/binpac_analyzer.h +++ b/tools/binpac/lib/binpac_analyzer.h @@ -1,27 +1,28 @@ #ifndef binpac_an_h #define binpac_an_h -namespace binpac { +namespace binpac + { // TODO: Add the Done() function // The interface for a connection analyzer -class ConnectionAnalyzer { +class ConnectionAnalyzer + { public: - virtual ~ConnectionAnalyzer() {} - virtual void NewData(bool is_orig, - const unsigned char* begin_of_data, + virtual ~ConnectionAnalyzer() { } + virtual void NewData(bool is_orig, const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0; -}; + }; // The interface for a flow analyzer -class FlowAnalyzer { +class FlowAnalyzer + { public: - virtual ~FlowAnalyzer() {} - virtual void NewData(const unsigned char* begin_of_data, - const unsigned char* end_of_data) = 0; -}; + virtual ~FlowAnalyzer() { } + virtual void NewData(const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0; + }; -} // namespace binpac + } // namespace binpac -#endif // binpac_an_h +#endif // binpac_an_h diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index 6bf154aea7..9469251413 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -1,20 +1,22 @@ -#include #include -#include // for memcpy +#include +#include // for memcpy #define binpac_regex_h #include "binpac.h" #include "binpac_buffer.h" -namespace binpac { +namespace binpac + { extern double network_time(); -namespace { - const unsigned char CR = '\r'; - const unsigned char LF = '\n'; -} +namespace + { +const unsigned char CR = '\r'; +const unsigned char LF = '\n'; + } binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = { // max_capacity @@ -67,9 +69,7 @@ void FlowBuffer::NewMessage() switch ( mode_ ) { case LINE_MODE: - bytes_to_advance = (frame_length_ + - (linebreak_style_ == STRICT_CRLF ? - 2 : 1)); + bytes_to_advance = (frame_length_ + (linebreak_style_ == STRICT_CRLF ? 2 : 1)); break; case FRAME_MODE: bytes_to_advance = frame_length_; @@ -118,14 +118,13 @@ void FlowBuffer::ExpandBuffer(int length) if ( length > policy.max_capacity ) { - std::string reason = strfmt("expand past max capacity %d/%d", - length, policy.max_capacity); + std::string reason = strfmt("expand past max capacity %d/%d", length, policy.max_capacity); throw ExceptionFlowBufferAlloc(reason.c_str()); } // Allocate a new buffer and copy the existing contents buffer_length_ = length; - unsigned char* new_buf = (unsigned char *) realloc(buffer_, buffer_length_); + unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_); if ( ! new_buf ) throw ExceptionFlowBufferAlloc("expand realloc OOM"); @@ -139,7 +138,7 @@ void FlowBuffer::ContractBuffer() return; buffer_length_ = policy.min_capacity; - unsigned char* new_buf = (unsigned char *) realloc(buffer_, buffer_length_); + unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_); if ( ! new_buf ) throw ExceptionFlowBufferAlloc("contract realloc OOM"); @@ -154,7 +153,7 @@ void FlowBuffer::SetLineBreaker(unsigned char* lbreaker) linebreak_style_ = LINE_BREAKER; } -void FlowBuffer::UnsetLineBreaker() +void FlowBuffer::UnsetLineBreaker() { linebreak_style_ = linebreak_style_default; } @@ -233,8 +232,7 @@ void FlowBuffer::NewData(const_byteptr begin, const_byteptr end) ClearPreviousData(); - BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || - orig_data_begin_ == orig_data_end_); + BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || orig_data_begin_ == orig_data_end_); orig_data_begin_ = begin; orig_data_end_ = end; @@ -273,8 +271,7 @@ void FlowBuffer::ClearPreviousData() { if ( frame_length_ > 0 ) { - frame_length_ -= - (orig_data_end_ - orig_data_begin_); + frame_length_ -= (orig_data_end_ - orig_data_begin_); } orig_data_begin_ = orig_data_end_; } @@ -320,14 +317,14 @@ Finite state automaton for CR_OR_LF: (!--line is complete, *--add to buffer) CR_OR_LF_0: - CR: CR_OR_LF_1 ! - LF: CR_OR_LF_0 ! - .: CR_OR_LF_0 * + CR: CR_OR_LF_1 ! + LF: CR_OR_LF_0 ! + .: CR_OR_LF_0 * CR_OR_LF_1: - CR: CR_OR_LF_1 ! - LF: CR_OR_LF_0 - .: CR_OR_LF_0 * + CR: CR_OR_LF_1 ! + LF: CR_OR_LF_0 + .: CR_OR_LF_0 * */ void FlowBuffer::MarkOrCopyLine_CR_OR_LF() @@ -335,8 +332,7 @@ void FlowBuffer::MarkOrCopyLine_CR_OR_LF() if ( ! (orig_data_begin_ && orig_data_end_) ) return; - if ( state_ == CR_OR_LF_1 && - orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF ) + if ( state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF ) { state_ = CR_OR_LF_0; ++orig_data_begin_; @@ -378,9 +374,8 @@ found_end_of_line: message_complete_ = true; #if DEBUG_FLOW_BUFFER - fprintf(stderr, "%.6f Line complete: [%s]\n", - network_time(), - string((const char *) begin(), (const char *) end()).c_str()); + fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(), + string((const char*)begin(), (const char*)end()).c_str()); #endif } @@ -389,14 +384,14 @@ Finite state automaton and STRICT_CRLF: (!--line is complete, *--add to buffer) STRICT_CRLF_0: - CR: STRICT_CRLF_1 * - LF: STRICT_CRLF_0 * - .: STRICT_CRLF_0 * + CR: STRICT_CRLF_1 * + LF: STRICT_CRLF_0 * + .: STRICT_CRLF_0 * STRICT_CRLF_1: - CR: STRICT_CRLF_1 * - LF: STRICT_CRLF_0 ! (--buffer_n_) - .: STRICT_CRLF_0 * + CR: STRICT_CRLF_1 * + LF: STRICT_CRLF_0 ! (--buffer_n_) + .: STRICT_CRLF_0 * */ void FlowBuffer::MarkOrCopyLine_STRICT_CRLF() @@ -442,9 +437,8 @@ found_end_of_line: message_complete_ = true; #if DEBUG_FLOW_BUFFER - fprintf(stderr, "%.6f Line complete: [%s]\n", - network_time(), - string((const char *) begin(), (const char *) end()).c_str()); + fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(), + string((const char*)begin(), (const char*)end()).c_str()); #endif } @@ -477,13 +471,11 @@ found_end_of_line: message_complete_ = true; #if DEBUG_FLOW_BUFFER - fprintf(stderr, "%.6f Line complete: [%s]\n", - network_time(), - string((const char *) begin(), (const char *) end()).c_str()); + fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(), + string((const char*)begin(), (const char*)end()).c_str()); #endif } - // Invariants: // // When buffer_n_ == 0: @@ -494,8 +486,7 @@ found_end_of_line: void FlowBuffer::MarkOrCopyFrame() { - if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && - orig_data_begin_ < orig_data_end_ ) + if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ ) { // Skip the lingering LF if ( *orig_data_begin_ == LF ) @@ -508,8 +499,7 @@ void FlowBuffer::MarkOrCopyFrame() if ( buffer_n_ == 0 ) { // If there is enough data - if ( frame_length_ >= 0 && - orig_data_end_ - orig_data_begin_ >= frame_length_ ) + if ( frame_length_ >= 0 && orig_data_end_ - orig_data_begin_ >= frame_length_ ) { // Do nothing except setting the message complete flag message_complete_ = true; @@ -518,15 +508,14 @@ void FlowBuffer::MarkOrCopyFrame() { if ( ! chunked_ ) { - AppendToBuffer(orig_data_begin_, - orig_data_end_ - orig_data_begin_); + AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); } message_complete_ = false; } } else { - BINPAC_ASSERT(!chunked_); + BINPAC_ASSERT(! chunked_); int bytes_to_copy = orig_data_end_ - orig_data_begin_; message_complete_ = false; if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ ) @@ -540,10 +529,8 @@ void FlowBuffer::MarkOrCopyFrame() #if DEBUG_FLOW_BUFFER if ( message_complete_ ) { - fprintf(stderr, "%.6f frame complete: [%s]\n", - network_time(), - string((const char *) begin(), - (const char *) end()).c_str()); + fprintf(stderr, "%.6f frame complete: [%s]\n", network_time(), + string((const char*)begin(), (const char*)end()).c_str()); } #endif } @@ -562,4 +549,4 @@ void FlowBuffer::AppendToBuffer(const_byteptr data, int len) BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_); } -} // namespace binpac + } // namespace binpac diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h index ef37082924..92bbf83a8b 100644 --- a/tools/binpac/lib/binpac_buffer.h +++ b/tools/binpac/lib/binpac_buffer.h @@ -2,24 +2,29 @@ #define binpac_buffer_h #include + #include "binpac.h" -namespace binpac { +namespace binpac + { -class FlowBuffer { +class FlowBuffer + { public: - struct Policy { + struct Policy + { int max_capacity; int min_capacity; int contract_threshold; - }; + }; - enum LineBreakStyle { - CR_OR_LF, // CR or LF or CRLF - STRICT_CRLF, // CR followed by LF - CR_LF_NUL, // CR or LF or CR-LF or CR-NUL - LINE_BREAKER, // User specified linebreaker - }; + enum LineBreakStyle + { + CR_OR_LF, // CR or LF or CRLF + STRICT_CRLF, // CR followed by LF + CR_LF_NUL, // CR or LF or CR-LF or CR-NUL + LINE_BREAKER, // User specified linebreaker + }; FlowBuffer(LineBreakStyle linebreak_style = CR_OR_LF); virtual ~FlowBuffer(); @@ -39,13 +44,12 @@ public: void DiscardData(); // Whether there is enough data for the frame - bool ready() const{ return message_complete_ || mode_ == UNKNOWN_MODE; } + bool ready() const { return message_complete_ || mode_ == UNKNOWN_MODE; } inline const_byteptr begin() const { BINPAC_ASSERT(ready()); - return ( buffer_n_ == 0 ) ? - orig_data_begin_ : buffer_; + return (buffer_n_ == 0) ? orig_data_begin_ : buffer_; } inline const_byteptr end() const @@ -64,18 +68,17 @@ public: inline int data_length() const { - if ( buffer_n_ > 0 ) + if ( buffer_n_ > 0 ) return buffer_n_; - if ( frame_length_ < 0 || - orig_data_begin_ + frame_length_ > orig_data_end_ ) + if ( frame_length_ < 0 || orig_data_begin_ + frame_length_ > orig_data_end_ ) return orig_data_end_ - orig_data_begin_; else return frame_length_; } inline bool data_available() const - { + { return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; } @@ -87,22 +90,20 @@ public: void GrowFrame(int new_frame_length); int data_seq() const - { - int data_seq_at_orig_data_begin = - data_seq_at_orig_data_end_ - - (orig_data_end_ - orig_data_begin_); + { + int data_seq_at_orig_data_begin = data_seq_at_orig_data_end_ - + (orig_data_end_ - orig_data_begin_); if ( buffer_n_ > 0 ) return data_seq_at_orig_data_begin; else - return data_seq_at_orig_data_begin + data_length(); + return data_seq_at_orig_data_begin + data_length(); } - bool eof() const { return eof_; } + bool eof() const { return eof_; } void set_eof(); bool have_pending_request() const { return have_pending_request_; } - static void init(Policy p) - { policy = p; } + static void init(Policy p) { policy = p; } protected: // Reset the buffer for a new message @@ -110,7 +111,7 @@ protected: void ClearPreviousData(); - // Expand the buffer to at least bytes. If there + // Expand the buffer to at least bytes. If there // are contents in the existing buffer, copy them to the new // buffer. void ExpandBuffer(int length); @@ -128,8 +129,8 @@ protected: void AppendToBuffer(const_byteptr data, int len); // MarkOrCopy{Line,Frame} sets message_complete_ and - // marks begin/end pointers if a line/frame is complete, - // otherwise it clears message_complete_ and copies all + // marks begin/end pointers if a line/frame is complete, + // otherwise it clears message_complete_ and copies all // the original data to the buffer. // void MarkOrCopy(); @@ -140,41 +141,43 @@ protected: void MarkOrCopyLine_STRICT_CRLF(); void MarkOrCopyLine_LINEBREAK(); - int buffer_n_; // number of bytes in the buffer - int buffer_length_; // size of the buffer + int buffer_n_; // number of bytes in the buffer + int buffer_length_; // size of the buffer unsigned char* buffer_; - bool message_complete_; - int frame_length_; - bool chunked_; + bool message_complete_; + int frame_length_; + bool chunked_; const_byteptr orig_data_begin_, orig_data_end_; LineBreakStyle linebreak_style_; LineBreakStyle linebreak_style_default; - unsigned char linebreaker_; + unsigned char linebreaker_; - enum { + enum + { UNKNOWN_MODE, LINE_MODE, FRAME_MODE, - } mode_; + } mode_; - enum { + enum + { CR_OR_LF_0, CR_OR_LF_1, STRICT_CRLF_0, STRICT_CRLF_1, FRAME_0, - } state_; + } state_; - int data_seq_at_orig_data_end_; - bool eof_; - bool have_pending_request_; + int data_seq_at_orig_data_end_; + bool eof_; + bool have_pending_request_; static Policy policy; -}; + }; -typedef FlowBuffer *flow_buffer_t; +typedef FlowBuffer* flow_buffer_t; -} // namespace binpac + } // namespace binpac #endif // binpac_buffer_h diff --git a/tools/binpac/lib/binpac_bytestring.cc b/tools/binpac/lib/binpac_bytestring.cc index b74fe369b1..1bde160024 100644 --- a/tools/binpac/lib/binpac_bytestring.cc +++ b/tools/binpac/lib/binpac_bytestring.cc @@ -1,24 +1,25 @@ #define binpac_regex_h -#include #include "binpac_bytestring.h" -namespace binpac -{ +#include -std::string std_string(bytestring const *s) +namespace binpac { - return std::string((const char *) s->begin(), (const char *) s->end()); + +std::string std_string(bytestring const* s) + { + return std::string((const char*)s->begin(), (const char*)s->end()); } -int bytestring_to_int(bytestring const *s) +int bytestring_to_int(bytestring const* s) { - return atoi((const char *) s->begin()); + return atoi((const char*)s->begin()); } -double bytestring_to_double(bytestring const *s) +double bytestring_to_double(bytestring const* s) { - return atof((const char *) s->begin()); + return atof((const char*)s->begin()); } -} // namespace binpac + } // namespace binpac diff --git a/tools/binpac/lib/binpac_bytestring.h b/tools/binpac/lib/binpac_bytestring.h index 13d1879aed..aba59c50fa 100644 --- a/tools/binpac/lib/binpac_bytestring.h +++ b/tools/binpac/lib/binpac_bytestring.h @@ -3,155 +3,118 @@ #include #include + #include "binpac.h" namespace binpac -{ + { -template class datastring; +template class datastring; -template -class const_datastring -{ +template class const_datastring + { public: - const_datastring() - : begin_(0), end_(0) - { - } + const_datastring() : begin_(0), end_(0) { } - const_datastring(T const *data, int length) - : begin_(data), end_(data + length) - { - } + const_datastring(T const* data, int length) : begin_(data), end_(data + length) { } - const_datastring(const T *begin, const T *end) - : begin_(begin), end_(end) - { - } + const_datastring(const T* begin, const T* end) : begin_(begin), end_(end) { } - const_datastring(datastring const &s) - : begin_(s.begin()), end_(s.end()) - { - } + const_datastring(datastring const& s) : begin_(s.begin()), end_(s.end()) { } - void init(const T *data, int length) + void init(const T* data, int length) { begin_ = data; end_ = data + length; } - T const *begin() const { return begin_; } - T const *end() const { return end_; } - int length() const { return end_ - begin_; } + T const* begin() const { return begin_; } + T const* end() const { return end_; } + int length() const { return end_ - begin_; } - T const &operator[](int index) const - { - return begin()[index]; - } + T const& operator[](int index) const { return begin()[index]; } - bool operator==(const_datastring const &s) + bool operator==(const_datastring const& s) { if ( length() != s.length() ) return false; - return memcmp((const void *) begin(), (const void *) s.begin(), - sizeof(T) * length()) == 0; + return memcmp((const void*)begin(), (const void*)s.begin(), sizeof(T) * length()) == 0; } - void set_begin(T const *begin) { begin_ = begin; } - void set_end(T const *end) { end_ = end; } + void set_begin(T const* begin) { begin_ = begin; } + void set_end(T const* end) { end_ = end; } private: - T const *begin_; - T const *end_; -}; + T const* begin_; + T const* end_; + }; -typedef const_datastring const_bytestring; +typedef const_datastring const_bytestring; -template -class datastring -{ +template class datastring + { public: - datastring() - { - clear(); - } + datastring() { clear(); } - datastring(T *data, int len) - { - set(data, len); - } + datastring(T* data, int len) { set(data, len); } - datastring(T const *begin, T const *end) - { - set_const(begin, end - begin); - } + datastring(T const* begin, T const* end) { set_const(begin, end - begin); } - datastring(datastring const &x) - : data_(x.data()), length_(x.length()) - { - } + datastring(datastring const& x) : data_(x.data()), length_(x.length()) { } - explicit datastring(const_datastring const &x) - { - set_const(x.begin(), x.length()); - } + explicit datastring(const_datastring const& x) { set_const(x.begin(), x.length()); } - datastring const &operator=(datastring const &x) + datastring const& operator=(datastring const& x) { - BINPAC_ASSERT(!data_); + BINPAC_ASSERT(! data_); set(x.data(), x.length()); return *this; } - void init(T const *begin, int length) + void init(T const* begin, int length) { - BINPAC_ASSERT(!data_); + BINPAC_ASSERT(! data_); set_const(begin, length); } void clear() { - data_ = 0; length_ = 0; + data_ = 0; + length_ = 0; } void free() { if ( data_ ) - delete [] data_; + delete[] data_; clear(); } - void clone() - { - set_const(begin(), length()); - } + void clone() { set_const(begin(), length()); } - datastring const &operator=(const_datastring const &x) + datastring const& operator=(const_datastring const& x) { - BINPAC_ASSERT(!data_); + BINPAC_ASSERT(! data_); set_const(x.begin(), x.length()); return *this; } - T const &operator[](int index) const - { - return begin()[index]; - } + T const& operator[](int index) const { return begin()[index]; } - T *data() const { return data_; } - int length() const { return length_; } + T* data() const { return data_; } + int length() const { return length_; } - T const *begin() const { return data_; } - T const *end() const { return data_ + length_; } + T const* begin() const { return data_; } + T const* end() const { return data_ + length_; } private: - void set(T *data, int len) + void set(T* data, int len) { data_ = data; length_ = len; } - void set_const(T const *data, int len) + void set_const(T const* data, int len) { length_ = len; data_ = new T[len + 1]; @@ -159,41 +122,39 @@ private: data_[len] = 0; } - T * data_; + T* data_; int length_; -}; + }; typedef datastring bytestring; -inline const char *c_str(bytestring const &s) +inline const char* c_str(bytestring const& s) { - return (const char *) s.begin(); + return (const char*)s.begin(); } -inline std::string std_str(const_bytestring const &s) +inline std::string std_str(const_bytestring const& s) { - return std::string((const char *) s.begin(), (const char *) s.end()); + return std::string((const char*)s.begin(), (const char*)s.end()); } -inline bool operator==(bytestring const &s1, const char *s2) +inline bool operator==(bytestring const& s1, const char* s2) { return strcmp(c_str(s1), s2) == 0; } -inline void get_pointers(const_bytestring const &s, - uint8 const **pbegin, uint8 const **pend) +inline void get_pointers(const_bytestring const& s, uint8 const** pbegin, uint8 const** pend) { *pbegin = s.begin(); *pend = s.end(); } -inline void get_pointers(bytestring const *s, - uint8 const **pbegin, uint8 const **pend) +inline void get_pointers(bytestring const* s, uint8 const** pbegin, uint8 const** pend) { *pbegin = s->begin(); *pend = s->end(); } -} // namespace binpac + } // namespace binpac -#endif // binpac_bytestring_h +#endif // binpac_bytestring_h diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h index cdbfd70405..3c9262d18f 100644 --- a/tools/binpac/lib/binpac_exception.h +++ b/tools/binpac/lib/binpac_exception.h @@ -1,133 +1,120 @@ #ifndef binpac_exception_h #define binpac_exception_h -#include #include +#include -namespace binpac { +namespace binpac + { class Exception -{ + { public: - Exception(const char* m = 0) - : msg_("binpac exception: ") + Exception(const char* m = 0) : msg_("binpac exception: ") { if ( m ) append(m); // abort(); } - void append(string m) { msg_ += m; } - string msg() const { return msg_; } - const char* c_msg() const { return msg_.c_str(); } + void append(string m) { msg_ += m; } + string msg() const { return msg_; } + const char* c_msg() const { return msg_.c_str(); } protected: string msg_; -}; + }; class ExceptionEnforceViolation : public Exception -{ + { public: ExceptionEnforceViolation(const char* where) { append(binpac_fmt("&enforce violation : %s", where)); } -}; + }; class ExceptionOutOfBound : public Exception -{ + { public: ExceptionOutOfBound(const char* where, int len_needed, int len_given) { - append(binpac_fmt("out_of_bound: %s: %d > %d", - where, len_needed, len_given)); + append(binpac_fmt("out_of_bound: %s: %d > %d", where, len_needed, len_given)); } -}; + }; class ExceptionInvalidCase : public Exception -{ + { public: - ExceptionInvalidCase(const char* location, - int64_t index, - const char *expected) - : location_(location), - index_(index), - expected_(expected) + ExceptionInvalidCase(const char* location, int64_t index, const char* expected) + : location_(location), index_(index), expected_(expected) { - append(binpac_fmt("invalid case: %s: %" PRIi64 " (%s)", - location, index, expected)); + append(binpac_fmt("invalid case: %s: %" PRIi64 " (%s)", location, index, expected)); } protected: const char* location_; int64_t index_; string expected_; -}; + }; class ExceptionInvalidCaseIndex : public Exception -{ + { public: - ExceptionInvalidCaseIndex(const char* location, - int64_t index) - : location_(location), - index_(index) + ExceptionInvalidCaseIndex(const char* location, int64_t index) + : location_(location), index_(index) { - append(binpac_fmt("invalid index for case: %s: %" PRIi64, - location, index)); + append(binpac_fmt("invalid index for case: %s: %" PRIi64, location, index)); } protected: const char* location_; int64_t index_; -}; + }; class ExceptionInvalidOffset : public Exception -{ + { public: - ExceptionInvalidOffset(const char* location, - int min_offset, int offset) - : location_(location), - min_offset_(min_offset), offset_(offset) + ExceptionInvalidOffset(const char* location, int min_offset, int offset) + : location_(location), min_offset_(min_offset), offset_(offset) { - append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", - location, min_offset, offset)); + append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", location, min_offset, + offset)); } protected: const char* location_; int min_offset_, offset_; -}; + }; class ExceptionStringMismatch : public Exception -{ + { public: - ExceptionStringMismatch(const char* location, - const char *expected, const char *actual_data) + ExceptionStringMismatch(const char* location, const char* expected, const char* actual_data) { append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"", - location, expected, actual_data)); + location, expected, actual_data)); } -}; + }; class ExceptionInvalidStringLength : public Exception -{ + { public: ExceptionInvalidStringLength(const char* location, int len) { - append(binpac_fmt("invalid length string: %s: %d", - location, len)); + append(binpac_fmt("invalid length string: %s: %d", location, len)); } -}; + }; class ExceptionFlowBufferAlloc : public Exception -{ + { public: ExceptionFlowBufferAlloc(const char* reason) { append(binpac_fmt("flowbuffer allocation failed: %s", reason)); } -}; + }; -} + } -#endif // binpac_exception_h +#endif // binpac_exception_h diff --git a/tools/binpac/lib/binpac_regex.cc b/tools/binpac/lib/binpac_regex.cc index 6f276c3462..9d6b890de4 100644 --- a/tools/binpac/lib/binpac_regex.cc +++ b/tools/binpac/lib/binpac_regex.cc @@ -3,8 +3,9 @@ class RE_Matcher; -namespace binpac { +namespace binpac + { std::vector* uncompiled_re_matchers = 0; -} + } diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index 7c742966a7..53c70e0f4e 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -1,13 +1,17 @@ #ifndef binpac_regex_h #define binpac_regex_h -#include "binpac.h" #include "zeek/RE.h" -namespace zeek { class RE_Matcher; } +#include "binpac.h" + +namespace zeek + { +class RE_Matcher; + } namespace binpac -{ + { // Must be called before any binpac functionality is used. // @@ -19,10 +23,10 @@ inline void init(FlowBuffer::Policy* fbp = 0); // Internal vector recording not yet compiled matchers. extern std::vector* uncompiled_re_matchers; -class RegExMatcher { +class RegExMatcher + { public: - RegExMatcher(const char *pattern) - : pattern_(pattern) + RegExMatcher(const char* pattern) : pattern_(pattern) { if ( ! uncompiled_re_matchers ) uncompiled_re_matchers = new std::vector; @@ -31,16 +35,10 @@ public: uncompiled_re_matchers->push_back(re_matcher_); } - ~RegExMatcher() - { - delete re_matcher_; - } + ~RegExMatcher() { delete re_matcher_; } // Returns the length of longest match, or -1 on mismatch. - int MatchPrefix(const_byteptr data, int len) - { - return re_matcher_->MatchPrefix(data, len); - } + int MatchPrefix(const_byteptr data, int len) { return re_matcher_->MatchPrefix(data, len); } private: friend void ::binpac::init(FlowBuffer::Policy*); @@ -49,8 +47,8 @@ private: static void init(); string pattern_; - zeek::RE_Matcher *re_matcher_; -}; + zeek::RE_Matcher* re_matcher_; + }; inline void RegExMatcher::init() { @@ -77,6 +75,6 @@ inline void init(FlowBuffer::Policy* fbp) FlowBuffer::init(*fbp); } -} // namespace binpac + } // namespace binpac -#endif // binpac_regex_h +#endif // binpac_regex_h diff --git a/tools/binpac/src/pac_action.cc b/tools/binpac/src/pac_action.cc index ca9f72d96e..549672ad88 100644 --- a/tools/binpac/src/pac_action.cc +++ b/tools/binpac/src/pac_action.cc @@ -1,3 +1,5 @@ +#include "pac_action.h" + #include "pac_embedded.h" #include "pac_exception.h" #include "pac_id.h" @@ -6,18 +8,9 @@ #include "pac_typedecl.h" #include "pac_utils.h" -#include "pac_action.h" - -AnalyzerAction::AnalyzerAction(ID *action_id, - When when, - ActionParam *param, - EmbeddedCode *code) - : AnalyzerElement(ACTION), - action_id_(action_id), - when_(when), - param_(param), - code_(code), - analyzer_(0) +AnalyzerAction::AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code) + : AnalyzerElement(ACTION), action_id_(action_id), when_(when), param_(param), code_(code), + analyzer_(0) { } @@ -33,31 +26,25 @@ string AnalyzerAction::action_function() const return strfmt("Action_%s", action_id_->Name()); } -void AnalyzerAction::InstallHook(AnalyzerDecl *analyzer) +void AnalyzerAction::InstallHook(AnalyzerDecl* analyzer) { ASSERT(0); analyzer_ = analyzer; // param_->MainDataType()->InstallAction(this); } -void AnalyzerAction::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl) +void AnalyzerAction::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) { Env action_func_env(decl->env(), this); - action_func_env.AddID(param_->id(), - TEMP_VAR, - param_->DataType()); + action_func_env.AddID(param_->id(), TEMP_VAR, param_->DataType()); action_func_env.SetEvaluated(param_->id()); - string action_func_proto = - strfmt("%s(%s)", - action_function().c_str(), - ParamDecls(&action_func_env).c_str()); + string action_func_proto = strfmt("%s(%s)", action_function().c_str(), + ParamDecls(&action_func_env).c_str()); out_h->println("void %s;", action_func_proto.c_str()); - out_cc->println("void %s::%s", - decl->class_name().c_str(), - action_func_proto.c_str()); + out_cc->println("void %s::%s", decl->class_name().c_str(), action_func_proto.c_str()); out_cc->inc_indent(); out_cc->println("{"); @@ -69,28 +56,27 @@ void AnalyzerAction::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl) out_cc->println(""); } -string AnalyzerAction::ParamDecls(Env *env) const +string AnalyzerAction::ParamDecls(Env* env) const { return param_->DeclStr(env); } -Type *ActionParam::MainDataType() const +Type* ActionParam::MainDataType() const { // Note: this is not equal to DataType() - Type *main_type = TypeDecl::LookUpType(type()->type_id()); + Type* main_type = TypeDecl::LookUpType(type()->type_id()); if ( ! main_type ) { - throw Exception(type()->type_id(), - "type not defined"); + throw Exception(type()->type_id(), "type not defined"); } return main_type; } -Type *ActionParam::DataType() const +Type* ActionParam::DataType() const { - Type *main_type = MainDataType(); + Type* main_type = MainDataType(); if ( ! type()->field_id() ) { @@ -98,22 +84,18 @@ Type *ActionParam::DataType() const } else { - Type *member_type = - main_type->MemberDataType(type()->field_id()); + Type* member_type = main_type->MemberDataType(type()->field_id()); if ( ! member_type ) { throw Exception(type()->field_id(), - strfmt("cannot find member type for `%s.%s'", - type()->type_id()->Name(), - type()->field_id()->Name())); + strfmt("cannot find member type for `%s.%s'", type()->type_id()->Name(), + type()->field_id()->Name())); } return member_type; } } -string ActionParam::DeclStr(Env *env) const +string ActionParam::DeclStr(Env* env) const { - return strfmt("%s %s", - DataType()->DataTypeStr().c_str(), - env->LValue(id())); + return strfmt("%s %s", DataType()->DataTypeStr().c_str(), env->LValue(id())); } diff --git a/tools/binpac/src/pac_action.h b/tools/binpac/src/pac_action.h index df0828b823..4718d95a31 100644 --- a/tools/binpac/src/pac_action.h +++ b/tools/binpac/src/pac_action.h @@ -3,72 +3,74 @@ // Classes representing analyzer actions. -#include "pac_common.h" #include "pac_analyzer.h" +#include "pac_common.h" class AnalyzerAction : public AnalyzerElement -{ + { public: - enum When { BEFORE, AFTER }; + enum When + { + BEFORE, + AFTER + }; - AnalyzerAction(ID *action_id, - When when, - ActionParam *param, - EmbeddedCode *code); + AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code); ~AnalyzerAction(); - When when() const { return when_; } - ActionParam *param() const { return param_; } - AnalyzerDecl *analyzer() const { return analyzer_; } + When when() const { return when_; } + ActionParam* param() const { return param_; } + AnalyzerDecl* analyzer() const { return analyzer_; } string action_function() const; // Generate function prototype and code for the action - void GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl); + void GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl); // Install the hook at the corresponding data type parsing // function to invoke the action. - void InstallHook(AnalyzerDecl *analyzer); + void InstallHook(AnalyzerDecl* analyzer); private: - string ParamDecls(Env *env) const; + string ParamDecls(Env* env) const; - ID *action_id_; + ID* action_id_; When when_; - ActionParam *param_; - EmbeddedCode *code_; - AnalyzerDecl *analyzer_; -}; + ActionParam* param_; + EmbeddedCode* code_; + AnalyzerDecl* analyzer_; + }; class ActionParam -{ + { public: - ActionParam(const ID *id, ActionParamType *type) - : id_(id), type_(type) {} + ActionParam(const ID* id, ActionParamType* type) : id_(id), type_(type) { } - const ID *id() const { return id_; } - ActionParamType *type() const { return type_; } + const ID* id() const { return id_; } + ActionParamType* type() const { return type_; } - Type *MainDataType() const; - Type *DataType() const; - string DeclStr(Env *env) const; + Type* MainDataType() const; + Type* DataType() const; + string DeclStr(Env* env) const; private: - const ID *id_; - ActionParamType *type_; -}; + const ID* id_; + ActionParamType* type_; + }; class ActionParamType -{ + { public: - ActionParamType(const ID *type_id, const ID *field_id = 0) - : type_id_(type_id), field_id_(field_id) {} + ActionParamType(const ID* type_id, const ID* field_id = 0) + : type_id_(type_id), field_id_(field_id) + { + } - const ID *type_id() const { return type_id_; } - const ID *field_id() const { return field_id_; } + const ID* type_id() const { return type_id_; } + const ID* field_id() const { return field_id_; } protected: const ID *type_id_, *field_id_; -}; + }; -#endif // pac_action_h +#endif // pac_action_h diff --git a/tools/binpac/src/pac_analyzer.cc b/tools/binpac/src/pac_analyzer.cc index 0c01190a9d..918678cadb 100644 --- a/tools/binpac/src/pac_analyzer.cc +++ b/tools/binpac/src/pac_analyzer.cc @@ -1,3 +1,5 @@ +#include "pac_analyzer.h" + #include "pac_action.h" #include "pac_context.h" #include "pac_embedded.h" @@ -12,11 +14,7 @@ #include "pac_type.h" #include "pac_varfield.h" -#include "pac_analyzer.h" - -AnalyzerDecl::AnalyzerDecl(ID *id, - DeclType decl_type, - ParamList *params) +AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params) : TypeDecl(id, params, new DummyType()) { decl_type_ = decl_type; @@ -47,74 +45,66 @@ AnalyzerDecl::~AnalyzerDecl() delete_list(AnalyzerHelperList, eof_helpers_); } -void AnalyzerDecl::AddElements(AnalyzerElementList *elemlist) +void AnalyzerDecl::AddElements(AnalyzerElementList* elemlist) { ASSERT(! env_); - foreach(i, AnalyzerElementList, elemlist) + foreach (i, AnalyzerElementList, elemlist) { - AnalyzerElement *elem = *i; + AnalyzerElement* elem = *i; switch ( elem->type() ) { case AnalyzerElement::STATE: { ASSERT(0); - AnalyzerState *state_elem = - (AnalyzerState *) elem; - statevars_->insert( - statevars_->end(), - state_elem->statevars()->begin(), - state_elem->statevars()->end()); + AnalyzerState* state_elem = (AnalyzerState*)elem; + statevars_->insert(statevars_->end(), state_elem->statevars()->begin(), + state_elem->statevars()->end()); } break; case AnalyzerElement::ACTION: { ASSERT(0); - AnalyzerAction *action_elem = - (AnalyzerAction *) elem; + AnalyzerAction* action_elem = (AnalyzerAction*)elem; actions_->push_back(action_elem); } break; case AnalyzerElement::HELPER: { - AnalyzerHelper *helper_elem = - (AnalyzerHelper *) elem; + AnalyzerHelper* helper_elem = (AnalyzerHelper*)elem; switch ( helper_elem->helper_type() ) - { + { case AnalyzerHelper::INIT_CODE: - constructor_helpers_->push_back(helper_elem); + constructor_helpers_->push_back(helper_elem); break; case AnalyzerHelper::CLEANUP_CODE: - destructor_helpers_->push_back(helper_elem); + destructor_helpers_->push_back(helper_elem); break; case AnalyzerHelper::EOF_CODE: - eof_helpers_->push_back(helper_elem); + eof_helpers_->push_back(helper_elem); break; default: - helpers_->push_back(helper_elem); + helpers_->push_back(helper_elem); } } break; case AnalyzerElement::FUNCTION: { - AnalyzerFunction *func_elem = - (AnalyzerFunction *) elem; - Function *func = func_elem->function(); + AnalyzerFunction* func_elem = (AnalyzerFunction*)elem; + Function* func = func_elem->function(); func->set_analyzer_decl(this); functions_->push_back(func); } break; case AnalyzerElement::FLOW: { - AnalyzerFlow *flow_elem = - (AnalyzerFlow *) elem; + AnalyzerFlow* flow_elem = (AnalyzerFlow*)elem; ProcessFlowElement(flow_elem); } break; case AnalyzerElement::DATAUNIT: { - AnalyzerDataUnit *dataunit_elem = - (AnalyzerDataUnit *) elem; + AnalyzerDataUnit* dataunit_elem = (AnalyzerDataUnit*)elem; ProcessDataUnitElement(dataunit_elem); } break; @@ -123,8 +113,8 @@ void AnalyzerDecl::AddElements(AnalyzerElementList *elemlist) } string AnalyzerDecl::class_name() const - { - return id_->Name(); + { + return id_->Name(); } void AnalyzerDecl::Prepare() @@ -134,19 +124,19 @@ void AnalyzerDecl::Prepare() ASSERT(statevars_->empty()); ASSERT(actions_->empty()); - foreach(i, FunctionList, functions_) + foreach (i, FunctionList, functions_) { - Function *function = *i; + Function* function = *i; function->Prepare(env_); } - foreach(i, StateVarList, statevars_) + foreach (i, StateVarList, statevars_) { - StateVar *statevar = *i; + StateVar* statevar = *i; env_->AddID(statevar->id(), STATE_VAR, statevar->type()); } - foreach(i, AnalyzerActionList, actions_) + foreach (i, AnalyzerActionList, actions_) { - AnalyzerAction *action = *i; + AnalyzerAction* action = *i; action->InstallHook(this); } } @@ -154,30 +144,30 @@ void AnalyzerDecl::Prepare() void AnalyzerDecl::GenForwardDeclaration(Output* out_h) { out_h->println("class %s;", class_name().c_str()); - foreach(i, FunctionList, functions_) + foreach (i, FunctionList, functions_) { - Function *function = *i; + Function* function = *i; function->GenForwardDeclaration(out_h); } } -void AnalyzerDecl::GenActions(Output *out_h, Output *out_cc) +void AnalyzerDecl::GenActions(Output* out_h, Output* out_cc) { - foreach(i, AnalyzerActionList, actions_) + foreach (i, AnalyzerActionList, actions_) { (*i)->GenCode(out_h, out_cc, this); } } -void AnalyzerDecl::GenHelpers(Output *out_h, Output *out_cc) +void AnalyzerDecl::GenHelpers(Output* out_h, Output* out_cc) { - foreach(i, AnalyzerHelperList, helpers_) + foreach (i, AnalyzerHelperList, helpers_) { (*i)->GenCode(out_h, out_cc, this); } } -void AnalyzerDecl::GenPubDecls(Output *out_h, Output *out_cc) +void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc) { TypeDecl::GenPubDecls(out_h, out_cc); @@ -196,7 +186,7 @@ void AnalyzerDecl::GenPubDecls(Output *out_h, Output *out_cc) // TODO: export public state variables } -void AnalyzerDecl::GenPrivDecls(Output *out_h, Output *out_cc) +void AnalyzerDecl::GenPrivDecls(Output* out_h, Output* out_cc) { TypeDecl::GenPrivDecls(out_h, out_cc); @@ -210,65 +200,65 @@ void AnalyzerDecl::GenPrivDecls(Output *out_h, Output *out_cc) // TODO: declare state variables } -void AnalyzerDecl::GenInitCode(Output *out_cc) +void AnalyzerDecl::GenInitCode(Output* out_cc) { TypeDecl::GenInitCode(out_cc); - foreach(i, AnalyzerHelperList, constructor_helpers_) + foreach (i, AnalyzerHelperList, constructor_helpers_) { (*i)->GenCode(0, out_cc, this); } } -void AnalyzerDecl::GenCleanUpCode(Output *out_cc) +void AnalyzerDecl::GenCleanUpCode(Output* out_cc) { TypeDecl::GenCleanUpCode(out_cc); - foreach(i, AnalyzerHelperList, destructor_helpers_) + foreach (i, AnalyzerHelperList, destructor_helpers_) { (*i)->GenCode(0, out_cc, this); } } -void AnalyzerDecl::GenStateVarDecls(Output *out_h) +void AnalyzerDecl::GenStateVarDecls(Output* out_h) { - foreach(i, StateVarList, statevars_) + foreach (i, StateVarList, statevars_) { - StateVar *var = *i; + StateVar* var = *i; var->GenDecl(out_h, env_); } } -void AnalyzerDecl::GenStateVarSetFunctions(Output *out_h) +void AnalyzerDecl::GenStateVarSetFunctions(Output* out_h) { - foreach(i, StateVarList, statevars_) + foreach (i, StateVarList, statevars_) { - StateVar *var = *i; + StateVar* var = *i; var->GenSetFunction(out_h, env_); } } -void AnalyzerDecl::GenStateVarInitCode(Output *out_cc) +void AnalyzerDecl::GenStateVarInitCode(Output* out_cc) { - foreach(i, StateVarList, statevars_) + foreach (i, StateVarList, statevars_) { - StateVar *var = *i; + StateVar* var = *i; var->GenInitCode(out_cc, env_); } } -void AnalyzerDecl::GenStateVarCleanUpCode(Output *out_cc) +void AnalyzerDecl::GenStateVarCleanUpCode(Output* out_cc) { - foreach(i, StateVarList, statevars_) + foreach (i, StateVarList, statevars_) { - StateVar *var = *i; + StateVar* var = *i; var->GenCleanUpCode(out_cc, env_); } } -void AnalyzerDecl::GenFunctions(Output *out_h, Output *out_cc) +void AnalyzerDecl::GenFunctions(Output* out_h, Output* out_cc) { - foreach(i, FunctionList, functions_) + foreach (i, FunctionList, functions_) { - Function *function = *i; + Function* function = *i; function->GenCode(out_h, out_cc); } } @@ -285,9 +275,9 @@ AnalyzerHelper::~AnalyzerHelper() delete code_; } -void AnalyzerHelper::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl) +void AnalyzerHelper::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) { - Output *out = 0; + Output* out = 0; switch ( helper_type_ ) { case MEMBER_DECLS: @@ -303,22 +293,18 @@ void AnalyzerHelper::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl) code()->GenCode(out, decl->env()); } -FlowField::FlowField(ID *flow_id, ParameterizedType *flow_type) - : Field(FLOW_FIELD, - TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, - flow_id, flow_type) +FlowField::FlowField(ID* flow_id, ParameterizedType* flow_type) + : Field(FLOW_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, flow_id, flow_type) { } -void FlowField::GenInitCode(Output *out_cc, Env *env) +void FlowField::GenInitCode(Output* out_cc, Env* env) { type_->GenPreParsing(out_cc, env); } -AnalyzerFlow::AnalyzerFlow(Direction dir, ID *type_id, ExprList *params) - : AnalyzerElement(FLOW), - dir_(dir), - type_id_(type_id) +AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params) + : AnalyzerElement(FLOW), dir_(dir), type_id_(type_id) { if ( ! params ) params = new ExprList(); @@ -326,9 +312,9 @@ AnalyzerFlow::AnalyzerFlow(Direction dir, ID *type_id, ExprList *params) // Add "this" to the list of params params->insert(params->begin(), new Expr(this_id->clone())); - ID *flow_id = ((dir == UP) ? upflow_id : downflow_id)->clone(); + ID* flow_id = ((dir == UP) ? upflow_id : downflow_id)->clone(); - ParameterizedType *flow_type = new ParameterizedType(type_id_, params); + ParameterizedType* flow_type = new ParameterizedType(type_id_, params); flow_field_ = new FlowField(flow_id, flow_type); @@ -340,18 +326,17 @@ AnalyzerFlow::~AnalyzerFlow() delete flow_field_; } -FlowDecl *AnalyzerFlow::flow_decl() +FlowDecl* AnalyzerFlow::flow_decl() { DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name()); if ( ! flow_decl_ ) { - Decl *decl = Decl::LookUpDecl(type_id_); + Decl* decl = Decl::LookUpDecl(type_id_); if ( decl && decl->decl_type() == Decl::FLOW ) - flow_decl_ = static_cast(decl); + flow_decl_ = static_cast(decl); if ( ! flow_decl_ ) { - throw Exception(this, - "cannot find the flow declaration"); + throw Exception(this, "cannot find the flow declaration"); } } return flow_decl_; diff --git a/tools/binpac/src/pac_analyzer.h b/tools/binpac/src/pac_analyzer.h index a5fd5245aa..49f41611df 100644 --- a/tools/binpac/src/pac_analyzer.h +++ b/tools/binpac/src/pac_analyzer.h @@ -7,162 +7,172 @@ class AnalyzerElement; class AnalyzerState; -class AnalyzerAction; // defined in pac_action.h +class AnalyzerAction; // defined in pac_action.h class AnalyzerHelper; class AnalyzerFlow; class AnalyzerDataUnit; class AnalyzerFunction; class ConnDecl; class FlowDecl; -typedef vector AnalyzerHelperList; -typedef vector FunctionList; +typedef vector AnalyzerHelperList; +typedef vector FunctionList; class AnalyzerDecl : public TypeDecl -{ + { public: - AnalyzerDecl(ID *id, DeclType decl_type, ParamList *params); + AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params); ~AnalyzerDecl(); - void AddElements(AnalyzerElementList *elemlist); + void AddElements(AnalyzerElementList* elemlist); void Prepare(); - void GenForwardDeclaration(Output *out_h); + void GenForwardDeclaration(Output* out_h); // void GenCode(Output *out_h, Output *out_cc); - void GenInitCode(Output *out_cc); - void GenCleanUpCode(Output *out_cc); + void GenInitCode(Output* out_cc); + void GenCleanUpCode(Output* out_cc); string class_name() const; // string cookie_name() const; protected: - virtual void ProcessFlowElement(AnalyzerFlow *flow_elem) = 0; - virtual void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) = 0; + virtual void ProcessFlowElement(AnalyzerFlow* flow_elem) = 0; + virtual void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) = 0; - // Generate public/private declarations for member functions and + // Generate public/private declarations for member functions and // variables - void GenPubDecls(Output *out_h, Output *out_cc); - void GenPrivDecls(Output *out_h, Output *out_cc); + void GenPubDecls(Output* out_h, Output* out_cc); + void GenPrivDecls(Output* out_h, Output* out_cc); // Generate the NewData() function - virtual void GenProcessFunc(Output *out_h, Output *out_cc) = 0; + virtual void GenProcessFunc(Output* out_h, Output* out_cc) = 0; // Generate the NewGap() function - virtual void GenGapFunc(Output *out_h, Output *out_cc) = 0; + virtual void GenGapFunc(Output* out_h, Output* out_cc) = 0; // Generate the FlowEOF() function - virtual void GenEOFFunc(Output *out_h, Output *out_cc) = 0; + virtual void GenEOFFunc(Output* out_h, Output* out_cc) = 0; // Generate the functions - void GenFunctions(Output *out_h, Output *out_cc); + void GenFunctions(Output* out_h, Output* out_cc); // Generate the action functions - void GenActions(Output *out_h, Output *out_cc); + void GenActions(Output* out_h, Output* out_cc); // Generate the helper code segments - void GenHelpers(Output *out_h, Output *out_cc); + void GenHelpers(Output* out_h, Output* out_cc); // Generate declarations for state variables and their set functions - void GenStateVarDecls(Output *out_h); - void GenStateVarSetFunctions(Output *out_h); + void GenStateVarDecls(Output* out_h); + void GenStateVarSetFunctions(Output* out_h); // Generate code for initializing and cleaning up (including // memory de-allocating) state variables - void GenStateVarInitCode(Output *out_cc); - void GenStateVarCleanUpCode(Output *out_cc); + void GenStateVarInitCode(Output* out_cc); + void GenStateVarCleanUpCode(Output* out_cc); - StateVarList *statevars_; - AnalyzerActionList *actions_; - AnalyzerHelperList *helpers_; - FunctionList *functions_; + StateVarList* statevars_; + AnalyzerActionList* actions_; + AnalyzerHelperList* helpers_; + FunctionList* functions_; - AnalyzerHelperList *constructor_helpers_; - AnalyzerHelperList *destructor_helpers_; - AnalyzerHelperList *eof_helpers_; -}; + AnalyzerHelperList* constructor_helpers_; + AnalyzerHelperList* destructor_helpers_; + AnalyzerHelperList* eof_helpers_; + }; class AnalyzerElement : public Object -{ + { public: - enum ElementType { STATE, ACTION, FUNCTION, HELPER, FLOW, DATAUNIT }; - AnalyzerElement(ElementType type) - : type_(type) {} - virtual ~AnalyzerElement() {} + enum ElementType + { + STATE, + ACTION, + FUNCTION, + HELPER, + FLOW, + DATAUNIT + }; + AnalyzerElement(ElementType type) : type_(type) { } + virtual ~AnalyzerElement() { } - ElementType type() const { return type_; } + ElementType type() const { return type_; } private: ElementType type_; -}; + }; // A collection of variables representing analyzer states. class AnalyzerState : public AnalyzerElement -{ + { public: - AnalyzerState(StateVarList *statevars) - : AnalyzerElement(STATE), - statevars_(statevars) {} + AnalyzerState(StateVarList* statevars) : AnalyzerElement(STATE), statevars_(statevars) { } ~AnalyzerState(); - StateVarList *statevars() const { return statevars_; } + StateVarList* statevars() const { return statevars_; } private: - StateVarList *statevars_; -}; + StateVarList* statevars_; + }; // A collection of embedded C++ code class AnalyzerHelper : public AnalyzerElement -{ + { public: - enum Type { + enum Type + { MEMBER_DECLS, INIT_CODE, CLEANUP_CODE, EOF_CODE, - }; - AnalyzerHelper(Type helper_type, EmbeddedCode *code) - : AnalyzerElement(HELPER), - helper_type_(helper_type), - code_(code) {} + }; + AnalyzerHelper(Type helper_type, EmbeddedCode* code) + : AnalyzerElement(HELPER), helper_type_(helper_type), code_(code) + { + } ~AnalyzerHelper(); - Type helper_type() const { return helper_type_; } + Type helper_type() const { return helper_type_; } - void GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl); + void GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl); - EmbeddedCode *code() const { return code_; } + EmbeddedCode* code() const { return code_; } private: Type helper_type_; - EmbeddedCode *code_; -}; + EmbeddedCode* code_; + }; // The type and parameters of (uni-directional) flows of a connection. class FlowField : public Field -{ + { public: - FlowField(ID *flow_id, ParameterizedType *flow_type); - void GenInitCode(Output *out, Env *env); -}; + FlowField(ID* flow_id, ParameterizedType* flow_type); + void GenInitCode(Output* out, Env* env); + }; class AnalyzerFlow : public AnalyzerElement -{ + { public: - enum Direction { UP, DOWN }; - AnalyzerFlow(Direction dir, ID *type_id, ExprList *params); + enum Direction + { + UP, + DOWN + }; + AnalyzerFlow(Direction dir, ID* type_id, ExprList* params); ~AnalyzerFlow(); - Direction dir() const { return dir_; } - FlowField *flow_field() const { return flow_field_; } + Direction dir() const { return dir_; } + FlowField* flow_field() const { return flow_field_; } - FlowDecl *flow_decl(); + FlowDecl* flow_decl(); private: Direction dir_; - ID *type_id_; - FlowField *flow_field_; - FlowDecl *flow_decl_; -}; + ID* type_id_; + FlowField* flow_field_; + FlowDecl* flow_decl_; + }; -#endif // pac_analyzer_h +#endif // pac_analyzer_h diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 16d961d80b..ebaed479ca 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -1,3 +1,5 @@ +#include "pac_array.h" + #include "pac_attr.h" #include "pac_dataptr.h" #include "pac_exception.h" @@ -9,9 +11,7 @@ #include "pac_utils.h" #include "pac_varfield.h" -#include "pac_array.h" - -ArrayType::ArrayType(Type *elemtype, Expr *length) +ArrayType::ArrayType(Type* elemtype, Expr* length) : Type(ARRAY), elemtype_(elemtype), length_(length) { init(); @@ -67,9 +67,9 @@ ArrayType::~ArrayType() delete elem_dataptr_until_expr_; } -Type *ArrayType::DoClone() const +Type* ArrayType::DoClone() const { - Type *elemtype = elemtype_->Clone(); + Type* elemtype = elemtype_->Clone(); if ( ! elemtype ) return 0; return new ArrayType(elemtype, length_); @@ -85,45 +85,45 @@ string ArrayType::DataTypeStr() const return datatype_str_; } -Type *ArrayType::ElementDataType() const +Type* ArrayType::ElementDataType() const { return elemtype_; } -string ArrayType::EvalElement(const string &array, const string &index) const +string ArrayType::EvalElement(const string& array, const string& index) const { if ( attr_transient_ ) - throw Exception(this, "cannot access element in &transient array"); + throw Exception(this, "cannot access element in &transient array"); return strfmt("(*(%s))[%s]", array.c_str(), index.c_str()); } -const ID *ArrayType::arraylength_var() const +const ID* ArrayType::arraylength_var() const { return arraylength_var_field_ ? arraylength_var_field_->id() : 0; } -const ID *ArrayType::elem_it_var() const +const ID* ArrayType::elem_it_var() const { return elem_it_var_field_ ? elem_it_var_field_->id() : 0; } -const ID *ArrayType::elem_var() const +const ID* ArrayType::elem_var() const { return elem_var_field_ ? elem_var_field_->id() : 0; } -const ID *ArrayType::elem_dataptr_var() const +const ID* ArrayType::elem_dataptr_var() const { return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : 0; } -const ID *ArrayType::elem_input_var() const +const ID* ArrayType::elem_input_var() const { return elem_input_var_field_ ? elem_input_var_field_->id() : 0; } -void ArrayType::ProcessAttr(Attr *a) +void ArrayType::ProcessAttr(Attr* a) { Type::ProcessAttr(a); @@ -133,15 +133,13 @@ void ArrayType::ProcessAttr(Attr *a) { if ( elemtype_->StaticSize(env()) != 1 ) { - throw Exception(elemtype_, - "&restofdata can be applied" - " to only byte arrays"); + throw Exception(elemtype_, "&restofdata can be applied" + " to only byte arrays"); } if ( length_ ) { - throw Exception(length_, - "&restofdata cannot be applied" - " to arrays with specified length"); + throw Exception(length_, "&restofdata cannot be applied" + " to arrays with specified length"); } attr_restofdata_ = true; // As the array automatically extends to the end of @@ -161,17 +159,15 @@ void ArrayType::ProcessAttr(Attr *a) bool ref_input = a->expr()->HasReference(input_macro_id); if ( ref_element && ref_input ) { - throw Exception(a->expr(), - "cannot reference both $element and $input " - "in the same &until---please separate them."); + throw Exception(a->expr(), "cannot reference both $element and $input " + "in the same &until---please separate them."); } if ( ref_element ) { if ( attr_until_element_expr_ ) { - throw Exception(a->expr(), - "multiple &until on $element"); + throw Exception(a->expr(), "multiple &until on $element"); } attr_until_element_expr_ = a->expr(); } @@ -179,8 +175,7 @@ void ArrayType::ProcessAttr(Attr *a) { if ( attr_until_input_expr_ ) { - throw Exception(a->expr(), - "multiple &until on $input"); + throw Exception(a->expr(), "multiple &until on $input"); } attr_until_input_expr_ = a->expr(); } @@ -188,8 +183,7 @@ void ArrayType::ProcessAttr(Attr *a) { if ( attr_generic_until_expr_ ) { - throw Exception(a->expr(), - "multiple &until condition"); + throw Exception(a->expr(), "multiple &until condition"); } attr_generic_until_expr_ = a->expr(); } @@ -201,51 +195,42 @@ void ArrayType::ProcessAttr(Attr *a) } } -void ArrayType::Prepare(Env *env, int flags) +void ArrayType::Prepare(Env* env, int flags) { if ( flags & TO_BE_PARSED ) { - ID *arraylength_var = new ID(strfmt("%s__arraylength", value_var()->Name())); - ID *elem_var = new ID(strfmt("%s__elem", value_var()->Name())); - ID *elem_it_var = new ID(strfmt("%s__it", elem_var->Name())); + ID* arraylength_var = new ID(strfmt("%s__arraylength", value_var()->Name())); + ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name())); + ID* elem_it_var = new ID(strfmt("%s__it", elem_var->Name())); - elem_var_field_ = - new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_); + elem_var_field_ = new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_); AddField(elem_var_field_); if ( incremental_parsing() ) { - arraylength_var_field_ = - new PrivVarField(arraylength_var, extern_type_int->Clone()); - elem_it_var_field_ = - new PrivVarField(elem_it_var, extern_type_int->Clone()); + arraylength_var_field_ = new PrivVarField(arraylength_var, extern_type_int->Clone()); + elem_it_var_field_ = new PrivVarField(elem_it_var, extern_type_int->Clone()); AddField(arraylength_var_field_); AddField(elem_it_var_field_); } else { - arraylength_var_field_ = - new TempVarField(arraylength_var, extern_type_int->Clone()); - elem_it_var_field_ = - new TempVarField(elem_it_var, extern_type_int->Clone()); + arraylength_var_field_ = new TempVarField(arraylength_var, extern_type_int->Clone()); + elem_it_var_field_ = new TempVarField(elem_it_var, extern_type_int->Clone()); arraylength_var_field_->Prepare(env); elem_it_var_field_->Prepare(env); // Add elem_dataptr_var only when not parsing incrementally - ID *elem_dataptr_var = - new ID(strfmt("%s__dataptr", elem_var->Name())); - elem_dataptr_var_field_ = new TempVarField( - elem_dataptr_var, - extern_type_const_byteptr->Clone()); + ID* elem_dataptr_var = new ID(strfmt("%s__dataptr", elem_var->Name())); + elem_dataptr_var_field_ = new TempVarField(elem_dataptr_var, + extern_type_const_byteptr->Clone()); elem_dataptr_var_field_->Prepare(env); // until(dataptr >= end_of_data) - elem_dataptr_until_expr_ = new Expr( - Expr::EXPR_GE, - new Expr(elem_dataptr_var->clone()), - new Expr(end_of_data->clone())); + elem_dataptr_until_expr_ = new Expr(Expr::EXPR_GE, new Expr(elem_dataptr_var->clone()), + new Expr(end_of_data->clone())); } if ( attr_until_input_expr_ ) @@ -259,7 +244,7 @@ void ArrayType::Prepare(Env *env, int flags) Type::Prepare(env, flags); } -void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) +void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data) { if ( env->Evaluated(arraylength_var()) ) return; @@ -272,23 +257,17 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) if ( length_ ) { - out_cc->println("%s = %s;", - env->LValue(arraylength_var()), - length_->EvalExpr(out_cc, env)); + out_cc->println("%s = %s;", env->LValue(arraylength_var()), length_->EvalExpr(out_cc, env)); env->SetEvaluated(arraylength_var()); // Check negative array length - out_cc->println("if ( %s < 0 )", - env->LValue(arraylength_var())); + out_cc->println("if ( %s < 0 )", env->LValue(arraylength_var())); out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", - data_id_str_.c_str()); - out_cc->println(" %s, (%s) - (%s));", - env->LValue(arraylength_var()), - env->RValue(end_of_data), - env->RValue(begin_of_data)); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); + out_cc->println(" %s, (%s) - (%s));", env->LValue(arraylength_var()), + env->RValue(end_of_data), env->RValue(begin_of_data)); out_cc->println("}"); out_cc->dec_indent(); @@ -305,15 +284,13 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) // with it. Note that this check is *not* looking for whether the // contents of the array will extend past the end of the data // buffer. - out_cc->println("// Check array element quantity: %s", - data_id_str_.c_str()); + out_cc->println("// Check array element quantity: %s", data_id_str_.c_str()); element_size = 1; } else { // Boundary check the entire array if elements have static size. - out_cc->println("// Check bounds for static-size array: %s", - data_id_str_.c_str()); + out_cc->println("// Check bounds for static-size array: %s", data_id_str_.c_str()); elemtype_->SetBoundaryChecked(); element_size = elemtype_->StaticSize(env); @@ -325,66 +302,57 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) // arbitrary number of empty records (i.e. cheap for them, // but costly for us unless we have special optimization // for this scenario to forgo the usual allocation). - throw Exception(this, "using an array of known-to-be-empty elements is possibly a bad idea"); + throw Exception( + this, "using an array of known-to-be-empty elements is possibly a bad idea"); } } const char* array_ptr_expr = data.ptr_expr(); - string max_elements_available = strfmt("((%s - %s) / %d)", - env->RValue(end_of_data), - array_ptr_expr, - element_size); + string max_elements_available = strfmt("((%s - %s) / %d)", env->RValue(end_of_data), + array_ptr_expr, element_size); - out_cc->println("if ( %s > %s )", - env->RValue(arraylength_var()), + out_cc->println("if ( %s > %s )", env->RValue(arraylength_var()), max_elements_available.c_str()); out_cc->inc_indent(); - out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", - data_id_str_.c_str()); - out_cc->println(" %s, (%s) - (%s));", - env->RValue(arraylength_var()), - env->RValue(end_of_data), - array_ptr_expr); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); + out_cc->println(" %s, (%s) - (%s));", env->RValue(arraylength_var()), + env->RValue(end_of_data), array_ptr_expr); out_cc->dec_indent(); } else if ( attr_restofdata_ ) { ASSERT(elemtype_->StaticSize(env) == 1); - out_cc->println("%s = (%s) - (%s);", - env->LValue(arraylength_var()), - env->RValue(end_of_data), - data.ptr_expr()); + out_cc->println("%s = (%s) - (%s);", env->LValue(arraylength_var()), + env->RValue(end_of_data), data.ptr_expr()); env->SetEvaluated(arraylength_var()); } } -void ArrayType::GenPubDecls(Output *out_h, Env *env) +void ArrayType::GenPubDecls(Output* out_h, Env* env) { Type::GenPubDecls(out_h, env); if ( declared_as_type() ) { if ( attr_transient_ ) - throw Exception(this, "cannot access element in &transient array"); + throw Exception(this, "cannot access element in &transient array"); out_h->println("int size() const { return %s ? %s->size() : 0; }", - env->RValue(value_var()), - env->RValue(value_var())); + env->RValue(value_var()), env->RValue(value_var())); out_h->println("%s operator[](int index) const { BINPAC_ASSERT(%s); return (*%s)[index]; }", - elemtype_->DataTypeConstRefStr().c_str(), - env->RValue(value_var()), - env->RValue(value_var())); + elemtype_->DataTypeConstRefStr().c_str(), env->RValue(value_var()), + env->RValue(value_var())); } } -void ArrayType::GenPrivDecls(Output *out_h, Env *env) +void ArrayType::GenPrivDecls(Output* out_h, Env* env) { ASSERT(elem_var_field_->type() == elemtype_); ASSERT(elemtype_->value_var()); Type::GenPrivDecls(out_h, env); } -void ArrayType::GenInitCode(Output *out_cc, Env *env) +void ArrayType::GenInitCode(Output* out_cc, Env* env) { // Do not initiate the array here // out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); @@ -393,24 +361,19 @@ void ArrayType::GenInitCode(Output *out_cc, Env *env) Type::GenInitCode(out_cc, env); if ( incremental_parsing() ) { - out_cc->println("%s = -1;", - env->LValue(elem_it_var())); + out_cc->println("%s = -1;", env->LValue(elem_it_var())); } } -void ArrayType::GenCleanUpCode(Output *out_cc, Env *env) +void ArrayType::GenCleanUpCode(Output* out_cc, Env* env) { Type::GenCleanUpCode(out_cc, env); if ( elemtype_->NeedsCleanUp() ) { if ( ! elem_var_field_ ) { - ID *elem_var = new ID(strfmt("%s__elem", value_var()->Name())); - elem_var_field_ = - new ParseVarField( - Field::NOT_CLASS_MEMBER, - elem_var, - elemtype_); + ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name())); + elem_var_field_ = new ParseVarField(Field::NOT_CLASS_MEMBER, elem_var, elemtype_); elem_var_field_->Prepare(env); } @@ -418,14 +381,11 @@ void ArrayType::GenCleanUpCode(Output *out_cc, Env *env) out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("for ( int i = 0; i < (int) %s->size(); ++i )", - env->RValue(value_var())); + out_cc->println("for ( int i = 0; i < (int) %s->size(); ++i )", env->RValue(value_var())); out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("%s %s = (*%s)[i];", - elemtype_->DataTypeStr().c_str(), - env->LValue(elem_var()), - lvalue()); + out_cc->println("%s %s = (*%s)[i];", elemtype_->DataTypeStr().c_str(), + env->LValue(elem_var()), lvalue()); elemtype_->GenCleanUpCode(out_cc, env); out_cc->println("}"); out_cc->dec_indent(); @@ -436,28 +396,25 @@ void ArrayType::GenCleanUpCode(Output *out_cc, Env *env) out_cc->println("delete %s;", lvalue()); } -string ArrayType::GenArrayInit(Output *out_cc, Env *env, bool known_array_length) +string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length) { string array_str; array_str = lvalue(); if ( incremental_parsing() ) { - out_cc->println("if ( %s < 0 )", - env->LValue(elem_it_var())); + out_cc->println("if ( %s < 0 )", env->LValue(elem_it_var())); out_cc->inc_indent(); out_cc->println("{"); out_cc->println("// Initialize only once"); out_cc->println("%s = 0;", env->LValue(elem_it_var())); } - out_cc->println("%s = new %s;", - lvalue(), vector_str_.c_str()); + out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); if ( known_array_length ) { - out_cc->println("%s->reserve(%s);", - lvalue(), env->RValue(arraylength_var())); + out_cc->println("%s->reserve(%s);", lvalue(), env->RValue(arraylength_var())); } if ( incremental_parsing() ) @@ -469,34 +426,29 @@ string ArrayType::GenArrayInit(Output *out_cc, Env *env, bool known_array_length return array_str; } -void ArrayType::GenElementAssignment(Output *out_cc, Env *env, - string const &array_str, bool use_vector) +void ArrayType::GenElementAssignment(Output* out_cc, Env* env, string const& array_str, + bool use_vector) { if ( attr_transient_ ) - { - // Just discard. - out_cc->println("delete %s;", env->LValue(elem_var())); - return; - } + { + // Just discard. + out_cc->println("delete %s;", env->LValue(elem_var())); + return; + } // Assign the element if ( ! use_vector ) { - out_cc->println("%s[%s] = %s;", - array_str.c_str(), - env->LValue(elem_it_var()), - env->LValue(elem_var())); + out_cc->println("%s[%s] = %s;", array_str.c_str(), env->LValue(elem_it_var()), + env->LValue(elem_var())); } else { - out_cc->println("%s->push_back(%s);", - array_str.c_str(), - env->LValue(elem_var())); + out_cc->println("%s->push_back(%s);", array_str.c_str(), env->LValue(elem_var())); } } -void ArrayType::DoGenParseCode(Output *out_cc, Env *env, - const DataPtr& data, int flags) +void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { GenArrayLength(out_cc, env, data); @@ -518,7 +470,7 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, There are two cases when the input length can be determined: 1. The array has a static size; 2. The array length can be computed before parsing and - each element is of constant size. + each element is of constant size. */ bool compute_size_var = false; @@ -529,9 +481,8 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, compute_size_var = false; if ( ! incremental_parsing() && - ( StaticSize(env) >= 0 || - ( env->Evaluated(arraylength_var()) && - elemtype_->StaticSize(env) >= 0 ) ) ) + (StaticSize(env) >= 0 || + (env->Evaluated(arraylength_var()) && elemtype_->StaticSize(env) >= 0)) ) { GenBoundaryCheck(out_cc, env, data); } @@ -552,22 +503,17 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, if ( elem_dataptr_var() ) { - out_cc->println("const_byteptr %s = %s;", - env->LValue(elem_dataptr_var()), data.ptr_expr()); + out_cc->println("const_byteptr %s = %s;", env->LValue(elem_dataptr_var()), data.ptr_expr()); env->SetEvaluated(elem_dataptr_var()); elem_data = DataPtr(env, elem_dataptr_var(), 0); } - string for_condition = known_array_length ? - strfmt("%s < %s", - env->LValue(elem_it_var()), - env->RValue(arraylength_var())) : - "/* forever */"; + string for_condition = known_array_length ? strfmt("%s < %s", env->LValue(elem_it_var()), + env->RValue(arraylength_var())) + : "/* forever */"; - out_cc->println("for (; %s; ++%s)", - for_condition.c_str(), - env->LValue(elem_it_var())); + out_cc->println("for (; %s; ++%s)", for_condition.c_str(), env->LValue(elem_it_var())); out_cc->inc_indent(); out_cc->println("{"); @@ -597,8 +543,7 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, if ( incremental_parsing() ) { - out_cc->println("if ( ! %s )", - elemtype_->parsing_complete(env).c_str()); + out_cc->println("if ( ! %s )", elemtype_->parsing_complete(env).c_str()); out_cc->inc_indent(); out_cc->println("goto %s;", kNeedMoreData); out_cc->dec_indent(); @@ -608,12 +553,10 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, if ( elem_dataptr_var() ) { - out_cc->println("%s += %s;", - env->LValue(elem_dataptr_var()), - elemtype_->DataSize(0, env, elem_data).c_str()); - out_cc->println("BINPAC_ASSERT(%s <= %s);", - env->RValue(elem_dataptr_var()), - env->RValue(end_of_data)); + out_cc->println("%s += %s;", env->LValue(elem_dataptr_var()), + elemtype_->DataSize(0, env, elem_data).c_str()); + out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(elem_dataptr_var()), + env->RValue(end_of_data)); } if ( attr_until_element_expr_ ) @@ -632,55 +575,45 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env, if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) ) { // Compute the data size - out_cc->println("%s = %s - (%s);", - env->LValue(size_var()), - env->RValue(elem_dataptr_var()), - data.ptr_expr()); + out_cc->println("%s = %s - (%s);", env->LValue(size_var()), env->RValue(elem_dataptr_var()), + data.ptr_expr()); env->SetEvaluated(size_var()); } } -void ArrayType::GenUntilInputCheck(Output *out_cc, Env *env) +void ArrayType::GenUntilInputCheck(Output* out_cc, Env* env) { - ID *elem_input_var_id = new ID( - strfmt("%s__elem_input", value_var()->Name())); - elem_input_var_field_ = new TempVarField( - elem_input_var_id, extern_type_const_bytestring->Clone()); + ID* elem_input_var_id = new ID(strfmt("%s__elem_input", value_var()->Name())); + elem_input_var_field_ = new TempVarField(elem_input_var_id, + extern_type_const_bytestring->Clone()); elem_input_var_field_->Prepare(env); - out_cc->println("%s %s(%s, %s);", - extern_type_const_bytestring->DataTypeStr().c_str(), - env->LValue(elem_input_var()), - env->RValue(begin_of_data), - env->RValue(end_of_data)); + out_cc->println("%s %s(%s, %s);", extern_type_const_bytestring->DataTypeStr().c_str(), + env->LValue(elem_input_var()), env->RValue(begin_of_data), + env->RValue(end_of_data)); env->SetEvaluated(elem_input_var()); GenUntilCheck(out_cc, env, attr_until_input_expr_, true); } -void ArrayType::GenUntilCheck(Output *out_cc, Env *env, - Expr *until_expr, bool delete_elem) +void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool delete_elem) { ASSERT(until_expr); Env check_env(env, this); - check_env.AddMacro(element_macro_id, - new Expr(elem_var()->clone())); + check_env.AddMacro(element_macro_id, new Expr(elem_var()->clone())); if ( elem_input_var() ) { - check_env.AddMacro(input_macro_id, - new Expr(elem_input_var()->clone())); + check_env.AddMacro(input_macro_id, new Expr(elem_input_var()->clone())); } out_cc->println("// Check &until(%s)", until_expr->orig()); - out_cc->println("if ( %s )", - until_expr->EvalExpr(out_cc, &check_env)); + out_cc->println("if ( %s )", until_expr->EvalExpr(out_cc, &check_env)); out_cc->inc_indent(); out_cc->println("{"); if ( parsing_complete_var() ) { - out_cc->println("%s = true;", - env->LValue(parsing_complete_var())); + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); } if ( elemtype_->IsPointerType() ) @@ -696,18 +629,14 @@ void ArrayType::GenUntilCheck(Output *out_cc, Env *env, out_cc->dec_indent(); } -void ArrayType::GenDynamicSize(Output *out_cc, Env *env, - const DataPtr& data) +void ArrayType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { ASSERT(! incremental_input()); - DEBUG_MSG("Generating dynamic size for array `%s'\n", - value_var()->Name()); + DEBUG_MSG("Generating dynamic size for array `%s'\n", value_var()->Name()); int elem_w = elemtype_->StaticSize(env); - if ( elem_w >= 0 && - ! attr_until_element_expr_ && - ! attr_until_input_expr_ && - ( length_ || attr_restofdata_ ) ) + if ( elem_w >= 0 && ! attr_until_element_expr_ && ! attr_until_input_expr_ && + (length_ || attr_restofdata_) ) { // If the elements have a fixed size, // we only need to compute the number of elements @@ -715,8 +644,8 @@ void ArrayType::GenDynamicSize(Output *out_cc, Env *env, ASSERT(compute_size_var); GenArrayLength(out_cc, env, data); ASSERT(env->Evaluated(arraylength_var())); - out_cc->println("%s = %d * %s;", - env->LValue(size_var()), elem_w, env->RValue(arraylength_var())); + out_cc->println("%s = %d * %s;", env->LValue(size_var()), elem_w, + env->RValue(arraylength_var())); env->SetEvaluated(size_var()); } else @@ -726,7 +655,7 @@ void ArrayType::GenDynamicSize(Output *out_cc, Env *env, } } -int ArrayType::StaticSize(Env *env) const +int ArrayType::StaticSize(Env* env) const { int num = 0; @@ -737,8 +666,7 @@ int ArrayType::StaticSize(Env *env) const if ( elem_w < 0 ) return -1; - DEBUG_MSG("static size of %s:%s = %d * %d\n", - decl_id()->Name(), lvalue(), elem_w, num); + DEBUG_MSG("static size of %s:%s = %d * %d\n", decl_id()->Name(), lvalue(), elem_w, num); return num * elem_w; } @@ -767,12 +695,11 @@ void ArrayType::DoMarkIncrementalInput() bool ArrayType::RequiresAnalyzerContext() { - return Type::RequiresAnalyzerContext() || - ( length_ && length_->RequiresAnalyzerContext() ) || + return Type::RequiresAnalyzerContext() || (length_ && length_->RequiresAnalyzerContext()) || elemtype_->RequiresAnalyzerContext(); } -bool ArrayType::DoTraverse(DataDepVisitor *visitor) +bool ArrayType::DoTraverse(DataDepVisitor* visitor) { if ( ! Type::DoTraverse(visitor) ) return false; diff --git a/tools/binpac/src/pac_array.h b/tools/binpac/src/pac_array.h index 022ef2ea4a..2433803fab 100644 --- a/tools/binpac/src/pac_array.h +++ b/tools/binpac/src/pac_array.h @@ -7,86 +7,81 @@ // Fixed-length array and variable length sequence with an ending pattern class ArrayType : public Type -{ + { public: - ArrayType(Type *arg_elemtype, Expr *arg_length = 0); + ArrayType(Type* arg_elemtype, Expr* arg_length = 0); ~ArrayType(); bool DefineValueVar() const; string DataTypeStr() const; - string DefaultValue() const { return "0"; } - Type *ElementDataType() const; + string DefaultValue() const { return "0"; } + Type* ElementDataType() const; - string EvalElement(const string &array, const string &index) const; + string EvalElement(const string& array, const string& index) const; - void ProcessAttr(Attr *a); + void ProcessAttr(Attr* a); - void Prepare(Env *env, int flags); + void Prepare(Env* env, int flags); - void GenPubDecls(Output *out, Env *env); - void GenPrivDecls(Output *out, Env *env); + void GenPubDecls(Output* out, Env* env); + void GenPrivDecls(Output* out, Env* env); - void GenInitCode(Output *out, Env *env); - void GenCleanUpCode(Output *out, Env *env); + void GenInitCode(Output* out, Env* env); + void GenCleanUpCode(Output* out, Env* env); - int StaticSize(Env *env) const; + int StaticSize(Env* env) const; void SetBoundaryChecked(); - void GenUntilInputCheck(Output *out_cc, Env *env); + void GenUntilInputCheck(Output* out_cc, Env* env); - bool IsPointerType() const { return true; } + bool IsPointerType() const { return true; } protected: void init(); - void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); - void GenDynamicSize(Output *out, Env *env, const DataPtr& data); - void GenArrayLength(Output *out_cc, Env *env, const DataPtr& data); - string GenArrayInit(Output *out_cc, Env *env, bool known_array_length); - void GenElementAssignment(Output *out_cc, Env *env, - string const &array_str, bool use_vector); - void GenUntilCheck(Output *out_cc, Env *env, - Expr *until_condition, bool delete_elem); + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); + void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + void GenArrayLength(Output* out_cc, Env* env, const DataPtr& data); + string GenArrayInit(Output* out_cc, Env* env, bool known_array_length); + void GenElementAssignment(Output* out_cc, Env* env, string const& array_str, bool use_vector); + void GenUntilCheck(Output* out_cc, Env* env, Expr* until_condition, bool delete_elem); - bool ByteOrderSensitive() const - { - return elemtype_->RequiresByteOrder(); - } + bool ByteOrderSensitive() const { return elemtype_->RequiresByteOrder(); } bool RequiresAnalyzerContext(); - Type *DoClone() const; + Type* DoClone() const; void DoMarkIncrementalInput(); - const ID *arraylength_var() const; - const ID *elem_it_var() const; - const ID *elem_var() const; - const ID *elem_dataptr_var() const; - const ID *elem_input_var() const; + const ID* arraylength_var() const; + const ID* elem_it_var() const; + const ID* elem_var() const; + const ID* elem_dataptr_var() const; + const ID* elem_input_var() const; protected: - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); private: - Type *elemtype_; - Expr *length_; + Type* elemtype_; + Expr* length_; string vector_str_; string datatype_str_; string end_of_array_loop_label_; - Field *arraylength_var_field_; - Field *elem_it_var_field_; - Field *elem_var_field_; - Field *elem_dataptr_var_field_; - Field *elem_input_var_field_; + Field* arraylength_var_field_; + Field* elem_it_var_field_; + Field* elem_var_field_; + Field* elem_dataptr_var_field_; + Field* elem_input_var_field_; // This does not come from &until, but is internally generated - Expr *elem_dataptr_until_expr_; + Expr* elem_dataptr_until_expr_; - Expr *attr_generic_until_expr_; - Expr *attr_until_element_expr_; - Expr *attr_until_input_expr_; -}; + Expr* attr_generic_until_expr_; + Expr* attr_until_element_expr_; + Expr* attr_until_input_expr_; + }; -#endif // pac_array_h +#endif // pac_array_h diff --git a/tools/binpac/src/pac_attr.cc b/tools/binpac/src/pac_attr.cc index 56396c4303..004388eb87 100644 --- a/tools/binpac/src/pac_attr.cc +++ b/tools/binpac/src/pac_attr.cc @@ -1,7 +1,8 @@ #include "pac_attr.h" + #include "pac_expr.h" -bool Attr::DoTraverse(DataDepVisitor *visitor) +bool Attr::DoTraverse(DataDepVisitor* visitor) { if ( expr_ && ! expr_->Traverse(visitor) ) return false; @@ -20,23 +21,20 @@ void Attr::init() delete_expr_ = false; } -Attr::Attr(AttrType type) - : DataDepElement(DataDepElement::ATTR) +Attr::Attr(AttrType type) : DataDepElement(DataDepElement::ATTR) { type_ = type; init(); } -Attr::Attr(AttrType type, Expr *expr) - : DataDepElement(DataDepElement::ATTR) +Attr::Attr(AttrType type, Expr* expr) : DataDepElement(DataDepElement::ATTR) { type_ = type; init(); expr_ = expr; } -Attr::Attr(AttrType type, ExprList *exprlist) - : DataDepElement(DataDepElement::ATTR) +Attr::Attr(AttrType type, ExprList* exprlist) : DataDepElement(DataDepElement::ATTR) { type_ = type; init(); @@ -44,8 +42,7 @@ Attr::Attr(AttrType type, ExprList *exprlist) delete_expr_ = true; } -Attr::Attr(AttrType type, SeqEnd *seqend) - : DataDepElement(DataDepElement::ATTR) +Attr::Attr(AttrType type, SeqEnd* seqend) : DataDepElement(DataDepElement::ATTR) { type_ = type; init(); @@ -58,8 +55,7 @@ Attr::~Attr() delete expr_; } -LetAttr::LetAttr(FieldList *letfields) - : Attr(ATTR_LET) +LetAttr::LetAttr(FieldList* letfields) : Attr(ATTR_LET) { letfields_ = letfields; } diff --git a/tools/binpac/src/pac_attr.h b/tools/binpac/src/pac_attr.h index 87479df77c..ef5dc65ff5 100644 --- a/tools/binpac/src/pac_attr.h +++ b/tools/binpac/src/pac_attr.h @@ -4,62 +4,63 @@ #include "pac_common.h" #include "pac_datadep.h" -enum AttrType { - ATTR_BYTEORDER, - ATTR_CHECK, +enum AttrType + { + ATTR_BYTEORDER, + ATTR_CHECK, ATTR_CHUNKED, ATTR_ENFORCE, ATTR_EXPORTSOURCEDATA, ATTR_IF, - ATTR_LENGTH, + ATTR_LENGTH, ATTR_LET, ATTR_LINEBREAKER, ATTR_MULTILINE, ATTR_ONELINE, ATTR_REFCOUNT, ATTR_REQUIRES, - ATTR_RESTOFDATA, - ATTR_RESTOFFLOW, + ATTR_RESTOFDATA, + ATTR_RESTOFFLOW, ATTR_TRANSIENT, ATTR_UNTIL, -}; + }; class Attr : public Object, public DataDepElement -{ + { public: Attr(AttrType type); - Attr(AttrType type, Expr *expr); - Attr(AttrType type, ExprList *exprlist); - Attr(AttrType type, SeqEnd *seqend); + Attr(AttrType type, Expr* expr); + Attr(AttrType type, ExprList* exprlist); + Attr(AttrType type, SeqEnd* seqend); virtual ~Attr(); - AttrType type() const { return type_; } - Expr *expr() const { return expr_; } - SeqEnd *seqend() const { return seqend_; } + AttrType type() const { return type_; } + Expr* expr() const { return expr_; } + SeqEnd* seqend() const { return seqend_; } bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); protected: void init(); AttrType type_; - Expr *expr_; - SeqEnd *seqend_; + Expr* expr_; + SeqEnd* seqend_; bool delete_expr_; -}; + }; class LetAttr : public Attr -{ + { public: - LetAttr(FieldList *letfields); - FieldList *letfields() const { return letfields_; } + LetAttr(FieldList* letfields); + FieldList* letfields() const { return letfields_; } private: - FieldList *letfields_; -}; + FieldList* letfields_; + }; -#endif // pac_attr_h +#endif // pac_attr_h diff --git a/tools/binpac/src/pac_btype.cc b/tools/binpac/src/pac_btype.cc index c565932d24..ae09bdb42b 100644 --- a/tools/binpac/src/pac_btype.cc +++ b/tools/binpac/src/pac_btype.cc @@ -1,9 +1,10 @@ #include "pac_btype.h" + #include "pac_dataptr.h" #include "pac_id.h" #include "pac_output.h" -Type *BuiltInType::DoClone() const +Type* BuiltInType::DoClone() const { return new BuiltInType(bit_type()); } @@ -11,20 +12,19 @@ Type *BuiltInType::DoClone() const bool BuiltInType::IsNumericType() const { BITType t = bit_type(); - return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || - t == UINT8 || t == UINT16 || t == UINT32 || t == UINT64); + return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || t == UINT8 || t == UINT16 || + t == UINT32 || t == UINT64); } -bool BuiltInType::CompatibleBuiltInTypes(BuiltInType *type1, - BuiltInType *type2) +bool BuiltInType::CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2) { return type1->IsNumericType() && type2->IsNumericType(); } static const char* basic_pactype_name[] = { -# define TYPE_DEF(name, pactype, ctype, size) pactype, -# include "pac_type.def" -# undef TYPE_DEF +#define TYPE_DEF(name, pactype, ctype, size) pactype, +#include "pac_type.def" +#undef TYPE_DEF 0, }; @@ -32,9 +32,7 @@ void BuiltInType::static_init() { for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type ) { - Type::AddPredefinedType( - basic_pactype_name[bit_type], - new BuiltInType((BITType) bit_type)); + Type::AddPredefinedType(basic_pactype_name[bit_type], new BuiltInType((BITType)bit_type)); } } @@ -48,9 +46,9 @@ int BuiltInType::LookUpByName(const char* name) } static const char* basic_ctype_name[] = { -# define TYPE_DEF(name, pactype, ctype, size) ctype, -# include "pac_type.def" -# undef TYPE_DEF +#define TYPE_DEF(name, pactype, ctype, size) ctype, +#include "pac_type.def" +#undef TYPE_DEF 0, }; @@ -66,12 +64,11 @@ string BuiltInType::DataTypeStr() const int BuiltInType::StaticSize(Env* /* env */) const { - static const size_t basic_type_size[] = - { -# define TYPE_DEF(name, pactype, ctype, size) size, -# include "pac_type.def" -# undef TYPE_DEF - }; + static const size_t basic_type_size[] = { +#define TYPE_DEF(name, pactype, ctype, size) size, +#include "pac_type.def" +#undef TYPE_DEF + }; return basic_type_size[bit_type_]; } @@ -96,8 +93,7 @@ void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) ASSERT(0); } -void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, - const DataPtr& data, int flags) +void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { if ( bit_type_ == EMPTY ) return; @@ -110,7 +106,7 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, if ( anonymous_value_var() ) return; - switch ( bit_type_ ) + switch ( bit_type_ ) { case EMPTY: // do nothing @@ -118,8 +114,8 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, case INT8: case UINT8: - out_cc->println("%s = *((%s const *) (%s));", - lvalue(), DataTypeStr().c_str(), data.ptr_expr()); + out_cc->println("%s = *((%s const *) (%s));", lvalue(), DataTypeStr().c_str(), + data.ptr_expr()); break; case INT16: case UINT16: @@ -134,13 +130,10 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, data.ptr_expr(), EvalByteOrder(out_cc, env).c_str()); #else - out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", - lvalue(), - EvalByteOrder(out_cc, env).c_str(), - DataTypeStr().c_str(), - data.ptr_expr()); + out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", lvalue(), + EvalByteOrder(out_cc, env).c_str(), DataTypeStr().c_str(), + data.ptr_expr()); #endif break; } } - diff --git a/tools/binpac/src/pac_btype.h b/tools/binpac/src/pac_btype.h index 4bdbf9390b..f168b832e2 100644 --- a/tools/binpac/src/pac_btype.h +++ b/tools/binpac/src/pac_btype.h @@ -4,49 +4,50 @@ #include "pac_type.h" class BuiltInType : public Type -{ + { public: - enum BITType { -# define TYPE_DEF(name, pactype, ctype, size) name, -# include "pac_type.def" -# undef TYPE_DEF - }; + enum BITType + { +#define TYPE_DEF(name, pactype, ctype, size) name, +#include "pac_type.def" +#undef TYPE_DEF + }; - static int LookUpByName(const char *name); + static int LookUpByName(const char* name); BuiltInType(BITType bit_type) - : Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN), - bit_type_(bit_type) {} + : Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN), bit_type_(bit_type) + { + } - BITType bit_type() const { return bit_type_; } + BITType bit_type() const { return bit_type_; } bool IsNumericType() const; bool DefineValueVar() const; string DataTypeStr() const; - string DefaultValue() const { return "0"; } + string DefaultValue() const { return "0"; } - int StaticSize(Env *env) const; + int StaticSize(Env* env) const; - bool IsPointerType() const { return false; } + bool IsPointerType() const { return false; } bool ByteOrderSensitive() const { return StaticSize(0) >= 2; } - void GenInitCode(Output *out_cc, Env *env); + void GenInitCode(Output* out_cc, Env* env); void DoMarkIncrementalInput(); protected: - void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); - void GenDynamicSize(Output *out, Env *env, const DataPtr& data); - Type *DoClone() const; + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); + void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + Type* DoClone() const; BITType bit_type_; public: static void static_init(); - static bool CompatibleBuiltInTypes(BuiltInType *type1, - BuiltInType *type2); -}; + static bool CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2); + }; -#endif // pac_btype_h +#endif // pac_btype_h diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index a2d326113c..2d326bf597 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -1,3 +1,9 @@ +#include "pac_case.h" + +#include +#include + +#include "pac_btype.h" #include "pac_exception.h" #include "pac_expr.h" #include "pac_exttype.h" @@ -5,18 +11,12 @@ #include "pac_output.h" #include "pac_typedecl.h" #include "pac_utils.h" -#include "pac_btype.h" - -#include "pac_case.h" - -#include -#include CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) : Type(CASE), index_expr_(index_expr), cases_(cases) { index_var_ = 0; - foreach(i, CaseFieldList, cases_) + foreach (i, CaseFieldList, cases_) AddField(*i); } @@ -27,10 +27,10 @@ CaseType::~CaseType() delete cases_; } -void CaseType::AddCaseField(CaseField *f) +void CaseType::AddCaseField(CaseField* f) { // All fields must be added before Prepare() - ASSERT(!env()); + ASSERT(! env()); AddField(f); cases_->push_back(f); @@ -47,11 +47,11 @@ string CaseType::DataTypeStr() const return strfmt("%s *", type_decl()->class_name().c_str()); } -Type *CaseType::ValueType() const +Type* CaseType::ValueType() const { foreach (i, CaseFieldList, cases_) { - CaseField *c = *i; + CaseField* c = *i; return c->type(); } ASSERT(0); @@ -73,13 +73,12 @@ void CaseType::Prepare(Env* env, int flags) env->AddID(index_var_, MEMBER_VAR, 0); // Sort the cases_ to put the default case at the end of the list - CaseFieldList::iterator default_case_it = - cases_->end(); // to avoid warning - CaseField *default_case = 0; + CaseFieldList::iterator default_case_it = cases_->end(); // to avoid warning + CaseField* default_case = 0; foreach (i, CaseFieldList, cases_) { - CaseField *c = *i; + CaseField* c = *i; if ( ! c->index() ) { if ( default_case ) @@ -96,7 +95,7 @@ void CaseType::Prepare(Env* env, int flags) foreach (i, CaseFieldList, cases_) { - CaseField *c = *i; + CaseField* c = *i; c->set_index_var(index_var_); c->set_case_type(this); } @@ -124,8 +123,8 @@ void CaseType::GenPubDecls(Output* out_h, Env* env) if ( t->tot() != Type::BUILTIN ) t = extern_type_int; - out_h->println("%s %s const { return %s; }", t->DataTypeStr().c_str(), - env->RValue(index_var_), env->LValue(index_var_)); + out_h->println("%s %s const { return %s; }", t->DataTypeStr().c_str(), env->RValue(index_var_), + env->LValue(index_var_)); Type::GenPubDecls(out_h, env); } @@ -145,7 +144,7 @@ void CaseType::GenCleanUpCode(Output* out_cc, Env* env) out_cc->println("{"); foreach (i, CaseFieldList, cases_) { - CaseField *c = *i; + CaseField* c = *i; c->GenCleanUpCode(out_cc, env); } out_cc->println("}"); @@ -153,8 +152,7 @@ void CaseType::GenCleanUpCode(Output* out_cc, Env* env) env->set_in_branch(false); } -void CaseType::DoGenParseCode(Output* out_cc, Env* env, - const DataPtr& data, int flags) +void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { if ( StaticSize(env) >= 0 ) GenBoundaryCheck(out_cc, env, data); @@ -164,8 +162,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, if ( ! incremental_input() ) compute_size_var = AddSizeVar(out_cc, env); - out_cc->println("%s = %s;", - env->LValue(index_var_), index_expr_->EvalExpr(out_cc, env)); + out_cc->println("%s = %s;", env->LValue(index_var_), index_expr_->EvalExpr(out_cc, env)); env->SetEvaluated(index_var_); env->set_in_branch(true); @@ -175,9 +172,8 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, bool has_default_case = false; foreach (i, CaseFieldList, cases_) { - CaseField *c = *i; - c->GenParseCode(out_cc, env, data, - compute_size_var ? size_var() : 0); + CaseField* c = *i; + c->GenParseCode(out_cc, env, data, compute_size_var ? size_var() : 0); if ( c->IsDefaultCase() ) has_default_case = true; } @@ -187,7 +183,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, out_cc->println("default:"); out_cc->inc_indent(); out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", - decl_id()->Name(), env->RValue(index_var_)); + decl_id()->Name(), env->RValue(index_var_)); out_cc->println("break;"); out_cc->dec_indent(); } @@ -199,8 +195,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, env->SetEvaluated(size_var()); } -void CaseType::GenDynamicSize(Output* out_cc, Env* env, - const DataPtr& data) +void CaseType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { GenParseCode(out_cc, env, data, 0); } @@ -210,9 +205,9 @@ int CaseType::StaticSize(Env* env) const int static_w = -1; foreach (i, CaseFieldList, cases_) { - CaseField *c = *i; + CaseField* c = *i; int w = c->StaticSize(env); - if ( w < 0 || ( static_w >= 0 && w != static_w ) ) + if ( w < 0 || (static_w >= 0 && w != static_w) ) return -1; static_w = w; } @@ -224,7 +219,7 @@ void CaseType::SetBoundaryChecked() Type::SetBoundaryChecked(); foreach (i, CaseFieldList, cases_) { - CaseField *c = *i; + CaseField* c = *i; c->SetBoundaryChecked(); } } @@ -233,7 +228,7 @@ void CaseType::DoMarkIncrementalInput() { foreach (i, CaseFieldList, cases_) { - CaseField *c = *i; + CaseField* c = *i; c->type()->MarkIncrementalInput(); } } @@ -242,7 +237,7 @@ bool CaseType::ByteOrderSensitive() const { foreach (i, CaseFieldList, cases_) { - CaseField *c = *i; + CaseField* c = *i; if ( c->RequiresByteOrder() ) return true; } @@ -250,10 +245,7 @@ bool CaseType::ByteOrderSensitive() const } CaseField::CaseField(ExprList* index, ID* id, Type* type) - : Field(CASE_FIELD, - TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, - id, type), - index_(index) + : Field(CASE_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), index_(index) { ASSERT(type_); type_->set_value_var(id, MEMBER_VAR); @@ -266,13 +258,13 @@ CaseField::~CaseField() delete_list(ExprList, index_); } -void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env, Type* switch_type) +void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_type) { if ( index_list ) { - foreach(i, ExprList, index_list) + foreach (i, ExprList, index_list) { - Expr *index_expr = *i; + Expr* index_expr = *i; Type* case_type = index_expr->DataType(env); @@ -338,8 +330,7 @@ void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env, Type* switch_typ // We're always using "int" for storage, so ok to just // cast into the type used by the switch statement since // some unsafe stuff is already checked above. - out_cc->println("case ((%s) %d):", - switch_type->DataTypeStr().c_str(), index_const); + out_cc->println("case ((%s) %d):", switch_type->DataTypeStr().c_str(), index_const); } } else @@ -363,8 +354,7 @@ void CaseField::GenPubDecls(Output* out_h, Env* env) if ( type_->DataTypeStr().empty() ) return; - out_h->println("%s %s const", - type_->DataTypeConstRefStr().c_str(), env->RValue(id_)); + out_h->println("%s %s const", type_->DataTypeConstRefStr().c_str(), env->RValue(id_)); out_h->inc_indent(); out_h->println("{"); @@ -383,11 +373,8 @@ void CaseField::GenPubDecls(Output* out_h, Env* env) out_h->println("default:"); out_h->inc_indent(); - out_h->println( - "throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");", - id_->LocName(), - env->RValue(index_var_), - OrigExprList(index_).c_str()); + out_h->println("throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");", + id_->LocName(), env->RValue(index_var_), OrigExprList(index_).c_str()); out_h->println("break;"); out_h->dec_indent(); @@ -426,47 +413,42 @@ void CaseField::GenCleanUpCode(Output* out_cc, Env* env) out_cc->dec_indent(); } -void CaseField::GenParseCode(Output* out_cc, Env* env, - const DataPtr& data, const ID* size_var) +void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, const ID* size_var) { GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); out_cc->inc_indent(); out_cc->println("// Parse \"%s\"", id_->Name()); out_cc->println("{"); - - { - Env case_env(env, this); - type_->GenPreParsing(out_cc, &case_env); - type_->GenParseCode(out_cc, &case_env, data, 0); - if ( size_var ) { - out_cc->println("%s = %s;", - case_env.LValue(size_var), - type_->DataSize(out_cc, &case_env, data).c_str()); + Env case_env(env, this); + + type_->GenPreParsing(out_cc, &case_env); + type_->GenParseCode(out_cc, &case_env, data, 0); + if ( size_var ) + { + out_cc->println("%s = %s;", case_env.LValue(size_var), + type_->DataSize(out_cc, &case_env, data).c_str()); + } + if ( type_->incremental_input() ) + { + ASSERT(case_type()->parsing_complete_var()); + out_cc->println("%s = %s;", case_env.LValue(case_type()->parsing_complete_var()), + case_env.RValue(type_->parsing_complete_var())); + } + out_cc->println("}"); } - if ( type_->incremental_input() ) - { - ASSERT(case_type()->parsing_complete_var()); - out_cc->println("%s = %s;", - case_env.LValue(case_type()->parsing_complete_var()), - case_env.RValue(type_->parsing_complete_var())); - } - out_cc->println("}"); - } out_cc->println("break;"); out_cc->dec_indent(); } -bool CaseField::DoTraverse(DataDepVisitor *visitor) - { - return Field::DoTraverse(visitor) && - type()->Traverse(visitor); +bool CaseField::DoTraverse(DataDepVisitor* visitor) + { + return Field::DoTraverse(visitor) && type()->Traverse(visitor); } -bool CaseField::RequiresAnalyzerContext() const - { - return Field::RequiresAnalyzerContext() || - type()->RequiresAnalyzerContext(); +bool CaseField::RequiresAnalyzerContext() const + { + return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext(); } diff --git a/tools/binpac/src/pac_case.h b/tools/binpac/src/pac_case.h index 7e7bb482ce..560dd8e35f 100644 --- a/tools/binpac/src/pac_case.h +++ b/tools/binpac/src/pac_case.h @@ -7,95 +7,94 @@ #include "pac_type.h" class CaseType : public Type -{ + { public: - CaseType(Expr *index, CaseFieldList *cases); + CaseType(Expr* index, CaseFieldList* cases); ~CaseType(); - void AddCaseField(CaseField *f); + void AddCaseField(CaseField* f); bool DefineValueVar() const; string DataTypeStr() const; string DefaultValue() const; - void Prepare(Env *env, int flags); + void Prepare(Env* env, int flags); - void GenPubDecls(Output *out, Env *env); - void GenPrivDecls(Output *out, Env *env); + void GenPubDecls(Output* out, Env* env); + void GenPrivDecls(Output* out, Env* env); - void GenInitCode(Output *out, Env *env); - void GenCleanUpCode(Output *out, Env *env); + void GenInitCode(Output* out, Env* env); + void GenCleanUpCode(Output* out, Env* env); - int StaticSize(Env *env) const; + int StaticSize(Env* env) const; void SetBoundaryChecked(); - Type *ValueType() const; + Type* ValueType() const; Expr* IndexExpr() const { return index_expr_; } - bool IsPointerType() const { return ValueType()->IsPointerType(); } + bool IsPointerType() const { return ValueType()->IsPointerType(); } protected: - void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); - void GenDynamicSize(Output *out, Env *env, const DataPtr& data); - Type *DoClone() const { return 0; } + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); + void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + Type* DoClone() const { return 0; } void DoMarkIncrementalInput(); bool ByteOrderSensitive() const; - Expr *index_expr_; - ID *index_var_; - CaseFieldList *cases_; + Expr* index_expr_; + ID* index_var_; + CaseFieldList* cases_; typedef map member_map_t; member_map_t member_map_; -}; + }; class CaseField : public Field -{ + { public: - CaseField(ExprList *index, ID *id, Type *type); + CaseField(ExprList* index, ID* id, Type* type); ~CaseField(); - CaseType *case_type() const { return case_type_; } - void set_case_type(CaseType *t) { case_type_ = t; } + CaseType* case_type() const { return case_type_; } + void set_case_type(CaseType* t) { case_type_ = t; } - ExprList *index() const { return index_; } + ExprList* index() const { return index_; } - const char *lvalue() const { return type_->lvalue(); } + const char* lvalue() const { return type_->lvalue(); } - const char *CaseStr(Env *env); - void set_index_var(const ID *var) { index_var_ = var; } - - void Prepare(Env *env); + const char* CaseStr(Env* env); + void set_index_var(const ID* var) { index_var_ = var; } - void GenPubDecls(Output *out, Env *env); + void Prepare(Env* env); - void GenInitCode(Output *out, Env *env); - void GenCleanUpCode(Output *out, Env *env); - void GenParseCode(Output *out, Env *env, - const DataPtr& data, const ID *size_var); + void GenPubDecls(Output* out, Env* env); - int StaticSize(Env *env) const { return type_->StaticSize(env); } + void GenInitCode(Output* out, Env* env); + void GenCleanUpCode(Output* out, Env* env); + void GenParseCode(Output* out, Env* env, const DataPtr& data, const ID* size_var); - bool IsDefaultCase() const { return ! index_; } - void SetBoundaryChecked() { type_->SetBoundaryChecked(); } + int StaticSize(Env* env) const { return type_->StaticSize(env); } - bool RequiresByteOrder() const { return type_->RequiresByteOrder(); } + bool IsDefaultCase() const { return ! index_; } + void SetBoundaryChecked() { type_->SetBoundaryChecked(); } + + bool RequiresByteOrder() const { return type_->RequiresByteOrder(); } bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); protected: - CaseType *case_type_; - ExprList *index_; - const ID *index_var_; -}; + CaseType* case_type_; + ExprList* index_; + const ID* index_var_; + }; // Generate a list of "case X:" lines from index_list. Each index // expression must be constant foldable. -void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env, Type* switch_type); +void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_type); -#endif // pac_case_h +#endif // pac_case_h diff --git a/tools/binpac/src/pac_cclass.h b/tools/binpac/src/pac_cclass.h index 87a7595996..daf88236dd 100644 --- a/tools/binpac/src/pac_cclass.h +++ b/tools/binpac/src/pac_cclass.h @@ -7,75 +7,75 @@ class CClassMethod; class CType; class CVariable; -typedef vector CClassMemberList; -typedef vector CClassMethodList; -typedef vector CVariableList; +typedef vector CClassMemberList; +typedef vector CClassMethodList; +typedef vector CVariableList; #include "pac_common.h" // Represents a C++ class. -// +// // For now we adopt a simple model: -// +// // 1. All members have a protected member variable "name_" and a // public constant access method "name()". -// +// // 2. All methods are public. // // 3. We do not check repeated names. class CClass -{ + { public: - CClass(const string &class_name); + CClass(const string& class_name); - void AddMember(CClassMember *member); - void AddMethod(CClassMember *method); + void AddMember(CClassMember* member); + void AddMethod(CClassMember* method); - void GenForwardDeclaration(Output *out_h); - void GenCode(Output *out_h, Output *out_cc); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); protected: string class_name_; - CClassMemberList *members_; - CClassMethodList *methods_; -}; + CClassMemberList* members_; + CClassMethodList* methods_; + }; class CVariable -{ + { public: - CClassMember(const string &name, CType *type); + CClassMember(const string& name, CType* type); string name() const { return name_; } - CType *type() const { return type_; } + CType* type() const { return type_; } protected: string name_; - CType *type_; -}; + CType* type_; + }; class CClassMember -{ + { public: - CClassMember(CVariable *var); - void GenCode(Output *out_h, Output *out_cc); + CClassMember(CVariable* var); + void GenCode(Output* out_h, Output* out_cc); string decl() const; protected: - CVariable *var_; -}; + CVariable* var_; + }; class CClassMethod -{ + { public: - CClassMethod(CVariable *var, CVariableList *params); + CClassMethod(CVariable* var, CVariableList* params); string decl() const; protected: - CVariable *var_; - CVariableList *params_; -}; + CVariable* var_; + CVariableList* params_; + }; -#endif // pac_cclass_h +#endif // pac_cclass_h diff --git a/tools/binpac/src/pac_common.h b/tools/binpac/src/pac_common.h index 079e14ac1f..90c1d3b4ab 100644 --- a/tools/binpac/src/pac_common.h +++ b/tools/binpac/src/pac_common.h @@ -1,13 +1,12 @@ #ifndef pac_common_h #define pac_common_h -#include "pac_utils.h" - +#include +#include +#include #include -#include -#include -#include +#include "pac_utils.h" using namespace std; @@ -22,7 +21,7 @@ extern int line_number; // etc. class Object -{ + { public: Object() { @@ -31,17 +30,15 @@ public: location = strfmt("%s:%d", filename.c_str(), line_number); } - ~Object() - { - } + ~Object() { } - const char* Location() const { return location.c_str(); } + const char* Location() const { return location.c_str(); } protected: string filename; int line_num; string location; -}; + }; class ActionParam; class ActionParamType; @@ -89,47 +86,47 @@ class WithInputField; // The ID of the current declaration. extern const ID* current_decl_id; -typedef vector ActionParamList; -typedef vector AnalyzerActionList; -typedef vector AnalyzerElementList; -typedef vector AttrList; -typedef vector CaseExprList; -typedef vector CaseFieldList; -typedef vector ContextFieldList; -typedef vector DeclList; -typedef vector EnumList; -typedef vector ExprList; -typedef vector FieldList; -typedef vector LetFieldList; -typedef vector NumList; -typedef vector ParamList; -typedef vector RecordFieldList; -typedef vector StateVarList; +typedef vector ActionParamList; +typedef vector AnalyzerActionList; +typedef vector AnalyzerElementList; +typedef vector AttrList; +typedef vector CaseExprList; +typedef vector CaseFieldList; +typedef vector ContextFieldList; +typedef vector DeclList; +typedef vector EnumList; +typedef vector ExprList; +typedef vector FieldList; +typedef vector LetFieldList; +typedef vector NumList; +typedef vector ParamList; +typedef vector RecordFieldList; +typedef vector StateVarList; -#define foreach(i, ct, pc) \ - if ( pc ) \ +#define foreach(i, ct, pc) \ + if ( pc ) \ for ( ct::iterator i = (pc)->begin(); i != (pc)->end(); ++i ) -#define delete_list(ct, pc) \ - { \ - foreach(delete_list_i, ct, pc) \ - delete *delete_list_i; \ - delete pc; \ - pc = 0; \ - } +#define delete_list(ct, pc) \ + { \ + foreach (delete_list_i, ct, pc) \ + delete *delete_list_i; \ + delete pc; \ + pc = 0; \ + } // Constants -const char * const kComputeFrameLength = "compute_frame_length"; -const char * const kFlowBufferClass = "FlowBuffer"; -const char * const kFlowBufferVar = "flow_buffer"; -const char * const kFlowEOF = "FlowEOF"; -const char * const kFlowGap = "NewGap"; -const char * const kInitialBufferLengthFunc = "initial_buffer_length"; -const char * const kNeedMoreData = "need_more_data"; -const char * const kNewData = "NewData"; -const char * const kParseFuncWithBuffer = "ParseBuffer"; -const char * const kParseFuncWithoutBuffer = "Parse"; -const char * const kRefCountClass = "binpac::RefCount"; -const char * const kTypeWithLengthClass = "binpac::TypeWithLength"; +const char* const kComputeFrameLength = "compute_frame_length"; +const char* const kFlowBufferClass = "FlowBuffer"; +const char* const kFlowBufferVar = "flow_buffer"; +const char* const kFlowEOF = "FlowEOF"; +const char* const kFlowGap = "NewGap"; +const char* const kInitialBufferLengthFunc = "initial_buffer_length"; +const char* const kNeedMoreData = "need_more_data"; +const char* const kNewData = "NewData"; +const char* const kParseFuncWithBuffer = "ParseBuffer"; +const char* const kParseFuncWithoutBuffer = "Parse"; +const char* const kRefCountClass = "binpac::RefCount"; +const char* const kTypeWithLengthClass = "binpac::TypeWithLength"; -#endif // pac_common_h +#endif // pac_common_h diff --git a/tools/binpac/src/pac_conn.cc b/tools/binpac/src/pac_conn.cc index e30608f5c1..409ae1e43a 100644 --- a/tools/binpac/src/pac_conn.cc +++ b/tools/binpac/src/pac_conn.cc @@ -1,3 +1,5 @@ +#include "pac_conn.h" + #include "pac_analyzer.h" #include "pac_dataunit.h" #include "pac_embedded.h" @@ -8,11 +10,7 @@ #include "pac_paramtype.h" #include "pac_type.h" -#include "pac_conn.h" - -ConnDecl::ConnDecl(ID *conn_id, - ParamList *params, - AnalyzerElementList *elemlist) +ConnDecl::ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist) : AnalyzerDecl(conn_id, CONN, params) { flows_[0] = flows_[1] = 0; @@ -27,12 +25,12 @@ ConnDecl::~ConnDecl() delete data_type_; } -void ConnDecl::AddBaseClass(vector *base_classes) const +void ConnDecl::AddBaseClass(vector* base_classes) const { - base_classes->push_back("binpac::ConnectionAnalyzer"); - } + base_classes->push_back("binpac::ConnectionAnalyzer"); + } -void ConnDecl::ProcessFlowElement(AnalyzerFlow *flow_elem) +void ConnDecl::ProcessFlowElement(AnalyzerFlow* flow_elem) { int flow_index; @@ -44,19 +42,16 @@ void ConnDecl::ProcessFlowElement(AnalyzerFlow *flow_elem) if ( flows_[flow_index] ) { throw Exception(flow_elem, - strfmt("%sflow already defined", - flow_index == 0 ? "up" : "down")); + strfmt("%sflow already defined", flow_index == 0 ? "up" : "down")); } flows_[flow_index] = flow_elem; type_->AddField(flow_elem->flow_field()); } -void ConnDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) +void ConnDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) { - throw Exception( - dataunit_elem, - "dataunit should be defined in only a flow declaration"); + throw Exception(dataunit_elem, "dataunit should be defined in only a flow declaration"); } void ConnDecl::Prepare() @@ -67,17 +62,17 @@ void ConnDecl::Prepare() flows_[1]->flow_decl()->set_conn_decl(this); } -void ConnDecl::GenPubDecls(Output *out_h, Output *out_cc) +void ConnDecl::GenPubDecls(Output* out_h, Output* out_cc) { AnalyzerDecl::GenPubDecls(out_h, out_cc); } -void ConnDecl::GenPrivDecls(Output *out_h, Output *out_cc) +void ConnDecl::GenPrivDecls(Output* out_h, Output* out_cc) { AnalyzerDecl::GenPrivDecls(out_h, out_cc); } -void ConnDecl::GenEOFFunc(Output *out_h, Output *out_cc) +void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc) { string proto = strfmt("%s(bool is_orig)", kFlowEOF); @@ -89,29 +84,25 @@ void ConnDecl::GenEOFFunc(Output *out_h, Output *out_cc) out_cc->println("if ( is_orig )"); out_cc->inc_indent(); - out_cc->println("%s->%s();", - env_->LValue(upflow_id), - kFlowEOF); + out_cc->println("%s->%s();", env_->LValue(upflow_id), kFlowEOF); out_cc->dec_indent(); out_cc->println("else"); out_cc->inc_indent(); - out_cc->println("%s->%s();", - env_->LValue(downflow_id), - kFlowEOF); + out_cc->println("%s->%s();", env_->LValue(downflow_id), kFlowEOF); - foreach(i, AnalyzerHelperList, eof_helpers_) + foreach (i, AnalyzerHelperList, eof_helpers_) { (*i)->GenCode(0, out_cc, this); } out_cc->dec_indent(); - + out_cc->println("}"); out_cc->dec_indent(); out_cc->println(""); } -void ConnDecl::GenGapFunc(Output *out_h, Output *out_cc) +void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc) { string proto = strfmt("%s(bool is_orig, int gap_length)", kFlowGap); @@ -123,27 +114,21 @@ void ConnDecl::GenGapFunc(Output *out_h, Output *out_cc) out_cc->println("if ( is_orig )"); out_cc->inc_indent(); - out_cc->println("%s->%s(gap_length);", - env_->LValue(upflow_id), - kFlowGap); + out_cc->println("%s->%s(gap_length);", env_->LValue(upflow_id), kFlowGap); out_cc->dec_indent(); out_cc->println("else"); out_cc->inc_indent(); - out_cc->println("%s->%s(gap_length);", - env_->LValue(downflow_id), - kFlowGap); + out_cc->println("%s->%s(gap_length);", env_->LValue(downflow_id), kFlowGap); out_cc->dec_indent(); - + out_cc->println("}"); out_cc->dec_indent(); out_cc->println(""); } -void ConnDecl::GenProcessFunc(Output *out_h, Output *out_cc) +void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc) { - string proto = - strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)", - kNewData); + string proto = strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)", kNewData); out_h->println("void %s;", proto.c_str()); @@ -153,17 +138,13 @@ void ConnDecl::GenProcessFunc(Output *out_h, Output *out_cc) out_cc->println("if ( is_orig )"); out_cc->inc_indent(); - out_cc->println("%s->%s(begin, end);", - env_->LValue(upflow_id), - kNewData); + out_cc->println("%s->%s(begin, end);", env_->LValue(upflow_id), kNewData); out_cc->dec_indent(); out_cc->println("else"); out_cc->inc_indent(); - out_cc->println("%s->%s(begin, end);", - env_->LValue(downflow_id), - kNewData); + out_cc->println("%s->%s(begin, end);", env_->LValue(downflow_id), kNewData); out_cc->dec_indent(); - + out_cc->println("}"); out_cc->dec_indent(); out_cc->println(""); diff --git a/tools/binpac/src/pac_conn.h b/tools/binpac/src/pac_conn.h index 0247bf7f7b..5c62b6b64d 100644 --- a/tools/binpac/src/pac_conn.h +++ b/tools/binpac/src/pac_conn.h @@ -1,34 +1,34 @@ #ifndef pac_conn_h #define pac_conn_h -#include "pac_decl.h" #include "pac_analyzer.h" +#include "pac_decl.h" class ConnDecl : public AnalyzerDecl -{ + { public: - ConnDecl(ID *conn_id, ParamList *params, AnalyzerElementList *elemlist); + ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist); ~ConnDecl(); void Prepare(); - Type* DataType() const { return data_type_; } + Type* DataType() const { return data_type_; } protected: - void AddBaseClass(vector *base_classes) const; + void AddBaseClass(vector* base_classes) const; - void GenProcessFunc(Output *out_h, Output *out_cc); - void GenGapFunc(Output *out_h, Output *out_cc); - void GenEOFFunc(Output *out_h, Output *out_cc); + void GenProcessFunc(Output* out_h, Output* out_cc); + void GenGapFunc(Output* out_h, Output* out_cc); + void GenEOFFunc(Output* out_h, Output* out_cc); - void GenPubDecls(Output *out_h, Output *out_cc); - void GenPrivDecls(Output *out_h, Output *out_cc); + void GenPubDecls(Output* out_h, Output* out_cc); + void GenPrivDecls(Output* out_h, Output* out_cc); - void ProcessFlowElement(AnalyzerFlow *flow_elem); - void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem); + void ProcessFlowElement(AnalyzerFlow* flow_elem); + void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem); - AnalyzerFlow *flows_[2]; - Type *data_type_; -}; + AnalyzerFlow* flows_[2]; + Type* data_type_; + }; -#endif // pac_conn_h +#endif // pac_conn_h diff --git a/tools/binpac/src/pac_context.cc b/tools/binpac/src/pac_context.cc index 8f9271beb2..6d7c12b6df 100644 --- a/tools/binpac/src/pac_context.cc +++ b/tools/binpac/src/pac_context.cc @@ -1,3 +1,5 @@ +#include "pac_context.h" + #include "pac_analyzer.h" #include "pac_exception.h" #include "pac_exttype.h" @@ -9,47 +11,38 @@ #include "pac_type.h" #include "pac_utils.h" -#include "pac_context.h" - -ContextField::ContextField(ID *id, Type *type) - : Field(CONTEXT_FIELD, - TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, - id, type) +ContextField::ContextField(ID* id, Type* type) + : Field(CONTEXT_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) { } -AnalyzerContextDecl *AnalyzerContextDecl::current_analyzer_context_ = 0; +AnalyzerContextDecl* AnalyzerContextDecl::current_analyzer_context_ = 0; -namespace { - ParamList *ContextFieldsToParams(ContextFieldList *context_fields) +namespace + { +ParamList* ContextFieldsToParams(ContextFieldList* context_fields) + { + // Convert context fields to parameters + ParamList* params = new ParamList(); + foreach (i, ContextFieldList, context_fields) { - // Convert context fields to parameters - ParamList *params = new ParamList(); - foreach(i, ContextFieldList, context_fields) - { - ContextField *f = *i; - params->push_back( - new Param(f->id()->clone(), - f->type())); - } - return params; + ContextField* f = *i; + params->push_back(new Param(f->id()->clone(), f->type())); } -} // namespace private + return params; + } + } // namespace private -AnalyzerContextDecl::AnalyzerContextDecl( - ID *id, - ContextFieldList *context_fields) - : TypeDecl(new ID(strfmt("Context%s", id->Name())), - ContextFieldsToParams(context_fields), - new DummyType()) +AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_fields) + : TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields), + new DummyType()) { context_name_id_ = id; if ( current_analyzer_context_ != 0 ) { - throw Exception(this, - strfmt("multiple declaration of analyzer context; " - "the previous one is `%s'", - current_analyzer_context_->id()->Name())); + throw Exception(this, strfmt("multiple declaration of analyzer context; " + "the previous one is `%s'", + current_analyzer_context_->id()->Name())); } else current_analyzer_context_ = this; @@ -70,25 +63,25 @@ AnalyzerContextDecl::~AnalyzerContextDecl() delete_list(ContextFieldList, context_fields_); } -void AnalyzerContextDecl::GenForwardDeclaration(Output *out_h) +void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h) { GenNamespaceBegin(out_h); TypeDecl::GenForwardDeclaration(out_h); } -void AnalyzerContextDecl::GenCode(Output *out_h, Output *out_cc) +void AnalyzerContextDecl::GenCode(Output* out_h, Output* out_cc) { GenNamespaceBegin(out_h); GenNamespaceBegin(out_cc); TypeDecl::GenCode(out_h, out_cc); } -void AnalyzerContextDecl::GenNamespaceBegin(Output *out) const +void AnalyzerContextDecl::GenNamespaceBegin(Output* out) const { out->println("namespace %s {", context_name_id()->Name()); } -void AnalyzerContextDecl::GenNamespaceEnd(Output *out) const +void AnalyzerContextDecl::GenNamespaceEnd(Output* out) const { out->println("} // namespace %s", context_name_id()->Name()); } @@ -98,23 +91,19 @@ void AnalyzerContextDecl::AddFlowBuffer() if ( flow_buffer_added_ ) return; - AddParam(new Param( - new ID(kFlowBufferVar), - FlowDecl::flow_buffer_type()->Clone())); + AddParam(new Param(new ID(kFlowBufferVar), FlowDecl::flow_buffer_type()->Clone())); flow_buffer_added_ = true; } -string AnalyzerContextDecl::mb_buffer(Env *env) +string AnalyzerContextDecl::mb_buffer(Env* env) { // A hack. The orthodox way would be to build an Expr of // context.flow_buffer_var, and then EvalExpr. - return strfmt("%s->%s()", - env->RValue(analyzer_context_id), - kFlowBufferVar); + return strfmt("%s->%s()", env->RValue(analyzer_context_id), kFlowBufferVar); } -Type *DummyType::DoClone() const +Type* DummyType::DoClone() const { // Fields will be copied in Type::Clone(). return new DummyType(); diff --git a/tools/binpac/src/pac_context.h b/tools/binpac/src/pac_context.h index 29704e0b8d..42ea969544 100644 --- a/tools/binpac/src/pac_context.h +++ b/tools/binpac/src/pac_context.h @@ -9,89 +9,95 @@ // AnalyzerContext represents a cookie that an analyzer gives to // parse functions of various message types. The cookie is parsed // to every parse function (if necessary) as parameter 'binpac_context'. -// +// // The members of the cookie is declared through 'analyzer' declarations, // such as in: // // analyzer SunRPC withcontext { // connection: RPC_Conn; // flow: RPC_Flow; -// }; +// }; // -// The cookie usually contains the connection and flow in which -// the message appears, and the context information can be -// accessed as members of the cookie, such as +// The cookie usually contains the connection and flow in which +// the message appears, and the context information can be +// accessed as members of the cookie, such as // ``binpac_context.connection''. class ContextField : public Field -{ + { public: - ContextField(ID *id, Type *type); -}; + ContextField(ID* id, Type* type); + }; class AnalyzerContextDecl : public TypeDecl -{ + { public: - AnalyzerContextDecl(ID *id, ContextFieldList *context_fields); + AnalyzerContextDecl(ID* id, ContextFieldList* context_fields); ~AnalyzerContextDecl(); void AddFlowBuffer(); - const ID *context_name_id() const { return context_name_id_; } + const ID* context_name_id() const { return context_name_id_; } // The type of analyzer context as a parameter - ParameterizedType *param_type() const { return param_type_; } + ParameterizedType* param_type() const { return param_type_; } - void GenForwardDeclaration(Output *out_h); - void GenCode(Output *out_h, Output *out_cc); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); - void GenNamespaceBegin(Output *out) const; - void GenNamespaceEnd(Output *out) const; + void GenNamespaceBegin(Output* out) const; + void GenNamespaceEnd(Output* out) const; private: - ID *context_name_id_; - ContextFieldList *context_fields_; - ParameterizedType *param_type_; + ID* context_name_id_; + ContextFieldList* context_fields_; + ParameterizedType* param_type_; bool flow_buffer_added_; -// static members + // static members public: - static AnalyzerContextDecl *current_analyzer_context() - { - return current_analyzer_context_; - } + static AnalyzerContextDecl* current_analyzer_context() { return current_analyzer_context_; } - static string mb_buffer(Env *env); + static string mb_buffer(Env* env); private: - static AnalyzerContextDecl *current_analyzer_context_; -}; + static AnalyzerContextDecl* current_analyzer_context_; + }; -class DummyType : public Type -{ +class DummyType : public Type + { public: - DummyType() : Type(DUMMY) {} + DummyType() : Type(DUMMY) { } - bool DefineValueVar() const { return false; } - string DataTypeStr() const { ASSERT(0); return ""; } + bool DefineValueVar() const { return false; } + string DataTypeStr() const + { + ASSERT(0); + return ""; + } - int StaticSize(Env* env) const { ASSERT(0); return -1; } + int StaticSize(Env* env) const + { + ASSERT(0); + return -1; + } bool ByteOrderSensitive() const { return false; } - bool IsPointerType() const { ASSERT(0); return false; } + bool IsPointerType() const + { + ASSERT(0); + return false; + } - void DoGenParseCode(Output* out, Env* env, - const DataPtr& data, int flags) - { ASSERT(0); } + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) { ASSERT(0); } // Generate code for computing the dynamic size of the type - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) - { ASSERT(0); } + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) { ASSERT(0); } protected: - Type *DoClone() const; - void DoMarkIncrementalInput() { ASSERT(0); } -}; + Type* DoClone() const; + void DoMarkIncrementalInput() { ASSERT(0); } + }; -#endif // pac_context_h +#endif // pac_context_h diff --git a/tools/binpac/src/pac_cstr.cc b/tools/binpac/src/pac_cstr.cc index 6e0eb027e0..69ca4f3526 100644 --- a/tools/binpac/src/pac_cstr.cc +++ b/tools/binpac/src/pac_cstr.cc @@ -1,87 +1,98 @@ #include "pac_cstr.h" + #include "pac_dbg.h" #include "pac_exception.h" -namespace { +namespace + { class EscapeException -{ + { public: - explicit EscapeException(const string &s) - { - msg_ = s; - } + explicit EscapeException(const string& s) { msg_ = s; } - const string &msg() const { return msg_; } + const string& msg() const { return msg_; } private: string msg_; -}; + }; // Copied from util.cc of Zeek int expand_escape(const char*& s) { - switch ( *(s++) ) { - case 'b': return '\b'; - case 'f': return '\f'; - case 'n': return '\n'; - case 'r': return '\r'; - case 't': return '\t'; - case 'a': return '\a'; - case 'v': return '\v'; + switch ( *(s++) ) + { + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'a': + return '\a'; + case 'v': + return '\v'; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': - { // \{1,3} - --s; // put back the first octal digit - const char* start = s; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { // \{1,3} + --s; // put back the first octal digit + const char* start = s; - // Don't increment inside loop control - // because if isdigit() is a macro it might - // expand into multiple increments ... + // Don't increment inside loop control + // because if isdigit() is a macro it might + // expand into multiple increments ... - // Here we define a maximum length for escape sequence - // to allow easy handling of string like: "^H0" as - // "\0100". + // Here we define a maximum length for escape sequence + // to allow easy handling of string like: "^H0" as + // "\0100". - for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s); ++s, ++len) - ; + for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s); ++s, ++len ) + ; - int result; - if ( sscanf(start, "%3o", &result) != 1 ) - throw EscapeException(strfmt("bad octal escape: \"%s", start)); + int result; + if ( sscanf(start, "%3o", &result) != 1 ) + throw EscapeException(strfmt("bad octal escape: \"%s", start)); - return result; + return result; + } + + case 'x': + { /* \x */ + const char* start = s; + + // Look at most 2 characters, so that "\x0ddir" -> "^Mdir". + for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s); ++s, ++len ) + ; + + int result; + if ( sscanf(start, "%2x", &result) != 1 ) + throw EscapeException(strfmt("bad hexadecimal escape: \"%s", start)); + + return result; + } + + default: + return s[-1]; } - - case 'x': - { /* \x */ - const char* start = s; - - // Look at most 2 characters, so that "\x0ddir" -> "^Mdir". - for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s); - ++s, ++len) - ; - - int result; - if ( sscanf(start, "%2x", &result) != 1 ) - throw EscapeException(strfmt("bad hexadecimal escape: \"%s", start)); - - return result; - } - - default: - return s[-1]; - } } -} // private namespace + } // private namespace -ConstString::ConstString(const string &s) - : str_(s) +ConstString::ConstString(const string& s) : str_(s) { // Copied from scan.l of Zeek - try + try { const char* text = str_.c_str(); int len = strlen(text) + 1; @@ -94,9 +105,9 @@ ConstString::ConstString(const string &s) { if ( *text == '\\' ) { - ++text; // skip '\' + ++text; // skip '\' new_s[i++] = expand_escape(text); - --text; // point to end of sequence + --text; // point to end of sequence } else { @@ -106,16 +117,15 @@ ConstString::ConstString(const string &s) ASSERT(i < len); // Get rid of trailing quote. - ASSERT(new_s[i-1] == '"'); - new_s[i-1] = '\0'; + ASSERT(new_s[i - 1] == '"'); + new_s[i - 1] = '\0'; unescaped_ = new_s; - delete [] new_s; + delete[] new_s; } - catch(EscapeException const &e) + catch ( EscapeException const& e ) { // Throw again with the object throw Exception(this, e.msg().c_str()); } } - diff --git a/tools/binpac/src/pac_cstr.h b/tools/binpac/src/pac_cstr.h index d1faaf7604..b9865e96d7 100644 --- a/tools/binpac/src/pac_cstr.h +++ b/tools/binpac/src/pac_cstr.h @@ -4,20 +4,20 @@ #include "pac_common.h" class ConstString : public Object -{ + { public: - ConstString(const string &s); + ConstString(const string& s); // The string in its escaped form, with surrounding '"'s - const string &str() const { return str_; } - const char *c_str() const { return str_.c_str(); } + const string& str() const { return str_; } + const char* c_str() const { return str_.c_str(); } // The unescaped string, without surrounding '"'s - const string &unescaped() const { return unescaped_; } + const string& unescaped() const { return unescaped_; } private: string str_; string unescaped_; -}; + }; -#endif // pac_cstr_h +#endif // pac_cstr_h diff --git a/tools/binpac/src/pac_ctype.cc b/tools/binpac/src/pac_ctype.cc index cfde2f461b..a664756327 100644 --- a/tools/binpac/src/pac_ctype.cc +++ b/tools/binpac/src/pac_ctype.cc @@ -1,21 +1,21 @@ #include "pac_ctype.h" -string CType::DeclareInstance(const string &var) const +string CType::DeclareInstance(const string& var) const { return strfmt("%s %s", name().c_str(), var.c_str()); } -string CType::DeclareConstReference(const string &var) const +string CType::DeclareConstReference(const string& var) const { return strfmt("%s const &%s", name().c_str(), var.c_str()); } -string CType::DeclareConstPointer(const string &var) const +string CType::DeclareConstPointer(const string& var) const { return strfmt("%s const *%s", name().c_str(), var.c_str()); } -string CType::DeclarePointer(const string &var) const +string CType::DeclarePointer(const string& var) const { return strfmt("%s *%s", name().c_str(), var.c_str()); } diff --git a/tools/binpac/src/pac_ctype.h b/tools/binpac/src/pac_ctype.h index aebbc34d6a..4cf64bf25d 100644 --- a/tools/binpac/src/pac_ctype.h +++ b/tools/binpac/src/pac_ctype.h @@ -5,19 +5,19 @@ // Represents a C++ type class CType -{ + { public: - CType(const string &name); + CType(const string& name); - string name() const { return name_; } + string name() const { return name_; } - string DeclareInstance(const string &var) const; - string DeclareConstReference(const string &var) const; - string DeclareConstPointer(const string &var) const; - string DeclarePointer(const string &var) const; + string DeclareInstance(const string& var) const; + string DeclareConstReference(const string& var) const; + string DeclareConstPointer(const string& var) const; + string DeclarePointer(const string& var) const; protected: string name_; -}; + }; -#endif // pac_ctype_h +#endif // pac_ctype_h diff --git a/tools/binpac/src/pac_datadep.cc b/tools/binpac/src/pac_datadep.cc index 8c43e0e106..a9a4f1adea 100644 --- a/tools/binpac/src/pac_datadep.cc +++ b/tools/binpac/src/pac_datadep.cc @@ -1,14 +1,12 @@ #include "pac_datadep.h" + #include "pac_expr.h" #include "pac_id.h" #include "pac_type.h" -DataDepElement::DataDepElement(DDE_Type type) - : dde_type_(type), in_traversal(false) - { - } +DataDepElement::DataDepElement(DDE_Type type) : dde_type_(type), in_traversal(false) { } -bool DataDepElement::Traverse(DataDepVisitor *visitor) +bool DataDepElement::Traverse(DataDepVisitor* visitor) { // Avoid infinite loop if ( in_traversal ) @@ -27,19 +25,19 @@ bool DataDepElement::Traverse(DataDepVisitor *visitor) return true; } -Expr *DataDepElement::expr() - { - return static_cast(this); - } - -Type *DataDepElement::type() - { - return static_cast(this); - } - -bool RequiresAnalyzerContext::PreProcess(DataDepElement *element) +Expr* DataDepElement::expr() { - switch ( element->dde_type() ) + return static_cast(this); + } + +Type* DataDepElement::type() + { + return static_cast(this); + } + +bool RequiresAnalyzerContext::PreProcess(DataDepElement* element) + { + switch ( element->dde_type() ) { case DataDepElement::EXPR: ProcessExpr(element->expr()); @@ -52,23 +50,22 @@ bool RequiresAnalyzerContext::PreProcess(DataDepElement *element) return ! requires_analyzer_context_; } -bool RequiresAnalyzerContext::PostProcess(DataDepElement *element) +bool RequiresAnalyzerContext::PostProcess(DataDepElement* element) { return ! requires_analyzer_context_; } -void RequiresAnalyzerContext::ProcessExpr(Expr *expr) +void RequiresAnalyzerContext::ProcessExpr(Expr* expr) { if ( expr->expr_type() == Expr::EXPR_ID ) { - requires_analyzer_context_ = - (requires_analyzer_context_ || - *expr->id() == *analyzer_context_id || - *expr->id() == *context_macro_id); + requires_analyzer_context_ = (requires_analyzer_context_ || + *expr->id() == *analyzer_context_id || + *expr->id() == *context_macro_id); } } -bool RequiresAnalyzerContext::compute(DataDepElement *element) +bool RequiresAnalyzerContext::compute(DataDepElement* element) { RequiresAnalyzerContext visitor; element->Traverse(&visitor); diff --git a/tools/binpac/src/pac_datadep.h b/tools/binpac/src/pac_datadep.h index a45053fb01..7cb8216ada 100644 --- a/tools/binpac/src/pac_datadep.h +++ b/tools/binpac/src/pac_datadep.h @@ -9,9 +9,11 @@ class DataDepVisitor; -class DataDepElement { +class DataDepElement + { public: - enum DDE_Type { + enum DDE_Type + { ATTR, CASEEXPR, EXPR, @@ -19,53 +21,52 @@ public: INPUT_BUFFER, PARAM, TYPE, - }; + }; DataDepElement(DDE_Type type); - virtual ~DataDepElement() {} + virtual ~DataDepElement() { } // Returns whether to continue traversal - bool Traverse(DataDepVisitor *visitor); + bool Traverse(DataDepVisitor* visitor); // Returns whether to continue traversal - virtual bool DoTraverse(DataDepVisitor *visitor) = 0; + virtual bool DoTraverse(DataDepVisitor* visitor) = 0; - DDE_Type dde_type() const { return dde_type_; } - Expr *expr(); - Type *type(); + DDE_Type dde_type() const { return dde_type_; } + Expr* expr(); + Type* type(); protected: DDE_Type dde_type_; bool in_traversal; -}; + }; -class DataDepVisitor { +class DataDepVisitor + { public: - virtual ~DataDepVisitor() {} + virtual ~DataDepVisitor() { } // Returns whether to continue traversal - virtual bool PreProcess(DataDepElement *element) = 0; - virtual bool PostProcess(DataDepElement *element) = 0; -}; + virtual bool PreProcess(DataDepElement* element) = 0; + virtual bool PostProcess(DataDepElement* element) = 0; + }; -class RequiresAnalyzerContext : public DataDepVisitor { +class RequiresAnalyzerContext : public DataDepVisitor + { public: - RequiresAnalyzerContext() : requires_analyzer_context_(false) {} + RequiresAnalyzerContext() : requires_analyzer_context_(false) { } // Returns whether to continue traversal - bool PreProcess(DataDepElement *element); - bool PostProcess(DataDepElement *element); + bool PreProcess(DataDepElement* element); + bool PostProcess(DataDepElement* element); - bool requires_analyzer_context() const - { - return requires_analyzer_context_; - } + bool requires_analyzer_context() const { return requires_analyzer_context_; } - static bool compute(DataDepElement *element); + static bool compute(DataDepElement* element); protected: - void ProcessExpr(Expr *expr); + void ProcessExpr(Expr* expr); bool requires_analyzer_context_; -}; + }; #endif // pac_datadep_h diff --git a/tools/binpac/src/pac_dataptr.cc b/tools/binpac/src/pac_dataptr.cc index 08071b1cf8..4ebb0dba42 100644 --- a/tools/binpac/src/pac_dataptr.cc +++ b/tools/binpac/src/pac_dataptr.cc @@ -1,12 +1,11 @@ +#include "pac_dataptr.h" + #include "pac_exception.h" #include "pac_id.h" #include "pac_output.h" #include "pac_utils.h" -#include "pac_dataptr.h" - -DataPtr::DataPtr(Env* env, const ID* id, const int offset) - : id_(id), offset_(offset) +DataPtr::DataPtr(Env* env, const ID* id, const int offset) : id_(id), offset_(offset) { if ( id_ ) { @@ -24,7 +23,7 @@ DataPtr::DataPtr(Env* env, const ID* id, const int offset) int DataPtr::AbsOffset(const ID* base_ptr) const { - return ( id() == base_ptr ) ? offset() : -1; + return (id() == base_ptr) ? offset() : -1; } char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const @@ -35,35 +34,27 @@ char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr)); } -void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, - const char* data_size, const char* data_name) const +void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size, + const char* data_name) const { ASSERT(id_); out_cc->println("// Checking out-of-bound for \"%s\"", data_name); - out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", - ptr_expr(), - data_size, - env->RValue(end_of_data), - ptr_expr(), - data_size, - ptr_expr()); + out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", ptr_expr(), data_size, + env->RValue(end_of_data), ptr_expr(), data_size, ptr_expr()); - out_cc->inc_indent(); + out_cc->inc_indent(); out_cc->println("{"); - char* data_offset = AbsOffsetExpr(env, begin_of_data); + char* data_offset = AbsOffsetExpr(env, begin_of_data); out_cc->println("// Handle out-of-bound condition"); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_name); - out_cc->println(" (%s) + (%s), ", - data_offset, data_size); - out_cc->println(" (%s) - (%s));", - env->RValue(end_of_data), env->RValue(begin_of_data)); + out_cc->println(" (%s) + (%s), ", data_offset, data_size); + out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->RValue(begin_of_data)); - delete [] data_offset; + delete[] data_offset; out_cc->println("}"); - out_cc->dec_indent(); + out_cc->dec_indent(); } - diff --git a/tools/binpac/src/pac_dataptr.h b/tools/binpac/src/pac_dataptr.h index 981707c9e9..be8885fc89 100644 --- a/tools/binpac/src/pac_dataptr.h +++ b/tools/binpac/src/pac_dataptr.h @@ -2,18 +2,20 @@ #define pac_dataptr_h #include + #include "pac_common.h" +#include "pac_dbg.h" // A data pointer is represented by an data pointer variable // plus a constant offset. class DataPtr -{ + { public: DataPtr(Env* env, const ID* arg_id, const int arg_off); DataPtr(DataPtr const& x) { *this = x; } - DataPtr const &operator=(DataPtr const &x) + DataPtr const& operator=(DataPtr const& x) { id_ = x.id(); offset_ = x.offset(); @@ -22,27 +24,25 @@ public: return *this; } - const ID* id() const { return id_; } - int offset() const { return offset_; } + const ID* id() const { return id_; } + int offset() const { return offset_; } const char* ptr_expr() const { - ASSERT(id_); - return ptr_expr_.c_str(); + ASSERT(id_); + return ptr_expr_.c_str(); } int AbsOffset(const ID* base_ptr) const; char* AbsOffsetExpr(Env* env, const ID* base_ptr) const; - void GenBoundaryCheck(Output* out, - Env* env, - const char* data_size, - const char* data_name) const; + void GenBoundaryCheck(Output* out, Env* env, const char* data_size, + const char* data_name) const; protected: const ID* id_; int offset_; string ptr_expr_; -}; + }; -#endif // pac_dataptr_h +#endif // pac_dataptr_h diff --git a/tools/binpac/src/pac_dataunit.cc b/tools/binpac/src/pac_dataunit.cc index 2b7218963d..df13f21025 100644 --- a/tools/binpac/src/pac_dataunit.cc +++ b/tools/binpac/src/pac_dataunit.cc @@ -1,32 +1,21 @@ -#include "pac_context.h" #include "pac_dataunit.h" + +#include "pac_context.h" #include "pac_output.h" #include "pac_paramtype.h" #include "pac_varfield.h" -AnalyzerDataUnit::AnalyzerDataUnit( - DataUnitType type, - ID *id, - ExprList *type_params, - ExprList *context_params) - : AnalyzerElement(DATAUNIT), - type_(type), - id_(id), - type_params_(type_params), - context_params_(context_params) +AnalyzerDataUnit::AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, + ExprList* context_params) + : AnalyzerElement(DATAUNIT), type_(type), id_(id), type_params_(type_params), + context_params_(context_params) { data_type_ = new ParameterizedType(id_, type_params_); context_type_ = new ParameterizedType( - AnalyzerContextDecl::current_analyzer_context()->id()->clone(), - context_params_); + AnalyzerContextDecl::current_analyzer_context()->id()->clone(), context_params_); - dataunit_var_field_ = new ParseVarField( - Field::CLASS_MEMBER, - dataunit_id->clone(), - data_type()); - context_var_field_ = new PrivVarField( - analyzer_context_id->clone(), - context_type()); + dataunit_var_field_ = new ParseVarField(Field::CLASS_MEMBER, dataunit_id->clone(), data_type()); + context_var_field_ = new PrivVarField(analyzer_context_id->clone(), context_type()); } AnalyzerDataUnit::~AnalyzerDataUnit() @@ -35,26 +24,22 @@ AnalyzerDataUnit::~AnalyzerDataUnit() delete context_var_field_; } -void AnalyzerDataUnit::Prepare(Env *env) +void AnalyzerDataUnit::Prepare(Env* env) { dataunit_var_field_->Prepare(env); context_var_field_->Prepare(env); } -void AnalyzerDataUnit::GenNewDataUnit(Output *out_cc, Env *env) +void AnalyzerDataUnit::GenNewDataUnit(Output* out_cc, Env* env) { - out_cc->println("%s = new %s(%s);", - env->LValue(dataunit_id), - data_type()->class_name().c_str(), - data_type()->EvalParameters(out_cc, env).c_str()); + out_cc->println("%s = new %s(%s);", env->LValue(dataunit_id), data_type()->class_name().c_str(), + data_type()->EvalParameters(out_cc, env).c_str()); } -void AnalyzerDataUnit::GenNewContext(Output *out_cc, Env *env) +void AnalyzerDataUnit::GenNewContext(Output* out_cc, Env* env) { - out_cc->println("%s = new %s(%s);", - env->LValue(analyzer_context_id), - context_type()->class_name().c_str(), - context_type()->EvalParameters(out_cc, env).c_str()); + out_cc->println("%s = new %s(%s);", env->LValue(analyzer_context_id), + context_type()->class_name().c_str(), + context_type()->EvalParameters(out_cc, env).c_str()); env->SetEvaluated(analyzer_context_id); } - diff --git a/tools/binpac/src/pac_dataunit.h b/tools/binpac/src/pac_dataunit.h index eb76378afa..c057a0d574 100644 --- a/tools/binpac/src/pac_dataunit.h +++ b/tools/binpac/src/pac_dataunit.h @@ -7,43 +7,43 @@ // data unit of a DCE/RPC flow is DCE_RPC_PDU. class AnalyzerDataUnit : public AnalyzerElement -{ + { public: - enum DataUnitType { DATAGRAM, FLOWUNIT }; - AnalyzerDataUnit( - DataUnitType type, - ID *id, - ExprList *type_params, - ExprList *context_params); + enum DataUnitType + { + DATAGRAM, + FLOWUNIT + }; + AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params); ~AnalyzerDataUnit(); - void Prepare(Env *env); + void Prepare(Env* env); // Initializes dataunit_id - void GenNewDataUnit(Output *out_cc, Env *env); + void GenNewDataUnit(Output* out_cc, Env* env); // Initializes analyzer_context_id - void GenNewContext(Output *out_cc, Env *env); + void GenNewContext(Output* out_cc, Env* env); - DataUnitType type() const { return type_; } - const ID *id() const { return id_; } - ExprList *type_params() const { return type_params_; } - ExprList *context_params() const { return context_params_; } + DataUnitType type() const { return type_; } + const ID* id() const { return id_; } + ExprList* type_params() const { return type_params_; } + ExprList* context_params() const { return context_params_; } - ParameterizedType *data_type() const { return data_type_; } - ParameterizedType *context_type() const { return context_type_; } + ParameterizedType* data_type() const { return data_type_; } + ParameterizedType* context_type() const { return context_type_; } - Field *dataunit_var_field() const { return dataunit_var_field_; } - Field *context_var_field() const { return context_var_field_; } + Field* dataunit_var_field() const { return dataunit_var_field_; } + Field* context_var_field() const { return context_var_field_; } private: DataUnitType type_; - ID *id_; - ExprList *type_params_; - ExprList *context_params_; - ParameterizedType *data_type_; - ParameterizedType *context_type_; - Field *dataunit_var_field_; - Field *context_var_field_; -}; + ID* id_; + ExprList* type_params_; + ExprList* context_params_; + ParameterizedType* data_type_; + ParameterizedType* context_type_; + Field* dataunit_var_field_; + Field* context_var_field_; + }; #endif // pac_dataunit_h diff --git a/tools/binpac/src/pac_dbg.h b/tools/binpac/src/pac_dbg.h index e24fdfcd9a..aebfda38fa 100644 --- a/tools/binpac/src/pac_dbg.h +++ b/tools/binpac/src/pac_dbg.h @@ -6,7 +6,9 @@ extern bool FLAGS_pac_debug; -#define ASSERT(x) assert(x) -#define DEBUG_MSG(x...) if ( FLAGS_pac_debug ) fprintf(stderr, x) +#define ASSERT(x) assert(x) +#define DEBUG_MSG(x...) \ + if ( FLAGS_pac_debug ) \ + fprintf(stderr, x) #endif /* pac_dbg_h */ diff --git a/tools/binpac/src/pac_decl-inl.h b/tools/binpac/src/pac_decl-inl.h index 97c369fa9f..84dfce9d01 100644 --- a/tools/binpac/src/pac_decl-inl.h +++ b/tools/binpac/src/pac_decl-inl.h @@ -3,4 +3,4 @@ #include "pac_id.h" -#endif // pac_decl_inl_h +#endif // pac_decl_inl_h diff --git a/tools/binpac/src/pac_decl.cc b/tools/binpac/src/pac_decl.cc index 0bf371ce31..3982e10116 100644 --- a/tools/binpac/src/pac_decl.cc +++ b/tools/binpac/src/pac_decl.cc @@ -1,3 +1,5 @@ +#include "pac_decl.h" + #include "pac_attr.h" #include "pac_context.h" #include "pac_dataptr.h" @@ -12,13 +14,10 @@ #include "pac_type.h" #include "pac_utils.h" -#include "pac_decl.h" - -DeclList *Decl::decl_list_ = 0; +DeclList* Decl::decl_list_ = 0; Decl::DeclMap Decl::decl_map_; -Decl::Decl(ID* id, DeclType decl_type) - : id_(id), decl_type_(decl_type), attrlist_(0) +Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(0) { decl_map_[id_] = this; if ( ! decl_list_ ) @@ -42,44 +41,42 @@ void Decl::AddAttrs(AttrList* attrs) return; if ( ! attrlist_ ) attrlist_ = new AttrList(); - foreach ( i, AttrList, attrs ) + foreach (i, AttrList, attrs) { attrlist_->push_back(*i); ProcessAttr(*i); } } -void Decl::ProcessAttr(Attr *attr) +void Decl::ProcessAttr(Attr* attr) { throw Exception(attr, "unhandled attribute"); } void Decl::SetAnalyzerContext() { - analyzer_context_ = - AnalyzerContextDecl::current_analyzer_context(); + analyzer_context_ = AnalyzerContextDecl::current_analyzer_context(); if ( ! analyzer_context_ ) { - throw Exception(this, - "analyzer context not defined"); + throw Exception(this, "analyzer context not defined"); } } -void Decl::ProcessDecls(Output *out_h, Output *out_cc) +void Decl::ProcessDecls(Output* out_h, Output* out_cc) { if ( ! decl_list_ ) return; - foreach(i, DeclList, decl_list_) + foreach (i, DeclList, decl_list_) { - Decl *decl = *i; + Decl* decl = *i; current_decl_id = decl->id(); decl->Prepare(); } - foreach(i, DeclList, decl_list_) + foreach (i, DeclList, decl_list_) { - Decl *decl = *i; + Decl* decl = *i; current_decl_id = decl->id(); decl->GenExternDeclaration(out_h); } @@ -87,12 +84,11 @@ void Decl::ProcessDecls(Output *out_h, Output *out_cc) out_h->println("namespace binpac {\n"); out_cc->println("namespace binpac {\n"); - AnalyzerContextDecl *analyzer_context = - AnalyzerContextDecl::current_analyzer_context(); + AnalyzerContextDecl* analyzer_context = AnalyzerContextDecl::current_analyzer_context(); - foreach(i, DeclList, decl_list_) + foreach (i, DeclList, decl_list_) { - Decl *decl = *i; + Decl* decl = *i; current_decl_id = decl->id(); decl->GenForwardDeclaration(out_h); } @@ -102,9 +98,9 @@ void Decl::ProcessDecls(Output *out_h, Output *out_cc) out_h->println(""); - foreach(i, DeclList, decl_list_) + foreach (i, DeclList, decl_list_) { - Decl *decl = *i; + Decl* decl = *i; current_decl_id = decl->id(); decl->GenCode(out_h, out_cc); } @@ -129,13 +125,9 @@ Decl* Decl::LookUpDecl(const ID* id) int HelperDecl::helper_id_seq = 0; -HelperDecl::HelperDecl(HelperType helper_type, - ID* context_id, - EmbeddedCode* code) - : Decl(new ID(strfmt("helper_%d", ++helper_id_seq)), HELPER), - helper_type_(helper_type), - context_id_(context_id), - code_(code) +HelperDecl::HelperDecl(HelperType helper_type, ID* context_id, EmbeddedCode* code) + : Decl(new ID(strfmt("helper_%d", ++helper_id_seq)), HELPER), helper_type_(helper_type), + context_id_(context_id), code_(code) { } @@ -150,15 +142,15 @@ void HelperDecl::Prepare() // Do nothing } -void HelperDecl::GenExternDeclaration(Output *out_h) +void HelperDecl::GenExternDeclaration(Output* out_h) { if ( helper_type_ == EXTERN ) code_->GenCode(out_h, global_env()); } -void HelperDecl::GenCode(Output *out_h, Output *out_cc) +void HelperDecl::GenCode(Output* out_h, Output* out_cc) { - Env *env = global_env(); + Env* env = global_env(); #if 0 if ( context_id_ ) diff --git a/tools/binpac/src/pac_decl.h b/tools/binpac/src/pac_decl.h index fc82f8ce34..4602fdac50 100644 --- a/tools/binpac/src/pac_decl.h +++ b/tools/binpac/src/pac_decl.h @@ -5,75 +5,92 @@ #include "pac_id.h" class Decl : public Object -{ + { public: // Note: ANALYZER is not for AnalyzerDecl (which is an // abstract class) , but for AnalyzerContextDecl. - enum DeclType { ENUM, LET, TYPE, FUNC, CONN, FLOW, ANALYZER, HELPER, REGEX }; + enum DeclType + { + ENUM, + LET, + TYPE, + FUNC, + CONN, + FLOW, + ANALYZER, + HELPER, + REGEX + }; - Decl(ID *id, DeclType decl_type); + Decl(ID* id, DeclType decl_type); virtual ~Decl(); - const ID *id() const { return id_; } - DeclType decl_type() const { return decl_type_; } - AnalyzerContextDecl *analyzer_context() const - { return analyzer_context_; } + const ID* id() const { return id_; } + DeclType decl_type() const { return decl_type_; } + AnalyzerContextDecl* analyzer_context() const { return analyzer_context_; } // NULL except for TypeDecl or AnalyzerDecl - virtual Env *env() const { return 0; } + virtual Env* env() const { return 0; } virtual void Prepare() = 0; // Generate declarations out of the "binpac" namespace - virtual void GenExternDeclaration(Output *out_h) { /* do nothing */ } + virtual void GenExternDeclaration(Output* out_h) + { /* do nothing */ + } // Generate declarations before definition of classes - virtual void GenForwardDeclaration(Output *out_h) = 0; + virtual void GenForwardDeclaration(Output* out_h) = 0; - virtual void GenCode(Output *out_h, Output *out_cc) = 0; + virtual void GenCode(Output* out_h, Output* out_cc) = 0; void TakeExprList(); - void AddAttrs(AttrList *attrlist); + void AddAttrs(AttrList* attrlist); void SetAnalyzerContext(); protected: - virtual void ProcessAttr(Attr *a); + virtual void ProcessAttr(Attr* a); - ID *id_; + ID* id_; DeclType decl_type_; - AttrList *attrlist_; - AnalyzerContextDecl *analyzer_context_; + AttrList* attrlist_; + AnalyzerContextDecl* analyzer_context_; public: - static void ProcessDecls(Output *out_h, Output *out_cc); - static Decl *LookUpDecl(const ID *id); + static void ProcessDecls(Output* out_h, Output* out_cc); + static Decl* LookUpDecl(const ID* id); private: - static DeclList *decl_list_; - typedef map DeclMap; + static DeclList* decl_list_; + typedef map DeclMap; static DeclMap decl_map_; -}; + }; class HelperDecl : public Decl -{ + { public: - enum HelperType { - HEADER, CODE, EXTERN, - }; - HelperDecl(HelperType type, ID *context_id, EmbeddedCode *code); + enum HelperType + { + HEADER, + CODE, + EXTERN, + }; + HelperDecl(HelperType type, ID* context_id, EmbeddedCode* code); ~HelperDecl(); void Prepare(); - void GenExternDeclaration(Output *out_h); - void GenForwardDeclaration(Output *out_h) { /* do nothing */ } - void GenCode(Output *out_h, Output *out_cc); + void GenExternDeclaration(Output* out_h); + void GenForwardDeclaration(Output* out_h) + { /* do nothing */ + } + void GenCode(Output* out_h, Output* out_cc); private: HelperType helper_type_; - ID *context_id_; - EmbeddedCode *code_; + ID* context_id_; + EmbeddedCode* code_; static int helper_id_seq; -}; + }; -#endif // pac_decl_h +#endif // pac_decl_h diff --git a/tools/binpac/src/pac_embedded.cc b/tools/binpac/src/pac_embedded.cc index aca2d03a19..1c07c6a218 100644 --- a/tools/binpac/src/pac_embedded.cc +++ b/tools/binpac/src/pac_embedded.cc @@ -1,27 +1,22 @@ -#include "pac_id.h" -#include "pac_primitive.h" -#include "pac_output.h" - #include "pac_embedded.h" -EmbeddedCodeSegment::EmbeddedCodeSegment(const string &s) - : s_(s), primitive_(0) - { - } +#include "pac_id.h" +#include "pac_output.h" +#include "pac_primitive.h" -EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive *primitive) - : s_(""), primitive_(primitive) - { - } +EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(0) { } + +EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive* primitive) + : s_(""), primitive_(primitive) { } EmbeddedCodeSegment::~EmbeddedCodeSegment() { delete primitive_; } -string EmbeddedCodeSegment::ToCode(Env *env) +string EmbeddedCodeSegment::ToCode(Env* env) { - if ( primitive_ && s_.empty() ) + if ( primitive_ && s_.empty() ) s_ = primitive_->ToCode(env); return s_; } @@ -41,12 +36,12 @@ void EmbeddedCode::Append(int atom) current_segment_ += static_cast(atom); } -void EmbeddedCode::Append(const char *str) +void EmbeddedCode::Append(const char* str) { current_segment_ += str; } -void EmbeddedCode::Append(PacPrimitive *primitive) +void EmbeddedCode::Append(PacPrimitive* primitive) { if ( ! current_segment_.empty() ) { @@ -56,7 +51,7 @@ void EmbeddedCode::Append(PacPrimitive *primitive) segments_->push_back(new EmbeddedCodeSegment(primitive)); } -void EmbeddedCode::GenCode(Output *out, Env *env) +void EmbeddedCode::GenCode(Output* out, Env* env) { if ( ! current_segment_.empty() ) { @@ -71,9 +66,9 @@ void EmbeddedCode::GenCode(Output *out, Env *env) // ID's name is used as its RValue env->set_allow_undefined_id(true); - foreach(i, EmbeddedCodeSegmentList, segments_) + foreach (i, EmbeddedCodeSegmentList, segments_) { - EmbeddedCodeSegment *segment = *i; + EmbeddedCodeSegment* segment = *i; out->print("%s", segment->ToCode(env).c_str()); } diff --git a/tools/binpac/src/pac_embedded.h b/tools/binpac/src/pac_embedded.h index b84de746e1..81a4f091a0 100644 --- a/tools/binpac/src/pac_embedded.h +++ b/tools/binpac/src/pac_embedded.h @@ -4,39 +4,39 @@ #include "pac_common.h" class EmbeddedCodeSegment -{ + { public: - explicit EmbeddedCodeSegment(const string &s); - explicit EmbeddedCodeSegment(PacPrimitive *primitive); + explicit EmbeddedCodeSegment(const string& s); + explicit EmbeddedCodeSegment(PacPrimitive* primitive); ~EmbeddedCodeSegment(); - string ToCode(Env *env); + string ToCode(Env* env); private: string s_; - PacPrimitive *primitive_; -}; + PacPrimitive* primitive_; + }; -typedef vector EmbeddedCodeSegmentList; +typedef vector EmbeddedCodeSegmentList; class EmbeddedCode : public Object -{ + { public: EmbeddedCode(); ~EmbeddedCode(); // Append a character void Append(int atom); - void Append(const char *str); + void Append(const char* str); // Append a PAC primitive - void Append(PacPrimitive *primitive); + void Append(PacPrimitive* primitive); - void GenCode(Output *out, Env *env); + void GenCode(Output* out, Env* env); private: string current_segment_; - EmbeddedCodeSegmentList *segments_; -}; + EmbeddedCodeSegmentList* segments_; + }; -#endif // pac_embedded_h +#endif // pac_embedded_h diff --git a/tools/binpac/src/pac_enum.cc b/tools/binpac/src/pac_enum.cc index deb1711bc6..f58dad5d86 100644 --- a/tools/binpac/src/pac_enum.cc +++ b/tools/binpac/src/pac_enum.cc @@ -1,14 +1,12 @@ -#include "pac_exception.h" #include "pac_enum.h" + +#include "pac_exception.h" #include "pac_expr.h" #include "pac_exttype.h" #include "pac_output.h" #include "pac_typedecl.h" -Enum::Enum(ID* id, Expr* expr) - : id_(id), expr_(expr) - { - } +Enum::Enum(ID* id, Expr* expr) : id_(id), expr_(expr) { } Enum::~Enum() { @@ -16,7 +14,7 @@ Enum::~Enum() delete expr_; } -void Enum::GenHeader(Output* out_h, int *pval) +void Enum::GenHeader(Output* out_h, int* pval) { ASSERT(pval); if ( expr_ ) @@ -30,31 +28,30 @@ void Enum::GenHeader(Output* out_h, int *pval) global_env()->AddConstID(id_, *pval); } -EnumDecl::EnumDecl(ID *id, EnumList *enumlist) - : Decl(id, ENUM), enumlist_(enumlist) +EnumDecl::EnumDecl(ID* id, EnumList* enumlist) : Decl(id, ENUM), enumlist_(enumlist) { - ID *type_id = id->clone(); + ID* type_id = id->clone(); datatype_ = new ExternType(type_id, ExternType::NUMBER); extern_typedecl_ = new TypeDecl(type_id, 0, datatype_); } EnumDecl::~EnumDecl() - { - delete_list(EnumList, enumlist_); + { + delete_list(EnumList, enumlist_); delete extern_typedecl_; } -void EnumDecl::Prepare() - { - // Do nothing +void EnumDecl::Prepare() + { + // Do nothing } -void EnumDecl::GenForwardDeclaration(Output *out_h) - { +void EnumDecl::GenForwardDeclaration(Output* out_h) + { out_h->println("enum %s {", id_->Name()); out_h->inc_indent(); int c = 0; - foreach(i, EnumList, enumlist_) + foreach (i, EnumList, enumlist_) { (*i)->GenHeader(out_h, &c); ++c; @@ -65,6 +62,5 @@ void EnumDecl::GenForwardDeclaration(Output *out_h) void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */) { - // Do nothing + // Do nothing } - diff --git a/tools/binpac/src/pac_enum.h b/tools/binpac/src/pac_enum.h index 6b255912b6..73534e12d8 100644 --- a/tools/binpac/src/pac_enum.h +++ b/tools/binpac/src/pac_enum.h @@ -4,34 +4,34 @@ #include "pac_decl.h" class Enum -{ + { public: - Enum(ID *id, Expr *expr = 0); + Enum(ID* id, Expr* expr = 0); ~Enum(); - void GenHeader(Output *out_h, int *pval); + void GenHeader(Output* out_h, int* pval); private: - ID *id_; - Expr *expr_; -}; + ID* id_; + Expr* expr_; + }; class EnumDecl : public Decl -{ + { public: - EnumDecl(ID *id, EnumList *enumlist); + EnumDecl(ID* id, EnumList* enumlist); ~EnumDecl(); - Type *DataType() const { return datatype_; } + Type* DataType() const { return datatype_; } void Prepare(); - void GenForwardDeclaration(Output *out_h); - void GenCode(Output *out_h, Output *out_cc); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); private: - EnumList *enumlist_; - Type *datatype_; - TypeDecl *extern_typedecl_; -}; + EnumList* enumlist_; + Type* datatype_; + TypeDecl* extern_typedecl_; + }; #endif // pac_enum_h diff --git a/tools/binpac/src/pac_exception.cc b/tools/binpac/src/pac_exception.cc index 64ad6663d9..43232c03aa 100644 --- a/tools/binpac/src/pac_exception.cc +++ b/tools/binpac/src/pac_exception.cc @@ -1,4 +1,5 @@ #include "pac_exception.h" + #include "pac_expr.h" #include "pac_id.h" #include "pac_utils.h" @@ -13,59 +14,50 @@ Exception::Exception(const Object* o, string msg) msg_ += msg; - if ( FLAGS_pac_debug ) + if ( FLAGS_pac_debug ) { DEBUG_MSG("Exception: %s\n", msg_.c_str()); abort(); } } -ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) - : Exception(id), id_(id) +ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) : Exception(id), id_(id) { append(strfmt("`%s' undeclared", id_->Name())); } -ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) - : Exception(id), id_(id) +ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) : Exception(id), id_(id) { append(strfmt("`%s' redefined", id_->Name())); } -ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) - : Exception(id), id_(id) +ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) : Exception(id), id_(id) { append(strfmt("ID `%s' not evaluated before used", id->Name())); } -ExceptionIDNotField::ExceptionIDNotField(const ID* id) - : Exception(id), id_(id) +ExceptionIDNotField::ExceptionIDNotField(const ID* id) : Exception(id), id_(id) { append(strfmt("ID `%s' is not a field", id_->Name())); } -ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id, - const ID *member_id) +ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id, const ID* member_id) : Exception(member_id), type_id_(type_id), member_id_(member_id) { - append(strfmt("type %s does not have member `%s'", - type_id_->Name(), member_id_->Name())); + append(strfmt("type %s does not have member `%s'", type_id_->Name(), member_id_->Name())); } -ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) - : Exception(id), id_(id) +ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) : Exception(id), id_(id) { append(strfmt("cyclic dependence through `%s'", id_->Name())); } -ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) - : Exception(o) +ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) : Exception(o) { append(msg.c_str()); } -ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) - : Exception(expr), expr(expr) +ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) : Exception(expr), expr(expr) { append(strfmt("Expression `%s' is not constant", expr->orig())); } @@ -73,11 +65,14 @@ ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr) : Exception(expr), expr(expr) { - append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index", expr->orig())); + append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index", + expr->orig())); } ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr) : Exception(expr), expr(expr) { - append(strfmt("Expression `%s' as a case index is outside the numeric limit of the type used for the switch expression", expr->orig())); + append(strfmt("Expression `%s' as a case index is outside the numeric limit of the type used " + "for the switch expression", + expr->orig())); } diff --git a/tools/binpac/src/pac_exception.h b/tools/binpac/src/pac_exception.h index c3320cf98e..08937e7e7a 100644 --- a/tools/binpac/src/pac_exception.h +++ b/tools/binpac/src/pac_exception.h @@ -7,107 +7,107 @@ using namespace std; #include "pac_common.h" class Exception -{ + { public: Exception(const Object* o, string msg = ""); - const char* msg() const { return msg_.c_str(); } - void append(string s) { msg_ += s; } + const char* msg() const { return msg_.c_str(); } + void append(string s) { msg_ += s; } private: string msg_; -}; + }; class ExceptionIDNotFound : public Exception -{ + { public: ExceptionIDNotFound(const ID* id); const ID* id() const { return id_; } private: const ID* id_; -}; + }; class ExceptionIDRedefinition : public Exception -{ + { public: ExceptionIDRedefinition(const ID* id); const ID* id() const { return id_; } private: const ID* id_; -}; + }; class ExceptionIDNotEvaluated : public Exception -{ + { public: ExceptionIDNotEvaluated(const ID* id); const ID* id() const { return id_; } private: const ID* id_; -}; + }; class ExceptionCyclicDependence : public Exception -{ + { public: ExceptionCyclicDependence(const ID* id); const ID* id() const { return id_; } private: const ID* id_; -}; + }; class ExceptionPaddingError : public Exception -{ + { public: ExceptionPaddingError(const Object* o, string msg); -}; + }; class ExceptionIDNotField : public Exception -{ + { public: ExceptionIDNotField(const ID* id); const ID* id() const { return id_; } private: const ID* id_; -}; + }; class ExceptionMemberNotFound : public Exception -{ + { public: - ExceptionMemberNotFound(const ID* type_id, const ID *member_id); + ExceptionMemberNotFound(const ID* type_id, const ID* member_id); private: const ID *type_id_, *member_id_; -}; + }; class ExceptionNonConstExpr : public Exception -{ + { public: ExceptionNonConstExpr(const Expr* expr); private: - const Expr *expr; -}; + const Expr* expr; + }; class ExceptionInvalidCaseSizeExpr : public Exception -{ + { public: ExceptionInvalidCaseSizeExpr(const Expr* expr); private: - const Expr *expr; -}; + const Expr* expr; + }; class ExceptionInvalidCaseLimitExpr : public Exception -{ + { public: ExceptionInvalidCaseLimitExpr(const Expr* expr); private: - const Expr *expr; -}; + const Expr* expr; + }; #endif /* pac_exception_h */ diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index 066f279ecd..f45b6c3344 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -1,7 +1,8 @@ +#include "pac_expr.h" + #include "pac_case.h" #include "pac_cstr.h" #include "pac_exception.h" -#include "pac_expr.h" #include "pac_exttype.h" #include "pac_id.h" #include "pac_number.h" @@ -12,13 +13,13 @@ #include "pac_typedecl.h" #include "pac_utils.h" -string OrigExprList(ExprList *list) +string OrigExprList(ExprList* list) { bool first = true; string str; - foreach(i, ExprList, list) + foreach (i, ExprList, list) { - Expr *expr = *i; + Expr* expr = *i; if ( first ) first = false; else @@ -28,12 +29,12 @@ string OrigExprList(ExprList *list) return str; } -string EvalExprList(ExprList *exprlist, Output *out, Env *env) +string EvalExprList(ExprList* exprlist, Output* out, Env* env) { string val_list(""); bool first = true; - foreach(i, ExprList, exprlist) + foreach (i, ExprList, exprlist) { if ( ! first ) val_list += ", "; @@ -44,11 +45,10 @@ string EvalExprList(ExprList *exprlist, Output *out, Env *env) return val_list; } -static const char* expr_fmt[] = -{ -# define EXPR_DEF(type, num_op, fmt) fmt, -# include "pac_expr.def" -# undef EXPR_DEF +static const char* expr_fmt[] = { +#define EXPR_DEF(type, num_op, fmt) fmt, +#include "pac_expr.def" +#undef EXPR_DEF }; void Expr::init() @@ -65,8 +65,7 @@ void Expr::init() cases_ = 0; } -Expr::Expr(ID* arg_id) - : DataDepElement(EXPR) +Expr::Expr(ID* arg_id) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_ID; @@ -75,8 +74,7 @@ Expr::Expr(ID* arg_id) orig_ = strfmt("%s", id_->Name()); } -Expr::Expr(Number* arg_num) - : DataDepElement(EXPR) +Expr::Expr(Number* arg_num) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_NUM; @@ -85,8 +83,7 @@ Expr::Expr(Number* arg_num) orig_ = strfmt("((int) %s)", num_->Str()); } -Expr::Expr(ConstString *cstr) - : DataDepElement(EXPR) +Expr::Expr(ConstString* cstr) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_CSTR; @@ -95,8 +92,7 @@ Expr::Expr(ConstString *cstr) orig_ = cstr_->str(); } -Expr::Expr(RegEx *regex) - : DataDepElement(EXPR) +Expr::Expr(RegEx* regex) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_REGEX; @@ -105,8 +101,7 @@ Expr::Expr(RegEx *regex) orig_ = strfmt("/%s/", regex_->str().c_str()); } -Expr::Expr(ExprType arg_type, Expr* op1) - : DataDepElement(EXPR) +Expr::Expr(ExprType arg_type, Expr* op1) : DataDepElement(EXPR) { init(); expr_type_ = arg_type; @@ -115,8 +110,7 @@ Expr::Expr(ExprType arg_type, Expr* op1) orig_ = strfmt(expr_fmt[expr_type_], op1->orig()); } -Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) - : DataDepElement(EXPR) +Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) : DataDepElement(EXPR) { init(); expr_type_ = arg_type; @@ -127,8 +121,7 @@ Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig()); } -Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) - : DataDepElement(EXPR) +Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) : DataDepElement(EXPR) { init(); expr_type_ = arg_type; @@ -139,8 +132,7 @@ Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig(), op3->orig()); } -Expr::Expr(ExprList *args) - : DataDepElement(EXPR) +Expr::Expr(ExprList* args) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_CALLARGS; @@ -150,8 +142,7 @@ Expr::Expr(ExprList *args) orig_ = OrigExprList(args_); } -Expr::Expr(Expr *index, CaseExprList *cases) - : DataDepElement(EXPR) +Expr::Expr(Expr* index, CaseExprList* cases) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_CASE; @@ -160,12 +151,10 @@ Expr::Expr(Expr *index, CaseExprList *cases) cases_ = cases; orig_ = strfmt("case %s of { ", index->orig()); - foreach(i, CaseExprList, cases_) + foreach (i, CaseExprList, cases_) { - CaseExpr *c = *i; - orig_ += strfmt("%s => %s; ", - OrigExprList(c->index()).c_str(), - c->value()->orig()); + CaseExpr* c = *i; + orig_ += strfmt("%s => %s; ", OrigExprList(c->index()).c_str(), c->value()->orig()); } orig_ += "}"; } @@ -180,7 +169,7 @@ Expr::~Expr() delete_list(CaseExprList, cases_); } -void Expr::AddCaseExpr(CaseExpr *case_expr) +void Expr::AddCaseExpr(CaseExpr* case_expr) { ASSERT(str_.empty()); ASSERT(expr_type_ == EXPR_CASE); @@ -188,7 +177,7 @@ void Expr::AddCaseExpr(CaseExpr *case_expr) cases_->push_back(case_expr); } -void Expr::GenStrFromFormat(Env *env) +void Expr::GenStrFromFormat(Env* env) { // The format != "@custom@" ASSERT(*expr_fmt[expr_type_] != '@'); @@ -196,20 +185,15 @@ void Expr::GenStrFromFormat(Env *env) switch ( num_operands_ ) { case 1: - str_ = strfmt(expr_fmt[expr_type_], - operand_[0]->str()); - break; + str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str()); + break; case 2: - str_ = strfmt(expr_fmt[expr_type_], - operand_[0]->str(), - operand_[1]->str()); - break; + str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str()); + break; case 3: - str_ = strfmt(expr_fmt[expr_type_], - operand_[0]->str(), - operand_[1]->str(), - operand_[2]->str()); - break; + str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str(), + operand_[2]->str()); + break; default: DEBUG_MSG("num_operands_ = %d, orig = %s\n", num_operands_, orig()); ASSERT(0); @@ -217,43 +201,41 @@ void Expr::GenStrFromFormat(Env *env) } } -namespace { +namespace + { - RecordField *GetRecordField(const ID *id, Env *env) - { - Field* field = env->GetField(id); - ASSERT(field); - if ( field->tof() != RECORD_FIELD && - field->tof() != PADDING_FIELD ) - throw Exception(id, "not a record field"); - RecordField *r = static_cast(field); - ASSERT(r); - return r; - } +RecordField* GetRecordField(const ID* id, Env* env) + { + Field* field = env->GetField(id); + ASSERT(field); + if ( field->tof() != RECORD_FIELD && field->tof() != PADDING_FIELD ) + throw Exception(id, "not a record field"); + RecordField* r = static_cast(field); + ASSERT(r); + return r; + } -} // private namespace + } // private namespace -void Expr::GenCaseEval(Output *out_cc, Env *env) +void Expr::GenCaseEval(Output* out_cc, Env* env) { ASSERT(expr_type_ == EXPR_CASE); ASSERT(operand_[0]); ASSERT(cases_); - Type *val_type = DataType(env); - ID *val_var = env->AddTempID(val_type); + Type* val_type = DataType(env); + ID* val_var = env->AddTempID(val_type); // DataType(env) can return a null pointer if an enum value is not // defined. if ( ! val_type ) throw Exception(this, "undefined case value"); - out_cc->println("%s %s;", - val_type->DataTypeStr().c_str(), - env->LValue(val_var)); + out_cc->println("%s %s;", val_type->DataTypeStr().c_str(), env->LValue(val_var)); // force evaluation of IDs appearing in case stmt - operand_[0]->ForceIDEval(out_cc, env); - foreach(i, CaseExprList, cases_) + operand_[0]->ForceIDEval(out_cc, env); + foreach (i, CaseExprList, cases_) (*i)->value()->ForceIDEval(out_cc, env); out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); @@ -262,11 +244,11 @@ void Expr::GenCaseEval(Output *out_cc, Env *env) out_cc->inc_indent(); out_cc->println("{"); - CaseExpr *default_case = 0; - foreach(i, CaseExprList, cases_) + CaseExpr* default_case = 0; + foreach (i, CaseExprList, cases_) { - CaseExpr *c = *i; - ExprList *index = c->index(); + CaseExpr* c = *i; + ExprList* index = c->index(); if ( ! index ) { if ( default_case ) @@ -277,9 +259,7 @@ void Expr::GenCaseEval(Output *out_cc, Env *env) { GenCaseStr(index, out_cc, env, switch_type); out_cc->inc_indent(); - out_cc->println("%s = %s;", - env->LValue(val_var), - c->value()->EvalExpr(out_cc, env)); + out_cc->println("%s = %s;", env->LValue(val_var), c->value()->EvalExpr(out_cc, env)); out_cc->println("break;"); out_cc->dec_indent(); } @@ -290,14 +270,13 @@ void Expr::GenCaseEval(Output *out_cc, Env *env) out_cc->inc_indent(); if ( default_case ) { - out_cc->println("%s = %s;", - env->LValue(val_var), + out_cc->println("%s = %s;", env->LValue(val_var), default_case->value()->EvalExpr(out_cc, env)); } else { - out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", - Location(), operand_[0]->EvalExpr(out_cc, env)); + out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", Location(), + operand_[0]->EvalExpr(out_cc, env)); } out_cc->println("break;"); out_cc->dec_indent(); @@ -333,20 +312,17 @@ void Expr::GenEval(Output* out_cc, Env* env) */ operand_[0]->GenEval(out_cc, env); - Type *ty0 = operand_[0]->DataType(env); + Type* ty0 = operand_[0]->DataType(env); if ( ty0 ) { - str_ = strfmt("%s%s", - operand_[0]->EvalExpr(out_cc, env), + str_ = strfmt("%s%s", operand_[0]->EvalExpr(out_cc, env), ty0->EvalMember(operand_[1]->id()).c_str()); } else { string tmp = strfmt("->%s()", operand_[1]->id()->Name()); - str_ = strfmt("%s%s", - operand_[0]->EvalExpr(out_cc, env), - tmp.c_str()); + str_ = strfmt("%s%s", operand_[0]->EvalExpr(out_cc, env), tmp.c_str()); } } break; @@ -358,8 +334,8 @@ void Expr::GenEval(Output* out_cc, Env* env) string v0 = operand_[0]->EvalExpr(out_cc, env); string v1 = operand_[1]->EvalExpr(out_cc, env); - - Type *ty0 = operand_[0]->DataType(env); + + Type* ty0 = operand_[0]->DataType(env); if ( ty0 ) str_ = ty0->EvalElement(v0, v1); else @@ -369,18 +345,18 @@ void Expr::GenEval(Output* out_cc, Env* env) case EXPR_SIZEOF: { - const ID *id = operand_[0]->id(); - RecordField *rf; - Type *ty; + const ID* id = operand_[0]->id(); + RecordField* rf; + Type* ty; - try + try { if ( (rf = GetRecordField(id, env)) != 0 ) { str_ = strfmt("%s", rf->FieldSize(out_cc, env)); } } - catch ( ExceptionIDNotFound &e ) + catch ( ExceptionIDNotFound& e ) { if ( (ty = TypeDecl::LookUpType(id)) != 0 ) { @@ -398,8 +374,8 @@ void Expr::GenEval(Output* out_cc, Env* env) case EXPR_OFFSETOF: { - const ID *id = operand_[0]->id(); - RecordField *rf = GetRecordField(id, env); + const ID* id = operand_[0]->id(); + RecordField* rf = GetRecordField(id, env); str_ = strfmt("%s", rf->FieldOffset(out_cc, env)); } break; @@ -423,7 +399,7 @@ void Expr::GenEval(Output* out_cc, Env* env) } void Expr::ForceIDEval(Output* out_cc, Env* env) - { + { switch ( expr_type_ ) { case EXPR_NUM: @@ -441,18 +417,18 @@ void Expr::ForceIDEval(Output* out_cc, Env* env) break; case EXPR_CALLARGS: - { - foreach(i, ExprList, args_) - (*i)->ForceIDEval(out_cc, env); + { + foreach (i, ExprList, args_) + (*i)->ForceIDEval(out_cc, env); } break; case EXPR_CASE: - { - operand_[0]->ForceIDEval(out_cc, env); - foreach(i, CaseExprList, cases_) + { + operand_[0]->ForceIDEval(out_cc, env); + foreach (i, CaseExprList, cases_) (*i)->value()->ForceIDEval(out_cc, env); - } + } break; default: @@ -464,16 +440,15 @@ void Expr::ForceIDEval(Output* out_cc, Env* env) } } - const char* Expr::EvalExpr(Output* out_cc, Env* env) { GenEval(out_cc, env); return str(); } -Type *Expr::DataType(Env *env) const +Type* Expr::DataType(Env* env) const { - Type *data_type; + Type* data_type; switch ( expr_type_ ) { @@ -484,7 +459,7 @@ Type *Expr::DataType(Env *env) const case EXPR_MEMBER: { // Get type of the parent - Type *parent_type = operand_[0]->DataType(env); + Type* parent_type = operand_[0]->DataType(env); if ( ! parent_type ) return 0; data_type = parent_type->MemberDataType(operand_[1]->id()); @@ -494,7 +469,7 @@ Type *Expr::DataType(Env *env) const case EXPR_SUBSCRIPT: { // Get type of the parent - Type *parent_type = operand_[0]->DataType(env); + Type* parent_type = operand_[0]->DataType(env); data_type = parent_type->ElementDataType(); } break; @@ -505,14 +480,13 @@ Type *Expr::DataType(Env *env) const case EXPR_COND: { - Type *type1 = operand_[1]->DataType(env); - Type *type2 = operand_[2]->DataType(env); + Type* type1 = operand_[1]->DataType(env); + Type* type2 = operand_[2]->DataType(env); if ( ! Type::CompatibleTypes(type1, type2) ) { - throw Exception(this, - strfmt("type mismatch: %s vs %s", - type1->DataTypeStr().c_str(), - type2->DataTypeStr().c_str())); + throw Exception(this, + strfmt("type mismatch: %s vs %s", type1->DataTypeStr().c_str(), + type2->DataTypeStr().c_str())); } data_type = type1; } @@ -526,20 +500,17 @@ Type *Expr::DataType(Env *env) const { if ( cases_ && ! cases_->empty() ) { - Type *type1 = - cases_->front()->value()->DataType(env); + Type* type1 = cases_->front()->value()->DataType(env); Type* numeric_with_largest_width = 0; - foreach(i, CaseExprList, cases_) + foreach (i, CaseExprList, cases_) { - Type *type2 = - (*i)->value()->DataType(env); + Type* type2 = (*i)->value()->DataType(env); if ( ! Type::CompatibleTypes(type1, type2) ) { - throw Exception(this, - strfmt("type mismatch: %s vs %s", - type1->DataTypeStr().c_str(), - type2->DataTypeStr().c_str())); + throw Exception(this, strfmt("type mismatch: %s vs %s", + type1->DataTypeStr().c_str(), + type2->DataTypeStr().c_str())); } if ( type1 == extern_type_nullptr ) type1 = type2; @@ -611,21 +582,19 @@ Type *Expr::DataType(Env *env) const return data_type; } -string Expr::DataTypeStr(Env *env) const +string Expr::DataTypeStr(Env* env) const { - Type *type = DataType(env); + Type* type = DataType(env); if ( ! type ) { - throw Exception(this, - strfmt("cannot find data type for expression `%s'", - orig())); + throw Exception(this, strfmt("cannot find data type for expression `%s'", orig())); } return type->DataTypeStr(); } -string Expr::SetFunc(Output *out, Env *env) +string Expr::SetFunc(Output* out, Env* env) { switch ( expr_type_ ) { @@ -635,172 +604,168 @@ string Expr::SetFunc(Output *out, Env *env) { // Evaluate the parent string parent_val(operand_[0]->EvalExpr(out, env)); - return parent_val - + "->" - + set_function(operand_[1]->id()); + return parent_val + "->" + set_function(operand_[1]->id()); } break; default: - throw Exception(this, - strfmt("cannot generate set function " - "for expression `%s'", orig())); + throw Exception(this, strfmt("cannot generate set function " + "for expression `%s'", + orig())); break; } } bool Expr::ConstFold(Env* env, int* pn) const { - switch ( expr_type_ ) + switch ( expr_type_ ) { - case EXPR_NUM: + case EXPR_NUM: *pn = num_->Num(); return true; case EXPR_ID: return env->GetConstant(id_, pn); - default: + default: // ### FIXME: folding consts return false; } } // TODO: build a generic data dependency extraction process -namespace { +namespace + { - // Maximum of two minimal header sizes - int mhs_max(int h1, int h2) +// Maximum of two minimal header sizes +int mhs_max(int h1, int h2) + { + if ( h1 < 0 || h2 < 0 ) + return -1; + else { - if ( h1 < 0 || h2 < 0 ) - return -1; - else + // return max(h1, h2); + return h1 > h2 ? h1 : h2; + } + } + +// MHS required to evaluate the field +int mhs_letfield(Env* env, LetField* field) + { + return field->expr()->MinimalHeaderSize(env); + } + +int mhs_recordfield(Env* env, RecordField* field) + { + int offset = field->static_offset(); + if ( offset < 0 ) // offset cannot be statically determined + return -1; + int size = field->StaticSize(env, offset); + if ( size < 0 ) // size cannot be statically determined + return -1; + return offset + size; + } + +int mhs_casefield(Env* env, CaseField* field) + { + // TODO: deal with the index + int size = field->StaticSize(env); + if ( size < 0 ) // size cannot be statically determined + return -1; + return size; + } + +int mhs_field(Env* env, Field* field) + { + int mhs = -1; + switch ( field->tof() ) + { + case LET_FIELD: { - // return max(h1, h2); - return h1 > h2 ? h1 : h2; + LetField* f = static_cast(field); + ASSERT(f); + mhs = mhs_letfield(env, f); } - } - - // MHS required to evaluate the field - int mhs_letfield(Env* env, LetField* field) - { - return field->expr()->MinimalHeaderSize(env); - } + break; - int mhs_recordfield(Env* env, RecordField* field) - { - int offset = field->static_offset(); - if ( offset < 0 ) // offset cannot be statically determined - return -1; - int size = field->StaticSize(env, offset); - if ( size < 0 ) // size cannot be statically determined - return -1; - return offset + size; - } + case CONTEXT_FIELD: + case FLOW_FIELD: + ASSERT(0); + break; - int mhs_casefield(Env* env, CaseField* field) - { - // TODO: deal with the index - int size = field->StaticSize(env); - if ( size < 0 ) // size cannot be statically determined - return -1; - return size; - } + case PARAM_FIELD: + mhs = 0; + break; - int mhs_field(Env* env, Field* field) - { - int mhs = -1; - switch ( field->tof() ) + case RECORD_FIELD: + case PADDING_FIELD: { - case LET_FIELD: - { - LetField *f = - static_cast(field); - ASSERT(f); - mhs = mhs_letfield(env, f); - } - break; - - case CONTEXT_FIELD: - case FLOW_FIELD: - ASSERT(0); - break; - - case PARAM_FIELD: - mhs = 0; - break; - - case RECORD_FIELD: - case PADDING_FIELD: - { - RecordField *f = - static_cast(field); - ASSERT(f); - mhs = mhs_recordfield(env, f); - } - break; - - case CASE_FIELD: - { - CaseField *f = - static_cast(field); - ASSERT(f); - mhs = mhs_casefield(env, f); - } - break; - - case PARSE_VAR_FIELD: - case PRIV_VAR_FIELD: - case PUB_VAR_FIELD: - case TEMP_VAR_FIELD: - mhs = 0; - break; - - case WITHINPUT_FIELD: - { - // ### TODO: fix this - mhs = -1; - } - break; + RecordField* f = static_cast(field); + ASSERT(f); + mhs = mhs_recordfield(env, f); } - return mhs; - } + break; - int mhs_id(Env *env, const ID *id) - { - int mhs = -1; - switch ( env->GetIDType(id) ) + case CASE_FIELD: { - case CONST: - case GLOBAL_VAR: - case TEMP_VAR: - case STATE_VAR: - case FUNC_ID: - case FUNC_PARAM: - mhs = 0; - break; - case MEMBER_VAR: - case PRIV_MEMBER_VAR: - { - Field* field = env->GetField(id); - if ( ! field ) - throw ExceptionIDNotField(id); - mhs = mhs_field(env, field); - } - break; - case UNION_VAR: - // TODO: deal with UNION_VAR - mhs = -1; - break; - case MACRO: - { - Expr *e = env->GetMacro(id); - mhs = e->MinimalHeaderSize(env); - } - break; + CaseField* f = static_cast(field); + ASSERT(f); + mhs = mhs_casefield(env, f); } - return mhs; - } -} + break; -int Expr::MinimalHeaderSize(Env *env) + case PARSE_VAR_FIELD: + case PRIV_VAR_FIELD: + case PUB_VAR_FIELD: + case TEMP_VAR_FIELD: + mhs = 0; + break; + + case WITHINPUT_FIELD: + { + // ### TODO: fix this + mhs = -1; + } + break; + } + return mhs; + } + +int mhs_id(Env* env, const ID* id) + { + int mhs = -1; + switch ( env->GetIDType(id) ) + { + case CONST: + case GLOBAL_VAR: + case TEMP_VAR: + case STATE_VAR: + case FUNC_ID: + case FUNC_PARAM: + mhs = 0; + break; + case MEMBER_VAR: + case PRIV_MEMBER_VAR: + { + Field* field = env->GetField(id); + if ( ! field ) + throw ExceptionIDNotField(id); + mhs = mhs_field(env, field); + } + break; + case UNION_VAR: + // TODO: deal with UNION_VAR + mhs = -1; + break; + case MACRO: + { + Expr* e = env->GetMacro(id); + mhs = e->MinimalHeaderSize(env); + } + break; + } + return mhs; + } + } + +int Expr::MinimalHeaderSize(Env* env) { int mhs; @@ -826,11 +791,10 @@ int Expr::MinimalHeaderSize(Env *env) case EXPR_SUBSCRIPT: { int index; - Type *array_type = operand_[0]->DataType(env); - Type *elem_type = array_type->ElementDataType(); + Type* array_type = operand_[0]->DataType(env); + Type* elem_type = array_type->ElementDataType(); int elem_size = elem_type->StaticSize(env); - if ( elem_size >= 0 && - operand_[1]->ConstFold(env, &index) ) + if ( elem_size >= 0 && operand_[1]->ConstFold(env, &index) ) { mhs = elem_size * index; } @@ -845,8 +809,8 @@ int Expr::MinimalHeaderSize(Env *env) { const ID* id = operand_[0]->id(); ASSERT(id); - RecordField *rf; - Type *ty; + RecordField* rf; + Type* ty; if ( (rf = GetRecordField(id, env)) != 0 ) { @@ -870,8 +834,8 @@ int Expr::MinimalHeaderSize(Env *env) { const ID* id = operand_[0]->id(); ASSERT(id); - RecordField *field = GetRecordField(id, env); - + RecordField* field = GetRecordField(id, env); + mhs = field->static_offset(); if ( mhs < 0 ) { @@ -885,21 +849,21 @@ int Expr::MinimalHeaderSize(Env *env) break; case EXPR_CALLARGS: - { - mhs = 0; + { + mhs = 0; if ( args_ ) - for ( unsigned int i = 0; i < args_->size(); ++i ) + for ( unsigned int i = 0; i < args_->size(); ++i ) mhs = mhs_max(mhs, (*args_)[i]->MinimalHeaderSize(env)); } - break; + break; case EXPR_CASE: - { - mhs = operand_[0]->MinimalHeaderSize(env); + { + mhs = operand_[0]->MinimalHeaderSize(env); for ( unsigned int i = 0; i < cases_->size(); ++i ) - { - CaseExpr * ce = (*cases_)[i]; + { + CaseExpr* ce = (*cases_)[i]; if ( ce->index() ) - for ( unsigned int j = 0; j < ce->index()->size(); ++j ) + for ( unsigned int j = 0; j < ce->index()->size(); ++j ) mhs = mhs_max(mhs, (*ce->index())[j]->MinimalHeaderSize(env)); mhs = mhs_max(mhs, ce->value()->MinimalHeaderSize(env)); } @@ -917,7 +881,7 @@ int Expr::MinimalHeaderSize(Env *env) return mhs; } -bool Expr::HasReference(const ID *id) const +bool Expr::HasReference(const ID* id) const { switch ( expr_type_ ) { @@ -929,7 +893,7 @@ bool Expr::HasReference(const ID *id) const case EXPR_CALLARGS: { - foreach(i, ExprList, args_) + foreach (i, ExprList, args_) if ( (*i)->HasReference(id) ) return true; } @@ -937,7 +901,7 @@ bool Expr::HasReference(const ID *id) const case EXPR_CASE: { - foreach(i, CaseExprList, cases_) + foreach (i, CaseExprList, cases_) if ( (*i)->HasReference(id) ) return true; } @@ -947,8 +911,7 @@ bool Expr::HasReference(const ID *id) const // Evaluate every operand by default for ( int i = 0; i < 3; ++i ) { - if ( operand_[i] && - operand_[i]->HasReference(id) ) + if ( operand_[i] && operand_[i]->HasReference(id) ) { return true; } @@ -957,7 +920,7 @@ bool Expr::HasReference(const ID *id) const } } -bool Expr::DoTraverse(DataDepVisitor *visitor) +bool Expr::DoTraverse(DataDepVisitor* visitor) { switch ( expr_type_ ) { @@ -977,7 +940,7 @@ bool Expr::DoTraverse(DataDepVisitor *visitor) case EXPR_CALLARGS: { - foreach(i, ExprList, args_) + foreach (i, ExprList, args_) if ( ! (*i)->Traverse(visitor) ) return false; } @@ -985,7 +948,7 @@ bool Expr::DoTraverse(DataDepVisitor *visitor) case EXPR_CASE: { - foreach(i, CaseExprList, cases_) + foreach (i, CaseExprList, cases_) if ( ! (*i)->Traverse(visitor) ) return false; } @@ -995,8 +958,7 @@ bool Expr::DoTraverse(DataDepVisitor *visitor) // Evaluate every operand by default for ( int i = 0; i < 3; ++i ) { - if ( operand_[i] && - ! operand_[i]->Traverse(visitor) ) + if ( operand_[i] && ! operand_[i]->Traverse(visitor) ) { return false; } @@ -1025,7 +987,7 @@ bool Expr::RequiresAnalyzerContext() const case EXPR_CALLARGS: { - foreach(i, ExprList, args_) + foreach (i, ExprList, args_) if ( (*i)->RequiresAnalyzerContext() ) return true; } @@ -1033,7 +995,7 @@ bool Expr::RequiresAnalyzerContext() const case EXPR_CASE: { - foreach(i, CaseExprList, cases_) + foreach (i, CaseExprList, cases_) if ( (*i)->RequiresAnalyzerContext() ) return true; } @@ -1042,8 +1004,7 @@ bool Expr::RequiresAnalyzerContext() const default: // Evaluate every operand by default for ( int i = 0; i < 3; ++i ) - if ( operand_[i] && - operand_[i]->RequiresAnalyzerContext() ) + if ( operand_[i] && operand_[i]->RequiresAnalyzerContext() ) { DEBUG_MSG("'%s' requires analyzer context\n", operand_[i]->orig()); return true; @@ -1052,9 +1013,8 @@ bool Expr::RequiresAnalyzerContext() const } } -CaseExpr::CaseExpr(ExprList *index, Expr *value) - : DataDepElement(DataDepElement::CASEEXPR), - index_(index), value_(value) +CaseExpr::CaseExpr(ExprList* index, Expr* value) + : DataDepElement(DataDepElement::CASEEXPR), index_(index), value_(value) { } @@ -1064,15 +1024,15 @@ CaseExpr::~CaseExpr() delete value_; } -bool CaseExpr::DoTraverse(DataDepVisitor *visitor) +bool CaseExpr::DoTraverse(DataDepVisitor* visitor) { - foreach(i, ExprList, index_) + foreach (i, ExprList, index_) if ( ! (*i)->Traverse(visitor) ) return false; return value_->Traverse(visitor); } -bool CaseExpr::HasReference(const ID *id) const +bool CaseExpr::HasReference(const ID* id) const { return value_->HasReference(id); } diff --git a/tools/binpac/src/pac_expr.h b/tools/binpac/src/pac_expr.h index be1e70c6ea..e4c8b71dc0 100644 --- a/tools/binpac/src/pac_expr.h +++ b/tools/binpac/src/pac_expr.h @@ -7,44 +7,45 @@ class CaseExpr; class Expr : public Object, public DataDepElement -{ + { public: - enum ExprType { -# define EXPR_DEF(type, x, y) type, -# include "pac_expr.def" -# undef EXPR_DEF - }; + enum ExprType + { +#define EXPR_DEF(type, x, y) type, +#include "pac_expr.def" +#undef EXPR_DEF + }; void init(); - Expr(ID *id); - Expr(Number *num); - Expr(ConstString *s); - Expr(RegEx *regex); - Expr(ExprList *args); // for EXPR_CALLARGS - Expr(Expr *index, CaseExprList *cases); + Expr(ID* id); + Expr(Number* num); + Expr(ConstString* s); + Expr(RegEx* regex); + Expr(ExprList* args); // for EXPR_CALLARGS + Expr(Expr* index, CaseExprList* cases); - Expr(ExprType type, Expr *op1); - Expr(ExprType type, Expr *op1, Expr *op2); - Expr(ExprType type, Expr *op1, Expr *op2, Expr *op3); + Expr(ExprType type, Expr* op1); + Expr(ExprType type, Expr* op1, Expr* op2); + Expr(ExprType type, Expr* op1, Expr* op2, Expr* op3); virtual ~Expr(); - const char *orig() const { return orig_.c_str(); } - const ID *id() const { return id_; } - const char *str() const { return str_.c_str(); } - ExprType expr_type() const { return expr_type_; } + const char* orig() const { return orig_.c_str(); } + const ID* id() const { return id_; } + const char* str() const { return str_.c_str(); } + ExprType expr_type() const { return expr_type_; } - void AddCaseExpr(CaseExpr *case_expr); + void AddCaseExpr(CaseExpr* case_expr); // Returns the data "type" of the expression. Here we only // do a serious job for the EXPR_MEMBER and EXPR_SUBSCRIPT // operators. For arithmetic operations, we fall back // to "int". - Type *DataType(Env *env) const; - string DataTypeStr(Env *env) const; + Type* DataType(Env* env) const; + string DataTypeStr(Env* env) const; - // Note: EvalExpr() may generate C++ statements in order to evaluate + // Note: EvalExpr() may generate C++ statements in order to evaluate // variables in the expression, so the following is wrong: // // out->print("int x = "); @@ -54,24 +55,24 @@ public: // // out->println("int x = %s", expr->EvalExpr(out, env)); // - const char *EvalExpr(Output *out, Env *env); + const char* EvalExpr(Output* out, Env* env); // force evaulation of IDs contained in this expression; // necessary with case expr and conditional let fields (&if) // for correct parsing of fields - void ForceIDEval(Output *out_cc, Env *env); + void ForceIDEval(Output* out_cc, Env* env); - // Returns the set_* function of the expression. + // Returns the set_* function of the expression. // The expression must be of form ID or x.ID. - string SetFunc(Output *out, Env *env); + string SetFunc(Output* out, Env* env); // Returns true if the expression folds to an integer // constant with env, and puts the constant in *pn. // - bool ConstFold(Env *env, int *pn) const; + bool ConstFold(Env* env, int* pn) const; // Whether id is referenced in the expression - bool HasReference(const ID *id) const; + bool HasReference(const ID* id) const; // Suppose the data for type might be incomplete, what is // the minimal number of bytes from data head required to @@ -79,61 +80,61 @@ public: // header do we need to determine the length of the frame? // // The parameter points to the Env of a type. - // + // // Returns -1 if the number is not a constant. // - int MinimalHeaderSize(Env *env); + int MinimalHeaderSize(Env* env); // Whether evaluation of the expression requires the analyzer context bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); private: ExprType expr_type_; int num_operands_; - Expr *operand_[3]; + Expr* operand_[3]; - ID *id_; // EXPR_ID - Number *num_; // EXPR_NUM - ConstString *cstr_; // EXPR_CSTR - RegEx *regex_; // EXPR_REGEX - ExprList *args_; // EXPR_CALLARGS - CaseExprList *cases_; // EXPR_CASE + ID* id_; // EXPR_ID + Number* num_; // EXPR_NUM + ConstString* cstr_; // EXPR_CSTR + RegEx* regex_; // EXPR_REGEX + ExprList* args_; // EXPR_CALLARGS + CaseExprList* cases_; // EXPR_CASE - string str_; // value string - string orig_; // original string for debugging info + string str_; // value string + string orig_; // original string for debugging info - void GenStrFromFormat(Env *env); - void GenEval(Output *out, Env *env); - void GenCaseEval(Output *out_cc, Env *env); -}; + void GenStrFromFormat(Env* env); + void GenEval(Output* out, Env* env); + void GenCaseEval(Output* out_cc, Env* env); + }; -string OrigExprList(ExprList *exprlist); -string EvalExprList(ExprList *exprlist, Output *out, Env *env); +string OrigExprList(ExprList* exprlist); +string EvalExprList(ExprList* exprlist, Output* out, Env* env); // An entry of the case expression, consisting of one or more constant // expressions for the case index and a value expression. class CaseExpr : public Object, public DataDepElement -{ + { public: - CaseExpr(ExprList *index, Expr *value); + CaseExpr(ExprList* index, Expr* value); virtual ~CaseExpr(); - ExprList *index() const { return index_; } - Expr *value() const { return value_; } + ExprList* index() const { return index_; } + Expr* value() const { return value_; } - bool HasReference(const ID *id) const; + bool HasReference(const ID* id) const; bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); private: - ExprList *index_; - Expr *value_; -}; + ExprList* index_; + Expr* value_; + }; -#endif // pac_expr_h +#endif // pac_expr_h diff --git a/tools/binpac/src/pac_exttype.cc b/tools/binpac/src/pac_exttype.cc index 65c89245f9..c048acc7a6 100644 --- a/tools/binpac/src/pac_exttype.cc +++ b/tools/binpac/src/pac_exttype.cc @@ -1,6 +1,7 @@ #include "pac_exttype.h" -#include "pac_id.h" + #include "pac_decl.h" +#include "pac_id.h" #include "pac_output.h" bool ExternType::DefineValueVar() const @@ -34,11 +35,9 @@ bool ExternType::ByteOrderSensitive() const return false; } -string ExternType::EvalMember(const ID *member_id) const +string ExternType::EvalMember(const ID* member_id) const { - return strfmt("%s%s", - ext_type_ == POINTER ? "->" : ".", - member_id->Name()); + return strfmt("%s%s", ext_type_ == POINTER ? "->" : ".", member_id->Name()); } void ExternType::GenInitCode(Output* out_cc, Env* env) @@ -58,27 +57,27 @@ void ExternType::GenDynamicSize(Output* out, Env* env, const DataPtr& data) ASSERT(0); } -Type *ExternType::DoClone() const - { - return new ExternType(id_->clone(), ext_type_); +Type* ExternType::DoClone() const + { + return new ExternType(id_->clone(), ext_type_); } // Definitions of pre-defined external types -#define EXTERNTYPE(name, ctype, exttype) ExternType *extern_type_##name = 0; +#define EXTERNTYPE(name, ctype, exttype) ExternType* extern_type_##name = 0; #include "pac_externtype.def" #undef EXTERNTYPE void ExternType::static_init() { - ID *id; + ID* id; // TypeDecl *decl; // decl = new TypeDecl(id, 0, extern_type_##name); -#define EXTERNTYPE(name, ctype, exttype) \ - id = new ID(#ctype); \ - extern_type_##name = new ExternType(id, ExternType::exttype); \ - Type::AddPredefinedType(#name, extern_type_##name); +#define EXTERNTYPE(name, ctype, exttype) \ + id = new ID(#ctype); \ + extern_type_##name = new ExternType(id, ExternType::exttype); \ + Type::AddPredefinedType(#name, extern_type_##name); #include "pac_externtype.def" #undef EXTERNTYPE } diff --git a/tools/binpac/src/pac_exttype.h b/tools/binpac/src/pac_exttype.h index a15ff6342e..8fe321a82c 100644 --- a/tools/binpac/src/pac_exttype.h +++ b/tools/binpac/src/pac_exttype.h @@ -9,41 +9,43 @@ // literally to the compiled code. class ExternType : public Type -{ + { public: - enum EXTType { PLAIN, NUMBER, POINTER }; - ExternType(const ID *id, EXTType ext_type) - : Type(EXTERN), - id_(id), - ext_type_(ext_type) {} + enum EXTType + { + PLAIN, + NUMBER, + POINTER + }; + ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) { } bool DefineValueVar() const; string DataTypeStr() const; - int StaticSize(Env *env) const; + int StaticSize(Env* env) const; bool ByteOrderSensitive() const; - string EvalMember(const ID *member_id) const; - bool IsNumericType() const { return ext_type_ == NUMBER; } - bool IsPointerType() const { return ext_type_ == POINTER; } + string EvalMember(const ID* member_id) const; + bool IsNumericType() const { return ext_type_ == NUMBER; } + bool IsPointerType() const { return ext_type_ == POINTER; } - void GenInitCode(Output *out_cc, Env *env); + void GenInitCode(Output* out_cc, Env* env); protected: - void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); - void GenDynamicSize(Output *out, Env *env, const DataPtr& data); + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); + void GenDynamicSize(Output* out, Env* env, const DataPtr& data); - Type *DoClone() const; + Type* DoClone() const; private: - const ID *id_; + const ID* id_; EXTType ext_type_; public: static void static_init(); -}; + }; -#define EXTERNTYPE(name, ctype, exttype) extern ExternType *extern_type_##name; +#define EXTERNTYPE(name, ctype, exttype) extern ExternType* extern_type_##name; #include "pac_externtype.def" #undef EXTERNTYPE -#endif // pac_exttype_h +#endif // pac_exttype_h diff --git a/tools/binpac/src/pac_field.cc b/tools/binpac/src/pac_field.cc index 7b7b337b1a..36205ba8a0 100644 --- a/tools/binpac/src/pac_field.cc +++ b/tools/binpac/src/pac_field.cc @@ -1,13 +1,13 @@ +#include "pac_field.h" + #include "pac_attr.h" #include "pac_common.h" #include "pac_exception.h" -#include "pac_field.h" #include "pac_id.h" #include "pac_type.h" -Field::Field(FieldType tof, int flags, ID *id, Type *type) - : DataDepElement(DataDepElement::FIELD), - tof_(tof), flags_(flags), id_(id), type_(type) +Field::Field(FieldType tof, int flags, ID* id, Type* type) + : DataDepElement(DataDepElement::FIELD), tof_(tof), flags_(flags), id_(id), type_(type) { decl_id_ = current_decl_id; field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name()); @@ -35,24 +35,22 @@ void Field::AddAttr(AttrList* attrs) delete_attrs = true; } - foreach(i, AttrList, attrs) + foreach (i, AttrList, attrs) ProcessAttr(*i); if ( delete_attrs ) delete attrs; } -void Field::ProcessAttr(Attr *a) +void Field::ProcessAttr(Attr* a) { switch ( a->type() ) { case ATTR_IF: - if ( tof() != LET_FIELD && - tof() != WITHINPUT_FIELD ) + if ( tof() != LET_FIELD && tof() != WITHINPUT_FIELD ) { - throw Exception(a, - "&if can only be applied to a " - "let field"); + throw Exception(a, "&if can only be applied to a " + "let field"); } break; default: @@ -76,7 +74,7 @@ int Field::ValueVarType() const return TEMP_VAR; } -void Field::Prepare(Env *env) +void Field::Prepare(Env* env) { if ( type_ ) { @@ -86,9 +84,7 @@ void Field::Prepare(Env *env) flags_ &= (~PUBLIC_READABLE); type_->set_value_var(id(), ValueVarType()); - type_->Prepare(env, - flags_ & TYPE_TO_BE_PARSED ? - Type::TO_BE_PARSED : 0); + type_->Prepare(env, flags_ & TYPE_TO_BE_PARSED ? Type::TO_BE_PARSED : 0); env->SetField(id(), this); } } @@ -109,7 +105,7 @@ void Field::GenPrivDecls(Output* out_h, Env* env) void Field::GenTempDecls(Output* out_h, Env* env) { // Generate temp field - if ( type_ && !(flags_ & CLASS_MEMBER) ) + if ( type_ && ! (flags_ & CLASS_MEMBER) ) type_->GenPrivDecls(out_h, env); } @@ -125,12 +121,12 @@ void Field::GenCleanUpCode(Output* out_cc, Env* env) type_->GenCleanUpCode(out_cc, env); } -bool Field::DoTraverse(DataDepVisitor *visitor) +bool Field::DoTraverse(DataDepVisitor* visitor) { // Check parameterized type if ( type_ && ! type_->Traverse(visitor) ) return false; - foreach(i, AttrList, attrs_) + foreach (i, AttrList, attrs_) if ( ! (*i)->Traverse(visitor) ) return false; return true; @@ -141,7 +137,7 @@ bool Field::RequiresAnalyzerContext() const // Check parameterized type if ( type_ && type_->RequiresAnalyzerContext() ) return true; - foreach(i, AttrList, attrs_) + foreach (i, AttrList, attrs_) if ( (*i)->RequiresAnalyzerContext() ) return true; return false; diff --git a/tools/binpac/src/pac_field.h b/tools/binpac/src/pac_field.h index 169c8110ec..bf95235aa6 100644 --- a/tools/binpac/src/pac_field.h +++ b/tools/binpac/src/pac_field.h @@ -6,30 +6,31 @@ // A "field" is a member of class. -enum FieldType { - CASE_FIELD, +enum FieldType + { + CASE_FIELD, CONTEXT_FIELD, FLOW_FIELD, - LET_FIELD, - PADDING_FIELD, + LET_FIELD, + PADDING_FIELD, PARAM_FIELD, - RECORD_FIELD, + RECORD_FIELD, PARSE_VAR_FIELD, PRIV_VAR_FIELD, PUB_VAR_FIELD, TEMP_VAR_FIELD, WITHINPUT_FIELD, -}; + }; class Field : public Object, public DataDepElement -{ + { public: - Field(FieldType tof, int flags, ID *id, Type *type); + Field(FieldType tof, int flags, ID* id, Type* type); // Field flags // Whether the field will be evaluated by calling the Parse() // function of the type - static const int TYPE_TO_BE_PARSED = 1; + static const int TYPE_TO_BE_PARSED = 1; static const int TYPE_NOT_TO_BE_PARSED = 0; // Whether the field is a member of the class or a temp @@ -43,17 +44,17 @@ public: virtual ~Field(); - FieldType tof() const { return tof_; } - const ID* id() const { return id_; } - Type *type() const { return type_; } - const ID* decl_id() const { return decl_id_; } + FieldType tof() const { return tof_; } + const ID* id() const { return id_; } + Type* type() const { return type_; } + const ID* decl_id() const { return decl_id_; } bool anonymous_field() const; void AddAttr(AttrList* attrs); // The field interface - virtual void ProcessAttr(Attr *attr); + virtual void ProcessAttr(Attr* attr); virtual void Prepare(Env* env); virtual void GenPubDecls(Output* out, Env* env); @@ -69,16 +70,16 @@ protected: int ValueVarType() const; bool ToBeParsed() const; - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); protected: FieldType tof_; int flags_; ID* id_; - Type *type_; + Type* type_; const ID* decl_id_; string field_id_str_; AttrList* attrs_; -}; + }; -#endif // pac_field_h +#endif // pac_field_h diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index 1a93b4b99f..fc0fd0a3eb 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -1,3 +1,5 @@ +#include "pac_flow.h" + #include "pac_analyzer.h" #include "pac_conn.h" #include "pac_context.h" @@ -7,17 +9,13 @@ #include "pac_exception.h" #include "pac_expr.h" #include "pac_exttype.h" -#include "pac_flow.h" #include "pac_output.h" #include "pac_param.h" #include "pac_paramtype.h" #include "pac_type.h" #include "pac_varfield.h" - -FlowDecl::FlowDecl(ID *id, - ParamList *params, - AnalyzerElementList *elemlist) +FlowDecl::FlowDecl(ID* id, ParamList* params, AnalyzerElementList* elemlist) : AnalyzerDecl(id, FLOW, params) { dataunit_ = 0; @@ -32,9 +30,9 @@ FlowDecl::~FlowDecl() delete dataunit_; } -ParameterizedType *FlowDecl::flow_buffer_type_ = 0; +ParameterizedType* FlowDecl::flow_buffer_type_ = 0; -ParameterizedType *FlowDecl::flow_buffer_type() +ParameterizedType* FlowDecl::flow_buffer_type() { if ( ! flow_buffer_type_ ) { @@ -43,24 +41,21 @@ ParameterizedType *FlowDecl::flow_buffer_type() return flow_buffer_type_; } -void FlowDecl::AddBaseClass(vector *base_classes) const +void FlowDecl::AddBaseClass(vector* base_classes) const { - base_classes->push_back("binpac::FlowAnalyzer"); - } - -void FlowDecl::ProcessFlowElement(AnalyzerFlow *flow_elem) - { - throw Exception( - flow_elem, - "flow should be defined in only a connection declaration"); + base_classes->push_back("binpac::FlowAnalyzer"); } -void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) +void FlowDecl::ProcessFlowElement(AnalyzerFlow* flow_elem) + { + throw Exception(flow_elem, "flow should be defined in only a connection declaration"); + } + +void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) { if ( dataunit_ ) { - throw Exception(dataunit_elem, - "dataunit already defined"); + throw Exception(dataunit_elem, "dataunit already defined"); } dataunit_ = dataunit_elem; @@ -68,17 +63,15 @@ void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) { dataunit_->data_type()->MarkIncrementalInput(); - flow_buffer_var_field_ = new PubVarField( - flow_buffer_id->clone(), - FlowDecl::flow_buffer_type()->Clone()); + flow_buffer_var_field_ = new PubVarField(flow_buffer_id->clone(), + FlowDecl::flow_buffer_type()->Clone()); type_->AddField(flow_buffer_var_field_); ASSERT(AnalyzerContextDecl::current_analyzer_context()); AnalyzerContextDecl::current_analyzer_context()->AddFlowBuffer(); // Add an argument to the context initiation - dataunit_->context_type()->AddParamArg( - new Expr(flow_buffer_var_field_->id()->clone())); + dataunit_->context_type()->AddParamArg(new Expr(flow_buffer_var_field_->id()->clone())); } } @@ -87,28 +80,25 @@ void FlowDecl::Prepare() // Add the connection parameter if ( ! conn_decl_ ) { - throw Exception(this, - "no connection is not declared for the flow"); + throw Exception(this, "no connection is not declared for the flow"); } if ( ! params_ ) params_ = new ParamList(); - params_->insert(params_->begin(), - new Param(connection_id->clone(), - conn_decl_->DataType())); + params_->insert(params_->begin(), new Param(connection_id->clone(), conn_decl_->DataType())); AnalyzerDecl::Prepare(); dataunit_->Prepare(env_); } -void FlowDecl::GenPubDecls(Output *out_h, Output *out_cc) +void FlowDecl::GenPubDecls(Output* out_h, Output* out_cc) { AnalyzerDecl::GenPubDecls(out_h, out_cc); } -void FlowDecl::GenPrivDecls(Output *out_h, Output *out_cc) +void FlowDecl::GenPrivDecls(Output* out_h, Output* out_cc) { // Declare the data unit dataunit_->dataunit_var_field()->GenPrivDecls(out_h, env_); @@ -119,14 +109,12 @@ void FlowDecl::GenPrivDecls(Output *out_h, Output *out_cc) AnalyzerDecl::GenPrivDecls(out_h, out_cc); } -void FlowDecl::GenInitCode(Output *out_cc) +void FlowDecl::GenInitCode(Output* out_cc) { AnalyzerDecl::GenInitCode(out_cc); - out_cc->println("%s = 0;", - env_->LValue(dataunit_id)); - out_cc->println("%s = 0;", - env_->LValue(analyzer_context_id)); + out_cc->println("%s = 0;", env_->LValue(dataunit_id)); + out_cc->println("%s = 0;", env_->LValue(analyzer_context_id)); if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { @@ -135,13 +123,13 @@ void FlowDecl::GenInitCode(Output *out_cc) } } -void FlowDecl::GenCleanUpCode(Output *out_cc) +void FlowDecl::GenCleanUpCode(Output* out_cc) { GenDeleteDataUnit(out_cc); AnalyzerDecl::GenCleanUpCode(out_cc); } -void FlowDecl::GenEOFFunc(Output *out_h, Output *out_cc) +void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc) { string proto = strfmt("%s()", kFlowEOF); @@ -151,23 +139,22 @@ void FlowDecl::GenEOFFunc(Output *out_h, Output *out_cc) out_cc->inc_indent(); out_cc->println("{"); - foreach(i, AnalyzerHelperList, eof_helpers_) + foreach (i, AnalyzerHelperList, eof_helpers_) { (*i)->GenCode(0, out_cc, this); } if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { - out_cc->println("%s->set_eof();", - env_->LValue(flow_buffer_id)); + out_cc->println("%s->set_eof();", env_->LValue(flow_buffer_id)); out_cc->println("%s(0, 0);", kNewData); } - + out_cc->println("}"); out_cc->dec_indent(); } -void FlowDecl::GenGapFunc(Output *out_h, Output *out_cc) +void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc) { string proto = strfmt("%s(int gap_length)", kFlowGap); @@ -179,24 +166,20 @@ void FlowDecl::GenGapFunc(Output *out_h, Output *out_cc) if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { - out_cc->println("%s->NewGap(gap_length);", - env_->LValue(flow_buffer_id)); + out_cc->println("%s->NewGap(gap_length);", env_->LValue(flow_buffer_id)); } - + out_cc->println("}"); out_cc->dec_indent(); } -void FlowDecl::GenProcessFunc(Output *out_h, Output *out_cc) +void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc) { env_->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); env_->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); - string proto = - strfmt("%s(const_byteptr %s, const_byteptr %s)", - kNewData, - env_->LValue(begin_of_data), - env_->LValue(end_of_data)); + string proto = strfmt("%s(const_byteptr %s, const_byteptr %s)", kNewData, + env_->LValue(begin_of_data), env_->LValue(end_of_data)); out_h->println("void %s;", proto.c_str()); @@ -232,8 +215,7 @@ void FlowDecl::GenProcessFunc(Output *out_h, Output *out_cc) GenCleanUpCode(out_cc); if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { - out_cc->println("%s->DiscardData();", - env_->LValue(flow_buffer_id)); + out_cc->println("%s->DiscardData();", env_->LValue(flow_buffer_id)); } out_cc->println("throw;"); out_cc->println("}"); @@ -244,21 +226,19 @@ void FlowDecl::GenProcessFunc(Output *out_h, Output *out_cc) out_cc->println(""); } -void FlowDecl::GenNewDataUnit(Output *out_cc) +void FlowDecl::GenNewDataUnit(Output* out_cc) { - Type *unit_datatype = dataunit_->data_type(); + Type* unit_datatype = dataunit_->data_type(); // dataunit_->data_type()->GenPreParsing(out_cc, env_); dataunit_->GenNewDataUnit(out_cc, env_); - if ( unit_datatype->buffer_input() && - unit_datatype->buffer_mode() == Type::BUFFER_BY_LENGTH ) + if ( unit_datatype->buffer_input() && unit_datatype->buffer_mode() == Type::BUFFER_BY_LENGTH ) { - out_cc->println("%s->NewFrame(0, false);", - env_->LValue(flow_buffer_id)); + out_cc->println("%s->NewFrame(0, false);", env_->LValue(flow_buffer_id)); } dataunit_->GenNewContext(out_cc, env_); } -void FlowDecl::GenDeleteDataUnit(Output *out_cc) +void FlowDecl::GenDeleteDataUnit(Output* out_cc) { // Do not just delete dataunit, because we may just want to Unref it. // out_cc->println("delete %s;", env_->LValue(dataunit_id)); @@ -266,28 +246,24 @@ void FlowDecl::GenDeleteDataUnit(Output *out_cc) dataunit_->context_type()->GenCleanUpCode(out_cc, env_); } -void FlowDecl::GenCodeFlowUnit(Output *out_cc) +void FlowDecl::GenCodeFlowUnit(Output* out_cc) { - Type *unit_datatype = dataunit_->data_type(); + Type* unit_datatype = dataunit_->data_type(); - out_cc->println("%s->NewData(%s, %s);", - env_->LValue(flow_buffer_id), - env_->RValue(begin_of_data), - env_->RValue(end_of_data)); + out_cc->println("%s->NewData(%s, %s);", env_->LValue(flow_buffer_id), + env_->RValue(begin_of_data), env_->RValue(end_of_data)); - out_cc->println("while ( %s->data_available() && ", - env_->LValue(flow_buffer_id)); + out_cc->println("while ( %s->data_available() && ", env_->LValue(flow_buffer_id)); out_cc->inc_indent(); out_cc->println("( !%s->have_pending_request() || %s->ready() ) )", - env_->LValue(flow_buffer_id), env_->LValue(flow_buffer_id)); + env_->LValue(flow_buffer_id), env_->LValue(flow_buffer_id)); out_cc->println("{"); // Generate a new dataunit if necessary out_cc->println("if ( ! %s )", env_->LValue(dataunit_id)); out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("BINPAC_ASSERT(!%s);", - env_->LValue(analyzer_context_id)); + out_cc->println("BINPAC_ASSERT(!%s);", env_->LValue(analyzer_context_id)); GenNewDataUnit(out_cc); out_cc->println("}"); out_cc->dec_indent(); @@ -295,8 +271,7 @@ void FlowDecl::GenCodeFlowUnit(Output *out_cc) DataPtr data(env_, 0, 0); unit_datatype->GenParseCode(out_cc, env_, data, 0); - out_cc->println("if ( %s )", - unit_datatype->parsing_complete(env_).c_str()); + out_cc->println("if ( %s )", unit_datatype->parsing_complete(env_).c_str()); out_cc->inc_indent(); out_cc->println("{"); out_cc->println("// Clean up the flow unit after parsing"); @@ -308,8 +283,7 @@ void FlowDecl::GenCodeFlowUnit(Output *out_cc) out_cc->inc_indent(); out_cc->println("{"); out_cc->println("// Resume upon next input segment"); - out_cc->println("BINPAC_ASSERT(!%s->ready());", - env_->RValue(flow_buffer_id)); + out_cc->println("BINPAC_ASSERT(!%s->ready());", env_->RValue(flow_buffer_id)); out_cc->println("break;"); out_cc->println("}"); out_cc->dec_indent(); @@ -318,14 +292,12 @@ void FlowDecl::GenCodeFlowUnit(Output *out_cc) out_cc->dec_indent(); } -void FlowDecl::GenCodeDatagram(Output *out_cc) +void FlowDecl::GenCodeDatagram(Output* out_cc) { - Type *unit_datatype = dataunit_->data_type(); + Type* unit_datatype = dataunit_->data_type(); GenNewDataUnit(out_cc); - string parse_params = strfmt("%s, %s", - env_->RValue(begin_of_data), - env_->RValue(end_of_data)); + string parse_params = strfmt("%s, %s", env_->RValue(begin_of_data), env_->RValue(end_of_data)); if ( RequiresAnalyzerContext::compute(unit_datatype) ) { diff --git a/tools/binpac/src/pac_flow.h b/tools/binpac/src/pac_flow.h index 652f206992..20397aefe8 100644 --- a/tools/binpac/src/pac_flow.h +++ b/tools/binpac/src/pac_flow.h @@ -4,44 +4,44 @@ #include "pac_analyzer.h" class FlowDecl : public AnalyzerDecl -{ + { public: - FlowDecl(ID *flow_id, ParamList *params, AnalyzerElementList *elemlist); + FlowDecl(ID* flow_id, ParamList* params, AnalyzerElementList* elemlist); ~FlowDecl(); void Prepare(); - void set_conn_decl(ConnDecl *c) { conn_decl_ = c; } + void set_conn_decl(ConnDecl* c) { conn_decl_ = c; } - static ParameterizedType *flow_buffer_type(); + static ParameterizedType* flow_buffer_type(); protected: - void AddBaseClass(vector *base_classes) const; + void AddBaseClass(vector* base_classes) const; - void GenInitCode(Output *out_cc); - void GenCleanUpCode(Output *out_cc); - void GenProcessFunc(Output *out_h, Output *out_cc); - void GenEOFFunc(Output *out_h, Output *out_cc); - void GenGapFunc(Output *out_h, Output *out_cc); + void GenInitCode(Output* out_cc); + void GenCleanUpCode(Output* out_cc); + void GenProcessFunc(Output* out_h, Output* out_cc); + void GenEOFFunc(Output* out_h, Output* out_cc); + void GenGapFunc(Output* out_h, Output* out_cc); - void GenPubDecls(Output *out_h, Output *out_cc); - void GenPrivDecls(Output *out_h, Output *out_cc); + void GenPubDecls(Output* out_h, Output* out_cc); + void GenPrivDecls(Output* out_h, Output* out_cc); - void ProcessFlowElement(AnalyzerFlow *flow_elem); - void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem); + void ProcessFlowElement(AnalyzerFlow* flow_elem); + void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem); private: - void GenNewDataUnit(Output *out_cc); - void GenDeleteDataUnit(Output *out_cc); - void GenCodeFlowUnit(Output *out_cc); - void GenCodeDatagram(Output *out_cc); + void GenNewDataUnit(Output* out_cc); + void GenDeleteDataUnit(Output* out_cc); + void GenCodeFlowUnit(Output* out_cc); + void GenCodeDatagram(Output* out_cc); - AnalyzerDataUnit *dataunit_; - ConnDecl *conn_decl_; + AnalyzerDataUnit* dataunit_; + ConnDecl* conn_decl_; - Field *flow_buffer_var_field_; + Field* flow_buffer_var_field_; - static ParameterizedType *flow_buffer_type_; -}; + static ParameterizedType* flow_buffer_type_; + }; -#endif // pac_flow_h +#endif // pac_flow_h diff --git a/tools/binpac/src/pac_func.cc b/tools/binpac/src/pac_func.cc index 8bde6e10f6..40894621cb 100644 --- a/tools/binpac/src/pac_func.cc +++ b/tools/binpac/src/pac_func.cc @@ -1,12 +1,13 @@ +#include "pac_func.h" + #include "pac_embedded.h" #include "pac_expr.h" -#include "pac_func.h" #include "pac_output.h" #include "pac_param.h" #include "pac_type.h" -Function::Function(ID *id, Type *type, ParamList *params) - : id_(id), type_(type), params_(params), expr_(0), code_(0) +Function::Function(ID* id, Type* type, ParamList* params) + : id_(id), type_(type), params_(params), expr_(0), code_(0) { analyzer_decl_ = 0; env_ = 0; @@ -22,16 +23,16 @@ Function::~Function() delete code_; } -void Function::Prepare(Env *env) +void Function::Prepare(Env* env) { env->AddID(id_, FUNC_ID, type_); env->SetEvaluated(id_); env_ = new Env(env, this); - foreach(i, ParamList, params_) + foreach (i, ParamList, params_) { - Param *p = *i; + Param* p = *i; env_->AddID(p->id(), FUNC_PARAM, p->type()); env_->SetEvaluated(p->id()); } @@ -44,22 +45,17 @@ void Function::GenForwardDeclaration(Output* out_h) void Function::GenCode(Output* out_h, Output* out_cc) { - out_h->println("%s %s(%s);", - type_->DataTypeStr().c_str(), - id_->Name(), - ParamDecls(params_).c_str()); + out_h->println("%s %s(%s);", type_->DataTypeStr().c_str(), id_->Name(), + ParamDecls(params_).c_str()); string class_str = ""; if ( analyzer_decl_ ) class_str = strfmt("%s::", analyzer_decl_->id()->Name()); - string proto_str = strfmt("%s %s%s(%s)", - type_->DataTypeStr().c_str(), - class_str.c_str(), - id_->Name(), - ParamDecls(params_).c_str()); + string proto_str = strfmt("%s %s%s(%s)", type_->DataTypeStr().c_str(), class_str.c_str(), + id_->Name(), ParamDecls(params_).c_str()); - ASSERT(!(expr_ && code_)); + ASSERT(! (expr_ && code_)); if ( expr_ ) { @@ -68,9 +64,8 @@ void Function::GenCode(Output* out_h, Output* out_cc) out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("return static_cast<%s>(%s);", - type_->DataTypeStr().c_str(), - expr_->EvalExpr(out_cc, env_)); + out_cc->println("return static_cast<%s>(%s);", type_->DataTypeStr().c_str(), + expr_->EvalExpr(out_cc, env_)); out_cc->println("}"); out_cc->dec_indent(); @@ -92,8 +87,7 @@ void Function::GenCode(Output* out_h, Output* out_cc) out_cc->println(""); } -FuncDecl::FuncDecl(Function *function) - : Decl(function->id()->clone(), FUNC), function_(function) +FuncDecl::FuncDecl(Function* function) : Decl(function->id()->clone(), FUNC), function_(function) { function_->Prepare(global_env()); } @@ -103,21 +97,19 @@ FuncDecl::~FuncDecl() delete function_; } -void FuncDecl::Prepare() - { - } +void FuncDecl::Prepare() { } -void FuncDecl::GenForwardDeclaration(Output *out_h) +void FuncDecl::GenForwardDeclaration(Output* out_h) { function_->GenForwardDeclaration(out_h); } -void FuncDecl::GenCode(Output *out_h, Output *out_cc) +void FuncDecl::GenCode(Output* out_h, Output* out_cc) { function_->GenCode(out_h, out_cc); } -AnalyzerFunction::AnalyzerFunction(Function *function) +AnalyzerFunction::AnalyzerFunction(Function* function) : AnalyzerElement(FUNCTION), function_(function) { } diff --git a/tools/binpac/src/pac_func.h b/tools/binpac/src/pac_func.h index df862323bb..249629f6de 100644 --- a/tools/binpac/src/pac_func.h +++ b/tools/binpac/src/pac_func.h @@ -1,68 +1,68 @@ #ifndef pac_func_h #define pac_func_h -#include "pac_decl.h" #include "pac_analyzer.h" +#include "pac_decl.h" class Function : public Object -{ + { public: - Function(ID *id, Type *type, ParamList *params); + Function(ID* id, Type* type, ParamList* params); ~Function(); - ID *id() const { return id_; } + ID* id() const { return id_; } - AnalyzerDecl *analyzer_decl() const { return analyzer_decl_; } - void set_analyzer_decl(AnalyzerDecl *decl) { analyzer_decl_ = decl; } + AnalyzerDecl* analyzer_decl() const { return analyzer_decl_; } + void set_analyzer_decl(AnalyzerDecl* decl) { analyzer_decl_ = decl; } - Expr *expr() const { return expr_; } - void set_expr(Expr *expr) { expr_ = expr; } + Expr* expr() const { return expr_; } + void set_expr(Expr* expr) { expr_ = expr; } - EmbeddedCode *code() const { return code_; } - void set_code(EmbeddedCode *code) { code_ = code; } + EmbeddedCode* code() const { return code_; } + void set_code(EmbeddedCode* code) { code_ = code; } - void Prepare(Env *env); - void GenForwardDeclaration(Output *out_h); - void GenCode(Output *out_h, Output *out_cc); + void Prepare(Env* env); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); private: - Env *env_; + Env* env_; - ID *id_; - Type *type_; - ParamList *params_; + ID* id_; + Type* type_; + ParamList* params_; - AnalyzerDecl *analyzer_decl_; + AnalyzerDecl* analyzer_decl_; - Expr *expr_; - EmbeddedCode *code_; -}; + Expr* expr_; + EmbeddedCode* code_; + }; class FuncDecl : public Decl -{ + { public: - FuncDecl(Function *function); + FuncDecl(Function* function); ~FuncDecl(); - Function *function() const { return function_; } + Function* function() const { return function_; } void Prepare(); - void GenForwardDeclaration(Output *out_h); - void GenCode(Output *out_h, Output *out_cc); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); private: - Function *function_; -}; + Function* function_; + }; class AnalyzerFunction : public AnalyzerElement -{ + { public: - AnalyzerFunction(Function *function); + AnalyzerFunction(Function* function); - Function *function() const { return function_; } + Function* function() const { return function_; } private: - Function *function_; -}; + Function* function_; + }; #endif // pac_func_h diff --git a/tools/binpac/src/pac_id.cc b/tools/binpac/src/pac_id.cc index 447348e978..1d4002b114 100644 --- a/tools/binpac/src/pac_id.cc +++ b/tools/binpac/src/pac_id.cc @@ -1,56 +1,57 @@ +#include "pac_id.h" + #include "pac_exception.h" #include "pac_expr.h" #include "pac_exttype.h" #include "pac_field.h" -#include "pac_id.h" #include "pac_type.h" #include "pac_utils.h" -const ID *default_value_var = 0; -const ID *null_id = 0; -const ID *null_byteseg_id = 0; -const ID *null_decl_id = 0; -const ID *begin_of_data = 0; -const ID *end_of_data = 0; -const ID *len_of_data = 0; -const ID *byteorder_id = 0; -const ID *bigendian_id = 0; -const ID *littleendian_id = 0; -const ID *unspecified_byteorder_id = 0; -const ID *const_true_id = 0; -const ID *const_false_id = 0; -const ID *analyzer_context_id = 0; -const ID *context_macro_id = 0; -const ID *this_id = 0; -const ID *sourcedata_id = 0; -const ID *connection_id = 0; -const ID *upflow_id = 0; -const ID *downflow_id = 0; -const ID *dataunit_id = 0; -const ID *flow_buffer_id = 0; -const ID *element_macro_id = 0; -const ID *input_macro_id = 0; -const ID *cxt_connection_id = 0; -const ID *cxt_flow_id = 0; -const ID *parsing_state_id = 0; -const ID *buffering_state_id = 0; +const ID* default_value_var = 0; +const ID* null_id = 0; +const ID* null_byteseg_id = 0; +const ID* null_decl_id = 0; +const ID* begin_of_data = 0; +const ID* end_of_data = 0; +const ID* len_of_data = 0; +const ID* byteorder_id = 0; +const ID* bigendian_id = 0; +const ID* littleendian_id = 0; +const ID* unspecified_byteorder_id = 0; +const ID* const_true_id = 0; +const ID* const_false_id = 0; +const ID* analyzer_context_id = 0; +const ID* context_macro_id = 0; +const ID* this_id = 0; +const ID* sourcedata_id = 0; +const ID* connection_id = 0; +const ID* upflow_id = 0; +const ID* downflow_id = 0; +const ID* dataunit_id = 0; +const ID* flow_buffer_id = 0; +const ID* element_macro_id = 0; +const ID* input_macro_id = 0; +const ID* cxt_connection_id = 0; +const ID* cxt_flow_id = 0; +const ID* parsing_state_id = 0; +const ID* buffering_state_id = 0; int ID::anonymous_id_seq = 0; -ID *ID::NewAnonymousID(const string &prefix) +ID* ID::NewAnonymousID(const string& prefix) { - ID *id = new ID(strfmt("%s%03d", prefix.c_str(), ++anonymous_id_seq)); + ID* id = new ID(strfmt("%s%03d", prefix.c_str(), ++anonymous_id_seq)); id->anonymous_id_ = true; return id; } -IDRecord::IDRecord(Env *arg_env, const ID* arg_id, IDType arg_id_type) +IDRecord::IDRecord(Env* arg_env, const ID* arg_id, IDType arg_id_type) : env(arg_env), id(arg_id), id_type(arg_id_type) { eval = 0; evaluated = in_evaluation = false; - setfunc = ""; // except for STATE_VAR - switch (id_type) + setfunc = ""; // except for STATE_VAR + switch ( id_type ) { case MEMBER_VAR: rvalue = strfmt("%s()", id->Name()); @@ -96,9 +97,7 @@ IDRecord::IDRecord(Env *arg_env, const ID* arg_id, IDType arg_id_type) macro = 0; } -IDRecord::~IDRecord() - { - } +IDRecord::~IDRecord() { } void IDRecord::SetConstant(int c) { @@ -107,20 +106,20 @@ void IDRecord::SetConstant(int c) constant = c; } -bool IDRecord::GetConstant(int *pc) const - { - if ( constant_set ) +bool IDRecord::GetConstant(int* pc) const + { + if ( constant_set ) *pc = constant; return constant_set; } -void IDRecord::SetMacro(Expr *e) +void IDRecord::SetMacro(Expr* e) { ASSERT(id_type == MACRO); macro = e; } -Expr *IDRecord::GetMacro() const +Expr* IDRecord::GetMacro() const { ASSERT(id_type == MACRO); return macro; @@ -187,7 +186,7 @@ Env::~Env() } } -void Env::AddID(const ID* id, IDType id_type, Type *data_type) +void Env::AddID(const ID* id, IDType id_type, Type* data_type) { DEBUG_MSG("To add ID `%s'...\n", id->Name()); id_map_t::iterator it = id_map.find(id); @@ -202,25 +201,25 @@ void Env::AddID(const ID* id, IDType id_type, Type *data_type) SetDataType(id, data_type); } -void Env::AddConstID(const ID* id, const int c, Type *type) +void Env::AddConstID(const ID* id, const int c, Type* type) { if ( ! type ) type = extern_type_int; AddID(id, CONST, type); SetConstant(id, c); - SetEvaluated(id); // a constant is always evaluated + SetEvaluated(id); // a constant is always evaluated } -void Env::AddMacro(const ID *id, Expr *macro) +void Env::AddMacro(const ID* id, Expr* macro) { AddID(id, MACRO, macro->DataType(this)); SetMacro(id, macro); SetEvaluated(id); } -ID *Env::AddTempID(Type *type) +ID* Env::AddTempID(Type* type) { - ID *id = ID::NewAnonymousID("t_var_"); + ID* id = ID::NewAnonymousID("t_var_"); AddID(id, TEMP_VAR, type); return id; } @@ -249,7 +248,7 @@ IDType Env::GetIDType(const ID* id) const const char* Env::RValue(const ID* id) const { - IDRecord *r = lookup(id, true, false); + IDRecord* r = lookup(id, true, false); if ( r ) return r->RValue(); else @@ -273,14 +272,14 @@ void Env::SetEvalMethod(const ID* id, Evaluatable* eval) void Env::Evaluate(Output* out, const ID* id) { - IDRecord *r = lookup(id, true, !allow_undefined_id()); + IDRecord* r = lookup(id, true, ! allow_undefined_id()); if ( r ) r->Evaluate(out, this); } bool Env::Evaluated(const ID* id) const { - IDRecord *r = lookup(id, true, !allow_undefined_id()); + IDRecord* r = lookup(id, true, ! allow_undefined_id()); if ( r ) return r->Evaluated(); else @@ -292,23 +291,20 @@ void Env::SetEvaluated(const ID* id, bool v) { if ( in_branch() ) { - Field *f = GetField(id); - if (f && f->tof() == LET_FIELD) + Field* f = GetField(id); + if ( f && f->tof() == LET_FIELD ) { - throw Exception( - context_object_, - strfmt("INTERNAL ERROR: " - "evaluating let field '%s' in a branch! " - "To work around this problem, " - "add '&requires(%s)' to the case type. " - "Sorry for the inconvenience.\n", - id->Name(), - id->Name())); + throw Exception(context_object_, strfmt("INTERNAL ERROR: " + "evaluating let field '%s' in a branch! " + "To work around this problem, " + "add '&requires(%s)' to the case type. " + "Sorry for the inconvenience.\n", + id->Name(), id->Name())); ASSERT(0); } } - IDRecord *r = lookup(id, false, false); + IDRecord* r = lookup(id, false, false); if ( r ) r->SetEvaluated(v); else if ( parent ) @@ -334,16 +330,16 @@ void Env::SetDataType(const ID* id, Type* type) Type* Env::GetDataType(const ID* id) const { - IDRecord *r = lookup(id, true, false); + IDRecord* r = lookup(id, true, false); if ( r ) return r->GetDataType(); else return 0; } -string Env::DataTypeStr(const ID *id) const +string Env::DataTypeStr(const ID* id) const { - Type *type = GetDataType(id); + Type* type = GetDataType(id); if ( ! type ) throw Exception(id, "data type not defined"); return type->DataTypeStr(); @@ -365,7 +361,7 @@ bool Env::GetConstant(const ID* id, int* pc) const return false; } -void Env::SetMacro(const ID* id, Expr *macro) +void Env::SetMacro(const ID* id, Expr* macro) { lookup(id, true, true)->SetMacro(macro); } @@ -409,7 +405,7 @@ void init_builtin_identifiers() Env* global_env() { - static Env *the_global_env = 0; + static Env* the_global_env = 0; if ( ! the_global_env ) { @@ -436,7 +432,7 @@ Env* global_env() return the_global_env; } -string set_function(const ID *id) +string set_function(const ID* id) { return strfmt("set_%s", id->Name()); } diff --git a/tools/binpac/src/pac_id.h b/tools/binpac/src/pac_id.h index fc70f9531d..2cfdbfbd94 100644 --- a/tools/binpac/src/pac_id.h +++ b/tools/binpac/src/pac_id.h @@ -10,11 +10,11 @@ using namespace std; #include "pac_utils.h" // Classes handling identifiers. -// +// // ID -- name and location of definition of an ID // -// IDRecord -- association of an ID, its definition type (const, global, temp, -// member, or union member), and its evaluation method. +// IDRecord -- association of an ID, its definition type (const, global, temp, +// member, or union member), and its evaluation method. // // Evaluatable -- interface for a variable or a field that needs be evaluated // before referenced. @@ -22,7 +22,8 @@ using namespace std; // Env -- a mapping from ID names to their L/R-value expressions and evaluation // methods. -enum IDType { +enum IDType + { CONST, GLOBAL_VAR, TEMP_VAR, @@ -33,7 +34,7 @@ enum IDType { MACRO, FUNC_ID, FUNC_PARAM, -}; + }; class ID; class IDRecord; @@ -41,206 +42,201 @@ class Env; class Evaluatable; class ID : public Object -{ + { public: - ID(string arg_name) - : name(arg_name), anonymous_id_(false) + ID(string arg_name) : name(arg_name), anonymous_id_(false) { locname = nfmt("%s:%s", Location(), Name()); } - ~ID() - { - delete [] locname; - } + ~ID() { delete[] locname; } - bool operator==(ID const &x) const { return name == x.Name(); } + bool operator==(ID const& x) const { return name == x.Name(); } - const char *Name() const { return name.c_str(); } - const char *LocName() const { return locname; } - bool is_anonymous() const { return anonymous_id_; } + const char* Name() const { return name.c_str(); } + const char* LocName() const { return locname; } + bool is_anonymous() const { return anonymous_id_; } - ID *clone() const { return new ID(Name()); } + ID* clone() const { return new ID(Name()); } protected: string name; bool anonymous_id_; - char *locname; + char* locname; friend class ID_ptr_cmp; public: - static ID *NewAnonymousID(const string &prefix); + static ID* NewAnonymousID(const string& prefix); + private: static int anonymous_id_seq; -}; + }; // A comparison operator for pointers to ID's. class ID_ptr_cmp -{ + { public: - bool operator()(const ID *const & id1, const ID *const & id2) const + bool operator()(const ID* const& id1, const ID* const& id2) const { ASSERT(id1); ASSERT(id2); return id1->name < id2->name; } -}; + }; class IDRecord -{ + { public: - IDRecord(Env *env, const ID *id, IDType id_type); + IDRecord(Env* env, const ID* id, IDType id_type); ~IDRecord(); - IDType GetType() const { return id_type; } + IDType GetType() const { return id_type; } - void SetDataType(Type *type) { data_type = type; } - Type *GetDataType() const { return data_type; } + void SetDataType(Type* type) { data_type = type; } + Type* GetDataType() const { return data_type; } - void SetEvalMethod(Evaluatable *arg_eval) { eval = arg_eval; } - void Evaluate(Output *out, Env *env); + void SetEvalMethod(Evaluatable* arg_eval) { eval = arg_eval; } + void Evaluate(Output* out, Env* env); void SetEvaluated(bool v); - bool Evaluated() const { return evaluated; } + bool Evaluated() const { return evaluated; } - void SetField(Field *f) { field = f; } - Field *GetField() const { return field; } + void SetField(Field* f) { field = f; } + Field* GetField() const { return field; } - void SetConstant(int c); - bool GetConstant(int *pc) const; + void SetConstant(int c); + bool GetConstant(int* pc) const; - void SetMacro(Expr *expr); - Expr *GetMacro() const; + void SetMacro(Expr* expr); + Expr* GetMacro() const; - const char * RValue() const; - const char * LValue() const; + const char* RValue() const; + const char* LValue() const; protected: - Env *env; - const ID *id; + Env* env; + const ID* id; IDType id_type; string rvalue; string lvalue; string setfunc; - Type *data_type; + Type* data_type; - Field *field; + Field* field; int constant; bool constant_set; - Expr *macro; + Expr* macro; bool evaluated; - bool in_evaluation; // to detect cyclic dependence - Evaluatable *eval; -}; + bool in_evaluation; // to detect cyclic dependence + Evaluatable* eval; + }; class Evaluatable -{ + { public: - virtual ~Evaluatable() {} - virtual void GenEval(Output *out, Env *env) = 0; -}; + virtual ~Evaluatable() { } + virtual void GenEval(Output* out, Env* env) = 0; + }; class Env -{ + { public: - Env(Env *parent_env, Object *context_object); + Env(Env* parent_env, Object* context_object); ~Env(); - bool allow_undefined_id() const { return allow_undefined_id_; } - void set_allow_undefined_id(bool x) { allow_undefined_id_ = x; } + bool allow_undefined_id() const { return allow_undefined_id_; } + void set_allow_undefined_id(bool x) { allow_undefined_id_ = x; } - bool in_branch() const { return in_branch_; } - void set_in_branch(bool x) { in_branch_ = x; } + bool in_branch() const { return in_branch_; } + void set_in_branch(bool x) { in_branch_ = x; } - void AddID(const ID *id, IDType id_type, Type *type); - void AddConstID(const ID *id, const int c, Type *type = 0); - void AddMacro(const ID *id, Expr *expr); + void AddID(const ID* id, IDType id_type, Type* type); + void AddConstID(const ID* id, const int c, Type* type = 0); + void AddMacro(const ID* id, Expr* expr); // Generate a temp ID with a unique name - ID *AddTempID(Type *type); + ID* AddTempID(Type* type); - IDType GetIDType(const ID *id) const; - const char * RValue(const ID *id) const; - const char * LValue(const ID *id) const; + IDType GetIDType(const ID* id) const; + const char* RValue(const ID* id) const; + const char* LValue(const ID* id) const; // const char *SetFunc(const ID *id) const; // Set evaluation method for the ID - void SetEvalMethod(const ID *id, Evaluatable *eval); + void SetEvalMethod(const ID* id, Evaluatable* eval); // Evaluate the ID according to the evaluation method. It // assumes the ID has an evaluation emthod. It does nothing // if the ID has already been evaluated. - void Evaluate(Output *out, const ID *id); + void Evaluate(Output* out, const ID* id); // Whether the ID has already been evaluated. - bool Evaluated(const ID *id) const; + bool Evaluated(const ID* id) const; // Set the ID as evaluated (or not). - void SetEvaluated(const ID *id, bool v = true); + void SetEvaluated(const ID* id, bool v = true); - void SetField(const ID *id, Field *field); - Field *GetField(const ID *id) const; + void SetField(const ID* id, Field* field); + Field* GetField(const ID* id) const; - bool GetConstant(const ID *id, int *pc) const; + bool GetConstant(const ID* id, int* pc) const; - Expr *GetMacro(const ID *id) const; + Expr* GetMacro(const ID* id) const; - Type *GetDataType(const ID *id) const; + Type* GetDataType(const ID* id) const; - string DataTypeStr(const ID *id) const; + string DataTypeStr(const ID* id) const; protected: - IDRecord *lookup(const ID *id, - bool recursive, - bool raise_exception) const; + IDRecord* lookup(const ID* id, bool recursive, bool raise_exception) const; - void SetDataType(const ID *id, Type *type); - void SetConstant(const ID *id, int constant); - void SetMacro(const ID *id, Expr *macro); + void SetDataType(const ID* id, Type* type); + void SetConstant(const ID* id, int constant); + void SetMacro(const ID* id, Expr* macro); private: - Env *parent; - Object *context_object_; + Env* parent; + Object* context_object_; typedef map id_map_t; id_map_t id_map; bool allow_undefined_id_; bool in_branch_; -}; + }; -extern const ID *default_value_var; -extern const ID *null_id; -extern const ID *null_byteseg_id; -extern const ID *begin_of_data; -extern const ID *end_of_data; -extern const ID *len_of_data; -extern const ID *byteorder_id; -extern const ID *bigendian_id; -extern const ID *littleendian_id; -extern const ID *unspecified_byteorder_id; -extern const ID *analyzer_context_id; -extern const ID *context_macro_id; -extern const ID *this_id; -extern const ID *sourcedata_id; +extern const ID* default_value_var; +extern const ID* null_id; +extern const ID* null_byteseg_id; +extern const ID* begin_of_data; +extern const ID* end_of_data; +extern const ID* len_of_data; +extern const ID* byteorder_id; +extern const ID* bigendian_id; +extern const ID* littleendian_id; +extern const ID* unspecified_byteorder_id; +extern const ID* analyzer_context_id; +extern const ID* context_macro_id; +extern const ID* this_id; +extern const ID* sourcedata_id; // extern const ID *sourcedata_begin_id; // extern const ID *sourcedata_end_id; -extern const ID *connection_id; -extern const ID *upflow_id; -extern const ID *downflow_id; -extern const ID *dataunit_id; -extern const ID *flow_buffer_id; -extern const ID *element_macro_id; -extern const ID *cxt_connection_id; -extern const ID *cxt_flow_id; -extern const ID *input_macro_id; -extern const ID *parsing_state_id; -extern const ID *buffering_state_id; +extern const ID* connection_id; +extern const ID* upflow_id; +extern const ID* downflow_id; +extern const ID* dataunit_id; +extern const ID* flow_buffer_id; +extern const ID* element_macro_id; +extern const ID* cxt_connection_id; +extern const ID* cxt_flow_id; +extern const ID* input_macro_id; +extern const ID* parsing_state_id; +extern const ID* buffering_state_id; extern void init_builtin_identifiers(); -extern Env *global_env(); +extern Env* global_env(); -extern string set_function(const ID *id); +extern string set_function(const ID* id); #endif // pac_id_h diff --git a/tools/binpac/src/pac_inputbuf.cc b/tools/binpac/src/pac_inputbuf.cc index 1974860693..caaefe6ffb 100644 --- a/tools/binpac/src/pac_inputbuf.cc +++ b/tools/binpac/src/pac_inputbuf.cc @@ -1,16 +1,14 @@ +#include "pac_inputbuf.h" + #include "pac_expr.h" #include "pac_exttype.h" #include "pac_id.h" -#include "pac_inputbuf.h" #include "pac_output.h" #include "pac_type.h" -InputBuffer::InputBuffer(Expr *expr) - : DataDepElement(INPUT_BUFFER), expr_(expr) - { - } +InputBuffer::InputBuffer(Expr* expr) : DataDepElement(INPUT_BUFFER), expr_(expr) { } -bool InputBuffer::DoTraverse(DataDepVisitor *visitor) +bool InputBuffer::DoTraverse(DataDepVisitor* visitor) { if ( expr_ && ! expr_->Traverse(visitor) ) return false; @@ -22,20 +20,16 @@ bool InputBuffer::RequiresAnalyzerContext() const return expr_->RequiresAnalyzerContext(); } -DataPtr InputBuffer::GenDataBeginEnd(Output *out_cc, Env *env) +DataPtr InputBuffer::GenDataBeginEnd(Output* out_cc, Env* env) { env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); - out_cc->println("%s %s, %s;", - extern_type_const_byteptr->DataTypeStr().c_str(), - env->LValue(begin_of_data), - env->LValue(end_of_data)); + out_cc->println("%s %s, %s;", extern_type_const_byteptr->DataTypeStr().c_str(), + env->LValue(begin_of_data), env->LValue(end_of_data)); - out_cc->println("get_pointers(%s, &%s, &%s);", - expr_->EvalExpr(out_cc, env), - env->LValue(begin_of_data), - env->LValue(end_of_data)); + out_cc->println("get_pointers(%s, &%s, &%s);", expr_->EvalExpr(out_cc, env), + env->LValue(begin_of_data), env->LValue(end_of_data)); env->SetEvaluated(begin_of_data); env->SetEvaluated(end_of_data); diff --git a/tools/binpac/src/pac_inputbuf.h b/tools/binpac/src/pac_inputbuf.h index f03a5193ab..036ed7ffec 100644 --- a/tools/binpac/src/pac_inputbuf.h +++ b/tools/binpac/src/pac_inputbuf.h @@ -7,18 +7,18 @@ class Expr; class InputBuffer : public Object, public DataDepElement -{ + { public: - InputBuffer(Expr *expr); + InputBuffer(Expr* expr); bool RequiresAnalyzerContext() const; - DataPtr GenDataBeginEnd(Output *out_cc, Env *env); + DataPtr GenDataBeginEnd(Output* out_cc, Env* env); protected: - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); private: - Expr *expr_; -}; + Expr* expr_; + }; #endif // pac_inputbuf_h diff --git a/tools/binpac/src/pac_let.cc b/tools/binpac/src/pac_let.cc index 0801f18a3b..aac806c189 100644 --- a/tools/binpac/src/pac_let.cc +++ b/tools/binpac/src/pac_let.cc @@ -1,21 +1,19 @@ +#include "pac_let.h" + #include "pac_expr.h" #include "pac_exttype.h" -#include "pac_let.h" #include "pac_output.h" #include "pac_type.h" -namespace { - -void GenLetEval(const ID *id, Expr *expr, string prefix, Output* out, Env* env) +namespace { - } -} // private namespace +void GenLetEval(const ID* id, Expr* expr, string prefix, Output* out, Env* env) { } -LetField::LetField(ID* id, Type *type, Expr* expr) - : Field(LET_FIELD, - TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, - id, type), + } // private namespace + +LetField::LetField(ID* id, Type* type, Expr* expr) + : Field(LET_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), expr_(expr) { ASSERT(expr_); @@ -26,16 +24,14 @@ LetField::~LetField() delete expr_; } -bool LetField::DoTraverse(DataDepVisitor *visitor) - { - return Field::DoTraverse(visitor) && - expr()->Traverse(visitor); +bool LetField::DoTraverse(DataDepVisitor* visitor) + { + return Field::DoTraverse(visitor) && expr()->Traverse(visitor); } -bool LetField::RequiresAnalyzerContext() const - { - return Field::RequiresAnalyzerContext() || - (expr() && expr()->RequiresAnalyzerContext()); +bool LetField::RequiresAnalyzerContext() const + { + return Field::RequiresAnalyzerContext() || (expr() && expr()->RequiresAnalyzerContext()); } void LetField::Prepare(Env* env) @@ -45,11 +41,11 @@ void LetField::Prepare(Env* env) ASSERT(expr_); type_ = expr_->DataType(env); if ( type_ ) - type_ = type_->Clone(); + type_ = type_->Clone(); else type_ = extern_type_int->Clone(); - foreach(i, AttrList, attrs_) + foreach (i, AttrList, attrs_) ProcessAttr(*i); } @@ -83,15 +79,12 @@ void LetField::GenParseCode(Output* out_cc, Env* env) // force evaluation of IDs contained in this expr expr()->ForceIDEval(out_cc, env); - out_cc->println("if ( %s )", - env->RValue(type_->has_value_var())); + out_cc->println("if ( %s )", env->RValue(type_->has_value_var())); out_cc->inc_indent(); out_cc->println("{"); } - out_cc->println("%s = %s;", - env->LValue(id_), - expr()->EvalExpr(out_cc, env)); + out_cc->println("%s = %s;", env->LValue(id_), expr()->EvalExpr(out_cc, env)); if ( ! env->Evaluated(id_) ) env->SetEvaluated(id_); @@ -107,20 +100,19 @@ void LetField::GenEval(Output* out_cc, Env* env) GenParseCode(out_cc, env); } -LetDecl::LetDecl(ID *id, Type *type, Expr *expr) - : Decl(id, LET), type_(type), expr_(expr) +LetDecl::LetDecl(ID* id, Type* type, Expr* expr) : Decl(id, LET), type_(type), expr_(expr) { if ( ! type_ ) { ASSERT(expr_); - type_ = expr_->DataType(global_env()); + type_ = expr_->DataType(global_env()); if ( type_ ) - type_ = type_->Clone(); + type_ = type_->Clone(); else type_ = extern_type_int->Clone(); } - Env *env = global_env(); + Env* env = global_env(); int c; if ( expr_ && expr_->ConstFold(env, &c) ) env->AddConstID(id_, c, type); @@ -134,30 +126,21 @@ LetDecl::~LetDecl() delete expr_; } -void LetDecl::Prepare() - { - } +void LetDecl::Prepare() { } -void LetDecl::GenForwardDeclaration(Output* out_h) - { - } +void LetDecl::GenForwardDeclaration(Output* out_h) { } -void LetDecl::GenCode(Output * out_h, Output *out_cc) +void LetDecl::GenCode(Output* out_h, Output* out_cc) { - out_h->println("extern %s const %s;", - type_->DataTypeStr().c_str(), - global_env()->RValue(id_)); + out_h->println("extern %s const %s;", type_->DataTypeStr().c_str(), global_env()->RValue(id_)); GenEval(out_cc, global_env()); } -void LetDecl::GenEval(Output *out_cc, Env * /* env */) +void LetDecl::GenEval(Output* out_cc, Env* /* env */) { - Env *env = global_env(); + Env* env = global_env(); string tmp = strfmt("%s const", type_->DataTypeStr().c_str()); - out_cc->println("%s %s = %s;", - tmp.c_str(), - env->LValue(id_), - expr_->EvalExpr(out_cc, env)); + out_cc->println("%s %s = %s;", tmp.c_str(), env->LValue(id_), expr_->EvalExpr(out_cc, env)); if ( ! env->Evaluated(id_) ) env->SetEvaluated(id_); diff --git a/tools/binpac/src/pac_let.h b/tools/binpac/src/pac_let.h index aba8128511..253f0fea50 100644 --- a/tools/binpac/src/pac_let.h +++ b/tools/binpac/src/pac_let.h @@ -5,12 +5,12 @@ #include "pac_field.h" class LetField : public Field, Evaluatable -{ + { public: - LetField(ID* arg_id, Type *type, Expr* arg_expr); + LetField(ID* arg_id, Type* type, Expr* arg_expr); ~LetField(); - Expr *expr() const { return expr_; } + Expr* expr() const { return expr_; } void Prepare(Env* env); @@ -21,28 +21,28 @@ public: bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); protected: Expr* expr_; -}; + }; class LetDecl : public Decl, Evaluatable -{ + { public: - LetDecl(ID *id, Type *type, Expr *expr); + LetDecl(ID* id, Type* type, Expr* expr); ~LetDecl(); - Expr *expr() const { return expr_; } + Expr* expr() const { return expr_; } void Prepare(); - void GenForwardDeclaration(Output *out_h); - void GenCode(Output *out_h, Output *out_cc); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); void GenEval(Output* out, Env* env); private: - Type *type_; - Expr *expr_; -}; + Type* type_; + Expr* expr_; + }; -#endif // pac_let_h +#endif // pac_let_h diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index 148ee3ee0b..c54eabea4b 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -1,17 +1,16 @@ -#include #include +#include +#include "config.h" #include "pac_common.h" #include "pac_decl.h" +#include "pac_exception.h" #include "pac_exttype.h" #include "pac_id.h" #include "pac_output.h" #include "pac_parse.h" #include "pac_type.h" #include "pac_utils.h" -#include "pac_exception.h" - -#include "config.h" extern int yydebug; extern int yyparse(); @@ -31,7 +30,7 @@ void add_to_include_directories(string dirs) unsigned int dir_begin = 0, dir_end; while ( dir_begin < dirs.length() ) { - for ( dir_end = dir_begin; dir_end < dirs.length(); ++dir_end) + for ( dir_end = dir_begin; dir_end < dirs.length(); ++dir_end ) if ( dirs[dir_end] == ':' ) break; @@ -54,8 +53,7 @@ void pac_init() void insert_comments(Output* out, const char* source_filename) { - out->println("// This file is automatically generated from %s.\n", - source_filename); + out->println("// This file is automatically generated from %s.\n", source_filename); } void insert_basictype_defs(Output* out) @@ -90,7 +88,7 @@ const char* to_id(const char* s) { static char t[1024]; int i; - for ( i = 0; s[i] && i < (int) sizeof(t) - 1; ++i ) + for ( i = 0; s[i] && i < (int)sizeof(t) - 1; ++i ) t[i] = isalnum(s[i]) ? s[i] : '_'; if ( isdigit(t[0]) ) t[0] = '_'; @@ -114,7 +112,7 @@ int compile(const char* filename) if ( ! FLAGS_output_directory.empty() ) { // Strip leading directories of filename - const char *last_slash = strrchr(filename, '/'); + const char* last_slash = strrchr(filename, '/'); if ( last_slash ) basename = last_slash + 1; else @@ -125,8 +123,7 @@ int compile(const char* filename) basename = filename; // If the file name ends with ".pac" - if ( basename.length() > 4 && - basename.substr(basename.length() - 4) == ".pac" ) + if ( basename.length() > 4 && basename.substr(basename.length() - 4) == ".pac" ) { basename = basename.substr(0, basename.length() - 4); } @@ -176,8 +173,7 @@ int compile(const char* filename) } catch ( OutputException& e ) { - fprintf(stderr, "Error in compiling %s: %s\n", - filename, e.errmsg()); + fprintf(stderr, "Error in compiling %s: %s\n", filename, e.errmsg()); ret = 1; } catch ( Exception& e ) @@ -211,21 +207,21 @@ void usage() // GCC uses __SANITIZE_ADDRESS__, Clang uses __has_feature #if defined(__SANITIZE_ADDRESS__) - #define USING_ASAN +#define USING_ASAN #endif #if defined(__has_feature) - #if __has_feature(address_sanitizer) - #define USING_ASAN - #endif +#if __has_feature(address_sanitizer) +#define USING_ASAN +#endif #endif // FreeBSD doesn't support LeakSanitizer -#if defined(USING_ASAN) && !defined(__FreeBSD__) - #include - #define BINPAC_LSAN_DISABLE(x) __lsan_disable(x) +#if defined(USING_ASAN) && ! defined(__FreeBSD__) +#include +#define BINPAC_LSAN_DISABLE(x) __lsan_disable(x) #else - #define BINPAC_LSAN_DISABLE(x) +#define BINPAC_LSAN_DISABLE(x) #endif int main(int argc, char* argv[]) @@ -236,12 +232,12 @@ int main(int argc, char* argv[]) BINPAC_LSAN_DISABLE(); #ifdef HAVE_MALLOC_OPTIONS - extern char *malloc_options; + extern char* malloc_options; #endif int o; while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 ) { - switch(o) + switch ( o ) { case 'D': yydebug = 1; @@ -271,10 +267,9 @@ int main(int argc, char* argv[]) } // Strip the trailing '/'s - while ( ! FLAGS_output_directory.empty() && - *(FLAGS_output_directory.end() - 1) == '/' ) + while ( ! FLAGS_output_directory.empty() && *(FLAGS_output_directory.end() - 1) == '/' ) { - FLAGS_output_directory.erase(FLAGS_output_directory.end()-1); + FLAGS_output_directory.erase(FLAGS_output_directory.end() - 1); } // Add the current directory to FLAGS_include_directories @@ -294,4 +289,3 @@ int main(int argc, char* argv[]) return ret; } - diff --git a/tools/binpac/src/pac_number.h b/tools/binpac/src/pac_number.h index f74b206417..2392a4e6be 100644 --- a/tools/binpac/src/pac_number.h +++ b/tools/binpac/src/pac_number.h @@ -4,18 +4,16 @@ #include "pac_common.h" class Number : public Object -{ + { public: - Number(int arg_n) - : s(strfmt("%d", arg_n)), n(arg_n) {} - Number(const char* arg_s, int arg_n) - : s(arg_s), n(arg_n) {} - const char* Str() const { return s.c_str(); } - int Num() const { return n; } + Number(int arg_n) : s(strfmt("%d", arg_n)), n(arg_n) { } + Number(const char* arg_s, int arg_n) : s(arg_s), n(arg_n) { } + const char* Str() const { return s.c_str(); } + int Num() const { return n; } protected: const string s; const int n; -}; + }; -#endif // pac_number_h +#endif // pac_number_h diff --git a/tools/binpac/src/pac_output.cc b/tools/binpac/src/pac_output.cc index aec1e92dfc..87d4bd93b0 100644 --- a/tools/binpac/src/pac_output.cc +++ b/tools/binpac/src/pac_output.cc @@ -1,19 +1,18 @@ -#include +#include "pac_output.h" + #include #include #include +#include #include "pac_utils.h" -#include "pac_output.h" OutputException::OutputException(const char* arg_msg) { msg = arg_msg; } -OutputException::~OutputException() - { - } +OutputException::~OutputException() { } Output::Output(string filename) { diff --git a/tools/binpac/src/pac_output.h b/tools/binpac/src/pac_output.h index 26cfd72667..607598759b 100644 --- a/tools/binpac/src/pac_output.h +++ b/tools/binpac/src/pac_output.h @@ -1,13 +1,14 @@ #ifndef pac_output_h #define pac_output_h -#include #include +#include #include using namespace std; -class OutputException { +class OutputException + { public: OutputException(const char* arg_msg); ~OutputException(); @@ -15,9 +16,10 @@ public: protected: string msg; -}; + }; -class Output { +class Output + { public: Output(string filename); ~Output(); @@ -35,6 +37,6 @@ protected: FILE* fp; int indent_; -}; + }; #endif /* pac_output_h */ diff --git a/tools/binpac/src/pac_param.cc b/tools/binpac/src/pac_param.cc index 21e452ee05..763cc64fec 100644 --- a/tools/binpac/src/pac_param.cc +++ b/tools/binpac/src/pac_param.cc @@ -1,3 +1,5 @@ +#include "pac_param.h" + #include "pac_decl.h" #include "pac_exttype.h" #include "pac_field.h" @@ -6,61 +8,51 @@ #include "pac_type.h" #include "pac_utils.h" -#include "pac_param.h" - -Param::Param(ID* id, Type *type) - : id_(id), type_(type) +Param::Param(ID* id, Type* type) : id_(id), type_(type) { if ( ! type_ ) type_ = extern_type_int->Clone(); - decl_str_ = strfmt("%s %s", - type_->DataTypeConstRefStr().c_str(), - id_->Name()); + decl_str_ = strfmt("%s %s", type_->DataTypeConstRefStr().c_str(), id_->Name()); param_field_ = new ParamField(this); } -Param::~Param() +Param::~Param() { } + +const string& Param::decl_str() const { + ASSERT(! decl_str_.empty()); + return decl_str_; } -const string &Param::decl_str() const - { - ASSERT(!decl_str_.empty()); - return decl_str_; - } - -string ParamDecls(ParamList *params) +string ParamDecls(ParamList* params) { string param_decls; int first = 1; foreach (i, ParamList, params) - { - Param* p = *i; - const char* decl_str = p->decl_str().c_str(); - if ( first ) - first = 0; - else - param_decls += ", "; - param_decls += decl_str; - } + { + Param* p = *i; + const char* decl_str = p->decl_str().c_str(); + if ( first ) + first = 0; + else + param_decls += ", "; + param_decls += decl_str; + } return param_decls; } -ParamField::ParamField(const Param *param) - : Field(PARAM_FIELD, - TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, - param->id(), - param->type()) +ParamField::ParamField(const Param* param) + : Field(PARAM_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, param->id(), + param->type()) { } -void ParamField::GenInitCode(Output *out_cc, Env *env) +void ParamField::GenInitCode(Output* out_cc, Env* env) { - out_cc->println("%s = %s;", - env->LValue(id()), id()->Name()); + out_cc->println("%s = %s;", env->LValue(id()), id()->Name()); env->SetEvaluated(id()); } diff --git a/tools/binpac/src/pac_param.h b/tools/binpac/src/pac_param.h index 5efc60fd3a..95a6eb456d 100644 --- a/tools/binpac/src/pac_param.h +++ b/tools/binpac/src/pac_param.h @@ -5,34 +5,34 @@ #include "pac_field.h" class Param : public Object -{ + { public: - Param(ID* id, Type* type); + Param(ID* id, Type* type); ~Param(); - ID *id() const { return id_; } - Type *type() const { return type_; } - const string & decl_str() const; - Field *param_field() const { return param_field_; } + ID* id() const { return id_; } + Type* type() const { return type_; } + const string& decl_str() const; + Field* param_field() const { return param_field_; } private: ID* id_; Type* type_; string decl_str_; - Field *param_field_; -}; + Field* param_field_; + }; class ParamField : public Field -{ + { public: - ParamField(const Param *param); + ParamField(const Param* param); - void GenInitCode(Output *out, Env *env); + void GenInitCode(Output* out, Env* env); void GenCleanUpCode(Output* out, Env* env); -}; + }; // Returns the string with a list of param declarations separated by ','. -string ParamDecls(ParamList *params); +string ParamDecls(ParamList* params); #if 0 // Generate assignments to parameters, in the form of "%s_ = %s;" % (id, id). @@ -45,4 +45,4 @@ void GenParamPubDecls(ParamList *params, Output *out_h, Env *env); void GenParamPrivDecls(ParamList *params, Output *out_h, Env *env); #endif -#endif // pac_param_h +#endif // pac_param_h diff --git a/tools/binpac/src/pac_paramtype.cc b/tools/binpac/src/pac_paramtype.cc index 96e79735a3..a5fd579e8c 100644 --- a/tools/binpac/src/pac_paramtype.cc +++ b/tools/binpac/src/pac_paramtype.cc @@ -1,9 +1,10 @@ +#include "pac_paramtype.h" + #include "pac_context.h" #include "pac_dataptr.h" #include "pac_exception.h" #include "pac_expr.h" #include "pac_output.h" -#include "pac_paramtype.h" #include "pac_typedecl.h" ParameterizedType::ParameterizedType(ID* type_id, ExprList* args) @@ -12,27 +13,25 @@ ParameterizedType::ParameterizedType(ID* type_id, ExprList* args) checking_requires_analyzer_context_ = false; } -ParameterizedType::~ParameterizedType() - { - } +ParameterizedType::~ParameterizedType() { } -string ParameterizedType::EvalMember(const ID *member_id) const +string ParameterizedType::EvalMember(const ID* member_id) const { - Type *ty = ReferredDataType(true); + Type* ty = ReferredDataType(true); return strfmt("->%s", ty->env()->RValue(member_id)); } string ParameterizedType::class_name() const - { - return type_id_->Name(); + { + return type_id_->Name(); } -Type *ParameterizedType::DoClone() const +Type* ParameterizedType::DoClone() const { return new ParameterizedType(type_id_->clone(), args_); } -void ParameterizedType::AddParamArg(Expr *arg) +void ParameterizedType::AddParamArg(Expr* arg) { args_->push_back(arg); } @@ -47,21 +46,20 @@ string ParameterizedType::DataTypeStr() const return strfmt("%s *", type_id_->Name()); } -Type *ParameterizedType::MemberDataType(const ID *member_id) const +Type* ParameterizedType::MemberDataType(const ID* member_id) const { - Type *ref_type = TypeDecl::LookUpType(type_id_); + Type* ref_type = TypeDecl::LookUpType(type_id_); if ( ! ref_type ) return 0; return ref_type->MemberDataType(member_id); } -Type *ParameterizedType::ReferredDataType(bool throw_exception) const +Type* ParameterizedType::ReferredDataType(bool throw_exception) const { Type* type = TypeDecl::LookUpType(type_id_); if ( ! type ) { - DEBUG_MSG("WARNING: cannot find referenced type for %s\n", - type_id_->Name()); + DEBUG_MSG("WARNING: cannot find referenced type for %s\n", type_id_->Name()); if ( throw_exception ) throw ExceptionIDNotFound(type_id_); } @@ -75,7 +73,7 @@ int ParameterizedType::StaticSize(Env* env) const void ParameterizedType::DoMarkIncrementalInput() { - Type *ty = ReferredDataType(true); + Type* ty = ReferredDataType(true); ty->MarkIncrementalInput(); @@ -85,15 +83,15 @@ void ParameterizedType::DoMarkIncrementalInput() Type::BufferMode ParameterizedType::buffer_mode() const { - // Note that the precedence is on attributes (&oneline or &length) + // Note that the precedence is on attributes (&oneline or &length) // specified on the parameterized type directly than on the type - // declaration. + // declaration. // - // If both &oneline and &length are specified at the same place, + // If both &oneline and &length are specified at the same place, // use &length. // BufferMode mode = Type::buffer_mode(); - Type *ty = ReferredDataType(true); + Type* ty = ReferredDataType(true); if ( mode != NOT_BUFFERABLE ) return mode; @@ -110,16 +108,16 @@ bool ParameterizedType::ByteOrderSensitive() const return ReferredDataType(true)->RequiresByteOrder(); } -bool ParameterizedType::DoTraverse(DataDepVisitor *visitor) +bool ParameterizedType::DoTraverse(DataDepVisitor* visitor) { if ( ! Type::DoTraverse(visitor) ) return false; - foreach(i, ExprList, args_) + foreach (i, ExprList, args_) if ( ! (*i)->Traverse(visitor) ) return false; - Type *ty = ReferredDataType(false); + Type* ty = ReferredDataType(false); if ( ty && ! ty->Traverse(visitor) ) return false; @@ -134,20 +132,19 @@ bool ParameterizedType::RequiresAnalyzerContext() bool ret = false; // If any argument expression refers to analyzer context - foreach(i, ExprList, args_) + foreach (i, ExprList, args_) if ( (*i)->RequiresAnalyzerContext() ) { ret = true; break; } - ret = ret || - Type::RequiresAnalyzerContext(); + ret = ret || Type::RequiresAnalyzerContext(); if ( ! ret ) { - Type *ty = ReferredDataType(false); + Type* ty = ReferredDataType(false); if ( ty ) - ret = ty->RequiresAnalyzerContext(); + ret = ty->RequiresAnalyzerContext(); } checking_requires_analyzer_context_ = false; @@ -163,7 +160,7 @@ void ParameterizedType::GenInitCode(Output* out_cc, Env* env) void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env) { - Type *ty = ReferredDataType(false); + Type* ty = ReferredDataType(false); if ( ty && ty->attr_refcount() ) out_cc->println("Unref(%s);", lvalue()); else @@ -172,7 +169,7 @@ void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env) Type::GenCleanUpCode(out_cc, env); } -string ParameterizedType::EvalParameters(Output* out_cc, Env *env) const +string ParameterizedType::EvalParameters(Output* out_cc, Env* env) const { string arg_str; @@ -190,27 +187,24 @@ string ParameterizedType::EvalParameters(Output* out_cc, Env *env) const return arg_str; } -void ParameterizedType::GenNewInstance(Output *out_cc, Env *env) +void ParameterizedType::GenNewInstance(Output* out_cc, Env* env) { - out_cc->println("%s = new %s(%s);", - lvalue(), - type_id_->Name(), - EvalParameters(out_cc, env).c_str()); + out_cc->println("%s = new %s(%s);", lvalue(), type_id_->Name(), + EvalParameters(out_cc, env).c_str()); } -void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, - const DataPtr& data, int flags) +void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { DEBUG_MSG("DoGenParseCode for %s\n", type_id_->Name()); - Type *ref_type = ReferredDataType(true); + Type* ref_type = ReferredDataType(true); - const char *parse_func; + const char* parse_func; string parse_params; if ( buffer_mode() == BUFFER_NOTHING ) - { - ASSERT(!ref_type->incremental_input()); + { + ASSERT(! ref_type->incremental_input()); parse_func = kParseFuncWithoutBuffer; parse_params = "0, 0"; } @@ -222,9 +216,7 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, else { parse_func = kParseFuncWithoutBuffer; - parse_params = strfmt("%s, %s", - data.ptr_expr(), - env->RValue(end_of_data)); + parse_params = strfmt("%s, %s", data.ptr_expr(), env->RValue(end_of_data)); } if ( RequiresAnalyzerContext::compute(ref_type) ) @@ -239,51 +231,43 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, } string call_parse_func = strfmt("%s->%s(%s)", - lvalue(), // parse() needs an LValue - parse_func, - parse_params.c_str()); + lvalue(), // parse() needs an LValue + parse_func, parse_params.c_str()); if ( incremental_input() ) { if ( buffer_mode() == BUFFER_NOTHING ) - { - out_cc->println("%s;", call_parse_func.c_str()); - out_cc->println("%s = true;", - env->LValue(parsing_complete_var())); + { + out_cc->println("%s;", call_parse_func.c_str()); + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); } else - { + { ASSERT(parsing_complete_var()); - out_cc->println("%s = %s;", - env->LValue(parsing_complete_var()), - call_parse_func.c_str()); + out_cc->println("%s = %s;", env->LValue(parsing_complete_var()), + call_parse_func.c_str()); // parsing_complete_var might have been already // evaluated when set to false if ( ! env->Evaluated(parsing_complete_var()) ) - env->SetEvaluated(parsing_complete_var()); + env->SetEvaluated(parsing_complete_var()); } } else { if ( AddSizeVar(out_cc, env) ) { - out_cc->println("%s = %s;", - env->LValue(size_var()), - call_parse_func.c_str()); + out_cc->println("%s = %s;", env->LValue(size_var()), call_parse_func.c_str()); env->SetEvaluated(size_var()); } else { - out_cc->println("%s;", - call_parse_func.c_str()); + out_cc->println("%s;", call_parse_func.c_str()); } } } -void ParameterizedType::GenDynamicSize(Output* out_cc, Env* env, - const DataPtr& data) +void ParameterizedType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { GenParseCode(out_cc, env, data, 0); } - diff --git a/tools/binpac/src/pac_paramtype.h b/tools/binpac/src/pac_paramtype.h index 743af1cad6..d5cc6b58a7 100644 --- a/tools/binpac/src/pac_paramtype.h +++ b/tools/binpac/src/pac_paramtype.h @@ -5,57 +5,57 @@ // An instantiated type: ID + expression list class ParameterizedType : public Type -{ + { public: - ParameterizedType(ID *type_id, ExprList *args); + ParameterizedType(ID* type_id, ExprList* args); ~ParameterizedType(); - Type *clone() const; + Type* clone() const; - string EvalMember(const ID *member_id) const; + string EvalMember(const ID* member_id) const; // Env *member_env() const; - void AddParamArg(Expr *arg); + void AddParamArg(Expr* arg); bool DefineValueVar() const; string DataTypeStr() const; - string DefaultValue() const { return "0"; } - Type *MemberDataType(const ID *member_id) const; + string DefaultValue() const { return "0"; } + Type* MemberDataType(const ID* member_id) const; // "throw_exception" specifies whether to throw an exception // if the referred data type is not found - Type *ReferredDataType(bool throw_exception) const; + Type* ReferredDataType(bool throw_exception) const; - void GenCleanUpCode(Output *out, Env *env); + void GenCleanUpCode(Output* out, Env* env); - int StaticSize(Env *env) const; + int StaticSize(Env* env) const; - bool IsPointerType() const { return true; } + bool IsPointerType() const { return true; } bool ByteOrderSensitive() const; bool RequiresAnalyzerContext(); - void GenInitCode(Output *out_cc, Env *env); + void GenInitCode(Output* out_cc, Env* env); string class_name() const; - string EvalParameters(Output *out_cc, Env *env) const; + string EvalParameters(Output* out_cc, Env* env) const; BufferMode buffer_mode() const; protected: - void GenNewInstance(Output *out, Env *env); + void GenNewInstance(Output* out, Env* env); - bool DoTraverse(DataDepVisitor *visitor); - Type *DoClone() const; + bool DoTraverse(DataDepVisitor* visitor); + Type* DoClone() const; void DoMarkIncrementalInput(); private: - ID *type_id_; - ExprList *args_; + ID* type_id_; + ExprList* args_; bool checking_requires_analyzer_context_; - void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); - void GenDynamicSize(Output *out, Env *env, const DataPtr& data); -}; + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); + void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + }; -#endif // pac_paramtype_h +#endif // pac_paramtype_h diff --git a/tools/binpac/src/pac_primitive.cc b/tools/binpac/src/pac_primitive.cc index 5e6d01ac61..51398340a6 100644 --- a/tools/binpac/src/pac_primitive.cc +++ b/tools/binpac/src/pac_primitive.cc @@ -1,36 +1,34 @@ +#include "pac_primitive.h" + #include "pac_dbg.h" #include "pac_expr.h" #include "pac_id.h" -#include "pac_primitive.h" #include "pac_type.h" -string PPVal::ToCode(Env *env) +string PPVal::ToCode(Env* env) { ASSERT(expr_); return string(expr_->EvalExpr(0, env)); } -string PPSet::ToCode(Env *env) +string PPSet::ToCode(Env* env) { ASSERT(expr_); return expr_->SetFunc(0, env); } -string PPType::ToCode(Env *env) +string PPType::ToCode(Env* env) { - Type *type = expr_->DataType(env); + Type* type = expr_->DataType(env); return type->DataTypeStr(); } -string PPConstDef::ToCode(Env *env) +string PPConstDef::ToCode(Env* env) { - Type *type = expr_->DataType(env); + Type* type = expr_->DataType(env); env->AddID(id_, TEMP_VAR, type); env->SetEvaluated(id_); string type_str = type->DataTypeStr(); - return strfmt("%s %s = %s", - type_str.c_str(), - env->LValue(id_), - expr_->EvalExpr(0, env)); + return strfmt("%s %s = %s", type_str.c_str(), env->LValue(id_), expr_->EvalExpr(0, env)); } diff --git a/tools/binpac/src/pac_primitive.h b/tools/binpac/src/pac_primitive.h index fb44e2009c..c51984d708 100644 --- a/tools/binpac/src/pac_primitive.h +++ b/tools/binpac/src/pac_primitive.h @@ -4,72 +4,75 @@ #include "pac_common.h" class PacPrimitive -{ + { public: - enum PrimitiveType { VAL, SET, TYPE, CONST_DEF }; + enum PrimitiveType + { + VAL, + SET, + TYPE, + CONST_DEF + }; - explicit PacPrimitive(PrimitiveType type) : type_(type) {} - virtual ~PacPrimitive() {} + explicit PacPrimitive(PrimitiveType type) : type_(type) { } + virtual ~PacPrimitive() { } - PrimitiveType type() const { return type_; } + PrimitiveType type() const { return type_; } - virtual string ToCode(Env *env) = 0; + virtual string ToCode(Env* env) = 0; private: PrimitiveType type_; -}; + }; class PPVal : public PacPrimitive -{ + { public: - PPVal(Expr *expr) : PacPrimitive(VAL), expr_(expr) {} - Expr *expr() const { return expr_; } + PPVal(Expr* expr) : PacPrimitive(VAL), expr_(expr) { } + Expr* expr() const { return expr_; } - string ToCode(Env *env); + string ToCode(Env* env); private: - Expr *expr_; -}; + Expr* expr_; + }; class PPSet : public PacPrimitive -{ + { public: - PPSet(Expr *expr) : PacPrimitive(SET), expr_(expr) {} - Expr *expr() const { return expr_; } + PPSet(Expr* expr) : PacPrimitive(SET), expr_(expr) { } + Expr* expr() const { return expr_; } - string ToCode(Env *env); + string ToCode(Env* env); private: - Expr *expr_; -}; + Expr* expr_; + }; class PPType : public PacPrimitive -{ + { public: - PPType(Expr *expr) : PacPrimitive(TYPE), expr_(expr) {} - Expr *expr() const { return expr_; } + PPType(Expr* expr) : PacPrimitive(TYPE), expr_(expr) { } + Expr* expr() const { return expr_; } - string ToCode(Env *env); + string ToCode(Env* env); private: - Expr *expr_; -}; + Expr* expr_; + }; class PPConstDef : public PacPrimitive -{ + { public: - PPConstDef(const ID *id, Expr *expr) - : PacPrimitive(CONST_DEF), - id_(id), - expr_(expr) {} - const ID *id() const { return id_; } - Expr *expr() const { return expr_; } + PPConstDef(const ID* id, Expr* expr) : PacPrimitive(CONST_DEF), id_(id), expr_(expr) { } + const ID* id() const { return id_; } + Expr* expr() const { return expr_; } - string ToCode(Env *env); + string ToCode(Env* env); private: - const ID *id_; - Expr *expr_; -}; + const ID* id_; + Expr* expr_; + }; -#endif // pac_primitive_h +#endif // pac_primitive_h diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index 50f850fba5..9b9f9e17df 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -1,3 +1,5 @@ +#include "pac_record.h" + #include "pac_attr.h" #include "pac_dataptr.h" #include "pac_exception.h" @@ -5,15 +7,12 @@ #include "pac_exttype.h" #include "pac_field.h" #include "pac_output.h" -#include "pac_record.h" #include "pac_type.h" #include "pac_typedecl.h" #include "pac_utils.h" #include "pac_varfield.h" - -RecordType::RecordType(RecordFieldList* record_fields) - : Type(RECORD) +RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD) { // Here we assume that the type is a standalone type. value_var_ = 0; @@ -36,10 +35,9 @@ RecordType::~RecordType() delete parsing_dataptr_var_field_; } -const ID *RecordType::parsing_dataptr_var() const - { - return parsing_dataptr_var_field_ ? - parsing_dataptr_var_field_->id() : 0; +const ID* RecordType::parsing_dataptr_var() const + { + return parsing_dataptr_var_field_ ? parsing_dataptr_var_field_->id() : 0; } bool RecordType::DefineValueVar() const @@ -57,12 +55,12 @@ void RecordType::Prepare(Env* env, int flags) { ASSERT(flags & TO_BE_PARSED); - RecordField *prev = 0; + RecordField* prev = 0; int offset = 0; int seq = 0; foreach (i, RecordFieldList, record_fields_) { - RecordField *f = *i; + RecordField* f = *i; f->set_record_type(this); f->set_prev(prev); if ( prev ) @@ -120,71 +118,62 @@ void RecordType::GenCleanUpCode(Output* out_cc, Env* env) Type::GenCleanUpCode(out_cc, env); } -void RecordType::DoGenParseCode(Output* out_cc, Env* env, - const DataPtr& data, int flags) +void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { - if ( !incremental_input() && StaticSize(env) >= 0 ) + if ( ! incremental_input() && StaticSize(env) >= 0 ) GenBoundaryCheck(out_cc, env, data); if ( incremental_parsing() ) { - out_cc->println("switch ( %s ) {", - env->LValue(parsing_state_id)); + out_cc->println("switch ( %s ) {", env->LValue(parsing_state_id)); out_cc->println("case 0:"); out_cc->inc_indent(); foreach (i, RecordFieldList, record_fields_) { - RecordField *f = *i; + RecordField* f = *i; f->GenParseCode(out_cc, env); out_cc->println(""); } out_cc->println(""); - out_cc->println("%s = true;", - env->LValue(parsing_complete_var())); + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); out_cc->dec_indent(); out_cc->println("}"); } else { - ASSERT( data.id() == begin_of_data && - data.offset() == 0 ); + ASSERT(data.id() == begin_of_data && data.offset() == 0); foreach (i, RecordFieldList, record_fields_) { - RecordField *f = *i; + RecordField* f = *i; f->GenParseCode(out_cc, env); out_cc->println(""); } if ( incremental_input() ) { ASSERT(parsing_complete_var()); - out_cc->println("%s = true;", - env->LValue(parsing_complete_var())); + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); } } if ( ! incremental_input() && AddSizeVar(out_cc, env) ) { - const DataPtr& end_of_record_dataptr = - record_fields_->back()->getFieldEnd(out_cc, env); + const DataPtr& end_of_record_dataptr = record_fields_->back()->getFieldEnd(out_cc, env); - out_cc->println("%s = %s - %s;", - env->LValue(size_var()), - end_of_record_dataptr.ptr_expr(), - env->RValue(begin_of_data)); + out_cc->println("%s = %s - %s;", env->LValue(size_var()), end_of_record_dataptr.ptr_expr(), + env->RValue(begin_of_data)); env->SetEvaluated(size_var()); } if ( ! boundary_checked() ) { - RecordField *last_field = record_fields_->back(); + RecordField* last_field = record_fields_->back(); if ( ! last_field->BoundaryChecked() ) GenBoundaryCheck(out_cc, env, data); } } -void RecordType::GenDynamicSize(Output* out_cc, Env* env, - const DataPtr& data) +void RecordType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { GenParseCode(out_cc, env, data, 0); } @@ -194,7 +183,7 @@ int RecordType::StaticSize(Env* env) const int tot_w = 0; foreach (i, RecordFieldList, record_fields_) { - RecordField *f = *i; + RecordField* f = *i; int w = f->StaticSize(env, tot_w); if ( w < 0 ) return -1; @@ -215,7 +204,7 @@ void RecordType::SetBoundaryChecked() foreach (i, RecordFieldList, record_fields_) { - RecordField *f = *i; + RecordField* f = *i; f->SetBoundaryChecked(); } } @@ -224,12 +213,12 @@ void RecordType::DoMarkIncrementalInput() { foreach (i, RecordFieldList, record_fields_) { - RecordField *f = *i; + RecordField* f = *i; f->type()->MarkIncrementalInput(); } } -bool RecordType::DoTraverse(DataDepVisitor *visitor) +bool RecordType::DoTraverse(DataDepVisitor* visitor) { return Type::DoTraverse(visitor); } @@ -238,17 +227,15 @@ bool RecordType::ByteOrderSensitive() const { foreach (i, RecordFieldList, record_fields_) { - RecordField *f = *i; + RecordField* f = *i; if ( f->RequiresByteOrder() ) return true; } return false; } -RecordField::RecordField(FieldType tof, ID *id, Type *type) - : Field(tof, - TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, - id, type) +RecordField::RecordField(FieldType tof, ID* id, Type* type) + : Field(tof, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) { begin_of_field_dataptr = 0; end_of_field_dataptr = 0; @@ -267,8 +254,8 @@ RecordField::~RecordField() { delete begin_of_field_dataptr; delete end_of_field_dataptr; - delete [] field_size_expr; - delete [] field_offset_expr; + delete[] field_size_expr; + delete[] field_offset_expr; delete end_of_field_dataptr_var; } @@ -281,11 +268,10 @@ const DataPtr& RecordField::getFieldBegin(Output* out_cc, Env* env) // The first field if ( ! begin_of_field_dataptr ) { - begin_of_field_dataptr = - new DataPtr(env, begin_of_data, 0); + begin_of_field_dataptr = new DataPtr(env, begin_of_data, 0); } return *begin_of_field_dataptr; - } + } } const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) @@ -300,12 +286,10 @@ const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) ASSERT(0); if ( ! end_of_field_dataptr ) { - const ID *dataptr_var = - record_type()->parsing_dataptr_var(); + const ID* dataptr_var = record_type()->parsing_dataptr_var(); ASSERT(dataptr_var); - end_of_field_dataptr = - new DataPtr(env, dataptr_var, 0); + end_of_field_dataptr = new DataPtr(env, dataptr_var, 0); } } else @@ -314,31 +298,23 @@ const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) if ( begin_ptr.id() == begin_of_data ) field_offset = begin_ptr.offset(); else - field_offset = -1; // unknown - + field_offset = -1; // unknown + int field_size = StaticSize(env, field_offset); - if ( field_size >= 0 ) // can be statically determinted + if ( field_size >= 0 ) // can be statically determinted { - end_of_field_dataptr = new DataPtr( - env, - begin_ptr.id(), - begin_ptr.offset() + field_size); + end_of_field_dataptr = new DataPtr(env, begin_ptr.id(), + begin_ptr.offset() + field_size); } else { // If not, we add a variable for the offset after the field - end_of_field_dataptr_var = new ID( - strfmt("dataptr_after_%s", id()->Name())); - env->AddID(end_of_field_dataptr_var, - TEMP_VAR, - extern_type_const_byteptr); + end_of_field_dataptr_var = new ID(strfmt("dataptr_after_%s", id()->Name())); + env->AddID(end_of_field_dataptr_var, TEMP_VAR, extern_type_const_byteptr); GenFieldEnd(out_cc, env, begin_ptr); - end_of_field_dataptr = new DataPtr( - env, - end_of_field_dataptr_var, - 0); + end_of_field_dataptr = new DataPtr(env, end_of_field_dataptr_var, 0); } } @@ -368,8 +344,7 @@ const char* RecordField::FieldOffset(Output* out_cc, Env* env) if ( begin.id() == begin_of_data ) field_offset_expr = nfmt("%d", begin.offset()); else - field_offset_expr = nfmt("(%s - %s)", - begin.ptr_expr(), env->RValue(begin_of_data)); + field_offset_expr = nfmt("(%s - %s)", begin.ptr_expr(), env->RValue(begin_of_data)); return field_offset_expr; } @@ -382,14 +357,14 @@ bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env) return true; // If I do not even know my size till I parse the data, my - // next field won't be able to check its boundary now. + // next field won't be able to check its boundary now. const DataPtr& begin = getFieldBegin(out_cc, env); if ( StaticSize(env, begin.AbsOffset(begin_of_data)) < 0 ) return false; - // Now we ask the next field to check its boundary. - if ( next() && next()->AttemptBoundaryCheck(out_cc, env) ) + // Now we ask the next field to check its boundary. + if ( next() && next()->AttemptBoundaryCheck(out_cc, env) ) { // If it works, we are all set SetBoundaryChecked(); @@ -400,15 +375,12 @@ bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env) return GenBoundaryCheck(out_cc, env); } -RecordDataField::RecordDataField(ID* id, Type* type) - : RecordField(RECORD_FIELD, id, type) +RecordDataField::RecordDataField(ID* id, Type* type) : RecordField(RECORD_FIELD, id, type) { ASSERT(type_); } -RecordDataField::~RecordDataField() - { - } +RecordDataField::~RecordDataField() { } void RecordDataField::Prepare(Env* env) { @@ -430,13 +402,12 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) DataPtr data(env, 0, 0); if ( ! record_type()->incremental_parsing() ) { - data = getFieldBegin(out_cc, env); + data = getFieldBegin(out_cc, env); Expr* len_expr = record_type()->attr_length_expr(); int len; - if ( ! record_type()->buffer_input() || - (len_expr && len_expr->ConstFold(env, &len)) ) + if ( ! record_type()->buffer_input() || (len_expr && len_expr->ConstFold(env, &len)) ) AttemptBoundaryCheck(out_cc, env); } @@ -449,9 +420,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) if ( type_->incremental_input() ) { // The enclosing record type must be incrementally parsed - out_cc->println("%s = %d;", - env->LValue(parsing_state_id), - parsing_state_seq()); + out_cc->println("%s = %d;", env->LValue(parsing_state_id), parsing_state_seq()); out_cc->println("/* fall through */"); out_cc->dec_indent(); out_cc->println("case %d:", parsing_state_seq()); @@ -465,8 +434,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) { ASSERT(type_->incremental_input()); - out_cc->println("if ( ! (%s) )", - type_->parsing_complete(env).c_str()); + out_cc->println("if ( ! (%s) )", type_->parsing_complete(env).c_str()); out_cc->inc_indent(); out_cc->println("goto %s;", kNeedMoreData); out_cc->dec_indent(); @@ -493,18 +461,14 @@ void RecordDataField::GenEval(Output* out_cc, Env* env) GenParseCode(out_cc, env); } -void RecordDataField::GenFieldEnd(Output* out_cc, Env* env, - const DataPtr& field_begin) +void RecordDataField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin) { - out_cc->println("const_byteptr const %s = %s + (%s);", - env->LValue(end_of_field_dataptr_var), - field_begin.ptr_expr(), - type_->DataSize(out_cc, env, field_begin).c_str()); + out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr(), type_->DataSize(out_cc, env, field_begin).c_str()); env->SetEvaluated(end_of_field_dataptr_var); - out_cc->println("BINPAC_ASSERT(%s <= %s);", - env->RValue(end_of_field_dataptr_var), - env->RValue(end_of_data)); + out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(end_of_field_dataptr_var), + env->RValue(end_of_data)); } void RecordDataField::SetBoundaryChecked() @@ -524,15 +488,14 @@ bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env) return true; } -bool RecordDataField::DoTraverse(DataDepVisitor *visitor) - { +bool RecordDataField::DoTraverse(DataDepVisitor* visitor) + { return Field::DoTraverse(visitor); } -bool RecordDataField::RequiresAnalyzerContext() const - { - return Field::RequiresAnalyzerContext() || - type()->RequiresAnalyzerContext(); +bool RecordDataField::RequiresAnalyzerContext() const + { + return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext(); } RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr) @@ -541,9 +504,7 @@ RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr) wordsize_ = -1; } -RecordPaddingField::~RecordPaddingField() - { - } +RecordPaddingField::~RecordPaddingField() { } void RecordPaddingField::Prepare(Env* env) { @@ -551,8 +512,7 @@ void RecordPaddingField::Prepare(Env* env) if ( ptype_ == PAD_TO_NEXT_WORD ) { if ( ! expr_->ConstFold(env, &wordsize_) ) - throw ExceptionPaddingError(this, - strfmt("padding word size not a constant")); + throw ExceptionPaddingError(this, strfmt("padding word size not a constant")); } } @@ -589,11 +549,9 @@ int RecordPaddingField::StaticSize(Env* env, int offset) const // can be statically computed, we can get its // static size if ( offset > target_offset ) - throw ExceptionPaddingError( - this, - strfmt("current offset = %d, " - "target offset = %d", - offset, target_offset)); + throw ExceptionPaddingError(this, strfmt("current offset = %d, " + "target offset = %d", + offset, target_offset)); return target_offset - offset; case PAD_TO_NEXT_WORD: @@ -601,8 +559,7 @@ int RecordPaddingField::StaticSize(Env* env, int offset) const return -1; offset_in_word = offset % wordsize_; - return ( offset_in_word == 0 ) ? - 0 : wordsize_ - offset_in_word; + return (offset_in_word == 0) ? 0 : wordsize_ - offset_in_word; } return -1; @@ -620,86 +577,67 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi expr_->EvalExpr(out_cc, env)); out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", - Location(), expr_->EvalExpr(out_cc, env)); + out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), + expr_->EvalExpr(out_cc, env)); out_cc->println("}"); out_cc->dec_indent(); out_cc->println(""); out_cc->println("const_byteptr const %s = %s + (%s);", - env->LValue(end_of_field_dataptr_var), - field_begin.ptr_expr(), - expr_->EvalExpr(out_cc, env)); + env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(), + expr_->EvalExpr(out_cc, env)); out_cc->println("// Checking out-of-bound padding for \"%s\"", field_id_str_.c_str()); - out_cc->println("if ( %s > %s || %s < %s )", - env->LValue(end_of_field_dataptr_var), - env->RValue(end_of_data), - env->LValue(end_of_field_dataptr_var), + out_cc->println("if ( %s > %s || %s < %s )", env->LValue(end_of_field_dataptr_var), + env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr()); out_cc->inc_indent(); out_cc->println("{"); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); - out_cc->println(" (%s), ", - expr_->EvalExpr(out_cc, env)); - out_cc->println(" (%s) - (%s));", - env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var)); + out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env)); + out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), + env->LValue(end_of_field_dataptr_var)); out_cc->println("}"); out_cc->dec_indent(); out_cc->println(""); break; case PAD_TO_OFFSET: - out_cc->println("const_byteptr %s = %s + (%s);", - env->LValue(end_of_field_dataptr_var), - env->RValue(begin_of_data), - expr_->EvalExpr(out_cc, env)); - out_cc->println("if ( %s < %s )", - env->LValue(end_of_field_dataptr_var), - field_begin.ptr_expr()); + out_cc->println("const_byteptr %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), + env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env)); + out_cc->println("if ( %s < %s )", env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr()); out_cc->inc_indent(); out_cc->println("{"); out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);", - id_->LocName(), - field_begin.ptr_expr(), - env->RValue(begin_of_data), - expr_->EvalExpr(out_cc, env)); - out_cc->println("%s = %s;", - env->LValue(end_of_field_dataptr_var), - field_begin.ptr_expr()); + id_->LocName(), field_begin.ptr_expr(), env->RValue(begin_of_data), + expr_->EvalExpr(out_cc, env)); + out_cc->println("%s = %s;", env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr()); out_cc->println("}"); out_cc->dec_indent(); - out_cc->println("if ( %s > %s )", - env->LValue(end_of_field_dataptr_var), - env->RValue(end_of_data)); + out_cc->println("if ( %s > %s )", env->LValue(end_of_field_dataptr_var), + env->RValue(end_of_data)); out_cc->inc_indent(); out_cc->println("{"); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); - out_cc->println(" (%s), ", - expr_->EvalExpr(out_cc, env)); - out_cc->println(" (%s) - (%s));", - env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var)); + out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env)); + out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), + env->LValue(end_of_field_dataptr_var)); out_cc->println("}"); out_cc->dec_indent(); break; case PAD_TO_NEXT_WORD: padding_var = nfmt("%s__size", id()->Name()); - out_cc->println("int %s = (%s - %s) %% %d;", - padding_var, - field_begin.ptr_expr(), - env->RValue(begin_of_data), - wordsize_); - out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", - padding_var, - padding_var, - wordsize_, - padding_var); + out_cc->println("int %s = (%s - %s) %% %d;", padding_var, field_begin.ptr_expr(), + env->RValue(begin_of_data), wordsize_); + out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", padding_var, padding_var, wordsize_, + padding_var); out_cc->println("const_byteptr const %s = %s + %s;", - env->LValue(end_of_field_dataptr_var), - field_begin.ptr_expr(), - padding_var); - delete [] padding_var; + env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(), + padding_var); + delete[] padding_var; break; } @@ -715,20 +653,18 @@ bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env) char* size; int ss = StaticSize(env, begin.AbsOffset(begin_of_data)); - ASSERT ( ss >= 0 ); - size = nfmt("%d", ss); - + ASSERT(ss >= 0); + size = nfmt("%d", ss); + begin.GenBoundaryCheck(out_cc, env, size, field_id_str_.c_str()); - delete [] size; + delete[] size; SetBoundaryChecked(); return true; } -bool RecordPaddingField::DoTraverse(DataDepVisitor *visitor) - { - return Field::DoTraverse(visitor) && - (! expr_ || expr_->Traverse(visitor)); +bool RecordPaddingField::DoTraverse(DataDepVisitor* visitor) + { + return Field::DoTraverse(visitor) && (! expr_ || expr_->Traverse(visitor)); } - diff --git a/tools/binpac/src/pac_record.h b/tools/binpac/src/pac_record.h index 04daa3a9f4..fa3cf80051 100644 --- a/tools/binpac/src/pac_record.h +++ b/tools/binpac/src/pac_record.h @@ -8,7 +8,7 @@ #include "pac_type.h" class RecordType : public Type -{ + { public: RecordType(RecordFieldList* fields); ~RecordType(); @@ -28,58 +28,62 @@ public: void SetBoundaryChecked(); - const ID *parsing_dataptr_var() const; + const ID* parsing_dataptr_var() const; - bool IsPointerType() const { ASSERT(0); return false; } + bool IsPointerType() const + { + ASSERT(0); + return false; + } protected: void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); void GenDynamicSize(Output* out, Env* env, const DataPtr& data); - Type *DoClone() const { return 0; } + Type* DoClone() const { return 0; } void DoMarkIncrementalInput(); - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); bool ByteOrderSensitive() const; private: - Field *parsing_dataptr_var_field_; + Field* parsing_dataptr_var_field_; RecordFieldList* record_fields_; -}; + }; // A data field of a record type. A RecordField corresponds to a // segment of input data, and therefore RecordField's are ordered---each // of them has a known previous and next field. class RecordField : public Field -{ + { public: - RecordField(FieldType tof, ID* id, Type *type); + RecordField(FieldType tof, ID* id, Type* type); ~RecordField(); - RecordType *record_type() const { return record_type_; } - void set_record_type(RecordType* ty) { record_type_ = ty; } + RecordType* record_type() const { return record_type_; } + void set_record_type(RecordType* ty) { record_type_ = ty; } virtual void GenParseCode(Output* out, Env* env) = 0; - RecordField* prev() const { return prev_; } - RecordField* next() const { return next_; } - void set_prev(RecordField* f) { prev_ = f; } - void set_next(RecordField* f) { next_ = f; } + RecordField* prev() const { return prev_; } + RecordField* next() const { return next_; } + void set_prev(RecordField* f) { prev_ = f; } + void set_next(RecordField* f) { next_ = f; } - int static_offset() const { return static_offset_; } - void set_static_offset(int offset) { static_offset_ = offset; } + int static_offset() const { return static_offset_; } + void set_static_offset(int offset) { static_offset_ = offset; } - int parsing_state_seq() const { return parsing_state_seq_; } - void set_parsing_state_seq(int x) { parsing_state_seq_ = x; } + int parsing_state_seq() const { return parsing_state_seq_; } + void set_parsing_state_seq(int x) { parsing_state_seq_ = x; } virtual int StaticSize(Env* env, int offset) const = 0; const char* FieldSize(Output* out, Env* env); const char* FieldOffset(Output* out, Env* env); - virtual bool BoundaryChecked() const { return boundary_checked_; } - virtual void SetBoundaryChecked() { boundary_checked_ = true; } + virtual bool BoundaryChecked() const { return boundary_checked_; } + virtual void SetBoundaryChecked() { boundary_checked_ = true; } virtual bool RequiresByteOrder() const = 0; @@ -101,14 +105,14 @@ protected: const DataPtr& getFieldBegin(Output* out_cc, Env* env); const DataPtr& getFieldEnd(Output* out_cc, Env* env); - virtual void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) = 0; + virtual void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) = 0; bool AttemptBoundaryCheck(Output* out_cc, Env* env); virtual bool GenBoundaryCheck(Output* out_cc, Env* env) = 0; -}; + }; class RecordDataField : public RecordField, public Evaluatable -{ + { public: RecordDataField(ID* arg_id, Type* arg_type); ~RecordDataField(); @@ -120,50 +124,62 @@ public: // Instantiates abstract class Evaluatable void GenEval(Output* out, Env* env); - int StaticSize(Env* env, int) const { return type()->StaticSize(env); } + int StaticSize(Env* env, int) const { return type()->StaticSize(env); } void SetBoundaryChecked(); - bool RequiresByteOrder() const - { return type()->RequiresByteOrder(); } + bool RequiresByteOrder() const { return type()->RequiresByteOrder(); } bool RequiresAnalyzerContext() const; protected: - void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); + void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); bool GenBoundaryCheck(Output* out_cc, Env* env); - bool DoTraverse(DataDepVisitor *visitor); -}; + bool DoTraverse(DataDepVisitor* visitor); + }; -enum PaddingType { PAD_BY_LENGTH, PAD_TO_OFFSET, PAD_TO_NEXT_WORD }; +enum PaddingType + { + PAD_BY_LENGTH, + PAD_TO_OFFSET, + PAD_TO_NEXT_WORD + }; class RecordPaddingField : public RecordField -{ + { public: RecordPaddingField(ID* id, PaddingType ptype, Expr* expr); ~RecordPaddingField(); void Prepare(Env* env); - void GenPubDecls(Output* out, Env* env) { /* nothing */ } - void GenPrivDecls(Output* out, Env* env) { /* nothing */ } + void GenPubDecls(Output* out, Env* env) + { /* nothing */ + } + void GenPrivDecls(Output* out, Env* env) + { /* nothing */ + } - void GenInitCode(Output* out, Env* env) { /* nothing */ } - void GenCleanUpCode(Output* out, Env* env) { /* nothing */ } + void GenInitCode(Output* out, Env* env) + { /* nothing */ + } + void GenCleanUpCode(Output* out, Env* env) + { /* nothing */ + } void GenParseCode(Output* out, Env* env); int StaticSize(Env* env, int offset) const; - bool RequiresByteOrder() const { return false; } + bool RequiresByteOrder() const { return false; } protected: - void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); + void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); bool GenBoundaryCheck(Output* out_cc, Env* env); - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); private: PaddingType ptype_; Expr* expr_; int wordsize_; -}; + }; -#endif // pac_record_h +#endif // pac_record_h diff --git a/tools/binpac/src/pac_redef.cc b/tools/binpac/src/pac_redef.cc index 260a9ce621..d720f2290a 100644 --- a/tools/binpac/src/pac_redef.cc +++ b/tools/binpac/src/pac_redef.cc @@ -1,151 +1,133 @@ +#include "pac_redef.h" + #include "pac_analyzer.h" #include "pac_case.h" #include "pac_exception.h" #include "pac_expr.h" #include "pac_func.h" #include "pac_record.h" -#include "pac_redef.h" #include "pac_type.h" #include "pac_typedecl.h" -namespace { - -Decl *find_decl(const ID *id) +namespace { - Decl *decl = Decl::LookUpDecl(id); + +Decl* find_decl(const ID* id) + { + Decl* decl = Decl::LookUpDecl(id); if ( ! decl ) { - throw Exception(id, - strfmt("cannot find declaration for %s", - id->Name())); + throw Exception(id, strfmt("cannot find declaration for %s", id->Name())); } return decl; } -} + } -Decl *ProcessTypeRedef(const ID *id, FieldList *fieldlist) +Decl* ProcessTypeRedef(const ID* id, FieldList* fieldlist) { - Decl *decl = find_decl(id); + Decl* decl = find_decl(id); if ( decl->decl_type() != Decl::TYPE ) { - throw Exception(id, - strfmt("not a type declaration: %s", - id->Name())); + throw Exception(id, strfmt("not a type declaration: %s", id->Name())); } - TypeDecl *type_decl = static_cast(decl); + TypeDecl* type_decl = static_cast(decl); ASSERT(type_decl); - Type *type = type_decl->type(); + Type* type = type_decl->type(); - foreach(i, FieldList, fieldlist) + foreach (i, FieldList, fieldlist) { - Field *f = *i; + Field* f = *i; // One cannot change data layout in 'redef'. // Only 'let' or 'action' can be added - if ( f->tof() == LET_FIELD || - f->tof() == WITHINPUT_FIELD ) + if ( f->tof() == LET_FIELD || f->tof() == WITHINPUT_FIELD ) { type->AddField(f); } - else if ( f->tof() == RECORD_FIELD || - f->tof() == PADDING_FIELD ) + else if ( f->tof() == RECORD_FIELD || f->tof() == PADDING_FIELD ) { - throw Exception(f, - "cannot change data layout in redef"); + throw Exception(f, "cannot change data layout in redef"); } else if ( f->tof() == CASE_FIELD ) { - throw Exception(f, - "use 'redef case' adding cases"); + throw Exception(f, "use 'redef case' adding cases"); } } return decl; } -Decl *ProcessCaseTypeRedef(const ID *id, CaseFieldList *casefieldlist) +Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist) { - Decl *decl = find_decl(id); + Decl* decl = find_decl(id); if ( decl->decl_type() != Decl::TYPE ) { - throw Exception(id, - strfmt("not a type declaration: %s", - id->Name())); + throw Exception(id, strfmt("not a type declaration: %s", id->Name())); } - TypeDecl *type_decl = static_cast(decl); + TypeDecl* type_decl = static_cast(decl); ASSERT(type_decl); - Type *type = type_decl->type(); + Type* type = type_decl->type(); if ( type->tot() != Type::CASE ) { - throw Exception(id, - strfmt("not a case type: %s", - id->Name())); + throw Exception(id, strfmt("not a case type: %s", id->Name())); } - CaseType *casetype = static_cast(type); + CaseType* casetype = static_cast(type); ASSERT(casetype); - foreach(i, CaseFieldList, casefieldlist) + foreach (i, CaseFieldList, casefieldlist) { - CaseField *f = *i; + CaseField* f = *i; casetype->AddCaseField(f); } return decl; } -Decl *ProcessCaseExprRedef(const ID *id, CaseExprList *caseexprlist) +Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist) { - Decl *decl = find_decl(id); + Decl* decl = find_decl(id); if ( decl->decl_type() != Decl::FUNC ) { - throw Exception(id, - strfmt("not a function declaration: %s", - id->Name())); + throw Exception(id, strfmt("not a function declaration: %s", id->Name())); } - FuncDecl *func_decl = static_cast(decl); + FuncDecl* func_decl = static_cast(decl); ASSERT(func_decl); - Expr *expr = func_decl->function()->expr(); - if ( ! expr ||expr->expr_type() != Expr::EXPR_CASE ) + Expr* expr = func_decl->function()->expr(); + if ( ! expr || expr->expr_type() != Expr::EXPR_CASE ) { - throw Exception(id, - strfmt("function not defined by a case expression: %s", - id->Name())); + throw Exception(id, strfmt("function not defined by a case expression: %s", id->Name())); } - foreach(i, CaseExprList, caseexprlist) + foreach (i, CaseExprList, caseexprlist) { - CaseExpr *e = *i; + CaseExpr* e = *i; expr->AddCaseExpr(e); } - + return decl; } -Decl *ProcessAnalyzerRedef(const ID *id, - Decl::DeclType decl_type, - AnalyzerElementList *elements) +Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerElementList* elements) { - Decl *decl = find_decl(id); + Decl* decl = find_decl(id); if ( decl->decl_type() != decl_type ) { - throw Exception(id, - strfmt("not a connection/flow declaration: %s", - id->Name())); + throw Exception(id, strfmt("not a connection/flow declaration: %s", id->Name())); } - AnalyzerDecl *analyzer_decl = static_cast(decl); + AnalyzerDecl* analyzer_decl = static_cast(decl); ASSERT(analyzer_decl); analyzer_decl->AddElements(elements); @@ -153,18 +135,16 @@ Decl *ProcessAnalyzerRedef(const ID *id, return decl; } -Decl *ProcessTypeAttrRedef(const ID *id, AttrList *attrlist) +Decl* ProcessTypeAttrRedef(const ID* id, AttrList* attrlist) { - Decl *decl = find_decl(id); + Decl* decl = find_decl(id); if ( decl->decl_type() != Decl::TYPE ) { - throw Exception(id, - strfmt("not a type declaration: %s", - id->Name())); + throw Exception(id, strfmt("not a type declaration: %s", id->Name())); } - TypeDecl *type_decl = static_cast(decl); + TypeDecl* type_decl = static_cast(decl); ASSERT(type_decl); type_decl->AddAttrs(attrlist); diff --git a/tools/binpac/src/pac_redef.h b/tools/binpac/src/pac_redef.h index 9a9c3030c4..3d6f0c259c 100644 --- a/tools/binpac/src/pac_redef.h +++ b/tools/binpac/src/pac_redef.h @@ -3,11 +3,9 @@ #include "pac_decl.h" -Decl *ProcessCaseTypeRedef(const ID *id, CaseFieldList *casefieldlist); -Decl *ProcessCaseExprRedef(const ID *id, CaseExprList *caseexprlist); -Decl *ProcessAnalyzerRedef(const ID *id, - Decl::DeclType decl_type, - AnalyzerElementList *elements); -Decl *ProcessTypeAttrRedef(const ID *id, AttrList *attrlist); +Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist); +Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist); +Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerElementList* elements); +Decl* ProcessTypeAttrRedef(const ID* id, AttrList* attrlist); -#endif // pac_redef_h +#endif // pac_redef_h diff --git a/tools/binpac/src/pac_regex.cc b/tools/binpac/src/pac_regex.cc index 1d01556bd6..42718ade3d 100644 --- a/tools/binpac/src/pac_regex.cc +++ b/tools/binpac/src/pac_regex.cc @@ -1,27 +1,28 @@ +#include "pac_regex.h" + #include "pac_exttype.h" #include "pac_id.h" #include "pac_output.h" -#include "pac_regex.h" #include "pac_type.h" // Depends on the regular expression library we are using -const char *RegEx::kREMatcherType = "RegExMatcher"; -const char *RegEx::kMatchPrefix = "MatchPrefix"; +const char* RegEx::kREMatcherType = "RegExMatcher"; +const char* RegEx::kMatchPrefix = "MatchPrefix"; -string escape_char(const string &s) +string escape_char(const string& s) { char* buf = new char[s.length() * 2 + 1]; int j = 0; - for ( int i = 0; i < (int) s.length(); ++i ) + for ( int i = 0; i < (int)s.length(); ++i ) { if ( s[i] == '\\' ) { - if ( i + 1 < (int) s.length() ) + if ( i + 1 < (int)s.length() ) { buf[j++] = '\\'; - if ( s[i+1] == '/' ) - buf[j-1] = s[++i]; - else if ( s[i+1] == '/' || s[i+1] == '\\' || s[i+1] == '"' ) + if ( s[i + 1] == '/' ) + buf[j - 1] = s[++i]; + else if ( s[i + 1] == '/' || s[i + 1] == '\\' || s[i + 1] == '"' ) buf[j++] = s[++i]; else buf[j++] = '\\'; @@ -41,11 +42,11 @@ string escape_char(const string &s) buf[j++] = '\0'; string rval = buf; - delete [] buf; + delete[] buf; return rval; } -RegEx::RegEx(const string &s) +RegEx::RegEx(const string& s) { str_ = escape_char(s); string prefix = strfmt("%s_re_", current_decl_id->Name()); @@ -53,12 +54,9 @@ RegEx::RegEx(const string &s) decl_ = new RegExDecl(this); } -RegEx::~RegEx() - { - } +RegEx::~RegEx() { } -RegExDecl::RegExDecl(RegEx *regex) - : Decl(regex->matcher_id(), REGEX) +RegExDecl::RegExDecl(RegEx* regex) : Decl(regex->matcher_id(), REGEX) { regex_ = regex; } @@ -68,17 +66,14 @@ void RegExDecl::Prepare() global_env()->AddID(id(), GLOBAL_VAR, extern_type_re_matcher); } -void RegExDecl::GenForwardDeclaration(Output *out_h) +void RegExDecl::GenForwardDeclaration(Output* out_h) { - out_h->println("extern %s %s;\n", - RegEx::kREMatcherType, - global_env()->LValue(regex_->matcher_id())); + out_h->println("extern %s %s;\n", RegEx::kREMatcherType, + global_env()->LValue(regex_->matcher_id())); } -void RegExDecl::GenCode(Output *out_h, Output *out_cc) +void RegExDecl::GenCode(Output* out_h, Output* out_cc) { - out_cc->println("%s %s(\"%s\");\n", - RegEx::kREMatcherType, - global_env()->LValue(regex_->matcher_id()), - regex_->str().c_str()); + out_cc->println("%s %s(\"%s\");\n", RegEx::kREMatcherType, + global_env()->LValue(regex_->matcher_id()), regex_->str().c_str()); } diff --git a/tools/binpac/src/pac_regex.h b/tools/binpac/src/pac_regex.h index 47c601b729..9fda47b408 100644 --- a/tools/binpac/src/pac_regex.h +++ b/tools/binpac/src/pac_regex.h @@ -7,35 +7,35 @@ class RegExDecl; class RegEx : public Object -{ + { public: - RegEx(const string &str); + RegEx(const string& str); ~RegEx(); - const string &str() const { return str_; } - ID *matcher_id() const { return matcher_id_; } + const string& str() const { return str_; } + ID* matcher_id() const { return matcher_id_; } private: string str_; - ID *matcher_id_; - RegExDecl *decl_; + ID* matcher_id_; + RegExDecl* decl_; public: - static const char *kREMatcherType; - static const char *kMatchPrefix; -}; + static const char* kREMatcherType; + static const char* kMatchPrefix; + }; class RegExDecl : public Decl -{ + { public: - RegExDecl(RegEx *regex); + RegExDecl(RegEx* regex); void Prepare(); - void GenForwardDeclaration(Output *out_h); - void GenCode(Output *out_h, Output *out_cc); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); private: - RegEx *regex_; -}; + RegEx* regex_; + }; -#endif // pac_regex_h +#endif // pac_regex_h diff --git a/tools/binpac/src/pac_state.cc b/tools/binpac/src/pac_state.cc index 83ee974391..3164c48434 100644 --- a/tools/binpac/src/pac_state.cc +++ b/tools/binpac/src/pac_state.cc @@ -1,36 +1,26 @@ +#include "pac_state.h" + #include "pac_id.h" #include "pac_output.h" #include "pac_type.h" -#include "pac_state.h" - -void StateVar::GenDecl(Output *out_h, Env *env) +void StateVar::GenDecl(Output* out_h, Env* env) { - out_h->println("%s %s;", - type_->DataTypeStr().c_str(), - env->LValue(id_)); + out_h->println("%s %s;", type_->DataTypeStr().c_str(), env->LValue(id_)); } -void StateVar::GenAccessFunction(Output *out_h, Env *env) +void StateVar::GenAccessFunction(Output* out_h, Env* env) { - out_h->println("%s %s const { return %s; }", - type_->DataTypeConstRefStr().c_str(), - env->RValue(id_), - env->LValue(id_)); + out_h->println("%s %s const { return %s; }", type_->DataTypeConstRefStr().c_str(), + env->RValue(id_), env->LValue(id_)); } -void StateVar::GenSetFunction(Output *out_h, Env *env) +void StateVar::GenSetFunction(Output* out_h, Env* env) { - out_h->println("void %s(%s x) { %s = x; }", - set_function(id_).c_str(), - type_->DataTypeConstRefStr().c_str(), - env->LValue(id_)); + out_h->println("void %s(%s x) { %s = x; }", set_function(id_).c_str(), + type_->DataTypeConstRefStr().c_str(), env->LValue(id_)); } -void StateVar::GenInitCode(Output *out_cc, Env *env) - { - } +void StateVar::GenInitCode(Output* out_cc, Env* env) { } -void StateVar::GenCleanUpCode(Output *out_cc, Env *env) - { - } +void StateVar::GenCleanUpCode(Output* out_cc, Env* env) { } diff --git a/tools/binpac/src/pac_state.h b/tools/binpac/src/pac_state.h index 82bb580f47..b9ac972f32 100644 --- a/tools/binpac/src/pac_state.h +++ b/tools/binpac/src/pac_state.h @@ -6,23 +6,22 @@ #include "pac_common.h" class StateVar -{ + { public: - StateVar(ID *id, Type *type) - : id_(id), type_(type) {} + StateVar(ID* id, Type* type) : id_(id), type_(type) { } - const ID *id() const { return id_; } - Type *type() const { return type_; } + const ID* id() const { return id_; } + Type* type() const { return type_; } - void GenDecl(Output *out_h, Env *env); - void GenAccessFunction(Output *out_h, Env *env); - void GenSetFunction(Output *out_h, Env *env); - void GenInitCode(Output *out_cc, Env *env); - void GenCleanUpCode(Output *out_cc, Env *env); + void GenDecl(Output* out_h, Env* env); + void GenAccessFunction(Output* out_h, Env* env); + void GenSetFunction(Output* out_h, Env* env); + void GenInitCode(Output* out_cc, Env* env); + void GenCleanUpCode(Output* out_cc, Env* env); private: - ID *id_; - Type *type_; -}; + ID* id_; + Type* type_; + }; -#endif // pac_state_h +#endif // pac_state_h diff --git a/tools/binpac/src/pac_strtype.cc b/tools/binpac/src/pac_strtype.cc index 1dc7832c5a..39169c37bf 100644 --- a/tools/binpac/src/pac_strtype.cc +++ b/tools/binpac/src/pac_strtype.cc @@ -1,3 +1,5 @@ +#include "pac_strtype.h" + #include "pac_attr.h" #include "pac_btype.h" #include "pac_cstr.h" @@ -8,27 +10,23 @@ #include "pac_id.h" #include "pac_output.h" #include "pac_regex.h" -#include "pac_strtype.h" #include "pac_varfield.h" -const char *StringType::kStringTypeName = "bytestring"; -const char *StringType::kConstStringTypeName = "const_bytestring"; +const char* StringType::kStringTypeName = "bytestring"; +const char* StringType::kConstStringTypeName = "const_bytestring"; -StringType::StringType(StringTypeEnum anystr) - : Type(STRING), type_(ANYSTR), str_(0), regex_(0) +StringType::StringType(StringTypeEnum anystr) : Type(STRING), type_(ANYSTR), str_(0), regex_(0) { ASSERT(anystr == ANYSTR); init(); } -StringType::StringType(ConstString *str) - : Type(STRING), type_(CSTR), str_(str), regex_(0) +StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(0) { init(); } -StringType::StringType(RegEx *regex) - : Type(STRING), type_(REGEX), str_(0), regex_(regex) +StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(0), regex_(regex) { ASSERT(regex_); init(); @@ -44,7 +42,7 @@ StringType::~StringType() { // TODO: Unref for Objects // Question: why Unref? - // + // // Unref(str_); // Unref(regex_); @@ -52,9 +50,9 @@ StringType::~StringType() delete elem_datatype_; } -Type *StringType::DoClone() const +Type* StringType::DoClone() const { - StringType *clone; + StringType* clone; switch ( type_ ) { @@ -82,16 +80,15 @@ bool StringType::DefineValueVar() const string StringType::DataTypeStr() const { - return strfmt("%s", - persistent() ? kStringTypeName : kConstStringTypeName); + return strfmt("%s", persistent() ? kStringTypeName : kConstStringTypeName); } -Type *StringType::ElementDataType() const +Type* StringType::ElementDataType() const { return elem_datatype_; } -void StringType::ProcessAttr(Attr *a) +void StringType::ProcessAttr(Attr* a) { Type::ProcessAttr(a); @@ -101,9 +98,8 @@ void StringType::ProcessAttr(Attr *a) { if ( type_ != ANYSTR ) { - throw Exception(a, - "&chunked can be applied" - " to only type bytestring"); + throw Exception(a, "&chunked can be applied" + " to only type bytestring"); } attr_chunked_ = true; SetBoundaryChecked(); @@ -114,12 +110,11 @@ void StringType::ProcessAttr(Attr *a) { if ( type_ != ANYSTR ) { - throw Exception(a, - "&restofdata can be applied" - " to only type bytestring"); + throw Exception(a, "&restofdata can be applied" + " to only type bytestring"); } attr_restofdata_ = true; - // As the string automatically extends to the end of + // As the string automatically extends to the end of // data, we do not have to check boundary. SetBoundaryChecked(); } @@ -129,12 +124,11 @@ void StringType::ProcessAttr(Attr *a) { if ( type_ != ANYSTR ) { - throw Exception(a, - "&restofflow can be applied" - " to only type bytestring"); + throw Exception(a, "&restofflow can be applied" + " to only type bytestring"); } attr_restofflow_ = true; - // As the string automatically extends to the end of + // As the string automatically extends to the end of // flow, we do not have to check boundary. SetBoundaryChecked(); } @@ -149,10 +143,9 @@ void StringType::Prepare(Env* env, int flags) { if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 ) { - ID *string_length_var = new ID(strfmt("%s_string_length", - value_var() ? value_var()->Name() : "val")); - string_length_var_field_ = new TempVarField( - string_length_var, extern_type_int->Clone()); + ID* string_length_var = new ID( + strfmt("%s_string_length", value_var() ? value_var()->Name() : "val")); + string_length_var_field_ = new TempVarField(string_length_var, extern_type_int->Clone()); string_length_var_field_->Prepare(env); } Type::Prepare(env, flags); @@ -211,17 +204,15 @@ int StringType::StaticSize(Env* env) const } } -const ID *StringType::string_length_var() const +const ID* StringType::string_length_var() const { return string_length_var_field_ ? string_length_var_field_->id() : 0; } -void StringType::GenDynamicSize(Output* out_cc, Env* env, - const DataPtr& data) +void StringType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { ASSERT(StaticSize(env) < 0); - DEBUG_MSG("Generating dynamic size for string `%s'\n", - value_var()->Name()); + DEBUG_MSG("Generating dynamic size for string `%s'\n", value_var()->Name()); if ( env->Evaluated(string_length_var()) ) return; @@ -244,15 +235,12 @@ void StringType::GenDynamicSize(Output* out_cc, Env* env, if ( ! incremental_input() && AddSizeVar(out_cc, env) ) { - out_cc->println("%s = %s;", - env->LValue(size_var()), - env->RValue(string_length_var())); + out_cc->println("%s = %s;", env->LValue(size_var()), env->RValue(string_length_var())); env->SetEvaluated(size_var()); } } -string StringType::GenStringSize(Output* out_cc, Env* env, - const DataPtr& data) +string StringType::GenStringSize(Output* out_cc, Env* env, const DataPtr& data) { int static_size = StaticSize(env); if ( static_size >= 0 ) @@ -261,8 +249,7 @@ string StringType::GenStringSize(Output* out_cc, Env* env, return env->RValue(string_length_var()); } -void StringType::DoGenParseCode(Output* out_cc, Env* env, - const DataPtr& data, int flags) +void StringType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { string str_size = GenStringSize(out_cc, env, data); @@ -283,8 +270,7 @@ void StringType::DoGenParseCode(Output* out_cc, Env* env, int len; - if ( type_ == ANYSTR && attr_length_expr_ && - attr_length_expr_->ConstFold(env, &len) ) + if ( type_ == ANYSTR && attr_length_expr_ && attr_length_expr_->ConstFold(env, &len) ) { // can check for a negative length now if ( len < 0 ) @@ -293,41 +279,31 @@ void StringType::DoGenParseCode(Output* out_cc, Env* env, else { out_cc->println("// check for negative sizes"); - out_cc->println("if ( %s < 0 )", - str_size.c_str()); - out_cc->println( - "throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", - Location(), str_size.c_str()); + out_cc->println("if ( %s < 0 )", str_size.c_str()); + out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), + str_size.c_str()); } - out_cc->println("%s.init(%s, %s);", - env->LValue(value_var()), - data.ptr_expr(), - str_size.c_str()); + out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), data.ptr_expr(), + str_size.c_str()); } if ( parsing_complete_var() ) { - out_cc->println("%s = true;", - env->LValue(parsing_complete_var())); + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); } } -void StringType::GenStringMismatch(Output* out_cc, Env* env, - const DataPtr& data, string pattern) +void StringType::GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern) { - string tmp = - strfmt("string((const char *) (%s), (const char *) %s).c_str()", - data.ptr_expr(), - env->RValue(end_of_data)); - out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", - Location(), - pattern.c_str(), - tmp.c_str()); + string tmp = strfmt("string((const char *) (%s), (const char *) %s).c_str()", data.ptr_expr(), + env->RValue(end_of_data)); + out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", Location(), + pattern.c_str(), tmp.c_str()); } -void StringType::GenCheckingCStr(Output* out_cc, Env* env, - const DataPtr& data, const string &str_size) +void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data, + const string& str_size) { // TODO: extend it for dynamic strings ASSERT(type_ == CSTR); @@ -337,10 +313,8 @@ void StringType::GenCheckingCStr(Output* out_cc, Env* env, string str_val = str_->str(); // Compare the string and report error on mismatch - out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", - data.ptr_expr(), - str_val.c_str(), - str_size.c_str()); + out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", data.ptr_expr(), str_val.c_str(), + str_size.c_str()); out_cc->inc_indent(); out_cc->println("{"); GenStringMismatch(out_cc, env, data, str_val); @@ -348,36 +322,28 @@ void StringType::GenCheckingCStr(Output* out_cc, Env* env, out_cc->dec_indent(); } -void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, - const DataPtr& data) +void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data) { - // string_length_var = + // string_length_var = // matcher.match_prefix( // begin, // end); - out_cc->println("%s = ", - env->LValue(string_length_var())); + out_cc->println("%s = ", env->LValue(string_length_var())); out_cc->inc_indent(); - out_cc->println("%s.%s(", - env->RValue(regex_->matcher_id()), - RegEx::kMatchPrefix); + out_cc->println("%s.%s(", env->RValue(regex_->matcher_id()), RegEx::kMatchPrefix); out_cc->inc_indent(); - out_cc->println("%s,", - data.ptr_expr()); - out_cc->println("%s - %s);", - env->RValue(end_of_data), - data.ptr_expr()); + out_cc->println("%s,", data.ptr_expr()); + out_cc->println("%s - %s);", env->RValue(end_of_data), data.ptr_expr()); out_cc->dec_indent(); out_cc->dec_indent(); env->SetEvaluated(string_length_var()); - out_cc->println("if ( %s < 0 )", - env->RValue(string_length_var())); + out_cc->println("if ( %s < 0 )", env->RValue(string_length_var())); out_cc->inc_indent(); out_cc->println("{"); string tmp = strfmt("\"%s\"", regex_->str().c_str()); @@ -386,42 +352,35 @@ void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, out_cc->dec_indent(); } -void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, - const DataPtr& data) +void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data) { ASSERT(type_ == ANYSTR); if ( attr_restofdata_ || attr_oneline_ ) { - out_cc->println("%s = (%s) - (%s);", - env->LValue(string_length_var()), - env->RValue(end_of_data), - data.ptr_expr()); + out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), + env->RValue(end_of_data), data.ptr_expr()); } else if ( attr_restofflow_ ) { - out_cc->println("%s = (%s) - (%s);", - env->LValue(string_length_var()), - env->RValue(end_of_data), - data.ptr_expr()); + out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), + env->RValue(end_of_data), data.ptr_expr()); } else if ( attr_length_expr_ ) { - out_cc->println("%s = %s;", - env->LValue(string_length_var()), - attr_length_expr_->EvalExpr(out_cc, env)); + out_cc->println("%s = %s;", env->LValue(string_length_var()), + attr_length_expr_->EvalExpr(out_cc, env)); } else { - throw Exception(this, - "cannot determine length of bytestring"); + throw Exception(this, "cannot determine length of bytestring"); } env->SetEvaluated(string_length_var()); } -bool StringType::DoTraverse(DataDepVisitor *visitor) - { +bool StringType::DoTraverse(DataDepVisitor* visitor) + { if ( ! Type::DoTraverse(visitor) ) return false; diff --git a/tools/binpac/src/pac_strtype.h b/tools/binpac/src/pac_strtype.h index 81520d7b7c..a7fe8de02d 100644 --- a/tools/binpac/src/pac_strtype.h +++ b/tools/binpac/src/pac_strtype.h @@ -5,19 +5,24 @@ // TODO: question: shall we merge it with ArrayType? class StringType : public Type -{ + { public: - enum StringTypeEnum { CSTR, REGEX, ANYSTR }; + enum StringTypeEnum + { + CSTR, + REGEX, + ANYSTR + }; explicit StringType(StringTypeEnum anystr); - explicit StringType(ConstString *str); - explicit StringType(RegEx *regex); + explicit StringType(ConstString* str); + explicit StringType(RegEx* regex); ~StringType(); bool DefineValueVar() const; string DataTypeStr() const; - string DefaultValue() const { return "0"; } - Type *ElementDataType() const; + string DefaultValue() const { return "0"; } + Type* ElementDataType() const; void Prepare(Env* env, int flags); @@ -31,52 +36,51 @@ public: int StaticSize(Env* env) const; - bool IsPointerType() const { return false; } + bool IsPointerType() const { return false; } - void ProcessAttr(Attr *a); + void ProcessAttr(Attr* a); protected: void init(); - // Generate computation of size of the string and returns the string + // Generate computation of size of the string and returns the string // representing a constant integer or name of the length variable. string GenStringSize(Output* out_cc, Env* env, const DataPtr& data); // Generate a string mismatch exception - void GenStringMismatch(Output* out_cc, Env* env, - const DataPtr& data, string pattern); + void GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern); void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); - void GenCheckingCStr(Output* out, Env* env, - const DataPtr& data, const string &str_size); + void GenCheckingCStr(Output* out, Env* env, const DataPtr& data, const string& str_size); void GenDynamicSize(Output* out, Env* env, const DataPtr& data); void GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data); void GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data); - Type *DoClone() const; + Type* DoClone() const; // TODO: insensitive towards byte order till we support unicode - bool ByteOrderSensitive() const { return false; } + bool ByteOrderSensitive() const { return false; } protected: - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); private: - const ID *string_length_var() const; + const ID* string_length_var() const; StringTypeEnum type_; - ConstString *str_; - RegEx *regex_; - Field *string_length_var_field_; - Type *elem_datatype_; + ConstString* str_; + RegEx* regex_; + Field* string_length_var_field_; + Type* elem_datatype_; public: static void static_init(); -private: - static const char *kStringTypeName; - static const char *kConstStringTypeName; -}; -#endif // pac_strtype_h +private: + static const char* kStringTypeName; + static const char* kConstStringTypeName; + }; + +#endif // pac_strtype_h diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index d4d9119c26..b50809edb8 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -1,3 +1,5 @@ +#include "pac_type.h" + #include "pac_action.h" #include "pac_array.h" #include "pac_attr.h" @@ -14,22 +16,19 @@ #include "pac_output.h" #include "pac_paramtype.h" #include "pac_strtype.h" -#include "pac_type.h" #include "pac_utils.h" #include "pac_varfield.h" #include "pac_withinput.h" - Type::type_map_t Type::type_map_; -Type::Type(TypeType tot) - : DataDepElement(DataDepElement::TYPE), tot_(tot) - { +Type::Type(TypeType tot) : DataDepElement(DataDepElement::TYPE), tot_(tot) + { type_decl_ = 0; type_decl_id_ = current_decl_id; declared_as_type_ = false; env_ = 0; - value_var_ = default_value_var; + value_var_ = default_value_var; ASSERT(value_var_); value_var_type_ = MEMBER_VAR; anonymous_value_var_ = false; @@ -75,7 +74,7 @@ Type::~Type() delete parsing_state_var_field_; delete buffering_state_var_field_; delete has_value_field_; - delete [] size_expr_; + delete[] size_expr_; delete_list(FieldList, fields_); delete attrs_; delete attr_byteorder_expr_; @@ -86,64 +85,64 @@ Type::~Type() delete_list(ExprList, attr_requires_); } -Type *Type::Clone() const +Type* Type::Clone() const { - Type *clone = DoClone(); + Type* clone = DoClone(); if ( clone ) { - foreach(i, FieldList, fields_) + foreach (i, FieldList, fields_) { - Field *f = *i; + Field* f = *i; clone->AddField(f); } - foreach(i, AttrList, attrs_) + foreach (i, AttrList, attrs_) { - Attr *a = *i; + Attr* a = *i; clone->ProcessAttr(a); } } return clone; } -string Type::EvalMember(const ID *member_id) const +string Type::EvalMember(const ID* member_id) const { ASSERT(0); return "@@@"; } -string Type::EvalElement(const string &array, const string &index) const +string Type::EvalElement(const string& array, const string& index) const { return strfmt("%s[%s]", array.c_str(), index.c_str()); } -const ID *Type::decl_id() const - { +const ID* Type::decl_id() const + { return type_decl_id_; } -void Type::set_type_decl(const TypeDecl *decl, bool declared_as_type) - { - type_decl_ = decl; +void Type::set_type_decl(const TypeDecl* decl, bool declared_as_type) + { + type_decl_ = decl; type_decl_id_ = decl->id(); declared_as_type_ = declared_as_type; } void Type::set_value_var(const ID* arg_id, int arg_id_type) - { - value_var_ = arg_id; - value_var_type_ = arg_id_type; + { + value_var_ = arg_id; + value_var_type_ = arg_id_type; if ( value_var_ ) anonymous_value_var_ = value_var_->is_anonymous(); } -const ID *Type::size_var() const +const ID* Type::size_var() const { return size_var_field_ ? size_var_field_->id() : 0; } -void Type::AddField(Field *f) +void Type::AddField(Field* f) { ASSERT(f); fields_->push_back(f); @@ -179,23 +178,22 @@ void Type::ProcessAttr(Attr* a) case ATTR_LET: { - LetAttr *letattr = static_cast(a); + LetAttr* letattr = static_cast(a); if ( ! attr_letfields_ ) attr_letfields_ = letattr->letfields(); else { // Append to attr_letfields_ - attr_letfields_->insert( - attr_letfields_->end(), - letattr->letfields()->begin(), - letattr->letfields()->end()); + attr_letfields_->insert(attr_letfields_->end(), letattr->letfields()->begin(), + letattr->letfields()->end()); } } break; case ATTR_LINEBREAKER: - if (strlen(a->expr()->orig()) != 6 ) - throw Exception(this, "invalid line breaker length, must be a single ASCII character. (Ex: \"\\001\".)"); + if ( strlen(a->expr()->orig()) != 6 ) + throw Exception(this, "invalid line breaker length, must be a single ASCII " + "character. (Ex: \"\\001\".)"); attr_linebreaker_ = a->expr(); break; @@ -218,12 +216,12 @@ void Type::ProcessAttr(Attr* a) case ATTR_TRANSIENT: attr_transient_ = true; break; - + case ATTR_CHUNKED: case ATTR_UNTIL: case ATTR_RESTOFDATA: case ATTR_RESTOFFLOW: - // Ignore + // Ignore // ... these are processed by { // {ArrayType, StringType}::ProcessAttr break; @@ -232,7 +230,7 @@ void Type::ProcessAttr(Attr* a) attrs_->push_back(a); } -string Type::EvalByteOrder(Output *out_cc, Env *env) const +string Type::EvalByteOrder(Output* out_cc, Env* env) const { // If &byteorder is specified for a field, rather // than a type declaration, we do not add a byteorder variable @@ -249,10 +247,9 @@ void Type::Prepare(Env* env, int flags) ASSERT(env_); // The name of the value variable - if ( value_var() ) + if ( value_var() ) { - data_id_str_ = strfmt("%s:%s", - decl_id()->Name(), value_var()->Name()); + data_id_str_ = strfmt("%s:%s", decl_id()->Name(), value_var()->Name()); } else { @@ -261,13 +258,11 @@ void Type::Prepare(Env* env, int flags) if ( value_var() ) { - env_->AddID(value_var(), - static_cast(value_var_type_), - this); + env_->AddID(value_var(), static_cast(value_var_type_), this); lvalue_ = strfmt("%s", env_->LValue(value_var())); } - foreach(i, FieldList, attr_letfields_) + foreach (i, FieldList, attr_letfields_) { AddField(*i); } @@ -275,55 +270,47 @@ void Type::Prepare(Env* env, int flags) if ( attr_exportsourcedata_ ) { ASSERT(flags & TO_BE_PARSED); - AddField(new PubVarField(sourcedata_id->clone(), - extern_type_const_bytestring->Clone())); + AddField(new PubVarField(sourcedata_id->clone(), extern_type_const_bytestring->Clone())); } // An optional field if ( attr_if_expr() ) { ASSERT(value_var()); - ID *has_value_id = new ID(strfmt("has_%s", value_var()->Name())); - has_value_field_ = new LetField(has_value_id, - extern_type_bool->Clone(), - attr_if_expr()); + ID* has_value_id = new ID(strfmt("has_%s", value_var()->Name())); + has_value_field_ = new LetField(has_value_id, extern_type_bool->Clone(), attr_if_expr()); AddField(has_value_field_); } if ( incremental_input() ) { ASSERT(flags & TO_BE_PARSED); - ID *parsing_complete_var = - new ID(strfmt("%s_parsing_complete", - value_var() ? value_var()->Name() : "val")); - DEBUG_MSG("Adding parsing complete var: %s\n", - parsing_complete_var->Name()); - parsing_complete_var_field_ = new TempVarField( - parsing_complete_var, extern_type_bool->Clone()); + ID* parsing_complete_var = new ID( + strfmt("%s_parsing_complete", value_var() ? value_var()->Name() : "val")); + DEBUG_MSG("Adding parsing complete var: %s\n", parsing_complete_var->Name()); + parsing_complete_var_field_ = new TempVarField(parsing_complete_var, + extern_type_bool->Clone()); parsing_complete_var_field_->Prepare(env); - if ( NeedsBufferingStateVar() && - ! env->GetDataType(buffering_state_id) ) + if ( NeedsBufferingStateVar() && ! env->GetDataType(buffering_state_id) ) { - buffering_state_var_field_ = new PrivVarField( - buffering_state_id->clone(), - extern_type_int->Clone()); + buffering_state_var_field_ = new PrivVarField(buffering_state_id->clone(), + extern_type_int->Clone()); AddField(buffering_state_var_field_); } if ( incremental_parsing() && tot_ == RECORD ) { ASSERT(! parsing_state_var_field_); - parsing_state_var_field_ = new PrivVarField( - parsing_state_id->clone(), - extern_type_int->Clone()); + parsing_state_var_field_ = new PrivVarField(parsing_state_id->clone(), + extern_type_int->Clone()); AddField(parsing_state_var_field_); } } foreach (i, FieldList, fields_) { - Field *f = *i; + Field* f = *i; f->Prepare(env); } } @@ -333,19 +320,17 @@ void Type::GenPubDecls(Output* out_h, Env* env) if ( DefineValueVar() ) { if ( attr_if_expr_ ) - out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }", - DataTypeConstRefStr().c_str(), - env->RValue(value_var()), - env->RValue(has_value_var()), lvalue()); + out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }", + DataTypeConstRefStr().c_str(), env->RValue(value_var()), + env->RValue(has_value_var()), lvalue()); else - out_h->println("%s %s const { return %s; }", - DataTypeConstRefStr().c_str(), - env->RValue(value_var()), lvalue()); + out_h->println("%s %s const { return %s; }", DataTypeConstRefStr().c_str(), + env->RValue(value_var()), lvalue()); } foreach (i, FieldList, fields_) { - Field *f = *i; + Field* f = *i; f->GenPubDecls(out_h, env); } } @@ -354,14 +339,12 @@ void Type::GenPrivDecls(Output* out_h, Env* env) { if ( DefineValueVar() ) { - out_h->println("%s %s;", - DataTypeStr().c_str(), - env->LValue(value_var())); + out_h->println("%s %s;", DataTypeStr().c_str(), env->LValue(value_var())); } foreach (i, FieldList, fields_) { - Field *f = *i; + Field* f = *i; f->GenPrivDecls(out_h, env); } } @@ -370,20 +353,18 @@ void Type::GenInitCode(Output* out_cc, Env* env) { foreach (i, FieldList, fields_) { - Field *f = *i; + Field* f = *i; f->GenInitCode(out_cc, env); } if ( parsing_state_var_field_ ) { - out_cc->println("%s = 0;", - env->LValue(parsing_state_var_field_->id())); + out_cc->println("%s = 0;", env->LValue(parsing_state_var_field_->id())); } if ( buffering_state_var_field_ ) { - out_cc->println("%s = 0;", - env->LValue(buffering_state_var_field_->id())); + out_cc->println("%s = 0;", env->LValue(buffering_state_var_field_->id())); } } @@ -391,18 +372,18 @@ void Type::GenCleanUpCode(Output* out_cc, Env* env) { foreach (i, FieldList, fields_) { - Field *f = *i; + Field* f = *i; if ( f->tof() != CASE_FIELD ) f->GenCleanUpCode(out_cc, env); } } -void Type::GenBufferConfiguration(Output *out_cc, Env *env) +void Type::GenBufferConfiguration(Output* out_cc, Env* env) { ASSERT(buffer_input()); string frame_buffer_arg; - + switch ( buffer_mode() ) { case BUFFER_NOTHING: @@ -410,12 +391,11 @@ void Type::GenBufferConfiguration(Output *out_cc, Env *env) case BUFFER_BY_LENGTH: if ( ! NeedsBufferingStateVar() ) - break; - + break; + if ( buffering_state_var_field_ ) { - out_cc->println("if ( %s == 0 )", - env->RValue(buffering_state_id)); + out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); out_cc->inc_indent(); out_cc->println("{"); } @@ -435,36 +415,30 @@ void Type::GenBufferConfiguration(Output *out_cc, Env *env) ASSERT(0); } - out_cc->println("%s->NewFrame(%s, %s);", - env->LValue(flow_buffer_id), - frame_buffer_arg.c_str(), - attr_chunked() ? "true" : "false"); + out_cc->println("%s->NewFrame(%s, %s);", env->LValue(flow_buffer_id), + frame_buffer_arg.c_str(), attr_chunked() ? "true" : "false"); if ( buffering_state_var_field_ ) { - out_cc->println("%s = 1;", - env->LValue(buffering_state_id)); + out_cc->println("%s = 1;", env->LValue(buffering_state_id)); out_cc->println("}"); out_cc->dec_indent(); } break; case BUFFER_BY_LINE: - out_cc->println("if ( %s == 0 )", - env->RValue(buffering_state_id)); + out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); out_cc->inc_indent(); out_cc->println("{"); if ( BufferableWithLineBreaker() ) out_cc->println("%s->SetLineBreaker((unsigned char*)%s);", - env->LValue(flow_buffer_id), LineBreaker()->orig()); - else - out_cc->println("%s->UnsetLineBreaker();", - env->LValue(flow_buffer_id)); - out_cc->println("%s->NewLine();", - env->LValue(flow_buffer_id)); + env->LValue(flow_buffer_id), LineBreaker()->orig()); + else + out_cc->println("%s->UnsetLineBreaker();", env->LValue(flow_buffer_id)); - out_cc->println("%s = 1;", - env->LValue(buffering_state_id)); + out_cc->println("%s->NewLine();", env->LValue(flow_buffer_id)); + + out_cc->println("%s = 1;", env->LValue(buffering_state_id)); out_cc->println("}"); out_cc->dec_indent(); break; @@ -475,7 +449,7 @@ void Type::GenBufferConfiguration(Output *out_cc, Env *env) } } -void Type::GenPreParsing(Output *out_cc, Env *env) +void Type::GenPreParsing(Output* out_cc, Env* env) { if ( incremental_input() && IsPointerType() ) { @@ -519,14 +493,12 @@ void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags { parsing_complete_var_field_->GenTempDecls(out_cc, env); - out_cc->println("%s = false;", - env->LValue(parsing_complete_var())); + out_cc->println("%s = false;", env->LValue(parsing_complete_var())); env->SetEvaluated(parsing_complete_var()); if ( buffer_mode() == BUFFER_NOTHING ) { - out_cc->println("%s = true;", - env->LValue(parsing_complete_var())); + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); } else if ( buffer_input() ) { @@ -540,20 +512,17 @@ void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags } else { - if ( attr_length_expr_) + if ( attr_length_expr_ ) { EvalLengthExpr(out_cc, env); GenBoundaryCheck(out_cc, env, data); out_cc->println("{"); - out_cc->println("// Setting %s with &length", - env->RValue(end_of_data)); - out_cc->println("%s %s = %s + %s;", - extern_type_const_byteptr->DataTypeStr().c_str(), - env->LValue(end_of_data), - data.ptr_expr(), - EvalLengthExpr(out_cc, env).c_str()); + out_cc->println("// Setting %s with &length", env->RValue(end_of_data)); + out_cc->println("%s %s = %s + %s;", extern_type_const_byteptr->DataTypeStr().c_str(), + env->LValue(end_of_data), data.ptr_expr(), + EvalLengthExpr(out_cc, env).c_str()); GenParseCode2(out_cc, env, data, flags); @@ -568,9 +537,8 @@ void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags void Type::GenBufferingLoop(Output* out_cc, Env* env, int flags) { - out_cc->println("while ( ! %s && %s->ready() )", - env->LValue(parsing_complete_var()), - env->LValue(flow_buffer_id)); + out_cc->println("while ( ! %s && %s->ready() )", env->LValue(parsing_complete_var()), + env->LValue(flow_buffer_id)); out_cc->inc_indent(); out_cc->println("{"); @@ -586,22 +554,18 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) { ASSERT(incremental_input()); - const ID *data_begin; + const ID* data_begin; if ( ! incremental_parsing() ) { env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); - out_cc->println("%s %s = %s->begin();", - env->DataTypeStr(begin_of_data).c_str(), - env->LValue(begin_of_data), - env->RValue(flow_buffer_id)); + out_cc->println("%s %s = %s->begin();", env->DataTypeStr(begin_of_data).c_str(), + env->LValue(begin_of_data), env->RValue(flow_buffer_id)); - out_cc->println("%s %s = %s->end();", - env->DataTypeStr(end_of_data).c_str(), - env->LValue(end_of_data), - env->RValue(flow_buffer_id)); + out_cc->println("%s %s = %s->end();", env->DataTypeStr(end_of_data).c_str(), + env->LValue(end_of_data), env->RValue(flow_buffer_id)); env->SetEvaluated(begin_of_data); env->SetEvaluated(end_of_data); @@ -615,9 +579,8 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) { if ( incremental_parsing() ) { - throw Exception(this, - "cannot handle &until($input...) " - "for incrementally parsed type"); + throw Exception(this, "cannot handle &until($input...) " + "for incrementally parsed type"); } array_until_input_->GenUntilInputCheck(out_cc, env); } @@ -627,8 +590,7 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) if ( attr_length_expr() ) { ASSERT(buffer_mode() == BUFFER_BY_LENGTH); - out_cc->println("switch ( %s )", - env->LValue(buffering_state_id)); + out_cc->println("switch ( %s )", env->LValue(buffering_state_id)); out_cc->inc_indent(); out_cc->println("{"); out_cc->println("case 0:"); @@ -646,9 +608,8 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) out_cc->println("%s = 2;", env->LValue(buffering_state_id)); Env frame_length_env(env, this); - out_cc->println("%s->GrowFrame(%s);", - env->LValue(flow_buffer_id), - attr_length_expr_->EvalExpr(out_cc, &frame_length_env)); + out_cc->println("%s->GrowFrame(%s);", env->LValue(flow_buffer_id), + attr_length_expr_->EvalExpr(out_cc, &frame_length_env)); out_cc->println("}"); out_cc->println("break;"); @@ -656,20 +617,16 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) out_cc->println("case 2:"); out_cc->inc_indent(); - out_cc->println("BINPAC_ASSERT(%s->ready());", - env->RValue(flow_buffer_id)); - out_cc->println("if ( %s->ready() )", - env->RValue(flow_buffer_id)); + out_cc->println("BINPAC_ASSERT(%s->ready());", env->RValue(flow_buffer_id)); + out_cc->println("if ( %s->ready() )", env->RValue(flow_buffer_id)); out_cc->inc_indent(); out_cc->println("{"); Env parse_env(env, this); GenParseCode2(out_cc, &parse_env, data, 0); - - out_cc->println("BINPAC_ASSERT(%s);", - parsing_complete(env).c_str()); - out_cc->println("%s = 0;", - env->LValue(buffering_state_id)); + + out_cc->println("BINPAC_ASSERT(%s);", parsing_complete(env).c_str()); + out_cc->println("%s = 0;", env->LValue(buffering_state_id)); out_cc->println("}"); out_cc->dec_indent(); @@ -679,18 +636,16 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) out_cc->println("default:"); out_cc->inc_indent(); - out_cc->println("BINPAC_ASSERT(%s <= 2);", - env->LValue(buffering_state_id)); + out_cc->println("BINPAC_ASSERT(%s <= 2);", env->LValue(buffering_state_id)); out_cc->println("break;"); - + out_cc->dec_indent(); out_cc->println("}"); out_cc->dec_indent(); } else if ( attr_restofflow_ ) { - out_cc->println("BINPAC_ASSERT(%s->eof());", - env->RValue(flow_buffer_id)); + out_cc->println("BINPAC_ASSERT(%s->eof());", env->RValue(flow_buffer_id)); GenParseCode2(out_cc, env, data, 0); } else if ( buffer_mode() == BUFFER_BY_LINE ) @@ -702,8 +657,7 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) GenParseCode2(out_cc, env, data, 0); } -void Type::GenParseCode2(Output* out_cc, Env* env, - const DataPtr& data, int flags) +void Type::GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags) { DEBUG_MSG("GenParseCode2 for %s\n", data_id_str_.c_str()); @@ -711,23 +665,18 @@ void Type::GenParseCode2(Output* out_cc, Env* env, { if ( incremental_parsing() ) { - throw Exception(this, - "cannot export raw data for incrementally parsed types"); + throw Exception(this, "cannot export raw data for incrementally parsed types"); } - out_cc->println("%s = const_bytestring(%s, %s);", - env->LValue(sourcedata_id), - data.ptr_expr(), - env->RValue(end_of_data)); + out_cc->println("%s = const_bytestring(%s, %s);", env->LValue(sourcedata_id), + data.ptr_expr(), env->RValue(end_of_data)); env->SetEvaluated(sourcedata_id); - + GenParseCode3(out_cc, env, data, flags); string datasize_str = DataSize(out_cc, env, data); - out_cc->println("%s.set_end(%s + %s);", - env->LValue(sourcedata_id), - data.ptr_expr(), - datasize_str.c_str()); + out_cc->println("%s.set_end(%s + %s);", env->LValue(sourcedata_id), data.ptr_expr(), + datasize_str.c_str()); } else { @@ -737,15 +686,15 @@ void Type::GenParseCode2(Output* out_cc, Env* env, void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags) { - foreach(i, ExprList, attr_requires_) + foreach (i, ExprList, attr_requires_) { - Expr *req = *i; + Expr* req = *i; req->EvalExpr(out_cc, env); } - foreach(i, FieldList, fields_) + foreach (i, FieldList, fields_) { - Field *f = *i; + Field* f = *i; f->GenTempDecls(out_cc, env); } @@ -759,17 +708,17 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag } out_cc->println("// Evaluate 'let' and 'withinput' fields"); - foreach(i, FieldList, fields_) + foreach (i, FieldList, fields_) { - Field *f = *i; + Field* f = *i; if ( f->tof() == LET_FIELD ) { - LetField *lf = static_cast(f); + LetField* lf = static_cast(f); lf->GenParseCode(out_cc, env); } else if ( f->tof() == WITHINPUT_FIELD ) { - WithInputField *af = static_cast(f); + WithInputField* af = static_cast(f); af->GenParseCode(out_cc, env); } } @@ -791,7 +740,7 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag if ( size_var() ) ASSERT(env->Evaluated(size_var())); - foreach(i, ExprList, attr_enforces_) + foreach (i, ExprList, attr_enforces_) { Expr* enforce = *i; const char* enforce_expr = enforce->EvalExpr(out_cc, env); @@ -803,20 +752,19 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag out_cc->println("}"); out_cc->dec_indent(); } - } -Type *Type::MemberDataType(const ID *member_id) const +Type* Type::MemberDataType(const ID* member_id) const { DEBUG_MSG("MemberDataType: %s::%s\n", type_decl_id_->Name(), member_id->Name()); ASSERT(env_); env_->set_allow_undefined_id(true); - Type *t = env_->GetDataType(member_id); + Type* t = env_->GetDataType(member_id); env_->set_allow_undefined_id(false); return t; } -Type *Type::ElementDataType() const +Type* Type::ElementDataType() const { return 0; } @@ -837,13 +785,12 @@ bool Type::AddSizeVar(Output* out_cc, Env* env) ASSERT(! incremental_input()); - ID *size_var_id = new ID(strfmt("%s__size", - value_var() ? value_var()->Name() : decl_id()->Name())); + ID* size_var_id = new ID( + strfmt("%s__size", value_var() ? value_var()->Name() : decl_id()->Name())); DEBUG_MSG("adding size var `%s' to env %p\n", size_var_id->Name(), env); - size_var_field_ = new TempVarField( - size_var_id, extern_type_int->Clone()); + size_var_field_ = new TempVarField(size_var_id, extern_type_int->Clone()); size_var_field_->Prepare(env); size_var_field_->GenTempDecls(out_cc, env); @@ -852,7 +799,7 @@ bool Type::AddSizeVar(Output* out_cc, Env* env) string Type::EvalLengthExpr(Output* out_cc, Env* env) { - ASSERT(!incremental_input()); + ASSERT(! incremental_input()); ASSERT(attr_length_expr_); int static_length; if ( attr_length_expr_->ConstFold(env, &static_length) ) @@ -860,9 +807,8 @@ string Type::EvalLengthExpr(Output* out_cc, Env* env) // How do we make sure size_var is evaluated with attr_length_expr_? if ( AddSizeVar(out_cc, env) ) { - out_cc->println("%s = %s;", - env->LValue(size_var()), - attr_length_expr_->EvalExpr(out_cc, env)); + out_cc->println("%s = %s;", env->LValue(size_var()), + attr_length_expr_->EvalExpr(out_cc, env)); env->SetEvaluated(size_var()); } return env->RValue(size_var()); @@ -890,15 +836,12 @@ string Type::DataSize(Output* out_cc, Env* env, const DataPtr& data) } } -void Type::GenBoundaryCheck(Output* out_cc, Env* env, - const DataPtr& data) +void Type::GenBoundaryCheck(Output* out_cc, Env* env, const DataPtr& data) { if ( boundary_checked() ) return; - data.GenBoundaryCheck(out_cc, env, - DataSize(out_cc, env, data).c_str(), - data_id_str_.c_str()); + data.GenBoundaryCheck(out_cc, env, DataSize(out_cc, env, data).c_str(), data_id_str_.c_str()); SetBoundaryChecked(); } @@ -922,13 +865,13 @@ bool Type::NeedsCleanUp() const } bool Type::RequiresByteOrder() const - { - return ! attr_byteorder_expr() && ByteOrderSensitive(); + { + return ! attr_byteorder_expr() && ByteOrderSensitive(); } bool Type::NeedsBufferingStateVar() const { - if ( !incremental_input() ) + if ( ! incremental_input() ) return false; switch ( buffer_mode() ) { @@ -938,14 +881,14 @@ bool Type::NeedsBufferingStateVar() const case BUFFER_BY_LINE: return true; case BUFFER_BY_LENGTH: - return ( attr_length_expr_ || attr_restofflow_ ); + return (attr_length_expr_ || attr_restofflow_); default: ASSERT(0); return false; } } -bool Type::DoTraverse(DataDepVisitor *visitor) +bool Type::DoTraverse(DataDepVisitor* visitor) { foreach (i, FieldList, fields_) { @@ -953,7 +896,7 @@ bool Type::DoTraverse(DataDepVisitor *visitor) return false; } - foreach(i, AttrList, attrs_) + foreach (i, AttrList, attrs_) { if ( ! (*i)->Traverse(visitor) ) return false; @@ -968,15 +911,15 @@ bool Type::RequiresAnalyzerContext() if ( buffer_input() ) return true; - + foreach (i, FieldList, fields_) { - Field *f = *i; + Field* f = *i; if ( f->RequiresAnalyzerContext() ) return true; } - foreach(i, AttrList, attrs_) + foreach (i, AttrList, attrs_) if ( (*i)->RequiresAnalyzerContext() ) return true; @@ -985,14 +928,13 @@ bool Type::RequiresAnalyzerContext() bool Type::IsEmptyType() const { - return ( StaticSize(global_env()) == 0 ); + return (StaticSize(global_env()) == 0); } void Type::MarkIncrementalInput() { - DEBUG_MSG("Handle incremental input for %s.%s\n", - decl_id()->Name(), - value_var() ? value_var()->Name() : "*"); + DEBUG_MSG("Handle incremental input for %s.%s\n", decl_id()->Name(), + value_var() ? value_var()->Name() : "*"); incremental_input_ = true; if ( Bufferable() ) @@ -1049,7 +991,7 @@ Type::BufferMode Type::buffer_mode() const return NOT_BUFFERABLE; } -const ID *Type::parsing_complete_var() const +const ID* Type::parsing_complete_var() const { if ( parsing_complete_var_field_ ) return parsing_complete_var_field_->id(); @@ -1057,13 +999,13 @@ const ID *Type::parsing_complete_var() const return 0; } -string Type::parsing_complete(Env *env) const +string Type::parsing_complete(Env* env) const { ASSERT(parsing_complete_var()); return env->RValue(parsing_complete_var()); } -const ID *Type::has_value_var() const +const ID* Type::has_value_var() const { if ( has_value_field_ ) return has_value_field_->id(); @@ -1078,7 +1020,7 @@ int Type::InitialBufferLength() const return attr_length_expr_->MinimalHeaderSize(env()); } -bool Type::CompatibleTypes(Type *type1, Type *type2) +bool Type::CompatibleTypes(Type* type1, Type* type2) { // If we cannot deduce one of the data types, assume that // they are compatible. @@ -1097,17 +1039,15 @@ bool Type::CompatibleTypes(Type *type1, Type *type2) return false; } - switch( type1->tot() ) + switch ( type1->tot() ) { case UNDEF: case EMPTY: return true; case BUILTIN: { - BuiltInType *t1 = - static_cast(type1); - BuiltInType *t2 = - static_cast(type2); + BuiltInType* t1 = static_cast(type1); + BuiltInType* t2 = static_cast(type2); return BuiltInType::CompatibleBuiltInTypes(t1, t2); } @@ -1117,15 +1057,12 @@ bool Type::CompatibleTypes(Type *type1, Type *type2) case EXTERN: return type1->DataTypeStr() == type2->DataTypeStr(); break; - + case ARRAY: { - ArrayType *t1 = - static_cast(type1); - ArrayType *t2 = - static_cast(type2); - return CompatibleTypes(t1->ElementDataType(), - t2->ElementDataType()); + ArrayType* t1 = static_cast(type1); + ArrayType* t2 = static_cast(type2); + return CompatibleTypes(t1->ElementDataType(), t2->ElementDataType()); } default: @@ -1134,7 +1071,7 @@ bool Type::CompatibleTypes(Type *type1, Type *type2) } } -Type *Type::LookUpByID(ID *id) +Type* Type::LookUpByID(ID* id) { // 1. Is it a pre-defined type? string name = id->Name(); @@ -1144,19 +1081,19 @@ Type *Type::LookUpByID(ID *id) } // 2. Is it a simple declared type? - Type *type = TypeDecl::LookUpType(id); + Type* type = TypeDecl::LookUpType(id); if ( type ) { - // Note: as a Type is always associated with a variable, + // Note: as a Type is always associated with a variable, // return a clone. switch ( type->tot() ) { case Type::BUILTIN: case Type::EXTERN: - case Type::STRING: + case Type::STRING: return type->Clone(); - case Type::ARRAY: + case Type::ARRAY: default: break; } @@ -1165,7 +1102,7 @@ Type *Type::LookUpByID(ID *id) return new ParameterizedType(id, 0); } -void Type::AddPredefinedType(const string &type_name, Type *type) +void Type::AddPredefinedType(const string& type_name, Type* type) { ASSERT(type_map_.find(type_name) == type_map_.end()); type_map_[type_name] = type; diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index 2de0a6fc76..d9ca103562 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -9,9 +9,10 @@ using namespace std; #include "pac_dbg.h" class Type : public Object, public DataDepElement -{ + { public: - enum TypeType { + enum TypeType + { UNDEF = -1, EMPTY, BUILTIN, @@ -22,85 +23,86 @@ public: STRING, EXTERN, DUMMY, - }; + }; explicit Type(TypeType tot); virtual ~Type(); - Type *Clone() const; + Type* Clone() const; // Type of type - TypeType tot() const { return tot_; } + TypeType tot() const { return tot_; } //////////////////////////////////////// // Code generation - virtual void Prepare(Env *env, int flags); + virtual void Prepare(Env* env, int flags); // Flag(s) for Prepare() static const int TO_BE_PARSED = 1; - virtual void GenPubDecls(Output *out, Env *env); - virtual void GenPrivDecls(Output *out, Env *env); + virtual void GenPubDecls(Output* out, Env* env); + virtual void GenPrivDecls(Output* out, Env* env); - virtual void GenInitCode(Output *out, Env *env); - virtual void GenCleanUpCode(Output *out, Env *env); + virtual void GenInitCode(Output* out, Env* env); + virtual void GenCleanUpCode(Output* out, Env* env); - void GenPreParsing(Output *out, Env *env); - void GenParseCode(Output *out, Env *env, const DataPtr& data, int flags); + void GenPreParsing(Output* out, Env* env); + void GenParseCode(Output* out, Env* env, const DataPtr& data, int flags); //////////////////////////////////////// // TODO: organize the various methods below - // The LValue string of the variable defined by the type. - // For example, if the type defines a record field, the - // lvalue is the member variable corresponding to the field; + // The LValue string of the variable defined by the type. + // For example, if the type defines a record field, the + // lvalue is the member variable corresponding to the field; // if the type appears in a type decl, then the lvalue is the // default value var. // - const char *lvalue() const { return lvalue_.c_str(); } + const char* lvalue() const { return lvalue_.c_str(); } // The TypeDecl that defined the type. // - const TypeDecl *type_decl() const { return type_decl_; } - void set_type_decl(const TypeDecl *decl, bool declared_as_type); + const TypeDecl* type_decl() const { return type_decl_; } + void set_type_decl(const TypeDecl* decl, bool declared_as_type); // Returns whether the type appears in a type declaration // (true) or as type specification of a field (false). // - bool declared_as_type() const { return declared_as_type_; } + bool declared_as_type() const { return declared_as_type_; } - // The ID of the decl in which the type appear. + // The ID of the decl in which the type appear. // - const ID *decl_id() const; + const ID* decl_id() const; - Env *env() const { return env_; } + Env* env() const { return env_; } - string EvalByteOrder(Output *out_cc, Env *env) const; + string EvalByteOrder(Output* out_cc, Env* env) const; - virtual string EvalMember(const ID *member_id) const; - virtual string EvalElement(const string &array, - const string &index) const; + virtual string EvalMember(const ID* member_id) const; + virtual string EvalElement(const string& array, const string& index) const; // The variable defined by the type - const ID *value_var() const { return value_var_; } - void set_value_var(const ID *arg_id, int arg_id_type); + const ID* value_var() const { return value_var_; } + void set_value_var(const ID* arg_id, int arg_id_type); - bool anonymous_value_var() const { return anonymous_value_var_; } + bool anonymous_value_var() const { return anonymous_value_var_; } - const ID *size_var() const; + const ID* size_var() const; // Adds a variable to env to represent the size of this type. - // Returns false if we do not need a size variable (because + // Returns false if we do not need a size variable (because // the type has a static size) or the size variable is already added. - bool AddSizeVar(Output *out, Env *env); + bool AddSizeVar(Output* out, Env* env); - const ID *parsing_state_var() const; + const ID* parsing_state_var() const; - const ID *has_value_var() const; + const ID* has_value_var() const; - void AddField(Field *f); + void AddField(Field* f); - void AddCheck(Expr *expr) { /* TODO */ } + void AddCheck(Expr* expr) + { /* TODO */ + } virtual bool DefineValueVar() const = 0; @@ -118,16 +120,17 @@ public: } // Returns a default value for the type - virtual string DefaultValue() const - { - ASSERT(0); return "@@@"; + virtual string DefaultValue() const + { + ASSERT(0); + return "@@@"; } // Returns the data type of the member field/case - virtual Type *MemberDataType(const ID *member_id) const; + virtual Type* MemberDataType(const ID* member_id) const; // Returns the data type of the element type of an array - virtual Type *ElementDataType() const; + virtual Type* ElementDataType() const; // Whether the type needs clean-up at deallocation. bool NeedsCleanUp() const; @@ -135,48 +138,45 @@ public: // Whether byte order must be determined before parsing the type. bool RequiresByteOrder() const; - // Whether class of the type requires a parameter of analyzer context. + // Whether class of the type requires a parameter of analyzer context. virtual bool RequiresAnalyzerContext(); virtual bool IsPointerType() const = 0; - virtual bool IsNumericType() const { return false; } + virtual bool IsNumericType() const { return false; } bool IsEmptyType() const; //////////////////////////////////////// // Attributes - virtual void ProcessAttr(Attr *a); + virtual void ProcessAttr(Attr* a); - bool attr_chunked() const { return attr_chunked_; } - Expr *attr_byteorder_expr() const { return attr_byteorder_expr_; } - Expr *attr_if_expr() const { return attr_if_expr_; } + bool attr_chunked() const { return attr_chunked_; } + Expr* attr_byteorder_expr() const { return attr_byteorder_expr_; } + Expr* attr_if_expr() const { return attr_if_expr_; } // TODO: generate the length expression automatically. - Expr *attr_length_expr() const { return attr_length_expr_; } - bool attr_refcount() const { return attr_refcount_; } - bool attr_transient() const { return attr_transient_; } + Expr* attr_length_expr() const { return attr_length_expr_; } + bool attr_refcount() const { return attr_refcount_; } + bool attr_transient() const { return attr_transient_; } // Whether the value remains valid outside the parse function - bool persistent() const - { - return ! attr_transient() && ! attr_chunked(); - } + bool persistent() const { return ! attr_transient() && ! attr_chunked(); } - void SetUntilCheck(ArrayType *t) { array_until_input_ = t; } + void SetUntilCheck(ArrayType* t) { array_until_input_ = t; } //////////////////////////////////////// // Size and boundary checking - virtual int StaticSize(Env *env) const = 0; - string DataSize(Output *out, Env *env, const DataPtr& data); + virtual int StaticSize(Env* env) const = 0; + string DataSize(Output* out, Env* env, const DataPtr& data); - bool boundary_checked() const { return boundary_checked_; } - virtual void SetBoundaryChecked() { boundary_checked_ = true; } - void GenBoundaryCheck(Output *out, Env *env, const DataPtr& data); + bool boundary_checked() const { return boundary_checked_; } + virtual void SetBoundaryChecked() { boundary_checked_ = true; } + void GenBoundaryCheck(Output* out, Env* env, const DataPtr& data); //////////////////////////////////////// // Handling incremental input - // + // // There are two ways to handle incremental input: (1) to // buffer the input before parsing; (2) to parse incrementally. - // + // // The type must be "bufferable" for (1). While for (2), // each member of the type must be able to handle incremental // input. @@ -185,17 +185,17 @@ public: virtual void DoMarkIncrementalInput(); // Whether the type may receive incremental input - bool incremental_input() const { return incremental_input_; } + bool incremental_input() const { return incremental_input_; } // Whether parsing should also be incremental - bool incremental_parsing() const { return incremental_parsing_; } + bool incremental_parsing() const { return incremental_parsing_; } // Whether we should buffer the input - bool buffer_input() const { return buffer_input_; } + bool buffer_input() const { return buffer_input_; } // Whether parsing of the type is completed - const ID *parsing_complete_var() const; - string parsing_complete(Env *env) const; + const ID* parsing_complete_var() const; + string parsing_complete(Env* env) const; // Whether the input is bufferable bool Bufferable() const; @@ -204,20 +204,21 @@ public: bool BufferableWithLineBreaker() const; Expr* LineBreaker() const; - enum BufferMode { + enum BufferMode + { NOT_BUFFERABLE, - BUFFER_NOTHING, // for type "empty" + BUFFER_NOTHING, // for type "empty" BUFFER_BY_LENGTH, BUFFER_BY_LINE, - }; + }; virtual BufferMode buffer_mode() const; - void GenBufferConfiguration(Output *out, Env *env); + void GenBufferConfiguration(Output* out, Env* env); int InitialBufferLength() const; protected: - virtual void GenNewInstance(Output *out, Env *env) {} + virtual void GenNewInstance(Output* out, Env* env) { } virtual bool ByteOrderSensitive() const = 0; @@ -228,86 +229,83 @@ protected: void GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags); void GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags); - virtual void DoGenParseCode(Output *out, Env *env, - const DataPtr& data, - int flags) = 0; + virtual void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) = 0; string EvalLengthExpr(Output* out_cc, Env* env); // Generate code for computing the dynamic size of the type - virtual void GenDynamicSize(Output *out, Env *env, - const DataPtr& data) = 0; + virtual void GenDynamicSize(Output* out, Env* env, const DataPtr& data) = 0; - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); - virtual Type *DoClone() const = 0; + virtual Type* DoClone() const = 0; protected: TypeType tot_; - const TypeDecl *type_decl_; + const TypeDecl* type_decl_; bool declared_as_type_; - const ID *type_decl_id_; - Env *env_; + const ID* type_decl_id_; + Env* env_; - const ID *value_var_; - bool anonymous_value_var_; // whether the ID is anonymous + const ID* value_var_; + bool anonymous_value_var_; // whether the ID is anonymous string data_id_str_; int value_var_type_; - Field *size_var_field_; - char *size_expr_; + Field* size_var_field_; + char* size_expr_; bool boundary_checked_; string lvalue_; - FieldList *fields_; + FieldList* fields_; bool incremental_input_; bool incremental_parsing_; bool buffer_input_; // A boolean variable on whether parsing of the type is completed - Field *parsing_complete_var_field_; + Field* parsing_complete_var_field_; // An integer variable holding the parsing state - Field *parsing_state_var_field_; + Field* parsing_state_var_field_; - Field *buffering_state_var_field_; + Field* buffering_state_var_field_; // The array type with &until($input...) condition, if // "this" is the element type - ArrayType *array_until_input_; + ArrayType* array_until_input_; // A "has_*" member var for fields with &if - LetField *has_value_field_; + LetField* has_value_field_; // Attributes - AttrList *attrs_; + AttrList* attrs_; - Expr *attr_byteorder_expr_; - ExprList *attr_checks_; - ExprList *attr_enforces_; + Expr* attr_byteorder_expr_; + ExprList* attr_checks_; + ExprList* attr_enforces_; bool attr_chunked_; bool attr_exportsourcedata_; - Expr *attr_if_expr_; - Expr *attr_length_expr_; - FieldList *attr_letfields_; - Expr *attr_multiline_end_; - Expr *attr_linebreaker_; + Expr* attr_if_expr_; + Expr* attr_length_expr_; + FieldList* attr_letfields_; + Expr* attr_multiline_end_; + Expr* attr_linebreaker_; bool attr_oneline_; bool attr_refcount_; - ExprList *attr_requires_; + ExprList* attr_requires_; bool attr_restofdata_; bool attr_restofflow_; bool attr_transient_; public: static void init(); - static bool CompatibleTypes(Type *type1, Type *type2); - static void AddPredefinedType(const string &type_name, Type *type); - static Type *LookUpByID(ID *id); + static bool CompatibleTypes(Type* type1, Type* type2); + static void AddPredefinedType(const string& type_name, Type* type); + static Type* LookUpByID(ID* id); protected: - typedef map type_map_t; + typedef map type_map_t; static type_map_t type_map_; -}; + }; -#endif // pac_type_h +#endif // pac_type_h diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc index a26b2f7ab6..cb6238e059 100644 --- a/tools/binpac/src/pac_typedecl.cc +++ b/tools/binpac/src/pac_typedecl.cc @@ -1,3 +1,5 @@ +#include "pac_typedecl.h" + #include "pac_attr.h" #include "pac_context.h" #include "pac_dataptr.h" @@ -12,7 +14,6 @@ #include "pac_paramtype.h" #include "pac_record.h" #include "pac_type.h" -#include "pac_typedecl.h" #include "pac_utils.h" TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type) @@ -35,7 +36,7 @@ void TypeDecl::ProcessAttr(Attr* a) type_->ProcessAttr(a); } -void TypeDecl::AddParam(Param *param) +void TypeDecl::AddParam(Param* param) { // Cannot work after Prepare() ASSERT(! env_); @@ -65,19 +66,17 @@ void TypeDecl::Prepare() if ( type_->attr_byteorder_expr() ) { - DEBUG_MSG("Adding byteorder field to %s\n", - id()->Name()); - type_->AddField(new LetField(byteorder_id->clone(), - extern_type_int, - type_->attr_byteorder_expr())); + DEBUG_MSG("Adding byteorder field to %s\n", id()->Name()); + type_->AddField( + new LetField(byteorder_id->clone(), extern_type_int, type_->attr_byteorder_expr())); } type_->Prepare(env_, Type::TO_BE_PARSED); } string TypeDecl::class_name() const - { - return id_->Name(); + { + return id_->Name(); } void TypeDecl::GenForwardDeclaration(Output* out_h) @@ -99,13 +98,11 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc) if ( RequiresAnalyzerContext::compute(type_) ) { - DEBUG_MSG("%s requires analyzer context\n", - id()->Name()); - Type *param_type = analyzer_context()->param_type(); + DEBUG_MSG("%s requires analyzer context\n", id()->Name()); + Type* param_type = analyzer_context()->param_type(); env_->AddID(analyzer_context_id, TEMP_VAR, param_type); env_->SetEvaluated(analyzer_context_id); - env_->AddMacro(context_macro_id, - new Expr(analyzer_context_id->clone())); + env_->AddMacro(context_macro_id, new Expr(analyzer_context_id->clone())); } // Add parameter "byteorder" @@ -170,30 +167,25 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc) out_h->println("};\n"); } -void TypeDecl::GenPubDecls(Output* out_h, Output *out_cc) +void TypeDecl::GenPubDecls(Output* out_h, Output* out_cc) { // GenParamPubDecls(params_, out_h, env_); } -void TypeDecl::GenPrivDecls(Output* out_h, Output *out_cc) +void TypeDecl::GenPrivDecls(Output* out_h, Output* out_cc) { // GenParamPrivDecls(params_, out_h, env_); } -void TypeDecl::GenInitCode(Output *out_cc) - { - } +void TypeDecl::GenInitCode(Output* out_cc) { } -void TypeDecl::GenCleanUpCode(Output *out_cc) - { - } +void TypeDecl::GenCleanUpCode(Output* out_cc) { } void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc) { string params_str = ParamDecls(params_); - string proto = - strfmt("%s(%s)", class_name().c_str(), params_str.c_str()); + string proto = strfmt("%s(%s)", class_name().c_str(), params_str.c_str()); out_h->println("%s;", proto.c_str()); @@ -230,32 +222,29 @@ void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) string TypeDecl::ParseFuncPrototype(Env* env) { - const char *func_name = 0; - const char *return_type = 0; + const char* func_name = 0; + const char* return_type = 0; string params; if ( type_->incremental_input() ) { func_name = kParseFuncWithBuffer; return_type = "bool"; - params = strfmt("flow_buffer_t %s", - env->LValue(flow_buffer_id)); + params = strfmt("flow_buffer_t %s", env->LValue(flow_buffer_id)); } else { func_name = kParseFuncWithoutBuffer; return_type = "int"; params = strfmt("const_byteptr const %s, const_byteptr const %s", - env->LValue(begin_of_data), - env->LValue(end_of_data)); + env->LValue(begin_of_data), env->LValue(end_of_data)); } if ( RequiresAnalyzerContext::compute(type_) ) { - Type *param_type = analyzer_context()->param_type(); - params += strfmt(", %s %s", - param_type->DataTypeConstRefStr().c_str(), - env->LValue(analyzer_context_id)); + Type* param_type = analyzer_context()->param_type(); + params += strfmt(", %s %s", param_type->DataTypeConstRefStr().c_str(), + env->LValue(analyzer_context_id)); } // Add parameter "byteorder" @@ -265,11 +254,10 @@ string TypeDecl::ParseFuncPrototype(Env* env) } // Returns " %s()%s". - return strfmt("%s %%s%s(%s)%%s", - return_type, func_name, params.c_str()); + return strfmt("%s %%s%s(%s)%%s", return_type, func_name, params.c_str()); } -void TypeDecl::GenParsingEnd(Output *out_cc, Env *env, const DataPtr &data) +void TypeDecl::GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data) { string ret_val_0, ret_val_1; @@ -283,34 +271,30 @@ void TypeDecl::GenParsingEnd(Output *out_cc, Env *env, const DataPtr &data) ret_val_0 = type_->DataSize(0, env, data).c_str(); ret_val_1 = "@@@"; - out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", - env->RValue(begin_of_data), - ret_val_0.c_str(), - env->RValue(end_of_data)); + out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", env->RValue(begin_of_data), + ret_val_0.c_str(), env->RValue(end_of_data)); } - if ( type_->incremental_parsing() && - ( type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY ) ) + if ( type_->incremental_parsing() && + (type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY) ) { - // In which case parsing may jump to label + // In which case parsing may jump to label // "need_more_data" ... - out_cc->println("BINPAC_ASSERT(%s);", - type_->parsing_complete(env).c_str()); + out_cc->println("BINPAC_ASSERT(%s);", type_->parsing_complete(env).c_str()); out_cc->println("return %s;", ret_val_0.c_str()); out_cc->println(""); out_cc->dec_indent(); out_cc->println("%s:", kNeedMoreData); out_cc->inc_indent(); - out_cc->println("BINPAC_ASSERT(!(%s));", - type_->parsing_complete(env).c_str()); + out_cc->println("BINPAC_ASSERT(!(%s));", type_->parsing_complete(env).c_str()); out_cc->println("return %s;", ret_val_1.c_str()); } else if ( type_->incremental_input() ) { out_cc->println("return %s;", ret_val_0.c_str()); } - else + else { out_cc->println("return %s;", ret_val_0.c_str()); } @@ -323,7 +307,7 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) // Env within the parse function Env p_func_env(env_, this); - Env *env = &p_func_env; + Env* env = &p_func_env; if ( type_->incremental_input() ) { @@ -380,21 +364,19 @@ void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc) int init_buffer_length = type_->InitialBufferLength(); - if ( init_buffer_length < 0 ) // cannot be statically determined + if ( init_buffer_length < 0 ) // cannot be statically determined { - throw Exception(type()->attr_length_expr(), - strfmt("cannot determine initial buffer length" - " for type %s", id_->Name())); + throw Exception(type()->attr_length_expr(), strfmt("cannot determine initial buffer length" + " for type %s", + id_->Name())); } - out_h->println("int %s() const { return %d; }", - func.c_str(), - init_buffer_length); + out_h->println("int %s() const { return %d; }", func.c_str(), init_buffer_length); } -Type* TypeDecl::LookUpType(const ID *id) +Type* TypeDecl::LookUpType(const ID* id) { - Decl *decl = LookUpDecl(id); + Decl* decl = LookUpDecl(id); if ( ! decl ) return 0; switch ( decl->decl_type() ) @@ -402,11 +384,10 @@ Type* TypeDecl::LookUpType(const ID *id) case TYPE: case CONN: case FLOW: - return static_cast(decl)->type(); + return static_cast(decl)->type(); case ENUM: - return static_cast(decl)->DataType(); + return static_cast(decl)->DataType(); default: return 0; } } - diff --git a/tools/binpac/src/pac_typedecl.h b/tools/binpac/src/pac_typedecl.h index 2aea7ad183..e393596d63 100644 --- a/tools/binpac/src/pac_typedecl.h +++ b/tools/binpac/src/pac_typedecl.h @@ -4,44 +4,44 @@ #include "pac_decl.h" class TypeDecl : public Decl -{ + { public: - TypeDecl(ID *arg_id, ParamList *arg_params, Type *arg_type); + TypeDecl(ID* arg_id, ParamList* arg_params, Type* arg_type); ~TypeDecl(); void Prepare(); - void GenForwardDeclaration(Output *out_h); - void GenCode(Output *out_h, Output *out_cc); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); - Env *env() const { return env_; } - Type *type() const { return type_; } + Env* env() const { return env_; } + Type* type() const { return type_; } string class_name() const; - static Type *LookUpType(const ID *id); + static Type* LookUpType(const ID* id); protected: - void AddParam(Param *param); - virtual void AddBaseClass(vector *base_classes) const {} - void ProcessAttr(Attr *a); + void AddParam(Param* param); + virtual void AddBaseClass(vector* base_classes) const { } + void ProcessAttr(Attr* a); - virtual void GenPubDecls(Output *out_h, Output *out_cc); - virtual void GenPrivDecls(Output *out_h, Output *out_cc); - virtual void GenInitCode(Output *out_cc); - virtual void GenCleanUpCode(Output *out_cc); + virtual void GenPubDecls(Output* out_h, Output* out_cc); + virtual void GenPrivDecls(Output* out_h, Output* out_cc); + virtual void GenInitCode(Output* out_cc); + virtual void GenCleanUpCode(Output* out_cc); - void GenConstructorFunc(Output *out_h, Output *out_cc); - void GenDestructorFunc(Output *out_h, Output *out_cc); + void GenConstructorFunc(Output* out_h, Output* out_cc); + void GenDestructorFunc(Output* out_h, Output* out_cc); string ParseFuncPrototype(Env* env); - void GenParseFunc(Output *out_h, Output *out_cc); + void GenParseFunc(Output* out_h, Output* out_cc); - void GenParsingEnd(Output *out_cc, Env *env, const DataPtr &data); + void GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data); - void GenInitialBufferLengthFunc(Output *out_h, Output *out_cc); + void GenInitialBufferLengthFunc(Output* out_h, Output* out_cc); protected: - Env *env_; + Env* env_; - ParamList *params_; - Type *type_; -}; + ParamList* params_; + Type* type_; + }; -#endif // pac_typedecl_h +#endif // pac_typedecl_h diff --git a/tools/binpac/src/pac_utils.cc b/tools/binpac/src/pac_utils.cc index ac32edbad7..ea77fb6f86 100644 --- a/tools/binpac/src/pac_utils.cc +++ b/tools/binpac/src/pac_utils.cc @@ -1,17 +1,18 @@ -#include -#include -#include - #include "pac_utils.h" -char* copy_string(const char* s) - { - char* c = new char[strlen(s)+1]; - strcpy(c, s); - return c; - } +#include +#include +#include -namespace { +char* copy_string(const char* s) + { + char* c = new char[strlen(s) + 1]; + strcpy(c, s); + return c; + } + +namespace + { const char* do_fmt(const char* format, va_list ap) { @@ -20,7 +21,7 @@ const char* do_fmt(const char* format, va_list ap) return buf; } -} + } string strfmt(const char* format, ...) { diff --git a/tools/binpac/src/pac_varfield.cc b/tools/binpac/src/pac_varfield.cc index 76f36910f6..897c6f5020 100644 --- a/tools/binpac/src/pac_varfield.cc +++ b/tools/binpac/src/pac_varfield.cc @@ -1,6 +1,6 @@ #include "pac_varfield.h" -void PrivVarField::Prepare(Env *env) +void PrivVarField::Prepare(Env* env) { Field::Prepare(env); } diff --git a/tools/binpac/src/pac_varfield.h b/tools/binpac/src/pac_varfield.h index 8fea8879f9..8395ffa6ce 100644 --- a/tools/binpac/src/pac_varfield.h +++ b/tools/binpac/src/pac_varfield.h @@ -5,47 +5,53 @@ // A private variable evaluated with parsing class ParseVarField : public Field -{ + { public: - ParseVarField(int is_class_member, ID* id, Type *type) - : Field(PARSE_VAR_FIELD, - TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, - id, type) {} - void GenPubDecls(Output* out, Env* env) { /* do nothing */ } -}; + ParseVarField(int is_class_member, ID* id, Type* type) + : Field(PARSE_VAR_FIELD, TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, id, + type) + { + } + void GenPubDecls(Output* out, Env* env) + { /* do nothing */ + } + }; // A public variable class PubVarField : public Field -{ + { public: - PubVarField(ID* id, Type *type) - : Field(PUB_VAR_FIELD, - TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, - id, type) {} - ~PubVarField() {} -}; + PubVarField(ID* id, Type* type) + : Field(PUB_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) + { + } + ~PubVarField() { } + }; // A private variable class PrivVarField : public Field -{ + { public: - PrivVarField(ID* id, Type *type) - : Field(PRIV_VAR_FIELD, - TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, - id, type) {} - ~PrivVarField() {} + PrivVarField(ID* id, Type* type) + : Field(PRIV_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, id, + type) + { + } + ~PrivVarField() { } - void GenPubDecls(Output* out, Env* env) { /* do nothing */ } -}; + void GenPubDecls(Output* out, Env* env) + { /* do nothing */ + } + }; class TempVarField : public Field -{ + { public: - TempVarField(ID* id, Type *type) - : Field(TEMP_VAR_FIELD, - TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, - id, type) {} - ~TempVarField() {} -}; + TempVarField(ID* id, Type* type) + : Field(TEMP_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, id, type) + { + } + ~TempVarField() { } + }; -#endif // pac_varfield_h +#endif // pac_varfield_h diff --git a/tools/binpac/src/pac_withinput.cc b/tools/binpac/src/pac_withinput.cc index 8c39053046..93ecf290ea 100644 --- a/tools/binpac/src/pac_withinput.cc +++ b/tools/binpac/src/pac_withinput.cc @@ -1,14 +1,13 @@ #include "pac_withinput.h" + #include "pac_dataptr.h" #include "pac_expr.h" #include "pac_inputbuf.h" #include "pac_output.h" #include "pac_type.h" -WithInputField::WithInputField(ID* id, Type *type, InputBuffer* input) - : Field(WITHINPUT_FIELD, - TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, - id, type), +WithInputField::WithInputField(ID* id, Type* type, InputBuffer* input) + : Field(WITHINPUT_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), input_(input) { ASSERT(type_); @@ -20,16 +19,14 @@ WithInputField::~WithInputField() delete input_; } -bool WithInputField::DoTraverse(DataDepVisitor *visitor) - { - return Field::DoTraverse(visitor) && - input()->Traverse(visitor); +bool WithInputField::DoTraverse(DataDepVisitor* visitor) + { + return Field::DoTraverse(visitor) && input()->Traverse(visitor); } -bool WithInputField::RequiresAnalyzerContext() const - { - return Field::RequiresAnalyzerContext() || - (input() && input()->RequiresAnalyzerContext()); +bool WithInputField::RequiresAnalyzerContext() const + { + return Field::RequiresAnalyzerContext() || (input() && input()->RequiresAnalyzerContext()); } void WithInputField::Prepare(Env* env) @@ -43,11 +40,10 @@ void WithInputField::GenEval(Output* out_cc, Env* env) GenParseCode(out_cc, env); if ( type_->attr_if_expr() ) { - out_cc->println("BINPAC_ASSERT(%s);", - env->RValue(type_->has_value_var())); + out_cc->println("BINPAC_ASSERT(%s);", env->RValue(type_->has_value_var())); } } - + void WithInputField::GenParseCode(Output* out_cc, Env* env) { out_cc->println("// Parse \"%s\"", id_->Name()); @@ -55,8 +51,7 @@ void WithInputField::GenParseCode(Output* out_cc, Env* env) { // A conditional field env->Evaluate(out_cc, type_->has_value_var()); - out_cc->println("if ( %s )", - env->RValue(type_->has_value_var())); + out_cc->println("if ( %s )", env->RValue(type_->has_value_var())); out_cc->inc_indent(); out_cc->println("{"); } @@ -66,9 +61,7 @@ void WithInputField::GenParseCode(Output* out_cc, Env* env) Env field_env(env, this); ASSERT(! type_->incremental_input()); type_->GenPreParsing(out_cc, &field_env); - type_->GenParseCode(out_cc, &field_env, - input()->GenDataBeginEnd(out_cc, &field_env), - 0); + type_->GenParseCode(out_cc, &field_env, input()->GenDataBeginEnd(out_cc, &field_env), 0); if ( type_->attr_if_expr() ) { diff --git a/tools/binpac/src/pac_withinput.h b/tools/binpac/src/pac_withinput.h index 18b086d61a..d4daebc444 100644 --- a/tools/binpac/src/pac_withinput.h +++ b/tools/binpac/src/pac_withinput.h @@ -6,12 +6,12 @@ #include "pac_field.h" class WithInputField : public Field, public Evaluatable -{ + { public: - WithInputField(ID* id, Type *type, InputBuffer* input); + WithInputField(ID* id, Type* type, InputBuffer* input); virtual ~WithInputField(); - InputBuffer *input() const { return input_; } + InputBuffer* input() const { return input_; } void Prepare(Env* env); @@ -29,10 +29,10 @@ public: bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor *visitor); + bool DoTraverse(DataDepVisitor* visitor); protected: - InputBuffer *input_; -}; + InputBuffer* input_; + }; -#endif // pac_withinput_h +#endif // pac_withinput_h From dd3737b5c839ecc3a4b16586136d26f5266c3a8f Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 7 Jul 2022 11:53:54 -0700 Subject: [PATCH 112/343] binpac: Apply bits of nadi-bittorrent patch that aren't applied --- tools/binpac/patches/nadi-bittorrent.patch | 171 --------------------- tools/binpac/src/pac_flow.cc | 2 +- tools/binpac/src/pac_type.cc | 20 +-- 3 files changed, 9 insertions(+), 184 deletions(-) delete mode 100644 tools/binpac/patches/nadi-bittorrent.patch diff --git a/tools/binpac/patches/nadi-bittorrent.patch b/tools/binpac/patches/nadi-bittorrent.patch deleted file mode 100644 index de0b68311f..0000000000 --- a/tools/binpac/patches/nadi-bittorrent.patch +++ /dev/null @@ -1,171 +0,0 @@ -Index: src/pac_type.h -=================================================================== ---- src/pac_type.h (revision 4130) -+++ src/pac_type.h (working copy) -@@ -78,12 +78,6 @@ - string EvalByteOrder(Output *out_cc, Env *env) const; - - virtual string EvalMember(const ID *member_id) const; --#if 0 -- // member_env() is used for finding a member of the type. -- // Thus member_env() of a ParameterizedType should return -- // ReferredDataType()->env() -- // virtual Env *member_env() const; --#endif - - // The variable defined by the type - const ID *value_var() const { return value_var_; } -@@ -223,6 +217,8 @@ - - virtual bool ByteOrderSensitive() const = 0; - -+ bool NeedsBufferingStateVar() const; -+ - void GenBufferingLoop(Output* out_cc, Env* env, int flags); - void GenParseBuffer(Output* out_cc, Env* env, int flags); - void GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags); -Index: lib/binpac_buffer.h -=================================================================== ---- lib/binpac_buffer.h (revision 4130) -+++ lib/binpac_buffer.h (working copy) -@@ -24,18 +24,18 @@ - void DiscardData(); - - // Whether there is enough data for the frame -- bool ready() const{ return message_complete_; } -+ bool ready() const{ return message_complete_ || mode_ == UNKNOWN_MODE; } - - inline const_byteptr begin() const - { -- BINPAC_ASSERT(message_complete_); -+ BINPAC_ASSERT(ready()); - return ( buffer_n_ == 0 ) ? - orig_data_begin_ : buffer_; - } - - inline const_byteptr end() const - { -- BINPAC_ASSERT(message_complete_); -+ BINPAC_ASSERT(ready()); - if ( buffer_n_ == 0 ) - { - BINPAC_ASSERT(frame_length_ >= 0); -Index: src/pac_type.cc -=================================================================== ---- src/pac_type.cc (revision 4130) -+++ src/pac_type.cc (working copy) -@@ -285,9 +285,8 @@ - parsing_complete_var, extern_type_bool->Clone()); - parsing_complete_var_field_->Prepare(env); - -- if ( ( buffer_mode() == BUFFER_BY_LENGTH || -- buffer_mode() == BUFFER_BY_LINE ) && -- ! env->GetDataType(buffering_state_id) ) -+ if ( NeedsBufferingStateVar() && -+ !env->GetDataType(buffering_state_id) ) - { - buffering_state_var_field_ = new PrivVarField( - buffering_state_id->clone(), -@@ -387,17 +386,17 @@ - break; - - case BUFFER_BY_LENGTH: -- if ( buffering_state_var_field_ ) -- { -- out_cc->println("if ( %s == 0 )", -- env->RValue(buffering_state_id)); -- out_cc->inc_indent(); -- out_cc->println("{"); -- } -+ if ( !NeedsBufferingStateVar() ) -+ break; - -+ ASSERT(env->GetDataType(buffering_state_id)); -+ out_cc->println("if ( %s == 0 )", -+ env->RValue(buffering_state_id)); -+ out_cc->inc_indent(); -+ out_cc->println("{"); -+ - if ( attr_length_expr_ ) - { -- // frame_buffer_arg = attr_length_expr_->EvalExpr(out_cc, env); - frame_buffer_arg = strfmt("%d", InitialBufferLength()); - } - else if ( attr_restofflow_ ) -@@ -407,7 +406,7 @@ - } - else - { -- frame_buffer_arg = strfmt("%d", InitialBufferLength()); -+ ASSERT(0); - } - - out_cc->println("%s->NewFrame(%s, %s);", -@@ -415,16 +414,14 @@ - frame_buffer_arg.c_str(), - attr_chunked() ? "true" : "false"); - -- if ( buffering_state_var_field_ ) -- { -- out_cc->println("%s = 1;", -- env->LValue(buffering_state_id)); -- out_cc->println("}"); -- out_cc->dec_indent(); -- } -+ out_cc->println("%s = 1;", -+ env->LValue(buffering_state_id)); -+ out_cc->println("}"); -+ out_cc->dec_indent(); - break; - - case BUFFER_BY_LINE: -+ ASSERT(env->GetDataType(buffering_state_id)); - out_cc->println("if ( %s == 0 )", - env->RValue(buffering_state_id)); - out_cc->inc_indent(); -@@ -890,6 +887,25 @@ - return ! attr_byteorder_expr() && ByteOrderSensitive(); - } - -+bool Type::NeedsBufferingStateVar() const -+ { -+ if ( !incremental_input() ) -+ return false; -+ switch ( buffer_mode() ) -+ { -+ case BUFFER_NOTHING: -+ case NOT_BUFFERABLE: -+ return false; -+ case BUFFER_BY_LINE: -+ return true; -+ case BUFFER_BY_LENGTH: -+ return ( attr_length_expr_ || attr_restofflow_ ); -+ default: -+ ASSERT(0); -+ return false; -+ } -+ } -+ - bool Type::DoTraverse(DataDepVisitor *visitor) - { - foreach (i, FieldList, fields_) -Index: src/pac_flow.cc -=================================================================== ---- src/pac_flow.cc (revision 4130) -+++ src/pac_flow.cc (working copy) -@@ -224,15 +224,13 @@ - out_cc->println("catch ( Exception const &e )"); - out_cc->inc_indent(); - out_cc->println("{"); -- out_cc->println("DEBUG_MSG(\"%%.6f binpac exception: %%s\\n\", network_time(), e.c_msg());"); - GenCleanUpCode(out_cc); - if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) - { - out_cc->println("%s->DiscardData();", - env_->LValue(flow_buffer_id)); -- out_cc->println("BINPAC_ASSERT(!%s->ready());", -- env_->RValue(flow_buffer_id)); - } -+ out_cc->println("throw e;"); - out_cc->println("}"); - out_cc->dec_indent(); diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index fc0fd0a3eb..23406024ba 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -217,7 +217,7 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc) { out_cc->println("%s->DiscardData();", env_->LValue(flow_buffer_id)); } - out_cc->println("throw;"); + out_cc->println("throw e;"); out_cc->println("}"); out_cc->dec_indent(); diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index b50809edb8..dcf81b84a7 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -393,12 +393,10 @@ void Type::GenBufferConfiguration(Output* out_cc, Env* env) if ( ! NeedsBufferingStateVar() ) break; - if ( buffering_state_var_field_ ) - { - out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); - out_cc->inc_indent(); - out_cc->println("{"); - } + ASSERT(env->GetDataType(buffering_state_id)); + out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); + out_cc->inc_indent(); + out_cc->println("{"); if ( attr_length_expr_ ) { @@ -418,15 +416,13 @@ void Type::GenBufferConfiguration(Output* out_cc, Env* env) out_cc->println("%s->NewFrame(%s, %s);", env->LValue(flow_buffer_id), frame_buffer_arg.c_str(), attr_chunked() ? "true" : "false"); - if ( buffering_state_var_field_ ) - { - out_cc->println("%s = 1;", env->LValue(buffering_state_id)); - out_cc->println("}"); - out_cc->dec_indent(); - } + out_cc->println("%s = 1;", env->LValue(buffering_state_id)); + out_cc->println("}"); + out_cc->dec_indent(); break; case BUFFER_BY_LINE: + ASSERT(env->GetDataType(buffering_state_id)); out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); out_cc->inc_indent(); out_cc->println("{"); From faa1b7abbf4cb373aa04304b4b12c0c18c3bfb7d Mon Sep 17 00:00:00 2001 From: Elad Solomon Date: Thu, 22 Apr 2021 17:36:41 +0300 Subject: [PATCH 113/343] binpac: Adapted binpac to compile with MSVC for Windows environment. --- tools/binpac/lib/binpac.h.in | 4 +++- tools/binpac/lib/binpac_regex.cc | 4 ++-- tools/binpac/src/CMakeLists.txt | 13 +++++++++++-- tools/binpac/src/pac_dbg.h | 6 ++---- tools/binpac/src/pac_scan.ll | 15 +++++++++++---- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index b106df9f09..59dab550c3 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -3,7 +3,9 @@ #ifndef binpac_h #define binpac_h +#ifndef _MSC_VER #include +#endif #cmakedefine HOST_BIGENDIAN #ifdef HOST_BIGENDIAN @@ -136,7 +138,7 @@ inline string strfmt(const char* format, ...) } // anonymous namespace -#define binpac_fmt(x...) strfmt(x).c_str() +#define binpac_fmt(...) strfmt(__VA_ARGS__).c_str() class RefCount { diff --git a/tools/binpac/lib/binpac_regex.cc b/tools/binpac/lib/binpac_regex.cc index 9d6b890de4..22edffddcc 100644 --- a/tools/binpac/lib/binpac_regex.cc +++ b/tools/binpac/lib/binpac_regex.cc @@ -1,11 +1,11 @@ #include -class RE_Matcher; +namespace zeek { class RE_Matcher; } namespace binpac { -std::vector* uncompiled_re_matchers = 0; +std::vector* uncompiled_re_matchers = 0; } diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 54ceb335c8..f239f64a9b 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -4,8 +4,13 @@ bison_target(PACParser pac_parse.yy ${BinPAC_BINARY_DIR}/src/pac_parse.cc COMPILE_FLAGS "--debug") flex_target(PACScanner pac_scan.ll ${BinPAC_BINARY_DIR}/pac_scan.cc) add_flex_bison_dependency(PACScanner PACParser) -set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") - +if (MSVC) + set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") +else() + set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") +endif() +include(RequireCXX17) + include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src) @@ -100,6 +105,10 @@ set(binpac_SRCS add_executable(binpac ${binpac_SRCS}) +if ( MSVC ) + target_link_libraries(binpac PRIVATE zeek_windows) +endif() + install(TARGETS binpac DESTINATION bin) # This is set to assist superprojects that want to build BinPac diff --git a/tools/binpac/src/pac_dbg.h b/tools/binpac/src/pac_dbg.h index aebfda38fa..249a882a5c 100644 --- a/tools/binpac/src/pac_dbg.h +++ b/tools/binpac/src/pac_dbg.h @@ -6,9 +6,7 @@ extern bool FLAGS_pac_debug; -#define ASSERT(x) assert(x) -#define DEBUG_MSG(x...) \ - if ( FLAGS_pac_debug ) \ - fprintf(stderr, x) +#define ASSERT(x) assert(x) +#define DEBUG_MSG(...) if ( FLAGS_pac_debug ) fprintf(stderr, __VA_ARGS__) #endif /* pac_dbg_h */ diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index 7917fa98a1..dd90792bff 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -20,8 +20,10 @@ #include "pac_record.h" #include "pac_type.h" #include "pac_utils.h" -#include + #include +#include +#include int line_number = 1; @@ -42,6 +44,11 @@ int char_token(int tok) void include_file(const char *filename); +string dirname(std::string_view path) +{ + return std::filesystem::path(path).parent_path().string(); +} + %} /* EC -- embedded code state */ @@ -334,10 +341,10 @@ void include_file(const char *filename) { char* tmp = new char[strlen(input_filename.c_str()) + 1]; strcpy(tmp, input_filename.c_str()); - char* dir = dirname(tmp); + string dir = dirname(tmp); - if ( dir ) - full_filename = string(dir) + "/" + filename; + if ( ! dir.empty() ) + full_filename = dir + "/" + filename; else { fprintf(stderr, "%s:%d error: cannot include file \"%s\": %s\n", From d21f99ef2b2803df6350bc331896ec322cdf4141 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 18 Oct 2022 13:30:06 -0700 Subject: [PATCH 114/343] binpac: Wrap native dirname() call in ifdef, call std::filesystem on Windows --- tools/binpac/src/pac_scan.ll | 60 ++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index dd90792bff..0a11d9bb93 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -22,9 +22,15 @@ #include "pac_utils.h" #include -#include #include +#ifdef MSVC +#include +#else +#include +#include +#endif + int line_number = 1; int begin_pac_primitive(int tok); @@ -44,11 +50,24 @@ int char_token(int tok) void include_file(const char *filename); -string dirname(std::string_view path) -{ - return std::filesystem::path(path).parent_path().string(); -} +std::string do_dirname(std::string_view s) + { +#ifdef MSVC + return std::filesystem::path(path).parent_path().string(); +#else + std::unique_ptr tmp{new char[s.size()+1]}; + strncpy(tmp.get(), s.data(), s.size()); + tmp[s.size()] = '\0'; + char* dn = dirname(tmp.get()); + if ( !dn ) + return ""; + + std::string res{dn}; + + return res; +#endif + } %} /* EC -- embedded code state */ @@ -337,25 +356,20 @@ void include_file(const char *filename) string full_filename; if ( filename[0] == '/' ) full_filename = filename; - else if ( filename[0] == '.' ) - { - char* tmp = new char[strlen(input_filename.c_str()) + 1]; - strcpy(tmp, input_filename.c_str()); - string dir = dirname(tmp); + else if ( filename[0] == '.' ) + { + string dir = do_dirname(input_filename); - if ( ! dir.empty() ) - full_filename = dir + "/" + filename; - else - { - fprintf(stderr, "%s:%d error: cannot include file \"%s\": %s\n", - input_filename.c_str(), line_number, filename, - strerror(errno)); - delete [] tmp; - return; - } - - delete [] tmp; - } + if ( ! dir.empty() ) + full_filename = dir + "/" + filename; + else + { + fprintf(stderr, "%s:%d error: cannot include file \"%s\": %s\n", + input_filename.c_str(), line_number, filename, + strerror(errno)); + return; + } + } else { int i; From 60265b8ce7ab4418fffaf2b0bd6a5f4a662b4b5f Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Fri, 14 Oct 2022 13:42:53 +0200 Subject: [PATCH 115/343] binpac: pac_scan: Exit with failure for include errors Elsewhere (zeek/zeek#2482), it was observed that when binpac encounters include failures, it still exits with 0 indicating success. Subsequent compilation of the produced .h and .cc files likely fails. Exit with 1 on include errors to make pin pointing issues easier by having make/ninja stop earlier. --- tools/binpac/src/pac_scan.ll | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index 0a11d9bb93..b6e6fa3b58 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -337,8 +337,7 @@ void switch_to_file(const char *filename) { fprintf(stderr, "%s:%d: error: cannot include file \"%s\"\n", input_filename.c_str(), line_number,filename); - --include_stack_ptr; - return; + exit( 1 ); } yyin = fp; @@ -367,7 +366,7 @@ void include_file(const char *filename) fprintf(stderr, "%s:%d error: cannot include file \"%s\": %s\n", input_filename.c_str(), line_number, filename, strerror(errno)); - return; + exit( 1 ); } } else From 9a4e01e63491161b18b9c5e1c75403cdaf96893f Mon Sep 17 00:00:00 2001 From: Tomer Lev Date: Mon, 24 Oct 2022 16:34:57 +0300 Subject: [PATCH 116/343] binpac: Additional Windows fixes. Fixed wrong MSVC macro definition and std::filesystem invocation. Linking to libunistd library --- tools/binpac/src/CMakeLists.txt | 2 +- tools/binpac/src/pac_scan.ll | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index f239f64a9b..74920f3ea8 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -106,7 +106,7 @@ set(binpac_SRCS add_executable(binpac ${binpac_SRCS}) if ( MSVC ) - target_link_libraries(binpac PRIVATE zeek_windows) + target_link_libraries(binpac PRIVATE libunistd) endif() install(TARGETS binpac DESTINATION bin) diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index b6e6fa3b58..449403d76d 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -24,7 +24,7 @@ #include #include -#ifdef MSVC +#ifdef _MSC_VER #include #else #include @@ -52,8 +52,8 @@ void include_file(const char *filename); std::string do_dirname(std::string_view s) { -#ifdef MSVC - return std::filesystem::path(path).parent_path().string(); +#ifdef _MSC_VER + return std::filesystem::path(s).parent_path().string(); #else std::unique_ptr tmp{new char[s.size()+1]}; strncpy(tmp.get(), s.data(), s.size()); From d5f2c9c3a89efa8e8225354081d4bfd48e2b1e68 Mon Sep 17 00:00:00 2001 From: Tomer Lev Date: Wed, 26 Oct 2022 17:45:36 +0300 Subject: [PATCH 117/343] binpac: Only adding subdir if running standalone --- tools/binpac/src/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 74920f3ea8..24529cce6e 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -106,6 +106,11 @@ set(binpac_SRCS add_executable(binpac ${binpac_SRCS}) if ( MSVC ) + # If building separately from zeek, we need to add the libunistd subdirectory so + # that linking doesn't fail. + if ("${CMAKE_PROJECT_NAME}" STREQUAL "BinPAC") + add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) + endif() target_link_libraries(binpac PRIVATE libunistd) endif() From 49a96f5216b7038591fe8f98bcf9013b622f2eb1 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Tue, 13 Dec 2022 15:14:15 -0800 Subject: [PATCH 118/343] binpac: address linter warnings about use of sprintf() --- tools/binpac/src/pac_parse.yy | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/binpac/src/pac_parse.yy b/tools/binpac/src/pac_parse.yy index 178af0604e..b1172c307c 100644 --- a/tools/binpac/src/pac_parse.yy +++ b/tools/binpac/src/pac_parse.yy @@ -1068,17 +1068,17 @@ const ID* current_decl_id = 0; int yyerror(const char msg[]) { - char* msgbuf = - new char[strlen(msg) + yyleng + 64]; + auto n = strlen(msg) + yyleng + 64; + char* msgbuf = new char[n]; if ( ! yychar || ! yytext || yytext[0] == '\0' ) - sprintf(msgbuf, "%s, at end of file", msg); + snprintf(msgbuf, n, "%s, at end of file", msg); else if ( yytext[0] == '\n' ) - sprintf(msgbuf, "%s, on previous line", msg); + snprintf(msgbuf, n, "%s, on previous line", msg); else - sprintf(msgbuf, "%s, at or near \"%s\"", msg, yytext); + snprintf(msgbuf, n, "%s, at or near \"%s\"", msg, yytext); /* extern int column; From 9f3750d0ccb9450b4612ce2c98aa2a298e4d0dd6 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 27 Jan 2023 08:03:08 -0700 Subject: [PATCH 119/343] binpac: Apply clang-tidy's modernize-use-nullptr check --- tools/binpac/lib/binpac_buffer.cc | 10 ++--- tools/binpac/lib/binpac_regex.cc | 2 +- tools/binpac/src/pac_action.cc | 2 +- tools/binpac/src/pac_analyzer.cc | 10 ++--- tools/binpac/src/pac_array.cc | 34 +++++++------- tools/binpac/src/pac_array.h | 2 +- tools/binpac/src/pac_attr.cc | 4 +- tools/binpac/src/pac_btype.cc | 4 +- tools/binpac/src/pac_case.cc | 14 +++--- tools/binpac/src/pac_case.h | 2 +- tools/binpac/src/pac_conn.cc | 6 +-- tools/binpac/src/pac_context.cc | 6 +-- tools/binpac/src/pac_decl.cc | 8 ++-- tools/binpac/src/pac_decl.h | 2 +- tools/binpac/src/pac_embedded.cc | 2 +- tools/binpac/src/pac_enum.cc | 2 +- tools/binpac/src/pac_expr.cc | 40 ++++++++--------- tools/binpac/src/pac_field.cc | 2 +- tools/binpac/src/pac_flow.cc | 14 +++--- tools/binpac/src/pac_func.cc | 6 +-- tools/binpac/src/pac_id.cc | 75 ++++++++++++++++--------------- tools/binpac/src/pac_main.cc | 8 ++-- tools/binpac/src/pac_paramtype.cc | 2 +- tools/binpac/src/pac_primitive.cc | 6 +-- tools/binpac/src/pac_record.cc | 28 ++++++------ tools/binpac/src/pac_record.h | 2 +- tools/binpac/src/pac_strtype.cc | 13 +++--- tools/binpac/src/pac_type.cc | 44 +++++++++--------- tools/binpac/src/pac_typedecl.cc | 14 +++--- 29 files changed, 183 insertions(+), 181 deletions(-) diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index 9469251413..56ad6a8b77 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -30,10 +30,10 @@ binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = { FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) { buffer_length_ = 0; - buffer_ = 0; + buffer_ = nullptr; - orig_data_begin_ = 0; - orig_data_end_ = 0; + orig_data_begin_ = nullptr; + orig_data_end_ = nullptr; linebreak_style_ = linebreak_style; linebreak_style_default = linebreak_style; @@ -209,7 +209,7 @@ void FlowBuffer::DiscardData() mode_ = UNKNOWN_MODE; message_complete_ = false; have_pending_request_ = false; - orig_data_begin_ = orig_data_end_ = 0; + orig_data_begin_ = orig_data_end_ = nullptr; buffer_n_ = 0; frame_length_ = 0; @@ -289,7 +289,7 @@ void FlowBuffer::NewGap(int length) frame_length_ = 0; } - orig_data_begin_ = orig_data_end_ = 0; + orig_data_begin_ = orig_data_end_ = nullptr; MarkOrCopy(); } diff --git a/tools/binpac/lib/binpac_regex.cc b/tools/binpac/lib/binpac_regex.cc index 22edffddcc..38379623de 100644 --- a/tools/binpac/lib/binpac_regex.cc +++ b/tools/binpac/lib/binpac_regex.cc @@ -6,6 +6,6 @@ namespace zeek { class RE_Matcher; } namespace binpac { -std::vector* uncompiled_re_matchers = 0; +std::vector* uncompiled_re_matchers = nullptr; } diff --git a/tools/binpac/src/pac_action.cc b/tools/binpac/src/pac_action.cc index 549672ad88..6a536184ee 100644 --- a/tools/binpac/src/pac_action.cc +++ b/tools/binpac/src/pac_action.cc @@ -10,7 +10,7 @@ AnalyzerAction::AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code) : AnalyzerElement(ACTION), action_id_(action_id), when_(when), param_(param), code_(code), - analyzer_(0) + analyzer_(nullptr) { } diff --git a/tools/binpac/src/pac_analyzer.cc b/tools/binpac/src/pac_analyzer.cc index 918678cadb..3a3b5a7c7b 100644 --- a/tools/binpac/src/pac_analyzer.cc +++ b/tools/binpac/src/pac_analyzer.cc @@ -30,7 +30,7 @@ AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params) SetAnalyzerContext(); - env_ = 0; + env_ = nullptr; } AnalyzerDecl::~AnalyzerDecl() @@ -205,7 +205,7 @@ void AnalyzerDecl::GenInitCode(Output* out_cc) TypeDecl::GenInitCode(out_cc); foreach (i, AnalyzerHelperList, constructor_helpers_) { - (*i)->GenCode(0, out_cc, this); + (*i)->GenCode(nullptr, out_cc, this); } } @@ -214,7 +214,7 @@ void AnalyzerDecl::GenCleanUpCode(Output* out_cc) TypeDecl::GenCleanUpCode(out_cc); foreach (i, AnalyzerHelperList, destructor_helpers_) { - (*i)->GenCode(0, out_cc, this); + (*i)->GenCode(nullptr, out_cc, this); } } @@ -277,7 +277,7 @@ AnalyzerHelper::~AnalyzerHelper() void AnalyzerHelper::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) { - Output* out = 0; + Output* out = nullptr; switch ( helper_type_ ) { case MEMBER_DECLS: @@ -318,7 +318,7 @@ AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params) flow_field_ = new FlowField(flow_id, flow_type); - flow_decl_ = 0; + flow_decl_ = nullptr; } AnalyzerFlow::~AnalyzerFlow() diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index ebaed479ca..d37a6c1a4d 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -37,13 +37,13 @@ ArrayType::ArrayType(Type* elemtype, Expr* length) void ArrayType::init() { - arraylength_var_field_ = 0; - elem_it_var_field_ = 0; - elem_var_field_ = 0; - elem_dataptr_var_field_ = 0; - elem_input_var_field_ = 0; + arraylength_var_field_ = nullptr; + elem_it_var_field_ = nullptr; + elem_var_field_ = nullptr; + elem_dataptr_var_field_ = nullptr; + elem_input_var_field_ = nullptr; - elem_dataptr_until_expr_ = 0; + elem_dataptr_until_expr_ = nullptr; end_of_array_loop_label_ = "@@@"; @@ -51,9 +51,9 @@ void ArrayType::init() datatype_str_ = strfmt("%s *", vector_str_.c_str()); - attr_generic_until_expr_ = 0; - attr_until_element_expr_ = 0; - attr_until_input_expr_ = 0; + attr_generic_until_expr_ = nullptr; + attr_until_element_expr_ = nullptr; + attr_until_input_expr_ = nullptr; } ArrayType::~ArrayType() @@ -71,7 +71,7 @@ Type* ArrayType::DoClone() const { Type* elemtype = elemtype_->Clone(); if ( ! elemtype ) - return 0; + return nullptr; return new ArrayType(elemtype, length_); } @@ -100,27 +100,27 @@ string ArrayType::EvalElement(const string& array, const string& index) const const ID* ArrayType::arraylength_var() const { - return arraylength_var_field_ ? arraylength_var_field_->id() : 0; + return arraylength_var_field_ ? arraylength_var_field_->id() : nullptr; } const ID* ArrayType::elem_it_var() const { - return elem_it_var_field_ ? elem_it_var_field_->id() : 0; + return elem_it_var_field_ ? elem_it_var_field_->id() : nullptr; } const ID* ArrayType::elem_var() const { - return elem_var_field_ ? elem_var_field_->id() : 0; + return elem_var_field_ ? elem_var_field_->id() : nullptr; } const ID* ArrayType::elem_dataptr_var() const { - return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : 0; + return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : nullptr; } const ID* ArrayType::elem_input_var() const { - return elem_input_var_field_ ? elem_input_var_field_->id() : 0; + return elem_input_var_field_ ? elem_input_var_field_->id() : nullptr; } void ArrayType::ProcessAttr(Attr* a) @@ -499,7 +499,7 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in ASSERT(elem_it_var()); - DataPtr elem_data(env, 0, 0); + DataPtr elem_data(env, nullptr, 0); if ( elem_dataptr_var() ) { @@ -554,7 +554,7 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in if ( elem_dataptr_var() ) { out_cc->println("%s += %s;", env->LValue(elem_dataptr_var()), - elemtype_->DataSize(0, env, elem_data).c_str()); + elemtype_->DataSize(nullptr, env, elem_data).c_str()); out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(elem_dataptr_var()), env->RValue(end_of_data)); } diff --git a/tools/binpac/src/pac_array.h b/tools/binpac/src/pac_array.h index 2433803fab..01f770d1d5 100644 --- a/tools/binpac/src/pac_array.h +++ b/tools/binpac/src/pac_array.h @@ -9,7 +9,7 @@ class ArrayType : public Type { public: - ArrayType(Type* arg_elemtype, Expr* arg_length = 0); + ArrayType(Type* arg_elemtype, Expr* arg_length = nullptr); ~ArrayType(); bool DefineValueVar() const; diff --git a/tools/binpac/src/pac_attr.cc b/tools/binpac/src/pac_attr.cc index 004388eb87..b4ba16e37c 100644 --- a/tools/binpac/src/pac_attr.cc +++ b/tools/binpac/src/pac_attr.cc @@ -16,8 +16,8 @@ bool Attr::RequiresAnalyzerContext() const void Attr::init() { - expr_ = 0; - seqend_ = 0; + expr_ = nullptr; + seqend_ = nullptr; delete_expr_ = false; } diff --git a/tools/binpac/src/pac_btype.cc b/tools/binpac/src/pac_btype.cc index ae09bdb42b..47939dde8c 100644 --- a/tools/binpac/src/pac_btype.cc +++ b/tools/binpac/src/pac_btype.cc @@ -25,7 +25,7 @@ static const char* basic_pactype_name[] = { #define TYPE_DEF(name, pactype, ctype, size) pactype, #include "pac_type.def" #undef TYPE_DEF - 0, + nullptr, }; void BuiltInType::static_init() @@ -49,7 +49,7 @@ static const char* basic_ctype_name[] = { #define TYPE_DEF(name, pactype, ctype, size) ctype, #include "pac_type.def" #undef TYPE_DEF - 0, + nullptr, }; bool BuiltInType::DefineValueVar() const diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index 2d326bf597..68fede97ad 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -15,7 +15,7 @@ CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) : Type(CASE), index_expr_(index_expr), cases_(cases) { - index_var_ = 0; + index_var_ = nullptr; foreach (i, CaseFieldList, cases_) AddField(*i); } @@ -55,7 +55,7 @@ Type* CaseType::ValueType() const return c->type(); } ASSERT(0); - return 0; + return nullptr; } string CaseType::DefaultValue() const @@ -70,11 +70,11 @@ void CaseType::Prepare(Env* env, int flags) index_var_ = new ID(strfmt("%s_case_index", value_var()->Name())); // Unable to get the type for index_var_ at this moment, but we'll // generate the right type based on index_expr_ later. - env->AddID(index_var_, MEMBER_VAR, 0); + env->AddID(index_var_, MEMBER_VAR, nullptr); // Sort the cases_ to put the default case at the end of the list CaseFieldList::iterator default_case_it = cases_->end(); // to avoid warning - CaseField* default_case = 0; + CaseField* default_case = nullptr; foreach (i, CaseFieldList, cases_) { @@ -173,7 +173,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int foreach (i, CaseFieldList, cases_) { CaseField* c = *i; - c->GenParseCode(out_cc, env, data, compute_size_var ? size_var() : 0); + c->GenParseCode(out_cc, env, data, compute_size_var ? size_var() : nullptr); if ( c->IsDefaultCase() ) has_default_case = true; } @@ -249,8 +249,8 @@ CaseField::CaseField(ExprList* index, ID* id, Type* type) { ASSERT(type_); type_->set_value_var(id, MEMBER_VAR); - case_type_ = 0; - index_var_ = 0; + case_type_ = nullptr; + index_var_ = nullptr; } CaseField::~CaseField() diff --git a/tools/binpac/src/pac_case.h b/tools/binpac/src/pac_case.h index 560dd8e35f..7d440fffa0 100644 --- a/tools/binpac/src/pac_case.h +++ b/tools/binpac/src/pac_case.h @@ -39,7 +39,7 @@ public: protected: void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); void GenDynamicSize(Output* out, Env* env, const DataPtr& data); - Type* DoClone() const { return 0; } + Type* DoClone() const { return nullptr; } void DoMarkIncrementalInput(); bool ByteOrderSensitive() const; diff --git a/tools/binpac/src/pac_conn.cc b/tools/binpac/src/pac_conn.cc index 409ae1e43a..385be6245e 100644 --- a/tools/binpac/src/pac_conn.cc +++ b/tools/binpac/src/pac_conn.cc @@ -13,9 +13,9 @@ ConnDecl::ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist) : AnalyzerDecl(conn_id, CONN, params) { - flows_[0] = flows_[1] = 0; + flows_[0] = flows_[1] = nullptr; AddElements(elemlist); - data_type_ = new ParameterizedType(conn_id->clone(), 0); + data_type_ = new ParameterizedType(conn_id->clone(), nullptr); } ConnDecl::~ConnDecl() @@ -92,7 +92,7 @@ void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc) foreach (i, AnalyzerHelperList, eof_helpers_) { - (*i)->GenCode(0, out_cc, this); + (*i)->GenCode(nullptr, out_cc, this); } out_cc->dec_indent(); diff --git a/tools/binpac/src/pac_context.cc b/tools/binpac/src/pac_context.cc index 6d7c12b6df..773014eeb7 100644 --- a/tools/binpac/src/pac_context.cc +++ b/tools/binpac/src/pac_context.cc @@ -16,7 +16,7 @@ ContextField::ContextField(ID* id, Type* type) { } -AnalyzerContextDecl* AnalyzerContextDecl::current_analyzer_context_ = 0; +AnalyzerContextDecl* AnalyzerContextDecl::current_analyzer_context_ = nullptr; namespace { @@ -38,7 +38,7 @@ AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_field new DummyType()) { context_name_id_ = id; - if ( current_analyzer_context_ != 0 ) + if ( current_analyzer_context_ != nullptr ) { throw Exception(this, strfmt("multiple declaration of analyzer context; " "the previous one is `%s'", @@ -49,7 +49,7 @@ AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_field context_fields_ = context_fields; - param_type_ = new ParameterizedType(id_->clone(), 0); + param_type_ = new ParameterizedType(id_->clone(), nullptr); flow_buffer_added_ = false; diff --git a/tools/binpac/src/pac_decl.cc b/tools/binpac/src/pac_decl.cc index 3982e10116..fc0f74ea64 100644 --- a/tools/binpac/src/pac_decl.cc +++ b/tools/binpac/src/pac_decl.cc @@ -14,10 +14,10 @@ #include "pac_type.h" #include "pac_utils.h" -DeclList* Decl::decl_list_ = 0; +DeclList* Decl::decl_list_ = nullptr; Decl::DeclMap Decl::decl_map_; -Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(0) +Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(nullptr) { decl_map_[id_] = this; if ( ! decl_list_ ) @@ -26,7 +26,7 @@ Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlis DEBUG_MSG("Finished Decl %s\n", id_->Name()); - analyzer_context_ = 0; + analyzer_context_ = nullptr; } Decl::~Decl() @@ -119,7 +119,7 @@ Decl* Decl::LookUpDecl(const ID* id) { DeclMap::iterator it = decl_map_.find(id); if ( it == decl_map_.end() ) - return 0; + return nullptr; return it->second; } diff --git a/tools/binpac/src/pac_decl.h b/tools/binpac/src/pac_decl.h index 4602fdac50..5e806389c8 100644 --- a/tools/binpac/src/pac_decl.h +++ b/tools/binpac/src/pac_decl.h @@ -30,7 +30,7 @@ public: AnalyzerContextDecl* analyzer_context() const { return analyzer_context_; } // NULL except for TypeDecl or AnalyzerDecl - virtual Env* env() const { return 0; } + virtual Env* env() const { return nullptr; } virtual void Prepare() = 0; diff --git a/tools/binpac/src/pac_embedded.cc b/tools/binpac/src/pac_embedded.cc index 1c07c6a218..9c10c594e2 100644 --- a/tools/binpac/src/pac_embedded.cc +++ b/tools/binpac/src/pac_embedded.cc @@ -4,7 +4,7 @@ #include "pac_output.h" #include "pac_primitive.h" -EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(0) { } +EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(nullptr) { } EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive* primitive) : s_(""), primitive_(primitive) { } diff --git a/tools/binpac/src/pac_enum.cc b/tools/binpac/src/pac_enum.cc index f58dad5d86..d52b9ea32e 100644 --- a/tools/binpac/src/pac_enum.cc +++ b/tools/binpac/src/pac_enum.cc @@ -32,7 +32,7 @@ EnumDecl::EnumDecl(ID* id, EnumList* enumlist) : Decl(id, ENUM), enumlist_(enuml { ID* type_id = id->clone(); datatype_ = new ExternType(type_id, ExternType::NUMBER); - extern_typedecl_ = new TypeDecl(type_id, 0, datatype_); + extern_typedecl_ = new TypeDecl(type_id, nullptr, datatype_); } EnumDecl::~EnumDecl() diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index f45b6c3344..ca51b0282d 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -53,16 +53,16 @@ static const char* expr_fmt[] = { void Expr::init() { - id_ = 0; - num_ = 0; - cstr_ = 0; - regex_ = 0; + id_ = nullptr; + num_ = nullptr; + cstr_ = nullptr; + regex_ = nullptr; num_operands_ = 0; - operand_[0] = 0; - operand_[1] = 0; - operand_[2] = 0; - args_ = 0; - cases_ = 0; + operand_[0] = nullptr; + operand_[1] = nullptr; + operand_[2] = nullptr; + args_ = nullptr; + cases_ = nullptr; } Expr::Expr(ID* arg_id) : DataDepElement(EXPR) @@ -117,7 +117,7 @@ Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) : DataDepElement(EXPR) num_operands_ = 2; operand_[0] = op1; operand_[1] = op2; - operand_[2] = 0; + operand_[2] = nullptr; orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig()); } @@ -244,7 +244,7 @@ void Expr::GenCaseEval(Output* out_cc, Env* env) out_cc->inc_indent(); out_cc->println("{"); - CaseExpr* default_case = 0; + CaseExpr* default_case = nullptr; foreach (i, CaseExprList, cases_) { CaseExpr* c = *i; @@ -266,7 +266,7 @@ void Expr::GenCaseEval(Output* out_cc, Env* env) } // Generate the default case after all other cases - GenCaseStr(0, out_cc, env, switch_type); + GenCaseStr(nullptr, out_cc, env, switch_type); out_cc->inc_indent(); if ( default_case ) { @@ -351,14 +351,14 @@ void Expr::GenEval(Output* out_cc, Env* env) try { - if ( (rf = GetRecordField(id, env)) != 0 ) + if ( (rf = GetRecordField(id, env)) != nullptr ) { str_ = strfmt("%s", rf->FieldSize(out_cc, env)); } } catch ( ExceptionIDNotFound& e ) { - if ( (ty = TypeDecl::LookUpType(id)) != 0 ) + if ( (ty = TypeDecl::LookUpType(id)) != nullptr ) { int ty_size = ty->StaticSize(global_env()); if ( ty_size >= 0 ) @@ -461,7 +461,7 @@ Type* Expr::DataType(Env* env) const // Get type of the parent Type* parent_type = operand_[0]->DataType(env); if ( ! parent_type ) - return 0; + return nullptr; data_type = parent_type->MemberDataType(operand_[1]->id()); } break; @@ -501,7 +501,7 @@ Type* Expr::DataType(Env* env) const if ( cases_ && ! cases_->empty() ) { Type* type1 = cases_->front()->value()->DataType(env); - Type* numeric_with_largest_width = 0; + Type* numeric_with_largest_width = nullptr; foreach (i, CaseExprList, cases_) { @@ -544,7 +544,7 @@ Type* Expr::DataType(Env* env) const data_type = numeric_with_largest_width ? numeric_with_largest_width : type1; } else - data_type = 0; + data_type = nullptr; } break; @@ -575,7 +575,7 @@ Type* Expr::DataType(Env* env) const break; default: - data_type = 0; + data_type = nullptr; break; } @@ -812,7 +812,7 @@ int Expr::MinimalHeaderSize(Env* env) RecordField* rf; Type* ty; - if ( (rf = GetRecordField(id, env)) != 0 ) + if ( (rf = GetRecordField(id, env)) != nullptr ) { if ( rf->StaticSize(env, -1) >= 0 ) mhs = 0; @@ -820,7 +820,7 @@ int Expr::MinimalHeaderSize(Env* env) mhs = mhs_recordfield(env, rf); } - else if ( (ty = TypeDecl::LookUpType(id)) != 0 ) + else if ( (ty = TypeDecl::LookUpType(id)) != nullptr ) { mhs = 0; } diff --git a/tools/binpac/src/pac_field.cc b/tools/binpac/src/pac_field.cc index 36205ba8a0..dc9fd81fb1 100644 --- a/tools/binpac/src/pac_field.cc +++ b/tools/binpac/src/pac_field.cc @@ -11,7 +11,7 @@ Field::Field(FieldType tof, int flags, ID* id, Type* type) { decl_id_ = current_decl_id; field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name()); - attrs_ = 0; + attrs_ = nullptr; } Field::~Field() diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index 23406024ba..ddf6029b01 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -18,9 +18,9 @@ FlowDecl::FlowDecl(ID* id, ParamList* params, AnalyzerElementList* elemlist) : AnalyzerDecl(id, FLOW, params) { - dataunit_ = 0; - conn_decl_ = 0; - flow_buffer_var_field_ = 0; + dataunit_ = nullptr; + conn_decl_ = nullptr; + flow_buffer_var_field_ = nullptr; AddElements(elemlist); } @@ -30,13 +30,13 @@ FlowDecl::~FlowDecl() delete dataunit_; } -ParameterizedType* FlowDecl::flow_buffer_type_ = 0; +ParameterizedType* FlowDecl::flow_buffer_type_ = nullptr; ParameterizedType* FlowDecl::flow_buffer_type() { if ( ! flow_buffer_type_ ) { - flow_buffer_type_ = new ParameterizedType(new ID(kFlowBufferClass), 0); + flow_buffer_type_ = new ParameterizedType(new ID(kFlowBufferClass), nullptr); } return flow_buffer_type_; } @@ -141,7 +141,7 @@ void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc) foreach (i, AnalyzerHelperList, eof_helpers_) { - (*i)->GenCode(0, out_cc, this); + (*i)->GenCode(nullptr, out_cc, this); } if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) @@ -268,7 +268,7 @@ void FlowDecl::GenCodeFlowUnit(Output* out_cc) out_cc->println("}"); out_cc->dec_indent(); - DataPtr data(env_, 0, 0); + DataPtr data(env_, nullptr, 0); unit_datatype->GenParseCode(out_cc, env_, data, 0); out_cc->println("if ( %s )", unit_datatype->parsing_complete(env_).c_str()); diff --git a/tools/binpac/src/pac_func.cc b/tools/binpac/src/pac_func.cc index 40894621cb..9770be4747 100644 --- a/tools/binpac/src/pac_func.cc +++ b/tools/binpac/src/pac_func.cc @@ -7,10 +7,10 @@ #include "pac_type.h" Function::Function(ID* id, Type* type, ParamList* params) - : id_(id), type_(type), params_(params), expr_(0), code_(0) + : id_(id), type_(type), params_(params), expr_(nullptr), code_(nullptr) { - analyzer_decl_ = 0; - env_ = 0; + analyzer_decl_ = nullptr; + env_ = nullptr; } Function::~Function() diff --git a/tools/binpac/src/pac_id.cc b/tools/binpac/src/pac_id.cc index 1d4002b114..15a0d7c12d 100644 --- a/tools/binpac/src/pac_id.cc +++ b/tools/binpac/src/pac_id.cc @@ -7,34 +7,34 @@ #include "pac_type.h" #include "pac_utils.h" -const ID* default_value_var = 0; -const ID* null_id = 0; -const ID* null_byteseg_id = 0; -const ID* null_decl_id = 0; -const ID* begin_of_data = 0; -const ID* end_of_data = 0; -const ID* len_of_data = 0; -const ID* byteorder_id = 0; -const ID* bigendian_id = 0; -const ID* littleendian_id = 0; -const ID* unspecified_byteorder_id = 0; -const ID* const_true_id = 0; -const ID* const_false_id = 0; -const ID* analyzer_context_id = 0; -const ID* context_macro_id = 0; -const ID* this_id = 0; -const ID* sourcedata_id = 0; -const ID* connection_id = 0; -const ID* upflow_id = 0; -const ID* downflow_id = 0; -const ID* dataunit_id = 0; -const ID* flow_buffer_id = 0; -const ID* element_macro_id = 0; -const ID* input_macro_id = 0; -const ID* cxt_connection_id = 0; -const ID* cxt_flow_id = 0; -const ID* parsing_state_id = 0; -const ID* buffering_state_id = 0; +const ID* default_value_var = nullptr; +const ID* null_id = nullptr; +const ID* null_byteseg_id = nullptr; +const ID* null_decl_id = nullptr; +const ID* begin_of_data = nullptr; +const ID* end_of_data = nullptr; +const ID* len_of_data = nullptr; +const ID* byteorder_id = nullptr; +const ID* bigendian_id = nullptr; +const ID* littleendian_id = nullptr; +const ID* unspecified_byteorder_id = nullptr; +const ID* const_true_id = nullptr; +const ID* const_false_id = nullptr; +const ID* analyzer_context_id = nullptr; +const ID* context_macro_id = nullptr; +const ID* this_id = nullptr; +const ID* sourcedata_id = nullptr; +const ID* connection_id = nullptr; +const ID* upflow_id = nullptr; +const ID* downflow_id = nullptr; +const ID* dataunit_id = nullptr; +const ID* flow_buffer_id = nullptr; +const ID* element_macro_id = nullptr; +const ID* input_macro_id = nullptr; +const ID* cxt_connection_id = nullptr; +const ID* cxt_flow_id = nullptr; +const ID* parsing_state_id = nullptr; +const ID* buffering_state_id = nullptr; int ID::anonymous_id_seq = 0; @@ -48,7 +48,7 @@ ID* ID::NewAnonymousID(const string& prefix) IDRecord::IDRecord(Env* arg_env, const ID* arg_id, IDType arg_id_type) : env(arg_env), id(arg_id), id_type(arg_id_type) { - eval = 0; + eval = nullptr; evaluated = in_evaluation = false; setfunc = ""; // except for STATE_VAR switch ( id_type ) @@ -91,10 +91,11 @@ IDRecord::IDRecord(Env* arg_env, const ID* arg_id, IDType arg_id_type) lvalue = "@FUNC_PARAM@"; break; } - data_type = 0; - field = 0; + + data_type = nullptr; + field = nullptr; constant = constant_set = false; - macro = 0; + macro = nullptr; } IDRecord::~IDRecord() { } @@ -156,7 +157,7 @@ void IDRecord::Evaluate(Output* out, Env* env) const char* IDRecord::RValue() const { if ( id_type == MACRO ) - return macro->EvalExpr(0, env); + return macro->EvalExpr(nullptr, env); if ( id_type == TEMP_VAR && ! evaluated ) throw ExceptionIDNotEvaluated(id); @@ -238,7 +239,7 @@ IDRecord* Env::lookup(const ID* id, bool recursive, bool raise_exception) const if ( raise_exception ) throw ExceptionIDNotFound(id); else - return 0; + return nullptr; } IDType Env::GetIDType(const ID* id) const @@ -334,7 +335,7 @@ Type* Env::GetDataType(const ID* id) const if ( r ) return r->GetDataType(); else - return 0; + return nullptr; } string Env::DataTypeStr(const ID* id) const @@ -405,11 +406,11 @@ void init_builtin_identifiers() Env* global_env() { - static Env* the_global_env = 0; + static Env* the_global_env = nullptr; if ( ! the_global_env ) { - the_global_env = new Env(0, 0); + the_global_env = new Env(nullptr, nullptr); // These two are defined in binpac.h, so we do not need to // generate code for them. diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index c54eabea4b..bea647a550 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -22,8 +22,8 @@ bool FLAGS_quiet = false; string FLAGS_output_directory; vector FLAGS_include_directories; -Output* header_output = 0; -Output* source_output = 0; +Output* header_output = nullptr; +Output* source_output = nullptr; void add_to_include_directories(string dirs) { @@ -182,8 +182,8 @@ int compile(const char* filename) exit(1); } - header_output = 0; - source_output = 0; + header_output = nullptr; + source_output = nullptr; input_filename = ""; fclose(fp_input); diff --git a/tools/binpac/src/pac_paramtype.cc b/tools/binpac/src/pac_paramtype.cc index a5fd579e8c..7fe61fe128 100644 --- a/tools/binpac/src/pac_paramtype.cc +++ b/tools/binpac/src/pac_paramtype.cc @@ -50,7 +50,7 @@ Type* ParameterizedType::MemberDataType(const ID* member_id) const { Type* ref_type = TypeDecl::LookUpType(type_id_); if ( ! ref_type ) - return 0; + return nullptr; return ref_type->MemberDataType(member_id); } diff --git a/tools/binpac/src/pac_primitive.cc b/tools/binpac/src/pac_primitive.cc index 51398340a6..2a5f47a2ee 100644 --- a/tools/binpac/src/pac_primitive.cc +++ b/tools/binpac/src/pac_primitive.cc @@ -8,13 +8,13 @@ string PPVal::ToCode(Env* env) { ASSERT(expr_); - return string(expr_->EvalExpr(0, env)); + return string(expr_->EvalExpr(nullptr, env)); } string PPSet::ToCode(Env* env) { ASSERT(expr_); - return expr_->SetFunc(0, env); + return expr_->SetFunc(nullptr, env); } string PPType::ToCode(Env* env) @@ -30,5 +30,5 @@ string PPConstDef::ToCode(Env* env) env->SetEvaluated(id_); string type_str = type->DataTypeStr(); - return strfmt("%s %s = %s", type_str.c_str(), env->LValue(id_), expr_->EvalExpr(0, env)); + return strfmt("%s %s = %s", type_str.c_str(), env->LValue(id_), expr_->EvalExpr(nullptr, env)); } diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index 9b9f9e17df..266dfc6dcf 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -15,7 +15,7 @@ RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD) { // Here we assume that the type is a standalone type. - value_var_ = 0; + value_var_ = nullptr; // Put all fields in fields_ foreach (i, RecordFieldList, record_fields) @@ -24,7 +24,7 @@ RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD) // Put RecordField's in record_fields_ record_fields_ = record_fields; - parsing_dataptr_var_field_ = 0; + parsing_dataptr_var_field_ = nullptr; } RecordType::~RecordType() @@ -37,7 +37,7 @@ RecordType::~RecordType() const ID* RecordType::parsing_dataptr_var() const { - return parsing_dataptr_var_field_ ? parsing_dataptr_var_field_->id() : 0; + return parsing_dataptr_var_field_ ? parsing_dataptr_var_field_->id() : nullptr; } bool RecordType::DefineValueVar() const @@ -55,7 +55,7 @@ void RecordType::Prepare(Env* env, int flags) { ASSERT(flags & TO_BE_PARSED); - RecordField* prev = 0; + RecordField* prev = nullptr; int offset = 0; int seq = 0; foreach (i, RecordFieldList, record_fields_) @@ -237,14 +237,14 @@ bool RecordType::ByteOrderSensitive() const RecordField::RecordField(FieldType tof, ID* id, Type* type) : Field(tof, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) { - begin_of_field_dataptr = 0; - end_of_field_dataptr = 0; - field_size_expr = 0; - field_offset_expr = 0; - end_of_field_dataptr_var = 0; - record_type_ = 0; - prev_ = 0; - next_ = 0; + begin_of_field_dataptr = nullptr; + end_of_field_dataptr = nullptr; + field_size_expr = nullptr; + field_offset_expr = nullptr; + end_of_field_dataptr_var = nullptr; + record_type_ = nullptr; + prev_ = nullptr; + next_ = nullptr; static_offset_ = -1; parsing_state_seq_ = 0; boundary_checked_ = false; @@ -399,7 +399,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) if ( record_type()->incremental_parsing() && prev() ) prev()->GenParseCode(out_cc, env); - DataPtr data(env, 0, 0); + DataPtr data(env, nullptr, 0); if ( ! record_type()->incremental_parsing() ) { data = getFieldBegin(out_cc, env); @@ -499,7 +499,7 @@ bool RecordDataField::RequiresAnalyzerContext() const } RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr) - : RecordField(PADDING_FIELD, id, 0), ptype_(ptype), expr_(expr) + : RecordField(PADDING_FIELD, id, nullptr), ptype_(ptype), expr_(expr) { wordsize_ = -1; } diff --git a/tools/binpac/src/pac_record.h b/tools/binpac/src/pac_record.h index fa3cf80051..7df944e4db 100644 --- a/tools/binpac/src/pac_record.h +++ b/tools/binpac/src/pac_record.h @@ -40,7 +40,7 @@ protected: void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); void GenDynamicSize(Output* out, Env* env, const DataPtr& data); - Type* DoClone() const { return 0; } + Type* DoClone() const { return nullptr; } void DoMarkIncrementalInput(); diff --git a/tools/binpac/src/pac_strtype.cc b/tools/binpac/src/pac_strtype.cc index 39169c37bf..6fa64bf31b 100644 --- a/tools/binpac/src/pac_strtype.cc +++ b/tools/binpac/src/pac_strtype.cc @@ -15,18 +15,19 @@ const char* StringType::kStringTypeName = "bytestring"; const char* StringType::kConstStringTypeName = "const_bytestring"; -StringType::StringType(StringTypeEnum anystr) : Type(STRING), type_(ANYSTR), str_(0), regex_(0) +StringType::StringType(StringTypeEnum anystr) + : Type(STRING), type_(ANYSTR), str_(nullptr), regex_(nullptr) { ASSERT(anystr == ANYSTR); init(); } -StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(0) +StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(nullptr) { init(); } -StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(0), regex_(regex) +StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(nullptr), regex_(regex) { ASSERT(regex_); init(); @@ -34,7 +35,7 @@ StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(0), rege void StringType::init() { - string_length_var_field_ = 0; + string_length_var_field_ = nullptr; elem_datatype_ = new BuiltInType(BuiltInType::UINT8); } @@ -67,7 +68,7 @@ Type* StringType::DoClone() const break; default: ASSERT(0); - return 0; + return nullptr; } return clone; @@ -206,7 +207,7 @@ int StringType::StaticSize(Env* env) const const ID* StringType::string_length_var() const { - return string_length_var_field_ ? string_length_var_field_->id() : 0; + return string_length_var_field_ ? string_length_var_field_->id() : nullptr; } void StringType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index dcf81b84a7..478c6e5826 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -24,23 +24,23 @@ Type::type_map_t Type::type_map_; Type::Type(TypeType tot) : DataDepElement(DataDepElement::TYPE), tot_(tot) { - type_decl_ = 0; + type_decl_ = nullptr; type_decl_id_ = current_decl_id; declared_as_type_ = false; - env_ = 0; + env_ = nullptr; value_var_ = default_value_var; ASSERT(value_var_); value_var_type_ = MEMBER_VAR; anonymous_value_var_ = false; - size_var_field_ = 0; - size_expr_ = 0; + size_var_field_ = nullptr; + size_expr_ = nullptr; boundary_checked_ = false; - parsing_complete_var_field_ = 0; - parsing_state_var_field_ = 0; - buffering_state_var_field_ = 0; - has_value_field_ = 0; + parsing_complete_var_field_ = nullptr; + parsing_state_var_field_ = nullptr; + buffering_state_var_field_ = nullptr; + has_value_field_ = nullptr; - array_until_input_ = 0; + array_until_input_ = nullptr; incremental_input_ = false; buffer_input_ = false; @@ -49,16 +49,16 @@ Type::Type(TypeType tot) : DataDepElement(DataDepElement::TYPE), tot_(tot) fields_ = new FieldList(); attrs_ = new AttrList(); - attr_byteorder_expr_ = 0; + attr_byteorder_expr_ = nullptr; attr_checks_ = new ExprList(); attr_enforces_ = new ExprList(); attr_chunked_ = false; attr_exportsourcedata_ = false; - attr_if_expr_ = 0; - attr_length_expr_ = 0; - attr_letfields_ = 0; - attr_multiline_end_ = 0; - attr_linebreaker_ = 0; + attr_if_expr_ = nullptr; + attr_length_expr_ = nullptr; + attr_letfields_ = nullptr; + attr_multiline_end_ = nullptr; + attr_linebreaker_ = nullptr; attr_oneline_ = false; attr_refcount_ = false; attr_requires_ = new ExprList(); @@ -139,7 +139,7 @@ void Type::set_value_var(const ID* arg_id, int arg_id_type) const ID* Type::size_var() const { - return size_var_field_ ? size_var_field_->id() : 0; + return size_var_field_ ? size_var_field_->id() : nullptr; } void Type::AddField(Field* f) @@ -569,7 +569,7 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) data_begin = begin_of_data; } else - data_begin = 0; + data_begin = nullptr; if ( array_until_input_ ) { @@ -762,7 +762,7 @@ Type* Type::MemberDataType(const ID* member_id) const Type* Type::ElementDataType() const { - return 0; + return nullptr; } // Returns false if it is not necessary to add size_var @@ -968,7 +968,7 @@ bool Type::Bufferable() const bool Type::BufferableWithLineBreaker() const { // If the input is an ASCII line with a given linebreaker; - return attr_linebreaker_ != 0; + return attr_linebreaker_ != nullptr; } Expr* Type::LineBreaker() const @@ -992,7 +992,7 @@ const ID* Type::parsing_complete_var() const if ( parsing_complete_var_field_ ) return parsing_complete_var_field_->id(); else - return 0; + return nullptr; } string Type::parsing_complete(Env* env) const @@ -1006,7 +1006,7 @@ const ID* Type::has_value_var() const if ( has_value_field_ ) return has_value_field_->id(); else - return 0; + return nullptr; } int Type::InitialBufferLength() const @@ -1095,7 +1095,7 @@ Type* Type::LookUpByID(ID* id) } } - return new ParameterizedType(id, 0); + return new ParameterizedType(id, nullptr); } void Type::AddPredefinedType(const string& type_name, Type* type) diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc index cb6238e059..bf99118be7 100644 --- a/tools/binpac/src/pac_typedecl.cc +++ b/tools/binpac/src/pac_typedecl.cc @@ -19,7 +19,7 @@ TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type) : Decl(id, TYPE), params_(params), type_(type) { - env_ = 0; + env_ = nullptr; type_->set_type_decl(this, true); } @@ -222,8 +222,8 @@ void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) string TypeDecl::ParseFuncPrototype(Env* env) { - const char* func_name = 0; - const char* return_type = 0; + const char* func_name = nullptr; + const char* return_type = nullptr; string params; if ( type_->incremental_input() ) @@ -268,7 +268,7 @@ void TypeDecl::GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data) } else { - ret_val_0 = type_->DataSize(0, env, data).c_str(); + ret_val_0 = type_->DataSize(nullptr, env, data).c_str(); ret_val_1 = "@@@"; out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", env->RValue(begin_of_data), @@ -347,7 +347,7 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) out_cc->inc_indent(); out_cc->println("{"); - DataPtr data(env, 0, 0); + DataPtr data(env, nullptr, 0); if ( ! type_->incremental_input() ) data = DataPtr(env, begin_of_data, 0); @@ -378,7 +378,7 @@ Type* TypeDecl::LookUpType(const ID* id) { Decl* decl = LookUpDecl(id); if ( ! decl ) - return 0; + return nullptr; switch ( decl->decl_type() ) { case TYPE: @@ -388,6 +388,6 @@ Type* TypeDecl::LookUpType(const ID* id) case ENUM: return static_cast(decl)->DataType(); default: - return 0; + return nullptr; } } From 613ffef4a235d295fe9d8e5ddbc0cc876bb4af43 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 27 Jan 2023 08:50:09 -0700 Subject: [PATCH 120/343] binpac: Use nullptr in generated code --- tools/binpac/src/pac_array.cc | 6 +++--- tools/binpac/src/pac_exttype.cc | 5 ++++- tools/binpac/src/pac_flow.cc | 6 +++--- tools/binpac/src/pac_paramtype.cc | 6 +++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index d37a6c1a4d..82e4f8c6fb 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -356,7 +356,7 @@ void ArrayType::GenInitCode(Output* out_cc, Env* env) { // Do not initiate the array here // out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); - out_cc->println("%s = 0;", lvalue()); + out_cc->println("%s = nullptr;", lvalue()); Type::GenInitCode(out_cc, env); if ( incremental_parsing() ) @@ -563,7 +563,7 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in GenUntilCheck(out_cc, env, attr_until_element_expr_, false); if ( elemtype_->IsPointerType() ) - out_cc->println("%s = 0;", env->LValue(elem_var())); + out_cc->println("%s = nullptr;", env->LValue(elem_var())); out_cc->println("}"); out_cc->dec_indent(); @@ -621,7 +621,7 @@ void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool d if ( delete_elem ) elemtype_->GenCleanUpCode(out_cc, env); else - out_cc->println("%s = 0;", env->LValue(elem_var())); + out_cc->println("%s = nullptr;", env->LValue(elem_var())); } out_cc->println("goto %s;", end_of_array_loop_label_.c_str()); diff --git a/tools/binpac/src/pac_exttype.cc b/tools/binpac/src/pac_exttype.cc index c048acc7a6..32f896e994 100644 --- a/tools/binpac/src/pac_exttype.cc +++ b/tools/binpac/src/pac_exttype.cc @@ -42,8 +42,11 @@ string ExternType::EvalMember(const ID* member_id) const void ExternType::GenInitCode(Output* out_cc, Env* env) { - if ( IsNumericType() || IsPointerType() ) + if ( IsNumericType() ) out_cc->println("%s = 0;", env->LValue(value_var())); + else if ( IsPointerType() ) + out_cc->println("%s = nullptr;", env->LValue(value_var())); + Type::GenInitCode(out_cc, env); } diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index ddf6029b01..75a42c92fd 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -113,8 +113,8 @@ void FlowDecl::GenInitCode(Output* out_cc) { AnalyzerDecl::GenInitCode(out_cc); - out_cc->println("%s = 0;", env_->LValue(dataunit_id)); - out_cc->println("%s = 0;", env_->LValue(analyzer_context_id)); + out_cc->println("%s = nullptr;", env_->LValue(dataunit_id)); + out_cc->println("%s = nullptr;", env_->LValue(analyzer_context_id)); if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { @@ -147,7 +147,7 @@ void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc) if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { out_cc->println("%s->set_eof();", env_->LValue(flow_buffer_id)); - out_cc->println("%s(0, 0);", kNewData); + out_cc->println("%s(nullptr, nullptr);", kNewData); } out_cc->println("}"); diff --git a/tools/binpac/src/pac_paramtype.cc b/tools/binpac/src/pac_paramtype.cc index 7fe61fe128..b9d2175b65 100644 --- a/tools/binpac/src/pac_paramtype.cc +++ b/tools/binpac/src/pac_paramtype.cc @@ -154,7 +154,7 @@ bool ParameterizedType::RequiresAnalyzerContext() void ParameterizedType::GenInitCode(Output* out_cc, Env* env) { ASSERT(persistent()); - out_cc->println("%s = 0;", env->LValue(value_var())); + out_cc->println("%s = nullptr;", env->LValue(value_var())); Type::GenInitCode(out_cc, env); } @@ -165,7 +165,7 @@ void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env) out_cc->println("Unref(%s);", lvalue()); else out_cc->println("delete %s;", lvalue()); - out_cc->println("%s = 0;", lvalue()); + out_cc->println("%s = nullptr;", lvalue()); Type::GenCleanUpCode(out_cc, env); } @@ -206,7 +206,7 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& { ASSERT(! ref_type->incremental_input()); parse_func = kParseFuncWithoutBuffer; - parse_params = "0, 0"; + parse_params = "nullptr, nullptr"; } else if ( ref_type->incremental_input() ) { From 45ef19049c6c16420ef4926481b375599f61b2a7 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 27 Jan 2023 10:21:29 -0700 Subject: [PATCH 121/343] binpac: Add final keyword to class definitions --- tools/binpac/src/pac_typedecl.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc index bf99118be7..9d7b363ef1 100644 --- a/tools/binpac/src/pac_typedecl.cc +++ b/tools/binpac/src/pac_typedecl.cc @@ -121,7 +121,7 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc) // The first line of class definition out_h->println(""); - out_h->print("class %s", class_name().c_str()); + out_h->print("class %s final", class_name().c_str()); bool first = true; vector::iterator i; for ( i = (&base_classes)->begin(); i != (&base_classes)->end(); ++i ) @@ -334,8 +334,8 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) out_h->println("// 2. If the input is not complete but the type supports"); out_h->println("// incremental input, returns number of input bytes + 1"); out_h->println("// (%s - %s + 1).", - env->LValue(end_of_data), - env->LValue(begin_of_data)); + env->LValue(end_of_data), + env->LValue(begin_of_data)); out_h->println("// 3. An exception will be thrown on error."); } #endif From 299f39e8e2a4b41071da982726fc86387e941464 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 30 Jan 2023 17:05:32 -0700 Subject: [PATCH 122/343] binpac: Mark overridden methods with 'override' --- tools/binpac/src/pac_action.h | 2 +- tools/binpac/src/pac_analyzer.h | 22 ++++----- tools/binpac/src/pac_array.h | 44 ++++++++--------- tools/binpac/src/pac_attr.h | 4 +- tools/binpac/src/pac_btype.h | 24 +++++----- tools/binpac/src/pac_case.h | 48 +++++++++---------- tools/binpac/src/pac_conn.h | 20 ++++---- tools/binpac/src/pac_context.h | 27 ++++++----- tools/binpac/src/pac_datadep.h | 4 +- tools/binpac/src/pac_dataunit.h | 2 +- tools/binpac/src/pac_decl.h | 10 ++-- tools/binpac/src/pac_enum.h | 8 ++-- tools/binpac/src/pac_expr.h | 8 ++-- tools/binpac/src/pac_exttype.h | 22 ++++----- tools/binpac/src/pac_field.h | 4 +- tools/binpac/src/pac_flow.h | 24 +++++----- tools/binpac/src/pac_func.h | 8 ++-- tools/binpac/src/pac_inputbuf.h | 2 +- tools/binpac/src/pac_let.h | 22 ++++----- tools/binpac/src/pac_param.h | 4 +- tools/binpac/src/pac_paramtype.h | 38 +++++++-------- tools/binpac/src/pac_primitive.h | 8 ++-- tools/binpac/src/pac_record.h | 82 ++++++++++++++++---------------- tools/binpac/src/pac_regex.h | 6 +-- tools/binpac/src/pac_strtype.h | 38 +++++++-------- tools/binpac/src/pac_type.h | 4 +- tools/binpac/src/pac_typedecl.h | 12 ++--- tools/binpac/src/pac_varfield.h | 10 ++-- tools/binpac/src/pac_withinput.h | 10 ++-- 29 files changed, 260 insertions(+), 257 deletions(-) diff --git a/tools/binpac/src/pac_action.h b/tools/binpac/src/pac_action.h index 4718d95a31..9f2ffcd970 100644 --- a/tools/binpac/src/pac_action.h +++ b/tools/binpac/src/pac_action.h @@ -17,7 +17,7 @@ public: AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code); - ~AnalyzerAction(); + ~AnalyzerAction() override; When when() const { return when_; } ActionParam* param() const { return param_; } diff --git a/tools/binpac/src/pac_analyzer.h b/tools/binpac/src/pac_analyzer.h index 49f41611df..8fa59db40a 100644 --- a/tools/binpac/src/pac_analyzer.h +++ b/tools/binpac/src/pac_analyzer.h @@ -21,16 +21,16 @@ class AnalyzerDecl : public TypeDecl { public: AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params); - ~AnalyzerDecl(); + ~AnalyzerDecl() override; void AddElements(AnalyzerElementList* elemlist); - void Prepare(); - void GenForwardDeclaration(Output* out_h); + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; // void GenCode(Output *out_h, Output *out_cc); - void GenInitCode(Output* out_cc); - void GenCleanUpCode(Output* out_cc); + void GenInitCode(Output* out_cc) override; + void GenCleanUpCode(Output* out_cc) override; string class_name() const; // string cookie_name() const; @@ -41,8 +41,8 @@ protected: // Generate public/private declarations for member functions and // variables - void GenPubDecls(Output* out_h, Output* out_cc); - void GenPrivDecls(Output* out_h, Output* out_cc); + void GenPubDecls(Output* out_h, Output* out_cc) override; + void GenPrivDecls(Output* out_h, Output* out_cc) override; // Generate the NewData() function virtual void GenProcessFunc(Output* out_h, Output* out_cc) = 0; @@ -107,7 +107,7 @@ class AnalyzerState : public AnalyzerElement { public: AnalyzerState(StateVarList* statevars) : AnalyzerElement(STATE), statevars_(statevars) { } - ~AnalyzerState(); + ~AnalyzerState() override; StateVarList* statevars() const { return statevars_; } @@ -130,7 +130,7 @@ public: : AnalyzerElement(HELPER), helper_type_(helper_type), code_(code) { } - ~AnalyzerHelper(); + ~AnalyzerHelper() override; Type helper_type() const { return helper_type_; } @@ -149,7 +149,7 @@ class FlowField : public Field { public: FlowField(ID* flow_id, ParameterizedType* flow_type); - void GenInitCode(Output* out, Env* env); + void GenInitCode(Output* out, Env* env) override; }; class AnalyzerFlow : public AnalyzerElement @@ -161,7 +161,7 @@ public: DOWN }; AnalyzerFlow(Direction dir, ID* type_id, ExprList* params); - ~AnalyzerFlow(); + ~AnalyzerFlow() override; Direction dir() const { return dir_; } FlowField* flow_field() const { return flow_field_; } diff --git a/tools/binpac/src/pac_array.h b/tools/binpac/src/pac_array.h index 01f770d1d5..01c8deeee5 100644 --- a/tools/binpac/src/pac_array.h +++ b/tools/binpac/src/pac_array.h @@ -10,48 +10,48 @@ class ArrayType : public Type { public: ArrayType(Type* arg_elemtype, Expr* arg_length = nullptr); - ~ArrayType(); + ~ArrayType() override; - bool DefineValueVar() const; - string DataTypeStr() const; - string DefaultValue() const { return "0"; } - Type* ElementDataType() const; + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override { return "0"; } + Type* ElementDataType() const override; - string EvalElement(const string& array, const string& index) const; + string EvalElement(const string& array, const string& index) const override; - void ProcessAttr(Attr* a); + void ProcessAttr(Attr* a) override; - void Prepare(Env* env, int flags); + void Prepare(Env* env, int flags) override; - void GenPubDecls(Output* out, Env* env); - void GenPrivDecls(Output* out, Env* env); + void GenPubDecls(Output* out, Env* env) override; + void GenPrivDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env); - void GenCleanUpCode(Output* out, Env* env); + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; - int StaticSize(Env* env) const; + int StaticSize(Env* env) const override; - void SetBoundaryChecked(); + void SetBoundaryChecked() override; void GenUntilInputCheck(Output* out_cc, Env* env); - bool IsPointerType() const { return true; } + bool IsPointerType() const override { return true; } protected: void init(); - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); - void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; void GenArrayLength(Output* out_cc, Env* env, const DataPtr& data); string GenArrayInit(Output* out_cc, Env* env, bool known_array_length); void GenElementAssignment(Output* out_cc, Env* env, string const& array_str, bool use_vector); void GenUntilCheck(Output* out_cc, Env* env, Expr* until_condition, bool delete_elem); - bool ByteOrderSensitive() const { return elemtype_->RequiresByteOrder(); } - bool RequiresAnalyzerContext(); + bool ByteOrderSensitive() const override { return elemtype_->RequiresByteOrder(); } + bool RequiresAnalyzerContext() override; - Type* DoClone() const; + Type* DoClone() const override; - void DoMarkIncrementalInput(); + void DoMarkIncrementalInput() override; const ID* arraylength_var() const; const ID* elem_it_var() const; @@ -60,7 +60,7 @@ protected: const ID* elem_input_var() const; protected: - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; private: Type* elemtype_; diff --git a/tools/binpac/src/pac_attr.h b/tools/binpac/src/pac_attr.h index ef5dc65ff5..e0fab09051 100644 --- a/tools/binpac/src/pac_attr.h +++ b/tools/binpac/src/pac_attr.h @@ -33,7 +33,7 @@ public: Attr(AttrType type, ExprList* exprlist); Attr(AttrType type, SeqEnd* seqend); - virtual ~Attr(); + ~Attr() override; AttrType type() const { return type_; } Expr* expr() const { return expr_; } @@ -42,7 +42,7 @@ public: bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; protected: void init(); diff --git a/tools/binpac/src/pac_btype.h b/tools/binpac/src/pac_btype.h index f168b832e2..73ca8f8932 100644 --- a/tools/binpac/src/pac_btype.h +++ b/tools/binpac/src/pac_btype.h @@ -22,26 +22,26 @@ public: BITType bit_type() const { return bit_type_; } - bool IsNumericType() const; + bool IsNumericType() const override; - bool DefineValueVar() const; - string DataTypeStr() const; - string DefaultValue() const { return "0"; } + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override { return "0"; } - int StaticSize(Env* env) const; + int StaticSize(Env* env) const override; - bool IsPointerType() const { return false; } + bool IsPointerType() const override { return false; } - bool ByteOrderSensitive() const { return StaticSize(0) >= 2; } + bool ByteOrderSensitive() const override { return StaticSize(0) >= 2; } - void GenInitCode(Output* out_cc, Env* env); + void GenInitCode(Output* out_cc, Env* env) override; - void DoMarkIncrementalInput(); + void DoMarkIncrementalInput() override; protected: - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); - void GenDynamicSize(Output* out, Env* env, const DataPtr& data); - Type* DoClone() const; + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; + Type* DoClone() const override; BITType bit_type_; diff --git a/tools/binpac/src/pac_case.h b/tools/binpac/src/pac_case.h index 7d440fffa0..501676bda0 100644 --- a/tools/binpac/src/pac_case.h +++ b/tools/binpac/src/pac_case.h @@ -10,39 +10,39 @@ class CaseType : public Type { public: CaseType(Expr* index, CaseFieldList* cases); - ~CaseType(); + ~CaseType() override; void AddCaseField(CaseField* f); - bool DefineValueVar() const; - string DataTypeStr() const; - string DefaultValue() const; + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override; - void Prepare(Env* env, int flags); + void Prepare(Env* env, int flags) override; - void GenPubDecls(Output* out, Env* env); - void GenPrivDecls(Output* out, Env* env); + void GenPubDecls(Output* out, Env* env) override; + void GenPrivDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env); - void GenCleanUpCode(Output* out, Env* env); + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; - int StaticSize(Env* env) const; + int StaticSize(Env* env) const override; - void SetBoundaryChecked(); + void SetBoundaryChecked() override; Type* ValueType() const; Expr* IndexExpr() const { return index_expr_; } - bool IsPointerType() const { return ValueType()->IsPointerType(); } + bool IsPointerType() const override { return ValueType()->IsPointerType(); } protected: - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); - void GenDynamicSize(Output* out, Env* env, const DataPtr& data); - Type* DoClone() const { return nullptr; } - void DoMarkIncrementalInput(); + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; + Type* DoClone() const override { return nullptr; } + void DoMarkIncrementalInput() override; - bool ByteOrderSensitive() const; + bool ByteOrderSensitive() const override; Expr* index_expr_; ID* index_var_; @@ -56,7 +56,7 @@ class CaseField : public Field { public: CaseField(ExprList* index, ID* id, Type* type); - ~CaseField(); + ~CaseField() override; CaseType* case_type() const { return case_type_; } void set_case_type(CaseType* t) { case_type_ = t; } @@ -68,12 +68,12 @@ public: const char* CaseStr(Env* env); void set_index_var(const ID* var) { index_var_ = var; } - void Prepare(Env* env); + void Prepare(Env* env) override; - void GenPubDecls(Output* out, Env* env); + void GenPubDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env); - void GenCleanUpCode(Output* out, Env* env); + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; void GenParseCode(Output* out, Env* env, const DataPtr& data, const ID* size_var); int StaticSize(Env* env) const { return type_->StaticSize(env); } @@ -82,10 +82,10 @@ public: void SetBoundaryChecked() { type_->SetBoundaryChecked(); } bool RequiresByteOrder() const { return type_->RequiresByteOrder(); } - bool RequiresAnalyzerContext() const; + bool RequiresAnalyzerContext() const override; protected: - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; protected: CaseType* case_type_; diff --git a/tools/binpac/src/pac_conn.h b/tools/binpac/src/pac_conn.h index 5c62b6b64d..edb10e7184 100644 --- a/tools/binpac/src/pac_conn.h +++ b/tools/binpac/src/pac_conn.h @@ -8,24 +8,24 @@ class ConnDecl : public AnalyzerDecl { public: ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist); - ~ConnDecl(); + ~ConnDecl() override; - void Prepare(); + void Prepare() override; Type* DataType() const { return data_type_; } protected: - void AddBaseClass(vector* base_classes) const; + void AddBaseClass(vector* base_classes) const override; - void GenProcessFunc(Output* out_h, Output* out_cc); - void GenGapFunc(Output* out_h, Output* out_cc); - void GenEOFFunc(Output* out_h, Output* out_cc); + void GenProcessFunc(Output* out_h, Output* out_cc) override; + void GenGapFunc(Output* out_h, Output* out_cc) override; + void GenEOFFunc(Output* out_h, Output* out_cc) override; - void GenPubDecls(Output* out_h, Output* out_cc); - void GenPrivDecls(Output* out_h, Output* out_cc); + void GenPubDecls(Output* out_h, Output* out_cc) override; + void GenPrivDecls(Output* out_h, Output* out_cc) override; - void ProcessFlowElement(AnalyzerFlow* flow_elem); - void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem); + void ProcessFlowElement(AnalyzerFlow* flow_elem) override; + void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) override; AnalyzerFlow* flows_[2]; Type* data_type_; diff --git a/tools/binpac/src/pac_context.h b/tools/binpac/src/pac_context.h index 42ea969544..86b9354310 100644 --- a/tools/binpac/src/pac_context.h +++ b/tools/binpac/src/pac_context.h @@ -33,7 +33,7 @@ class AnalyzerContextDecl : public TypeDecl { public: AnalyzerContextDecl(ID* id, ContextFieldList* context_fields); - ~AnalyzerContextDecl(); + ~AnalyzerContextDecl() override; void AddFlowBuffer(); @@ -42,8 +42,8 @@ public: // The type of analyzer context as a parameter ParameterizedType* param_type() const { return param_type_; } - void GenForwardDeclaration(Output* out_h); - void GenCode(Output* out_h, Output* out_cc); + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; void GenNamespaceBegin(Output* out) const; void GenNamespaceEnd(Output* out) const; @@ -69,35 +69,38 @@ class DummyType : public Type public: DummyType() : Type(DUMMY) { } - bool DefineValueVar() const { return false; } - string DataTypeStr() const + bool DefineValueVar() const override { return false; } + string DataTypeStr() const override { ASSERT(0); return ""; } - int StaticSize(Env* env) const + int StaticSize(Env* env) const override { ASSERT(0); return -1; } - bool ByteOrderSensitive() const { return false; } + bool ByteOrderSensitive() const override { return false; } - bool IsPointerType() const + bool IsPointerType() const override { ASSERT(0); return false; } - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) { ASSERT(0); } + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override + { + ASSERT(0); + } // Generate code for computing the dynamic size of the type - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) { ASSERT(0); } + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override { ASSERT(0); } protected: - Type* DoClone() const; - void DoMarkIncrementalInput() { ASSERT(0); } + Type* DoClone() const override; + void DoMarkIncrementalInput() override { ASSERT(0); } }; #endif // pac_context_h diff --git a/tools/binpac/src/pac_datadep.h b/tools/binpac/src/pac_datadep.h index 7cb8216ada..0b7a429f3d 100644 --- a/tools/binpac/src/pac_datadep.h +++ b/tools/binpac/src/pac_datadep.h @@ -56,8 +56,8 @@ public: RequiresAnalyzerContext() : requires_analyzer_context_(false) { } // Returns whether to continue traversal - bool PreProcess(DataDepElement* element); - bool PostProcess(DataDepElement* element); + bool PreProcess(DataDepElement* element) override; + bool PostProcess(DataDepElement* element) override; bool requires_analyzer_context() const { return requires_analyzer_context_; } diff --git a/tools/binpac/src/pac_dataunit.h b/tools/binpac/src/pac_dataunit.h index c057a0d574..d9f16d1640 100644 --- a/tools/binpac/src/pac_dataunit.h +++ b/tools/binpac/src/pac_dataunit.h @@ -15,7 +15,7 @@ public: FLOWUNIT }; AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params); - ~AnalyzerDataUnit(); + ~AnalyzerDataUnit() override; void Prepare(Env* env); diff --git a/tools/binpac/src/pac_decl.h b/tools/binpac/src/pac_decl.h index 5e806389c8..39b84dc614 100644 --- a/tools/binpac/src/pac_decl.h +++ b/tools/binpac/src/pac_decl.h @@ -76,14 +76,14 @@ public: EXTERN, }; HelperDecl(HelperType type, ID* context_id, EmbeddedCode* code); - ~HelperDecl(); + ~HelperDecl() override; - void Prepare(); - void GenExternDeclaration(Output* out_h); - void GenForwardDeclaration(Output* out_h) + void Prepare() override; + void GenExternDeclaration(Output* out_h) override; + void GenForwardDeclaration(Output* out_h) override { /* do nothing */ } - void GenCode(Output* out_h, Output* out_cc); + void GenCode(Output* out_h, Output* out_cc) override; private: HelperType helper_type_; diff --git a/tools/binpac/src/pac_enum.h b/tools/binpac/src/pac_enum.h index 73534e12d8..1f3b8d9cca 100644 --- a/tools/binpac/src/pac_enum.h +++ b/tools/binpac/src/pac_enum.h @@ -20,13 +20,13 @@ class EnumDecl : public Decl { public: EnumDecl(ID* id, EnumList* enumlist); - ~EnumDecl(); + ~EnumDecl() override; Type* DataType() const { return datatype_; } - void Prepare(); - void GenForwardDeclaration(Output* out_h); - void GenCode(Output* out_h, Output* out_cc); + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; private: EnumList* enumlist_; diff --git a/tools/binpac/src/pac_expr.h b/tools/binpac/src/pac_expr.h index e4c8b71dc0..8a4cad8295 100644 --- a/tools/binpac/src/pac_expr.h +++ b/tools/binpac/src/pac_expr.h @@ -29,7 +29,7 @@ public: Expr(ExprType type, Expr* op1, Expr* op2); Expr(ExprType type, Expr* op1, Expr* op2, Expr* op3); - virtual ~Expr(); + ~Expr() override; const char* orig() const { return orig_.c_str(); } const ID* id() const { return id_; } @@ -89,7 +89,7 @@ public: bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; private: ExprType expr_type_; @@ -121,7 +121,7 @@ class CaseExpr : public Object, public DataDepElement { public: CaseExpr(ExprList* index, Expr* value); - virtual ~CaseExpr(); + ~CaseExpr() override; ExprList* index() const { return index_; } Expr* value() const { return value_; } @@ -130,7 +130,7 @@ public: bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; private: ExprList* index_; diff --git a/tools/binpac/src/pac_exttype.h b/tools/binpac/src/pac_exttype.h index 8fe321a82c..8d9b008f60 100644 --- a/tools/binpac/src/pac_exttype.h +++ b/tools/binpac/src/pac_exttype.h @@ -19,22 +19,22 @@ public: }; ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) { } - bool DefineValueVar() const; - string DataTypeStr() const; - int StaticSize(Env* env) const; - bool ByteOrderSensitive() const; + bool DefineValueVar() const override; + string DataTypeStr() const override; + int StaticSize(Env* env) const override; + bool ByteOrderSensitive() const override; - string EvalMember(const ID* member_id) const; - bool IsNumericType() const { return ext_type_ == NUMBER; } - bool IsPointerType() const { return ext_type_ == POINTER; } + string EvalMember(const ID* member_id) const override; + bool IsNumericType() const override { return ext_type_ == NUMBER; } + bool IsPointerType() const override { return ext_type_ == POINTER; } - void GenInitCode(Output* out_cc, Env* env); + void GenInitCode(Output* out_cc, Env* env) override; protected: - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); - void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; - Type* DoClone() const; + Type* DoClone() const override; private: const ID* id_; diff --git a/tools/binpac/src/pac_field.h b/tools/binpac/src/pac_field.h index bf95235aa6..2327db6cad 100644 --- a/tools/binpac/src/pac_field.h +++ b/tools/binpac/src/pac_field.h @@ -42,7 +42,7 @@ public: static const int PUBLIC_READABLE = 4; static const int NOT_PUBLIC_READABLE = 0; - virtual ~Field(); + ~Field() override; FieldType tof() const { return tof_; } const ID* id() const { return id_; } @@ -70,7 +70,7 @@ protected: int ValueVarType() const; bool ToBeParsed() const; - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; protected: FieldType tof_; diff --git a/tools/binpac/src/pac_flow.h b/tools/binpac/src/pac_flow.h index 20397aefe8..ea018c6834 100644 --- a/tools/binpac/src/pac_flow.h +++ b/tools/binpac/src/pac_flow.h @@ -7,28 +7,28 @@ class FlowDecl : public AnalyzerDecl { public: FlowDecl(ID* flow_id, ParamList* params, AnalyzerElementList* elemlist); - ~FlowDecl(); + ~FlowDecl() override; - void Prepare(); + void Prepare() override; void set_conn_decl(ConnDecl* c) { conn_decl_ = c; } static ParameterizedType* flow_buffer_type(); protected: - void AddBaseClass(vector* base_classes) const; + void AddBaseClass(vector* base_classes) const override; - void GenInitCode(Output* out_cc); - void GenCleanUpCode(Output* out_cc); - void GenProcessFunc(Output* out_h, Output* out_cc); - void GenEOFFunc(Output* out_h, Output* out_cc); - void GenGapFunc(Output* out_h, Output* out_cc); + void GenInitCode(Output* out_cc) override; + void GenCleanUpCode(Output* out_cc) override; + void GenProcessFunc(Output* out_h, Output* out_cc) override; + void GenEOFFunc(Output* out_h, Output* out_cc) override; + void GenGapFunc(Output* out_h, Output* out_cc) override; - void GenPubDecls(Output* out_h, Output* out_cc); - void GenPrivDecls(Output* out_h, Output* out_cc); + void GenPubDecls(Output* out_h, Output* out_cc) override; + void GenPrivDecls(Output* out_h, Output* out_cc) override; - void ProcessFlowElement(AnalyzerFlow* flow_elem); - void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem); + void ProcessFlowElement(AnalyzerFlow* flow_elem) override; + void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) override; private: void GenNewDataUnit(Output* out_cc); diff --git a/tools/binpac/src/pac_func.h b/tools/binpac/src/pac_func.h index 249629f6de..5d7352f510 100644 --- a/tools/binpac/src/pac_func.h +++ b/tools/binpac/src/pac_func.h @@ -42,13 +42,13 @@ class FuncDecl : public Decl { public: FuncDecl(Function* function); - ~FuncDecl(); + ~FuncDecl() override; Function* function() const { return function_; } - void Prepare(); - void GenForwardDeclaration(Output* out_h); - void GenCode(Output* out_h, Output* out_cc); + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; private: Function* function_; diff --git a/tools/binpac/src/pac_inputbuf.h b/tools/binpac/src/pac_inputbuf.h index 036ed7ffec..46ca864ece 100644 --- a/tools/binpac/src/pac_inputbuf.h +++ b/tools/binpac/src/pac_inputbuf.h @@ -15,7 +15,7 @@ public: DataPtr GenDataBeginEnd(Output* out_cc, Env* env); protected: - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; private: Expr* expr_; diff --git a/tools/binpac/src/pac_let.h b/tools/binpac/src/pac_let.h index 253f0fea50..1bf774dd1e 100644 --- a/tools/binpac/src/pac_let.h +++ b/tools/binpac/src/pac_let.h @@ -8,20 +8,20 @@ class LetField : public Field, Evaluatable { public: LetField(ID* arg_id, Type* type, Expr* arg_expr); - ~LetField(); + ~LetField() override; Expr* expr() const { return expr_; } - void Prepare(Env* env); + void Prepare(Env* env) override; - void GenInitCode(Output* out, Env* env); + void GenInitCode(Output* out, Env* env) override; void GenParseCode(Output* out, Env* env); - void GenEval(Output* out, Env* env); + void GenEval(Output* out, Env* env) override; - bool RequiresAnalyzerContext() const; + bool RequiresAnalyzerContext() const override; protected: - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; protected: Expr* expr_; @@ -31,14 +31,14 @@ class LetDecl : public Decl, Evaluatable { public: LetDecl(ID* id, Type* type, Expr* expr); - ~LetDecl(); + ~LetDecl() override; Expr* expr() const { return expr_; } - void Prepare(); - void GenForwardDeclaration(Output* out_h); - void GenCode(Output* out_h, Output* out_cc); - void GenEval(Output* out, Env* env); + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; + void GenEval(Output* out, Env* env) override; private: Type* type_; diff --git a/tools/binpac/src/pac_param.h b/tools/binpac/src/pac_param.h index 95a6eb456d..90afeaba80 100644 --- a/tools/binpac/src/pac_param.h +++ b/tools/binpac/src/pac_param.h @@ -27,8 +27,8 @@ class ParamField : public Field public: ParamField(const Param* param); - void GenInitCode(Output* out, Env* env); - void GenCleanUpCode(Output* out, Env* env); + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; }; // Returns the string with a list of param declarations separated by ','. diff --git a/tools/binpac/src/pac_paramtype.h b/tools/binpac/src/pac_paramtype.h index d5cc6b58a7..0eda097563 100644 --- a/tools/binpac/src/pac_paramtype.h +++ b/tools/binpac/src/pac_paramtype.h @@ -8,54 +8,54 @@ class ParameterizedType : public Type { public: ParameterizedType(ID* type_id, ExprList* args); - ~ParameterizedType(); + ~ParameterizedType() override; Type* clone() const; - string EvalMember(const ID* member_id) const; + string EvalMember(const ID* member_id) const override; // Env *member_env() const; void AddParamArg(Expr* arg); - bool DefineValueVar() const; - string DataTypeStr() const; - string DefaultValue() const { return "0"; } - Type* MemberDataType(const ID* member_id) const; + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override { return "0"; } + Type* MemberDataType(const ID* member_id) const override; // "throw_exception" specifies whether to throw an exception // if the referred data type is not found Type* ReferredDataType(bool throw_exception) const; - void GenCleanUpCode(Output* out, Env* env); + void GenCleanUpCode(Output* out, Env* env) override; - int StaticSize(Env* env) const; + int StaticSize(Env* env) const override; - bool IsPointerType() const { return true; } + bool IsPointerType() const override { return true; } - bool ByteOrderSensitive() const; - bool RequiresAnalyzerContext(); + bool ByteOrderSensitive() const override; + bool RequiresAnalyzerContext() override; - void GenInitCode(Output* out_cc, Env* env); + void GenInitCode(Output* out_cc, Env* env) override; string class_name() const; string EvalParameters(Output* out_cc, Env* env) const; - BufferMode buffer_mode() const; + BufferMode buffer_mode() const override; protected: - void GenNewInstance(Output* out, Env* env); + void GenNewInstance(Output* out, Env* env) override; - bool DoTraverse(DataDepVisitor* visitor); - Type* DoClone() const; - void DoMarkIncrementalInput(); + bool DoTraverse(DataDepVisitor* visitor) override; + Type* DoClone() const override; + void DoMarkIncrementalInput() override; private: ID* type_id_; ExprList* args_; bool checking_requires_analyzer_context_; - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); - void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; }; #endif // pac_paramtype_h diff --git a/tools/binpac/src/pac_primitive.h b/tools/binpac/src/pac_primitive.h index c51984d708..736049387a 100644 --- a/tools/binpac/src/pac_primitive.h +++ b/tools/binpac/src/pac_primitive.h @@ -31,7 +31,7 @@ public: PPVal(Expr* expr) : PacPrimitive(VAL), expr_(expr) { } Expr* expr() const { return expr_; } - string ToCode(Env* env); + string ToCode(Env* env) override; private: Expr* expr_; @@ -43,7 +43,7 @@ public: PPSet(Expr* expr) : PacPrimitive(SET), expr_(expr) { } Expr* expr() const { return expr_; } - string ToCode(Env* env); + string ToCode(Env* env) override; private: Expr* expr_; @@ -55,7 +55,7 @@ public: PPType(Expr* expr) : PacPrimitive(TYPE), expr_(expr) { } Expr* expr() const { return expr_; } - string ToCode(Env* env); + string ToCode(Env* env) override; private: Expr* expr_; @@ -68,7 +68,7 @@ public: const ID* id() const { return id_; } Expr* expr() const { return expr_; } - string ToCode(Env* env); + string ToCode(Env* env) override; private: const ID* id_; diff --git a/tools/binpac/src/pac_record.h b/tools/binpac/src/pac_record.h index 7df944e4db..235607241d 100644 --- a/tools/binpac/src/pac_record.h +++ b/tools/binpac/src/pac_record.h @@ -11,41 +11,41 @@ class RecordType : public Type { public: RecordType(RecordFieldList* fields); - ~RecordType(); + ~RecordType() override; - bool DefineValueVar() const; - string DataTypeStr() const; + bool DefineValueVar() const override; + string DataTypeStr() const override; - void Prepare(Env* env, int flags); + void Prepare(Env* env, int flags) override; - void GenPubDecls(Output* out, Env* env); - void GenPrivDecls(Output* out, Env* env); + void GenPubDecls(Output* out, Env* env) override; + void GenPrivDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env); - void GenCleanUpCode(Output* out, Env* env); + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; - int StaticSize(Env* env) const; + int StaticSize(Env* env) const override; - void SetBoundaryChecked(); + void SetBoundaryChecked() override; const ID* parsing_dataptr_var() const; - bool IsPointerType() const + bool IsPointerType() const override { ASSERT(0); return false; } protected: - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); - void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; - Type* DoClone() const { return nullptr; } + Type* DoClone() const override { return nullptr; } - void DoMarkIncrementalInput(); + void DoMarkIncrementalInput() override; - bool DoTraverse(DataDepVisitor* visitor); - bool ByteOrderSensitive() const; + bool DoTraverse(DataDepVisitor* visitor) override; + bool ByteOrderSensitive() const override; private: Field* parsing_dataptr_var_field_; @@ -60,7 +60,7 @@ class RecordField : public Field { public: RecordField(FieldType tof, ID* id, Type* type); - ~RecordField(); + ~RecordField() override; RecordType* record_type() const { return record_type_; } void set_record_type(RecordType* ty) { record_type_ = ty; } @@ -115,26 +115,26 @@ class RecordDataField : public RecordField, public Evaluatable { public: RecordDataField(ID* arg_id, Type* arg_type); - ~RecordDataField(); + ~RecordDataField() override; // Instantiates abstract class Field - void Prepare(Env* env); - void GenParseCode(Output* out, Env* env); + void Prepare(Env* env) override; + void GenParseCode(Output* out, Env* env) override; // Instantiates abstract class Evaluatable - void GenEval(Output* out, Env* env); + void GenEval(Output* out, Env* env) override; - int StaticSize(Env* env, int) const { return type()->StaticSize(env); } + int StaticSize(Env* env, int) const override { return type()->StaticSize(env); } - void SetBoundaryChecked(); + void SetBoundaryChecked() override; - bool RequiresByteOrder() const { return type()->RequiresByteOrder(); } - bool RequiresAnalyzerContext() const; + bool RequiresByteOrder() const override { return type()->RequiresByteOrder(); } + bool RequiresAnalyzerContext() const override; protected: - void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); - bool GenBoundaryCheck(Output* out_cc, Env* env); - bool DoTraverse(DataDepVisitor* visitor); + void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) override; + bool GenBoundaryCheck(Output* out_cc, Env* env) override; + bool DoTraverse(DataDepVisitor* visitor) override; }; enum PaddingType @@ -148,33 +148,33 @@ class RecordPaddingField : public RecordField { public: RecordPaddingField(ID* id, PaddingType ptype, Expr* expr); - ~RecordPaddingField(); + ~RecordPaddingField() override; - void Prepare(Env* env); + void Prepare(Env* env) override; - void GenPubDecls(Output* out, Env* env) + void GenPubDecls(Output* out, Env* env) override { /* nothing */ } - void GenPrivDecls(Output* out, Env* env) + void GenPrivDecls(Output* out, Env* env) override { /* nothing */ } - void GenInitCode(Output* out, Env* env) + void GenInitCode(Output* out, Env* env) override { /* nothing */ } - void GenCleanUpCode(Output* out, Env* env) + void GenCleanUpCode(Output* out, Env* env) override { /* nothing */ } - void GenParseCode(Output* out, Env* env); + void GenParseCode(Output* out, Env* env) override; - int StaticSize(Env* env, int offset) const; + int StaticSize(Env* env, int offset) const override; - bool RequiresByteOrder() const { return false; } + bool RequiresByteOrder() const override { return false; } protected: - void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); - bool GenBoundaryCheck(Output* out_cc, Env* env); - bool DoTraverse(DataDepVisitor* visitor); + void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) override; + bool GenBoundaryCheck(Output* out_cc, Env* env) override; + bool DoTraverse(DataDepVisitor* visitor) override; private: PaddingType ptype_; diff --git a/tools/binpac/src/pac_regex.h b/tools/binpac/src/pac_regex.h index 9fda47b408..2cf48cf2c2 100644 --- a/tools/binpac/src/pac_regex.h +++ b/tools/binpac/src/pac_regex.h @@ -30,9 +30,9 @@ class RegExDecl : public Decl public: RegExDecl(RegEx* regex); - void Prepare(); - void GenForwardDeclaration(Output* out_h); - void GenCode(Output* out_h, Output* out_cc); + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; private: RegEx* regex_; diff --git a/tools/binpac/src/pac_strtype.h b/tools/binpac/src/pac_strtype.h index a7fe8de02d..f4acdc087e 100644 --- a/tools/binpac/src/pac_strtype.h +++ b/tools/binpac/src/pac_strtype.h @@ -17,28 +17,28 @@ public: explicit StringType(StringTypeEnum anystr); explicit StringType(ConstString* str); explicit StringType(RegEx* regex); - ~StringType(); + ~StringType() override; - bool DefineValueVar() const; - string DataTypeStr() const; - string DefaultValue() const { return "0"; } - Type* ElementDataType() const; + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override { return "0"; } + Type* ElementDataType() const override; - void Prepare(Env* env, int flags); + void Prepare(Env* env, int flags) override; - void GenPubDecls(Output* out, Env* env); - void GenPrivDecls(Output* out, Env* env); + void GenPubDecls(Output* out, Env* env) override; + void GenPrivDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env); - void GenCleanUpCode(Output* out, Env* env); + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; - void DoMarkIncrementalInput(); + void DoMarkIncrementalInput() override; - int StaticSize(Env* env) const; + int StaticSize(Env* env) const override; - bool IsPointerType() const { return false; } + bool IsPointerType() const override { return false; } - void ProcessAttr(Attr* a); + void ProcessAttr(Attr* a) override; protected: void init(); @@ -50,21 +50,21 @@ protected: // Generate a string mismatch exception void GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern); - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; void GenCheckingCStr(Output* out, Env* env, const DataPtr& data, const string& str_size); - void GenDynamicSize(Output* out, Env* env, const DataPtr& data); + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; void GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data); void GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data); - Type* DoClone() const; + Type* DoClone() const override; // TODO: insensitive towards byte order till we support unicode - bool ByteOrderSensitive() const { return false; } + bool ByteOrderSensitive() const override { return false; } protected: - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; private: const ID* string_length_var() const; diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index d9ca103562..34322d550a 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -26,7 +26,7 @@ public: }; explicit Type(TypeType tot); - virtual ~Type(); + ~Type() override; Type* Clone() const; @@ -236,7 +236,7 @@ protected: // Generate code for computing the dynamic size of the type virtual void GenDynamicSize(Output* out, Env* env, const DataPtr& data) = 0; - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; virtual Type* DoClone() const = 0; diff --git a/tools/binpac/src/pac_typedecl.h b/tools/binpac/src/pac_typedecl.h index e393596d63..f7933d59b8 100644 --- a/tools/binpac/src/pac_typedecl.h +++ b/tools/binpac/src/pac_typedecl.h @@ -7,12 +7,12 @@ class TypeDecl : public Decl { public: TypeDecl(ID* arg_id, ParamList* arg_params, Type* arg_type); - ~TypeDecl(); - void Prepare(); - void GenForwardDeclaration(Output* out_h); - void GenCode(Output* out_h, Output* out_cc); + ~TypeDecl() override; + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; - Env* env() const { return env_; } + Env* env() const override { return env_; } Type* type() const { return type_; } string class_name() const; static Type* LookUpType(const ID* id); @@ -20,7 +20,7 @@ public: protected: void AddParam(Param* param); virtual void AddBaseClass(vector* base_classes) const { } - void ProcessAttr(Attr* a); + void ProcessAttr(Attr* a) override; virtual void GenPubDecls(Output* out_h, Output* out_cc); virtual void GenPrivDecls(Output* out_h, Output* out_cc); diff --git a/tools/binpac/src/pac_varfield.h b/tools/binpac/src/pac_varfield.h index 8395ffa6ce..06e991e2c1 100644 --- a/tools/binpac/src/pac_varfield.h +++ b/tools/binpac/src/pac_varfield.h @@ -12,7 +12,7 @@ public: type) { } - void GenPubDecls(Output* out, Env* env) + void GenPubDecls(Output* out, Env* env) override { /* do nothing */ } }; @@ -25,7 +25,7 @@ public: : Field(PUB_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) { } - ~PubVarField() { } + ~PubVarField() override { } }; // A private variable @@ -37,9 +37,9 @@ public: type) { } - ~PrivVarField() { } + ~PrivVarField() override { } - void GenPubDecls(Output* out, Env* env) + void GenPubDecls(Output* out, Env* env) override { /* do nothing */ } }; @@ -51,7 +51,7 @@ public: : Field(TEMP_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, id, type) { } - ~TempVarField() { } + ~TempVarField() override { } }; #endif // pac_varfield_h diff --git a/tools/binpac/src/pac_withinput.h b/tools/binpac/src/pac_withinput.h index d4daebc444..aee1c3d7b9 100644 --- a/tools/binpac/src/pac_withinput.h +++ b/tools/binpac/src/pac_withinput.h @@ -9,11 +9,11 @@ class WithInputField : public Field, public Evaluatable { public: WithInputField(ID* id, Type* type, InputBuffer* input); - virtual ~WithInputField(); + ~WithInputField() override; InputBuffer* input() const { return input_; } - void Prepare(Env* env); + void Prepare(Env* env) override; // void GenPubDecls(Output* out, Env* env); // void GenPrivDecls(Output* out, Env* env); @@ -24,12 +24,12 @@ public: void GenParseCode(Output* out, Env* env); // Instantiate the Evaluatable interface - void GenEval(Output* out, Env* env); + void GenEval(Output* out, Env* env) override; - bool RequiresAnalyzerContext() const; + bool RequiresAnalyzerContext() const override; protected: - bool DoTraverse(DataDepVisitor* visitor); + bool DoTraverse(DataDepVisitor* visitor) override; protected: InputBuffer* input_; From 65da8cf5de349b9b2e9fefb01bcff436ac177a54 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 30 Jan 2023 17:30:53 -0700 Subject: [PATCH 123/343] binpac: Avoid initializing array length variables twice in generated code --- tools/binpac/src/pac_array.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 82e4f8c6fb..3df4eacd01 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -252,7 +252,9 @@ void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data) if ( ! incremental_parsing() ) { arraylength_var_field_->GenTempDecls(out_cc, env); - arraylength_var_field_->GenInitCode(out_cc, env); + // This is about to get initialized below, don't initialize it twice. + if ( ! length_ && ! attr_restofdata_ ) + arraylength_var_field_->GenInitCode(out_cc, env); } if ( length_ ) From 5264b957f1251322ecc09e6f2d1f4818b4abf84d Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 30 Jan 2023 17:31:13 -0700 Subject: [PATCH 124/343] binpac: Generate range-based for loops for array cleanup --- tools/binpac/src/pac_array.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 3df4eacd01..215fe37fd8 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -383,11 +383,10 @@ void ArrayType::GenCleanUpCode(Output* out_cc, Env* env) out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("for ( int i = 0; i < (int) %s->size(); ++i )", env->RValue(value_var())); + out_cc->println("for ( auto* %s : *%s )", env->LValue(elem_var()), + env->RValue(value_var())); out_cc->inc_indent(); out_cc->println("{"); - out_cc->println("%s %s = (*%s)[i];", elemtype_->DataTypeStr().c_str(), - env->LValue(elem_var()), lvalue()); elemtype_->GenCleanUpCode(out_cc, env); out_cc->println("}"); out_cc->dec_indent(); From e05a0b8748bef0bc4f7100122e1abceb65fea35f Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 17 Feb 2023 17:53:57 -0700 Subject: [PATCH 125/343] binpac: Remove argument from BINPAC_LSAN_DISABLE macro to fix warning on Windows --- tools/binpac/src/pac_main.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index bea647a550..17580b3608 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -219,9 +219,9 @@ void usage() // FreeBSD doesn't support LeakSanitizer #if defined(USING_ASAN) && ! defined(__FreeBSD__) #include -#define BINPAC_LSAN_DISABLE(x) __lsan_disable(x) +#define BINPAC_LSAN_DISABLE() __lsan_disable() #else -#define BINPAC_LSAN_DISABLE(x) +#define BINPAC_LSAN_DISABLE() #endif int main(int argc, char* argv[]) From ba7a7c2201cd3f40389214c5f544e352d728aa95 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sat, 18 Feb 2023 21:17:11 -0700 Subject: [PATCH 126/343] binpac: Include stdint.h early to prevent redefinition of int type macros --- tools/binpac/src/pac_scan.ll | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index 449403d76d..e3b35d3663 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -1,3 +1,11 @@ +%top{ +// Include stdint.h at the start of the generated file. Typically +// MSVC will include this header later, after the definitions of +// the integral type macros. MSVC then complains that about the +// redefinition of the types. Including stdint.h early avoids this. +#include +} + %{ #include "pac_action.h" #include "pac_array.h" From 4d0a29a725172226bf901531d848270411376aa8 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 24 Mar 2023 11:55:46 -0700 Subject: [PATCH 127/343] binpac: Don't output comment for &let/&withinput if no such fields exist --- tools/binpac/src/pac_type.cc | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index 478c6e5826..f6a9085857 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -703,19 +703,22 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag out_cc->println("{"); } - out_cc->println("// Evaluate 'let' and 'withinput' fields"); - foreach (i, FieldList, fields_) + if ( ! fields_->empty() ) { - Field* f = *i; - if ( f->tof() == LET_FIELD ) + out_cc->println("// Evaluate 'let' and 'withinput' fields"); + foreach (i, FieldList, fields_) { - LetField* lf = static_cast(f); - lf->GenParseCode(out_cc, env); - } - else if ( f->tof() == WITHINPUT_FIELD ) - { - WithInputField* af = static_cast(f); - af->GenParseCode(out_cc, env); + Field* f = *i; + if ( f->tof() == LET_FIELD ) + { + LetField* lf = static_cast(f); + lf->GenParseCode(out_cc, env); + } + else if ( f->tof() == WITHINPUT_FIELD ) + { + WithInputField* af = static_cast(f); + af->GenParseCode(out_cc, env); + } } } From d39df6b243d9a5df4f3bb8b6e3f09780a8c40a9c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 24 May 2023 12:21:15 -0700 Subject: [PATCH 128/343] binpac: Remove vendored CMake files from repo --- tools/binpac/src/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 24529cce6e..f1a3068b8c 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -1,6 +1,5 @@ bison_target(PACParser pac_parse.yy ${BinPAC_BINARY_DIR}/src/pac_parse.cc - HEADER ${BinPAC_BINARY_DIR}/src/pac_parse.h - VERBOSE ${BinPAC_BINARY_DIR}/src/pac_parse.output + DEFINES_FILE ${BinPAC_BINARY_DIR}/src/pac_parse.h COMPILE_FLAGS "--debug") flex_target(PACScanner pac_scan.ll ${BinPAC_BINARY_DIR}/pac_scan.cc) add_flex_bison_dependency(PACScanner PACParser) @@ -10,7 +9,7 @@ else() set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") endif() include(RequireCXX17) - + include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src) From b7cc5afa788f87bd654fa4cc3baf5e17e2825d4f Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 15 Jun 2023 11:44:45 -0700 Subject: [PATCH 129/343] binpac: Require CMake 3.15.0 to build, similar to the recent changes to zeek and broker --- tools/binpac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 0960a0a410..30a4ad41c1 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR) project(BinPAC C CXX) include(cmake/CommonCMakeConfig.cmake) From 874de5d25b74f9634330677471f0e2862ba56a75 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 15 Jun 2023 11:45:13 -0700 Subject: [PATCH 130/343] binpac: Force -std=c++17 mode for cmake targets, remove use of RequireCXX17.cmake --- tools/binpac/lib/CMakeLists.txt | 7 ++++++- tools/binpac/src/CMakeLists.txt | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index d79b3f38b1..219018edb6 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -27,7 +27,9 @@ set(binpac_lib_SRCS if ( ENABLE_SHARED ) add_library(binpac_lib SHARED ${binpac_lib_SRCS}) + target_compile_features(binpac_lib PRIVATE cxx_std_17) set_target_properties(binpac_lib PROPERTIES + CXX_EXTENSIONS OFF SOVERSION ${BINPAC_SOVERSION} VERSION ${BINPAC_VERSION_MAJOR}.${BINPAC_VERSION_MINOR} MACOSX_RPATH true @@ -37,7 +39,10 @@ endif () if ( ENABLE_STATIC ) add_library(binpac_static STATIC ${binpac_lib_SRCS}) - set_target_properties(binpac_static PROPERTIES OUTPUT_NAME binpac) + target_compile_features(binpac_static PRIVATE cxx_std_17) + set_target_properties(binpac_static PROPERTIES + CXX_EXTENSIONS OFF + OUTPUT_NAME binpac) install(TARGETS binpac_static DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif () diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index f1a3068b8c..1cfb83f505 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -8,7 +8,6 @@ if (MSVC) else() set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") endif() -include(RequireCXX17) include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src) @@ -103,6 +102,8 @@ set(binpac_SRCS ) add_executable(binpac ${binpac_SRCS}) +target_compile_features(binpac PRIVATE cxx_std_17) +set_target_properties(binpac PROPERTIES CXX_EXTENSIONS OFF) if ( MSVC ) # If building separately from zeek, we need to add the libunistd subdirectory so From a4bc3fdf327c8cdf629d5a79579e7591f5b99545 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 30 Jun 2023 14:04:12 -0700 Subject: [PATCH 131/343] binpac: Add /J flag on Windows to force unsigned char --- tools/binpac/CMakeLists.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 30a4ad41c1..b5ca54a665 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -31,12 +31,16 @@ FindRequiredPackage(FLEX) FindRequiredPackage(BISON) if (MISSING_PREREQS) - foreach (prereq ${MISSING_PREREQ_DESCS}) - message(SEND_ERROR ${prereq}) - endforeach () - message(FATAL_ERROR "Configuration aborted due to missing prerequisites") + foreach (prereq ${MISSING_PREREQ_DESCS}) + message(SEND_ERROR ${prereq}) + endforeach () + message(FATAL_ERROR "Configuration aborted due to missing prerequisites") endif () +if (MSVC) + add_compile_options(/J) # Similar to -funsigned-char on other platforms +endif() + ######################################################################## ## System Introspection From 716bf016a1a04f7a969c6330d16f1cc70b39c23a Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 2 Aug 2023 12:58:31 -0700 Subject: [PATCH 132/343] binpac: Remove usage of FindRequiredPackage --- tools/binpac/CMakeLists.txt | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index b5ca54a665..92d9abc0f8 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -25,17 +25,8 @@ include(GNUInstallDirs) ######################################################################## ## Dependency Configuration -include(FindRequiredPackage) - -FindRequiredPackage(FLEX) -FindRequiredPackage(BISON) - -if (MISSING_PREREQS) - foreach (prereq ${MISSING_PREREQ_DESCS}) - message(SEND_ERROR ${prereq}) - endforeach () - message(FATAL_ERROR "Configuration aborted due to missing prerequisites") -endif () +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) if (MSVC) add_compile_options(/J) # Similar to -funsigned-char on other platforms From 3297de477b6ccc9b10f92cfb4fbd0633af3ffa97 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 30 Oct 2023 13:15:14 -0700 Subject: [PATCH 133/343] binpac: Reformat C++ code in Spicy style --- tools/binpac/lib/binpac_analyzer.h | 24 +- tools/binpac/lib/binpac_buffer.cc | 729 +++++------ tools/binpac/lib/binpac_buffer.h | 263 ++-- tools/binpac/lib/binpac_bytestring.cc | 20 +- tools/binpac/lib/binpac_bytestring.h | 198 ++- tools/binpac/lib/binpac_exception.h | 143 +- tools/binpac/lib/binpac_regex.cc | 9 +- tools/binpac/lib/binpac_regex.h | 80 +- tools/binpac/src/pac_action.cc | 127 +- tools/binpac/src/pac_action.h | 82 +- tools/binpac/src/pac_analyzer.cc | 488 +++---- tools/binpac/src/pac_analyzer.h | 199 ++- tools/binpac/src/pac_array.cc | 1288 +++++++++--------- tools/binpac/src/pac_array.h | 103 +- tools/binpac/src/pac_attr.cc | 85 +- tools/binpac/src/pac_attr.h | 85 +- tools/binpac/src/pac_btype.cc | 164 +-- tools/binpac/src/pac_btype.h | 49 +- tools/binpac/src/pac_case.cc | 690 +++++----- tools/binpac/src/pac_case.h | 106 +- tools/binpac/src/pac_cclass.h | 62 +- tools/binpac/src/pac_common.h | 46 +- tools/binpac/src/pac_conn.cc | 202 ++- tools/binpac/src/pac_conn.h | 33 +- tools/binpac/src/pac_context.cc | 138 +- tools/binpac/src/pac_context.h | 99 +- tools/binpac/src/pac_cstr.cc | 183 ++- tools/binpac/src/pac_cstr.h | 21 +- tools/binpac/src/pac_ctype.cc | 24 +- tools/binpac/src/pac_ctype.h | 19 +- tools/binpac/src/pac_datadep.cc | 95 +- tools/binpac/src/pac_datadep.h | 80 +- tools/binpac/src/pac_dataptr.cc | 78 +- tools/binpac/src/pac_dataptr.h | 48 +- tools/binpac/src/pac_dataunit.cc | 58 +- tools/binpac/src/pac_dataunit.h | 57 +- tools/binpac/src/pac_dbg.h | 6 +- tools/binpac/src/pac_decl.cc | 214 ++- tools/binpac/src/pac_decl.h | 116 +- tools/binpac/src/pac_embedded.cc | 94 +- tools/binpac/src/pac_embedded.h | 42 +- tools/binpac/src/pac_enum.cc | 93 +- tools/binpac/src/pac_enum.h | 38 +- tools/binpac/src/pac_exception.cc | 101 +- tools/binpac/src/pac_exception.h | 111 +- tools/binpac/src/pac_expr.cc | 1744 +++++++++++-------------- tools/binpac/src/pac_expr.h | 179 ++- tools/binpac/src/pac_exttype.cc | 97 +- tools/binpac/src/pac_exttype.h | 42 +- tools/binpac/src/pac_field.cc | 213 ++- tools/binpac/src/pac_field.h | 112 +- tools/binpac/src/pac_flow.cc | 431 +++--- tools/binpac/src/pac_flow.h | 51 +- tools/binpac/src/pac_func.cc | 141 +- tools/binpac/src/pac_func.h | 73 +- tools/binpac/src/pac_id.cc | 618 ++++----- tools/binpac/src/pac_id.h | 238 ++-- tools/binpac/src/pac_inputbuf.cc | 41 +- tools/binpac/src/pac_inputbuf.h | 15 +- tools/binpac/src/pac_let.cc | 201 ++- tools/binpac/src/pac_let.h | 48 +- tools/binpac/src/pac_main.cc | 373 +++--- tools/binpac/src/pac_number.h | 17 +- tools/binpac/src/pac_output.cc | 110 +- tools/binpac/src/pac_output.h | 38 +- tools/binpac/src/pac_param.cc | 75 +- tools/binpac/src/pac_param.h | 36 +- tools/binpac/src/pac_paramtype.cc | 392 +++--- tools/binpac/src/pac_paramtype.h | 67 +- tools/binpac/src/pac_primitive.cc | 42 +- tools/binpac/src/pac_primitive.h | 79 +- tools/binpac/src/pac_record.cc | 958 ++++++-------- tools/binpac/src/pac_record.h | 220 ++-- tools/binpac/src/pac_redef.cc | 199 ++- tools/binpac/src/pac_regex.cc | 104 +- tools/binpac/src/pac_regex.h | 38 +- tools/binpac/src/pac_state.cc | 29 +- tools/binpac/src/pac_state.h | 25 +- tools/binpac/src/pac_strtype.cc | 561 ++++---- tools/binpac/src/pac_strtype.h | 94 +- tools/binpac/src/pac_type.cc | 1649 +++++++++++------------ tools/binpac/src/pac_type.h | 438 +++---- tools/binpac/src/pac_typedecl.cc | 532 ++++---- tools/binpac/src/pac_typedecl.h | 55 +- tools/binpac/src/pac_utils.cc | 57 +- tools/binpac/src/pac_varfield.cc | 5 +- tools/binpac/src/pac_varfield.h | 61 +- tools/binpac/src/pac_withinput.cc | 99 +- tools/binpac/src/pac_withinput.h | 33 +- 89 files changed, 7887 insertions(+), 9733 deletions(-) diff --git a/tools/binpac/lib/binpac_analyzer.h b/tools/binpac/lib/binpac_analyzer.h index c49fe22f20..23931eeb27 100644 --- a/tools/binpac/lib/binpac_analyzer.h +++ b/tools/binpac/lib/binpac_analyzer.h @@ -1,28 +1,24 @@ #ifndef binpac_an_h #define binpac_an_h -namespace binpac - { +namespace binpac { // TODO: Add the Done() function // The interface for a connection analyzer -class ConnectionAnalyzer - { +class ConnectionAnalyzer { public: - virtual ~ConnectionAnalyzer() { } - virtual void NewData(bool is_orig, const unsigned char* begin_of_data, - const unsigned char* end_of_data) = 0; - }; + virtual ~ConnectionAnalyzer() {} + virtual void NewData(bool is_orig, const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0; +}; // The interface for a flow analyzer -class FlowAnalyzer - { +class FlowAnalyzer { public: - virtual ~FlowAnalyzer() { } - virtual void NewData(const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0; - }; + virtual ~FlowAnalyzer() {} + virtual void NewData(const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0; +}; - } // namespace binpac +} // namespace binpac #endif // binpac_an_h diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index 56ad6a8b77..915c370e1d 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -7,310 +7,248 @@ #include "binpac.h" #include "binpac_buffer.h" -namespace binpac - { +namespace binpac { extern double network_time(); -namespace - { +namespace { const unsigned char CR = '\r'; const unsigned char LF = '\n'; - } +} // namespace binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = { - // max_capacity - 10 * 1024 * 1024, - // min_capacity - 512, - // contract_threshold - 2 * 1024 * 1024, + // max_capacity + 10 * 1024 * 1024, + // min_capacity + 512, + // contract_threshold + 2 * 1024 * 1024, }; -FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) - { - buffer_length_ = 0; - buffer_ = nullptr; +FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) { + buffer_length_ = 0; + buffer_ = nullptr; - orig_data_begin_ = nullptr; - orig_data_end_ = nullptr; + orig_data_begin_ = nullptr; + orig_data_end_ = nullptr; - linebreak_style_ = linebreak_style; - linebreak_style_default = linebreak_style; - linebreaker_ = 0; - ResetLineState(); + linebreak_style_ = linebreak_style; + linebreak_style_default = linebreak_style; + linebreaker_ = 0; + ResetLineState(); - mode_ = UNKNOWN_MODE; - frame_length_ = 0; - chunked_ = false; + mode_ = UNKNOWN_MODE; + frame_length_ = 0; + chunked_ = false; - data_seq_at_orig_data_end_ = 0; - eof_ = false; - have_pending_request_ = false; + data_seq_at_orig_data_end_ = 0; + eof_ = false; + have_pending_request_ = false; - buffer_n_ = 0; + buffer_n_ = 0; - NewMessage(); - } + NewMessage(); +} -FlowBuffer::~FlowBuffer() - { - if ( buffer_ ) - free(buffer_); - } +FlowBuffer::~FlowBuffer() { + if ( buffer_ ) + free(buffer_); +} -void FlowBuffer::NewMessage() - { - BINPAC_ASSERT(frame_length_ >= 0); +void FlowBuffer::NewMessage() { + BINPAC_ASSERT(frame_length_ >= 0); - int bytes_to_advance = 0; - if ( buffer_n_ == 0 ) - { - switch ( mode_ ) - { - case LINE_MODE: - bytes_to_advance = (frame_length_ + (linebreak_style_ == STRICT_CRLF ? 2 : 1)); - break; - case FRAME_MODE: - bytes_to_advance = frame_length_; - break; - case UNKNOWN_MODE: - break; - } - } + int bytes_to_advance = 0; + if ( buffer_n_ == 0 ) { + switch ( mode_ ) { + case LINE_MODE: bytes_to_advance = (frame_length_ + (linebreak_style_ == STRICT_CRLF ? 2 : 1)); break; + case FRAME_MODE: bytes_to_advance = frame_length_; break; + case UNKNOWN_MODE: break; + } + } - orig_data_begin_ += bytes_to_advance; - BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_); + orig_data_begin_ += bytes_to_advance; + BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_); - buffer_n_ = 0; - message_complete_ = false; - ContractBuffer(); - } + buffer_n_ = 0; + message_complete_ = false; + ContractBuffer(); +} -void FlowBuffer::ResetLineState() - { - switch ( linebreak_style_ ) - { - case CR_OR_LF: - state_ = CR_OR_LF_0; - break; - case STRICT_CRLF: - state_ = STRICT_CRLF_0; - break; - case LINE_BREAKER: - break; // Nothing to reset - default: - BINPAC_ASSERT(0); - break; - } - } +void FlowBuffer::ResetLineState() { + switch ( linebreak_style_ ) { + case CR_OR_LF: state_ = CR_OR_LF_0; break; + case STRICT_CRLF: state_ = STRICT_CRLF_0; break; + case LINE_BREAKER: break; // Nothing to reset + default: BINPAC_ASSERT(0); break; + } +} -void FlowBuffer::ExpandBuffer(int length) - { - if ( buffer_length_ >= length ) - return; +void FlowBuffer::ExpandBuffer(int length) { + if ( buffer_length_ >= length ) + return; - if ( length < policy.min_capacity ) - length = policy.min_capacity; + if ( length < policy.min_capacity ) + length = policy.min_capacity; - if ( length < buffer_length_ * 2 ) - length = buffer_length_ * 2; + if ( length < buffer_length_ * 2 ) + length = buffer_length_ * 2; - if ( length > policy.max_capacity ) - { - std::string reason = strfmt("expand past max capacity %d/%d", length, policy.max_capacity); - throw ExceptionFlowBufferAlloc(reason.c_str()); - } + if ( length > policy.max_capacity ) { + std::string reason = strfmt("expand past max capacity %d/%d", length, policy.max_capacity); + throw ExceptionFlowBufferAlloc(reason.c_str()); + } - // Allocate a new buffer and copy the existing contents - buffer_length_ = length; - unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_); + // Allocate a new buffer and copy the existing contents + buffer_length_ = length; + unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_); - if ( ! new_buf ) - throw ExceptionFlowBufferAlloc("expand realloc OOM"); + if ( ! new_buf ) + throw ExceptionFlowBufferAlloc("expand realloc OOM"); - buffer_ = new_buf; - } + buffer_ = new_buf; +} -void FlowBuffer::ContractBuffer() - { - if ( buffer_length_ < policy.contract_threshold ) - return; +void FlowBuffer::ContractBuffer() { + if ( buffer_length_ < policy.contract_threshold ) + return; - buffer_length_ = policy.min_capacity; - unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_); + buffer_length_ = policy.min_capacity; + unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_); - if ( ! new_buf ) - throw ExceptionFlowBufferAlloc("contract realloc OOM"); + if ( ! new_buf ) + throw ExceptionFlowBufferAlloc("contract realloc OOM"); - buffer_ = new_buf; - } + buffer_ = new_buf; +} -void FlowBuffer::SetLineBreaker(unsigned char* lbreaker) - { - linebreaker_ = *lbreaker; - linebreak_style_default = linebreak_style_; - linebreak_style_ = LINE_BREAKER; - } +void FlowBuffer::SetLineBreaker(unsigned char* lbreaker) { + linebreaker_ = *lbreaker; + linebreak_style_default = linebreak_style_; + linebreak_style_ = LINE_BREAKER; +} -void FlowBuffer::UnsetLineBreaker() - { - linebreak_style_ = linebreak_style_default; - } +void FlowBuffer::UnsetLineBreaker() { linebreak_style_ = linebreak_style_default; } -void FlowBuffer::NewLine() - { - FlowBuffer::NewMessage(); - mode_ = LINE_MODE; - frame_length_ = 0; - chunked_ = false; - have_pending_request_ = true; - if ( state_ == FRAME_0 ) - ResetLineState(); - MarkOrCopyLine(); - } +void FlowBuffer::NewLine() { + FlowBuffer::NewMessage(); + mode_ = LINE_MODE; + frame_length_ = 0; + chunked_ = false; + have_pending_request_ = true; + if ( state_ == FRAME_0 ) + ResetLineState(); + MarkOrCopyLine(); +} -void FlowBuffer::NewFrame(int frame_length, bool chunked) - { - FlowBuffer::NewMessage(); - mode_ = FRAME_MODE; - frame_length_ = frame_length; - chunked_ = chunked; - have_pending_request_ = true; - MarkOrCopyFrame(); - } +void FlowBuffer::NewFrame(int frame_length, bool chunked) { + FlowBuffer::NewMessage(); + mode_ = FRAME_MODE; + frame_length_ = frame_length; + chunked_ = chunked; + have_pending_request_ = true; + MarkOrCopyFrame(); +} -void FlowBuffer::BufferData(const_byteptr data, const_byteptr end) - { - mode_ = FRAME_MODE; - frame_length_ += (end - data); - MarkOrCopyFrame(); - NewData(data, end); - } +void FlowBuffer::BufferData(const_byteptr data, const_byteptr end) { + mode_ = FRAME_MODE; + frame_length_ += (end - data); + MarkOrCopyFrame(); + NewData(data, end); +} -void FlowBuffer::FinishBuffer() - { - message_complete_ = true; - } +void FlowBuffer::FinishBuffer() { message_complete_ = true; } -void FlowBuffer::GrowFrame(int length) - { - BINPAC_ASSERT(frame_length_ >= 0); - if ( length <= frame_length_ ) - return; - BINPAC_ASSERT(! chunked_ || frame_length_ == 0); - mode_ = FRAME_MODE; - frame_length_ = length; - MarkOrCopyFrame(); - } +void FlowBuffer::GrowFrame(int length) { + BINPAC_ASSERT(frame_length_ >= 0); + if ( length <= frame_length_ ) + return; + BINPAC_ASSERT(! chunked_ || frame_length_ == 0); + mode_ = FRAME_MODE; + frame_length_ = length; + MarkOrCopyFrame(); +} -void FlowBuffer::DiscardData() - { - mode_ = UNKNOWN_MODE; - message_complete_ = false; - have_pending_request_ = false; - orig_data_begin_ = orig_data_end_ = nullptr; +void FlowBuffer::DiscardData() { + mode_ = UNKNOWN_MODE; + message_complete_ = false; + have_pending_request_ = false; + orig_data_begin_ = orig_data_end_ = nullptr; - buffer_n_ = 0; - frame_length_ = 0; - ContractBuffer(); - } + buffer_n_ = 0; + frame_length_ = 0; + ContractBuffer(); +} -void FlowBuffer::set_eof() - { - // fprintf(stderr, "EOF\n"); - eof_ = true; - if ( chunked_ ) - frame_length_ = orig_data_end_ - orig_data_begin_; - if ( frame_length_ < 0 ) - frame_length_ = 0; - } +void FlowBuffer::set_eof() { + // fprintf(stderr, "EOF\n"); + eof_ = true; + if ( chunked_ ) + frame_length_ = orig_data_end_ - orig_data_begin_; + if ( frame_length_ < 0 ) + frame_length_ = 0; +} -void FlowBuffer::NewData(const_byteptr begin, const_byteptr end) - { - BINPAC_ASSERT(begin <= end); +void FlowBuffer::NewData(const_byteptr begin, const_byteptr end) { + BINPAC_ASSERT(begin <= end); - ClearPreviousData(); + ClearPreviousData(); - BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || orig_data_begin_ == orig_data_end_); + BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || orig_data_begin_ == orig_data_end_); - orig_data_begin_ = begin; - orig_data_end_ = end; - data_seq_at_orig_data_end_ += (end - begin); + orig_data_begin_ = begin; + orig_data_end_ = end; + data_seq_at_orig_data_end_ += (end - begin); - MarkOrCopy(); - } + MarkOrCopy(); +} -void FlowBuffer::MarkOrCopy() - { - if ( ! message_complete_ ) - { - switch ( mode_ ) - { - case LINE_MODE: - MarkOrCopyLine(); - break; +void FlowBuffer::MarkOrCopy() { + if ( ! message_complete_ ) { + switch ( mode_ ) { + case LINE_MODE: MarkOrCopyLine(); break; - case FRAME_MODE: - MarkOrCopyFrame(); - break; + case FRAME_MODE: MarkOrCopyFrame(); break; - default: - break; - } - } - } + default: break; + } + } +} -void FlowBuffer::ClearPreviousData() - { - // All previous data must have been processed or buffered already - if ( orig_data_begin_ < orig_data_end_ ) - { - BINPAC_ASSERT(buffer_n_ == 0); - if ( chunked_ ) - { - if ( frame_length_ > 0 ) - { - frame_length_ -= (orig_data_end_ - orig_data_begin_); - } - orig_data_begin_ = orig_data_end_; - } - } - } +void FlowBuffer::ClearPreviousData() { + // All previous data must have been processed or buffered already + if ( orig_data_begin_ < orig_data_end_ ) { + BINPAC_ASSERT(buffer_n_ == 0); + if ( chunked_ ) { + if ( frame_length_ > 0 ) { + frame_length_ -= (orig_data_end_ - orig_data_begin_); + } + orig_data_begin_ = orig_data_end_; + } + } +} -void FlowBuffer::NewGap(int length) - { - ClearPreviousData(); +void FlowBuffer::NewGap(int length) { + ClearPreviousData(); - if ( chunked_ && frame_length_ >= 0 ) - { - frame_length_ -= length; - if ( frame_length_ < 0 ) - frame_length_ = 0; - } + if ( chunked_ && frame_length_ >= 0 ) { + frame_length_ -= length; + if ( frame_length_ < 0 ) + frame_length_ = 0; + } - orig_data_begin_ = orig_data_end_ = nullptr; - MarkOrCopy(); - } + orig_data_begin_ = orig_data_end_ = nullptr; + MarkOrCopy(); +} -void FlowBuffer::MarkOrCopyLine() - { - switch ( linebreak_style_ ) - { - case CR_OR_LF: - MarkOrCopyLine_CR_OR_LF(); - break; - case STRICT_CRLF: - MarkOrCopyLine_STRICT_CRLF(); - break; - case LINE_BREAKER: - MarkOrCopyLine_LINEBREAK(); - break; - default: - BINPAC_ASSERT(0); - break; - } - } +void FlowBuffer::MarkOrCopyLine() { + switch ( linebreak_style_ ) { + case CR_OR_LF: MarkOrCopyLine_CR_OR_LF(); break; + case STRICT_CRLF: MarkOrCopyLine_STRICT_CRLF(); break; + case LINE_BREAKER: MarkOrCopyLine_LINEBREAK(); break; + default: BINPAC_ASSERT(0); break; + } +} /* Finite state automaton for CR_OR_LF: @@ -327,57 +265,49 @@ CR_OR_LF_1: .: CR_OR_LF_0 * */ -void FlowBuffer::MarkOrCopyLine_CR_OR_LF() - { - if ( ! (orig_data_begin_ && orig_data_end_) ) - return; +void FlowBuffer::MarkOrCopyLine_CR_OR_LF() { + if ( ! (orig_data_begin_ && orig_data_end_) ) + return; - if ( state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF ) - { - state_ = CR_OR_LF_0; - ++orig_data_begin_; - } + if ( state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF ) { + state_ = CR_OR_LF_0; + ++orig_data_begin_; + } - const_byteptr data; - for ( data = orig_data_begin_; data < orig_data_end_; ++data ) - { - switch ( *data ) - { - case CR: - state_ = CR_OR_LF_1; - goto found_end_of_line; + const_byteptr data; + for ( data = orig_data_begin_; data < orig_data_end_; ++data ) { + switch ( *data ) { + case CR: state_ = CR_OR_LF_1; goto found_end_of_line; - case LF: - // state_ = CR_OR_LF_0; - goto found_end_of_line; + case LF: + // state_ = CR_OR_LF_0; + goto found_end_of_line; - default: - // state_ = CR_OR_LF_0; - break; - } - } + default: + // state_ = CR_OR_LF_0; + break; + } + } - AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); - return; + AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); + return; found_end_of_line: - if ( buffer_n_ == 0 ) - { - frame_length_ = data - orig_data_begin_; - } - else - { - AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); - // But eliminate the last CR or LF - --buffer_n_; - } - message_complete_ = true; + if ( buffer_n_ == 0 ) { + frame_length_ = data - orig_data_begin_; + } + else { + AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); + // But eliminate the last CR or LF + --buffer_n_; + } + message_complete_ = true; #if DEBUG_FLOW_BUFFER - fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(), - string((const char*)begin(), (const char*)end()).c_str()); + fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(), + string((const char*)begin(), (const char*)end()).c_str()); #endif - } +} /* Finite state automaton and STRICT_CRLF: @@ -394,87 +324,73 @@ STRICT_CRLF_1: .: STRICT_CRLF_0 * */ -void FlowBuffer::MarkOrCopyLine_STRICT_CRLF() - { - const_byteptr data; - for ( data = orig_data_begin_; data < orig_data_end_; ++data ) - { - switch ( *data ) - { - case CR: - state_ = STRICT_CRLF_1; - break; +void FlowBuffer::MarkOrCopyLine_STRICT_CRLF() { + const_byteptr data; + for ( data = orig_data_begin_; data < orig_data_end_; ++data ) { + switch ( *data ) { + case CR: state_ = STRICT_CRLF_1; break; - case LF: - if ( state_ == STRICT_CRLF_1 ) - { - state_ = STRICT_CRLF_0; - goto found_end_of_line; - } - break; + case LF: + if ( state_ == STRICT_CRLF_1 ) { + state_ = STRICT_CRLF_0; + goto found_end_of_line; + } + break; - default: - state_ = STRICT_CRLF_0; - break; - } - } + default: state_ = STRICT_CRLF_0; break; + } + } - AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); - return; + AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); + return; found_end_of_line: - if ( buffer_n_ == 0 ) - { - frame_length_ = data - 1 - orig_data_begin_; - } - else - { - AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); - // Pop the preceding CR and LF from the buffer - buffer_n_ -= 2; - } + if ( buffer_n_ == 0 ) { + frame_length_ = data - 1 - orig_data_begin_; + } + else { + AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); + // Pop the preceding CR and LF from the buffer + buffer_n_ -= 2; + } - message_complete_ = true; + message_complete_ = true; #if DEBUG_FLOW_BUFFER - fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(), - string((const char*)begin(), (const char*)end()).c_str()); + fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(), + string((const char*)begin(), (const char*)end()).c_str()); #endif - } +} -void FlowBuffer::MarkOrCopyLine_LINEBREAK() - { - if ( ! (orig_data_begin_ && orig_data_end_) ) - return; +void FlowBuffer::MarkOrCopyLine_LINEBREAK() { + if ( ! (orig_data_begin_ && orig_data_end_) ) + return; - const_byteptr data; - for ( data = orig_data_begin_; data < orig_data_end_; ++data ) - { - if ( *data == linebreaker_ ) - goto found_end_of_line; - } + const_byteptr data; + for ( data = orig_data_begin_; data < orig_data_end_; ++data ) { + if ( *data == linebreaker_ ) + goto found_end_of_line; + } - AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); - return; + AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); + return; found_end_of_line: - if ( buffer_n_ == 0 ) - { - frame_length_ = data - orig_data_begin_; - } - else - { - AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); - // But eliminate the last CR or LF - --buffer_n_; - } - message_complete_ = true; + if ( buffer_n_ == 0 ) { + frame_length_ = data - orig_data_begin_; + } + else { + AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); + // But eliminate the last 'linebreaker' character + --buffer_n_; + } + message_complete_ = true; #if DEBUG_FLOW_BUFFER - fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(), - string((const char*)begin(), (const char*)end()).c_str()); + fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(), + string((const char*)begin(), (const char*)end()).c_str()); #endif - } +} // Invariants: // @@ -484,69 +400,58 @@ found_end_of_line: // When buffer_n_ > 0: // Frame = [0..buffer_n_][orig_data_begin_..] -void FlowBuffer::MarkOrCopyFrame() - { - if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ ) - { - // Skip the lingering LF - if ( *orig_data_begin_ == LF ) - { - ++orig_data_begin_; - } - state_ = FRAME_0; - } +void FlowBuffer::MarkOrCopyFrame() { + if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ ) { + // Skip the lingering LF + if ( *orig_data_begin_ == LF ) { + ++orig_data_begin_; + } + state_ = FRAME_0; + } - if ( buffer_n_ == 0 ) - { - // If there is enough data - if ( frame_length_ >= 0 && orig_data_end_ - orig_data_begin_ >= frame_length_ ) - { - // Do nothing except setting the message complete flag - message_complete_ = true; - } - else - { - if ( ! chunked_ ) - { - AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); - } - message_complete_ = false; - } - } - else - { - BINPAC_ASSERT(! chunked_); - int bytes_to_copy = orig_data_end_ - orig_data_begin_; - message_complete_ = false; - if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ ) - { - bytes_to_copy = frame_length_ - buffer_n_; - message_complete_ = true; - } - AppendToBuffer(orig_data_begin_, bytes_to_copy); - } + if ( buffer_n_ == 0 ) { + // If there is enough data + if ( frame_length_ >= 0 && orig_data_end_ - orig_data_begin_ >= frame_length_ ) { + // Do nothing except setting the message complete flag + message_complete_ = true; + } + else { + if ( ! chunked_ ) { + AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_); + } + message_complete_ = false; + } + } + else { + BINPAC_ASSERT(! chunked_); + int bytes_to_copy = orig_data_end_ - orig_data_begin_; + message_complete_ = false; + if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ ) { + bytes_to_copy = frame_length_ - buffer_n_; + message_complete_ = true; + } + AppendToBuffer(orig_data_begin_, bytes_to_copy); + } #if DEBUG_FLOW_BUFFER - if ( message_complete_ ) - { - fprintf(stderr, "%.6f frame complete: [%s]\n", network_time(), - string((const char*)begin(), (const char*)end()).c_str()); - } + if ( message_complete_ ) { + fprintf(stderr, "%.6f frame complete: [%s]\n", network_time(), + string((const char*)begin(), (const char*)end()).c_str()); + } #endif - } +} -void FlowBuffer::AppendToBuffer(const_byteptr data, int len) - { - if ( len <= 0 ) - return; +void FlowBuffer::AppendToBuffer(const_byteptr data, int len) { + if ( len <= 0 ) + return; - BINPAC_ASSERT(! chunked_); - ExpandBuffer(buffer_n_ + len); - memcpy(buffer_ + buffer_n_, data, len); - buffer_n_ += len; + BINPAC_ASSERT(! chunked_); + ExpandBuffer(buffer_n_ + len); + memcpy(buffer_ + buffer_n_, data, len); + buffer_n_ += len; - orig_data_begin_ += len; - BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_); - } + orig_data_begin_ += len; + BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_); +} - } // namespace binpac +} // namespace binpac diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h index 92bbf83a8b..3eb118e71c 100644 --- a/tools/binpac/lib/binpac_buffer.h +++ b/tools/binpac/lib/binpac_buffer.h @@ -5,179 +5,164 @@ #include "binpac.h" -namespace binpac - { +namespace binpac { -class FlowBuffer - { +class FlowBuffer { public: - struct Policy - { - int max_capacity; - int min_capacity; - int contract_threshold; - }; + struct Policy { + int max_capacity; + int min_capacity; + int contract_threshold; + }; - enum LineBreakStyle - { - CR_OR_LF, // CR or LF or CRLF - STRICT_CRLF, // CR followed by LF - CR_LF_NUL, // CR or LF or CR-LF or CR-NUL - LINE_BREAKER, // User specified linebreaker - }; + enum LineBreakStyle { + CR_OR_LF, // CR or LF or CRLF + STRICT_CRLF, // CR followed by LF + CR_LF_NUL, // CR or LF or CR-LF or CR-NUL + LINE_BREAKER, // User specified linebreaker + }; - FlowBuffer(LineBreakStyle linebreak_style = CR_OR_LF); - virtual ~FlowBuffer(); + FlowBuffer(LineBreakStyle linebreak_style = CR_OR_LF); + virtual ~FlowBuffer(); - void NewData(const_byteptr begin, const_byteptr end); - void NewGap(int length); + void NewData(const_byteptr begin, const_byteptr end); + void NewGap(int length); - // Interface for delayed parsing. Sometimes BinPAC doesn't get the - // buffering right and then one can use these to feed parts - // individually and assemble them internally. After calling - // FinishBuffer(), one can send the uppper-layer flow an FlowEOF() to - // trigger parsing. - void BufferData(const_byteptr data, const_byteptr end); - void FinishBuffer(); + // Interface for delayed parsing. Sometimes BinPAC doesn't get the + // buffering right and then one can use these to feed parts + // individually and assemble them internally. After calling + // FinishBuffer(), one can send the uppper-layer flow an FlowEOF() to + // trigger parsing. + void BufferData(const_byteptr data, const_byteptr end); + void FinishBuffer(); - // Discard unprocessed data - void DiscardData(); + // Discard unprocessed data + void DiscardData(); - // Whether there is enough data for the frame - bool ready() const { return message_complete_ || mode_ == UNKNOWN_MODE; } + // Whether there is enough data for the frame + bool ready() const { return message_complete_ || mode_ == UNKNOWN_MODE; } - inline const_byteptr begin() const - { - BINPAC_ASSERT(ready()); - return (buffer_n_ == 0) ? orig_data_begin_ : buffer_; - } + inline const_byteptr begin() const { + BINPAC_ASSERT(ready()); + return (buffer_n_ == 0) ? orig_data_begin_ : buffer_; + } - inline const_byteptr end() const - { - BINPAC_ASSERT(ready()); - if ( buffer_n_ == 0 ) - { - BINPAC_ASSERT(frame_length_ >= 0); - const_byteptr end = orig_data_begin_ + frame_length_; - BINPAC_ASSERT(end <= orig_data_end_); - return end; - } - else - return buffer_ + buffer_n_; - } + inline const_byteptr end() const { + BINPAC_ASSERT(ready()); + if ( buffer_n_ == 0 ) { + BINPAC_ASSERT(frame_length_ >= 0); + const_byteptr end = orig_data_begin_ + frame_length_; + BINPAC_ASSERT(end <= orig_data_end_); + return end; + } + else + return buffer_ + buffer_n_; + } - inline int data_length() const - { - if ( buffer_n_ > 0 ) - return buffer_n_; + inline int data_length() const { + if ( buffer_n_ > 0 ) + return buffer_n_; - if ( frame_length_ < 0 || orig_data_begin_ + frame_length_ > orig_data_end_ ) - return orig_data_end_ - orig_data_begin_; - else - return frame_length_; - } + if ( frame_length_ < 0 || orig_data_begin_ + frame_length_ > orig_data_end_ ) + return orig_data_end_ - orig_data_begin_; + else + return frame_length_; + } - inline bool data_available() const - { - return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; - } + inline bool data_available() const { return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; } - void SetLineBreaker(unsigned char* lbreaker); - void UnsetLineBreaker(); - void NewLine(); - // A negative frame_length represents a frame till EOF - void NewFrame(int frame_length, bool chunked_); - void GrowFrame(int new_frame_length); + void SetLineBreaker(unsigned char* lbreaker); + void UnsetLineBreaker(); + void NewLine(); + // A negative frame_length represents a frame till EOF + void NewFrame(int frame_length, bool chunked_); + void GrowFrame(int new_frame_length); - int data_seq() const - { - int data_seq_at_orig_data_begin = data_seq_at_orig_data_end_ - - (orig_data_end_ - orig_data_begin_); - if ( buffer_n_ > 0 ) - return data_seq_at_orig_data_begin; - else - return data_seq_at_orig_data_begin + data_length(); - } - bool eof() const { return eof_; } - void set_eof(); + int data_seq() const { + int data_seq_at_orig_data_begin = data_seq_at_orig_data_end_ - (orig_data_end_ - orig_data_begin_); + if ( buffer_n_ > 0 ) + return data_seq_at_orig_data_begin; + else + return data_seq_at_orig_data_begin + data_length(); + } + bool eof() const { return eof_; } + void set_eof(); - bool have_pending_request() const { return have_pending_request_; } + bool have_pending_request() const { return have_pending_request_; } - static void init(Policy p) { policy = p; } + static void init(Policy p) { policy = p; } protected: - // Reset the buffer for a new message - void NewMessage(); + // Reset the buffer for a new message + void NewMessage(); - void ClearPreviousData(); + void ClearPreviousData(); - // Expand the buffer to at least bytes. If there - // are contents in the existing buffer, copy them to the new - // buffer. - void ExpandBuffer(int length); + // Expand the buffer to at least bytes. If there + // are contents in the existing buffer, copy them to the new + // buffer. + void ExpandBuffer(int length); - // Contract the buffer to some minimum capacity. - // Existing contents in the buffer are preserved (but only usage - // at the time of creation this function is when the contents - // are being discarded due to parsing exception or have already been - // copied out after parsing a complete unit). - void ContractBuffer(); + // Contract the buffer to some minimum capacity. + // Existing contents in the buffer are preserved (but only usage + // at the time of creation this function is when the contents + // are being discarded due to parsing exception or have already been + // copied out after parsing a complete unit). + void ContractBuffer(); - // Reset line state when transit from frame mode to line mode. - void ResetLineState(); + // Reset line state when transit from frame mode to line mode. + void ResetLineState(); - void AppendToBuffer(const_byteptr data, int len); + void AppendToBuffer(const_byteptr data, int len); - // MarkOrCopy{Line,Frame} sets message_complete_ and - // marks begin/end pointers if a line/frame is complete, - // otherwise it clears message_complete_ and copies all - // the original data to the buffer. - // - void MarkOrCopy(); - void MarkOrCopyLine(); - void MarkOrCopyFrame(); + // MarkOrCopy{Line,Frame} sets message_complete_ and + // marks begin/end pointers if a line/frame is complete, + // otherwise it clears message_complete_ and copies all + // the original data to the buffer. + // + void MarkOrCopy(); + void MarkOrCopyLine(); + void MarkOrCopyFrame(); - void MarkOrCopyLine_CR_OR_LF(); - void MarkOrCopyLine_STRICT_CRLF(); - void MarkOrCopyLine_LINEBREAK(); + void MarkOrCopyLine_CR_OR_LF(); + void MarkOrCopyLine_STRICT_CRLF(); + void MarkOrCopyLine_LINEBREAK(); - int buffer_n_; // number of bytes in the buffer - int buffer_length_; // size of the buffer - unsigned char* buffer_; - bool message_complete_; - int frame_length_; - bool chunked_; - const_byteptr orig_data_begin_, orig_data_end_; + int buffer_n_; // number of bytes in the buffer + int buffer_length_; // size of the buffer + unsigned char* buffer_; + bool message_complete_; + int frame_length_; + bool chunked_; + const_byteptr orig_data_begin_, orig_data_end_; - LineBreakStyle linebreak_style_; - LineBreakStyle linebreak_style_default; - unsigned char linebreaker_; + LineBreakStyle linebreak_style_; + LineBreakStyle linebreak_style_default; + unsigned char linebreaker_; - enum - { - UNKNOWN_MODE, - LINE_MODE, - FRAME_MODE, - } mode_; + enum { + UNKNOWN_MODE, + LINE_MODE, + FRAME_MODE, + } mode_; - enum - { - CR_OR_LF_0, - CR_OR_LF_1, - STRICT_CRLF_0, - STRICT_CRLF_1, - FRAME_0, - } state_; + enum { + CR_OR_LF_0, + CR_OR_LF_1, + STRICT_CRLF_0, + STRICT_CRLF_1, + FRAME_0, + } state_; - int data_seq_at_orig_data_end_; - bool eof_; - bool have_pending_request_; + int data_seq_at_orig_data_end_; + bool eof_; + bool have_pending_request_; - static Policy policy; - }; + static Policy policy; +}; typedef FlowBuffer* flow_buffer_t; - } // namespace binpac +} // namespace binpac #endif // binpac_buffer_h diff --git a/tools/binpac/lib/binpac_bytestring.cc b/tools/binpac/lib/binpac_bytestring.cc index 1bde160024..be34209d6c 100644 --- a/tools/binpac/lib/binpac_bytestring.cc +++ b/tools/binpac/lib/binpac_bytestring.cc @@ -4,22 +4,12 @@ #include -namespace binpac - { +namespace binpac { -std::string std_string(bytestring const* s) - { - return std::string((const char*)s->begin(), (const char*)s->end()); - } +std::string std_string(bytestring const* s) { return std::string((const char*)s->begin(), (const char*)s->end()); } -int bytestring_to_int(bytestring const* s) - { - return atoi((const char*)s->begin()); - } +int bytestring_to_int(bytestring const* s) { return atoi((const char*)s->begin()); } -double bytestring_to_double(bytestring const* s) - { - return atof((const char*)s->begin()); - } +double bytestring_to_double(bytestring const* s) { return atof((const char*)s->begin()); } - } // namespace binpac +} // namespace binpac diff --git a/tools/binpac/lib/binpac_bytestring.h b/tools/binpac/lib/binpac_bytestring.h index aba59c50fa..c9b856f655 100644 --- a/tools/binpac/lib/binpac_bytestring.h +++ b/tools/binpac/lib/binpac_bytestring.h @@ -6,155 +6,137 @@ #include "binpac.h" -namespace binpac - { +namespace binpac { -template class datastring; +template +class datastring; -template class const_datastring - { +template +class const_datastring { public: - const_datastring() : begin_(0), end_(0) { } + const_datastring() : begin_(0), end_(0) {} - const_datastring(T const* data, int length) : begin_(data), end_(data + length) { } + const_datastring(T const* data, int length) : begin_(data), end_(data + length) {} - const_datastring(const T* begin, const T* end) : begin_(begin), end_(end) { } + const_datastring(const T* begin, const T* end) : begin_(begin), end_(end) {} - const_datastring(datastring const& s) : begin_(s.begin()), end_(s.end()) { } + const_datastring(datastring const& s) : begin_(s.begin()), end_(s.end()) {} - void init(const T* data, int length) - { - begin_ = data; - end_ = data + length; - } + void init(const T* data, int length) { + begin_ = data; + end_ = data + length; + } - T const* begin() const { return begin_; } - T const* end() const { return end_; } - int length() const { return end_ - begin_; } + T const* begin() const { return begin_; } + T const* end() const { return end_; } + int length() const { return end_ - begin_; } - T const& operator[](int index) const { return begin()[index]; } + T const& operator[](int index) const { return begin()[index]; } - bool operator==(const_datastring const& s) - { - if ( length() != s.length() ) - return false; - return memcmp((const void*)begin(), (const void*)s.begin(), sizeof(T) * length()) == 0; - } + bool operator==(const_datastring const& s) { + if ( length() != s.length() ) + return false; + return memcmp((const void*)begin(), (const void*)s.begin(), sizeof(T) * length()) == 0; + } - void set_begin(T const* begin) { begin_ = begin; } - void set_end(T const* end) { end_ = end; } + void set_begin(T const* begin) { begin_ = begin; } + void set_end(T const* end) { end_ = end; } private: - T const* begin_; - T const* end_; - }; + T const* begin_; + T const* end_; +}; typedef const_datastring const_bytestring; -template class datastring - { +template +class datastring { public: - datastring() { clear(); } + datastring() { clear(); } - datastring(T* data, int len) { set(data, len); } + datastring(T* data, int len) { set(data, len); } - datastring(T const* begin, T const* end) { set_const(begin, end - begin); } + datastring(T const* begin, T const* end) { set_const(begin, end - begin); } - datastring(datastring const& x) : data_(x.data()), length_(x.length()) { } + datastring(datastring const& x) : data_(x.data()), length_(x.length()) {} - explicit datastring(const_datastring const& x) { set_const(x.begin(), x.length()); } + explicit datastring(const_datastring const& x) { set_const(x.begin(), x.length()); } - datastring const& operator=(datastring const& x) - { - BINPAC_ASSERT(! data_); - set(x.data(), x.length()); - return *this; - } + datastring const& operator=(datastring const& x) { + BINPAC_ASSERT(! data_); + set(x.data(), x.length()); + return *this; + } - void init(T const* begin, int length) - { - BINPAC_ASSERT(! data_); - set_const(begin, length); - } + void init(T const* begin, int length) { + BINPAC_ASSERT(! data_); + set_const(begin, length); + } - void clear() - { - data_ = 0; - length_ = 0; - } + void clear() { + data_ = 0; + length_ = 0; + } - void free() - { - if ( data_ ) - delete[] data_; - clear(); - } + void free() { + if ( data_ ) + delete[] data_; + clear(); + } - void clone() { set_const(begin(), length()); } + void clone() { set_const(begin(), length()); } - datastring const& operator=(const_datastring const& x) - { - BINPAC_ASSERT(! data_); - set_const(x.begin(), x.length()); - return *this; - } + datastring const& operator=(const_datastring const& x) { + BINPAC_ASSERT(! data_); + set_const(x.begin(), x.length()); + return *this; + } - T const& operator[](int index) const { return begin()[index]; } + T const& operator[](int index) const { return begin()[index]; } - T* data() const { return data_; } - int length() const { return length_; } + T* data() const { return data_; } + int length() const { return length_; } - T const* begin() const { return data_; } - T const* end() const { return data_ + length_; } + T const* begin() const { return data_; } + T const* end() const { return data_ + length_; } private: - void set(T* data, int len) - { - data_ = data; - length_ = len; - } + void set(T* data, int len) { + data_ = data; + length_ = len; + } - void set_const(T const* data, int len) - { - length_ = len; - data_ = new T[len + 1]; - memcpy(data_, data, sizeof(T) * len); - data_[len] = 0; - } + void set_const(T const* data, int len) { + length_ = len; + data_ = new T[len + 1]; + memcpy(data_, data, sizeof(T) * len); + data_[len] = 0; + } - T* data_; - int length_; - }; + T* data_; + int length_; +}; typedef datastring bytestring; -inline const char* c_str(bytestring const& s) - { - return (const char*)s.begin(); - } +inline const char* c_str(bytestring const& s) { return (const char*)s.begin(); } -inline std::string std_str(const_bytestring const& s) - { - return std::string((const char*)s.begin(), (const char*)s.end()); - } +inline std::string std_str(const_bytestring const& s) { + return std::string((const char*)s.begin(), (const char*)s.end()); +} -inline bool operator==(bytestring const& s1, const char* s2) - { - return strcmp(c_str(s1), s2) == 0; - } +inline bool operator==(bytestring const& s1, const char* s2) { return strcmp(c_str(s1), s2) == 0; } -inline void get_pointers(const_bytestring const& s, uint8 const** pbegin, uint8 const** pend) - { - *pbegin = s.begin(); - *pend = s.end(); - } +inline void get_pointers(const_bytestring const& s, uint8 const** pbegin, uint8 const** pend) { + *pbegin = s.begin(); + *pend = s.end(); +} -inline void get_pointers(bytestring const* s, uint8 const** pbegin, uint8 const** pend) - { - *pbegin = s->begin(); - *pend = s->end(); - } +inline void get_pointers(bytestring const* s, uint8 const** pbegin, uint8 const** pend) { + *pbegin = s->begin(); + *pend = s->end(); +} - } // namespace binpac +} // namespace binpac #endif // binpac_bytestring_h diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h index 3c9262d18f..6b4f57a718 100644 --- a/tools/binpac/lib/binpac_exception.h +++ b/tools/binpac/lib/binpac_exception.h @@ -4,117 +4,92 @@ #include #include -namespace binpac - { +namespace binpac { -class Exception - { +class Exception { public: - Exception(const char* m = 0) : msg_("binpac exception: ") - { - if ( m ) - append(m); - // abort(); - } + Exception(const char* m = 0) : msg_("binpac exception: ") { + if ( m ) + append(m); + // abort(); + } - void append(string m) { msg_ += m; } - string msg() const { return msg_; } - const char* c_msg() const { return msg_.c_str(); } + void append(string m) { msg_ += m; } + string msg() const { return msg_; } + const char* c_msg() const { return msg_.c_str(); } protected: - string msg_; - }; + string msg_; +}; -class ExceptionEnforceViolation : public Exception - { +class ExceptionEnforceViolation : public Exception { public: - ExceptionEnforceViolation(const char* where) - { - append(binpac_fmt("&enforce violation : %s", where)); - } - }; + ExceptionEnforceViolation(const char* where) { append(binpac_fmt("&enforce violation : %s", where)); } +}; -class ExceptionOutOfBound : public Exception - { +class ExceptionOutOfBound : public Exception { public: - ExceptionOutOfBound(const char* where, int len_needed, int len_given) - { - append(binpac_fmt("out_of_bound: %s: %d > %d", where, len_needed, len_given)); - } - }; + ExceptionOutOfBound(const char* where, int len_needed, int len_given) { + append(binpac_fmt("out_of_bound: %s: %d > %d", where, len_needed, len_given)); + } +}; -class ExceptionInvalidCase : public Exception - { +class ExceptionInvalidCase : public Exception { public: - ExceptionInvalidCase(const char* location, int64_t index, const char* expected) - : location_(location), index_(index), expected_(expected) - { - append(binpac_fmt("invalid case: %s: %" PRIi64 " (%s)", location, index, expected)); - } + ExceptionInvalidCase(const char* location, int64_t index, const char* expected) + : location_(location), index_(index), expected_(expected) { + append(binpac_fmt("invalid case: %s: %" PRIi64 " (%s)", location, index, expected)); + } protected: - const char* location_; - int64_t index_; - string expected_; - }; + const char* location_; + int64_t index_; + string expected_; +}; -class ExceptionInvalidCaseIndex : public Exception - { +class ExceptionInvalidCaseIndex : public Exception { public: - ExceptionInvalidCaseIndex(const char* location, int64_t index) - : location_(location), index_(index) - { - append(binpac_fmt("invalid index for case: %s: %" PRIi64, location, index)); - } + ExceptionInvalidCaseIndex(const char* location, int64_t index) : location_(location), index_(index) { + append(binpac_fmt("invalid index for case: %s: %" PRIi64, location, index)); + } protected: - const char* location_; - int64_t index_; - }; + const char* location_; + int64_t index_; +}; -class ExceptionInvalidOffset : public Exception - { +class ExceptionInvalidOffset : public Exception { public: - ExceptionInvalidOffset(const char* location, int min_offset, int offset) - : location_(location), min_offset_(min_offset), offset_(offset) - { - append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", location, min_offset, - offset)); - } + ExceptionInvalidOffset(const char* location, int min_offset, int offset) + : location_(location), min_offset_(min_offset), offset_(offset) { + append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", location, min_offset, offset)); + } protected: - const char* location_; - int min_offset_, offset_; - }; + const char* location_; + int min_offset_, offset_; +}; -class ExceptionStringMismatch : public Exception - { +class ExceptionStringMismatch : public Exception { public: - ExceptionStringMismatch(const char* location, const char* expected, const char* actual_data) - { - append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"", - location, expected, actual_data)); - } - }; + ExceptionStringMismatch(const char* location, const char* expected, const char* actual_data) { + append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"", location, expected, + actual_data)); + } +}; -class ExceptionInvalidStringLength : public Exception - { +class ExceptionInvalidStringLength : public Exception { public: - ExceptionInvalidStringLength(const char* location, int len) - { - append(binpac_fmt("invalid length string: %s: %d", location, len)); - } - }; + ExceptionInvalidStringLength(const char* location, int len) { + append(binpac_fmt("invalid length string: %s: %d", location, len)); + } +}; -class ExceptionFlowBufferAlloc : public Exception - { +class ExceptionFlowBufferAlloc : public Exception { public: - ExceptionFlowBufferAlloc(const char* reason) - { - append(binpac_fmt("flowbuffer allocation failed: %s", reason)); - } - }; + ExceptionFlowBufferAlloc(const char* reason) { append(binpac_fmt("flowbuffer allocation failed: %s", reason)); } +}; - } +} // namespace binpac #endif // binpac_exception_h diff --git a/tools/binpac/lib/binpac_regex.cc b/tools/binpac/lib/binpac_regex.cc index 38379623de..3fb146772b 100644 --- a/tools/binpac/lib/binpac_regex.cc +++ b/tools/binpac/lib/binpac_regex.cc @@ -1,11 +1,12 @@ #include -namespace zeek { class RE_Matcher; } +namespace zeek { +class RE_Matcher; +} -namespace binpac - { +namespace binpac { std::vector* uncompiled_re_matchers = nullptr; - } +} diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index 53c70e0f4e..d8e2a05c23 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -5,13 +5,11 @@ #include "binpac.h" -namespace zeek - { +namespace zeek { class RE_Matcher; - } +} -namespace binpac - { +namespace binpac { // Must be called before any binpac functionality is used. // @@ -23,58 +21,52 @@ inline void init(FlowBuffer::Policy* fbp = 0); // Internal vector recording not yet compiled matchers. extern std::vector* uncompiled_re_matchers; -class RegExMatcher - { +class RegExMatcher { public: - RegExMatcher(const char* pattern) : pattern_(pattern) - { - if ( ! uncompiled_re_matchers ) - uncompiled_re_matchers = new std::vector; + RegExMatcher(const char* pattern) : pattern_(pattern) { + if ( ! uncompiled_re_matchers ) + uncompiled_re_matchers = new std::vector; - re_matcher_ = new zeek::RE_Matcher(pattern_.c_str()); - uncompiled_re_matchers->push_back(re_matcher_); - } + re_matcher_ = new zeek::RE_Matcher(pattern_.c_str()); + uncompiled_re_matchers->push_back(re_matcher_); + } - ~RegExMatcher() { delete re_matcher_; } + ~RegExMatcher() { delete re_matcher_; } - // Returns the length of longest match, or -1 on mismatch. - int MatchPrefix(const_byteptr data, int len) { return re_matcher_->MatchPrefix(data, len); } + // Returns the length of longest match, or -1 on mismatch. + int MatchPrefix(const_byteptr data, int len) { return re_matcher_->MatchPrefix(data, len); } private: - friend void ::binpac::init(FlowBuffer::Policy*); + friend void ::binpac::init(FlowBuffer::Policy*); - // Function, and state, for compiling matchers. - static void init(); + // Function, and state, for compiling matchers. + static void init(); - string pattern_; - zeek::RE_Matcher* re_matcher_; - }; + string pattern_; + zeek::RE_Matcher* re_matcher_; +}; -inline void RegExMatcher::init() - { - if ( ! uncompiled_re_matchers ) - return; +inline void RegExMatcher::init() { + if ( ! uncompiled_re_matchers ) + return; - for ( size_t i = 0; i < uncompiled_re_matchers->size(); ++i ) - { - if ( ! (*uncompiled_re_matchers)[i]->Compile() ) - { - fprintf(stderr, "binpac: cannot compile regular expression\n"); - exit(1); - } - } + for ( size_t i = 0; i < uncompiled_re_matchers->size(); ++i ) { + if ( ! (*uncompiled_re_matchers)[i]->Compile() ) { + fprintf(stderr, "binpac: cannot compile regular expression\n"); + exit(1); + } + } - uncompiled_re_matchers->clear(); - } + uncompiled_re_matchers->clear(); +} -inline void init(FlowBuffer::Policy* fbp) - { - RegExMatcher::init(); +inline void init(FlowBuffer::Policy* fbp) { + RegExMatcher::init(); - if ( fbp ) - FlowBuffer::init(*fbp); - } + if ( fbp ) + FlowBuffer::init(*fbp); +} - } // namespace binpac +} // namespace binpac #endif // binpac_regex_h diff --git a/tools/binpac/src/pac_action.cc b/tools/binpac/src/pac_action.cc index 6a536184ee..05cd611029 100644 --- a/tools/binpac/src/pac_action.cc +++ b/tools/binpac/src/pac_action.cc @@ -9,93 +9,72 @@ #include "pac_utils.h" AnalyzerAction::AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code) - : AnalyzerElement(ACTION), action_id_(action_id), when_(when), param_(param), code_(code), - analyzer_(nullptr) - { - } + : AnalyzerElement(ACTION), action_id_(action_id), when_(when), param_(param), code_(code), analyzer_(nullptr) {} -AnalyzerAction::~AnalyzerAction() - { - delete action_id_; - delete param_; - delete code_; - } +AnalyzerAction::~AnalyzerAction() { + delete action_id_; + delete param_; + delete code_; +} -string AnalyzerAction::action_function() const - { - return strfmt("Action_%s", action_id_->Name()); - } +string AnalyzerAction::action_function() const { return strfmt("Action_%s", action_id_->Name()); } -void AnalyzerAction::InstallHook(AnalyzerDecl* analyzer) - { - ASSERT(0); - analyzer_ = analyzer; - // param_->MainDataType()->InstallAction(this); - } +void AnalyzerAction::InstallHook(AnalyzerDecl* analyzer) { + ASSERT(0); + analyzer_ = analyzer; + // param_->MainDataType()->InstallAction(this); +} -void AnalyzerAction::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) - { - Env action_func_env(decl->env(), this); - action_func_env.AddID(param_->id(), TEMP_VAR, param_->DataType()); - action_func_env.SetEvaluated(param_->id()); +void AnalyzerAction::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) { + Env action_func_env(decl->env(), this); + action_func_env.AddID(param_->id(), TEMP_VAR, param_->DataType()); + action_func_env.SetEvaluated(param_->id()); - string action_func_proto = strfmt("%s(%s)", action_function().c_str(), - ParamDecls(&action_func_env).c_str()); + string action_func_proto = strfmt("%s(%s)", action_function().c_str(), ParamDecls(&action_func_env).c_str()); - out_h->println("void %s;", action_func_proto.c_str()); + out_h->println("void %s;", action_func_proto.c_str()); - out_cc->println("void %s::%s", decl->class_name().c_str(), action_func_proto.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("void %s::%s", decl->class_name().c_str(), action_func_proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); - code_->GenCode(out_cc, &action_func_env); + code_->GenCode(out_cc, &action_func_env); - out_cc->println(""); - out_cc->println("}"); - out_cc->dec_indent(); - out_cc->println(""); - } + out_cc->println(""); + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); +} -string AnalyzerAction::ParamDecls(Env* env) const - { - return param_->DeclStr(env); - } +string AnalyzerAction::ParamDecls(Env* env) const { return param_->DeclStr(env); } -Type* ActionParam::MainDataType() const - { - // Note: this is not equal to DataType() - Type* main_type = TypeDecl::LookUpType(type()->type_id()); +Type* ActionParam::MainDataType() const { + // Note: this is not equal to DataType() + Type* main_type = TypeDecl::LookUpType(type()->type_id()); - if ( ! main_type ) - { - throw Exception(type()->type_id(), "type not defined"); - } + if ( ! main_type ) { + throw Exception(type()->type_id(), "type not defined"); + } - return main_type; - } + return main_type; +} -Type* ActionParam::DataType() const - { - Type* main_type = MainDataType(); +Type* ActionParam::DataType() const { + Type* main_type = MainDataType(); - if ( ! type()->field_id() ) - { - return main_type; - } - else - { - Type* member_type = main_type->MemberDataType(type()->field_id()); - if ( ! member_type ) - { - throw Exception(type()->field_id(), - strfmt("cannot find member type for `%s.%s'", type()->type_id()->Name(), - type()->field_id()->Name())); - } - return member_type; - } - } + if ( ! type()->field_id() ) { + return main_type; + } + else { + Type* member_type = main_type->MemberDataType(type()->field_id()); + if ( ! member_type ) { + throw Exception(type()->field_id(), strfmt("cannot find member type for `%s.%s'", type()->type_id()->Name(), + type()->field_id()->Name())); + } + return member_type; + } +} -string ActionParam::DeclStr(Env* env) const - { - return strfmt("%s %s", DataType()->DataTypeStr().c_str(), env->LValue(id())); - } +string ActionParam::DeclStr(Env* env) const { + return strfmt("%s %s", DataType()->DataTypeStr().c_str(), env->LValue(id())); +} diff --git a/tools/binpac/src/pac_action.h b/tools/binpac/src/pac_action.h index 9f2ffcd970..3e8d4357e1 100644 --- a/tools/binpac/src/pac_action.h +++ b/tools/binpac/src/pac_action.h @@ -6,71 +6,61 @@ #include "pac_analyzer.h" #include "pac_common.h" -class AnalyzerAction : public AnalyzerElement - { +class AnalyzerAction : public AnalyzerElement { public: - enum When - { - BEFORE, - AFTER - }; + enum When { BEFORE, AFTER }; - AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code); + AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code); - ~AnalyzerAction() override; + ~AnalyzerAction() override; - When when() const { return when_; } - ActionParam* param() const { return param_; } - AnalyzerDecl* analyzer() const { return analyzer_; } - string action_function() const; + When when() const { return when_; } + ActionParam* param() const { return param_; } + AnalyzerDecl* analyzer() const { return analyzer_; } + string action_function() const; - // Generate function prototype and code for the action - void GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl); + // Generate function prototype and code for the action + void GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl); - // Install the hook at the corresponding data type parsing - // function to invoke the action. - void InstallHook(AnalyzerDecl* analyzer); + // Install the hook at the corresponding data type parsing + // function to invoke the action. + void InstallHook(AnalyzerDecl* analyzer); private: - string ParamDecls(Env* env) const; + string ParamDecls(Env* env) const; - ID* action_id_; - When when_; - ActionParam* param_; - EmbeddedCode* code_; - AnalyzerDecl* analyzer_; - }; + ID* action_id_; + When when_; + ActionParam* param_; + EmbeddedCode* code_; + AnalyzerDecl* analyzer_; +}; -class ActionParam - { +class ActionParam { public: - ActionParam(const ID* id, ActionParamType* type) : id_(id), type_(type) { } + ActionParam(const ID* id, ActionParamType* type) : id_(id), type_(type) {} - const ID* id() const { return id_; } - ActionParamType* type() const { return type_; } + const ID* id() const { return id_; } + ActionParamType* type() const { return type_; } - Type* MainDataType() const; - Type* DataType() const; - string DeclStr(Env* env) const; + Type* MainDataType() const; + Type* DataType() const; + string DeclStr(Env* env) const; private: - const ID* id_; - ActionParamType* type_; - }; + const ID* id_; + ActionParamType* type_; +}; -class ActionParamType - { +class ActionParamType { public: - ActionParamType(const ID* type_id, const ID* field_id = 0) - : type_id_(type_id), field_id_(field_id) - { - } + ActionParamType(const ID* type_id, const ID* field_id = 0) : type_id_(type_id), field_id_(field_id) {} - const ID* type_id() const { return type_id_; } - const ID* field_id() const { return field_id_; } + const ID* type_id() const { return type_id_; } + const ID* field_id() const { return field_id_; } protected: - const ID *type_id_, *field_id_; - }; + const ID *type_id_, *field_id_; +}; #endif // pac_action_h diff --git a/tools/binpac/src/pac_analyzer.cc b/tools/binpac/src/pac_analyzer.cc index 3a3b5a7c7b..d404fa34d6 100644 --- a/tools/binpac/src/pac_analyzer.cc +++ b/tools/binpac/src/pac_analyzer.cc @@ -14,330 +14,250 @@ #include "pac_type.h" #include "pac_varfield.h" -AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params) - : TypeDecl(id, params, new DummyType()) - { - decl_type_ = decl_type; +AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params) : TypeDecl(id, params, new DummyType()) { + decl_type_ = decl_type; - statevars_ = new StateVarList(); - actions_ = new AnalyzerActionList(); - helpers_ = new AnalyzerHelperList(); - functions_ = new FunctionList(); + statevars_ = new StateVarList(); + actions_ = new AnalyzerActionList(); + helpers_ = new AnalyzerHelperList(); + functions_ = new FunctionList(); - constructor_helpers_ = new AnalyzerHelperList(); - destructor_helpers_ = new AnalyzerHelperList(); - eof_helpers_ = new AnalyzerHelperList(); + constructor_helpers_ = new AnalyzerHelperList(); + destructor_helpers_ = new AnalyzerHelperList(); + eof_helpers_ = new AnalyzerHelperList(); - SetAnalyzerContext(); + SetAnalyzerContext(); - env_ = nullptr; - } + env_ = nullptr; +} -AnalyzerDecl::~AnalyzerDecl() - { - delete_list(StateVarList, statevars_); - delete_list(AnalyzerActionList, actions_); - delete_list(AnalyzerHelperList, helpers_); - delete_list(FunctionList, functions_); - delete_list(ParamList, params_); - delete_list(AnalyzerHelperList, constructor_helpers_); - delete_list(AnalyzerHelperList, destructor_helpers_); - delete_list(AnalyzerHelperList, eof_helpers_); - } +AnalyzerDecl::~AnalyzerDecl() { + delete_list(StateVarList, statevars_); + delete_list(AnalyzerActionList, actions_); + delete_list(AnalyzerHelperList, helpers_); + delete_list(FunctionList, functions_); + delete_list(ParamList, params_); + delete_list(AnalyzerHelperList, constructor_helpers_); + delete_list(AnalyzerHelperList, destructor_helpers_); + delete_list(AnalyzerHelperList, eof_helpers_); +} -void AnalyzerDecl::AddElements(AnalyzerElementList* elemlist) - { - ASSERT(! env_); - foreach (i, AnalyzerElementList, elemlist) - { - AnalyzerElement* elem = *i; - switch ( elem->type() ) - { - case AnalyzerElement::STATE: - { - ASSERT(0); - AnalyzerState* state_elem = (AnalyzerState*)elem; - statevars_->insert(statevars_->end(), state_elem->statevars()->begin(), - state_elem->statevars()->end()); - } - break; - case AnalyzerElement::ACTION: - { - ASSERT(0); - AnalyzerAction* action_elem = (AnalyzerAction*)elem; - actions_->push_back(action_elem); - } - break; - case AnalyzerElement::HELPER: - { - AnalyzerHelper* helper_elem = (AnalyzerHelper*)elem; +void AnalyzerDecl::AddElements(AnalyzerElementList* elemlist) { + ASSERT(! env_); + foreach (i, AnalyzerElementList, elemlist) { + AnalyzerElement* elem = *i; + switch ( elem->type() ) { + case AnalyzerElement::STATE: { + ASSERT(0); + AnalyzerState* state_elem = (AnalyzerState*)elem; + statevars_->insert(statevars_->end(), state_elem->statevars()->begin(), state_elem->statevars()->end()); + } break; + case AnalyzerElement::ACTION: { + ASSERT(0); + AnalyzerAction* action_elem = (AnalyzerAction*)elem; + actions_->push_back(action_elem); + } break; + case AnalyzerElement::HELPER: { + AnalyzerHelper* helper_elem = (AnalyzerHelper*)elem; - switch ( helper_elem->helper_type() ) - { - case AnalyzerHelper::INIT_CODE: - constructor_helpers_->push_back(helper_elem); - break; - case AnalyzerHelper::CLEANUP_CODE: - destructor_helpers_->push_back(helper_elem); - break; - case AnalyzerHelper::EOF_CODE: - eof_helpers_->push_back(helper_elem); - break; - default: - helpers_->push_back(helper_elem); - } - } - break; - case AnalyzerElement::FUNCTION: - { - AnalyzerFunction* func_elem = (AnalyzerFunction*)elem; - Function* func = func_elem->function(); - func->set_analyzer_decl(this); - functions_->push_back(func); - } - break; - case AnalyzerElement::FLOW: - { - AnalyzerFlow* flow_elem = (AnalyzerFlow*)elem; - ProcessFlowElement(flow_elem); - } - break; - case AnalyzerElement::DATAUNIT: - { - AnalyzerDataUnit* dataunit_elem = (AnalyzerDataUnit*)elem; - ProcessDataUnitElement(dataunit_elem); - } - break; - } - } - } + switch ( helper_elem->helper_type() ) { + case AnalyzerHelper::INIT_CODE: constructor_helpers_->push_back(helper_elem); break; + case AnalyzerHelper::CLEANUP_CODE: destructor_helpers_->push_back(helper_elem); break; + case AnalyzerHelper::EOF_CODE: eof_helpers_->push_back(helper_elem); break; + default: helpers_->push_back(helper_elem); + } + } break; + case AnalyzerElement::FUNCTION: { + AnalyzerFunction* func_elem = (AnalyzerFunction*)elem; + Function* func = func_elem->function(); + func->set_analyzer_decl(this); + functions_->push_back(func); + } break; + case AnalyzerElement::FLOW: { + AnalyzerFlow* flow_elem = (AnalyzerFlow*)elem; + ProcessFlowElement(flow_elem); + } break; + case AnalyzerElement::DATAUNIT: { + AnalyzerDataUnit* dataunit_elem = (AnalyzerDataUnit*)elem; + ProcessDataUnitElement(dataunit_elem); + } break; + } + } +} -string AnalyzerDecl::class_name() const - { - return id_->Name(); - } +string AnalyzerDecl::class_name() const { return id_->Name(); } -void AnalyzerDecl::Prepare() - { - TypeDecl::Prepare(); +void AnalyzerDecl::Prepare() { + TypeDecl::Prepare(); - ASSERT(statevars_->empty()); - ASSERT(actions_->empty()); + ASSERT(statevars_->empty()); + ASSERT(actions_->empty()); - foreach (i, FunctionList, functions_) - { - Function* function = *i; - function->Prepare(env_); - } - foreach (i, StateVarList, statevars_) - { - StateVar* statevar = *i; - env_->AddID(statevar->id(), STATE_VAR, statevar->type()); - } - foreach (i, AnalyzerActionList, actions_) - { - AnalyzerAction* action = *i; - action->InstallHook(this); - } - } + foreach (i, FunctionList, functions_) { + Function* function = *i; + function->Prepare(env_); + } + foreach (i, StateVarList, statevars_) { + StateVar* statevar = *i; + env_->AddID(statevar->id(), STATE_VAR, statevar->type()); + } + foreach (i, AnalyzerActionList, actions_) { + AnalyzerAction* action = *i; + action->InstallHook(this); + } +} -void AnalyzerDecl::GenForwardDeclaration(Output* out_h) - { - out_h->println("class %s;", class_name().c_str()); - foreach (i, FunctionList, functions_) - { - Function* function = *i; - function->GenForwardDeclaration(out_h); - } - } +void AnalyzerDecl::GenForwardDeclaration(Output* out_h) { + out_h->println("class %s;", class_name().c_str()); + foreach (i, FunctionList, functions_) { + Function* function = *i; + function->GenForwardDeclaration(out_h); + } +} -void AnalyzerDecl::GenActions(Output* out_h, Output* out_cc) - { - foreach (i, AnalyzerActionList, actions_) - { - (*i)->GenCode(out_h, out_cc, this); - } - } +void AnalyzerDecl::GenActions(Output* out_h, Output* out_cc) { + foreach (i, AnalyzerActionList, actions_) { + (*i)->GenCode(out_h, out_cc, this); + } +} -void AnalyzerDecl::GenHelpers(Output* out_h, Output* out_cc) - { - foreach (i, AnalyzerHelperList, helpers_) - { - (*i)->GenCode(out_h, out_cc, this); - } - } +void AnalyzerDecl::GenHelpers(Output* out_h, Output* out_cc) { + foreach (i, AnalyzerHelperList, helpers_) { + (*i)->GenCode(out_h, out_cc, this); + } +} -void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc) - { - TypeDecl::GenPubDecls(out_h, out_cc); +void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc) { + TypeDecl::GenPubDecls(out_h, out_cc); - GenProcessFunc(out_h, out_cc); - GenGapFunc(out_h, out_cc); - GenEOFFunc(out_h, out_cc); - out_h->println(""); + GenProcessFunc(out_h, out_cc); + GenGapFunc(out_h, out_cc); + GenEOFFunc(out_h, out_cc); + out_h->println(""); - if ( ! functions_->empty() ) - { - out_h->println("// Functions"); - GenFunctions(out_h, out_cc); - out_h->println(""); - } + if ( ! functions_->empty() ) { + out_h->println("// Functions"); + GenFunctions(out_h, out_cc); + out_h->println(""); + } - // TODO: export public state variables - } + // TODO: export public state variables +} -void AnalyzerDecl::GenPrivDecls(Output* out_h, Output* out_cc) - { - TypeDecl::GenPrivDecls(out_h, out_cc); +void AnalyzerDecl::GenPrivDecls(Output* out_h, Output* out_cc) { + TypeDecl::GenPrivDecls(out_h, out_cc); - if ( ! helpers_->empty() ) - { - out_h->println(""); - out_h->println("// Additional members"); - GenHelpers(out_h, out_cc); - } + if ( ! helpers_->empty() ) { + out_h->println(""); + out_h->println("// Additional members"); + GenHelpers(out_h, out_cc); + } - // TODO: declare state variables - } + // TODO: declare state variables +} -void AnalyzerDecl::GenInitCode(Output* out_cc) - { - TypeDecl::GenInitCode(out_cc); - foreach (i, AnalyzerHelperList, constructor_helpers_) - { - (*i)->GenCode(nullptr, out_cc, this); - } - } +void AnalyzerDecl::GenInitCode(Output* out_cc) { + TypeDecl::GenInitCode(out_cc); + foreach (i, AnalyzerHelperList, constructor_helpers_) { + (*i)->GenCode(nullptr, out_cc, this); + } +} -void AnalyzerDecl::GenCleanUpCode(Output* out_cc) - { - TypeDecl::GenCleanUpCode(out_cc); - foreach (i, AnalyzerHelperList, destructor_helpers_) - { - (*i)->GenCode(nullptr, out_cc, this); - } - } +void AnalyzerDecl::GenCleanUpCode(Output* out_cc) { + TypeDecl::GenCleanUpCode(out_cc); + foreach (i, AnalyzerHelperList, destructor_helpers_) { + (*i)->GenCode(nullptr, out_cc, this); + } +} -void AnalyzerDecl::GenStateVarDecls(Output* out_h) - { - foreach (i, StateVarList, statevars_) - { - StateVar* var = *i; - var->GenDecl(out_h, env_); - } - } +void AnalyzerDecl::GenStateVarDecls(Output* out_h) { + foreach (i, StateVarList, statevars_) { + StateVar* var = *i; + var->GenDecl(out_h, env_); + } +} -void AnalyzerDecl::GenStateVarSetFunctions(Output* out_h) - { - foreach (i, StateVarList, statevars_) - { - StateVar* var = *i; - var->GenSetFunction(out_h, env_); - } - } +void AnalyzerDecl::GenStateVarSetFunctions(Output* out_h) { + foreach (i, StateVarList, statevars_) { + StateVar* var = *i; + var->GenSetFunction(out_h, env_); + } +} -void AnalyzerDecl::GenStateVarInitCode(Output* out_cc) - { - foreach (i, StateVarList, statevars_) - { - StateVar* var = *i; - var->GenInitCode(out_cc, env_); - } - } +void AnalyzerDecl::GenStateVarInitCode(Output* out_cc) { + foreach (i, StateVarList, statevars_) { + StateVar* var = *i; + var->GenInitCode(out_cc, env_); + } +} -void AnalyzerDecl::GenStateVarCleanUpCode(Output* out_cc) - { - foreach (i, StateVarList, statevars_) - { - StateVar* var = *i; - var->GenCleanUpCode(out_cc, env_); - } - } +void AnalyzerDecl::GenStateVarCleanUpCode(Output* out_cc) { + foreach (i, StateVarList, statevars_) { + StateVar* var = *i; + var->GenCleanUpCode(out_cc, env_); + } +} -void AnalyzerDecl::GenFunctions(Output* out_h, Output* out_cc) - { - foreach (i, FunctionList, functions_) - { - Function* function = *i; - function->GenCode(out_h, out_cc); - } - } +void AnalyzerDecl::GenFunctions(Output* out_h, Output* out_cc) { + foreach (i, FunctionList, functions_) { + Function* function = *i; + function->GenCode(out_h, out_cc); + } +} -AnalyzerState::~AnalyzerState() - { - // Note: do not delete elements of statevars_, because they - // are referenced by the AnalyzerDecl. - delete statevars_; - } +AnalyzerState::~AnalyzerState() { + // Note: do not delete elements of statevars_, because they + // are referenced by the AnalyzerDecl. + delete statevars_; +} -AnalyzerHelper::~AnalyzerHelper() - { - delete code_; - } +AnalyzerHelper::~AnalyzerHelper() { delete code_; } -void AnalyzerHelper::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) - { - Output* out = nullptr; - switch ( helper_type_ ) - { - case MEMBER_DECLS: - out = out_h; - break; - case INIT_CODE: - case CLEANUP_CODE: - case EOF_CODE: - out = out_cc; - break; - } - ASSERT(out); - code()->GenCode(out, decl->env()); - } +void AnalyzerHelper::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) { + Output* out = nullptr; + switch ( helper_type_ ) { + case MEMBER_DECLS: out = out_h; break; + case INIT_CODE: + case CLEANUP_CODE: + case EOF_CODE: out = out_cc; break; + } + ASSERT(out); + code()->GenCode(out, decl->env()); +} FlowField::FlowField(ID* flow_id, ParameterizedType* flow_type) - : Field(FLOW_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, flow_id, flow_type) - { - } + : Field(FLOW_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, flow_id, flow_type) {} -void FlowField::GenInitCode(Output* out_cc, Env* env) - { - type_->GenPreParsing(out_cc, env); - } +void FlowField::GenInitCode(Output* out_cc, Env* env) { type_->GenPreParsing(out_cc, env); } AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params) - : AnalyzerElement(FLOW), dir_(dir), type_id_(type_id) - { - if ( ! params ) - params = new ExprList(); + : AnalyzerElement(FLOW), dir_(dir), type_id_(type_id) { + if ( ! params ) + params = new ExprList(); - // Add "this" to the list of params - params->insert(params->begin(), new Expr(this_id->clone())); + // Add "this" to the list of params + params->insert(params->begin(), new Expr(this_id->clone())); - ID* flow_id = ((dir == UP) ? upflow_id : downflow_id)->clone(); + ID* flow_id = ((dir == UP) ? upflow_id : downflow_id)->clone(); - ParameterizedType* flow_type = new ParameterizedType(type_id_, params); + ParameterizedType* flow_type = new ParameterizedType(type_id_, params); - flow_field_ = new FlowField(flow_id, flow_type); + flow_field_ = new FlowField(flow_id, flow_type); - flow_decl_ = nullptr; - } + flow_decl_ = nullptr; +} -AnalyzerFlow::~AnalyzerFlow() - { - delete flow_field_; - } +AnalyzerFlow::~AnalyzerFlow() { delete flow_field_; } -FlowDecl* AnalyzerFlow::flow_decl() - { - DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name()); - if ( ! flow_decl_ ) - { - Decl* decl = Decl::LookUpDecl(type_id_); - if ( decl && decl->decl_type() == Decl::FLOW ) - flow_decl_ = static_cast(decl); - if ( ! flow_decl_ ) - { - throw Exception(this, "cannot find the flow declaration"); - } - } - return flow_decl_; - } +FlowDecl* AnalyzerFlow::flow_decl() { + DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name()); + if ( ! flow_decl_ ) { + Decl* decl = Decl::LookUpDecl(type_id_); + if ( decl && decl->decl_type() == Decl::FLOW ) + flow_decl_ = static_cast(decl); + if ( ! flow_decl_ ) { + throw Exception(this, "cannot find the flow declaration"); + } + } + return flow_decl_; +} diff --git a/tools/binpac/src/pac_analyzer.h b/tools/binpac/src/pac_analyzer.h index 8fa59db40a..671e2b030f 100644 --- a/tools/binpac/src/pac_analyzer.h +++ b/tools/binpac/src/pac_analyzer.h @@ -17,162 +17,141 @@ class FlowDecl; typedef vector AnalyzerHelperList; typedef vector FunctionList; -class AnalyzerDecl : public TypeDecl - { +class AnalyzerDecl : public TypeDecl { public: - AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params); - ~AnalyzerDecl() override; + AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params); + ~AnalyzerDecl() override; - void AddElements(AnalyzerElementList* elemlist); + void AddElements(AnalyzerElementList* elemlist); - void Prepare() override; - void GenForwardDeclaration(Output* out_h) override; - // void GenCode(Output *out_h, Output *out_cc); + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + // void GenCode(Output *out_h, Output *out_cc); - void GenInitCode(Output* out_cc) override; - void GenCleanUpCode(Output* out_cc) override; + void GenInitCode(Output* out_cc) override; + void GenCleanUpCode(Output* out_cc) override; - string class_name() const; - // string cookie_name() const; + string class_name() const; + // string cookie_name() const; protected: - virtual void ProcessFlowElement(AnalyzerFlow* flow_elem) = 0; - virtual void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) = 0; + virtual void ProcessFlowElement(AnalyzerFlow* flow_elem) = 0; + virtual void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) = 0; - // Generate public/private declarations for member functions and - // variables - void GenPubDecls(Output* out_h, Output* out_cc) override; - void GenPrivDecls(Output* out_h, Output* out_cc) override; + // Generate public/private declarations for member functions and + // variables + void GenPubDecls(Output* out_h, Output* out_cc) override; + void GenPrivDecls(Output* out_h, Output* out_cc) override; - // Generate the NewData() function - virtual void GenProcessFunc(Output* out_h, Output* out_cc) = 0; + // Generate the NewData() function + virtual void GenProcessFunc(Output* out_h, Output* out_cc) = 0; - // Generate the NewGap() function - virtual void GenGapFunc(Output* out_h, Output* out_cc) = 0; + // Generate the NewGap() function + virtual void GenGapFunc(Output* out_h, Output* out_cc) = 0; - // Generate the FlowEOF() function - virtual void GenEOFFunc(Output* out_h, Output* out_cc) = 0; + // Generate the FlowEOF() function + virtual void GenEOFFunc(Output* out_h, Output* out_cc) = 0; - // Generate the functions - void GenFunctions(Output* out_h, Output* out_cc); + // Generate the functions + void GenFunctions(Output* out_h, Output* out_cc); - // Generate the action functions - void GenActions(Output* out_h, Output* out_cc); + // Generate the action functions + void GenActions(Output* out_h, Output* out_cc); - // Generate the helper code segments - void GenHelpers(Output* out_h, Output* out_cc); + // Generate the helper code segments + void GenHelpers(Output* out_h, Output* out_cc); - // Generate declarations for state variables and their set functions - void GenStateVarDecls(Output* out_h); - void GenStateVarSetFunctions(Output* out_h); + // Generate declarations for state variables and their set functions + void GenStateVarDecls(Output* out_h); + void GenStateVarSetFunctions(Output* out_h); - // Generate code for initializing and cleaning up (including - // memory de-allocating) state variables - void GenStateVarInitCode(Output* out_cc); - void GenStateVarCleanUpCode(Output* out_cc); + // Generate code for initializing and cleaning up (including + // memory de-allocating) state variables + void GenStateVarInitCode(Output* out_cc); + void GenStateVarCleanUpCode(Output* out_cc); - StateVarList* statevars_; - AnalyzerActionList* actions_; - AnalyzerHelperList* helpers_; - FunctionList* functions_; + StateVarList* statevars_; + AnalyzerActionList* actions_; + AnalyzerHelperList* helpers_; + FunctionList* functions_; - AnalyzerHelperList* constructor_helpers_; - AnalyzerHelperList* destructor_helpers_; - AnalyzerHelperList* eof_helpers_; - }; + AnalyzerHelperList* constructor_helpers_; + AnalyzerHelperList* destructor_helpers_; + AnalyzerHelperList* eof_helpers_; +}; -class AnalyzerElement : public Object - { +class AnalyzerElement : public Object { public: - enum ElementType - { - STATE, - ACTION, - FUNCTION, - HELPER, - FLOW, - DATAUNIT - }; - AnalyzerElement(ElementType type) : type_(type) { } - virtual ~AnalyzerElement() { } + enum ElementType { STATE, ACTION, FUNCTION, HELPER, FLOW, DATAUNIT }; + AnalyzerElement(ElementType type) : type_(type) {} + virtual ~AnalyzerElement() {} - ElementType type() const { return type_; } + ElementType type() const { return type_; } private: - ElementType type_; - }; + ElementType type_; +}; // A collection of variables representing analyzer states. -class AnalyzerState : public AnalyzerElement - { +class AnalyzerState : public AnalyzerElement { public: - AnalyzerState(StateVarList* statevars) : AnalyzerElement(STATE), statevars_(statevars) { } - ~AnalyzerState() override; + AnalyzerState(StateVarList* statevars) : AnalyzerElement(STATE), statevars_(statevars) {} + ~AnalyzerState() override; - StateVarList* statevars() const { return statevars_; } + StateVarList* statevars() const { return statevars_; } private: - StateVarList* statevars_; - }; + StateVarList* statevars_; +}; // A collection of embedded C++ code -class AnalyzerHelper : public AnalyzerElement - { +class AnalyzerHelper : public AnalyzerElement { public: - enum Type - { - MEMBER_DECLS, - INIT_CODE, - CLEANUP_CODE, - EOF_CODE, - }; - AnalyzerHelper(Type helper_type, EmbeddedCode* code) - : AnalyzerElement(HELPER), helper_type_(helper_type), code_(code) - { - } - ~AnalyzerHelper() override; + enum Type { + MEMBER_DECLS, + INIT_CODE, + CLEANUP_CODE, + EOF_CODE, + }; + AnalyzerHelper(Type helper_type, EmbeddedCode* code) + : AnalyzerElement(HELPER), helper_type_(helper_type), code_(code) {} + ~AnalyzerHelper() override; - Type helper_type() const { return helper_type_; } + Type helper_type() const { return helper_type_; } - void GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl); + void GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl); - EmbeddedCode* code() const { return code_; } + EmbeddedCode* code() const { return code_; } private: - Type helper_type_; - EmbeddedCode* code_; - }; + Type helper_type_; + EmbeddedCode* code_; +}; // The type and parameters of (uni-directional) flows of a connection. -class FlowField : public Field - { +class FlowField : public Field { public: - FlowField(ID* flow_id, ParameterizedType* flow_type); - void GenInitCode(Output* out, Env* env) override; - }; + FlowField(ID* flow_id, ParameterizedType* flow_type); + void GenInitCode(Output* out, Env* env) override; +}; -class AnalyzerFlow : public AnalyzerElement - { +class AnalyzerFlow : public AnalyzerElement { public: - enum Direction - { - UP, - DOWN - }; - AnalyzerFlow(Direction dir, ID* type_id, ExprList* params); - ~AnalyzerFlow() override; + enum Direction { UP, DOWN }; + AnalyzerFlow(Direction dir, ID* type_id, ExprList* params); + ~AnalyzerFlow() override; - Direction dir() const { return dir_; } - FlowField* flow_field() const { return flow_field_; } + Direction dir() const { return dir_; } + FlowField* flow_field() const { return flow_field_; } - FlowDecl* flow_decl(); + FlowDecl* flow_decl(); private: - Direction dir_; - ID* type_id_; - FlowField* flow_field_; - FlowDecl* flow_decl_; - }; + Direction dir_; + ID* type_id_; + FlowField* flow_field_; + FlowDecl* flow_decl_; +}; #endif // pac_analyzer_h diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index 215fe37fd8..bf7710a7e4 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -11,705 +11,589 @@ #include "pac_utils.h" #include "pac_varfield.h" -ArrayType::ArrayType(Type* elemtype, Expr* length) - : Type(ARRAY), elemtype_(elemtype), length_(length) - { - init(); - - switch ( elemtype_->tot() ) - { - case BUILTIN: - case PARAMETERIZED: - case STRING: - case EXTERN: - break; - - case ARRAY: - case CASE: - case DUMMY: - case EMPTY: - case RECORD: - case UNDEF: - ASSERT(0); - break; - } - } - -void ArrayType::init() - { - arraylength_var_field_ = nullptr; - elem_it_var_field_ = nullptr; - elem_var_field_ = nullptr; - elem_dataptr_var_field_ = nullptr; - elem_input_var_field_ = nullptr; - - elem_dataptr_until_expr_ = nullptr; - - end_of_array_loop_label_ = "@@@"; - - vector_str_ = strfmt("vector<%s>", elemtype_->DataTypeStr().c_str()); - - datatype_str_ = strfmt("%s *", vector_str_.c_str()); - - attr_generic_until_expr_ = nullptr; - attr_until_element_expr_ = nullptr; - attr_until_input_expr_ = nullptr; - } - -ArrayType::~ArrayType() - { - delete arraylength_var_field_; - delete elem_it_var_field_; - delete elem_var_field_; - delete elem_dataptr_var_field_; - delete elem_input_var_field_; - - delete elem_dataptr_until_expr_; - } - -Type* ArrayType::DoClone() const - { - Type* elemtype = elemtype_->Clone(); - if ( ! elemtype ) - return nullptr; - return new ArrayType(elemtype, length_); - } - -bool ArrayType::DefineValueVar() const - { - return true; - } - -string ArrayType::DataTypeStr() const - { - return datatype_str_; - } - -Type* ArrayType::ElementDataType() const - { - return elemtype_; - } - -string ArrayType::EvalElement(const string& array, const string& index) const - { - if ( attr_transient_ ) - throw Exception(this, "cannot access element in &transient array"); - - return strfmt("(*(%s))[%s]", array.c_str(), index.c_str()); - } - -const ID* ArrayType::arraylength_var() const - { - return arraylength_var_field_ ? arraylength_var_field_->id() : nullptr; - } - -const ID* ArrayType::elem_it_var() const - { - return elem_it_var_field_ ? elem_it_var_field_->id() : nullptr; - } - -const ID* ArrayType::elem_var() const - { - return elem_var_field_ ? elem_var_field_->id() : nullptr; - } - -const ID* ArrayType::elem_dataptr_var() const - { - return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : nullptr; - } - -const ID* ArrayType::elem_input_var() const - { - return elem_input_var_field_ ? elem_input_var_field_->id() : nullptr; - } - -void ArrayType::ProcessAttr(Attr* a) - { - Type::ProcessAttr(a); - - switch ( a->type() ) - { - case ATTR_RESTOFDATA: - { - if ( elemtype_->StaticSize(env()) != 1 ) - { - throw Exception(elemtype_, "&restofdata can be applied" - " to only byte arrays"); - } - if ( length_ ) - { - throw Exception(length_, "&restofdata cannot be applied" - " to arrays with specified length"); - } - attr_restofdata_ = true; - // As the array automatically extends to the end of - // data, we do not have to check boundary. - SetBoundaryChecked(); - } - break; - - case ATTR_RESTOFFLOW: - attr_restofflow_ = true; - // TODO: handle &restofflow - break; - - case ATTR_UNTIL: - { - bool ref_element = a->expr()->HasReference(element_macro_id); - bool ref_input = a->expr()->HasReference(input_macro_id); - if ( ref_element && ref_input ) - { - throw Exception(a->expr(), "cannot reference both $element and $input " - "in the same &until---please separate them."); - } - - if ( ref_element ) - { - if ( attr_until_element_expr_ ) - { - throw Exception(a->expr(), "multiple &until on $element"); - } - attr_until_element_expr_ = a->expr(); - } - else if ( ref_input ) - { - if ( attr_until_input_expr_ ) - { - throw Exception(a->expr(), "multiple &until on $input"); - } - attr_until_input_expr_ = a->expr(); - } - else - { - if ( attr_generic_until_expr_ ) - { - throw Exception(a->expr(), "multiple &until condition"); - } - attr_generic_until_expr_ = a->expr(); - } - } - break; - - default: - break; - } - } - -void ArrayType::Prepare(Env* env, int flags) - { - if ( flags & TO_BE_PARSED ) - { - ID* arraylength_var = new ID(strfmt("%s__arraylength", value_var()->Name())); - ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name())); - ID* elem_it_var = new ID(strfmt("%s__it", elem_var->Name())); - - elem_var_field_ = new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_); - AddField(elem_var_field_); - - if ( incremental_parsing() ) - { - arraylength_var_field_ = new PrivVarField(arraylength_var, extern_type_int->Clone()); - elem_it_var_field_ = new PrivVarField(elem_it_var, extern_type_int->Clone()); - - AddField(arraylength_var_field_); - AddField(elem_it_var_field_); - } - else - { - arraylength_var_field_ = new TempVarField(arraylength_var, extern_type_int->Clone()); - elem_it_var_field_ = new TempVarField(elem_it_var, extern_type_int->Clone()); - - arraylength_var_field_->Prepare(env); - elem_it_var_field_->Prepare(env); - - // Add elem_dataptr_var only when not parsing incrementally - ID* elem_dataptr_var = new ID(strfmt("%s__dataptr", elem_var->Name())); - elem_dataptr_var_field_ = new TempVarField(elem_dataptr_var, - extern_type_const_byteptr->Clone()); - elem_dataptr_var_field_->Prepare(env); - - // until(dataptr >= end_of_data) - elem_dataptr_until_expr_ = new Expr(Expr::EXPR_GE, new Expr(elem_dataptr_var->clone()), - new Expr(end_of_data->clone())); - } - - if ( attr_until_input_expr_ ) - { - elemtype_->SetUntilCheck(this); - } - - end_of_array_loop_label_ = strfmt("end_of_%s", value_var()->Name()); - } - - Type::Prepare(env, flags); - } - -void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data) - { - if ( env->Evaluated(arraylength_var()) ) - return; - - if ( ! incremental_parsing() ) - { - arraylength_var_field_->GenTempDecls(out_cc, env); - // This is about to get initialized below, don't initialize it twice. - if ( ! length_ && ! attr_restofdata_ ) - arraylength_var_field_->GenInitCode(out_cc, env); - } - - if ( length_ ) - { - out_cc->println("%s = %s;", env->LValue(arraylength_var()), length_->EvalExpr(out_cc, env)); - - env->SetEvaluated(arraylength_var()); - - // Check negative array length - out_cc->println("if ( %s < 0 )", env->LValue(arraylength_var())); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); - out_cc->println(" %s, (%s) - (%s));", env->LValue(arraylength_var()), - env->RValue(end_of_data), env->RValue(begin_of_data)); - out_cc->println("}"); - out_cc->dec_indent(); - - int element_size; - - if ( elemtype_->StaticSize(env) == -1 ) - { - // Check for overlong array quantity. We cap it at the maximum - // array size (assume 1-byte elements * array length) as we can't - // possibly store more elements. e.g. this helps prevent - // user-controlled length fields from causing an excessive - // iteration and/or memory-allocation (for the array we'll be - // parsing into) unless they actually sent enough data to go along - // with it. Note that this check is *not* looking for whether the - // contents of the array will extend past the end of the data - // buffer. - out_cc->println("// Check array element quantity: %s", data_id_str_.c_str()); - element_size = 1; - } - else - { - // Boundary check the entire array if elements have static size. - out_cc->println("// Check bounds for static-size array: %s", data_id_str_.c_str()); - elemtype_->SetBoundaryChecked(); - element_size = elemtype_->StaticSize(env); - - if ( element_size == 0 ) - { - // If we know we have an array of empty elements, probably - // better to structure the parser as just a single empty - // field to avoid DoS vulnerability of allocating - // arbitrary number of empty records (i.e. cheap for them, - // but costly for us unless we have special optimization - // for this scenario to forgo the usual allocation). - throw Exception( - this, "using an array of known-to-be-empty elements is possibly a bad idea"); - } - } - - const char* array_ptr_expr = data.ptr_expr(); - string max_elements_available = strfmt("((%s - %s) / %d)", env->RValue(end_of_data), - array_ptr_expr, element_size); - - out_cc->println("if ( %s > %s )", env->RValue(arraylength_var()), - max_elements_available.c_str()); - out_cc->inc_indent(); - out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); - out_cc->println(" %s, (%s) - (%s));", env->RValue(arraylength_var()), - env->RValue(end_of_data), array_ptr_expr); - out_cc->dec_indent(); - } - else if ( attr_restofdata_ ) - { - ASSERT(elemtype_->StaticSize(env) == 1); - out_cc->println("%s = (%s) - (%s);", env->LValue(arraylength_var()), - env->RValue(end_of_data), data.ptr_expr()); - env->SetEvaluated(arraylength_var()); - } - } - -void ArrayType::GenPubDecls(Output* out_h, Env* env) - { - Type::GenPubDecls(out_h, env); - - if ( declared_as_type() ) - { - if ( attr_transient_ ) - throw Exception(this, "cannot access element in &transient array"); - - out_h->println("int size() const { return %s ? %s->size() : 0; }", - env->RValue(value_var()), env->RValue(value_var())); - out_h->println("%s operator[](int index) const { BINPAC_ASSERT(%s); return (*%s)[index]; }", - elemtype_->DataTypeConstRefStr().c_str(), env->RValue(value_var()), - env->RValue(value_var())); - } - } - -void ArrayType::GenPrivDecls(Output* out_h, Env* env) - { - ASSERT(elem_var_field_->type() == elemtype_); - ASSERT(elemtype_->value_var()); - Type::GenPrivDecls(out_h, env); - } - -void ArrayType::GenInitCode(Output* out_cc, Env* env) - { - // Do not initiate the array here - // out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); - out_cc->println("%s = nullptr;", lvalue()); - - Type::GenInitCode(out_cc, env); - if ( incremental_parsing() ) - { - out_cc->println("%s = -1;", env->LValue(elem_it_var())); - } - } - -void ArrayType::GenCleanUpCode(Output* out_cc, Env* env) - { - Type::GenCleanUpCode(out_cc, env); - if ( elemtype_->NeedsCleanUp() ) - { - if ( ! elem_var_field_ ) - { - ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name())); - elem_var_field_ = new ParseVarField(Field::NOT_CLASS_MEMBER, elem_var, elemtype_); - elem_var_field_->Prepare(env); - } - - out_cc->println("if ( %s )", env->RValue(value_var())); - out_cc->inc_indent(); - out_cc->println("{"); - - out_cc->println("for ( auto* %s : *%s )", env->LValue(elem_var()), - env->RValue(value_var())); - out_cc->inc_indent(); - out_cc->println("{"); - elemtype_->GenCleanUpCode(out_cc, env); - out_cc->println("}"); - out_cc->dec_indent(); - - out_cc->println("}"); - out_cc->dec_indent(); - } - out_cc->println("delete %s;", lvalue()); - } - -string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length) - { - string array_str; - - array_str = lvalue(); - if ( incremental_parsing() ) - { - out_cc->println("if ( %s < 0 )", env->LValue(elem_it_var())); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("// Initialize only once"); - out_cc->println("%s = 0;", env->LValue(elem_it_var())); - } - - out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); - - if ( known_array_length ) - { - out_cc->println("%s->reserve(%s);", lvalue(), env->RValue(arraylength_var())); - } - - if ( incremental_parsing() ) - { - out_cc->println("}"); - out_cc->dec_indent(); - } - - return array_str; - } - -void ArrayType::GenElementAssignment(Output* out_cc, Env* env, string const& array_str, - bool use_vector) - { - if ( attr_transient_ ) - { - // Just discard. - out_cc->println("delete %s;", env->LValue(elem_var())); - return; - } - - // Assign the element - if ( ! use_vector ) - { - out_cc->println("%s[%s] = %s;", array_str.c_str(), env->LValue(elem_it_var()), - env->LValue(elem_var())); - } - else - { - out_cc->println("%s->push_back(%s);", array_str.c_str(), env->LValue(elem_var())); - } - } - -void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) - { - GenArrayLength(out_cc, env, data); - - // Otherwise these variables are declared as member variables - if ( ! incremental_parsing() ) - { - // Declare and initialize temporary variables - elem_var_field_->GenInitCode(out_cc, env); - elem_it_var_field_->GenTempDecls(out_cc, env); - out_cc->println("%s = 0;", env->LValue(elem_it_var())); - env->SetEvaluated(elem_it_var()); - } - - /* - If the input length can be determined without parsing - individual elements, generate the boundary checking before - parsing (unless in the case of incremental parsing). - - There are two cases when the input length can be determined: - 1. The array has a static size; - 2. The array length can be computed before parsing and - each element is of constant size. - */ - - bool compute_size_var = false; - - if ( incremental_input() ) - { - // Do not compute size_var on incremental input - compute_size_var = false; - - if ( ! incremental_parsing() && - (StaticSize(env) >= 0 || - (env->Evaluated(arraylength_var()) && elemtype_->StaticSize(env) >= 0)) ) - { - GenBoundaryCheck(out_cc, env, data); - } - } - else - { - compute_size_var = AddSizeVar(out_cc, env); - } - - bool known_array_length = env->Evaluated(arraylength_var()); - string array_str = GenArrayInit(out_cc, env, known_array_length); - - bool use_vector = true; - - ASSERT(elem_it_var()); - - DataPtr elem_data(env, nullptr, 0); - - if ( elem_dataptr_var() ) - { - out_cc->println("const_byteptr %s = %s;", env->LValue(elem_dataptr_var()), data.ptr_expr()); - env->SetEvaluated(elem_dataptr_var()); - - elem_data = DataPtr(env, elem_dataptr_var(), 0); - } - - string for_condition = known_array_length ? strfmt("%s < %s", env->LValue(elem_it_var()), - env->RValue(arraylength_var())) - : "/* forever */"; - - out_cc->println("for (; %s; ++%s)", for_condition.c_str(), env->LValue(elem_it_var())); - out_cc->inc_indent(); - out_cc->println("{"); - - if ( attr_generic_until_expr_ ) - GenUntilCheck(out_cc, env, attr_generic_until_expr_, true); - - if ( elem_dataptr_var() ) - { - if ( length_ ) - { - // Array has a known-length expression like uint16[4] vs. uint16[]. - // Here, arriving at the end of the data buffer should not be a - // valid loop-termination condition (which is what the - // GenUntilCheck() call produces). Instead, rely on the loop - // counter to terminate iteration or else the parsing code - // generated for each element should throw an OOB exception if - // there's insufficient data in the buffer. - } - else - { - GenUntilCheck(out_cc, env, elem_dataptr_until_expr_, false); - } - } - - elemtype_->GenPreParsing(out_cc, env); - elemtype_->GenParseCode(out_cc, env, elem_data, flags); - - if ( incremental_parsing() ) - { - out_cc->println("if ( ! %s )", elemtype_->parsing_complete(env).c_str()); - out_cc->inc_indent(); - out_cc->println("goto %s;", kNeedMoreData); - out_cc->dec_indent(); - } - - GenElementAssignment(out_cc, env, array_str, use_vector); - - if ( elem_dataptr_var() ) - { - out_cc->println("%s += %s;", env->LValue(elem_dataptr_var()), - elemtype_->DataSize(nullptr, env, elem_data).c_str()); - out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(elem_dataptr_var()), - env->RValue(end_of_data)); - } - - if ( attr_until_element_expr_ ) - GenUntilCheck(out_cc, env, attr_until_element_expr_, false); - - if ( elemtype_->IsPointerType() ) - out_cc->println("%s = nullptr;", env->LValue(elem_var())); - - out_cc->println("}"); - out_cc->dec_indent(); - - out_cc->dec_indent(); - out_cc->println("%s: ;", end_of_array_loop_label_.c_str()); - out_cc->inc_indent(); - - if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) ) - { - // Compute the data size - out_cc->println("%s = %s - (%s);", env->LValue(size_var()), env->RValue(elem_dataptr_var()), - data.ptr_expr()); - env->SetEvaluated(size_var()); - } - } - -void ArrayType::GenUntilInputCheck(Output* out_cc, Env* env) - { - ID* elem_input_var_id = new ID(strfmt("%s__elem_input", value_var()->Name())); - elem_input_var_field_ = new TempVarField(elem_input_var_id, - extern_type_const_bytestring->Clone()); - elem_input_var_field_->Prepare(env); - - out_cc->println("%s %s(%s, %s);", extern_type_const_bytestring->DataTypeStr().c_str(), - env->LValue(elem_input_var()), env->RValue(begin_of_data), - env->RValue(end_of_data)); - env->SetEvaluated(elem_input_var()); - - GenUntilCheck(out_cc, env, attr_until_input_expr_, true); - } - -void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool delete_elem) - { - ASSERT(until_expr); - - Env check_env(env, this); - check_env.AddMacro(element_macro_id, new Expr(elem_var()->clone())); - if ( elem_input_var() ) - { - check_env.AddMacro(input_macro_id, new Expr(elem_input_var()->clone())); - } - - out_cc->println("// Check &until(%s)", until_expr->orig()); - out_cc->println("if ( %s )", until_expr->EvalExpr(out_cc, &check_env)); - out_cc->inc_indent(); - out_cc->println("{"); - if ( parsing_complete_var() ) - { - out_cc->println("%s = true;", env->LValue(parsing_complete_var())); - } - - if ( elemtype_->IsPointerType() ) - { - if ( delete_elem ) - elemtype_->GenCleanUpCode(out_cc, env); - else - out_cc->println("%s = nullptr;", env->LValue(elem_var())); - } - - out_cc->println("goto %s;", end_of_array_loop_label_.c_str()); - out_cc->println("}"); - out_cc->dec_indent(); - } - -void ArrayType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) - { - ASSERT(! incremental_input()); - DEBUG_MSG("Generating dynamic size for array `%s'\n", value_var()->Name()); - - int elem_w = elemtype_->StaticSize(env); - if ( elem_w >= 0 && ! attr_until_element_expr_ && ! attr_until_input_expr_ && - (length_ || attr_restofdata_) ) - { - // If the elements have a fixed size, - // we only need to compute the number of elements - bool compute_size_var = AddSizeVar(out_cc, env); - ASSERT(compute_size_var); - GenArrayLength(out_cc, env, data); - ASSERT(env->Evaluated(arraylength_var())); - out_cc->println("%s = %d * %s;", env->LValue(size_var()), elem_w, - env->RValue(arraylength_var())); - env->SetEvaluated(size_var()); - } - else - { - // Otherwise we need parse the array dynamically - GenParseCode(out_cc, env, data, 0); - } - } - -int ArrayType::StaticSize(Env* env) const - { - int num = 0; - - if ( ! length_ || ! length_->ConstFold(env, &num) ) - return -1; - - int elem_w = elemtype_->StaticSize(env); - if ( elem_w < 0 ) - return -1; - - DEBUG_MSG("static size of %s:%s = %d * %d\n", decl_id()->Name(), lvalue(), elem_w, num); - - return num * elem_w; - } - -void ArrayType::SetBoundaryChecked() - { - Type::SetBoundaryChecked(); - - if ( attr_length_expr_ ) - { - // When using &length on an array, only treat its elements as - // already-bounds-checked if they are a single byte in length. - if ( elemtype_->StaticSize(env()) == 1 ) - elemtype_->SetBoundaryChecked(); - - return; - } - - elemtype_->SetBoundaryChecked(); - } - -void ArrayType::DoMarkIncrementalInput() - { - elemtype_->MarkIncrementalInput(); - } - -bool ArrayType::RequiresAnalyzerContext() - { - return Type::RequiresAnalyzerContext() || (length_ && length_->RequiresAnalyzerContext()) || - elemtype_->RequiresAnalyzerContext(); - } - -bool ArrayType::DoTraverse(DataDepVisitor* visitor) - { - if ( ! Type::DoTraverse(visitor) ) - return false; - - if ( length_ && ! length_->Traverse(visitor) ) - return false; - - if ( ! elemtype_->Traverse(visitor) ) - return false; - - return true; - } +ArrayType::ArrayType(Type* elemtype, Expr* length) : Type(ARRAY), elemtype_(elemtype), length_(length) { + init(); + + switch ( elemtype_->tot() ) { + case BUILTIN: + case PARAMETERIZED: + case STRING: + case EXTERN: break; + + case ARRAY: + case CASE: + case DUMMY: + case EMPTY: + case RECORD: + case UNDEF: ASSERT(0); break; + } +} + +void ArrayType::init() { + arraylength_var_field_ = nullptr; + elem_it_var_field_ = nullptr; + elem_var_field_ = nullptr; + elem_dataptr_var_field_ = nullptr; + elem_input_var_field_ = nullptr; + + elem_dataptr_until_expr_ = nullptr; + + end_of_array_loop_label_ = "@@@"; + + vector_str_ = strfmt("vector<%s>", elemtype_->DataTypeStr().c_str()); + + datatype_str_ = strfmt("%s *", vector_str_.c_str()); + + attr_generic_until_expr_ = nullptr; + attr_until_element_expr_ = nullptr; + attr_until_input_expr_ = nullptr; +} + +ArrayType::~ArrayType() { + delete arraylength_var_field_; + delete elem_it_var_field_; + delete elem_var_field_; + delete elem_dataptr_var_field_; + delete elem_input_var_field_; + + delete elem_dataptr_until_expr_; +} + +Type* ArrayType::DoClone() const { + Type* elemtype = elemtype_->Clone(); + if ( ! elemtype ) + return nullptr; + return new ArrayType(elemtype, length_); +} + +bool ArrayType::DefineValueVar() const { return true; } + +string ArrayType::DataTypeStr() const { return datatype_str_; } + +Type* ArrayType::ElementDataType() const { return elemtype_; } + +string ArrayType::EvalElement(const string& array, const string& index) const { + if ( attr_transient_ ) + throw Exception(this, "cannot access element in &transient array"); + + return strfmt("(*(%s))[%s]", array.c_str(), index.c_str()); +} + +const ID* ArrayType::arraylength_var() const { return arraylength_var_field_ ? arraylength_var_field_->id() : nullptr; } + +const ID* ArrayType::elem_it_var() const { return elem_it_var_field_ ? elem_it_var_field_->id() : nullptr; } + +const ID* ArrayType::elem_var() const { return elem_var_field_ ? elem_var_field_->id() : nullptr; } + +const ID* ArrayType::elem_dataptr_var() const { + return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : nullptr; +} + +const ID* ArrayType::elem_input_var() const { return elem_input_var_field_ ? elem_input_var_field_->id() : nullptr; } + +void ArrayType::ProcessAttr(Attr* a) { + Type::ProcessAttr(a); + + switch ( a->type() ) { + case ATTR_RESTOFDATA: { + if ( elemtype_->StaticSize(env()) != 1 ) { + throw Exception(elemtype_, + "&restofdata can be applied" + " to only byte arrays"); + } + if ( length_ ) { + throw Exception(length_, + "&restofdata cannot be applied" + " to arrays with specified length"); + } + attr_restofdata_ = true; + // As the array automatically extends to the end of + // data, we do not have to check boundary. + SetBoundaryChecked(); + } break; + + case ATTR_RESTOFFLOW: + attr_restofflow_ = true; + // TODO: handle &restofflow + break; + + case ATTR_UNTIL: { + bool ref_element = a->expr()->HasReference(element_macro_id); + bool ref_input = a->expr()->HasReference(input_macro_id); + if ( ref_element && ref_input ) { + throw Exception(a->expr(), + "cannot reference both $element and $input " + "in the same &until---please separate them."); + } + + if ( ref_element ) { + if ( attr_until_element_expr_ ) { + throw Exception(a->expr(), "multiple &until on $element"); + } + attr_until_element_expr_ = a->expr(); + } + else if ( ref_input ) { + if ( attr_until_input_expr_ ) { + throw Exception(a->expr(), "multiple &until on $input"); + } + attr_until_input_expr_ = a->expr(); + } + else { + if ( attr_generic_until_expr_ ) { + throw Exception(a->expr(), "multiple &until condition"); + } + attr_generic_until_expr_ = a->expr(); + } + } break; + + default: break; + } +} + +void ArrayType::Prepare(Env* env, int flags) { + if ( flags & TO_BE_PARSED ) { + ID* arraylength_var = new ID(strfmt("%s__arraylength", value_var()->Name())); + ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name())); + ID* elem_it_var = new ID(strfmt("%s__it", elem_var->Name())); + + elem_var_field_ = new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_); + AddField(elem_var_field_); + + if ( incremental_parsing() ) { + arraylength_var_field_ = new PrivVarField(arraylength_var, extern_type_int->Clone()); + elem_it_var_field_ = new PrivVarField(elem_it_var, extern_type_int->Clone()); + + AddField(arraylength_var_field_); + AddField(elem_it_var_field_); + } + else { + arraylength_var_field_ = new TempVarField(arraylength_var, extern_type_int->Clone()); + elem_it_var_field_ = new TempVarField(elem_it_var, extern_type_int->Clone()); + + arraylength_var_field_->Prepare(env); + elem_it_var_field_->Prepare(env); + + // Add elem_dataptr_var only when not parsing incrementally + ID* elem_dataptr_var = new ID(strfmt("%s__dataptr", elem_var->Name())); + elem_dataptr_var_field_ = new TempVarField(elem_dataptr_var, extern_type_const_byteptr->Clone()); + elem_dataptr_var_field_->Prepare(env); + + // until(dataptr >= end_of_data) + elem_dataptr_until_expr_ = + new Expr(Expr::EXPR_GE, new Expr(elem_dataptr_var->clone()), new Expr(end_of_data->clone())); + } + + if ( attr_until_input_expr_ ) { + elemtype_->SetUntilCheck(this); + } + + end_of_array_loop_label_ = strfmt("end_of_%s", value_var()->Name()); + } + + Type::Prepare(env, flags); +} + +void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data) { + if ( env->Evaluated(arraylength_var()) ) + return; + + if ( ! incremental_parsing() ) { + arraylength_var_field_->GenTempDecls(out_cc, env); + // This is about to get initialized below, don't initialize it twice. + if ( ! length_ && ! attr_restofdata_ ) + arraylength_var_field_->GenInitCode(out_cc, env); + } + + if ( length_ ) { + out_cc->println("%s = %s;", env->LValue(arraylength_var()), length_->EvalExpr(out_cc, env)); + + env->SetEvaluated(arraylength_var()); + + // Check negative array length + out_cc->println("if ( %s < 0 )", env->LValue(arraylength_var())); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); + out_cc->println(" %s, (%s) - (%s));", env->LValue(arraylength_var()), env->RValue(end_of_data), + env->RValue(begin_of_data)); + out_cc->println("}"); + out_cc->dec_indent(); + + int element_size; + + if ( elemtype_->StaticSize(env) == -1 ) { + // Check for overlong array quantity. We cap it at the maximum + // array size (assume 1-byte elements * array length) as we can't + // possibly store more elements. e.g. this helps prevent + // user-controlled length fields from causing an excessive + // iteration and/or memory-allocation (for the array we'll be + // parsing into) unless they actually sent enough data to go along + // with it. Note that this check is *not* looking for whether the + // contents of the array will extend past the end of the data + // buffer. + out_cc->println("// Check array element quantity: %s", data_id_str_.c_str()); + element_size = 1; + } + else { + // Boundary check the entire array if elements have static size. + out_cc->println("// Check bounds for static-size array: %s", data_id_str_.c_str()); + elemtype_->SetBoundaryChecked(); + element_size = elemtype_->StaticSize(env); + + if ( element_size == 0 ) { + // If we know we have an array of empty elements, probably + // better to structure the parser as just a single empty + // field to avoid DoS vulnerability of allocating + // arbitrary number of empty records (i.e. cheap for them, + // but costly for us unless we have special optimization + // for this scenario to forgo the usual allocation). + throw Exception(this, "using an array of known-to-be-empty elements is possibly a bad idea"); + } + } + + const char* array_ptr_expr = data.ptr_expr(); + string max_elements_available = + strfmt("((%s - %s) / %d)", env->RValue(end_of_data), array_ptr_expr, element_size); + + out_cc->println("if ( %s > %s )", env->RValue(arraylength_var()), max_elements_available.c_str()); + out_cc->inc_indent(); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); + out_cc->println(" %s, (%s) - (%s));", env->RValue(arraylength_var()), env->RValue(end_of_data), + array_ptr_expr); + out_cc->dec_indent(); + } + else if ( attr_restofdata_ ) { + ASSERT(elemtype_->StaticSize(env) == 1); + out_cc->println("%s = (%s) - (%s);", env->LValue(arraylength_var()), env->RValue(end_of_data), data.ptr_expr()); + env->SetEvaluated(arraylength_var()); + } +} + +void ArrayType::GenPubDecls(Output* out_h, Env* env) { + Type::GenPubDecls(out_h, env); + + if ( declared_as_type() ) { + if ( attr_transient_ ) + throw Exception(this, "cannot access element in &transient array"); + + out_h->println("int size() const { return %s ? %s->size() : 0; }", env->RValue(value_var()), + env->RValue(value_var())); + out_h->println("%s operator[](int index) const { BINPAC_ASSERT(%s); return (*%s)[index]; }", + elemtype_->DataTypeConstRefStr().c_str(), env->RValue(value_var()), env->RValue(value_var())); + } +} + +void ArrayType::GenPrivDecls(Output* out_h, Env* env) { + ASSERT(elem_var_field_->type() == elemtype_); + ASSERT(elemtype_->value_var()); + Type::GenPrivDecls(out_h, env); +} + +void ArrayType::GenInitCode(Output* out_cc, Env* env) { + // Do not initiate the array here + // out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); + out_cc->println("%s = nullptr;", lvalue()); + + Type::GenInitCode(out_cc, env); + if ( incremental_parsing() ) { + out_cc->println("%s = -1;", env->LValue(elem_it_var())); + } +} + +void ArrayType::GenCleanUpCode(Output* out_cc, Env* env) { + Type::GenCleanUpCode(out_cc, env); + if ( elemtype_->NeedsCleanUp() ) { + if ( ! elem_var_field_ ) { + ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name())); + elem_var_field_ = new ParseVarField(Field::NOT_CLASS_MEMBER, elem_var, elemtype_); + elem_var_field_->Prepare(env); + } + + out_cc->println("if ( %s )", env->RValue(value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + + out_cc->println("for ( auto* %s : *%s )", env->LValue(elem_var()), env->RValue(value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + elemtype_->GenCleanUpCode(out_cc, env); + out_cc->println("}"); + out_cc->dec_indent(); + + out_cc->println("}"); + out_cc->dec_indent(); + } + out_cc->println("delete %s;", lvalue()); +} + +string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length) { + string array_str; + + array_str = lvalue(); + if ( incremental_parsing() ) { + out_cc->println("if ( %s < 0 )", env->LValue(elem_it_var())); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("// Initialize only once"); + out_cc->println("%s = 0;", env->LValue(elem_it_var())); + } + + out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); + + if ( known_array_length ) { + out_cc->println("%s->reserve(%s);", lvalue(), env->RValue(arraylength_var())); + } + + if ( incremental_parsing() ) { + out_cc->println("}"); + out_cc->dec_indent(); + } + + return array_str; +} + +void ArrayType::GenElementAssignment(Output* out_cc, Env* env, string const& array_str, bool use_vector) { + if ( attr_transient_ ) { + // Just discard. + out_cc->println("delete %s;", env->LValue(elem_var())); + return; + } + + // Assign the element + if ( ! use_vector ) { + out_cc->println("%s[%s] = %s;", array_str.c_str(), env->LValue(elem_it_var()), env->LValue(elem_var())); + } + else { + out_cc->println("%s->push_back(%s);", array_str.c_str(), env->LValue(elem_var())); + } +} + +void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { + GenArrayLength(out_cc, env, data); + + // Otherwise these variables are declared as member variables + if ( ! incremental_parsing() ) { + // Declare and initialize temporary variables + elem_var_field_->GenInitCode(out_cc, env); + elem_it_var_field_->GenTempDecls(out_cc, env); + out_cc->println("%s = 0;", env->LValue(elem_it_var())); + env->SetEvaluated(elem_it_var()); + } + + /* + If the input length can be determined without parsing + individual elements, generate the boundary checking before + parsing (unless in the case of incremental parsing). + + There are two cases when the input length can be determined: + 1. The array has a static size; + 2. The array length can be computed before parsing and + each element is of constant size. + */ + + bool compute_size_var = false; + + if ( incremental_input() ) { + // Do not compute size_var on incremental input + compute_size_var = false; + + if ( ! incremental_parsing() && + (StaticSize(env) >= 0 || (env->Evaluated(arraylength_var()) && elemtype_->StaticSize(env) >= 0)) ) { + GenBoundaryCheck(out_cc, env, data); + } + } + else { + compute_size_var = AddSizeVar(out_cc, env); + } + + bool known_array_length = env->Evaluated(arraylength_var()); + string array_str = GenArrayInit(out_cc, env, known_array_length); + + bool use_vector = true; + + ASSERT(elem_it_var()); + + DataPtr elem_data(env, nullptr, 0); + + if ( elem_dataptr_var() ) { + out_cc->println("const_byteptr %s = %s;", env->LValue(elem_dataptr_var()), data.ptr_expr()); + env->SetEvaluated(elem_dataptr_var()); + + elem_data = DataPtr(env, elem_dataptr_var(), 0); + } + + string for_condition = known_array_length ? + strfmt("%s < %s", env->LValue(elem_it_var()), env->RValue(arraylength_var())) : + "/* forever */"; + + out_cc->println("for (; %s; ++%s)", for_condition.c_str(), env->LValue(elem_it_var())); + out_cc->inc_indent(); + out_cc->println("{"); + + if ( attr_generic_until_expr_ ) + GenUntilCheck(out_cc, env, attr_generic_until_expr_, true); + + if ( elem_dataptr_var() ) { + if ( length_ ) { + // Array has a known-length expression like uint16[4] vs. uint16[]. + // Here, arriving at the end of the data buffer should not be a + // valid loop-termination condition (which is what the + // GenUntilCheck() call produces). Instead, rely on the loop + // counter to terminate iteration or else the parsing code + // generated for each element should throw an OOB exception if + // there's insufficient data in the buffer. + } + else { + GenUntilCheck(out_cc, env, elem_dataptr_until_expr_, false); + } + } + + elemtype_->GenPreParsing(out_cc, env); + elemtype_->GenParseCode(out_cc, env, elem_data, flags); + + if ( incremental_parsing() ) { + out_cc->println("if ( ! %s )", elemtype_->parsing_complete(env).c_str()); + out_cc->inc_indent(); + out_cc->println("goto %s;", kNeedMoreData); + out_cc->dec_indent(); + } + + GenElementAssignment(out_cc, env, array_str, use_vector); + + if ( elem_dataptr_var() ) { + out_cc->println("%s += %s;", env->LValue(elem_dataptr_var()), + elemtype_->DataSize(nullptr, env, elem_data).c_str()); + out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(elem_dataptr_var()), env->RValue(end_of_data)); + } + + if ( attr_until_element_expr_ ) + GenUntilCheck(out_cc, env, attr_until_element_expr_, false); + + if ( elemtype_->IsPointerType() ) + out_cc->println("%s = nullptr;", env->LValue(elem_var())); + + out_cc->println("}"); + out_cc->dec_indent(); + + out_cc->dec_indent(); + out_cc->println("%s: ;", end_of_array_loop_label_.c_str()); + out_cc->inc_indent(); + + if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) ) { + // Compute the data size + out_cc->println("%s = %s - (%s);", env->LValue(size_var()), env->RValue(elem_dataptr_var()), data.ptr_expr()); + env->SetEvaluated(size_var()); + } +} + +void ArrayType::GenUntilInputCheck(Output* out_cc, Env* env) { + ID* elem_input_var_id = new ID(strfmt("%s__elem_input", value_var()->Name())); + elem_input_var_field_ = new TempVarField(elem_input_var_id, extern_type_const_bytestring->Clone()); + elem_input_var_field_->Prepare(env); + + out_cc->println("%s %s(%s, %s);", extern_type_const_bytestring->DataTypeStr().c_str(), + env->LValue(elem_input_var()), env->RValue(begin_of_data), env->RValue(end_of_data)); + env->SetEvaluated(elem_input_var()); + + GenUntilCheck(out_cc, env, attr_until_input_expr_, true); +} + +void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool delete_elem) { + ASSERT(until_expr); + + Env check_env(env, this); + check_env.AddMacro(element_macro_id, new Expr(elem_var()->clone())); + if ( elem_input_var() ) { + check_env.AddMacro(input_macro_id, new Expr(elem_input_var()->clone())); + } + + out_cc->println("// Check &until(%s)", until_expr->orig()); + out_cc->println("if ( %s )", until_expr->EvalExpr(out_cc, &check_env)); + out_cc->inc_indent(); + out_cc->println("{"); + if ( parsing_complete_var() ) { + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); + } + + if ( elemtype_->IsPointerType() ) { + if ( delete_elem ) + elemtype_->GenCleanUpCode(out_cc, env); + else + out_cc->println("%s = nullptr;", env->LValue(elem_var())); + } + + out_cc->println("goto %s;", end_of_array_loop_label_.c_str()); + out_cc->println("}"); + out_cc->dec_indent(); +} + +void ArrayType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { + ASSERT(! incremental_input()); + DEBUG_MSG("Generating dynamic size for array `%s'\n", value_var()->Name()); + + int elem_w = elemtype_->StaticSize(env); + if ( elem_w >= 0 && ! attr_until_element_expr_ && ! attr_until_input_expr_ && (length_ || attr_restofdata_) ) { + // If the elements have a fixed size, + // we only need to compute the number of elements + bool compute_size_var = AddSizeVar(out_cc, env); + ASSERT(compute_size_var); + GenArrayLength(out_cc, env, data); + ASSERT(env->Evaluated(arraylength_var())); + out_cc->println("%s = %d * %s;", env->LValue(size_var()), elem_w, env->RValue(arraylength_var())); + env->SetEvaluated(size_var()); + } + else { + // Otherwise we need parse the array dynamically + GenParseCode(out_cc, env, data, 0); + } +} + +int ArrayType::StaticSize(Env* env) const { + int num = 0; + + if ( ! length_ || ! length_->ConstFold(env, &num) ) + return -1; + + int elem_w = elemtype_->StaticSize(env); + if ( elem_w < 0 ) + return -1; + + DEBUG_MSG("static size of %s:%s = %d * %d\n", decl_id()->Name(), lvalue(), elem_w, num); + + return num * elem_w; +} + +void ArrayType::SetBoundaryChecked() { + Type::SetBoundaryChecked(); + + if ( attr_length_expr_ ) { + // When using &length on an array, only treat its elements as + // already-bounds-checked if they are a single byte in length. + if ( elemtype_->StaticSize(env()) == 1 ) + elemtype_->SetBoundaryChecked(); + + return; + } + + elemtype_->SetBoundaryChecked(); +} + +void ArrayType::DoMarkIncrementalInput() { elemtype_->MarkIncrementalInput(); } + +bool ArrayType::RequiresAnalyzerContext() { + return Type::RequiresAnalyzerContext() || (length_ && length_->RequiresAnalyzerContext()) || + elemtype_->RequiresAnalyzerContext(); +} + +bool ArrayType::DoTraverse(DataDepVisitor* visitor) { + if ( ! Type::DoTraverse(visitor) ) + return false; + + if ( length_ && ! length_->Traverse(visitor) ) + return false; + + if ( ! elemtype_->Traverse(visitor) ) + return false; + + return true; +} diff --git a/tools/binpac/src/pac_array.h b/tools/binpac/src/pac_array.h index 01c8deeee5..2baadc840f 100644 --- a/tools/binpac/src/pac_array.h +++ b/tools/binpac/src/pac_array.h @@ -6,82 +6,81 @@ // Fixed-length array and variable length sequence with an ending pattern -class ArrayType : public Type - { +class ArrayType : public Type { public: - ArrayType(Type* arg_elemtype, Expr* arg_length = nullptr); - ~ArrayType() override; + ArrayType(Type* arg_elemtype, Expr* arg_length = nullptr); + ~ArrayType() override; - bool DefineValueVar() const override; - string DataTypeStr() const override; - string DefaultValue() const override { return "0"; } - Type* ElementDataType() const override; + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override { return "0"; } + Type* ElementDataType() const override; - string EvalElement(const string& array, const string& index) const override; + string EvalElement(const string& array, const string& index) const override; - void ProcessAttr(Attr* a) override; + void ProcessAttr(Attr* a) override; - void Prepare(Env* env, int flags) override; + void Prepare(Env* env, int flags) override; - void GenPubDecls(Output* out, Env* env) override; - void GenPrivDecls(Output* out, Env* env) override; + void GenPubDecls(Output* out, Env* env) override; + void GenPrivDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env) override; - void GenCleanUpCode(Output* out, Env* env) override; + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; - int StaticSize(Env* env) const override; + int StaticSize(Env* env) const override; - void SetBoundaryChecked() override; - void GenUntilInputCheck(Output* out_cc, Env* env); + void SetBoundaryChecked() override; + void GenUntilInputCheck(Output* out_cc, Env* env); - bool IsPointerType() const override { return true; } + bool IsPointerType() const override { return true; } protected: - void init(); + void init(); - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; - void GenArrayLength(Output* out_cc, Env* env, const DataPtr& data); - string GenArrayInit(Output* out_cc, Env* env, bool known_array_length); - void GenElementAssignment(Output* out_cc, Env* env, string const& array_str, bool use_vector); - void GenUntilCheck(Output* out_cc, Env* env, Expr* until_condition, bool delete_elem); + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; + void GenArrayLength(Output* out_cc, Env* env, const DataPtr& data); + string GenArrayInit(Output* out_cc, Env* env, bool known_array_length); + void GenElementAssignment(Output* out_cc, Env* env, string const& array_str, bool use_vector); + void GenUntilCheck(Output* out_cc, Env* env, Expr* until_condition, bool delete_elem); - bool ByteOrderSensitive() const override { return elemtype_->RequiresByteOrder(); } - bool RequiresAnalyzerContext() override; + bool ByteOrderSensitive() const override { return elemtype_->RequiresByteOrder(); } + bool RequiresAnalyzerContext() override; - Type* DoClone() const override; + Type* DoClone() const override; - void DoMarkIncrementalInput() override; + void DoMarkIncrementalInput() override; - const ID* arraylength_var() const; - const ID* elem_it_var() const; - const ID* elem_var() const; - const ID* elem_dataptr_var() const; - const ID* elem_input_var() const; + const ID* arraylength_var() const; + const ID* elem_it_var() const; + const ID* elem_var() const; + const ID* elem_dataptr_var() const; + const ID* elem_input_var() const; protected: - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; private: - Type* elemtype_; - Expr* length_; + Type* elemtype_; + Expr* length_; - string vector_str_; - string datatype_str_; - string end_of_array_loop_label_; + string vector_str_; + string datatype_str_; + string end_of_array_loop_label_; - Field* arraylength_var_field_; - Field* elem_it_var_field_; - Field* elem_var_field_; - Field* elem_dataptr_var_field_; - Field* elem_input_var_field_; + Field* arraylength_var_field_; + Field* elem_it_var_field_; + Field* elem_var_field_; + Field* elem_dataptr_var_field_; + Field* elem_input_var_field_; - // This does not come from &until, but is internally generated - Expr* elem_dataptr_until_expr_; + // This does not come from &until, but is internally generated + Expr* elem_dataptr_until_expr_; - Expr* attr_generic_until_expr_; - Expr* attr_until_element_expr_; - Expr* attr_until_input_expr_; - }; + Expr* attr_generic_until_expr_; + Expr* attr_until_element_expr_; + Expr* attr_until_input_expr_; +}; #endif // pac_array_h diff --git a/tools/binpac/src/pac_attr.cc b/tools/binpac/src/pac_attr.cc index b4ba16e37c..858f5051ce 100644 --- a/tools/binpac/src/pac_attr.cc +++ b/tools/binpac/src/pac_attr.cc @@ -2,60 +2,47 @@ #include "pac_expr.h" -bool Attr::DoTraverse(DataDepVisitor* visitor) - { - if ( expr_ && ! expr_->Traverse(visitor) ) - return false; - return true; - } +bool Attr::DoTraverse(DataDepVisitor* visitor) { + if ( expr_ && ! expr_->Traverse(visitor) ) + return false; + return true; +} -bool Attr::RequiresAnalyzerContext() const - { - return (expr_ && expr_->RequiresAnalyzerContext()); - } +bool Attr::RequiresAnalyzerContext() const { return (expr_ && expr_->RequiresAnalyzerContext()); } -void Attr::init() - { - expr_ = nullptr; - seqend_ = nullptr; - delete_expr_ = false; - } +void Attr::init() { + expr_ = nullptr; + seqend_ = nullptr; + delete_expr_ = false; +} -Attr::Attr(AttrType type) : DataDepElement(DataDepElement::ATTR) - { - type_ = type; - init(); - } +Attr::Attr(AttrType type) : DataDepElement(DataDepElement::ATTR) { + type_ = type; + init(); +} -Attr::Attr(AttrType type, Expr* expr) : DataDepElement(DataDepElement::ATTR) - { - type_ = type; - init(); - expr_ = expr; - } +Attr::Attr(AttrType type, Expr* expr) : DataDepElement(DataDepElement::ATTR) { + type_ = type; + init(); + expr_ = expr; +} -Attr::Attr(AttrType type, ExprList* exprlist) : DataDepElement(DataDepElement::ATTR) - { - type_ = type; - init(); - expr_ = new Expr(exprlist); - delete_expr_ = true; - } +Attr::Attr(AttrType type, ExprList* exprlist) : DataDepElement(DataDepElement::ATTR) { + type_ = type; + init(); + expr_ = new Expr(exprlist); + delete_expr_ = true; +} -Attr::Attr(AttrType type, SeqEnd* seqend) : DataDepElement(DataDepElement::ATTR) - { - type_ = type; - init(); - seqend_ = seqend; - } +Attr::Attr(AttrType type, SeqEnd* seqend) : DataDepElement(DataDepElement::ATTR) { + type_ = type; + init(); + seqend_ = seqend; +} -Attr::~Attr() - { - if ( delete_expr_ ) - delete expr_; - } +Attr::~Attr() { + if ( delete_expr_ ) + delete expr_; +} -LetAttr::LetAttr(FieldList* letfields) : Attr(ATTR_LET) - { - letfields_ = letfields; - } +LetAttr::LetAttr(FieldList* letfields) : Attr(ATTR_LET) { letfields_ = letfields; } diff --git a/tools/binpac/src/pac_attr.h b/tools/binpac/src/pac_attr.h index e0fab09051..1b6a0d8321 100644 --- a/tools/binpac/src/pac_attr.h +++ b/tools/binpac/src/pac_attr.h @@ -4,63 +4,60 @@ #include "pac_common.h" #include "pac_datadep.h" -enum AttrType - { - ATTR_BYTEORDER, - ATTR_CHECK, - ATTR_CHUNKED, - ATTR_ENFORCE, - ATTR_EXPORTSOURCEDATA, - ATTR_IF, - ATTR_LENGTH, - ATTR_LET, - ATTR_LINEBREAKER, - ATTR_MULTILINE, - ATTR_ONELINE, - ATTR_REFCOUNT, - ATTR_REQUIRES, - ATTR_RESTOFDATA, - ATTR_RESTOFFLOW, - ATTR_TRANSIENT, - ATTR_UNTIL, - }; +enum AttrType { + ATTR_BYTEORDER, + ATTR_CHECK, + ATTR_CHUNKED, + ATTR_ENFORCE, + ATTR_EXPORTSOURCEDATA, + ATTR_IF, + ATTR_LENGTH, + ATTR_LET, + ATTR_LINEBREAKER, + ATTR_MULTILINE, + ATTR_ONELINE, + ATTR_REFCOUNT, + ATTR_REQUIRES, + ATTR_RESTOFDATA, + ATTR_RESTOFFLOW, + ATTR_TRANSIENT, + ATTR_UNTIL, +}; -class Attr : public Object, public DataDepElement - { +class Attr : public Object, public DataDepElement { public: - Attr(AttrType type); - Attr(AttrType type, Expr* expr); - Attr(AttrType type, ExprList* exprlist); - Attr(AttrType type, SeqEnd* seqend); + Attr(AttrType type); + Attr(AttrType type, Expr* expr); + Attr(AttrType type, ExprList* exprlist); + Attr(AttrType type, SeqEnd* seqend); - ~Attr() override; + ~Attr() override; - AttrType type() const { return type_; } - Expr* expr() const { return expr_; } - SeqEnd* seqend() const { return seqend_; } + AttrType type() const { return type_; } + Expr* expr() const { return expr_; } + SeqEnd* seqend() const { return seqend_; } - bool RequiresAnalyzerContext() const; + bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; protected: - void init(); + void init(); - AttrType type_; - Expr* expr_; - SeqEnd* seqend_; - bool delete_expr_; - }; + AttrType type_; + Expr* expr_; + SeqEnd* seqend_; + bool delete_expr_; +}; -class LetAttr : public Attr - { +class LetAttr : public Attr { public: - LetAttr(FieldList* letfields); - FieldList* letfields() const { return letfields_; } + LetAttr(FieldList* letfields); + FieldList* letfields() const { return letfields_; } private: - FieldList* letfields_; - }; + FieldList* letfields_; +}; #endif // pac_attr_h diff --git a/tools/binpac/src/pac_btype.cc b/tools/binpac/src/pac_btype.cc index 47939dde8c..9be860bc6c 100644 --- a/tools/binpac/src/pac_btype.cc +++ b/tools/binpac/src/pac_btype.cc @@ -4,125 +4,104 @@ #include "pac_id.h" #include "pac_output.h" -Type* BuiltInType::DoClone() const - { - return new BuiltInType(bit_type()); - } +Type* BuiltInType::DoClone() const { return new BuiltInType(bit_type()); } -bool BuiltInType::IsNumericType() const - { - BITType t = bit_type(); - return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || t == UINT8 || t == UINT16 || - t == UINT32 || t == UINT64); - } +bool BuiltInType::IsNumericType() const { + BITType t = bit_type(); + return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || t == UINT8 || t == UINT16 || t == UINT32 || + t == UINT64); +} -bool BuiltInType::CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2) - { - return type1->IsNumericType() && type2->IsNumericType(); - } +bool BuiltInType::CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2) { + return type1->IsNumericType() && type2->IsNumericType(); +} static const char* basic_pactype_name[] = { #define TYPE_DEF(name, pactype, ctype, size) pactype, #include "pac_type.def" #undef TYPE_DEF - nullptr, + nullptr, }; -void BuiltInType::static_init() - { - for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type ) - { - Type::AddPredefinedType(basic_pactype_name[bit_type], new BuiltInType((BITType)bit_type)); - } - } +void BuiltInType::static_init() { + for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type ) { + Type::AddPredefinedType(basic_pactype_name[bit_type], new BuiltInType((BITType)bit_type)); + } +} -int BuiltInType::LookUpByName(const char* name) - { - ASSERT(0); - for ( int i = 0; basic_pactype_name[i]; ++i ) - if ( strcmp(basic_pactype_name[i], name) == 0 ) - return i; - return -1; - } +int BuiltInType::LookUpByName(const char* name) { + ASSERT(0); + for ( int i = 0; basic_pactype_name[i]; ++i ) + if ( strcmp(basic_pactype_name[i], name) == 0 ) + return i; + return -1; +} static const char* basic_ctype_name[] = { #define TYPE_DEF(name, pactype, ctype, size) ctype, #include "pac_type.def" #undef TYPE_DEF - nullptr, + nullptr, }; -bool BuiltInType::DefineValueVar() const - { - return bit_type_ != EMPTY; - } +bool BuiltInType::DefineValueVar() const { return bit_type_ != EMPTY; } -string BuiltInType::DataTypeStr() const - { - return basic_ctype_name[bit_type_]; - } +string BuiltInType::DataTypeStr() const { return basic_ctype_name[bit_type_]; } -int BuiltInType::StaticSize(Env* /* env */) const - { - static const size_t basic_type_size[] = { +int BuiltInType::StaticSize(Env* /* env */) const { + static const size_t basic_type_size[] = { #define TYPE_DEF(name, pactype, ctype, size) size, #include "pac_type.def" #undef TYPE_DEF - }; + }; - return basic_type_size[bit_type_]; - } + return basic_type_size[bit_type_]; +} -void BuiltInType::DoMarkIncrementalInput() - { - if ( bit_type_ == EMPTY ) - return; - Type::DoMarkIncrementalInput(); - } +void BuiltInType::DoMarkIncrementalInput() { + if ( bit_type_ == EMPTY ) + return; + Type::DoMarkIncrementalInput(); +} -void BuiltInType::GenInitCode(Output* out_cc, Env* env) - { - if ( bit_type_ != EMPTY ) - out_cc->println("%s = 0;", env->LValue(value_var())); - Type::GenInitCode(out_cc, env); - } +void BuiltInType::GenInitCode(Output* out_cc, Env* env) { + if ( bit_type_ != EMPTY ) + out_cc->println("%s = 0;", env->LValue(value_var())); + Type::GenInitCode(out_cc, env); +} -void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) - { - /* should never be called */ - ASSERT(0); - } +void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { + /* should never be called */ + ASSERT(0); +} -void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) - { - if ( bit_type_ == EMPTY ) - return; +void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { + if ( bit_type_ == EMPTY ) + return; - // There is no need to generate the size variable - // out_cc->println("%s = sizeof(%s);", size_var(), DataTypeStr().c_str()); + // There is no need to generate the size variable + // out_cc->println("%s = sizeof(%s);", size_var(), DataTypeStr().c_str()); - GenBoundaryCheck(out_cc, env, data); + GenBoundaryCheck(out_cc, env, data); - if ( anonymous_value_var() ) - return; + if ( anonymous_value_var() ) + return; - switch ( bit_type_ ) - { - case EMPTY: - // do nothing - break; + switch ( bit_type_ ) { + case EMPTY: + // do nothing + break; - case INT8: - case UINT8: - out_cc->println("%s = *((%s const *) (%s));", lvalue(), DataTypeStr().c_str(), - data.ptr_expr()); - break; - case INT16: - case UINT16: - case INT32: - case UINT32: - case INT64: - case UINT64: + case INT8: + case UINT8: + out_cc->println("%s = *((%s const *) (%s));", lvalue(), DataTypeStr().c_str(), data.ptr_expr()); + break; + case INT16: + case UINT16: + case INT32: + case UINT32: + case INT64: + case UINT64: #if 0 out_cc->println("%s = UnMarshall<%s>(%s, %s);", lvalue(), @@ -130,10 +109,9 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, data.ptr_expr(), EvalByteOrder(out_cc, env).c_str()); #else - out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", lvalue(), - EvalByteOrder(out_cc, env).c_str(), DataTypeStr().c_str(), - data.ptr_expr()); + out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", lvalue(), + EvalByteOrder(out_cc, env).c_str(), DataTypeStr().c_str(), data.ptr_expr()); #endif - break; - } - } + break; + } +} diff --git a/tools/binpac/src/pac_btype.h b/tools/binpac/src/pac_btype.h index 73ca8f8932..bff7be5404 100644 --- a/tools/binpac/src/pac_btype.h +++ b/tools/binpac/src/pac_btype.h @@ -3,51 +3,46 @@ #include "pac_type.h" -class BuiltInType : public Type - { +class BuiltInType : public Type { public: - enum BITType - { + enum BITType { #define TYPE_DEF(name, pactype, ctype, size) name, #include "pac_type.def" #undef TYPE_DEF - }; + }; - static int LookUpByName(const char* name); + static int LookUpByName(const char* name); - BuiltInType(BITType bit_type) - : Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN), bit_type_(bit_type) - { - } + BuiltInType(BITType bit_type) : Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN), bit_type_(bit_type) {} - BITType bit_type() const { return bit_type_; } + BITType bit_type() const { return bit_type_; } - bool IsNumericType() const override; + bool IsNumericType() const override; - bool DefineValueVar() const override; - string DataTypeStr() const override; - string DefaultValue() const override { return "0"; } + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override { return "0"; } - int StaticSize(Env* env) const override; + int StaticSize(Env* env) const override; - bool IsPointerType() const override { return false; } + bool IsPointerType() const override { return false; } - bool ByteOrderSensitive() const override { return StaticSize(0) >= 2; } + bool ByteOrderSensitive() const override { return StaticSize(0) >= 2; } - void GenInitCode(Output* out_cc, Env* env) override; + void GenInitCode(Output* out_cc, Env* env) override; - void DoMarkIncrementalInput() override; + void DoMarkIncrementalInput() override; protected: - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; - Type* DoClone() const override; + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; + Type* DoClone() const override; - BITType bit_type_; + BITType bit_type_; public: - static void static_init(); - static bool CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2); - }; + static void static_init(); + static bool CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2); +}; #endif // pac_btype_h diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index 68fede97ad..a2131ca2d4 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -12,443 +12,381 @@ #include "pac_typedecl.h" #include "pac_utils.h" -CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) - : Type(CASE), index_expr_(index_expr), cases_(cases) - { - index_var_ = nullptr; - foreach (i, CaseFieldList, cases_) - AddField(*i); - } +CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) : Type(CASE), index_expr_(index_expr), cases_(cases) { + index_var_ = nullptr; + foreach (i, CaseFieldList, cases_) + AddField(*i); +} -CaseType::~CaseType() - { - delete index_var_; - delete index_expr_; - delete cases_; - } +CaseType::~CaseType() { + delete index_var_; + delete index_expr_; + delete cases_; +} -void CaseType::AddCaseField(CaseField* f) - { - // All fields must be added before Prepare() - ASSERT(! env()); +void CaseType::AddCaseField(CaseField* f) { + // All fields must be added before Prepare() + ASSERT(! env()); - AddField(f); - cases_->push_back(f); - } + AddField(f); + cases_->push_back(f); +} -bool CaseType::DefineValueVar() const - { - return false; - } +bool CaseType::DefineValueVar() const { return false; } -string CaseType::DataTypeStr() const - { - ASSERT(type_decl()); - return strfmt("%s *", type_decl()->class_name().c_str()); - } +string CaseType::DataTypeStr() const { + ASSERT(type_decl()); + return strfmt("%s *", type_decl()->class_name().c_str()); +} -Type* CaseType::ValueType() const - { - foreach (i, CaseFieldList, cases_) - { - CaseField* c = *i; - return c->type(); - } - ASSERT(0); - return nullptr; - } +Type* CaseType::ValueType() const { + foreach (i, CaseFieldList, cases_) { + CaseField* c = *i; + return c->type(); + } + ASSERT(0); + return nullptr; +} -string CaseType::DefaultValue() const - { - return ValueType()->DefaultValue(); - } +string CaseType::DefaultValue() const { return ValueType()->DefaultValue(); } -void CaseType::Prepare(Env* env, int flags) - { - ASSERT(flags & TO_BE_PARSED); +void CaseType::Prepare(Env* env, int flags) { + ASSERT(flags & TO_BE_PARSED); - index_var_ = new ID(strfmt("%s_case_index", value_var()->Name())); - // Unable to get the type for index_var_ at this moment, but we'll - // generate the right type based on index_expr_ later. - env->AddID(index_var_, MEMBER_VAR, nullptr); + index_var_ = new ID(strfmt("%s_case_index", value_var()->Name())); + // Unable to get the type for index_var_ at this moment, but we'll + // generate the right type based on index_expr_ later. + env->AddID(index_var_, MEMBER_VAR, nullptr); - // Sort the cases_ to put the default case at the end of the list - CaseFieldList::iterator default_case_it = cases_->end(); // to avoid warning - CaseField* default_case = nullptr; + // Sort the cases_ to put the default case at the end of the list + CaseFieldList::iterator default_case_it = cases_->end(); // to avoid warning + CaseField* default_case = nullptr; - foreach (i, CaseFieldList, cases_) - { - CaseField* c = *i; - if ( ! c->index() ) - { - if ( default_case ) - throw Exception(c, "duplicate default case"); - default_case_it = i; - default_case = c; - } - } - if ( default_case ) - { - cases_->erase(default_case_it); - cases_->push_back(default_case); - } + foreach (i, CaseFieldList, cases_) { + CaseField* c = *i; + if ( ! c->index() ) { + if ( default_case ) + throw Exception(c, "duplicate default case"); + default_case_it = i; + default_case = c; + } + } + if ( default_case ) { + cases_->erase(default_case_it); + cases_->push_back(default_case); + } - foreach (i, CaseFieldList, cases_) - { - CaseField* c = *i; - c->set_index_var(index_var_); - c->set_case_type(this); - } + foreach (i, CaseFieldList, cases_) { + CaseField* c = *i; + c->set_index_var(index_var_); + c->set_case_type(this); + } - Type::Prepare(env, flags); - } + Type::Prepare(env, flags); +} -void CaseType::GenPrivDecls(Output* out_h, Env* env) - { - Type* t = index_expr_->DataType(env); +void CaseType::GenPrivDecls(Output* out_h, Env* env) { + Type* t = index_expr_->DataType(env); - if ( t->tot() != Type::BUILTIN ) - // It's a Type::EXTERN with a C++ type of "int", "bool", or "enum", - // any of which will convert consistently using an int as storage type. - t = extern_type_int; + if ( t->tot() != Type::BUILTIN ) + // It's a Type::EXTERN with a C++ type of "int", "bool", or "enum", + // any of which will convert consistently using an int as storage type. + t = extern_type_int; - out_h->println("%s %s;", t->DataTypeStr().c_str(), env->LValue(index_var_)); - Type::GenPrivDecls(out_h, env); - } + out_h->println("%s %s;", t->DataTypeStr().c_str(), env->LValue(index_var_)); + Type::GenPrivDecls(out_h, env); +} -void CaseType::GenPubDecls(Output* out_h, Env* env) - { - Type* t = index_expr_->DataType(env); +void CaseType::GenPubDecls(Output* out_h, Env* env) { + Type* t = index_expr_->DataType(env); - if ( t->tot() != Type::BUILTIN ) - t = extern_type_int; + if ( t->tot() != Type::BUILTIN ) + t = extern_type_int; - out_h->println("%s %s const { return %s; }", t->DataTypeStr().c_str(), env->RValue(index_var_), - env->LValue(index_var_)); - Type::GenPubDecls(out_h, env); - } + out_h->println("%s %s const { return %s; }", t->DataTypeStr().c_str(), env->RValue(index_var_), + env->LValue(index_var_)); + Type::GenPubDecls(out_h, env); +} -void CaseType::GenInitCode(Output* out_cc, Env* env) - { - out_cc->println("%s = -1;", env->LValue(index_var_)); - Type::GenInitCode(out_cc, env); - } +void CaseType::GenInitCode(Output* out_cc, Env* env) { + out_cc->println("%s = -1;", env->LValue(index_var_)); + Type::GenInitCode(out_cc, env); +} -void CaseType::GenCleanUpCode(Output* out_cc, Env* env) - { - Type::GenCleanUpCode(out_cc, env); +void CaseType::GenCleanUpCode(Output* out_cc, Env* env) { + Type::GenCleanUpCode(out_cc, env); - env->set_in_branch(true); - out_cc->println("switch ( %s )", env->RValue(index_var_)); - out_cc->inc_indent(); - out_cc->println("{"); - foreach (i, CaseFieldList, cases_) - { - CaseField* c = *i; - c->GenCleanUpCode(out_cc, env); - } - out_cc->println("}"); - out_cc->dec_indent(); - env->set_in_branch(false); - } + env->set_in_branch(true); + out_cc->println("switch ( %s )", env->RValue(index_var_)); + out_cc->inc_indent(); + out_cc->println("{"); + foreach (i, CaseFieldList, cases_) { + CaseField* c = *i; + c->GenCleanUpCode(out_cc, env); + } + out_cc->println("}"); + out_cc->dec_indent(); + env->set_in_branch(false); +} -void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) - { - if ( StaticSize(env) >= 0 ) - GenBoundaryCheck(out_cc, env, data); +void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { + if ( StaticSize(env) >= 0 ) + GenBoundaryCheck(out_cc, env, data); - bool compute_size_var = false; + bool compute_size_var = false; - if ( ! incremental_input() ) - compute_size_var = AddSizeVar(out_cc, env); + if ( ! incremental_input() ) + compute_size_var = AddSizeVar(out_cc, env); - out_cc->println("%s = %s;", env->LValue(index_var_), index_expr_->EvalExpr(out_cc, env)); - env->SetEvaluated(index_var_); - - env->set_in_branch(true); - out_cc->println("switch ( %s )", env->RValue(index_var_)); - out_cc->inc_indent(); - out_cc->println("{"); - bool has_default_case = false; - foreach (i, CaseFieldList, cases_) - { - CaseField* c = *i; - c->GenParseCode(out_cc, env, data, compute_size_var ? size_var() : nullptr); - if ( c->IsDefaultCase() ) - has_default_case = true; - } + out_cc->println("%s = %s;", env->LValue(index_var_), index_expr_->EvalExpr(out_cc, env)); + env->SetEvaluated(index_var_); - if ( ! has_default_case ) - { - out_cc->println("default:"); - out_cc->inc_indent(); - out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", - decl_id()->Name(), env->RValue(index_var_)); - out_cc->println("break;"); - out_cc->dec_indent(); - } - out_cc->println("}"); - out_cc->dec_indent(); - env->set_in_branch(false); + env->set_in_branch(true); + out_cc->println("switch ( %s )", env->RValue(index_var_)); + out_cc->inc_indent(); + out_cc->println("{"); + bool has_default_case = false; + foreach (i, CaseFieldList, cases_) { + CaseField* c = *i; + c->GenParseCode(out_cc, env, data, compute_size_var ? size_var() : nullptr); + if ( c->IsDefaultCase() ) + has_default_case = true; + } - if ( compute_size_var ) - env->SetEvaluated(size_var()); - } + if ( ! has_default_case ) { + out_cc->println("default:"); + out_cc->inc_indent(); + out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", decl_id()->Name(), + env->RValue(index_var_)); + out_cc->println("break;"); + out_cc->dec_indent(); + } + out_cc->println("}"); + out_cc->dec_indent(); + env->set_in_branch(false); -void CaseType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) - { - GenParseCode(out_cc, env, data, 0); - } + if ( compute_size_var ) + env->SetEvaluated(size_var()); +} -int CaseType::StaticSize(Env* env) const - { - int static_w = -1; - foreach (i, CaseFieldList, cases_) - { - CaseField* c = *i; - int w = c->StaticSize(env); - if ( w < 0 || (static_w >= 0 && w != static_w) ) - return -1; - static_w = w; - } - return static_w; - } +void CaseType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { GenParseCode(out_cc, env, data, 0); } -void CaseType::SetBoundaryChecked() - { - Type::SetBoundaryChecked(); - foreach (i, CaseFieldList, cases_) - { - CaseField* c = *i; - c->SetBoundaryChecked(); - } - } +int CaseType::StaticSize(Env* env) const { + int static_w = -1; + foreach (i, CaseFieldList, cases_) { + CaseField* c = *i; + int w = c->StaticSize(env); + if ( w < 0 || (static_w >= 0 && w != static_w) ) + return -1; + static_w = w; + } + return static_w; +} -void CaseType::DoMarkIncrementalInput() - { - foreach (i, CaseFieldList, cases_) - { - CaseField* c = *i; - c->type()->MarkIncrementalInput(); - } - } +void CaseType::SetBoundaryChecked() { + Type::SetBoundaryChecked(); + foreach (i, CaseFieldList, cases_) { + CaseField* c = *i; + c->SetBoundaryChecked(); + } +} -bool CaseType::ByteOrderSensitive() const - { - foreach (i, CaseFieldList, cases_) - { - CaseField* c = *i; - if ( c->RequiresByteOrder() ) - return true; - } - return false; - } +void CaseType::DoMarkIncrementalInput() { + foreach (i, CaseFieldList, cases_) { + CaseField* c = *i; + c->type()->MarkIncrementalInput(); + } +} + +bool CaseType::ByteOrderSensitive() const { + foreach (i, CaseFieldList, cases_) { + CaseField* c = *i; + if ( c->RequiresByteOrder() ) + return true; + } + return false; +} CaseField::CaseField(ExprList* index, ID* id, Type* type) - : Field(CASE_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), index_(index) - { - ASSERT(type_); - type_->set_value_var(id, MEMBER_VAR); - case_type_ = nullptr; - index_var_ = nullptr; - } + : Field(CASE_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), index_(index) { + ASSERT(type_); + type_->set_value_var(id, MEMBER_VAR); + case_type_ = nullptr; + index_var_ = nullptr; +} -CaseField::~CaseField() - { - delete_list(ExprList, index_); - } +CaseField::~CaseField() { delete_list(ExprList, index_); } -void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_type) - { - if ( index_list ) - { - foreach (i, ExprList, index_list) - { - Expr* index_expr = *i; +void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_type) { + if ( index_list ) { + foreach (i, ExprList, index_list) { + Expr* index_expr = *i; - Type* case_type = index_expr->DataType(env); + Type* case_type = index_expr->DataType(env); - if ( case_type->tot() == Type::BUILTIN && case_type->StaticSize(env) > 4 ) - throw ExceptionInvalidCaseSizeExpr(index_expr); + if ( case_type->tot() == Type::BUILTIN && case_type->StaticSize(env) > 4 ) + throw ExceptionInvalidCaseSizeExpr(index_expr); - int index_const; - - if ( ! index_expr->ConstFold(env, &index_const) ) - throw ExceptionNonConstExpr(index_expr); + int index_const; - // External C++ types like "int", "bool", "enum" - // all use "int" type internally by default. - int case_type_width = 4; - int switch_type_width = 4; + if ( ! index_expr->ConstFold(env, &index_const) ) + throw ExceptionNonConstExpr(index_expr); - if ( switch_type->tot() == Type::BUILTIN ) - switch_type_width = switch_type->StaticSize(env); + // External C++ types like "int", "bool", "enum" + // all use "int" type internally by default. + int case_type_width = 4; + int switch_type_width = 4; - if ( case_type->tot() == Type::BUILTIN ) - case_type_width = case_type->StaticSize(env); + if ( switch_type->tot() == Type::BUILTIN ) + switch_type_width = switch_type->StaticSize(env); - if ( case_type_width > switch_type_width ) - { - BuiltInType* st = (BuiltInType*)switch_type; + if ( case_type->tot() == Type::BUILTIN ) + case_type_width = case_type->StaticSize(env); - if ( switch_type_width == 1 ) - { - if ( st->bit_type() == BuiltInType::INT8 ) - { - if ( index_const < std::numeric_limits::min() ) - throw ExceptionInvalidCaseLimitExpr(index_expr); - if ( index_const > std::numeric_limits::max() ) - throw ExceptionInvalidCaseLimitExpr(index_expr); - } - else - { - if ( index_const < std::numeric_limits::min() ) - throw ExceptionInvalidCaseLimitExpr(index_expr); - if ( index_const > std::numeric_limits::max() ) - throw ExceptionInvalidCaseLimitExpr(index_expr); - } - } - else if ( switch_type_width == 2 ) - { - if ( st->bit_type() == BuiltInType::INT16 ) - { - if ( index_const < std::numeric_limits::min() ) - throw ExceptionInvalidCaseLimitExpr(index_expr); - if ( index_const > std::numeric_limits::max() ) - throw ExceptionInvalidCaseLimitExpr(index_expr); - } - else - { - if ( index_const < std::numeric_limits::min() ) - throw ExceptionInvalidCaseLimitExpr(index_expr); - if ( index_const > std::numeric_limits::max() ) - throw ExceptionInvalidCaseLimitExpr(index_expr); - } - } - } + if ( case_type_width > switch_type_width ) { + BuiltInType* st = (BuiltInType*)switch_type; - // We're always using "int" for storage, so ok to just - // cast into the type used by the switch statement since - // some unsafe stuff is already checked above. - out_cc->println("case ((%s) %d):", switch_type->DataTypeStr().c_str(), index_const); - } - } - else - { - out_cc->println("default:"); - } - } + if ( switch_type_width == 1 ) { + if ( st->bit_type() == BuiltInType::INT8 ) { + if ( index_const < std::numeric_limits::min() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + if ( index_const > std::numeric_limits::max() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + } + else { + if ( index_const < std::numeric_limits::min() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + if ( index_const > std::numeric_limits::max() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + } + } + else if ( switch_type_width == 2 ) { + if ( st->bit_type() == BuiltInType::INT16 ) { + if ( index_const < std::numeric_limits::min() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + if ( index_const > std::numeric_limits::max() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + } + else { + if ( index_const < std::numeric_limits::min() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + if ( index_const > std::numeric_limits::max() ) + throw ExceptionInvalidCaseLimitExpr(index_expr); + } + } + else { + assert(0); + } + } -void CaseField::Prepare(Env* env) - { - ASSERT(index_var_); - Field::Prepare(env); - } + // We're always using "int" for storage, so ok to just + // cast into the type used by the switch statement since + // some unsafe stuff is already checked above. + out_cc->println("case ((%s) %d):", switch_type->DataTypeStr().c_str(), index_const); + } + } + else { + out_cc->println("default:"); + } +} -void CaseField::GenPubDecls(Output* out_h, Env* env) - { - if ( ! ((flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER)) ) - return; +void CaseField::Prepare(Env* env) { + ASSERT(index_var_); + Field::Prepare(env); +} - // Skip type "empty" - if ( type_->DataTypeStr().empty() ) - return; +void CaseField::GenPubDecls(Output* out_h, Env* env) { + if ( ! ((flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER)) ) + return; - out_h->println("%s %s const", type_->DataTypeConstRefStr().c_str(), env->RValue(id_)); + // Skip type "empty" + if ( type_->DataTypeStr().empty() ) + return; - out_h->inc_indent(); - out_h->println("{"); + out_h->println("%s %s const", type_->DataTypeConstRefStr().c_str(), env->RValue(id_)); - if ( ! index_ ) - out_h->println("return %s;", lvalue()); - else - { - out_h->println("switch ( %s )", env->RValue(index_var_)); - out_h->inc_indent(); - out_h->println("{"); - GenCaseStr(index_, out_h, env, case_type()->IndexExpr()->DataType(env)); - out_h->inc_indent(); - out_h->println("break; // OK"); - out_h->dec_indent(); + out_h->inc_indent(); + out_h->println("{"); - out_h->println("default:"); - out_h->inc_indent(); - out_h->println("throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");", - id_->LocName(), env->RValue(index_var_), OrigExprList(index_).c_str()); - out_h->println("break;"); - out_h->dec_indent(); + if ( ! index_ ) + out_h->println("return %s;", lvalue()); + else { + out_h->println("switch ( %s )", env->RValue(index_var_)); + out_h->inc_indent(); + out_h->println("{"); + GenCaseStr(index_, out_h, env, case_type()->IndexExpr()->DataType(env)); + out_h->inc_indent(); + out_h->println("break; // OK"); + out_h->dec_indent(); - out_h->println("}"); - out_h->dec_indent(); + out_h->println("default:"); + out_h->inc_indent(); + out_h->println("throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");", id_->LocName(), + env->RValue(index_var_), OrigExprList(index_).c_str()); + out_h->println("break;"); + out_h->dec_indent(); - out_h->println("return %s;", lvalue()); - } + out_h->println("}"); + out_h->dec_indent(); - out_h->println("}"); - out_h->dec_indent(); - } + out_h->println("return %s;", lvalue()); + } -void CaseField::GenInitCode(Output* out_cc, Env* env) - { - // GenCaseStr(index_, out_cc, env); - // out_cc->inc_indent(); - // out_cc->println("{"); - // out_cc->println("// Initialize \"%s\"", id_->Name()); - type_->GenInitCode(out_cc, env); - // out_cc->println("}"); - // out_cc->println("break;"); - // out_cc->dec_indent(); - } + out_h->println("}"); + out_h->dec_indent(); +} -void CaseField::GenCleanUpCode(Output* out_cc, Env* env) - { - GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); - out_cc->inc_indent(); - out_cc->println("// Clean up \"%s\"", id_->Name()); - out_cc->println("{"); - if ( ! anonymous_field() ) - type_->GenCleanUpCode(out_cc, env); - out_cc->println("}"); - out_cc->println("break;"); - out_cc->dec_indent(); - } +void CaseField::GenInitCode(Output* out_cc, Env* env) { + // GenCaseStr(index_, out_cc, env); + // out_cc->inc_indent(); + // out_cc->println("{"); + // out_cc->println("// Initialize \"%s\"", id_->Name()); + type_->GenInitCode(out_cc, env); + // out_cc->println("}"); + // out_cc->println("break;"); + // out_cc->dec_indent(); +} -void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, const ID* size_var) - { - GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); - out_cc->inc_indent(); - out_cc->println("// Parse \"%s\"", id_->Name()); - out_cc->println("{"); +void CaseField::GenCleanUpCode(Output* out_cc, Env* env) { + GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); + out_cc->inc_indent(); + out_cc->println("// Clean up \"%s\"", id_->Name()); + out_cc->println("{"); + if ( ! anonymous_field() ) + type_->GenCleanUpCode(out_cc, env); + out_cc->println("}"); + out_cc->println("break;"); + out_cc->dec_indent(); +} - { - Env case_env(env, this); +void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, const ID* size_var) { + GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); + out_cc->inc_indent(); + out_cc->println("// Parse \"%s\"", id_->Name()); + out_cc->println("{"); - type_->GenPreParsing(out_cc, &case_env); - type_->GenParseCode(out_cc, &case_env, data, 0); - if ( size_var ) - { - out_cc->println("%s = %s;", case_env.LValue(size_var), - type_->DataSize(out_cc, &case_env, data).c_str()); - } - if ( type_->incremental_input() ) - { - ASSERT(case_type()->parsing_complete_var()); - out_cc->println("%s = %s;", case_env.LValue(case_type()->parsing_complete_var()), - case_env.RValue(type_->parsing_complete_var())); - } - out_cc->println("}"); - } + { + Env case_env(env, this); - out_cc->println("break;"); - out_cc->dec_indent(); - } + type_->GenPreParsing(out_cc, &case_env); + type_->GenParseCode(out_cc, &case_env, data, 0); + if ( size_var ) { + out_cc->println("%s = %s;", case_env.LValue(size_var), type_->DataSize(out_cc, &case_env, data).c_str()); + } + if ( type_->incremental_input() ) { + ASSERT(case_type()->parsing_complete_var()); + out_cc->println("%s = %s;", case_env.LValue(case_type()->parsing_complete_var()), + case_env.RValue(type_->parsing_complete_var())); + } + out_cc->println("}"); + } -bool CaseField::DoTraverse(DataDepVisitor* visitor) - { - return Field::DoTraverse(visitor) && type()->Traverse(visitor); - } + out_cc->println("break;"); + out_cc->dec_indent(); +} -bool CaseField::RequiresAnalyzerContext() const - { - return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext(); - } +bool CaseField::DoTraverse(DataDepVisitor* visitor) { return Field::DoTraverse(visitor) && type()->Traverse(visitor); } + +bool CaseField::RequiresAnalyzerContext() const { + return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext(); +} diff --git a/tools/binpac/src/pac_case.h b/tools/binpac/src/pac_case.h index 501676bda0..bb8e862b43 100644 --- a/tools/binpac/src/pac_case.h +++ b/tools/binpac/src/pac_case.h @@ -6,92 +6,90 @@ #include "pac_id.h" #include "pac_type.h" -class CaseType : public Type - { +class CaseType : public Type { public: - CaseType(Expr* index, CaseFieldList* cases); - ~CaseType() override; + CaseType(Expr* index, CaseFieldList* cases); + ~CaseType() override; - void AddCaseField(CaseField* f); + void AddCaseField(CaseField* f); - bool DefineValueVar() const override; - string DataTypeStr() const override; - string DefaultValue() const override; + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override; - void Prepare(Env* env, int flags) override; + void Prepare(Env* env, int flags) override; - void GenPubDecls(Output* out, Env* env) override; - void GenPrivDecls(Output* out, Env* env) override; + void GenPubDecls(Output* out, Env* env) override; + void GenPrivDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env) override; - void GenCleanUpCode(Output* out, Env* env) override; + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; - int StaticSize(Env* env) const override; + int StaticSize(Env* env) const override; - void SetBoundaryChecked() override; + void SetBoundaryChecked() override; - Type* ValueType() const; + Type* ValueType() const; - Expr* IndexExpr() const { return index_expr_; } + Expr* IndexExpr() const { return index_expr_; } - bool IsPointerType() const override { return ValueType()->IsPointerType(); } + bool IsPointerType() const override { return ValueType()->IsPointerType(); } protected: - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; - Type* DoClone() const override { return nullptr; } - void DoMarkIncrementalInput() override; + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; + Type* DoClone() const override { return nullptr; } + void DoMarkIncrementalInput() override; - bool ByteOrderSensitive() const override; + bool ByteOrderSensitive() const override; - Expr* index_expr_; - ID* index_var_; - CaseFieldList* cases_; + Expr* index_expr_; + ID* index_var_; + CaseFieldList* cases_; - typedef map member_map_t; - member_map_t member_map_; - }; + typedef map member_map_t; + member_map_t member_map_; +}; -class CaseField : public Field - { +class CaseField : public Field { public: - CaseField(ExprList* index, ID* id, Type* type); - ~CaseField() override; + CaseField(ExprList* index, ID* id, Type* type); + ~CaseField() override; - CaseType* case_type() const { return case_type_; } - void set_case_type(CaseType* t) { case_type_ = t; } + CaseType* case_type() const { return case_type_; } + void set_case_type(CaseType* t) { case_type_ = t; } - ExprList* index() const { return index_; } + ExprList* index() const { return index_; } - const char* lvalue() const { return type_->lvalue(); } + const char* lvalue() const { return type_->lvalue(); } - const char* CaseStr(Env* env); - void set_index_var(const ID* var) { index_var_ = var; } + const char* CaseStr(Env* env); + void set_index_var(const ID* var) { index_var_ = var; } - void Prepare(Env* env) override; + void Prepare(Env* env) override; - void GenPubDecls(Output* out, Env* env) override; + void GenPubDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env) override; - void GenCleanUpCode(Output* out, Env* env) override; - void GenParseCode(Output* out, Env* env, const DataPtr& data, const ID* size_var); + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; + void GenParseCode(Output* out, Env* env, const DataPtr& data, const ID* size_var); - int StaticSize(Env* env) const { return type_->StaticSize(env); } + int StaticSize(Env* env) const { return type_->StaticSize(env); } - bool IsDefaultCase() const { return ! index_; } - void SetBoundaryChecked() { type_->SetBoundaryChecked(); } + bool IsDefaultCase() const { return ! index_; } + void SetBoundaryChecked() { type_->SetBoundaryChecked(); } - bool RequiresByteOrder() const { return type_->RequiresByteOrder(); } - bool RequiresAnalyzerContext() const override; + bool RequiresByteOrder() const { return type_->RequiresByteOrder(); } + bool RequiresAnalyzerContext() const override; protected: - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; protected: - CaseType* case_type_; - ExprList* index_; - const ID* index_var_; - }; + CaseType* case_type_; + ExprList* index_; + const ID* index_var_; +}; // Generate a list of "case X:" lines from index_list. Each index // expression must be constant foldable. diff --git a/tools/binpac/src/pac_cclass.h b/tools/binpac/src/pac_cclass.h index daf88236dd..d1129f6f99 100644 --- a/tools/binpac/src/pac_cclass.h +++ b/tools/binpac/src/pac_cclass.h @@ -24,58 +24,54 @@ typedef vector CVariableList; // // 3. We do not check repeated names. -class CClass - { +class CClass { public: - CClass(const string& class_name); + CClass(const string& class_name); - void AddMember(CClassMember* member); - void AddMethod(CClassMember* method); + void AddMember(CClassMember* member); + void AddMethod(CClassMember* method); - void GenForwardDeclaration(Output* out_h); - void GenCode(Output* out_h, Output* out_cc); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); protected: - string class_name_; - CClassMemberList* members_; - CClassMethodList* methods_; - }; + string class_name_; + CClassMemberList* members_; + CClassMethodList* methods_; +}; -class CVariable - { +class CVariable { public: - CClassMember(const string& name, CType* type); + CClassMember(const string& name, CType* type); - string name() const { return name_; } - CType* type() const { return type_; } + string name() const { return name_; } + CType* type() const { return type_; } protected: - string name_; - CType* type_; - }; + string name_; + CType* type_; +}; -class CClassMember - { +class CClassMember { public: - CClassMember(CVariable* var); - void GenCode(Output* out_h, Output* out_cc); + CClassMember(CVariable* var); + void GenCode(Output* out_h, Output* out_cc); - string decl() const; + string decl() const; protected: - CVariable* var_; - }; + CVariable* var_; +}; -class CClassMethod - { +class CClassMethod { public: - CClassMethod(CVariable* var, CVariableList* params); + CClassMethod(CVariable* var, CVariableList* params); - string decl() const; + string decl() const; protected: - CVariable* var_; - CVariableList* params_; - }; + CVariable* var_; + CVariableList* params_; +}; #endif // pac_cclass_h diff --git a/tools/binpac/src/pac_common.h b/tools/binpac/src/pac_common.h index 90c1d3b4ab..8ddc7f1c7f 100644 --- a/tools/binpac/src/pac_common.h +++ b/tools/binpac/src/pac_common.h @@ -20,25 +20,23 @@ extern int line_number; // representing language elements -- identifiers, types, expressions, // etc. -class Object - { +class Object { public: - Object() - { - filename = input_filename; - line_num = line_number; - location = strfmt("%s:%d", filename.c_str(), line_number); - } + Object() { + filename = input_filename; + line_num = line_number; + location = strfmt("%s:%d", filename.c_str(), line_number); + } - ~Object() { } + ~Object() {} - const char* Location() const { return location.c_str(); } + const char* Location() const { return location.c_str(); } protected: - string filename; - int line_num; - string location; - }; + string filename; + int line_num; + string location; +}; class ActionParam; class ActionParamType; @@ -103,17 +101,17 @@ typedef vector ParamList; typedef vector RecordFieldList; typedef vector StateVarList; -#define foreach(i, ct, pc) \ - if ( pc ) \ - for ( ct::iterator i = (pc)->begin(); i != (pc)->end(); ++i ) +#define foreach(i, ct, pc) \ + if ( pc ) \ + for ( ct::iterator i = (pc)->begin(); i != (pc)->end(); ++i ) -#define delete_list(ct, pc) \ - { \ - foreach (delete_list_i, ct, pc) \ - delete *delete_list_i; \ - delete pc; \ - pc = 0; \ - } +#define delete_list(ct, pc) \ + { \ + foreach (delete_list_i, ct, pc) \ + delete *delete_list_i; \ + delete pc; \ + pc = 0; \ + } // Constants const char* const kComputeFrameLength = "compute_frame_length"; diff --git a/tools/binpac/src/pac_conn.cc b/tools/binpac/src/pac_conn.cc index 385be6245e..4d04c690ec 100644 --- a/tools/binpac/src/pac_conn.cc +++ b/tools/binpac/src/pac_conn.cc @@ -11,141 +11,123 @@ #include "pac_type.h" ConnDecl::ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist) - : AnalyzerDecl(conn_id, CONN, params) - { - flows_[0] = flows_[1] = nullptr; - AddElements(elemlist); - data_type_ = new ParameterizedType(conn_id->clone(), nullptr); - } + : AnalyzerDecl(conn_id, CONN, params) { + flows_[0] = flows_[1] = nullptr; + AddElements(elemlist); + data_type_ = new ParameterizedType(conn_id->clone(), nullptr); +} -ConnDecl::~ConnDecl() - { - delete flows_[0]; - delete flows_[1]; - delete data_type_; - } +ConnDecl::~ConnDecl() { + delete flows_[0]; + delete flows_[1]; + delete data_type_; +} -void ConnDecl::AddBaseClass(vector* base_classes) const - { - base_classes->push_back("binpac::ConnectionAnalyzer"); - } +void ConnDecl::AddBaseClass(vector* base_classes) const { + base_classes->push_back("binpac::ConnectionAnalyzer"); +} -void ConnDecl::ProcessFlowElement(AnalyzerFlow* flow_elem) - { - int flow_index; +void ConnDecl::ProcessFlowElement(AnalyzerFlow* flow_elem) { + int flow_index; - if ( flow_elem->dir() == AnalyzerFlow::UP ) - flow_index = 0; - else - flow_index = 1; + if ( flow_elem->dir() == AnalyzerFlow::UP ) + flow_index = 0; + else + flow_index = 1; - if ( flows_[flow_index] ) - { - throw Exception(flow_elem, - strfmt("%sflow already defined", flow_index == 0 ? "up" : "down")); - } + if ( flows_[flow_index] ) { + throw Exception(flow_elem, strfmt("%sflow already defined", flow_index == 0 ? "up" : "down")); + } - flows_[flow_index] = flow_elem; - type_->AddField(flow_elem->flow_field()); - } + flows_[flow_index] = flow_elem; + type_->AddField(flow_elem->flow_field()); +} -void ConnDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) - { - throw Exception(dataunit_elem, "dataunit should be defined in only a flow declaration"); - } +void ConnDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) { + throw Exception(dataunit_elem, "dataunit should be defined in only a flow declaration"); +} -void ConnDecl::Prepare() - { - AnalyzerDecl::Prepare(); +void ConnDecl::Prepare() { + AnalyzerDecl::Prepare(); - flows_[0]->flow_decl()->set_conn_decl(this); - flows_[1]->flow_decl()->set_conn_decl(this); - } + flows_[0]->flow_decl()->set_conn_decl(this); + flows_[1]->flow_decl()->set_conn_decl(this); +} -void ConnDecl::GenPubDecls(Output* out_h, Output* out_cc) - { - AnalyzerDecl::GenPubDecls(out_h, out_cc); - } +void ConnDecl::GenPubDecls(Output* out_h, Output* out_cc) { AnalyzerDecl::GenPubDecls(out_h, out_cc); } -void ConnDecl::GenPrivDecls(Output* out_h, Output* out_cc) - { - AnalyzerDecl::GenPrivDecls(out_h, out_cc); - } +void ConnDecl::GenPrivDecls(Output* out_h, Output* out_cc) { AnalyzerDecl::GenPrivDecls(out_h, out_cc); } -void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc) - { - string proto = strfmt("%s(bool is_orig)", kFlowEOF); +void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc) { + string proto = strfmt("%s(bool is_orig)", kFlowEOF); - out_h->println("void %s;", proto.c_str()); + out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); - out_cc->println("if ( is_orig )"); - out_cc->inc_indent(); - out_cc->println("%s->%s();", env_->LValue(upflow_id), kFlowEOF); - out_cc->dec_indent(); - out_cc->println("else"); - out_cc->inc_indent(); - out_cc->println("%s->%s();", env_->LValue(downflow_id), kFlowEOF); + out_cc->println("if ( is_orig )"); + out_cc->inc_indent(); + out_cc->println("%s->%s();", env_->LValue(upflow_id), kFlowEOF); + out_cc->dec_indent(); + out_cc->println("else"); + out_cc->inc_indent(); + out_cc->println("%s->%s();", env_->LValue(downflow_id), kFlowEOF); - foreach (i, AnalyzerHelperList, eof_helpers_) - { - (*i)->GenCode(nullptr, out_cc, this); - } + foreach (i, AnalyzerHelperList, eof_helpers_) { + (*i)->GenCode(nullptr, out_cc, this); + } - out_cc->dec_indent(); + out_cc->dec_indent(); - out_cc->println("}"); - out_cc->dec_indent(); - out_cc->println(""); - } + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); +} -void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc) - { - string proto = strfmt("%s(bool is_orig, int gap_length)", kFlowGap); +void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc) { + string proto = strfmt("%s(bool is_orig, int gap_length)", kFlowGap); - out_h->println("void %s;", proto.c_str()); + out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); - out_cc->println("if ( is_orig )"); - out_cc->inc_indent(); - out_cc->println("%s->%s(gap_length);", env_->LValue(upflow_id), kFlowGap); - out_cc->dec_indent(); - out_cc->println("else"); - out_cc->inc_indent(); - out_cc->println("%s->%s(gap_length);", env_->LValue(downflow_id), kFlowGap); - out_cc->dec_indent(); + out_cc->println("if ( is_orig )"); + out_cc->inc_indent(); + out_cc->println("%s->%s(gap_length);", env_->LValue(upflow_id), kFlowGap); + out_cc->dec_indent(); + out_cc->println("else"); + out_cc->inc_indent(); + out_cc->println("%s->%s(gap_length);", env_->LValue(downflow_id), kFlowGap); + out_cc->dec_indent(); - out_cc->println("}"); - out_cc->dec_indent(); - out_cc->println(""); - } + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); +} -void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc) - { - string proto = strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)", kNewData); +void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc) { + string proto = strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)", kNewData); - out_h->println("void %s;", proto.c_str()); + out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); - out_cc->println("if ( is_orig )"); - out_cc->inc_indent(); - out_cc->println("%s->%s(begin, end);", env_->LValue(upflow_id), kNewData); - out_cc->dec_indent(); - out_cc->println("else"); - out_cc->inc_indent(); - out_cc->println("%s->%s(begin, end);", env_->LValue(downflow_id), kNewData); - out_cc->dec_indent(); + out_cc->println("if ( is_orig )"); + out_cc->inc_indent(); + out_cc->println("%s->%s(begin, end);", env_->LValue(upflow_id), kNewData); + out_cc->dec_indent(); + out_cc->println("else"); + out_cc->inc_indent(); + out_cc->println("%s->%s(begin, end);", env_->LValue(downflow_id), kNewData); + out_cc->dec_indent(); - out_cc->println("}"); - out_cc->dec_indent(); - out_cc->println(""); - } + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); +} diff --git a/tools/binpac/src/pac_conn.h b/tools/binpac/src/pac_conn.h index edb10e7184..eb63cce603 100644 --- a/tools/binpac/src/pac_conn.h +++ b/tools/binpac/src/pac_conn.h @@ -4,31 +4,30 @@ #include "pac_analyzer.h" #include "pac_decl.h" -class ConnDecl : public AnalyzerDecl - { +class ConnDecl : public AnalyzerDecl { public: - ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist); - ~ConnDecl() override; + ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist); + ~ConnDecl() override; - void Prepare() override; + void Prepare() override; - Type* DataType() const { return data_type_; } + Type* DataType() const { return data_type_; } protected: - void AddBaseClass(vector* base_classes) const override; + void AddBaseClass(vector* base_classes) const override; - void GenProcessFunc(Output* out_h, Output* out_cc) override; - void GenGapFunc(Output* out_h, Output* out_cc) override; - void GenEOFFunc(Output* out_h, Output* out_cc) override; + void GenProcessFunc(Output* out_h, Output* out_cc) override; + void GenGapFunc(Output* out_h, Output* out_cc) override; + void GenEOFFunc(Output* out_h, Output* out_cc) override; - void GenPubDecls(Output* out_h, Output* out_cc) override; - void GenPrivDecls(Output* out_h, Output* out_cc) override; + void GenPubDecls(Output* out_h, Output* out_cc) override; + void GenPrivDecls(Output* out_h, Output* out_cc) override; - void ProcessFlowElement(AnalyzerFlow* flow_elem) override; - void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) override; + void ProcessFlowElement(AnalyzerFlow* flow_elem) override; + void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) override; - AnalyzerFlow* flows_[2]; - Type* data_type_; - }; + AnalyzerFlow* flows_[2]; + Type* data_type_; +}; #endif // pac_conn_h diff --git a/tools/binpac/src/pac_context.cc b/tools/binpac/src/pac_context.cc index 773014eeb7..59f3ee20bb 100644 --- a/tools/binpac/src/pac_context.cc +++ b/tools/binpac/src/pac_context.cc @@ -12,99 +12,83 @@ #include "pac_utils.h" ContextField::ContextField(ID* id, Type* type) - : Field(CONTEXT_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) - { - } + : Field(CONTEXT_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) {} AnalyzerContextDecl* AnalyzerContextDecl::current_analyzer_context_ = nullptr; -namespace - { -ParamList* ContextFieldsToParams(ContextFieldList* context_fields) - { - // Convert context fields to parameters - ParamList* params = new ParamList(); - foreach (i, ContextFieldList, context_fields) - { - ContextField* f = *i; - params->push_back(new Param(f->id()->clone(), f->type())); - } - return params; - } - } // namespace private +namespace { +ParamList* ContextFieldsToParams(ContextFieldList* context_fields) { + // Convert context fields to parameters + ParamList* params = new ParamList(); + foreach (i, ContextFieldList, context_fields) { + ContextField* f = *i; + params->push_back(new Param(f->id()->clone(), f->type())); + } + return params; +} +} // namespace AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_fields) - : TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields), - new DummyType()) - { - context_name_id_ = id; - if ( current_analyzer_context_ != nullptr ) - { - throw Exception(this, strfmt("multiple declaration of analyzer context; " - "the previous one is `%s'", - current_analyzer_context_->id()->Name())); - } - else - current_analyzer_context_ = this; + : TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields), new DummyType()) { + context_name_id_ = id; + if ( current_analyzer_context_ != nullptr ) { + throw Exception(this, strfmt("multiple declaration of analyzer context; " + "the previous one is `%s'", + current_analyzer_context_->id()->Name())); + } + else + current_analyzer_context_ = this; - context_fields_ = context_fields; + context_fields_ = context_fields; - param_type_ = new ParameterizedType(id_->clone(), nullptr); + param_type_ = new ParameterizedType(id_->clone(), nullptr); - flow_buffer_added_ = false; + flow_buffer_added_ = false; - DEBUG_MSG("Context type: %s\n", param_type()->class_name().c_str()); - } + DEBUG_MSG("Context type: %s\n", param_type()->class_name().c_str()); +} -AnalyzerContextDecl::~AnalyzerContextDecl() - { - delete context_name_id_; - delete param_type_; - delete_list(ContextFieldList, context_fields_); - } +AnalyzerContextDecl::~AnalyzerContextDecl() { + delete context_name_id_; + delete param_type_; + delete_list(ContextFieldList, context_fields_); +} -void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h) - { - GenNamespaceBegin(out_h); - TypeDecl::GenForwardDeclaration(out_h); - } +void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h) { + GenNamespaceBegin(out_h); + TypeDecl::GenForwardDeclaration(out_h); +} -void AnalyzerContextDecl::GenCode(Output* out_h, Output* out_cc) - { - GenNamespaceBegin(out_h); - GenNamespaceBegin(out_cc); - TypeDecl::GenCode(out_h, out_cc); - } +void AnalyzerContextDecl::GenCode(Output* out_h, Output* out_cc) { + GenNamespaceBegin(out_h); + GenNamespaceBegin(out_cc); + TypeDecl::GenCode(out_h, out_cc); +} -void AnalyzerContextDecl::GenNamespaceBegin(Output* out) const - { - out->println("namespace %s {", context_name_id()->Name()); - } +void AnalyzerContextDecl::GenNamespaceBegin(Output* out) const { + out->println("namespace %s {", context_name_id()->Name()); +} -void AnalyzerContextDecl::GenNamespaceEnd(Output* out) const - { - out->println("} // namespace %s", context_name_id()->Name()); - } +void AnalyzerContextDecl::GenNamespaceEnd(Output* out) const { + out->println("} // namespace %s", context_name_id()->Name()); +} -void AnalyzerContextDecl::AddFlowBuffer() - { - if ( flow_buffer_added_ ) - return; +void AnalyzerContextDecl::AddFlowBuffer() { + if ( flow_buffer_added_ ) + return; - AddParam(new Param(new ID(kFlowBufferVar), FlowDecl::flow_buffer_type()->Clone())); + AddParam(new Param(new ID(kFlowBufferVar), FlowDecl::flow_buffer_type()->Clone())); - flow_buffer_added_ = true; - } + flow_buffer_added_ = true; +} -string AnalyzerContextDecl::mb_buffer(Env* env) - { - // A hack. The orthodox way would be to build an Expr of - // context.flow_buffer_var, and then EvalExpr. - return strfmt("%s->%s()", env->RValue(analyzer_context_id), kFlowBufferVar); - } +string AnalyzerContextDecl::mb_buffer(Env* env) { + // A hack. The orthodox way would be to build an Expr of + // context.flow_buffer_var, and then EvalExpr. + return strfmt("%s->%s()", env->RValue(analyzer_context_id), kFlowBufferVar); +} -Type* DummyType::DoClone() const - { - // Fields will be copied in Type::Clone(). - return new DummyType(); - } +Type* DummyType::DoClone() const { + // Fields will be copied in Type::Clone(). + return new DummyType(); +} diff --git a/tools/binpac/src/pac_context.h b/tools/binpac/src/pac_context.h index 86b9354310..a52052e10e 100644 --- a/tools/binpac/src/pac_context.h +++ b/tools/binpac/src/pac_context.h @@ -23,84 +23,75 @@ // accessed as members of the cookie, such as // ``binpac_context.connection''. -class ContextField : public Field - { +class ContextField : public Field { public: - ContextField(ID* id, Type* type); - }; + ContextField(ID* id, Type* type); +}; -class AnalyzerContextDecl : public TypeDecl - { +class AnalyzerContextDecl : public TypeDecl { public: - AnalyzerContextDecl(ID* id, ContextFieldList* context_fields); - ~AnalyzerContextDecl() override; + AnalyzerContextDecl(ID* id, ContextFieldList* context_fields); + ~AnalyzerContextDecl() override; - void AddFlowBuffer(); + void AddFlowBuffer(); - const ID* context_name_id() const { return context_name_id_; } + const ID* context_name_id() const { return context_name_id_; } - // The type of analyzer context as a parameter - ParameterizedType* param_type() const { return param_type_; } + // The type of analyzer context as a parameter + ParameterizedType* param_type() const { return param_type_; } - void GenForwardDeclaration(Output* out_h) override; - void GenCode(Output* out_h, Output* out_cc) override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; - void GenNamespaceBegin(Output* out) const; - void GenNamespaceEnd(Output* out) const; + void GenNamespaceBegin(Output* out) const; + void GenNamespaceEnd(Output* out) const; private: - ID* context_name_id_; - ContextFieldList* context_fields_; - ParameterizedType* param_type_; - bool flow_buffer_added_; + ID* context_name_id_; + ContextFieldList* context_fields_; + ParameterizedType* param_type_; + bool flow_buffer_added_; - // static members + // static members public: - static AnalyzerContextDecl* current_analyzer_context() { return current_analyzer_context_; } + static AnalyzerContextDecl* current_analyzer_context() { return current_analyzer_context_; } - static string mb_buffer(Env* env); + static string mb_buffer(Env* env); private: - static AnalyzerContextDecl* current_analyzer_context_; - }; + static AnalyzerContextDecl* current_analyzer_context_; +}; -class DummyType : public Type - { +class DummyType : public Type { public: - DummyType() : Type(DUMMY) { } + DummyType() : Type(DUMMY) {} - bool DefineValueVar() const override { return false; } - string DataTypeStr() const override - { - ASSERT(0); - return ""; - } + bool DefineValueVar() const override { return false; } + string DataTypeStr() const override { + ASSERT(0); + return ""; + } - int StaticSize(Env* env) const override - { - ASSERT(0); - return -1; - } + int StaticSize(Env* env) const override { + ASSERT(0); + return -1; + } - bool ByteOrderSensitive() const override { return false; } + bool ByteOrderSensitive() const override { return false; } - bool IsPointerType() const override - { - ASSERT(0); - return false; - } + bool IsPointerType() const override { + ASSERT(0); + return false; + } - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override - { - ASSERT(0); - } + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override { ASSERT(0); } - // Generate code for computing the dynamic size of the type - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override { ASSERT(0); } + // Generate code for computing the dynamic size of the type + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override { ASSERT(0); } protected: - Type* DoClone() const override; - void DoMarkIncrementalInput() override { ASSERT(0); } - }; + Type* DoClone() const override; + void DoMarkIncrementalInput() override { ASSERT(0); } +}; #endif // pac_context_h diff --git a/tools/binpac/src/pac_cstr.cc b/tools/binpac/src/pac_cstr.cc index 69ca4f3526..cd3120a29a 100644 --- a/tools/binpac/src/pac_cstr.cc +++ b/tools/binpac/src/pac_cstr.cc @@ -3,129 +3,108 @@ #include "pac_dbg.h" #include "pac_exception.h" -namespace - { +namespace { -class EscapeException - { +class EscapeException { public: - explicit EscapeException(const string& s) { msg_ = s; } + explicit EscapeException(const string& s) { msg_ = s; } - const string& msg() const { return msg_; } + const string& msg() const { return msg_; } private: - string msg_; - }; + string msg_; +}; // Copied from util.cc of Zeek -int expand_escape(const char*& s) - { - switch ( *(s++) ) - { - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'a': - return '\a'; - case 'v': - return '\v'; +int expand_escape(const char*& s) { + switch ( *(s++) ) { + case 'b': return '\b'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'a': return '\a'; + case 'v': return '\v'; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { // \{1,3} - --s; // put back the first octal digit - const char* start = s; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': { // \{1,3} + --s; // put back the first octal digit + const char* start = s; - // Don't increment inside loop control - // because if isdigit() is a macro it might - // expand into multiple increments ... + // Don't increment inside loop control + // because if isdigit() is a macro it might + // expand into multiple increments ... - // Here we define a maximum length for escape sequence - // to allow easy handling of string like: "^H0" as - // "\0100". + // Here we define a maximum length for escape sequence + // to allow easy handling of string like: "^H0" as + // "\0100". - for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s); ++s, ++len ) - ; + for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s); ++s, ++len ) + ; - int result; - if ( sscanf(start, "%3o", &result) != 1 ) - throw EscapeException(strfmt("bad octal escape: \"%s", start)); + int result; + if ( sscanf(start, "%3o", &result) != 1 ) + throw EscapeException(strfmt("bad octal escape: \"%s", start)); - return result; - } + return result; + } - case 'x': - { /* \x */ - const char* start = s; + case 'x': { /* \x */ + const char* start = s; - // Look at most 2 characters, so that "\x0ddir" -> "^Mdir". - for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s); ++s, ++len ) - ; + // Look at most 2 characters, so that "\x0ddir" -> "^Mdir". + for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s); ++s, ++len ) + ; - int result; - if ( sscanf(start, "%2x", &result) != 1 ) - throw EscapeException(strfmt("bad hexadecimal escape: \"%s", start)); + int result; + if ( sscanf(start, "%2x", &result) != 1 ) + throw EscapeException(strfmt("bad hexadecimal escape: \"%s", start)); - return result; - } + return result; + } - default: - return s[-1]; - } - } + default: return s[-1]; + } +} - } // private namespace +} // namespace -ConstString::ConstString(const string& s) : str_(s) - { - // Copied from scan.l of Zeek - try - { - const char* text = str_.c_str(); - int len = strlen(text) + 1; - int i = 0; +ConstString::ConstString(const string& s) : str_(s) { + // Copied from scan.l of Zeek + try { + const char* text = str_.c_str(); + int len = strlen(text) + 1; + int i = 0; - char* new_s = new char[len]; + char* new_s = new char[len]; - // Skip leading quote. - for ( ++text; *text; ++text ) - { - if ( *text == '\\' ) - { - ++text; // skip '\' - new_s[i++] = expand_escape(text); - --text; // point to end of sequence - } - else - { - new_s[i++] = *text; - } - } - ASSERT(i < len); + // Skip leading quote. + for ( ++text; *text; ++text ) { + if ( *text == '\\' ) { + ++text; // skip '\' + new_s[i++] = expand_escape(text); + --text; // point to end of sequence + } + else { + new_s[i++] = *text; + } + } + ASSERT(i < len); - // Get rid of trailing quote. - ASSERT(new_s[i - 1] == '"'); - new_s[i - 1] = '\0'; + // Get rid of trailing quote. + ASSERT(new_s[i - 1] == '"'); + new_s[i - 1] = '\0'; - unescaped_ = new_s; - delete[] new_s; - } - catch ( EscapeException const& e ) - { - // Throw again with the object - throw Exception(this, e.msg().c_str()); - } - } + unescaped_ = new_s; + delete[] new_s; + } catch ( EscapeException const& e ) { + // Throw again with the object + throw Exception(this, e.msg().c_str()); + } +} diff --git a/tools/binpac/src/pac_cstr.h b/tools/binpac/src/pac_cstr.h index b9865e96d7..7443397329 100644 --- a/tools/binpac/src/pac_cstr.h +++ b/tools/binpac/src/pac_cstr.h @@ -3,21 +3,20 @@ #include "pac_common.h" -class ConstString : public Object - { +class ConstString : public Object { public: - ConstString(const string& s); + ConstString(const string& s); - // The string in its escaped form, with surrounding '"'s - const string& str() const { return str_; } - const char* c_str() const { return str_.c_str(); } + // The string in its escaped form, with surrounding '"'s + const string& str() const { return str_; } + const char* c_str() const { return str_.c_str(); } - // The unescaped string, without surrounding '"'s - const string& unescaped() const { return unescaped_; } + // The unescaped string, without surrounding '"'s + const string& unescaped() const { return unescaped_; } private: - string str_; - string unescaped_; - }; + string str_; + string unescaped_; +}; #endif // pac_cstr_h diff --git a/tools/binpac/src/pac_ctype.cc b/tools/binpac/src/pac_ctype.cc index a664756327..3ef8003472 100644 --- a/tools/binpac/src/pac_ctype.cc +++ b/tools/binpac/src/pac_ctype.cc @@ -1,21 +1,13 @@ #include "pac_ctype.h" -string CType::DeclareInstance(const string& var) const - { - return strfmt("%s %s", name().c_str(), var.c_str()); - } +string CType::DeclareInstance(const string& var) const { return strfmt("%s %s", name().c_str(), var.c_str()); } -string CType::DeclareConstReference(const string& var) const - { - return strfmt("%s const &%s", name().c_str(), var.c_str()); - } +string CType::DeclareConstReference(const string& var) const { + return strfmt("%s const &%s", name().c_str(), var.c_str()); +} -string CType::DeclareConstPointer(const string& var) const - { - return strfmt("%s const *%s", name().c_str(), var.c_str()); - } +string CType::DeclareConstPointer(const string& var) const { + return strfmt("%s const *%s", name().c_str(), var.c_str()); +} -string CType::DeclarePointer(const string& var) const - { - return strfmt("%s *%s", name().c_str(), var.c_str()); - } +string CType::DeclarePointer(const string& var) const { return strfmt("%s *%s", name().c_str(), var.c_str()); } diff --git a/tools/binpac/src/pac_ctype.h b/tools/binpac/src/pac_ctype.h index 4cf64bf25d..11ab0b8f82 100644 --- a/tools/binpac/src/pac_ctype.h +++ b/tools/binpac/src/pac_ctype.h @@ -4,20 +4,19 @@ #include "pac_common.h" // Represents a C++ type -class CType - { +class CType { public: - CType(const string& name); + CType(const string& name); - string name() const { return name_; } + string name() const { return name_; } - string DeclareInstance(const string& var) const; - string DeclareConstReference(const string& var) const; - string DeclareConstPointer(const string& var) const; - string DeclarePointer(const string& var) const; + string DeclareInstance(const string& var) const; + string DeclareConstReference(const string& var) const; + string DeclareConstPointer(const string& var) const; + string DeclarePointer(const string& var) const; protected: - string name_; - }; + string name_; +}; #endif // pac_ctype_h diff --git a/tools/binpac/src/pac_datadep.cc b/tools/binpac/src/pac_datadep.cc index a9a4f1adea..32567dcda5 100644 --- a/tools/binpac/src/pac_datadep.cc +++ b/tools/binpac/src/pac_datadep.cc @@ -4,70 +4,51 @@ #include "pac_id.h" #include "pac_type.h" -DataDepElement::DataDepElement(DDE_Type type) : dde_type_(type), in_traversal(false) { } +DataDepElement::DataDepElement(DDE_Type type) : dde_type_(type), in_traversal(false) {} -bool DataDepElement::Traverse(DataDepVisitor* visitor) - { - // Avoid infinite loop - if ( in_traversal ) - return true; - if ( ! visitor->PreProcess(this) ) - return false; +bool DataDepElement::Traverse(DataDepVisitor* visitor) { + // Avoid infinite loop + if ( in_traversal ) + return true; + if ( ! visitor->PreProcess(this) ) + return false; - in_traversal = true; - bool cont = DoTraverse(visitor); - in_traversal = false; + in_traversal = true; + bool cont = DoTraverse(visitor); + in_traversal = false; - if ( ! cont ) - return false; - if ( ! visitor->PostProcess(this) ) - return false; - return true; - } + if ( ! cont ) + return false; + if ( ! visitor->PostProcess(this) ) + return false; + return true; +} -Expr* DataDepElement::expr() - { - return static_cast(this); - } +Expr* DataDepElement::expr() { return static_cast(this); } -Type* DataDepElement::type() - { - return static_cast(this); - } +Type* DataDepElement::type() { return static_cast(this); } -bool RequiresAnalyzerContext::PreProcess(DataDepElement* element) - { - switch ( element->dde_type() ) - { - case DataDepElement::EXPR: - ProcessExpr(element->expr()); - break; - default: - break; - } +bool RequiresAnalyzerContext::PreProcess(DataDepElement* element) { + switch ( element->dde_type() ) { + case DataDepElement::EXPR: ProcessExpr(element->expr()); break; + default: break; + } - // Continue traversal until we know the answer is 'yes' - return ! requires_analyzer_context_; - } + // Continue traversal until we know the answer is 'yes' + return ! requires_analyzer_context_; +} -bool RequiresAnalyzerContext::PostProcess(DataDepElement* element) - { - return ! requires_analyzer_context_; - } +bool RequiresAnalyzerContext::PostProcess(DataDepElement* element) { return ! requires_analyzer_context_; } -void RequiresAnalyzerContext::ProcessExpr(Expr* expr) - { - if ( expr->expr_type() == Expr::EXPR_ID ) - { - requires_analyzer_context_ = (requires_analyzer_context_ || - *expr->id() == *analyzer_context_id || - *expr->id() == *context_macro_id); - } - } +void RequiresAnalyzerContext::ProcessExpr(Expr* expr) { + if ( expr->expr_type() == Expr::EXPR_ID ) { + requires_analyzer_context_ = + (requires_analyzer_context_ || *expr->id() == *analyzer_context_id || *expr->id() == *context_macro_id); + } +} -bool RequiresAnalyzerContext::compute(DataDepElement* element) - { - RequiresAnalyzerContext visitor; - element->Traverse(&visitor); - return visitor.requires_analyzer_context_; - } +bool RequiresAnalyzerContext::compute(DataDepElement* element) { + RequiresAnalyzerContext visitor; + element->Traverse(&visitor); + return visitor.requires_analyzer_context_; +} diff --git a/tools/binpac/src/pac_datadep.h b/tools/binpac/src/pac_datadep.h index 0b7a429f3d..184e2563b9 100644 --- a/tools/binpac/src/pac_datadep.h +++ b/tools/binpac/src/pac_datadep.h @@ -9,64 +9,60 @@ class DataDepVisitor; -class DataDepElement - { +class DataDepElement { public: - enum DDE_Type - { - ATTR, - CASEEXPR, - EXPR, - FIELD, - INPUT_BUFFER, - PARAM, - TYPE, - }; + enum DDE_Type { + ATTR, + CASEEXPR, + EXPR, + FIELD, + INPUT_BUFFER, + PARAM, + TYPE, + }; - DataDepElement(DDE_Type type); - virtual ~DataDepElement() { } + DataDepElement(DDE_Type type); + virtual ~DataDepElement() {} - // Returns whether to continue traversal - bool Traverse(DataDepVisitor* visitor); + // Returns whether to continue traversal + bool Traverse(DataDepVisitor* visitor); - // Returns whether to continue traversal - virtual bool DoTraverse(DataDepVisitor* visitor) = 0; + // Returns whether to continue traversal + virtual bool DoTraverse(DataDepVisitor* visitor) = 0; - DDE_Type dde_type() const { return dde_type_; } - Expr* expr(); - Type* type(); + DDE_Type dde_type() const { return dde_type_; } + Expr* expr(); + Type* type(); protected: - DDE_Type dde_type_; - bool in_traversal; - }; + DDE_Type dde_type_; + bool in_traversal; +}; -class DataDepVisitor - { +class DataDepVisitor { public: - virtual ~DataDepVisitor() { } - // Returns whether to continue traversal - virtual bool PreProcess(DataDepElement* element) = 0; - virtual bool PostProcess(DataDepElement* element) = 0; - }; + virtual ~DataDepVisitor() {} + // Returns whether to continue traversal + virtual bool PreProcess(DataDepElement* element) = 0; + virtual bool PostProcess(DataDepElement* element) = 0; +}; -class RequiresAnalyzerContext : public DataDepVisitor - { +class RequiresAnalyzerContext : public DataDepVisitor { public: - RequiresAnalyzerContext() : requires_analyzer_context_(false) { } + RequiresAnalyzerContext() : requires_analyzer_context_(false) {} - // Returns whether to continue traversal - bool PreProcess(DataDepElement* element) override; - bool PostProcess(DataDepElement* element) override; + // Returns whether to continue traversal + bool PreProcess(DataDepElement* element) override; + bool PostProcess(DataDepElement* element) override; - bool requires_analyzer_context() const { return requires_analyzer_context_; } + bool requires_analyzer_context() const { return requires_analyzer_context_; } - static bool compute(DataDepElement* element); + static bool compute(DataDepElement* element); protected: - void ProcessExpr(Expr* expr); + void ProcessExpr(Expr* expr); - bool requires_analyzer_context_; - }; + bool requires_analyzer_context_; +}; #endif // pac_datadep_h diff --git a/tools/binpac/src/pac_dataptr.cc b/tools/binpac/src/pac_dataptr.cc index 4ebb0dba42..1b3d19606c 100644 --- a/tools/binpac/src/pac_dataptr.cc +++ b/tools/binpac/src/pac_dataptr.cc @@ -5,56 +5,48 @@ #include "pac_output.h" #include "pac_utils.h" -DataPtr::DataPtr(Env* env, const ID* id, const int offset) : id_(id), offset_(offset) - { - if ( id_ ) - { - if ( ! env->Evaluated(id_) ) - throw ExceptionIDNotEvaluated(id_); +DataPtr::DataPtr(Env* env, const ID* id, const int offset) : id_(id), offset_(offset) { + if ( id_ ) { + if ( ! env->Evaluated(id_) ) + throw ExceptionIDNotEvaluated(id_); - if ( offset_ == 0 ) - ptr_expr_ = strfmt("%s", env->RValue(id_)); - else - ptr_expr_ = strfmt("(%s + %d)", env->RValue(id_), offset_); - } - else - ptr_expr_ = "(null id)"; - } + if ( offset_ == 0 ) + ptr_expr_ = strfmt("%s", env->RValue(id_)); + else + ptr_expr_ = strfmt("(%s + %d)", env->RValue(id_), offset_); + } + else + ptr_expr_ = "(null id)"; +} -int DataPtr::AbsOffset(const ID* base_ptr) const - { - return (id() == base_ptr) ? offset() : -1; - } +int DataPtr::AbsOffset(const ID* base_ptr) const { return (id() == base_ptr) ? offset() : -1; } -char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const - { - if ( AbsOffset(base_ptr) >= 0 ) - return nfmt("%d", offset()); - else - return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr)); - } +char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const { + if ( AbsOffset(base_ptr) >= 0 ) + return nfmt("%d", offset()); + else + return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr)); +} -void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size, - const char* data_name) const - { - ASSERT(id_); +void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size, const char* data_name) const { + ASSERT(id_); - out_cc->println("// Checking out-of-bound for \"%s\"", data_name); - out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", ptr_expr(), data_size, - env->RValue(end_of_data), ptr_expr(), data_size, ptr_expr()); + out_cc->println("// Checking out-of-bound for \"%s\"", data_name); + out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", ptr_expr(), data_size, env->RValue(end_of_data), + ptr_expr(), data_size, ptr_expr()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->inc_indent(); + out_cc->println("{"); - char* data_offset = AbsOffsetExpr(env, begin_of_data); + char* data_offset = AbsOffsetExpr(env, begin_of_data); - out_cc->println("// Handle out-of-bound condition"); - out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_name); - out_cc->println(" (%s) + (%s), ", data_offset, data_size); - out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->RValue(begin_of_data)); + out_cc->println("// Handle out-of-bound condition"); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_name); + out_cc->println(" (%s) + (%s), ", data_offset, data_size); + out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->RValue(begin_of_data)); - delete[] data_offset; + delete[] data_offset; - out_cc->println("}"); - out_cc->dec_indent(); - } + out_cc->println("}"); + out_cc->dec_indent(); +} diff --git a/tools/binpac/src/pac_dataptr.h b/tools/binpac/src/pac_dataptr.h index be8885fc89..1ad102f8a1 100644 --- a/tools/binpac/src/pac_dataptr.h +++ b/tools/binpac/src/pac_dataptr.h @@ -9,40 +9,36 @@ // A data pointer is represented by an data pointer variable // plus a constant offset. -class DataPtr - { +class DataPtr { public: - DataPtr(Env* env, const ID* arg_id, const int arg_off); - DataPtr(DataPtr const& x) { *this = x; } + DataPtr(Env* env, const ID* arg_id, const int arg_off); + DataPtr(DataPtr const& x) { *this = x; } - DataPtr const& operator=(DataPtr const& x) - { - id_ = x.id(); - offset_ = x.offset(); - ptr_expr_ = x.ptr_expr(); + DataPtr const& operator=(DataPtr const& x) { + id_ = x.id(); + offset_ = x.offset(); + ptr_expr_ = x.ptr_expr(); - return *this; - } + return *this; + } - const ID* id() const { return id_; } - int offset() const { return offset_; } + const ID* id() const { return id_; } + int offset() const { return offset_; } - const char* ptr_expr() const - { - ASSERT(id_); - return ptr_expr_.c_str(); - } + const char* ptr_expr() const { + ASSERT(id_); + return ptr_expr_.c_str(); + } - int AbsOffset(const ID* base_ptr) const; - char* AbsOffsetExpr(Env* env, const ID* base_ptr) const; + int AbsOffset(const ID* base_ptr) const; + char* AbsOffsetExpr(Env* env, const ID* base_ptr) const; - void GenBoundaryCheck(Output* out, Env* env, const char* data_size, - const char* data_name) const; + void GenBoundaryCheck(Output* out, Env* env, const char* data_size, const char* data_name) const; protected: - const ID* id_; - int offset_; - string ptr_expr_; - }; + const ID* id_; + int offset_; + string ptr_expr_; +}; #endif // pac_dataptr_h diff --git a/tools/binpac/src/pac_dataunit.cc b/tools/binpac/src/pac_dataunit.cc index df13f21025..a51ba4ccca 100644 --- a/tools/binpac/src/pac_dataunit.cc +++ b/tools/binpac/src/pac_dataunit.cc @@ -5,41 +5,33 @@ #include "pac_paramtype.h" #include "pac_varfield.h" -AnalyzerDataUnit::AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, - ExprList* context_params) - : AnalyzerElement(DATAUNIT), type_(type), id_(id), type_params_(type_params), - context_params_(context_params) - { - data_type_ = new ParameterizedType(id_, type_params_); - context_type_ = new ParameterizedType( - AnalyzerContextDecl::current_analyzer_context()->id()->clone(), context_params_); +AnalyzerDataUnit::AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params) + : AnalyzerElement(DATAUNIT), type_(type), id_(id), type_params_(type_params), context_params_(context_params) { + data_type_ = new ParameterizedType(id_, type_params_); + context_type_ = + new ParameterizedType(AnalyzerContextDecl::current_analyzer_context()->id()->clone(), context_params_); - dataunit_var_field_ = new ParseVarField(Field::CLASS_MEMBER, dataunit_id->clone(), data_type()); - context_var_field_ = new PrivVarField(analyzer_context_id->clone(), context_type()); - } + dataunit_var_field_ = new ParseVarField(Field::CLASS_MEMBER, dataunit_id->clone(), data_type()); + context_var_field_ = new PrivVarField(analyzer_context_id->clone(), context_type()); +} -AnalyzerDataUnit::~AnalyzerDataUnit() - { - delete dataunit_var_field_; - delete context_var_field_; - } +AnalyzerDataUnit::~AnalyzerDataUnit() { + delete dataunit_var_field_; + delete context_var_field_; +} -void AnalyzerDataUnit::Prepare(Env* env) - { - dataunit_var_field_->Prepare(env); - context_var_field_->Prepare(env); - } +void AnalyzerDataUnit::Prepare(Env* env) { + dataunit_var_field_->Prepare(env); + context_var_field_->Prepare(env); +} -void AnalyzerDataUnit::GenNewDataUnit(Output* out_cc, Env* env) - { - out_cc->println("%s = new %s(%s);", env->LValue(dataunit_id), data_type()->class_name().c_str(), - data_type()->EvalParameters(out_cc, env).c_str()); - } +void AnalyzerDataUnit::GenNewDataUnit(Output* out_cc, Env* env) { + out_cc->println("%s = new %s(%s);", env->LValue(dataunit_id), data_type()->class_name().c_str(), + data_type()->EvalParameters(out_cc, env).c_str()); +} -void AnalyzerDataUnit::GenNewContext(Output* out_cc, Env* env) - { - out_cc->println("%s = new %s(%s);", env->LValue(analyzer_context_id), - context_type()->class_name().c_str(), - context_type()->EvalParameters(out_cc, env).c_str()); - env->SetEvaluated(analyzer_context_id); - } +void AnalyzerDataUnit::GenNewContext(Output* out_cc, Env* env) { + out_cc->println("%s = new %s(%s);", env->LValue(analyzer_context_id), context_type()->class_name().c_str(), + context_type()->EvalParameters(out_cc, env).c_str()); + env->SetEvaluated(analyzer_context_id); +} diff --git a/tools/binpac/src/pac_dataunit.h b/tools/binpac/src/pac_dataunit.h index d9f16d1640..cf3d6edaa0 100644 --- a/tools/binpac/src/pac_dataunit.h +++ b/tools/binpac/src/pac_dataunit.h @@ -6,44 +6,39 @@ // The type and parameters of input data unit of a flow. For instance, the // data unit of a DCE/RPC flow is DCE_RPC_PDU. -class AnalyzerDataUnit : public AnalyzerElement - { +class AnalyzerDataUnit : public AnalyzerElement { public: - enum DataUnitType - { - DATAGRAM, - FLOWUNIT - }; - AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params); - ~AnalyzerDataUnit() override; + enum DataUnitType { DATAGRAM, FLOWUNIT }; + AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params); + ~AnalyzerDataUnit() override; - void Prepare(Env* env); + void Prepare(Env* env); - // Initializes dataunit_id - void GenNewDataUnit(Output* out_cc, Env* env); - // Initializes analyzer_context_id - void GenNewContext(Output* out_cc, Env* env); + // Initializes dataunit_id + void GenNewDataUnit(Output* out_cc, Env* env); + // Initializes analyzer_context_id + void GenNewContext(Output* out_cc, Env* env); - DataUnitType type() const { return type_; } - const ID* id() const { return id_; } - ExprList* type_params() const { return type_params_; } - ExprList* context_params() const { return context_params_; } + DataUnitType type() const { return type_; } + const ID* id() const { return id_; } + ExprList* type_params() const { return type_params_; } + ExprList* context_params() const { return context_params_; } - ParameterizedType* data_type() const { return data_type_; } - ParameterizedType* context_type() const { return context_type_; } + ParameterizedType* data_type() const { return data_type_; } + ParameterizedType* context_type() const { return context_type_; } - Field* dataunit_var_field() const { return dataunit_var_field_; } - Field* context_var_field() const { return context_var_field_; } + Field* dataunit_var_field() const { return dataunit_var_field_; } + Field* context_var_field() const { return context_var_field_; } private: - DataUnitType type_; - ID* id_; - ExprList* type_params_; - ExprList* context_params_; - ParameterizedType* data_type_; - ParameterizedType* context_type_; - Field* dataunit_var_field_; - Field* context_var_field_; - }; + DataUnitType type_; + ID* id_; + ExprList* type_params_; + ExprList* context_params_; + ParameterizedType* data_type_; + ParameterizedType* context_type_; + Field* dataunit_var_field_; + Field* context_var_field_; +}; #endif // pac_dataunit_h diff --git a/tools/binpac/src/pac_dbg.h b/tools/binpac/src/pac_dbg.h index 249a882a5c..04b8518096 100644 --- a/tools/binpac/src/pac_dbg.h +++ b/tools/binpac/src/pac_dbg.h @@ -6,7 +6,9 @@ extern bool FLAGS_pac_debug; -#define ASSERT(x) assert(x) -#define DEBUG_MSG(...) if ( FLAGS_pac_debug ) fprintf(stderr, __VA_ARGS__) +#define ASSERT(x) assert(x) +#define DEBUG_MSG(...) \ + if ( FLAGS_pac_debug ) \ + fprintf(stderr, __VA_ARGS__) #endif /* pac_dbg_h */ diff --git a/tools/binpac/src/pac_decl.cc b/tools/binpac/src/pac_decl.cc index fc0f74ea64..dbc93b1ab0 100644 --- a/tools/binpac/src/pac_decl.cc +++ b/tools/binpac/src/pac_decl.cc @@ -17,140 +17,120 @@ DeclList* Decl::decl_list_ = nullptr; Decl::DeclMap Decl::decl_map_; -Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(nullptr) - { - decl_map_[id_] = this; - if ( ! decl_list_ ) - decl_list_ = new DeclList(); - decl_list_->push_back(this); +Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(nullptr) { + decl_map_[id_] = this; + if ( ! decl_list_ ) + decl_list_ = new DeclList(); + decl_list_->push_back(this); - DEBUG_MSG("Finished Decl %s\n", id_->Name()); + DEBUG_MSG("Finished Decl %s\n", id_->Name()); - analyzer_context_ = nullptr; - } + analyzer_context_ = nullptr; +} -Decl::~Decl() - { - delete id_; - delete_list(AttrList, attrlist_); - } +Decl::~Decl() { + delete id_; + delete_list(AttrList, attrlist_); +} -void Decl::AddAttrs(AttrList* attrs) - { - if ( ! attrs ) - return; - if ( ! attrlist_ ) - attrlist_ = new AttrList(); - foreach (i, AttrList, attrs) - { - attrlist_->push_back(*i); - ProcessAttr(*i); - } - } +void Decl::AddAttrs(AttrList* attrs) { + if ( ! attrs ) + return; + if ( ! attrlist_ ) + attrlist_ = new AttrList(); + foreach (i, AttrList, attrs) { + attrlist_->push_back(*i); + ProcessAttr(*i); + } +} -void Decl::ProcessAttr(Attr* attr) - { - throw Exception(attr, "unhandled attribute"); - } +void Decl::ProcessAttr(Attr* attr) { throw Exception(attr, "unhandled attribute"); } -void Decl::SetAnalyzerContext() - { - analyzer_context_ = AnalyzerContextDecl::current_analyzer_context(); - if ( ! analyzer_context_ ) - { - throw Exception(this, "analyzer context not defined"); - } - } +void Decl::SetAnalyzerContext() { + analyzer_context_ = AnalyzerContextDecl::current_analyzer_context(); + if ( ! analyzer_context_ ) { + throw Exception(this, "analyzer context not defined"); + } +} -void Decl::ProcessDecls(Output* out_h, Output* out_cc) - { - if ( ! decl_list_ ) - return; +void Decl::ProcessDecls(Output* out_h, Output* out_cc) { + if ( ! decl_list_ ) + return; - foreach (i, DeclList, decl_list_) - { - Decl* decl = *i; - current_decl_id = decl->id(); - decl->Prepare(); - } + foreach (i, DeclList, decl_list_) { + Decl* decl = *i; + current_decl_id = decl->id(); + decl->Prepare(); + } - foreach (i, DeclList, decl_list_) - { - Decl* decl = *i; - current_decl_id = decl->id(); - decl->GenExternDeclaration(out_h); - } + foreach (i, DeclList, decl_list_) { + Decl* decl = *i; + current_decl_id = decl->id(); + decl->GenExternDeclaration(out_h); + } - out_h->println("namespace binpac {\n"); - out_cc->println("namespace binpac {\n"); + out_h->println("namespace binpac {\n"); + out_cc->println("namespace binpac {\n"); - AnalyzerContextDecl* analyzer_context = AnalyzerContextDecl::current_analyzer_context(); + AnalyzerContextDecl* analyzer_context = AnalyzerContextDecl::current_analyzer_context(); - foreach (i, DeclList, decl_list_) - { - Decl* decl = *i; - current_decl_id = decl->id(); - decl->GenForwardDeclaration(out_h); - } + foreach (i, DeclList, decl_list_) { + Decl* decl = *i; + current_decl_id = decl->id(); + decl->GenForwardDeclaration(out_h); + } - if ( analyzer_context ) - analyzer_context->GenNamespaceEnd(out_h); + if ( analyzer_context ) + analyzer_context->GenNamespaceEnd(out_h); - out_h->println(""); + out_h->println(""); - foreach (i, DeclList, decl_list_) - { - Decl* decl = *i; - current_decl_id = decl->id(); - decl->GenCode(out_h, out_cc); - } + foreach (i, DeclList, decl_list_) { + Decl* decl = *i; + current_decl_id = decl->id(); + decl->GenCode(out_h, out_cc); + } - if ( analyzer_context ) - { - analyzer_context->GenNamespaceEnd(out_h); - analyzer_context->GenNamespaceEnd(out_cc); - } + if ( analyzer_context ) { + analyzer_context->GenNamespaceEnd(out_h); + analyzer_context->GenNamespaceEnd(out_cc); + } - out_h->println("} // namespace binpac"); - out_cc->println("} // namespace binpac"); - } + out_h->println("} // namespace binpac"); + out_cc->println("} // namespace binpac"); +} -Decl* Decl::LookUpDecl(const ID* id) - { - DeclMap::iterator it = decl_map_.find(id); - if ( it == decl_map_.end() ) - return nullptr; - return it->second; - } +Decl* Decl::LookUpDecl(const ID* id) { + DeclMap::iterator it = decl_map_.find(id); + if ( it == decl_map_.end() ) + return nullptr; + return it->second; +} int HelperDecl::helper_id_seq = 0; HelperDecl::HelperDecl(HelperType helper_type, ID* context_id, EmbeddedCode* code) - : Decl(new ID(strfmt("helper_%d", ++helper_id_seq)), HELPER), helper_type_(helper_type), - context_id_(context_id), code_(code) - { - } + : Decl(new ID(strfmt("helper_%d", ++helper_id_seq)), HELPER), + helper_type_(helper_type), + context_id_(context_id), + code_(code) {} -HelperDecl::~HelperDecl() - { - delete context_id_; - delete code_; - } +HelperDecl::~HelperDecl() { + delete context_id_; + delete code_; +} -void HelperDecl::Prepare() - { - // Do nothing - } +void HelperDecl::Prepare() { + // Do nothing +} -void HelperDecl::GenExternDeclaration(Output* out_h) - { - if ( helper_type_ == EXTERN ) - code_->GenCode(out_h, global_env()); - } +void HelperDecl::GenExternDeclaration(Output* out_h) { + if ( helper_type_ == EXTERN ) + code_->GenCode(out_h, global_env()); +} -void HelperDecl::GenCode(Output* out_h, Output* out_cc) - { - Env* env = global_env(); +void HelperDecl::GenCode(Output* out_h, Output* out_cc) { + Env* env = global_env(); #if 0 if ( context_id_ ) @@ -172,12 +152,12 @@ void HelperDecl::GenCode(Output* out_h, Output* out_cc) } #endif - if ( helper_type_ == HEADER ) - code_->GenCode(out_h, env); - else if ( helper_type_ == CODE ) - code_->GenCode(out_cc, env); - else if ( helper_type_ == EXTERN ) - ; // do nothing - else - ASSERT(0); - } + if ( helper_type_ == HEADER ) + code_->GenCode(out_h, env); + else if ( helper_type_ == CODE ) + code_->GenCode(out_cc, env); + else if ( helper_type_ == EXTERN ) + ; // do nothing + else + ASSERT(0); +} diff --git a/tools/binpac/src/pac_decl.h b/tools/binpac/src/pac_decl.h index 39b84dc614..f3c4426b3c 100644 --- a/tools/binpac/src/pac_decl.h +++ b/tools/binpac/src/pac_decl.h @@ -4,93 +4,77 @@ #include "pac_common.h" #include "pac_id.h" -class Decl : public Object - { +class Decl : public Object { public: - // Note: ANALYZER is not for AnalyzerDecl (which is an - // abstract class) , but for AnalyzerContextDecl. - enum DeclType - { - ENUM, - LET, - TYPE, - FUNC, - CONN, - FLOW, - ANALYZER, - HELPER, - REGEX - }; + // Note: ANALYZER is not for AnalyzerDecl (which is an + // abstract class) , but for AnalyzerContextDecl. + enum DeclType { ENUM, LET, TYPE, FUNC, CONN, FLOW, ANALYZER, HELPER, REGEX }; - Decl(ID* id, DeclType decl_type); - virtual ~Decl(); + Decl(ID* id, DeclType decl_type); + virtual ~Decl(); - const ID* id() const { return id_; } - DeclType decl_type() const { return decl_type_; } - AnalyzerContextDecl* analyzer_context() const { return analyzer_context_; } + const ID* id() const { return id_; } + DeclType decl_type() const { return decl_type_; } + AnalyzerContextDecl* analyzer_context() const { return analyzer_context_; } - // NULL except for TypeDecl or AnalyzerDecl - virtual Env* env() const { return nullptr; } + // NULL except for TypeDecl or AnalyzerDecl + virtual Env* env() const { return nullptr; } - virtual void Prepare() = 0; + virtual void Prepare() = 0; - // Generate declarations out of the "binpac" namespace - virtual void GenExternDeclaration(Output* out_h) - { /* do nothing */ - } + // Generate declarations out of the "binpac" namespace + virtual void GenExternDeclaration(Output* out_h) { /* do nothing */ + } - // Generate declarations before definition of classes - virtual void GenForwardDeclaration(Output* out_h) = 0; + // Generate declarations before definition of classes + virtual void GenForwardDeclaration(Output* out_h) = 0; - virtual void GenCode(Output* out_h, Output* out_cc) = 0; + virtual void GenCode(Output* out_h, Output* out_cc) = 0; - void TakeExprList(); - void AddAttrs(AttrList* attrlist); - void SetAnalyzerContext(); + void TakeExprList(); + void AddAttrs(AttrList* attrlist); + void SetAnalyzerContext(); protected: - virtual void ProcessAttr(Attr* a); + virtual void ProcessAttr(Attr* a); - ID* id_; - DeclType decl_type_; - AttrList* attrlist_; - AnalyzerContextDecl* analyzer_context_; + ID* id_; + DeclType decl_type_; + AttrList* attrlist_; + AnalyzerContextDecl* analyzer_context_; public: - static void ProcessDecls(Output* out_h, Output* out_cc); - static Decl* LookUpDecl(const ID* id); + static void ProcessDecls(Output* out_h, Output* out_cc); + static Decl* LookUpDecl(const ID* id); private: - static DeclList* decl_list_; - typedef map DeclMap; - static DeclMap decl_map_; - }; + static DeclList* decl_list_; + typedef map DeclMap; + static DeclMap decl_map_; +}; -class HelperDecl : public Decl - { +class HelperDecl : public Decl { public: - enum HelperType - { - HEADER, - CODE, - EXTERN, - }; - HelperDecl(HelperType type, ID* context_id, EmbeddedCode* code); - ~HelperDecl() override; + enum HelperType { + HEADER, + CODE, + EXTERN, + }; + HelperDecl(HelperType type, ID* context_id, EmbeddedCode* code); + ~HelperDecl() override; - void Prepare() override; - void GenExternDeclaration(Output* out_h) override; - void GenForwardDeclaration(Output* out_h) override - { /* do nothing */ - } - void GenCode(Output* out_h, Output* out_cc) override; + void Prepare() override; + void GenExternDeclaration(Output* out_h) override; + void GenForwardDeclaration(Output* out_h) override { /* do nothing */ + } + void GenCode(Output* out_h, Output* out_cc) override; private: - HelperType helper_type_; - ID* context_id_; - EmbeddedCode* code_; + HelperType helper_type_; + ID* context_id_; + EmbeddedCode* code_; - static int helper_id_seq; - }; + static int helper_id_seq; +}; #endif // pac_decl_h diff --git a/tools/binpac/src/pac_embedded.cc b/tools/binpac/src/pac_embedded.cc index 9c10c594e2..48dc39143e 100644 --- a/tools/binpac/src/pac_embedded.cc +++ b/tools/binpac/src/pac_embedded.cc @@ -4,74 +4,52 @@ #include "pac_output.h" #include "pac_primitive.h" -EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(nullptr) { } +EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(nullptr) {} -EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive* primitive) - : s_(""), primitive_(primitive) { } +EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive* primitive) : s_(""), primitive_(primitive) {} -EmbeddedCodeSegment::~EmbeddedCodeSegment() - { - delete primitive_; - } +EmbeddedCodeSegment::~EmbeddedCodeSegment() { delete primitive_; } -string EmbeddedCodeSegment::ToCode(Env* env) - { - if ( primitive_ && s_.empty() ) - s_ = primitive_->ToCode(env); - return s_; - } +string EmbeddedCodeSegment::ToCode(Env* env) { + if ( primitive_ && s_.empty() ) + s_ = primitive_->ToCode(env); + return s_; +} -EmbeddedCode::EmbeddedCode() - { - segments_ = new EmbeddedCodeSegmentList(); - } +EmbeddedCode::EmbeddedCode() { segments_ = new EmbeddedCodeSegmentList(); } -EmbeddedCode::~EmbeddedCode() - { - delete_list(EmbeddedCodeSegmentList, segments_); - } +EmbeddedCode::~EmbeddedCode() { delete_list(EmbeddedCodeSegmentList, segments_); } -void EmbeddedCode::Append(int atom) - { - current_segment_ += static_cast(atom); - } +void EmbeddedCode::Append(int atom) { current_segment_ += static_cast(atom); } -void EmbeddedCode::Append(const char* str) - { - current_segment_ += str; - } +void EmbeddedCode::Append(const char* str) { current_segment_ += str; } -void EmbeddedCode::Append(PacPrimitive* primitive) - { - if ( ! current_segment_.empty() ) - { - segments_->push_back(new EmbeddedCodeSegment(current_segment_)); - current_segment_ = ""; - } - segments_->push_back(new EmbeddedCodeSegment(primitive)); - } +void EmbeddedCode::Append(PacPrimitive* primitive) { + if ( ! current_segment_.empty() ) { + segments_->push_back(new EmbeddedCodeSegment(current_segment_)); + current_segment_ = ""; + } + segments_->push_back(new EmbeddedCodeSegment(primitive)); +} -void EmbeddedCode::GenCode(Output* out, Env* env) - { - if ( ! current_segment_.empty() ) - { - segments_->push_back(new EmbeddedCodeSegment(current_segment_)); - current_segment_ = ""; - } +void EmbeddedCode::GenCode(Output* out, Env* env) { + if ( ! current_segment_.empty() ) { + segments_->push_back(new EmbeddedCodeSegment(current_segment_)); + current_segment_ = ""; + } - // TODO: return to the generated file after embedded code - // out->print("#line %d \"%s\"\n", line_num, filename.c_str()); + // TODO: return to the generated file after embedded code + // out->print("#line %d \"%s\"\n", line_num, filename.c_str()); - // Allow use of RValue for undefined ID, in which case the - // ID's name is used as its RValue - env->set_allow_undefined_id(true); + // Allow use of RValue for undefined ID, in which case the + // ID's name is used as its RValue + env->set_allow_undefined_id(true); - foreach (i, EmbeddedCodeSegmentList, segments_) - { - EmbeddedCodeSegment* segment = *i; - out->print("%s", segment->ToCode(env).c_str()); - } + foreach (i, EmbeddedCodeSegmentList, segments_) { + EmbeddedCodeSegment* segment = *i; + out->print("%s", segment->ToCode(env).c_str()); + } - env->set_allow_undefined_id(false); - out->print("\n"); - } + env->set_allow_undefined_id(false); + out->print("\n"); +} diff --git a/tools/binpac/src/pac_embedded.h b/tools/binpac/src/pac_embedded.h index 81a4f091a0..93403411b2 100644 --- a/tools/binpac/src/pac_embedded.h +++ b/tools/binpac/src/pac_embedded.h @@ -3,40 +3,38 @@ #include "pac_common.h" -class EmbeddedCodeSegment - { +class EmbeddedCodeSegment { public: - explicit EmbeddedCodeSegment(const string& s); - explicit EmbeddedCodeSegment(PacPrimitive* primitive); - ~EmbeddedCodeSegment(); + explicit EmbeddedCodeSegment(const string& s); + explicit EmbeddedCodeSegment(PacPrimitive* primitive); + ~EmbeddedCodeSegment(); - string ToCode(Env* env); + string ToCode(Env* env); private: - string s_; - PacPrimitive* primitive_; - }; + string s_; + PacPrimitive* primitive_; +}; typedef vector EmbeddedCodeSegmentList; -class EmbeddedCode : public Object - { +class EmbeddedCode : public Object { public: - EmbeddedCode(); - ~EmbeddedCode(); + EmbeddedCode(); + ~EmbeddedCode(); - // Append a character - void Append(int atom); - void Append(const char* str); + // Append a character + void Append(int atom); + void Append(const char* str); - // Append a PAC primitive - void Append(PacPrimitive* primitive); + // Append a PAC primitive + void Append(PacPrimitive* primitive); - void GenCode(Output* out, Env* env); + void GenCode(Output* out, Env* env); private: - string current_segment_; - EmbeddedCodeSegmentList* segments_; - }; + string current_segment_; + EmbeddedCodeSegmentList* segments_; +}; #endif // pac_embedded_h diff --git a/tools/binpac/src/pac_enum.cc b/tools/binpac/src/pac_enum.cc index d52b9ea32e..5a017820c7 100644 --- a/tools/binpac/src/pac_enum.cc +++ b/tools/binpac/src/pac_enum.cc @@ -6,61 +6,52 @@ #include "pac_output.h" #include "pac_typedecl.h" -Enum::Enum(ID* id, Expr* expr) : id_(id), expr_(expr) { } +Enum::Enum(ID* id, Expr* expr) : id_(id), expr_(expr) {} -Enum::~Enum() - { - delete id_; - delete expr_; - } +Enum::~Enum() { + delete id_; + delete expr_; +} -void Enum::GenHeader(Output* out_h, int* pval) - { - ASSERT(pval); - if ( expr_ ) - { - if ( ! expr_->ConstFold(global_env(), pval) ) - throw ExceptionNonConstExpr(expr_); - out_h->println("%s = %d,", id_->Name(), *pval); - } - else - out_h->println("%s,", id_->Name()); - global_env()->AddConstID(id_, *pval); - } +void Enum::GenHeader(Output* out_h, int* pval) { + ASSERT(pval); + if ( expr_ ) { + if ( ! expr_->ConstFold(global_env(), pval) ) + throw ExceptionNonConstExpr(expr_); + out_h->println("%s = %d,", id_->Name(), *pval); + } + else + out_h->println("%s,", id_->Name()); + global_env()->AddConstID(id_, *pval); +} -EnumDecl::EnumDecl(ID* id, EnumList* enumlist) : Decl(id, ENUM), enumlist_(enumlist) - { - ID* type_id = id->clone(); - datatype_ = new ExternType(type_id, ExternType::NUMBER); - extern_typedecl_ = new TypeDecl(type_id, nullptr, datatype_); - } +EnumDecl::EnumDecl(ID* id, EnumList* enumlist) : Decl(id, ENUM), enumlist_(enumlist) { + ID* type_id = id->clone(); + datatype_ = new ExternType(type_id, ExternType::NUMBER); + extern_typedecl_ = new TypeDecl(type_id, nullptr, datatype_); +} -EnumDecl::~EnumDecl() - { - delete_list(EnumList, enumlist_); - delete extern_typedecl_; - } +EnumDecl::~EnumDecl() { + delete_list(EnumList, enumlist_); + delete extern_typedecl_; +} -void EnumDecl::Prepare() - { - // Do nothing - } +void EnumDecl::Prepare() { + // Do nothing +} -void EnumDecl::GenForwardDeclaration(Output* out_h) - { - out_h->println("enum %s {", id_->Name()); - out_h->inc_indent(); - int c = 0; - foreach (i, EnumList, enumlist_) - { - (*i)->GenHeader(out_h, &c); - ++c; - } - out_h->dec_indent(); - out_h->println("};"); - } +void EnumDecl::GenForwardDeclaration(Output* out_h) { + out_h->println("enum %s {", id_->Name()); + out_h->inc_indent(); + int c = 0; + foreach (i, EnumList, enumlist_) { + (*i)->GenHeader(out_h, &c); + ++c; + } + out_h->dec_indent(); + out_h->println("};"); +} -void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */) - { - // Do nothing - } +void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */) { + // Do nothing +} diff --git a/tools/binpac/src/pac_enum.h b/tools/binpac/src/pac_enum.h index 1f3b8d9cca..fa7fdec776 100644 --- a/tools/binpac/src/pac_enum.h +++ b/tools/binpac/src/pac_enum.h @@ -3,35 +3,33 @@ #include "pac_decl.h" -class Enum - { +class Enum { public: - Enum(ID* id, Expr* expr = 0); - ~Enum(); + Enum(ID* id, Expr* expr = 0); + ~Enum(); - void GenHeader(Output* out_h, int* pval); + void GenHeader(Output* out_h, int* pval); private: - ID* id_; - Expr* expr_; - }; + ID* id_; + Expr* expr_; +}; -class EnumDecl : public Decl - { +class EnumDecl : public Decl { public: - EnumDecl(ID* id, EnumList* enumlist); - ~EnumDecl() override; + EnumDecl(ID* id, EnumList* enumlist); + ~EnumDecl() override; - Type* DataType() const { return datatype_; } + Type* DataType() const { return datatype_; } - void Prepare() override; - void GenForwardDeclaration(Output* out_h) override; - void GenCode(Output* out_h, Output* out_cc) override; + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; private: - EnumList* enumlist_; - Type* datatype_; - TypeDecl* extern_typedecl_; - }; + EnumList* enumlist_; + Type* datatype_; + TypeDecl* extern_typedecl_; +}; #endif // pac_enum_h diff --git a/tools/binpac/src/pac_exception.cc b/tools/binpac/src/pac_exception.cc index 43232c03aa..c985338796 100644 --- a/tools/binpac/src/pac_exception.cc +++ b/tools/binpac/src/pac_exception.cc @@ -4,75 +4,58 @@ #include "pac_id.h" #include "pac_utils.h" -Exception::Exception(const Object* o, string msg) - { - if ( o ) - { - msg_ = o->Location(); - msg_ += ": error : "; - } +Exception::Exception(const Object* o, string msg) { + if ( o ) { + msg_ = o->Location(); + msg_ += ": error : "; + } - msg_ += msg; + msg_ += msg; - if ( FLAGS_pac_debug ) - { - DEBUG_MSG("Exception: %s\n", msg_.c_str()); - abort(); - } - } + if ( FLAGS_pac_debug ) { + DEBUG_MSG("Exception: %s\n", msg_.c_str()); + abort(); + } +} -ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) : Exception(id), id_(id) - { - append(strfmt("`%s' undeclared", id_->Name())); - } +ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) : Exception(id), id_(id) { + append(strfmt("`%s' undeclared", id_->Name())); +} -ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) : Exception(id), id_(id) - { - append(strfmt("`%s' redefined", id_->Name())); - } +ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) : Exception(id), id_(id) { + append(strfmt("`%s' redefined", id_->Name())); +} -ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) : Exception(id), id_(id) - { - append(strfmt("ID `%s' not evaluated before used", id->Name())); - } +ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) : Exception(id), id_(id) { + append(strfmt("ID `%s' not evaluated before used", id->Name())); +} -ExceptionIDNotField::ExceptionIDNotField(const ID* id) : Exception(id), id_(id) - { - append(strfmt("ID `%s' is not a field", id_->Name())); - } +ExceptionIDNotField::ExceptionIDNotField(const ID* id) : Exception(id), id_(id) { + append(strfmt("ID `%s' is not a field", id_->Name())); +} ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id, const ID* member_id) - : Exception(member_id), type_id_(type_id), member_id_(member_id) - { - append(strfmt("type %s does not have member `%s'", type_id_->Name(), member_id_->Name())); - } + : Exception(member_id), type_id_(type_id), member_id_(member_id) { + append(strfmt("type %s does not have member `%s'", type_id_->Name(), member_id_->Name())); +} -ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) : Exception(id), id_(id) - { - append(strfmt("cyclic dependence through `%s'", id_->Name())); - } +ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) : Exception(id), id_(id) { + append(strfmt("cyclic dependence through `%s'", id_->Name())); +} -ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) : Exception(o) - { - append(msg.c_str()); - } +ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) : Exception(o) { append(msg.c_str()); } -ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) : Exception(expr), expr(expr) - { - append(strfmt("Expression `%s' is not constant", expr->orig())); - } +ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) : Exception(expr), expr(expr) { + append(strfmt("Expression `%s' is not constant", expr->orig())); +} -ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr) - : Exception(expr), expr(expr) - { - append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index", - expr->orig())); - } +ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr) : Exception(expr), expr(expr) { + append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index", expr->orig())); +} -ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr) - : Exception(expr), expr(expr) - { - append(strfmt("Expression `%s' as a case index is outside the numeric limit of the type used " - "for the switch expression", - expr->orig())); - } +ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr) : Exception(expr), expr(expr) { + append( + strfmt("Expression `%s' as a case index is outside the numeric limit of the type used " + "for the switch expression", + expr->orig())); +} diff --git a/tools/binpac/src/pac_exception.h b/tools/binpac/src/pac_exception.h index 08937e7e7a..c3860539a1 100644 --- a/tools/binpac/src/pac_exception.h +++ b/tools/binpac/src/pac_exception.h @@ -6,108 +6,97 @@ using namespace std; #include "pac_common.h" -class Exception - { +class Exception { public: - Exception(const Object* o, string msg = ""); + Exception(const Object* o, string msg = ""); - const char* msg() const { return msg_.c_str(); } - void append(string s) { msg_ += s; } + const char* msg() const { return msg_.c_str(); } + void append(string s) { msg_ += s; } private: - string msg_; - }; + string msg_; +}; -class ExceptionIDNotFound : public Exception - { +class ExceptionIDNotFound : public Exception { public: - ExceptionIDNotFound(const ID* id); - const ID* id() const { return id_; } + ExceptionIDNotFound(const ID* id); + const ID* id() const { return id_; } private: - const ID* id_; - }; + const ID* id_; +}; -class ExceptionIDRedefinition : public Exception - { +class ExceptionIDRedefinition : public Exception { public: - ExceptionIDRedefinition(const ID* id); - const ID* id() const { return id_; } + ExceptionIDRedefinition(const ID* id); + const ID* id() const { return id_; } private: - const ID* id_; - }; + const ID* id_; +}; -class ExceptionIDNotEvaluated : public Exception - { +class ExceptionIDNotEvaluated : public Exception { public: - ExceptionIDNotEvaluated(const ID* id); - const ID* id() const { return id_; } + ExceptionIDNotEvaluated(const ID* id); + const ID* id() const { return id_; } private: - const ID* id_; - }; + const ID* id_; +}; -class ExceptionCyclicDependence : public Exception - { +class ExceptionCyclicDependence : public Exception { public: - ExceptionCyclicDependence(const ID* id); - const ID* id() const { return id_; } + ExceptionCyclicDependence(const ID* id); + const ID* id() const { return id_; } private: - const ID* id_; - }; + const ID* id_; +}; -class ExceptionPaddingError : public Exception - { +class ExceptionPaddingError : public Exception { public: - ExceptionPaddingError(const Object* o, string msg); - }; + ExceptionPaddingError(const Object* o, string msg); +}; -class ExceptionIDNotField : public Exception - { +class ExceptionIDNotField : public Exception { public: - ExceptionIDNotField(const ID* id); - const ID* id() const { return id_; } + ExceptionIDNotField(const ID* id); + const ID* id() const { return id_; } private: - const ID* id_; - }; + const ID* id_; +}; -class ExceptionMemberNotFound : public Exception - { +class ExceptionMemberNotFound : public Exception { public: - ExceptionMemberNotFound(const ID* type_id, const ID* member_id); + ExceptionMemberNotFound(const ID* type_id, const ID* member_id); private: - const ID *type_id_, *member_id_; - }; + const ID *type_id_, *member_id_; +}; -class ExceptionNonConstExpr : public Exception - { +class ExceptionNonConstExpr : public Exception { public: - ExceptionNonConstExpr(const Expr* expr); + ExceptionNonConstExpr(const Expr* expr); private: - const Expr* expr; - }; + const Expr* expr; +}; -class ExceptionInvalidCaseSizeExpr : public Exception - { +class ExceptionInvalidCaseSizeExpr : public Exception { public: - ExceptionInvalidCaseSizeExpr(const Expr* expr); + ExceptionInvalidCaseSizeExpr(const Expr* expr); private: - const Expr* expr; - }; + const Expr* expr; +}; -class ExceptionInvalidCaseLimitExpr : public Exception - { +class ExceptionInvalidCaseLimitExpr : public Exception { public: - ExceptionInvalidCaseLimitExpr(const Expr* expr); + ExceptionInvalidCaseLimitExpr(const Expr* expr); private: - const Expr* expr; - }; + const Expr* expr; +}; #endif /* pac_exception_h */ diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index ca51b0282d..98fd1e29f7 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -13,37 +13,33 @@ #include "pac_typedecl.h" #include "pac_utils.h" -string OrigExprList(ExprList* list) - { - bool first = true; - string str; - foreach (i, ExprList, list) - { - Expr* expr = *i; - if ( first ) - first = false; - else - str += ", "; - str += expr->orig(); - } - return str; - } +string OrigExprList(ExprList* list) { + bool first = true; + string str; + foreach (i, ExprList, list) { + Expr* expr = *i; + if ( first ) + first = false; + else + str += ", "; + str += expr->orig(); + } + return str; +} -string EvalExprList(ExprList* exprlist, Output* out, Env* env) - { - string val_list(""); - bool first = true; +string EvalExprList(ExprList* exprlist, Output* out, Env* env) { + string val_list(""); + bool first = true; - foreach (i, ExprList, exprlist) - { - if ( ! first ) - val_list += ", "; - val_list += (*i)->EvalExpr(out, env); - first = false; - } + foreach (i, ExprList, exprlist) { + if ( ! first ) + val_list += ", "; + val_list += (*i)->EvalExpr(out, env); + first = false; + } - return val_list; - } + return val_list; +} static const char* expr_fmt[] = { #define EXPR_DEF(type, num_op, fmt) fmt, @@ -51,994 +47,806 @@ static const char* expr_fmt[] = { #undef EXPR_DEF }; -void Expr::init() - { - id_ = nullptr; - num_ = nullptr; - cstr_ = nullptr; - regex_ = nullptr; - num_operands_ = 0; - operand_[0] = nullptr; - operand_[1] = nullptr; - operand_[2] = nullptr; - args_ = nullptr; - cases_ = nullptr; - } - -Expr::Expr(ID* arg_id) : DataDepElement(EXPR) - { - init(); - expr_type_ = EXPR_ID; - id_ = arg_id; - num_operands_ = 0; - orig_ = strfmt("%s", id_->Name()); - } - -Expr::Expr(Number* arg_num) : DataDepElement(EXPR) - { - init(); - expr_type_ = EXPR_NUM; - num_ = arg_num; - num_operands_ = 0; - orig_ = strfmt("((int) %s)", num_->Str()); - } - -Expr::Expr(ConstString* cstr) : DataDepElement(EXPR) - { - init(); - expr_type_ = EXPR_CSTR; - cstr_ = cstr; - num_operands_ = 0; - orig_ = cstr_->str(); - } - -Expr::Expr(RegEx* regex) : DataDepElement(EXPR) - { - init(); - expr_type_ = EXPR_REGEX; - regex_ = regex; - num_operands_ = 0; - orig_ = strfmt("/%s/", regex_->str().c_str()); - } - -Expr::Expr(ExprType arg_type, Expr* op1) : DataDepElement(EXPR) - { - init(); - expr_type_ = arg_type; - num_operands_ = 1; - operand_[0] = op1; - orig_ = strfmt(expr_fmt[expr_type_], op1->orig()); - } - -Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) : DataDepElement(EXPR) - { - init(); - expr_type_ = arg_type; - num_operands_ = 2; - operand_[0] = op1; - operand_[1] = op2; - operand_[2] = nullptr; - orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig()); - } - -Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) : DataDepElement(EXPR) - { - init(); - expr_type_ = arg_type; - num_operands_ = 3; - operand_[0] = op1; - operand_[1] = op2; - operand_[2] = op3; - orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig(), op3->orig()); - } - -Expr::Expr(ExprList* args) : DataDepElement(EXPR) - { - init(); - expr_type_ = EXPR_CALLARGS; - num_operands_ = -1; - args_ = args; - - orig_ = OrigExprList(args_); - } - -Expr::Expr(Expr* index, CaseExprList* cases) : DataDepElement(EXPR) - { - init(); - expr_type_ = EXPR_CASE; - num_operands_ = -1; - operand_[0] = index; - cases_ = cases; - - orig_ = strfmt("case %s of { ", index->orig()); - foreach (i, CaseExprList, cases_) - { - CaseExpr* c = *i; - orig_ += strfmt("%s => %s; ", OrigExprList(c->index()).c_str(), c->value()->orig()); - } - orig_ += "}"; - } - -Expr::~Expr() - { - delete id_; - delete operand_[0]; - delete operand_[1]; - delete operand_[2]; - delete_list(ExprList, args_); - delete_list(CaseExprList, cases_); - } - -void Expr::AddCaseExpr(CaseExpr* case_expr) - { - ASSERT(str_.empty()); - ASSERT(expr_type_ == EXPR_CASE); - ASSERT(cases_); - cases_->push_back(case_expr); - } - -void Expr::GenStrFromFormat(Env* env) - { - // The format != "@custom@" - ASSERT(*expr_fmt[expr_type_] != '@'); - - switch ( num_operands_ ) - { - case 1: - str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str()); - break; - case 2: - str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str()); - break; - case 3: - str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str(), - operand_[2]->str()); - break; - default: - DEBUG_MSG("num_operands_ = %d, orig = %s\n", num_operands_, orig()); - ASSERT(0); - break; - } - } - -namespace - { - -RecordField* GetRecordField(const ID* id, Env* env) - { - Field* field = env->GetField(id); - ASSERT(field); - if ( field->tof() != RECORD_FIELD && field->tof() != PADDING_FIELD ) - throw Exception(id, "not a record field"); - RecordField* r = static_cast(field); - ASSERT(r); - return r; - } - - } // private namespace - -void Expr::GenCaseEval(Output* out_cc, Env* env) - { - ASSERT(expr_type_ == EXPR_CASE); - ASSERT(operand_[0]); - ASSERT(cases_); - - Type* val_type = DataType(env); - ID* val_var = env->AddTempID(val_type); - - // DataType(env) can return a null pointer if an enum value is not - // defined. - if ( ! val_type ) - throw Exception(this, "undefined case value"); - - out_cc->println("%s %s;", val_type->DataTypeStr().c_str(), env->LValue(val_var)); - - // force evaluation of IDs appearing in case stmt - operand_[0]->ForceIDEval(out_cc, env); - foreach (i, CaseExprList, cases_) - (*i)->value()->ForceIDEval(out_cc, env); - - out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); - Type* switch_type = operand_[0]->DataType(env); - - out_cc->inc_indent(); - out_cc->println("{"); - - CaseExpr* default_case = nullptr; - foreach (i, CaseExprList, cases_) - { - CaseExpr* c = *i; - ExprList* index = c->index(); - if ( ! index ) - { - if ( default_case ) - throw Exception(c, "duplicate default cases"); - default_case = c; - } - else - { - GenCaseStr(index, out_cc, env, switch_type); - out_cc->inc_indent(); - out_cc->println("%s = %s;", env->LValue(val_var), c->value()->EvalExpr(out_cc, env)); - out_cc->println("break;"); - out_cc->dec_indent(); - } - } - - // Generate the default case after all other cases - GenCaseStr(nullptr, out_cc, env, switch_type); - out_cc->inc_indent(); - if ( default_case ) - { - out_cc->println("%s = %s;", env->LValue(val_var), - default_case->value()->EvalExpr(out_cc, env)); - } - else - { - out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", Location(), - operand_[0]->EvalExpr(out_cc, env)); - } - out_cc->println("break;"); - out_cc->dec_indent(); - - out_cc->println("}"); - out_cc->dec_indent(); - - env->SetEvaluated(val_var); - str_ = env->RValue(val_var); - } - -void Expr::GenEval(Output* out_cc, Env* env) - { - switch ( expr_type_ ) - { - case EXPR_NUM: - str_ = num_->Str(); - break; - - case EXPR_ID: - if ( ! env->Evaluated(id_) ) - env->Evaluate(out_cc, id_); - str_ = env->RValue(id_); - break; - - case EXPR_MEMBER: - { - /* - For member expressions such X.Y, evaluating - X only is sufficient. (Actually trying to - evaluate Y will lead to error because Y is - not defined in the current environment.) - */ - operand_[0]->GenEval(out_cc, env); - - Type* ty0 = operand_[0]->DataType(env); - - if ( ty0 ) - { - str_ = strfmt("%s%s", operand_[0]->EvalExpr(out_cc, env), - ty0->EvalMember(operand_[1]->id()).c_str()); - } - else - { - string tmp = strfmt("->%s()", operand_[1]->id()->Name()); - str_ = strfmt("%s%s", operand_[0]->EvalExpr(out_cc, env), tmp.c_str()); - } - } - break; - - case EXPR_SUBSCRIPT: - { - operand_[0]->GenEval(out_cc, env); - operand_[1]->GenEval(out_cc, env); - - string v0 = operand_[0]->EvalExpr(out_cc, env); - string v1 = operand_[1]->EvalExpr(out_cc, env); - - Type* ty0 = operand_[0]->DataType(env); - if ( ty0 ) - str_ = ty0->EvalElement(v0, v1); - else - str_ = strfmt("%s[%s]", v0.c_str(), v1.c_str()); - } - break; - - case EXPR_SIZEOF: - { - const ID* id = operand_[0]->id(); - RecordField* rf; - Type* ty; - - try - { - if ( (rf = GetRecordField(id, env)) != nullptr ) - { - str_ = strfmt("%s", rf->FieldSize(out_cc, env)); - } - } - catch ( ExceptionIDNotFound& e ) - { - if ( (ty = TypeDecl::LookUpType(id)) != nullptr ) - { - int ty_size = ty->StaticSize(global_env()); - if ( ty_size >= 0 ) - str_ = strfmt("%d", ty_size); - else - throw Exception(id, "unknown size"); - } - else - throw Exception(id, "not a record field or type"); - } - } - break; - - case EXPR_OFFSETOF: - { - const ID* id = operand_[0]->id(); - RecordField* rf = GetRecordField(id, env); - str_ = strfmt("%s", rf->FieldOffset(out_cc, env)); - } - break; - - case EXPR_CALLARGS: - str_ = EvalExprList(args_, out_cc, env); - break; - - case EXPR_CASE: - GenCaseEval(out_cc, env); - break; - - default: - // Evaluate every operand by default - for ( int i = 0; i < 3; ++i ) - if ( operand_[i] ) - operand_[i]->GenEval(out_cc, env); - GenStrFromFormat(env); - break; - } - } - -void Expr::ForceIDEval(Output* out_cc, Env* env) - { - switch ( expr_type_ ) - { - case EXPR_NUM: - case EXPR_SIZEOF: - case EXPR_OFFSETOF: - break; - - case EXPR_ID: - if ( ! env->Evaluated(id_) ) - env->Evaluate(out_cc, id_); - break; - - case EXPR_MEMBER: - operand_[0]->ForceIDEval(out_cc, env); - break; - - case EXPR_CALLARGS: - { - foreach (i, ExprList, args_) - (*i)->ForceIDEval(out_cc, env); - } - break; - - case EXPR_CASE: - { - operand_[0]->ForceIDEval(out_cc, env); - foreach (i, CaseExprList, cases_) - (*i)->value()->ForceIDEval(out_cc, env); - } - break; - - default: - // Evaluate every operand by default - for ( int i = 0; i < 3; ++i ) - if ( operand_[i] ) - operand_[i]->ForceIDEval(out_cc, env); - break; - } - } - -const char* Expr::EvalExpr(Output* out_cc, Env* env) - { - GenEval(out_cc, env); - return str(); - } - -Type* Expr::DataType(Env* env) const - { - Type* data_type; - - switch ( expr_type_ ) - { - case EXPR_ID: - data_type = env->GetDataType(id_); - break; - - case EXPR_MEMBER: - { - // Get type of the parent - Type* parent_type = operand_[0]->DataType(env); - if ( ! parent_type ) - return nullptr; - data_type = parent_type->MemberDataType(operand_[1]->id()); - } - break; - - case EXPR_SUBSCRIPT: - { - // Get type of the parent - Type* parent_type = operand_[0]->DataType(env); - data_type = parent_type->ElementDataType(); - } - break; - - case EXPR_PAREN: - data_type = operand_[0]->DataType(env); - break; - - case EXPR_COND: - { - Type* type1 = operand_[1]->DataType(env); - Type* type2 = operand_[2]->DataType(env); - if ( ! Type::CompatibleTypes(type1, type2) ) - { - throw Exception(this, - strfmt("type mismatch: %s vs %s", type1->DataTypeStr().c_str(), - type2->DataTypeStr().c_str())); - } - data_type = type1; - } - break; - - case EXPR_CALL: - data_type = operand_[0]->DataType(env); - break; - - case EXPR_CASE: - { - if ( cases_ && ! cases_->empty() ) - { - Type* type1 = cases_->front()->value()->DataType(env); - Type* numeric_with_largest_width = nullptr; - - foreach (i, CaseExprList, cases_) - { - Type* type2 = (*i)->value()->DataType(env); - if ( ! Type::CompatibleTypes(type1, type2) ) - { - throw Exception(this, strfmt("type mismatch: %s vs %s", - type1->DataTypeStr().c_str(), - type2->DataTypeStr().c_str())); - } - if ( type1 == extern_type_nullptr ) - type1 = type2; - - if ( type2 && type2->IsNumericType() ) - { - if ( numeric_with_largest_width ) - { - int largest; - int contender; - - // External C++ types like "int", "bool", "enum" use "int" - // storage internally. - if ( numeric_with_largest_width->tot() == Type::EXTERN ) - largest = sizeof(int); - else - largest = numeric_with_largest_width->StaticSize(env); - - if ( type2->tot() == Type::EXTERN ) - contender = sizeof(int); - else - contender = type2->StaticSize(env); - - if ( contender > largest ) - numeric_with_largest_width = type2; - } - else - numeric_with_largest_width = type2; - } - } - data_type = numeric_with_largest_width ? numeric_with_largest_width : type1; - } - else - data_type = nullptr; - } - break; - - case EXPR_NUM: - case EXPR_SIZEOF: - case EXPR_OFFSETOF: - case EXPR_NEG: - case EXPR_PLUS: - case EXPR_MINUS: - case EXPR_TIMES: - case EXPR_DIV: - case EXPR_MOD: - case EXPR_BITNOT: - case EXPR_BITAND: - case EXPR_BITOR: - case EXPR_BITXOR: - case EXPR_LSHIFT: - case EXPR_RSHIFT: - case EXPR_EQUAL: - case EXPR_GE: - case EXPR_LE: - case EXPR_GT: - case EXPR_LT: - case EXPR_NOT: - case EXPR_AND: - case EXPR_OR: - data_type = extern_type_int; - break; - - default: - data_type = nullptr; - break; - } - - return data_type; - } - -string Expr::DataTypeStr(Env* env) const - { - Type* type = DataType(env); - - if ( ! type ) - { - throw Exception(this, strfmt("cannot find data type for expression `%s'", orig())); - } - - return type->DataTypeStr(); - } - -string Expr::SetFunc(Output* out, Env* env) - { - switch ( expr_type_ ) - { - case EXPR_ID: - return set_function(id_); - case EXPR_MEMBER: - { - // Evaluate the parent - string parent_val(operand_[0]->EvalExpr(out, env)); - return parent_val + "->" + set_function(operand_[1]->id()); - } - break; - default: - throw Exception(this, strfmt("cannot generate set function " - "for expression `%s'", - orig())); - break; - } - } - -bool Expr::ConstFold(Env* env, int* pn) const - { - switch ( expr_type_ ) - { - case EXPR_NUM: - *pn = num_->Num(); - return true; - case EXPR_ID: - return env->GetConstant(id_, pn); - default: - // ### FIXME: folding consts - return false; - } - } +void Expr::init() { + id_ = nullptr; + num_ = nullptr; + cstr_ = nullptr; + regex_ = nullptr; + num_operands_ = 0; + operand_[0] = nullptr; + operand_[1] = nullptr; + operand_[2] = nullptr; + args_ = nullptr; + cases_ = nullptr; +} + +Expr::Expr(ID* arg_id) : DataDepElement(EXPR) { + init(); + expr_type_ = EXPR_ID; + id_ = arg_id; + num_operands_ = 0; + orig_ = strfmt("%s", id_->Name()); +} + +Expr::Expr(Number* arg_num) : DataDepElement(EXPR) { + init(); + expr_type_ = EXPR_NUM; + num_ = arg_num; + num_operands_ = 0; + orig_ = strfmt("((int) %s)", num_->Str()); +} + +Expr::Expr(ConstString* cstr) : DataDepElement(EXPR) { + init(); + expr_type_ = EXPR_CSTR; + cstr_ = cstr; + num_operands_ = 0; + orig_ = cstr_->str(); +} + +Expr::Expr(RegEx* regex) : DataDepElement(EXPR) { + init(); + expr_type_ = EXPR_REGEX; + regex_ = regex; + num_operands_ = 0; + orig_ = strfmt("/%s/", regex_->str().c_str()); +} + +Expr::Expr(ExprType arg_type, Expr* op1) : DataDepElement(EXPR) { + init(); + expr_type_ = arg_type; + num_operands_ = 1; + operand_[0] = op1; + orig_ = strfmt(expr_fmt[expr_type_], op1->orig()); +} + +Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) : DataDepElement(EXPR) { + init(); + expr_type_ = arg_type; + num_operands_ = 2; + operand_[0] = op1; + operand_[1] = op2; + operand_[2] = nullptr; + orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig()); +} + +Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) : DataDepElement(EXPR) { + init(); + expr_type_ = arg_type; + num_operands_ = 3; + operand_[0] = op1; + operand_[1] = op2; + operand_[2] = op3; + orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig(), op3->orig()); +} + +Expr::Expr(ExprList* args) : DataDepElement(EXPR) { + init(); + expr_type_ = EXPR_CALLARGS; + num_operands_ = -1; + args_ = args; + + orig_ = OrigExprList(args_); +} + +Expr::Expr(Expr* index, CaseExprList* cases) : DataDepElement(EXPR) { + init(); + expr_type_ = EXPR_CASE; + num_operands_ = -1; + operand_[0] = index; + cases_ = cases; + + orig_ = strfmt("case %s of { ", index->orig()); + foreach (i, CaseExprList, cases_) { + CaseExpr* c = *i; + orig_ += strfmt("%s => %s; ", OrigExprList(c->index()).c_str(), c->value()->orig()); + } + orig_ += "}"; +} + +Expr::~Expr() { + delete id_; + delete operand_[0]; + delete operand_[1]; + delete operand_[2]; + delete_list(ExprList, args_); + delete_list(CaseExprList, cases_); +} + +void Expr::AddCaseExpr(CaseExpr* case_expr) { + ASSERT(str_.empty()); + ASSERT(expr_type_ == EXPR_CASE); + ASSERT(cases_); + cases_->push_back(case_expr); +} + +void Expr::GenStrFromFormat(Env* env) { + // The format != "@custom@" + ASSERT(*expr_fmt[expr_type_] != '@'); + + switch ( num_operands_ ) { + case 1: str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str()); break; + case 2: str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str()); break; + case 3: str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str(), operand_[2]->str()); break; + default: + DEBUG_MSG("num_operands_ = %d, orig = %s\n", num_operands_, orig()); + ASSERT(0); + break; + } +} + +namespace { + +RecordField* GetRecordField(const ID* id, Env* env) { + Field* field = env->GetField(id); + ASSERT(field); + if ( field->tof() != RECORD_FIELD && field->tof() != PADDING_FIELD ) + throw Exception(id, "not a record field"); + RecordField* r = static_cast(field); + ASSERT(r); + return r; +} + +} // namespace + +void Expr::GenCaseEval(Output* out_cc, Env* env) { + ASSERT(expr_type_ == EXPR_CASE); + ASSERT(operand_[0]); + ASSERT(cases_); + + Type* val_type = DataType(env); + ID* val_var = env->AddTempID(val_type); + + // DataType(env) can return a null pointer if an enum value is not + // defined. + if ( ! val_type ) + throw Exception(this, "undefined case value"); + + out_cc->println("%s %s;", val_type->DataTypeStr().c_str(), env->LValue(val_var)); + + // force evaluation of IDs appearing in case stmt + operand_[0]->ForceIDEval(out_cc, env); + foreach (i, CaseExprList, cases_) + (*i)->value()->ForceIDEval(out_cc, env); + + out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); + Type* switch_type = operand_[0]->DataType(env); + + out_cc->inc_indent(); + out_cc->println("{"); + + CaseExpr* default_case = nullptr; + foreach (i, CaseExprList, cases_) { + CaseExpr* c = *i; + ExprList* index = c->index(); + if ( ! index ) { + if ( default_case ) + throw Exception(c, "duplicate default cases"); + default_case = c; + } + else { + GenCaseStr(index, out_cc, env, switch_type); + out_cc->inc_indent(); + out_cc->println("%s = %s;", env->LValue(val_var), c->value()->EvalExpr(out_cc, env)); + out_cc->println("break;"); + out_cc->dec_indent(); + } + } + + // Generate the default case after all other cases + GenCaseStr(nullptr, out_cc, env, switch_type); + out_cc->inc_indent(); + if ( default_case ) { + out_cc->println("%s = %s;", env->LValue(val_var), default_case->value()->EvalExpr(out_cc, env)); + } + else { + out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", Location(), + operand_[0]->EvalExpr(out_cc, env)); + } + out_cc->println("break;"); + out_cc->dec_indent(); + + out_cc->println("}"); + out_cc->dec_indent(); + + env->SetEvaluated(val_var); + str_ = env->RValue(val_var); +} + +void Expr::GenEval(Output* out_cc, Env* env) { + switch ( expr_type_ ) { + case EXPR_NUM: str_ = num_->Str(); break; + + case EXPR_ID: + if ( ! env->Evaluated(id_) ) + env->Evaluate(out_cc, id_); + str_ = env->RValue(id_); + break; + + case EXPR_MEMBER: { + /* + For member expressions such X.Y, evaluating + X only is sufficient. (Actually trying to + evaluate Y will lead to error because Y is + not defined in the current environment.) + */ + operand_[0]->GenEval(out_cc, env); + + Type* ty0 = operand_[0]->DataType(env); + + if ( ty0 ) { + str_ = strfmt("%s%s", operand_[0]->EvalExpr(out_cc, env), ty0->EvalMember(operand_[1]->id()).c_str()); + } + else { + string tmp = strfmt("->%s()", operand_[1]->id()->Name()); + str_ = strfmt("%s%s", operand_[0]->EvalExpr(out_cc, env), tmp.c_str()); + } + } break; + + case EXPR_SUBSCRIPT: { + operand_[0]->GenEval(out_cc, env); + operand_[1]->GenEval(out_cc, env); + + string v0 = operand_[0]->EvalExpr(out_cc, env); + string v1 = operand_[1]->EvalExpr(out_cc, env); + + Type* ty0 = operand_[0]->DataType(env); + if ( ty0 ) + str_ = ty0->EvalElement(v0, v1); + else + str_ = strfmt("%s[%s]", v0.c_str(), v1.c_str()); + } break; + + case EXPR_SIZEOF: { + const ID* id = operand_[0]->id(); + RecordField* rf; + Type* ty; + + try { + if ( (rf = GetRecordField(id, env)) != nullptr ) { + str_ = strfmt("%s", rf->FieldSize(out_cc, env)); + } + } catch ( ExceptionIDNotFound& e ) { + if ( (ty = TypeDecl::LookUpType(id)) != nullptr ) { + int ty_size = ty->StaticSize(global_env()); + if ( ty_size >= 0 ) + str_ = strfmt("%d", ty_size); + else + throw Exception(id, "unknown size"); + } + else + throw Exception(id, "not a record field or type"); + } + } break; + + case EXPR_OFFSETOF: { + const ID* id = operand_[0]->id(); + RecordField* rf = GetRecordField(id, env); + str_ = strfmt("%s", rf->FieldOffset(out_cc, env)); + } break; + + case EXPR_CALLARGS: str_ = EvalExprList(args_, out_cc, env); break; + + case EXPR_CASE: GenCaseEval(out_cc, env); break; + + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) + if ( operand_[i] ) + operand_[i]->GenEval(out_cc, env); + GenStrFromFormat(env); + break; + } +} + +void Expr::ForceIDEval(Output* out_cc, Env* env) { + switch ( expr_type_ ) { + case EXPR_NUM: + case EXPR_SIZEOF: + case EXPR_OFFSETOF: break; + + case EXPR_ID: + if ( ! env->Evaluated(id_) ) + env->Evaluate(out_cc, id_); + break; + + case EXPR_MEMBER: operand_[0]->ForceIDEval(out_cc, env); break; + + case EXPR_CALLARGS: { + foreach (i, ExprList, args_) + (*i)->ForceIDEval(out_cc, env); + } break; + + case EXPR_CASE: { + operand_[0]->ForceIDEval(out_cc, env); + foreach (i, CaseExprList, cases_) + (*i)->value()->ForceIDEval(out_cc, env); + } break; + + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) + if ( operand_[i] ) + operand_[i]->ForceIDEval(out_cc, env); + break; + } +} + +const char* Expr::EvalExpr(Output* out_cc, Env* env) { + GenEval(out_cc, env); + return str(); +} + +Type* Expr::DataType(Env* env) const { + Type* data_type; + + switch ( expr_type_ ) { + case EXPR_ID: data_type = env->GetDataType(id_); break; + + case EXPR_MEMBER: { + // Get type of the parent + Type* parent_type = operand_[0]->DataType(env); + if ( ! parent_type ) + return nullptr; + data_type = parent_type->MemberDataType(operand_[1]->id()); + } break; + + case EXPR_SUBSCRIPT: { + // Get type of the parent + Type* parent_type = operand_[0]->DataType(env); + data_type = parent_type->ElementDataType(); + } break; + + case EXPR_PAREN: data_type = operand_[0]->DataType(env); break; + + case EXPR_COND: { + Type* type1 = operand_[1]->DataType(env); + Type* type2 = operand_[2]->DataType(env); + if ( ! Type::CompatibleTypes(type1, type2) ) { + throw Exception(this, strfmt("type mismatch: %s vs %s", type1->DataTypeStr().c_str(), + type2->DataTypeStr().c_str())); + } + data_type = type1; + } break; + + case EXPR_CALL: data_type = operand_[0]->DataType(env); break; + + case EXPR_CASE: { + if ( cases_ && ! cases_->empty() ) { + Type* type1 = cases_->front()->value()->DataType(env); + Type* numeric_with_largest_width = nullptr; + + foreach (i, CaseExprList, cases_) { + Type* type2 = (*i)->value()->DataType(env); + if ( ! Type::CompatibleTypes(type1, type2) ) { + throw Exception(this, strfmt("type mismatch: %s vs %s", type1->DataTypeStr().c_str(), + type2->DataTypeStr().c_str())); + } + if ( type1 == extern_type_nullptr ) + type1 = type2; + + if ( type2 && type2->IsNumericType() ) { + if ( numeric_with_largest_width ) { + int largest; + int contender; + + // External C++ types like "int", "bool", "enum" use "int" + // storage internally. + if ( numeric_with_largest_width->tot() == Type::EXTERN ) + largest = sizeof(int); + else + largest = numeric_with_largest_width->StaticSize(env); + + if ( type2->tot() == Type::EXTERN ) + contender = sizeof(int); + else + contender = type2->StaticSize(env); + + if ( contender > largest ) + numeric_with_largest_width = type2; + } + else + numeric_with_largest_width = type2; + } + } + data_type = numeric_with_largest_width ? numeric_with_largest_width : type1; + } + else + data_type = nullptr; + } break; + + case EXPR_NUM: + case EXPR_SIZEOF: + case EXPR_OFFSETOF: + case EXPR_NEG: + case EXPR_PLUS: + case EXPR_MINUS: + case EXPR_TIMES: + case EXPR_DIV: + case EXPR_MOD: + case EXPR_BITNOT: + case EXPR_BITAND: + case EXPR_BITOR: + case EXPR_BITXOR: + case EXPR_LSHIFT: + case EXPR_RSHIFT: + case EXPR_EQUAL: + case EXPR_GE: + case EXPR_LE: + case EXPR_GT: + case EXPR_LT: + case EXPR_NOT: + case EXPR_AND: + case EXPR_OR: data_type = extern_type_int; break; + + default: data_type = nullptr; break; + } + + return data_type; +} + +string Expr::DataTypeStr(Env* env) const { + Type* type = DataType(env); + + if ( ! type ) { + throw Exception(this, strfmt("cannot find data type for expression `%s'", orig())); + } + + return type->DataTypeStr(); +} + +string Expr::SetFunc(Output* out, Env* env) { + switch ( expr_type_ ) { + case EXPR_ID: return set_function(id_); + case EXPR_MEMBER: { + // Evaluate the parent + string parent_val(operand_[0]->EvalExpr(out, env)); + return parent_val + "->" + set_function(operand_[1]->id()); + } break; + default: + throw Exception(this, strfmt("cannot generate set function " + "for expression `%s'", + orig())); + break; + } +} + +bool Expr::ConstFold(Env* env, int* pn) const { + switch ( expr_type_ ) { + case EXPR_NUM: *pn = num_->Num(); return true; + case EXPR_ID: return env->GetConstant(id_, pn); + default: + // ### FIXME: folding consts + return false; + } +} // TODO: build a generic data dependency extraction process -namespace - { +namespace { // Maximum of two minimal header sizes -int mhs_max(int h1, int h2) - { - if ( h1 < 0 || h2 < 0 ) - return -1; - else - { - // return max(h1, h2); - return h1 > h2 ? h1 : h2; - } - } +int mhs_max(int h1, int h2) { + if ( h1 < 0 || h2 < 0 ) + return -1; + else { + // return max(h1, h2); + return h1 > h2 ? h1 : h2; + } +} // MHS required to evaluate the field -int mhs_letfield(Env* env, LetField* field) - { - return field->expr()->MinimalHeaderSize(env); - } +int mhs_letfield(Env* env, LetField* field) { return field->expr()->MinimalHeaderSize(env); } -int mhs_recordfield(Env* env, RecordField* field) - { - int offset = field->static_offset(); - if ( offset < 0 ) // offset cannot be statically determined - return -1; - int size = field->StaticSize(env, offset); - if ( size < 0 ) // size cannot be statically determined - return -1; - return offset + size; - } +int mhs_recordfield(Env* env, RecordField* field) { + int offset = field->static_offset(); + if ( offset < 0 ) // offset cannot be statically determined + return -1; + int size = field->StaticSize(env, offset); + if ( size < 0 ) // size cannot be statically determined + return -1; + return offset + size; +} -int mhs_casefield(Env* env, CaseField* field) - { - // TODO: deal with the index - int size = field->StaticSize(env); - if ( size < 0 ) // size cannot be statically determined - return -1; - return size; - } +int mhs_casefield(Env* env, CaseField* field) { + // TODO: deal with the index + int size = field->StaticSize(env); + if ( size < 0 ) // size cannot be statically determined + return -1; + return size; +} -int mhs_field(Env* env, Field* field) - { - int mhs = -1; - switch ( field->tof() ) - { - case LET_FIELD: - { - LetField* f = static_cast(field); - ASSERT(f); - mhs = mhs_letfield(env, f); - } - break; +int mhs_field(Env* env, Field* field) { + int mhs = -1; + switch ( field->tof() ) { + case LET_FIELD: { + LetField* f = static_cast(field); + ASSERT(f); + mhs = mhs_letfield(env, f); + } break; - case CONTEXT_FIELD: - case FLOW_FIELD: - ASSERT(0); - break; + case CONTEXT_FIELD: + case FLOW_FIELD: ASSERT(0); break; - case PARAM_FIELD: - mhs = 0; - break; + case PARAM_FIELD: mhs = 0; break; - case RECORD_FIELD: - case PADDING_FIELD: - { - RecordField* f = static_cast(field); - ASSERT(f); - mhs = mhs_recordfield(env, f); - } - break; + case RECORD_FIELD: + case PADDING_FIELD: { + RecordField* f = static_cast(field); + ASSERT(f); + mhs = mhs_recordfield(env, f); + } break; - case CASE_FIELD: - { - CaseField* f = static_cast(field); - ASSERT(f); - mhs = mhs_casefield(env, f); - } - break; + case CASE_FIELD: { + CaseField* f = static_cast(field); + ASSERT(f); + mhs = mhs_casefield(env, f); + } break; - case PARSE_VAR_FIELD: - case PRIV_VAR_FIELD: - case PUB_VAR_FIELD: - case TEMP_VAR_FIELD: - mhs = 0; - break; + case PARSE_VAR_FIELD: + case PRIV_VAR_FIELD: + case PUB_VAR_FIELD: + case TEMP_VAR_FIELD: mhs = 0; break; - case WITHINPUT_FIELD: - { - // ### TODO: fix this - mhs = -1; - } - break; - } - return mhs; - } + case WITHINPUT_FIELD: { + // ### TODO: fix this + mhs = -1; + } break; + } + return mhs; +} -int mhs_id(Env* env, const ID* id) - { - int mhs = -1; - switch ( env->GetIDType(id) ) - { - case CONST: - case GLOBAL_VAR: - case TEMP_VAR: - case STATE_VAR: - case FUNC_ID: - case FUNC_PARAM: - mhs = 0; - break; - case MEMBER_VAR: - case PRIV_MEMBER_VAR: - { - Field* field = env->GetField(id); - if ( ! field ) - throw ExceptionIDNotField(id); - mhs = mhs_field(env, field); - } - break; - case UNION_VAR: - // TODO: deal with UNION_VAR - mhs = -1; - break; - case MACRO: - { - Expr* e = env->GetMacro(id); - mhs = e->MinimalHeaderSize(env); - } - break; - } - return mhs; - } - } +int mhs_id(Env* env, const ID* id) { + int mhs = -1; + switch ( env->GetIDType(id) ) { + case CONST: + case GLOBAL_VAR: + case TEMP_VAR: + case STATE_VAR: + case FUNC_ID: + case FUNC_PARAM: mhs = 0; break; + case MEMBER_VAR: + case PRIV_MEMBER_VAR: { + Field* field = env->GetField(id); + if ( ! field ) + throw ExceptionIDNotField(id); + mhs = mhs_field(env, field); + } break; + case UNION_VAR: + // TODO: deal with UNION_VAR + mhs = -1; + break; + case MACRO: { + Expr* e = env->GetMacro(id); + mhs = e->MinimalHeaderSize(env); + } break; + } + return mhs; +} +} // namespace -int Expr::MinimalHeaderSize(Env* env) - { - int mhs; +int Expr::MinimalHeaderSize(Env* env) { + int mhs; - switch ( expr_type_ ) - { - case EXPR_NUM: - // Zero byte is required - mhs = 0; - break; + switch ( expr_type_ ) { + case EXPR_NUM: + // Zero byte is required + mhs = 0; + break; - case EXPR_ID: - mhs = mhs_id(env, id_); - break; + case EXPR_ID: mhs = mhs_id(env, id_); break; - case EXPR_MEMBER: - // TODO: this is not a tight bound because - // one actually does not have to parse the - // whole record to compute one particular - // field. - mhs = operand_[0]->MinimalHeaderSize(env); - break; + case EXPR_MEMBER: + // TODO: this is not a tight bound because + // one actually does not have to parse the + // whole record to compute one particular + // field. + mhs = operand_[0]->MinimalHeaderSize(env); + break; - case EXPR_SUBSCRIPT: - { - int index; - Type* array_type = operand_[0]->DataType(env); - Type* elem_type = array_type->ElementDataType(); - int elem_size = elem_type->StaticSize(env); - if ( elem_size >= 0 && operand_[1]->ConstFold(env, &index) ) - { - mhs = elem_size * index; - } - else - { - mhs = -1; - } - } - break; + case EXPR_SUBSCRIPT: { + int index; + Type* array_type = operand_[0]->DataType(env); + Type* elem_type = array_type->ElementDataType(); + int elem_size = elem_type->StaticSize(env); + if ( elem_size >= 0 && operand_[1]->ConstFold(env, &index) ) { + mhs = elem_size * index; + } + else { + mhs = -1; + } + } break; - case EXPR_SIZEOF: - { - const ID* id = operand_[0]->id(); - ASSERT(id); - RecordField* rf; - Type* ty; + case EXPR_SIZEOF: { + const ID* id = operand_[0]->id(); + ASSERT(id); + RecordField* rf; + Type* ty; - if ( (rf = GetRecordField(id, env)) != nullptr ) - { - if ( rf->StaticSize(env, -1) >= 0 ) - mhs = 0; - else - mhs = mhs_recordfield(env, rf); - } + if ( (rf = GetRecordField(id, env)) != nullptr ) { + if ( rf->StaticSize(env, -1) >= 0 ) + mhs = 0; + else + mhs = mhs_recordfield(env, rf); + } - else if ( (ty = TypeDecl::LookUpType(id)) != nullptr ) - { - mhs = 0; - } + else if ( (ty = TypeDecl::LookUpType(id)) != nullptr ) { + mhs = 0; + } - else - throw Exception(id, "not a record field or type"); - } - break; + else + throw Exception(id, "not a record field or type"); + } break; - case EXPR_OFFSETOF: - { - const ID* id = operand_[0]->id(); - ASSERT(id); - RecordField* field = GetRecordField(id, env); + case EXPR_OFFSETOF: { + const ID* id = operand_[0]->id(); + ASSERT(id); + RecordField* field = GetRecordField(id, env); - mhs = field->static_offset(); - if ( mhs < 0 ) - { - mhs = 0; - // Take the MHS of the preceding (non-let) field - RecordField* prev_field = field->prev(); - ASSERT(prev_field); - mhs = mhs_recordfield(env, prev_field); - } - } - break; + mhs = field->static_offset(); + if ( mhs < 0 ) { + mhs = 0; + // Take the MHS of the preceding (non-let) field + RecordField* prev_field = field->prev(); + ASSERT(prev_field); + mhs = mhs_recordfield(env, prev_field); + } + } break; - case EXPR_CALLARGS: - { - mhs = 0; - if ( args_ ) - for ( unsigned int i = 0; i < args_->size(); ++i ) - mhs = mhs_max(mhs, (*args_)[i]->MinimalHeaderSize(env)); - } - break; - case EXPR_CASE: - { - mhs = operand_[0]->MinimalHeaderSize(env); - for ( unsigned int i = 0; i < cases_->size(); ++i ) - { - CaseExpr* ce = (*cases_)[i]; - if ( ce->index() ) - for ( unsigned int j = 0; j < ce->index()->size(); ++j ) - mhs = mhs_max(mhs, (*ce->index())[j]->MinimalHeaderSize(env)); - mhs = mhs_max(mhs, ce->value()->MinimalHeaderSize(env)); - } - } - break; - default: - // Evaluate every operand by default - mhs = 0; - for ( int i = 0; i < 3; ++i ) - if ( operand_[i] ) - mhs = mhs_max(mhs, operand_[i]->MinimalHeaderSize(env)); - break; - } + case EXPR_CALLARGS: { + mhs = 0; + if ( args_ ) + for ( unsigned int i = 0; i < args_->size(); ++i ) + mhs = mhs_max(mhs, (*args_)[i]->MinimalHeaderSize(env)); + } break; + case EXPR_CASE: { + mhs = operand_[0]->MinimalHeaderSize(env); + for ( unsigned int i = 0; i < cases_->size(); ++i ) { + CaseExpr* ce = (*cases_)[i]; + if ( ce->index() ) + for ( unsigned int j = 0; j < ce->index()->size(); ++j ) + mhs = mhs_max(mhs, (*ce->index())[j]->MinimalHeaderSize(env)); + mhs = mhs_max(mhs, ce->value()->MinimalHeaderSize(env)); + } + } break; + default: + // Evaluate every operand by default + mhs = 0; + for ( int i = 0; i < 3; ++i ) + if ( operand_[i] ) + mhs = mhs_max(mhs, operand_[i]->MinimalHeaderSize(env)); + break; + } - return mhs; - } + return mhs; +} -bool Expr::HasReference(const ID* id) const - { - switch ( expr_type_ ) - { - case EXPR_ID: - return *id == *id_; +bool Expr::HasReference(const ID* id) const { + switch ( expr_type_ ) { + case EXPR_ID: return *id == *id_; - case EXPR_MEMBER: - return operand_[0]->HasReference(id); + case EXPR_MEMBER: return operand_[0]->HasReference(id); - case EXPR_CALLARGS: - { - foreach (i, ExprList, args_) - if ( (*i)->HasReference(id) ) - return true; - } - return false; + case EXPR_CALLARGS: { + foreach (i, ExprList, args_) + if ( (*i)->HasReference(id) ) + return true; + } + return false; - case EXPR_CASE: - { - foreach (i, CaseExprList, cases_) - if ( (*i)->HasReference(id) ) - return true; - } - return false; + case EXPR_CASE: { + foreach (i, CaseExprList, cases_) + if ( (*i)->HasReference(id) ) + return true; + } + return false; - default: - // Evaluate every operand by default - for ( int i = 0; i < 3; ++i ) - { - if ( operand_[i] && operand_[i]->HasReference(id) ) - { - return true; - } - } - return false; - } - } + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) { + if ( operand_[i] && operand_[i]->HasReference(id) ) { + return true; + } + } + return false; + } +} -bool Expr::DoTraverse(DataDepVisitor* visitor) - { - switch ( expr_type_ ) - { - case EXPR_ID: - break; +bool Expr::DoTraverse(DataDepVisitor* visitor) { + switch ( expr_type_ ) { + case EXPR_ID: break; - case EXPR_MEMBER: - /* - For member expressions such X.Y, evaluating - X only is sufficient. (Actually trying to - evaluate Y will lead to error because Y is - not defined in the current environment.) - */ - if ( ! operand_[0]->Traverse(visitor) ) - return false; - break; + case EXPR_MEMBER: + /* + For member expressions such X.Y, evaluating + X only is sufficient. (Actually trying to + evaluate Y will lead to error because Y is + not defined in the current environment.) + */ + if ( ! operand_[0]->Traverse(visitor) ) + return false; + break; - case EXPR_CALLARGS: - { - foreach (i, ExprList, args_) - if ( ! (*i)->Traverse(visitor) ) - return false; - } - break; + case EXPR_CALLARGS: { + foreach (i, ExprList, args_) + if ( ! (*i)->Traverse(visitor) ) + return false; + } break; - case EXPR_CASE: - { - foreach (i, CaseExprList, cases_) - if ( ! (*i)->Traverse(visitor) ) - return false; - } - break; + case EXPR_CASE: { + foreach (i, CaseExprList, cases_) + if ( ! (*i)->Traverse(visitor) ) + return false; + } break; - default: - // Evaluate every operand by default - for ( int i = 0; i < 3; ++i ) - { - if ( operand_[i] && ! operand_[i]->Traverse(visitor) ) - { - return false; - } - } - break; - } + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) { + if ( operand_[i] && ! operand_[i]->Traverse(visitor) ) { + return false; + } + } + break; + } - return true; - } + return true; +} -bool Expr::RequiresAnalyzerContext() const - { - switch ( expr_type_ ) - { - case EXPR_ID: - return *id_ == *analyzer_context_id; +bool Expr::RequiresAnalyzerContext() const { + switch ( expr_type_ ) { + case EXPR_ID: return *id_ == *analyzer_context_id; - case EXPR_MEMBER: - /* - For member expressions such X.Y, evaluating - X only is sufficient. (Actually trying to - evaluate Y will lead to error because Y is - not defined in the current environment.) - */ - return operand_[0]->RequiresAnalyzerContext(); + case EXPR_MEMBER: + /* + For member expressions such X.Y, evaluating + X only is sufficient. (Actually trying to + evaluate Y will lead to error because Y is + not defined in the current environment.) + */ + return operand_[0]->RequiresAnalyzerContext(); - case EXPR_CALLARGS: - { - foreach (i, ExprList, args_) - if ( (*i)->RequiresAnalyzerContext() ) - return true; - } - return false; + case EXPR_CALLARGS: { + foreach (i, ExprList, args_) + if ( (*i)->RequiresAnalyzerContext() ) + return true; + } + return false; - case EXPR_CASE: - { - foreach (i, CaseExprList, cases_) - if ( (*i)->RequiresAnalyzerContext() ) - return true; - } - return false; + case EXPR_CASE: { + foreach (i, CaseExprList, cases_) + if ( (*i)->RequiresAnalyzerContext() ) + return true; + } + return false; - default: - // Evaluate every operand by default - for ( int i = 0; i < 3; ++i ) - if ( operand_[i] && operand_[i]->RequiresAnalyzerContext() ) - { - DEBUG_MSG("'%s' requires analyzer context\n", operand_[i]->orig()); - return true; - } - return false; - } - } + default: + // Evaluate every operand by default + for ( int i = 0; i < 3; ++i ) + if ( operand_[i] && operand_[i]->RequiresAnalyzerContext() ) { + DEBUG_MSG("'%s' requires analyzer context\n", operand_[i]->orig()); + return true; + } + return false; + } +} CaseExpr::CaseExpr(ExprList* index, Expr* value) - : DataDepElement(DataDepElement::CASEEXPR), index_(index), value_(value) - { - } + : DataDepElement(DataDepElement::CASEEXPR), index_(index), value_(value) {} -CaseExpr::~CaseExpr() - { - delete_list(ExprList, index_); - delete value_; - } +CaseExpr::~CaseExpr() { + delete_list(ExprList, index_); + delete value_; +} -bool CaseExpr::DoTraverse(DataDepVisitor* visitor) - { - foreach (i, ExprList, index_) - if ( ! (*i)->Traverse(visitor) ) - return false; - return value_->Traverse(visitor); - } +bool CaseExpr::DoTraverse(DataDepVisitor* visitor) { + foreach (i, ExprList, index_) + if ( ! (*i)->Traverse(visitor) ) + return false; + return value_->Traverse(visitor); +} -bool CaseExpr::HasReference(const ID* id) const - { - return value_->HasReference(id); - } +bool CaseExpr::HasReference(const ID* id) const { return value_->HasReference(id); } -bool CaseExpr::RequiresAnalyzerContext() const - { - // index_ should evaluate to constants - return value_->RequiresAnalyzerContext(); - } +bool CaseExpr::RequiresAnalyzerContext() const { + // index_ should evaluate to constants + return value_->RequiresAnalyzerContext(); +} diff --git a/tools/binpac/src/pac_expr.h b/tools/binpac/src/pac_expr.h index 8a4cad8295..8d50c904e3 100644 --- a/tools/binpac/src/pac_expr.h +++ b/tools/binpac/src/pac_expr.h @@ -6,135 +6,132 @@ class CaseExpr; -class Expr : public Object, public DataDepElement - { +class Expr : public Object, public DataDepElement { public: - enum ExprType - { + enum ExprType { #define EXPR_DEF(type, x, y) type, #include "pac_expr.def" #undef EXPR_DEF - }; + }; - void init(); + void init(); - Expr(ID* id); - Expr(Number* num); - Expr(ConstString* s); - Expr(RegEx* regex); - Expr(ExprList* args); // for EXPR_CALLARGS - Expr(Expr* index, CaseExprList* cases); + Expr(ID* id); + Expr(Number* num); + Expr(ConstString* s); + Expr(RegEx* regex); + Expr(ExprList* args); // for EXPR_CALLARGS + Expr(Expr* index, CaseExprList* cases); - Expr(ExprType type, Expr* op1); - Expr(ExprType type, Expr* op1, Expr* op2); - Expr(ExprType type, Expr* op1, Expr* op2, Expr* op3); + Expr(ExprType type, Expr* op1); + Expr(ExprType type, Expr* op1, Expr* op2); + Expr(ExprType type, Expr* op1, Expr* op2, Expr* op3); - ~Expr() override; + ~Expr() override; - const char* orig() const { return orig_.c_str(); } - const ID* id() const { return id_; } - const char* str() const { return str_.c_str(); } - ExprType expr_type() const { return expr_type_; } + const char* orig() const { return orig_.c_str(); } + const ID* id() const { return id_; } + const char* str() const { return str_.c_str(); } + ExprType expr_type() const { return expr_type_; } - void AddCaseExpr(CaseExpr* case_expr); + void AddCaseExpr(CaseExpr* case_expr); - // Returns the data "type" of the expression. Here we only - // do a serious job for the EXPR_MEMBER and EXPR_SUBSCRIPT - // operators. For arithmetic operations, we fall back - // to "int". - Type* DataType(Env* env) const; - string DataTypeStr(Env* env) const; + // Returns the data "type" of the expression. Here we only + // do a serious job for the EXPR_MEMBER and EXPR_SUBSCRIPT + // operators. For arithmetic operations, we fall back + // to "int". + Type* DataType(Env* env) const; + string DataTypeStr(Env* env) const; - // Note: EvalExpr() may generate C++ statements in order to evaluate - // variables in the expression, so the following is wrong: - // - // out->print("int x = "); - // out->println("%s", expr->EvalExpr(out, env)); - // - // While putting them together is right: - // - // out->println("int x = %s", expr->EvalExpr(out, env)); - // - const char* EvalExpr(Output* out, Env* env); + // Note: EvalExpr() may generate C++ statements in order to evaluate + // variables in the expression, so the following is wrong: + // + // out->print("int x = "); + // out->println("%s", expr->EvalExpr(out, env)); + // + // While putting them together is right: + // + // out->println("int x = %s", expr->EvalExpr(out, env)); + // + const char* EvalExpr(Output* out, Env* env); - // force evaulation of IDs contained in this expression; - // necessary with case expr and conditional let fields (&if) - // for correct parsing of fields - void ForceIDEval(Output* out_cc, Env* env); + // force evaulation of IDs contained in this expression; + // necessary with case expr and conditional let fields (&if) + // for correct parsing of fields + void ForceIDEval(Output* out_cc, Env* env); - // Returns the set_* function of the expression. - // The expression must be of form ID or x.ID. - string SetFunc(Output* out, Env* env); + // Returns the set_* function of the expression. + // The expression must be of form ID or x.ID. + string SetFunc(Output* out, Env* env); - // Returns true if the expression folds to an integer - // constant with env, and puts the constant in *pn. - // - bool ConstFold(Env* env, int* pn) const; + // Returns true if the expression folds to an integer + // constant with env, and puts the constant in *pn. + // + bool ConstFold(Env* env, int* pn) const; - // Whether id is referenced in the expression - bool HasReference(const ID* id) const; + // Whether id is referenced in the expression + bool HasReference(const ID* id) const; - // Suppose the data for type might be incomplete, what is - // the minimal number of bytes from data head required to - // compute the expression? For example, how many bytes of frame - // header do we need to determine the length of the frame? - // - // The parameter points to the Env of a type. - // - // Returns -1 if the number is not a constant. - // - int MinimalHeaderSize(Env* env); + // Suppose the data for type might be incomplete, what is + // the minimal number of bytes from data head required to + // compute the expression? For example, how many bytes of frame + // header do we need to determine the length of the frame? + // + // The parameter points to the Env of a type. + // + // Returns -1 if the number is not a constant. + // + int MinimalHeaderSize(Env* env); - // Whether evaluation of the expression requires the analyzer context - bool RequiresAnalyzerContext() const; + // Whether evaluation of the expression requires the analyzer context + bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; private: - ExprType expr_type_; + ExprType expr_type_; - int num_operands_; - Expr* operand_[3]; + int num_operands_; + Expr* operand_[3]; - ID* id_; // EXPR_ID - Number* num_; // EXPR_NUM - ConstString* cstr_; // EXPR_CSTR - RegEx* regex_; // EXPR_REGEX - ExprList* args_; // EXPR_CALLARGS - CaseExprList* cases_; // EXPR_CASE + ID* id_; // EXPR_ID + Number* num_; // EXPR_NUM + ConstString* cstr_; // EXPR_CSTR + RegEx* regex_; // EXPR_REGEX + ExprList* args_; // EXPR_CALLARGS + CaseExprList* cases_; // EXPR_CASE - string str_; // value string - string orig_; // original string for debugging info + string str_; // value string + string orig_; // original string for debugging info - void GenStrFromFormat(Env* env); - void GenEval(Output* out, Env* env); - void GenCaseEval(Output* out_cc, Env* env); - }; + void GenStrFromFormat(Env* env); + void GenEval(Output* out, Env* env); + void GenCaseEval(Output* out_cc, Env* env); +}; string OrigExprList(ExprList* exprlist); string EvalExprList(ExprList* exprlist, Output* out, Env* env); // An entry of the case expression, consisting of one or more constant // expressions for the case index and a value expression. -class CaseExpr : public Object, public DataDepElement - { +class CaseExpr : public Object, public DataDepElement { public: - CaseExpr(ExprList* index, Expr* value); - ~CaseExpr() override; + CaseExpr(ExprList* index, Expr* value); + ~CaseExpr() override; - ExprList* index() const { return index_; } - Expr* value() const { return value_; } + ExprList* index() const { return index_; } + Expr* value() const { return value_; } - bool HasReference(const ID* id) const; - bool RequiresAnalyzerContext() const; + bool HasReference(const ID* id) const; + bool RequiresAnalyzerContext() const; protected: - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; private: - ExprList* index_; - Expr* value_; - }; + ExprList* index_; + Expr* value_; +}; #endif // pac_expr_h diff --git a/tools/binpac/src/pac_exttype.cc b/tools/binpac/src/pac_exttype.cc index 32f896e994..d9acd40a75 100644 --- a/tools/binpac/src/pac_exttype.cc +++ b/tools/binpac/src/pac_exttype.cc @@ -4,66 +4,42 @@ #include "pac_id.h" #include "pac_output.h" -bool ExternType::DefineValueVar() const - { - return true; - } +bool ExternType::DefineValueVar() const { return true; } -string ExternType::DataTypeStr() const - { - switch ( ext_type_ ) - { - case PLAIN: - case NUMBER: - return id_->Name(); - case POINTER: - return string(id_->Name()) + " *"; - default: - ASSERT(0); - return ""; - } - } +string ExternType::DataTypeStr() const { + switch ( ext_type_ ) { + case PLAIN: + case NUMBER: return id_->Name(); + case POINTER: return string(id_->Name()) + " *"; + default: ASSERT(0); return ""; + } +} -int ExternType::StaticSize(Env* env) const - { - ASSERT(0); - return -1; - } +int ExternType::StaticSize(Env* env) const { + ASSERT(0); + return -1; +} -bool ExternType::ByteOrderSensitive() const - { - return false; - } +bool ExternType::ByteOrderSensitive() const { return false; } -string ExternType::EvalMember(const ID* member_id) const - { - return strfmt("%s%s", ext_type_ == POINTER ? "->" : ".", member_id->Name()); - } +string ExternType::EvalMember(const ID* member_id) const { + return strfmt("%s%s", ext_type_ == POINTER ? "->" : ".", member_id->Name()); +} -void ExternType::GenInitCode(Output* out_cc, Env* env) - { - if ( IsNumericType() ) - out_cc->println("%s = 0;", env->LValue(value_var())); - else if ( IsPointerType() ) - out_cc->println("%s = nullptr;", env->LValue(value_var())); +void ExternType::GenInitCode(Output* out_cc, Env* env) { + if ( IsNumericType() ) + out_cc->println("%s = 0;", env->LValue(value_var())); + else if ( IsPointerType() ) + out_cc->println("%s = nullptr;", env->LValue(value_var())); - Type::GenInitCode(out_cc, env); - } + Type::GenInitCode(out_cc, env); +} -void ExternType::DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) - { - ASSERT(0); - } +void ExternType::DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) { ASSERT(0); } -void ExternType::GenDynamicSize(Output* out, Env* env, const DataPtr& data) - { - ASSERT(0); - } +void ExternType::GenDynamicSize(Output* out, Env* env, const DataPtr& data) { ASSERT(0); } -Type* ExternType::DoClone() const - { - return new ExternType(id_->clone(), ext_type_); - } +Type* ExternType::DoClone() const { return new ExternType(id_->clone(), ext_type_); } // Definitions of pre-defined external types @@ -71,16 +47,15 @@ Type* ExternType::DoClone() const #include "pac_externtype.def" #undef EXTERNTYPE -void ExternType::static_init() - { - ID* id; - // TypeDecl *decl; - // decl = new TypeDecl(id, 0, extern_type_##name); +void ExternType::static_init() { + ID* id; + // TypeDecl *decl; + // decl = new TypeDecl(id, 0, extern_type_##name); -#define EXTERNTYPE(name, ctype, exttype) \ - id = new ID(#ctype); \ - extern_type_##name = new ExternType(id, ExternType::exttype); \ - Type::AddPredefinedType(#name, extern_type_##name); +#define EXTERNTYPE(name, ctype, exttype) \ + id = new ID(#ctype); \ + extern_type_##name = new ExternType(id, ExternType::exttype); \ + Type::AddPredefinedType(#name, extern_type_##name); #include "pac_externtype.def" #undef EXTERNTYPE - } +} diff --git a/tools/binpac/src/pac_exttype.h b/tools/binpac/src/pac_exttype.h index 8d9b008f60..a5eaaa35be 100644 --- a/tools/binpac/src/pac_exttype.h +++ b/tools/binpac/src/pac_exttype.h @@ -8,41 +8,35 @@ // spefication, e.g., in a record field). The type name is copied // literally to the compiled code. -class ExternType : public Type - { +class ExternType : public Type { public: - enum EXTType - { - PLAIN, - NUMBER, - POINTER - }; - ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) { } + enum EXTType { PLAIN, NUMBER, POINTER }; + ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) {} - bool DefineValueVar() const override; - string DataTypeStr() const override; - int StaticSize(Env* env) const override; - bool ByteOrderSensitive() const override; + bool DefineValueVar() const override; + string DataTypeStr() const override; + int StaticSize(Env* env) const override; + bool ByteOrderSensitive() const override; - string EvalMember(const ID* member_id) const override; - bool IsNumericType() const override { return ext_type_ == NUMBER; } - bool IsPointerType() const override { return ext_type_ == POINTER; } + string EvalMember(const ID* member_id) const override; + bool IsNumericType() const override { return ext_type_ == NUMBER; } + bool IsPointerType() const override { return ext_type_ == POINTER; } - void GenInitCode(Output* out_cc, Env* env) override; + void GenInitCode(Output* out_cc, Env* env) override; protected: - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; - Type* DoClone() const override; + Type* DoClone() const override; private: - const ID* id_; - EXTType ext_type_; + const ID* id_; + EXTType ext_type_; public: - static void static_init(); - }; + static void static_init(); +}; #define EXTERNTYPE(name, ctype, exttype) extern ExternType* extern_type_##name; #include "pac_externtype.def" diff --git a/tools/binpac/src/pac_field.cc b/tools/binpac/src/pac_field.cc index dc9fd81fb1..0673555878 100644 --- a/tools/binpac/src/pac_field.cc +++ b/tools/binpac/src/pac_field.cc @@ -7,138 +7,117 @@ #include "pac_type.h" Field::Field(FieldType tof, int flags, ID* id, Type* type) - : DataDepElement(DataDepElement::FIELD), tof_(tof), flags_(flags), id_(id), type_(type) - { - decl_id_ = current_decl_id; - field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name()); - attrs_ = nullptr; - } + : DataDepElement(DataDepElement::FIELD), tof_(tof), flags_(flags), id_(id), type_(type) { + decl_id_ = current_decl_id; + field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name()); + attrs_ = nullptr; +} -Field::~Field() - { - delete id_; - delete type_; - delete_list(AttrList, attrs_); - } +Field::~Field() { + delete id_; + delete type_; + delete_list(AttrList, attrs_); +} -void Field::AddAttr(AttrList* attrs) - { - bool delete_attrs = false; +void Field::AddAttr(AttrList* attrs) { + bool delete_attrs = false; - if ( ! attrs_ ) - { - attrs_ = attrs; - } - else - { - attrs_->insert(attrs_->end(), attrs->begin(), attrs->end()); - delete_attrs = true; - } + if ( ! attrs_ ) { + attrs_ = attrs; + } + else { + attrs_->insert(attrs_->end(), attrs->begin(), attrs->end()); + delete_attrs = true; + } - foreach (i, AttrList, attrs) - ProcessAttr(*i); + foreach (i, AttrList, attrs) + ProcessAttr(*i); - if ( delete_attrs ) - delete attrs; - } + if ( delete_attrs ) + delete attrs; +} -void Field::ProcessAttr(Attr* a) - { - switch ( a->type() ) - { - case ATTR_IF: - if ( tof() != LET_FIELD && tof() != WITHINPUT_FIELD ) - { - throw Exception(a, "&if can only be applied to a " - "let field"); - } - break; - default: - break; - } +void Field::ProcessAttr(Attr* a) { + switch ( a->type() ) { + case ATTR_IF: + if ( tof() != LET_FIELD && tof() != WITHINPUT_FIELD ) { + throw Exception(a, + "&if can only be applied to a " + "let field"); + } + break; + default: break; + } - if ( type_ ) - type_->ProcessAttr(a); - } + if ( type_ ) + type_->ProcessAttr(a); +} -bool Field::anonymous_field() const - { - return type_ && type_->anonymous_value_var(); - } +bool Field::anonymous_field() const { return type_ && type_->anonymous_value_var(); } -int Field::ValueVarType() const - { - if ( flags_ & CLASS_MEMBER ) - return (flags_ & PUBLIC_READABLE) ? MEMBER_VAR : PRIV_MEMBER_VAR; - else - return TEMP_VAR; - } +int Field::ValueVarType() const { + if ( flags_ & CLASS_MEMBER ) + return (flags_ & PUBLIC_READABLE) ? MEMBER_VAR : PRIV_MEMBER_VAR; + else + return TEMP_VAR; +} -void Field::Prepare(Env* env) - { - if ( type_ ) - { - if ( anonymous_field() ) - flags_ &= ~(CLASS_MEMBER | PUBLIC_READABLE); - if ( ! type_->persistent() ) - flags_ &= (~PUBLIC_READABLE); +void Field::Prepare(Env* env) { + if ( type_ ) { + if ( anonymous_field() ) + flags_ &= ~(CLASS_MEMBER | PUBLIC_READABLE); + if ( ! type_->persistent() ) + flags_ &= (~PUBLIC_READABLE); - type_->set_value_var(id(), ValueVarType()); - type_->Prepare(env, flags_ & TYPE_TO_BE_PARSED ? Type::TO_BE_PARSED : 0); - env->SetField(id(), this); - } - } + type_->set_value_var(id(), ValueVarType()); + type_->Prepare(env, flags_ & TYPE_TO_BE_PARSED ? Type::TO_BE_PARSED : 0); + env->SetField(id(), this); + } +} -void Field::GenPubDecls(Output* out_h, Env* env) - { - if ( type_ && (flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER) ) - type_->GenPubDecls(out_h, env); - } +void Field::GenPubDecls(Output* out_h, Env* env) { + if ( type_ && (flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER) ) + type_->GenPubDecls(out_h, env); +} -void Field::GenPrivDecls(Output* out_h, Env* env) - { - // Generate private declaration only if it is a class member - if ( type_ && (flags_ & CLASS_MEMBER) ) - type_->GenPrivDecls(out_h, env); - } +void Field::GenPrivDecls(Output* out_h, Env* env) { + // Generate private declaration only if it is a class member + if ( type_ && (flags_ & CLASS_MEMBER) ) + type_->GenPrivDecls(out_h, env); +} -void Field::GenTempDecls(Output* out_h, Env* env) - { - // Generate temp field - if ( type_ && ! (flags_ & CLASS_MEMBER) ) - type_->GenPrivDecls(out_h, env); - } +void Field::GenTempDecls(Output* out_h, Env* env) { + // Generate temp field + if ( type_ && ! (flags_ & CLASS_MEMBER) ) + type_->GenPrivDecls(out_h, env); +} -void Field::GenInitCode(Output* out_cc, Env* env) - { - if ( type_ && ! anonymous_field() ) - type_->GenInitCode(out_cc, env); - } +void Field::GenInitCode(Output* out_cc, Env* env) { + if ( type_ && ! anonymous_field() ) + type_->GenInitCode(out_cc, env); +} -void Field::GenCleanUpCode(Output* out_cc, Env* env) - { - if ( type_ && ! anonymous_field() ) - type_->GenCleanUpCode(out_cc, env); - } +void Field::GenCleanUpCode(Output* out_cc, Env* env) { + if ( type_ && ! anonymous_field() ) + type_->GenCleanUpCode(out_cc, env); +} -bool Field::DoTraverse(DataDepVisitor* visitor) - { - // Check parameterized type - if ( type_ && ! type_->Traverse(visitor) ) - return false; - foreach (i, AttrList, attrs_) - if ( ! (*i)->Traverse(visitor) ) - return false; - return true; - } +bool Field::DoTraverse(DataDepVisitor* visitor) { + // Check parameterized type + if ( type_ && ! type_->Traverse(visitor) ) + return false; + foreach (i, AttrList, attrs_) + if ( ! (*i)->Traverse(visitor) ) + return false; + return true; +} -bool Field::RequiresAnalyzerContext() const - { - // Check parameterized type - if ( type_ && type_->RequiresAnalyzerContext() ) - return true; - foreach (i, AttrList, attrs_) - if ( (*i)->RequiresAnalyzerContext() ) - return true; - return false; - } +bool Field::RequiresAnalyzerContext() const { + // Check parameterized type + if ( type_ && type_->RequiresAnalyzerContext() ) + return true; + foreach (i, AttrList, attrs_) + if ( (*i)->RequiresAnalyzerContext() ) + return true; + return false; +} diff --git a/tools/binpac/src/pac_field.h b/tools/binpac/src/pac_field.h index 2327db6cad..bde5ff0f43 100644 --- a/tools/binpac/src/pac_field.h +++ b/tools/binpac/src/pac_field.h @@ -6,80 +6,78 @@ // A "field" is a member of class. -enum FieldType - { - CASE_FIELD, - CONTEXT_FIELD, - FLOW_FIELD, - LET_FIELD, - PADDING_FIELD, - PARAM_FIELD, - RECORD_FIELD, - PARSE_VAR_FIELD, - PRIV_VAR_FIELD, - PUB_VAR_FIELD, - TEMP_VAR_FIELD, - WITHINPUT_FIELD, - }; +enum FieldType { + CASE_FIELD, + CONTEXT_FIELD, + FLOW_FIELD, + LET_FIELD, + PADDING_FIELD, + PARAM_FIELD, + RECORD_FIELD, + PARSE_VAR_FIELD, + PRIV_VAR_FIELD, + PUB_VAR_FIELD, + TEMP_VAR_FIELD, + WITHINPUT_FIELD, +}; -class Field : public Object, public DataDepElement - { +class Field : public Object, public DataDepElement { public: - Field(FieldType tof, int flags, ID* id, Type* type); - // Field flags + Field(FieldType tof, int flags, ID* id, Type* type); + // Field flags - // Whether the field will be evaluated by calling the Parse() - // function of the type - static const int TYPE_TO_BE_PARSED = 1; - static const int TYPE_NOT_TO_BE_PARSED = 0; + // Whether the field will be evaluated by calling the Parse() + // function of the type + static const int TYPE_TO_BE_PARSED = 1; + static const int TYPE_NOT_TO_BE_PARSED = 0; - // Whether the field is a member of the class or a temp - // variable - static const int CLASS_MEMBER = 2; - static const int NOT_CLASS_MEMBER = 0; + // Whether the field is a member of the class or a temp + // variable + static const int CLASS_MEMBER = 2; + static const int NOT_CLASS_MEMBER = 0; - // Whether the field is public readable - static const int PUBLIC_READABLE = 4; - static const int NOT_PUBLIC_READABLE = 0; + // Whether the field is public readable + static const int PUBLIC_READABLE = 4; + static const int NOT_PUBLIC_READABLE = 0; - ~Field() override; + ~Field() override; - FieldType tof() const { return tof_; } - const ID* id() const { return id_; } - Type* type() const { return type_; } - const ID* decl_id() const { return decl_id_; } + FieldType tof() const { return tof_; } + const ID* id() const { return id_; } + Type* type() const { return type_; } + const ID* decl_id() const { return decl_id_; } - bool anonymous_field() const; + bool anonymous_field() const; - void AddAttr(AttrList* attrs); + void AddAttr(AttrList* attrs); - // The field interface - virtual void ProcessAttr(Attr* attr); - virtual void Prepare(Env* env); + // The field interface + virtual void ProcessAttr(Attr* attr); + virtual void Prepare(Env* env); - virtual void GenPubDecls(Output* out, Env* env); - virtual void GenPrivDecls(Output* out, Env* env); - virtual void GenTempDecls(Output* out, Env* env); + virtual void GenPubDecls(Output* out, Env* env); + virtual void GenPrivDecls(Output* out, Env* env); + virtual void GenTempDecls(Output* out, Env* env); - virtual void GenInitCode(Output* out, Env* env); - virtual void GenCleanUpCode(Output* out, Env* env); + virtual void GenInitCode(Output* out, Env* env); + virtual void GenCleanUpCode(Output* out, Env* env); - virtual bool RequiresAnalyzerContext() const; + virtual bool RequiresAnalyzerContext() const; protected: - int ValueVarType() const; - bool ToBeParsed() const; + int ValueVarType() const; + bool ToBeParsed() const; - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; protected: - FieldType tof_; - int flags_; - ID* id_; - Type* type_; - const ID* decl_id_; - string field_id_str_; - AttrList* attrs_; - }; + FieldType tof_; + int flags_; + ID* id_; + Type* type_; + const ID* decl_id_; + string field_id_str_; + AttrList* attrs_; +}; #endif // pac_field_h diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index 75a42c92fd..72c8a83b64 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -15,298 +15,257 @@ #include "pac_type.h" #include "pac_varfield.h" -FlowDecl::FlowDecl(ID* id, ParamList* params, AnalyzerElementList* elemlist) - : AnalyzerDecl(id, FLOW, params) - { - dataunit_ = nullptr; - conn_decl_ = nullptr; - flow_buffer_var_field_ = nullptr; - AddElements(elemlist); - } +FlowDecl::FlowDecl(ID* id, ParamList* params, AnalyzerElementList* elemlist) : AnalyzerDecl(id, FLOW, params) { + dataunit_ = nullptr; + conn_decl_ = nullptr; + flow_buffer_var_field_ = nullptr; + AddElements(elemlist); +} -FlowDecl::~FlowDecl() - { - delete flow_buffer_var_field_; - delete dataunit_; - } +FlowDecl::~FlowDecl() { + delete flow_buffer_var_field_; + delete dataunit_; +} ParameterizedType* FlowDecl::flow_buffer_type_ = nullptr; -ParameterizedType* FlowDecl::flow_buffer_type() - { - if ( ! flow_buffer_type_ ) - { - flow_buffer_type_ = new ParameterizedType(new ID(kFlowBufferClass), nullptr); - } - return flow_buffer_type_; - } +ParameterizedType* FlowDecl::flow_buffer_type() { + if ( ! flow_buffer_type_ ) { + flow_buffer_type_ = new ParameterizedType(new ID(kFlowBufferClass), nullptr); + } + return flow_buffer_type_; +} -void FlowDecl::AddBaseClass(vector* base_classes) const - { - base_classes->push_back("binpac::FlowAnalyzer"); - } +void FlowDecl::AddBaseClass(vector* base_classes) const { base_classes->push_back("binpac::FlowAnalyzer"); } -void FlowDecl::ProcessFlowElement(AnalyzerFlow* flow_elem) - { - throw Exception(flow_elem, "flow should be defined in only a connection declaration"); - } +void FlowDecl::ProcessFlowElement(AnalyzerFlow* flow_elem) { + throw Exception(flow_elem, "flow should be defined in only a connection declaration"); +} -void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) - { - if ( dataunit_ ) - { - throw Exception(dataunit_elem, "dataunit already defined"); - } - dataunit_ = dataunit_elem; +void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) { + if ( dataunit_ ) { + throw Exception(dataunit_elem, "dataunit already defined"); + } + dataunit_ = dataunit_elem; - if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) - { - dataunit_->data_type()->MarkIncrementalInput(); + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { + dataunit_->data_type()->MarkIncrementalInput(); - flow_buffer_var_field_ = new PubVarField(flow_buffer_id->clone(), - FlowDecl::flow_buffer_type()->Clone()); - type_->AddField(flow_buffer_var_field_); + flow_buffer_var_field_ = new PubVarField(flow_buffer_id->clone(), FlowDecl::flow_buffer_type()->Clone()); + type_->AddField(flow_buffer_var_field_); - ASSERT(AnalyzerContextDecl::current_analyzer_context()); - AnalyzerContextDecl::current_analyzer_context()->AddFlowBuffer(); + ASSERT(AnalyzerContextDecl::current_analyzer_context()); + AnalyzerContextDecl::current_analyzer_context()->AddFlowBuffer(); - // Add an argument to the context initiation - dataunit_->context_type()->AddParamArg(new Expr(flow_buffer_var_field_->id()->clone())); - } - } + // Add an argument to the context initiation + dataunit_->context_type()->AddParamArg(new Expr(flow_buffer_var_field_->id()->clone())); + } +} -void FlowDecl::Prepare() - { - // Add the connection parameter - if ( ! conn_decl_ ) - { - throw Exception(this, "no connection is not declared for the flow"); - } +void FlowDecl::Prepare() { + // Add the connection parameter + if ( ! conn_decl_ ) { + throw Exception(this, "no connection is not declared for the flow"); + } - if ( ! params_ ) - params_ = new ParamList(); + if ( ! params_ ) + params_ = new ParamList(); - params_->insert(params_->begin(), new Param(connection_id->clone(), conn_decl_->DataType())); + params_->insert(params_->begin(), new Param(connection_id->clone(), conn_decl_->DataType())); - AnalyzerDecl::Prepare(); + AnalyzerDecl::Prepare(); - dataunit_->Prepare(env_); - } + dataunit_->Prepare(env_); +} -void FlowDecl::GenPubDecls(Output* out_h, Output* out_cc) - { - AnalyzerDecl::GenPubDecls(out_h, out_cc); - } +void FlowDecl::GenPubDecls(Output* out_h, Output* out_cc) { AnalyzerDecl::GenPubDecls(out_h, out_cc); } -void FlowDecl::GenPrivDecls(Output* out_h, Output* out_cc) - { - // Declare the data unit - dataunit_->dataunit_var_field()->GenPrivDecls(out_h, env_); +void FlowDecl::GenPrivDecls(Output* out_h, Output* out_cc) { + // Declare the data unit + dataunit_->dataunit_var_field()->GenPrivDecls(out_h, env_); - // Declare the analyzer context - dataunit_->context_var_field()->GenPrivDecls(out_h, env_); + // Declare the analyzer context + dataunit_->context_var_field()->GenPrivDecls(out_h, env_); - AnalyzerDecl::GenPrivDecls(out_h, out_cc); - } + AnalyzerDecl::GenPrivDecls(out_h, out_cc); +} -void FlowDecl::GenInitCode(Output* out_cc) - { - AnalyzerDecl::GenInitCode(out_cc); +void FlowDecl::GenInitCode(Output* out_cc) { + AnalyzerDecl::GenInitCode(out_cc); - out_cc->println("%s = nullptr;", env_->LValue(dataunit_id)); - out_cc->println("%s = nullptr;", env_->LValue(analyzer_context_id)); + out_cc->println("%s = nullptr;", env_->LValue(dataunit_id)); + out_cc->println("%s = nullptr;", env_->LValue(analyzer_context_id)); - if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) - { - flow_buffer_var_field_->type()->GenPreParsing(out_cc, env_); - env_->SetEvaluated(flow_buffer_var_field_->id()); - } - } + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { + flow_buffer_var_field_->type()->GenPreParsing(out_cc, env_); + env_->SetEvaluated(flow_buffer_var_field_->id()); + } +} -void FlowDecl::GenCleanUpCode(Output* out_cc) - { - GenDeleteDataUnit(out_cc); - AnalyzerDecl::GenCleanUpCode(out_cc); - } +void FlowDecl::GenCleanUpCode(Output* out_cc) { + GenDeleteDataUnit(out_cc); + AnalyzerDecl::GenCleanUpCode(out_cc); +} -void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc) - { - string proto = strfmt("%s()", kFlowEOF); +void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc) { + string proto = strfmt("%s()", kFlowEOF); - out_h->println("void %s;", proto.c_str()); + out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); - foreach (i, AnalyzerHelperList, eof_helpers_) - { - (*i)->GenCode(nullptr, out_cc, this); - } + foreach (i, AnalyzerHelperList, eof_helpers_) { + (*i)->GenCode(nullptr, out_cc, this); + } - if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) - { - out_cc->println("%s->set_eof();", env_->LValue(flow_buffer_id)); - out_cc->println("%s(nullptr, nullptr);", kNewData); - } + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { + out_cc->println("%s->set_eof();", env_->LValue(flow_buffer_id)); + out_cc->println("%s(nullptr, nullptr);", kNewData); + } - out_cc->println("}"); - out_cc->dec_indent(); - } + out_cc->println("}"); + out_cc->dec_indent(); +} -void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc) - { - string proto = strfmt("%s(int gap_length)", kFlowGap); +void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc) { + string proto = strfmt("%s(int gap_length)", kFlowGap); - out_h->println("void %s;", proto.c_str()); + out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); - if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) - { - out_cc->println("%s->NewGap(gap_length);", env_->LValue(flow_buffer_id)); - } + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { + out_cc->println("%s->NewGap(gap_length);", env_->LValue(flow_buffer_id)); + } - out_cc->println("}"); - out_cc->dec_indent(); - } + out_cc->println("}"); + out_cc->dec_indent(); +} -void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc) - { - env_->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); - env_->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); +void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc) { + env_->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); + env_->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); - string proto = strfmt("%s(const_byteptr %s, const_byteptr %s)", kNewData, - env_->LValue(begin_of_data), env_->LValue(end_of_data)); + string proto = strfmt("%s(const_byteptr %s, const_byteptr %s)", kNewData, env_->LValue(begin_of_data), + env_->LValue(end_of_data)); - out_h->println("void %s;", proto.c_str()); + out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); - out_cc->println("try"); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("try"); + out_cc->inc_indent(); + out_cc->println("{"); - env_->SetEvaluated(begin_of_data); - env_->SetEvaluated(end_of_data); + env_->SetEvaluated(begin_of_data); + env_->SetEvaluated(end_of_data); - switch ( dataunit_->type() ) - { - case AnalyzerDataUnit::DATAGRAM: - GenCodeDatagram(out_cc); - break; - case AnalyzerDataUnit::FLOWUNIT: - GenCodeFlowUnit(out_cc); - break; - default: - ASSERT(0); - } + switch ( dataunit_->type() ) { + case AnalyzerDataUnit::DATAGRAM: GenCodeDatagram(out_cc); break; + case AnalyzerDataUnit::FLOWUNIT: GenCodeFlowUnit(out_cc); break; + default: ASSERT(0); + } - out_cc->println("}"); - out_cc->dec_indent(); + out_cc->println("}"); + out_cc->dec_indent(); - out_cc->println("catch ( binpac::Exception const &e )"); - out_cc->inc_indent(); - out_cc->println("{"); - GenCleanUpCode(out_cc); - if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) - { - out_cc->println("%s->DiscardData();", env_->LValue(flow_buffer_id)); - } - out_cc->println("throw e;"); - out_cc->println("}"); - out_cc->dec_indent(); + out_cc->println("catch ( binpac::Exception const &e )"); + out_cc->inc_indent(); + out_cc->println("{"); + GenCleanUpCode(out_cc); + if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { + out_cc->println("%s->DiscardData();", env_->LValue(flow_buffer_id)); + } + out_cc->println("throw e;"); + out_cc->println("}"); + out_cc->dec_indent(); - out_cc->println("}"); - out_cc->dec_indent(); - out_cc->println(""); - } + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); +} -void FlowDecl::GenNewDataUnit(Output* out_cc) - { - Type* unit_datatype = dataunit_->data_type(); - // dataunit_->data_type()->GenPreParsing(out_cc, env_); - dataunit_->GenNewDataUnit(out_cc, env_); - if ( unit_datatype->buffer_input() && unit_datatype->buffer_mode() == Type::BUFFER_BY_LENGTH ) - { - out_cc->println("%s->NewFrame(0, false);", env_->LValue(flow_buffer_id)); - } - dataunit_->GenNewContext(out_cc, env_); - } +void FlowDecl::GenNewDataUnit(Output* out_cc) { + Type* unit_datatype = dataunit_->data_type(); + // dataunit_->data_type()->GenPreParsing(out_cc, env_); + dataunit_->GenNewDataUnit(out_cc, env_); + if ( unit_datatype->buffer_input() && unit_datatype->buffer_mode() == Type::BUFFER_BY_LENGTH ) { + out_cc->println("%s->NewFrame(0, false);", env_->LValue(flow_buffer_id)); + } + dataunit_->GenNewContext(out_cc, env_); +} -void FlowDecl::GenDeleteDataUnit(Output* out_cc) - { - // Do not just delete dataunit, because we may just want to Unref it. - // out_cc->println("delete %s;", env_->LValue(dataunit_id)); - dataunit_->data_type()->GenCleanUpCode(out_cc, env_); - dataunit_->context_type()->GenCleanUpCode(out_cc, env_); - } +void FlowDecl::GenDeleteDataUnit(Output* out_cc) { + // Do not just delete dataunit, because we may just want to Unref it. + // out_cc->println("delete %s;", env_->LValue(dataunit_id)); + dataunit_->data_type()->GenCleanUpCode(out_cc, env_); + dataunit_->context_type()->GenCleanUpCode(out_cc, env_); +} -void FlowDecl::GenCodeFlowUnit(Output* out_cc) - { - Type* unit_datatype = dataunit_->data_type(); +void FlowDecl::GenCodeFlowUnit(Output* out_cc) { + Type* unit_datatype = dataunit_->data_type(); - out_cc->println("%s->NewData(%s, %s);", env_->LValue(flow_buffer_id), - env_->RValue(begin_of_data), env_->RValue(end_of_data)); + out_cc->println("%s->NewData(%s, %s);", env_->LValue(flow_buffer_id), env_->RValue(begin_of_data), + env_->RValue(end_of_data)); - out_cc->println("while ( %s->data_available() && ", env_->LValue(flow_buffer_id)); - out_cc->inc_indent(); - out_cc->println("( !%s->have_pending_request() || %s->ready() ) )", - env_->LValue(flow_buffer_id), env_->LValue(flow_buffer_id)); - out_cc->println("{"); + out_cc->println("while ( %s->data_available() && ", env_->LValue(flow_buffer_id)); + out_cc->inc_indent(); + out_cc->println("( !%s->have_pending_request() || %s->ready() ) )", env_->LValue(flow_buffer_id), + env_->LValue(flow_buffer_id)); + out_cc->println("{"); - // Generate a new dataunit if necessary - out_cc->println("if ( ! %s )", env_->LValue(dataunit_id)); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("BINPAC_ASSERT(!%s);", env_->LValue(analyzer_context_id)); - GenNewDataUnit(out_cc); - out_cc->println("}"); - out_cc->dec_indent(); + // Generate a new dataunit if necessary + out_cc->println("if ( ! %s )", env_->LValue(dataunit_id)); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("BINPAC_ASSERT(!%s);", env_->LValue(analyzer_context_id)); + GenNewDataUnit(out_cc); + out_cc->println("}"); + out_cc->dec_indent(); - DataPtr data(env_, nullptr, 0); - unit_datatype->GenParseCode(out_cc, env_, data, 0); + DataPtr data(env_, nullptr, 0); + unit_datatype->GenParseCode(out_cc, env_, data, 0); - out_cc->println("if ( %s )", unit_datatype->parsing_complete(env_).c_str()); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("// Clean up the flow unit after parsing"); - GenDeleteDataUnit(out_cc); - // out_cc->println("BINPAC_ASSERT(%s == 0);", env_->LValue(dataunit_id)); - out_cc->println("}"); - out_cc->dec_indent(); - out_cc->println("else"); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("// Resume upon next input segment"); - out_cc->println("BINPAC_ASSERT(!%s->ready());", env_->RValue(flow_buffer_id)); - out_cc->println("break;"); - out_cc->println("}"); - out_cc->dec_indent(); + out_cc->println("if ( %s )", unit_datatype->parsing_complete(env_).c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("// Clean up the flow unit after parsing"); + GenDeleteDataUnit(out_cc); + // out_cc->println("BINPAC_ASSERT(%s == 0);", env_->LValue(dataunit_id)); + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println("else"); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("// Resume upon next input segment"); + out_cc->println("BINPAC_ASSERT(!%s->ready());", env_->RValue(flow_buffer_id)); + out_cc->println("break;"); + out_cc->println("}"); + out_cc->dec_indent(); - out_cc->println("}"); - out_cc->dec_indent(); - } + out_cc->println("}"); + out_cc->dec_indent(); +} -void FlowDecl::GenCodeDatagram(Output* out_cc) - { - Type* unit_datatype = dataunit_->data_type(); - GenNewDataUnit(out_cc); +void FlowDecl::GenCodeDatagram(Output* out_cc) { + Type* unit_datatype = dataunit_->data_type(); + GenNewDataUnit(out_cc); - string parse_params = strfmt("%s, %s", env_->RValue(begin_of_data), env_->RValue(end_of_data)); + string parse_params = strfmt("%s, %s", env_->RValue(begin_of_data), env_->RValue(end_of_data)); - if ( RequiresAnalyzerContext::compute(unit_datatype) ) - { - parse_params += ", "; - parse_params += env_->RValue(analyzer_context_id); - } + if ( RequiresAnalyzerContext::compute(unit_datatype) ) { + parse_params += ", "; + parse_params += env_->RValue(analyzer_context_id); + } - DataPtr dataptr(env_, begin_of_data, 0); - unit_datatype->GenParseCode(out_cc, env_, dataptr, 0); + DataPtr dataptr(env_, begin_of_data, 0); + unit_datatype->GenParseCode(out_cc, env_, dataptr, 0); - GenDeleteDataUnit(out_cc); - } + GenDeleteDataUnit(out_cc); +} diff --git a/tools/binpac/src/pac_flow.h b/tools/binpac/src/pac_flow.h index ea018c6834..ae15b6bbad 100644 --- a/tools/binpac/src/pac_flow.h +++ b/tools/binpac/src/pac_flow.h @@ -3,45 +3,44 @@ #include "pac_analyzer.h" -class FlowDecl : public AnalyzerDecl - { +class FlowDecl : public AnalyzerDecl { public: - FlowDecl(ID* flow_id, ParamList* params, AnalyzerElementList* elemlist); - ~FlowDecl() override; + FlowDecl(ID* flow_id, ParamList* params, AnalyzerElementList* elemlist); + ~FlowDecl() override; - void Prepare() override; + void Prepare() override; - void set_conn_decl(ConnDecl* c) { conn_decl_ = c; } + void set_conn_decl(ConnDecl* c) { conn_decl_ = c; } - static ParameterizedType* flow_buffer_type(); + static ParameterizedType* flow_buffer_type(); protected: - void AddBaseClass(vector* base_classes) const override; + void AddBaseClass(vector* base_classes) const override; - void GenInitCode(Output* out_cc) override; - void GenCleanUpCode(Output* out_cc) override; - void GenProcessFunc(Output* out_h, Output* out_cc) override; - void GenEOFFunc(Output* out_h, Output* out_cc) override; - void GenGapFunc(Output* out_h, Output* out_cc) override; + void GenInitCode(Output* out_cc) override; + void GenCleanUpCode(Output* out_cc) override; + void GenProcessFunc(Output* out_h, Output* out_cc) override; + void GenEOFFunc(Output* out_h, Output* out_cc) override; + void GenGapFunc(Output* out_h, Output* out_cc) override; - void GenPubDecls(Output* out_h, Output* out_cc) override; - void GenPrivDecls(Output* out_h, Output* out_cc) override; + void GenPubDecls(Output* out_h, Output* out_cc) override; + void GenPrivDecls(Output* out_h, Output* out_cc) override; - void ProcessFlowElement(AnalyzerFlow* flow_elem) override; - void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) override; + void ProcessFlowElement(AnalyzerFlow* flow_elem) override; + void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) override; private: - void GenNewDataUnit(Output* out_cc); - void GenDeleteDataUnit(Output* out_cc); - void GenCodeFlowUnit(Output* out_cc); - void GenCodeDatagram(Output* out_cc); + void GenNewDataUnit(Output* out_cc); + void GenDeleteDataUnit(Output* out_cc); + void GenCodeFlowUnit(Output* out_cc); + void GenCodeDatagram(Output* out_cc); - AnalyzerDataUnit* dataunit_; - ConnDecl* conn_decl_; + AnalyzerDataUnit* dataunit_; + ConnDecl* conn_decl_; - Field* flow_buffer_var_field_; + Field* flow_buffer_var_field_; - static ParameterizedType* flow_buffer_type_; - }; + static ParameterizedType* flow_buffer_type_; +}; #endif // pac_flow_h diff --git a/tools/binpac/src/pac_func.cc b/tools/binpac/src/pac_func.cc index 9770be4747..3aa6d17811 100644 --- a/tools/binpac/src/pac_func.cc +++ b/tools/binpac/src/pac_func.cc @@ -7,109 +7,86 @@ #include "pac_type.h" Function::Function(ID* id, Type* type, ParamList* params) - : id_(id), type_(type), params_(params), expr_(nullptr), code_(nullptr) - { - analyzer_decl_ = nullptr; - env_ = nullptr; - } + : id_(id), type_(type), params_(params), expr_(nullptr), code_(nullptr) { + analyzer_decl_ = nullptr; + env_ = nullptr; +} -Function::~Function() - { - delete id_; - delete type_; - delete_list(ParamList, params_); - delete env_; - delete expr_; - delete code_; - } +Function::~Function() { + delete id_; + delete type_; + delete_list(ParamList, params_); + delete env_; + delete expr_; + delete code_; +} -void Function::Prepare(Env* env) - { - env->AddID(id_, FUNC_ID, type_); - env->SetEvaluated(id_); +void Function::Prepare(Env* env) { + env->AddID(id_, FUNC_ID, type_); + env->SetEvaluated(id_); - env_ = new Env(env, this); + env_ = new Env(env, this); - foreach (i, ParamList, params_) - { - Param* p = *i; - env_->AddID(p->id(), FUNC_PARAM, p->type()); - env_->SetEvaluated(p->id()); - } - } + foreach (i, ParamList, params_) { + Param* p = *i; + env_->AddID(p->id(), FUNC_PARAM, p->type()); + env_->SetEvaluated(p->id()); + } +} -void Function::GenForwardDeclaration(Output* out_h) - { - // Do nothing - } +void Function::GenForwardDeclaration(Output* out_h) { + // Do nothing +} -void Function::GenCode(Output* out_h, Output* out_cc) - { - out_h->println("%s %s(%s);", type_->DataTypeStr().c_str(), id_->Name(), - ParamDecls(params_).c_str()); +void Function::GenCode(Output* out_h, Output* out_cc) { + out_h->println("%s %s(%s);", type_->DataTypeStr().c_str(), id_->Name(), ParamDecls(params_).c_str()); - string class_str = ""; - if ( analyzer_decl_ ) - class_str = strfmt("%s::", analyzer_decl_->id()->Name()); + string class_str = ""; + if ( analyzer_decl_ ) + class_str = strfmt("%s::", analyzer_decl_->id()->Name()); - string proto_str = strfmt("%s %s%s(%s)", type_->DataTypeStr().c_str(), class_str.c_str(), - id_->Name(), ParamDecls(params_).c_str()); + string proto_str = strfmt("%s %s%s(%s)", type_->DataTypeStr().c_str(), class_str.c_str(), id_->Name(), + ParamDecls(params_).c_str()); - ASSERT(! (expr_ && code_)); + ASSERT(! (expr_ && code_)); - if ( expr_ ) - { - out_cc->println("%s", proto_str.c_str()); + if ( expr_ ) { + out_cc->println("%s", proto_str.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->inc_indent(); + out_cc->println("{"); - out_cc->println("return static_cast<%s>(%s);", type_->DataTypeStr().c_str(), - expr_->EvalExpr(out_cc, env_)); + out_cc->println("return static_cast<%s>(%s);", type_->DataTypeStr().c_str(), expr_->EvalExpr(out_cc, env_)); - out_cc->println("}"); - out_cc->dec_indent(); - } + out_cc->println("}"); + out_cc->dec_indent(); + } - else if ( code_ ) - { - out_cc->println("%s", proto_str.c_str()); + else if ( code_ ) { + out_cc->println("%s", proto_str.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->inc_indent(); + out_cc->println("{"); - code_->GenCode(out_cc, env_); + code_->GenCode(out_cc, env_); - out_cc->println("}"); - out_cc->dec_indent(); - } + out_cc->println("}"); + out_cc->dec_indent(); + } - out_cc->println(""); - } + out_cc->println(""); +} -FuncDecl::FuncDecl(Function* function) : Decl(function->id()->clone(), FUNC), function_(function) - { - function_->Prepare(global_env()); - } +FuncDecl::FuncDecl(Function* function) : Decl(function->id()->clone(), FUNC), function_(function) { + function_->Prepare(global_env()); +} -FuncDecl::~FuncDecl() - { - delete function_; - } +FuncDecl::~FuncDecl() { delete function_; } -void FuncDecl::Prepare() { } +void FuncDecl::Prepare() {} -void FuncDecl::GenForwardDeclaration(Output* out_h) - { - function_->GenForwardDeclaration(out_h); - } +void FuncDecl::GenForwardDeclaration(Output* out_h) { function_->GenForwardDeclaration(out_h); } -void FuncDecl::GenCode(Output* out_h, Output* out_cc) - { - function_->GenCode(out_h, out_cc); - } +void FuncDecl::GenCode(Output* out_h, Output* out_cc) { function_->GenCode(out_h, out_cc); } -AnalyzerFunction::AnalyzerFunction(Function* function) - : AnalyzerElement(FUNCTION), function_(function) - { - } +AnalyzerFunction::AnalyzerFunction(Function* function) : AnalyzerElement(FUNCTION), function_(function) {} diff --git a/tools/binpac/src/pac_func.h b/tools/binpac/src/pac_func.h index 5d7352f510..4246450496 100644 --- a/tools/binpac/src/pac_func.h +++ b/tools/binpac/src/pac_func.h @@ -4,65 +4,62 @@ #include "pac_analyzer.h" #include "pac_decl.h" -class Function : public Object - { +class Function : public Object { public: - Function(ID* id, Type* type, ParamList* params); - ~Function(); + Function(ID* id, Type* type, ParamList* params); + ~Function(); - ID* id() const { return id_; } + ID* id() const { return id_; } - AnalyzerDecl* analyzer_decl() const { return analyzer_decl_; } - void set_analyzer_decl(AnalyzerDecl* decl) { analyzer_decl_ = decl; } + AnalyzerDecl* analyzer_decl() const { return analyzer_decl_; } + void set_analyzer_decl(AnalyzerDecl* decl) { analyzer_decl_ = decl; } - Expr* expr() const { return expr_; } - void set_expr(Expr* expr) { expr_ = expr; } + Expr* expr() const { return expr_; } + void set_expr(Expr* expr) { expr_ = expr; } - EmbeddedCode* code() const { return code_; } - void set_code(EmbeddedCode* code) { code_ = code; } + EmbeddedCode* code() const { return code_; } + void set_code(EmbeddedCode* code) { code_ = code; } - void Prepare(Env* env); - void GenForwardDeclaration(Output* out_h); - void GenCode(Output* out_h, Output* out_cc); + void Prepare(Env* env); + void GenForwardDeclaration(Output* out_h); + void GenCode(Output* out_h, Output* out_cc); private: - Env* env_; + Env* env_; - ID* id_; - Type* type_; - ParamList* params_; + ID* id_; + Type* type_; + ParamList* params_; - AnalyzerDecl* analyzer_decl_; + AnalyzerDecl* analyzer_decl_; - Expr* expr_; - EmbeddedCode* code_; - }; + Expr* expr_; + EmbeddedCode* code_; +}; -class FuncDecl : public Decl - { +class FuncDecl : public Decl { public: - FuncDecl(Function* function); - ~FuncDecl() override; + FuncDecl(Function* function); + ~FuncDecl() override; - Function* function() const { return function_; } + Function* function() const { return function_; } - void Prepare() override; - void GenForwardDeclaration(Output* out_h) override; - void GenCode(Output* out_h, Output* out_cc) override; + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; private: - Function* function_; - }; + Function* function_; +}; -class AnalyzerFunction : public AnalyzerElement - { +class AnalyzerFunction : public AnalyzerElement { public: - AnalyzerFunction(Function* function); + AnalyzerFunction(Function* function); - Function* function() const { return function_; } + Function* function() const { return function_; } private: - Function* function_; - }; + Function* function_; +}; #endif // pac_func_h diff --git a/tools/binpac/src/pac_id.cc b/tools/binpac/src/pac_id.cc index 15a0d7c12d..06c2d4373d 100644 --- a/tools/binpac/src/pac_id.cc +++ b/tools/binpac/src/pac_id.cc @@ -38,402 +38,338 @@ const ID* buffering_state_id = nullptr; int ID::anonymous_id_seq = 0; -ID* ID::NewAnonymousID(const string& prefix) - { - ID* id = new ID(strfmt("%s%03d", prefix.c_str(), ++anonymous_id_seq)); - id->anonymous_id_ = true; - return id; - } +ID* ID::NewAnonymousID(const string& prefix) { + ID* id = new ID(strfmt("%s%03d", prefix.c_str(), ++anonymous_id_seq)); + id->anonymous_id_ = true; + return id; +} IDRecord::IDRecord(Env* arg_env, const ID* arg_id, IDType arg_id_type) - : env(arg_env), id(arg_id), id_type(arg_id_type) - { - eval = nullptr; - evaluated = in_evaluation = false; - setfunc = ""; // except for STATE_VAR - switch ( id_type ) - { - case MEMBER_VAR: - rvalue = strfmt("%s()", id->Name()); - lvalue = strfmt("%s_", id->Name()); - break; - case PRIV_MEMBER_VAR: - rvalue = strfmt("%s_", id->Name()); - lvalue = strfmt("%s_", id->Name()); - break; - case UNION_VAR: - rvalue = strfmt("%s()", id->Name()); - lvalue = strfmt("%s_", id->Name()); - break; - case CONST: - case GLOBAL_VAR: - rvalue = strfmt("%s", id->Name()); - lvalue = strfmt("%s", id->Name()); - break; - case TEMP_VAR: - rvalue = strfmt("t_%s", id->Name()); - lvalue = strfmt("t_%s", id->Name()); - break; - case STATE_VAR: - rvalue = strfmt("%s()", id->Name()); - lvalue = strfmt("%s_", id->Name()); - break; - case MACRO: - rvalue = "@MACRO@"; - lvalue = "@MACRO@"; - break; - case FUNC_ID: - rvalue = strfmt("%s", id->Name()); - lvalue = "@FUNC_ID@"; - break; - case FUNC_PARAM: - rvalue = strfmt("%s", id->Name()); - lvalue = "@FUNC_PARAM@"; - break; - } + : env(arg_env), id(arg_id), id_type(arg_id_type) { + eval = nullptr; + evaluated = in_evaluation = false; + setfunc = ""; // except for STATE_VAR + switch ( id_type ) { + case MEMBER_VAR: + rvalue = strfmt("%s()", id->Name()); + lvalue = strfmt("%s_", id->Name()); + break; + case PRIV_MEMBER_VAR: + rvalue = strfmt("%s_", id->Name()); + lvalue = strfmt("%s_", id->Name()); + break; + case UNION_VAR: + rvalue = strfmt("%s()", id->Name()); + lvalue = strfmt("%s_", id->Name()); + break; + case CONST: + case GLOBAL_VAR: + rvalue = strfmt("%s", id->Name()); + lvalue = strfmt("%s", id->Name()); + break; + case TEMP_VAR: + rvalue = strfmt("t_%s", id->Name()); + lvalue = strfmt("t_%s", id->Name()); + break; + case STATE_VAR: + rvalue = strfmt("%s()", id->Name()); + lvalue = strfmt("%s_", id->Name()); + break; + case MACRO: + rvalue = "@MACRO@"; + lvalue = "@MACRO@"; + break; + case FUNC_ID: + rvalue = strfmt("%s", id->Name()); + lvalue = "@FUNC_ID@"; + break; + case FUNC_PARAM: + rvalue = strfmt("%s", id->Name()); + lvalue = "@FUNC_PARAM@"; + break; + } - data_type = nullptr; - field = nullptr; - constant = constant_set = false; - macro = nullptr; - } + data_type = nullptr; + field = nullptr; + constant = constant_set = false; + macro = nullptr; +} -IDRecord::~IDRecord() { } +IDRecord::~IDRecord() {} -void IDRecord::SetConstant(int c) - { - ASSERT(id_type == CONST); - constant_set = true; - constant = c; - } +void IDRecord::SetConstant(int c) { + ASSERT(id_type == CONST); + constant_set = true; + constant = c; +} -bool IDRecord::GetConstant(int* pc) const - { - if ( constant_set ) - *pc = constant; - return constant_set; - } +bool IDRecord::GetConstant(int* pc) const { + if ( constant_set ) + *pc = constant; + return constant_set; +} -void IDRecord::SetMacro(Expr* e) - { - ASSERT(id_type == MACRO); - macro = e; - } +void IDRecord::SetMacro(Expr* e) { + ASSERT(id_type == MACRO); + macro = e; +} -Expr* IDRecord::GetMacro() const - { - ASSERT(id_type == MACRO); - return macro; - } +Expr* IDRecord::GetMacro() const { + ASSERT(id_type == MACRO); + return macro; +} -void IDRecord::SetEvaluated(bool v) - { - if ( v ) - ASSERT(! evaluated); - evaluated = v; - } +void IDRecord::SetEvaluated(bool v) { + if ( v ) + ASSERT(! evaluated); + evaluated = v; +} -void IDRecord::Evaluate(Output* out, Env* env) - { - if ( evaluated ) - return; +void IDRecord::Evaluate(Output* out, Env* env) { + if ( evaluated ) + return; - if ( ! out ) - throw ExceptionIDNotEvaluated(id); + if ( ! out ) + throw ExceptionIDNotEvaluated(id); - if ( ! eval ) - throw Exception(id, "no evaluation method"); - - if ( in_evaluation ) - throw ExceptionCyclicDependence(id); + if ( ! eval ) + throw Exception(id, "no evaluation method"); - in_evaluation = true; - eval->GenEval(out, env); - in_evaluation = false; + if ( in_evaluation ) + throw ExceptionCyclicDependence(id); - evaluated = true; - } + in_evaluation = true; + eval->GenEval(out, env); + in_evaluation = false; -const char* IDRecord::RValue() const - { - if ( id_type == MACRO ) - return macro->EvalExpr(nullptr, env); + evaluated = true; +} - if ( id_type == TEMP_VAR && ! evaluated ) - throw ExceptionIDNotEvaluated(id); +const char* IDRecord::RValue() const { + if ( id_type == MACRO ) + return macro->EvalExpr(nullptr, env); - return rvalue.c_str(); - } + if ( id_type == TEMP_VAR && ! evaluated ) + throw ExceptionIDNotEvaluated(id); -const char* IDRecord::LValue() const - { - ASSERT(id_type != MACRO && id_type != FUNC_ID); - return lvalue.c_str(); - } + return rvalue.c_str(); +} -Env::Env(Env* parent_env, Object* context_object) - : parent(parent_env), context_object_(context_object) - { - allow_undefined_id_ = false; - in_branch_ = false; - } +const char* IDRecord::LValue() const { + ASSERT(id_type != MACRO && id_type != FUNC_ID); + return lvalue.c_str(); +} -Env::~Env() - { - for ( id_map_t::iterator it = id_map.begin(); it != id_map.end(); ++it ) - { - delete it->second; - it->second = 0; - } - } +Env::Env(Env* parent_env, Object* context_object) : parent(parent_env), context_object_(context_object) { + allow_undefined_id_ = false; + in_branch_ = false; +} -void Env::AddID(const ID* id, IDType id_type, Type* data_type) - { - DEBUG_MSG("To add ID `%s'...\n", id->Name()); - id_map_t::iterator it = id_map.find(id); - if ( it != id_map.end() ) - { - DEBUG_MSG("Duplicate definition: `%s'\n", it->first->Name()); - throw ExceptionIDRedefinition(id); - } - id_map[id] = new IDRecord(this, id, id_type); - // TODO: figure out when data_type must be non-NULL - // ASSERT(data_type); - SetDataType(id, data_type); - } +Env::~Env() { + for ( id_map_t::iterator it = id_map.begin(); it != id_map.end(); ++it ) { + delete it->second; + it->second = 0; + } +} -void Env::AddConstID(const ID* id, const int c, Type* type) - { - if ( ! type ) - type = extern_type_int; - AddID(id, CONST, type); - SetConstant(id, c); - SetEvaluated(id); // a constant is always evaluated - } +void Env::AddID(const ID* id, IDType id_type, Type* data_type) { + DEBUG_MSG("To add ID `%s'...\n", id->Name()); + id_map_t::iterator it = id_map.find(id); + if ( it != id_map.end() ) { + DEBUG_MSG("Duplicate definition: `%s'\n", it->first->Name()); + throw ExceptionIDRedefinition(id); + } + id_map[id] = new IDRecord(this, id, id_type); + // TODO: figure out when data_type must be non-NULL + // ASSERT(data_type); + SetDataType(id, data_type); +} -void Env::AddMacro(const ID* id, Expr* macro) - { - AddID(id, MACRO, macro->DataType(this)); - SetMacro(id, macro); - SetEvaluated(id); - } +void Env::AddConstID(const ID* id, const int c, Type* type) { + if ( ! type ) + type = extern_type_int; + AddID(id, CONST, type); + SetConstant(id, c); + SetEvaluated(id); // a constant is always evaluated +} -ID* Env::AddTempID(Type* type) - { - ID* id = ID::NewAnonymousID("t_var_"); - AddID(id, TEMP_VAR, type); - return id; - } +void Env::AddMacro(const ID* id, Expr* macro) { + AddID(id, MACRO, macro->DataType(this)); + SetMacro(id, macro); + SetEvaluated(id); +} -IDRecord* Env::lookup(const ID* id, bool recursive, bool raise_exception) const - { - ASSERT(id); +ID* Env::AddTempID(Type* type) { + ID* id = ID::NewAnonymousID("t_var_"); + AddID(id, TEMP_VAR, type); + return id; +} - id_map_t::const_iterator it = id_map.find(id); - if ( it != id_map.end() ) - return it->second; +IDRecord* Env::lookup(const ID* id, bool recursive, bool raise_exception) const { + ASSERT(id); - if ( recursive && parent ) - return parent->lookup(id, recursive, raise_exception); + id_map_t::const_iterator it = id_map.find(id); + if ( it != id_map.end() ) + return it->second; - if ( raise_exception ) - throw ExceptionIDNotFound(id); - else - return nullptr; - } + if ( recursive && parent ) + return parent->lookup(id, recursive, raise_exception); -IDType Env::GetIDType(const ID* id) const - { - return lookup(id, true, true)->GetType(); - } + if ( raise_exception ) + throw ExceptionIDNotFound(id); + else + return nullptr; +} -const char* Env::RValue(const ID* id) const - { - IDRecord* r = lookup(id, true, false); - if ( r ) - return r->RValue(); - else - { - if ( allow_undefined_id() ) - return id->Name(); - else - throw ExceptionIDNotFound(id); - } - } +IDType Env::GetIDType(const ID* id) const { return lookup(id, true, true)->GetType(); } -const char* Env::LValue(const ID* id) const - { - return lookup(id, true, true)->LValue(); - } +const char* Env::RValue(const ID* id) const { + IDRecord* r = lookup(id, true, false); + if ( r ) + return r->RValue(); + else { + if ( allow_undefined_id() ) + return id->Name(); + else + throw ExceptionIDNotFound(id); + } +} -void Env::SetEvalMethod(const ID* id, Evaluatable* eval) - { - lookup(id, true, true)->SetEvalMethod(eval); - } +const char* Env::LValue(const ID* id) const { return lookup(id, true, true)->LValue(); } -void Env::Evaluate(Output* out, const ID* id) - { - IDRecord* r = lookup(id, true, ! allow_undefined_id()); - if ( r ) - r->Evaluate(out, this); - } +void Env::SetEvalMethod(const ID* id, Evaluatable* eval) { lookup(id, true, true)->SetEvalMethod(eval); } -bool Env::Evaluated(const ID* id) const - { - IDRecord* r = lookup(id, true, ! allow_undefined_id()); - if ( r ) - return r->Evaluated(); - else - // Assume undefined variables are already evaluated - return true; - } +void Env::Evaluate(Output* out, const ID* id) { + IDRecord* r = lookup(id, true, ! allow_undefined_id()); + if ( r ) + r->Evaluate(out, this); +} -void Env::SetEvaluated(const ID* id, bool v) - { - if ( in_branch() ) - { - Field* f = GetField(id); - if ( f && f->tof() == LET_FIELD ) - { - throw Exception(context_object_, strfmt("INTERNAL ERROR: " - "evaluating let field '%s' in a branch! " - "To work around this problem, " - "add '&requires(%s)' to the case type. " - "Sorry for the inconvenience.\n", - id->Name(), id->Name())); - ASSERT(0); - } - } +bool Env::Evaluated(const ID* id) const { + IDRecord* r = lookup(id, true, ! allow_undefined_id()); + if ( r ) + return r->Evaluated(); + else + // Assume undefined variables are already evaluated + return true; +} - IDRecord* r = lookup(id, false, false); - if ( r ) - r->SetEvaluated(v); - else if ( parent ) - parent->SetEvaluated(id, v); - else - throw ExceptionIDNotFound(id); - } +void Env::SetEvaluated(const ID* id, bool v) { + if ( in_branch() ) { + Field* f = GetField(id); + if ( f && f->tof() == LET_FIELD ) { + throw Exception(context_object_, strfmt("INTERNAL ERROR: " + "evaluating let field '%s' in a branch! " + "To work around this problem, " + "add '&requires(%s)' to the case type. " + "Sorry for the inconvenience.\n", + id->Name(), id->Name())); + ASSERT(0); + } + } -void Env::SetField(const ID* id, Field* field) - { - lookup(id, false, true)->SetField(field); - } + IDRecord* r = lookup(id, false, false); + if ( r ) + r->SetEvaluated(v); + else if ( parent ) + parent->SetEvaluated(id, v); + else + throw ExceptionIDNotFound(id); +} -Field* Env::GetField(const ID* id) const - { - return lookup(id, true, true)->GetField(); - } +void Env::SetField(const ID* id, Field* field) { lookup(id, false, true)->SetField(field); } -void Env::SetDataType(const ID* id, Type* type) - { - lookup(id, true, true)->SetDataType(type); - } +Field* Env::GetField(const ID* id) const { return lookup(id, true, true)->GetField(); } -Type* Env::GetDataType(const ID* id) const - { - IDRecord* r = lookup(id, true, false); - if ( r ) - return r->GetDataType(); - else - return nullptr; - } +void Env::SetDataType(const ID* id, Type* type) { lookup(id, true, true)->SetDataType(type); } -string Env::DataTypeStr(const ID* id) const - { - Type* type = GetDataType(id); - if ( ! type ) - throw Exception(id, "data type not defined"); - return type->DataTypeStr(); - } +Type* Env::GetDataType(const ID* id) const { + IDRecord* r = lookup(id, true, false); + if ( r ) + return r->GetDataType(); + else + return nullptr; +} -void Env::SetConstant(const ID* id, int constant) - { - lookup(id, false, true)->SetConstant(constant); - } +string Env::DataTypeStr(const ID* id) const { + Type* type = GetDataType(id); + if ( ! type ) + throw Exception(id, "data type not defined"); + return type->DataTypeStr(); +} -bool Env::GetConstant(const ID* id, int* pc) const - { - ASSERT(pc); - // lookup without raising exception - IDRecord* r = lookup(id, true, false); - if ( r ) - return r->GetConstant(pc); - else - return false; - } +void Env::SetConstant(const ID* id, int constant) { lookup(id, false, true)->SetConstant(constant); } -void Env::SetMacro(const ID* id, Expr* macro) - { - lookup(id, true, true)->SetMacro(macro); - } +bool Env::GetConstant(const ID* id, int* pc) const { + ASSERT(pc); + // lookup without raising exception + IDRecord* r = lookup(id, true, false); + if ( r ) + return r->GetConstant(pc); + else + return false; +} -Expr* Env::GetMacro(const ID* id) const - { - return lookup(id, true, true)->GetMacro(); - } +void Env::SetMacro(const ID* id, Expr* macro) { lookup(id, true, true)->SetMacro(macro); } -void init_builtin_identifiers() - { - default_value_var = new ID("val"); - null_id = new ID("NULL"); - null_byteseg_id = new ID("null_byteseg"); - begin_of_data = new ID("begin_of_data"); - end_of_data = new ID("end_of_data"); - len_of_data = new ID("length_of_data"); - byteorder_id = new ID("byteorder"); - bigendian_id = new ID("bigendian"); - littleendian_id = new ID("littleendian"); - unspecified_byteorder_id = new ID("unspecified_byteorder"); - const_true_id = new ID("true"); - const_false_id = new ID("false"); - analyzer_context_id = new ID("context"); - this_id = new ID("this"); - sourcedata_id = new ID("sourcedata"); - connection_id = new ID("connection"); - upflow_id = new ID("upflow"); - downflow_id = new ID("downflow"); - dataunit_id = new ID("dataunit"); - flow_buffer_id = new ID("flow_buffer"); - element_macro_id = new ID("$element"); - input_macro_id = new ID("$input"); - context_macro_id = new ID("$context"); - parsing_state_id = new ID("parsing_state"); - buffering_state_id = new ID("buffering_state"); +Expr* Env::GetMacro(const ID* id) const { return lookup(id, true, true)->GetMacro(); } - null_decl_id = new ID(""); - current_decl_id = null_decl_id; - } +void init_builtin_identifiers() { + default_value_var = new ID("val"); + null_id = new ID("NULL"); + null_byteseg_id = new ID("null_byteseg"); + begin_of_data = new ID("begin_of_data"); + end_of_data = new ID("end_of_data"); + len_of_data = new ID("length_of_data"); + byteorder_id = new ID("byteorder"); + bigendian_id = new ID("bigendian"); + littleendian_id = new ID("littleendian"); + unspecified_byteorder_id = new ID("unspecified_byteorder"); + const_true_id = new ID("true"); + const_false_id = new ID("false"); + analyzer_context_id = new ID("context"); + this_id = new ID("this"); + sourcedata_id = new ID("sourcedata"); + connection_id = new ID("connection"); + upflow_id = new ID("upflow"); + downflow_id = new ID("downflow"); + dataunit_id = new ID("dataunit"); + flow_buffer_id = new ID("flow_buffer"); + element_macro_id = new ID("$element"); + input_macro_id = new ID("$input"); + context_macro_id = new ID("$context"); + parsing_state_id = new ID("parsing_state"); + buffering_state_id = new ID("buffering_state"); -Env* global_env() - { - static Env* the_global_env = nullptr; + null_decl_id = new ID(""); + current_decl_id = null_decl_id; +} - if ( ! the_global_env ) - { - the_global_env = new Env(nullptr, nullptr); +Env* global_env() { + static Env* the_global_env = nullptr; - // These two are defined in binpac.h, so we do not need to - // generate code for them. - the_global_env->AddConstID(bigendian_id, 0); - the_global_env->AddConstID(littleendian_id, 1); - the_global_env->AddConstID(unspecified_byteorder_id, -1); - the_global_env->AddConstID(const_false_id, 0); - the_global_env->AddConstID(const_true_id, 1); - // A hack for ID "this" - the_global_env->AddConstID(this_id, 0); - the_global_env->AddConstID(null_id, 0, extern_type_nullptr); + if ( ! the_global_env ) { + the_global_env = new Env(nullptr, nullptr); + + // These two are defined in binpac.h, so we do not need to + // generate code for them. + the_global_env->AddConstID(bigendian_id, 0); + the_global_env->AddConstID(littleendian_id, 1); + the_global_env->AddConstID(unspecified_byteorder_id, -1); + the_global_env->AddConstID(const_false_id, 0); + the_global_env->AddConstID(const_true_id, 1); + // A hack for ID "this" + the_global_env->AddConstID(this_id, 0); + the_global_env->AddConstID(null_id, 0, extern_type_nullptr); #if 0 the_global_env->AddID(null_byteseg_id, GLOBAL_VAR, extern_type_const_byteseg); #endif - } + } - return the_global_env; - } + return the_global_env; +} -string set_function(const ID* id) - { - return strfmt("set_%s", id->Name()); - } +string set_function(const ID* id) { return strfmt("set_%s", id->Name()); } diff --git a/tools/binpac/src/pac_id.h b/tools/binpac/src/pac_id.h index 2cfdbfbd94..9c46da50c0 100644 --- a/tools/binpac/src/pac_id.h +++ b/tools/binpac/src/pac_id.h @@ -22,189 +22,179 @@ using namespace std; // Env -- a mapping from ID names to their L/R-value expressions and evaluation // methods. -enum IDType - { - CONST, - GLOBAL_VAR, - TEMP_VAR, - MEMBER_VAR, - PRIV_MEMBER_VAR, - UNION_VAR, - STATE_VAR, - MACRO, - FUNC_ID, - FUNC_PARAM, - }; +enum IDType { + CONST, + GLOBAL_VAR, + TEMP_VAR, + MEMBER_VAR, + PRIV_MEMBER_VAR, + UNION_VAR, + STATE_VAR, + MACRO, + FUNC_ID, + FUNC_PARAM, +}; class ID; class IDRecord; class Env; class Evaluatable; -class ID : public Object - { +class ID : public Object { public: - ID(string arg_name) : name(arg_name), anonymous_id_(false) - { - locname = nfmt("%s:%s", Location(), Name()); - } - ~ID() { delete[] locname; } + ID(string arg_name) : name(arg_name), anonymous_id_(false) { locname = nfmt("%s:%s", Location(), Name()); } + ~ID() { delete[] locname; } - bool operator==(ID const& x) const { return name == x.Name(); } + bool operator==(ID const& x) const { return name == x.Name(); } - const char* Name() const { return name.c_str(); } - const char* LocName() const { return locname; } - bool is_anonymous() const { return anonymous_id_; } + const char* Name() const { return name.c_str(); } + const char* LocName() const { return locname; } + bool is_anonymous() const { return anonymous_id_; } - ID* clone() const { return new ID(Name()); } + ID* clone() const { return new ID(Name()); } protected: - string name; - bool anonymous_id_; - char* locname; - friend class ID_ptr_cmp; + string name; + bool anonymous_id_; + char* locname; + friend class ID_ptr_cmp; public: - static ID* NewAnonymousID(const string& prefix); + static ID* NewAnonymousID(const string& prefix); private: - static int anonymous_id_seq; - }; + static int anonymous_id_seq; +}; // A comparison operator for pointers to ID's. -class ID_ptr_cmp - { +class ID_ptr_cmp { public: - bool operator()(const ID* const& id1, const ID* const& id2) const - { - ASSERT(id1); - ASSERT(id2); - return id1->name < id2->name; - } - }; + bool operator()(const ID* const& id1, const ID* const& id2) const { + ASSERT(id1); + ASSERT(id2); + return id1->name < id2->name; + } +}; -class IDRecord - { +class IDRecord { public: - IDRecord(Env* env, const ID* id, IDType id_type); - ~IDRecord(); + IDRecord(Env* env, const ID* id, IDType id_type); + ~IDRecord(); - IDType GetType() const { return id_type; } + IDType GetType() const { return id_type; } - void SetDataType(Type* type) { data_type = type; } - Type* GetDataType() const { return data_type; } + void SetDataType(Type* type) { data_type = type; } + Type* GetDataType() const { return data_type; } - void SetEvalMethod(Evaluatable* arg_eval) { eval = arg_eval; } - void Evaluate(Output* out, Env* env); - void SetEvaluated(bool v); - bool Evaluated() const { return evaluated; } + void SetEvalMethod(Evaluatable* arg_eval) { eval = arg_eval; } + void Evaluate(Output* out, Env* env); + void SetEvaluated(bool v); + bool Evaluated() const { return evaluated; } - void SetField(Field* f) { field = f; } - Field* GetField() const { return field; } + void SetField(Field* f) { field = f; } + Field* GetField() const { return field; } - void SetConstant(int c); - bool GetConstant(int* pc) const; + void SetConstant(int c); + bool GetConstant(int* pc) const; - void SetMacro(Expr* expr); - Expr* GetMacro() const; + void SetMacro(Expr* expr); + Expr* GetMacro() const; - const char* RValue() const; - const char* LValue() const; + const char* RValue() const; + const char* LValue() const; protected: - Env* env; - const ID* id; - IDType id_type; + Env* env; + const ID* id; + IDType id_type; - string rvalue; - string lvalue; - string setfunc; + string rvalue; + string lvalue; + string setfunc; - Type* data_type; + Type* data_type; - Field* field; + Field* field; - int constant; - bool constant_set; + int constant; + bool constant_set; - Expr* macro; + Expr* macro; - bool evaluated; - bool in_evaluation; // to detect cyclic dependence - Evaluatable* eval; - }; + bool evaluated; + bool in_evaluation; // to detect cyclic dependence + Evaluatable* eval; +}; -class Evaluatable - { +class Evaluatable { public: - virtual ~Evaluatable() { } - virtual void GenEval(Output* out, Env* env) = 0; - }; + virtual ~Evaluatable() {} + virtual void GenEval(Output* out, Env* env) = 0; +}; -class Env - { +class Env { public: - Env(Env* parent_env, Object* context_object); - ~Env(); + Env(Env* parent_env, Object* context_object); + ~Env(); - bool allow_undefined_id() const { return allow_undefined_id_; } - void set_allow_undefined_id(bool x) { allow_undefined_id_ = x; } + bool allow_undefined_id() const { return allow_undefined_id_; } + void set_allow_undefined_id(bool x) { allow_undefined_id_ = x; } - bool in_branch() const { return in_branch_; } - void set_in_branch(bool x) { in_branch_ = x; } + bool in_branch() const { return in_branch_; } + void set_in_branch(bool x) { in_branch_ = x; } - void AddID(const ID* id, IDType id_type, Type* type); - void AddConstID(const ID* id, const int c, Type* type = 0); - void AddMacro(const ID* id, Expr* expr); + void AddID(const ID* id, IDType id_type, Type* type); + void AddConstID(const ID* id, const int c, Type* type = 0); + void AddMacro(const ID* id, Expr* expr); - // Generate a temp ID with a unique name - ID* AddTempID(Type* type); + // Generate a temp ID with a unique name + ID* AddTempID(Type* type); - IDType GetIDType(const ID* id) const; - const char* RValue(const ID* id) const; - const char* LValue(const ID* id) const; - // const char *SetFunc(const ID *id) const; + IDType GetIDType(const ID* id) const; + const char* RValue(const ID* id) const; + const char* LValue(const ID* id) const; + // const char *SetFunc(const ID *id) const; - // Set evaluation method for the ID - void SetEvalMethod(const ID* id, Evaluatable* eval); + // Set evaluation method for the ID + void SetEvalMethod(const ID* id, Evaluatable* eval); - // Evaluate the ID according to the evaluation method. It - // assumes the ID has an evaluation emthod. It does nothing - // if the ID has already been evaluated. - void Evaluate(Output* out, const ID* id); + // Evaluate the ID according to the evaluation method. It + // assumes the ID has an evaluation emthod. It does nothing + // if the ID has already been evaluated. + void Evaluate(Output* out, const ID* id); - // Whether the ID has already been evaluated. - bool Evaluated(const ID* id) const; + // Whether the ID has already been evaluated. + bool Evaluated(const ID* id) const; - // Set the ID as evaluated (or not). - void SetEvaluated(const ID* id, bool v = true); + // Set the ID as evaluated (or not). + void SetEvaluated(const ID* id, bool v = true); - void SetField(const ID* id, Field* field); - Field* GetField(const ID* id) const; + void SetField(const ID* id, Field* field); + Field* GetField(const ID* id) const; - bool GetConstant(const ID* id, int* pc) const; + bool GetConstant(const ID* id, int* pc) const; - Expr* GetMacro(const ID* id) const; + Expr* GetMacro(const ID* id) const; - Type* GetDataType(const ID* id) const; + Type* GetDataType(const ID* id) const; - string DataTypeStr(const ID* id) const; + string DataTypeStr(const ID* id) const; protected: - IDRecord* lookup(const ID* id, bool recursive, bool raise_exception) const; + IDRecord* lookup(const ID* id, bool recursive, bool raise_exception) const; - void SetDataType(const ID* id, Type* type); - void SetConstant(const ID* id, int constant); - void SetMacro(const ID* id, Expr* macro); + void SetDataType(const ID* id, Type* type); + void SetConstant(const ID* id, int constant); + void SetMacro(const ID* id, Expr* macro); private: - Env* parent; - Object* context_object_; - typedef map id_map_t; - id_map_t id_map; - bool allow_undefined_id_; - bool in_branch_; - }; + Env* parent; + Object* context_object_; + typedef map id_map_t; + id_map_t id_map; + bool allow_undefined_id_; + bool in_branch_; +}; extern const ID* default_value_var; extern const ID* null_id; diff --git a/tools/binpac/src/pac_inputbuf.cc b/tools/binpac/src/pac_inputbuf.cc index caaefe6ffb..c425bae868 100644 --- a/tools/binpac/src/pac_inputbuf.cc +++ b/tools/binpac/src/pac_inputbuf.cc @@ -6,33 +6,28 @@ #include "pac_output.h" #include "pac_type.h" -InputBuffer::InputBuffer(Expr* expr) : DataDepElement(INPUT_BUFFER), expr_(expr) { } +InputBuffer::InputBuffer(Expr* expr) : DataDepElement(INPUT_BUFFER), expr_(expr) {} -bool InputBuffer::DoTraverse(DataDepVisitor* visitor) - { - if ( expr_ && ! expr_->Traverse(visitor) ) - return false; - return true; - } +bool InputBuffer::DoTraverse(DataDepVisitor* visitor) { + if ( expr_ && ! expr_->Traverse(visitor) ) + return false; + return true; +} -bool InputBuffer::RequiresAnalyzerContext() const - { - return expr_->RequiresAnalyzerContext(); - } +bool InputBuffer::RequiresAnalyzerContext() const { return expr_->RequiresAnalyzerContext(); } -DataPtr InputBuffer::GenDataBeginEnd(Output* out_cc, Env* env) - { - env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); - env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); +DataPtr InputBuffer::GenDataBeginEnd(Output* out_cc, Env* env) { + env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); + env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); - out_cc->println("%s %s, %s;", extern_type_const_byteptr->DataTypeStr().c_str(), - env->LValue(begin_of_data), env->LValue(end_of_data)); + out_cc->println("%s %s, %s;", extern_type_const_byteptr->DataTypeStr().c_str(), env->LValue(begin_of_data), + env->LValue(end_of_data)); - out_cc->println("get_pointers(%s, &%s, &%s);", expr_->EvalExpr(out_cc, env), - env->LValue(begin_of_data), env->LValue(end_of_data)); + out_cc->println("get_pointers(%s, &%s, &%s);", expr_->EvalExpr(out_cc, env), env->LValue(begin_of_data), + env->LValue(end_of_data)); - env->SetEvaluated(begin_of_data); - env->SetEvaluated(end_of_data); + env->SetEvaluated(begin_of_data); + env->SetEvaluated(end_of_data); - return DataPtr(env, begin_of_data, 0); - } + return DataPtr(env, begin_of_data, 0); +} diff --git a/tools/binpac/src/pac_inputbuf.h b/tools/binpac/src/pac_inputbuf.h index 46ca864ece..5d7fa5c9b1 100644 --- a/tools/binpac/src/pac_inputbuf.h +++ b/tools/binpac/src/pac_inputbuf.h @@ -6,19 +6,18 @@ class Expr; -class InputBuffer : public Object, public DataDepElement - { +class InputBuffer : public Object, public DataDepElement { public: - InputBuffer(Expr* expr); + InputBuffer(Expr* expr); - bool RequiresAnalyzerContext() const; - DataPtr GenDataBeginEnd(Output* out_cc, Env* env); + bool RequiresAnalyzerContext() const; + DataPtr GenDataBeginEnd(Output* out_cc, Env* env); protected: - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; private: - Expr* expr_; - }; + Expr* expr_; +}; #endif // pac_inputbuf_h diff --git a/tools/binpac/src/pac_let.cc b/tools/binpac/src/pac_let.cc index aac806c189..8aa3adc20b 100644 --- a/tools/binpac/src/pac_let.cc +++ b/tools/binpac/src/pac_let.cc @@ -5,143 +5,118 @@ #include "pac_output.h" #include "pac_type.h" -namespace - { +namespace { -void GenLetEval(const ID* id, Expr* expr, string prefix, Output* out, Env* env) { } +void GenLetEval(const ID* id, Expr* expr, string prefix, Output* out, Env* env) {} - } // private namespace +} // namespace LetField::LetField(ID* id, Type* type, Expr* expr) - : Field(LET_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), - expr_(expr) - { - ASSERT(expr_); - } + : Field(LET_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), expr_(expr) { + ASSERT(expr_); +} -LetField::~LetField() - { - delete expr_; - } +LetField::~LetField() { delete expr_; } -bool LetField::DoTraverse(DataDepVisitor* visitor) - { - return Field::DoTraverse(visitor) && expr()->Traverse(visitor); - } +bool LetField::DoTraverse(DataDepVisitor* visitor) { return Field::DoTraverse(visitor) && expr()->Traverse(visitor); } -bool LetField::RequiresAnalyzerContext() const - { - return Field::RequiresAnalyzerContext() || (expr() && expr()->RequiresAnalyzerContext()); - } +bool LetField::RequiresAnalyzerContext() const { + return Field::RequiresAnalyzerContext() || (expr() && expr()->RequiresAnalyzerContext()); +} -void LetField::Prepare(Env* env) - { - if ( ! type_ ) - { - ASSERT(expr_); - type_ = expr_->DataType(env); - if ( type_ ) - type_ = type_->Clone(); - else - type_ = extern_type_int->Clone(); +void LetField::Prepare(Env* env) { + if ( ! type_ ) { + ASSERT(expr_); + type_ = expr_->DataType(env); + if ( type_ ) + type_ = type_->Clone(); + else + type_ = extern_type_int->Clone(); - foreach (i, AttrList, attrs_) - ProcessAttr(*i); - } + foreach (i, AttrList, attrs_) + ProcessAttr(*i); + } - Field::Prepare(env); - env->SetEvalMethod(id_, this); - } + Field::Prepare(env); + env->SetEvalMethod(id_, this); +} -void LetField::GenInitCode(Output* out_cc, Env* env) - { - int v; - if ( expr_ && expr_->ConstFold(env, &v) ) - { - DEBUG_MSG("Folding const for `%s'\n", id_->Name()); - GenEval(out_cc, env); - } - else - type_->GenInitCode(out_cc, env); - } +void LetField::GenInitCode(Output* out_cc, Env* env) { + int v; + if ( expr_ && expr_->ConstFold(env, &v) ) { + DEBUG_MSG("Folding const for `%s'\n", id_->Name()); + GenEval(out_cc, env); + } + else + type_->GenInitCode(out_cc, env); +} -void LetField::GenParseCode(Output* out_cc, Env* env) - { - if ( env->Evaluated(id_) ) - return; +void LetField::GenParseCode(Output* out_cc, Env* env) { + if ( env->Evaluated(id_) ) + return; - if ( type_->attr_if_expr() ) - { - // A conditional field + if ( type_->attr_if_expr() ) { + // A conditional field - env->Evaluate(out_cc, type_->has_value_var()); + env->Evaluate(out_cc, type_->has_value_var()); - // force evaluation of IDs contained in this expr - expr()->ForceIDEval(out_cc, env); + // force evaluation of IDs contained in this expr + expr()->ForceIDEval(out_cc, env); - out_cc->println("if ( %s )", env->RValue(type_->has_value_var())); - out_cc->inc_indent(); - out_cc->println("{"); - } + out_cc->println("if ( %s )", env->RValue(type_->has_value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + } - out_cc->println("%s = %s;", env->LValue(id_), expr()->EvalExpr(out_cc, env)); - if ( ! env->Evaluated(id_) ) - env->SetEvaluated(id_); + out_cc->println("%s = %s;", env->LValue(id_), expr()->EvalExpr(out_cc, env)); + if ( ! env->Evaluated(id_) ) + env->SetEvaluated(id_); - if ( type_->attr_if_expr() ) - { - out_cc->println("}"); - out_cc->dec_indent(); - } - } + if ( type_->attr_if_expr() ) { + out_cc->println("}"); + out_cc->dec_indent(); + } +} -void LetField::GenEval(Output* out_cc, Env* env) - { - GenParseCode(out_cc, env); - } +void LetField::GenEval(Output* out_cc, Env* env) { GenParseCode(out_cc, env); } -LetDecl::LetDecl(ID* id, Type* type, Expr* expr) : Decl(id, LET), type_(type), expr_(expr) - { - if ( ! type_ ) - { - ASSERT(expr_); - type_ = expr_->DataType(global_env()); - if ( type_ ) - type_ = type_->Clone(); - else - type_ = extern_type_int->Clone(); - } +LetDecl::LetDecl(ID* id, Type* type, Expr* expr) : Decl(id, LET), type_(type), expr_(expr) { + if ( ! type_ ) { + ASSERT(expr_); + type_ = expr_->DataType(global_env()); + if ( type_ ) + type_ = type_->Clone(); + else + type_ = extern_type_int->Clone(); + } - Env* env = global_env(); - int c; - if ( expr_ && expr_->ConstFold(env, &c) ) - env->AddConstID(id_, c, type); - else - env->AddID(id_, GLOBAL_VAR, type_); - } + Env* env = global_env(); + int c; + if ( expr_ && expr_->ConstFold(env, &c) ) + env->AddConstID(id_, c, type); + else + env->AddID(id_, GLOBAL_VAR, type_); +} -LetDecl::~LetDecl() - { - delete type_; - delete expr_; - } +LetDecl::~LetDecl() { + delete type_; + delete expr_; +} -void LetDecl::Prepare() { } +void LetDecl::Prepare() {} -void LetDecl::GenForwardDeclaration(Output* out_h) { } +void LetDecl::GenForwardDeclaration(Output* out_h) {} -void LetDecl::GenCode(Output* out_h, Output* out_cc) - { - out_h->println("extern %s const %s;", type_->DataTypeStr().c_str(), global_env()->RValue(id_)); - GenEval(out_cc, global_env()); - } +void LetDecl::GenCode(Output* out_h, Output* out_cc) { + out_h->println("extern %s const %s;", type_->DataTypeStr().c_str(), global_env()->RValue(id_)); + GenEval(out_cc, global_env()); +} -void LetDecl::GenEval(Output* out_cc, Env* /* env */) - { - Env* env = global_env(); - string tmp = strfmt("%s const", type_->DataTypeStr().c_str()); - out_cc->println("%s %s = %s;", tmp.c_str(), env->LValue(id_), expr_->EvalExpr(out_cc, env)); +void LetDecl::GenEval(Output* out_cc, Env* /* env */) { + Env* env = global_env(); + string tmp = strfmt("%s const", type_->DataTypeStr().c_str()); + out_cc->println("%s %s = %s;", tmp.c_str(), env->LValue(id_), expr_->EvalExpr(out_cc, env)); - if ( ! env->Evaluated(id_) ) - env->SetEvaluated(id_); - } + if ( ! env->Evaluated(id_) ) + env->SetEvaluated(id_); +} diff --git a/tools/binpac/src/pac_let.h b/tools/binpac/src/pac_let.h index 1bf774dd1e..ac14bebef0 100644 --- a/tools/binpac/src/pac_let.h +++ b/tools/binpac/src/pac_let.h @@ -4,45 +4,43 @@ #include "pac_decl.h" #include "pac_field.h" -class LetField : public Field, Evaluatable - { +class LetField : public Field, Evaluatable { public: - LetField(ID* arg_id, Type* type, Expr* arg_expr); - ~LetField() override; + LetField(ID* arg_id, Type* type, Expr* arg_expr); + ~LetField() override; - Expr* expr() const { return expr_; } + Expr* expr() const { return expr_; } - void Prepare(Env* env) override; + void Prepare(Env* env) override; - void GenInitCode(Output* out, Env* env) override; - void GenParseCode(Output* out, Env* env); - void GenEval(Output* out, Env* env) override; + void GenInitCode(Output* out, Env* env) override; + void GenParseCode(Output* out, Env* env); + void GenEval(Output* out, Env* env) override; - bool RequiresAnalyzerContext() const override; + bool RequiresAnalyzerContext() const override; protected: - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; protected: - Expr* expr_; - }; + Expr* expr_; +}; -class LetDecl : public Decl, Evaluatable - { +class LetDecl : public Decl, Evaluatable { public: - LetDecl(ID* id, Type* type, Expr* expr); - ~LetDecl() override; + LetDecl(ID* id, Type* type, Expr* expr); + ~LetDecl() override; - Expr* expr() const { return expr_; } + Expr* expr() const { return expr_; } - void Prepare() override; - void GenForwardDeclaration(Output* out_h) override; - void GenCode(Output* out_h, Output* out_cc) override; - void GenEval(Output* out, Env* env) override; + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; + void GenEval(Output* out, Env* env) override; private: - Type* type_; - Expr* expr_; - }; + Type* type_; + Expr* expr_; +}; #endif // pac_let_h diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index 17580b3608..152702425d 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -25,185 +25,168 @@ vector FLAGS_include_directories; Output* header_output = nullptr; Output* source_output = nullptr; -void add_to_include_directories(string dirs) - { - unsigned int dir_begin = 0, dir_end; - while ( dir_begin < dirs.length() ) - { - for ( dir_end = dir_begin; dir_end < dirs.length(); ++dir_end ) - if ( dirs[dir_end] == ':' ) - break; +void add_to_include_directories(string dirs) { + unsigned int dir_begin = 0, dir_end; + while ( dir_begin < dirs.length() ) { + for ( dir_end = dir_begin; dir_end < dirs.length(); ++dir_end ) + if ( dirs[dir_end] == ':' ) + break; - string dir = dirs.substr(dir_begin, dir_end - dir_begin); + string dir = dirs.substr(dir_begin, dir_end - dir_begin); - // Add a trailing '/' if necessary - if ( dir.length() > 0 && *(dir.end() - 1) != '/' ) - dir += '/'; - - FLAGS_include_directories.push_back(dir); - dir_begin = dir_end + 1; - } - } + // Add a trailing '/' if necessary + if ( dir.length() > 0 && *(dir.end() - 1) != '/' ) + dir += '/'; -void pac_init() - { - init_builtin_identifiers(); - Type::init(); - } + FLAGS_include_directories.push_back(dir); + dir_begin = dir_end + 1; + } +} -void insert_comments(Output* out, const char* source_filename) - { - out->println("// This file is automatically generated from %s.\n", source_filename); - } +void pac_init() { + init_builtin_identifiers(); + Type::init(); +} -void insert_basictype_defs(Output* out) - { - out->println("#ifndef pac_type_defs"); - out->println("#define pac_type_defs"); - out->println(""); - out->println("typedef char int8;"); - out->println("typedef short int16;"); - out->println("typedef long int32;"); - out->println("typedef long long int64;"); - - out->println("typedef unsigned char uint8;"); - out->println("typedef unsigned short uint16;"); - out->println("typedef unsigned long uint32;"); - out->println("typedef unsigned long long uint64;"); - - out->println(""); - out->println("#endif /* pac_type_defs */"); - out->println(""); - } +void insert_comments(Output* out, const char* source_filename) { + out->println("// This file is automatically generated from %s.\n", source_filename); +} -void insert_byteorder_macros(Output* out) - { - out->println("#define FixByteOrder16(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap16(x))"); - out->println("#define FixByteOrder32(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap32(x))"); - out->println("#define FixByteOrder64(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap64(x))"); - out->println(""); - } +void insert_basictype_defs(Output* out) { + out->println("#ifndef pac_type_defs"); + out->println("#define pac_type_defs"); + out->println(""); + out->println("typedef char int8;"); + out->println("typedef short int16;"); + out->println("typedef long int32;"); + out->println("typedef long long int64;"); -const char* to_id(const char* s) - { - static char t[1024]; - int i; - for ( i = 0; s[i] && i < (int)sizeof(t) - 1; ++i ) - t[i] = isalnum(s[i]) ? s[i] : '_'; - if ( isdigit(t[0]) ) - t[0] = '_'; - t[i] = '\0'; - return t; - } + out->println("typedef unsigned char uint8;"); + out->println("typedef unsigned short uint16;"); + out->println("typedef unsigned long uint32;"); + out->println("typedef unsigned long long uint64;"); -int compile(const char* filename) - { - FILE* fp_input = fopen(filename, "r"); - if ( ! fp_input ) - { - string tmp = strfmt("Error in opening %s", filename); - perror(tmp.c_str()); - return -1; - } - input_filename = filename; + out->println(""); + out->println("#endif /* pac_type_defs */"); + out->println(""); +} - string basename; +void insert_byteorder_macros(Output* out) { + out->println("#define FixByteOrder16(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap16(x))"); + out->println("#define FixByteOrder32(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap32(x))"); + out->println("#define FixByteOrder64(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap64(x))"); + out->println(""); +} - if ( ! FLAGS_output_directory.empty() ) - { - // Strip leading directories of filename - const char* last_slash = strrchr(filename, '/'); - if ( last_slash ) - basename = last_slash + 1; - else - basename = filename; - basename = FLAGS_output_directory + "/" + basename; - } - else - basename = filename; +const char* to_id(const char* s) { + static char t[1024]; + int i; + for ( i = 0; s[i] && i < (int)sizeof(t) - 1; ++i ) + t[i] = isalnum(s[i]) ? s[i] : '_'; + if ( isdigit(t[0]) ) + t[0] = '_'; + t[i] = '\0'; + return t; +} - // If the file name ends with ".pac" - if ( basename.length() > 4 && basename.substr(basename.length() - 4) == ".pac" ) - { - basename = basename.substr(0, basename.length() - 4); - } +int compile(const char* filename) { + FILE* fp_input = fopen(filename, "r"); + if ( ! fp_input ) { + string tmp = strfmt("Error in opening %s", filename); + perror(tmp.c_str()); + return -1; + } + input_filename = filename; - basename += "_pac"; + string basename; - DEBUG_MSG("Output file: %s.{h,cc}\n", basename.c_str()); + if ( ! FLAGS_output_directory.empty() ) { + // Strip leading directories of filename + const char* last_slash = strrchr(filename, '/'); + if ( last_slash ) + basename = last_slash + 1; + else + basename = filename; + basename = FLAGS_output_directory + "/" + basename; + } + else + basename = filename; - int ret = 0; + // If the file name ends with ".pac" + if ( basename.length() > 4 && basename.substr(basename.length() - 4) == ".pac" ) { + basename = basename.substr(0, basename.length() - 4); + } - try - { - switch_to_file(fp_input); - if ( yyparse() ) - return 1; + basename += "_pac"; - Output out_h(strfmt("%s.h", basename.c_str())); - Output out_cc(strfmt("%s.cc", basename.c_str())); + DEBUG_MSG("Output file: %s.{h,cc}\n", basename.c_str()); - header_output = &out_h; - source_output = &out_cc; + int ret = 0; - insert_comments(&out_h, filename); - insert_comments(&out_cc, filename); + try { + switch_to_file(fp_input); + if ( yyparse() ) + return 1; - const char* filename_id = to_id(filename); + Output out_h(strfmt("%s.h", basename.c_str())); + Output out_cc(strfmt("%s.cc", basename.c_str())); - out_h.println("#ifndef %s_h", filename_id); - out_h.println("#define %s_h", filename_id); - out_h.println(""); - out_h.println("#include "); - out_h.println(""); - out_h.println("#include \"binpac.h\""); - out_h.println(""); + header_output = &out_h; + source_output = &out_cc; - out_cc.println(""); - out_cc.println("#ifdef __clang__"); - out_cc.println("#pragma clang diagnostic ignored \"-Wparentheses-equality\""); - out_cc.println("#endif"); - out_cc.println(""); + insert_comments(&out_h, filename); + insert_comments(&out_cc, filename); - out_cc.println("#include \"%s.h\"\n", basename.c_str()); + const char* filename_id = to_id(filename); - Decl::ProcessDecls(&out_h, &out_cc); + out_h.println("#ifndef %s_h", filename_id); + out_h.println("#define %s_h", filename_id); + out_h.println(""); + out_h.println("#include "); + out_h.println(""); + out_h.println("#include \"binpac.h\""); + out_h.println(""); - out_h.println("#endif /* %s_h */", filename_id); - } - catch ( OutputException& e ) - { - fprintf(stderr, "Error in compiling %s: %s\n", filename, e.errmsg()); - ret = 1; - } - catch ( Exception& e ) - { - fprintf(stderr, "%s\n", e.msg()); - exit(1); - } + out_cc.println(""); + out_cc.println("#ifdef __clang__"); + out_cc.println("#pragma clang diagnostic ignored \"-Wparentheses-equality\""); + out_cc.println("#endif"); + out_cc.println(""); - header_output = nullptr; - source_output = nullptr; - input_filename = ""; - fclose(fp_input); + out_cc.println("#include \"%s.h\"\n", basename.c_str()); - return ret; - } + Decl::ProcessDecls(&out_h, &out_cc); -void usage() - { + out_h.println("#endif /* %s_h */", filename_id); + } catch ( OutputException& e ) { + fprintf(stderr, "Error in compiling %s: %s\n", filename, e.errmsg()); + ret = 1; + } catch ( Exception& e ) { + fprintf(stderr, "%s\n", e.msg()); + exit(1); + } + + header_output = nullptr; + source_output = nullptr; + input_filename = ""; + fclose(fp_input); + + return ret; +} + +void usage() { #ifdef BINPAC_VERSION - fprintf(stderr, "binpac version %s\n", BINPAC_VERSION); + fprintf(stderr, "binpac version %s\n", BINPAC_VERSION); #endif - fprintf(stderr, "usage: binpac [options] \n"); - fprintf(stderr, " | pac-language input files\n"); - fprintf(stderr, " -d | use given directory for compiler output\n"); - fprintf(stderr, " -D | enable debugging output\n"); - fprintf(stderr, " -q | stay quiet\n"); - fprintf(stderr, " -h | show command line help\n"); - fprintf(stderr, " -I | include in input file search path\n"); - exit(1); - } + fprintf(stderr, "usage: binpac [options] \n"); + fprintf(stderr, " | pac-language input files\n"); + fprintf(stderr, " -d | use given directory for compiler output\n"); + fprintf(stderr, " -D | enable debugging output\n"); + fprintf(stderr, " -q | stay quiet\n"); + fprintf(stderr, " -h | show command line help\n"); + fprintf(stderr, " -I | include in input file search path\n"); + exit(1); +} // GCC uses __SANITIZE_ADDRESS__, Clang uses __has_feature #if defined(__SANITIZE_ADDRESS__) @@ -224,68 +207,56 @@ void usage() #define BINPAC_LSAN_DISABLE() #endif -int main(int argc, char* argv[]) - { - // We generally do not care at all if binpac is leaking and other - // projects that use it, like Zeek, only have their build tripped up - // by the default behavior of LSAN to treat leaks as errors. - BINPAC_LSAN_DISABLE(); +int main(int argc, char* argv[]) { + // We generally do not care at all if binpac is leaking and other + // projects that use it, like Zeek, only have their build tripped up + // by the default behavior of LSAN to treat leaks as errors. + BINPAC_LSAN_DISABLE(); #ifdef HAVE_MALLOC_OPTIONS - extern char* malloc_options; + extern char* malloc_options; #endif - int o; - while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 ) - { - switch ( o ) - { - case 'D': - yydebug = 1; - FLAGS_pac_debug = true; + int o; + while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 ) { + switch ( o ) { + case 'D': yydebug = 1; FLAGS_pac_debug = true; #ifdef HAVE_MALLOC_OPTIONS - malloc_options = "A"; + malloc_options = "A"; #endif - break; - - case 'q': - FLAGS_quiet = true; - break; + break; - case 'I': - // Add to FLAGS_include_directories - add_to_include_directories(optarg); - break; + case 'q': FLAGS_quiet = true; break; - case 'd': - FLAGS_output_directory = optarg; - break; + case 'I': + // Add to FLAGS_include_directories + add_to_include_directories(optarg); + break; - case 'h': - usage(); - break; - } - } + case 'd': FLAGS_output_directory = optarg; break; - // Strip the trailing '/'s - while ( ! FLAGS_output_directory.empty() && *(FLAGS_output_directory.end() - 1) == '/' ) - { - FLAGS_output_directory.erase(FLAGS_output_directory.end() - 1); - } + case 'h': usage(); break; + } + } - // Add the current directory to FLAGS_include_directories - add_to_include_directories("."); + // Strip the trailing '/'s + while ( ! FLAGS_output_directory.empty() && *(FLAGS_output_directory.end() - 1) == '/' ) { + FLAGS_output_directory.erase(FLAGS_output_directory.end() - 1); + } - pac_init(); + // Add the current directory to FLAGS_include_directories + add_to_include_directories("."); - argc -= optind; - argv += optind; - if ( argc == 0 ) - compile("-"); + pac_init(); - int ret = 0; - for ( int i = 0; i < argc; ++i ) - if ( compile(argv[i]) ) - ret = 1; + argc -= optind; + argv += optind; + if ( argc == 0 ) + compile("-"); - return ret; - } + int ret = 0; + for ( int i = 0; i < argc; ++i ) + if ( compile(argv[i]) ) + ret = 1; + + return ret; +} diff --git a/tools/binpac/src/pac_number.h b/tools/binpac/src/pac_number.h index 2392a4e6be..5f8bfa6197 100644 --- a/tools/binpac/src/pac_number.h +++ b/tools/binpac/src/pac_number.h @@ -3,17 +3,16 @@ #include "pac_common.h" -class Number : public Object - { +class Number : public Object { public: - Number(int arg_n) : s(strfmt("%d", arg_n)), n(arg_n) { } - Number(const char* arg_s, int arg_n) : s(arg_s), n(arg_n) { } - const char* Str() const { return s.c_str(); } - int Num() const { return n; } + Number(int arg_n) : s(strfmt("%d", arg_n)), n(arg_n) {} + Number(const char* arg_s, int arg_n) : s(arg_s), n(arg_n) {} + const char* Str() const { return s.c_str(); } + int Num() const { return n; } protected: - const string s; - const int n; - }; + const string s; + const int n; +}; #endif // pac_number_h diff --git a/tools/binpac/src/pac_output.cc b/tools/binpac/src/pac_output.cc index 87d4bd93b0..13b256856b 100644 --- a/tools/binpac/src/pac_output.cc +++ b/tools/binpac/src/pac_output.cc @@ -7,77 +7,65 @@ #include "pac_utils.h" -OutputException::OutputException(const char* arg_msg) - { - msg = arg_msg; - } +OutputException::OutputException(const char* arg_msg) { msg = arg_msg; } -OutputException::~OutputException() { } +OutputException::~OutputException() {} -Output::Output(string filename) - { - fp = fopen(filename.c_str(), "w"); - if ( ! fp ) - throw OutputException(strerror(errno)); - indent_ = 0; - } +Output::Output(string filename) { + fp = fopen(filename.c_str(), "w"); + if ( ! fp ) + throw OutputException(strerror(errno)); + indent_ = 0; +} -Output::~Output() - { - if ( fp ) - fclose(fp); - } +Output::~Output() { + if ( fp ) + fclose(fp); +} -int Output::print(const char* fmt, va_list ap) - { - int r = vfprintf(fp, fmt, ap); - if ( r == -1 ) - throw OutputException(strerror(errno)); - return r; - } +int Output::print(const char* fmt, va_list ap) { + int r = vfprintf(fp, fmt, ap); + if ( r == -1 ) + throw OutputException(strerror(errno)); + return r; +} -int Output::print(const char* fmt, ...) - { - va_list ap; - va_start(ap, fmt); - int r = -1; +int Output::print(const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + int r = -1; - try - { - r = print(fmt, ap); - } + try { + r = print(fmt, ap); + } - catch ( ... ) - { - va_end(ap); - throw; - } + catch ( ... ) { + va_end(ap); + throw; + } - va_end(ap); - return r; - } + va_end(ap); + return r; +} -int Output::println(const char* fmt, ...) - { - for ( int i = 0; i < indent(); ++i ) - fprintf(fp, "\t"); +int Output::println(const char* fmt, ...) { + for ( int i = 0; i < indent(); ++i ) + fprintf(fp, "\t"); - va_list ap; - va_start(ap, fmt); - int r = -1; + va_list ap; + va_start(ap, fmt); + int r = -1; - try - { - r = print(fmt, ap); - } + try { + r = print(fmt, ap); + } - catch ( ... ) - { - va_end(ap); - throw; - } + catch ( ... ) { + va_end(ap); + throw; + } - va_end(ap); - fprintf(fp, "\n"); - return r; - } + va_end(ap); + fprintf(fp, "\n"); + return r; +} diff --git a/tools/binpac/src/pac_output.h b/tools/binpac/src/pac_output.h index 607598759b..4c612b0cce 100644 --- a/tools/binpac/src/pac_output.h +++ b/tools/binpac/src/pac_output.h @@ -7,36 +7,34 @@ using namespace std; -class OutputException - { +class OutputException { public: - OutputException(const char* arg_msg); - ~OutputException(); - const char* errmsg() const { return msg.c_str(); } + OutputException(const char* arg_msg); + ~OutputException(); + const char* errmsg() const { return msg.c_str(); } protected: - string msg; - }; + string msg; +}; -class Output - { +class Output { public: - Output(string filename); - ~Output(); + Output(string filename); + ~Output(); - int println(const char* fmt, ...); - int print(const char* fmt, ...); + int println(const char* fmt, ...); + int print(const char* fmt, ...); - int indent() const { return indent_; } + int indent() const { return indent_; } - void inc_indent() { ++indent_; } - void dec_indent() { --indent_; } + void inc_indent() { ++indent_; } + void dec_indent() { --indent_; } protected: - int print(const char* fmt, va_list ap); + int print(const char* fmt, va_list ap); - FILE* fp; - int indent_; - }; + FILE* fp; + int indent_; +}; #endif /* pac_output_h */ diff --git a/tools/binpac/src/pac_param.cc b/tools/binpac/src/pac_param.cc index 763cc64fec..91f1984873 100644 --- a/tools/binpac/src/pac_param.cc +++ b/tools/binpac/src/pac_param.cc @@ -8,55 +8,46 @@ #include "pac_type.h" #include "pac_utils.h" -Param::Param(ID* id, Type* type) : id_(id), type_(type) - { - if ( ! type_ ) - type_ = extern_type_int->Clone(); +Param::Param(ID* id, Type* type) : id_(id), type_(type) { + if ( ! type_ ) + type_ = extern_type_int->Clone(); - decl_str_ = strfmt("%s %s", type_->DataTypeConstRefStr().c_str(), id_->Name()); + decl_str_ = strfmt("%s %s", type_->DataTypeConstRefStr().c_str(), id_->Name()); - param_field_ = new ParamField(this); - } + param_field_ = new ParamField(this); +} -Param::~Param() { } +Param::~Param() {} -const string& Param::decl_str() const - { - ASSERT(! decl_str_.empty()); - return decl_str_; - } +const string& Param::decl_str() const { + ASSERT(! decl_str_.empty()); + return decl_str_; +} -string ParamDecls(ParamList* params) - { - string param_decls; +string ParamDecls(ParamList* params) { + string param_decls; - int first = 1; - foreach (i, ParamList, params) - { - Param* p = *i; - const char* decl_str = p->decl_str().c_str(); - if ( first ) - first = 0; - else - param_decls += ", "; - param_decls += decl_str; - } - return param_decls; - } + int first = 1; + foreach (i, ParamList, params) { + Param* p = *i; + const char* decl_str = p->decl_str().c_str(); + if ( first ) + first = 0; + else + param_decls += ", "; + param_decls += decl_str; + } + return param_decls; +} ParamField::ParamField(const Param* param) - : Field(PARAM_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, param->id(), - param->type()) - { - } + : Field(PARAM_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, param->id(), param->type()) {} -void ParamField::GenInitCode(Output* out_cc, Env* env) - { - out_cc->println("%s = %s;", env->LValue(id()), id()->Name()); - env->SetEvaluated(id()); - } +void ParamField::GenInitCode(Output* out_cc, Env* env) { + out_cc->println("%s = %s;", env->LValue(id()), id()->Name()); + env->SetEvaluated(id()); +} -void ParamField::GenCleanUpCode(Output* out_cc, Env* env) - { - // Do nothing - } +void ParamField::GenCleanUpCode(Output* out_cc, Env* env) { + // Do nothing +} diff --git a/tools/binpac/src/pac_param.h b/tools/binpac/src/pac_param.h index 90afeaba80..5e1e101d5b 100644 --- a/tools/binpac/src/pac_param.h +++ b/tools/binpac/src/pac_param.h @@ -4,32 +4,30 @@ #include "pac_common.h" #include "pac_field.h" -class Param : public Object - { +class Param : public Object { public: - Param(ID* id, Type* type); - ~Param(); + Param(ID* id, Type* type); + ~Param(); - ID* id() const { return id_; } - Type* type() const { return type_; } - const string& decl_str() const; - Field* param_field() const { return param_field_; } + ID* id() const { return id_; } + Type* type() const { return type_; } + const string& decl_str() const; + Field* param_field() const { return param_field_; } private: - ID* id_; - Type* type_; - string decl_str_; - Field* param_field_; - }; + ID* id_; + Type* type_; + string decl_str_; + Field* param_field_; +}; -class ParamField : public Field - { +class ParamField : public Field { public: - ParamField(const Param* param); + ParamField(const Param* param); - void GenInitCode(Output* out, Env* env) override; - void GenCleanUpCode(Output* out, Env* env) override; - }; + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; +}; // Returns the string with a list of param declarations separated by ','. string ParamDecls(ParamList* params); diff --git a/tools/binpac/src/pac_paramtype.cc b/tools/binpac/src/pac_paramtype.cc index b9d2175b65..25370a40f1 100644 --- a/tools/binpac/src/pac_paramtype.cc +++ b/tools/binpac/src/pac_paramtype.cc @@ -8,266 +8,214 @@ #include "pac_typedecl.h" ParameterizedType::ParameterizedType(ID* type_id, ExprList* args) - : Type(PARAMETERIZED), type_id_(type_id), args_(args) - { - checking_requires_analyzer_context_ = false; - } + : Type(PARAMETERIZED), type_id_(type_id), args_(args) { + checking_requires_analyzer_context_ = false; +} -ParameterizedType::~ParameterizedType() { } +ParameterizedType::~ParameterizedType() {} -string ParameterizedType::EvalMember(const ID* member_id) const - { - Type* ty = ReferredDataType(true); - return strfmt("->%s", ty->env()->RValue(member_id)); - } +string ParameterizedType::EvalMember(const ID* member_id) const { + Type* ty = ReferredDataType(true); + return strfmt("->%s", ty->env()->RValue(member_id)); +} -string ParameterizedType::class_name() const - { - return type_id_->Name(); - } +string ParameterizedType::class_name() const { return type_id_->Name(); } -Type* ParameterizedType::DoClone() const - { - return new ParameterizedType(type_id_->clone(), args_); - } +Type* ParameterizedType::DoClone() const { return new ParameterizedType(type_id_->clone(), args_); } -void ParameterizedType::AddParamArg(Expr* arg) - { - args_->push_back(arg); - } +void ParameterizedType::AddParamArg(Expr* arg) { args_->push_back(arg); } -bool ParameterizedType::DefineValueVar() const - { - return true; - } +bool ParameterizedType::DefineValueVar() const { return true; } -string ParameterizedType::DataTypeStr() const - { - return strfmt("%s *", type_id_->Name()); - } +string ParameterizedType::DataTypeStr() const { return strfmt("%s *", type_id_->Name()); } -Type* ParameterizedType::MemberDataType(const ID* member_id) const - { - Type* ref_type = TypeDecl::LookUpType(type_id_); - if ( ! ref_type ) - return nullptr; - return ref_type->MemberDataType(member_id); - } +Type* ParameterizedType::MemberDataType(const ID* member_id) const { + Type* ref_type = TypeDecl::LookUpType(type_id_); + if ( ! ref_type ) + return nullptr; + return ref_type->MemberDataType(member_id); +} -Type* ParameterizedType::ReferredDataType(bool throw_exception) const - { - Type* type = TypeDecl::LookUpType(type_id_); - if ( ! type ) - { - DEBUG_MSG("WARNING: cannot find referenced type for %s\n", type_id_->Name()); - if ( throw_exception ) - throw ExceptionIDNotFound(type_id_); - } - return type; - } +Type* ParameterizedType::ReferredDataType(bool throw_exception) const { + Type* type = TypeDecl::LookUpType(type_id_); + if ( ! type ) { + DEBUG_MSG("WARNING: cannot find referenced type for %s\n", type_id_->Name()); + if ( throw_exception ) + throw ExceptionIDNotFound(type_id_); + } + return type; +} -int ParameterizedType::StaticSize(Env* env) const - { - return ReferredDataType(true)->StaticSize(env); - } +int ParameterizedType::StaticSize(Env* env) const { return ReferredDataType(true)->StaticSize(env); } -void ParameterizedType::DoMarkIncrementalInput() - { - Type* ty = ReferredDataType(true); +void ParameterizedType::DoMarkIncrementalInput() { + Type* ty = ReferredDataType(true); - ty->MarkIncrementalInput(); + ty->MarkIncrementalInput(); - buffer_input_ = ty->buffer_input(); - incremental_parsing_ = ty->incremental_parsing(); - } + buffer_input_ = ty->buffer_input(); + incremental_parsing_ = ty->incremental_parsing(); +} -Type::BufferMode ParameterizedType::buffer_mode() const - { - // Note that the precedence is on attributes (&oneline or &length) - // specified on the parameterized type directly than on the type - // declaration. - // - // If both &oneline and &length are specified at the same place, - // use &length. - // - BufferMode mode = Type::buffer_mode(); - Type* ty = ReferredDataType(true); +Type::BufferMode ParameterizedType::buffer_mode() const { + // Note that the precedence is on attributes (&oneline or &length) + // specified on the parameterized type directly than on the type + // declaration. + // + // If both &oneline and &length are specified at the same place, + // use &length. + // + BufferMode mode = Type::buffer_mode(); + Type* ty = ReferredDataType(true); - if ( mode != NOT_BUFFERABLE ) - return mode; - else if ( ty->BufferableByLength() ) - return BUFFER_BY_LENGTH; - else if ( ty->BufferableByLine() ) - return BUFFER_BY_LINE; + if ( mode != NOT_BUFFERABLE ) + return mode; + else if ( ty->BufferableByLength() ) + return BUFFER_BY_LENGTH; + else if ( ty->BufferableByLine() ) + return BUFFER_BY_LINE; - return NOT_BUFFERABLE; - } + return NOT_BUFFERABLE; +} -bool ParameterizedType::ByteOrderSensitive() const - { - return ReferredDataType(true)->RequiresByteOrder(); - } +bool ParameterizedType::ByteOrderSensitive() const { return ReferredDataType(true)->RequiresByteOrder(); } -bool ParameterizedType::DoTraverse(DataDepVisitor* visitor) - { - if ( ! Type::DoTraverse(visitor) ) - return false; +bool ParameterizedType::DoTraverse(DataDepVisitor* visitor) { + if ( ! Type::DoTraverse(visitor) ) + return false; - foreach (i, ExprList, args_) - if ( ! (*i)->Traverse(visitor) ) - return false; + foreach (i, ExprList, args_) + if ( ! (*i)->Traverse(visitor) ) + return false; - Type* ty = ReferredDataType(false); - if ( ty && ! ty->Traverse(visitor) ) - return false; + Type* ty = ReferredDataType(false); + if ( ty && ! ty->Traverse(visitor) ) + return false; - return true; - } + return true; +} -bool ParameterizedType::RequiresAnalyzerContext() - { - if ( checking_requires_analyzer_context_ ) - return false; - checking_requires_analyzer_context_ = true; +bool ParameterizedType::RequiresAnalyzerContext() { + if ( checking_requires_analyzer_context_ ) + return false; + checking_requires_analyzer_context_ = true; - bool ret = false; - // If any argument expression refers to analyzer context - foreach (i, ExprList, args_) - if ( (*i)->RequiresAnalyzerContext() ) - { - ret = true; - break; - } - ret = ret || Type::RequiresAnalyzerContext(); + bool ret = false; + // If any argument expression refers to analyzer context + foreach (i, ExprList, args_) + if ( (*i)->RequiresAnalyzerContext() ) { + ret = true; + break; + } + ret = ret || Type::RequiresAnalyzerContext(); - if ( ! ret ) - { - Type* ty = ReferredDataType(false); - if ( ty ) - ret = ty->RequiresAnalyzerContext(); - } + if ( ! ret ) { + Type* ty = ReferredDataType(false); + if ( ty ) + ret = ty->RequiresAnalyzerContext(); + } - checking_requires_analyzer_context_ = false; - return ret; - } + checking_requires_analyzer_context_ = false; + return ret; +} -void ParameterizedType::GenInitCode(Output* out_cc, Env* env) - { - ASSERT(persistent()); - out_cc->println("%s = nullptr;", env->LValue(value_var())); - Type::GenInitCode(out_cc, env); - } +void ParameterizedType::GenInitCode(Output* out_cc, Env* env) { + ASSERT(persistent()); + out_cc->println("%s = nullptr;", env->LValue(value_var())); + Type::GenInitCode(out_cc, env); +} -void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env) - { - Type* ty = ReferredDataType(false); - if ( ty && ty->attr_refcount() ) - out_cc->println("Unref(%s);", lvalue()); - else - out_cc->println("delete %s;", lvalue()); - out_cc->println("%s = nullptr;", lvalue()); - Type::GenCleanUpCode(out_cc, env); - } +void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env) { + Type* ty = ReferredDataType(false); + if ( ty && ty->attr_refcount() ) + out_cc->println("Unref(%s);", lvalue()); + else + out_cc->println("delete %s;", lvalue()); + out_cc->println("%s = nullptr;", lvalue()); + Type::GenCleanUpCode(out_cc, env); +} -string ParameterizedType::EvalParameters(Output* out_cc, Env* env) const - { - string arg_str; +string ParameterizedType::EvalParameters(Output* out_cc, Env* env) const { + string arg_str; - int first = 1; - foreach (i, ExprList, args_) - { - Expr* e = *i; - if ( first ) - first = 0; - else - arg_str += ", "; - arg_str += e->EvalExpr(out_cc, env); - } + int first = 1; + foreach (i, ExprList, args_) { + Expr* e = *i; + if ( first ) + first = 0; + else + arg_str += ", "; + arg_str += e->EvalExpr(out_cc, env); + } - return arg_str; - } + return arg_str; +} -void ParameterizedType::GenNewInstance(Output* out_cc, Env* env) - { - out_cc->println("%s = new %s(%s);", lvalue(), type_id_->Name(), - EvalParameters(out_cc, env).c_str()); - } +void ParameterizedType::GenNewInstance(Output* out_cc, Env* env) { + out_cc->println("%s = new %s(%s);", lvalue(), type_id_->Name(), EvalParameters(out_cc, env).c_str()); +} -void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) - { - DEBUG_MSG("DoGenParseCode for %s\n", type_id_->Name()); +void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { + DEBUG_MSG("DoGenParseCode for %s\n", type_id_->Name()); - Type* ref_type = ReferredDataType(true); + Type* ref_type = ReferredDataType(true); - const char* parse_func; - string parse_params; + const char* parse_func; + string parse_params; - if ( buffer_mode() == BUFFER_NOTHING ) - { - ASSERT(! ref_type->incremental_input()); - parse_func = kParseFuncWithoutBuffer; - parse_params = "nullptr, nullptr"; - } - else if ( ref_type->incremental_input() ) - { - parse_func = kParseFuncWithBuffer; - parse_params = env->RValue(flow_buffer_id); - } - else - { - parse_func = kParseFuncWithoutBuffer; - parse_params = strfmt("%s, %s", data.ptr_expr(), env->RValue(end_of_data)); - } + if ( buffer_mode() == BUFFER_NOTHING ) { + ASSERT(! ref_type->incremental_input()); + parse_func = kParseFuncWithoutBuffer; + parse_params = "nullptr, nullptr"; + } + else if ( ref_type->incremental_input() ) { + parse_func = kParseFuncWithBuffer; + parse_params = env->RValue(flow_buffer_id); + } + else { + parse_func = kParseFuncWithoutBuffer; + parse_params = strfmt("%s, %s", data.ptr_expr(), env->RValue(end_of_data)); + } - if ( RequiresAnalyzerContext::compute(ref_type) ) - { - parse_params += strfmt(", %s", env->RValue(analyzer_context_id)); - } + if ( RequiresAnalyzerContext::compute(ref_type) ) { + parse_params += strfmt(", %s", env->RValue(analyzer_context_id)); + } - if ( ref_type->RequiresByteOrder() ) - { - env->Evaluate(out_cc, byteorder_id); - parse_params += strfmt(", %s", env->RValue(byteorder_id)); - } + if ( ref_type->RequiresByteOrder() ) { + env->Evaluate(out_cc, byteorder_id); + parse_params += strfmt(", %s", env->RValue(byteorder_id)); + } - string call_parse_func = strfmt("%s->%s(%s)", - lvalue(), // parse() needs an LValue - parse_func, parse_params.c_str()); + string call_parse_func = strfmt("%s->%s(%s)", + lvalue(), // parse() needs an LValue + parse_func, parse_params.c_str()); - if ( incremental_input() ) - { - if ( buffer_mode() == BUFFER_NOTHING ) - { - out_cc->println("%s;", call_parse_func.c_str()); - out_cc->println("%s = true;", env->LValue(parsing_complete_var())); - } - else - { - ASSERT(parsing_complete_var()); - out_cc->println("%s = %s;", env->LValue(parsing_complete_var()), - call_parse_func.c_str()); + if ( incremental_input() ) { + if ( buffer_mode() == BUFFER_NOTHING ) { + out_cc->println("%s;", call_parse_func.c_str()); + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); + } + else { + ASSERT(parsing_complete_var()); + out_cc->println("%s = %s;", env->LValue(parsing_complete_var()), call_parse_func.c_str()); - // parsing_complete_var might have been already - // evaluated when set to false - if ( ! env->Evaluated(parsing_complete_var()) ) - env->SetEvaluated(parsing_complete_var()); - } - } - else - { - if ( AddSizeVar(out_cc, env) ) - { - out_cc->println("%s = %s;", env->LValue(size_var()), call_parse_func.c_str()); - env->SetEvaluated(size_var()); - } - else - { - out_cc->println("%s;", call_parse_func.c_str()); - } - } - } + // parsing_complete_var might have been already + // evaluated when set to false + if ( ! env->Evaluated(parsing_complete_var()) ) + env->SetEvaluated(parsing_complete_var()); + } + } + else { + if ( AddSizeVar(out_cc, env) ) { + out_cc->println("%s = %s;", env->LValue(size_var()), call_parse_func.c_str()); + env->SetEvaluated(size_var()); + } + else { + out_cc->println("%s;", call_parse_func.c_str()); + } + } +} -void ParameterizedType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) - { - GenParseCode(out_cc, env, data, 0); - } +void ParameterizedType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { + GenParseCode(out_cc, env, data, 0); +} diff --git a/tools/binpac/src/pac_paramtype.h b/tools/binpac/src/pac_paramtype.h index 0eda097563..72e427c580 100644 --- a/tools/binpac/src/pac_paramtype.h +++ b/tools/binpac/src/pac_paramtype.h @@ -4,58 +4,57 @@ #include "pac_type.h" // An instantiated type: ID + expression list -class ParameterizedType : public Type - { +class ParameterizedType : public Type { public: - ParameterizedType(ID* type_id, ExprList* args); - ~ParameterizedType() override; + ParameterizedType(ID* type_id, ExprList* args); + ~ParameterizedType() override; - Type* clone() const; + Type* clone() const; - string EvalMember(const ID* member_id) const override; - // Env *member_env() const; + string EvalMember(const ID* member_id) const override; + // Env *member_env() const; - void AddParamArg(Expr* arg); + void AddParamArg(Expr* arg); - bool DefineValueVar() const override; - string DataTypeStr() const override; - string DefaultValue() const override { return "0"; } - Type* MemberDataType(const ID* member_id) const override; + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override { return "0"; } + Type* MemberDataType(const ID* member_id) const override; - // "throw_exception" specifies whether to throw an exception - // if the referred data type is not found - Type* ReferredDataType(bool throw_exception) const; + // "throw_exception" specifies whether to throw an exception + // if the referred data type is not found + Type* ReferredDataType(bool throw_exception) const; - void GenCleanUpCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; - int StaticSize(Env* env) const override; + int StaticSize(Env* env) const override; - bool IsPointerType() const override { return true; } + bool IsPointerType() const override { return true; } - bool ByteOrderSensitive() const override; - bool RequiresAnalyzerContext() override; + bool ByteOrderSensitive() const override; + bool RequiresAnalyzerContext() override; - void GenInitCode(Output* out_cc, Env* env) override; + void GenInitCode(Output* out_cc, Env* env) override; - string class_name() const; - string EvalParameters(Output* out_cc, Env* env) const; + string class_name() const; + string EvalParameters(Output* out_cc, Env* env) const; - BufferMode buffer_mode() const override; + BufferMode buffer_mode() const override; protected: - void GenNewInstance(Output* out, Env* env) override; + void GenNewInstance(Output* out, Env* env) override; - bool DoTraverse(DataDepVisitor* visitor) override; - Type* DoClone() const override; - void DoMarkIncrementalInput() override; + bool DoTraverse(DataDepVisitor* visitor) override; + Type* DoClone() const override; + void DoMarkIncrementalInput() override; private: - ID* type_id_; - ExprList* args_; - bool checking_requires_analyzer_context_; + ID* type_id_; + ExprList* args_; + bool checking_requires_analyzer_context_; - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; - }; + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; +}; #endif // pac_paramtype_h diff --git a/tools/binpac/src/pac_primitive.cc b/tools/binpac/src/pac_primitive.cc index 2a5f47a2ee..faf43bc234 100644 --- a/tools/binpac/src/pac_primitive.cc +++ b/tools/binpac/src/pac_primitive.cc @@ -5,30 +5,26 @@ #include "pac_id.h" #include "pac_type.h" -string PPVal::ToCode(Env* env) - { - ASSERT(expr_); - return string(expr_->EvalExpr(nullptr, env)); - } +string PPVal::ToCode(Env* env) { + ASSERT(expr_); + return string(expr_->EvalExpr(nullptr, env)); +} -string PPSet::ToCode(Env* env) - { - ASSERT(expr_); - return expr_->SetFunc(nullptr, env); - } +string PPSet::ToCode(Env* env) { + ASSERT(expr_); + return expr_->SetFunc(nullptr, env); +} -string PPType::ToCode(Env* env) - { - Type* type = expr_->DataType(env); - return type->DataTypeStr(); - } +string PPType::ToCode(Env* env) { + Type* type = expr_->DataType(env); + return type->DataTypeStr(); +} -string PPConstDef::ToCode(Env* env) - { - Type* type = expr_->DataType(env); - env->AddID(id_, TEMP_VAR, type); - env->SetEvaluated(id_); +string PPConstDef::ToCode(Env* env) { + Type* type = expr_->DataType(env); + env->AddID(id_, TEMP_VAR, type); + env->SetEvaluated(id_); - string type_str = type->DataTypeStr(); - return strfmt("%s %s = %s", type_str.c_str(), env->LValue(id_), expr_->EvalExpr(nullptr, env)); - } + string type_str = type->DataTypeStr(); + return strfmt("%s %s = %s", type_str.c_str(), env->LValue(id_), expr_->EvalExpr(nullptr, env)); +} diff --git a/tools/binpac/src/pac_primitive.h b/tools/binpac/src/pac_primitive.h index 736049387a..9ee248b8e1 100644 --- a/tools/binpac/src/pac_primitive.h +++ b/tools/binpac/src/pac_primitive.h @@ -3,76 +3,65 @@ #include "pac_common.h" -class PacPrimitive - { +class PacPrimitive { public: - enum PrimitiveType - { - VAL, - SET, - TYPE, - CONST_DEF - }; + enum PrimitiveType { VAL, SET, TYPE, CONST_DEF }; - explicit PacPrimitive(PrimitiveType type) : type_(type) { } - virtual ~PacPrimitive() { } + explicit PacPrimitive(PrimitiveType type) : type_(type) {} + virtual ~PacPrimitive() {} - PrimitiveType type() const { return type_; } + PrimitiveType type() const { return type_; } - virtual string ToCode(Env* env) = 0; + virtual string ToCode(Env* env) = 0; private: - PrimitiveType type_; - }; + PrimitiveType type_; +}; -class PPVal : public PacPrimitive - { +class PPVal : public PacPrimitive { public: - PPVal(Expr* expr) : PacPrimitive(VAL), expr_(expr) { } - Expr* expr() const { return expr_; } + PPVal(Expr* expr) : PacPrimitive(VAL), expr_(expr) {} + Expr* expr() const { return expr_; } - string ToCode(Env* env) override; + string ToCode(Env* env) override; private: - Expr* expr_; - }; + Expr* expr_; +}; -class PPSet : public PacPrimitive - { +class PPSet : public PacPrimitive { public: - PPSet(Expr* expr) : PacPrimitive(SET), expr_(expr) { } - Expr* expr() const { return expr_; } + PPSet(Expr* expr) : PacPrimitive(SET), expr_(expr) {} + Expr* expr() const { return expr_; } - string ToCode(Env* env) override; + string ToCode(Env* env) override; private: - Expr* expr_; - }; + Expr* expr_; +}; -class PPType : public PacPrimitive - { +class PPType : public PacPrimitive { public: - PPType(Expr* expr) : PacPrimitive(TYPE), expr_(expr) { } - Expr* expr() const { return expr_; } + PPType(Expr* expr) : PacPrimitive(TYPE), expr_(expr) {} + Expr* expr() const { return expr_; } - string ToCode(Env* env) override; + string ToCode(Env* env) override; private: - Expr* expr_; - }; + Expr* expr_; +}; -class PPConstDef : public PacPrimitive - { +class PPConstDef : public PacPrimitive { public: - PPConstDef(const ID* id, Expr* expr) : PacPrimitive(CONST_DEF), id_(id), expr_(expr) { } - const ID* id() const { return id_; } - Expr* expr() const { return expr_; } + PPConstDef(const ID* id, Expr* expr) : PacPrimitive(CONST_DEF), id_(id), expr_(expr) {} + const ID* id() const { return id_; } + Expr* expr() const { return expr_; } - string ToCode(Env* env) override; + string ToCode(Env* env) override; private: - const ID* id_; - Expr* expr_; - }; + const ID* id_; + Expr* expr_; +}; #endif // pac_primitive_h diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index 266dfc6dcf..d7ed8dbfbf 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -12,75 +12,64 @@ #include "pac_utils.h" #include "pac_varfield.h" -RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD) - { - // Here we assume that the type is a standalone type. - value_var_ = nullptr; +RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD) { + // Here we assume that the type is a standalone type. + value_var_ = nullptr; - // Put all fields in fields_ - foreach (i, RecordFieldList, record_fields) - AddField(*i); + // Put all fields in fields_ + foreach (i, RecordFieldList, record_fields) + AddField(*i); - // Put RecordField's in record_fields_ - record_fields_ = record_fields; + // Put RecordField's in record_fields_ + record_fields_ = record_fields; - parsing_dataptr_var_field_ = nullptr; - } + parsing_dataptr_var_field_ = nullptr; +} -RecordType::~RecordType() - { - // Do not delete_list(RecordFieldList, record_fields_) - // because the fields are also in fields_. - delete record_fields_; - delete parsing_dataptr_var_field_; - } +RecordType::~RecordType() { + // Do not delete_list(RecordFieldList, record_fields_) + // because the fields are also in fields_. + delete record_fields_; + delete parsing_dataptr_var_field_; +} -const ID* RecordType::parsing_dataptr_var() const - { - return parsing_dataptr_var_field_ ? parsing_dataptr_var_field_->id() : nullptr; - } +const ID* RecordType::parsing_dataptr_var() const { + return parsing_dataptr_var_field_ ? parsing_dataptr_var_field_->id() : nullptr; +} -bool RecordType::DefineValueVar() const - { - return false; - } +bool RecordType::DefineValueVar() const { return false; } -string RecordType::DataTypeStr() const - { - ASSERT(type_decl()); - return strfmt("%s *", type_decl()->class_name().c_str()); - } +string RecordType::DataTypeStr() const { + ASSERT(type_decl()); + return strfmt("%s *", type_decl()->class_name().c_str()); +} -void RecordType::Prepare(Env* env, int flags) - { - ASSERT(flags & TO_BE_PARSED); +void RecordType::Prepare(Env* env, int flags) { + ASSERT(flags & TO_BE_PARSED); - RecordField* prev = nullptr; - int offset = 0; - int seq = 0; - foreach (i, RecordFieldList, record_fields_) - { - RecordField* f = *i; - f->set_record_type(this); - f->set_prev(prev); - if ( prev ) - prev->set_next(f); - prev = f; - if ( offset >= 0 ) - { - f->set_static_offset(offset); - int w = f->StaticSize(env, offset); - if ( w < 0 ) - offset = -1; - else - offset += w; - } - ++seq; - f->set_parsing_state_seq(seq); - } + RecordField* prev = nullptr; + int offset = 0; + int seq = 0; + foreach (i, RecordFieldList, record_fields_) { + RecordField* f = *i; + f->set_record_type(this); + f->set_prev(prev); + if ( prev ) + prev->set_next(f); + prev = f; + if ( offset >= 0 ) { + f->set_static_offset(offset); + int w = f->StaticSize(env, offset); + if ( w < 0 ) + offset = -1; + else + offset += w; + } + ++seq; + f->set_parsing_state_seq(seq); + } - if ( incremental_parsing() ) - { + if ( incremental_parsing() ) { #if 0 ASSERT(! parsing_state_var_field_); ID *parsing_state_var_id = new ID("parsing_state"); @@ -93,355 +82,297 @@ void RecordType::Prepare(Env* env, int flags) parsing_dataptr_var_id, extern_type_const_byteptr->Clone()); parsing_dataptr_var_field_->Prepare(env); #endif - } + } - Type::Prepare(env, flags); - } + Type::Prepare(env, flags); +} -void RecordType::GenPubDecls(Output* out_h, Env* env) - { - Type::GenPubDecls(out_h, env); - } +void RecordType::GenPubDecls(Output* out_h, Env* env) { Type::GenPubDecls(out_h, env); } -void RecordType::GenPrivDecls(Output* out_h, Env* env) - { - Type::GenPrivDecls(out_h, env); - } +void RecordType::GenPrivDecls(Output* out_h, Env* env) { Type::GenPrivDecls(out_h, env); } -void RecordType::GenInitCode(Output* out_cc, Env* env) - { - Type::GenInitCode(out_cc, env); - } +void RecordType::GenInitCode(Output* out_cc, Env* env) { Type::GenInitCode(out_cc, env); } -void RecordType::GenCleanUpCode(Output* out_cc, Env* env) - { - Type::GenCleanUpCode(out_cc, env); - } +void RecordType::GenCleanUpCode(Output* out_cc, Env* env) { Type::GenCleanUpCode(out_cc, env); } -void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) - { - if ( ! incremental_input() && StaticSize(env) >= 0 ) - GenBoundaryCheck(out_cc, env, data); +void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { + if ( ! incremental_input() && StaticSize(env) >= 0 ) + GenBoundaryCheck(out_cc, env, data); - if ( incremental_parsing() ) - { - out_cc->println("switch ( %s ) {", env->LValue(parsing_state_id)); + if ( incremental_parsing() ) { + out_cc->println("switch ( %s ) {", env->LValue(parsing_state_id)); - out_cc->println("case 0:"); - out_cc->inc_indent(); - foreach (i, RecordFieldList, record_fields_) - { - RecordField* f = *i; - f->GenParseCode(out_cc, env); - out_cc->println(""); - } - out_cc->println(""); - out_cc->println("%s = true;", env->LValue(parsing_complete_var())); - out_cc->dec_indent(); - out_cc->println("}"); - } - else - { - ASSERT(data.id() == begin_of_data && data.offset() == 0); - foreach (i, RecordFieldList, record_fields_) - { - RecordField* f = *i; - f->GenParseCode(out_cc, env); - out_cc->println(""); - } - if ( incremental_input() ) - { - ASSERT(parsing_complete_var()); - out_cc->println("%s = true;", env->LValue(parsing_complete_var())); - } - } + out_cc->println("case 0:"); + out_cc->inc_indent(); + foreach (i, RecordFieldList, record_fields_) { + RecordField* f = *i; + f->GenParseCode(out_cc, env); + out_cc->println(""); + } + out_cc->println(""); + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); + out_cc->dec_indent(); + out_cc->println("}"); + } + else { + ASSERT(data.id() == begin_of_data && data.offset() == 0); + foreach (i, RecordFieldList, record_fields_) { + RecordField* f = *i; + f->GenParseCode(out_cc, env); + out_cc->println(""); + } + if ( incremental_input() ) { + ASSERT(parsing_complete_var()); + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); + } + } - if ( ! incremental_input() && AddSizeVar(out_cc, env) ) - { - const DataPtr& end_of_record_dataptr = record_fields_->back()->getFieldEnd(out_cc, env); + if ( ! incremental_input() && AddSizeVar(out_cc, env) ) { + const DataPtr& end_of_record_dataptr = record_fields_->back()->getFieldEnd(out_cc, env); - out_cc->println("%s = %s - %s;", env->LValue(size_var()), end_of_record_dataptr.ptr_expr(), - env->RValue(begin_of_data)); - env->SetEvaluated(size_var()); - } + out_cc->println("%s = %s - %s;", env->LValue(size_var()), end_of_record_dataptr.ptr_expr(), + env->RValue(begin_of_data)); + env->SetEvaluated(size_var()); + } - if ( ! boundary_checked() ) - { - RecordField* last_field = record_fields_->back(); - if ( ! last_field->BoundaryChecked() ) - GenBoundaryCheck(out_cc, env, data); - } - } + if ( ! boundary_checked() ) { + RecordField* last_field = record_fields_->back(); + if ( ! last_field->BoundaryChecked() ) + GenBoundaryCheck(out_cc, env, data); + } +} -void RecordType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) - { - GenParseCode(out_cc, env, data, 0); - } +void RecordType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { GenParseCode(out_cc, env, data, 0); } -int RecordType::StaticSize(Env* env) const - { - int tot_w = 0; - foreach (i, RecordFieldList, record_fields_) - { - RecordField* f = *i; - int w = f->StaticSize(env, tot_w); - if ( w < 0 ) - return -1; - tot_w += w; - } - return tot_w; - } +int RecordType::StaticSize(Env* env) const { + int tot_w = 0; + foreach (i, RecordFieldList, record_fields_) { + RecordField* f = *i; + int w = f->StaticSize(env, tot_w); + if ( w < 0 ) + return -1; + tot_w += w; + } + return tot_w; +} -void RecordType::SetBoundaryChecked() - { - Type::SetBoundaryChecked(); +void RecordType::SetBoundaryChecked() { + Type::SetBoundaryChecked(); - if ( StaticSize(env()) < 0 || attr_length_expr_ ) - // Don't assume sufficient bounds checking has been done on fields - // if the record is of variable size or if its size is set from &length - // (whose value is not necessarily trustworthy). - return; + if ( StaticSize(env()) < 0 || attr_length_expr_ ) + // Don't assume sufficient bounds checking has been done on fields + // if the record is of variable size or if its size is set from &length + // (whose value is not necessarily trustworthy). + return; - foreach (i, RecordFieldList, record_fields_) - { - RecordField* f = *i; - f->SetBoundaryChecked(); - } - } + foreach (i, RecordFieldList, record_fields_) { + RecordField* f = *i; + f->SetBoundaryChecked(); + } +} -void RecordType::DoMarkIncrementalInput() - { - foreach (i, RecordFieldList, record_fields_) - { - RecordField* f = *i; - f->type()->MarkIncrementalInput(); - } - } +void RecordType::DoMarkIncrementalInput() { + foreach (i, RecordFieldList, record_fields_) { + RecordField* f = *i; + f->type()->MarkIncrementalInput(); + } +} -bool RecordType::DoTraverse(DataDepVisitor* visitor) - { - return Type::DoTraverse(visitor); - } +bool RecordType::DoTraverse(DataDepVisitor* visitor) { return Type::DoTraverse(visitor); } -bool RecordType::ByteOrderSensitive() const - { - foreach (i, RecordFieldList, record_fields_) - { - RecordField* f = *i; - if ( f->RequiresByteOrder() ) - return true; - } - return false; - } +bool RecordType::ByteOrderSensitive() const { + foreach (i, RecordFieldList, record_fields_) { + RecordField* f = *i; + if ( f->RequiresByteOrder() ) + return true; + } + return false; +} RecordField::RecordField(FieldType tof, ID* id, Type* type) - : Field(tof, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) - { - begin_of_field_dataptr = nullptr; - end_of_field_dataptr = nullptr; - field_size_expr = nullptr; - field_offset_expr = nullptr; - end_of_field_dataptr_var = nullptr; - record_type_ = nullptr; - prev_ = nullptr; - next_ = nullptr; - static_offset_ = -1; - parsing_state_seq_ = 0; - boundary_checked_ = false; - } + : Field(tof, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) { + begin_of_field_dataptr = nullptr; + end_of_field_dataptr = nullptr; + field_size_expr = nullptr; + field_offset_expr = nullptr; + end_of_field_dataptr_var = nullptr; + record_type_ = nullptr; + prev_ = nullptr; + next_ = nullptr; + static_offset_ = -1; + parsing_state_seq_ = 0; + boundary_checked_ = false; +} -RecordField::~RecordField() - { - delete begin_of_field_dataptr; - delete end_of_field_dataptr; - delete[] field_size_expr; - delete[] field_offset_expr; - delete end_of_field_dataptr_var; - } +RecordField::~RecordField() { + delete begin_of_field_dataptr; + delete end_of_field_dataptr; + delete[] field_size_expr; + delete[] field_offset_expr; + delete end_of_field_dataptr_var; +} -const DataPtr& RecordField::getFieldBegin(Output* out_cc, Env* env) - { - if ( prev() ) - return prev()->getFieldEnd(out_cc, env); - else - { - // The first field - if ( ! begin_of_field_dataptr ) - { - begin_of_field_dataptr = new DataPtr(env, begin_of_data, 0); - } - return *begin_of_field_dataptr; - } - } +const DataPtr& RecordField::getFieldBegin(Output* out_cc, Env* env) { + if ( prev() ) + return prev()->getFieldEnd(out_cc, env); + else { + // The first field + if ( ! begin_of_field_dataptr ) { + begin_of_field_dataptr = new DataPtr(env, begin_of_data, 0); + } + return *begin_of_field_dataptr; + } +} -const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) - { - if ( end_of_field_dataptr ) - return *end_of_field_dataptr; +const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) { + if ( end_of_field_dataptr ) + return *end_of_field_dataptr; - const DataPtr& begin_ptr = getFieldBegin(out_cc, env); + const DataPtr& begin_ptr = getFieldBegin(out_cc, env); - if ( record_type()->incremental_parsing() ) - { - ASSERT(0); - if ( ! end_of_field_dataptr ) - { - const ID* dataptr_var = record_type()->parsing_dataptr_var(); - ASSERT(dataptr_var); + if ( record_type()->incremental_parsing() ) { + ASSERT(0); + if ( ! end_of_field_dataptr ) { + const ID* dataptr_var = record_type()->parsing_dataptr_var(); + ASSERT(dataptr_var); - end_of_field_dataptr = new DataPtr(env, dataptr_var, 0); - } - } - else - { - int field_offset; - if ( begin_ptr.id() == begin_of_data ) - field_offset = begin_ptr.offset(); - else - field_offset = -1; // unknown + end_of_field_dataptr = new DataPtr(env, dataptr_var, 0); + } + } + else { + int field_offset; + if ( begin_ptr.id() == begin_of_data ) + field_offset = begin_ptr.offset(); + else + field_offset = -1; // unknown - int field_size = StaticSize(env, field_offset); - if ( field_size >= 0 ) // can be statically determinted - { - end_of_field_dataptr = new DataPtr(env, begin_ptr.id(), - begin_ptr.offset() + field_size); - } - else - { - // If not, we add a variable for the offset after the field - end_of_field_dataptr_var = new ID(strfmt("dataptr_after_%s", id()->Name())); - env->AddID(end_of_field_dataptr_var, TEMP_VAR, extern_type_const_byteptr); + int field_size = StaticSize(env, field_offset); + if ( field_size >= 0 ) // can be statically determinted + { + end_of_field_dataptr = new DataPtr(env, begin_ptr.id(), begin_ptr.offset() + field_size); + } + else { + // If not, we add a variable for the offset after the field + end_of_field_dataptr_var = new ID(strfmt("dataptr_after_%s", id()->Name())); + env->AddID(end_of_field_dataptr_var, TEMP_VAR, extern_type_const_byteptr); - GenFieldEnd(out_cc, env, begin_ptr); + GenFieldEnd(out_cc, env, begin_ptr); - end_of_field_dataptr = new DataPtr(env, end_of_field_dataptr_var, 0); - } - } + end_of_field_dataptr = new DataPtr(env, end_of_field_dataptr_var, 0); + } + } - return *end_of_field_dataptr; - } + return *end_of_field_dataptr; +} -const char* RecordField::FieldSize(Output* out_cc, Env* env) - { - if ( field_size_expr ) - return field_size_expr; +const char* RecordField::FieldSize(Output* out_cc, Env* env) { + if ( field_size_expr ) + return field_size_expr; - const DataPtr& begin = getFieldBegin(out_cc, env); - const DataPtr& end = getFieldEnd(out_cc, env); - if ( begin.id() == end.id() ) - field_size_expr = nfmt("%d", end.offset() - begin.offset()); - else - field_size_expr = nfmt("(%s - %s)", end.ptr_expr(), begin.ptr_expr()); - return field_size_expr; - } + const DataPtr& begin = getFieldBegin(out_cc, env); + const DataPtr& end = getFieldEnd(out_cc, env); + if ( begin.id() == end.id() ) + field_size_expr = nfmt("%d", end.offset() - begin.offset()); + else + field_size_expr = nfmt("(%s - %s)", end.ptr_expr(), begin.ptr_expr()); + return field_size_expr; +} -const char* RecordField::FieldOffset(Output* out_cc, Env* env) - { - if ( field_offset_expr ) - return field_offset_expr; +const char* RecordField::FieldOffset(Output* out_cc, Env* env) { + if ( field_offset_expr ) + return field_offset_expr; - const DataPtr& begin = getFieldBegin(out_cc, env); - if ( begin.id() == begin_of_data ) - field_offset_expr = nfmt("%d", begin.offset()); - else - field_offset_expr = nfmt("(%s - %s)", begin.ptr_expr(), env->RValue(begin_of_data)); - return field_offset_expr; - } + const DataPtr& begin = getFieldBegin(out_cc, env); + if ( begin.id() == begin_of_data ) + field_offset_expr = nfmt("%d", begin.offset()); + else + field_offset_expr = nfmt("(%s - %s)", begin.ptr_expr(), env->RValue(begin_of_data)); + return field_offset_expr; +} // The reasoning behind AttemptBoundaryCheck is: "If my next field // can check its boundary, then I don't have to check mine, and it // will save me a boundary-check." -bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env) - { - if ( boundary_checked_ ) - return true; +bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env) { + if ( boundary_checked_ ) + return true; - // If I do not even know my size till I parse the data, my - // next field won't be able to check its boundary now. + // If I do not even know my size till I parse the data, my + // next field won't be able to check its boundary now. - const DataPtr& begin = getFieldBegin(out_cc, env); - if ( StaticSize(env, begin.AbsOffset(begin_of_data)) < 0 ) - return false; + const DataPtr& begin = getFieldBegin(out_cc, env); + if ( StaticSize(env, begin.AbsOffset(begin_of_data)) < 0 ) + return false; - // Now we ask the next field to check its boundary. - if ( next() && next()->AttemptBoundaryCheck(out_cc, env) ) - { - // If it works, we are all set - SetBoundaryChecked(); - return true; - } - else - // If it fails, then I can still try to do it by myself - return GenBoundaryCheck(out_cc, env); - } + // Now we ask the next field to check its boundary. + if ( next() && next()->AttemptBoundaryCheck(out_cc, env) ) { + // If it works, we are all set + SetBoundaryChecked(); + return true; + } + else + // If it fails, then I can still try to do it by myself + return GenBoundaryCheck(out_cc, env); +} -RecordDataField::RecordDataField(ID* id, Type* type) : RecordField(RECORD_FIELD, id, type) - { - ASSERT(type_); - } +RecordDataField::RecordDataField(ID* id, Type* type) : RecordField(RECORD_FIELD, id, type) { ASSERT(type_); } -RecordDataField::~RecordDataField() { } +RecordDataField::~RecordDataField() {} -void RecordDataField::Prepare(Env* env) - { - Field::Prepare(env); - env->SetEvalMethod(id_, this); - env->SetField(id_, this); - } +void RecordDataField::Prepare(Env* env) { + Field::Prepare(env); + env->SetEvalMethod(id_, this); + env->SetField(id_, this); +} -void RecordDataField::GenParseCode(Output* out_cc, Env* env) - { - if ( env->Evaluated(id()) ) - return; +void RecordDataField::GenParseCode(Output* out_cc, Env* env) { + if ( env->Evaluated(id()) ) + return; - // Always evaluate record fields in order if parsing - // is incremental. - if ( record_type()->incremental_parsing() && prev() ) - prev()->GenParseCode(out_cc, env); + // Always evaluate record fields in order if parsing + // is incremental. + if ( record_type()->incremental_parsing() && prev() ) + prev()->GenParseCode(out_cc, env); - DataPtr data(env, nullptr, 0); - if ( ! record_type()->incremental_parsing() ) - { - data = getFieldBegin(out_cc, env); + DataPtr data(env, nullptr, 0); + if ( ! record_type()->incremental_parsing() ) { + data = getFieldBegin(out_cc, env); - Expr* len_expr = record_type()->attr_length_expr(); - int len; + Expr* len_expr = record_type()->attr_length_expr(); + int len; - if ( ! record_type()->buffer_input() || (len_expr && len_expr->ConstFold(env, &len)) ) - AttemptBoundaryCheck(out_cc, env); - } + if ( ! record_type()->buffer_input() || (len_expr && len_expr->ConstFold(env, &len)) ) + AttemptBoundaryCheck(out_cc, env); + } - out_cc->println("// Parse \"%s\"", id_->Name()); + out_cc->println("// Parse \"%s\"", id_->Name()); #if 0 out_cc->println("DEBUG_MSG(\"%%.6f Parse %s\\n\", network_time());", id_->Name()); #endif - type_->GenPreParsing(out_cc, env); - if ( type_->incremental_input() ) - { - // The enclosing record type must be incrementally parsed - out_cc->println("%s = %d;", env->LValue(parsing_state_id), parsing_state_seq()); - out_cc->println("/* fall through */"); - out_cc->dec_indent(); - out_cc->println("case %d:", parsing_state_seq()); - out_cc->inc_indent(); - out_cc->println("{"); - } + type_->GenPreParsing(out_cc, env); + if ( type_->incremental_input() ) { + // The enclosing record type must be incrementally parsed + out_cc->println("%s = %d;", env->LValue(parsing_state_id), parsing_state_seq()); + out_cc->println("/* fall through */"); + out_cc->dec_indent(); + out_cc->println("case %d:", parsing_state_seq()); + out_cc->inc_indent(); + out_cc->println("{"); + } - type_->GenParseCode(out_cc, env, data, 0); + type_->GenParseCode(out_cc, env, data, 0); - if ( record_type()->incremental_parsing() ) - { - ASSERT(type_->incremental_input()); + if ( record_type()->incremental_parsing() ) { + ASSERT(type_->incremental_input()); - out_cc->println("if ( ! (%s) )", type_->parsing_complete(env).c_str()); - out_cc->inc_indent(); - out_cc->println("goto %s;", kNeedMoreData); - out_cc->dec_indent(); - } + out_cc->println("if ( ! (%s) )", type_->parsing_complete(env).c_str()); + out_cc->inc_indent(); + out_cc->println("goto %s;", kNeedMoreData); + out_cc->dec_indent(); + } - if ( record_type()->incremental_parsing() ) - { + if ( record_type()->incremental_parsing() ) { #if 0 const ID *dataptr_var = record_type()->parsing_dataptr_var(); @@ -450,221 +381,188 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) env->LValue(dataptr_var), type_->DataSize(out_cc, env, data).c_str()); #endif - out_cc->println("}"); - } + out_cc->println("}"); + } - SetBoundaryChecked(); - } + SetBoundaryChecked(); +} -void RecordDataField::GenEval(Output* out_cc, Env* env) - { - GenParseCode(out_cc, env); - } +void RecordDataField::GenEval(Output* out_cc, Env* env) { GenParseCode(out_cc, env); } -void RecordDataField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin) - { - out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), - field_begin.ptr_expr(), type_->DataSize(out_cc, env, field_begin).c_str()); - env->SetEvaluated(end_of_field_dataptr_var); +void RecordDataField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin) { + out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr(), type_->DataSize(out_cc, env, field_begin).c_str()); + env->SetEvaluated(end_of_field_dataptr_var); - out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(end_of_field_dataptr_var), - env->RValue(end_of_data)); - } + out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(end_of_field_dataptr_var), env->RValue(end_of_data)); +} -void RecordDataField::SetBoundaryChecked() - { - RecordField::SetBoundaryChecked(); - type_->SetBoundaryChecked(); - } +void RecordDataField::SetBoundaryChecked() { + RecordField::SetBoundaryChecked(); + type_->SetBoundaryChecked(); +} -bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env) - { - if ( boundary_checked_ ) - return true; +bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env) { + if ( boundary_checked_ ) + return true; - type_->GenBoundaryCheck(out_cc, env, getFieldBegin(out_cc, env)); + type_->GenBoundaryCheck(out_cc, env, getFieldBegin(out_cc, env)); - SetBoundaryChecked(); - return true; - } + SetBoundaryChecked(); + return true; +} -bool RecordDataField::DoTraverse(DataDepVisitor* visitor) - { - return Field::DoTraverse(visitor); - } +bool RecordDataField::DoTraverse(DataDepVisitor* visitor) { return Field::DoTraverse(visitor); } -bool RecordDataField::RequiresAnalyzerContext() const - { - return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext(); - } +bool RecordDataField::RequiresAnalyzerContext() const { + return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext(); +} RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr) - : RecordField(PADDING_FIELD, id, nullptr), ptype_(ptype), expr_(expr) - { - wordsize_ = -1; - } + : RecordField(PADDING_FIELD, id, nullptr), ptype_(ptype), expr_(expr) { + wordsize_ = -1; +} -RecordPaddingField::~RecordPaddingField() { } +RecordPaddingField::~RecordPaddingField() {} -void RecordPaddingField::Prepare(Env* env) - { - Field::Prepare(env); - if ( ptype_ == PAD_TO_NEXT_WORD ) - { - if ( ! expr_->ConstFold(env, &wordsize_) ) - throw ExceptionPaddingError(this, strfmt("padding word size not a constant")); - } - } +void RecordPaddingField::Prepare(Env* env) { + Field::Prepare(env); + if ( ptype_ == PAD_TO_NEXT_WORD ) { + if ( ! expr_->ConstFold(env, &wordsize_) ) + throw ExceptionPaddingError(this, strfmt("padding word size not a constant")); + } +} -void RecordPaddingField::GenParseCode(Output* out_cc, Env* env) - { - // Always evaluate record fields in order if parsing - // is incremental. - if ( record_type()->incremental_parsing() && prev() ) - prev()->GenParseCode(out_cc, env); - } +void RecordPaddingField::GenParseCode(Output* out_cc, Env* env) { + // Always evaluate record fields in order if parsing + // is incremental. + if ( record_type()->incremental_parsing() && prev() ) + prev()->GenParseCode(out_cc, env); +} -int RecordPaddingField::StaticSize(Env* env, int offset) const - { - int length; - int target_offset; - int offset_in_word; +int RecordPaddingField::StaticSize(Env* env, int offset) const { + int length; + int target_offset; + int offset_in_word; - switch ( ptype_ ) - { - case PAD_BY_LENGTH: - return expr_->ConstFold(env, &length) ? length : -1; + switch ( ptype_ ) { + case PAD_BY_LENGTH: return expr_->ConstFold(env, &length) ? length : -1; - case PAD_TO_OFFSET: - // If the current offset cannot be statically - // determined, we need to Generate code to - // check the offset - if ( offset == -1 ) - return -1; + case PAD_TO_OFFSET: + // If the current offset cannot be statically + // determined, we need to Generate code to + // check the offset + if ( offset == -1 ) + return -1; - if ( ! expr_->ConstFold(env, &target_offset) ) - return -1; + if ( ! expr_->ConstFold(env, &target_offset) ) + return -1; - // If both the current and target offsets - // can be statically computed, we can get its - // static size - if ( offset > target_offset ) - throw ExceptionPaddingError(this, strfmt("current offset = %d, " - "target offset = %d", - offset, target_offset)); - return target_offset - offset; + // If both the current and target offsets + // can be statically computed, we can get its + // static size + if ( offset > target_offset ) + throw ExceptionPaddingError(this, strfmt("current offset = %d, " + "target offset = %d", + offset, target_offset)); + return target_offset - offset; - case PAD_TO_NEXT_WORD: - if ( offset == -1 || wordsize_ == -1 ) - return -1; + case PAD_TO_NEXT_WORD: + if ( offset == -1 || wordsize_ == -1 ) + return -1; - offset_in_word = offset % wordsize_; - return (offset_in_word == 0) ? 0 : wordsize_ - offset_in_word; - } + offset_in_word = offset % wordsize_; + return (offset_in_word == 0) ? 0 : wordsize_ - offset_in_word; + } - return -1; - } + return -1; +} -void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin) - { - ASSERT(! env->Evaluated(end_of_field_dataptr_var)); +void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin) { + ASSERT(! env->Evaluated(end_of_field_dataptr_var)); - char* padding_var; - switch ( ptype_ ) - { - case PAD_BY_LENGTH: - out_cc->println("if ( (%s) < 0 ) // check for negative pad length", - expr_->EvalExpr(out_cc, env)); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), - expr_->EvalExpr(out_cc, env)); - out_cc->println("}"); - out_cc->dec_indent(); - out_cc->println(""); + char* padding_var; + switch ( ptype_ ) { + case PAD_BY_LENGTH: + out_cc->println("if ( (%s) < 0 ) // check for negative pad length", expr_->EvalExpr(out_cc, env)); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), + expr_->EvalExpr(out_cc, env)); + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); - out_cc->println("const_byteptr const %s = %s + (%s);", - env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(), - expr_->EvalExpr(out_cc, env)); + out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr(), expr_->EvalExpr(out_cc, env)); - out_cc->println("// Checking out-of-bound padding for \"%s\"", field_id_str_.c_str()); - out_cc->println("if ( %s > %s || %s < %s )", env->LValue(end_of_field_dataptr_var), - env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var), - field_begin.ptr_expr()); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); - out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env)); - out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), - env->LValue(end_of_field_dataptr_var)); - out_cc->println("}"); - out_cc->dec_indent(); - out_cc->println(""); - break; + out_cc->println("// Checking out-of-bound padding for \"%s\"", field_id_str_.c_str()); + out_cc->println("if ( %s > %s || %s < %s )", env->LValue(end_of_field_dataptr_var), + env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr()); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); + out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env)); + out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var)); + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println(""); + break; - case PAD_TO_OFFSET: - out_cc->println("const_byteptr %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), - env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env)); - out_cc->println("if ( %s < %s )", env->LValue(end_of_field_dataptr_var), - field_begin.ptr_expr()); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);", - id_->LocName(), field_begin.ptr_expr(), env->RValue(begin_of_data), - expr_->EvalExpr(out_cc, env)); - out_cc->println("%s = %s;", env->LValue(end_of_field_dataptr_var), - field_begin.ptr_expr()); - out_cc->println("}"); - out_cc->dec_indent(); - out_cc->println("if ( %s > %s )", env->LValue(end_of_field_dataptr_var), - env->RValue(end_of_data)); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); - out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env)); - out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), - env->LValue(end_of_field_dataptr_var)); - out_cc->println("}"); - out_cc->dec_indent(); - break; + case PAD_TO_OFFSET: + out_cc->println("const_byteptr %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), + env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env)); + out_cc->println("if ( %s < %s )", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr()); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);", id_->LocName(), + field_begin.ptr_expr(), env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env)); + out_cc->println("%s = %s;", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr()); + out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println("if ( %s > %s )", env->LValue(end_of_field_dataptr_var), env->RValue(end_of_data)); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); + out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env)); + out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var)); + out_cc->println("}"); + out_cc->dec_indent(); + break; - case PAD_TO_NEXT_WORD: - padding_var = nfmt("%s__size", id()->Name()); - out_cc->println("int %s = (%s - %s) %% %d;", padding_var, field_begin.ptr_expr(), - env->RValue(begin_of_data), wordsize_); - out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", padding_var, padding_var, wordsize_, - padding_var); - out_cc->println("const_byteptr const %s = %s + %s;", - env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(), - padding_var); - delete[] padding_var; - break; - } + case PAD_TO_NEXT_WORD: + padding_var = nfmt("%s__size", id()->Name()); + out_cc->println("int %s = (%s - %s) %% %d;", padding_var, field_begin.ptr_expr(), + env->RValue(begin_of_data), wordsize_); + out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", padding_var, padding_var, wordsize_, padding_var); + out_cc->println("const_byteptr const %s = %s + %s;", env->LValue(end_of_field_dataptr_var), + field_begin.ptr_expr(), padding_var); + delete[] padding_var; + break; + } - env->SetEvaluated(end_of_field_dataptr_var); - } + env->SetEvaluated(end_of_field_dataptr_var); +} -bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env) - { - if ( boundary_checked_ ) - return true; +bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env) { + if ( boundary_checked_ ) + return true; - const DataPtr& begin = getFieldBegin(out_cc, env); + const DataPtr& begin = getFieldBegin(out_cc, env); - char* size; - int ss = StaticSize(env, begin.AbsOffset(begin_of_data)); - ASSERT(ss >= 0); - size = nfmt("%d", ss); + char* size; + int ss = StaticSize(env, begin.AbsOffset(begin_of_data)); + ASSERT(ss >= 0); + size = nfmt("%d", ss); - begin.GenBoundaryCheck(out_cc, env, size, field_id_str_.c_str()); + begin.GenBoundaryCheck(out_cc, env, size, field_id_str_.c_str()); - delete[] size; + delete[] size; - SetBoundaryChecked(); - return true; - } + SetBoundaryChecked(); + return true; +} -bool RecordPaddingField::DoTraverse(DataDepVisitor* visitor) - { - return Field::DoTraverse(visitor) && (! expr_ || expr_->Traverse(visitor)); - } +bool RecordPaddingField::DoTraverse(DataDepVisitor* visitor) { + return Field::DoTraverse(visitor) && (! expr_ || expr_->Traverse(visitor)); +} diff --git a/tools/binpac/src/pac_record.h b/tools/binpac/src/pac_record.h index 235607241d..539a04a6ba 100644 --- a/tools/binpac/src/pac_record.h +++ b/tools/binpac/src/pac_record.h @@ -7,179 +7,165 @@ #include "pac_let.h" #include "pac_type.h" -class RecordType : public Type - { +class RecordType : public Type { public: - RecordType(RecordFieldList* fields); - ~RecordType() override; + RecordType(RecordFieldList* fields); + ~RecordType() override; - bool DefineValueVar() const override; - string DataTypeStr() const override; + bool DefineValueVar() const override; + string DataTypeStr() const override; - void Prepare(Env* env, int flags) override; + void Prepare(Env* env, int flags) override; - void GenPubDecls(Output* out, Env* env) override; - void GenPrivDecls(Output* out, Env* env) override; + void GenPubDecls(Output* out, Env* env) override; + void GenPrivDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env) override; - void GenCleanUpCode(Output* out, Env* env) override; + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; - int StaticSize(Env* env) const override; + int StaticSize(Env* env) const override; - void SetBoundaryChecked() override; + void SetBoundaryChecked() override; - const ID* parsing_dataptr_var() const; + const ID* parsing_dataptr_var() const; - bool IsPointerType() const override - { - ASSERT(0); - return false; - } + bool IsPointerType() const override { + ASSERT(0); + return false; + } protected: - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; - Type* DoClone() const override { return nullptr; } + Type* DoClone() const override { return nullptr; } - void DoMarkIncrementalInput() override; + void DoMarkIncrementalInput() override; - bool DoTraverse(DataDepVisitor* visitor) override; - bool ByteOrderSensitive() const override; + bool DoTraverse(DataDepVisitor* visitor) override; + bool ByteOrderSensitive() const override; private: - Field* parsing_dataptr_var_field_; - RecordFieldList* record_fields_; - }; + Field* parsing_dataptr_var_field_; + RecordFieldList* record_fields_; +}; // A data field of a record type. A RecordField corresponds to a // segment of input data, and therefore RecordField's are ordered---each // of them has a known previous and next field. -class RecordField : public Field - { +class RecordField : public Field { public: - RecordField(FieldType tof, ID* id, Type* type); - ~RecordField() override; + RecordField(FieldType tof, ID* id, Type* type); + ~RecordField() override; - RecordType* record_type() const { return record_type_; } - void set_record_type(RecordType* ty) { record_type_ = ty; } + RecordType* record_type() const { return record_type_; } + void set_record_type(RecordType* ty) { record_type_ = ty; } - virtual void GenParseCode(Output* out, Env* env) = 0; + virtual void GenParseCode(Output* out, Env* env) = 0; - RecordField* prev() const { return prev_; } - RecordField* next() const { return next_; } - void set_prev(RecordField* f) { prev_ = f; } - void set_next(RecordField* f) { next_ = f; } + RecordField* prev() const { return prev_; } + RecordField* next() const { return next_; } + void set_prev(RecordField* f) { prev_ = f; } + void set_next(RecordField* f) { next_ = f; } - int static_offset() const { return static_offset_; } - void set_static_offset(int offset) { static_offset_ = offset; } + int static_offset() const { return static_offset_; } + void set_static_offset(int offset) { static_offset_ = offset; } - int parsing_state_seq() const { return parsing_state_seq_; } - void set_parsing_state_seq(int x) { parsing_state_seq_ = x; } + int parsing_state_seq() const { return parsing_state_seq_; } + void set_parsing_state_seq(int x) { parsing_state_seq_ = x; } - virtual int StaticSize(Env* env, int offset) const = 0; - const char* FieldSize(Output* out, Env* env); - const char* FieldOffset(Output* out, Env* env); + virtual int StaticSize(Env* env, int offset) const = 0; + const char* FieldSize(Output* out, Env* env); + const char* FieldOffset(Output* out, Env* env); - virtual bool BoundaryChecked() const { return boundary_checked_; } - virtual void SetBoundaryChecked() { boundary_checked_ = true; } + virtual bool BoundaryChecked() const { return boundary_checked_; } + virtual void SetBoundaryChecked() { boundary_checked_ = true; } - virtual bool RequiresByteOrder() const = 0; + virtual bool RequiresByteOrder() const = 0; - friend class RecordType; + friend class RecordType; protected: - RecordType* record_type_; - RecordField* prev_; - RecordField* next_; - bool boundary_checked_; - int static_offset_; - int parsing_state_seq_; + RecordType* record_type_; + RecordField* prev_; + RecordField* next_; + bool boundary_checked_; + int static_offset_; + int parsing_state_seq_; - DataPtr* begin_of_field_dataptr; - DataPtr* end_of_field_dataptr; - char* field_size_expr; - char* field_offset_expr; - ID* end_of_field_dataptr_var; + DataPtr* begin_of_field_dataptr; + DataPtr* end_of_field_dataptr; + char* field_size_expr; + char* field_offset_expr; + ID* end_of_field_dataptr_var; - const DataPtr& getFieldBegin(Output* out_cc, Env* env); - const DataPtr& getFieldEnd(Output* out_cc, Env* env); - virtual void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) = 0; + const DataPtr& getFieldBegin(Output* out_cc, Env* env); + const DataPtr& getFieldEnd(Output* out_cc, Env* env); + virtual void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) = 0; - bool AttemptBoundaryCheck(Output* out_cc, Env* env); - virtual bool GenBoundaryCheck(Output* out_cc, Env* env) = 0; - }; + bool AttemptBoundaryCheck(Output* out_cc, Env* env); + virtual bool GenBoundaryCheck(Output* out_cc, Env* env) = 0; +}; -class RecordDataField : public RecordField, public Evaluatable - { +class RecordDataField : public RecordField, public Evaluatable { public: - RecordDataField(ID* arg_id, Type* arg_type); - ~RecordDataField() override; + RecordDataField(ID* arg_id, Type* arg_type); + ~RecordDataField() override; - // Instantiates abstract class Field - void Prepare(Env* env) override; - void GenParseCode(Output* out, Env* env) override; + // Instantiates abstract class Field + void Prepare(Env* env) override; + void GenParseCode(Output* out, Env* env) override; - // Instantiates abstract class Evaluatable - void GenEval(Output* out, Env* env) override; + // Instantiates abstract class Evaluatable + void GenEval(Output* out, Env* env) override; - int StaticSize(Env* env, int) const override { return type()->StaticSize(env); } + int StaticSize(Env* env, int) const override { return type()->StaticSize(env); } - void SetBoundaryChecked() override; + void SetBoundaryChecked() override; - bool RequiresByteOrder() const override { return type()->RequiresByteOrder(); } - bool RequiresAnalyzerContext() const override; + bool RequiresByteOrder() const override { return type()->RequiresByteOrder(); } + bool RequiresAnalyzerContext() const override; protected: - void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) override; - bool GenBoundaryCheck(Output* out_cc, Env* env) override; - bool DoTraverse(DataDepVisitor* visitor) override; - }; + void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) override; + bool GenBoundaryCheck(Output* out_cc, Env* env) override; + bool DoTraverse(DataDepVisitor* visitor) override; +}; -enum PaddingType - { - PAD_BY_LENGTH, - PAD_TO_OFFSET, - PAD_TO_NEXT_WORD - }; +enum PaddingType { PAD_BY_LENGTH, PAD_TO_OFFSET, PAD_TO_NEXT_WORD }; -class RecordPaddingField : public RecordField - { +class RecordPaddingField : public RecordField { public: - RecordPaddingField(ID* id, PaddingType ptype, Expr* expr); - ~RecordPaddingField() override; + RecordPaddingField(ID* id, PaddingType ptype, Expr* expr); + ~RecordPaddingField() override; - void Prepare(Env* env) override; + void Prepare(Env* env) override; - void GenPubDecls(Output* out, Env* env) override - { /* nothing */ - } - void GenPrivDecls(Output* out, Env* env) override - { /* nothing */ - } + void GenPubDecls(Output* out, Env* env) override { /* nothing */ + } + void GenPrivDecls(Output* out, Env* env) override { /* nothing */ + } - void GenInitCode(Output* out, Env* env) override - { /* nothing */ - } - void GenCleanUpCode(Output* out, Env* env) override - { /* nothing */ - } - void GenParseCode(Output* out, Env* env) override; + void GenInitCode(Output* out, Env* env) override { /* nothing */ + } + void GenCleanUpCode(Output* out, Env* env) override { /* nothing */ + } + void GenParseCode(Output* out, Env* env) override; - int StaticSize(Env* env, int offset) const override; + int StaticSize(Env* env, int offset) const override; - bool RequiresByteOrder() const override { return false; } + bool RequiresByteOrder() const override { return false; } protected: - void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) override; - bool GenBoundaryCheck(Output* out_cc, Env* env) override; - bool DoTraverse(DataDepVisitor* visitor) override; + void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) override; + bool GenBoundaryCheck(Output* out_cc, Env* env) override; + bool DoTraverse(DataDepVisitor* visitor) override; private: - PaddingType ptype_; - Expr* expr_; - int wordsize_; - }; + PaddingType ptype_; + Expr* expr_; + int wordsize_; +}; #endif // pac_record_h diff --git a/tools/binpac/src/pac_redef.cc b/tools/binpac/src/pac_redef.cc index d720f2290a..c4368bbb5f 100644 --- a/tools/binpac/src/pac_redef.cc +++ b/tools/binpac/src/pac_redef.cc @@ -9,145 +9,124 @@ #include "pac_type.h" #include "pac_typedecl.h" -namespace - { +namespace { -Decl* find_decl(const ID* id) - { - Decl* decl = Decl::LookUpDecl(id); - if ( ! decl ) - { - throw Exception(id, strfmt("cannot find declaration for %s", id->Name())); - } +Decl* find_decl(const ID* id) { + Decl* decl = Decl::LookUpDecl(id); + if ( ! decl ) { + throw Exception(id, strfmt("cannot find declaration for %s", id->Name())); + } - return decl; - } + return decl; +} - } +} // namespace -Decl* ProcessTypeRedef(const ID* id, FieldList* fieldlist) - { - Decl* decl = find_decl(id); +Decl* ProcessTypeRedef(const ID* id, FieldList* fieldlist) { + Decl* decl = find_decl(id); - if ( decl->decl_type() != Decl::TYPE ) - { - throw Exception(id, strfmt("not a type declaration: %s", id->Name())); - } + if ( decl->decl_type() != Decl::TYPE ) { + throw Exception(id, strfmt("not a type declaration: %s", id->Name())); + } - TypeDecl* type_decl = static_cast(decl); - ASSERT(type_decl); - Type* type = type_decl->type(); + TypeDecl* type_decl = static_cast(decl); + ASSERT(type_decl); + Type* type = type_decl->type(); - foreach (i, FieldList, fieldlist) - { - Field* f = *i; + foreach (i, FieldList, fieldlist) { + Field* f = *i; - // One cannot change data layout in 'redef'. - // Only 'let' or 'action' can be added - if ( f->tof() == LET_FIELD || f->tof() == WITHINPUT_FIELD ) - { - type->AddField(f); - } - else if ( f->tof() == RECORD_FIELD || f->tof() == PADDING_FIELD ) - { - throw Exception(f, "cannot change data layout in redef"); - } - else if ( f->tof() == CASE_FIELD ) - { - throw Exception(f, "use 'redef case' adding cases"); - } - } + // One cannot change data layout in 'redef'. + // Only 'let' or 'action' can be added + if ( f->tof() == LET_FIELD || f->tof() == WITHINPUT_FIELD ) { + type->AddField(f); + } + else if ( f->tof() == RECORD_FIELD || f->tof() == PADDING_FIELD ) { + throw Exception(f, "cannot change data layout in redef"); + } + else if ( f->tof() == CASE_FIELD ) { + throw Exception(f, "use 'redef case' adding cases"); + } + } - return decl; - } + return decl; +} -Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist) - { - Decl* decl = find_decl(id); +Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist) { + Decl* decl = find_decl(id); - if ( decl->decl_type() != Decl::TYPE ) - { - throw Exception(id, strfmt("not a type declaration: %s", id->Name())); - } + if ( decl->decl_type() != Decl::TYPE ) { + throw Exception(id, strfmt("not a type declaration: %s", id->Name())); + } - TypeDecl* type_decl = static_cast(decl); - ASSERT(type_decl); + TypeDecl* type_decl = static_cast(decl); + ASSERT(type_decl); - Type* type = type_decl->type(); - if ( type->tot() != Type::CASE ) - { - throw Exception(id, strfmt("not a case type: %s", id->Name())); - } + Type* type = type_decl->type(); + if ( type->tot() != Type::CASE ) { + throw Exception(id, strfmt("not a case type: %s", id->Name())); + } - CaseType* casetype = static_cast(type); - ASSERT(casetype); + CaseType* casetype = static_cast(type); + ASSERT(casetype); - foreach (i, CaseFieldList, casefieldlist) - { - CaseField* f = *i; - casetype->AddCaseField(f); - } + foreach (i, CaseFieldList, casefieldlist) { + CaseField* f = *i; + casetype->AddCaseField(f); + } - return decl; - } + return decl; +} -Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist) - { - Decl* decl = find_decl(id); +Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist) { + Decl* decl = find_decl(id); - if ( decl->decl_type() != Decl::FUNC ) - { - throw Exception(id, strfmt("not a function declaration: %s", id->Name())); - } + if ( decl->decl_type() != Decl::FUNC ) { + throw Exception(id, strfmt("not a function declaration: %s", id->Name())); + } - FuncDecl* func_decl = static_cast(decl); - ASSERT(func_decl); + FuncDecl* func_decl = static_cast(decl); + ASSERT(func_decl); - Expr* expr = func_decl->function()->expr(); - if ( ! expr || expr->expr_type() != Expr::EXPR_CASE ) - { - throw Exception(id, strfmt("function not defined by a case expression: %s", id->Name())); - } + Expr* expr = func_decl->function()->expr(); + if ( ! expr || expr->expr_type() != Expr::EXPR_CASE ) { + throw Exception(id, strfmt("function not defined by a case expression: %s", id->Name())); + } - foreach (i, CaseExprList, caseexprlist) - { - CaseExpr* e = *i; - expr->AddCaseExpr(e); - } + foreach (i, CaseExprList, caseexprlist) { + CaseExpr* e = *i; + expr->AddCaseExpr(e); + } - return decl; - } + return decl; +} -Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerElementList* elements) - { - Decl* decl = find_decl(id); +Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerElementList* elements) { + Decl* decl = find_decl(id); - if ( decl->decl_type() != decl_type ) - { - throw Exception(id, strfmt("not a connection/flow declaration: %s", id->Name())); - } + if ( decl->decl_type() != decl_type ) { + throw Exception(id, strfmt("not a connection/flow declaration: %s", id->Name())); + } - AnalyzerDecl* analyzer_decl = static_cast(decl); - ASSERT(analyzer_decl); + AnalyzerDecl* analyzer_decl = static_cast(decl); + ASSERT(analyzer_decl); - analyzer_decl->AddElements(elements); + analyzer_decl->AddElements(elements); - return decl; - } + return decl; +} -Decl* ProcessTypeAttrRedef(const ID* id, AttrList* attrlist) - { - Decl* decl = find_decl(id); +Decl* ProcessTypeAttrRedef(const ID* id, AttrList* attrlist) { + Decl* decl = find_decl(id); - if ( decl->decl_type() != Decl::TYPE ) - { - throw Exception(id, strfmt("not a type declaration: %s", id->Name())); - } + if ( decl->decl_type() != Decl::TYPE ) { + throw Exception(id, strfmt("not a type declaration: %s", id->Name())); + } - TypeDecl* type_decl = static_cast(decl); - ASSERT(type_decl); + TypeDecl* type_decl = static_cast(decl); + ASSERT(type_decl); - type_decl->AddAttrs(attrlist); + type_decl->AddAttrs(attrlist); - return decl; - } + return decl; +} diff --git a/tools/binpac/src/pac_regex.cc b/tools/binpac/src/pac_regex.cc index 42718ade3d..fc7c48469f 100644 --- a/tools/binpac/src/pac_regex.cc +++ b/tools/binpac/src/pac_regex.cc @@ -9,71 +9,55 @@ const char* RegEx::kREMatcherType = "RegExMatcher"; const char* RegEx::kMatchPrefix = "MatchPrefix"; -string escape_char(const string& s) - { - char* buf = new char[s.length() * 2 + 1]; - int j = 0; - for ( int i = 0; i < (int)s.length(); ++i ) - { - if ( s[i] == '\\' ) - { - if ( i + 1 < (int)s.length() ) - { - buf[j++] = '\\'; - if ( s[i + 1] == '/' ) - buf[j - 1] = s[++i]; - else if ( s[i + 1] == '/' || s[i + 1] == '\\' || s[i + 1] == '"' ) - buf[j++] = s[++i]; - else - buf[j++] = '\\'; - } - } - else if ( s[i] == '"' ) - { - buf[j++] = '\\'; - buf[j++] = '"'; - } - else - { - buf[j++] = s[i]; - } - } +string escape_char(const string& s) { + char* buf = new char[s.length() * 2 + 1]; + int j = 0; + for ( int i = 0; i < (int)s.length(); ++i ) { + if ( s[i] == '\\' ) { + if ( i + 1 < (int)s.length() ) { + buf[j++] = '\\'; + if ( s[i + 1] == '/' ) + buf[j - 1] = s[++i]; + else if ( s[i + 1] == '/' || s[i + 1] == '\\' || s[i + 1] == '"' ) + buf[j++] = s[++i]; + else + buf[j++] = '\\'; + } + } + else if ( s[i] == '"' ) { + buf[j++] = '\\'; + buf[j++] = '"'; + } + else { + buf[j++] = s[i]; + } + } - buf[j++] = '\0'; + buf[j++] = '\0'; - string rval = buf; - delete[] buf; - return rval; - } + string rval = buf; + delete[] buf; + return rval; +} -RegEx::RegEx(const string& s) - { - str_ = escape_char(s); - string prefix = strfmt("%s_re_", current_decl_id->Name()); - matcher_id_ = ID::NewAnonymousID(prefix); - decl_ = new RegExDecl(this); - } +RegEx::RegEx(const string& s) { + str_ = escape_char(s); + string prefix = strfmt("%s_re_", current_decl_id->Name()); + matcher_id_ = ID::NewAnonymousID(prefix); + decl_ = new RegExDecl(this); +} -RegEx::~RegEx() { } +RegEx::~RegEx() {} -RegExDecl::RegExDecl(RegEx* regex) : Decl(regex->matcher_id(), REGEX) - { - regex_ = regex; - } +RegExDecl::RegExDecl(RegEx* regex) : Decl(regex->matcher_id(), REGEX) { regex_ = regex; } -void RegExDecl::Prepare() - { - global_env()->AddID(id(), GLOBAL_VAR, extern_type_re_matcher); - } +void RegExDecl::Prepare() { global_env()->AddID(id(), GLOBAL_VAR, extern_type_re_matcher); } -void RegExDecl::GenForwardDeclaration(Output* out_h) - { - out_h->println("extern %s %s;\n", RegEx::kREMatcherType, - global_env()->LValue(regex_->matcher_id())); - } +void RegExDecl::GenForwardDeclaration(Output* out_h) { + out_h->println("extern %s %s;\n", RegEx::kREMatcherType, global_env()->LValue(regex_->matcher_id())); +} -void RegExDecl::GenCode(Output* out_h, Output* out_cc) - { - out_cc->println("%s %s(\"%s\");\n", RegEx::kREMatcherType, - global_env()->LValue(regex_->matcher_id()), regex_->str().c_str()); - } +void RegExDecl::GenCode(Output* out_h, Output* out_cc) { + out_cc->println("%s %s(\"%s\");\n", RegEx::kREMatcherType, global_env()->LValue(regex_->matcher_id()), + regex_->str().c_str()); +} diff --git a/tools/binpac/src/pac_regex.h b/tools/binpac/src/pac_regex.h index 2cf48cf2c2..93487b8da8 100644 --- a/tools/binpac/src/pac_regex.h +++ b/tools/binpac/src/pac_regex.h @@ -6,36 +6,34 @@ class RegExDecl; -class RegEx : public Object - { +class RegEx : public Object { public: - RegEx(const string& str); - ~RegEx(); + RegEx(const string& str); + ~RegEx(); - const string& str() const { return str_; } - ID* matcher_id() const { return matcher_id_; } + const string& str() const { return str_; } + ID* matcher_id() const { return matcher_id_; } private: - string str_; - ID* matcher_id_; - RegExDecl* decl_; + string str_; + ID* matcher_id_; + RegExDecl* decl_; public: - static const char* kREMatcherType; - static const char* kMatchPrefix; - }; + static const char* kREMatcherType; + static const char* kMatchPrefix; +}; -class RegExDecl : public Decl - { +class RegExDecl : public Decl { public: - RegExDecl(RegEx* regex); + RegExDecl(RegEx* regex); - void Prepare() override; - void GenForwardDeclaration(Output* out_h) override; - void GenCode(Output* out_h, Output* out_cc) override; + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; private: - RegEx* regex_; - }; + RegEx* regex_; +}; #endif // pac_regex_h diff --git a/tools/binpac/src/pac_state.cc b/tools/binpac/src/pac_state.cc index 3164c48434..03aba62610 100644 --- a/tools/binpac/src/pac_state.cc +++ b/tools/binpac/src/pac_state.cc @@ -4,23 +4,20 @@ #include "pac_output.h" #include "pac_type.h" -void StateVar::GenDecl(Output* out_h, Env* env) - { - out_h->println("%s %s;", type_->DataTypeStr().c_str(), env->LValue(id_)); - } +void StateVar::GenDecl(Output* out_h, Env* env) { + out_h->println("%s %s;", type_->DataTypeStr().c_str(), env->LValue(id_)); +} -void StateVar::GenAccessFunction(Output* out_h, Env* env) - { - out_h->println("%s %s const { return %s; }", type_->DataTypeConstRefStr().c_str(), - env->RValue(id_), env->LValue(id_)); - } +void StateVar::GenAccessFunction(Output* out_h, Env* env) { + out_h->println("%s %s const { return %s; }", type_->DataTypeConstRefStr().c_str(), env->RValue(id_), + env->LValue(id_)); +} -void StateVar::GenSetFunction(Output* out_h, Env* env) - { - out_h->println("void %s(%s x) { %s = x; }", set_function(id_).c_str(), - type_->DataTypeConstRefStr().c_str(), env->LValue(id_)); - } +void StateVar::GenSetFunction(Output* out_h, Env* env) { + out_h->println("void %s(%s x) { %s = x; }", set_function(id_).c_str(), type_->DataTypeConstRefStr().c_str(), + env->LValue(id_)); +} -void StateVar::GenInitCode(Output* out_cc, Env* env) { } +void StateVar::GenInitCode(Output* out_cc, Env* env) {} -void StateVar::GenCleanUpCode(Output* out_cc, Env* env) { } +void StateVar::GenCleanUpCode(Output* out_cc, Env* env) {} diff --git a/tools/binpac/src/pac_state.h b/tools/binpac/src/pac_state.h index b9ac972f32..d54219d3da 100644 --- a/tools/binpac/src/pac_state.h +++ b/tools/binpac/src/pac_state.h @@ -5,23 +5,22 @@ #include "pac_common.h" -class StateVar - { +class StateVar { public: - StateVar(ID* id, Type* type) : id_(id), type_(type) { } + StateVar(ID* id, Type* type) : id_(id), type_(type) {} - const ID* id() const { return id_; } - Type* type() const { return type_; } + const ID* id() const { return id_; } + Type* type() const { return type_; } - void GenDecl(Output* out_h, Env* env); - void GenAccessFunction(Output* out_h, Env* env); - void GenSetFunction(Output* out_h, Env* env); - void GenInitCode(Output* out_cc, Env* env); - void GenCleanUpCode(Output* out_cc, Env* env); + void GenDecl(Output* out_h, Env* env); + void GenAccessFunction(Output* out_h, Env* env); + void GenSetFunction(Output* out_h, Env* env); + void GenInitCode(Output* out_cc, Env* env); + void GenCleanUpCode(Output* out_cc, Env* env); private: - ID* id_; - Type* type_; - }; + ID* id_; + Type* type_; +}; #endif // pac_state_h diff --git a/tools/binpac/src/pac_strtype.cc b/tools/binpac/src/pac_strtype.cc index 6fa64bf31b..99fe7b3199 100644 --- a/tools/binpac/src/pac_strtype.cc +++ b/tools/binpac/src/pac_strtype.cc @@ -15,388 +15,293 @@ const char* StringType::kStringTypeName = "bytestring"; const char* StringType::kConstStringTypeName = "const_bytestring"; -StringType::StringType(StringTypeEnum anystr) - : Type(STRING), type_(ANYSTR), str_(nullptr), regex_(nullptr) - { - ASSERT(anystr == ANYSTR); - init(); - } +StringType::StringType(StringTypeEnum anystr) : Type(STRING), type_(ANYSTR), str_(nullptr), regex_(nullptr) { + ASSERT(anystr == ANYSTR); + init(); +} -StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(nullptr) - { - init(); - } +StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(nullptr) { init(); } -StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(nullptr), regex_(regex) - { - ASSERT(regex_); - init(); - } +StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(nullptr), regex_(regex) { + ASSERT(regex_); + init(); +} -void StringType::init() - { - string_length_var_field_ = nullptr; - elem_datatype_ = new BuiltInType(BuiltInType::UINT8); - } +void StringType::init() { + string_length_var_field_ = nullptr; + elem_datatype_ = new BuiltInType(BuiltInType::UINT8); +} -StringType::~StringType() - { - // TODO: Unref for Objects - // Question: why Unref? - // - // Unref(str_); - // Unref(regex_); +StringType::~StringType() { + // TODO: Unref for Objects + // Question: why Unref? + // + // Unref(str_); + // Unref(regex_); - delete string_length_var_field_; - delete elem_datatype_; - } + delete string_length_var_field_; + delete elem_datatype_; +} -Type* StringType::DoClone() const - { - StringType* clone; +Type* StringType::DoClone() const { + StringType* clone; - switch ( type_ ) - { - case ANYSTR: - clone = new StringType(ANYSTR); - break; - case CSTR: - clone = new StringType(str_); - break; - case REGEX: - clone = new StringType(regex_); - break; - default: - ASSERT(0); - return nullptr; - } + switch ( type_ ) { + case ANYSTR: clone = new StringType(ANYSTR); break; + case CSTR: clone = new StringType(str_); break; + case REGEX: clone = new StringType(regex_); break; + default: ASSERT(0); return nullptr; + } - return clone; - } + return clone; +} -bool StringType::DefineValueVar() const - { - return true; - } +bool StringType::DefineValueVar() const { return true; } -string StringType::DataTypeStr() const - { - return strfmt("%s", persistent() ? kStringTypeName : kConstStringTypeName); - } +string StringType::DataTypeStr() const { return strfmt("%s", persistent() ? kStringTypeName : kConstStringTypeName); } -Type* StringType::ElementDataType() const - { - return elem_datatype_; - } +Type* StringType::ElementDataType() const { return elem_datatype_; } -void StringType::ProcessAttr(Attr* a) - { - Type::ProcessAttr(a); +void StringType::ProcessAttr(Attr* a) { + Type::ProcessAttr(a); - switch ( a->type() ) - { - case ATTR_CHUNKED: - { - if ( type_ != ANYSTR ) - { - throw Exception(a, "&chunked can be applied" - " to only type bytestring"); - } - attr_chunked_ = true; - SetBoundaryChecked(); - } - break; + switch ( a->type() ) { + case ATTR_CHUNKED: { + if ( type_ != ANYSTR ) { + throw Exception(a, + "&chunked can be applied" + " to only type bytestring"); + } + attr_chunked_ = true; + SetBoundaryChecked(); + } break; - case ATTR_RESTOFDATA: - { - if ( type_ != ANYSTR ) - { - throw Exception(a, "&restofdata can be applied" - " to only type bytestring"); - } - attr_restofdata_ = true; - // As the string automatically extends to the end of - // data, we do not have to check boundary. - SetBoundaryChecked(); - } - break; + case ATTR_RESTOFDATA: { + if ( type_ != ANYSTR ) { + throw Exception(a, + "&restofdata can be applied" + " to only type bytestring"); + } + attr_restofdata_ = true; + // As the string automatically extends to the end of + // data, we do not have to check boundary. + SetBoundaryChecked(); + } break; - case ATTR_RESTOFFLOW: - { - if ( type_ != ANYSTR ) - { - throw Exception(a, "&restofflow can be applied" - " to only type bytestring"); - } - attr_restofflow_ = true; - // As the string automatically extends to the end of - // flow, we do not have to check boundary. - SetBoundaryChecked(); - } - break; + case ATTR_RESTOFFLOW: { + if ( type_ != ANYSTR ) { + throw Exception(a, + "&restofflow can be applied" + " to only type bytestring"); + } + attr_restofflow_ = true; + // As the string automatically extends to the end of + // flow, we do not have to check boundary. + SetBoundaryChecked(); + } break; - default: - break; - } - } + default: break; + } +} -void StringType::Prepare(Env* env, int flags) - { - if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 ) - { - ID* string_length_var = new ID( - strfmt("%s_string_length", value_var() ? value_var()->Name() : "val")); - string_length_var_field_ = new TempVarField(string_length_var, extern_type_int->Clone()); - string_length_var_field_->Prepare(env); - } - Type::Prepare(env, flags); - } +void StringType::Prepare(Env* env, int flags) { + if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 ) { + ID* string_length_var = new ID(strfmt("%s_string_length", value_var() ? value_var()->Name() : "val")); + string_length_var_field_ = new TempVarField(string_length_var, extern_type_int->Clone()); + string_length_var_field_->Prepare(env); + } + Type::Prepare(env, flags); +} -void StringType::GenPubDecls(Output* out_h, Env* env) - { - Type::GenPubDecls(out_h, env); - } +void StringType::GenPubDecls(Output* out_h, Env* env) { Type::GenPubDecls(out_h, env); } -void StringType::GenPrivDecls(Output* out_h, Env* env) - { - Type::GenPrivDecls(out_h, env); - } +void StringType::GenPrivDecls(Output* out_h, Env* env) { Type::GenPrivDecls(out_h, env); } -void StringType::GenInitCode(Output* out_cc, Env* env) - { - Type::GenInitCode(out_cc, env); - } +void StringType::GenInitCode(Output* out_cc, Env* env) { Type::GenInitCode(out_cc, env); } -void StringType::GenCleanUpCode(Output* out_cc, Env* env) - { - Type::GenCleanUpCode(out_cc, env); - if ( persistent() ) - out_cc->println("%s.free();", env->LValue(value_var())); - } +void StringType::GenCleanUpCode(Output* out_cc, Env* env) { + Type::GenCleanUpCode(out_cc, env); + if ( persistent() ) + out_cc->println("%s.free();", env->LValue(value_var())); +} -void StringType::DoMarkIncrementalInput() - { - if ( attr_restofflow_ ) - { - // Do nothing - ASSERT(type_ == ANYSTR); - } - else - { - Type::DoMarkIncrementalInput(); - } - } +void StringType::DoMarkIncrementalInput() { + if ( attr_restofflow_ ) { + // Do nothing + ASSERT(type_ == ANYSTR); + } + else { + Type::DoMarkIncrementalInput(); + } +} -int StringType::StaticSize(Env* env) const - { - switch ( type_ ) - { - case CSTR: - // Use length of the unescaped string - return str_->unescaped().length(); - case REGEX: - // TODO: static size for a regular expression? - case ANYSTR: - return -1; +int StringType::StaticSize(Env* env) const { + switch ( type_ ) { + case CSTR: + // Use length of the unescaped string + return str_->unescaped().length(); + case REGEX: + // TODO: static size for a regular expression? + case ANYSTR: return -1; - default: - ASSERT(0); - return -1; - } - } + default: ASSERT(0); return -1; + } +} -const ID* StringType::string_length_var() const - { - return string_length_var_field_ ? string_length_var_field_->id() : nullptr; - } +const ID* StringType::string_length_var() const { + return string_length_var_field_ ? string_length_var_field_->id() : nullptr; +} -void StringType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) - { - ASSERT(StaticSize(env) < 0); - DEBUG_MSG("Generating dynamic size for string `%s'\n", value_var()->Name()); +void StringType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { + ASSERT(StaticSize(env) < 0); + DEBUG_MSG("Generating dynamic size for string `%s'\n", value_var()->Name()); - if ( env->Evaluated(string_length_var()) ) - return; + if ( env->Evaluated(string_length_var()) ) + return; - string_length_var_field_->GenTempDecls(out_cc, env); + string_length_var_field_->GenTempDecls(out_cc, env); - switch ( type_ ) - { - case ANYSTR: - GenDynamicSizeAnyStr(out_cc, env, data); - break; - case CSTR: - ASSERT(0); - break; - case REGEX: - // TODO: static size for a regular expression? - GenDynamicSizeRegEx(out_cc, env, data); - break; - } + switch ( type_ ) { + case ANYSTR: GenDynamicSizeAnyStr(out_cc, env, data); break; + case CSTR: ASSERT(0); break; + case REGEX: + // TODO: static size for a regular expression? + GenDynamicSizeRegEx(out_cc, env, data); + break; + } - if ( ! incremental_input() && AddSizeVar(out_cc, env) ) - { - out_cc->println("%s = %s;", env->LValue(size_var()), env->RValue(string_length_var())); - env->SetEvaluated(size_var()); - } - } + if ( ! incremental_input() && AddSizeVar(out_cc, env) ) { + out_cc->println("%s = %s;", env->LValue(size_var()), env->RValue(string_length_var())); + env->SetEvaluated(size_var()); + } +} -string StringType::GenStringSize(Output* out_cc, Env* env, const DataPtr& data) - { - int static_size = StaticSize(env); - if ( static_size >= 0 ) - return strfmt("%d", static_size); - GenDynamicSize(out_cc, env, data); - return env->RValue(string_length_var()); - } +string StringType::GenStringSize(Output* out_cc, Env* env, const DataPtr& data) { + int static_size = StaticSize(env); + if ( static_size >= 0 ) + return strfmt("%d", static_size); + GenDynamicSize(out_cc, env, data); + return env->RValue(string_length_var()); +} -void StringType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) - { - string str_size = GenStringSize(out_cc, env, data); +void StringType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { + string str_size = GenStringSize(out_cc, env, data); - // Generate additional checking - switch ( type_ ) - { - case CSTR: - GenCheckingCStr(out_cc, env, data, str_size); - break; - case REGEX: - case ANYSTR: - break; - } + // Generate additional checking + switch ( type_ ) { + case CSTR: GenCheckingCStr(out_cc, env, data, str_size); break; + case REGEX: + case ANYSTR: break; + } - if ( ! anonymous_value_var() ) - { - // Set the value variable + if ( ! anonymous_value_var() ) { + // Set the value variable - int len; + int len; - if ( type_ == ANYSTR && attr_length_expr_ && attr_length_expr_->ConstFold(env, &len) ) - { - // can check for a negative length now - if ( len < 0 ) - throw Exception(this, "negative &length on string"); - } - else - { - out_cc->println("// check for negative sizes"); - out_cc->println("if ( %s < 0 )", str_size.c_str()); - out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), - str_size.c_str()); - } + if ( type_ == ANYSTR && attr_length_expr_ && attr_length_expr_->ConstFold(env, &len) ) { + // can check for a negative length now + if ( len < 0 ) + throw Exception(this, "negative &length on string"); + } + else { + out_cc->println("// check for negative sizes"); + out_cc->println("if ( %s < 0 )", str_size.c_str()); + out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), str_size.c_str()); + } - out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), data.ptr_expr(), - str_size.c_str()); - } + out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), data.ptr_expr(), str_size.c_str()); + } - if ( parsing_complete_var() ) - { - out_cc->println("%s = true;", env->LValue(parsing_complete_var())); - } - } + if ( parsing_complete_var() ) { + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); + } +} -void StringType::GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern) - { - string tmp = strfmt("string((const char *) (%s), (const char *) %s).c_str()", data.ptr_expr(), - env->RValue(end_of_data)); - out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", Location(), - pattern.c_str(), tmp.c_str()); - } +void StringType::GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern) { + string tmp = + strfmt("string((const char *) (%s), (const char *) %s).c_str()", data.ptr_expr(), env->RValue(end_of_data)); + out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", Location(), pattern.c_str(), tmp.c_str()); +} -void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data, - const string& str_size) - { - // TODO: extend it for dynamic strings - ASSERT(type_ == CSTR); +void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data, const string& str_size) { + // TODO: extend it for dynamic strings + ASSERT(type_ == CSTR); - GenBoundaryCheck(out_cc, env, data); + GenBoundaryCheck(out_cc, env, data); - string str_val = str_->str(); + string str_val = str_->str(); - // Compare the string and report error on mismatch - out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", data.ptr_expr(), str_val.c_str(), - str_size.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); - GenStringMismatch(out_cc, env, data, str_val); - out_cc->println("}"); - out_cc->dec_indent(); - } + // Compare the string and report error on mismatch + out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", data.ptr_expr(), str_val.c_str(), str_size.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + GenStringMismatch(out_cc, env, data, str_val); + out_cc->println("}"); + out_cc->dec_indent(); +} -void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data) - { - // string_length_var = - // matcher.match_prefix( - // begin, - // end); +void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data) { + // string_length_var = + // matcher.match_prefix( + // begin, + // end); - out_cc->println("%s = ", env->LValue(string_length_var())); - out_cc->inc_indent(); + out_cc->println("%s = ", env->LValue(string_length_var())); + out_cc->inc_indent(); - out_cc->println("%s.%s(", env->RValue(regex_->matcher_id()), RegEx::kMatchPrefix); + out_cc->println("%s.%s(", env->RValue(regex_->matcher_id()), RegEx::kMatchPrefix); - out_cc->inc_indent(); - out_cc->println("%s,", data.ptr_expr()); - out_cc->println("%s - %s);", env->RValue(end_of_data), data.ptr_expr()); + out_cc->inc_indent(); + out_cc->println("%s,", data.ptr_expr()); + out_cc->println("%s - %s);", env->RValue(end_of_data), data.ptr_expr()); - out_cc->dec_indent(); - out_cc->dec_indent(); + out_cc->dec_indent(); + out_cc->dec_indent(); - env->SetEvaluated(string_length_var()); + env->SetEvaluated(string_length_var()); - out_cc->println("if ( %s < 0 )", env->RValue(string_length_var())); - out_cc->inc_indent(); - out_cc->println("{"); - string tmp = strfmt("\"%s\"", regex_->str().c_str()); - GenStringMismatch(out_cc, env, data, tmp); - out_cc->println("}"); - out_cc->dec_indent(); - } + out_cc->println("if ( %s < 0 )", env->RValue(string_length_var())); + out_cc->inc_indent(); + out_cc->println("{"); + string tmp = strfmt("\"%s\"", regex_->str().c_str()); + GenStringMismatch(out_cc, env, data, tmp); + out_cc->println("}"); + out_cc->dec_indent(); +} -void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data) - { - ASSERT(type_ == ANYSTR); +void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data) { + ASSERT(type_ == ANYSTR); - if ( attr_restofdata_ || attr_oneline_ ) - { - out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), - env->RValue(end_of_data), data.ptr_expr()); - } - else if ( attr_restofflow_ ) - { - out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), - env->RValue(end_of_data), data.ptr_expr()); - } - else if ( attr_length_expr_ ) - { - out_cc->println("%s = %s;", env->LValue(string_length_var()), - attr_length_expr_->EvalExpr(out_cc, env)); - } - else - { - throw Exception(this, "cannot determine length of bytestring"); - } + if ( attr_restofdata_ || attr_oneline_ ) { + out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), env->RValue(end_of_data), + data.ptr_expr()); + } + else if ( attr_restofflow_ ) { + out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), env->RValue(end_of_data), + data.ptr_expr()); + } + else if ( attr_length_expr_ ) { + out_cc->println("%s = %s;", env->LValue(string_length_var()), attr_length_expr_->EvalExpr(out_cc, env)); + } + else { + throw Exception(this, "cannot determine length of bytestring"); + } - env->SetEvaluated(string_length_var()); - } + env->SetEvaluated(string_length_var()); +} -bool StringType::DoTraverse(DataDepVisitor* visitor) - { - if ( ! Type::DoTraverse(visitor) ) - return false; +bool StringType::DoTraverse(DataDepVisitor* visitor) { + if ( ! Type::DoTraverse(visitor) ) + return false; - switch ( type_ ) - { - case ANYSTR: - case CSTR: - case REGEX: - break; - } + switch ( type_ ) { + case ANYSTR: + case CSTR: + case REGEX: break; + } - return true; - } + return true; +} -void StringType::static_init() - { - Type::AddPredefinedType("bytestring", new StringType(ANYSTR)); - } +void StringType::static_init() { Type::AddPredefinedType("bytestring", new StringType(ANYSTR)); } diff --git a/tools/binpac/src/pac_strtype.h b/tools/binpac/src/pac_strtype.h index f4acdc087e..ce087d1756 100644 --- a/tools/binpac/src/pac_strtype.h +++ b/tools/binpac/src/pac_strtype.h @@ -4,83 +4,77 @@ #include "pac_type.h" // TODO: question: shall we merge it with ArrayType? -class StringType : public Type - { +class StringType : public Type { public: - enum StringTypeEnum - { - CSTR, - REGEX, - ANYSTR - }; + enum StringTypeEnum { CSTR, REGEX, ANYSTR }; - explicit StringType(StringTypeEnum anystr); - explicit StringType(ConstString* str); - explicit StringType(RegEx* regex); - ~StringType() override; + explicit StringType(StringTypeEnum anystr); + explicit StringType(ConstString* str); + explicit StringType(RegEx* regex); + ~StringType() override; - bool DefineValueVar() const override; - string DataTypeStr() const override; - string DefaultValue() const override { return "0"; } - Type* ElementDataType() const override; + bool DefineValueVar() const override; + string DataTypeStr() const override; + string DefaultValue() const override { return "0"; } + Type* ElementDataType() const override; - void Prepare(Env* env, int flags) override; + void Prepare(Env* env, int flags) override; - void GenPubDecls(Output* out, Env* env) override; - void GenPrivDecls(Output* out, Env* env) override; + void GenPubDecls(Output* out, Env* env) override; + void GenPrivDecls(Output* out, Env* env) override; - void GenInitCode(Output* out, Env* env) override; - void GenCleanUpCode(Output* out, Env* env) override; + void GenInitCode(Output* out, Env* env) override; + void GenCleanUpCode(Output* out, Env* env) override; - void DoMarkIncrementalInput() override; + void DoMarkIncrementalInput() override; - int StaticSize(Env* env) const override; + int StaticSize(Env* env) const override; - bool IsPointerType() const override { return false; } + bool IsPointerType() const override { return false; } - void ProcessAttr(Attr* a) override; + void ProcessAttr(Attr* a) override; protected: - void init(); + void init(); - // Generate computation of size of the string and returns the string - // representing a constant integer or name of the length variable. - string GenStringSize(Output* out_cc, Env* env, const DataPtr& data); + // Generate computation of size of the string and returns the string + // representing a constant integer or name of the length variable. + string GenStringSize(Output* out_cc, Env* env, const DataPtr& data); - // Generate a string mismatch exception - void GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern); + // Generate a string mismatch exception + void GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern); - void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; + void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override; - void GenCheckingCStr(Output* out, Env* env, const DataPtr& data, const string& str_size); + void GenCheckingCStr(Output* out, Env* env, const DataPtr& data, const string& str_size); - void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; - void GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data); - void GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data); + void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override; + void GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data); + void GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data); - Type* DoClone() const override; + Type* DoClone() const override; - // TODO: insensitive towards byte order till we support unicode - bool ByteOrderSensitive() const override { return false; } + // TODO: insensitive towards byte order till we support unicode + bool ByteOrderSensitive() const override { return false; } protected: - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; private: - const ID* string_length_var() const; + const ID* string_length_var() const; - StringTypeEnum type_; - ConstString* str_; - RegEx* regex_; - Field* string_length_var_field_; - Type* elem_datatype_; + StringTypeEnum type_; + ConstString* str_; + RegEx* regex_; + Field* string_length_var_field_; + Type* elem_datatype_; public: - static void static_init(); + static void static_init(); private: - static const char* kStringTypeName; - static const char* kConstStringTypeName; - }; + static const char* kStringTypeName; + static const char* kConstStringTypeName; +}; #endif // pac_strtype_h diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index f6a9085857..b507777efa 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -22,1094 +22,903 @@ Type::type_map_t Type::type_map_; -Type::Type(TypeType tot) : DataDepElement(DataDepElement::TYPE), tot_(tot) - { - type_decl_ = nullptr; - type_decl_id_ = current_decl_id; - declared_as_type_ = false; - env_ = nullptr; - value_var_ = default_value_var; - ASSERT(value_var_); - value_var_type_ = MEMBER_VAR; - anonymous_value_var_ = false; - size_var_field_ = nullptr; - size_expr_ = nullptr; - boundary_checked_ = false; - parsing_complete_var_field_ = nullptr; - parsing_state_var_field_ = nullptr; - buffering_state_var_field_ = nullptr; - has_value_field_ = nullptr; +Type::Type(TypeType tot) : DataDepElement(DataDepElement::TYPE), tot_(tot) { + type_decl_ = nullptr; + type_decl_id_ = current_decl_id; + declared_as_type_ = false; + env_ = nullptr; + value_var_ = default_value_var; + ASSERT(value_var_); + value_var_type_ = MEMBER_VAR; + anonymous_value_var_ = false; + size_var_field_ = nullptr; + size_expr_ = nullptr; + boundary_checked_ = false; + parsing_complete_var_field_ = nullptr; + parsing_state_var_field_ = nullptr; + buffering_state_var_field_ = nullptr; + has_value_field_ = nullptr; - array_until_input_ = nullptr; + array_until_input_ = nullptr; - incremental_input_ = false; - buffer_input_ = false; - incremental_parsing_ = false; + incremental_input_ = false; + buffer_input_ = false; + incremental_parsing_ = false; - fields_ = new FieldList(); + fields_ = new FieldList(); - attrs_ = new AttrList(); - attr_byteorder_expr_ = nullptr; - attr_checks_ = new ExprList(); - attr_enforces_ = new ExprList(); - attr_chunked_ = false; - attr_exportsourcedata_ = false; - attr_if_expr_ = nullptr; - attr_length_expr_ = nullptr; - attr_letfields_ = nullptr; - attr_multiline_end_ = nullptr; - attr_linebreaker_ = nullptr; - attr_oneline_ = false; - attr_refcount_ = false; - attr_requires_ = new ExprList(); - attr_restofdata_ = false; - attr_restofflow_ = false; - attr_transient_ = false; - } + attrs_ = new AttrList(); + attr_byteorder_expr_ = nullptr; + attr_checks_ = new ExprList(); + attr_enforces_ = new ExprList(); + attr_chunked_ = false; + attr_exportsourcedata_ = false; + attr_if_expr_ = nullptr; + attr_length_expr_ = nullptr; + attr_letfields_ = nullptr; + attr_multiline_end_ = nullptr; + attr_linebreaker_ = nullptr; + attr_oneline_ = false; + attr_refcount_ = false; + attr_requires_ = new ExprList(); + attr_restofdata_ = false; + attr_restofflow_ = false; + attr_transient_ = false; +} -Type::~Type() - { - delete size_var_field_; - delete parsing_complete_var_field_; - delete parsing_state_var_field_; - delete buffering_state_var_field_; - delete has_value_field_; - delete[] size_expr_; - delete_list(FieldList, fields_); - delete attrs_; - delete attr_byteorder_expr_; - delete attr_if_expr_; - delete attr_length_expr_; - delete_list(ExprList, attr_checks_); - delete_list(ExprList, attr_enforces_); - delete_list(ExprList, attr_requires_); - } +Type::~Type() { + delete size_var_field_; + delete parsing_complete_var_field_; + delete parsing_state_var_field_; + delete buffering_state_var_field_; + delete has_value_field_; + delete[] size_expr_; + delete_list(FieldList, fields_); + delete attrs_; + delete attr_byteorder_expr_; + delete attr_if_expr_; + delete attr_length_expr_; + delete_list(ExprList, attr_checks_); + delete_list(ExprList, attr_enforces_); + delete_list(ExprList, attr_requires_); +} -Type* Type::Clone() const - { - Type* clone = DoClone(); - if ( clone ) - { - foreach (i, FieldList, fields_) - { - Field* f = *i; - clone->AddField(f); - } +Type* Type::Clone() const { + Type* clone = DoClone(); + if ( clone ) { + foreach (i, FieldList, fields_) { + Field* f = *i; + clone->AddField(f); + } - foreach (i, AttrList, attrs_) - { - Attr* a = *i; - clone->ProcessAttr(a); - } - } - return clone; - } + foreach (i, AttrList, attrs_) { + Attr* a = *i; + clone->ProcessAttr(a); + } + } + return clone; +} -string Type::EvalMember(const ID* member_id) const - { - ASSERT(0); - return "@@@"; - } +string Type::EvalMember(const ID* member_id) const { + ASSERT(0); + return "@@@"; +} -string Type::EvalElement(const string& array, const string& index) const - { - return strfmt("%s[%s]", array.c_str(), index.c_str()); - } +string Type::EvalElement(const string& array, const string& index) const { + return strfmt("%s[%s]", array.c_str(), index.c_str()); +} -const ID* Type::decl_id() const - { - return type_decl_id_; - } +const ID* Type::decl_id() const { return type_decl_id_; } -void Type::set_type_decl(const TypeDecl* decl, bool declared_as_type) - { - type_decl_ = decl; - type_decl_id_ = decl->id(); - declared_as_type_ = declared_as_type; - } +void Type::set_type_decl(const TypeDecl* decl, bool declared_as_type) { + type_decl_ = decl; + type_decl_id_ = decl->id(); + declared_as_type_ = declared_as_type; +} -void Type::set_value_var(const ID* arg_id, int arg_id_type) - { - value_var_ = arg_id; - value_var_type_ = arg_id_type; +void Type::set_value_var(const ID* arg_id, int arg_id_type) { + value_var_ = arg_id; + value_var_type_ = arg_id_type; - if ( value_var_ ) - anonymous_value_var_ = value_var_->is_anonymous(); - } + if ( value_var_ ) + anonymous_value_var_ = value_var_->is_anonymous(); +} -const ID* Type::size_var() const - { - return size_var_field_ ? size_var_field_->id() : nullptr; - } +const ID* Type::size_var() const { return size_var_field_ ? size_var_field_->id() : nullptr; } -void Type::AddField(Field* f) - { - ASSERT(f); - fields_->push_back(f); - } +void Type::AddField(Field* f) { + ASSERT(f); + fields_->push_back(f); +} -void Type::ProcessAttr(Attr* a) - { - switch ( a->type() ) - { - case ATTR_BYTEORDER: - attr_byteorder_expr_ = a->expr(); - break; +void Type::ProcessAttr(Attr* a) { + switch ( a->type() ) { + case ATTR_BYTEORDER: attr_byteorder_expr_ = a->expr(); break; - case ATTR_CHECK: - attr_checks_->push_back(a->expr()); - break; + case ATTR_CHECK: attr_checks_->push_back(a->expr()); break; - case ATTR_ENFORCE: - attr_enforces_->push_back(a->expr()); - break; + case ATTR_ENFORCE: attr_enforces_->push_back(a->expr()); break; - case ATTR_EXPORTSOURCEDATA: - attr_exportsourcedata_ = true; - break; + case ATTR_EXPORTSOURCEDATA: attr_exportsourcedata_ = true; break; - case ATTR_LENGTH: - attr_length_expr_ = a->expr(); - break; + case ATTR_LENGTH: attr_length_expr_ = a->expr(); break; - case ATTR_IF: - attr_if_expr_ = a->expr(); - break; + case ATTR_IF: attr_if_expr_ = a->expr(); break; - case ATTR_LET: - { - LetAttr* letattr = static_cast(a); - if ( ! attr_letfields_ ) - attr_letfields_ = letattr->letfields(); - else - { - // Append to attr_letfields_ - attr_letfields_->insert(attr_letfields_->end(), letattr->letfields()->begin(), - letattr->letfields()->end()); - } - } - break; + case ATTR_LET: { + LetAttr* letattr = static_cast(a); + if ( ! attr_letfields_ ) + attr_letfields_ = letattr->letfields(); + else { + // Append to attr_letfields_ + attr_letfields_->insert(attr_letfields_->end(), letattr->letfields()->begin(), + letattr->letfields()->end()); + } + } break; - case ATTR_LINEBREAKER: - if ( strlen(a->expr()->orig()) != 6 ) - throw Exception(this, "invalid line breaker length, must be a single ASCII " - "character. (Ex: \"\\001\".)"); - attr_linebreaker_ = a->expr(); - break; + case ATTR_LINEBREAKER: + if ( strlen(a->expr()->orig()) != 6 ) + throw Exception(this, + "invalid line breaker length, must be a single ASCII " + "character. (Ex: \"\\001\".)"); + attr_linebreaker_ = a->expr(); + break; - case ATTR_MULTILINE: - attr_multiline_end_ = a->expr(); - break; + case ATTR_MULTILINE: attr_multiline_end_ = a->expr(); break; - case ATTR_ONELINE: - attr_oneline_ = true; - break; + case ATTR_ONELINE: attr_oneline_ = true; break; - case ATTR_REFCOUNT: - attr_refcount_ = true; - break; + case ATTR_REFCOUNT: attr_refcount_ = true; break; - case ATTR_REQUIRES: - attr_requires_->push_back(a->expr()); - break; + case ATTR_REQUIRES: attr_requires_->push_back(a->expr()); break; - case ATTR_TRANSIENT: - attr_transient_ = true; - break; + case ATTR_TRANSIENT: attr_transient_ = true; break; - case ATTR_CHUNKED: - case ATTR_UNTIL: - case ATTR_RESTOFDATA: - case ATTR_RESTOFFLOW: - // Ignore - // ... these are processed by { - // {ArrayType, StringType}::ProcessAttr - break; - } + case ATTR_CHUNKED: + case ATTR_UNTIL: + case ATTR_RESTOFDATA: + case ATTR_RESTOFFLOW: + // Ignore + // ... these are processed by { + // {ArrayType, StringType}::ProcessAttr + break; + } - attrs_->push_back(a); - } + attrs_->push_back(a); +} -string Type::EvalByteOrder(Output* out_cc, Env* env) const - { - // If &byteorder is specified for a field, rather - // than a type declaration, we do not add a byteorder variable - // to the class, but instead evaluate it directly. - if ( attr_byteorder_expr() && ! declared_as_type() ) - return attr_byteorder_expr()->EvalExpr(out_cc, global_env()); - env->Evaluate(out_cc, byteorder_id); - return env->RValue(byteorder_id); - } +string Type::EvalByteOrder(Output* out_cc, Env* env) const { + // If &byteorder is specified for a field, rather + // than a type declaration, we do not add a byteorder variable + // to the class, but instead evaluate it directly. + if ( attr_byteorder_expr() && ! declared_as_type() ) + return attr_byteorder_expr()->EvalExpr(out_cc, global_env()); + env->Evaluate(out_cc, byteorder_id); + return env->RValue(byteorder_id); +} -void Type::Prepare(Env* env, int flags) - { - env_ = env; - ASSERT(env_); +void Type::Prepare(Env* env, int flags) { + env_ = env; + ASSERT(env_); - // The name of the value variable - if ( value_var() ) - { - data_id_str_ = strfmt("%s:%s", decl_id()->Name(), value_var()->Name()); - } - else - { - data_id_str_ = strfmt("%s", decl_id()->Name()); - } + // The name of the value variable + if ( value_var() ) { + data_id_str_ = strfmt("%s:%s", decl_id()->Name(), value_var()->Name()); + } + else { + data_id_str_ = strfmt("%s", decl_id()->Name()); + } - if ( value_var() ) - { - env_->AddID(value_var(), static_cast(value_var_type_), this); - lvalue_ = strfmt("%s", env_->LValue(value_var())); - } + if ( value_var() ) { + env_->AddID(value_var(), static_cast(value_var_type_), this); + lvalue_ = strfmt("%s", env_->LValue(value_var())); + } - foreach (i, FieldList, attr_letfields_) - { - AddField(*i); - } + foreach (i, FieldList, attr_letfields_) { + AddField(*i); + } - if ( attr_exportsourcedata_ ) - { - ASSERT(flags & TO_BE_PARSED); - AddField(new PubVarField(sourcedata_id->clone(), extern_type_const_bytestring->Clone())); - } + if ( attr_exportsourcedata_ ) { + ASSERT(flags & TO_BE_PARSED); + AddField(new PubVarField(sourcedata_id->clone(), extern_type_const_bytestring->Clone())); + } - // An optional field - if ( attr_if_expr() ) - { - ASSERT(value_var()); - ID* has_value_id = new ID(strfmt("has_%s", value_var()->Name())); - has_value_field_ = new LetField(has_value_id, extern_type_bool->Clone(), attr_if_expr()); - AddField(has_value_field_); - } + // An optional field + if ( attr_if_expr() ) { + ASSERT(value_var()); + ID* has_value_id = new ID(strfmt("has_%s", value_var()->Name())); + has_value_field_ = new LetField(has_value_id, extern_type_bool->Clone(), attr_if_expr()); + AddField(has_value_field_); + } - if ( incremental_input() ) - { - ASSERT(flags & TO_BE_PARSED); - ID* parsing_complete_var = new ID( - strfmt("%s_parsing_complete", value_var() ? value_var()->Name() : "val")); - DEBUG_MSG("Adding parsing complete var: %s\n", parsing_complete_var->Name()); - parsing_complete_var_field_ = new TempVarField(parsing_complete_var, - extern_type_bool->Clone()); - parsing_complete_var_field_->Prepare(env); + if ( incremental_input() ) { + ASSERT(flags & TO_BE_PARSED); + ID* parsing_complete_var = new ID(strfmt("%s_parsing_complete", value_var() ? value_var()->Name() : "val")); + DEBUG_MSG("Adding parsing complete var: %s\n", parsing_complete_var->Name()); + parsing_complete_var_field_ = new TempVarField(parsing_complete_var, extern_type_bool->Clone()); + parsing_complete_var_field_->Prepare(env); - if ( NeedsBufferingStateVar() && ! env->GetDataType(buffering_state_id) ) - { - buffering_state_var_field_ = new PrivVarField(buffering_state_id->clone(), - extern_type_int->Clone()); - AddField(buffering_state_var_field_); - } + if ( NeedsBufferingStateVar() && ! env->GetDataType(buffering_state_id) ) { + buffering_state_var_field_ = new PrivVarField(buffering_state_id->clone(), extern_type_int->Clone()); + AddField(buffering_state_var_field_); + } - if ( incremental_parsing() && tot_ == RECORD ) - { - ASSERT(! parsing_state_var_field_); - parsing_state_var_field_ = new PrivVarField(parsing_state_id->clone(), - extern_type_int->Clone()); - AddField(parsing_state_var_field_); - } - } + if ( incremental_parsing() && tot_ == RECORD ) { + ASSERT(! parsing_state_var_field_); + parsing_state_var_field_ = new PrivVarField(parsing_state_id->clone(), extern_type_int->Clone()); + AddField(parsing_state_var_field_); + } + } - foreach (i, FieldList, fields_) - { - Field* f = *i; - f->Prepare(env); - } - } + foreach (i, FieldList, fields_) { + Field* f = *i; + f->Prepare(env); + } +} -void Type::GenPubDecls(Output* out_h, Env* env) - { - if ( DefineValueVar() ) - { - if ( attr_if_expr_ ) - out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }", - DataTypeConstRefStr().c_str(), env->RValue(value_var()), - env->RValue(has_value_var()), lvalue()); - else - out_h->println("%s %s const { return %s; }", DataTypeConstRefStr().c_str(), - env->RValue(value_var()), lvalue()); - } +void Type::GenPubDecls(Output* out_h, Env* env) { + if ( DefineValueVar() ) { + if ( attr_if_expr_ ) + out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }", DataTypeConstRefStr().c_str(), + env->RValue(value_var()), env->RValue(has_value_var()), lvalue()); + else + out_h->println("%s %s const { return %s; }", DataTypeConstRefStr().c_str(), env->RValue(value_var()), + lvalue()); + } - foreach (i, FieldList, fields_) - { - Field* f = *i; - f->GenPubDecls(out_h, env); - } - } + foreach (i, FieldList, fields_) { + Field* f = *i; + f->GenPubDecls(out_h, env); + } +} -void Type::GenPrivDecls(Output* out_h, Env* env) - { - if ( DefineValueVar() ) - { - out_h->println("%s %s;", DataTypeStr().c_str(), env->LValue(value_var())); - } +void Type::GenPrivDecls(Output* out_h, Env* env) { + if ( DefineValueVar() ) { + out_h->println("%s %s;", DataTypeStr().c_str(), env->LValue(value_var())); + } - foreach (i, FieldList, fields_) - { - Field* f = *i; - f->GenPrivDecls(out_h, env); - } - } + foreach (i, FieldList, fields_) { + Field* f = *i; + f->GenPrivDecls(out_h, env); + } +} -void Type::GenInitCode(Output* out_cc, Env* env) - { - foreach (i, FieldList, fields_) - { - Field* f = *i; - f->GenInitCode(out_cc, env); - } +void Type::GenInitCode(Output* out_cc, Env* env) { + foreach (i, FieldList, fields_) { + Field* f = *i; + f->GenInitCode(out_cc, env); + } - if ( parsing_state_var_field_ ) - { - out_cc->println("%s = 0;", env->LValue(parsing_state_var_field_->id())); - } + if ( parsing_state_var_field_ ) { + out_cc->println("%s = 0;", env->LValue(parsing_state_var_field_->id())); + } - if ( buffering_state_var_field_ ) - { - out_cc->println("%s = 0;", env->LValue(buffering_state_var_field_->id())); - } - } + if ( buffering_state_var_field_ ) { + out_cc->println("%s = 0;", env->LValue(buffering_state_var_field_->id())); + } +} -void Type::GenCleanUpCode(Output* out_cc, Env* env) - { - foreach (i, FieldList, fields_) - { - Field* f = *i; - if ( f->tof() != CASE_FIELD ) - f->GenCleanUpCode(out_cc, env); - } - } +void Type::GenCleanUpCode(Output* out_cc, Env* env) { + foreach (i, FieldList, fields_) { + Field* f = *i; + if ( f->tof() != CASE_FIELD ) + f->GenCleanUpCode(out_cc, env); + } +} -void Type::GenBufferConfiguration(Output* out_cc, Env* env) - { - ASSERT(buffer_input()); +void Type::GenBufferConfiguration(Output* out_cc, Env* env) { + ASSERT(buffer_input()); - string frame_buffer_arg; + string frame_buffer_arg; - switch ( buffer_mode() ) - { - case BUFFER_NOTHING: - break; + switch ( buffer_mode() ) { + case BUFFER_NOTHING: break; - case BUFFER_BY_LENGTH: - if ( ! NeedsBufferingStateVar() ) - break; + case BUFFER_BY_LENGTH: + if ( ! NeedsBufferingStateVar() ) + break; - ASSERT(env->GetDataType(buffering_state_id)); - out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); - out_cc->inc_indent(); - out_cc->println("{"); + ASSERT(env->GetDataType(buffering_state_id)); + out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); + out_cc->inc_indent(); + out_cc->println("{"); - if ( attr_length_expr_ ) - { - // frame_buffer_arg = attr_length_expr_->EvalExpr(out_cc, env); - frame_buffer_arg = strfmt("%d", InitialBufferLength()); - } - else if ( attr_restofflow_ ) - { - ASSERT(attr_chunked()); - frame_buffer_arg = "-1"; - } - else - { - ASSERT(0); - } + if ( attr_length_expr_ ) { + // frame_buffer_arg = attr_length_expr_->EvalExpr(out_cc, env); + frame_buffer_arg = strfmt("%d", InitialBufferLength()); + } + else if ( attr_restofflow_ ) { + ASSERT(attr_chunked()); + frame_buffer_arg = "-1"; + } + else { + ASSERT(0); + } - out_cc->println("%s->NewFrame(%s, %s);", env->LValue(flow_buffer_id), - frame_buffer_arg.c_str(), attr_chunked() ? "true" : "false"); + out_cc->println("%s->NewFrame(%s, %s);", env->LValue(flow_buffer_id), frame_buffer_arg.c_str(), + attr_chunked() ? "true" : "false"); - out_cc->println("%s = 1;", env->LValue(buffering_state_id)); - out_cc->println("}"); - out_cc->dec_indent(); - break; + out_cc->println("%s = 1;", env->LValue(buffering_state_id)); + out_cc->println("}"); + out_cc->dec_indent(); + break; - case BUFFER_BY_LINE: - ASSERT(env->GetDataType(buffering_state_id)); - out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); - out_cc->inc_indent(); - out_cc->println("{"); - if ( BufferableWithLineBreaker() ) - out_cc->println("%s->SetLineBreaker((unsigned char*)%s);", - env->LValue(flow_buffer_id), LineBreaker()->orig()); - else - out_cc->println("%s->UnsetLineBreaker();", env->LValue(flow_buffer_id)); + case BUFFER_BY_LINE: + ASSERT(env->GetDataType(buffering_state_id)); + out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); + out_cc->inc_indent(); + out_cc->println("{"); - out_cc->println("%s->NewLine();", env->LValue(flow_buffer_id)); + if ( BufferableWithLineBreaker() ) + out_cc->println("%s->SetLineBreaker((unsigned char*)%s);", env->LValue(flow_buffer_id), + LineBreaker()->orig()); + else + out_cc->println("%s->UnsetLineBreaker();", env->LValue(flow_buffer_id)); - out_cc->println("%s = 1;", env->LValue(buffering_state_id)); - out_cc->println("}"); - out_cc->dec_indent(); - break; + out_cc->println("%s->NewLine();", env->LValue(flow_buffer_id)); - default: - ASSERT(0); - break; - } - } + out_cc->println("%s = 1;", env->LValue(buffering_state_id)); + out_cc->println("}"); + out_cc->dec_indent(); + break; -void Type::GenPreParsing(Output* out_cc, Env* env) - { - if ( incremental_input() && IsPointerType() ) - { - out_cc->println("if ( ! %s )", env->LValue(value_var())); - out_cc->inc_indent(); - out_cc->println("{"); - GenNewInstance(out_cc, env); - out_cc->println("}"); - out_cc->dec_indent(); - } - else - GenNewInstance(out_cc, env); + default: ASSERT(0); break; + } +} - if ( buffer_input() ) - { - GenBufferConfiguration(out_cc, env); - } - } +void Type::GenPreParsing(Output* out_cc, Env* env) { + if ( incremental_input() && IsPointerType() ) { + out_cc->println("if ( ! %s )", env->LValue(value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + GenNewInstance(out_cc, env); + out_cc->println("}"); + out_cc->dec_indent(); + } + else + GenNewInstance(out_cc, env); + + if ( buffer_input() ) { + GenBufferConfiguration(out_cc, env); + } +} // Wrappers around DoGenParseCode, which does the real job -void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) - { - if ( value_var() && env->Evaluated(value_var()) ) - return; +void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) { + if ( value_var() && env->Evaluated(value_var()) ) + return; - DEBUG_MSG("GenParseCode for %s\n", data_id_str_.c_str()); + DEBUG_MSG("GenParseCode for %s\n", data_id_str_.c_str()); - if ( attr_if_expr() ) - { - ASSERT(has_value_var()); - ASSERT(env->Evaluated(has_value_var())); - } + if ( attr_if_expr() ) { + ASSERT(has_value_var()); + ASSERT(env->Evaluated(has_value_var())); + } - if ( value_var() && anonymous_value_var() ) - { - GenPrivDecls(out_cc, env); - GenInitCode(out_cc, env); - } + if ( value_var() && anonymous_value_var() ) { + GenPrivDecls(out_cc, env); + GenInitCode(out_cc, env); + } - if ( incremental_input() ) - { - parsing_complete_var_field_->GenTempDecls(out_cc, env); + if ( incremental_input() ) { + parsing_complete_var_field_->GenTempDecls(out_cc, env); - out_cc->println("%s = false;", env->LValue(parsing_complete_var())); - env->SetEvaluated(parsing_complete_var()); + out_cc->println("%s = false;", env->LValue(parsing_complete_var())); + env->SetEvaluated(parsing_complete_var()); - if ( buffer_mode() == BUFFER_NOTHING ) - { - out_cc->println("%s = true;", env->LValue(parsing_complete_var())); - } - else if ( buffer_input() ) - { - if ( declared_as_type() ) - GenParseBuffer(out_cc, env, flags); - else - GenBufferingLoop(out_cc, env, flags); - } - else - GenParseCode2(out_cc, env, data, flags); - } - else - { - if ( attr_length_expr_ ) - { - EvalLengthExpr(out_cc, env); + if ( buffer_mode() == BUFFER_NOTHING ) { + out_cc->println("%s = true;", env->LValue(parsing_complete_var())); + } + else if ( buffer_input() ) { + if ( declared_as_type() ) + GenParseBuffer(out_cc, env, flags); + else + GenBufferingLoop(out_cc, env, flags); + } + else + GenParseCode2(out_cc, env, data, flags); + } + else { + if ( attr_length_expr_ ) { + EvalLengthExpr(out_cc, env); - GenBoundaryCheck(out_cc, env, data); + GenBoundaryCheck(out_cc, env, data); - out_cc->println("{"); - out_cc->println("// Setting %s with &length", env->RValue(end_of_data)); - out_cc->println("%s %s = %s + %s;", extern_type_const_byteptr->DataTypeStr().c_str(), - env->LValue(end_of_data), data.ptr_expr(), - EvalLengthExpr(out_cc, env).c_str()); + out_cc->println("{"); + out_cc->println("// Setting %s with &length", env->RValue(end_of_data)); + out_cc->println("%s %s = %s + %s;", extern_type_const_byteptr->DataTypeStr().c_str(), + env->LValue(end_of_data), data.ptr_expr(), EvalLengthExpr(out_cc, env).c_str()); - GenParseCode2(out_cc, env, data, flags); + GenParseCode2(out_cc, env, data, flags); - out_cc->println("}"); - } - else - { - GenParseCode2(out_cc, env, data, flags); - } - } - } + out_cc->println("}"); + } + else { + GenParseCode2(out_cc, env, data, flags); + } + } +} -void Type::GenBufferingLoop(Output* out_cc, Env* env, int flags) - { - out_cc->println("while ( ! %s && %s->ready() )", env->LValue(parsing_complete_var()), - env->LValue(flow_buffer_id)); +void Type::GenBufferingLoop(Output* out_cc, Env* env, int flags) { + out_cc->println("while ( ! %s && %s->ready() )", env->LValue(parsing_complete_var()), env->LValue(flow_buffer_id)); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->inc_indent(); + out_cc->println("{"); - Env buffer_env(env, this); - GenParseBuffer(out_cc, &buffer_env, flags); + Env buffer_env(env, this); + GenParseBuffer(out_cc, &buffer_env, flags); - out_cc->println("}"); - out_cc->dec_indent(); - } + out_cc->println("}"); + out_cc->dec_indent(); +} -void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) - { - ASSERT(incremental_input()); +void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) { + ASSERT(incremental_input()); - const ID* data_begin; + const ID* data_begin; - if ( ! incremental_parsing() ) - { - env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); - env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); + if ( ! incremental_parsing() ) { + env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); + env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); - out_cc->println("%s %s = %s->begin();", env->DataTypeStr(begin_of_data).c_str(), - env->LValue(begin_of_data), env->RValue(flow_buffer_id)); + out_cc->println("%s %s = %s->begin();", env->DataTypeStr(begin_of_data).c_str(), env->LValue(begin_of_data), + env->RValue(flow_buffer_id)); - out_cc->println("%s %s = %s->end();", env->DataTypeStr(end_of_data).c_str(), - env->LValue(end_of_data), env->RValue(flow_buffer_id)); + out_cc->println("%s %s = %s->end();", env->DataTypeStr(end_of_data).c_str(), env->LValue(end_of_data), + env->RValue(flow_buffer_id)); - env->SetEvaluated(begin_of_data); - env->SetEvaluated(end_of_data); + env->SetEvaluated(begin_of_data); + env->SetEvaluated(end_of_data); - data_begin = begin_of_data; - } - else - data_begin = nullptr; + data_begin = begin_of_data; + } + else + data_begin = nullptr; - if ( array_until_input_ ) - { - if ( incremental_parsing() ) - { - throw Exception(this, "cannot handle &until($input...) " - "for incrementally parsed type"); - } - array_until_input_->GenUntilInputCheck(out_cc, env); - } + if ( array_until_input_ ) { + if ( incremental_parsing() ) { + throw Exception(this, + "cannot handle &until($input...) " + "for incrementally parsed type"); + } + array_until_input_->GenUntilInputCheck(out_cc, env); + } - DataPtr data(env, data_begin, 0); + DataPtr data(env, data_begin, 0); - if ( attr_length_expr() ) - { - ASSERT(buffer_mode() == BUFFER_BY_LENGTH); - out_cc->println("switch ( %s )", env->LValue(buffering_state_id)); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("case 0:"); - out_cc->inc_indent(); - GenBufferConfiguration(out_cc, env); - out_cc->println("%s = 1;", env->LValue(buffering_state_id)); - out_cc->println("break;"); - out_cc->dec_indent(); + if ( attr_length_expr() ) { + ASSERT(buffer_mode() == BUFFER_BY_LENGTH); + out_cc->println("switch ( %s )", env->LValue(buffering_state_id)); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("case 0:"); + out_cc->inc_indent(); + GenBufferConfiguration(out_cc, env); + out_cc->println("%s = 1;", env->LValue(buffering_state_id)); + out_cc->println("break;"); + out_cc->dec_indent(); - out_cc->println("case 1:"); - out_cc->inc_indent(); + out_cc->println("case 1:"); + out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("{"); - out_cc->println("%s = 2;", env->LValue(buffering_state_id)); + out_cc->println("%s = 2;", env->LValue(buffering_state_id)); - Env frame_length_env(env, this); - out_cc->println("%s->GrowFrame(%s);", env->LValue(flow_buffer_id), - attr_length_expr_->EvalExpr(out_cc, &frame_length_env)); - out_cc->println("}"); - out_cc->println("break;"); + Env frame_length_env(env, this); + out_cc->println("%s->GrowFrame(%s);", env->LValue(flow_buffer_id), + attr_length_expr_->EvalExpr(out_cc, &frame_length_env)); + out_cc->println("}"); + out_cc->println("break;"); - out_cc->dec_indent(); - out_cc->println("case 2:"); - out_cc->inc_indent(); + out_cc->dec_indent(); + out_cc->println("case 2:"); + out_cc->inc_indent(); - out_cc->println("BINPAC_ASSERT(%s->ready());", env->RValue(flow_buffer_id)); - out_cc->println("if ( %s->ready() )", env->RValue(flow_buffer_id)); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("BINPAC_ASSERT(%s->ready());", env->RValue(flow_buffer_id)); + out_cc->println("if ( %s->ready() )", env->RValue(flow_buffer_id)); + out_cc->inc_indent(); + out_cc->println("{"); - Env parse_env(env, this); - GenParseCode2(out_cc, &parse_env, data, 0); + Env parse_env(env, this); + GenParseCode2(out_cc, &parse_env, data, 0); - out_cc->println("BINPAC_ASSERT(%s);", parsing_complete(env).c_str()); - out_cc->println("%s = 0;", env->LValue(buffering_state_id)); - out_cc->println("}"); - out_cc->dec_indent(); + out_cc->println("BINPAC_ASSERT(%s);", parsing_complete(env).c_str()); + out_cc->println("%s = 0;", env->LValue(buffering_state_id)); + out_cc->println("}"); + out_cc->dec_indent(); - out_cc->println("break;"); + out_cc->println("break;"); - out_cc->dec_indent(); - out_cc->println("default:"); - out_cc->inc_indent(); + out_cc->dec_indent(); + out_cc->println("default:"); + out_cc->inc_indent(); - out_cc->println("BINPAC_ASSERT(%s <= 2);", env->LValue(buffering_state_id)); - out_cc->println("break;"); + out_cc->println("BINPAC_ASSERT(%s <= 2);", env->LValue(buffering_state_id)); + out_cc->println("break;"); - out_cc->dec_indent(); - out_cc->println("}"); - out_cc->dec_indent(); - } - else if ( attr_restofflow_ ) - { - out_cc->println("BINPAC_ASSERT(%s->eof());", env->RValue(flow_buffer_id)); - GenParseCode2(out_cc, env, data, 0); - } - else if ( buffer_mode() == BUFFER_BY_LINE ) - { - GenParseCode2(out_cc, env, data, 0); - out_cc->println("%s = 0;", env->LValue(buffering_state_id)); - } - else - GenParseCode2(out_cc, env, data, 0); - } + out_cc->dec_indent(); + out_cc->println("}"); + out_cc->dec_indent(); + } + else if ( attr_restofflow_ ) { + out_cc->println("BINPAC_ASSERT(%s->eof());", env->RValue(flow_buffer_id)); + GenParseCode2(out_cc, env, data, 0); + } + else if ( buffer_mode() == BUFFER_BY_LINE ) { + GenParseCode2(out_cc, env, data, 0); + out_cc->println("%s = 0;", env->LValue(buffering_state_id)); + } + else + GenParseCode2(out_cc, env, data, 0); +} -void Type::GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags) - { - DEBUG_MSG("GenParseCode2 for %s\n", data_id_str_.c_str()); +void Type::GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags) { + DEBUG_MSG("GenParseCode2 for %s\n", data_id_str_.c_str()); - if ( attr_exportsourcedata_ ) - { - if ( incremental_parsing() ) - { - throw Exception(this, "cannot export raw data for incrementally parsed types"); - } + if ( attr_exportsourcedata_ ) { + if ( incremental_parsing() ) { + throw Exception(this, "cannot export raw data for incrementally parsed types"); + } - out_cc->println("%s = const_bytestring(%s, %s);", env->LValue(sourcedata_id), - data.ptr_expr(), env->RValue(end_of_data)); - env->SetEvaluated(sourcedata_id); + out_cc->println("%s = const_bytestring(%s, %s);", env->LValue(sourcedata_id), data.ptr_expr(), + env->RValue(end_of_data)); + env->SetEvaluated(sourcedata_id); - GenParseCode3(out_cc, env, data, flags); + GenParseCode3(out_cc, env, data, flags); - string datasize_str = DataSize(out_cc, env, data); - out_cc->println("%s.set_end(%s + %s);", env->LValue(sourcedata_id), data.ptr_expr(), - datasize_str.c_str()); - } - else - { - GenParseCode3(out_cc, env, data, flags); - } - } + string datasize_str = DataSize(out_cc, env, data); + out_cc->println("%s.set_end(%s + %s);", env->LValue(sourcedata_id), data.ptr_expr(), datasize_str.c_str()); + } + else { + GenParseCode3(out_cc, env, data, flags); + } +} -void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags) - { - foreach (i, ExprList, attr_requires_) - { - Expr* req = *i; - req->EvalExpr(out_cc, env); - } +void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags) { + foreach (i, ExprList, attr_requires_) { + Expr* req = *i; + req->EvalExpr(out_cc, env); + } - foreach (i, FieldList, fields_) - { - Field* f = *i; - f->GenTempDecls(out_cc, env); - } + foreach (i, FieldList, fields_) { + Field* f = *i; + f->GenTempDecls(out_cc, env); + } - DoGenParseCode(out_cc, env, data, flags); + DoGenParseCode(out_cc, env, data, flags); - if ( incremental_input() ) - { - out_cc->println("if ( %s )", parsing_complete(env).c_str()); - out_cc->inc_indent(); - out_cc->println("{"); - } + if ( incremental_input() ) { + out_cc->println("if ( %s )", parsing_complete(env).c_str()); + out_cc->inc_indent(); + out_cc->println("{"); + } - if ( ! fields_->empty() ) - { - out_cc->println("// Evaluate 'let' and 'withinput' fields"); - foreach (i, FieldList, fields_) - { - Field* f = *i; - if ( f->tof() == LET_FIELD ) - { - LetField* lf = static_cast(f); - lf->GenParseCode(out_cc, env); - } - else if ( f->tof() == WITHINPUT_FIELD ) - { - WithInputField* af = static_cast(f); - af->GenParseCode(out_cc, env); - } - } - } + if ( ! fields_->empty() ) { + out_cc->println("// Evaluate 'let' and 'withinput' fields"); + foreach (i, FieldList, fields_) { + Field* f = *i; + if ( f->tof() == LET_FIELD ) { + LetField* lf = static_cast(f); + lf->GenParseCode(out_cc, env); + } + else if ( f->tof() == WITHINPUT_FIELD ) { + WithInputField* af = static_cast(f); + af->GenParseCode(out_cc, env); + } + } + } - if ( value_var() && anonymous_value_var() ) - { - GenCleanUpCode(out_cc, env); - } + if ( value_var() && anonymous_value_var() ) { + GenCleanUpCode(out_cc, env); + } - if ( incremental_input() ) - { - out_cc->println("}"); - out_cc->dec_indent(); - } + if ( incremental_input() ) { + out_cc->println("}"); + out_cc->dec_indent(); + } - if ( value_var() ) - env->SetEvaluated(value_var()); + if ( value_var() ) + env->SetEvaluated(value_var()); - if ( size_var() ) - ASSERT(env->Evaluated(size_var())); + if ( size_var() ) + ASSERT(env->Evaluated(size_var())); - foreach (i, ExprList, attr_enforces_) - { - Expr* enforce = *i; - const char* enforce_expr = enforce->EvalExpr(out_cc, env); - out_cc->println("// Evaluate '&enforce' attribute"); - out_cc->println("if (!%s)", enforce_expr); - out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("throw binpac::ExceptionEnforceViolation(\"%s\");", data_id_str_.c_str()); - out_cc->println("}"); - out_cc->dec_indent(); - } - } + foreach (i, ExprList, attr_enforces_) { + Expr* enforce = *i; + const char* enforce_expr = enforce->EvalExpr(out_cc, env); + out_cc->println("// Evaluate '&enforce' attribute"); + out_cc->println("if (!%s)", enforce_expr); + out_cc->inc_indent(); + out_cc->println("{"); + out_cc->println("throw binpac::ExceptionEnforceViolation(\"%s\");", data_id_str_.c_str()); + out_cc->println("}"); + out_cc->dec_indent(); + } +} -Type* Type::MemberDataType(const ID* member_id) const - { - DEBUG_MSG("MemberDataType: %s::%s\n", type_decl_id_->Name(), member_id->Name()); - ASSERT(env_); - env_->set_allow_undefined_id(true); - Type* t = env_->GetDataType(member_id); - env_->set_allow_undefined_id(false); - return t; - } +Type* Type::MemberDataType(const ID* member_id) const { + DEBUG_MSG("MemberDataType: %s::%s\n", type_decl_id_->Name(), member_id->Name()); + ASSERT(env_); + env_->set_allow_undefined_id(true); + Type* t = env_->GetDataType(member_id); + env_->set_allow_undefined_id(false); + return t; +} -Type* Type::ElementDataType() const - { - return nullptr; - } +Type* Type::ElementDataType() const { return nullptr; } // Returns false if it is not necessary to add size_var // (it is already added or the type has a fixed size). -bool Type::AddSizeVar(Output* out_cc, Env* env) - { - if ( size_var() ) - { - DEBUG_MSG("size var `%s' already added\n", size_var()->Name()); - ASSERT(env->Evaluated(size_var())); - return false; - } +bool Type::AddSizeVar(Output* out_cc, Env* env) { + if ( size_var() ) { + DEBUG_MSG("size var `%s' already added\n", size_var()->Name()); + ASSERT(env->Evaluated(size_var())); + return false; + } - if ( StaticSize(env) >= 0 ) - return false; + if ( StaticSize(env) >= 0 ) + return false; - ASSERT(! incremental_input()); + ASSERT(! incremental_input()); - ID* size_var_id = new ID( - strfmt("%s__size", value_var() ? value_var()->Name() : decl_id()->Name())); + ID* size_var_id = new ID(strfmt("%s__size", value_var() ? value_var()->Name() : decl_id()->Name())); - DEBUG_MSG("adding size var `%s' to env %p\n", size_var_id->Name(), env); + DEBUG_MSG("adding size var `%s' to env %p\n", size_var_id->Name(), env); - size_var_field_ = new TempVarField(size_var_id, extern_type_int->Clone()); - size_var_field_->Prepare(env); - size_var_field_->GenTempDecls(out_cc, env); + size_var_field_ = new TempVarField(size_var_id, extern_type_int->Clone()); + size_var_field_->Prepare(env); + size_var_field_->GenTempDecls(out_cc, env); - return true; - } + return true; +} -string Type::EvalLengthExpr(Output* out_cc, Env* env) - { - ASSERT(! incremental_input()); - ASSERT(attr_length_expr_); - int static_length; - if ( attr_length_expr_->ConstFold(env, &static_length) ) - return strfmt("%d", static_length); - // How do we make sure size_var is evaluated with attr_length_expr_? - if ( AddSizeVar(out_cc, env) ) - { - out_cc->println("%s = %s;", env->LValue(size_var()), - attr_length_expr_->EvalExpr(out_cc, env)); - env->SetEvaluated(size_var()); - } - return env->RValue(size_var()); - } +string Type::EvalLengthExpr(Output* out_cc, Env* env) { + ASSERT(! incremental_input()); + ASSERT(attr_length_expr_); + int static_length; + if ( attr_length_expr_->ConstFold(env, &static_length) ) + return strfmt("%d", static_length); + // How do we make sure size_var is evaluated with attr_length_expr_? + if ( AddSizeVar(out_cc, env) ) { + out_cc->println("%s = %s;", env->LValue(size_var()), attr_length_expr_->EvalExpr(out_cc, env)); + env->SetEvaluated(size_var()); + } + return env->RValue(size_var()); +} -string Type::DataSize(Output* out_cc, Env* env, const DataPtr& data) - { - if ( attr_length_expr_ ) - return EvalLengthExpr(out_cc, env); +string Type::DataSize(Output* out_cc, Env* env, const DataPtr& data) { + if ( attr_length_expr_ ) + return EvalLengthExpr(out_cc, env); - int ss = StaticSize(env); - if ( ss >= 0 ) - { - return strfmt("%d", ss); - } - else - { - if ( ! size_var() || ! env->Evaluated(size_var()) ) - { - ASSERT(out_cc != 0); - GenDynamicSize(out_cc, env, data); - ASSERT(size_var()); - } - return env->RValue(size_var()); - } - } + int ss = StaticSize(env); + if ( ss >= 0 ) { + return strfmt("%d", ss); + } + else { + if ( ! size_var() || ! env->Evaluated(size_var()) ) { + ASSERT(out_cc != 0); + GenDynamicSize(out_cc, env, data); + ASSERT(size_var()); + } + return env->RValue(size_var()); + } +} -void Type::GenBoundaryCheck(Output* out_cc, Env* env, const DataPtr& data) - { - if ( boundary_checked() ) - return; +void Type::GenBoundaryCheck(Output* out_cc, Env* env, const DataPtr& data) { + if ( boundary_checked() ) + return; - data.GenBoundaryCheck(out_cc, env, DataSize(out_cc, env, data).c_str(), data_id_str_.c_str()); + data.GenBoundaryCheck(out_cc, env, DataSize(out_cc, env, data).c_str(), data_id_str_.c_str()); - SetBoundaryChecked(); - } + SetBoundaryChecked(); +} -bool Type::NeedsCleanUp() const - { - switch ( tot_ ) - { - case EMPTY: - case BUILTIN: - return false; - case ARRAY: - case PARAMETERIZED: - case STRING: - return true; - default: - ASSERT(0); - return true; - } - return true; - } +bool Type::NeedsCleanUp() const { + switch ( tot_ ) { + case EMPTY: + case BUILTIN: return false; + case ARRAY: + case PARAMETERIZED: + case STRING: return true; + default: ASSERT(0); return true; + } + return true; +} -bool Type::RequiresByteOrder() const - { - return ! attr_byteorder_expr() && ByteOrderSensitive(); - } +bool Type::RequiresByteOrder() const { return ! attr_byteorder_expr() && ByteOrderSensitive(); } -bool Type::NeedsBufferingStateVar() const - { - if ( ! incremental_input() ) - return false; - switch ( buffer_mode() ) - { - case BUFFER_NOTHING: - case NOT_BUFFERABLE: - return false; - case BUFFER_BY_LINE: - return true; - case BUFFER_BY_LENGTH: - return (attr_length_expr_ || attr_restofflow_); - default: - ASSERT(0); - return false; - } - } +bool Type::NeedsBufferingStateVar() const { + if ( ! incremental_input() ) + return false; + switch ( buffer_mode() ) { + case BUFFER_NOTHING: + case NOT_BUFFERABLE: return false; + case BUFFER_BY_LINE: return true; + case BUFFER_BY_LENGTH: return (attr_length_expr_ || attr_restofflow_); + default: ASSERT(0); return false; + } +} -bool Type::DoTraverse(DataDepVisitor* visitor) - { - foreach (i, FieldList, fields_) - { - if ( ! (*i)->Traverse(visitor) ) - return false; - } +bool Type::DoTraverse(DataDepVisitor* visitor) { + foreach (i, FieldList, fields_) { + if ( ! (*i)->Traverse(visitor) ) + return false; + } - foreach (i, AttrList, attrs_) - { - if ( ! (*i)->Traverse(visitor) ) - return false; - } + foreach (i, AttrList, attrs_) { + if ( ! (*i)->Traverse(visitor) ) + return false; + } - return true; - } + return true; +} -bool Type::RequiresAnalyzerContext() - { - ASSERT(0); +bool Type::RequiresAnalyzerContext() { + ASSERT(0); - if ( buffer_input() ) - return true; + if ( buffer_input() ) + return true; - foreach (i, FieldList, fields_) - { - Field* f = *i; - if ( f->RequiresAnalyzerContext() ) - return true; - } + foreach (i, FieldList, fields_) { + Field* f = *i; + if ( f->RequiresAnalyzerContext() ) + return true; + } - foreach (i, AttrList, attrs_) - if ( (*i)->RequiresAnalyzerContext() ) - return true; + foreach (i, AttrList, attrs_) + if ( (*i)->RequiresAnalyzerContext() ) + return true; - return false; - } + return false; +} -bool Type::IsEmptyType() const - { - return (StaticSize(global_env()) == 0); - } +bool Type::IsEmptyType() const { return (StaticSize(global_env()) == 0); } -void Type::MarkIncrementalInput() - { - DEBUG_MSG("Handle incremental input for %s.%s\n", decl_id()->Name(), - value_var() ? value_var()->Name() : "*"); +void Type::MarkIncrementalInput() { + DEBUG_MSG("Handle incremental input for %s.%s\n", decl_id()->Name(), value_var() ? value_var()->Name() : "*"); - incremental_input_ = true; - if ( Bufferable() ) - buffer_input_ = true; - else - { - incremental_parsing_ = true; - DoMarkIncrementalInput(); - } - } + incremental_input_ = true; + if ( Bufferable() ) + buffer_input_ = true; + else { + incremental_parsing_ = true; + DoMarkIncrementalInput(); + } +} -void Type::DoMarkIncrementalInput() - { - throw Exception(this, "cannot handle incremental input"); - } +void Type::DoMarkIncrementalInput() { throw Exception(this, "cannot handle incremental input"); } -bool Type::BufferableByLength() const - { - // If the input is an "frame buffer" with specified length - return attr_length_expr_ || attr_restofflow_; - } +bool Type::BufferableByLength() const { + // If the input is an "frame buffer" with specified length + return attr_length_expr_ || attr_restofflow_; +} -bool Type::BufferableByLine() const - { - // If the input is an ASCII line; - return attr_oneline_; - } +bool Type::BufferableByLine() const { + // If the input is an ASCII line; + return attr_oneline_; +} -bool Type::Bufferable() const - { - // If the input is an ASCII line or an "frame buffer" - return IsEmptyType() || BufferableByLength() || BufferableByLine(); - } +bool Type::Bufferable() const { + // If the input is an ASCII line or an "frame buffer" + return IsEmptyType() || BufferableByLength() || BufferableByLine(); +} -bool Type::BufferableWithLineBreaker() const - { - // If the input is an ASCII line with a given linebreaker; - return attr_linebreaker_ != nullptr; - } +bool Type::BufferableWithLineBreaker() const { + // If the input is an ASCII line with a given linebreaker; + return attr_linebreaker_ != nullptr; +} -Expr* Type::LineBreaker() const - { - return attr_linebreaker_; - } +Expr* Type::LineBreaker() const { return attr_linebreaker_; } -Type::BufferMode Type::buffer_mode() const - { - if ( IsEmptyType() ) - return BUFFER_NOTHING; - else if ( BufferableByLength() ) - return BUFFER_BY_LENGTH; - else if ( BufferableByLine() ) - return BUFFER_BY_LINE; - return NOT_BUFFERABLE; - } +Type::BufferMode Type::buffer_mode() const { + if ( IsEmptyType() ) + return BUFFER_NOTHING; + else if ( BufferableByLength() ) + return BUFFER_BY_LENGTH; + else if ( BufferableByLine() ) + return BUFFER_BY_LINE; + return NOT_BUFFERABLE; +} -const ID* Type::parsing_complete_var() const - { - if ( parsing_complete_var_field_ ) - return parsing_complete_var_field_->id(); - else - return nullptr; - } +const ID* Type::parsing_complete_var() const { + if ( parsing_complete_var_field_ ) + return parsing_complete_var_field_->id(); + else + return nullptr; +} -string Type::parsing_complete(Env* env) const - { - ASSERT(parsing_complete_var()); - return env->RValue(parsing_complete_var()); - } +string Type::parsing_complete(Env* env) const { + ASSERT(parsing_complete_var()); + return env->RValue(parsing_complete_var()); +} -const ID* Type::has_value_var() const - { - if ( has_value_field_ ) - return has_value_field_->id(); - else - return nullptr; - } +const ID* Type::has_value_var() const { + if ( has_value_field_ ) + return has_value_field_->id(); + else + return nullptr; +} -int Type::InitialBufferLength() const - { - if ( ! attr_length_expr_ ) - return 0; - return attr_length_expr_->MinimalHeaderSize(env()); - } +int Type::InitialBufferLength() const { + if ( ! attr_length_expr_ ) + return 0; + return attr_length_expr_->MinimalHeaderSize(env()); +} -bool Type::CompatibleTypes(Type* type1, Type* type2) - { - // If we cannot deduce one of the data types, assume that - // they are compatible. - if ( ! type1 || ! type2 ) - return true; +bool Type::CompatibleTypes(Type* type1, Type* type2) { + // If we cannot deduce one of the data types, assume that + // they are compatible. + if ( ! type1 || ! type2 ) + return true; - // We do not have enough information about extern types - if ( type1->tot() == EXTERN || type2->tot() == EXTERN ) - return true; + // We do not have enough information about extern types + if ( type1->tot() == EXTERN || type2->tot() == EXTERN ) + return true; - if ( type1->tot() != type2->tot() ) - { - if ( type1->IsNumericType() && type2->IsNumericType() ) - return true; - else - return false; - } + if ( type1->tot() != type2->tot() ) { + if ( type1->IsNumericType() && type2->IsNumericType() ) + return true; + else + return false; + } - switch ( type1->tot() ) - { - case UNDEF: - case EMPTY: - return true; - case BUILTIN: - { - BuiltInType* t1 = static_cast(type1); - BuiltInType* t2 = static_cast(type2); - return BuiltInType::CompatibleBuiltInTypes(t1, t2); - } + switch ( type1->tot() ) { + case UNDEF: + case EMPTY: return true; + case BUILTIN: { + BuiltInType* t1 = static_cast(type1); + BuiltInType* t2 = static_cast(type2); + return BuiltInType::CompatibleBuiltInTypes(t1, t2); + } - case PARAMETERIZED: - case RECORD: - case CASE: - case EXTERN: - return type1->DataTypeStr() == type2->DataTypeStr(); - break; + case PARAMETERIZED: + case RECORD: + case CASE: + case EXTERN: return type1->DataTypeStr() == type2->DataTypeStr(); break; - case ARRAY: - { - ArrayType* t1 = static_cast(type1); - ArrayType* t2 = static_cast(type2); - return CompatibleTypes(t1->ElementDataType(), t2->ElementDataType()); - } + case ARRAY: { + ArrayType* t1 = static_cast(type1); + ArrayType* t2 = static_cast(type2); + return CompatibleTypes(t1->ElementDataType(), t2->ElementDataType()); + } - default: - ASSERT(0); - return false; - } - } + default: ASSERT(0); return false; + } +} -Type* Type::LookUpByID(ID* id) - { - // 1. Is it a pre-defined type? - string name = id->Name(); - if ( type_map_.find(name) != type_map_.end() ) - { - return type_map_[name]->Clone(); - } +Type* Type::LookUpByID(ID* id) { + // 1. Is it a pre-defined type? + string name = id->Name(); + if ( type_map_.find(name) != type_map_.end() ) { + return type_map_[name]->Clone(); + } - // 2. Is it a simple declared type? - Type* type = TypeDecl::LookUpType(id); - if ( type ) - { - // Note: as a Type is always associated with a variable, - // return a clone. - switch ( type->tot() ) - { - case Type::BUILTIN: - case Type::EXTERN: - case Type::STRING: - return type->Clone(); + // 2. Is it a simple declared type? + Type* type = TypeDecl::LookUpType(id); + if ( type ) { + // Note: as a Type is always associated with a variable, + // return a clone. + switch ( type->tot() ) { + case Type::BUILTIN: + case Type::EXTERN: + case Type::STRING: return type->Clone(); - case Type::ARRAY: - default: - break; - } - } + case Type::ARRAY: + default: break; + } + } - return new ParameterizedType(id, nullptr); - } + return new ParameterizedType(id, nullptr); +} -void Type::AddPredefinedType(const string& type_name, Type* type) - { - ASSERT(type_map_.find(type_name) == type_map_.end()); - type_map_[type_name] = type; - } +void Type::AddPredefinedType(const string& type_name, Type* type) { + ASSERT(type_map_.find(type_name) == type_map_.end()); + type_map_[type_name] = type; +} -void Type::init() - { - BuiltInType::static_init(); - ExternType::static_init(); - StringType::static_init(); - } +void Type::init() { + BuiltInType::static_init(); + ExternType::static_init(); + StringType::static_init(); +} diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index 34322d550a..faae7e2a21 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -8,304 +8,298 @@ using namespace std; #include "pac_datadep.h" #include "pac_dbg.h" -class Type : public Object, public DataDepElement - { +class Type : public Object, public DataDepElement { public: - enum TypeType - { - UNDEF = -1, - EMPTY, - BUILTIN, - PARAMETERIZED, - RECORD, - CASE, - ARRAY, - STRING, - EXTERN, - DUMMY, - }; + enum TypeType { + UNDEF = -1, + EMPTY, + BUILTIN, + PARAMETERIZED, + RECORD, + CASE, + ARRAY, + STRING, + EXTERN, + DUMMY, + }; - explicit Type(TypeType tot); - ~Type() override; + explicit Type(TypeType tot); + ~Type() override; - Type* Clone() const; + Type* Clone() const; - // Type of type - TypeType tot() const { return tot_; } + // Type of type + TypeType tot() const { return tot_; } - //////////////////////////////////////// - // Code generation - virtual void Prepare(Env* env, int flags); + //////////////////////////////////////// + // Code generation + virtual void Prepare(Env* env, int flags); - // Flag(s) for Prepare() - static const int TO_BE_PARSED = 1; + // Flag(s) for Prepare() + static const int TO_BE_PARSED = 1; - virtual void GenPubDecls(Output* out, Env* env); - virtual void GenPrivDecls(Output* out, Env* env); + virtual void GenPubDecls(Output* out, Env* env); + virtual void GenPrivDecls(Output* out, Env* env); - virtual void GenInitCode(Output* out, Env* env); - virtual void GenCleanUpCode(Output* out, Env* env); + virtual void GenInitCode(Output* out, Env* env); + virtual void GenCleanUpCode(Output* out, Env* env); - void GenPreParsing(Output* out, Env* env); - void GenParseCode(Output* out, Env* env, const DataPtr& data, int flags); + void GenPreParsing(Output* out, Env* env); + void GenParseCode(Output* out, Env* env, const DataPtr& data, int flags); - //////////////////////////////////////// - // TODO: organize the various methods below + //////////////////////////////////////// + // TODO: organize the various methods below - // The LValue string of the variable defined by the type. - // For example, if the type defines a record field, the - // lvalue is the member variable corresponding to the field; - // if the type appears in a type decl, then the lvalue is the - // default value var. - // - const char* lvalue() const { return lvalue_.c_str(); } + // The LValue string of the variable defined by the type. + // For example, if the type defines a record field, the + // lvalue is the member variable corresponding to the field; + // if the type appears in a type decl, then the lvalue is the + // default value var. + // + const char* lvalue() const { return lvalue_.c_str(); } - // The TypeDecl that defined the type. - // - const TypeDecl* type_decl() const { return type_decl_; } - void set_type_decl(const TypeDecl* decl, bool declared_as_type); + // The TypeDecl that defined the type. + // + const TypeDecl* type_decl() const { return type_decl_; } + void set_type_decl(const TypeDecl* decl, bool declared_as_type); - // Returns whether the type appears in a type declaration - // (true) or as type specification of a field (false). - // - bool declared_as_type() const { return declared_as_type_; } + // Returns whether the type appears in a type declaration + // (true) or as type specification of a field (false). + // + bool declared_as_type() const { return declared_as_type_; } - // The ID of the decl in which the type appear. - // - const ID* decl_id() const; + // The ID of the decl in which the type appear. + // + const ID* decl_id() const; - Env* env() const { return env_; } + Env* env() const { return env_; } - string EvalByteOrder(Output* out_cc, Env* env) const; + string EvalByteOrder(Output* out_cc, Env* env) const; - virtual string EvalMember(const ID* member_id) const; - virtual string EvalElement(const string& array, const string& index) const; + virtual string EvalMember(const ID* member_id) const; + virtual string EvalElement(const string& array, const string& index) const; - // The variable defined by the type - const ID* value_var() const { return value_var_; } - void set_value_var(const ID* arg_id, int arg_id_type); + // The variable defined by the type + const ID* value_var() const { return value_var_; } + void set_value_var(const ID* arg_id, int arg_id_type); - bool anonymous_value_var() const { return anonymous_value_var_; } + bool anonymous_value_var() const { return anonymous_value_var_; } - const ID* size_var() const; + const ID* size_var() const; - // Adds a variable to env to represent the size of this type. - // Returns false if we do not need a size variable (because - // the type has a static size) or the size variable is already added. - bool AddSizeVar(Output* out, Env* env); + // Adds a variable to env to represent the size of this type. + // Returns false if we do not need a size variable (because + // the type has a static size) or the size variable is already added. + bool AddSizeVar(Output* out, Env* env); - const ID* parsing_state_var() const; + const ID* parsing_state_var() const; - const ID* has_value_var() const; + const ID* has_value_var() const; - void AddField(Field* f); + void AddField(Field* f); - void AddCheck(Expr* expr) - { /* TODO */ - } + void AddCheck(Expr* expr) { /* TODO */ + } - virtual bool DefineValueVar() const = 0; + virtual bool DefineValueVar() const = 0; - // Returns C++ datatype string - virtual string DataTypeStr() const = 0; + // Returns C++ datatype string + virtual string DataTypeStr() const = 0; - // Returns const reference of the C++ data type (unless the type - // is numeric or pointer) - string DataTypeConstRefStr() const - { - string data_type = DataTypeStr(); - if ( ! IsPointerType() && ! IsNumericType() ) - data_type += " const &"; - return data_type; - } + // Returns const reference of the C++ data type (unless the type + // is numeric or pointer) + string DataTypeConstRefStr() const { + string data_type = DataTypeStr(); + if ( ! IsPointerType() && ! IsNumericType() ) + data_type += " const &"; + return data_type; + } - // Returns a default value for the type - virtual string DefaultValue() const - { - ASSERT(0); - return "@@@"; - } + // Returns a default value for the type + virtual string DefaultValue() const { + ASSERT(0); + return "@@@"; + } - // Returns the data type of the member field/case - virtual Type* MemberDataType(const ID* member_id) const; + // Returns the data type of the member field/case + virtual Type* MemberDataType(const ID* member_id) const; - // Returns the data type of the element type of an array - virtual Type* ElementDataType() const; + // Returns the data type of the element type of an array + virtual Type* ElementDataType() const; - // Whether the type needs clean-up at deallocation. - bool NeedsCleanUp() const; + // Whether the type needs clean-up at deallocation. + bool NeedsCleanUp() const; - // Whether byte order must be determined before parsing the type. - bool RequiresByteOrder() const; + // Whether byte order must be determined before parsing the type. + bool RequiresByteOrder() const; - // Whether class of the type requires a parameter of analyzer context. - virtual bool RequiresAnalyzerContext(); + // Whether class of the type requires a parameter of analyzer context. + virtual bool RequiresAnalyzerContext(); - virtual bool IsPointerType() const = 0; - virtual bool IsNumericType() const { return false; } - bool IsEmptyType() const; + virtual bool IsPointerType() const = 0; + virtual bool IsNumericType() const { return false; } + bool IsEmptyType() const; - //////////////////////////////////////// - // Attributes - virtual void ProcessAttr(Attr* a); + //////////////////////////////////////// + // Attributes + virtual void ProcessAttr(Attr* a); - bool attr_chunked() const { return attr_chunked_; } - Expr* attr_byteorder_expr() const { return attr_byteorder_expr_; } - Expr* attr_if_expr() const { return attr_if_expr_; } - // TODO: generate the length expression automatically. - Expr* attr_length_expr() const { return attr_length_expr_; } - bool attr_refcount() const { return attr_refcount_; } - bool attr_transient() const { return attr_transient_; } + bool attr_chunked() const { return attr_chunked_; } + Expr* attr_byteorder_expr() const { return attr_byteorder_expr_; } + Expr* attr_if_expr() const { return attr_if_expr_; } + // TODO: generate the length expression automatically. + Expr* attr_length_expr() const { return attr_length_expr_; } + bool attr_refcount() const { return attr_refcount_; } + bool attr_transient() const { return attr_transient_; } - // Whether the value remains valid outside the parse function - bool persistent() const { return ! attr_transient() && ! attr_chunked(); } + // Whether the value remains valid outside the parse function + bool persistent() const { return ! attr_transient() && ! attr_chunked(); } - void SetUntilCheck(ArrayType* t) { array_until_input_ = t; } + void SetUntilCheck(ArrayType* t) { array_until_input_ = t; } - //////////////////////////////////////// - // Size and boundary checking - virtual int StaticSize(Env* env) const = 0; - string DataSize(Output* out, Env* env, const DataPtr& data); + //////////////////////////////////////// + // Size and boundary checking + virtual int StaticSize(Env* env) const = 0; + string DataSize(Output* out, Env* env, const DataPtr& data); - bool boundary_checked() const { return boundary_checked_; } - virtual void SetBoundaryChecked() { boundary_checked_ = true; } - void GenBoundaryCheck(Output* out, Env* env, const DataPtr& data); + bool boundary_checked() const { return boundary_checked_; } + virtual void SetBoundaryChecked() { boundary_checked_ = true; } + void GenBoundaryCheck(Output* out, Env* env, const DataPtr& data); - //////////////////////////////////////// - // Handling incremental input - // - // There are two ways to handle incremental input: (1) to - // buffer the input before parsing; (2) to parse incrementally. - // - // The type must be "bufferable" for (1). While for (2), - // each member of the type must be able to handle incremental - // input. + //////////////////////////////////////// + // Handling incremental input + // + // There are two ways to handle incremental input: (1) to + // buffer the input before parsing; (2) to parse incrementally. + // + // The type must be "bufferable" for (1). While for (2), + // each member of the type must be able to handle incremental + // input. - void MarkIncrementalInput(); - virtual void DoMarkIncrementalInput(); + void MarkIncrementalInput(); + virtual void DoMarkIncrementalInput(); - // Whether the type may receive incremental input - bool incremental_input() const { return incremental_input_; } + // Whether the type may receive incremental input + bool incremental_input() const { return incremental_input_; } - // Whether parsing should also be incremental - bool incremental_parsing() const { return incremental_parsing_; } + // Whether parsing should also be incremental + bool incremental_parsing() const { return incremental_parsing_; } - // Whether we should buffer the input - bool buffer_input() const { return buffer_input_; } + // Whether we should buffer the input + bool buffer_input() const { return buffer_input_; } - // Whether parsing of the type is completed - const ID* parsing_complete_var() const; - string parsing_complete(Env* env) const; + // Whether parsing of the type is completed + const ID* parsing_complete_var() const; + string parsing_complete(Env* env) const; - // Whether the input is bufferable - bool Bufferable() const; - bool BufferableByLength() const; - bool BufferableByLine() const; - bool BufferableWithLineBreaker() const; - Expr* LineBreaker() const; + // Whether the input is bufferable + bool Bufferable() const; + bool BufferableByLength() const; + bool BufferableByLine() const; + bool BufferableWithLineBreaker() const; + Expr* LineBreaker() const; - enum BufferMode - { - NOT_BUFFERABLE, - BUFFER_NOTHING, // for type "empty" - BUFFER_BY_LENGTH, - BUFFER_BY_LINE, - }; - virtual BufferMode buffer_mode() const; + enum BufferMode { + NOT_BUFFERABLE, + BUFFER_NOTHING, // for type "empty" + BUFFER_BY_LENGTH, + BUFFER_BY_LINE, + }; + virtual BufferMode buffer_mode() const; - void GenBufferConfiguration(Output* out, Env* env); + void GenBufferConfiguration(Output* out, Env* env); - int InitialBufferLength() const; + int InitialBufferLength() const; protected: - virtual void GenNewInstance(Output* out, Env* env) { } + virtual void GenNewInstance(Output* out, Env* env) {} - virtual bool ByteOrderSensitive() const = 0; + virtual bool ByteOrderSensitive() const = 0; - bool NeedsBufferingStateVar() const; + bool NeedsBufferingStateVar() const; - void GenBufferingLoop(Output* out_cc, Env* env, int flags); - void GenParseBuffer(Output* out_cc, Env* env, int flags); - void GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags); - void GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags); + void GenBufferingLoop(Output* out_cc, Env* env, int flags); + void GenParseBuffer(Output* out_cc, Env* env, int flags); + void GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags); + void GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags); - virtual void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) = 0; + virtual void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) = 0; - string EvalLengthExpr(Output* out_cc, Env* env); + string EvalLengthExpr(Output* out_cc, Env* env); - // Generate code for computing the dynamic size of the type - virtual void GenDynamicSize(Output* out, Env* env, const DataPtr& data) = 0; + // Generate code for computing the dynamic size of the type + virtual void GenDynamicSize(Output* out, Env* env, const DataPtr& data) = 0; - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; - virtual Type* DoClone() const = 0; + virtual Type* DoClone() const = 0; protected: - TypeType tot_; - const TypeDecl* type_decl_; - bool declared_as_type_; - const ID* type_decl_id_; - Env* env_; + TypeType tot_; + const TypeDecl* type_decl_; + bool declared_as_type_; + const ID* type_decl_id_; + Env* env_; - const ID* value_var_; - bool anonymous_value_var_; // whether the ID is anonymous + const ID* value_var_; + bool anonymous_value_var_; // whether the ID is anonymous - string data_id_str_; - int value_var_type_; - Field* size_var_field_; - char* size_expr_; - bool boundary_checked_; - string lvalue_; - FieldList* fields_; + string data_id_str_; + int value_var_type_; + Field* size_var_field_; + char* size_expr_; + bool boundary_checked_; + string lvalue_; + FieldList* fields_; - bool incremental_input_; - bool incremental_parsing_; - bool buffer_input_; + bool incremental_input_; + bool incremental_parsing_; + bool buffer_input_; - // A boolean variable on whether parsing of the type is completed - Field* parsing_complete_var_field_; + // A boolean variable on whether parsing of the type is completed + Field* parsing_complete_var_field_; - // An integer variable holding the parsing state - Field* parsing_state_var_field_; + // An integer variable holding the parsing state + Field* parsing_state_var_field_; - Field* buffering_state_var_field_; + Field* buffering_state_var_field_; - // The array type with &until($input...) condition, if - // "this" is the element type - ArrayType* array_until_input_; + // The array type with &until($input...) condition, if + // "this" is the element type + ArrayType* array_until_input_; - // A "has_*" member var for fields with &if - LetField* has_value_field_; + // A "has_*" member var for fields with &if + LetField* has_value_field_; - // Attributes - AttrList* attrs_; + // Attributes + AttrList* attrs_; - Expr* attr_byteorder_expr_; - ExprList* attr_checks_; - ExprList* attr_enforces_; - bool attr_chunked_; - bool attr_exportsourcedata_; - Expr* attr_if_expr_; - Expr* attr_length_expr_; - FieldList* attr_letfields_; - Expr* attr_multiline_end_; - Expr* attr_linebreaker_; - bool attr_oneline_; - bool attr_refcount_; - ExprList* attr_requires_; - bool attr_restofdata_; - bool attr_restofflow_; - bool attr_transient_; + Expr* attr_byteorder_expr_; + ExprList* attr_checks_; + ExprList* attr_enforces_; + bool attr_chunked_; + bool attr_exportsourcedata_; + Expr* attr_if_expr_; + Expr* attr_length_expr_; + FieldList* attr_letfields_; + Expr* attr_multiline_end_; + Expr* attr_linebreaker_; + bool attr_oneline_; + bool attr_refcount_; + ExprList* attr_requires_; + bool attr_restofdata_; + bool attr_restofflow_; + bool attr_transient_; public: - static void init(); - static bool CompatibleTypes(Type* type1, Type* type2); - static void AddPredefinedType(const string& type_name, Type* type); - static Type* LookUpByID(ID* id); + static void init(); + static bool CompatibleTypes(Type* type1, Type* type2); + static void AddPredefinedType(const string& type_name, Type* type); + static Type* LookUpByID(ID* id); protected: - typedef map type_map_t; - static type_map_t type_map_; - }; + typedef map type_map_t; + static type_map_t type_map_; +}; #endif // pac_type_h diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc index 9d7b363ef1..5e48c9e2f1 100644 --- a/tools/binpac/src/pac_typedecl.cc +++ b/tools/binpac/src/pac_typedecl.cc @@ -16,315 +16,275 @@ #include "pac_type.h" #include "pac_utils.h" -TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type) - : Decl(id, TYPE), params_(params), type_(type) - { - env_ = nullptr; - type_->set_type_decl(this, true); - } +TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type) : Decl(id, TYPE), params_(params), type_(type) { + env_ = nullptr; + type_->set_type_decl(this, true); +} -TypeDecl::~TypeDecl() - { - delete env_; - delete type_; +TypeDecl::~TypeDecl() { + delete env_; + delete type_; - delete_list(ParamList, params_); - } + delete_list(ParamList, params_); +} -void TypeDecl::ProcessAttr(Attr* a) - { - type_->ProcessAttr(a); - } +void TypeDecl::ProcessAttr(Attr* a) { type_->ProcessAttr(a); } -void TypeDecl::AddParam(Param* param) - { - // Cannot work after Prepare() - ASSERT(! env_); - params_->push_back(param); - } +void TypeDecl::AddParam(Param* param) { + // Cannot work after Prepare() + ASSERT(! env_); + params_->push_back(param); +} -void TypeDecl::Prepare() - { - DEBUG_MSG("Preparing type %s\n", id()->Name()); +void TypeDecl::Prepare() { + DEBUG_MSG("Preparing type %s\n", id()->Name()); - if ( type_->tot() != Type::EXTERN && type_->tot() != Type::DUMMY ) - SetAnalyzerContext(); + if ( type_->tot() != Type::EXTERN && type_->tot() != Type::DUMMY ) + SetAnalyzerContext(); - // As a type ID can be used in the same way function is, add the - // id as a FUNC_ID and set it as evaluated. - global_env()->AddID(id(), FUNC_ID, type_); - global_env()->SetEvaluated(id()); + // As a type ID can be used in the same way function is, add the + // id as a FUNC_ID and set it as evaluated. + global_env()->AddID(id(), FUNC_ID, type_); + global_env()->SetEvaluated(id()); - env_ = new Env(global_env(), this); + env_ = new Env(global_env(), this); - foreach (i, ParamList, params_) - { - Param* p = *i; - // p->Prepare(env_); - type_->AddField(p->param_field()); - } + foreach (i, ParamList, params_) { + Param* p = *i; + // p->Prepare(env_); + type_->AddField(p->param_field()); + } - if ( type_->attr_byteorder_expr() ) - { - DEBUG_MSG("Adding byteorder field to %s\n", id()->Name()); - type_->AddField( - new LetField(byteorder_id->clone(), extern_type_int, type_->attr_byteorder_expr())); - } + if ( type_->attr_byteorder_expr() ) { + DEBUG_MSG("Adding byteorder field to %s\n", id()->Name()); + type_->AddField(new LetField(byteorder_id->clone(), extern_type_int, type_->attr_byteorder_expr())); + } - type_->Prepare(env_, Type::TO_BE_PARSED); - } + type_->Prepare(env_, Type::TO_BE_PARSED); +} -string TypeDecl::class_name() const - { - return id_->Name(); - } +string TypeDecl::class_name() const { return id_->Name(); } -void TypeDecl::GenForwardDeclaration(Output* out_h) - { - // Do not generate declaration for external types - if ( type_->tot() == Type::EXTERN ) - return; - out_h->println("class %s;", class_name().c_str()); - } +void TypeDecl::GenForwardDeclaration(Output* out_h) { + // Do not generate declaration for external types + if ( type_->tot() == Type::EXTERN ) + return; + out_h->println("class %s;", class_name().c_str()); +} -void TypeDecl::GenCode(Output* out_h, Output* out_cc) - { - // Do not generate code for external types - if ( type_->tot() == Type::EXTERN || type_->tot() == Type::STRING ) - return; +void TypeDecl::GenCode(Output* out_h, Output* out_cc) { + // Do not generate code for external types + if ( type_->tot() == Type::EXTERN || type_->tot() == Type::STRING ) + return; - if ( !FLAGS_quiet ) - fprintf(stderr, "Generating code for %s\n", class_name().c_str()); + if ( ! FLAGS_quiet ) + fprintf(stderr, "Generating code for %s\n", class_name().c_str()); - if ( RequiresAnalyzerContext::compute(type_) ) - { - DEBUG_MSG("%s requires analyzer context\n", id()->Name()); - Type* param_type = analyzer_context()->param_type(); - env_->AddID(analyzer_context_id, TEMP_VAR, param_type); - env_->SetEvaluated(analyzer_context_id); - env_->AddMacro(context_macro_id, new Expr(analyzer_context_id->clone())); - } + if ( RequiresAnalyzerContext::compute(type_) ) { + DEBUG_MSG("%s requires analyzer context\n", id()->Name()); + Type* param_type = analyzer_context()->param_type(); + env_->AddID(analyzer_context_id, TEMP_VAR, param_type); + env_->SetEvaluated(analyzer_context_id); + env_->AddMacro(context_macro_id, new Expr(analyzer_context_id->clone())); + } - // Add parameter "byteorder" - if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) - { - env_->AddID(byteorder_id, TEMP_VAR, extern_type_int); - env_->SetEvaluated(byteorder_id); - } + // Add parameter "byteorder" + if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) { + env_->AddID(byteorder_id, TEMP_VAR, extern_type_int); + env_->SetEvaluated(byteorder_id); + } - vector base_classes; + vector base_classes; - AddBaseClass(&base_classes); + AddBaseClass(&base_classes); - if ( type_->attr_refcount() ) - base_classes.push_back(kRefCountClass); + if ( type_->attr_refcount() ) + base_classes.push_back(kRefCountClass); - // The first line of class definition - out_h->println(""); - out_h->print("class %s final", class_name().c_str()); - bool first = true; - vector::iterator i; - for ( i = (&base_classes)->begin(); i != (&base_classes)->end(); ++i ) - { - if ( first ) - { - out_h->print(" : public %s", i->c_str()); - first = false; - } - else - out_h->print(", public %s", i->c_str()); - } - out_h->print("\n"); + // The first line of class definition + out_h->println(""); + out_h->print("class %s final", class_name().c_str()); + bool first = true; + vector::iterator i; + for ( i = base_classes.begin(); i != base_classes.end(); ++i ) { + if ( first ) { + out_h->print(" : public %s", i->c_str()); + first = false; + } + else + out_h->print(", public %s", i->c_str()); + } + out_h->print("\n"); - // Public members - out_h->println("{"); - out_h->println("public:"); - out_h->inc_indent(); + // Public members + out_h->println("{"); + out_h->println("public:"); + out_h->inc_indent(); - GenConstructorFunc(out_h, out_cc); - GenDestructorFunc(out_h, out_cc); + GenConstructorFunc(out_h, out_cc); + GenDestructorFunc(out_h, out_cc); - if ( type_->attr_length_expr() ) - GenInitialBufferLengthFunc(out_h, out_cc); + if ( type_->attr_length_expr() ) + GenInitialBufferLengthFunc(out_h, out_cc); - GenParseFunc(out_h, out_cc); + GenParseFunc(out_h, out_cc); - out_h->println(""); - out_h->println("// Member access functions"); - type_->GenPubDecls(out_h, env_); - out_h->println(""); + out_h->println(""); + out_h->println("// Member access functions"); + type_->GenPubDecls(out_h, env_); + out_h->println(""); - GenPubDecls(out_h, out_cc); + GenPubDecls(out_h, out_cc); - out_h->dec_indent(); - out_h->println("protected:"); - out_h->inc_indent(); + out_h->dec_indent(); + out_h->println("protected:"); + out_h->inc_indent(); - GenPrivDecls(out_h, out_cc); - type_->GenPrivDecls(out_h, env_); + GenPrivDecls(out_h, out_cc); + type_->GenPrivDecls(out_h, env_); - out_h->dec_indent(); - out_h->println("};\n"); - } + out_h->dec_indent(); + out_h->println("};\n"); +} -void TypeDecl::GenPubDecls(Output* out_h, Output* out_cc) - { - // GenParamPubDecls(params_, out_h, env_); - } +void TypeDecl::GenPubDecls(Output* out_h, Output* out_cc) { + // GenParamPubDecls(params_, out_h, env_); +} -void TypeDecl::GenPrivDecls(Output* out_h, Output* out_cc) - { - // GenParamPrivDecls(params_, out_h, env_); - } +void TypeDecl::GenPrivDecls(Output* out_h, Output* out_cc) { + // GenParamPrivDecls(params_, out_h, env_); +} -void TypeDecl::GenInitCode(Output* out_cc) { } +void TypeDecl::GenInitCode(Output* out_cc) {} -void TypeDecl::GenCleanUpCode(Output* out_cc) { } +void TypeDecl::GenCleanUpCode(Output* out_cc) {} -void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc) - { - string params_str = ParamDecls(params_); +void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc) { + string params_str = ParamDecls(params_); - string proto = strfmt("%s(%s)", class_name().c_str(), params_str.c_str()); + string proto = strfmt("%s(%s)", class_name().c_str(), params_str.c_str()); - out_h->println("%s;", proto.c_str()); + out_h->println("%s;", proto.c_str()); - out_cc->println("%s::%s", class_name().c_str(), proto.c_str()); - out_cc->inc_indent(); + out_cc->println("%s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("{"); - // GenParamAssignments(params_, out_cc, env_); + // GenParamAssignments(params_, out_cc, env_); - type_->GenInitCode(out_cc, env_); - GenInitCode(out_cc); + type_->GenInitCode(out_cc, env_); + GenInitCode(out_cc); - out_cc->println("}\n"); - out_cc->dec_indent(); - } + out_cc->println("}\n"); + out_cc->dec_indent(); +} -void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) - { - string proto = strfmt("~%s()", class_name().c_str()); +void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) { + string proto = strfmt("~%s()", class_name().c_str()); - out_h->println("%s;", proto.c_str()); + out_h->println("%s;", proto.c_str()); - out_cc->println("%s::%s", class_name().c_str(), proto.c_str()); - out_cc->inc_indent(); - out_cc->println("{"); + out_cc->println("%s::%s", class_name().c_str(), proto.c_str()); + out_cc->inc_indent(); + out_cc->println("{"); - GenCleanUpCode(out_cc); - type_->GenCleanUpCode(out_cc, env_); + GenCleanUpCode(out_cc); + type_->GenCleanUpCode(out_cc, env_); - out_cc->println("}\n"); - out_cc->dec_indent(); - } + out_cc->println("}\n"); + out_cc->dec_indent(); +} -string TypeDecl::ParseFuncPrototype(Env* env) - { - const char* func_name = nullptr; - const char* return_type = nullptr; - string params; +string TypeDecl::ParseFuncPrototype(Env* env) { + const char* func_name = nullptr; + const char* return_type = nullptr; + string params; - if ( type_->incremental_input() ) - { - func_name = kParseFuncWithBuffer; - return_type = "bool"; - params = strfmt("flow_buffer_t %s", env->LValue(flow_buffer_id)); - } - else - { - func_name = kParseFuncWithoutBuffer; - return_type = "int"; - params = strfmt("const_byteptr const %s, const_byteptr const %s", - env->LValue(begin_of_data), env->LValue(end_of_data)); - } + if ( type_->incremental_input() ) { + func_name = kParseFuncWithBuffer; + return_type = "bool"; + params = strfmt("flow_buffer_t %s", env->LValue(flow_buffer_id)); + } + else { + func_name = kParseFuncWithoutBuffer; + return_type = "int"; + params = strfmt("const_byteptr const %s, const_byteptr const %s", env->LValue(begin_of_data), + env->LValue(end_of_data)); + } - if ( RequiresAnalyzerContext::compute(type_) ) - { - Type* param_type = analyzer_context()->param_type(); - params += strfmt(", %s %s", param_type->DataTypeConstRefStr().c_str(), - env->LValue(analyzer_context_id)); - } + if ( RequiresAnalyzerContext::compute(type_) ) { + Type* param_type = analyzer_context()->param_type(); + params += strfmt(", %s %s", param_type->DataTypeConstRefStr().c_str(), env->LValue(analyzer_context_id)); + } - // Add parameter "byteorder" - if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) - { - params += strfmt(", int %s", env->LValue(byteorder_id)); - } + // Add parameter "byteorder" + if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) { + params += strfmt(", int %s", env->LValue(byteorder_id)); + } - // Returns " %s()%s". - return strfmt("%s %%s%s(%s)%%s", return_type, func_name, params.c_str()); - } + // Returns " %s()%s". + return strfmt("%s %%s%s(%s)%%s", return_type, func_name, params.c_str()); +} -void TypeDecl::GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data) - { - string ret_val_0, ret_val_1; +void TypeDecl::GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data) { + string ret_val_0, ret_val_1; - if ( type_->incremental_input() ) - { - ret_val_0 = type_->parsing_complete(env).c_str(); - ret_val_1 = "false"; - } - else - { - ret_val_0 = type_->DataSize(nullptr, env, data).c_str(); - ret_val_1 = "@@@"; + if ( type_->incremental_input() ) { + ret_val_0 = type_->parsing_complete(env).c_str(); + ret_val_1 = "false"; + } + else { + ret_val_0 = type_->DataSize(nullptr, env, data).c_str(); + ret_val_1 = "@@@"; - out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", env->RValue(begin_of_data), - ret_val_0.c_str(), env->RValue(end_of_data)); - } + out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", env->RValue(begin_of_data), ret_val_0.c_str(), + env->RValue(end_of_data)); + } - if ( type_->incremental_parsing() && - (type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY) ) - { - // In which case parsing may jump to label - // "need_more_data" ... - out_cc->println("BINPAC_ASSERT(%s);", type_->parsing_complete(env).c_str()); - out_cc->println("return %s;", ret_val_0.c_str()); + if ( type_->incremental_parsing() && (type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY) ) { + // In which case parsing may jump to label + // "need_more_data" ... + out_cc->println("BINPAC_ASSERT(%s);", type_->parsing_complete(env).c_str()); + out_cc->println("return %s;", ret_val_0.c_str()); - out_cc->println(""); - out_cc->dec_indent(); - out_cc->println("%s:", kNeedMoreData); - out_cc->inc_indent(); - out_cc->println("BINPAC_ASSERT(!(%s));", type_->parsing_complete(env).c_str()); - out_cc->println("return %s;", ret_val_1.c_str()); - } - else if ( type_->incremental_input() ) - { - out_cc->println("return %s;", ret_val_0.c_str()); - } - else - { - out_cc->println("return %s;", ret_val_0.c_str()); - } - } + out_cc->println(""); + out_cc->dec_indent(); + out_cc->println("%s:", kNeedMoreData); + out_cc->inc_indent(); + out_cc->println("BINPAC_ASSERT(!(%s));", type_->parsing_complete(env).c_str()); + out_cc->println("return %s;", ret_val_1.c_str()); + } + else if ( type_->incremental_input() ) { + out_cc->println("return %s;", ret_val_0.c_str()); + } + else { + out_cc->println("return %s;", ret_val_0.c_str()); + } +} -void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) - { - if ( type_->tot() == Type::DUMMY ) - return; +void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) { + if ( type_->tot() == Type::DUMMY ) + return; - // Env within the parse function - Env p_func_env(env_, this); - Env* env = &p_func_env; + // Env within the parse function + Env p_func_env(env_, this); + Env* env = &p_func_env; - if ( type_->incremental_input() ) - { - env->AddID(flow_buffer_id, TEMP_VAR, extern_type_flowbuffer); - env->SetEvaluated(flow_buffer_id); - } - else - { - env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); - env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); + if ( type_->incremental_input() ) { + env->AddID(flow_buffer_id, TEMP_VAR, extern_type_flowbuffer); + env->SetEvaluated(flow_buffer_id); + } + else { + env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); + env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); - env->SetEvaluated(begin_of_data); - env->SetEvaluated(end_of_data); - } + env->SetEvaluated(begin_of_data); + env->SetEvaluated(end_of_data); + } - string proto; - proto = ParseFuncPrototype(env); + string proto; + proto = ParseFuncPrototype(env); #if 0 if ( func_type == PARSE ) @@ -340,54 +300,48 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) } #endif - out_h->println(proto.c_str(), "", ";"); + out_h->println(proto.c_str(), "", ";"); - string tmp = strfmt("%s::", class_name().c_str()); - out_cc->println(proto.c_str(), tmp.c_str(), ""); - out_cc->inc_indent(); - out_cc->println("{"); + string tmp = strfmt("%s::", class_name().c_str()); + out_cc->println(proto.c_str(), tmp.c_str(), ""); + out_cc->inc_indent(); + out_cc->println("{"); - DataPtr data(env, nullptr, 0); + DataPtr data(env, nullptr, 0); - if ( ! type_->incremental_input() ) - data = DataPtr(env, begin_of_data, 0); - type_->GenParseCode(out_cc, env, data, 0); - GenParsingEnd(out_cc, env, data); + if ( ! type_->incremental_input() ) + data = DataPtr(env, begin_of_data, 0); + type_->GenParseCode(out_cc, env, data, 0); + GenParsingEnd(out_cc, env, data); - out_cc->println("}\n"); - out_cc->dec_indent(); - } + out_cc->println("}\n"); + out_cc->dec_indent(); +} -void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc) - { - string func(kInitialBufferLengthFunc); +void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc) { + string func(kInitialBufferLengthFunc); - int init_buffer_length = type_->InitialBufferLength(); + int init_buffer_length = type_->InitialBufferLength(); - if ( init_buffer_length < 0 ) // cannot be statically determined - { - throw Exception(type()->attr_length_expr(), strfmt("cannot determine initial buffer length" - " for type %s", - id_->Name())); - } + if ( init_buffer_length < 0 ) // cannot be statically determined + { + throw Exception(type()->attr_length_expr(), strfmt("cannot determine initial buffer length" + " for type %s", + id_->Name())); + } - out_h->println("int %s() const { return %d; }", func.c_str(), init_buffer_length); - } + out_h->println("int %s() const { return %d; }", func.c_str(), init_buffer_length); +} -Type* TypeDecl::LookUpType(const ID* id) - { - Decl* decl = LookUpDecl(id); - if ( ! decl ) - return nullptr; - switch ( decl->decl_type() ) - { - case TYPE: - case CONN: - case FLOW: - return static_cast(decl)->type(); - case ENUM: - return static_cast(decl)->DataType(); - default: - return nullptr; - } - } +Type* TypeDecl::LookUpType(const ID* id) { + Decl* decl = LookUpDecl(id); + if ( ! decl ) + return nullptr; + switch ( decl->decl_type() ) { + case TYPE: + case CONN: + case FLOW: return static_cast(decl)->type(); + case ENUM: return static_cast(decl)->DataType(); + default: return nullptr; + } +} diff --git a/tools/binpac/src/pac_typedecl.h b/tools/binpac/src/pac_typedecl.h index f7933d59b8..fa55fe4969 100644 --- a/tools/binpac/src/pac_typedecl.h +++ b/tools/binpac/src/pac_typedecl.h @@ -3,45 +3,44 @@ #include "pac_decl.h" -class TypeDecl : public Decl - { +class TypeDecl : public Decl { public: - TypeDecl(ID* arg_id, ParamList* arg_params, Type* arg_type); - ~TypeDecl() override; - void Prepare() override; - void GenForwardDeclaration(Output* out_h) override; - void GenCode(Output* out_h, Output* out_cc) override; + TypeDecl(ID* arg_id, ParamList* arg_params, Type* arg_type); + ~TypeDecl() override; + void Prepare() override; + void GenForwardDeclaration(Output* out_h) override; + void GenCode(Output* out_h, Output* out_cc) override; - Env* env() const override { return env_; } - Type* type() const { return type_; } - string class_name() const; - static Type* LookUpType(const ID* id); + Env* env() const override { return env_; } + Type* type() const { return type_; } + string class_name() const; + static Type* LookUpType(const ID* id); protected: - void AddParam(Param* param); - virtual void AddBaseClass(vector* base_classes) const { } - void ProcessAttr(Attr* a) override; + void AddParam(Param* param); + virtual void AddBaseClass(vector* base_classes) const {} + void ProcessAttr(Attr* a) override; - virtual void GenPubDecls(Output* out_h, Output* out_cc); - virtual void GenPrivDecls(Output* out_h, Output* out_cc); - virtual void GenInitCode(Output* out_cc); - virtual void GenCleanUpCode(Output* out_cc); + virtual void GenPubDecls(Output* out_h, Output* out_cc); + virtual void GenPrivDecls(Output* out_h, Output* out_cc); + virtual void GenInitCode(Output* out_cc); + virtual void GenCleanUpCode(Output* out_cc); - void GenConstructorFunc(Output* out_h, Output* out_cc); - void GenDestructorFunc(Output* out_h, Output* out_cc); + void GenConstructorFunc(Output* out_h, Output* out_cc); + void GenDestructorFunc(Output* out_h, Output* out_cc); - string ParseFuncPrototype(Env* env); - void GenParseFunc(Output* out_h, Output* out_cc); + string ParseFuncPrototype(Env* env); + void GenParseFunc(Output* out_h, Output* out_cc); - void GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data); + void GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data); - void GenInitialBufferLengthFunc(Output* out_h, Output* out_cc); + void GenInitialBufferLengthFunc(Output* out_h, Output* out_cc); protected: - Env* env_; + Env* env_; - ParamList* params_; - Type* type_; - }; + ParamList* params_; + Type* type_; +}; #endif // pac_typedecl_h diff --git a/tools/binpac/src/pac_utils.cc b/tools/binpac/src/pac_utils.cc index ea77fb6f86..c68c200af3 100644 --- a/tools/binpac/src/pac_utils.cc +++ b/tools/binpac/src/pac_utils.cc @@ -4,39 +4,34 @@ #include #include -char* copy_string(const char* s) - { - char* c = new char[strlen(s) + 1]; - strcpy(c, s); - return c; - } +char* copy_string(const char* s) { + char* c = new char[strlen(s) + 1]; + strcpy(c, s); + return c; +} -namespace - { +namespace { -const char* do_fmt(const char* format, va_list ap) - { - static char buf[1024]; - vsnprintf(buf, sizeof(buf), format, ap); - return buf; - } +const char* do_fmt(const char* format, va_list ap) { + static char buf[1024]; + vsnprintf(buf, sizeof(buf), format, ap); + return buf; +} - } +} // namespace -string strfmt(const char* format, ...) - { - va_list ap; - va_start(ap, format); - const char* r = do_fmt(format, ap); - va_end(ap); - return string(r); - } +string strfmt(const char* format, ...) { + va_list ap; + va_start(ap, format); + const char* r = do_fmt(format, ap); + va_end(ap); + return string(r); +} -char* nfmt(const char* format, ...) - { - va_list ap; - va_start(ap, format); - const char* r = do_fmt(format, ap); - va_end(ap); - return copy_string(r); - } +char* nfmt(const char* format, ...) { + va_list ap; + va_start(ap, format); + const char* r = do_fmt(format, ap); + va_end(ap); + return copy_string(r); +} diff --git a/tools/binpac/src/pac_varfield.cc b/tools/binpac/src/pac_varfield.cc index 897c6f5020..e0860f9241 100644 --- a/tools/binpac/src/pac_varfield.cc +++ b/tools/binpac/src/pac_varfield.cc @@ -1,6 +1,3 @@ #include "pac_varfield.h" -void PrivVarField::Prepare(Env* env) - { - Field::Prepare(env); - } +void PrivVarField::Prepare(Env* env) { Field::Prepare(env); } diff --git a/tools/binpac/src/pac_varfield.h b/tools/binpac/src/pac_varfield.h index 06e991e2c1..7d1685fd82 100644 --- a/tools/binpac/src/pac_varfield.h +++ b/tools/binpac/src/pac_varfield.h @@ -4,54 +4,37 @@ #include "pac_field.h" // A private variable evaluated with parsing -class ParseVarField : public Field - { +class ParseVarField : public Field { public: - ParseVarField(int is_class_member, ID* id, Type* type) - : Field(PARSE_VAR_FIELD, TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, id, - type) - { - } - void GenPubDecls(Output* out, Env* env) override - { /* do nothing */ - } - }; + ParseVarField(int is_class_member, ID* id, Type* type) + : Field(PARSE_VAR_FIELD, TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, id, type) {} + void GenPubDecls(Output* out, Env* env) override { /* do nothing */ + } +}; // A public variable -class PubVarField : public Field - { +class PubVarField : public Field { public: - PubVarField(ID* id, Type* type) - : Field(PUB_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) - { - } - ~PubVarField() override { } - }; + PubVarField(ID* id, Type* type) + : Field(PUB_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) {} + ~PubVarField() override {} +}; // A private variable -class PrivVarField : public Field - { +class PrivVarField : public Field { public: - PrivVarField(ID* id, Type* type) - : Field(PRIV_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, id, - type) - { - } - ~PrivVarField() override { } + PrivVarField(ID* id, Type* type) + : Field(PRIV_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, id, type) {} + ~PrivVarField() override {} - void GenPubDecls(Output* out, Env* env) override - { /* do nothing */ - } - }; + void GenPubDecls(Output* out, Env* env) override { /* do nothing */ + } +}; -class TempVarField : public Field - { +class TempVarField : public Field { public: - TempVarField(ID* id, Type* type) - : Field(TEMP_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, id, type) - { - } - ~TempVarField() override { } - }; + TempVarField(ID* id, Type* type) : Field(TEMP_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, id, type) {} + ~TempVarField() override {} +}; #endif // pac_varfield_h diff --git a/tools/binpac/src/pac_withinput.cc b/tools/binpac/src/pac_withinput.cc index 93ecf290ea..50b8a2b8ab 100644 --- a/tools/binpac/src/pac_withinput.cc +++ b/tools/binpac/src/pac_withinput.cc @@ -7,67 +7,54 @@ #include "pac_type.h" WithInputField::WithInputField(ID* id, Type* type, InputBuffer* input) - : Field(WITHINPUT_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), - input_(input) - { - ASSERT(type_); - ASSERT(input_); - } + : Field(WITHINPUT_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), input_(input) { + ASSERT(type_); + ASSERT(input_); +} -WithInputField::~WithInputField() - { - delete input_; - } +WithInputField::~WithInputField() { delete input_; } -bool WithInputField::DoTraverse(DataDepVisitor* visitor) - { - return Field::DoTraverse(visitor) && input()->Traverse(visitor); - } +bool WithInputField::DoTraverse(DataDepVisitor* visitor) { + return Field::DoTraverse(visitor) && input()->Traverse(visitor); +} -bool WithInputField::RequiresAnalyzerContext() const - { - return Field::RequiresAnalyzerContext() || (input() && input()->RequiresAnalyzerContext()); - } +bool WithInputField::RequiresAnalyzerContext() const { + return Field::RequiresAnalyzerContext() || (input() && input()->RequiresAnalyzerContext()); +} -void WithInputField::Prepare(Env* env) - { - Field::Prepare(env); - env->SetEvalMethod(id_, this); - } +void WithInputField::Prepare(Env* env) { + Field::Prepare(env); + env->SetEvalMethod(id_, this); +} -void WithInputField::GenEval(Output* out_cc, Env* env) - { - GenParseCode(out_cc, env); - if ( type_->attr_if_expr() ) - { - out_cc->println("BINPAC_ASSERT(%s);", env->RValue(type_->has_value_var())); - } - } +void WithInputField::GenEval(Output* out_cc, Env* env) { + GenParseCode(out_cc, env); + if ( type_->attr_if_expr() ) { + out_cc->println("BINPAC_ASSERT(%s);", env->RValue(type_->has_value_var())); + } +} -void WithInputField::GenParseCode(Output* out_cc, Env* env) - { - out_cc->println("// Parse \"%s\"", id_->Name()); - if ( type_->attr_if_expr() ) - { - // A conditional field - env->Evaluate(out_cc, type_->has_value_var()); - out_cc->println("if ( %s )", env->RValue(type_->has_value_var())); - out_cc->inc_indent(); - out_cc->println("{"); - } - else - out_cc->println("{"); +void WithInputField::GenParseCode(Output* out_cc, Env* env) { + out_cc->println("// Parse \"%s\"", id_->Name()); + if ( type_->attr_if_expr() ) { + // A conditional field + env->Evaluate(out_cc, type_->has_value_var()); + out_cc->println("if ( %s )", env->RValue(type_->has_value_var())); + out_cc->inc_indent(); + out_cc->println("{"); + } + else + out_cc->println("{"); - Env field_env(env, this); - ASSERT(! type_->incremental_input()); - type_->GenPreParsing(out_cc, &field_env); - type_->GenParseCode(out_cc, &field_env, input()->GenDataBeginEnd(out_cc, &field_env), 0); + Env field_env(env, this); + ASSERT(! type_->incremental_input()); + type_->GenPreParsing(out_cc, &field_env); + type_->GenParseCode(out_cc, &field_env, input()->GenDataBeginEnd(out_cc, &field_env), 0); - if ( type_->attr_if_expr() ) - { - out_cc->println("}"); - out_cc->dec_indent(); - } - else - out_cc->println("}"); - } + if ( type_->attr_if_expr() ) { + out_cc->println("}"); + out_cc->dec_indent(); + } + else + out_cc->println("}"); +} diff --git a/tools/binpac/src/pac_withinput.h b/tools/binpac/src/pac_withinput.h index aee1c3d7b9..fb9827257e 100644 --- a/tools/binpac/src/pac_withinput.h +++ b/tools/binpac/src/pac_withinput.h @@ -5,34 +5,33 @@ #include "pac_decl.h" #include "pac_field.h" -class WithInputField : public Field, public Evaluatable - { +class WithInputField : public Field, public Evaluatable { public: - WithInputField(ID* id, Type* type, InputBuffer* input); - ~WithInputField() override; + WithInputField(ID* id, Type* type, InputBuffer* input); + ~WithInputField() override; - InputBuffer* input() const { return input_; } + InputBuffer* input() const { return input_; } - void Prepare(Env* env) override; + void Prepare(Env* env) override; - // void GenPubDecls(Output* out, Env* env); - // void GenPrivDecls(Output* out, Env* env); + // void GenPubDecls(Output* out, Env* env); + // void GenPrivDecls(Output* out, Env* env); - // void GenInitCode(Output* out, Env* env); - // void GenCleanUpCode(Output* out, Env* env); + // void GenInitCode(Output* out, Env* env); + // void GenCleanUpCode(Output* out, Env* env); - void GenParseCode(Output* out, Env* env); + void GenParseCode(Output* out, Env* env); - // Instantiate the Evaluatable interface - void GenEval(Output* out, Env* env) override; + // Instantiate the Evaluatable interface + void GenEval(Output* out, Env* env) override; - bool RequiresAnalyzerContext() const override; + bool RequiresAnalyzerContext() const override; protected: - bool DoTraverse(DataDepVisitor* visitor) override; + bool DoTraverse(DataDepVisitor* visitor) override; protected: - InputBuffer* input_; - }; + InputBuffer* input_; +}; #endif // pac_withinput_h From 964817f9bfcc5059b042c85d21e370844bf39ae5 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 30 Oct 2023 13:16:15 -0700 Subject: [PATCH 134/343] binpac: Add cmake-format and typos pre-commit configs --- tools/binpac/CMakeLists.txt | 70 ++++++++++---------- tools/binpac/lib/CMakeLists.txt | 80 +++++++++++------------ tools/binpac/lib/binpac.h.in | 6 ++ tools/binpac/lib/binpac_buffer.h | 2 +- tools/binpac/patches/binpac-patch-doc.txt | 2 +- tools/binpac/src/CMakeLists.txt | 46 +++++++------ tools/binpac/src/pac_expr.h | 2 +- tools/binpac/src/pac_exttype.h | 4 +- 8 files changed, 108 insertions(+), 104 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 92d9abc0f8..5076cfa68e 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -14,49 +14,48 @@ set(BINPAC_SOVERSION 0) set(ENABLE_SHARED true) -if ( ENABLE_STATIC_ONLY ) +if(ENABLE_STATIC_ONLY) set(ENABLE_STATIC true) set(ENABLE_SHARED false) -endif () +endif() # Set default install paths include(GNUInstallDirs) -######################################################################## -## Dependency Configuration +# ############################################################################## +# Dependency Configuration find_package(FLEX REQUIRED) find_package(BISON REQUIRED) -if (MSVC) +if(MSVC) add_compile_options(/J) # Similar to -funsigned-char on other platforms endif() -######################################################################## -## System Introspection +# ############################################################################## +# System Introspection -configure_file(${PROJECT_SOURCE_DIR}/config.h.in - ${PROJECT_BINARY_DIR}/config.h) +configure_file(${PROJECT_SOURCE_DIR}/config.h.in ${PROJECT_BINARY_DIR}/config.h) include_directories(BEFORE ${PROJECT_BINARY_DIR}) -######################################################################## -## Recurse on sub-directories +# ############################################################################## +# Recurse on sub-directories add_subdirectory(lib) add_subdirectory(src) -######################################################################## -## Build Summary +# ############################################################################## +# Build Summary -if (CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) -endif () +if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) +endif() macro(display test desc summary) - if ( ${test} ) + if(${test}) set(${summary} ${desc}) - else () + else() set(${summary} no) endif() endmacro() @@ -65,23 +64,22 @@ display(ENABLE_SHARED yes shared_summary) display(ENABLE_STATIC yes static_summary) message( - "\n==================| BinPAC Build Summary |====================" - "\nVersion: ${BINPAC_VERSION}" - "\nSO version: ${BINPAC_SOVERSION}" - "\n" - "\nBuild Type: ${CMAKE_BUILD_TYPE}" - "\nDebug mode: ${ENABLE_DEBUG}" - "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" - "\nShared libs: ${shared_summary}" - "\nStatic libs: ${static_summary}" - "\n" - "\nCC: ${CMAKE_C_COMPILER}" - "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" - "\nCXX: ${CMAKE_CXX_COMPILER}" - "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" - "\nCPP: ${CMAKE_CXX_COMPILER}" - "\n" - "\n================================================================\n" -) + "\n==================| BinPAC Build Summary |====================" + "\nVersion: ${BINPAC_VERSION}" + "\nSO version: ${BINPAC_SOVERSION}" + "\n" + "\nBuild Type: ${CMAKE_BUILD_TYPE}" + "\nDebug mode: ${ENABLE_DEBUG}" + "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nShared libs: ${shared_summary}" + "\nStatic libs: ${static_summary}" + "\n" + "\nCC: ${CMAKE_C_COMPILER}" + "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" + "\nCXX: ${CMAKE_CXX_COMPILER}" + "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" + "\nCPP: ${CMAKE_CXX_COMPILER}" + "\n" + "\n================================================================\n") include(UserChangedWarning) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index 219018edb6..0c5bf15a57 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -7,61 +7,55 @@ check_type_size("unsigned int" SIZEOF_UNSIGNED_INT) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/binpac.h.in ${CMAKE_CURRENT_BINARY_DIR}/binpac.h) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) set(binpac_headers - ${CMAKE_CURRENT_BINARY_DIR}/binpac.h - binpac_analyzer.h - binpac_buffer.h - binpac_bytestring.h - binpac_exception.h - binpac_regex.h -) + ${CMAKE_CURRENT_BINARY_DIR}/binpac.h binpac_analyzer.h binpac_buffer.h + binpac_bytestring.h binpac_exception.h binpac_regex.h) -set(binpac_lib_SRCS - binpac_buffer.cc - binpac_bytestring.cc - binpac_regex.cc - ${binpac_headers} -) +set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc binpac_regex.cc + ${binpac_headers}) -if ( ENABLE_SHARED ) +if(ENABLE_SHARED) add_library(binpac_lib SHARED ${binpac_lib_SRCS}) target_compile_features(binpac_lib PRIVATE cxx_std_17) - set_target_properties(binpac_lib PROPERTIES - CXX_EXTENSIONS OFF - SOVERSION ${BINPAC_SOVERSION} - VERSION ${BINPAC_VERSION_MAJOR}.${BINPAC_VERSION_MINOR} - MACOSX_RPATH true - OUTPUT_NAME binpac) + set_target_properties( + binpac_lib + PROPERTIES CXX_EXTENSIONS OFF + SOVERSION ${BINPAC_SOVERSION} + VERSION ${BINPAC_VERSION_MAJOR}.${BINPAC_VERSION_MINOR} + MACOSX_RPATH true + OUTPUT_NAME binpac) install(TARGETS binpac_lib DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif () +endif() -if ( ENABLE_STATIC ) +if(ENABLE_STATIC) add_library(binpac_static STATIC ${binpac_lib_SRCS}) target_compile_features(binpac_static PRIVATE cxx_std_17) - set_target_properties(binpac_static PROPERTIES - CXX_EXTENSIONS OFF - OUTPUT_NAME binpac) + set_target_properties(binpac_static PROPERTIES CXX_EXTENSIONS OFF OUTPUT_NAME + binpac) install(TARGETS binpac_static DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif () +endif() -if ( ZEEK_ROOT_DIR ) - # Installed in binpac subdir just for organization purposes. - install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/binpac) -else () - install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -endif () +if(ZEEK_ROOT_DIR) + # Installed in binpac subdir just for organization purposes. + install(FILES ${binpac_headers} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/binpac) +else() + install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +endif() -# This is set to assist superprojects that want to build BinPac -# from source and rely on it as a target -if ( ENABLE_SHARED ) - set(BinPAC_LIBRARY binpac_lib CACHE STRING "BinPAC library" FORCE) -else () - set(BinPAC_LIBRARY binpac_static CACHE STRING "BinPAC library" FORCE) -endif () +# This is set to assist superprojects that want to build BinPac from source and +# rely on it as a target +if(ENABLE_SHARED) + set(BinPAC_LIBRARY + binpac_lib + CACHE STRING "BinPAC library" FORCE) +else() + set(BinPAC_LIBRARY + binpac_static + CACHE STRING "BinPAC library" FORCE) +endif() set(BinPAC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} - CACHE STRING "BinPAC header directories" FORCE -) + CACHE STRING "BinPAC header directories" FORCE) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index 59dab550c3..ad11509953 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -72,6 +72,8 @@ inline uint16 pac_swap(const uint16 x) inline int16 pac_swap(const int16 x) { + // Forward to unsigned version with argument/result casted + // appropriately. uint16 (*p)(const uint16) = &pac_swap; return (*p)(x); } @@ -86,6 +88,8 @@ inline uint32 pac_swap(const uint32 x) inline int32 pac_swap(const int32 x) { + // Forward to unsigned version with argument/result casted + // appropriately. uint32 (*p)(const uint32) = &pac_swap; return (*p)(x); } @@ -104,6 +108,8 @@ inline uint64 pac_swap(const uint64 x) inline int64 pac_swap(const int64 x) { + // Forward to unsigned version with argument/result casted + // appropriately. uint64 (*p)(const uint64) = &pac_swap; return (*p)(x); } diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h index 3eb118e71c..a4de6d66e9 100644 --- a/tools/binpac/lib/binpac_buffer.h +++ b/tools/binpac/lib/binpac_buffer.h @@ -31,7 +31,7 @@ public: // Interface for delayed parsing. Sometimes BinPAC doesn't get the // buffering right and then one can use these to feed parts // individually and assemble them internally. After calling - // FinishBuffer(), one can send the uppper-layer flow an FlowEOF() to + // FinishBuffer(), one can send the upper-layer flow an FlowEOF() to // trigger parsing. void BufferData(const_byteptr data, const_byteptr end); void FinishBuffer(); diff --git a/tools/binpac/patches/binpac-patch-doc.txt b/tools/binpac/patches/binpac-patch-doc.txt index 052285eaea..ab0f406c75 100644 --- a/tools/binpac/patches/binpac-patch-doc.txt +++ b/tools/binpac/patches/binpac-patch-doc.txt @@ -62,7 +62,7 @@ numbers of issues below correspond to the patch numbers in cases - problem: initialization of buffer occurs in every Parse call, regardless if it was initialized before or not; initialization - is correct only on first such occurence + is correct only on first such occurrence - solution: check to buffer_state is to be created always when buffering_state_id is in environment in Type::GenBufferConfig - changed condition from buffering_state_var_field_ to diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 1cfb83f505..0c21b9024c 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -1,16 +1,22 @@ -bison_target(PACParser pac_parse.yy ${BinPAC_BINARY_DIR}/src/pac_parse.cc - DEFINES_FILE ${BinPAC_BINARY_DIR}/src/pac_parse.h - COMPILE_FLAGS "--debug") +bison_target( + PACParser pac_parse.yy ${BinPAC_BINARY_DIR}/src/pac_parse.cc + DEFINES_FILE ${BinPAC_BINARY_DIR}/src/pac_parse.h + COMPILE_FLAGS "--debug") flex_target(PACScanner pac_scan.ll ${BinPAC_BINARY_DIR}/pac_scan.cc) add_flex_bison_dependency(PACScanner PACParser) -if (MSVC) - set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") +if(MSVC) + set_property( + SOURCE pac_scan.cc + APPEND_STRING + PROPERTY COMPILE_FLAGS "/wd4018") else() - set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") + set_property( + SOURCE pac_scan.cc + APPEND_STRING + PROPERTY COMPILE_FLAGS "-Wno-sign-compare") endif() -include_directories(${PROJECT_SOURCE_DIR}/src - ${PROJECT_BINARY_DIR}/src) +include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src) set(binpac_SRCS ${BISON_PACParser_INPUT} @@ -98,25 +104,25 @@ set(binpac_SRCS pac_typedecl.h pac_utils.h pac_varfield.h - pac_withinput.h -) + pac_withinput.h) add_executable(binpac ${binpac_SRCS}) target_compile_features(binpac PRIVATE cxx_std_17) set_target_properties(binpac PROPERTIES CXX_EXTENSIONS OFF) -if ( MSVC ) - # If building separately from zeek, we need to add the libunistd subdirectory so - # that linking doesn't fail. - if ("${CMAKE_PROJECT_NAME}" STREQUAL "BinPAC") - add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) - endif() - target_link_libraries(binpac PRIVATE libunistd) +if(MSVC) + # If building separately from zeek, we need to add the libunistd subdirectory + # so that linking doesn't fail. + if("${CMAKE_PROJECT_NAME}" STREQUAL "BinPAC") + add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) + endif() + target_link_libraries(binpac PRIVATE libunistd) endif() install(TARGETS binpac DESTINATION bin) -# This is set to assist superprojects that want to build BinPac -# from source and rely on it as a target -set(BinPAC_EXE binpac +# This is set to assist superprojects that want to build BinPac from source and +# rely on it as a target +set(BinPAC_EXE + binpac CACHE STRING "BinPAC executable" FORCE) diff --git a/tools/binpac/src/pac_expr.h b/tools/binpac/src/pac_expr.h index 8d50c904e3..07c33f9dc1 100644 --- a/tools/binpac/src/pac_expr.h +++ b/tools/binpac/src/pac_expr.h @@ -55,7 +55,7 @@ public: // const char* EvalExpr(Output* out, Env* env); - // force evaulation of IDs contained in this expression; + // force evaluation of IDs contained in this expression; // necessary with case expr and conditional let fields (&if) // for correct parsing of fields void ForceIDEval(Output* out_cc, Env* env); diff --git a/tools/binpac/src/pac_exttype.h b/tools/binpac/src/pac_exttype.h index a5eaaa35be..1abe5e50dc 100644 --- a/tools/binpac/src/pac_exttype.h +++ b/tools/binpac/src/pac_exttype.h @@ -5,8 +5,8 @@ // ExternType represent external C++ types that are not defined in // PAC specification (therefore they cannot appear in data layout -// spefication, e.g., in a record field). The type name is copied -// literally to the compiled code. +// specification, e.g., in a record field). The type name is copied +// literally to the compiled code. class ExternType : public Type { public: From dacfe747b9d12da1a104f9ba954cfc4513390d9b Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 25 Apr 2024 12:42:54 -0700 Subject: [PATCH 135/343] binpac: Format output closer to what clang-format would output --- tools/binpac/src/pac_action.cc | 5 ++-- tools/binpac/src/pac_array.cc | 32 +++++++++------------ tools/binpac/src/pac_btype.cc | 10 +++---- tools/binpac/src/pac_case.cc | 41 ++++++++++++++------------- tools/binpac/src/pac_conn.cc | 15 ++++------ tools/binpac/src/pac_ctype.cc | 6 ++-- tools/binpac/src/pac_dataptr.cc | 5 ++-- tools/binpac/src/pac_expr.cc | 5 ++-- tools/binpac/src/pac_flow.cc | 43 +++++++++++----------------- tools/binpac/src/pac_func.cc | 12 +++----- tools/binpac/src/pac_let.cc | 5 ++-- tools/binpac/src/pac_output.cc | 7 ++++- tools/binpac/src/pac_paramtype.cc | 2 +- tools/binpac/src/pac_record.cc | 28 ++++++++---------- tools/binpac/src/pac_strtype.cc | 10 +++---- tools/binpac/src/pac_type.cc | 47 ++++++++++++++----------------- tools/binpac/src/pac_type.h | 2 +- tools/binpac/src/pac_typedecl.cc | 22 ++++++--------- tools/binpac/src/pac_withinput.cc | 5 ++-- 19 files changed, 132 insertions(+), 170 deletions(-) diff --git a/tools/binpac/src/pac_action.cc b/tools/binpac/src/pac_action.cc index 05cd611029..2863f65402 100644 --- a/tools/binpac/src/pac_action.cc +++ b/tools/binpac/src/pac_action.cc @@ -34,15 +34,14 @@ void AnalyzerAction::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) out_h->println("void %s;", action_func_proto.c_str()); - out_cc->println("void %s::%s", decl->class_name().c_str(), action_func_proto.c_str()); + out_cc->println("void %s::%s {", decl->class_name().c_str(), action_func_proto.c_str()); out_cc->inc_indent(); - out_cc->println("{"); code_->GenCode(out_cc, &action_func_env); out_cc->println(""); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); out_cc->println(""); } diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index bf7710a7e4..b59d9a43a1 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -42,7 +42,7 @@ void ArrayType::init() { vector_str_ = strfmt("vector<%s>", elemtype_->DataTypeStr().c_str()); - datatype_str_ = strfmt("%s *", vector_str_.c_str()); + datatype_str_ = strfmt("%s*", vector_str_.c_str()); attr_generic_until_expr_ = nullptr; attr_until_element_expr_ = nullptr; @@ -210,14 +210,13 @@ void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data) { env->SetEvaluated(arraylength_var()); // Check negative array length - out_cc->println("if ( %s < 0 )", env->LValue(arraylength_var())); + out_cc->println("if ( %s < 0 ) {", env->LValue(arraylength_var())); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); out_cc->println(" %s, (%s) - (%s));", env->LValue(arraylength_var()), env->RValue(end_of_data), env->RValue(begin_of_data)); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); int element_size; @@ -309,19 +308,17 @@ void ArrayType::GenCleanUpCode(Output* out_cc, Env* env) { elem_var_field_->Prepare(env); } - out_cc->println("if ( %s )", env->RValue(value_var())); + out_cc->println("if ( %s ) {", env->RValue(value_var())); out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("for ( auto* %s : *%s )", env->LValue(elem_var()), env->RValue(value_var())); + out_cc->println("for ( auto* %s : *%s ) {", env->LValue(elem_var()), env->RValue(value_var())); out_cc->inc_indent(); - out_cc->println("{"); elemtype_->GenCleanUpCode(out_cc, env); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } out_cc->println("delete %s;", lvalue()); } @@ -331,9 +328,8 @@ string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length array_str = lvalue(); if ( incremental_parsing() ) { - out_cc->println("if ( %s < 0 )", env->LValue(elem_it_var())); + out_cc->println("if ( %s < 0 ) {", env->LValue(elem_it_var())); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("// Initialize only once"); out_cc->println("%s = 0;", env->LValue(elem_it_var())); } @@ -345,8 +341,8 @@ string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length } if ( incremental_parsing() ) { - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } return array_str; @@ -426,9 +422,8 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in strfmt("%s < %s", env->LValue(elem_it_var()), env->RValue(arraylength_var())) : "/* forever */"; - out_cc->println("for (; %s; ++%s)", for_condition.c_str(), env->LValue(elem_it_var())); + out_cc->println("for (; %s; ++%s) {", for_condition.c_str(), env->LValue(elem_it_var())); out_cc->inc_indent(); - out_cc->println("{"); if ( attr_generic_until_expr_ ) GenUntilCheck(out_cc, env, attr_generic_until_expr_, true); @@ -472,8 +467,8 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in if ( elemtype_->IsPointerType() ) out_cc->println("%s = nullptr;", env->LValue(elem_var())); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); out_cc->dec_indent(); out_cc->println("%s: ;", end_of_array_loop_label_.c_str()); @@ -508,9 +503,8 @@ void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool d } out_cc->println("// Check &until(%s)", until_expr->orig()); - out_cc->println("if ( %s )", until_expr->EvalExpr(out_cc, &check_env)); + out_cc->println("if ( %s ) {", until_expr->EvalExpr(out_cc, &check_env)); out_cc->inc_indent(); - out_cc->println("{"); if ( parsing_complete_var() ) { out_cc->println("%s = true;", env->LValue(parsing_complete_var())); } @@ -523,8 +517,8 @@ void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool d } out_cc->println("goto %s;", end_of_array_loop_label_.c_str()); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } void ArrayType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { diff --git a/tools/binpac/src/pac_btype.cc b/tools/binpac/src/pac_btype.cc index 9be860bc6c..d56b9ab6df 100644 --- a/tools/binpac/src/pac_btype.cc +++ b/tools/binpac/src/pac_btype.cc @@ -94,7 +94,7 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, case INT8: case UINT8: - out_cc->println("%s = *((%s const *) (%s));", lvalue(), DataTypeStr().c_str(), data.ptr_expr()); + out_cc->println("%s = *((%s const*)(%s));", lvalue(), DataTypeStr().c_str(), data.ptr_expr()); break; case INT16: case UINT16: @@ -104,13 +104,13 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, case UINT64: #if 0 out_cc->println("%s = UnMarshall<%s>(%s, %s);", - lvalue(), - DataTypeStr().c_str(), + lvalue(), + DataTypeStr().c_str(), data.ptr_expr(), EvalByteOrder(out_cc, env).c_str()); #else - out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", lvalue(), - EvalByteOrder(out_cc, env).c_str(), DataTypeStr().c_str(), data.ptr_expr()); + out_cc->println("%s = FixByteOrder(%s, *((%s const*)(%s)));", lvalue(), EvalByteOrder(out_cc, env).c_str(), + DataTypeStr().c_str(), data.ptr_expr()); #endif break; } diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index a2131ca2d4..187eaf37c8 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -36,7 +36,7 @@ bool CaseType::DefineValueVar() const { return false; } string CaseType::DataTypeStr() const { ASSERT(type_decl()); - return strfmt("%s *", type_decl()->class_name().c_str()); + return strfmt("%s*", type_decl()->class_name().c_str()); } Type* CaseType::ValueType() const { @@ -117,15 +117,14 @@ void CaseType::GenCleanUpCode(Output* out_cc, Env* env) { Type::GenCleanUpCode(out_cc, env); env->set_in_branch(true); - out_cc->println("switch ( %s )", env->RValue(index_var_)); + out_cc->println("switch ( %s ) {", env->RValue(index_var_)); out_cc->inc_indent(); - out_cc->println("{"); foreach (i, CaseFieldList, cases_) { CaseField* c = *i; c->GenCleanUpCode(out_cc, env); } - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); env->set_in_branch(false); } @@ -142,9 +141,8 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int env->SetEvaluated(index_var_); env->set_in_branch(true); - out_cc->println("switch ( %s )", env->RValue(index_var_)); + out_cc->println("switch ( %s ) {", env->RValue(index_var_)); out_cc->inc_indent(); - out_cc->println("{"); bool has_default_case = false; foreach (i, CaseFieldList, cases_) { CaseField* c = *i; @@ -161,8 +159,8 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int out_cc->println("break;"); out_cc->dec_indent(); } - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); env->set_in_branch(false); if ( compute_size_var ) @@ -282,7 +280,7 @@ void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_typ // We're always using "int" for storage, so ok to just // cast into the type used by the switch statement since // some unsafe stuff is already checked above. - out_cc->println("case ((%s) %d):", switch_type->DataTypeStr().c_str(), index_const); + out_cc->println("case ((%s)%d):", switch_type->DataTypeStr().c_str(), index_const); } } else { @@ -303,17 +301,14 @@ void CaseField::GenPubDecls(Output* out_h, Env* env) { if ( type_->DataTypeStr().empty() ) return; - out_h->println("%s %s const", type_->DataTypeConstRefStr().c_str(), env->RValue(id_)); - + out_h->println("%s %s const {", type_->DataTypeConstRefStr().c_str(), env->RValue(id_)); out_h->inc_indent(); - out_h->println("{"); if ( ! index_ ) out_h->println("return %s;", lvalue()); else { - out_h->println("switch ( %s )", env->RValue(index_var_)); + out_h->println("switch ( %s ) {", env->RValue(index_var_)); out_h->inc_indent(); - out_h->println("{"); GenCaseStr(index_, out_h, env, case_type()->IndexExpr()->DataType(env)); out_h->inc_indent(); out_h->println("break; // OK"); @@ -326,14 +321,14 @@ void CaseField::GenPubDecls(Output* out_h, Env* env) { out_h->println("break;"); out_h->dec_indent(); - out_h->println("}"); out_h->dec_indent(); + out_h->println("}"); out_h->println("return %s;", lvalue()); } - out_h->println("}"); out_h->dec_indent(); + out_h->println("}"); } void CaseField::GenInitCode(Output* out_cc, Env* env) { @@ -351,10 +346,16 @@ void CaseField::GenCleanUpCode(Output* out_cc, Env* env) { GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); out_cc->inc_indent(); out_cc->println("// Clean up \"%s\"", id_->Name()); - out_cc->println("{"); - if ( ! anonymous_field() ) + if ( ! anonymous_field() ) { + out_cc->println("{"); + out_cc->inc_indent(); type_->GenCleanUpCode(out_cc, env); - out_cc->println("}"); + out_cc->dec_indent(); + out_cc->println("}"); + } + else + out_cc->println("{}"); + out_cc->println("break;"); out_cc->dec_indent(); } @@ -364,6 +365,7 @@ void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, cons out_cc->inc_indent(); out_cc->println("// Parse \"%s\"", id_->Name()); out_cc->println("{"); + out_cc->inc_indent(); { Env case_env(env, this); @@ -378,9 +380,10 @@ void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, cons out_cc->println("%s = %s;", case_env.LValue(case_type()->parsing_complete_var()), case_env.RValue(type_->parsing_complete_var())); } - out_cc->println("}"); } + out_cc->dec_indent(); + out_cc->println("}"); out_cc->println("break;"); out_cc->dec_indent(); } diff --git a/tools/binpac/src/pac_conn.cc b/tools/binpac/src/pac_conn.cc index 4d04c690ec..4e7bc01cfe 100644 --- a/tools/binpac/src/pac_conn.cc +++ b/tools/binpac/src/pac_conn.cc @@ -63,9 +63,8 @@ void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc) { out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->println("void %s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("if ( is_orig )"); out_cc->inc_indent(); @@ -81,8 +80,8 @@ void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc) { out_cc->dec_indent(); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); out_cc->println(""); } @@ -91,9 +90,8 @@ void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc) { out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->println("void %s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("if ( is_orig )"); out_cc->inc_indent(); @@ -104,8 +102,8 @@ void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc) { out_cc->println("%s->%s(gap_length);", env_->LValue(downflow_id), kFlowGap); out_cc->dec_indent(); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); out_cc->println(""); } @@ -114,9 +112,8 @@ void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc) { out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->println("void %s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("if ( is_orig )"); out_cc->inc_indent(); @@ -127,7 +124,7 @@ void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc) { out_cc->println("%s->%s(begin, end);", env_->LValue(downflow_id), kNewData); out_cc->dec_indent(); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); out_cc->println(""); } diff --git a/tools/binpac/src/pac_ctype.cc b/tools/binpac/src/pac_ctype.cc index 3ef8003472..cb36a9f51c 100644 --- a/tools/binpac/src/pac_ctype.cc +++ b/tools/binpac/src/pac_ctype.cc @@ -3,11 +3,11 @@ string CType::DeclareInstance(const string& var) const { return strfmt("%s %s", name().c_str(), var.c_str()); } string CType::DeclareConstReference(const string& var) const { - return strfmt("%s const &%s", name().c_str(), var.c_str()); + return strfmt("%s const& %s", name().c_str(), var.c_str()); } string CType::DeclareConstPointer(const string& var) const { - return strfmt("%s const *%s", name().c_str(), var.c_str()); + return strfmt("%s const* %s", name().c_str(), var.c_str()); } -string CType::DeclarePointer(const string& var) const { return strfmt("%s *%s", name().c_str(), var.c_str()); } +string CType::DeclarePointer(const string& var) const { return strfmt("%s* %s", name().c_str(), var.c_str()); } diff --git a/tools/binpac/src/pac_dataptr.cc b/tools/binpac/src/pac_dataptr.cc index 1b3d19606c..53d44e60b0 100644 --- a/tools/binpac/src/pac_dataptr.cc +++ b/tools/binpac/src/pac_dataptr.cc @@ -32,11 +32,10 @@ void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size, ASSERT(id_); out_cc->println("// Checking out-of-bound for \"%s\"", data_name); - out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", ptr_expr(), data_size, env->RValue(end_of_data), + out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s ) {", ptr_expr(), data_size, env->RValue(end_of_data), ptr_expr(), data_size, ptr_expr()); out_cc->inc_indent(); - out_cc->println("{"); char* data_offset = AbsOffsetExpr(env, begin_of_data); @@ -47,6 +46,6 @@ void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size, delete[] data_offset; - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index 98fd1e29f7..4f74859f72 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -209,11 +209,10 @@ void Expr::GenCaseEval(Output* out_cc, Env* env) { foreach (i, CaseExprList, cases_) (*i)->value()->ForceIDEval(out_cc, env); - out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); + out_cc->println("switch ( %s ) {", operand_[0]->EvalExpr(out_cc, env)); Type* switch_type = operand_[0]->DataType(env); out_cc->inc_indent(); - out_cc->println("{"); CaseExpr* default_case = nullptr; foreach (i, CaseExprList, cases_) { @@ -246,8 +245,8 @@ void Expr::GenCaseEval(Output* out_cc, Env* env) { out_cc->println("break;"); out_cc->dec_indent(); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); env->SetEvaluated(val_var); str_ = env->RValue(val_var); diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index 72c8a83b64..2138acb573 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -112,9 +112,8 @@ void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc) { out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->println("void %s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); - out_cc->println("{"); foreach (i, AnalyzerHelperList, eof_helpers_) { (*i)->GenCode(nullptr, out_cc, this); @@ -125,8 +124,8 @@ void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc) { out_cc->println("%s(nullptr, nullptr);", kNewData); } - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc) { @@ -134,16 +133,15 @@ void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc) { out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->println("void %s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); - out_cc->println("{"); if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { out_cc->println("%s->NewGap(gap_length);", env_->LValue(flow_buffer_id)); } - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc) { @@ -155,13 +153,11 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc) { out_h->println("void %s;", proto.c_str()); - out_cc->println("void %s::%s", class_name().c_str(), proto.c_str()); + out_cc->println("void %s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); - out_cc->println("{"); - out_cc->println("try"); + out_cc->println("try {"); out_cc->inc_indent(); - out_cc->println("{"); env_->SetEvaluated(begin_of_data); env_->SetEvaluated(end_of_data); @@ -172,22 +168,20 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc) { default: ASSERT(0); } - out_cc->println("}"); out_cc->dec_indent(); - out_cc->println("catch ( binpac::Exception const &e )"); + out_cc->println("} catch ( binpac::Exception const& e ) {"); out_cc->inc_indent(); - out_cc->println("{"); GenCleanUpCode(out_cc); if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) { out_cc->println("%s->DiscardData();", env_->LValue(flow_buffer_id)); } out_cc->println("throw e;"); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); out_cc->println(""); } @@ -216,41 +210,36 @@ void FlowDecl::GenCodeFlowUnit(Output* out_cc) { out_cc->println("while ( %s->data_available() && ", env_->LValue(flow_buffer_id)); out_cc->inc_indent(); - out_cc->println("( !%s->have_pending_request() || %s->ready() ) )", env_->LValue(flow_buffer_id), + out_cc->println("( !%s->have_pending_request() || %s->ready() ) ) {", env_->LValue(flow_buffer_id), env_->LValue(flow_buffer_id)); - out_cc->println("{"); // Generate a new dataunit if necessary - out_cc->println("if ( ! %s )", env_->LValue(dataunit_id)); + out_cc->println("if ( ! %s ) {", env_->LValue(dataunit_id)); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("BINPAC_ASSERT(!%s);", env_->LValue(analyzer_context_id)); GenNewDataUnit(out_cc); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); DataPtr data(env_, nullptr, 0); unit_datatype->GenParseCode(out_cc, env_, data, 0); - out_cc->println("if ( %s )", unit_datatype->parsing_complete(env_).c_str()); + out_cc->println("if ( %s ) {", unit_datatype->parsing_complete(env_).c_str()); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("// Clean up the flow unit after parsing"); GenDeleteDataUnit(out_cc); // out_cc->println("BINPAC_ASSERT(%s == 0);", env_->LValue(dataunit_id)); - out_cc->println("}"); out_cc->dec_indent(); - out_cc->println("else"); + out_cc->println("} else {"); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("// Resume upon next input segment"); out_cc->println("BINPAC_ASSERT(!%s->ready());", env_->RValue(flow_buffer_id)); out_cc->println("break;"); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } void FlowDecl::GenCodeDatagram(Output* out_cc) { diff --git a/tools/binpac/src/pac_func.cc b/tools/binpac/src/pac_func.cc index 3aa6d17811..6c1e3804aa 100644 --- a/tools/binpac/src/pac_func.cc +++ b/tools/binpac/src/pac_func.cc @@ -51,27 +51,23 @@ void Function::GenCode(Output* out_h, Output* out_cc) { ASSERT(! (expr_ && code_)); if ( expr_ ) { - out_cc->println("%s", proto_str.c_str()); - + out_cc->println("%s {", proto_str.c_str()); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("return static_cast<%s>(%s);", type_->DataTypeStr().c_str(), expr_->EvalExpr(out_cc, env_)); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } else if ( code_ ) { - out_cc->println("%s", proto_str.c_str()); - + out_cc->println("%s {", proto_str.c_str()); out_cc->inc_indent(); - out_cc->println("{"); code_->GenCode(out_cc, env_); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } out_cc->println(""); diff --git a/tools/binpac/src/pac_let.cc b/tools/binpac/src/pac_let.cc index 8aa3adc20b..27917cdce2 100644 --- a/tools/binpac/src/pac_let.cc +++ b/tools/binpac/src/pac_let.cc @@ -63,9 +63,8 @@ void LetField::GenParseCode(Output* out_cc, Env* env) { // force evaluation of IDs contained in this expr expr()->ForceIDEval(out_cc, env); - out_cc->println("if ( %s )", env->RValue(type_->has_value_var())); + out_cc->println("if ( %s ) {", env->RValue(type_->has_value_var())); out_cc->inc_indent(); - out_cc->println("{"); } out_cc->println("%s = %s;", env->LValue(id_), expr()->EvalExpr(out_cc, env)); @@ -73,8 +72,8 @@ void LetField::GenParseCode(Output* out_cc, Env* env) { env->SetEvaluated(id_); if ( type_->attr_if_expr() ) { - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } } diff --git a/tools/binpac/src/pac_output.cc b/tools/binpac/src/pac_output.cc index 13b256856b..6171b80b0c 100644 --- a/tools/binpac/src/pac_output.cc +++ b/tools/binpac/src/pac_output.cc @@ -49,8 +49,13 @@ int Output::print(const char* fmt, ...) { } int Output::println(const char* fmt, ...) { + if ( strlen(fmt) == 0 ) { + fprintf(fp, "\n"); + return 0; + } + for ( int i = 0; i < indent(); ++i ) - fprintf(fp, "\t"); + fprintf(fp, " "); va_list ap; va_start(ap, fmt); diff --git a/tools/binpac/src/pac_paramtype.cc b/tools/binpac/src/pac_paramtype.cc index 25370a40f1..8cacd1669a 100644 --- a/tools/binpac/src/pac_paramtype.cc +++ b/tools/binpac/src/pac_paramtype.cc @@ -27,7 +27,7 @@ void ParameterizedType::AddParamArg(Expr* arg) { args_->push_back(arg); } bool ParameterizedType::DefineValueVar() const { return true; } -string ParameterizedType::DataTypeStr() const { return strfmt("%s *", type_id_->Name()); } +string ParameterizedType::DataTypeStr() const { return strfmt("%s*", type_id_->Name()); } Type* ParameterizedType::MemberDataType(const ID* member_id) const { Type* ref_type = TypeDecl::LookUpType(type_id_); diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index d7ed8dbfbf..a65074751c 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -41,7 +41,7 @@ bool RecordType::DefineValueVar() const { return false; } string RecordType::DataTypeStr() const { ASSERT(type_decl()); - return strfmt("%s *", type_decl()->class_name().c_str()); + return strfmt("%s*", type_decl()->class_name().c_str()); } void RecordType::Prepare(Env* env, int flags) { @@ -347,7 +347,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) { out_cc->println("// Parse \"%s\"", id_->Name()); #if 0 - out_cc->println("DEBUG_MSG(\"%%.6f Parse %s\\n\", network_time());", + out_cc->println("DEBUG_MSG(\"%%.6f Parse %s\\n\", network_time());", id_->Name()); #endif type_->GenPreParsing(out_cc, env); @@ -357,8 +357,8 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) { out_cc->println("/* fall through */"); out_cc->dec_indent(); out_cc->println("case %d:", parsing_state_seq()); - out_cc->inc_indent(); out_cc->println("{"); + out_cc->inc_indent(); } type_->GenParseCode(out_cc, env, data, 0); @@ -374,7 +374,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env) { if ( record_type()->incremental_parsing() ) { #if 0 - const ID *dataptr_var = + const ID *dataptr_var = record_type()->parsing_dataptr_var(); ASSERT(dataptr_var); out_cc->println("%s += (%s);", @@ -484,50 +484,46 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi char* padding_var; switch ( ptype_ ) { case PAD_BY_LENGTH: - out_cc->println("if ( (%s) < 0 ) // check for negative pad length", expr_->EvalExpr(out_cc, env)); + out_cc->println("if ( (%s) < 0 ) { // check for negative pad length", expr_->EvalExpr(out_cc, env)); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), expr_->EvalExpr(out_cc, env)); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); out_cc->println(""); out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(), expr_->EvalExpr(out_cc, env)); out_cc->println("// Checking out-of-bound padding for \"%s\"", field_id_str_.c_str()); - out_cc->println("if ( %s > %s || %s < %s )", env->LValue(end_of_field_dataptr_var), + out_cc->println("if ( %s > %s || %s < %s ) {", env->LValue(end_of_field_dataptr_var), env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr()); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env)); out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var)); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); out_cc->println(""); break; case PAD_TO_OFFSET: out_cc->println("const_byteptr %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env)); - out_cc->println("if ( %s < %s )", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr()); + out_cc->println("if ( %s < %s ) {", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr()); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);", id_->LocName(), field_begin.ptr_expr(), env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env)); out_cc->println("%s = %s;", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr()); - out_cc->println("}"); out_cc->dec_indent(); - out_cc->println("if ( %s > %s )", env->LValue(end_of_field_dataptr_var), env->RValue(end_of_data)); + out_cc->println("}"); + out_cc->println("if ( %s > %s ) {", env->LValue(end_of_field_dataptr_var), env->RValue(end_of_data)); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env)); out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var)); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); break; case PAD_TO_NEXT_WORD: diff --git a/tools/binpac/src/pac_strtype.cc b/tools/binpac/src/pac_strtype.cc index 99fe7b3199..00d9c3df2d 100644 --- a/tools/binpac/src/pac_strtype.cc +++ b/tools/binpac/src/pac_strtype.cc @@ -233,12 +233,11 @@ void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data, string str_val = str_->str(); // Compare the string and report error on mismatch - out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", data.ptr_expr(), str_val.c_str(), str_size.c_str()); + out_cc->println("if ( memcmp(%s, %s, %s) != 0 ) {", data.ptr_expr(), str_val.c_str(), str_size.c_str()); out_cc->inc_indent(); - out_cc->println("{"); GenStringMismatch(out_cc, env, data, str_val); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data) { @@ -261,13 +260,12 @@ void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& da env->SetEvaluated(string_length_var()); - out_cc->println("if ( %s < 0 )", env->RValue(string_length_var())); + out_cc->println("if ( %s < 0 ) {", env->RValue(string_length_var())); out_cc->inc_indent(); - out_cc->println("{"); string tmp = strfmt("\"%s\"", regex_->str().c_str()); GenStringMismatch(out_cc, env, data, tmp); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data) { diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index b507777efa..9ea73fd339 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -319,9 +319,8 @@ void Type::GenBufferConfiguration(Output* out_cc, Env* env) { break; ASSERT(env->GetDataType(buffering_state_id)); - out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); + out_cc->println("if ( %s == 0 ) {", env->RValue(buffering_state_id)); out_cc->inc_indent(); - out_cc->println("{"); if ( attr_length_expr_ ) { // frame_buffer_arg = attr_length_expr_->EvalExpr(out_cc, env); @@ -339,15 +338,14 @@ void Type::GenBufferConfiguration(Output* out_cc, Env* env) { attr_chunked() ? "true" : "false"); out_cc->println("%s = 1;", env->LValue(buffering_state_id)); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); break; case BUFFER_BY_LINE: ASSERT(env->GetDataType(buffering_state_id)); - out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id)); + out_cc->println("if ( %s == 0 ) {", env->RValue(buffering_state_id)); out_cc->inc_indent(); - out_cc->println("{"); if ( BufferableWithLineBreaker() ) out_cc->println("%s->SetLineBreaker((unsigned char*)%s);", env->LValue(flow_buffer_id), @@ -358,8 +356,8 @@ void Type::GenBufferConfiguration(Output* out_cc, Env* env) { out_cc->println("%s->NewLine();", env->LValue(flow_buffer_id)); out_cc->println("%s = 1;", env->LValue(buffering_state_id)); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); break; default: ASSERT(0); break; @@ -368,12 +366,11 @@ void Type::GenBufferConfiguration(Output* out_cc, Env* env) { void Type::GenPreParsing(Output* out_cc, Env* env) { if ( incremental_input() && IsPointerType() ) { - out_cc->println("if ( ! %s )", env->LValue(value_var())); + out_cc->println("if ( ! %s ) {", env->LValue(value_var())); out_cc->inc_indent(); - out_cc->println("{"); GenNewInstance(out_cc, env); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } else GenNewInstance(out_cc, env); @@ -425,12 +422,14 @@ void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags GenBoundaryCheck(out_cc, env, data); out_cc->println("{"); + out_cc->inc_indent(); out_cc->println("// Setting %s with &length", env->RValue(end_of_data)); out_cc->println("%s %s = %s + %s;", extern_type_const_byteptr->DataTypeStr().c_str(), env->LValue(end_of_data), data.ptr_expr(), EvalLengthExpr(out_cc, env).c_str()); GenParseCode2(out_cc, env, data, flags); + out_cc->dec_indent(); out_cc->println("}"); } else { @@ -440,16 +439,16 @@ void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags } void Type::GenBufferingLoop(Output* out_cc, Env* env, int flags) { - out_cc->println("while ( ! %s && %s->ready() )", env->LValue(parsing_complete_var()), env->LValue(flow_buffer_id)); + out_cc->println("while ( ! %s && %s->ready() ) {", env->LValue(parsing_complete_var()), + env->LValue(flow_buffer_id)); out_cc->inc_indent(); - out_cc->println("{"); Env buffer_env(env, this); GenParseBuffer(out_cc, &buffer_env, flags); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) { @@ -488,9 +487,8 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) { if ( attr_length_expr() ) { ASSERT(buffer_mode() == BUFFER_BY_LENGTH); - out_cc->println("switch ( %s )", env->LValue(buffering_state_id)); + out_cc->println("switch ( %s ) {", env->LValue(buffering_state_id)); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("case 0:"); out_cc->inc_indent(); GenBufferConfiguration(out_cc, env); @@ -499,34 +497,33 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) { out_cc->dec_indent(); out_cc->println("case 1:"); - out_cc->inc_indent(); out_cc->println("{"); + out_cc->inc_indent(); out_cc->println("%s = 2;", env->LValue(buffering_state_id)); Env frame_length_env(env, this); out_cc->println("%s->GrowFrame(%s);", env->LValue(flow_buffer_id), attr_length_expr_->EvalExpr(out_cc, &frame_length_env)); + out_cc->dec_indent(); out_cc->println("}"); out_cc->println("break;"); - out_cc->dec_indent(); out_cc->println("case 2:"); out_cc->inc_indent(); out_cc->println("BINPAC_ASSERT(%s->ready());", env->RValue(flow_buffer_id)); - out_cc->println("if ( %s->ready() )", env->RValue(flow_buffer_id)); + out_cc->println("if ( %s->ready() ) {", env->RValue(flow_buffer_id)); out_cc->inc_indent(); - out_cc->println("{"); Env parse_env(env, this); GenParseCode2(out_cc, &parse_env, data, 0); out_cc->println("BINPAC_ASSERT(%s);", parsing_complete(env).c_str()); out_cc->println("%s = 0;", env->LValue(buffering_state_id)); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); out_cc->println("break;"); @@ -538,8 +535,8 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) { out_cc->println("break;"); out_cc->dec_indent(); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } else if ( attr_restofflow_ ) { out_cc->println("BINPAC_ASSERT(%s->eof());", env->RValue(flow_buffer_id)); @@ -589,9 +586,8 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag DoGenParseCode(out_cc, env, data, flags); if ( incremental_input() ) { - out_cc->println("if ( %s )", parsing_complete(env).c_str()); + out_cc->println("if ( %s ) {", parsing_complete(env).c_str()); out_cc->inc_indent(); - out_cc->println("{"); } if ( ! fields_->empty() ) { @@ -614,8 +610,8 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag } if ( incremental_input() ) { - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } if ( value_var() ) @@ -628,12 +624,11 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag Expr* enforce = *i; const char* enforce_expr = enforce->EvalExpr(out_cc, env); out_cc->println("// Evaluate '&enforce' attribute"); - out_cc->println("if (!%s)", enforce_expr); + out_cc->println("if (!%s) {", enforce_expr); out_cc->inc_indent(); - out_cc->println("{"); out_cc->println("throw binpac::ExceptionEnforceViolation(\"%s\");", data_id_str_.c_str()); - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } } diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index faae7e2a21..f2cf137706 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -111,7 +111,7 @@ public: string DataTypeConstRefStr() const { string data_type = DataTypeStr(); if ( ! IsPointerType() && ! IsNumericType() ) - data_type += " const &"; + data_type += " const&"; return data_type; } diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc index 5e48c9e2f1..5488490911 100644 --- a/tools/binpac/src/pac_typedecl.cc +++ b/tools/binpac/src/pac_typedecl.cc @@ -114,10 +114,9 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc) { else out_h->print(", public %s", i->c_str()); } - out_h->print("\n"); + out_h->println(" {"); // Public members - out_h->println("{"); out_h->println("public:"); out_h->inc_indent(); @@ -166,18 +165,16 @@ void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc) { out_h->println("%s;", proto.c_str()); - out_cc->println("%s::%s", class_name().c_str(), proto.c_str()); + out_cc->println("%s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); - out_cc->println("{"); - // GenParamAssignments(params_, out_cc, env_); type_->GenInitCode(out_cc, env_); GenInitCode(out_cc); - out_cc->println("}\n"); out_cc->dec_indent(); + out_cc->println("}\n"); } void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) { @@ -185,15 +182,14 @@ void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) { out_h->println("%s;", proto.c_str()); - out_cc->println("%s::%s", class_name().c_str(), proto.c_str()); + out_cc->println("%s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); - out_cc->println("{"); GenCleanUpCode(out_cc); type_->GenCleanUpCode(out_cc, env_); - out_cc->println("}\n"); out_cc->dec_indent(); + out_cc->println("}\n"); } string TypeDecl::ParseFuncPrototype(Env* env) { @@ -283,8 +279,7 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) { env->SetEvaluated(end_of_data); } - string proto; - proto = ParseFuncPrototype(env); + string proto = ParseFuncPrototype(env); #if 0 if ( func_type == PARSE ) @@ -303,9 +298,8 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) { out_h->println(proto.c_str(), "", ";"); string tmp = strfmt("%s::", class_name().c_str()); - out_cc->println(proto.c_str(), tmp.c_str(), ""); + out_cc->println(proto.c_str(), tmp.c_str(), " {"); out_cc->inc_indent(); - out_cc->println("{"); DataPtr data(env, nullptr, 0); @@ -314,8 +308,8 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) { type_->GenParseCode(out_cc, env, data, 0); GenParsingEnd(out_cc, env, data); - out_cc->println("}\n"); out_cc->dec_indent(); + out_cc->println("}\n"); } void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc) { diff --git a/tools/binpac/src/pac_withinput.cc b/tools/binpac/src/pac_withinput.cc index 50b8a2b8ab..6eb43f03f1 100644 --- a/tools/binpac/src/pac_withinput.cc +++ b/tools/binpac/src/pac_withinput.cc @@ -39,9 +39,8 @@ void WithInputField::GenParseCode(Output* out_cc, Env* env) { if ( type_->attr_if_expr() ) { // A conditional field env->Evaluate(out_cc, type_->has_value_var()); - out_cc->println("if ( %s )", env->RValue(type_->has_value_var())); + out_cc->println("if ( %s ) {", env->RValue(type_->has_value_var())); out_cc->inc_indent(); - out_cc->println("{"); } else out_cc->println("{"); @@ -52,8 +51,8 @@ void WithInputField::GenParseCode(Output* out_cc, Env* env) { type_->GenParseCode(out_cc, &field_env, input()->GenDataBeginEnd(out_cc, &field_env), 0); if ( type_->attr_if_expr() ) { - out_cc->println("}"); out_cc->dec_indent(); + out_cc->println("}"); } else out_cc->println("}"); From 670c4dcbcfa2ddb2aa419e965ad8e55235b9b9bb Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 9 May 2025 16:23:40 -0700 Subject: [PATCH 136/343] binpac: Add missing .cmake-format.json, reformat with pre-commit --- tools/binpac/CMakeLists.txt | 68 ++++++++++++++-------------- tools/binpac/lib/CMakeLists.txt | 78 ++++++++++++++------------------- tools/binpac/src/CMakeLists.txt | 42 +++++++----------- tools/binpac/src/pac_decl.cc | 4 +- 4 files changed, 86 insertions(+), 106 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 5076cfa68e..a07ce34354 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -14,10 +14,10 @@ set(BINPAC_SOVERSION 0) set(ENABLE_SHARED true) -if(ENABLE_STATIC_ONLY) - set(ENABLE_STATIC true) - set(ENABLE_SHARED false) -endif() +if (ENABLE_STATIC_ONLY) + set(ENABLE_STATIC true) + set(ENABLE_SHARED false) +endif () # Set default install paths include(GNUInstallDirs) @@ -28,9 +28,9 @@ include(GNUInstallDirs) find_package(FLEX REQUIRED) find_package(BISON REQUIRED) -if(MSVC) - add_compile_options(/J) # Similar to -funsigned-char on other platforms -endif() +if (MSVC) + add_compile_options(/J) # Similar to -funsigned-char on other platforms +endif () # ############################################################################## # System Introspection @@ -48,38 +48,38 @@ add_subdirectory(src) # ############################################################################## # Build Summary -if(CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) -endif() +if (CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) +endif () -macro(display test desc summary) - if(${test}) - set(${summary} ${desc}) - else() - set(${summary} no) - endif() -endmacro() +macro (display test desc summary) + if (${test}) + set(${summary} ${desc}) + else () + set(${summary} no) + endif () +endmacro () display(ENABLE_SHARED yes shared_summary) display(ENABLE_STATIC yes static_summary) message( - "\n==================| BinPAC Build Summary |====================" - "\nVersion: ${BINPAC_VERSION}" - "\nSO version: ${BINPAC_SOVERSION}" - "\n" - "\nBuild Type: ${CMAKE_BUILD_TYPE}" - "\nDebug mode: ${ENABLE_DEBUG}" - "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" - "\nShared libs: ${shared_summary}" - "\nStatic libs: ${static_summary}" - "\n" - "\nCC: ${CMAKE_C_COMPILER}" - "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" - "\nCXX: ${CMAKE_CXX_COMPILER}" - "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" - "\nCPP: ${CMAKE_CXX_COMPILER}" - "\n" - "\n================================================================\n") + "\n==================| BinPAC Build Summary |====================" + "\nVersion: ${BINPAC_VERSION}" + "\nSO version: ${BINPAC_SOVERSION}" + "\n" + "\nBuild Type: ${CMAKE_BUILD_TYPE}" + "\nDebug mode: ${ENABLE_DEBUG}" + "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nShared libs: ${shared_summary}" + "\nStatic libs: ${static_summary}" + "\n" + "\nCC: ${CMAKE_C_COMPILER}" + "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" + "\nCXX: ${CMAKE_CXX_COMPILER}" + "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" + "\nCPP: ${CMAKE_CXX_COMPILER}" + "\n" + "\n================================================================\n") include(UserChangedWarning) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index 0c5bf15a57..726a3b813a 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -4,58 +4,48 @@ test_big_endian(HOST_BIGENDIAN) include(CheckTypeSize) check_type_size("unsigned int" SIZEOF_UNSIGNED_INT) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/binpac.h.in - ${CMAKE_CURRENT_BINARY_DIR}/binpac.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/binpac.h.in ${CMAKE_CURRENT_BINARY_DIR}/binpac.h) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) -set(binpac_headers - ${CMAKE_CURRENT_BINARY_DIR}/binpac.h binpac_analyzer.h binpac_buffer.h - binpac_bytestring.h binpac_exception.h binpac_regex.h) +set(binpac_headers ${CMAKE_CURRENT_BINARY_DIR}/binpac.h binpac_analyzer.h binpac_buffer.h + binpac_bytestring.h binpac_exception.h binpac_regex.h) -set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc binpac_regex.cc - ${binpac_headers}) +set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc binpac_regex.cc ${binpac_headers}) -if(ENABLE_SHARED) - add_library(binpac_lib SHARED ${binpac_lib_SRCS}) - target_compile_features(binpac_lib PRIVATE cxx_std_17) - set_target_properties( - binpac_lib - PROPERTIES CXX_EXTENSIONS OFF - SOVERSION ${BINPAC_SOVERSION} - VERSION ${BINPAC_VERSION_MAJOR}.${BINPAC_VERSION_MINOR} - MACOSX_RPATH true - OUTPUT_NAME binpac) - install(TARGETS binpac_lib DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif() +if (ENABLE_SHARED) + add_library(binpac_lib SHARED ${binpac_lib_SRCS}) + target_compile_features(binpac_lib PRIVATE cxx_std_17) + set_target_properties( + binpac_lib + PROPERTIES CXX_EXTENSIONS OFF + SOVERSION ${BINPAC_SOVERSION} + VERSION ${BINPAC_VERSION_MAJOR}.${BINPAC_VERSION_MINOR} + MACOSX_RPATH true + OUTPUT_NAME binpac) + install(TARGETS binpac_lib DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif () -if(ENABLE_STATIC) - add_library(binpac_static STATIC ${binpac_lib_SRCS}) - target_compile_features(binpac_static PRIVATE cxx_std_17) - set_target_properties(binpac_static PROPERTIES CXX_EXTENSIONS OFF OUTPUT_NAME - binpac) - install(TARGETS binpac_static DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif() +if (ENABLE_STATIC) + add_library(binpac_static STATIC ${binpac_lib_SRCS}) + target_compile_features(binpac_static PRIVATE cxx_std_17) + set_target_properties(binpac_static PROPERTIES CXX_EXTENSIONS OFF OUTPUT_NAME binpac) + install(TARGETS binpac_static DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif () -if(ZEEK_ROOT_DIR) - # Installed in binpac subdir just for organization purposes. - install(FILES ${binpac_headers} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/binpac) -else() - install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -endif() +if (ZEEK_ROOT_DIR) + # Installed in binpac subdir just for organization purposes. + install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/binpac) +else () + install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +endif () # This is set to assist superprojects that want to build BinPac from source and # rely on it as a target -if(ENABLE_SHARED) - set(BinPAC_LIBRARY - binpac_lib - CACHE STRING "BinPAC library" FORCE) -else() - set(BinPAC_LIBRARY - binpac_static - CACHE STRING "BinPAC library" FORCE) -endif() +if (ENABLE_SHARED) + set(BinPAC_LIBRARY binpac_lib CACHE STRING "BinPAC library" FORCE) +else () + set(BinPAC_LIBRARY binpac_static CACHE STRING "BinPAC library" FORCE) +endif () -set(BinPAC_INCLUDE_DIR - ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} +set(BinPAC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} CACHE STRING "BinPAC header directories" FORCE) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 0c21b9024c..d2b14b210b 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -1,20 +1,12 @@ -bison_target( - PACParser pac_parse.yy ${BinPAC_BINARY_DIR}/src/pac_parse.cc - DEFINES_FILE ${BinPAC_BINARY_DIR}/src/pac_parse.h - COMPILE_FLAGS "--debug") +bison_target(PACParser pac_parse.yy ${BinPAC_BINARY_DIR}/src/pac_parse.cc + DEFINES_FILE ${BinPAC_BINARY_DIR}/src/pac_parse.h COMPILE_FLAGS "--debug") flex_target(PACScanner pac_scan.ll ${BinPAC_BINARY_DIR}/pac_scan.cc) add_flex_bison_dependency(PACScanner PACParser) -if(MSVC) - set_property( - SOURCE pac_scan.cc - APPEND_STRING - PROPERTY COMPILE_FLAGS "/wd4018") -else() - set_property( - SOURCE pac_scan.cc - APPEND_STRING - PROPERTY COMPILE_FLAGS "-Wno-sign-compare") -endif() +if (MSVC) + set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") +else () + set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") +endif () include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src) @@ -110,19 +102,17 @@ add_executable(binpac ${binpac_SRCS}) target_compile_features(binpac PRIVATE cxx_std_17) set_target_properties(binpac PROPERTIES CXX_EXTENSIONS OFF) -if(MSVC) - # If building separately from zeek, we need to add the libunistd subdirectory - # so that linking doesn't fail. - if("${CMAKE_PROJECT_NAME}" STREQUAL "BinPAC") - add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) - endif() - target_link_libraries(binpac PRIVATE libunistd) -endif() +if (MSVC) + # If building separately from zeek, we need to add the libunistd subdirectory + # so that linking doesn't fail. + if ("${CMAKE_PROJECT_NAME}" STREQUAL "BinPAC") + add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) + endif () + target_link_libraries(binpac PRIVATE libunistd) +endif () install(TARGETS binpac DESTINATION bin) # This is set to assist superprojects that want to build BinPac from source and # rely on it as a target -set(BinPAC_EXE - binpac - CACHE STRING "BinPAC executable" FORCE) +set(BinPAC_EXE binpac CACHE STRING "BinPAC executable" FORCE) diff --git a/tools/binpac/src/pac_decl.cc b/tools/binpac/src/pac_decl.cc index dbc93b1ab0..1ea3325d0f 100644 --- a/tools/binpac/src/pac_decl.cc +++ b/tools/binpac/src/pac_decl.cc @@ -138,8 +138,8 @@ void HelperDecl::GenCode(Output* out_h, Output* out_cc) { Decl *decl = Decl::LookUpDecl(context_id_); if ( ! decl ) { - throw Exception(context_id_, - fmt("cannot find declaration for %s", + throw Exception(context_id_, + fmt("cannot find declaration for %s", context_id_->Name())); } env = decl->env(); From 54a0e018059037eb81d59268f2713370e6227d3e Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 16 Apr 2025 18:35:26 -0700 Subject: [PATCH 137/343] binpac: Wrap generated switch statements in NOLINTs for bugprone-branch-clone Binpac generates a lot of switch statements with repeated blocks in them (typically empty blocks). Running clang-tidy on the generated code with bugprone-branch-clone generates a lot of warnings. Instead of doing a ton of analysis in binpac to avoid generating the duplicates, just mark any switch generated with an annotation to avoid reporting them. --- tools/binpac/src/pac_case.cc | 6 ++++++ tools/binpac/src/pac_expr.cc | 2 ++ tools/binpac/src/pac_record.cc | 2 ++ tools/binpac/src/pac_type.cc | 2 ++ 4 files changed, 12 insertions(+) diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index 187eaf37c8..cc629d2253 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -117,6 +117,7 @@ void CaseType::GenCleanUpCode(Output* out_cc, Env* env) { Type::GenCleanUpCode(out_cc, env); env->set_in_branch(true); + out_cc->println("// NOLINTBEGIN(bugprone-branch-clone)"); out_cc->println("switch ( %s ) {", env->RValue(index_var_)); out_cc->inc_indent(); foreach (i, CaseFieldList, cases_) { @@ -125,6 +126,7 @@ void CaseType::GenCleanUpCode(Output* out_cc, Env* env) { } out_cc->dec_indent(); out_cc->println("}"); + out_cc->println("// NOLINTEND(bugprone-branch-clone)"); env->set_in_branch(false); } @@ -141,6 +143,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int env->SetEvaluated(index_var_); env->set_in_branch(true); + out_cc->println("// NOLINTBEGIN(bugprone-branch-clone)"); out_cc->println("switch ( %s ) {", env->RValue(index_var_)); out_cc->inc_indent(); bool has_default_case = false; @@ -161,6 +164,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int } out_cc->dec_indent(); out_cc->println("}"); + out_cc->println("// NOLINTEND(bugprone-branch-clone)"); env->set_in_branch(false); if ( compute_size_var ) @@ -307,6 +311,7 @@ void CaseField::GenPubDecls(Output* out_h, Env* env) { if ( ! index_ ) out_h->println("return %s;", lvalue()); else { + out_h->println("// NOLINTBEGIN(bugprone-branch-clone)"); out_h->println("switch ( %s ) {", env->RValue(index_var_)); out_h->inc_indent(); GenCaseStr(index_, out_h, env, case_type()->IndexExpr()->DataType(env)); @@ -323,6 +328,7 @@ void CaseField::GenPubDecls(Output* out_h, Env* env) { out_h->dec_indent(); out_h->println("}"); + out_h->println("// NOLINTEND(bugprone-branch-clone)"); out_h->println("return %s;", lvalue()); } diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index 4f74859f72..fca87cff66 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -209,6 +209,7 @@ void Expr::GenCaseEval(Output* out_cc, Env* env) { foreach (i, CaseExprList, cases_) (*i)->value()->ForceIDEval(out_cc, env); + out_cc->println("// NOLINTBEGIN(bugprone-branch-clone)"); out_cc->println("switch ( %s ) {", operand_[0]->EvalExpr(out_cc, env)); Type* switch_type = operand_[0]->DataType(env); @@ -247,6 +248,7 @@ void Expr::GenCaseEval(Output* out_cc, Env* env) { out_cc->dec_indent(); out_cc->println("}"); + out_cc->println("// NOLINTEND(bugprone-branch-clone)"); env->SetEvaluated(val_var); str_ = env->RValue(val_var); diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index a65074751c..145604b13a 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -100,6 +100,7 @@ void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, i GenBoundaryCheck(out_cc, env, data); if ( incremental_parsing() ) { + out_cc->println("// NOLINTBEGIN(bugprone-branch-clone)"); out_cc->println("switch ( %s ) {", env->LValue(parsing_state_id)); out_cc->println("case 0:"); @@ -113,6 +114,7 @@ void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, i out_cc->println("%s = true;", env->LValue(parsing_complete_var())); out_cc->dec_indent(); out_cc->println("}"); + out_cc->println("// NOLINTEND(bugprone-branch-clone)"); } else { ASSERT(data.id() == begin_of_data && data.offset() == 0); diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index 9ea73fd339..7a66f65a87 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -487,6 +487,7 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) { if ( attr_length_expr() ) { ASSERT(buffer_mode() == BUFFER_BY_LENGTH); + out_cc->println("// NOLINTBEGIN(bugprone-branch-clone)"); out_cc->println("switch ( %s ) {", env->LValue(buffering_state_id)); out_cc->inc_indent(); out_cc->println("case 0:"); @@ -537,6 +538,7 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags) { out_cc->dec_indent(); out_cc->dec_indent(); out_cc->println("}"); + out_cc->println("// NOLINTEND(bugprone-branch-clone)"); } else if ( attr_restofflow_ ) { out_cc->println("BINPAC_ASSERT(%s->eof());", env->RValue(flow_buffer_id)); From 3cf68302a2fdedee4dd3b3c6b8ebb708116eafb8 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 15 May 2025 17:20:31 -0700 Subject: [PATCH 138/343] binpac: Make 'bool' a discrete type and handle it differently when generating code This fixes clang-tidy modernize-use-bool-literals findings in the generated code --- tools/binpac/src/pac_case.cc | 5 ++++- tools/binpac/src/pac_externtype.def | 2 +- tools/binpac/src/pac_exttype.cc | 5 ++++- tools/binpac/src/pac_exttype.h | 3 ++- tools/binpac/src/pac_type.cc | 4 ++-- tools/binpac/src/pac_type.h | 3 ++- 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index cc629d2253..38f7963dfe 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -284,7 +284,10 @@ void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_typ // We're always using "int" for storage, so ok to just // cast into the type used by the switch statement since // some unsafe stuff is already checked above. - out_cc->println("case ((%s)%d):", switch_type->DataTypeStr().c_str(), index_const); + if ( ! switch_type->IsBooleanType() ) + out_cc->println("case ((%s)%d):", switch_type->DataTypeStr().c_str(), index_const); + else + out_cc->println("case %s:", index_const == 0 ? "false" : "true"); } } else { diff --git a/tools/binpac/src/pac_externtype.def b/tools/binpac/src/pac_externtype.def index aeac5a51b0..48475d0d39 100644 --- a/tools/binpac/src/pac_externtype.def +++ b/tools/binpac/src/pac_externtype.def @@ -1,4 +1,4 @@ -EXTERNTYPE(bool, bool, NUMBER) +EXTERNTYPE(bool, bool, BOOLEAN) EXTERNTYPE(int, int, NUMBER) EXTERNTYPE(double, double, NUMBER) EXTERNTYPE(string, string, PLAIN) diff --git a/tools/binpac/src/pac_exttype.cc b/tools/binpac/src/pac_exttype.cc index d9acd40a75..7b9970c91e 100644 --- a/tools/binpac/src/pac_exttype.cc +++ b/tools/binpac/src/pac_exttype.cc @@ -9,7 +9,8 @@ bool ExternType::DefineValueVar() const { return true; } string ExternType::DataTypeStr() const { switch ( ext_type_ ) { case PLAIN: - case NUMBER: return id_->Name(); + case NUMBER: + case BOOLEAN: return id_->Name(); case POINTER: return string(id_->Name()) + " *"; default: ASSERT(0); return ""; } @@ -31,6 +32,8 @@ void ExternType::GenInitCode(Output* out_cc, Env* env) { out_cc->println("%s = 0;", env->LValue(value_var())); else if ( IsPointerType() ) out_cc->println("%s = nullptr;", env->LValue(value_var())); + else if ( IsBooleanType() ) + out_cc->println("%s = false;", env->LValue(value_var())); Type::GenInitCode(out_cc, env); } diff --git a/tools/binpac/src/pac_exttype.h b/tools/binpac/src/pac_exttype.h index 1abe5e50dc..8f49332d6b 100644 --- a/tools/binpac/src/pac_exttype.h +++ b/tools/binpac/src/pac_exttype.h @@ -10,7 +10,7 @@ class ExternType : public Type { public: - enum EXTType { PLAIN, NUMBER, POINTER }; + enum EXTType { PLAIN, NUMBER, POINTER, BOOLEAN }; ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) {} bool DefineValueVar() const override; @@ -21,6 +21,7 @@ public: string EvalMember(const ID* member_id) const override; bool IsNumericType() const override { return ext_type_ == NUMBER; } bool IsPointerType() const override { return ext_type_ == POINTER; } + bool IsBooleanType() const override { return ext_type_ == BOOLEAN; } void GenInitCode(Output* out_cc, Env* env) override; diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index 7a66f65a87..394d1492f8 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -887,8 +887,8 @@ bool Type::CompatibleTypes(Type* type1, Type* type2) { Type* Type::LookUpByID(ID* id) { // 1. Is it a pre-defined type? string name = id->Name(); - if ( type_map_.find(name) != type_map_.end() ) { - return type_map_[name]->Clone(); + if ( auto it = type_map_.find(name); it != type_map_.end() ) { + return it->second->Clone(); } // 2. Is it a simple declared type? diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index f2cf137706..a4bf2e8eca 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -110,7 +110,7 @@ public: // is numeric or pointer) string DataTypeConstRefStr() const { string data_type = DataTypeStr(); - if ( ! IsPointerType() && ! IsNumericType() ) + if ( ! IsPointerType() && ! IsNumericType() && ! IsBooleanType() ) data_type += " const&"; return data_type; } @@ -138,6 +138,7 @@ public: virtual bool IsPointerType() const = 0; virtual bool IsNumericType() const { return false; } + virtual bool IsBooleanType() const { return false; } bool IsEmptyType() const; //////////////////////////////////////// From 45d07641e479363bb1622f4b9f20ec284fcf3867 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 16 May 2025 15:26:18 -0700 Subject: [PATCH 139/343] binpac: Make 'nullptr' a keyword, allow values to be set to it and compared against it This helps fix 'modernize-use-nullptr' findings in generated code. --- tools/binpac/src/CMakeLists.txt | 1 + tools/binpac/src/pac_common.h | 1 + tools/binpac/src/pac_expr.cc | 13 +++++++++---- tools/binpac/src/pac_expr.def | 1 + tools/binpac/src/pac_expr.h | 2 ++ tools/binpac/src/pac_nullptr.h | 14 ++++++++++++++ tools/binpac/src/pac_parse.yy | 9 ++++++++- tools/binpac/src/pac_scan.ll | 5 +++++ 8 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 tools/binpac/src/pac_nullptr.h diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index d2b14b210b..921e51d87e 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -82,6 +82,7 @@ set(binpac_SRCS pac_id.h pac_inputbuf.h pac_let.h + pac_nullptr.h pac_number.h pac_output.h pac_param.h diff --git a/tools/binpac/src/pac_common.h b/tools/binpac/src/pac_common.h index 8ddc7f1c7f..0808450c27 100644 --- a/tools/binpac/src/pac_common.h +++ b/tools/binpac/src/pac_common.h @@ -65,6 +65,7 @@ class InputBuffer; class LetDef; class LetField; class ID; +class Nullptr; class Number; class Output; class PacPrimitive; diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index fca87cff66..360562afc5 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -5,6 +5,7 @@ #include "pac_exception.h" #include "pac_exttype.h" #include "pac_id.h" +#include "pac_nullptr.h" #include "pac_number.h" #include "pac_output.h" #include "pac_record.h" @@ -64,7 +65,6 @@ Expr::Expr(ID* arg_id) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_ID; id_ = arg_id; - num_operands_ = 0; orig_ = strfmt("%s", id_->Name()); } @@ -72,15 +72,20 @@ Expr::Expr(Number* arg_num) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_NUM; num_ = arg_num; - num_operands_ = 0; orig_ = strfmt("((int) %s)", num_->Str()); } +Expr::Expr(Nullptr* arg_nullp) : DataDepElement(EXPR) { + init(); + expr_type_ = EXPR_NULLPTR; + nullp_ = arg_nullp; + orig_ = strfmt("%s", nullp_->Str()); +} + Expr::Expr(ConstString* cstr) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_CSTR; cstr_ = cstr; - num_operands_ = 0; orig_ = cstr_->str(); } @@ -88,7 +93,6 @@ Expr::Expr(RegEx* regex) : DataDepElement(EXPR) { init(); expr_type_ = EXPR_REGEX; regex_ = regex; - num_operands_ = 0; orig_ = strfmt("/%s/", regex_->str().c_str()); } @@ -257,6 +261,7 @@ void Expr::GenCaseEval(Output* out_cc, Env* env) { void Expr::GenEval(Output* out_cc, Env* env) { switch ( expr_type_ ) { case EXPR_NUM: str_ = num_->Str(); break; + case EXPR_NULLPTR: str_ = nullp_->Str(); break; case EXPR_ID: if ( ! env->Evaluated(id_) ) diff --git a/tools/binpac/src/pac_expr.def b/tools/binpac/src/pac_expr.def index d7c0319522..5b1fbec5c3 100644 --- a/tools/binpac/src/pac_expr.def +++ b/tools/binpac/src/pac_expr.def @@ -1,5 +1,6 @@ EXPR_DEF(EXPR_ID, 0, "%s") EXPR_DEF(EXPR_NUM, 0, "%s") +EXPR_DEF(EXPR_NULLPTR, 0, "%s") EXPR_DEF(EXPR_CSTR, 0, "%s") EXPR_DEF(EXPR_REGEX, 0, "REGEX(%s)") EXPR_DEF(EXPR_SUBSCRIPT, 2, "@element@(%s[%s])") diff --git a/tools/binpac/src/pac_expr.h b/tools/binpac/src/pac_expr.h index 07c33f9dc1..c24afd4f88 100644 --- a/tools/binpac/src/pac_expr.h +++ b/tools/binpac/src/pac_expr.h @@ -18,6 +18,7 @@ public: Expr(ID* id); Expr(Number* num); + Expr(Nullptr* nullp); Expr(ConstString* s); Expr(RegEx* regex); Expr(ExprList* args); // for EXPR_CALLARGS @@ -101,6 +102,7 @@ private: RegEx* regex_; // EXPR_REGEX ExprList* args_; // EXPR_CALLARGS CaseExprList* cases_; // EXPR_CASE + Nullptr* nullp_; // EXPR_NULLPTR string str_; // value string string orig_; // original string for debugging info diff --git a/tools/binpac/src/pac_nullptr.h b/tools/binpac/src/pac_nullptr.h new file mode 100644 index 0000000000..f1fe8e545a --- /dev/null +++ b/tools/binpac/src/pac_nullptr.h @@ -0,0 +1,14 @@ +#ifndef pac_nullptr_h +#define pac_nullptr_h + +#include "pac_common.h" + +class Nullptr : public Object { +public: + const char* Str() const { return s.c_str(); } + +protected: + const string s = "nullptr"; +}; + +#endif // pac_nullptr_h diff --git a/tools/binpac/src/pac_parse.yy b/tools/binpac/src/pac_parse.yy index b1172c307c..95488f7f8d 100644 --- a/tools/binpac/src/pac_parse.yy +++ b/tools/binpac/src/pac_parse.yy @@ -25,7 +25,7 @@ %token TOK_EMBEDDED_ATOM TOK_EMBEDDED_STRING %token TOK_PAC_VAL TOK_PAC_SET TOK_PAC_TYPE TOK_PAC_TYPEOF TOK_PAC_CONST_DEF %token TOK_END_PAC -%token TOK_EXTERN +%token TOK_EXTERN TOK_NULLPTR %nonassoc '=' TOK_PLUSEQ %left ';' @@ -66,6 +66,7 @@ %type funcproto function %type TOK_ID tok_id optfieldid %type input +%type TOK_NULLPTR %type TOK_NUMBER %type embedded_pac_primitive %type param @@ -105,6 +106,7 @@ #include "pac_id.h" #include "pac_inputbuf.h" #include "pac_let.h" +#include "pac_nullptr.h" #include "pac_output.h" #include "pac_param.h" #include "pac_paramtype.h" @@ -160,6 +162,7 @@ extern Output* source_output; InputBuffer *input; LetFieldList *letfieldlist; LetField *letfield; + Nullptr *nullp; Number *num; PacPrimitive *pacprimitive; Param *param; @@ -576,6 +579,10 @@ expr : tok_id { $$ = new Expr($1); } + | TOK_NULLPTR + { + $$ = new Expr($1); + } | expr '[' expr ']' { $$ = new Expr(Expr::EXPR_SUBSCRIPT, $1, $3); diff --git a/tools/binpac/src/pac_scan.ll b/tools/binpac/src/pac_scan.ll index e3b35d3663..edcb216c94 100644 --- a/tools/binpac/src/pac_scan.ll +++ b/tools/binpac/src/pac_scan.ll @@ -21,6 +21,7 @@ #include "pac_expr.h" #include "pac_flow.h" #include "pac_id.h" +#include "pac_nullptr.h" #include "pac_number.h" #include "pac_output.h" #include "pac_param.h" @@ -200,6 +201,10 @@ ESCSEQ (\\([^\n]|[0-7]{3}|x[[:xdigit:]]{2})) yylval.val = AnalyzerDataUnit::FLOWUNIT; return TOK_DATAUNIT; } +nullptr { + yylval.nullp = new Nullptr(); + return TOK_NULLPTR; + } of return TOK_OF; offsetof return TOK_OFFSETOF; padding return TOK_PADDING; From 09936133a66a5e62acfd018193781ea9d4bdd93c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 21 May 2025 16:42:23 -0700 Subject: [PATCH 140/343] binpac: Reorder the fields in pac_type.h for better packing --- tools/binpac/src/pac_type.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index a4bf2e8eca..507ac1c886 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -1,7 +1,9 @@ #ifndef pac_type_h #define pac_type_h +#include #include + using namespace std; #include "pac_common.h" @@ -10,7 +12,7 @@ using namespace std; class Type : public Object, public DataDepElement { public: - enum TypeType { + enum TypeType : int8_t { UNDEF = -1, EMPTY, BUILTIN, @@ -200,7 +202,7 @@ public: bool BufferableWithLineBreaker() const; Expr* LineBreaker() const; - enum BufferMode { + enum BufferMode : uint8_t { NOT_BUFFERABLE, BUFFER_NOTHING, // for type "empty" BUFFER_BY_LENGTH, @@ -236,20 +238,21 @@ protected: virtual Type* DoClone() const = 0; protected: - TypeType tot_; const TypeDecl* type_decl_; - bool declared_as_type_; const ID* type_decl_id_; Env* env_; const ID* value_var_; + bool anonymous_value_var_; // whether the ID is anonymous + bool declared_as_type_; + bool boundary_checked_; + TypeType tot_; string data_id_str_; int value_var_type_; Field* size_var_field_; char* size_expr_; - bool boundary_checked_; string lvalue_; FieldList* fields_; @@ -278,13 +281,13 @@ protected: Expr* attr_byteorder_expr_; ExprList* attr_checks_; ExprList* attr_enforces_; - bool attr_chunked_; - bool attr_exportsourcedata_; Expr* attr_if_expr_; Expr* attr_length_expr_; FieldList* attr_letfields_; Expr* attr_multiline_end_; Expr* attr_linebreaker_; + bool attr_chunked_; + bool attr_exportsourcedata_; bool attr_oneline_; bool attr_refcount_; ExprList* attr_requires_; From 28cc9ca3ecd0148c33196940a88738f3c34a65af Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 9 Jun 2025 17:04:56 -0700 Subject: [PATCH 141/343] binpac: Add NOLINT for clang-tidy performance-enum-size to generated headers --- tools/binpac/src/pac_enum.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/binpac/src/pac_enum.cc b/tools/binpac/src/pac_enum.cc index 5a017820c7..02e90fe0c6 100644 --- a/tools/binpac/src/pac_enum.cc +++ b/tools/binpac/src/pac_enum.cc @@ -41,6 +41,7 @@ void EnumDecl::Prepare() { } void EnumDecl::GenForwardDeclaration(Output* out_h) { + out_h->println("// NOLINTNEXTLINE(performance-enum-size)"); out_h->println("enum %s {", id_->Name()); out_h->inc_indent(); int c = 0; From ef962376bcbe41acfbea968012f350b2062246f7 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 10 Jun 2025 10:34:15 -0700 Subject: [PATCH 142/343] binpac: Add 'override' to virtual methods in generated code --- tools/binpac/lib/binpac_analyzer.h | 4 ++-- tools/binpac/src/pac_conn.cc | 2 +- tools/binpac/src/pac_flow.cc | 2 +- tools/binpac/src/pac_typedecl.cc | 8 +++++++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/binpac/lib/binpac_analyzer.h b/tools/binpac/lib/binpac_analyzer.h index 23931eeb27..e3e4a9ffd5 100644 --- a/tools/binpac/lib/binpac_analyzer.h +++ b/tools/binpac/lib/binpac_analyzer.h @@ -8,14 +8,14 @@ namespace binpac { // The interface for a connection analyzer class ConnectionAnalyzer { public: - virtual ~ConnectionAnalyzer() {} + virtual ~ConnectionAnalyzer() = default; virtual void NewData(bool is_orig, const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0; }; // The interface for a flow analyzer class FlowAnalyzer { public: - virtual ~FlowAnalyzer() {} + virtual ~FlowAnalyzer() = default; virtual void NewData(const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0; }; diff --git a/tools/binpac/src/pac_conn.cc b/tools/binpac/src/pac_conn.cc index 4e7bc01cfe..deb8a77a6e 100644 --- a/tools/binpac/src/pac_conn.cc +++ b/tools/binpac/src/pac_conn.cc @@ -110,7 +110,7 @@ void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc) { void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc) { string proto = strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)", kNewData); - out_h->println("void %s;", proto.c_str()); + out_h->println("void %s override;", proto.c_str()); out_cc->println("void %s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index 2138acb573..7b72979b38 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -151,7 +151,7 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc) { string proto = strfmt("%s(const_byteptr %s, const_byteptr %s)", kNewData, env_->LValue(begin_of_data), env_->LValue(end_of_data)); - out_h->println("void %s;", proto.c_str()); + out_h->println("void %s override;", proto.c_str()); out_cc->println("void %s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc index 5488490911..268fdc3344 100644 --- a/tools/binpac/src/pac_typedecl.cc +++ b/tools/binpac/src/pac_typedecl.cc @@ -178,9 +178,15 @@ void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc) { } void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) { + vector base_classes; + AddBaseClass(&base_classes); + string proto = strfmt("~%s()", class_name().c_str()); - out_h->println("%s;", proto.c_str()); + if ( base_classes.empty() ) + out_h->println("%s;", proto.c_str()); + else + out_h->println("%s override;", proto.c_str()); out_cc->println("%s::%s {", class_name().c_str(), proto.c_str()); out_cc->inc_indent(); From bb382fc0c0eb7518adc69bc4e15066d96a9eda26 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 27 Jun 2025 13:01:07 -0700 Subject: [PATCH 143/343] binpac: Fix clang-tidy readability-isolate-declaration finding in generated code --- tools/binpac/src/pac_inputbuf.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/binpac/src/pac_inputbuf.cc b/tools/binpac/src/pac_inputbuf.cc index c425bae868..ae2756361a 100644 --- a/tools/binpac/src/pac_inputbuf.cc +++ b/tools/binpac/src/pac_inputbuf.cc @@ -20,8 +20,8 @@ DataPtr InputBuffer::GenDataBeginEnd(Output* out_cc, Env* env) { env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); - out_cc->println("%s %s, %s;", extern_type_const_byteptr->DataTypeStr().c_str(), env->LValue(begin_of_data), - env->LValue(end_of_data)); + out_cc->println("%s %s;", extern_type_const_byteptr->DataTypeStr().c_str(), env->LValue(begin_of_data)); + out_cc->println("%s %s;", extern_type_const_byteptr->DataTypeStr().c_str(), env->LValue(end_of_data)); out_cc->println("get_pointers(%s, &%s, &%s);", expr_->EvalExpr(out_cc, env), env->LValue(begin_of_data), env->LValue(end_of_data)); From b9b4fcb78b5abfb79f91478bfcfe74e1fd0512ac Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 1 May 2024 15:32:37 -0700 Subject: [PATCH 144/343] binpac: Require C++20 for builds --- tools/binpac/CMakeLists.txt | 1 + tools/binpac/lib/CMakeLists.txt | 7 ++----- tools/binpac/src/CMakeLists.txt | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index a07ce34354..7dbec04ca2 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR) project(BinPAC C CXX) include(cmake/CommonCMakeConfig.cmake) +include(cmake/RequireCXXStd.cmake) file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) string(REPLACE "." " " _version_numbers ${BINPAC_VERSION}) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index 726a3b813a..de2eb4aa4f 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -14,11 +14,9 @@ set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc binpac_regex.cc ${binp if (ENABLE_SHARED) add_library(binpac_lib SHARED ${binpac_lib_SRCS}) - target_compile_features(binpac_lib PRIVATE cxx_std_17) set_target_properties( binpac_lib - PROPERTIES CXX_EXTENSIONS OFF - SOVERSION ${BINPAC_SOVERSION} + PROPERTIES SOVERSION ${BINPAC_SOVERSION} VERSION ${BINPAC_VERSION_MAJOR}.${BINPAC_VERSION_MINOR} MACOSX_RPATH true OUTPUT_NAME binpac) @@ -27,8 +25,7 @@ endif () if (ENABLE_STATIC) add_library(binpac_static STATIC ${binpac_lib_SRCS}) - target_compile_features(binpac_static PRIVATE cxx_std_17) - set_target_properties(binpac_static PROPERTIES CXX_EXTENSIONS OFF OUTPUT_NAME binpac) + set_target_properties(binpac_static PROPERTIES OUTPUT_NAME binpac) install(TARGETS binpac_static DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif () diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index 921e51d87e..f3c8b2e2b9 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -99,9 +99,9 @@ set(binpac_SRCS pac_varfield.h pac_withinput.h) +include(${PROJECT_SOURCE_DIR}/cmake/RequireCXXStd.cmake) + add_executable(binpac ${binpac_SRCS}) -target_compile_features(binpac PRIVATE cxx_std_17) -set_target_properties(binpac PROPERTIES CXX_EXTENSIONS OFF) if (MSVC) # If building separately from zeek, we need to add the libunistd subdirectory From 710e2eaced8770e4439c9775e99a035ba400f8ce Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 1 Jul 2025 16:30:21 -0700 Subject: [PATCH 145/343] binpac: Make sure pac_expr fields are initialized --- tools/binpac/src/pac_expr.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/tools/binpac/src/pac_expr.h b/tools/binpac/src/pac_expr.h index c24afd4f88..f72f1439e2 100644 --- a/tools/binpac/src/pac_expr.h +++ b/tools/binpac/src/pac_expr.h @@ -1,6 +1,8 @@ #ifndef pac_expr_h #define pac_expr_h +#include + #include "pac_common.h" #include "pac_datadep.h" @@ -8,7 +10,7 @@ class CaseExpr; class Expr : public Object, public DataDepElement { public: - enum ExprType { + enum ExprType : uint8_t { #define EXPR_DEF(type, x, y) type, #include "pac_expr.def" #undef EXPR_DEF @@ -93,16 +95,16 @@ protected: private: ExprType expr_type_; - int num_operands_; - Expr* operand_[3]; + int num_operands_ = 0; + Expr* operand_[3] = {nullptr}; - ID* id_; // EXPR_ID - Number* num_; // EXPR_NUM - ConstString* cstr_; // EXPR_CSTR - RegEx* regex_; // EXPR_REGEX - ExprList* args_; // EXPR_CALLARGS - CaseExprList* cases_; // EXPR_CASE - Nullptr* nullp_; // EXPR_NULLPTR + ID* id_ = nullptr; // EXPR_ID + Number* num_ = nullptr; // EXPR_NUM + ConstString* cstr_ = nullptr; // EXPR_CSTR + RegEx* regex_ = nullptr; // EXPR_REGEX + ExprList* args_ = nullptr; // EXPR_CALLARGS + CaseExprList* cases_ = nullptr; // EXPR_CASE + Nullptr* nullp_ = nullptr; // EXPR_NULLPTR string str_; // value string string orig_; // original string for debugging info From d13cdd642788d068a6be4cac2457d2d3b9a3cc4e Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 1 Jul 2025 16:34:03 -0700 Subject: [PATCH 146/343] binpac: Use std::move for a string value --- tools/binpac/src/pac_main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index 152702425d..fca52ef5cc 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -38,7 +38,7 @@ void add_to_include_directories(string dirs) { if ( dir.length() > 0 && *(dir.end() - 1) != '/' ) dir += '/'; - FLAGS_include_directories.push_back(dir); + FLAGS_include_directories.push_back(std::move(dir)); dir_begin = dir_end + 1; } } From a25b5b65ffb4d82aa59ef83723ef21d7f9955f50 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 1 Jul 2025 16:36:38 -0700 Subject: [PATCH 147/343] binpac: Fix coverity unchecked return warning --- tools/binpac/src/pac_datadep.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/binpac/src/pac_datadep.cc b/tools/binpac/src/pac_datadep.cc index 32567dcda5..85402db510 100644 --- a/tools/binpac/src/pac_datadep.cc +++ b/tools/binpac/src/pac_datadep.cc @@ -49,6 +49,8 @@ void RequiresAnalyzerContext::ProcessExpr(Expr* expr) { bool RequiresAnalyzerContext::compute(DataDepElement* element) { RequiresAnalyzerContext visitor; - element->Traverse(&visitor); + // This result is intentionally ignored. We want to traverse, but always return + // the same result. + std::ignore = element->Traverse(&visitor); return visitor.requires_analyzer_context_; } From 79733d9390d85164d2cf3bb0c79b068ac233e2ec Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 18 Aug 2025 13:44:38 -0700 Subject: [PATCH 148/343] binpac: Restore README file without version number --- tools/binpac/README | 1115 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1115 insertions(+) create mode 100644 tools/binpac/README diff --git a/tools/binpac/README b/tools/binpac/README new file mode 100644 index 0000000000..f87c08addb --- /dev/null +++ b/tools/binpac/README @@ -0,0 +1,1115 @@ +.. -*- mode: rst-mode -*- + +====== +BinPAC +====== + +BinPAC is a high level language for describing protocol parsers and +generates C++ code. It is currently maintained and distributed with the +Zeek Network Security Monitor distribution, however, the generated parsers +may be used with other programs besides Zeek. + +BinPAC originally existed as a separate project to the main Zeek repository. +You can see the archived repository at https://github.com/zeek/binpac. The +repository only exists for historical reasons, as all new work done to +BinPAC is done in the main Zeek repo. + +.. contents:: + +Prerequisites +============= + +BinPAC relies on the following libraries and tools, which need to be +installed before you begin: + + * Flex (Fast Lexical Analyzer) + Flex is already installed on most systems, so with luck you can + skip having to install it yourself. + + * Bison (GNU Parser Generator) + Bison is also already installed on many system. + + * CMake 3.15.0 or greater + CMake is a cross-platform, open-source build system, typically + not installed by default. See http://www.cmake.org for more + information regarding CMake and the installation steps below for + how to use it to build this distribution. CMake generates native + Makefiles that depend on GNU Make by default + +Glossary and Convention +======================= + +To make this document easier to read, the following are the glossary +and convention used. + + - PAC grammar - .pac file written by user. + - PAC source - _pac.cc file generated by binpac + - PAC header - _pac.h file generated by binpac + - Analyzer - Protocol decoder generated by compiling PAC grammar + - Field - a member of a record + - Primary field - member of a record as direct result of parsing + - Derivative field - member of a record evaluated through post processing + +BinPAC Language Reference +========================= + +BinPAC language consists of: + + - analyzer + - type - data structure like definition describing parsing unit. Types can built on each other to form more complex type similar to yacc productions. + - flow - "flow" defines how data will be fed into the analyzer and the top level parsing unit. + - Keywords + - Built-in macros + +Defining an analyzer +-------------------- + +There are two components to an analyzer definition: the top level context +and the connection definition. + + +Context Definition +~~~~~~~~~~~~~~~~~~ + +Each analyzer requires a top level context defined by the following syntax: + +.. code:: + + analyzer withcontext { + ... context members ... + } + +Typically top level context contains pointer to top level analyzer +and connection definition like below: + +.. code:: + + analyzer HTTP withcontext { + connection : HTTP_analyzer; + flow : HTTP_flow; + }; + + +Connection Definition +~~~~~~~~~~~~~~~~~~~~~ + +A "connection" defines the entry point into the analyzer. It consists of +two "flow" definitions, an "upflow" and a "downflow". + +.. code:: + + connection (optional parameter) { + upflow = ; + downflow = ; + } + +Example: + +.. code:: + + connection HTTP_analyzer { + upflow = HTTP_flow (true); + downflow = HTTP_flow (false); + }; + +type +---- + +A "type" is the basic building block of binpac-generated parser, and describes +the structure of a byte segment. Each non-primitive "type" generates a C++ +class that can independently parse the structure which it describes. + +Syntax: + +.. code:: + + type {()} = { + cases or members declaration. + } ; + +Example: + +PAC grammar:: + + type myType = record { + data:uint8; + }; + +PAC header:: + + class myType{ + public: + myType(); + ~myType(); + int Parse(const_byteptr const t_begin_of_data, const_byteptr const t_end_of_data); + uint8 data() const { return data_; } + protected: + uint8 data_; + }; + + +Primitives +~~~~~~~~~~ + +Primitive type can be treated as #define in C language. They are embedded +into other type which reference them but do not generate any parsing +code of their own. Available primitive types are: + + - int8 + - int16 + - int32 + - uint8 + - uint16 + - uint32 + - Regular expression ( ``type HTTP_URI = RE/[[:alnum:][:punct:]]+/;`` ) + - bytestring + +Examples: + +.. code:: + + type foo = record { x: number; }; + +is equivalent to: + +.. code:: + + type foo = record { x: uint8[3]; }; + +(Note: this behavior may change in future versions of binpac.) + +record +~~~~~~ + +A "record" composes primitive type(s) and other record(s) to create +new "type". This new "type" in turn can be used as part of parent type +or directly for parsing. + +Example: + +.. code:: + + type SMB_body = record { + word_count : uint8; + parameter_words : uint16[word_count]; + byte_count : uint16; + } + +case +~~~~ + +The "case" compositor allows switching between different parsing methods. + +.. code:: + + type SMB_string(unicode: bool, offset: int) = case unicode of { + true -> u: SMB_unicode_string(offset); + false -> a: SMB_ascii_string; + }; + +A "case" supports an optional "default" label to denote none of the +above labels are matched. If no fields follow a given label, a user +can specify an arbitrary field name with the "empty" type. See +the following example. + +.. code:: + + type HTTP_Message(expect_body: ExpectBody) = record { + headers: HTTP_Headers; + body_or_not: case expect_body of { + BODY_NOT_EXPECTED -> none: empty; + default -> body: HTTP_Body(expect_body); + }; + }; + +Note that only one field is allowed after a given label. If multiple fields +are to be specified, they should be packed in another "record" type first. +The other usages of `case`_ are described later. + +array +~~~~~ + +A type can be defined as a sequence of "single-type elements". By default, +array type continue parsing for the array element in an infinite loop. +Or an array size can be specified to control the number of +match. &until can be also conditionally end parsing: + +.. code:: + + # This will match for 10 element only + type HTTP_Headers = HTTP_Header [10]; + + # This will match until the condition is met + type HTTP_Headers = HTTP_Header [] &until(/*Some condition*/); + +Array can also be used directly inside of "record". For example: + +.. code:: + + type DNS_message = record { + header: DNS_header; + question: DNS_question(this)[header.qdcount]; + answer: DNS_rr(this, DNS_ANSWER)[header.ancount]; + authority: DNS_rr(this, DNS_AUTHORITY)[header.nscount]; + additional: DNS_rr(this, DNS_ADDITIONAL)[header.arcount]; + }&byteorder = bigendian, &exportsourcedata + +flow +---- + +A "flow" defines how data is fed into the analyzer. It also maintains +custom state information declared by `%member`_. flow is configured by +specifying type of data unit. + +Syntax: + +.. code:: + + flow () { + = withcontext (); + }; + +When "flow" is added to top level context analyzer, it enables use of &oneline +and &length in "record" type. flow buffers data when there is not enough +to evaluate the record and dispatches data for evaluation when the +threshold is reached. + +flowunit +~~~~~~~~ + +When flowunit is used, the analyzer uses flow buffer to handle incremental +input and provide support for &oneline/&length. For further detail on +this, see `Buffering`_. + +.. code:: + + flowunit = HTTP_PDU(is_orig) withcontext (analyzer, this); + +datagram +~~~~~~~~ + +Opposite to flowunit, by declaring data unit as datagram, flow buffer is +opted out. This results in faster parsing but no incremental input +or buffering support. + +.. code:: + + datagram = HTTP_PDU(is_orig) withcontext (analyzer, this); + +Byte Ordering and Alignment +--------------------------- + +Byte Ordering +~~~~~~~~~~~~~ + +Byte Alignment +~~~~~~~~~~~~~~ + +.. code:: + + type RPC_Opaque = record { + length: uint32; + data: uint8[length]; + pad: padding align 4; # pad to 4-byte boundary + }; + +Functions +--------- + +User can define functions in binpac. +Function can be declared using one of the three ways: + +PAC with embedded body +~~~~~~~~~~~~~~~~~~~~~~ + +PAC style function prototype and embed the body using %{ %}:: + + function print_stuff(value :const_bytestring):bool + %{ + printf("Value [%s]\n", std_str(value).c_str()); + %} + +PAC with PAC-case body +~~~~~~~~~~~~~~~~~~~~~~ + +Pac style function with a case body, this type of declaration is useful for +extending later by casefunc:: + + function RPC_Service(prog: uint32, vers: uint32): EnumRPCService = + case prog of { + default -> RPC_SERVICE_UNKNOWN; + }; + + +Inlined by %code +~~~~~~~~~~~~~~~~ + +Function can be completely inlined by using %code:: + + %code{ + EnumRPCService RPC_Service(const RPC_Call* call) + { + return call ? call->service() : RPC_SERVICE_UNKNOWN; + } + %} + + +Extending +--------- + +PAC code can be extended by using "refine". This is useful for code +reusing and splitting functionality for parallel development. + +Extending record +~~~~~~~~~~~~~~~~ + +Record can be extended to add additional attribute(s) by +using "refine typeattr". One of the typical use is to add &let for split +protocol parsing from protocol analysis. + +.. code:: + + refine typeattr HTTP_RequestLine += &let { + process_request: bool = + process_func(method, uri, version); + }; + +Extending type case +~~~~~~~~~~~~~~~~~~~ + +.. code:: + + refine casetype RPC_Params += { + RPC_SERVICE_PORTMAP -> portmap: PortmapParams(call); + }; + +Extending function case +~~~~~~~~~~~~~~~~~~~~~~~ + +Function which is declared as a PAC case can be extended by adding +additional case into the switch. + +.. code:: + + refine casefunc RPC_BuildCallVal += { + RPC_SERVICE_PORTMAP -> + PortmapBuildCallVal(call, call.params.portmap); + }; + +Extending connection +~~~~~~~~~~~~~~~~~~~~ + +Connection can be extended to add functions and members. Example:: + + refine connection RPC_Conn += { + function ProcessPortmapReply(results: PortmapResults): bool + %{ + %} + }; + +State Management +---------------- + +State is maintained by extending parsing class by declaring derivative. +State lasts until the top level parsing unit (flowunit/datagram is destroyed). + +Keywords +-------- + +Source code embedding +~~~~~~~~~~~~~~~~~~~~~ + +C++ code can be embedded within the .pac file using the following +directives. These code will be copied into the final generated code. + +- %header{...%} + + Code to be inserted in binpac generated header file. + +- %code{...%} + + Code to be inserted at the beginning of binpac generated C++ file. + +.. _%member: + +- %member{...%} + + Add additional member(s) to connection (?) and flow class. + +- %init{...%} + + Code to be inserted in flow constructor. + +- %cleanup{...%} + + Code to be inserted in flow destructor. + +Embedded pac primitive +~~~~~~~~~~~~~~~~~~~~~~ + +- ${ + +- $set{ + +- $type{ + +- $typeof{ + +- $const_def{ + +Condition checking +~~~~~~~~~~~~~~~~~~ + +&until +...... + +"&until" is used in conjunction with array declaration. It specifies exit +condition for array parsing. + +.. code:: + + type HTTP_Headers = HTTP_Header[] &until($input.length() == 0); + +&requires +......... + +Process data dependencies before evaluating field. + +Example: typically, derivative field is evaluated after primary field. +However "&requires" is used to force evaluate of length before msg_body. + +.. code:: + + type RPC_Message = record { + xid: uint32; + msg_type: uint32; + msg_body: case msg_type of { + RPC_CALL -> call: RPC_Call(this); + RPC_REPLY -> reply: RPC_Reply(this); + } &requires(length); + } &let { + length = sourcedata.length(); # length of the RPC_Message + } &byteorder = bigendian, &exportsourcedata, &refcount; + +&if +... + +Evaluate field only if condition is met. + +.. code:: + + type DNS_label(msg: DNS_message) = record { + length: uint8; + data: case label_type of { + 0 -> label: bytestring &length = length; + 3 -> ptr_lo: uint8; + }; + } &let { + label_type: uint8 = length >> 6; + last: bool = (length == 0) || (label_type == 3); + ptr: DNS_name(msg) + withinput $context.flow.get_pointer(msg.sourcedata, + ((length & 0x3f) << 8) | ptr_lo) + &if(label_type == 3); + clear_pointer_set: bool = $context.flow.reset_pointer_set() + &if(last); + }; + +.. _case: + +case +.... + +There are two uses to the "case" keyword. + +* As part of record field. In this scenario, it allow alternative + methods to parse a field. Example:: + + type RPC_Reply(msg: RPC_Message) = record { + stat: uint32; + reply: case stat of { + MSG_ACCEPTED -> areply: RPC_AcceptedReply(call); + MSG_DENIED -> rreply: RPC_RejectedReply(call); + }; + } &let { + call: RPC_Call = context.connection.FindCall(msg.xid); + success: bool = (stat == MSG_ACCEPTED && areply.stat == SUCCESS); + }; + + +* As function definition. Example:: + + function RPC_Service(prog: uint32, vers: uint32): EnumRPCService = + case prog of { + default -> RPC_SERVICE_UNKNOWN; + }; + + +Note that one can "refine" both types of cases: + +.. code:: + + refine casefunc RPC_Service += { + 100000 -> RPC_SERVICE_PORTMAP; + }; + +Built-in macros +~~~~~~~~~~~~~~~ + +$input +...... + +This macro refers to the data that was passed into the ParseBuffer +function. When $input is used, binpac generate a const_bytestring +which contains the start and end pointer of the input. + +PAC grammar:: + + &until($input.length()==0); + +PAC source:: + + const_bytestring t_val__elem_input(t_begin_of_data, t_end_of_data); + if ( ( t_val__elem_input.length() == 0 ) ) + +$element +........ + +$element provides access to entry of the array type. Following are +the ways which $element can be used. + +* Current element. Check on the value of the most recently parsed entry. + This would get executed after each time an entry is parsed. Example:: + + type SMB_ascii_string = uint8[] &until($element == 0); + +* Current element's field. Example:: + + type DNS_label(msg: DNS_message) = record { + length: uint8; + data: case label_type of { + 0 -> label: bytestring &length = length; + 3 -> ptr_lo: uint8; + }; + } &let { + label_type: uint8 = length >> 6; + last: bool = (length == 0) || (label_type == 3); + }; + type DNS_name(msg: DNS_message) = record { + labels: DNS_label(msg)[] &until($element.last); + }; + +$context +........ + +This macro refers to the Analyzer context class (Context class gets +generated from analyzer withcontext {}). Using this macro, users +can gain access to the "flow" object and "analyzer" object. + +Other keywords +~~~~~~~~~~~~~~ + +&transient +.......... + +Do not create copy of the bytestring + +.. code:: + + type MIME_Line = record { + line: bytestring &restofdata &transient; + } &oneline; + +&let +.... + +Adds derivative field to a record + +.. code:: + + type ncp_request(length: uint32) = record { + data : uint8[length]; + } &let { + function = length > 0 ? data[0] : 0; + subfunction = length > 1 ? data[1] : 0; + }; + +let +... + +Declares global value. If the user does not specify a type, +the compiler will assume the "int" type. + +PAC grammar:: + + let myValue:uint8=10; + +PAC source:: + + uint8 const myValue = 10; + +PAC header:: + + extern uint8 const myValue; + +&restofdata +........... + +Grab the rest of the data available in the FlowBuffer. + +PAC grammar:: + + onebyte: uint8; + value: bytestring &restofdata &transient; + +PAC source:: + + // Parse "onebyte" + onebyte_ = *((uint8 const *) (t_begin_of_data)); + // Parse "value" + int t_value_string_length; + t_value_string_length = (t_end_of_data) - ((t_begin_of_data + 1)); + int t_value__size; + t_value__size = t_value_string_length; + value_.init((t_begin_of_data + 1), t_value_string_length); + +&length +....... + +Length can appear in two different contexts: as property of a field +or as property of a record. +Examples: +&length as field property:: + + protocol : bytestring &length = 4; + +translates into:: + + const_byteptr t_end_of_data = t_begin_of_data + 4; + int t_protocol_string_length; + t_protocol_string_length = 4; + int t_protocol__size; + t_protocol__size = t_protocol_string_length; + protocol_.init(t_begin_of_data, t_protocol_string_length); + + +&check +...... + +This was originally intended to implement the behavior of the +superseding "&enforce" attribute. It always has and always will just be +a no-op to ensure anything that uses this doesn't suddenly and +unintentionally break. + +&enforce +........ + +Check a condition and raise exception if not met. + +&chunked and $chunk +................... + +When parsing a long field with variable length, "chunked" can be used to +improve performance. However, chunked field are not buffered across +packet. Data for the chunk in the current packet can be access by +using "$chunk". + +&exportsourcedata +................. + +Data matched for a particular type, the data matched can be retained by +using "&exportsourcedata". + +.pac file + +.. code:: + + type myType = record { + data:uint8; + } &exportsourcedata; + +_pac.h + +.. code:: + + class myType + { + public: + myType(); + ~myType(); + int Parse(const_byteptr const t_begin_of_data, const_byteptr const _end_of_data); + uint8 myData() const { return myData_; } + const_bytestring const & sourcedata() const { return sourcedata_; } + protected: + uint8 myData_; + const_bytestring sourcedata_; + }; + +_pac.cc + +.. code:: + + sourcedata_ = const_bytestring(t_begin_of_data, t_end_of_data); + sourcedata_.set_end(t_begin_of_data + 1); + +Source data can be used within the type that match it or at the parent type. + +.. code:: + + type myParentType (child:myType) = record { + somedata:uint8; + } &let{ + do_something:bool = print_stuff(child.sourcedata); + }; + +translates into + +.. code:: + + do_something_ = print_stuff(child()->sourcedata()); + +&refcount +......... + + +withinput +......... + + +Parsing Methodology +=================== + +.. _Buffering: + +Buffering +--------- + +binpac supports incremental input to deal with packet fragmentation. This +is done via use of FlowBuffer class and maintaining buffering/parsing states. + +FlowBuffer Class +~~~~~~~~~~~~~~~~ + +FlowBuffer provides two mode of buffering: line and frame. Line mode is +useful for parsing line based language like HTTP. Frame mode is best for +fixed length message. Buffering mode can be switched during parsing and +is done transparently to the grammar writer. + +At compile time binpac calculates number of bytes required to evaluate +each field. During run time, data is buffered up in FlowBuffer until +there is enough to evaluate the "record". To optimize the buffering +process, if FlowBuffer has enough data to evaluate on the first NewData, +it would only mark the start and end pointer instead of copying. + +- void **NewMessage**\(); + + - Advances the orig_data_begin\_ pointer depend on current mode\_. Moves + by 1/2 characters in LINE_MODE, by frame_length\_ in FRAME_MODE + and nothing in UNKNOWN_MODE (default mode). + + - Set buffer_n\_ to 0 + + - Reset message_complete\_ + +- void **NewLine**\(); + + - Reset frame_length\_ and chunked\_, set mode\_ to LINE_MODE + +- void **NewFrame**\(int frame_length, bool chunked\_); + +- void **GrowFrame**\(int new_frame_length); + +- void **AppendToBuffer**\(const_byteptr data, int len); + + - Reallocate buffer\_ to add new data then copy data + +- void **ExpandBuffer**\(int length); + + - Reallocate buffer\_ to new size if new size is bigger than current size. + + - Set minimum size to 512 (optimization?) + +- void **MarkOrCopyLine**\(); + + - Seek current input for end of line (CR/LF/CRLF depend on line break mode). + If found append found data to buffer if one is already created or mark (set + frame_length\_) if one is not created (to minimize copying). If end of line + is not found, append partial data till end of input to buffer. Buffer + is created if one is not there. + +- const_byteptr **begin**\()/**end**\() + + - Returns buffer\_ and buffer_n\_ if a buffer exist, otherwise + orig_data_begin\_ and orig_data_begin\_ + frame_length\_. + +Parsing States +~~~~~~~~~~~~~~ + +* buffering_state\_ - each parsing class contains a flag indicating whether + there are enough data buffered to evaluate the next block. + +* parsing_state\_ - each parsing class which consists of multiple parsing + data unit (line/frames) has this flag indicating the parsing stage. Each + time new data comes in, it invokes parsing function and switch on + parsing_state to determine which sub parser to use next. + +Regular Expression +------------------ + +Evaluation Order +---------------- + +Running Binpac-generated Analyzer Standalone +============================================ + +To run binpac-generated code independent of Zeek. Regex library must be +substituted. Below is one way of doing it. Use the following three header +files. + +RE.h +---- + +.. code:: + + /*Dummy file to replace Zeek's file*/ + #include "binpac_pcre.h" + #include "bro_dummy.h" + +bro_dummy.h +----------- + +.. code:: + + #ifndef BRO_DUMMY + #define BRO_DUMMY + #define DEBUG_MSG(x...) fprintf(stderr, x) + /*Dummy to link, this function suppose to be in Zeek*/ + double network_time(); + #endif + +binpac_pcre.h +------------- + +.. code:: + + #ifndef bro_pcre_h + #define bro_pcre_h + #include + #include + #include + using namespace std; + // TODO: use configure to figure out the location of pcre.h + #include "pcre.h" + class RE_Matcher { + public: + RE_Matcher(const char* pat){ + pattern_ = "^"; + pattern_ += "("; + pattern_ += pat; + pattern_ += ")"; + pcre_ = NULL; + pextra_ = NULL; + } + ~RE_Matcher() { + if (pcre_) { + pcre_free(pcre_); + } + } + int Compile() { + const char *err = NULL; + int erroffset = 0; + pcre_ = pcre_compile(pattern_.c_str(), + 0, // options, + &err, + &erroffset, + NULL); + if (pcre_ == NULL) { + fprintf(stderr, + "Error in RE_Matcher::Compile(): %d:%s\n", + erroffset, err); + return 0; + } + return 1; + } + + int MatchPrefix (const char* s, int n){ + const char *err=NULL; + assert(pcre_); + const int MAX_NUM_OFFSETS = 30; + int offsets[MAX_NUM_OFFSETS]; + int ret = pcre_exec(pcre_, + pextra_, // pcre_extra + //NULL, // pcre_extra + s, n, + 0, // offset + 0, // options + offsets, + MAX_NUM_OFFSETS); + if (ret < 0) { + return -1; + } + assert(offsets[0] == 0); + return offsets[1]; + } + protected: + pcre *pcre_; + string pattern_; + }; + #endif + +main.cc +------- + +In your main source, add this dummy stub. + +.. code:: + + /*Dummy to link, this function suppose to be in Zeek*/ + double network_time(){ + return 0; + } + + +Q & A +===== + +* Does &oneline only work when "flow" is used? + + Yes. binpac uses the flowunit definition in "flow" to figure out which + types require buffering. For those that do, the parse function is: + + .. code:: + + bool ParseBuffer(flow_buffer_t t_flow_buffer, ContextHTTP * t_context); + + And the code of flow_buffer_t provides the functionality of buffering up to + one line. That's why &oneline is only active when "flow" is used and the + type requires buffering. + + In certain cases we would want to use &oneline even if the type does + not require buffering, binpac currently does not provide such functionality. + +* How would incremental input work in the case of regex? + + A regex should not take incremental input. (The binpac compiler will + complain when that happens.) It should always appear below some type + that has either &length=... or &oneline. + +* What is the role of Context_ class (generated by analyzer + withcontext)? + +* What is the difference between ''withcontext'' and w/o ''withcontext''? + + withcontext should always be there. It's fine to have an empty context. + +* Elaborate on $context and how it is related to "withcontext". + + A "context" parameter is passed to every type. It provides a vehicle to + pass something to every type without adding a parameter to every type. + In that sense, it's optional. It exists for convenience. + +* Example usage of composite type array. + + Please see HTTP_Headers in http-protocol.pac in the Zeek source code. + +* Clarification on "connection" keyword (binpac paper). + +* Need a new way to attach hook additional code to each class beside &let. + +* &transient, how is this different from declaring anonymous field? and + currently it doesn't seem to do much + + .. code:: + + type HTTP_Header = record { + name: HTTP_HEADER_NAME &transient; + : HTTP_WS; + value: bytestring &restofdata &transient; + } &oneline; + + .. code:: + + // Parse "name" + int t_name_string_length; + t_name_string_length = + HTTP_HEADER_NAME_re_011.MatchPrefix( + t_begin_of_data, + t_end_of_data - t_begin_of_data); + if ( t_name_string_length < 0 ) + { + throw ExceptionStringMismatch( "./http-protocol.pac:96", + "|([^: \\t]+:)", + string((const char *) (t_begin_of_data), (const char *) t_end_of_data).c_str() + ); + } + int t_name__size; + t_name__size = t_name_string_length; + name_.init(t_begin_of_data, t_name_string_length); + +* Detail on the globals ($context, $element, $input...etc) + +* How does BinPAC work with dynamic protocol detection? + + Well, you can use the code in DNS-binpac.cc as a reference. First, + create a pointer to the connection. (See the example in DNS-binpac.cc) + + .. code:: + + interp = new binpac::DNS::DNS_Conn(this); + + Pass the data received from "DeliverPacket" or "DeliverStream" to + "interp->NewData()". (Again, see the example in DNS-binpac.cc) + + .. code:: + + void DNS_UDP_Analyzer_binpac::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) + { + Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); + interp->NewData(orig, data, data + len); + } + +* Explanation of &withinput + +* Difference between using flow and not using flow (binpac generates Parse + method instead of ParseBuffer) + +* &check currently working? + +* Difference between flowunit and datagram, datagram and &oneline, &length? + +* Go over TODO list in binpac release + +* How would input get handle/buffered when length is not known (chunked) + +* More feature multi byte character? utf16 utf32 etc. + +TODO List +========= + +New Features +------------ + +* Provides a method to match simple ascii text. + +* Allows use fixed length array in addition to vector. + +Bugs +---- + +Small clean-ups +~~~~~~~~~~~~~~~ + +* Remove anonymous field bytestring assignment. + +* Redundant overflow checking/more efficient fixed length text copying. + +Warning/Errors +~~~~~~~~~~~~~~ + +Things that compiler should flag out at code generation time + +* Give warning when &transient is used on none bytestring + +* Give warning when &oneline, &length is used and flowunit is not. + +* Warning when more than one "connection" is defined From 03774866371a9d49d849fb9b7c7f05f17df5a601 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sun, 17 Aug 2025 18:58:00 -0700 Subject: [PATCH 149/343] binpac: Remove submodule, adapt CMake configuration for Zeek build --- .gitmodules | 3 -- CMakeLists.txt | 8 ++-- auxil/binpac | 1 - tools/binpac/CMakeLists.txt | 81 --------------------------------- tools/binpac/lib/CMakeLists.txt | 40 ++++++++-------- tools/binpac/src/CMakeLists.txt | 66 +++++---------------------- tools/binpac/src/pac_main.cc | 1 - 7 files changed, 34 insertions(+), 166 deletions(-) delete mode 160000 auxil/binpac diff --git a/.gitmodules b/.gitmodules index 73f8a0aead..a83702e82a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "auxil/zeek-aux"] path = auxil/zeek-aux url = https://github.com/zeek/zeek-aux -[submodule "auxil/binpac"] - path = auxil/binpac - url = https://github.com/zeek/binpac [submodule "auxil/zeekctl"] path = auxil/zeekctl url = https://github.com/zeek/zeekctl diff --git a/CMakeLists.txt b/CMakeLists.txt index 18a2072853..d2b4734d54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -396,14 +396,14 @@ endfunction () add_zeek_dynamic_plugin_build_interface_include_directories( ${PROJECT_SOURCE_DIR}/src/include - ${PROJECT_SOURCE_DIR}/auxil/binpac/lib + ${PROJECT_SOURCE_DIR}/tools/binpac/lib ${PROJECT_SOURCE_DIR}/auxil/broker/libbroker ${PROJECT_SOURCE_DIR}/auxil/paraglob/include ${PROJECT_SOURCE_DIR}/auxil/prometheus-cpp/core/include ${PROJECT_SOURCE_DIR}/auxil/expected-lite/include ${CMAKE_BINARY_DIR}/src ${CMAKE_BINARY_DIR}/src/include - ${CMAKE_BINARY_DIR}/auxil/binpac/lib + ${CMAKE_BINARY_DIR}/tools/binpac/lib ${CMAKE_BINARY_DIR}/auxil/broker/libbroker ${CMAKE_BINARY_DIR}/auxil/prometheus-cpp/core/include) @@ -892,12 +892,12 @@ if (BUILD_STATIC_BINPAC) set(ENABLE_STATIC_ONLY true) endif () -add_subdirectory(auxil/binpac) +add_subdirectory(tools/binpac) set(ENABLE_STATIC_ONLY ${ENABLE_STATIC_ONLY_SAVED}) # FIXME: avoid hard-coding a path for multi-config generator support. See the # TODO in ZeekPluginConfig.cmake.in. -set(BINPAC_EXE_PATH "${CMAKE_BINARY_DIR}/auxil/binpac/src/binpac${CMAKE_EXECUTABLE_SUFFIX}") +set(BINPAC_EXE_PATH "${CMAKE_BINARY_DIR}/tools/binpac/src/binpac${CMAKE_EXECUTABLE_SUFFIX}") set(_binpac_exe_path "included") # Need to call find_package so it sets up the include paths used by plugin builds. diff --git a/auxil/binpac b/auxil/binpac deleted file mode 160000 index 48f75b5f64..0000000000 --- a/auxil/binpac +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 48f75b5f6415fe9d597e3e991cec635b1bc400dc diff --git a/tools/binpac/CMakeLists.txt b/tools/binpac/CMakeLists.txt index 7dbec04ca2..d02456bfec 100644 --- a/tools/binpac/CMakeLists.txt +++ b/tools/binpac/CMakeLists.txt @@ -1,86 +1,5 @@ -cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR) -project(BinPAC C CXX) -include(cmake/CommonCMakeConfig.cmake) -include(cmake/RequireCXXStd.cmake) - -file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BINPAC_VERSION LIMIT_COUNT 1) -string(REPLACE "." " " _version_numbers ${BINPAC_VERSION}) -separate_arguments(_version_numbers) -list(GET _version_numbers 0 BINPAC_VERSION_MAJOR) -list(GET _version_numbers 1 BINPAC_VERSION_MINOR) -string(REGEX REPLACE "-[0-9]*$" "" BINPAC_VERSION_MINOR ${BINPAC_VERSION_MINOR}) - -# The SO number shall increase only if binary interface changes. -set(BINPAC_SOVERSION 0) - -set(ENABLE_SHARED true) - -if (ENABLE_STATIC_ONLY) - set(ENABLE_STATIC true) - set(ENABLE_SHARED false) -endif () - -# Set default install paths -include(GNUInstallDirs) - -# ############################################################################## -# Dependency Configuration - -find_package(FLEX REQUIRED) -find_package(BISON REQUIRED) - -if (MSVC) - add_compile_options(/J) # Similar to -funsigned-char on other platforms -endif () - -# ############################################################################## -# System Introspection - -configure_file(${PROJECT_SOURCE_DIR}/config.h.in ${PROJECT_BINARY_DIR}/config.h) - -include_directories(BEFORE ${PROJECT_BINARY_DIR}) - # ############################################################################## # Recurse on sub-directories add_subdirectory(lib) add_subdirectory(src) - -# ############################################################################## -# Build Summary - -if (CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) -endif () - -macro (display test desc summary) - if (${test}) - set(${summary} ${desc}) - else () - set(${summary} no) - endif () -endmacro () - -display(ENABLE_SHARED yes shared_summary) -display(ENABLE_STATIC yes static_summary) - -message( - "\n==================| BinPAC Build Summary |====================" - "\nVersion: ${BINPAC_VERSION}" - "\nSO version: ${BINPAC_SOVERSION}" - "\n" - "\nBuild Type: ${CMAKE_BUILD_TYPE}" - "\nDebug mode: ${ENABLE_DEBUG}" - "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" - "\nShared libs: ${shared_summary}" - "\nStatic libs: ${static_summary}" - "\n" - "\nCC: ${CMAKE_C_COMPILER}" - "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" - "\nCXX: ${CMAKE_CXX_COMPILER}" - "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" - "\nCPP: ${CMAKE_CXX_COMPILER}" - "\n" - "\n================================================================\n") - -include(UserChangedWarning) diff --git a/tools/binpac/lib/CMakeLists.txt b/tools/binpac/lib/CMakeLists.txt index de2eb4aa4f..3502fa1fa0 100644 --- a/tools/binpac/lib/CMakeLists.txt +++ b/tools/binpac/lib/CMakeLists.txt @@ -10,23 +10,27 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) set(binpac_headers ${CMAKE_CURRENT_BINARY_DIR}/binpac.h binpac_analyzer.h binpac_buffer.h binpac_bytestring.h binpac_exception.h binpac_regex.h) -set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc binpac_regex.cc ${binpac_headers}) +set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc binpac_regex.cc) -if (ENABLE_SHARED) - add_library(binpac_lib SHARED ${binpac_lib_SRCS}) - set_target_properties( - binpac_lib - PROPERTIES SOVERSION ${BINPAC_SOVERSION} - VERSION ${BINPAC_VERSION_MAJOR}.${BINPAC_VERSION_MINOR} - MACOSX_RPATH true - OUTPUT_NAME binpac) - install(TARGETS binpac_lib DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif () - -if (ENABLE_STATIC) - add_library(binpac_static STATIC ${binpac_lib_SRCS}) +if (BUILD_STATIC_BINPAC) + add_library(binpac_static STATIC) + target_sources(binpac_static PRIVATE ${binpac_lib_SRCS}) set_target_properties(binpac_static PROPERTIES OUTPUT_NAME binpac) install(TARGETS binpac_static DESTINATION ${CMAKE_INSTALL_LIBDIR}) + if (MSVC) + target_compile_options(binpac_static PRIVATE "/J") + endif () + set(BinPAC_LIBRARY binpac_static CACHE STRING "BinPAC library" FORCE) +else () + add_library(binpac_lib SHARED) + target_sources(binpac_lib PRIVATE ${binpac_lib_SRCS}) + target_sources(binpac_lib INTERFACE ${binpac_headers}) + set_target_properties(binpac_lib PROPERTIES MACOSX_RPATH true OUTPUT_NAME binpac) + if (MSVC) + target_compile_options(binpac_lib PRIVATE "/J") + endif () + install(TARGETS binpac_lib DESTINATION ${CMAKE_INSTALL_LIBDIR}) + set(BinPAC_LIBRARY binpac_lib CACHE STRING "BinPAC library" FORCE) endif () if (ZEEK_ROOT_DIR) @@ -36,13 +40,5 @@ else () install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) endif () -# This is set to assist superprojects that want to build BinPac from source and -# rely on it as a target -if (ENABLE_SHARED) - set(BinPAC_LIBRARY binpac_lib CACHE STRING "BinPAC library" FORCE) -else () - set(BinPAC_LIBRARY binpac_static CACHE STRING "BinPAC library" FORCE) -endif () - set(BinPAC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} CACHE STRING "BinPAC header directories" FORCE) diff --git a/tools/binpac/src/CMakeLists.txt b/tools/binpac/src/CMakeLists.txt index f3c8b2e2b9..2a3654c2e7 100644 --- a/tools/binpac/src/CMakeLists.txt +++ b/tools/binpac/src/CMakeLists.txt @@ -1,6 +1,9 @@ -bison_target(PACParser pac_parse.yy ${BinPAC_BINARY_DIR}/src/pac_parse.cc - DEFINES_FILE ${BinPAC_BINARY_DIR}/src/pac_parse.h COMPILE_FLAGS "--debug") -flex_target(PACScanner pac_scan.ll ${BinPAC_BINARY_DIR}/pac_scan.cc) +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) + +bison_target(PACParser pac_parse.yy ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.cc + DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/pac_parse.h COMPILE_FLAGS "--debug") +flex_target(PACScanner pac_scan.ll ${CMAKE_CURRENT_BINARY_DIR}/pac_scan.cc) add_flex_bison_dependency(PACScanner PACParser) if (MSVC) set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") @@ -8,8 +11,6 @@ else () set_property(SOURCE pac_scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") endif () -include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src) - set(binpac_SRCS ${BISON_PACParser_INPUT} ${FLEX_PACScanner_INPUT} @@ -52,62 +53,19 @@ set(binpac_SRCS pac_output.cc pac_utils.cc pac_exception.cc - pac_main.cc - pac_action.h - pac_analyzer.h - pac_array.h - pac_attr.h - pac_btype.h - pac_case.h - pac_cclass.h - pac_common.h - pac_conn.h - pac_context.h - pac_cstr.h - pac_ctype.h - pac_datadep.h - pac_dataptr.h - pac_dataunit.h - pac_dbg.h - pac_decl-inl.h - pac_decl.h - pac_embedded.h - pac_enum.h - pac_exception.h - pac_expr.h - pac_exttype.h - pac_field.h - pac_flow.h - pac_func.h - pac_id.h - pac_inputbuf.h - pac_let.h - pac_nullptr.h - pac_number.h - pac_output.h - pac_param.h - pac_paramtype.h - pac_primitive.h - pac_record.h - pac_redef.h - pac_regex.h - pac_state.h - pac_strtype.h - pac_type.h - pac_typedecl.h - pac_utils.h - pac_varfield.h - pac_withinput.h) - -include(${PROJECT_SOURCE_DIR}/cmake/RequireCXXStd.cmake) + pac_main.cc) add_executable(binpac ${binpac_SRCS}) +target_include_directories(binpac BEFORE PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(binpac BEFORE PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + if (MSVC) + target_compile_options(binpac PUBLIC "/J") # If building separately from zeek, we need to add the libunistd subdirectory # so that linking doesn't fail. if ("${CMAKE_PROJECT_NAME}" STREQUAL "BinPAC") - add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) + add_subdirectory(${PROJECT_SOURCE_DIR}auxil/libunistd EXCLUDE_FROM_ALL) endif () target_link_libraries(binpac PRIVATE libunistd) endif () diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index fca52ef5cc..cd9a11feb9 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -1,7 +1,6 @@ #include #include -#include "config.h" #include "pac_common.h" #include "pac_decl.h" #include "pac_exception.h" From 6bddc06f8d156e8b6675c574d877634167f781d5 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 13 Aug 2025 15:47:47 -0700 Subject: [PATCH 150/343] Add copyright headers to all of the binpac source files --- tools/binpac/lib/binpac_analyzer.h | 2 ++ tools/binpac/lib/binpac_buffer.cc | 2 ++ tools/binpac/lib/binpac_buffer.h | 2 ++ tools/binpac/lib/binpac_bytestring.cc | 2 ++ tools/binpac/lib/binpac_bytestring.h | 2 ++ tools/binpac/lib/binpac_exception.h | 2 ++ tools/binpac/lib/binpac_regex.cc | 1 + tools/binpac/src/pac_action.cc | 2 ++ tools/binpac/src/pac_action.h | 2 ++ tools/binpac/src/pac_analyzer.cc | 2 ++ tools/binpac/src/pac_analyzer.h | 2 ++ tools/binpac/src/pac_array.cc | 2 ++ tools/binpac/src/pac_array.h | 2 ++ tools/binpac/src/pac_attr.cc | 2 ++ tools/binpac/src/pac_attr.h | 2 ++ tools/binpac/src/pac_btype.cc | 2 ++ tools/binpac/src/pac_btype.h | 2 ++ tools/binpac/src/pac_case.cc | 2 ++ tools/binpac/src/pac_case.h | 2 ++ tools/binpac/src/pac_cclass.h | 2 ++ tools/binpac/src/pac_common.h | 2 ++ tools/binpac/src/pac_conn.cc | 2 ++ tools/binpac/src/pac_conn.h | 2 ++ tools/binpac/src/pac_context.cc | 2 ++ tools/binpac/src/pac_context.h | 2 ++ tools/binpac/src/pac_cstr.cc | 2 ++ tools/binpac/src/pac_cstr.h | 2 ++ tools/binpac/src/pac_ctype.cc | 2 ++ tools/binpac/src/pac_ctype.h | 2 ++ tools/binpac/src/pac_datadep.cc | 2 ++ tools/binpac/src/pac_datadep.h | 2 ++ tools/binpac/src/pac_dataptr.cc | 2 ++ tools/binpac/src/pac_dataptr.h | 2 ++ tools/binpac/src/pac_dataunit.cc | 2 ++ tools/binpac/src/pac_dataunit.h | 2 ++ tools/binpac/src/pac_dbg.h | 2 ++ tools/binpac/src/pac_decl-inl.h | 2 ++ tools/binpac/src/pac_decl.cc | 2 ++ tools/binpac/src/pac_decl.h | 2 ++ tools/binpac/src/pac_embedded.cc | 2 ++ tools/binpac/src/pac_embedded.h | 2 ++ tools/binpac/src/pac_enum.cc | 2 ++ tools/binpac/src/pac_enum.h | 2 ++ tools/binpac/src/pac_exception.cc | 2 ++ tools/binpac/src/pac_exception.h | 2 ++ tools/binpac/src/pac_expr.cc | 2 ++ tools/binpac/src/pac_expr.h | 2 ++ tools/binpac/src/pac_exttype.cc | 2 ++ tools/binpac/src/pac_exttype.h | 2 ++ tools/binpac/src/pac_field.cc | 2 ++ tools/binpac/src/pac_field.h | 2 ++ tools/binpac/src/pac_flow.cc | 2 ++ tools/binpac/src/pac_flow.h | 2 ++ tools/binpac/src/pac_func.cc | 2 ++ tools/binpac/src/pac_func.h | 2 ++ tools/binpac/src/pac_id.cc | 2 ++ tools/binpac/src/pac_id.h | 2 ++ tools/binpac/src/pac_inputbuf.cc | 2 ++ tools/binpac/src/pac_inputbuf.h | 2 ++ tools/binpac/src/pac_let.cc | 2 ++ tools/binpac/src/pac_let.h | 2 ++ tools/binpac/src/pac_main.cc | 2 ++ tools/binpac/src/pac_nullptr.h | 2 ++ tools/binpac/src/pac_number.h | 2 ++ tools/binpac/src/pac_output.cc | 2 ++ tools/binpac/src/pac_output.h | 2 ++ tools/binpac/src/pac_param.cc | 2 ++ tools/binpac/src/pac_param.h | 2 ++ tools/binpac/src/pac_paramtype.cc | 2 ++ tools/binpac/src/pac_paramtype.h | 2 ++ tools/binpac/src/pac_primitive.cc | 2 ++ tools/binpac/src/pac_primitive.h | 2 ++ tools/binpac/src/pac_record.cc | 2 ++ tools/binpac/src/pac_record.h | 2 ++ tools/binpac/src/pac_redef.cc | 2 ++ tools/binpac/src/pac_redef.h | 2 ++ tools/binpac/src/pac_regex.cc | 2 ++ tools/binpac/src/pac_regex.h | 2 ++ tools/binpac/src/pac_state.cc | 2 ++ tools/binpac/src/pac_state.h | 2 ++ tools/binpac/src/pac_strtype.cc | 2 ++ tools/binpac/src/pac_strtype.h | 2 ++ tools/binpac/src/pac_type.cc | 2 ++ tools/binpac/src/pac_type.h | 2 ++ tools/binpac/src/pac_typedecl.cc | 2 ++ tools/binpac/src/pac_typedecl.h | 2 ++ tools/binpac/src/pac_utils.cc | 2 ++ tools/binpac/src/pac_utils.h | 2 ++ tools/binpac/src/pac_varfield.cc | 2 ++ tools/binpac/src/pac_varfield.h | 2 ++ tools/binpac/src/pac_withinput.cc | 2 ++ tools/binpac/src/pac_withinput.h | 2 ++ 92 files changed, 183 insertions(+) diff --git a/tools/binpac/lib/binpac_analyzer.h b/tools/binpac/lib/binpac_analyzer.h index e3e4a9ffd5..9e03b593d1 100644 --- a/tools/binpac/lib/binpac_analyzer.h +++ b/tools/binpac/lib/binpac_analyzer.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef binpac_an_h #define binpac_an_h diff --git a/tools/binpac/lib/binpac_buffer.cc b/tools/binpac/lib/binpac_buffer.cc index 915c370e1d..92cde625c8 100644 --- a/tools/binpac/lib/binpac_buffer.cc +++ b/tools/binpac/lib/binpac_buffer.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include #include #include // for memcpy diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h index a4de6d66e9..f7cf012950 100644 --- a/tools/binpac/lib/binpac_buffer.h +++ b/tools/binpac/lib/binpac_buffer.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef binpac_buffer_h #define binpac_buffer_h diff --git a/tools/binpac/lib/binpac_bytestring.cc b/tools/binpac/lib/binpac_bytestring.cc index be34209d6c..dd07d78976 100644 --- a/tools/binpac/lib/binpac_bytestring.cc +++ b/tools/binpac/lib/binpac_bytestring.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #define binpac_regex_h #include "binpac_bytestring.h" diff --git a/tools/binpac/lib/binpac_bytestring.h b/tools/binpac/lib/binpac_bytestring.h index c9b856f655..6a33f2eb8f 100644 --- a/tools/binpac/lib/binpac_bytestring.h +++ b/tools/binpac/lib/binpac_bytestring.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef binpac_bytestring_h #define binpac_bytestring_h diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h index 6b4f57a718..8578ae83fc 100644 --- a/tools/binpac/lib/binpac_exception.h +++ b/tools/binpac/lib/binpac_exception.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef binpac_exception_h #define binpac_exception_h diff --git a/tools/binpac/lib/binpac_regex.cc b/tools/binpac/lib/binpac_regex.cc index 3fb146772b..34ca1add2a 100644 --- a/tools/binpac/lib/binpac_regex.cc +++ b/tools/binpac/lib/binpac_regex.cc @@ -1,3 +1,4 @@ +// See the file "COPYING" in the main distribution directory for copyright. #include diff --git a/tools/binpac/src/pac_action.cc b/tools/binpac/src/pac_action.cc index 2863f65402..12afd6a9ba 100644 --- a/tools/binpac/src/pac_action.cc +++ b/tools/binpac/src/pac_action.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_action.h" #include "pac_embedded.h" diff --git a/tools/binpac/src/pac_action.h b/tools/binpac/src/pac_action.h index 3e8d4357e1..521fc4d0da 100644 --- a/tools/binpac/src/pac_action.h +++ b/tools/binpac/src/pac_action.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_action_h #define pac_action_h diff --git a/tools/binpac/src/pac_analyzer.cc b/tools/binpac/src/pac_analyzer.cc index d404fa34d6..d128afadab 100644 --- a/tools/binpac/src/pac_analyzer.cc +++ b/tools/binpac/src/pac_analyzer.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_analyzer.h" #include "pac_action.h" diff --git a/tools/binpac/src/pac_analyzer.h b/tools/binpac/src/pac_analyzer.h index 671e2b030f..7c6a6c523a 100644 --- a/tools/binpac/src/pac_analyzer.h +++ b/tools/binpac/src/pac_analyzer.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_analyzer_h #define pac_analyzer_h diff --git a/tools/binpac/src/pac_array.cc b/tools/binpac/src/pac_array.cc index b59d9a43a1..d942de1c96 100644 --- a/tools/binpac/src/pac_array.cc +++ b/tools/binpac/src/pac_array.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_array.h" #include "pac_attr.h" diff --git a/tools/binpac/src/pac_array.h b/tools/binpac/src/pac_array.h index 2baadc840f..bf0791a805 100644 --- a/tools/binpac/src/pac_array.h +++ b/tools/binpac/src/pac_array.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_array_h #define pac_array_h diff --git a/tools/binpac/src/pac_attr.cc b/tools/binpac/src/pac_attr.cc index 858f5051ce..a917ea2ea2 100644 --- a/tools/binpac/src/pac_attr.cc +++ b/tools/binpac/src/pac_attr.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_attr.h" #include "pac_expr.h" diff --git a/tools/binpac/src/pac_attr.h b/tools/binpac/src/pac_attr.h index 1b6a0d8321..7dd5a74d05 100644 --- a/tools/binpac/src/pac_attr.h +++ b/tools/binpac/src/pac_attr.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_attr_h #define pac_attr_h diff --git a/tools/binpac/src/pac_btype.cc b/tools/binpac/src/pac_btype.cc index d56b9ab6df..27844d786c 100644 --- a/tools/binpac/src/pac_btype.cc +++ b/tools/binpac/src/pac_btype.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_btype.h" #include "pac_dataptr.h" diff --git a/tools/binpac/src/pac_btype.h b/tools/binpac/src/pac_btype.h index bff7be5404..320d2cb886 100644 --- a/tools/binpac/src/pac_btype.h +++ b/tools/binpac/src/pac_btype.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_btype_h #define pac_btype_h diff --git a/tools/binpac/src/pac_case.cc b/tools/binpac/src/pac_case.cc index 38f7963dfe..c9c859cc80 100644 --- a/tools/binpac/src/pac_case.cc +++ b/tools/binpac/src/pac_case.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_case.h" #include diff --git a/tools/binpac/src/pac_case.h b/tools/binpac/src/pac_case.h index bb8e862b43..bbeefaaf18 100644 --- a/tools/binpac/src/pac_case.h +++ b/tools/binpac/src/pac_case.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_case_h #define pac_case_h diff --git a/tools/binpac/src/pac_cclass.h b/tools/binpac/src/pac_cclass.h index d1129f6f99..c28b297f22 100644 --- a/tools/binpac/src/pac_cclass.h +++ b/tools/binpac/src/pac_cclass.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_cclass_h #define pac_cclass_h diff --git a/tools/binpac/src/pac_common.h b/tools/binpac/src/pac_common.h index 0808450c27..4289506882 100644 --- a/tools/binpac/src/pac_common.h +++ b/tools/binpac/src/pac_common.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_common_h #define pac_common_h diff --git a/tools/binpac/src/pac_conn.cc b/tools/binpac/src/pac_conn.cc index deb8a77a6e..ae26c75a1c 100644 --- a/tools/binpac/src/pac_conn.cc +++ b/tools/binpac/src/pac_conn.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_conn.h" #include "pac_analyzer.h" diff --git a/tools/binpac/src/pac_conn.h b/tools/binpac/src/pac_conn.h index eb63cce603..08acaebb1b 100644 --- a/tools/binpac/src/pac_conn.h +++ b/tools/binpac/src/pac_conn.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_conn_h #define pac_conn_h diff --git a/tools/binpac/src/pac_context.cc b/tools/binpac/src/pac_context.cc index 59f3ee20bb..ced1770377 100644 --- a/tools/binpac/src/pac_context.cc +++ b/tools/binpac/src/pac_context.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_context.h" #include "pac_analyzer.h" diff --git a/tools/binpac/src/pac_context.h b/tools/binpac/src/pac_context.h index a52052e10e..bb5a8264b3 100644 --- a/tools/binpac/src/pac_context.h +++ b/tools/binpac/src/pac_context.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_context_h #define pac_context_h diff --git a/tools/binpac/src/pac_cstr.cc b/tools/binpac/src/pac_cstr.cc index cd3120a29a..fa61824af3 100644 --- a/tools/binpac/src/pac_cstr.cc +++ b/tools/binpac/src/pac_cstr.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_cstr.h" #include "pac_dbg.h" diff --git a/tools/binpac/src/pac_cstr.h b/tools/binpac/src/pac_cstr.h index 7443397329..90735cc2d5 100644 --- a/tools/binpac/src/pac_cstr.h +++ b/tools/binpac/src/pac_cstr.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_cstr_h #define pac_cstr_h diff --git a/tools/binpac/src/pac_ctype.cc b/tools/binpac/src/pac_ctype.cc index cb36a9f51c..f892c03105 100644 --- a/tools/binpac/src/pac_ctype.cc +++ b/tools/binpac/src/pac_ctype.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_ctype.h" string CType::DeclareInstance(const string& var) const { return strfmt("%s %s", name().c_str(), var.c_str()); } diff --git a/tools/binpac/src/pac_ctype.h b/tools/binpac/src/pac_ctype.h index 11ab0b8f82..472d89fb64 100644 --- a/tools/binpac/src/pac_ctype.h +++ b/tools/binpac/src/pac_ctype.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_ctype_h #define pac_ctype_h diff --git a/tools/binpac/src/pac_datadep.cc b/tools/binpac/src/pac_datadep.cc index 85402db510..dfa85ebb48 100644 --- a/tools/binpac/src/pac_datadep.cc +++ b/tools/binpac/src/pac_datadep.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_datadep.h" #include "pac_expr.h" diff --git a/tools/binpac/src/pac_datadep.h b/tools/binpac/src/pac_datadep.h index 184e2563b9..9267375241 100644 --- a/tools/binpac/src/pac_datadep.h +++ b/tools/binpac/src/pac_datadep.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_datadep_h #define pac_datadep_h diff --git a/tools/binpac/src/pac_dataptr.cc b/tools/binpac/src/pac_dataptr.cc index 53d44e60b0..8abe60283d 100644 --- a/tools/binpac/src/pac_dataptr.cc +++ b/tools/binpac/src/pac_dataptr.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_dataptr.h" #include "pac_exception.h" diff --git a/tools/binpac/src/pac_dataptr.h b/tools/binpac/src/pac_dataptr.h index 1ad102f8a1..676b610d02 100644 --- a/tools/binpac/src/pac_dataptr.h +++ b/tools/binpac/src/pac_dataptr.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_dataptr_h #define pac_dataptr_h diff --git a/tools/binpac/src/pac_dataunit.cc b/tools/binpac/src/pac_dataunit.cc index a51ba4ccca..50443dc0ca 100644 --- a/tools/binpac/src/pac_dataunit.cc +++ b/tools/binpac/src/pac_dataunit.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_dataunit.h" #include "pac_context.h" diff --git a/tools/binpac/src/pac_dataunit.h b/tools/binpac/src/pac_dataunit.h index cf3d6edaa0..e8a6fe9465 100644 --- a/tools/binpac/src/pac_dataunit.h +++ b/tools/binpac/src/pac_dataunit.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_dataunit_h #define pac_dataunit_h diff --git a/tools/binpac/src/pac_dbg.h b/tools/binpac/src/pac_dbg.h index 04b8518096..9f930ffc40 100644 --- a/tools/binpac/src/pac_dbg.h +++ b/tools/binpac/src/pac_dbg.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_dbg_h #define pac_dbg_h diff --git a/tools/binpac/src/pac_decl-inl.h b/tools/binpac/src/pac_decl-inl.h index 84dfce9d01..587fa43163 100644 --- a/tools/binpac/src/pac_decl-inl.h +++ b/tools/binpac/src/pac_decl-inl.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_decl_inl_h #define pac_decl_inl_h diff --git a/tools/binpac/src/pac_decl.cc b/tools/binpac/src/pac_decl.cc index 1ea3325d0f..f8605cbdb4 100644 --- a/tools/binpac/src/pac_decl.cc +++ b/tools/binpac/src/pac_decl.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_decl.h" #include "pac_attr.h" diff --git a/tools/binpac/src/pac_decl.h b/tools/binpac/src/pac_decl.h index f3c4426b3c..b5e2a2557a 100644 --- a/tools/binpac/src/pac_decl.h +++ b/tools/binpac/src/pac_decl.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_decl_h #define pac_decl_h diff --git a/tools/binpac/src/pac_embedded.cc b/tools/binpac/src/pac_embedded.cc index 48dc39143e..3296715ac9 100644 --- a/tools/binpac/src/pac_embedded.cc +++ b/tools/binpac/src/pac_embedded.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_embedded.h" #include "pac_id.h" diff --git a/tools/binpac/src/pac_embedded.h b/tools/binpac/src/pac_embedded.h index 93403411b2..a2f85f74f7 100644 --- a/tools/binpac/src/pac_embedded.h +++ b/tools/binpac/src/pac_embedded.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_embedded_h #define pac_embedded_h diff --git a/tools/binpac/src/pac_enum.cc b/tools/binpac/src/pac_enum.cc index 02e90fe0c6..e31563d6de 100644 --- a/tools/binpac/src/pac_enum.cc +++ b/tools/binpac/src/pac_enum.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_enum.h" #include "pac_exception.h" diff --git a/tools/binpac/src/pac_enum.h b/tools/binpac/src/pac_enum.h index fa7fdec776..1b74e9016a 100644 --- a/tools/binpac/src/pac_enum.h +++ b/tools/binpac/src/pac_enum.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_enum_h #define pac_enum_h diff --git a/tools/binpac/src/pac_exception.cc b/tools/binpac/src/pac_exception.cc index c985338796..dfa911618c 100644 --- a/tools/binpac/src/pac_exception.cc +++ b/tools/binpac/src/pac_exception.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_exception.h" #include "pac_expr.h" diff --git a/tools/binpac/src/pac_exception.h b/tools/binpac/src/pac_exception.h index c3860539a1..2c06603dec 100644 --- a/tools/binpac/src/pac_exception.h +++ b/tools/binpac/src/pac_exception.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_exception_h #define pac_exception_h diff --git a/tools/binpac/src/pac_expr.cc b/tools/binpac/src/pac_expr.cc index 360562afc5..fc4cbcc38d 100644 --- a/tools/binpac/src/pac_expr.cc +++ b/tools/binpac/src/pac_expr.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_expr.h" #include "pac_case.h" diff --git a/tools/binpac/src/pac_expr.h b/tools/binpac/src/pac_expr.h index f72f1439e2..7fc698db75 100644 --- a/tools/binpac/src/pac_expr.h +++ b/tools/binpac/src/pac_expr.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_expr_h #define pac_expr_h diff --git a/tools/binpac/src/pac_exttype.cc b/tools/binpac/src/pac_exttype.cc index 7b9970c91e..d2adb77aee 100644 --- a/tools/binpac/src/pac_exttype.cc +++ b/tools/binpac/src/pac_exttype.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_exttype.h" #include "pac_decl.h" diff --git a/tools/binpac/src/pac_exttype.h b/tools/binpac/src/pac_exttype.h index 8f49332d6b..cf4ead6643 100644 --- a/tools/binpac/src/pac_exttype.h +++ b/tools/binpac/src/pac_exttype.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_exttype_h #define pac_exttype_h diff --git a/tools/binpac/src/pac_field.cc b/tools/binpac/src/pac_field.cc index 0673555878..b706c744d8 100644 --- a/tools/binpac/src/pac_field.cc +++ b/tools/binpac/src/pac_field.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_field.h" #include "pac_attr.h" diff --git a/tools/binpac/src/pac_field.h b/tools/binpac/src/pac_field.h index bde5ff0f43..8211eca839 100644 --- a/tools/binpac/src/pac_field.h +++ b/tools/binpac/src/pac_field.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_field_h #define pac_field_h diff --git a/tools/binpac/src/pac_flow.cc b/tools/binpac/src/pac_flow.cc index 7b72979b38..6e6944a78d 100644 --- a/tools/binpac/src/pac_flow.cc +++ b/tools/binpac/src/pac_flow.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_flow.h" #include "pac_analyzer.h" diff --git a/tools/binpac/src/pac_flow.h b/tools/binpac/src/pac_flow.h index ae15b6bbad..7008248b62 100644 --- a/tools/binpac/src/pac_flow.h +++ b/tools/binpac/src/pac_flow.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_flow_h #define pac_flow_h diff --git a/tools/binpac/src/pac_func.cc b/tools/binpac/src/pac_func.cc index 6c1e3804aa..e94b1fc6c5 100644 --- a/tools/binpac/src/pac_func.cc +++ b/tools/binpac/src/pac_func.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_func.h" #include "pac_embedded.h" diff --git a/tools/binpac/src/pac_func.h b/tools/binpac/src/pac_func.h index 4246450496..a604a89714 100644 --- a/tools/binpac/src/pac_func.h +++ b/tools/binpac/src/pac_func.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_func_h #define pac_func_h diff --git a/tools/binpac/src/pac_id.cc b/tools/binpac/src/pac_id.cc index 06c2d4373d..1c18e27157 100644 --- a/tools/binpac/src/pac_id.cc +++ b/tools/binpac/src/pac_id.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_id.h" #include "pac_exception.h" diff --git a/tools/binpac/src/pac_id.h b/tools/binpac/src/pac_id.h index 9c46da50c0..7299283439 100644 --- a/tools/binpac/src/pac_id.h +++ b/tools/binpac/src/pac_id.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_id_h #define pac_id_h diff --git a/tools/binpac/src/pac_inputbuf.cc b/tools/binpac/src/pac_inputbuf.cc index ae2756361a..d047532ed3 100644 --- a/tools/binpac/src/pac_inputbuf.cc +++ b/tools/binpac/src/pac_inputbuf.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_inputbuf.h" #include "pac_expr.h" diff --git a/tools/binpac/src/pac_inputbuf.h b/tools/binpac/src/pac_inputbuf.h index 5d7fa5c9b1..56fde403cf 100644 --- a/tools/binpac/src/pac_inputbuf.h +++ b/tools/binpac/src/pac_inputbuf.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_inputbuf_h #define pac_inputbuf_h diff --git a/tools/binpac/src/pac_let.cc b/tools/binpac/src/pac_let.cc index 27917cdce2..7682e3fd36 100644 --- a/tools/binpac/src/pac_let.cc +++ b/tools/binpac/src/pac_let.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_let.h" #include "pac_expr.h" diff --git a/tools/binpac/src/pac_let.h b/tools/binpac/src/pac_let.h index ac14bebef0..27fe5c7424 100644 --- a/tools/binpac/src/pac_let.h +++ b/tools/binpac/src/pac_let.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_let_h #define pac_let_h diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index cd9a11feb9..e645bd08f0 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include #include diff --git a/tools/binpac/src/pac_nullptr.h b/tools/binpac/src/pac_nullptr.h index f1fe8e545a..ef80bbd845 100644 --- a/tools/binpac/src/pac_nullptr.h +++ b/tools/binpac/src/pac_nullptr.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_nullptr_h #define pac_nullptr_h diff --git a/tools/binpac/src/pac_number.h b/tools/binpac/src/pac_number.h index 5f8bfa6197..6fdd164624 100644 --- a/tools/binpac/src/pac_number.h +++ b/tools/binpac/src/pac_number.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_number_h #define pac_number_h diff --git a/tools/binpac/src/pac_output.cc b/tools/binpac/src/pac_output.cc index 6171b80b0c..7889d1f224 100644 --- a/tools/binpac/src/pac_output.cc +++ b/tools/binpac/src/pac_output.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_output.h" #include diff --git a/tools/binpac/src/pac_output.h b/tools/binpac/src/pac_output.h index 4c612b0cce..15a4b8ed2f 100644 --- a/tools/binpac/src/pac_output.h +++ b/tools/binpac/src/pac_output.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_output_h #define pac_output_h diff --git a/tools/binpac/src/pac_param.cc b/tools/binpac/src/pac_param.cc index 91f1984873..4e9b851baa 100644 --- a/tools/binpac/src/pac_param.cc +++ b/tools/binpac/src/pac_param.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_param.h" #include "pac_decl.h" diff --git a/tools/binpac/src/pac_param.h b/tools/binpac/src/pac_param.h index 5e1e101d5b..50b1d5ce8c 100644 --- a/tools/binpac/src/pac_param.h +++ b/tools/binpac/src/pac_param.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_param_h #define pac_param_h diff --git a/tools/binpac/src/pac_paramtype.cc b/tools/binpac/src/pac_paramtype.cc index 8cacd1669a..9fd2511b1a 100644 --- a/tools/binpac/src/pac_paramtype.cc +++ b/tools/binpac/src/pac_paramtype.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_paramtype.h" #include "pac_context.h" diff --git a/tools/binpac/src/pac_paramtype.h b/tools/binpac/src/pac_paramtype.h index 72e427c580..d4d10c3b50 100644 --- a/tools/binpac/src/pac_paramtype.h +++ b/tools/binpac/src/pac_paramtype.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_paramtype_h #define pac_paramtype_h diff --git a/tools/binpac/src/pac_primitive.cc b/tools/binpac/src/pac_primitive.cc index faf43bc234..e129cc81f6 100644 --- a/tools/binpac/src/pac_primitive.cc +++ b/tools/binpac/src/pac_primitive.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_primitive.h" #include "pac_dbg.h" diff --git a/tools/binpac/src/pac_primitive.h b/tools/binpac/src/pac_primitive.h index 9ee248b8e1..d9869c15d2 100644 --- a/tools/binpac/src/pac_primitive.h +++ b/tools/binpac/src/pac_primitive.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_primitive_h #define pac_primitive_h diff --git a/tools/binpac/src/pac_record.cc b/tools/binpac/src/pac_record.cc index 145604b13a..d11ba20d43 100644 --- a/tools/binpac/src/pac_record.cc +++ b/tools/binpac/src/pac_record.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_record.h" #include "pac_attr.h" diff --git a/tools/binpac/src/pac_record.h b/tools/binpac/src/pac_record.h index 539a04a6ba..287608c7fa 100644 --- a/tools/binpac/src/pac_record.h +++ b/tools/binpac/src/pac_record.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_record_h #define pac_record_h diff --git a/tools/binpac/src/pac_redef.cc b/tools/binpac/src/pac_redef.cc index c4368bbb5f..03c327ec7c 100644 --- a/tools/binpac/src/pac_redef.cc +++ b/tools/binpac/src/pac_redef.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_redef.h" #include "pac_analyzer.h" diff --git a/tools/binpac/src/pac_redef.h b/tools/binpac/src/pac_redef.h index 3d6f0c259c..432df7e2f9 100644 --- a/tools/binpac/src/pac_redef.h +++ b/tools/binpac/src/pac_redef.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_redef_h #define pac_redef_h diff --git a/tools/binpac/src/pac_regex.cc b/tools/binpac/src/pac_regex.cc index fc7c48469f..517ca91451 100644 --- a/tools/binpac/src/pac_regex.cc +++ b/tools/binpac/src/pac_regex.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_regex.h" #include "pac_exttype.h" diff --git a/tools/binpac/src/pac_regex.h b/tools/binpac/src/pac_regex.h index 93487b8da8..fa4cc081da 100644 --- a/tools/binpac/src/pac_regex.h +++ b/tools/binpac/src/pac_regex.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_regex_h #define pac_regex_h diff --git a/tools/binpac/src/pac_state.cc b/tools/binpac/src/pac_state.cc index 03aba62610..e14ec5fea4 100644 --- a/tools/binpac/src/pac_state.cc +++ b/tools/binpac/src/pac_state.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_state.h" #include "pac_id.h" diff --git a/tools/binpac/src/pac_state.h b/tools/binpac/src/pac_state.h index d54219d3da..a26d98785d 100644 --- a/tools/binpac/src/pac_state.h +++ b/tools/binpac/src/pac_state.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_state_h #define pac_state_h diff --git a/tools/binpac/src/pac_strtype.cc b/tools/binpac/src/pac_strtype.cc index 00d9c3df2d..63ea247d87 100644 --- a/tools/binpac/src/pac_strtype.cc +++ b/tools/binpac/src/pac_strtype.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_strtype.h" #include "pac_attr.h" diff --git a/tools/binpac/src/pac_strtype.h b/tools/binpac/src/pac_strtype.h index ce087d1756..4e725b5f13 100644 --- a/tools/binpac/src/pac_strtype.h +++ b/tools/binpac/src/pac_strtype.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_strtype_h #define pac_strtype_h diff --git a/tools/binpac/src/pac_type.cc b/tools/binpac/src/pac_type.cc index 394d1492f8..a3654b80b6 100644 --- a/tools/binpac/src/pac_type.cc +++ b/tools/binpac/src/pac_type.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_type.h" #include "pac_action.h" diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index 507ac1c886..05df25870f 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_type_h #define pac_type_h diff --git a/tools/binpac/src/pac_typedecl.cc b/tools/binpac/src/pac_typedecl.cc index 268fdc3344..5b3ca26179 100644 --- a/tools/binpac/src/pac_typedecl.cc +++ b/tools/binpac/src/pac_typedecl.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_typedecl.h" #include "pac_attr.h" diff --git a/tools/binpac/src/pac_typedecl.h b/tools/binpac/src/pac_typedecl.h index fa55fe4969..8b6e6a80e6 100644 --- a/tools/binpac/src/pac_typedecl.h +++ b/tools/binpac/src/pac_typedecl.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_typedecl_h #define pac_typedecl_h diff --git a/tools/binpac/src/pac_utils.cc b/tools/binpac/src/pac_utils.cc index c68c200af3..5d9b2651e2 100644 --- a/tools/binpac/src/pac_utils.cc +++ b/tools/binpac/src/pac_utils.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_utils.h" #include diff --git a/tools/binpac/src/pac_utils.h b/tools/binpac/src/pac_utils.h index ec70e6be8b..553d791b81 100644 --- a/tools/binpac/src/pac_utils.h +++ b/tools/binpac/src/pac_utils.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_utils_h #define pac_utils_h diff --git a/tools/binpac/src/pac_varfield.cc b/tools/binpac/src/pac_varfield.cc index e0860f9241..713c584d00 100644 --- a/tools/binpac/src/pac_varfield.cc +++ b/tools/binpac/src/pac_varfield.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_varfield.h" void PrivVarField::Prepare(Env* env) { Field::Prepare(env); } diff --git a/tools/binpac/src/pac_varfield.h b/tools/binpac/src/pac_varfield.h index 7d1685fd82..e9c0c3df61 100644 --- a/tools/binpac/src/pac_varfield.h +++ b/tools/binpac/src/pac_varfield.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_varfield_h #define pac_varfield_h diff --git a/tools/binpac/src/pac_withinput.cc b/tools/binpac/src/pac_withinput.cc index 6eb43f03f1..0bffbd34eb 100644 --- a/tools/binpac/src/pac_withinput.cc +++ b/tools/binpac/src/pac_withinput.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "pac_withinput.h" #include "pac_dataptr.h" diff --git a/tools/binpac/src/pac_withinput.h b/tools/binpac/src/pac_withinput.h index fb9827257e..13c30cd680 100644 --- a/tools/binpac/src/pac_withinput.h +++ b/tools/binpac/src/pac_withinput.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef pac_withinput_h #define pac_withinput_h From 8a7c6df278f0c14dd30db742cf643940fa5b5a82 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 13 Aug 2025 15:48:29 -0700 Subject: [PATCH 151/343] Fix clang-tidy findings in the binpac lib code --- tools/binpac/lib/binpac.h.in | 195 ++++++++++++--------------- tools/binpac/lib/binpac_buffer.h | 8 +- tools/binpac/lib/binpac_bytestring.h | 17 +-- tools/binpac/lib/binpac_exception.h | 15 ++- tools/binpac/lib/binpac_regex.h | 10 +- tools/binpac/src/pac_main.cc | 3 - 6 files changed, 117 insertions(+), 131 deletions(-) diff --git a/tools/binpac/lib/binpac.h.in b/tools/binpac/lib/binpac.h.in index ad11509953..59b1d940ab 100644 --- a/tools/binpac/lib/binpac.h.in +++ b/tools/binpac/lib/binpac.h.in @@ -9,16 +9,16 @@ #cmakedefine HOST_BIGENDIAN #ifdef HOST_BIGENDIAN -# define HOST_BYTEORDER bigendian +#define HOST_BYTEORDER bigendian #else -# define HOST_BYTEORDER littleendian +#define HOST_BYTEORDER littleendian #endif -#include -#include -#include +#include +#include +#include +#include #include -#include // Expose C99 functionality from inttypes.h, which would otherwise not be // available in C++. @@ -26,9 +26,7 @@ #define __STDC_FORMAT_MACROS #endif -#include - -#define BINPAC_ASSERT(x) assert(x) +static constexpr void BINPAC_ASSERT(bool val) { assert(val); } using namespace std; @@ -41,23 +39,21 @@ const int unspecified_byteorder = -1; #ifndef pac_type_defs #define pac_type_defs -typedef int8_t int8; -typedef int16_t int16; -typedef int32_t int32; -typedef int64_t int64; -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; -typedef void *nulptr; -typedef void *voidptr; -typedef uint8 *byteptr; -typedef const uint8 *const_byteptr; -typedef const char *const_charptr; +using int8 = int8_t; +using int16 = int16_t; +using int32 = int32_t; +using int64 = int64_t; +using uint8 = uint8_t; +using uint16 = uint16_t; +using uint32 = uint32_t; +using uint64 = uint64_t; +using nulptr = void*; +using voidptr = void*; +using byteptr = uint8*; +using const_byteptr = const uint8*; +using const_charptr = const char*; -#if @SIZEOF_UNSIGNED_INT@ != 4 -#error "unexpected size of unsigned int" -#endif +static_assert(sizeof(unsigned int) == 4, "Unexpected size of unsigned int"); #endif /* pac_type_defs */ @@ -65,106 +61,93 @@ typedef const char *const_charptr; namespace { -inline uint16 pac_swap(const uint16 x) - { - return (x >> 8) | ((x & 0xff) << 8); - } +inline uint16 pac_swap(const uint16 x) { return (x >> 8) | ((x & 0xff) << 8); } -inline int16 pac_swap(const int16 x) - { - // Forward to unsigned version with argument/result casted - // appropriately. - uint16 (*p)(const uint16) = &pac_swap; - return (*p)(x); - } +inline int16 pac_swap(const int16 x) { + // Forward to unsigned version with argument/result casted + // appropriately. + uint16 (*p)(const uint16) = &pac_swap; + return (*p)(x); +} -inline uint32 pac_swap(const uint32 x) - { - return (x >> 24) | - ((x & 0xff0000) >> 8) | - ((x & 0xff00) << 8) | - ((x & 0xff) << 24); - } +inline uint32 pac_swap(const uint32 x) { + return (x >> 24) | ((x & 0xff0000) >> 8) | ((x & 0xff00) << 8) | ((x & 0xff) << 24); +} -inline int32 pac_swap(const int32 x) - { - // Forward to unsigned version with argument/result casted - // appropriately. - uint32 (*p)(const uint32) = &pac_swap; - return (*p)(x); - } +inline int32 pac_swap(const int32 x) { + // Forward to unsigned version with argument/result casted + // appropriately. + uint32 (*p)(const uint32) = &pac_swap; + return (*p)(x); +} -inline uint64 pac_swap(const uint64 x) - { - return x >> 56 | - (x & 0xff000000000000) >> 40 | - (x & 0xff0000000000) >> 24 | - (x & 0xff00000000) >> 8 | - (x & 0xff000000) << 8 | - (x & 0xff0000) << 24 | - (x & 0xff00) << 40 | - (x & 0xff) << 56; - } - -inline int64 pac_swap(const int64 x) - { - // Forward to unsigned version with argument/result casted - // appropriately. - uint64 (*p)(const uint64) = &pac_swap; - return (*p)(x); - } +inline uint64 pac_swap(const uint64 x) { + return x >> 56 | (x & 0xff000000000000) >> 40 | (x & 0xff0000000000) >> 24 | (x & 0xff00000000) >> 8 | + (x & 0xff000000) << 8 | (x & 0xff0000) << 24 | (x & 0xff00) << 40 | (x & 0xff) << 56; +} -#define FixByteOrder(byteorder, x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap(x)) +inline int64 pac_swap(const int64 x) { + // Forward to unsigned version with argument/result casted + // appropriately. + uint64 (*p)(const uint64) = &pac_swap; + return (*p)(x); +} -template -inline T UnMarshall(const unsigned char *data, int byteorder) - { - T result = 0; - for ( int i = 0; i < (int) sizeof(T); ++i ) - result = ( result << 8 ) | - data[byteorder == bigendian ? i : sizeof(T) - 1 - i]; - return result; - } +template +static constexpr T FixByteOrder(int byteorder, T x) { + if ( byteorder == HOST_BYTEORDER ) + return x; -inline const char* do_fmt(const char* format, va_list ap) - { - static char buf[1024]; - vsnprintf(buf, sizeof(buf), format, ap); - return buf; - } + return static_cast(pac_swap(x)); +} -inline string strfmt(const char* format, ...) - { - va_list ap; - va_start(ap, format); - const char* r = do_fmt(format, ap); - va_end(ap); - return string(r); - } +template +inline T UnMarshall(const unsigned char* data, int byteorder) { + T result = 0; + for ( int i = 0; i < (int)sizeof(T); ++i ) + result = (result << 8) | data[byteorder == bigendian ? i : sizeof(T) - 1 - i]; + return result; +} + +inline const char* do_fmt(const char* format, va_list ap) { + static char buf[1024]; + vsnprintf(buf, sizeof(buf), format, ap); + return buf; +} + +inline string strfmt(const char* format, ...) { + va_list ap; + va_start(ap, format); + const char* r = do_fmt(format, ap); + va_end(ap); + return {r}; +} } // anonymous namespace +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define binpac_fmt(...) strfmt(__VA_ARGS__).c_str() -class RefCount -{ +class RefCount { public: - RefCount() { count = 1; } - virtual ~RefCount() {} - void Ref() { ++count; } - int Unref() { BINPAC_ASSERT(count > 0); return --count; } + RefCount() { count = 1; } + virtual ~RefCount() {} + void Ref() { ++count; } + int Unref() { + BINPAC_ASSERT(count > 0); + return --count; + } private: - int count; + int count; }; namespace { - inline void Unref(RefCount *x) - { - if ( x && x->Unref() <= 0 ) - delete x; - } -} // anonymous namespace +inline void Unref(RefCount* x) { + if ( x && x->Unref() <= 0 ) + delete x; +} +} // anonymous namespace } // namespace binpac diff --git a/tools/binpac/lib/binpac_buffer.h b/tools/binpac/lib/binpac_buffer.h index f7cf012950..bd34c9769d 100644 --- a/tools/binpac/lib/binpac_buffer.h +++ b/tools/binpac/lib/binpac_buffer.h @@ -17,7 +17,7 @@ public: int contract_threshold; }; - enum LineBreakStyle { + enum LineBreakStyle : uint8_t { CR_OR_LF, // CR or LF or CRLF STRICT_CRLF, // CR followed by LF CR_LF_NUL, // CR or LF or CR-LF or CR-NUL @@ -142,13 +142,13 @@ protected: LineBreakStyle linebreak_style_default; unsigned char linebreaker_; - enum { + enum : uint8_t { UNKNOWN_MODE, LINE_MODE, FRAME_MODE, } mode_; - enum { + enum : uint8_t { CR_OR_LF_0, CR_OR_LF_1, STRICT_CRLF_0, @@ -163,7 +163,7 @@ protected: static Policy policy; }; -typedef FlowBuffer* flow_buffer_t; +using flow_buffer_t = FlowBuffer*; } // namespace binpac diff --git a/tools/binpac/lib/binpac_bytestring.h b/tools/binpac/lib/binpac_bytestring.h index 6a33f2eb8f..152ef7c42c 100644 --- a/tools/binpac/lib/binpac_bytestring.h +++ b/tools/binpac/lib/binpac_bytestring.h @@ -3,7 +3,7 @@ #ifndef binpac_bytestring_h #define binpac_bytestring_h -#include +#include #include #include "binpac.h" @@ -16,7 +16,7 @@ class datastring; template class const_datastring { public: - const_datastring() : begin_(0), end_(0) {} + const_datastring() : begin_(nullptr), end_(nullptr) {} const_datastring(T const* data, int length) : begin_(data), end_(data + length) {} @@ -49,7 +49,7 @@ private: T const* end_; }; -typedef const_datastring const_bytestring; +using const_bytestring = const_datastring; template class datastring { @@ -65,6 +65,9 @@ public: explicit datastring(const_datastring const& x) { set_const(x.begin(), x.length()); } datastring const& operator=(datastring const& x) { + if ( this == &x ) + return *this; + BINPAC_ASSERT(! data_); set(x.data(), x.length()); return *this; @@ -76,7 +79,7 @@ public: } void clear() { - data_ = 0; + data_ = nullptr; length_ = 0; } @@ -119,13 +122,11 @@ private: int length_; }; -typedef datastring bytestring; +using bytestring = datastring; inline const char* c_str(bytestring const& s) { return (const char*)s.begin(); } -inline std::string std_str(const_bytestring const& s) { - return std::string((const char*)s.begin(), (const char*)s.end()); -} +inline std::string std_str(const_bytestring const& s) { return {(const char*)s.begin(), (const char*)s.end()}; } inline bool operator==(bytestring const& s1, const char* s2) { return strcmp(c_str(s1), s2) == 0; } diff --git a/tools/binpac/lib/binpac_exception.h b/tools/binpac/lib/binpac_exception.h index 8578ae83fc..52bd6f7421 100644 --- a/tools/binpac/lib/binpac_exception.h +++ b/tools/binpac/lib/binpac_exception.h @@ -3,25 +3,26 @@ #ifndef binpac_exception_h #define binpac_exception_h -#include -#include +#include +#include +#include namespace binpac { class Exception { public: - Exception(const char* m = 0) : msg_("binpac exception: ") { + Exception(const char* m = nullptr) : msg_("binpac exception: ") { if ( m ) append(m); // abort(); } - void append(string m) { msg_ += m; } - string msg() const { return msg_; } + void append(std::string m) { msg_ += m; } + std::string msg() const { return msg_; } const char* c_msg() const { return msg_.c_str(); } protected: - string msg_; + std::string msg_; }; class ExceptionEnforceViolation : public Exception { @@ -46,7 +47,7 @@ public: protected: const char* location_; int64_t index_; - string expected_; + std::string expected_; }; class ExceptionInvalidCaseIndex : public Exception { diff --git a/tools/binpac/lib/binpac_regex.h b/tools/binpac/lib/binpac_regex.h index d8e2a05c23..6e1ea11101 100644 --- a/tools/binpac/lib/binpac_regex.h +++ b/tools/binpac/lib/binpac_regex.h @@ -1,6 +1,10 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #ifndef binpac_regex_h #define binpac_regex_h +#include + #include "zeek/RE.h" #include "binpac.h" @@ -16,7 +20,7 @@ namespace binpac { // Note, this must be declared/defined here, and inline, because the RE // functionality can only be used when compiling from inside Zeek. // A copy is made of any FlowBuffer policy struct data passed. -inline void init(FlowBuffer::Policy* fbp = 0); +inline void init(FlowBuffer::Policy* fbp = nullptr); // Internal vector recording not yet compiled matchers. extern std::vector* uncompiled_re_matchers; @@ -50,8 +54,8 @@ inline void RegExMatcher::init() { if ( ! uncompiled_re_matchers ) return; - for ( size_t i = 0; i < uncompiled_re_matchers->size(); ++i ) { - if ( ! (*uncompiled_re_matchers)[i]->Compile() ) { + for ( const auto& matcher : *uncompiled_re_matchers ) { + if ( ! matcher->Compile() ) { fprintf(stderr, "binpac: cannot compile regular expression\n"); exit(1); } diff --git a/tools/binpac/src/pac_main.cc b/tools/binpac/src/pac_main.cc index e645bd08f0..f3e5847f52 100644 --- a/tools/binpac/src/pac_main.cc +++ b/tools/binpac/src/pac_main.cc @@ -176,9 +176,6 @@ int compile(const char* filename) { } void usage() { -#ifdef BINPAC_VERSION - fprintf(stderr, "binpac version %s\n", BINPAC_VERSION); -#endif fprintf(stderr, "usage: binpac [options] \n"); fprintf(stderr, " | pac-language input files\n"); fprintf(stderr, " -d | use given directory for compiler output\n"); From 137e8bddc98ddfd63c55dabf7beeb258e48493a4 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 18 Aug 2025 13:46:17 -0700 Subject: [PATCH 152/343] Run pre-commit on merged binpac code --- tools/binpac/src/pac_decl.h | 6 ++---- tools/binpac/src/pac_record.h | 12 ++++-------- tools/binpac/src/pac_type.h | 3 +-- tools/binpac/src/pac_varfield.h | 6 ++---- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/tools/binpac/src/pac_decl.h b/tools/binpac/src/pac_decl.h index b5e2a2557a..be27fb29ce 100644 --- a/tools/binpac/src/pac_decl.h +++ b/tools/binpac/src/pac_decl.h @@ -25,8 +25,7 @@ public: virtual void Prepare() = 0; // Generate declarations out of the "binpac" namespace - virtual void GenExternDeclaration(Output* out_h) { /* do nothing */ - } + virtual void GenExternDeclaration(Output* out_h) { /* do nothing */ } // Generate declarations before definition of classes virtual void GenForwardDeclaration(Output* out_h) = 0; @@ -67,8 +66,7 @@ public: void Prepare() override; void GenExternDeclaration(Output* out_h) override; - void GenForwardDeclaration(Output* out_h) override { /* do nothing */ - } + void GenForwardDeclaration(Output* out_h) override { /* do nothing */ } void GenCode(Output* out_h, Output* out_cc) override; private: diff --git a/tools/binpac/src/pac_record.h b/tools/binpac/src/pac_record.h index 287608c7fa..58abbc81bb 100644 --- a/tools/binpac/src/pac_record.h +++ b/tools/binpac/src/pac_record.h @@ -144,15 +144,11 @@ public: void Prepare(Env* env) override; - void GenPubDecls(Output* out, Env* env) override { /* nothing */ - } - void GenPrivDecls(Output* out, Env* env) override { /* nothing */ - } + void GenPubDecls(Output* out, Env* env) override { /* nothing */ } + void GenPrivDecls(Output* out, Env* env) override { /* nothing */ } - void GenInitCode(Output* out, Env* env) override { /* nothing */ - } - void GenCleanUpCode(Output* out, Env* env) override { /* nothing */ - } + void GenInitCode(Output* out, Env* env) override { /* nothing */ } + void GenCleanUpCode(Output* out, Env* env) override { /* nothing */ } void GenParseCode(Output* out, Env* env) override; int StaticSize(Env* env, int offset) const override; diff --git a/tools/binpac/src/pac_type.h b/tools/binpac/src/pac_type.h index 05df25870f..33e8a45c98 100644 --- a/tools/binpac/src/pac_type.h +++ b/tools/binpac/src/pac_type.h @@ -102,8 +102,7 @@ public: void AddField(Field* f); - void AddCheck(Expr* expr) { /* TODO */ - } + void AddCheck(Expr* expr) { /* TODO */ } virtual bool DefineValueVar() const = 0; diff --git a/tools/binpac/src/pac_varfield.h b/tools/binpac/src/pac_varfield.h index e9c0c3df61..6fbf2148af 100644 --- a/tools/binpac/src/pac_varfield.h +++ b/tools/binpac/src/pac_varfield.h @@ -10,8 +10,7 @@ class ParseVarField : public Field { public: ParseVarField(int is_class_member, ID* id, Type* type) : Field(PARSE_VAR_FIELD, TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, id, type) {} - void GenPubDecls(Output* out, Env* env) override { /* do nothing */ - } + void GenPubDecls(Output* out, Env* env) override { /* do nothing */ } }; // A public variable @@ -29,8 +28,7 @@ public: : Field(PRIV_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, id, type) {} ~PrivVarField() override {} - void GenPubDecls(Output* out, Env* env) override { /* do nothing */ - } + void GenPubDecls(Output* out, Env* env) override { /* do nothing */ } }; class TempVarField : public Field { From 73e8f2c79d8d55ec0c6ba9b7f86403c1f78ee056 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 12 Jul 2018 17:02:34 -0500 Subject: [PATCH 153/343] bifcl: First commit --- tools/bifcl/README | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tools/bifcl/README diff --git a/tools/bifcl/README b/tools/bifcl/README new file mode 100644 index 0000000000..e69de29bb2 From 3a4f38a04bc1fe944cb37ef8ef20fab9f2d48665 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 12 Jul 2018 17:44:57 -0500 Subject: [PATCH 154/343] bifcl: Port bifcl code from Bro --- tools/bifcl/CMakeLists.txt | 71 ++++ tools/bifcl/README | 19 + tools/bifcl/bif_arg.cc | 82 ++++ tools/bifcl/builtin-func.l | 422 ++++++++++++++++++++ tools/bifcl/builtin-func.y | 785 +++++++++++++++++++++++++++++++++++++ tools/bifcl/module_util.cc | 67 ++++ 6 files changed, 1446 insertions(+) create mode 100644 tools/bifcl/CMakeLists.txt create mode 100644 tools/bifcl/bif_arg.cc create mode 100644 tools/bifcl/builtin-func.l create mode 100644 tools/bifcl/builtin-func.y create mode 100644 tools/bifcl/module_util.cc diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt new file mode 100644 index 0000000000..f13498b554 --- /dev/null +++ b/tools/bifcl/CMakeLists.txt @@ -0,0 +1,71 @@ +project(BifCl C CXX) + +cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) + +include(cmake/CommonCMakeConfig.cmake) + +include(FindRequiredPackage) + +FindRequiredPackage(BISON) +FindRequiredPackage(FLEX) + +if ( MISSING_PREREQS ) + foreach (prereq ${MISSING_PREREQ_DESCS}) + message(SEND_ERROR ${prereq}) + endforeach () + message(FATAL_ERROR "Configuration aborted due to missing prerequisites") +endif () + +include_directories(BEFORE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +set(BISON_FLAGS "--debug") + +# BIF parser/scanner +bison_target(BIFParser builtin-func.y + ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.cc + HEADER ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.h + #VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.output + COMPILE_FLAGS "${BISON_FLAGS}") +flex_target(BIFScanner builtin-func.l ${CMAKE_CURRENT_BINARY_DIR}/bif_lex.cc) +add_flex_bison_dependency(BIFScanner BIFParser) + +set(bifcl_SRCS + ${BISON_BIFParser_INPUT} + ${FLEX_BIFScanner_INPUT} + ${BISON_BIFParser_OUTPUTS} + ${FLEX_BIFScanner_OUTPUTS} + bif_arg.cc + bif_arg.h + module_util.cc + module_util.h +) + +add_executable(bifcl ${bifcl_SRCS}) + +install(TARGETS bifcl DESTINATION bin) + +if (CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) +endif () + +message( + "\n====================| Bifcl Build Summary |=====================" + "\n" + "\nBuild type: ${CMAKE_BUILD_TYPE}" + "\nBuild dir: ${CMAKE_BINARY_DIR}" + "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nDebug mode: ${ENABLE_DEBUG}" + "\n" + "\nCC: ${CMAKE_C_COMPILER}" + "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" + "\nCXX: ${CMAKE_CXX_COMPILER}" + "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" + "\nCPP: ${CMAKE_CXX_COMPILER}" + "\n" + "\n================================================================\n" +) + +include(UserChangedWarning) diff --git a/tools/bifcl/README b/tools/bifcl/README index e69de29bb2..0ec59344ec 100644 --- a/tools/bifcl/README +++ b/tools/bifcl/README @@ -0,0 +1,19 @@ +.. _Bro: https://bro.org + +================ +Bro BIF Compiler +================ + +The ``bifcl`` program simply takes a ``.bif`` file as input and +generates C++ header/source files along with a ``.bro`` script +that all-together provide the declaration and implementation of Bro_ +Built-In-Functions (BIFs), which can then be compiled and shipped +as part of a Bro plugin. + +A BIF allows one to write arbitrary C++ code and access it via a +function call inside a Bro script. In this way, they can also be +used to access parts of Bro's internal C++ API that aren't already +exposed via their own BIFs. + +At the moment, learning the format of a ``.bif`` file is likely easiest +by just taking a look at the ``.bif`` files inside the Bro source-tree. diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc new file mode 100644 index 0000000000..f83333220d --- /dev/null +++ b/tools/bifcl/bif_arg.cc @@ -0,0 +1,82 @@ + +#include +#include +using namespace std; + +#include + +#include "bif_arg.h" + +static struct { + const char* bif_type; + const char* bro_type; + const char* c_type; + const char* accessor; + const char* constructor; +} builtin_func_arg_type[] = { +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ + {bif_type, bro_type, c_type, accessor, constructor}, +#include "bif_type.def" +#undef DEFINE_BIF_TYPE +}; + +extern const char* arg_list_name; + +BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, int arg_type) + { + name = arg_name; + type = arg_type; + type_str = ""; + attr_str = ""; + } + +BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, const char* arg_type_str, + const char* arg_attr_str) + { + name = arg_name; + type = TYPE_OTHER; + type_str = arg_type_str; + attr_str = arg_attr_str; + + for ( int i = 0; builtin_func_arg_type[i].bif_type[0] != '\0'; ++i ) + if ( ! strcmp(builtin_func_arg_type[i].bif_type, arg_type_str) ) + { + type = i; + type_str = ""; + } + } + +void BuiltinFuncArg::PrintBro(FILE* fp) + { + fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].bro_type, + type_str, attr_str); + } + +void BuiltinFuncArg::PrintCDef(FILE* fp, int n) + { + fprintf(fp, + "\t%s %s = (%s) (", + builtin_func_arg_type[type].c_type, + name, + builtin_func_arg_type[type].c_type); + + char buf[1024]; + snprintf(buf, sizeof(buf), "(*%s)[%d]", arg_list_name, n); + // Print the accessor expression. + fprintf(fp, builtin_func_arg_type[type].accessor, buf); + + fprintf(fp, ");\n"); + } + +void BuiltinFuncArg::PrintCArg(FILE* fp, int n) + { + const char* ctype = builtin_func_arg_type[type].c_type; + char buf[1024]; + + fprintf(fp, "%s %s", ctype, name); + } + +void BuiltinFuncArg::PrintBroValConstructor(FILE* fp) + { + fprintf(fp, builtin_func_arg_type[type].constructor, name); + } diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l new file mode 100644 index 0000000000..2d59408f83 --- /dev/null +++ b/tools/bifcl/builtin-func.l @@ -0,0 +1,422 @@ +%{ +#include +#include +#include +#include "bif_arg.h" +#include "bif_parse.h" + +char* copy_string(const char* s) + { + char* c = new char[strlen(s)+1]; + strcpy(c, s); + return c; + } + +int line_number = 1; + +extern int in_c_code; + +int check_c_mode(int t) + { + if ( ! in_c_code ) + return t; + + yylval.str = copy_string(yytext); + return TOK_C_TOKEN; + } +%} + +WS [ \t]+ +OWS [ \t]* + /* Note, bifcl only accepts a single "::" in IDs while the policy + layer acceptes multiple. (But the policy layer doesn't have + a hierachy. */ +IDCOMPONENT [A-Za-z_][A-Za-z_0-9]* +ID {IDCOMPONENT}(::{IDCOMPONENT})? +ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) +DEC [[:digit:]]+ +HEX [0-9a-fA-F]+ + + +%option nodefault + +%% + +#.* { + yylval.str = copy_string(yytext); + return TOK_COMMENT; + } + +\n { + ++line_number; + return TOK_LF; + } + +{WS} { + yylval.str = copy_string(yytext); + return TOK_WS; + } + +[=,:;] return check_c_mode(yytext[0]); + +"%{" return TOK_LPB; +"%}" return TOK_RPB; +"%%{" return TOK_LPPB; +"%%}" return TOK_RPPB; + +"%(" return check_c_mode(TOK_LPP); +"%)" return check_c_mode(TOK_RPP); +"..." return check_c_mode(TOK_VAR_ARG); +"function" return check_c_mode(TOK_FUNCTION); +"event" return check_c_mode(TOK_EVENT); +"const" return check_c_mode(TOK_CONST); +"enum" return check_c_mode(TOK_ENUM); +"type" return check_c_mode(TOK_TYPE); +"record" return check_c_mode(TOK_RECORD); +"set" return check_c_mode(TOK_SET); +"table" return check_c_mode(TOK_TABLE); +"vector" return check_c_mode(TOK_VECTOR); +"of" return check_c_mode(TOK_OF); +"opaque" return check_c_mode(TOK_OPAQUE); +"module" return check_c_mode(TOK_MODULE); + +"@ARG@" return TOK_ARG; +"@ARGS@" return TOK_ARGS; +"@ARGC@" return TOK_ARGC; + +"T" yylval.val = 1; return TOK_BOOL; +"F" yylval.val = 0; return TOK_BOOL; + +{DEC} { + yylval.str = copy_string(yytext); + return TOK_INT; + } + +"0x"{HEX} { + yylval.str = copy_string(yytext); + return TOK_INT; + } + + +{ID} { + yylval.str = copy_string(yytext); + return TOK_ID; + } + + /* + Hacky way to pass along arbitrary attribute expressions since the BIF parser + has little understanding of valid Bro expressions. With this pattern, the + attribute expression should stop when it reaches another attribute, another + function argument, or the end of the function declaration. + */ +&{ID}({OWS}={OWS}[^&%;,]+)? { + int t = check_c_mode(TOK_ATTR); + + if ( t == TOK_ATTR ) + { + yylval.str = copy_string(yytext); + return TOK_ATTR; + } + else + return t; + } + +\"([^\\\n\"]|{ESCSEQ})*\" { + yylval.str = copy_string(yytext); + return TOK_CSTR; + } + +\'([^\\\n\']|{ESCSEQ})*\' { + yylval.str = copy_string(yytext); + return TOK_CSTR; + } + +. { + yylval.val = yytext[0]; + return TOK_ATOM; + } +%% + +int yywrap() + { + yy_delete_buffer(YY_CURRENT_BUFFER); + return 1; + } + +extern int yyparse(); +char* input_filename = 0; +char* input_filename_with_path = 0; +char* plugin = 0; +int alternative_mode = 0; + +FILE* fp_bro_init = 0; +FILE* fp_func_def = 0; +FILE* fp_func_h = 0; +FILE* fp_func_init = 0; +FILE* fp_func_register = 0; +FILE* fp_netvar_h = 0; +FILE* fp_netvar_def = 0; +FILE* fp_netvar_init = 0; + +void remove_file(const char *surfix); +void err_exit(void); +FILE* open_output_file(const char* surfix); +void close_if_open(FILE **fpp); +void close_all_output_files(void); + + +FILE* open_output_file(const char* surfix) + { + char fn[1024]; + FILE* fp; + + snprintf(fn, sizeof(fn), "%s.%s", input_filename, surfix); + if ( (fp = fopen(fn, "w")) == NULL ) + { + fprintf(stderr, "Error: cannot open file: %s\n", fn); + err_exit(); + } + + return fp; + } + +void usage() + { + fprintf(stderr, "usage: bifcl [-p | -s] *.bif\n"); + exit(1); + } + +void init_alternative_mode() + { + fp_bro_init = open_output_file("bro"); + fp_func_h = open_output_file("h"); + fp_func_def = open_output_file("cc"); + fp_func_init = open_output_file("init.cc"); + fp_func_register = plugin ? open_output_file("register.cc") : NULL; + + fp_netvar_h = fp_func_h; + fp_netvar_def = fp_func_def; + fp_netvar_init = fp_func_init; + + int n = 1024 + strlen(input_filename); + char auto_gen_comment[n]; + + snprintf(auto_gen_comment, n, + "This file was automatically generated by bifcl from %s (%s mode).", + input_filename_with_path, plugin ? "plugin" : "alternative"); + + fprintf(fp_bro_init, "# %s\n\n", auto_gen_comment); + fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); + + if ( fp_func_register ) + fprintf(fp_func_register, "// %s\n\n", auto_gen_comment); + + static char guard[1024]; + if ( getcwd(guard, sizeof(guard)) == NULL ) + { + fprintf(stderr, "Error: cannot get current working directory\n"); + err_exit(); + } + strncat(guard, "/", sizeof(guard) - strlen(guard) - 1); + strncat(guard, input_filename, sizeof(guard) - strlen(guard) - 1); + + for ( char* p = guard; *p; p++ ) + { + if ( ! isalnum(*p) ) + *p = '_'; + } + + fprintf(fp_func_h, "#if defined(BRO_IN_NETVAR) || ! defined(%s)\n", guard); + + fprintf(fp_func_h, "#ifndef BRO_IN_NETVAR\n"); + fprintf(fp_func_h, "#ifndef %s\n", guard); + fprintf(fp_func_h, "#define %s\n", guard); + fprintf(fp_func_h, "#include \"bro-bif.h\"\n"); + fprintf(fp_func_h, "#endif\n"); + fprintf(fp_func_h, "#endif\n"); + fprintf(fp_func_h, "\n"); + + fprintf(fp_func_def, "\n"); + fprintf(fp_func_def, "#include \"%s.h\"\n", input_filename); + fprintf(fp_func_def, "\n"); + + static char name[1024]; + strncpy(name, input_filename, sizeof(name)); + char* dot = strchr(name, '.'); + if ( dot ) + *dot = '\0'; + + if ( plugin ) + { + static char plugin_canon[1024]; + strncpy(plugin_canon, plugin, sizeof(plugin_canon)); + char* colon = strstr(plugin_canon, "::"); + + if ( colon ) { + *colon = '_'; + memmove(colon + 1, colon + 2, plugin_canon + strlen(plugin_canon) - colon); + } + + fprintf(fp_func_init, "\n"); + fprintf(fp_func_init, "#include \n"); + fprintf(fp_func_init, "#include \n"); + fprintf(fp_func_init, "#include \"plugin/Plugin.h\"\n"); + fprintf(fp_func_init, "#include \"%s.h\"\n", input_filename); + fprintf(fp_func_init, "\n"); + fprintf(fp_func_init, "namespace plugin { namespace %s {\n", plugin_canon); + fprintf(fp_func_init, "\n"); + fprintf(fp_func_init, "void __bif_%s_init(plugin::Plugin* plugin)\n", name); + fprintf(fp_func_init, "\t{\n"); + + fprintf(fp_func_register, "#include \"plugin/Manager.h\"\n"); + fprintf(fp_func_register, "\n"); + fprintf(fp_func_register, "namespace plugin { namespace %s {\n", plugin_canon); + fprintf(fp_func_register, "void __bif_%s_init(plugin::Plugin* plugin);\n", name); + fprintf(fp_func_register, "::plugin::__RegisterBif __register_bifs_%s_%s(\"%s\", __bif_%s_init);\n", plugin_canon, name, plugin, name); + fprintf(fp_func_register, "} }\n"); + } + } + +void finish_alternative_mode() + { + fprintf(fp_func_h, "\n"); + fprintf(fp_func_h, "#endif\n"); + + if ( plugin ) + { + fprintf(fp_func_init, "\n"); + fprintf(fp_func_init, "\t}\n"); + fprintf(fp_func_init, "} }\n"); + fprintf(fp_func_init, "\n"); + fprintf(fp_func_init, "\n"); + } + } + +int main(int argc, char* argv[]) + { + int opt; + + while ( (opt = getopt(argc, argv, "p:s")) != -1 ) + { + switch ( opt ) { + case 'p': + alternative_mode = 1; + plugin = optarg; + break; + + case 's': + alternative_mode = 1; + break; + + default: + usage(); + } + } + + for ( int i = optind; i < argc; i++ ) + { + FILE* fp_input; + char* slash; + + input_filename = input_filename_with_path = argv[i]; + slash = strrchr(input_filename, '/'); + + if ( (fp_input = fopen(input_filename, "r")) == NULL ) + { + fprintf(stderr, "Error: cannot open file: %s\n", input_filename); + /* no output files open. can simply exit */ + exit(1); + } + + if ( slash ) + input_filename = slash + 1; + + if ( ! alternative_mode ) + { + fp_bro_init = open_output_file("bro"); + fp_func_h = open_output_file("func_h"); + fp_func_def = open_output_file("func_def"); + fp_func_init = open_output_file("func_init"); + fp_netvar_h = open_output_file("netvar_h"); + fp_netvar_def = open_output_file("netvar_def"); + fp_netvar_init = open_output_file("netvar_init"); + + int n = 1024 + strlen(input_filename); + char auto_gen_comment[n]; + + snprintf(auto_gen_comment, n, + "This file was automatically generated by bifcl from %s.", + input_filename); + + fprintf(fp_bro_init, "# %s\n\n", auto_gen_comment); + fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); + fprintf(fp_netvar_def, "// %s\n\n", auto_gen_comment); + fprintf(fp_netvar_h, "// %s\n\n", auto_gen_comment); + fprintf(fp_netvar_init, "// %s\n\n", auto_gen_comment); + } + + else + init_alternative_mode(); + + yy_switch_to_buffer(yy_create_buffer(fp_input, YY_BUF_SIZE)); + yyparse(); + + if ( alternative_mode ) + finish_alternative_mode(); + + fclose(fp_input); + close_all_output_files(); + + } + } + +void close_if_open(FILE **fpp) + { + if (*fpp) + fclose(*fpp); + *fpp = NULL; + } + +void close_all_output_files(void) + { + close_if_open(&fp_bro_init); + close_if_open(&fp_func_h); + close_if_open(&fp_func_def); + close_if_open(&fp_func_init); + close_if_open(&fp_func_register); + + if ( ! alternative_mode ) + { + close_if_open(&fp_netvar_h); + close_if_open(&fp_netvar_def); + close_if_open(&fp_netvar_init); + } + } + +void remove_file(const char *surfix) + { + char fn[1024]; + + snprintf(fn, sizeof(fn), "%s.%s", input_filename, surfix); + unlink(fn); + } + +void err_exit(void) + { + close_all_output_files(); + /* clean up. remove all output files we've generated so far */ + remove_file("bro"); + remove_file("func_h"); + remove_file("func_def"); + remove_file("func_init"); + remove_file("func_register"); + remove_file("netvar_h"); + remove_file("netvar_def"); + remove_file("netvar_init"); + exit(1); + } + diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y new file mode 100644 index 0000000000..0f895ced52 --- /dev/null +++ b/tools/bifcl/builtin-func.y @@ -0,0 +1,785 @@ +%{ +#include +#include +#include +#include + +using namespace std; + +#include +#include + +#include "module_util.h" + +using namespace std; + +extern int line_number; +extern char* input_filename; +extern char* plugin; + +#define print_line_directive(fp) fprintf(fp, "\n#line %d \"%s\"\n", line_number, input_filename) + +extern FILE* fp_bro_init; +extern FILE* fp_func_def; +extern FILE* fp_func_h; +extern FILE* fp_func_init; +extern FILE* fp_netvar_h; +extern FILE* fp_netvar_def; +extern FILE* fp_netvar_init; + +int in_c_code = 0; +string current_module = GLOBAL_MODULE_NAME; +int definition_type; +string type_name; + + +enum { + C_SEGMENT_DEF, + FUNC_DEF, + EVENT_DEF, + TYPE_DEF, + CONST_DEF, +}; + +// Holds the name of a declared object (function, enum, record type, event, +// etc. and information about namespaces, etc. +struct decl_struct { + string module_name; + string bare_name; // name without module or namespace + string c_namespace_start; // "opening" namespace for use in netvar_* + string c_namespace_end; // closing "}" for all the above namespaces + string c_fullname; // fully qualified name (namespace::....) for use in netvar_init + string bro_fullname; // fully qualified bro name, for netvar (and lookup_ID()) + string bro_name; // the name as we read it from input. What we write into the .bro file + + // special cases for events. Events have an EventHandlerPtr + // and a generate_* function. This name is for the generate_* function + string generate_bare_name; + string generate_c_fullname; + string generate_c_namespace_start; + string generate_c_namespace_end; +} decl; + +void set_definition_type(int type, const char *arg_type_name) + { + definition_type = type; + if ( type == TYPE_DEF && arg_type_name ) + type_name = string(arg_type_name); + else + type_name = ""; + } + +void set_decl_name(const char *name) + { + decl.bare_name = extract_var_name(name); + + // make_full_var_name prepends the correct module, if any + // then we can extract the module name again. + string varname = make_full_var_name(current_module.c_str(), name); + decl.module_name = extract_module_name(varname.c_str()); + + decl.c_namespace_start = ""; + decl.c_namespace_end = ""; + decl.c_fullname = ""; + decl.bro_fullname = ""; + decl.bro_name = ""; + + decl.generate_c_fullname = ""; + decl.generate_bare_name = string("generate_") + decl.bare_name; + decl.generate_c_namespace_start = ""; + decl.generate_c_namespace_end = ""; + + switch ( definition_type ) { + case TYPE_DEF: + decl.c_namespace_start = "namespace BifType { namespace " + type_name + "{ "; + decl.c_namespace_end = " } }"; + decl.c_fullname = "BifType::" + type_name + "::"; + break; + + case CONST_DEF: + decl.c_namespace_start = "namespace BifConst { "; + decl.c_namespace_end = " } "; + decl.c_fullname = "BifConst::"; + break; + + case FUNC_DEF: + decl.c_namespace_start = "namespace BifFunc { "; + decl.c_namespace_end = " } "; + decl.c_fullname = "BifFunc::"; + break; + + case EVENT_DEF: + decl.c_namespace_start = ""; + decl.c_namespace_end = ""; + decl.c_fullname = "::"; // need this for namespace qualified events due do event_c_body + decl.generate_c_namespace_start = "namespace BifEvent { "; + decl.generate_c_namespace_end = " } "; + decl.generate_c_fullname = "BifEvent::"; + break; + + default: + break; + } + + if ( decl.module_name != GLOBAL_MODULE_NAME ) + { + decl.c_namespace_start += "namespace " + decl.module_name + " { "; + decl.c_namespace_end += string(" }"); + decl.c_fullname += decl.module_name + "::"; + decl.bro_fullname += decl.module_name + "::"; + + decl.generate_c_namespace_start += "namespace " + decl.module_name + " { "; + decl.generate_c_namespace_end += " } "; + decl.generate_c_fullname += decl.module_name + "::"; + } + + decl.bro_fullname += decl.bare_name; + if ( definition_type == FUNC_DEF ) + decl.bare_name = string("bro_") + decl.bare_name; + + decl.c_fullname += decl.bare_name; + decl.bro_name += name; + decl.generate_c_fullname += decl.generate_bare_name; + + } + +const char* arg_list_name = "BiF_ARGS"; + +#include "bif_arg.h" + +/* Map bif/bro type names to C types for use in const declaration */ +static struct { + const char* bif_type; + const char* bro_type; + const char* c_type; + const char* accessor; + const char* constructor; +} builtin_types[] = { +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ + {bif_type, bro_type, c_type, accessor, constructor}, +#include "bif_type.def" +#undef DEFINE_BIF_TYPE +}; + +int get_type_index(const char *type_name) + { + for ( int i = 0; builtin_types[i].bif_type[0] != '\0'; ++i ) + { + if ( strcmp(builtin_types[i].bif_type, type_name) == 0 ) + return i; + } + return TYPE_OTHER; + } + + +int var_arg; // whether the number of arguments is variable +std::vector args; + +extern int yyerror(const char[]); +extern int yywarn(const char msg[]); +extern int yylex(); + +char* concat(const char* str1, const char* str2) + { + int len1 = strlen(str1); + int len2 = strlen(str2); + + char* s = new char[len1 + len2 +1]; + + memcpy(s, str1, len1); + memcpy(s + len1, str2, len2); + + s[len1+len2] = '\0'; + + return s; + } + +// Print the bro_event_* function prototype in C++, without the ending ';' +void print_event_c_prototype(FILE *fp, bool is_header) + { + if ( is_header ) + fprintf(fp, "%s void %s(analyzer::Analyzer* analyzer%s", + decl.generate_c_namespace_start.c_str(), decl.generate_bare_name.c_str(), + args.size() ? ", " : "" ); + else + fprintf(fp, "void %s(analyzer::Analyzer* analyzer%s", + decl.generate_c_fullname.c_str(), + args.size() ? ", " : "" ); + for ( int i = 0; i < (int) args.size(); ++i ) + { + if ( i > 0 ) + fprintf(fp, ", "); + args[i]->PrintCArg(fp, i); + } + fprintf(fp, ")"); + if ( is_header ) + fprintf(fp, "; %s\n", decl.generate_c_namespace_end.c_str()); + else + fprintf(fp, "\n"); + } + +// Print the bro_event_* function body in C++. +void print_event_c_body(FILE *fp) + { + fprintf(fp, "\t{\n"); + fprintf(fp, "\t// Note that it is intentional that here we do not\n"); + fprintf(fp, "\t// check if %s is NULL, which should happen *before*\n", + decl.c_fullname.c_str()); + fprintf(fp, "\t// %s is called to avoid unnecessary Val\n", + decl.generate_c_fullname.c_str()); + fprintf(fp, "\t// allocation.\n"); + fprintf(fp, "\n"); + + fprintf(fp, "\tval_list* vl = new val_list;\n\n"); + BuiltinFuncArg *connection_arg = 0; + + for ( int i = 0; i < (int) args.size(); ++i ) + { + fprintf(fp, "\t"); + fprintf(fp, "vl->append("); + args[i]->PrintBroValConstructor(fp); + fprintf(fp, ");\n"); + + if ( args[i]->Type() == TYPE_CONNECTION ) + { + if ( connection_arg == 0 ) + connection_arg = args[i]; + else + { + // We are seeing two connection type arguments. + yywarn("Warning: with more than connection-type " + "event arguments, bifcl only passes " + "the first one to EventMgr as cookie."); + } + } + } + + fprintf(fp, "\n"); + fprintf(fp, "\tmgr.QueueEvent(%s, vl, SOURCE_LOCAL, analyzer->GetID(), timer_mgr", + decl.c_fullname.c_str()); + + if ( connection_arg ) + // Pass the connection to the EventMgr as the "cookie" + fprintf(fp, ", %s", connection_arg->Name()); + + fprintf(fp, ");\n"); + fprintf(fp, "\t} // event generation\n"); + //fprintf(fp, "%s // end namespace\n", decl.generate_c_namespace_end.c_str()); + } + +void record_bif_item(const char* id, const char* type) + { + if ( ! plugin ) + return; + + fprintf(fp_func_init, "\tplugin->AddBifItem(\"%s\", plugin::BifItem::%s);\n", id, type); + } + +%} + +%token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG +%token TOK_BOOL +%token TOK_FUNCTION TOK_EVENT TOK_CONST TOK_ENUM TOK_OF +%token TOK_TYPE TOK_RECORD TOK_SET TOK_VECTOR TOK_OPAQUE TOK_TABLE TOK_MODULE +%token TOK_ARGS TOK_ARG TOK_ARGC +%token TOK_ID TOK_ATTR TOK_CSTR TOK_LF TOK_WS TOK_COMMENT +%token TOK_ATOM TOK_INT TOK_C_TOKEN + +%left ',' ':' + +%type TOK_C_TOKEN TOK_ID TOK_CSTR TOK_WS TOK_COMMENT TOK_ATTR TOK_INT opt_ws type attr_list opt_attr_list opt_func_attrs +%type TOK_ATOM TOK_BOOL + +%union { + const char* str; + int val; +} + +%% + +builtin_lang: definitions + { + fprintf(fp_bro_init, "} # end of export section\n"); + fprintf(fp_bro_init, "module %s;\n", GLOBAL_MODULE_NAME); + } + + + +definitions: definitions definition opt_ws + { + if ( in_c_code ) + fprintf(fp_func_def, "%s", $3); + else + fprintf(fp_bro_init, "%s", $3); + } + | opt_ws + { + fprintf(fp_bro_init, "%s", $1); + fprintf(fp_bro_init, "export {\n"); + } + ; + +definition: event_def + | func_def + | c_code_segment + | enum_def + | const_def + | type_def + | module_def + ; + + +module_def: TOK_MODULE opt_ws TOK_ID opt_ws ';' + { + current_module = string($3); + fprintf(fp_bro_init, "module %s;\n", $3); + } + + // XXX: Add the netvar glue so that the event engine knows about + // the type. One still has to define the type in bro.init. + // Would be nice, if we could just define the record type here + // and then copy to the .bif.bro file, but type declarations in + // Bro can be quite powerful. Don't know whether it's worth it + // extend the bif-language to be able to handle that all.... + // Or we just support a simple form of record type definitions + // TODO: add other types (tables, sets) +type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' + { + set_decl_name($3); + + fprintf(fp_netvar_h, "%s extern %sType * %s; %s\n", + decl.c_namespace_start.c_str(), type_name.c_str(), + decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, "%s %sType * %s; %s\n", + decl.c_namespace_start.c_str(), type_name.c_str(), + decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_init, + "\t%s = internal_type(\"%s\")->As%sType();\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str(), + type_name.c_str()); + + record_bif_item(decl.bro_fullname.c_str(), "TYPE"); + } + ; + +type_def_types: TOK_RECORD + { set_definition_type(TYPE_DEF, "Record"); } + | TOK_SET + { set_definition_type(TYPE_DEF, "Set"); } + | TOK_VECTOR + { set_definition_type(TYPE_DEF, "Vector"); } + | TOK_TABLE + { set_definition_type(TYPE_DEF, "Table"); } + ; + +opt_func_attrs: attr_list opt_ws + { $$ = $1; } + | /* nothing */ + { $$ = ""; } + ; + +event_def: event_prefix opt_ws plain_head opt_func_attrs + { fprintf(fp_bro_init, "%s", $4); } end_of_head ';' + { + print_event_c_prototype(fp_func_h, true); + print_event_c_prototype(fp_func_def, false); + print_event_c_body(fp_func_def); + } + +func_def: func_prefix opt_ws typed_head opt_func_attrs + { fprintf(fp_bro_init, "%s", $4); } end_of_head body + ; + +enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list + { + // First, put an end to the enum type decl. + fprintf(fp_bro_init, "} "); + fprintf(fp_bro_init, "%s", $4); + fprintf(fp_bro_init, ";\n"); + if ( decl.module_name != GLOBAL_MODULE_NAME ) + fprintf(fp_netvar_h, "}; } }\n"); + else + fprintf(fp_netvar_h, "}; }\n"); + + // Now generate the netvar's. + fprintf(fp_netvar_h, "%s extern EnumType * %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, "%s EnumType * %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_init, + "\t%s = internal_type(\"%s\")->AsEnumType();\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + + record_bif_item(decl.bro_fullname.c_str(), "TYPE"); + } + ; + +enum_def_1: TOK_ENUM opt_ws TOK_ID opt_ws TOK_LPB opt_ws + { + set_definition_type(TYPE_DEF, "Enum"); + set_decl_name($3); + fprintf(fp_bro_init, "type %s: enum %s{%s", decl.bro_name.c_str(), $4, $6); + + // this is the namespace were the enumerators are defined, not where + // the type is defined. + // We don't support fully qualified names as enumerators. Use a module name + fprintf(fp_netvar_h, "namespace BifEnum { "); + if ( decl.module_name != GLOBAL_MODULE_NAME ) + fprintf(fp_netvar_h, "namespace %s { ", decl.module_name.c_str()); + fprintf(fp_netvar_h, "enum %s {\n", $3); + } + ; + +enum_list: enum_list TOK_ID opt_ws ',' opt_ws + { + fprintf(fp_bro_init, "%s%s,%s", $2, $3, $5); + fprintf(fp_netvar_h, "\t%s,\n", $2); + } + | enum_list TOK_ID opt_ws '=' opt_ws TOK_INT opt_ws ',' opt_ws + { + fprintf(fp_bro_init, "%s = %s%s,%s", $2, $6, $7, $9); + fprintf(fp_netvar_h, "\t%s = %s,\n", $2, $6); + } + | /* nothing */ + ; + + +const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' + { + set_definition_type(CONST_DEF, 0); + set_decl_name($3); + int typeidx = get_type_index($7); + char accessor[1024]; + + snprintf(accessor, sizeof(accessor), builtin_types[typeidx].accessor, ""); + + + fprintf(fp_netvar_h, "%s extern %s %s; %s\n", + decl.c_namespace_start.c_str(), + builtin_types[typeidx].c_type, decl.bare_name.c_str(), + decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, "%s %s %s; %s\n", + decl.c_namespace_start.c_str(), + builtin_types[typeidx].c_type, decl.bare_name.c_str(), + decl.c_namespace_end.c_str()); + fprintf(fp_netvar_init, "\t%s = internal_const_val(\"%s\")%s;\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str(), + accessor); + + record_bif_item(decl.bro_fullname.c_str(), "CONSTANT"); + } + +attr_list: + attr_list TOK_ATTR + { $$ = concat($1, $2); } + | + TOK_ATTR + ; + +opt_attr_list: + attr_list + | /* nothing */ + { $$ = ""; } + ; + +func_prefix: TOK_FUNCTION + { set_definition_type(FUNC_DEF, 0); } + ; + +event_prefix: TOK_EVENT + { set_definition_type(EVENT_DEF, 0); } + ; + +end_of_head: /* nothing */ + { + fprintf(fp_bro_init, ";\n"); + } + ; + +typed_head: plain_head return_type + { + } + ; + +plain_head: head_1 args arg_end opt_ws + { + if ( var_arg ) + fprintf(fp_bro_init, "va_args: any"); + else + { + for ( int i = 0; i < (int) args.size(); ++i ) + { + if ( i > 0 ) + fprintf(fp_bro_init, ", "); + args[i]->PrintBro(fp_bro_init); + } + } + + fprintf(fp_bro_init, ")"); + + fprintf(fp_bro_init, "%s", $4); + fprintf(fp_func_def, "%s", $4); + } + ; + +head_1: TOK_ID opt_ws arg_begin + { + const char* method_type = 0; + set_decl_name($1); + + if ( definition_type == FUNC_DEF ) + { + method_type = "function"; + print_line_directive(fp_func_def); + } + else if ( definition_type == EVENT_DEF ) + method_type = "event"; + + if ( method_type ) + fprintf(fp_bro_init, + "global %s: %s%s(", + decl.bro_name.c_str(), method_type, $2); + + if ( definition_type == FUNC_DEF ) + { + fprintf(fp_func_init, + "\t(void) new BuiltinFunc(%s, \"%s\", 0);\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + + fprintf(fp_func_h, + "%sextern Val* %s(Frame* frame, val_list*);%s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + + fprintf(fp_func_def, + "Val* %s(Frame* frame, val_list* %s)", + decl.c_fullname.c_str(), arg_list_name); + + record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); + } + else if ( definition_type == EVENT_DEF ) + { + // TODO: add namespace for events here + fprintf(fp_netvar_h, + "%sextern EventHandlerPtr %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + + fprintf(fp_netvar_def, + "%sEventHandlerPtr %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + + fprintf(fp_netvar_init, + "\t%s = internal_handler(\"%s\");\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + + record_bif_item(decl.bro_fullname.c_str(), "EVENT"); + + // C++ prototypes of bro_event_* functions will + // be generated later. + } + } + ; + +arg_begin: TOK_LPP + { args.clear(); var_arg = 0; } + ; + +arg_end: TOK_RPP + ; + +args: args_1 + | opt_ws + { /* empty, to avoid yacc complaint about type clash */ } + ; + +args_1: args_1 ',' opt_ws arg opt_ws opt_attr_list + { if ( ! args.empty() ) args[args.size()-1]->SetAttrStr($6); } + | opt_ws arg opt_ws opt_attr_list + { if ( ! args.empty() ) args[args.size()-1]->SetAttrStr($4); } + ; + +// TODO: Migrate all other compound types to this rule. Once the BiF language +// can parse all regular Bro types, we can throw out the unnecessary +// boilerplate typedefs for addr_set, string_set, etc. +type: + TOK_OPAQUE opt_ws TOK_OF opt_ws TOK_ID + { $$ = concat("opaque of ", $5); } + | TOK_ID + { $$ = $1; } + ; + +arg: TOK_ID opt_ws ':' opt_ws type + { args.push_back(new BuiltinFuncArg($1, $5)); } + | TOK_VAR_ARG + { + if ( definition_type == EVENT_DEF ) + yyerror("events cannot have variable arguments"); + var_arg = 1; + } + ; + +return_type: ':' opt_ws type opt_ws + { + BuiltinFuncArg* ret = new BuiltinFuncArg("", $3); + ret->PrintBro(fp_bro_init); + delete ret; + fprintf(fp_func_def, "%s", $4); + } + ; + +body: body_start c_body body_end + { + fprintf(fp_func_def, " // end of %s\n", decl.c_fullname.c_str()); + print_line_directive(fp_func_def); + } + ; + +c_code_begin: /* empty */ + { + in_c_code = 1; + print_line_directive(fp_func_def); + } + ; + +c_code_end: /* empty */ + { in_c_code = 0; } + ; + +body_start: TOK_LPB c_code_begin + { + int implicit_arg = 0; + int argc = args.size(); + + fprintf(fp_func_def, "{"); + + if ( argc > 0 || ! var_arg ) + fprintf(fp_func_def, "\n"); + + if ( ! var_arg ) + { + fprintf(fp_func_def, "\tif ( %s->length() != %d )\n", arg_list_name, argc); + fprintf(fp_func_def, "\t\t{\n"); + fprintf(fp_func_def, + "\t\treporter->Error(\"%s() takes exactly %d argument(s)\");\n", + decl.bro_fullname.c_str(), argc); + fprintf(fp_func_def, "\t\treturn 0;\n"); + fprintf(fp_func_def, "\t\t}\n"); + } + else if ( argc > 0 ) + { + fprintf(fp_func_def, "\tif ( %s->length() < %d )\n", arg_list_name, argc); + fprintf(fp_func_def, "\t\t{\n"); + fprintf(fp_func_def, + "\t\treporter->Error(\"%s() takes at least %d argument(s)\");\n", + decl.bro_fullname.c_str(), argc); + fprintf(fp_func_def, "\t\treturn 0;\n"); + fprintf(fp_func_def, "\t\t}\n"); + } + + for ( int i = 0; i < (int) args.size(); ++i ) + args[i]->PrintCDef(fp_func_def, i + implicit_arg); + print_line_directive(fp_func_def); + } + ; + +body_end: TOK_RPB c_code_end + { + fprintf(fp_func_def, "}"); + } + ; + +c_code_segment: TOK_LPPB c_code_begin c_body c_code_end TOK_RPPB + ; + +c_body: opt_ws + { fprintf(fp_func_def, "%s", $1); } + | c_body c_atom opt_ws + { fprintf(fp_func_def, "%s", $3); } + ; + +c_atom: TOK_ID + { fprintf(fp_func_def, "%s", $1); } + | TOK_C_TOKEN + { fprintf(fp_func_def, "%s", $1); } + | TOK_ARG + { fprintf(fp_func_def, "(*%s)", arg_list_name); } + | TOK_ARGS + { fprintf(fp_func_def, "%s", arg_list_name); } + | TOK_ARGC + { fprintf(fp_func_def, "%s->length()", arg_list_name); } + | TOK_CSTR + { fprintf(fp_func_def, "%s", $1); } + | TOK_ATOM + { fprintf(fp_func_def, "%c", $1); } + | TOK_INT + { fprintf(fp_func_def, "%s", $1); } + + ; + +opt_ws: opt_ws TOK_WS + { $$ = concat($1, $2); } + | opt_ws TOK_LF + { $$ = concat($1, "\n"); } + | opt_ws TOK_COMMENT + { + if ( in_c_code ) + $$ = concat($1, $2); + else + if ( $2[1] == '#' ) + // This is a special type of comment that is used to + // generate bro script documentation, so pass it through. + $$ = concat($1, $2); + else + $$ = $1; + } + | /* empty */ + { $$ = ""; } + ; + +%% + +extern char* yytext; +extern char* input_filename; +extern int line_number; +void err_exit(void); + +void print_msg(const char msg[]) + { + int msg_len = strlen(msg) + strlen(yytext) + 64; + char* msgbuf = new char[msg_len]; + + if ( yytext[0] == '\n' ) + snprintf(msgbuf, msg_len, "%s, on previous line", msg); + + else if ( yytext[0] == '\0' ) + snprintf(msgbuf, msg_len, "%s, at end of file", msg); + + else + snprintf(msgbuf, msg_len, "%s, at or near \"%s\"", msg, yytext); + + /* + extern int column; + sprintf(msgbuf, "%*s\n%*s\n", column, "^", column, msg); + */ + + if ( input_filename ) + fprintf(stderr, "%s:%d: ", input_filename, line_number); + else + fprintf(stderr, "line %d: ", line_number); + fprintf(stderr, "%s\n", msgbuf); + + delete [] msgbuf; + } + +int yywarn(const char msg[]) + { + print_msg(msg); + return 0; + } + +int yyerror(const char msg[]) + { + print_msg(msg); + + err_exit(); + return 0; + } diff --git a/tools/bifcl/module_util.cc b/tools/bifcl/module_util.cc new file mode 100644 index 0000000000..d5817a7d7a --- /dev/null +++ b/tools/bifcl/module_util.cc @@ -0,0 +1,67 @@ +// +// See the file "COPYING" in the main distribution directory for copyright. + +#include +#include +#include "module_util.h" + +static int streq(const char* s1, const char* s2) + { + return ! strcmp(s1, s2); + } + +// Returns it without trailing "::". +string extract_module_name(const char* name) + { + string module_name = name; + string::size_type pos = module_name.rfind("::"); + + if ( pos == string::npos ) + return string(GLOBAL_MODULE_NAME); + + module_name.erase(pos); + + return module_name; + } + +string extract_var_name(const char *name) + { + string var_name = name; + string::size_type pos = var_name.rfind("::"); + + if ( pos == string::npos ) + return var_name; + + if ( pos + 2 > var_name.size() ) + return string(""); + + return var_name.substr(pos+2); + } + +string normalized_module_name(const char* module_name) + { + int mod_len; + if ( (mod_len = strlen(module_name)) >= 2 && + streq(module_name + mod_len - 2, "::") ) + mod_len -= 2; + + return string(module_name, mod_len); + } + +string make_full_var_name(const char* module_name, const char* var_name) + { + if ( ! module_name || streq(module_name, GLOBAL_MODULE_NAME) || + strstr(var_name, "::") ) + { + if ( streq(GLOBAL_MODULE_NAME, extract_module_name(var_name).c_str()) ) + return extract_var_name(var_name); + + return string(var_name); + } + + string full_name = normalized_module_name(module_name); + full_name += "::"; + full_name += var_name; + + return full_name; + } From c3f6c8a4a07759b057b246f683a08ba5a37cb801 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 24 Jul 2018 01:58:34 +0000 Subject: [PATCH 155/343] bifcl: Fix compiler warning. --- tools/bifcl/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index f13498b554..a716e07ef7 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -31,6 +31,7 @@ bison_target(BIFParser builtin-func.y COMPILE_FLAGS "${BISON_FLAGS}") flex_target(BIFScanner builtin-func.l ${CMAKE_CURRENT_BINARY_DIR}/bif_lex.cc) add_flex_bison_dependency(BIFScanner BIFParser) +set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") set(bifcl_SRCS ${BISON_BIFParser_INPUT} From a95808bc6b63b9d0e9f5043587f712ae1c9f9f2b Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 4 Apr 2019 01:12:47 -0500 Subject: [PATCH 156/343] bifcl: Change file extension of auto-generated script files Changed ".bro" file extension to ".zeek". --- tools/bifcl/README | 2 +- tools/bifcl/builtin-func.l | 6 +++--- tools/bifcl/builtin-func.y | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/bifcl/README b/tools/bifcl/README index 0ec59344ec..a3eff7ee57 100644 --- a/tools/bifcl/README +++ b/tools/bifcl/README @@ -5,7 +5,7 @@ Bro BIF Compiler ================ The ``bifcl`` program simply takes a ``.bif`` file as input and -generates C++ header/source files along with a ``.bro`` script +generates C++ header/source files along with a ``.zeek`` script that all-together provide the declaration and implementation of Bro_ Built-In-Functions (BIFs), which can then be compiled and shipped as part of a Bro plugin. diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 2d59408f83..d8c1ddb750 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -188,7 +188,7 @@ void usage() void init_alternative_mode() { - fp_bro_init = open_output_file("bro"); + fp_bro_init = open_output_file("zeek"); fp_func_h = open_output_file("h"); fp_func_def = open_output_file("cc"); fp_func_init = open_output_file("init.cc"); @@ -335,7 +335,7 @@ int main(int argc, char* argv[]) if ( ! alternative_mode ) { - fp_bro_init = open_output_file("bro"); + fp_bro_init = open_output_file("zeek"); fp_func_h = open_output_file("func_h"); fp_func_def = open_output_file("func_def"); fp_func_init = open_output_file("func_init"); @@ -409,7 +409,7 @@ void err_exit(void) { close_all_output_files(); /* clean up. remove all output files we've generated so far */ - remove_file("bro"); + remove_file("zeek"); remove_file("func_h"); remove_file("func_def"); remove_file("func_init"); diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 0f895ced52..40d0c76838 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -50,7 +50,7 @@ struct decl_struct { string c_namespace_end; // closing "}" for all the above namespaces string c_fullname; // fully qualified name (namespace::....) for use in netvar_init string bro_fullname; // fully qualified bro name, for netvar (and lookup_ID()) - string bro_name; // the name as we read it from input. What we write into the .bro file + string bro_name; // the name as we read it from input. What we write into the .zeek file // special cases for events. Events have an EventHandlerPtr // and a generate_* function. This name is for the generate_* function @@ -338,7 +338,7 @@ module_def: TOK_MODULE opt_ws TOK_ID opt_ws ';' // XXX: Add the netvar glue so that the event engine knows about // the type. One still has to define the type in bro.init. // Would be nice, if we could just define the record type here - // and then copy to the .bif.bro file, but type declarations in + // and then copy to the .bif.zeek file, but type declarations in // Bro can be quite powerful. Don't know whether it's worth it // extend the bif-language to be able to handle that all.... // Or we just support a simple form of record type definitions From 3b8932ff01ced4d586c4db63b15c070e29117bd8 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 11 Apr 2019 19:31:37 -0700 Subject: [PATCH 157/343] bifcl: Update codegen to use faster val_list and event queue API --- tools/bifcl/builtin-func.y | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 40d0c76838..c2147fd540 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -230,15 +230,15 @@ void print_event_c_body(FILE *fp) fprintf(fp, "\t// allocation.\n"); fprintf(fp, "\n"); - fprintf(fp, "\tval_list* vl = new val_list;\n\n"); - BuiltinFuncArg *connection_arg = 0; + BuiltinFuncArg* connection_arg = 0; + + fprintf(fp, "\tmgr.QueueEventFast(%s, val_list{\n", decl.c_fullname.c_str()); for ( int i = 0; i < (int) args.size(); ++i ) { - fprintf(fp, "\t"); - fprintf(fp, "vl->append("); + fprintf(fp, "\t "); args[i]->PrintBroValConstructor(fp); - fprintf(fp, ");\n"); + fprintf(fp, ",\n"); if ( args[i]->Type() == TYPE_CONNECTION ) { @@ -254,9 +254,7 @@ void print_event_c_body(FILE *fp) } } - fprintf(fp, "\n"); - fprintf(fp, "\tmgr.QueueEvent(%s, vl, SOURCE_LOCAL, analyzer->GetID(), timer_mgr", - decl.c_fullname.c_str()); + fprintf(fp, "\t },\n\t SOURCE_LOCAL, analyzer->GetID(), timer_mgr"); if ( connection_arg ) // Pass the connection to the EventMgr as the "cookie" From 3ce42f2f35d477cb91106de491d6257d59b11c44 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 16 May 2019 23:51:10 -0500 Subject: [PATCH 158/343] bifcl: Rename Bro to Zeek --- tools/bifcl/README | 18 +++++++++--------- tools/bifcl/builtin-func.l | 2 +- tools/bifcl/builtin-func.y | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/bifcl/README b/tools/bifcl/README index a3eff7ee57..f96c7a4451 100644 --- a/tools/bifcl/README +++ b/tools/bifcl/README @@ -1,19 +1,19 @@ -.. _Bro: https://bro.org +.. _Zeek: https://www.zeek.org -================ -Bro BIF Compiler -================ +================= +Zeek BIF Compiler +================= The ``bifcl`` program simply takes a ``.bif`` file as input and generates C++ header/source files along with a ``.zeek`` script -that all-together provide the declaration and implementation of Bro_ +that all-together provide the declaration and implementation of Zeek_ Built-In-Functions (BIFs), which can then be compiled and shipped -as part of a Bro plugin. +as part of a Zeek plugin. A BIF allows one to write arbitrary C++ code and access it via a -function call inside a Bro script. In this way, they can also be -used to access parts of Bro's internal C++ API that aren't already +function call inside a Zeek script. In this way, they can also be +used to access parts of Zeek's internal C++ API that aren't already exposed via their own BIFs. At the moment, learning the format of a ``.bif`` file is likely easiest -by just taking a look at the ``.bif`` files inside the Bro source-tree. +by just taking a look at the ``.bif`` files inside the Zeek source-tree. diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index d8c1ddb750..6c834bdd66 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -105,7 +105,7 @@ HEX [0-9a-fA-F]+ /* Hacky way to pass along arbitrary attribute expressions since the BIF parser - has little understanding of valid Bro expressions. With this pattern, the + has little understanding of valid Zeek expressions. With this pattern, the attribute expression should stop when it reaches another attribute, another function argument, or the end of the function declaration. */ diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index c2147fd540..6a17ad246e 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -337,7 +337,7 @@ module_def: TOK_MODULE opt_ws TOK_ID opt_ws ';' // the type. One still has to define the type in bro.init. // Would be nice, if we could just define the record type here // and then copy to the .bif.zeek file, but type declarations in - // Bro can be quite powerful. Don't know whether it's worth it + // Zeek can be quite powerful. Don't know whether it's worth it // extend the bif-language to be able to handle that all.... // Or we just support a simple form of record type definitions // TODO: add other types (tables, sets) @@ -596,7 +596,7 @@ args_1: args_1 ',' opt_ws arg opt_ws opt_attr_list ; // TODO: Migrate all other compound types to this rule. Once the BiF language -// can parse all regular Bro types, we can throw out the unnecessary +// can parse all regular Zeek types, we can throw out the unnecessary // boilerplate typedefs for addr_set, string_set, etc. type: TOK_OPAQUE opt_ws TOK_OF opt_ws TOK_ID From a86b98bb9ef1e100900beb78a8b1bbf6af4fecbc Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 24 Oct 2019 19:13:05 -0700 Subject: [PATCH 159/343] bifcl: Move headers into include/ subdir This avoids potential problems with libc++ 8+ on case-insensitive file systems due to inclusion of a new header called which will end up conflicting with the VERSION file if the search path includes the project root. --- tools/bifcl/CMakeLists.txt | 6 ++-- tools/bifcl/include/bif_arg.h | 51 +++++++++++++++++++++++++++++++ tools/bifcl/include/bif_type.def | 22 +++++++++++++ tools/bifcl/include/module_util.h | 17 +++++++++++ 4 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 tools/bifcl/include/bif_arg.h create mode 100644 tools/bifcl/include/bif_type.def create mode 100644 tools/bifcl/include/module_util.h diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index a716e07ef7..e111d5454d 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -17,7 +17,7 @@ if ( MISSING_PREREQS ) endif () include_directories(BEFORE - ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR} ) @@ -39,9 +39,9 @@ set(bifcl_SRCS ${BISON_BIFParser_OUTPUTS} ${FLEX_BIFScanner_OUTPUTS} bif_arg.cc - bif_arg.h + include/bif_arg.h module_util.cc - module_util.h + include/module_util.h ) add_executable(bifcl ${bifcl_SRCS}) diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h new file mode 100644 index 0000000000..906cfd9c6a --- /dev/null +++ b/tools/bifcl/include/bif_arg.h @@ -0,0 +1,51 @@ +#ifndef bif_arg_h +#define bif_arg_h + +#include + +enum builtin_func_arg_type { +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ + id, +#include "bif_type.def" +#undef DEFINE_BIF_TYPE +/* + TYPE_ANY, + TYPE_BOOL, + TYPE_COUNT, + TYPE_INT, + TYPE_STRING, + TYPE_PATTERN, + TYPE_PORT, + TYPE_OTHER, +*/ +}; + +extern const char* builtin_func_arg_type_bro_name[]; + +class BuiltinFuncArg { +public: + BuiltinFuncArg(const char* arg_name, int arg_type); + BuiltinFuncArg(const char* arg_name, const char* arg_type_str, + const char* arg_attr_str = ""); + + void SetAttrStr(const char* arg_attr_str) + { + attr_str = arg_attr_str; + }; + + const char* Name() const { return name; } + int Type() const { return type; } + + void PrintBro(FILE* fp); + void PrintCDef(FILE* fp, int n); + void PrintCArg(FILE* fp, int n); + void PrintBroValConstructor(FILE* fp); + +protected: + const char* name; + int type; + const char* type_str; + const char* attr_str; +}; + +#endif diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def new file mode 100644 index 0000000000..9b17011cc3 --- /dev/null +++ b/tools/bifcl/include/bif_type.def @@ -0,0 +1,22 @@ +// DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) + +DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "%s->AsAddrVal()", "%s") +DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "%s", "%s") +DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "val_mgr->GetBool(%s)") +DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "%s", "%s") +DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->BuildConnVal()") +DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "%s->AsCount()", "val_mgr->GetCount(%s)") +DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "%s->AsDouble()", "new Val(%s, TYPE_DOUBLE)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "%s->AsFile()", "new Val(%s)") +DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "%s->AsInt()", "val_mgr->GetInt(%s)") +DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "%s->AsInterval()", "new IntervalVal(%s, Seconds)") +DEFINE_BIF_TYPE(TYPE_PACKET, "packet", "packet", "TCP_TracePacket*", "%s->AsRecordVal()->GetOrigin()", "%s->PacketVal()") +DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "%s->AsPattern()", "new PatternVal(%s)") +// DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "uint32", "%s->AsPortVal()->Port()", "incomplete data") +DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "%s->AsPortVal()", "%s") +DEFINE_BIF_TYPE(TYPE_PORTVAL, "portval", "port", "PortVal*", "%s->AsPortVal()", "%s") +DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "%s->AsStringVal()", "%s") +// DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "BroString*", "%s->AsString()", "new StringVal(%s)") +DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "%s->AsSubNetVal()", "%s") +DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "%s->AsTime()", "new Val(%s, TYPE_TIME)") +DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "%s", "%s") diff --git a/tools/bifcl/include/module_util.h b/tools/bifcl/include/module_util.h new file mode 100644 index 0000000000..8475c86f9d --- /dev/null +++ b/tools/bifcl/include/module_util.h @@ -0,0 +1,17 @@ +// +// These functions are used by both Zeek and bifcl. +// + +#include + +using namespace std; + +static const char* GLOBAL_MODULE_NAME = "GLOBAL"; + +extern string extract_module_name(const char* name); +extern string extract_var_name(const char* name); +extern string normalized_module_name(const char* module_name); // w/o :: + +// Concatenates module_name::var_name unless var_name is already fully +// qualified, in which case it is returned unmodified. +extern string make_full_var_name(const char* module_name, const char* var_name); From 81b23aff92e7bb0f978aaedb8efa6a8f354bf0d3 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 28 Oct 2019 17:58:16 -0700 Subject: [PATCH 160/343] bifcl: Move CMake project() after cmake_minimum_required() --- tools/bifcl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index e111d5454d..114b78a74c 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -1,6 +1,6 @@ -project(BifCl C CXX) cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) +project(BifCl C CXX) include(cmake/CommonCMakeConfig.cmake) From c60bd14d5675dabc5853a47bee35781d2be4d000 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 19 Dec 2019 12:24:59 -0800 Subject: [PATCH 161/343] bifcl: Disable LeakSanitizer Related to https://github.com/zeek/zeek/issues/699 --- tools/bifcl/builtin-func.l | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 6c834bdd66..ad58f81f9e 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -294,8 +294,29 @@ void finish_alternative_mode() } } +// GCC uses __SANITIZE_ADDRESS__, Clang uses __has_feature +#if defined(__SANITIZE_ADDRESS__) + #define USING_ASAN +#endif + +#if defined(__has_feature) + #if __has_feature(address_sanitizer) + #define USING_ASAN + #endif +#endif + +#if defined(USING_ASAN) + #include +#endif + int main(int argc, char* argv[]) { + #if defined(USING_ASAN) + // We generally do not care at all if bifcl is leaking and the default + // behavior of LSAN to treat leaks as errors only trips up Zeek's build. + __lsan_disable(); + #endif + int opt; while ( (opt = getopt(argc, argv, "p:s")) != -1 ) From 7009f1dda6f92b1966b86bb704f960155a38390b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 10 Feb 2020 12:00:31 -0800 Subject: [PATCH 162/343] bifcl: Fix header include guards --- tools/bifcl/include/bif_arg.h | 5 +---- tools/bifcl/include/module_util.h | 2 ++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index 906cfd9c6a..4edf23344a 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -1,5 +1,4 @@ -#ifndef bif_arg_h -#define bif_arg_h +#pragma once #include @@ -47,5 +46,3 @@ protected: const char* type_str; const char* attr_str; }; - -#endif diff --git a/tools/bifcl/include/module_util.h b/tools/bifcl/include/module_util.h index 8475c86f9d..fa5f24964f 100644 --- a/tools/bifcl/include/module_util.h +++ b/tools/bifcl/include/module_util.h @@ -2,6 +2,8 @@ // These functions are used by both Zeek and bifcl. // +#pragma once + #include using namespace std; From 163a86fc4e0f71f184c28b7531d17acc4a964192 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 20 Mar 2020 18:01:03 -0700 Subject: [PATCH 163/343] bifcl: Move BIF function arguments from val_list to vector of IntrusivePtr --- tools/bifcl/bif_arg.cc | 2 +- tools/bifcl/builtin-func.y | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index f83333220d..fc70628b8f 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -61,7 +61,7 @@ void BuiltinFuncArg::PrintCDef(FILE* fp, int n) builtin_func_arg_type[type].c_type); char buf[1024]; - snprintf(buf, sizeof(buf), "(*%s)[%d]", arg_list_name, n); + snprintf(buf, sizeof(buf), "(*%s)[%d].get()", arg_list_name, n); // Print the accessor expression. fprintf(fp, builtin_func_arg_type[type].accessor, buf); diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 6a17ad246e..1e689b9059 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -545,11 +545,11 @@ head_1: TOK_ID opt_ws arg_begin decl.c_fullname.c_str(), decl.bro_fullname.c_str()); fprintf(fp_func_h, - "%sextern Val* %s(Frame* frame, val_list*);%s\n", + "%sextern Val* %s(Frame* frame, const zeek::Args*);%s\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, - "Val* %s(Frame* frame, val_list* %s)", + "Val* %s(Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); @@ -654,7 +654,7 @@ body_start: TOK_LPB c_code_begin if ( ! var_arg ) { - fprintf(fp_func_def, "\tif ( %s->length() != %d )\n", arg_list_name, argc); + fprintf(fp_func_def, "\tif ( %s->size() != %d )\n", arg_list_name, argc); fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, "\t\treporter->Error(\"%s() takes exactly %d argument(s)\");\n", @@ -664,7 +664,7 @@ body_start: TOK_LPB c_code_begin } else if ( argc > 0 ) { - fprintf(fp_func_def, "\tif ( %s->length() < %d )\n", arg_list_name, argc); + fprintf(fp_func_def, "\tif ( %s->size() < %d )\n", arg_list_name, argc); fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, "\t\treporter->Error(\"%s() takes at least %d argument(s)\");\n", @@ -703,7 +703,7 @@ c_atom: TOK_ID | TOK_ARGS { fprintf(fp_func_def, "%s", arg_list_name); } | TOK_ARGC - { fprintf(fp_func_def, "%s->length()", arg_list_name); } + { fprintf(fp_func_def, "%s->size()", arg_list_name); } | TOK_CSTR { fprintf(fp_func_def, "%s", $1); } | TOK_ATOM From de453419d7ebcbbd12292c9f10bd95157c7ef653 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 25 Mar 2020 15:18:53 -0700 Subject: [PATCH 164/343] bifcl: Use EventMgr::Enqueue() instead of QueueEventFast() --- tools/bifcl/builtin-func.y | 2 +- tools/bifcl/include/bif_type.def | 38 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 1e689b9059..bb1217f78c 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -232,7 +232,7 @@ void print_event_c_body(FILE *fp) BuiltinFuncArg* connection_arg = 0; - fprintf(fp, "\tmgr.QueueEventFast(%s, val_list{\n", decl.c_fullname.c_str()); + fprintf(fp, "\tmgr.Enqueue(%s, zeek::Args{\n", decl.c_fullname.c_str()); for ( int i = 0; i < (int) args.size(); ++i ) { diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 9b17011cc3..a8e880d636 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -1,22 +1,22 @@ // DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) -DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "%s->AsAddrVal()", "%s") -DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "%s", "%s") -DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "val_mgr->GetBool(%s)") -DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "%s", "%s") -DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->BuildConnVal()") -DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "%s->AsCount()", "val_mgr->GetCount(%s)") -DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "%s->AsDouble()", "new Val(%s, TYPE_DOUBLE)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "%s->AsFile()", "new Val(%s)") -DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "%s->AsInt()", "val_mgr->GetInt(%s)") -DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "%s->AsInterval()", "new IntervalVal(%s, Seconds)") -DEFINE_BIF_TYPE(TYPE_PACKET, "packet", "packet", "TCP_TracePacket*", "%s->AsRecordVal()->GetOrigin()", "%s->PacketVal()") -DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "%s->AsPattern()", "new PatternVal(%s)") +DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "%s->AsAddrVal()", "IntrusivePtr{AdoptRef{}, %s}") +DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") +DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "IntrusivePtr{AdoptRef{}, val_mgr->GetBool(%s)}") +DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") +DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "%s->AsRecordVal()->GetOrigin()", "IntrusivePtr{AdoptRef{}, %s->BuildConnVal()}") +DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "%s->AsCount()", "IntrusivePtr{AdoptRef{}, val_mgr->GetCount(%s)}") +DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "%s->AsDouble()", "make_intrusive(%s, TYPE_DOUBLE)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "%s->AsFile()", "make_intrusive(%s)") +DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "%s->AsInt()", "IntrusivePtr{AdoptRef{}, val_mgr->GetInt(%s)}") +DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "%s->AsInterval()", "make_intrusive(%s, Seconds)") +DEFINE_BIF_TYPE(TYPE_PACKET, "packet", "packet", "TCP_TracePacket*", "%s->AsRecordVal()->GetOrigin()", "IntrusivePtr{AdoptRef{}, %s->PacketVal()}") +DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "%s->AsPattern()", "make_intrusive(%s)") // DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "uint32", "%s->AsPortVal()->Port()", "incomplete data") -DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "%s->AsPortVal()", "%s") -DEFINE_BIF_TYPE(TYPE_PORTVAL, "portval", "port", "PortVal*", "%s->AsPortVal()", "%s") -DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "%s->AsStringVal()", "%s") -// DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "BroString*", "%s->AsString()", "new StringVal(%s)") -DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "%s->AsSubNetVal()", "%s") -DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "%s->AsTime()", "new Val(%s, TYPE_TIME)") -DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "%s", "%s") +DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "%s->AsPortVal()", "IntrusivePtr{AdoptRef{}, %s}") +DEFINE_BIF_TYPE(TYPE_PORTVAL, "portval", "port", "PortVal*", "%s->AsPortVal()", "IntrusivePtr{AdoptRef{}, %s}") +DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "%s->AsStringVal()", "IntrusivePtr{AdoptRef{}, %s}") +// DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "BroString*", "%s->AsString()", "make_intrusive(%s)") +DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "%s->AsSubNetVal()", "IntrusivePtr{AdoptRef{}, %s}") +DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "%s->AsTime()", "make_intrusive(%s, TYPE_TIME)") +DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") From b6b094b43af955fb6bb05d8f3eb1a19bef5f1159 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 25 Mar 2020 19:02:38 -0700 Subject: [PATCH 165/343] bifcl: Don't pass a TimerMgr to EventMgr::Enqueue() --- tools/bifcl/builtin-func.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index bb1217f78c..a02a95d717 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -254,7 +254,7 @@ void print_event_c_body(FILE *fp) } } - fprintf(fp, "\t },\n\t SOURCE_LOCAL, analyzer->GetID(), timer_mgr"); + fprintf(fp, "\t },\n\t SOURCE_LOCAL, analyzer->GetID()"); if ( connection_arg ) // Pass the connection to the EventMgr as the "cookie" From e5c62c01a42f627bfdb86e63896ede18325b0b68 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 1 Apr 2020 16:04:44 -0700 Subject: [PATCH 166/343] bifcl: Support multiple/alternate event prototype definitions --- tools/bifcl/builtin-func.y | 45 ++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index a02a95d717..c1121a8ef5 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -32,6 +32,11 @@ string current_module = GLOBAL_MODULE_NAME; int definition_type; string type_name; +// Alternate event prototypes are only written to the .zeek file, but +// don't need any further changes to C++ source/header files, so this +// set keeps track of whether the first event prototype information has +// already been defined/written to the C++ files. +static std::set events; enum { C_SEGMENT_DEF, @@ -379,9 +384,13 @@ opt_func_attrs: attr_list opt_ws event_def: event_prefix opt_ws plain_head opt_func_attrs { fprintf(fp_bro_init, "%s", $4); } end_of_head ';' { - print_event_c_prototype(fp_func_h, true); - print_event_c_prototype(fp_func_def, false); - print_event_c_body(fp_func_def); + if ( events.find(decl.bro_fullname) == events.end() ) + { + print_event_c_prototype(fp_func_h, true); + print_event_c_prototype(fp_func_def, false); + print_event_c_body(fp_func_def); + events.insert(decl.bro_fullname); + } } func_def: func_prefix opt_ws typed_head opt_func_attrs @@ -556,23 +565,25 @@ head_1: TOK_ID opt_ws arg_begin } else if ( definition_type == EVENT_DEF ) { - // TODO: add namespace for events here - fprintf(fp_netvar_h, - "%sextern EventHandlerPtr %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + if ( events.find(decl.bro_fullname) == events.end() ) + { + // TODO: add namespace for events here + fprintf(fp_netvar_h, + "%sextern EventHandlerPtr %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, - "%sEventHandlerPtr %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, + "%sEventHandlerPtr %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_init, - "\t%s = internal_handler(\"%s\");\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + fprintf(fp_netvar_init, + "\t%s = internal_handler(\"%s\");\n", + decl.c_fullname.c_str(), decl.bro_fullname.c_str()); - record_bif_item(decl.bro_fullname.c_str(), "EVENT"); - - // C++ prototypes of bro_event_* functions will - // be generated later. + record_bif_item(decl.bro_fullname.c_str(), "EVENT"); + // C++ prototypes of bro_event_* functions will + // be generated later. + } } } ; From df5249e7dd81dbfc7a2c4d33076fab39a5ed9a84 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 15 Apr 2020 16:19:48 -0700 Subject: [PATCH 167/343] bifcl: Remove use of Variable-Length-Arrays Related to https://github.com/zeek/zeek/issues/895 --- tools/bifcl/CMakeLists.txt | 2 ++ tools/bifcl/builtin-func.l | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index 114b78a74c..fb3dcac3af 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -16,6 +16,8 @@ if ( MISSING_PREREQS ) message(FATAL_ERROR "Configuration aborted due to missing prerequisites") endif () +include(RequireCXX17) + include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR} diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index ad58f81f9e..9387bebd0d 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -2,6 +2,7 @@ #include #include #include +#include #include "bif_arg.h" #include "bif_parse.h" @@ -199,7 +200,8 @@ void init_alternative_mode() fp_netvar_init = fp_func_init; int n = 1024 + strlen(input_filename); - char auto_gen_comment[n]; + auto auto_gen_comment_buf = std::make_unique(n); + auto auto_gen_comment = auto_gen_comment_buf.get(); snprintf(auto_gen_comment, n, "This file was automatically generated by bifcl from %s (%s mode).", @@ -365,7 +367,8 @@ int main(int argc, char* argv[]) fp_netvar_init = open_output_file("netvar_init"); int n = 1024 + strlen(input_filename); - char auto_gen_comment[n]; + auto auto_gen_comment_buf = std::make_unique(n); + auto auto_gen_comment = auto_gen_comment_buf.get(); snprintf(auto_gen_comment, n, "This file was automatically generated by bifcl from %s.", From 9a3ac5de98f90ec36b2b36cd3c0fb0503c5b60f7 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 3 Apr 2020 16:30:32 -0700 Subject: [PATCH 168/343] bifcl: Change BIFs to return a wrapper object That allows implicit conversion from either Val* or IntrusivePtr --- tools/bifcl/builtin-func.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index c1121a8ef5..000e90f0de 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -554,11 +554,11 @@ head_1: TOK_ID opt_ws arg_begin decl.c_fullname.c_str(), decl.bro_fullname.c_str()); fprintf(fp_func_h, - "%sextern Val* %s(Frame* frame, const zeek::Args*);%s\n", + "%sextern BifReturnVal %s(Frame* frame, const zeek::Args*);%s\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, - "Val* %s(Frame* frame, const zeek::Args* %s)", + "BifReturnVal %s(Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); From c2841cb1b2da214ff6427d1d9971c04372d6ec50 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 8 Apr 2020 16:37:29 -0700 Subject: [PATCH 169/343] bifcl: Update deprecated ValManager::Get usages --- tools/bifcl/include/bif_type.def | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index a8e880d636..39fbdf71f9 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -2,13 +2,13 @@ DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "%s->AsAddrVal()", "IntrusivePtr{AdoptRef{}, %s}") DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") -DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "IntrusivePtr{AdoptRef{}, val_mgr->GetBool(%s)}") +DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "val_mgr->Bool(%s)") DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "%s->AsRecordVal()->GetOrigin()", "IntrusivePtr{AdoptRef{}, %s->BuildConnVal()}") -DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "%s->AsCount()", "IntrusivePtr{AdoptRef{}, val_mgr->GetCount(%s)}") +DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "%s->AsCount()", "val_mgr->Count(%s)") DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "%s->AsDouble()", "make_intrusive(%s, TYPE_DOUBLE)") DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "%s->AsFile()", "make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "%s->AsInt()", "IntrusivePtr{AdoptRef{}, val_mgr->GetInt(%s)}") +DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "%s->AsInt()", "val_mgr->Int(%s)") DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "%s->AsInterval()", "make_intrusive(%s, Seconds)") DEFINE_BIF_TYPE(TYPE_PACKET, "packet", "packet", "TCP_TracePacket*", "%s->AsRecordVal()->GetOrigin()", "IntrusivePtr{AdoptRef{}, %s->PacketVal()}") DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "%s->AsPattern()", "make_intrusive(%s)") From 7958f7854cda7f8e7a0026bef4a041090e7bf195 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 8 Apr 2020 20:44:28 -0700 Subject: [PATCH 170/343] bifcl: Return nullptr instead of 0 in BIF error conditions --- tools/bifcl/builtin-func.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 000e90f0de..4cc4183ae1 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -670,7 +670,7 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\t\treporter->Error(\"%s() takes exactly %d argument(s)\");\n", decl.bro_fullname.c_str(), argc); - fprintf(fp_func_def, "\t\treturn 0;\n"); + fprintf(fp_func_def, "\t\treturn nullptr;\n"); fprintf(fp_func_def, "\t\t}\n"); } else if ( argc > 0 ) @@ -680,7 +680,7 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\t\treporter->Error(\"%s() takes at least %d argument(s)\");\n", decl.bro_fullname.c_str(), argc); - fprintf(fp_func_def, "\t\treturn 0;\n"); + fprintf(fp_func_def, "\t\treturn nullptr;\n"); fprintf(fp_func_def, "\t\t}\n"); } From 0f5c621bd7a40ccfc13d16393983b761dc1ed491 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 8 Apr 2020 21:45:37 -0700 Subject: [PATCH 171/343] bifcl: Update deprecated Connection::BuildConnVal usage --- tools/bifcl/include/bif_type.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 39fbdf71f9..23e9c40da3 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -4,7 +4,7 @@ DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "%s->AsAddrVal()", "I DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "val_mgr->Bool(%s)") DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") -DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "%s->AsRecordVal()->GetOrigin()", "IntrusivePtr{AdoptRef{}, %s->BuildConnVal()}") +DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->ConnVal()") DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "%s->AsCount()", "val_mgr->Count(%s)") DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "%s->AsDouble()", "make_intrusive(%s, TYPE_DOUBLE)") DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "%s->AsFile()", "make_intrusive(%s)") From b29ecfd82233424c9d2c9d487e795ceaf9725511 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 17 Apr 2020 18:41:14 -0700 Subject: [PATCH 172/343] bifcl: Deprecate BifEvent::generate_*, add BifEvent::enqueue_* --- tools/bifcl/bif_arg.cc | 18 ++++--- tools/bifcl/builtin-func.y | 81 ++++++++++++++++++++++---------- tools/bifcl/include/bif_arg.h | 16 ++----- tools/bifcl/include/bif_type.def | 39 +++++++-------- 4 files changed, 89 insertions(+), 65 deletions(-) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index fc70628b8f..cc9fc27cac 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -11,11 +11,13 @@ static struct { const char* bif_type; const char* bro_type; const char* c_type; + const char* c_type_smart; const char* accessor; const char* constructor; + const char* ctor_smart; } builtin_func_arg_type[] = { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ - {bif_type, bro_type, c_type, accessor, constructor}, +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart) \ + {bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE }; @@ -68,15 +70,19 @@ void BuiltinFuncArg::PrintCDef(FILE* fp, int n) fprintf(fp, ");\n"); } -void BuiltinFuncArg::PrintCArg(FILE* fp, int n) +void BuiltinFuncArg::PrintCArg(FILE* fp, int n, bool smart) { - const char* ctype = builtin_func_arg_type[type].c_type; + const char* ctype = smart ? builtin_func_arg_type[type].c_type_smart + : builtin_func_arg_type[type].c_type; char buf[1024]; fprintf(fp, "%s %s", ctype, name); } -void BuiltinFuncArg::PrintBroValConstructor(FILE* fp) +void BuiltinFuncArg::PrintBroValConstructor(FILE* fp, bool smart) { - fprintf(fp, builtin_func_arg_type[type].constructor, name); + if ( smart ) + fprintf(fp, builtin_func_arg_type[type].ctor_smart, name); + else + fprintf(fp, builtin_func_arg_type[type].constructor, name); } diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 4cc4183ae1..c17a98359b 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -63,6 +63,8 @@ struct decl_struct { string generate_c_fullname; string generate_c_namespace_start; string generate_c_namespace_end; + string enqueue_c_barename; + string enqueue_c_fullname; } decl; void set_definition_type(int type, const char *arg_type_name) @@ -90,7 +92,9 @@ void set_decl_name(const char *name) decl.bro_name = ""; decl.generate_c_fullname = ""; + decl.enqueue_c_fullname = ""; decl.generate_bare_name = string("generate_") + decl.bare_name; + decl.enqueue_c_barename = string("enqueue_") + decl.bare_name; decl.generate_c_namespace_start = ""; decl.generate_c_namespace_end = ""; @@ -120,6 +124,7 @@ void set_decl_name(const char *name) decl.generate_c_namespace_start = "namespace BifEvent { "; decl.generate_c_namespace_end = " } "; decl.generate_c_fullname = "BifEvent::"; + decl.enqueue_c_fullname = "BifEvent::"; break; default: @@ -136,6 +141,7 @@ void set_decl_name(const char *name) decl.generate_c_namespace_start += "namespace " + decl.module_name + " { "; decl.generate_c_namespace_end += " } "; decl.generate_c_fullname += decl.module_name + "::"; + decl.enqueue_c_fullname += decl.module_name + "::"; } decl.bro_fullname += decl.bare_name; @@ -145,7 +151,7 @@ void set_decl_name(const char *name) decl.c_fullname += decl.bare_name; decl.bro_name += name; decl.generate_c_fullname += decl.generate_bare_name; - + decl.enqueue_c_fullname += decl.enqueue_c_barename; } const char* arg_list_name = "BiF_ARGS"; @@ -157,11 +163,13 @@ static struct { const char* bif_type; const char* bro_type; const char* c_type; + const char* c_type_smart; const char* accessor; const char* constructor; + const char* ctor_smatr; } builtin_types[] = { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ - {bif_type, bro_type, c_type, accessor, constructor}, +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart) \ + {bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE }; @@ -199,32 +207,54 @@ char* concat(const char* str1, const char* str2) return s; } -// Print the bro_event_* function prototype in C++, without the ending ';' -void print_event_c_prototype(FILE *fp, bool is_header) +static void print_event_c_prototype_args(FILE* fp, bool smart) { - if ( is_header ) + for ( auto i = 0u; i < args.size(); ++i ) + { + if ( i > 0 ) + fprintf(fp, ", "); + + args[i]->PrintCArg(fp, i, smart); + } + } + +static void print_event_c_prototype_header(FILE* fp, bool smart) + { + if ( smart ) fprintf(fp, "%s void %s(analyzer::Analyzer* analyzer%s", - decl.generate_c_namespace_start.c_str(), decl.generate_bare_name.c_str(), + decl.generate_c_namespace_start.c_str(), + decl.enqueue_c_barename.c_str(), + args.size() ? ", " : "" ); + else + fprintf(fp, "%s [[deprecated(\"Remove in 4.1. Use %s instead.\")]] void %s(analyzer::Analyzer* analyzer%s", + decl.generate_c_namespace_start.c_str(), + decl.enqueue_c_fullname.c_str(), + decl.generate_bare_name.c_str(), + args.size() ? ", " : "" ); + + + print_event_c_prototype_args(fp, smart); + fprintf(fp, ")"); + fprintf(fp, "; %s\n", decl.generate_c_namespace_end.c_str()); + } + +static void print_event_c_prototype_impl(FILE* fp, bool smart) + { + if ( smart ) + fprintf(fp, "void %s(analyzer::Analyzer* analyzer%s", + decl.enqueue_c_fullname.c_str(), args.size() ? ", " : "" ); else fprintf(fp, "void %s(analyzer::Analyzer* analyzer%s", decl.generate_c_fullname.c_str(), args.size() ? ", " : "" ); - for ( int i = 0; i < (int) args.size(); ++i ) - { - if ( i > 0 ) - fprintf(fp, ", "); - args[i]->PrintCArg(fp, i); - } + + print_event_c_prototype_args(fp, smart); fprintf(fp, ")"); - if ( is_header ) - fprintf(fp, "; %s\n", decl.generate_c_namespace_end.c_str()); - else - fprintf(fp, "\n"); + fprintf(fp, "\n"); } -// Print the bro_event_* function body in C++. -void print_event_c_body(FILE *fp) +static void print_event_c_body(FILE* fp, bool smart) { fprintf(fp, "\t{\n"); fprintf(fp, "\t// Note that it is intentional that here we do not\n"); @@ -242,7 +272,7 @@ void print_event_c_body(FILE *fp) for ( int i = 0; i < (int) args.size(); ++i ) { fprintf(fp, "\t "); - args[i]->PrintBroValConstructor(fp); + args[i]->PrintBroValConstructor(fp, smart); fprintf(fp, ",\n"); if ( args[i]->Type() == TYPE_CONNECTION ) @@ -266,7 +296,7 @@ void print_event_c_body(FILE *fp) fprintf(fp, ", %s", connection_arg->Name()); fprintf(fp, ");\n"); - fprintf(fp, "\t} // event generation\n"); + fprintf(fp, "\t}\n\n"); //fprintf(fp, "%s // end namespace\n", decl.generate_c_namespace_end.c_str()); } @@ -386,9 +416,12 @@ event_def: event_prefix opt_ws plain_head opt_func_attrs { if ( events.find(decl.bro_fullname) == events.end() ) { - print_event_c_prototype(fp_func_h, true); - print_event_c_prototype(fp_func_def, false); - print_event_c_body(fp_func_def); + print_event_c_prototype_header(fp_func_h, false); + print_event_c_prototype_impl(fp_func_def, false); + print_event_c_body(fp_func_def, false); + print_event_c_prototype_header(fp_func_h, true); + print_event_c_prototype_impl(fp_func_def, true); + print_event_c_body(fp_func_def, true); events.insert(decl.bro_fullname); } } diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index 4edf23344a..c1dd5064b6 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -3,20 +3,10 @@ #include enum builtin_func_arg_type { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) \ +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart) \ id, #include "bif_type.def" #undef DEFINE_BIF_TYPE -/* - TYPE_ANY, - TYPE_BOOL, - TYPE_COUNT, - TYPE_INT, - TYPE_STRING, - TYPE_PATTERN, - TYPE_PORT, - TYPE_OTHER, -*/ }; extern const char* builtin_func_arg_type_bro_name[]; @@ -37,8 +27,8 @@ public: void PrintBro(FILE* fp); void PrintCDef(FILE* fp, int n); - void PrintCArg(FILE* fp, int n); - void PrintBroValConstructor(FILE* fp); + void PrintCArg(FILE* fp, int n, bool smart); + void PrintBroValConstructor(FILE* fp, bool smart); protected: const char* name; diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 23e9c40da3..974e8c6db5 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -1,22 +1,17 @@ -// DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) - -DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "%s->AsAddrVal()", "IntrusivePtr{AdoptRef{}, %s}") -DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") -DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "val_mgr->Bool(%s)") -DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") -DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->ConnVal()") -DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "%s->AsCount()", "val_mgr->Count(%s)") -DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "%s->AsDouble()", "make_intrusive(%s, TYPE_DOUBLE)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "%s->AsFile()", "make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "%s->AsInt()", "val_mgr->Int(%s)") -DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "%s->AsInterval()", "make_intrusive(%s, Seconds)") -DEFINE_BIF_TYPE(TYPE_PACKET, "packet", "packet", "TCP_TracePacket*", "%s->AsRecordVal()->GetOrigin()", "IntrusivePtr{AdoptRef{}, %s->PacketVal()}") -DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "%s->AsPattern()", "make_intrusive(%s)") -// DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "uint32", "%s->AsPortVal()->Port()", "incomplete data") -DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "%s->AsPortVal()", "IntrusivePtr{AdoptRef{}, %s}") -DEFINE_BIF_TYPE(TYPE_PORTVAL, "portval", "port", "PortVal*", "%s->AsPortVal()", "IntrusivePtr{AdoptRef{}, %s}") -DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "%s->AsStringVal()", "IntrusivePtr{AdoptRef{}, %s}") -// DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "BroString*", "%s->AsString()", "make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "%s->AsSubNetVal()", "IntrusivePtr{AdoptRef{}, %s}") -DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "%s->AsTime()", "make_intrusive(%s, TYPE_TIME)") -DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "%s", "IntrusivePtr{AdoptRef{}, %s}") +// (id, bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart) +DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "IntrusivePtr", "%s->AsAddrVal()", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "IntrusivePtr", "%s", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "val_mgr->Bool(%s)", "val_mgr->Bool(%s)") +DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "IntrusivePtr", "%s", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->ConnVal()", "%s->ConnVal()") +DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "val_mgr->Count(%s)", "val_mgr->Count(%s)") +DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "make_intrusive(%s, TYPE_DOUBLE)", "make_intrusive(%s, TYPE_DOUBLE)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "IntrusivePtr", "%s->AsFile()", "make_intrusive(%s)", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "val_mgr->Int(%s)", "val_mgr->Int(%s)") +DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "make_intrusive(%s, Seconds)", "make_intrusive(%s, Seconds)") +DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "IntrusivePtr", "%s->AsPattern()", "make_intrusive(%s)", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "IntrusivePtr", "%s->AsPortVal()", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "IntrusivePtr", "%s->AsStringVal()", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "IntrusivePtr", "%s->AsSubNetVal()", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "make_intrusive(%s, TYPE_TIME)", "make_intrusive(%s, TYPE_TIME)") +DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "IntrusivePtr", "%s", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") From 719b8082cad0ab5679ab9ddba74245bf863c6e75 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 8 May 2020 17:42:37 -0700 Subject: [PATCH 173/343] bifcl: Update deprecated use of internal_type() --- tools/bifcl/builtin-func.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index c17a98359b..0a8998393f 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -387,7 +387,7 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\t%s = internal_type(\"%s\")->As%sType();\n", + "\t%s = zeek::lookup_type(\"%s\")->As%sType();\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str(), type_name.c_str()); @@ -447,7 +447,7 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list fprintf(fp_netvar_def, "%s EnumType * %s; %s\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\t%s = internal_type(\"%s\")->AsEnumType();\n", + "\t%s = zeek::lookup_type(\"%s\")->AsEnumType();\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); record_bif_item(decl.bro_fullname.c_str(), "TYPE"); From 53d6f6665e1042995552333f40414b4bc4271855 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 8 May 2020 18:40:19 -0700 Subject: [PATCH 174/343] bifcl: Replace deprecated use of internal_const_val() --- tools/bifcl/builtin-func.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 0a8998393f..5ebf12c547 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -502,7 +502,7 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' decl.c_namespace_start.c_str(), builtin_types[typeidx].c_type, decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_init, "\t%s = internal_const_val(\"%s\")%s;\n", + fprintf(fp_netvar_init, "\t%s = zeek::lookup_const(\"%s\").get()%s;\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str(), accessor); From 59e86c6ea0bf1c7886d5a5cbfdb476b57a564c11 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 12 May 2020 18:08:23 -0700 Subject: [PATCH 175/343] bifcl: Renaming/scoping of lookup functions --- tools/bifcl/builtin-func.y | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 5ebf12c547..f85838774c 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -387,7 +387,7 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\t%s = zeek::lookup_type(\"%s\")->As%sType();\n", + "\t%s = zeek::id::lookup_type(\"%s\")->As%sType();\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str(), type_name.c_str()); @@ -447,7 +447,7 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list fprintf(fp_netvar_def, "%s EnumType * %s; %s\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\t%s = zeek::lookup_type(\"%s\")->AsEnumType();\n", + "\t%s = zeek::id::lookup_type(\"%s\")->AsEnumType();\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); record_bif_item(decl.bro_fullname.c_str(), "TYPE"); @@ -502,7 +502,7 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' decl.c_namespace_start.c_str(), builtin_types[typeidx].c_type, decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_init, "\t%s = zeek::lookup_const(\"%s\").get()%s;\n", + fprintf(fp_netvar_init, "\t%s = zeek::id::lookup_const(\"%s\").get()%s;\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str(), accessor); From 36dec9dbb5e7fe732090d12f1a694f3327e29edb Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 13 May 2020 18:22:38 -0700 Subject: [PATCH 176/343] bifcl: Change internal_handler() usage --- tools/bifcl/builtin-func.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index f85838774c..8731358309 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -610,7 +610,7 @@ head_1: TOK_ID opt_ws arg_begin decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\t%s = internal_handler(\"%s\");\n", + "\t%s = event_registry->Register(\"%s\");\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); record_bif_item(decl.bro_fullname.c_str(), "EVENT"); From 620680d878e4304c570a354e9b6516df62ea57fc Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 13 May 2020 20:20:29 -0700 Subject: [PATCH 177/343] bifcl: Deprecate all BroType* in BifType:: namespace Replaced with equivalently named IntrusivePtr in zeek::BifType:: --- tools/bifcl/builtin-func.l | 5 +++++ tools/bifcl/builtin-func.y | 34 ++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 9387bebd0d..502a383a23 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -386,9 +386,14 @@ int main(int argc, char* argv[]) else init_alternative_mode(); + fprintf(fp_netvar_init, "#pragma GCC diagnostic push\n"); + fprintf(fp_netvar_init, "#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n\n"); + yy_switch_to_buffer(yy_create_buffer(fp_input, YY_BUF_SIZE)); yyparse(); + fprintf(fp_netvar_init, "\n\n#pragma GCC diagnostic pop\n"); + if ( alternative_mode ) finish_alternative_mode(); diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 8731358309..44e26ca8cf 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -380,16 +380,28 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' { set_decl_name($3); - fprintf(fp_netvar_h, "%s extern %sType * %s; %s\n", + fprintf(fp_netvar_h, "namespace zeek { %s extern IntrusivePtr<%sType> %s; %s}\n", + decl.c_namespace_start.c_str(), type_name.c_str(), + decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern %sType * %s; %s\n", + decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), type_name.c_str(), + decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + + + fprintf(fp_netvar_def, "namespace zeek { %s IntrusivePtr<%sType> %s; %s}\n", decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_def, "%s %sType * %s; %s\n", decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_init, - "\t%s = zeek::id::lookup_type(\"%s\")->As%sType();\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str(), - type_name.c_str()); + "\tzeek::%s = zeek::id::lookup_type<%sType>(\"%s\");\n", + decl.c_fullname.c_str(), type_name.c_str(), + decl.bro_fullname.c_str()); + fprintf(fp_netvar_init, + "\t%s = zeek::%s.get();\n", + decl.c_fullname.c_str(), decl.c_fullname.c_str()); record_bif_item(decl.bro_fullname.c_str(), "TYPE"); } @@ -442,13 +454,23 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list fprintf(fp_netvar_h, "}; }\n"); // Now generate the netvar's. - fprintf(fp_netvar_h, "%s extern EnumType * %s; %s\n", + fprintf(fp_netvar_h, "namespace zeek { %s extern IntrusivePtr %s; %s}\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern EnumType * %s; %s\n", + decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), + decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + + fprintf(fp_netvar_def, "namespace zeek { %s IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_def, "%s EnumType * %s; %s\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_init, - "\t%s = zeek::id::lookup_type(\"%s\")->AsEnumType();\n", + "\tzeek::%s = zeek::id::lookup_type(\"%s\");\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + fprintf(fp_netvar_init, + "\t%s = zeek::%s.get();\n", + decl.c_fullname.c_str(), decl.c_fullname.c_str()); record_bif_item(decl.bro_fullname.c_str(), "TYPE"); } From d72884064a44b89bd481bcbe2b635b41ee7bb645 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 13 May 2020 23:37:48 -0700 Subject: [PATCH 178/343] bifcl: Deprecate names in BifConst, replace with zeek::BifConst Some Val* types are also replaced with IntrusivePtr --- tools/bifcl/bif_arg.cc | 6 ++++-- tools/bifcl/builtin-func.y | 31 +++++++++++++++++++++++------ tools/bifcl/include/bif_arg.h | 2 +- tools/bifcl/include/bif_type.def | 34 ++++++++++++++++---------------- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index cc9fc27cac..d87c5bb43e 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -13,11 +13,13 @@ static struct { const char* c_type; const char* c_type_smart; const char* accessor; + const char* accessor_smart; + const char* cast_smart; const char* constructor; const char* ctor_smart; } builtin_func_arg_type[] = { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart) \ - {bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart}, +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) \ + {bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE }; diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 44e26ca8cf..27fd8aea8a 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -165,11 +165,13 @@ static struct { const char* c_type; const char* c_type_smart; const char* accessor; + const char* accessor_smart; + const char* cast_smart; const char* constructor; const char* ctor_smatr; } builtin_types[] = { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart) \ - {bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart}, +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) \ + {bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE }; @@ -512,21 +514,38 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' set_decl_name($3); int typeidx = get_type_index($7); char accessor[1024]; + char accessor_smart[1024]; snprintf(accessor, sizeof(accessor), builtin_types[typeidx].accessor, ""); + snprintf(accessor_smart, sizeof(accessor_smart), builtin_types[typeidx].accessor_smart, ""); - fprintf(fp_netvar_h, "%s extern %s %s; %s\n", + fprintf(fp_netvar_h, "namespace zeek { %s extern %s %s; %s }\n", decl.c_namespace_start.c_str(), + builtin_types[typeidx].c_type_smart, decl.bare_name.c_str(), + decl.c_namespace_end.c_str()); + fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern %s %s; %s\n", + decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), builtin_types[typeidx].c_type, decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + + fprintf(fp_netvar_def, "namespace zeek { %s %s %s; %s }\n", + decl.c_namespace_start.c_str(), + builtin_types[typeidx].c_type_smart, decl.bare_name.c_str(), + decl.c_namespace_end.c_str()); fprintf(fp_netvar_def, "%s %s %s; %s\n", decl.c_namespace_start.c_str(), builtin_types[typeidx].c_type, decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_init, "\t%s = zeek::id::lookup_const(\"%s\").get()%s;\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str(), - accessor); + + fprintf(fp_netvar_init, "\t{\n"); + fprintf(fp_netvar_init, "\tconst auto& v = zeek::id::lookup_const%s(\"%s\");\n", + builtin_types[typeidx].cast_smart, decl.bro_fullname.c_str()); + fprintf(fp_netvar_init, "\tzeek::%s = v%s;\n", + decl.c_fullname.c_str(), accessor_smart); + fprintf(fp_netvar_init, "\t%s = v.get()%s;\n", + decl.c_fullname.c_str(), accessor); + fprintf(fp_netvar_init, "\t}\n"); record_bif_item(decl.bro_fullname.c_str(), "CONSTANT"); } diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index c1dd5064b6..bd8b9c58d2 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -3,7 +3,7 @@ #include enum builtin_func_arg_type { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart) \ +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) \ id, #include "bif_type.def" #undef DEFINE_BIF_TYPE diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 974e8c6db5..86c8673f77 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -1,17 +1,17 @@ -// (id, bif_type, bro_type, c_type, c_type_smart, accessor, constructor, ctor_smart) -DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "IntrusivePtr", "%s->AsAddrVal()", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "IntrusivePtr", "%s", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "val_mgr->Bool(%s)", "val_mgr->Bool(%s)") -DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "IntrusivePtr", "%s", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->ConnVal()", "%s->ConnVal()") -DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "val_mgr->Count(%s)", "val_mgr->Count(%s)") -DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "make_intrusive(%s, TYPE_DOUBLE)", "make_intrusive(%s, TYPE_DOUBLE)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "IntrusivePtr", "%s->AsFile()", "make_intrusive(%s)", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "val_mgr->Int(%s)", "val_mgr->Int(%s)") -DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "make_intrusive(%s, Seconds)", "make_intrusive(%s, Seconds)") -DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "IntrusivePtr", "%s->AsPattern()", "make_intrusive(%s)", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "IntrusivePtr", "%s->AsPortVal()", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "IntrusivePtr", "%s->AsStringVal()", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "IntrusivePtr", "%s->AsSubNetVal()", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "make_intrusive(%s, TYPE_TIME)", "make_intrusive(%s, TYPE_TIME)") -DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "IntrusivePtr", "%s", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +// (id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) +DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "IntrusivePtr", "%s->AsAddrVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "IntrusivePtr", "%s", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "val_mgr->Bool(%s)", "val_mgr->Bool(%s)") +DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "IntrusivePtr", "%s", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") +DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "val_mgr->Count(%s)", "val_mgr->Count(%s)") +DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "make_intrusive(%s, TYPE_DOUBLE)", "make_intrusive(%s, TYPE_DOUBLE)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "IntrusivePtr", "%s->AsFile()", "%s", "", "make_intrusive(%s)", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "val_mgr->Int(%s)", "val_mgr->Int(%s)") +DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "make_intrusive(%s, Seconds)", "make_intrusive(%s, Seconds)") +DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "IntrusivePtr", "%s->AsPattern()", "%s", "", "make_intrusive(%s)", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "IntrusivePtr", "%s->AsPortVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "IntrusivePtr", "%s->AsStringVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "IntrusivePtr", "%s->AsSubNetVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "%s->AsTime()", "", "make_intrusive(%s, TYPE_TIME)", "make_intrusive(%s, TYPE_TIME)") +DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "IntrusivePtr", "%s", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") From 4c2fb01981cc87bf8beb902f3c150e9e85c39fd0 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 14 May 2020 14:16:16 -0700 Subject: [PATCH 179/343] bifcl: Deprecate BifFunc:: declarations, replace with zeek::BifFunc:: Also changes name of function slightly, example: bro_fmt -> fmt_bif. --- tools/bifcl/builtin-func.y | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 27fd8aea8a..0dc2cbd2fc 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -145,9 +145,6 @@ void set_decl_name(const char *name) } decl.bro_fullname += decl.bare_name; - if ( definition_type == FUNC_DEF ) - decl.bare_name = string("bro_") + decl.bare_name; - decl.c_fullname += decl.bare_name; decl.bro_name += name; decl.generate_c_fullname += decl.generate_bare_name; @@ -624,15 +621,30 @@ head_1: TOK_ID opt_ws arg_begin if ( definition_type == FUNC_DEF ) { fprintf(fp_func_init, - "\t(void) new BuiltinFunc(%s, \"%s\", 0);\n", + "\t(void) new BuiltinFunc(zeek::%s_bif, \"%s\", 0);\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + // This is the "canonical" version, with argument type and order + // mostly for historical reasons. There's also no "bro_" prefix + // in the function name itself, but does have a "_bif" suffix + // to potentially help differentiate from other functions + // (e.g. ones at global scope that may be used to implement + // the BIF itself). fprintf(fp_func_h, - "%sextern BifReturnVal %s(Frame* frame, const zeek::Args*);%s\n", + "namespace zeek { %sextern BifReturnVal %s_bif(Frame* frame, const zeek::Args*);%s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + // This is the deprecated, legacy, version of the BIF that + // forwards to the "canonical" version. It also does have + // a "bro_" prefix in the name itself, but no "_bif" suffix. + fprintf(fp_func_h, + "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(Frame* frame, const zeek::Args* args)", + decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), decl.bare_name.c_str()); + fprintf(fp_func_h, " { return zeek::%s_bif(frame, args); } %s\n", + decl.c_fullname.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_func_def, - "BifReturnVal %s(Frame* frame, const zeek::Args* %s)", + "BifReturnVal zeek::%s_bif(Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); From 2ef1aacd36b37d972c3f0c5e484100a13e339b6a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 14 May 2020 14:45:14 -0700 Subject: [PATCH 180/343] bifcl: Use zeek::BifEvent:: for enqueue_ functions instead of BifEvent:: The old BifEvent::generate_ functions were already deprecated --- tools/bifcl/builtin-func.y | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 0dc2cbd2fc..53c8e7a537 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -124,7 +124,7 @@ void set_decl_name(const char *name) decl.generate_c_namespace_start = "namespace BifEvent { "; decl.generate_c_namespace_end = " } "; decl.generate_c_fullname = "BifEvent::"; - decl.enqueue_c_fullname = "BifEvent::"; + decl.enqueue_c_fullname = "zeek::BifEvent::"; break; default: @@ -220,12 +220,12 @@ static void print_event_c_prototype_args(FILE* fp, bool smart) static void print_event_c_prototype_header(FILE* fp, bool smart) { if ( smart ) - fprintf(fp, "%s void %s(analyzer::Analyzer* analyzer%s", + fprintf(fp, "namespace zeek { %s void %s(analyzer::Analyzer* analyzer%s", decl.generate_c_namespace_start.c_str(), decl.enqueue_c_barename.c_str(), args.size() ? ", " : "" ); else - fprintf(fp, "%s [[deprecated(\"Remove in 4.1. Use %s instead.\")]] void %s(analyzer::Analyzer* analyzer%s", + fprintf(fp, "%s [[deprecated(\"Remove in 4.1. Use %s.\")]] void %s(analyzer::Analyzer* analyzer%s", decl.generate_c_namespace_start.c_str(), decl.enqueue_c_fullname.c_str(), decl.generate_bare_name.c_str(), @@ -234,7 +234,7 @@ static void print_event_c_prototype_header(FILE* fp, bool smart) print_event_c_prototype_args(fp, smart); fprintf(fp, ")"); - fprintf(fp, "; %s\n", decl.generate_c_namespace_end.c_str()); + fprintf(fp, "; %s%s\n", decl.generate_c_namespace_end.c_str(), smart ? " }" : ""); } static void print_event_c_prototype_impl(FILE* fp, bool smart) From 23b4af393f247db7841110ea6b8613a333d182d2 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 14 May 2020 17:56:27 -0700 Subject: [PATCH 181/343] bifcl: Switch zeek::id::lookup to zeek::id::find --- tools/bifcl/builtin-func.y | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 53c8e7a537..22a3e46a3f 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -395,7 +395,7 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\tzeek::%s = zeek::id::lookup_type<%sType>(\"%s\");\n", + "\tzeek::%s = zeek::id::find_type<%sType>(\"%s\");\n", decl.c_fullname.c_str(), type_name.c_str(), decl.bro_fullname.c_str()); fprintf(fp_netvar_init, @@ -465,7 +465,7 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\tzeek::%s = zeek::id::lookup_type(\"%s\");\n", + "\tzeek::%s = zeek::id::find_type(\"%s\");\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); fprintf(fp_netvar_init, "\t%s = zeek::%s.get();\n", @@ -536,7 +536,7 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, "\t{\n"); - fprintf(fp_netvar_init, "\tconst auto& v = zeek::id::lookup_const%s(\"%s\");\n", + fprintf(fp_netvar_init, "\tconst auto& v = zeek::id::find_const%s(\"%s\");\n", builtin_types[typeidx].cast_smart, decl.bro_fullname.c_str()); fprintf(fp_netvar_init, "\tzeek::%s = v%s;\n", decl.c_fullname.c_str(), accessor_smart); From 99fa631ddd7feaaa6f717774c185571d971f1556 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 15 May 2020 17:09:44 -0700 Subject: [PATCH 182/343] bifcl: Change constructor for BroFile args --- tools/bifcl/include/bif_type.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 86c8673f77..ebc025cfb7 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -6,7 +6,7 @@ DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "Int DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "val_mgr->Count(%s)", "val_mgr->Count(%s)") DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "make_intrusive(%s, TYPE_DOUBLE)", "make_intrusive(%s, TYPE_DOUBLE)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "IntrusivePtr", "%s->AsFile()", "%s", "", "make_intrusive(%s)", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "IntrusivePtr", "%s->AsFile()", "%s", "", "make_intrusive(IntrusivePtr{AdoptRef{}, %s})", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "val_mgr->Int(%s)", "val_mgr->Int(%s)") DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "make_intrusive(%s, Seconds)", "make_intrusive(%s, Seconds)") DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "IntrusivePtr", "%s->AsPattern()", "%s", "", "make_intrusive(%s)", "std::move(%s)") From 4686ba3824752d5dc0e7d129bb43b54c22539d8d Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 22 May 2020 14:38:27 -0700 Subject: [PATCH 183/343] bifcl: Include Func.h in files during build --- tools/bifcl/builtin-func.l | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 502a383a23..e6db494d05 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -242,6 +242,7 @@ void init_alternative_mode() fprintf(fp_func_def, "\n"); fprintf(fp_func_def, "#include \"%s.h\"\n", input_filename); + fprintf(fp_func_def, "#include \"Func.h\"\n"); fprintf(fp_func_def, "\n"); static char name[1024]; @@ -265,6 +266,7 @@ void init_alternative_mode() fprintf(fp_func_init, "#include \n"); fprintf(fp_func_init, "#include \n"); fprintf(fp_func_init, "#include \"plugin/Plugin.h\"\n"); + fprintf(fp_func_init, "#include \"Func.h\"\n"); fprintf(fp_func_init, "#include \"%s.h\"\n", input_filename); fprintf(fp_func_init, "\n"); fprintf(fp_func_init, "namespace plugin { namespace %s {\n", plugin_canon); @@ -448,4 +450,3 @@ void err_exit(void) remove_file("netvar_init"); exit(1); } - From 011f66cb2d9c1e01104193be4e4a318904eb47ca Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 2 Jun 2020 18:18:40 -0700 Subject: [PATCH 184/343] bifcl: Use new TimeVal/DoubleVal subclass ctors --- tools/bifcl/include/bif_type.def | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index ebc025cfb7..388b6195a8 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -5,7 +5,7 @@ DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "IntrusivePtr", "%s", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "val_mgr->Count(%s)", "val_mgr->Count(%s)") -DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "make_intrusive(%s, TYPE_DOUBLE)", "make_intrusive(%s, TYPE_DOUBLE)") +DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "make_intrusive(%s)", "make_intrusive(%s)") DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "IntrusivePtr", "%s->AsFile()", "%s", "", "make_intrusive(IntrusivePtr{AdoptRef{}, %s})", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "val_mgr->Int(%s)", "val_mgr->Int(%s)") DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "make_intrusive(%s, Seconds)", "make_intrusive(%s, Seconds)") @@ -13,5 +13,5 @@ DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "Int DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "IntrusivePtr", "%s->AsPortVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "IntrusivePtr", "%s->AsStringVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "IntrusivePtr", "%s->AsSubNetVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "%s->AsTime()", "", "make_intrusive(%s, TYPE_TIME)", "make_intrusive(%s, TYPE_TIME)") +DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "%s->AsTime()", "", "make_intrusive(%s)", "make_intrusive(%s)") DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "IntrusivePtr", "%s", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") From 9f317f02a47639c532b4eda5574d0363c111df63 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 14 May 2020 16:13:07 -0700 Subject: [PATCH 185/343] bifcl: Update namespace for __RegisterBif function --- tools/bifcl/builtin-func.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index e6db494d05..f6a246a082 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -278,7 +278,7 @@ void init_alternative_mode() fprintf(fp_func_register, "\n"); fprintf(fp_func_register, "namespace plugin { namespace %s {\n", plugin_canon); fprintf(fp_func_register, "void __bif_%s_init(plugin::Plugin* plugin);\n", name); - fprintf(fp_func_register, "::plugin::__RegisterBif __register_bifs_%s_%s(\"%s\", __bif_%s_init);\n", plugin_canon, name, plugin, name); + fprintf(fp_func_register, "zeek::detail::plugin::__RegisterBif __register_bifs_%s_%s(\"%s\", __bif_%s_init);\n", plugin_canon, name, plugin, name); fprintf(fp_func_register, "} }\n"); } } From 6813ddaaa9cf4e0463d895fa806eb9cc9812c6d1 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 14 May 2020 17:17:21 -0700 Subject: [PATCH 186/343] bifcl: Update namespace for plugin::Plugin and plugin::BifItem classes --- tools/bifcl/builtin-func.l | 4 ++-- tools/bifcl/builtin-func.y | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index f6a246a082..e08c1b1505 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -271,13 +271,13 @@ void init_alternative_mode() fprintf(fp_func_init, "\n"); fprintf(fp_func_init, "namespace plugin { namespace %s {\n", plugin_canon); fprintf(fp_func_init, "\n"); - fprintf(fp_func_init, "void __bif_%s_init(plugin::Plugin* plugin)\n", name); + fprintf(fp_func_init, "void __bif_%s_init(zeek::plugin::Plugin* plugin)\n", name); fprintf(fp_func_init, "\t{\n"); fprintf(fp_func_register, "#include \"plugin/Manager.h\"\n"); fprintf(fp_func_register, "\n"); fprintf(fp_func_register, "namespace plugin { namespace %s {\n", plugin_canon); - fprintf(fp_func_register, "void __bif_%s_init(plugin::Plugin* plugin);\n", name); + fprintf(fp_func_register, "void __bif_%s_init(zeek::plugin::Plugin* plugin);\n", name); fprintf(fp_func_register, "zeek::detail::plugin::__RegisterBif __register_bifs_%s_%s(\"%s\", __bif_%s_init);\n", plugin_canon, name, plugin, name); fprintf(fp_func_register, "} }\n"); } diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 22a3e46a3f..f9040571c9 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -304,7 +304,7 @@ void record_bif_item(const char* id, const char* type) if ( ! plugin ) return; - fprintf(fp_func_init, "\tplugin->AddBifItem(\"%s\", plugin::BifItem::%s);\n", id, type); + fprintf(fp_func_init, "\tplugin->AddBifItem(\"%s\", zeek::plugin::BifItem::%s);\n", id, type); } %} From 73fb715657f55e15244cf9ee8f8926dd2aa64463 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 9 Jun 2020 17:05:09 -0700 Subject: [PATCH 187/343] bifcl: Update namespace for *Type classes --- tools/bifcl/builtin-func.y | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index f9040571c9..c6459d543e 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -379,23 +379,23 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' { set_decl_name($3); - fprintf(fp_netvar_h, "namespace zeek { %s extern IntrusivePtr<%sType> %s; %s}\n", + fprintf(fp_netvar_h, "namespace zeek { %s extern IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern %sType * %s; %s\n", + fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern zeek::%sType * %s; %s\n", decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "namespace zeek { %s IntrusivePtr<%sType> %s; %s}\n", + fprintf(fp_netvar_def, "namespace zeek { %s IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s %sType * %s; %s\n", + fprintf(fp_netvar_def, "%s zeek::%sType * %s; %s\n", decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\tzeek::%s = zeek::id::find_type<%sType>(\"%s\");\n", + "\tzeek::%s = zeek::id::find_type(\"%s\");\n", decl.c_fullname.c_str(), type_name.c_str(), decl.bro_fullname.c_str()); fprintf(fp_netvar_init, @@ -453,19 +453,19 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list fprintf(fp_netvar_h, "}; }\n"); // Now generate the netvar's. - fprintf(fp_netvar_h, "namespace zeek { %s extern IntrusivePtr %s; %s}\n", + fprintf(fp_netvar_h, "namespace zeek { %s extern IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern EnumType * %s; %s\n", + fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern zeek::EnumType * %s; %s\n", decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "namespace zeek { %s IntrusivePtr %s; %s}\n", + fprintf(fp_netvar_def, "namespace zeek { %s IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s EnumType * %s; %s\n", + fprintf(fp_netvar_def, "%s zeek::EnumType * %s; %s\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\tzeek::%s = zeek::id::find_type(\"%s\");\n", + "\tzeek::%s = zeek::id::find_type(\"%s\");\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); fprintf(fp_netvar_init, "\t%s = zeek::%s.get();\n", From 79bbe9a7bfa31454d188663d94fb3002cf19450c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sat, 13 Jun 2020 07:54:32 -0700 Subject: [PATCH 188/343] bifcl: Move IntrusivePtr to the zeek namespace --- tools/bifcl/builtin-func.y | 8 ++++---- tools/bifcl/include/bif_type.def | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index c6459d543e..d28d2cdcd9 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -379,7 +379,7 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' { set_decl_name($3); - fprintf(fp_netvar_h, "namespace zeek { %s extern IntrusivePtr %s; %s}\n", + fprintf(fp_netvar_h, "namespace zeek { %s extern zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern zeek::%sType * %s; %s\n", @@ -387,7 +387,7 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "namespace zeek { %s IntrusivePtr %s; %s}\n", + fprintf(fp_netvar_def, "namespace zeek { %s zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_def, "%s zeek::%sType * %s; %s\n", @@ -453,13 +453,13 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list fprintf(fp_netvar_h, "}; }\n"); // Now generate the netvar's. - fprintf(fp_netvar_h, "namespace zeek { %s extern IntrusivePtr %s; %s}\n", + fprintf(fp_netvar_h, "namespace zeek { %s extern zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern zeek::EnumType * %s; %s\n", decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "namespace zeek { %s IntrusivePtr %s; %s}\n", + fprintf(fp_netvar_def, "namespace zeek { %s zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_def, "%s zeek::EnumType * %s; %s\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 388b6195a8..6b3387c41f 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -1,17 +1,17 @@ // (id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) -DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "IntrusivePtr", "%s->AsAddrVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "IntrusivePtr", "%s", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "zeek::IntrusivePtr", "%s->AsAddrVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "val_mgr->Bool(%s)", "val_mgr->Bool(%s)") -DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "IntrusivePtr", "%s", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "val_mgr->Count(%s)", "val_mgr->Count(%s)") -DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "make_intrusive(%s)", "make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "IntrusivePtr", "%s->AsFile()", "%s", "", "make_intrusive(IntrusivePtr{AdoptRef{}, %s})", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "val_mgr->Int(%s)", "val_mgr->Int(%s)") -DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "make_intrusive(%s, Seconds)", "make_intrusive(%s, Seconds)") -DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "IntrusivePtr", "%s->AsPattern()", "%s", "", "make_intrusive(%s)", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "IntrusivePtr", "%s->AsPortVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "IntrusivePtr", "%s->AsStringVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "IntrusivePtr", "%s->AsSubNetVal()", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "%s->AsTime()", "", "make_intrusive(%s)", "make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "IntrusivePtr", "%s", "%s", "", "IntrusivePtr{AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") +DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "zeek::IntrusivePtr", "%s->AsPortVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "zeek::IntrusivePtr", "%s->AsStringVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "zeek::IntrusivePtr", "%s->AsSubNetVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "%s->AsTime()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") +DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") From 0597535149b031158932fca965890a7b795d92e8 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 15 Jun 2020 19:05:29 -0700 Subject: [PATCH 189/343] bifcl: Move all Val classes to the zeek namespaces --- tools/bifcl/builtin-func.y | 6 +++--- tools/bifcl/include/bif_type.def | 34 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index d28d2cdcd9..b9b41ff230 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -631,20 +631,20 @@ head_1: TOK_ID opt_ws arg_begin // (e.g. ones at global scope that may be used to implement // the BIF itself). fprintf(fp_func_h, - "namespace zeek { %sextern BifReturnVal %s_bif(Frame* frame, const zeek::Args*);%s }\n", + "namespace zeek { %sextern BifReturnVal %s_bif(::Frame* frame, const zeek::Args*);%s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); // This is the deprecated, legacy, version of the BIF that // forwards to the "canonical" version. It also does have // a "bro_" prefix in the name itself, but no "_bif" suffix. fprintf(fp_func_h, - "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(Frame* frame, const zeek::Args* args)", + "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(::Frame* frame, const zeek::Args* args)", decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), decl.bare_name.c_str()); fprintf(fp_func_h, " { return zeek::%s_bif(frame, args); } %s\n", decl.c_fullname.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, - "BifReturnVal zeek::%s_bif(Frame* frame, const zeek::Args* %s)", + "BifReturnVal zeek::%s_bif(::Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 6b3387c41f..ab168f3d34 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -1,17 +1,17 @@ -// (id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) -DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "zeek::IntrusivePtr", "%s->AsAddrVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "val_mgr->Bool(%s)", "val_mgr->Bool(%s)") -DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") -DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "val_mgr->Count(%s)", "val_mgr->Count(%s)") -DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "val_mgr->Int(%s)", "val_mgr->Int(%s)") -DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") -DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "PortVal*", "zeek::IntrusivePtr", "%s->AsPortVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "StringVal*", "zeek::IntrusivePtr", "%s->AsStringVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "SubNetVal*", "zeek::IntrusivePtr", "%s->AsSubNetVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "%s->AsTime()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +// (id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) +DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "zeek::AddrVal*", "zeek::IntrusivePtr", "%s->AsAddrVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "val_mgr->Bool(%s)", "val_mgr->Bool(%s)") +DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") +DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "val_mgr->Count(%s)", "val_mgr->Count(%s)") +DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "val_mgr->Int(%s)", "val_mgr->Int(%s)") +DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") +DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "zeek::PortVal*", "zeek::IntrusivePtr", "%s->AsPortVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "zeek::StringVal*", "zeek::IntrusivePtr", "%s->AsStringVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "zeek::SubNetVal*", "zeek::IntrusivePtr", "%s->AsSubNetVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "%s->AsTime()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") +DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") From 13dac125214d3153d6bc0878ccba83380e4be9a8 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 16 Jun 2020 10:24:43 -0700 Subject: [PATCH 190/343] bifcl: Move Frame to the zeek::detail namespace --- tools/bifcl/builtin-func.y | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index b9b41ff230..fd4bd4198c 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -631,20 +631,20 @@ head_1: TOK_ID opt_ws arg_begin // (e.g. ones at global scope that may be used to implement // the BIF itself). fprintf(fp_func_h, - "namespace zeek { %sextern BifReturnVal %s_bif(::Frame* frame, const zeek::Args*);%s }\n", + "namespace zeek { %sextern BifReturnVal %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); // This is the deprecated, legacy, version of the BIF that // forwards to the "canonical" version. It also does have // a "bro_" prefix in the name itself, but no "_bif" suffix. fprintf(fp_func_h, - "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(::Frame* frame, const zeek::Args* args)", + "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(zeek::detail::Frame* frame, const zeek::Args* args)", decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), decl.bare_name.c_str()); fprintf(fp_func_h, " { return zeek::%s_bif(frame, args); } %s\n", decl.c_fullname.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, - "BifReturnVal zeek::%s_bif(::Frame* frame, const zeek::Args* %s)", + "BifReturnVal zeek::%s_bif(zeek::detail::Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); From ff7b41ff12aaa87a8d727462a8c3a0c9634b90a1 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 22 Jun 2020 15:46:52 -0700 Subject: [PATCH 191/343] bifcl: Move BuiltinFunc to zeek namespace --- tools/bifcl/builtin-func.y | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index fd4bd4198c..5fa221e9ce 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -621,7 +621,7 @@ head_1: TOK_ID opt_ws arg_begin if ( definition_type == FUNC_DEF ) { fprintf(fp_func_init, - "\t(void) new BuiltinFunc(zeek::%s_bif, \"%s\", 0);\n", + "\t(void) new zeek::detail::BuiltinFunc(zeek::%s_bif, \"%s\", 0);\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); // This is the "canonical" version, with argument type and order @@ -631,20 +631,20 @@ head_1: TOK_ID opt_ws arg_begin // (e.g. ones at global scope that may be used to implement // the BIF itself). fprintf(fp_func_h, - "namespace zeek { %sextern BifReturnVal %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", + "namespace zeek { %sextern BifReturnVal %s_bif(::zeek::detail::Frame* frame, const ::zeek::Args*);%s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); // This is the deprecated, legacy, version of the BIF that // forwards to the "canonical" version. It also does have // a "bro_" prefix in the name itself, but no "_bif" suffix. fprintf(fp_func_h, - "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(zeek::detail::Frame* frame, const zeek::Args* args)", + "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(::zeek::detail::Frame* frame, const ::zeek::Args* args)", decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), decl.bare_name.c_str()); fprintf(fp_func_h, " { return zeek::%s_bif(frame, args); } %s\n", decl.c_fullname.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, - "BifReturnVal zeek::%s_bif(zeek::detail::Frame* frame, const zeek::Args* %s)", + "BifReturnVal zeek::%s_bif(::zeek::detail::Frame* frame, const ::zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); From 6204542b5a60ea2957f29f002c48bc793befa7ac Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 2 Jul 2020 11:07:02 -0700 Subject: [PATCH 192/343] bifcl: Review cleanup --- tools/bifcl/builtin-func.y | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 5fa221e9ce..c120f7992b 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -631,20 +631,20 @@ head_1: TOK_ID opt_ws arg_begin // (e.g. ones at global scope that may be used to implement // the BIF itself). fprintf(fp_func_h, - "namespace zeek { %sextern BifReturnVal %s_bif(::zeek::detail::Frame* frame, const ::zeek::Args*);%s }\n", + "namespace zeek { %sextern BifReturnVal %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); // This is the deprecated, legacy, version of the BIF that // forwards to the "canonical" version. It also does have // a "bro_" prefix in the name itself, but no "_bif" suffix. fprintf(fp_func_h, - "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(::zeek::detail::Frame* frame, const ::zeek::Args* args)", + "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(zeek::detail::Frame* frame, const zeek::Args* args)", decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), decl.bare_name.c_str()); fprintf(fp_func_h, " { return zeek::%s_bif(frame, args); } %s\n", decl.c_fullname.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, - "BifReturnVal zeek::%s_bif(::zeek::detail::Frame* frame, const ::zeek::Args* %s)", + "BifReturnVal zeek::%s_bif(zeek::detail::Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); From b203311bad02de7dd24917eea250536e75cd5316 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 2 Jul 2020 16:14:17 -0700 Subject: [PATCH 193/343] bifcl: Add zeek:: namespace to val_mgr usage --- tools/bifcl/include/bif_type.def | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index ab168f3d34..6addf461ab 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -1,13 +1,13 @@ // (id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "zeek::AddrVal*", "zeek::IntrusivePtr", "%s->AsAddrVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "val_mgr->Bool(%s)", "val_mgr->Bool(%s)") +DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "zeek::val_mgr->Bool(%s)", "zeek::val_mgr->Bool(%s)") DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") -DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "val_mgr->Count(%s)", "val_mgr->Count(%s)") +DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "zeek::val_mgr->Count(%s)", "zeek::val_mgr->Count(%s)") DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "val_mgr->Int(%s)", "val_mgr->Int(%s)") +DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "zeek::val_mgr->Int(%s)", "zeek::val_mgr->Int(%s)") DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "zeek::PortVal*", "zeek::IntrusivePtr", "%s->AsPortVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") From a5a7f08c374d008e7b674d624952f6f75b918f7a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 3 Jul 2020 14:41:08 -0700 Subject: [PATCH 194/343] bifcl: Fix stringop-truncation compiler warning --- tools/bifcl/builtin-func.l | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index e08c1b1505..2382da0f24 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -246,7 +246,7 @@ void init_alternative_mode() fprintf(fp_func_def, "\n"); static char name[1024]; - strncpy(name, input_filename, sizeof(name)); + strncpy(name, input_filename, sizeof(name) - 1); char* dot = strchr(name, '.'); if ( dot ) *dot = '\0'; @@ -254,7 +254,7 @@ void init_alternative_mode() if ( plugin ) { static char plugin_canon[1024]; - strncpy(plugin_canon, plugin, sizeof(plugin_canon)); + strncpy(plugin_canon, plugin, sizeof(plugin_canon) - 1); char* colon = strstr(plugin_canon, "::"); if ( colon ) { From fe0b3dd13f4b1c7f9fa1d20237fee1bac5d9c73f Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 3 Jul 2020 23:55:07 -0700 Subject: [PATCH 195/343] bifcl: Ensure strncpy null-termination --- tools/bifcl/builtin-func.l | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 2382da0f24..841168ca6b 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -247,6 +247,7 @@ void init_alternative_mode() static char name[1024]; strncpy(name, input_filename, sizeof(name) - 1); + name[sizeof(name) - 1] = 0; char* dot = strchr(name, '.'); if ( dot ) *dot = '\0'; @@ -255,6 +256,7 @@ void init_alternative_mode() { static char plugin_canon[1024]; strncpy(plugin_canon, plugin, sizeof(plugin_canon) - 1); + plugin_canon[sizeof(plugin_canon) - 1] = 0; char* colon = strstr(plugin_canon, "::"); if ( colon ) { From caf565c5395396efd95947ae0332d4a87daf8a3c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 22 Jul 2020 15:39:37 -0700 Subject: [PATCH 196/343] bifcl: Move base analyzer classes to zeek namespace --- tools/bifcl/builtin-func.y | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index c120f7992b..3912ec569c 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -220,12 +220,12 @@ static void print_event_c_prototype_args(FILE* fp, bool smart) static void print_event_c_prototype_header(FILE* fp, bool smart) { if ( smart ) - fprintf(fp, "namespace zeek { %s void %s(analyzer::Analyzer* analyzer%s", + fprintf(fp, "namespace zeek { %s void %s(zeek::analyzer::Analyzer* analyzer%s", decl.generate_c_namespace_start.c_str(), decl.enqueue_c_barename.c_str(), args.size() ? ", " : "" ); else - fprintf(fp, "%s [[deprecated(\"Remove in 4.1. Use %s.\")]] void %s(analyzer::Analyzer* analyzer%s", + fprintf(fp, "%s [[deprecated(\"Remove in 4.1. Use %s.\")]] void %s(zeek::analyzer::Analyzer* analyzer%s", decl.generate_c_namespace_start.c_str(), decl.enqueue_c_fullname.c_str(), decl.generate_bare_name.c_str(), @@ -240,11 +240,11 @@ static void print_event_c_prototype_header(FILE* fp, bool smart) static void print_event_c_prototype_impl(FILE* fp, bool smart) { if ( smart ) - fprintf(fp, "void %s(analyzer::Analyzer* analyzer%s", + fprintf(fp, "void %s(zeek::analyzer::Analyzer* analyzer%s", decl.enqueue_c_fullname.c_str(), args.size() ? ", " : "" ); else - fprintf(fp, "void %s(analyzer::Analyzer* analyzer%s", + fprintf(fp, "void %s(zeek::analyzer::Analyzer* analyzer%s", decl.generate_c_fullname.c_str(), args.size() ? ", " : "" ); From 2090786ac513ff2c33b9c491134336fccd12299f Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 20 Jul 2020 11:59:17 -0700 Subject: [PATCH 197/343] bifcl: Move BroFile to zeek namespace, rename to File --- tools/bifcl/include/bif_type.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 6addf461ab..88789c8564 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -6,7 +6,7 @@ DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "zeek::Val*", DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "zeek::val_mgr->Count(%s)", "zeek::val_mgr->Count(%s)") DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "BroFile*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "zeek::File*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "zeek::val_mgr->Int(%s)", "zeek::val_mgr->Int(%s)") DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") From cffecc503336771412aa461591271aa8b63de0b2 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 20 Jul 2020 14:44:57 -0700 Subject: [PATCH 198/343] bifcl: Move event code to zeek namespace, rename mgr to event_mgr --- tools/bifcl/builtin-func.y | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 3912ec569c..688bd810c1 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -266,7 +266,7 @@ static void print_event_c_body(FILE* fp, bool smart) BuiltinFuncArg* connection_arg = 0; - fprintf(fp, "\tmgr.Enqueue(%s, zeek::Args{\n", decl.c_fullname.c_str()); + fprintf(fp, "\tzeek::event_mgr.Enqueue(%s, zeek::Args{\n", decl.c_fullname.c_str()); for ( int i = 0; i < (int) args.size(); ++i ) { @@ -655,12 +655,12 @@ head_1: TOK_ID opt_ws arg_begin { // TODO: add namespace for events here fprintf(fp_netvar_h, - "%sextern EventHandlerPtr %s; %s\n", + "%sextern zeek::EventHandlerPtr %s; %s\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_def, - "%sEventHandlerPtr %s; %s\n", - decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + "%szeek::EventHandlerPtr %s; %s\n", + decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, "\t%s = event_registry->Register(\"%s\");\n", From 5c94ea02c5093b82199c497b5cca7e0a43b9acf9 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 21 Jul 2020 15:35:39 -0700 Subject: [PATCH 199/343] bifcl: Move BifReturnVal to zeek::detail namespace --- tools/bifcl/builtin-func.y | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 688bd810c1..36a47cfcca 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -631,20 +631,20 @@ head_1: TOK_ID opt_ws arg_begin // (e.g. ones at global scope that may be used to implement // the BIF itself). fprintf(fp_func_h, - "namespace zeek { %sextern BifReturnVal %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", + "namespace zeek { %sextern zeek::detail::BifReturnVal %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); // This is the deprecated, legacy, version of the BIF that // forwards to the "canonical" version. It also does have // a "bro_" prefix in the name itself, but no "_bif" suffix. fprintf(fp_func_h, - "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline BifReturnVal bro_%s(zeek::detail::Frame* frame, const zeek::Args* args)", + "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline zeek::detail::BifReturnVal bro_%s(zeek::detail::Frame* frame, const zeek::Args* args)", decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), decl.bare_name.c_str()); fprintf(fp_func_h, " { return zeek::%s_bif(frame, args); } %s\n", decl.c_fullname.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, - "BifReturnVal zeek::%s_bif(zeek::detail::Frame* frame, const zeek::Args* %s)", + "zeek::detail::BifReturnVal zeek::%s_bif(zeek::detail::Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); From c5189596dac4bab65988325ecab1c4db8d9e753b Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 22 Jul 2020 15:03:06 -0700 Subject: [PATCH 200/343] bifcl: Move Connection to zeek namespace --- tools/bifcl/include/bif_type.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 88789c8564..0db924ee27 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -3,7 +3,7 @@ DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "zeek::AddrVal*", DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "zeek::val_mgr->Bool(%s)", "zeek::val_mgr->Bool(%s)") DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "Connection*", "Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") +DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "zeek::Connection*", "zeek::Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "zeek::val_mgr->Count(%s)", "zeek::val_mgr->Count(%s)") DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "zeek::File*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") From 74d21a40e4b01ee5bab01cf9eab0647d617d50a2 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 6 Aug 2020 15:47:32 -0700 Subject: [PATCH 201/343] bifcl: SOURCE_LOCAL is part of the zeek::util::detail namespace now --- tools/bifcl/builtin-func.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 36a47cfcca..0688f16611 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -288,7 +288,7 @@ static void print_event_c_body(FILE* fp, bool smart) } } - fprintf(fp, "\t },\n\t SOURCE_LOCAL, analyzer->GetID()"); + fprintf(fp, "\t },\n\t zeek::util::detail::SOURCE_LOCAL, analyzer->GetID()"); if ( connection_arg ) // Pass the connection to the EventMgr as the "cookie" From 56d981304270bdc00fd25fb798f09720ca46c70e Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 13 Aug 2020 12:23:52 -0700 Subject: [PATCH 202/343] bifcl: Move __RegisterBif from zeek::detail::plugin to zeek::plugin::detail --- tools/bifcl/builtin-func.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 841168ca6b..bd5c2e7f9e 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -280,7 +280,7 @@ void init_alternative_mode() fprintf(fp_func_register, "\n"); fprintf(fp_func_register, "namespace plugin { namespace %s {\n", plugin_canon); fprintf(fp_func_register, "void __bif_%s_init(zeek::plugin::Plugin* plugin);\n", name); - fprintf(fp_func_register, "zeek::detail::plugin::__RegisterBif __register_bifs_%s_%s(\"%s\", __bif_%s_init);\n", plugin_canon, name, plugin, name); + fprintf(fp_func_register, "zeek::plugin::detail::__RegisterBif __register_bifs_%s_%s(\"%s\", __bif_%s_init);\n", plugin_canon, name, plugin, name); fprintf(fp_func_register, "} }\n"); } } From 406f68f7fae09e3d2a638f10a7fbf2a0a28f146c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 25 Aug 2020 16:33:50 -0700 Subject: [PATCH 203/343] bifcl: Rename bro-bif.h to zeek-bif.h --- tools/bifcl/builtin-func.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index bd5c2e7f9e..6ec121f405 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -235,7 +235,7 @@ void init_alternative_mode() fprintf(fp_func_h, "#ifndef BRO_IN_NETVAR\n"); fprintf(fp_func_h, "#ifndef %s\n", guard); fprintf(fp_func_h, "#define %s\n", guard); - fprintf(fp_func_h, "#include \"bro-bif.h\"\n"); + fprintf(fp_func_h, "#include \"zeek-bif.h\"\n"); fprintf(fp_func_h, "#endif\n"); fprintf(fp_func_h, "#endif\n"); fprintf(fp_func_h, "\n"); From fbc98f4dd543eabf990342fc121bd1cb0166a2dc Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 26 Aug 2020 18:04:11 -0700 Subject: [PATCH 204/343] bifcl: Postpone initialization of constants for subdir BIFs --- tools/bifcl/builtin-func.y | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 0688f16611..da63657732 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -16,6 +16,7 @@ using namespace std; extern int line_number; extern char* input_filename; extern char* plugin; +extern int alternative_mode; #define print_line_directive(fp) fprintf(fp, "\n#line %d \"%s\"\n", line_number, input_filename) @@ -535,6 +536,9 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' builtin_types[typeidx].c_type, decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + if ( alternative_mode && ! plugin ) + fprintf(fp_netvar_init, "\tzeek::detail::bif_initializers.emplace_back([]()\n"); + fprintf(fp_netvar_init, "\t{\n"); fprintf(fp_netvar_init, "\tconst auto& v = zeek::id::find_const%s(\"%s\");\n", builtin_types[typeidx].cast_smart, decl.bro_fullname.c_str()); @@ -544,6 +548,9 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' decl.c_fullname.c_str(), accessor); fprintf(fp_netvar_init, "\t}\n"); + if ( alternative_mode && ! plugin ) + fprintf(fp_netvar_init, "\t);\n"); + record_bif_item(decl.bro_fullname.c_str(), "CONSTANT"); } From 23a4b7e7c193fdd68ad7dc40d6e7123f65f5af59 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 1 Dec 2020 21:50:31 -0800 Subject: [PATCH 205/343] bifcl: Update minimum required CMake to 3.5 --- tools/bifcl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index fb3dcac3af..ed06464e8f 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(BifCl C CXX) include(cmake/CommonCMakeConfig.cmake) From 72fa791294986c8949abea95bebb3a9b457b3e9a Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Tue, 10 Nov 2020 13:43:06 -0800 Subject: [PATCH 206/343] bifcl: support for new FileVal class --- tools/bifcl/include/bif_type.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 0db924ee27..92baace92f 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -6,7 +6,7 @@ DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "zeek::Val*", DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "zeek::Connection*", "zeek::Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "zeek::val_mgr->Count(%s)", "zeek::val_mgr->Count(%s)") DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "zeek::File*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "zeek::File*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "zeek::val_mgr->Int(%s)", "zeek::val_mgr->Int(%s)") DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") From 279d5f3fad5ce2dcf3e7d27f6b5206b669e34cd2 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 21 Jan 2021 10:34:26 -0700 Subject: [PATCH 207/343] bifcl: Remove v4.1 deprecation warnings --- tools/bifcl/bif_arg.cc | 15 ++----- tools/bifcl/builtin-func.y | 85 +++++++++-------------------------- tools/bifcl/include/bif_arg.h | 4 +- 3 files changed, 26 insertions(+), 78 deletions(-) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index d87c5bb43e..abeba2872a 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -72,19 +72,12 @@ void BuiltinFuncArg::PrintCDef(FILE* fp, int n) fprintf(fp, ");\n"); } -void BuiltinFuncArg::PrintCArg(FILE* fp, int n, bool smart) +void BuiltinFuncArg::PrintCArg(FILE* fp, int n) { - const char* ctype = smart ? builtin_func_arg_type[type].c_type_smart - : builtin_func_arg_type[type].c_type; - char buf[1024]; - - fprintf(fp, "%s %s", ctype, name); + fprintf(fp, "%s %s", builtin_func_arg_type[type].c_type_smart, name); } -void BuiltinFuncArg::PrintBroValConstructor(FILE* fp, bool smart) +void BuiltinFuncArg::PrintBroValConstructor(FILE* fp) { - if ( smart ) - fprintf(fp, builtin_func_arg_type[type].ctor_smart, name); - else - fprintf(fp, builtin_func_arg_type[type].constructor, name); + fprintf(fp, builtin_func_arg_type[type].ctor_smart, name); } diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index da63657732..0aad969649 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -207,54 +207,41 @@ char* concat(const char* str1, const char* str2) return s; } -static void print_event_c_prototype_args(FILE* fp, bool smart) +static void print_event_c_prototype_args(FILE* fp) { for ( auto i = 0u; i < args.size(); ++i ) { if ( i > 0 ) fprintf(fp, ", "); - args[i]->PrintCArg(fp, i, smart); + args[i]->PrintCArg(fp, i); } } -static void print_event_c_prototype_header(FILE* fp, bool smart) +static void print_event_c_prototype_header(FILE* fp) { - if ( smart ) - fprintf(fp, "namespace zeek { %s void %s(zeek::analyzer::Analyzer* analyzer%s", - decl.generate_c_namespace_start.c_str(), - decl.enqueue_c_barename.c_str(), - args.size() ? ", " : "" ); - else - fprintf(fp, "%s [[deprecated(\"Remove in 4.1. Use %s.\")]] void %s(zeek::analyzer::Analyzer* analyzer%s", - decl.generate_c_namespace_start.c_str(), - decl.enqueue_c_fullname.c_str(), - decl.generate_bare_name.c_str(), - args.size() ? ", " : "" ); + fprintf(fp, "namespace zeek { %s void %s(zeek::analyzer::Analyzer* analyzer%s", + decl.generate_c_namespace_start.c_str(), + decl.enqueue_c_barename.c_str(), + args.size() ? ", " : "" ); - - print_event_c_prototype_args(fp, smart); + print_event_c_prototype_args(fp); fprintf(fp, ")"); - fprintf(fp, "; %s%s\n", decl.generate_c_namespace_end.c_str(), smart ? " }" : ""); + fprintf(fp, "; %s }\n", decl.generate_c_namespace_end.c_str()); } -static void print_event_c_prototype_impl(FILE* fp, bool smart) +static void print_event_c_prototype_impl(FILE* fp) { - if ( smart ) - fprintf(fp, "void %s(zeek::analyzer::Analyzer* analyzer%s", - decl.enqueue_c_fullname.c_str(), - args.size() ? ", " : "" ); - else - fprintf(fp, "void %s(zeek::analyzer::Analyzer* analyzer%s", - decl.generate_c_fullname.c_str(), - args.size() ? ", " : "" ); + fprintf(fp, "void %s(zeek::analyzer::Analyzer* analyzer%s", + decl.enqueue_c_fullname.c_str(), + args.size() ? ", " : "" ); - print_event_c_prototype_args(fp, smart); + print_event_c_prototype_args(fp); fprintf(fp, ")"); fprintf(fp, "\n"); } -static void print_event_c_body(FILE* fp, bool smart) +static void print_event_c_body(FILE* fp) { fprintf(fp, "\t{\n"); fprintf(fp, "\t// Note that it is intentional that here we do not\n"); @@ -272,7 +259,7 @@ static void print_event_c_body(FILE* fp, bool smart) for ( int i = 0; i < (int) args.size(); ++i ) { fprintf(fp, "\t "); - args[i]->PrintBroValConstructor(fp, smart); + args[i]->PrintBroValConstructor(fp); fprintf(fp, ",\n"); if ( args[i]->Type() == TYPE_CONNECTION ) @@ -383,10 +370,6 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' fprintf(fp_netvar_h, "namespace zeek { %s extern zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern zeek::%sType * %s; %s\n", - decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), type_name.c_str(), - decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "namespace zeek { %s zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), type_name.c_str(), @@ -399,9 +382,6 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' "\tzeek::%s = zeek::id::find_type(\"%s\");\n", decl.c_fullname.c_str(), type_name.c_str(), decl.bro_fullname.c_str()); - fprintf(fp_netvar_init, - "\t%s = zeek::%s.get();\n", - decl.c_fullname.c_str(), decl.c_fullname.c_str()); record_bif_item(decl.bro_fullname.c_str(), "TYPE"); } @@ -428,12 +408,9 @@ event_def: event_prefix opt_ws plain_head opt_func_attrs { if ( events.find(decl.bro_fullname) == events.end() ) { - print_event_c_prototype_header(fp_func_h, false); - print_event_c_prototype_impl(fp_func_def, false); - print_event_c_body(fp_func_def, false); - print_event_c_prototype_header(fp_func_h, true); - print_event_c_prototype_impl(fp_func_def, true); - print_event_c_body(fp_func_def, true); + print_event_c_prototype_header(fp_func_h); + print_event_c_prototype_impl(fp_func_def); + print_event_c_body(fp_func_def); events.insert(decl.bro_fullname); } } @@ -456,10 +433,6 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list // Now generate the netvar's. fprintf(fp_netvar_h, "namespace zeek { %s extern zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern zeek::EnumType * %s; %s\n", - decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), - decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "namespace zeek { %s zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_def, "%s zeek::EnumType * %s; %s\n", @@ -468,9 +441,6 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list fprintf(fp_netvar_init, "\tzeek::%s = zeek::id::find_type(\"%s\");\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); - fprintf(fp_netvar_init, - "\t%s = zeek::%s.get();\n", - decl.c_fullname.c_str(), decl.c_fullname.c_str()); record_bif_item(decl.bro_fullname.c_str(), "TYPE"); } @@ -522,10 +492,6 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' decl.c_namespace_start.c_str(), builtin_types[typeidx].c_type_smart, decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_h, "%s [[deprecated(\"Remove in v4.1. Use zeek::%s.\")]] extern %s %s; %s\n", - decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), - builtin_types[typeidx].c_type, decl.bare_name.c_str(), - decl.c_namespace_end.c_str()); fprintf(fp_netvar_def, "namespace zeek { %s %s %s; %s }\n", decl.c_namespace_start.c_str(), @@ -544,8 +510,6 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' builtin_types[typeidx].cast_smart, decl.bro_fullname.c_str()); fprintf(fp_netvar_init, "\tzeek::%s = v%s;\n", decl.c_fullname.c_str(), accessor_smart); - fprintf(fp_netvar_init, "\t%s = v.get()%s;\n", - decl.c_fullname.c_str(), accessor); fprintf(fp_netvar_init, "\t}\n"); if ( alternative_mode && ! plugin ) @@ -641,15 +605,6 @@ head_1: TOK_ID opt_ws arg_begin "namespace zeek { %sextern zeek::detail::BifReturnVal %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - // This is the deprecated, legacy, version of the BIF that - // forwards to the "canonical" version. It also does have - // a "bro_" prefix in the name itself, but no "_bif" suffix. - fprintf(fp_func_h, - "%s [[deprecated(\"Remove in v4.1. Use zeek::%s_bif.\")]] inline zeek::detail::BifReturnVal bro_%s(zeek::detail::Frame* frame, const zeek::Args* args)", - decl.c_namespace_start.c_str(), decl.c_fullname.c_str(), decl.bare_name.c_str()); - fprintf(fp_func_h, " { return zeek::%s_bif(frame, args); } %s\n", - decl.c_fullname.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_func_def, "zeek::detail::BifReturnVal zeek::%s_bif(zeek::detail::Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); @@ -670,7 +625,7 @@ head_1: TOK_ID opt_ws arg_begin decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, - "\t%s = event_registry->Register(\"%s\");\n", + "\t%s = zeek::event_registry->Register(\"%s\");\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); record_bif_item(decl.bro_fullname.c_str(), "EVENT"); diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index bd8b9c58d2..6ed4c56921 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -27,8 +27,8 @@ public: void PrintBro(FILE* fp); void PrintCDef(FILE* fp, int n); - void PrintCArg(FILE* fp, int n, bool smart); - void PrintBroValConstructor(FILE* fp, bool smart); + void PrintCArg(FILE* fp, int n); + void PrintBroValConstructor(FILE* fp); protected: const char* name; From 34c4f678cfdae431c8fc69dbe49a7c5b0846d1be Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 29 Jan 2021 19:14:58 -0800 Subject: [PATCH 208/343] bifcl: Add missing zeek/ to generated header includes Related to https://github.com/zeek/zeek/pull/1377 --- tools/bifcl/builtin-func.l | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 6ec121f405..5a23060014 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -235,14 +235,14 @@ void init_alternative_mode() fprintf(fp_func_h, "#ifndef BRO_IN_NETVAR\n"); fprintf(fp_func_h, "#ifndef %s\n", guard); fprintf(fp_func_h, "#define %s\n", guard); - fprintf(fp_func_h, "#include \"zeek-bif.h\"\n"); + fprintf(fp_func_h, "#include \"zeek/zeek-bif.h\"\n"); fprintf(fp_func_h, "#endif\n"); fprintf(fp_func_h, "#endif\n"); fprintf(fp_func_h, "\n"); fprintf(fp_func_def, "\n"); fprintf(fp_func_def, "#include \"%s.h\"\n", input_filename); - fprintf(fp_func_def, "#include \"Func.h\"\n"); + fprintf(fp_func_def, "#include \"zeek/Func.h\"\n"); fprintf(fp_func_def, "\n"); static char name[1024]; @@ -267,8 +267,8 @@ void init_alternative_mode() fprintf(fp_func_init, "\n"); fprintf(fp_func_init, "#include \n"); fprintf(fp_func_init, "#include \n"); - fprintf(fp_func_init, "#include \"plugin/Plugin.h\"\n"); - fprintf(fp_func_init, "#include \"Func.h\"\n"); + fprintf(fp_func_init, "#include \"zeek/plugin/Plugin.h\"\n"); + fprintf(fp_func_init, "#include \"zeek/Func.h\"\n"); fprintf(fp_func_init, "#include \"%s.h\"\n", input_filename); fprintf(fp_func_init, "\n"); fprintf(fp_func_init, "namespace plugin { namespace %s {\n", plugin_canon); @@ -276,7 +276,7 @@ void init_alternative_mode() fprintf(fp_func_init, "void __bif_%s_init(zeek::plugin::Plugin* plugin)\n", name); fprintf(fp_func_init, "\t{\n"); - fprintf(fp_func_register, "#include \"plugin/Manager.h\"\n"); + fprintf(fp_func_register, "#include \"zeek/plugin/Manager.h\"\n"); fprintf(fp_func_register, "\n"); fprintf(fp_func_register, "namespace plugin { namespace %s {\n", plugin_canon); fprintf(fp_func_register, "void __bif_%s_init(zeek::plugin::Plugin* plugin);\n", name); From ae56d45a1f0e76d2620b1e49264adfe3734284c6 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 12 Mar 2021 12:07:12 -0800 Subject: [PATCH 209/343] bifcl: Prevent use of LeakSanitizer on FreeBSD --- tools/bifcl/builtin-func.l | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 5a23060014..ca9c9d1c85 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -311,17 +311,19 @@ void finish_alternative_mode() #endif #endif -#if defined(USING_ASAN) +// FreeBSD doesn't support LeakSanitizer +#if defined(USING_ASAN) && !defined(__FreeBSD__) #include + #define BIFCL_LSAN_DISABLE(x) __lsan_disable(x) +#else + #define BIFCL_LSAN_DISABLE(x) #endif int main(int argc, char* argv[]) { - #if defined(USING_ASAN) // We generally do not care at all if bifcl is leaking and the default // behavior of LSAN to treat leaks as errors only trips up Zeek's build. - __lsan_disable(); - #endif + BIFCL_LSAN_DISABLE(); int opt; From ea625959c119ee38081ff8abf2a071b65257df0a Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 11 Mar 2021 14:23:59 -0700 Subject: [PATCH 210/343] bifcl: Rename Session::ConnVal() to Session::GetVal() --- tools/bifcl/include/bif_type.def | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 92baace92f..586ef7b4da 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -3,10 +3,10 @@ DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "zeek::AddrVal*", DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "zeek::val_mgr->Bool(%s)", "zeek::val_mgr->Bool(%s)") DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "zeek::Connection*", "zeek::Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->ConnVal()", "%s->ConnVal()") +DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "zeek::Connection*", "zeek::Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->GetVal()", "%s->GetVal()") DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "zeek::val_mgr->Count(%s)", "zeek::val_mgr->Count(%s)") DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "zeek::File*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "zeek::File*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "zeek::val_mgr->Int(%s)", "zeek::val_mgr->Int(%s)") DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") From d0ed7131086d9658c7c5c1f3dde33b8609e0e5e3 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 28 Jun 2021 12:57:18 +0000 Subject: [PATCH 211/343] bifcl: Updates for building Zeek as a subproject --- tools/bifcl/CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index ed06464e8f..5260cd4cdf 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -19,19 +19,19 @@ endif () include(RequireCXX17) include_directories(BEFORE - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_BINARY_DIR} + ${BifCl_SOURCE_DIR}/include + ${BifCl_BINARY_DIR} ) set(BISON_FLAGS "--debug") # BIF parser/scanner bison_target(BIFParser builtin-func.y - ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.cc - HEADER ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.h - #VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.output + ${BifCl_BINARY_DIR}/bif_parse.cc + HEADER ${BifCl_BINARY_DIR}/bif_parse.h + #VERBOSE ${BifCl_BINARY_DIR}/bif_parse.output COMPILE_FLAGS "${BISON_FLAGS}") -flex_target(BIFScanner builtin-func.l ${CMAKE_CURRENT_BINARY_DIR}/bif_lex.cc) +flex_target(BIFScanner builtin-func.l ${BifCl_BINARY_DIR}/bif_lex.cc) add_flex_bison_dependency(BIFScanner BIFParser) set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") @@ -58,7 +58,7 @@ message( "\n====================| Bifcl Build Summary |=====================" "\n" "\nBuild type: ${CMAKE_BUILD_TYPE}" - "\nBuild dir: ${CMAKE_BINARY_DIR}" + "\nBuild dir: ${PROJECT_BINARY_DIR}" "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" "\nDebug mode: ${ENABLE_DEBUG}" "\n" From 02fe78a03f538bdfbb617678dba8ce010fee2df0 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 3 Nov 2021 15:23:17 -0700 Subject: [PATCH 212/343] bifcl: Allow analyzer to be passed as nullptr for enqueue methods This allows the methods to be used in contexts where the analyzer ID is not available or when the ID doesn't matter, such as in packet analyzers. --- tools/bifcl/builtin-func.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 0aad969649..ce4b8c0bf2 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -276,7 +276,7 @@ static void print_event_c_body(FILE* fp) } } - fprintf(fp, "\t },\n\t zeek::util::detail::SOURCE_LOCAL, analyzer->GetID()"); + fprintf(fp, "\t },\n\t zeek::util::detail::SOURCE_LOCAL, analyzer ? analyzer->GetID() : 0"); if ( connection_arg ) // Pass the connection to the EventMgr as the "cookie" From 2f3f7e9ce23cce5b21385253a3dd55e705dc34e9 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Thu, 3 Feb 2022 14:54:08 -0800 Subject: [PATCH 213/343] bifcl: trimmed & regularized some minor variable naming --- tools/bifcl/builtin-func.y | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index ce4b8c0bf2..674555f9a6 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -59,11 +59,9 @@ struct decl_struct { string bro_name; // the name as we read it from input. What we write into the .zeek file // special cases for events. Events have an EventHandlerPtr - // and a generate_* function. This name is for the generate_* function - string generate_bare_name; - string generate_c_fullname; - string generate_c_namespace_start; - string generate_c_namespace_end; + // and a enqueue_* function. This name is for the enqueue_* function + string enqueue_c_namespace_start; + string enqueue_c_namespace_end; string enqueue_c_barename; string enqueue_c_fullname; } decl; @@ -92,12 +90,10 @@ void set_decl_name(const char *name) decl.bro_fullname = ""; decl.bro_name = ""; - decl.generate_c_fullname = ""; decl.enqueue_c_fullname = ""; - decl.generate_bare_name = string("generate_") + decl.bare_name; decl.enqueue_c_barename = string("enqueue_") + decl.bare_name; - decl.generate_c_namespace_start = ""; - decl.generate_c_namespace_end = ""; + decl.enqueue_c_namespace_start = ""; + decl.enqueue_c_namespace_end = ""; switch ( definition_type ) { case TYPE_DEF: @@ -122,9 +118,8 @@ void set_decl_name(const char *name) decl.c_namespace_start = ""; decl.c_namespace_end = ""; decl.c_fullname = "::"; // need this for namespace qualified events due do event_c_body - decl.generate_c_namespace_start = "namespace BifEvent { "; - decl.generate_c_namespace_end = " } "; - decl.generate_c_fullname = "BifEvent::"; + decl.enqueue_c_namespace_start = "namespace BifEvent { "; + decl.enqueue_c_namespace_end = " } "; decl.enqueue_c_fullname = "zeek::BifEvent::"; break; @@ -139,16 +134,14 @@ void set_decl_name(const char *name) decl.c_fullname += decl.module_name + "::"; decl.bro_fullname += decl.module_name + "::"; - decl.generate_c_namespace_start += "namespace " + decl.module_name + " { "; - decl.generate_c_namespace_end += " } "; - decl.generate_c_fullname += decl.module_name + "::"; + decl.enqueue_c_namespace_start += "namespace " + decl.module_name + " { "; + decl.enqueue_c_namespace_end += " } "; decl.enqueue_c_fullname += decl.module_name + "::"; } decl.bro_fullname += decl.bare_name; decl.c_fullname += decl.bare_name; decl.bro_name += name; - decl.generate_c_fullname += decl.generate_bare_name; decl.enqueue_c_fullname += decl.enqueue_c_barename; } @@ -221,13 +214,13 @@ static void print_event_c_prototype_args(FILE* fp) static void print_event_c_prototype_header(FILE* fp) { fprintf(fp, "namespace zeek { %s void %s(zeek::analyzer::Analyzer* analyzer%s", - decl.generate_c_namespace_start.c_str(), + decl.enqueue_c_namespace_start.c_str(), decl.enqueue_c_barename.c_str(), args.size() ? ", " : "" ); print_event_c_prototype_args(fp); fprintf(fp, ")"); - fprintf(fp, "; %s }\n", decl.generate_c_namespace_end.c_str()); + fprintf(fp, "; %s }\n", decl.enqueue_c_namespace_end.c_str()); } static void print_event_c_prototype_impl(FILE* fp) @@ -248,7 +241,7 @@ static void print_event_c_body(FILE* fp) fprintf(fp, "\t// check if %s is NULL, which should happen *before*\n", decl.c_fullname.c_str()); fprintf(fp, "\t// %s is called to avoid unnecessary Val\n", - decl.generate_c_fullname.c_str()); + decl.enqueue_c_fullname.c_str()); fprintf(fp, "\t// allocation.\n"); fprintf(fp, "\n"); @@ -284,7 +277,7 @@ static void print_event_c_body(FILE* fp) fprintf(fp, ");\n"); fprintf(fp, "\t}\n\n"); - //fprintf(fp, "%s // end namespace\n", decl.generate_c_namespace_end.c_str()); + //fprintf(fp, "%s // end namespace\n", decl.enqueue_c_namespace_end.c_str()); } void record_bif_item(const char* id, const char* type) From 669875a9b7a35be5371d413ea0e9c724b3e8eeec Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 28 Jun 2022 15:33:20 -0700 Subject: [PATCH 214/343] bifcl: Deprecate bro_int_t and bro_uint_t --- tools/bifcl/include/bif_type.def | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index 586ef7b4da..d97f547822 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -4,10 +4,10 @@ DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "zeek::Val*", DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "zeek::val_mgr->Bool(%s)", "zeek::val_mgr->Bool(%s)") DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "zeek::Connection*", "zeek::Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->GetVal()", "%s->GetVal()") -DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "bro_uint_t", "bro_uint_t", "%s->AsCount()", "%s->AsCount()", "", "zeek::val_mgr->Count(%s)", "zeek::val_mgr->Count(%s)") +DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "zeek_uint_t", "zeek_uint_t", "%s->AsCount()", "%s->AsCount()", "", "zeek::val_mgr->Count(%s)", "zeek::val_mgr->Count(%s)") DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "zeek::File*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "bro_int_t", "bro_int_t", "%s->AsInt()", "%s->AsInt()", "", "zeek::val_mgr->Int(%s)", "zeek::val_mgr->Int(%s)") +DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "zeek_int_t", "zeek_int_t", "%s->AsInt()", "%s->AsInt()", "", "zeek::val_mgr->Int(%s)", "zeek::val_mgr->Int(%s)") DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "zeek::PortVal*", "zeek::IntrusivePtr", "%s->AsPortVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") From e080c5c6b2b8815ea406ade18bc11c1c7a4c4197 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 29 Jun 2022 11:56:51 -0700 Subject: [PATCH 215/343] bifcl: Remove remaining uses of Bro naming --- tools/bifcl/bif_arg.cc | 12 ++-- tools/bifcl/builtin-func.l | 16 ++--- tools/bifcl/builtin-func.y | 110 +++++++++++++++---------------- tools/bifcl/include/bif_arg.h | 4 +- tools/bifcl/include/bif_type.def | 34 +++++----- 5 files changed, 88 insertions(+), 88 deletions(-) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index abeba2872a..7018e9e02d 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -9,7 +9,7 @@ using namespace std; static struct { const char* bif_type; - const char* bro_type; + const char* zeek_type; const char* c_type; const char* c_type_smart; const char* accessor; @@ -18,8 +18,8 @@ static struct { const char* constructor; const char* ctor_smart; } builtin_func_arg_type[] = { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) \ - {bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart}, +#define DEFINE_BIF_TYPE(id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) \ + {bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE }; @@ -50,9 +50,9 @@ BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, const char* arg_type_str, } } -void BuiltinFuncArg::PrintBro(FILE* fp) +void BuiltinFuncArg::PrintZeek(FILE* fp) { - fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].bro_type, + fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].zeek_type, type_str, attr_str); } @@ -77,7 +77,7 @@ void BuiltinFuncArg::PrintCArg(FILE* fp, int n) fprintf(fp, "%s %s", builtin_func_arg_type[type].c_type_smart, name); } -void BuiltinFuncArg::PrintBroValConstructor(FILE* fp) +void BuiltinFuncArg::PrintValConstructor(FILE* fp) { fprintf(fp, builtin_func_arg_type[type].ctor_smart, name); } diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index ca9c9d1c85..b6464ecd36 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -150,7 +150,7 @@ char* input_filename_with_path = 0; char* plugin = 0; int alternative_mode = 0; -FILE* fp_bro_init = 0; +FILE* fp_zeek_init = 0; FILE* fp_func_def = 0; FILE* fp_func_h = 0; FILE* fp_func_init = 0; @@ -189,7 +189,7 @@ void usage() void init_alternative_mode() { - fp_bro_init = open_output_file("zeek"); + fp_zeek_init = open_output_file("zeek"); fp_func_h = open_output_file("h"); fp_func_def = open_output_file("cc"); fp_func_init = open_output_file("init.cc"); @@ -207,7 +207,7 @@ void init_alternative_mode() "This file was automatically generated by bifcl from %s (%s mode).", input_filename_with_path, plugin ? "plugin" : "alternative"); - fprintf(fp_bro_init, "# %s\n\n", auto_gen_comment); + fprintf(fp_zeek_init, "# %s\n\n", auto_gen_comment); fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); @@ -230,9 +230,9 @@ void init_alternative_mode() *p = '_'; } - fprintf(fp_func_h, "#if defined(BRO_IN_NETVAR) || ! defined(%s)\n", guard); + fprintf(fp_func_h, "#if defined(ZEEK_IN_NETVAR) || ! defined(%s)\n", guard); - fprintf(fp_func_h, "#ifndef BRO_IN_NETVAR\n"); + fprintf(fp_func_h, "#ifndef ZEEK_IN_NETVAR\n"); fprintf(fp_func_h, "#ifndef %s\n", guard); fprintf(fp_func_h, "#define %s\n", guard); fprintf(fp_func_h, "#include \"zeek/zeek-bif.h\"\n"); @@ -364,7 +364,7 @@ int main(int argc, char* argv[]) if ( ! alternative_mode ) { - fp_bro_init = open_output_file("zeek"); + fp_zeek_init = open_output_file("zeek"); fp_func_h = open_output_file("func_h"); fp_func_def = open_output_file("func_def"); fp_func_init = open_output_file("func_init"); @@ -380,7 +380,7 @@ int main(int argc, char* argv[]) "This file was automatically generated by bifcl from %s.", input_filename); - fprintf(fp_bro_init, "# %s\n\n", auto_gen_comment); + fprintf(fp_zeek_init, "# %s\n\n", auto_gen_comment); fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); @@ -418,7 +418,7 @@ void close_if_open(FILE **fpp) void close_all_output_files(void) { - close_if_open(&fp_bro_init); + close_if_open(&fp_zeek_init); close_if_open(&fp_func_h); close_if_open(&fp_func_def); close_if_open(&fp_func_init); diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 674555f9a6..e1ca2e13e2 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -20,7 +20,7 @@ extern int alternative_mode; #define print_line_directive(fp) fprintf(fp, "\n#line %d \"%s\"\n", line_number, input_filename) -extern FILE* fp_bro_init; +extern FILE* fp_zeek_init; extern FILE* fp_func_def; extern FILE* fp_func_h; extern FILE* fp_func_init; @@ -55,8 +55,8 @@ struct decl_struct { string c_namespace_start; // "opening" namespace for use in netvar_* string c_namespace_end; // closing "}" for all the above namespaces string c_fullname; // fully qualified name (namespace::....) for use in netvar_init - string bro_fullname; // fully qualified bro name, for netvar (and lookup_ID()) - string bro_name; // the name as we read it from input. What we write into the .zeek file + string zeek_fullname; // fully qualified zeek name, for netvar (and lookup_ID()) + string zeek_name; // the name as we read it from input. What we write into the .zeek file // special cases for events. Events have an EventHandlerPtr // and a enqueue_* function. This name is for the enqueue_* function @@ -87,8 +87,8 @@ void set_decl_name(const char *name) decl.c_namespace_start = ""; decl.c_namespace_end = ""; decl.c_fullname = ""; - decl.bro_fullname = ""; - decl.bro_name = ""; + decl.zeek_fullname = ""; + decl.zeek_name = ""; decl.enqueue_c_fullname = ""; decl.enqueue_c_barename = string("enqueue_") + decl.bare_name; @@ -132,16 +132,16 @@ void set_decl_name(const char *name) decl.c_namespace_start += "namespace " + decl.module_name + " { "; decl.c_namespace_end += string(" }"); decl.c_fullname += decl.module_name + "::"; - decl.bro_fullname += decl.module_name + "::"; + decl.zeek_fullname += decl.module_name + "::"; decl.enqueue_c_namespace_start += "namespace " + decl.module_name + " { "; decl.enqueue_c_namespace_end += " } "; decl.enqueue_c_fullname += decl.module_name + "::"; } - decl.bro_fullname += decl.bare_name; + decl.zeek_fullname += decl.bare_name; decl.c_fullname += decl.bare_name; - decl.bro_name += name; + decl.zeek_name += name; decl.enqueue_c_fullname += decl.enqueue_c_barename; } @@ -149,10 +149,10 @@ const char* arg_list_name = "BiF_ARGS"; #include "bif_arg.h" -/* Map bif/bro type names to C types for use in const declaration */ +/* Map bif/zeek type names to C types for use in const declaration */ static struct { const char* bif_type; - const char* bro_type; + const char* zeek_type; const char* c_type; const char* c_type_smart; const char* accessor; @@ -161,8 +161,8 @@ static struct { const char* constructor; const char* ctor_smatr; } builtin_types[] = { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) \ - {bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart}, +#define DEFINE_BIF_TYPE(id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) \ + {bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE }; @@ -252,7 +252,7 @@ static void print_event_c_body(FILE* fp) for ( int i = 0; i < (int) args.size(); ++i ) { fprintf(fp, "\t "); - args[i]->PrintBroValConstructor(fp); + args[i]->PrintValConstructor(fp); fprintf(fp, ",\n"); if ( args[i]->Type() == TYPE_CONNECTION ) @@ -312,8 +312,8 @@ void record_bif_item(const char* id, const char* type) builtin_lang: definitions { - fprintf(fp_bro_init, "} # end of export section\n"); - fprintf(fp_bro_init, "module %s;\n", GLOBAL_MODULE_NAME); + fprintf(fp_zeek_init, "} # end of export section\n"); + fprintf(fp_zeek_init, "module %s;\n", GLOBAL_MODULE_NAME); } @@ -323,12 +323,12 @@ definitions: definitions definition opt_ws if ( in_c_code ) fprintf(fp_func_def, "%s", $3); else - fprintf(fp_bro_init, "%s", $3); + fprintf(fp_zeek_init, "%s", $3); } | opt_ws { - fprintf(fp_bro_init, "%s", $1); - fprintf(fp_bro_init, "export {\n"); + fprintf(fp_zeek_init, "%s", $1); + fprintf(fp_zeek_init, "export {\n"); } ; @@ -345,11 +345,11 @@ definition: event_def module_def: TOK_MODULE opt_ws TOK_ID opt_ws ';' { current_module = string($3); - fprintf(fp_bro_init, "module %s;\n", $3); + fprintf(fp_zeek_init, "module %s;\n", $3); } // XXX: Add the netvar glue so that the event engine knows about - // the type. One still has to define the type in bro.init. + // the type. One still has to define the type in zeek.init. // Would be nice, if we could just define the record type here // and then copy to the .bif.zeek file, but type declarations in // Zeek can be quite powerful. Don't know whether it's worth it @@ -374,9 +374,9 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' fprintf(fp_netvar_init, "\tzeek::%s = zeek::id::find_type(\"%s\");\n", decl.c_fullname.c_str(), type_name.c_str(), - decl.bro_fullname.c_str()); + decl.zeek_fullname.c_str()); - record_bif_item(decl.bro_fullname.c_str(), "TYPE"); + record_bif_item(decl.zeek_fullname.c_str(), "TYPE"); } ; @@ -397,27 +397,27 @@ opt_func_attrs: attr_list opt_ws ; event_def: event_prefix opt_ws plain_head opt_func_attrs - { fprintf(fp_bro_init, "%s", $4); } end_of_head ';' + { fprintf(fp_zeek_init, "%s", $4); } end_of_head ';' { - if ( events.find(decl.bro_fullname) == events.end() ) + if ( events.find(decl.zeek_fullname) == events.end() ) { print_event_c_prototype_header(fp_func_h); print_event_c_prototype_impl(fp_func_def); print_event_c_body(fp_func_def); - events.insert(decl.bro_fullname); + events.insert(decl.zeek_fullname); } } func_def: func_prefix opt_ws typed_head opt_func_attrs - { fprintf(fp_bro_init, "%s", $4); } end_of_head body + { fprintf(fp_zeek_init, "%s", $4); } end_of_head body ; enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list { // First, put an end to the enum type decl. - fprintf(fp_bro_init, "} "); - fprintf(fp_bro_init, "%s", $4); - fprintf(fp_bro_init, ";\n"); + fprintf(fp_zeek_init, "} "); + fprintf(fp_zeek_init, "%s", $4); + fprintf(fp_zeek_init, ";\n"); if ( decl.module_name != GLOBAL_MODULE_NAME ) fprintf(fp_netvar_h, "}; } }\n"); else @@ -433,9 +433,9 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list fprintf(fp_netvar_init, "\tzeek::%s = zeek::id::find_type(\"%s\");\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + decl.c_fullname.c_str(), decl.zeek_fullname.c_str()); - record_bif_item(decl.bro_fullname.c_str(), "TYPE"); + record_bif_item(decl.zeek_fullname.c_str(), "TYPE"); } ; @@ -443,7 +443,7 @@ enum_def_1: TOK_ENUM opt_ws TOK_ID opt_ws TOK_LPB opt_ws { set_definition_type(TYPE_DEF, "Enum"); set_decl_name($3); - fprintf(fp_bro_init, "type %s: enum %s{%s", decl.bro_name.c_str(), $4, $6); + fprintf(fp_zeek_init, "type %s: enum %s{%s", decl.zeek_name.c_str(), $4, $6); // this is the namespace were the enumerators are defined, not where // the type is defined. @@ -457,12 +457,12 @@ enum_def_1: TOK_ENUM opt_ws TOK_ID opt_ws TOK_LPB opt_ws enum_list: enum_list TOK_ID opt_ws ',' opt_ws { - fprintf(fp_bro_init, "%s%s,%s", $2, $3, $5); + fprintf(fp_zeek_init, "%s%s,%s", $2, $3, $5); fprintf(fp_netvar_h, "\t%s,\n", $2); } | enum_list TOK_ID opt_ws '=' opt_ws TOK_INT opt_ws ',' opt_ws { - fprintf(fp_bro_init, "%s = %s%s,%s", $2, $6, $7, $9); + fprintf(fp_zeek_init, "%s = %s%s,%s", $2, $6, $7, $9); fprintf(fp_netvar_h, "\t%s = %s,\n", $2, $6); } | /* nothing */ @@ -500,7 +500,7 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' fprintf(fp_netvar_init, "\t{\n"); fprintf(fp_netvar_init, "\tconst auto& v = zeek::id::find_const%s(\"%s\");\n", - builtin_types[typeidx].cast_smart, decl.bro_fullname.c_str()); + builtin_types[typeidx].cast_smart, decl.zeek_fullname.c_str()); fprintf(fp_netvar_init, "\tzeek::%s = v%s;\n", decl.c_fullname.c_str(), accessor_smart); fprintf(fp_netvar_init, "\t}\n"); @@ -508,7 +508,7 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' if ( alternative_mode && ! plugin ) fprintf(fp_netvar_init, "\t);\n"); - record_bif_item(decl.bro_fullname.c_str(), "CONSTANT"); + record_bif_item(decl.zeek_fullname.c_str(), "CONSTANT"); } attr_list: @@ -534,7 +534,7 @@ event_prefix: TOK_EVENT end_of_head: /* nothing */ { - fprintf(fp_bro_init, ";\n"); + fprintf(fp_zeek_init, ";\n"); } ; @@ -546,20 +546,20 @@ typed_head: plain_head return_type plain_head: head_1 args arg_end opt_ws { if ( var_arg ) - fprintf(fp_bro_init, "va_args: any"); + fprintf(fp_zeek_init, "va_args: any"); else { for ( int i = 0; i < (int) args.size(); ++i ) { if ( i > 0 ) - fprintf(fp_bro_init, ", "); - args[i]->PrintBro(fp_bro_init); + fprintf(fp_zeek_init, ", "); + args[i]->PrintZeek(fp_zeek_init); } } - fprintf(fp_bro_init, ")"); + fprintf(fp_zeek_init, ")"); - fprintf(fp_bro_init, "%s", $4); + fprintf(fp_zeek_init, "%s", $4); fprintf(fp_func_def, "%s", $4); } ; @@ -578,18 +578,18 @@ head_1: TOK_ID opt_ws arg_begin method_type = "event"; if ( method_type ) - fprintf(fp_bro_init, + fprintf(fp_zeek_init, "global %s: %s%s(", - decl.bro_name.c_str(), method_type, $2); + decl.zeek_name.c_str(), method_type, $2); if ( definition_type == FUNC_DEF ) { fprintf(fp_func_init, "\t(void) new zeek::detail::BuiltinFunc(zeek::%s_bif, \"%s\", 0);\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + decl.c_fullname.c_str(), decl.zeek_fullname.c_str()); // This is the "canonical" version, with argument type and order - // mostly for historical reasons. There's also no "bro_" prefix + // mostly for historical reasons. There's also no "zeek_" prefix // in the function name itself, but does have a "_bif" suffix // to potentially help differentiate from other functions // (e.g. ones at global scope that may be used to implement @@ -602,11 +602,11 @@ head_1: TOK_ID opt_ws arg_begin "zeek::detail::BifReturnVal zeek::%s_bif(zeek::detail::Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); - record_bif_item(decl.bro_fullname.c_str(), "FUNCTION"); + record_bif_item(decl.zeek_fullname.c_str(), "FUNCTION"); } else if ( definition_type == EVENT_DEF ) { - if ( events.find(decl.bro_fullname) == events.end() ) + if ( events.find(decl.zeek_fullname) == events.end() ) { // TODO: add namespace for events here fprintf(fp_netvar_h, @@ -619,10 +619,10 @@ head_1: TOK_ID opt_ws arg_begin fprintf(fp_netvar_init, "\t%s = zeek::event_registry->Register(\"%s\");\n", - decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + decl.c_fullname.c_str(), decl.zeek_fullname.c_str()); - record_bif_item(decl.bro_fullname.c_str(), "EVENT"); - // C++ prototypes of bro_event_* functions will + record_bif_item(decl.zeek_fullname.c_str(), "EVENT"); + // C++ prototypes of zeek_event_* functions will // be generated later. } } @@ -670,7 +670,7 @@ arg: TOK_ID opt_ws ':' opt_ws type return_type: ':' opt_ws type opt_ws { BuiltinFuncArg* ret = new BuiltinFuncArg("", $3); - ret->PrintBro(fp_bro_init); + ret->PrintZeek(fp_zeek_init); delete ret; fprintf(fp_func_def, "%s", $4); } @@ -710,7 +710,7 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, "\t\treporter->Error(\"%s() takes exactly %d argument(s)\");\n", - decl.bro_fullname.c_str(), argc); + decl.zeek_fullname.c_str(), argc); fprintf(fp_func_def, "\t\treturn nullptr;\n"); fprintf(fp_func_def, "\t\t}\n"); } @@ -720,7 +720,7 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, "\t\treporter->Error(\"%s() takes at least %d argument(s)\");\n", - decl.bro_fullname.c_str(), argc); + decl.zeek_fullname.c_str(), argc); fprintf(fp_func_def, "\t\treturn nullptr;\n"); fprintf(fp_func_def, "\t\t}\n"); } @@ -776,7 +776,7 @@ opt_ws: opt_ws TOK_WS else if ( $2[1] == '#' ) // This is a special type of comment that is used to - // generate bro script documentation, so pass it through. + // generate zeek script documentation, so pass it through. $$ = concat($1, $2); else $$ = $1; diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index 6ed4c56921..254d766e23 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -25,10 +25,10 @@ public: const char* Name() const { return name; } int Type() const { return type; } - void PrintBro(FILE* fp); + void PrintZeek(FILE* fp); void PrintCDef(FILE* fp, int n); void PrintCArg(FILE* fp, int n); - void PrintBroValConstructor(FILE* fp); + void PrintValConstructor(FILE* fp); protected: const char* name; diff --git a/tools/bifcl/include/bif_type.def b/tools/bifcl/include/bif_type.def index d97f547822..88d557c047 100644 --- a/tools/bifcl/include/bif_type.def +++ b/tools/bifcl/include/bif_type.def @@ -1,17 +1,17 @@ -// (id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) -DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "zeek::AddrVal*", "zeek::IntrusivePtr", "%s->AsAddrVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "zeek::val_mgr->Bool(%s)", "zeek::val_mgr->Bool(%s)") -DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "zeek::Connection*", "zeek::Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->GetVal()", "%s->GetVal()") -DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "zeek_uint_t", "zeek_uint_t", "%s->AsCount()", "%s->AsCount()", "", "zeek::val_mgr->Count(%s)", "zeek::val_mgr->Count(%s)") -DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "zeek::File*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "zeek_int_t", "zeek_int_t", "%s->AsInt()", "%s->AsInt()", "", "zeek::val_mgr->Int(%s)", "zeek::val_mgr->Int(%s)") -DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") -DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "zeek::PortVal*", "zeek::IntrusivePtr", "%s->AsPortVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "zeek::StringVal*", "zeek::IntrusivePtr", "%s->AsStringVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "zeek::SubNetVal*", "zeek::IntrusivePtr", "%s->AsSubNetVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") -DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "%s->AsTime()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") -DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +// (id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) +DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "zeek::AddrVal*", "zeek::IntrusivePtr", "%s->AsAddrVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "int", "%s->AsBool()", "%s->AsBool()", "", "zeek::val_mgr->Bool(%s)", "zeek::val_mgr->Bool(%s)") +DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_CONNECTION, "connection", "connection", "zeek::Connection*", "zeek::Connection*", "%s->AsRecordVal()->GetOrigin()", "%s->AsRecordVal()->GetOrigin()", "", "%s->GetVal()", "%s->GetVal()") +DEFINE_BIF_TYPE(TYPE_COUNT, "count", "count", "zeek_uint_t", "zeek_uint_t", "%s->AsCount()", "%s->AsCount()", "", "zeek::val_mgr->Count(%s)", "zeek::val_mgr->Count(%s)") +DEFINE_BIF_TYPE(TYPE_DOUBLE, "double", "double", "double", "double", "%s->AsDouble()", "%s->AsDouble()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") +DEFINE_BIF_TYPE(TYPE_FILE, "file", "file", "zeek::File*", "zeek::IntrusivePtr", "%s->AsFile()", "%s", "", "zeek::make_intrusive(zeek::IntrusivePtr{zeek::AdoptRef{}, %s})", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_INT, "int", "int", "zeek_int_t", "zeek_int_t", "%s->AsInt()", "%s->AsInt()", "", "zeek::val_mgr->Int(%s)", "zeek::val_mgr->Int(%s)") +DEFINE_BIF_TYPE(TYPE_INTERVAL, "interval", "interval", "double", "double", "%s->AsInterval()", "%s->AsInterval()", "", "zeek::make_intrusive(%s, Seconds)", "zeek::make_intrusive(%s, Seconds)") +DEFINE_BIF_TYPE(TYPE_PATTERN, "pattern", "pattern", "RE_Matcher*", "zeek::IntrusivePtr", "%s->AsPattern()", "%s", "", "zeek::make_intrusive(%s)", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_PORT, "port", "port", "zeek::PortVal*", "zeek::IntrusivePtr", "%s->AsPortVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_STRING, "string", "string", "zeek::StringVal*", "zeek::IntrusivePtr", "%s->AsStringVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_SUBNET, "subnet", "subnet", "zeek::SubNetVal*", "zeek::IntrusivePtr", "%s->AsSubNetVal()", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") +DEFINE_BIF_TYPE(TYPE_TIME, "time", "time", "double", "double", "%s->AsTime()", "%s->AsTime()", "", "zeek::make_intrusive(%s)", "zeek::make_intrusive(%s)") +DEFINE_BIF_TYPE(TYPE_OTHER, "", "", "zeek::Val*", "zeek::IntrusivePtr", "%s", "%s", "", "zeek::IntrusivePtr{zeek::AdoptRef{}, %s}", "std::move(%s)") From 09d32687401dfbff59736d88817c7a783dd9ae87 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Sun, 25 Sep 2022 22:28:54 +0200 Subject: [PATCH 216/343] bifcl: Keep zeekygen comments close to their definitions The Yacc grammar treats comments like other whitespace and when seeing the first definition in a file would previously emit all whitespace before emitting the `export` section containing the definition. This lead to the first definition being separated from their zeekygen documention (separated by `export {`). With this patch we start the export section before emitting whitespace. While this might now pull more "whitespace" into the exported part, it avoids breaking the association between zeekygen comments and definitions. Closes #15. --- tools/bifcl/builtin-func.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index e1ca2e13e2..b8c67426d6 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -327,8 +327,8 @@ definitions: definitions definition opt_ws } | opt_ws { - fprintf(fp_zeek_init, "%s", $1); fprintf(fp_zeek_init, "export {\n"); + fprintf(fp_zeek_init, "%s", $1); } ; From f69f9e06e1f5ffa919417354d4faaada263c2196 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 11 Oct 2022 12:14:12 -0700 Subject: [PATCH 217/343] bifcl: Use full path to filename in #line directives in generated code This fixes the DWARF information gets output by the compiler, and allows debuggers to use the full path name to display contextual information when a session stops inside of BIF code. --- tools/bifcl/builtin-func.y | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index b8c67426d6..d4fb2d968e 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -15,10 +15,11 @@ using namespace std; extern int line_number; extern char* input_filename; +extern char* input_filename_with_path; extern char* plugin; extern int alternative_mode; -#define print_line_directive(fp) fprintf(fp, "\n#line %d \"%s\"\n", line_number, input_filename) +#define print_line_directive(fp) fprintf(fp, "\n#line %d \"%s\"\n", line_number, input_filename_with_path) extern FILE* fp_zeek_init; extern FILE* fp_func_def; From 552be424c440a36627c3194693b08d393b8a0d05 Mon Sep 17 00:00:00 2001 From: Elad Solomon Date: Thu, 22 Apr 2021 17:41:55 +0300 Subject: [PATCH 218/343] bifcl: Adapted bifcl to compile with MSVC for Windows environment. --- tools/bifcl/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index 5260cd4cdf..abe34bb950 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -16,6 +16,11 @@ if ( MISSING_PREREQS ) message(FATAL_ERROR "Configuration aborted due to missing prerequisites") endif () +if (MSVC) + set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") +else() + set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") +endif() include(RequireCXX17) include_directories(BEFORE @@ -33,7 +38,6 @@ bison_target(BIFParser builtin-func.y COMPILE_FLAGS "${BISON_FLAGS}") flex_target(BIFScanner builtin-func.l ${BifCl_BINARY_DIR}/bif_lex.cc) add_flex_bison_dependency(BIFScanner BIFParser) -set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") set(bifcl_SRCS ${BISON_BIFParser_INPUT} @@ -48,6 +52,10 @@ set(bifcl_SRCS add_executable(bifcl ${bifcl_SRCS}) +if (MSVC) + target_link_libraries(bifcl PRIVATE zeek_windows) +endif() + install(TARGETS bifcl DESTINATION bin) if (CMAKE_BUILD_TYPE) From 3a18b2144cb157f255cebdba1473e81e7f9c6ae9 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 18 Oct 2022 14:56:28 -0700 Subject: [PATCH 219/343] bifcl: Add clang-format and run it on everything --- tools/bifcl/bif_arg.cc | 23 +++++++++++------------ tools/bifcl/include/bif_arg.h | 25 ++++++++++++------------- tools/bifcl/module_util.cc | 15 +++++++-------- 3 files changed, 30 insertions(+), 33 deletions(-) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index 7018e9e02d..c4f27f96de 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -7,7 +7,8 @@ using namespace std; #include "bif_arg.h" -static struct { +static struct + { const char* bif_type; const char* zeek_type; const char* c_type; @@ -17,12 +18,14 @@ static struct { const char* cast_smart; const char* constructor; const char* ctor_smart; -} builtin_func_arg_type[] = { -#define DEFINE_BIF_TYPE(id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) \ - {bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart}, + } builtin_func_arg_type[] = { +#define DEFINE_BIF_TYPE(id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, \ + cast_smart, constructor, ctor_smart) \ + {bif_type, zeek_type, c_type, c_type_smart, accessor, \ + accessor_smart, cast_smart, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE -}; + }; extern const char* arg_list_name; @@ -52,17 +55,13 @@ BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, const char* arg_type_str, void BuiltinFuncArg::PrintZeek(FILE* fp) { - fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].zeek_type, - type_str, attr_str); + fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].zeek_type, type_str, attr_str); } void BuiltinFuncArg::PrintCDef(FILE* fp, int n) { - fprintf(fp, - "\t%s %s = (%s) (", - builtin_func_arg_type[type].c_type, - name, - builtin_func_arg_type[type].c_type); + fprintf(fp, "\t%s %s = (%s) (", builtin_func_arg_type[type].c_type, name, + builtin_func_arg_type[type].c_type); char buf[1024]; snprintf(buf, sizeof(buf), "(*%s)[%d].get()", arg_list_name, n); diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index 254d766e23..4ca9de0d21 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -2,28 +2,27 @@ #include -enum builtin_func_arg_type { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart) \ +enum builtin_func_arg_type + { +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, \ + cast_smart, constructor, ctor_smart) \ id, #include "bif_type.def" #undef DEFINE_BIF_TYPE -}; + }; extern const char* builtin_func_arg_type_bro_name[]; -class BuiltinFuncArg { +class BuiltinFuncArg + { public: BuiltinFuncArg(const char* arg_name, int arg_type); - BuiltinFuncArg(const char* arg_name, const char* arg_type_str, - const char* arg_attr_str = ""); + BuiltinFuncArg(const char* arg_name, const char* arg_type_str, const char* arg_attr_str = ""); - void SetAttrStr(const char* arg_attr_str) - { - attr_str = arg_attr_str; - }; + void SetAttrStr(const char* arg_attr_str) { attr_str = arg_attr_str; }; - const char* Name() const { return name; } - int Type() const { return type; } + const char* Name() const { return name; } + int Type() const { return type; } void PrintZeek(FILE* fp); void PrintCDef(FILE* fp, int n); @@ -35,4 +34,4 @@ protected: int type; const char* type_str; const char* attr_str; -}; + }; diff --git a/tools/bifcl/module_util.cc b/tools/bifcl/module_util.cc index d5817a7d7a..f2fd445eff 100644 --- a/tools/bifcl/module_util.cc +++ b/tools/bifcl/module_util.cc @@ -1,10 +1,11 @@ // // See the file "COPYING" in the main distribution directory for copyright. -#include -#include #include "module_util.h" +#include +#include + static int streq(const char* s1, const char* s2) { return ! strcmp(s1, s2); @@ -24,7 +25,7 @@ string extract_module_name(const char* name) return module_name; } -string extract_var_name(const char *name) +string extract_var_name(const char* name) { string var_name = name; string::size_type pos = var_name.rfind("::"); @@ -35,14 +36,13 @@ string extract_var_name(const char *name) if ( pos + 2 > var_name.size() ) return string(""); - return var_name.substr(pos+2); + return var_name.substr(pos + 2); } string normalized_module_name(const char* module_name) { int mod_len; - if ( (mod_len = strlen(module_name)) >= 2 && - streq(module_name + mod_len - 2, "::") ) + if ( (mod_len = strlen(module_name)) >= 2 && streq(module_name + mod_len - 2, "::") ) mod_len -= 2; return string(module_name, mod_len); @@ -50,8 +50,7 @@ string normalized_module_name(const char* module_name) string make_full_var_name(const char* module_name, const char* var_name) { - if ( ! module_name || streq(module_name, GLOBAL_MODULE_NAME) || - strstr(var_name, "::") ) + if ( ! module_name || streq(module_name, GLOBAL_MODULE_NAME) || strstr(var_name, "::") ) { if ( streq(GLOBAL_MODULE_NAME, extract_module_name(var_name).c_str()) ) return extract_var_name(var_name); From c6042154b9e75f60f7a85ce1481a30d55da8625a Mon Sep 17 00:00:00 2001 From: Tomer Lev Date: Mon, 24 Oct 2022 16:28:51 +0300 Subject: [PATCH 220/343] bifcl: Adding support for libunistd. Also adding pragma guard for the right arch --- tools/bifcl/CMakeLists.txt | 2 +- tools/bifcl/builtin-func.l | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index abe34bb950..75929d0f13 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -53,7 +53,7 @@ set(bifcl_SRCS add_executable(bifcl ${bifcl_SRCS}) if (MSVC) - target_link_libraries(bifcl PRIVATE zeek_windows) + target_link_libraries(bifcl PRIVATE libunistd) endif() install(TARGETS bifcl DESTINATION bin) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index b6464ecd36..4eb0b5fcca 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -332,7 +332,7 @@ int main(int argc, char* argv[]) switch ( opt ) { case 'p': alternative_mode = 1; - plugin = optarg; + plugin = (char*) optarg; break; case 's': @@ -392,13 +392,17 @@ int main(int argc, char* argv[]) else init_alternative_mode(); + fprintf(fp_netvar_init, "#ifdef __GNUC__\n"); fprintf(fp_netvar_init, "#pragma GCC diagnostic push\n"); fprintf(fp_netvar_init, "#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n\n"); - + fprintf(fp_netvar_init, "#endif\n"); + yy_switch_to_buffer(yy_create_buffer(fp_input, YY_BUF_SIZE)); yyparse(); + fprintf(fp_netvar_init, "#ifdef __GNUC__\n"); fprintf(fp_netvar_init, "\n\n#pragma GCC diagnostic pop\n"); + fprintf(fp_netvar_init, "#endif\n"); if ( alternative_mode ) finish_alternative_mode(); From 4352f0c0bbb3f699766b833c1c66ae0a901b1b67 Mon Sep 17 00:00:00 2001 From: Tomer Lev Date: Wed, 26 Oct 2022 17:43:39 +0300 Subject: [PATCH 221/343] bifcl: Only adding subdir if running standalone --- tools/bifcl/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index 75929d0f13..e8b8c0d3d5 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -53,6 +53,11 @@ set(bifcl_SRCS add_executable(bifcl ${bifcl_SRCS}) if (MSVC) + # If building separately from zeek, we need to add the libunistd subdirectory so + # that linking doesn't fail. + if ("${CMAKE_PROJECT_NAME}" STREQUAL "BifCl") + add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) + endif() target_link_libraries(bifcl PRIVATE libunistd) endif() From 0c4676e8359a75573610f177100986459fdb4584 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sat, 18 Feb 2023 19:02:34 -0700 Subject: [PATCH 222/343] bifcl: Remove argument from BIFCL_LSAN_DISABLE macro to fix warning on Windows --- tools/bifcl/builtin-func.l | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 4eb0b5fcca..93294e9f93 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -314,9 +314,9 @@ void finish_alternative_mode() // FreeBSD doesn't support LeakSanitizer #if defined(USING_ASAN) && !defined(__FreeBSD__) #include - #define BIFCL_LSAN_DISABLE(x) __lsan_disable(x) + #define BIFCL_LSAN_DISABLE() __lsan_disable() #else - #define BIFCL_LSAN_DISABLE(x) + #define BIFCL_LSAN_DISABLE() #endif int main(int argc, char* argv[]) @@ -396,7 +396,7 @@ int main(int argc, char* argv[]) fprintf(fp_netvar_init, "#pragma GCC diagnostic push\n"); fprintf(fp_netvar_init, "#pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n\n"); fprintf(fp_netvar_init, "#endif\n"); - + yy_switch_to_buffer(yy_create_buffer(fp_input, YY_BUF_SIZE)); yyparse(); From 4ed4f3e1b84f1af450fab1c066d945ca4bfedd6f Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sat, 18 Feb 2023 21:13:33 -0700 Subject: [PATCH 223/343] bifcl: Include stdint.h early to prevent redefinition of int type macros --- tools/bifcl/builtin-func.l | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 93294e9f93..fe6b028317 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -1,3 +1,11 @@ +%top{ +// Include stdint.h at the start of the generated file. Typically +// MSVC will include this header later, after the definitions of +// the integral type macros. MSVC then complains that about the +// redefinition of the types. Including stdint.h early avoids this. +#include +} + %{ #include #include From 224a42e1f04fdcadbb4c2bf4261630eef19a74fb Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 23 Feb 2023 10:21:10 -0700 Subject: [PATCH 224/343] bifcl: Use nullptrs for pointer initializations --- tools/bifcl/builtin-func.l | 26 +++++++++++++------------- tools/bifcl/builtin-func.y | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index fe6b028317..5b98f054d4 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -153,19 +153,19 @@ int yywrap() } extern int yyparse(); -char* input_filename = 0; -char* input_filename_with_path = 0; -char* plugin = 0; +char* input_filename = nullptr; +char* input_filename_with_path = nullptr; +char* plugin = nullptr; int alternative_mode = 0; -FILE* fp_zeek_init = 0; -FILE* fp_func_def = 0; -FILE* fp_func_h = 0; -FILE* fp_func_init = 0; -FILE* fp_func_register = 0; -FILE* fp_netvar_h = 0; -FILE* fp_netvar_def = 0; -FILE* fp_netvar_init = 0; +FILE* fp_zeek_init = nullptr; +FILE* fp_func_def = nullptr; +FILE* fp_func_h = nullptr; +FILE* fp_func_init = nullptr; +FILE* fp_func_register = nullptr; +FILE* fp_netvar_h = nullptr; +FILE* fp_netvar_def = nullptr; +FILE* fp_netvar_init = nullptr; void remove_file(const char *surfix); void err_exit(void); @@ -201,7 +201,7 @@ void init_alternative_mode() fp_func_h = open_output_file("h"); fp_func_def = open_output_file("cc"); fp_func_init = open_output_file("init.cc"); - fp_func_register = plugin ? open_output_file("register.cc") : NULL; + fp_func_register = plugin ? open_output_file("register.cc") : nullptr; fp_netvar_h = fp_func_h; fp_netvar_def = fp_func_def; @@ -425,7 +425,7 @@ void close_if_open(FILE **fpp) { if (*fpp) fclose(*fpp); - *fpp = NULL; + *fpp = nullptr; } void close_all_output_files(void) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index d4fb2d968e..2188eb3293 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -246,7 +246,7 @@ static void print_event_c_body(FILE* fp) fprintf(fp, "\t// allocation.\n"); fprintf(fp, "\n"); - BuiltinFuncArg* connection_arg = 0; + BuiltinFuncArg* connection_arg = nullptr; fprintf(fp, "\tzeek::event_mgr.Enqueue(%s, zeek::Args{\n", decl.c_fullname.c_str()); @@ -258,7 +258,7 @@ static void print_event_c_body(FILE* fp) if ( args[i]->Type() == TYPE_CONNECTION ) { - if ( connection_arg == 0 ) + if ( connection_arg == nullptr ) connection_arg = args[i]; else { @@ -567,7 +567,7 @@ plain_head: head_1 args arg_end opt_ws head_1: TOK_ID opt_ws arg_begin { - const char* method_type = 0; + const char* method_type = nullptr; set_decl_name($1); if ( definition_type == FUNC_DEF ) From 8662b29ac6193b5fb9e241db9fba49dedad6c60e Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 23 Feb 2023 10:22:04 -0700 Subject: [PATCH 225/343] bifcl: Use bools for boolean comparisons --- tools/bifcl/builtin-func.l | 8 ++++---- tools/bifcl/builtin-func.y | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 5b98f054d4..8f0468ceab 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -23,7 +23,7 @@ char* copy_string(const char* s) int line_number = 1; -extern int in_c_code; +extern bool in_c_code; int check_c_mode(int t) { @@ -156,7 +156,7 @@ extern int yyparse(); char* input_filename = nullptr; char* input_filename_with_path = nullptr; char* plugin = nullptr; -int alternative_mode = 0; +bool alternative_mode = false; FILE* fp_zeek_init = nullptr; FILE* fp_func_def = nullptr; @@ -339,12 +339,12 @@ int main(int argc, char* argv[]) { switch ( opt ) { case 'p': - alternative_mode = 1; + alternative_mode = true; plugin = (char*) optarg; break; case 's': - alternative_mode = 1; + alternative_mode = true; break; default: diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 2188eb3293..365ff15bd3 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -17,7 +17,7 @@ extern int line_number; extern char* input_filename; extern char* input_filename_with_path; extern char* plugin; -extern int alternative_mode; +extern bool alternative_mode; #define print_line_directive(fp) fprintf(fp, "\n#line %d \"%s\"\n", line_number, input_filename_with_path) @@ -29,7 +29,7 @@ extern FILE* fp_netvar_h; extern FILE* fp_netvar_def; extern FILE* fp_netvar_init; -int in_c_code = 0; +bool in_c_code = false; string current_module = GLOBAL_MODULE_NAME; int definition_type; string type_name; @@ -686,13 +686,13 @@ body: body_start c_body body_end c_code_begin: /* empty */ { - in_c_code = 1; + in_c_code = true; print_line_directive(fp_func_def); } ; c_code_end: /* empty */ - { in_c_code = 0; } + { in_c_code = false; } ; body_start: TOK_LPB c_code_begin From 8e295df115088dca099e96564e27f2102d00b618 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 23 Feb 2023 13:14:34 -0700 Subject: [PATCH 226/343] bifcl: Other minor cleanups --- tools/bifcl/builtin-func.l | 7 +++---- tools/bifcl/builtin-func.y | 2 -- tools/bifcl/include/bif_arg.h | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 8f0468ceab..6d31f9613a 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -255,7 +255,7 @@ void init_alternative_mode() static char name[1024]; strncpy(name, input_filename, sizeof(name) - 1); - name[sizeof(name) - 1] = 0; + name[sizeof(name) - 1] = '\0'; char* dot = strchr(name, '.'); if ( dot ) *dot = '\0'; @@ -264,7 +264,7 @@ void init_alternative_mode() { static char plugin_canon[1024]; strncpy(plugin_canon, plugin, sizeof(plugin_canon) - 1); - plugin_canon[sizeof(plugin_canon) - 1] = 0; + plugin_canon[sizeof(plugin_canon) - 1] = '\0'; char* colon = strstr(plugin_canon, "::"); if ( colon ) { @@ -355,10 +355,9 @@ int main(int argc, char* argv[]) for ( int i = optind; i < argc; i++ ) { FILE* fp_input; - char* slash; input_filename = input_filename_with_path = argv[i]; - slash = strrchr(input_filename, '/'); + char* slash = strrchr(input_filename, '/'); if ( (fp_input = fopen(input_filename, "r")) == NULL ) { diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 365ff15bd3..66ef357d05 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -4,8 +4,6 @@ #include #include -using namespace std; - #include #include diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index 4ca9de0d21..588f1d60d2 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -13,7 +13,7 @@ enum builtin_func_arg_type extern const char* builtin_func_arg_type_bro_name[]; -class BuiltinFuncArg +class BuiltinFuncArg final { public: BuiltinFuncArg(const char* arg_name, int arg_type); @@ -29,7 +29,7 @@ public: void PrintCArg(FILE* fp, int n); void PrintValConstructor(FILE* fp); -protected: +private: const char* name; int type; const char* type_str; From efb32d31fceae2090a65d0f56fe43902b6c00f93 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 19 Apr 2023 16:11:10 +0200 Subject: [PATCH 227/343] bifcl: builtin-func.l: Allow more than just one additional component I'm not sure why this was restricted to only two components, the following appears functional in Zeek scripts. module A::B::C; export { type MyRecord: record { a: string; }; } Closes #25. --- tools/bifcl/builtin-func.l | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 6d31f9613a..063a394cfb 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -37,11 +37,8 @@ int check_c_mode(int t) WS [ \t]+ OWS [ \t]* - /* Note, bifcl only accepts a single "::" in IDs while the policy - layer acceptes multiple. (But the policy layer doesn't have - a hierachy. */ IDCOMPONENT [A-Za-z_][A-Za-z_0-9]* -ID {IDCOMPONENT}(::{IDCOMPONENT})? +ID {IDCOMPONENT}(::{IDCOMPONENT})* ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) DEC [[:digit:]]+ HEX [0-9a-fA-F]+ From e7cce57f2b2291a91f4e6a2f4f2de7a9e38c79e8 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 19 Apr 2023 14:15:09 +0200 Subject: [PATCH 228/343] bifcl: Render runtime type checks for var_args bifs Currently, Zeek disables any static type checking for var_arg bifs. However, the generated preamble for var_args bifs assume that typed positional arguments are correctly typed and blindly calls the type converters on them. This easily triggers abort()s at runtime currently when a script mistakenly uses the wrong types for var_arg bifs. For example, calling publish_rr() with a port instead of a string causes a hard-abort with Zeek 5.0.8. $ zeek -e 'Cluster::publish_rr(Cluster::Pool(), 80/tcp)' fatal error in : Val::CONVERTER (port/string) (80/tcp) Aborted (core dumped) Extend bifcl so that for var_arg functions and the types that bifcl understands, we render a runtime type check and explicit early return to avoid the abort(). For any/other types, the implementer of the bif continuous to be responsible for type checking. This isn't solving the var_args situation generally, but avoids some ad-hoc fixes trickling in current bif implementations. Some references: https://github.com/zeek/zeek/issues/1523 https://github.com/zeek/zeek/issues/2425 https://github.com/zeek/zeek/issues/2935 https://github.com/zeek/zeek/pull/2950 --- tools/bifcl/bif_arg.cc | 23 ++++++++++++++++++++--- tools/bifcl/builtin-func.y | 10 +++++----- tools/bifcl/include/bif_arg.h | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index c4f27f96de..735b5ff329 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -9,6 +9,7 @@ using namespace std; static struct { + const char* type_enum; const char* bif_type; const char* zeek_type; const char* c_type; @@ -21,8 +22,8 @@ static struct } builtin_func_arg_type[] = { #define DEFINE_BIF_TYPE(id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, \ cast_smart, constructor, ctor_smart) \ - {bif_type, zeek_type, c_type, c_type_smart, accessor, \ - accessor_smart, cast_smart, constructor, ctor_smart}, + {#id, bif_type, zeek_type, c_type, c_type_smart, \ + accessor, accessor_smart, cast_smart, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE }; @@ -58,8 +59,24 @@ void BuiltinFuncArg::PrintZeek(FILE* fp) fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].zeek_type, type_str, attr_str); } -void BuiltinFuncArg::PrintCDef(FILE* fp, int n) +void BuiltinFuncArg::PrintCDef(FILE* fp, int n, bool runtime_type_check) { + // Generate a runtime type-check pre-amble for types we understand + if ( runtime_type_check && type != TYPE_OTHER && type != TYPE_ANY ) + { + fprintf(fp, "\t\t{\n"); + fprintf(fp, "\t\t// Runtime type check for %s argument\n", name); + fprintf(fp, "\t\tzeek::TypeTag __tag = (*%s)[%d]->GetType()->Tag();\n", arg_list_name, n); + fprintf(fp, "\t\tif ( __tag != %s )\n", builtin_func_arg_type[type].type_enum); + fprintf(fp, "\t\t\t{\n"); + fprintf(fp, + "\t\t\tzeek::emit_builtin_error(zeek::util::fmt(\"expected type %s for %s, got " + "%%s\", zeek::type_name(__tag)));\n", + builtin_func_arg_type[type].zeek_type, name); + fprintf(fp, "\t\t\treturn nullptr;\n"); + fprintf(fp, "\t\t\t}\n"); + fprintf(fp, "\t\t}\n"); + } fprintf(fp, "\t%s %s = (%s) (", builtin_func_arg_type[type].c_type, name, builtin_func_arg_type[type].c_type); diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 66ef357d05..87144e18b7 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -708,8 +708,8 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\tif ( %s->size() != %d )\n", arg_list_name, argc); fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, - "\t\treporter->Error(\"%s() takes exactly %d argument(s)\");\n", - decl.zeek_fullname.c_str(), argc); + "\t\tzeek::emit_builtin_error(zeek::util::fmt(\"%s() takes exactly %d argument(s), got %%lu\", %s->size()));\n", + decl.zeek_fullname.c_str(), argc, arg_list_name); fprintf(fp_func_def, "\t\treturn nullptr;\n"); fprintf(fp_func_def, "\t\t}\n"); } @@ -718,14 +718,14 @@ body_start: TOK_LPB c_code_begin fprintf(fp_func_def, "\tif ( %s->size() < %d )\n", arg_list_name, argc); fprintf(fp_func_def, "\t\t{\n"); fprintf(fp_func_def, - "\t\treporter->Error(\"%s() takes at least %d argument(s)\");\n", - decl.zeek_fullname.c_str(), argc); + "\t\tzeek::emit_builtin_error(zeek::util::fmt(\"%s() takes at least %d argument(s), got %%lu\", %s->size()));\n", + decl.zeek_fullname.c_str(), argc, arg_list_name); fprintf(fp_func_def, "\t\treturn nullptr;\n"); fprintf(fp_func_def, "\t\t}\n"); } for ( int i = 0; i < (int) args.size(); ++i ) - args[i]->PrintCDef(fp_func_def, i + implicit_arg); + args[i]->PrintCDef(fp_func_def, i + implicit_arg, var_arg); print_line_directive(fp_func_def); } ; diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index 588f1d60d2..67df7be12d 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -25,7 +25,7 @@ public: int Type() const { return type; } void PrintZeek(FILE* fp); - void PrintCDef(FILE* fp, int n); + void PrintCDef(FILE* fp, int n, bool runtime_type_check = false); void PrintCArg(FILE* fp, int n); void PrintValConstructor(FILE* fp); From 7275016bcb8bfe29e040aa07b9c120c1da0bea25 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 24 May 2023 12:22:04 -0700 Subject: [PATCH 229/343] bifcl: Remove vendored CMake files from repo --- tools/bifcl/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index e8b8c0d3d5..1f382d36fb 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -33,8 +33,7 @@ set(BISON_FLAGS "--debug") # BIF parser/scanner bison_target(BIFParser builtin-func.y ${BifCl_BINARY_DIR}/bif_parse.cc - HEADER ${BifCl_BINARY_DIR}/bif_parse.h - #VERBOSE ${BifCl_BINARY_DIR}/bif_parse.output + DEFINES_FILE ${BifCl_BINARY_DIR}/bif_parse.h COMPILE_FLAGS "${BISON_FLAGS}") flex_target(BIFScanner builtin-func.l ${BifCl_BINARY_DIR}/bif_lex.cc) add_flex_bison_dependency(BIFScanner BIFParser) From af2a1b67bc92d578d7aa22afe8c9d1b79e5beeb1 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 15 Jun 2023 11:45:41 -0700 Subject: [PATCH 230/343] bifcl: Require CMake 3.15.0 to build, similar to the recent changes to zeek and broker --- tools/bifcl/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index 1f382d36fb..71b7522229 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -1,5 +1,4 @@ - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR) project(BifCl C CXX) include(cmake/CommonCMakeConfig.cmake) From 3004675015e2ced0508f5f4774ecbbe5ea3e2393 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 15 Jun 2023 11:45:51 -0700 Subject: [PATCH 231/343] bifcl: Force -std=c++17 mode for cmake targets, remove use of RequireCXX17.cmake --- tools/bifcl/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index 71b7522229..3df5f0f39c 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -20,7 +20,6 @@ if (MSVC) else() set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") endif() -include(RequireCXX17) include_directories(BEFORE ${BifCl_SOURCE_DIR}/include @@ -49,6 +48,8 @@ set(bifcl_SRCS ) add_executable(bifcl ${bifcl_SRCS}) +target_compile_features(bifcl PRIVATE cxx_std_17) +set_target_properties(bifcl PROPERTIES CXX_EXTENSIONS OFF) if (MSVC) # If building separately from zeek, we need to add the libunistd subdirectory so From af0c68c183bb1f33be503a37f57deb579cb32be9 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 30 Jun 2023 14:04:23 -0700 Subject: [PATCH 232/343] bifcl: Add /J flag on Windows to force unsigned char --- tools/bifcl/CMakeLists.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index 3df5f0f39c..52210aec45 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -9,16 +9,17 @@ FindRequiredPackage(BISON) FindRequiredPackage(FLEX) if ( MISSING_PREREQS ) - foreach (prereq ${MISSING_PREREQ_DESCS}) - message(SEND_ERROR ${prereq}) - endforeach () - message(FATAL_ERROR "Configuration aborted due to missing prerequisites") + foreach (prereq ${MISSING_PREREQ_DESCS}) + message(SEND_ERROR ${prereq}) + endforeach () + message(FATAL_ERROR "Configuration aborted due to missing prerequisites") endif () if (MSVC) - set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") + add_compile_options(/J) # Similar to -funsigned-char on other platforms + set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") else() - set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") + set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") endif() include_directories(BEFORE From 8e5b722145d86c33a53175ba47db38d1462e1f66 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 2 Aug 2023 13:03:36 -0700 Subject: [PATCH 233/343] bifcl: Remove usage of FindRequiredPackage --- tools/bifcl/CMakeLists.txt | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index 52210aec45..23d7c3b5b1 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -3,17 +3,8 @@ project(BifCl C CXX) include(cmake/CommonCMakeConfig.cmake) -include(FindRequiredPackage) - -FindRequiredPackage(BISON) -FindRequiredPackage(FLEX) - -if ( MISSING_PREREQS ) - foreach (prereq ${MISSING_PREREQ_DESCS}) - message(SEND_ERROR ${prereq}) - endforeach () - message(FATAL_ERROR "Configuration aborted due to missing prerequisites") -endif () +find_package(BISON REQUIRED) +find_package(FLEX REQUIRED) if (MSVC) add_compile_options(/J) # Similar to -funsigned-char on other platforms From f2cd4ae3e68ed5a9104bfedda7cb9388a9e07b0e Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 30 Oct 2023 13:04:05 -0700 Subject: [PATCH 234/343] bifcl: Reformat Bifcl in Spicy style --- tools/bifcl/CMakeLists.txt | 91 +++++++++++----------- tools/bifcl/bif_arg.cc | 140 +++++++++++++++------------------- tools/bifcl/include/bif_arg.h | 42 +++++----- tools/bifcl/module_util.cc | 78 +++++++++---------- 4 files changed, 164 insertions(+), 187 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index 23d7c3b5b1..49327b4ac6 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -6,73 +6,74 @@ include(cmake/CommonCMakeConfig.cmake) find_package(BISON REQUIRED) find_package(FLEX REQUIRED) -if (MSVC) +if(MSVC) add_compile_options(/J) # Similar to -funsigned-char on other platforms - set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") + set_property( + SOURCE bif_lex.cc + APPEND_STRING + PROPERTY COMPILE_FLAGS "/wd4018") else() - set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") + set_property( + SOURCE bif_lex.cc + APPEND_STRING + PROPERTY COMPILE_FLAGS "-Wno-sign-compare") endif() -include_directories(BEFORE - ${BifCl_SOURCE_DIR}/include - ${BifCl_BINARY_DIR} -) +include_directories(BEFORE ${BifCl_SOURCE_DIR}/include ${BifCl_BINARY_DIR}) set(BISON_FLAGS "--debug") # BIF parser/scanner -bison_target(BIFParser builtin-func.y - ${BifCl_BINARY_DIR}/bif_parse.cc - DEFINES_FILE ${BifCl_BINARY_DIR}/bif_parse.h - COMPILE_FLAGS "${BISON_FLAGS}") +bison_target( + BIFParser builtin-func.y ${BifCl_BINARY_DIR}/bif_parse.cc + DEFINES_FILE ${BifCl_BINARY_DIR}/bif_parse.h + COMPILE_FLAGS "${BISON_FLAGS}") flex_target(BIFScanner builtin-func.l ${BifCl_BINARY_DIR}/bif_lex.cc) add_flex_bison_dependency(BIFScanner BIFParser) set(bifcl_SRCS - ${BISON_BIFParser_INPUT} - ${FLEX_BIFScanner_INPUT} - ${BISON_BIFParser_OUTPUTS} - ${FLEX_BIFScanner_OUTPUTS} - bif_arg.cc - include/bif_arg.h - module_util.cc - include/module_util.h -) + ${BISON_BIFParser_INPUT} + ${FLEX_BIFScanner_INPUT} + ${BISON_BIFParser_OUTPUTS} + ${FLEX_BIFScanner_OUTPUTS} + bif_arg.cc + include/bif_arg.h + module_util.cc + include/module_util.h) add_executable(bifcl ${bifcl_SRCS}) target_compile_features(bifcl PRIVATE cxx_std_17) set_target_properties(bifcl PROPERTIES CXX_EXTENSIONS OFF) -if (MSVC) - # If building separately from zeek, we need to add the libunistd subdirectory so - # that linking doesn't fail. - if ("${CMAKE_PROJECT_NAME}" STREQUAL "BifCl") - add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) - endif() - target_link_libraries(bifcl PRIVATE libunistd) +if(MSVC) + # If building separately from zeek, we need to add the libunistd subdirectory + # so that linking doesn't fail. + if("${CMAKE_PROJECT_NAME}" STREQUAL "BifCl") + add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) + endif() + target_link_libraries(bifcl PRIVATE libunistd) endif() install(TARGETS bifcl DESTINATION bin) -if (CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) -endif () +if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) +endif() message( - "\n====================| Bifcl Build Summary |=====================" - "\n" - "\nBuild type: ${CMAKE_BUILD_TYPE}" - "\nBuild dir: ${PROJECT_BINARY_DIR}" - "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" - "\nDebug mode: ${ENABLE_DEBUG}" - "\n" - "\nCC: ${CMAKE_C_COMPILER}" - "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" - "\nCXX: ${CMAKE_CXX_COMPILER}" - "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" - "\nCPP: ${CMAKE_CXX_COMPILER}" - "\n" - "\n================================================================\n" -) + "\n====================| Bifcl Build Summary |=====================" + "\n" + "\nBuild type: ${CMAKE_BUILD_TYPE}" + "\nBuild dir: ${PROJECT_BINARY_DIR}" + "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nDebug mode: ${ENABLE_DEBUG}" + "\n" + "\nCC: ${CMAKE_C_COMPILER}" + "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" + "\nCXX: ${CMAKE_CXX_COMPILER}" + "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" + "\nCPP: ${CMAKE_CXX_COMPILER}" + "\n" + "\n================================================================\n") include(UserChangedWarning) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index 735b5ff329..a0196d7bf9 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -7,93 +7,79 @@ using namespace std; #include "bif_arg.h" -static struct - { - const char* type_enum; - const char* bif_type; - const char* zeek_type; - const char* c_type; - const char* c_type_smart; - const char* accessor; - const char* accessor_smart; - const char* cast_smart; - const char* constructor; - const char* ctor_smart; - } builtin_func_arg_type[] = { -#define DEFINE_BIF_TYPE(id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, \ - cast_smart, constructor, ctor_smart) \ - {#id, bif_type, zeek_type, c_type, c_type_smart, \ - accessor, accessor_smart, cast_smart, constructor, ctor_smart}, +static struct { + const char* type_enum; + const char* bif_type; + const char* zeek_type; + const char* c_type; + const char* c_type_smart; + const char* accessor; + const char* accessor_smart; + const char* cast_smart; + const char* constructor; + const char* ctor_smart; +} builtin_func_arg_type[] = { +#define DEFINE_BIF_TYPE(id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, \ + constructor, ctor_smart) \ + {#id, bif_type, zeek_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, constructor, ctor_smart}, #include "bif_type.def" #undef DEFINE_BIF_TYPE - }; +}; extern const char* arg_list_name; -BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, int arg_type) - { - name = arg_name; - type = arg_type; - type_str = ""; - attr_str = ""; - } +BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, int arg_type) { + name = arg_name; + type = arg_type; + type_str = ""; + attr_str = ""; +} -BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, const char* arg_type_str, - const char* arg_attr_str) - { - name = arg_name; - type = TYPE_OTHER; - type_str = arg_type_str; - attr_str = arg_attr_str; +BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, const char* arg_type_str, const char* arg_attr_str) { + name = arg_name; + type = TYPE_OTHER; + type_str = arg_type_str; + attr_str = arg_attr_str; - for ( int i = 0; builtin_func_arg_type[i].bif_type[0] != '\0'; ++i ) - if ( ! strcmp(builtin_func_arg_type[i].bif_type, arg_type_str) ) - { - type = i; - type_str = ""; - } - } + for ( int i = 0; builtin_func_arg_type[i].bif_type[0] != '\0'; ++i ) + if ( ! strcmp(builtin_func_arg_type[i].bif_type, arg_type_str) ) { + type = i; + type_str = ""; + } +} -void BuiltinFuncArg::PrintZeek(FILE* fp) - { - fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].zeek_type, type_str, attr_str); - } +void BuiltinFuncArg::PrintZeek(FILE* fp) { + fprintf(fp, "%s: %s%s %s", name, builtin_func_arg_type[type].zeek_type, type_str, attr_str); +} -void BuiltinFuncArg::PrintCDef(FILE* fp, int n, bool runtime_type_check) - { - // Generate a runtime type-check pre-amble for types we understand - if ( runtime_type_check && type != TYPE_OTHER && type != TYPE_ANY ) - { - fprintf(fp, "\t\t{\n"); - fprintf(fp, "\t\t// Runtime type check for %s argument\n", name); - fprintf(fp, "\t\tzeek::TypeTag __tag = (*%s)[%d]->GetType()->Tag();\n", arg_list_name, n); - fprintf(fp, "\t\tif ( __tag != %s )\n", builtin_func_arg_type[type].type_enum); - fprintf(fp, "\t\t\t{\n"); - fprintf(fp, - "\t\t\tzeek::emit_builtin_error(zeek::util::fmt(\"expected type %s for %s, got " - "%%s\", zeek::type_name(__tag)));\n", - builtin_func_arg_type[type].zeek_type, name); - fprintf(fp, "\t\t\treturn nullptr;\n"); - fprintf(fp, "\t\t\t}\n"); - fprintf(fp, "\t\t}\n"); - } - fprintf(fp, "\t%s %s = (%s) (", builtin_func_arg_type[type].c_type, name, - builtin_func_arg_type[type].c_type); +void BuiltinFuncArg::PrintCDef(FILE* fp, int n, bool runtime_type_check) { + // Generate a runtime type-check pre-amble for types we understand + if ( runtime_type_check && type != TYPE_OTHER && type != TYPE_ANY ) { + fprintf(fp, "\t\t{\n"); + fprintf(fp, "\t\t// Runtime type check for %s argument\n", name); + fprintf(fp, "\t\tzeek::TypeTag __tag = (*%s)[%d]->GetType()->Tag();\n", arg_list_name, n); + fprintf(fp, "\t\tif ( __tag != %s )\n", builtin_func_arg_type[type].type_enum); + fprintf(fp, "\t\t\t{\n"); + fprintf(fp, + "\t\t\tzeek::emit_builtin_error(zeek::util::fmt(\"expected type %s for %s, got " + "%%s\", zeek::type_name(__tag)));\n", + builtin_func_arg_type[type].zeek_type, name); + fprintf(fp, "\t\t\treturn nullptr;\n"); + fprintf(fp, "\t\t\t}\n"); + fprintf(fp, "\t\t}\n"); + } + fprintf(fp, "\t%s %s = (%s) (", builtin_func_arg_type[type].c_type, name, builtin_func_arg_type[type].c_type); - char buf[1024]; - snprintf(buf, sizeof(buf), "(*%s)[%d].get()", arg_list_name, n); - // Print the accessor expression. - fprintf(fp, builtin_func_arg_type[type].accessor, buf); + char buf[1024]; + snprintf(buf, sizeof(buf), "(*%s)[%d].get()", arg_list_name, n); + // Print the accessor expression. + fprintf(fp, builtin_func_arg_type[type].accessor, buf); - fprintf(fp, ");\n"); - } + fprintf(fp, ");\n"); +} -void BuiltinFuncArg::PrintCArg(FILE* fp, int n) - { - fprintf(fp, "%s %s", builtin_func_arg_type[type].c_type_smart, name); - } +void BuiltinFuncArg::PrintCArg(FILE* fp, int n) { + fprintf(fp, "%s %s", builtin_func_arg_type[type].c_type_smart, name); +} -void BuiltinFuncArg::PrintValConstructor(FILE* fp) - { - fprintf(fp, builtin_func_arg_type[type].ctor_smart, name); - } +void BuiltinFuncArg::PrintValConstructor(FILE* fp) { fprintf(fp, builtin_func_arg_type[type].ctor_smart, name); } diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index 67df7be12d..f983e89dd6 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -2,36 +2,34 @@ #include -enum builtin_func_arg_type - { -#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, \ - cast_smart, constructor, ctor_smart) \ - id, +enum builtin_func_arg_type { +#define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, \ + constructor, ctor_smart) \ + id, #include "bif_type.def" #undef DEFINE_BIF_TYPE - }; +}; extern const char* builtin_func_arg_type_bro_name[]; -class BuiltinFuncArg final - { +class BuiltinFuncArg final { public: - BuiltinFuncArg(const char* arg_name, int arg_type); - BuiltinFuncArg(const char* arg_name, const char* arg_type_str, const char* arg_attr_str = ""); + BuiltinFuncArg(const char* arg_name, int arg_type); + BuiltinFuncArg(const char* arg_name, const char* arg_type_str, const char* arg_attr_str = ""); - void SetAttrStr(const char* arg_attr_str) { attr_str = arg_attr_str; }; + void SetAttrStr(const char* arg_attr_str) { attr_str = arg_attr_str; }; - const char* Name() const { return name; } - int Type() const { return type; } + const char* Name() const { return name; } + int Type() const { return type; } - void PrintZeek(FILE* fp); - void PrintCDef(FILE* fp, int n, bool runtime_type_check = false); - void PrintCArg(FILE* fp, int n); - void PrintValConstructor(FILE* fp); + void PrintZeek(FILE* fp); + void PrintCDef(FILE* fp, int n, bool runtime_type_check = false); + void PrintCArg(FILE* fp, int n); + void PrintValConstructor(FILE* fp); private: - const char* name; - int type; - const char* type_str; - const char* attr_str; - }; + const char* name; + int type; + const char* type_str; + const char* attr_str; +}; diff --git a/tools/bifcl/module_util.cc b/tools/bifcl/module_util.cc index f2fd445eff..27e1141fde 100644 --- a/tools/bifcl/module_util.cc +++ b/tools/bifcl/module_util.cc @@ -6,61 +6,53 @@ #include #include -static int streq(const char* s1, const char* s2) - { - return ! strcmp(s1, s2); - } +static int streq(const char* s1, const char* s2) { return ! strcmp(s1, s2); } // Returns it without trailing "::". -string extract_module_name(const char* name) - { - string module_name = name; - string::size_type pos = module_name.rfind("::"); +string extract_module_name(const char* name) { + string module_name = name; + string::size_type pos = module_name.rfind("::"); - if ( pos == string::npos ) - return string(GLOBAL_MODULE_NAME); + if ( pos == string::npos ) + return string(GLOBAL_MODULE_NAME); - module_name.erase(pos); + module_name.erase(pos); - return module_name; - } + return module_name; +} -string extract_var_name(const char* name) - { - string var_name = name; - string::size_type pos = var_name.rfind("::"); +string extract_var_name(const char* name) { + string var_name = name; + string::size_type pos = var_name.rfind("::"); - if ( pos == string::npos ) - return var_name; + if ( pos == string::npos ) + return var_name; - if ( pos + 2 > var_name.size() ) - return string(""); + if ( pos + 2 > var_name.size() ) + return string(""); - return var_name.substr(pos + 2); - } + return var_name.substr(pos + 2); +} -string normalized_module_name(const char* module_name) - { - int mod_len; - if ( (mod_len = strlen(module_name)) >= 2 && streq(module_name + mod_len - 2, "::") ) - mod_len -= 2; +string normalized_module_name(const char* module_name) { + int mod_len; + if ( (mod_len = strlen(module_name)) >= 2 && streq(module_name + mod_len - 2, "::") ) + mod_len -= 2; - return string(module_name, mod_len); - } + return string(module_name, mod_len); +} -string make_full_var_name(const char* module_name, const char* var_name) - { - if ( ! module_name || streq(module_name, GLOBAL_MODULE_NAME) || strstr(var_name, "::") ) - { - if ( streq(GLOBAL_MODULE_NAME, extract_module_name(var_name).c_str()) ) - return extract_var_name(var_name); +string make_full_var_name(const char* module_name, const char* var_name) { + if ( ! module_name || streq(module_name, GLOBAL_MODULE_NAME) || strstr(var_name, "::") ) { + if ( streq(GLOBAL_MODULE_NAME, extract_module_name(var_name).c_str()) ) + return extract_var_name(var_name); - return string(var_name); - } + return string(var_name); + } - string full_name = normalized_module_name(module_name); - full_name += "::"; - full_name += var_name; + string full_name = normalized_module_name(module_name); + full_name += "::"; + full_name += var_name; - return full_name; - } + return full_name; +} From dac04be85994bd3ff4b3a91006e7b1e815a910d0 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 16 Jan 2024 17:15:05 -0700 Subject: [PATCH 235/343] bifcl: Make BIFs just return ValPtr directly instead of BifReturnVal --- tools/bifcl/builtin-func.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 87144e18b7..5dac0d08d4 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -594,11 +594,11 @@ head_1: TOK_ID opt_ws arg_begin // (e.g. ones at global scope that may be used to implement // the BIF itself). fprintf(fp_func_h, - "namespace zeek { %sextern zeek::detail::BifReturnVal %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", + "namespace zeek { %sextern zeek::ValPtr %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, - "zeek::detail::BifReturnVal zeek::%s_bif(zeek::detail::Frame* frame, const zeek::Args* %s)", + "zeek::ValPtr zeek::%s_bif(zeek::detail::Frame* frame, const zeek::Args* %s)", decl.c_fullname.c_str(), arg_list_name); record_bif_item(decl.zeek_fullname.c_str(), "FUNCTION"); From d2edc334ad73377b86ecebdf7bbbe2cc9e5f2cd2 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 8 Jan 2024 17:18:24 -0700 Subject: [PATCH 236/343] bifcl: Add #pragma once to generated headers --- tools/bifcl/builtin-func.l | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index 063a394cfb..daba11585f 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -215,6 +215,7 @@ void init_alternative_mode() fprintf(fp_zeek_init, "# %s\n\n", auto_gen_comment); fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_h, "#pragma once\n\n"); fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); if ( fp_func_register ) @@ -387,9 +388,11 @@ int main(int argc, char* argv[]) fprintf(fp_zeek_init, "# %s\n\n", auto_gen_comment); fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_h, "#pragma once\n\n"); fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); fprintf(fp_netvar_def, "// %s\n\n", auto_gen_comment); fprintf(fp_netvar_h, "// %s\n\n", auto_gen_comment); + fprintf(fp_netvar_h, "#pragma once\n\n"); fprintf(fp_netvar_init, "// %s\n\n", auto_gen_comment); } From 2f97833acd97cf2d4dea54edd1f9796f4183d03a Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 6 Mar 2025 12:46:36 -0700 Subject: [PATCH 237/343] bifcl: Switch namespacing in generated code to C++-17-style nested namespaces --- tools/bifcl/builtin-func.y | 82 +++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 5dac0d08d4..c8de523d24 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -96,20 +96,17 @@ void set_decl_name(const char *name) switch ( definition_type ) { case TYPE_DEF: - decl.c_namespace_start = "namespace BifType { namespace " + type_name + "{ "; - decl.c_namespace_end = " } }"; + decl.c_namespace_start = "BifType::" + type_name + ""; decl.c_fullname = "BifType::" + type_name + "::"; break; case CONST_DEF: - decl.c_namespace_start = "namespace BifConst { "; - decl.c_namespace_end = " } "; + decl.c_namespace_start = "BifConst"; decl.c_fullname = "BifConst::"; break; case FUNC_DEF: - decl.c_namespace_start = "namespace BifFunc { "; - decl.c_namespace_end = " } "; + decl.c_namespace_start = "BifFunc"; decl.c_fullname = "BifFunc::"; break; @@ -117,8 +114,7 @@ void set_decl_name(const char *name) decl.c_namespace_start = ""; decl.c_namespace_end = ""; decl.c_fullname = "::"; // need this for namespace qualified events due do event_c_body - decl.enqueue_c_namespace_start = "namespace BifEvent { "; - decl.enqueue_c_namespace_end = " } "; + decl.enqueue_c_namespace_start = "BifEvent"; decl.enqueue_c_fullname = "zeek::BifEvent::"; break; @@ -128,13 +124,25 @@ void set_decl_name(const char *name) if ( decl.module_name != GLOBAL_MODULE_NAME ) { - decl.c_namespace_start += "namespace " + decl.module_name + " { "; - decl.c_namespace_end += string(" }"); + if ( decl.c_namespace_start.empty() ) { + decl.c_namespace_start += "namespace " + decl.module_name + " { "; + decl.c_namespace_end += " }"; + } + else { + decl.c_namespace_start += "::" + decl.module_name; + decl.c_namespace_end = ""; + } decl.c_fullname += decl.module_name + "::"; decl.zeek_fullname += decl.module_name + "::"; - decl.enqueue_c_namespace_start += "namespace " + decl.module_name + " { "; - decl.enqueue_c_namespace_end += " } "; + if ( decl.enqueue_c_namespace_start.empty() ) { + decl.enqueue_c_namespace_start += "namespace " + decl.module_name + " { "; + decl.enqueue_c_namespace_end += " } "; + } + else { + decl.enqueue_c_namespace_start += "::" + decl.module_name; + decl.enqueue_c_namespace_end = ""; + } decl.enqueue_c_fullname += decl.module_name + "::"; } @@ -212,7 +220,7 @@ static void print_event_c_prototype_args(FILE* fp) static void print_event_c_prototype_header(FILE* fp) { - fprintf(fp, "namespace zeek { %s void %s(zeek::analyzer::Analyzer* analyzer%s", + fprintf(fp, "namespace zeek::%s { void %s(zeek::analyzer::Analyzer* analyzer%s", decl.enqueue_c_namespace_start.c_str(), decl.enqueue_c_barename.c_str(), args.size() ? ", " : "" ); @@ -359,16 +367,13 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' { set_decl_name($3); - fprintf(fp_netvar_h, "namespace zeek { %s extern zeek::IntrusivePtr %s; %s}\n", - decl.c_namespace_start.c_str(), type_name.c_str(), - decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_h, "namespace zeek::%s { extern zeek::IntrusivePtr %s; }\n", + decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str()); - fprintf(fp_netvar_def, "namespace zeek { %s zeek::IntrusivePtr %s; %s}\n", - decl.c_namespace_start.c_str(), type_name.c_str(), - decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s zeek::%sType * %s; %s\n", - decl.c_namespace_start.c_str(), type_name.c_str(), - decl.bare_name.c_str(), decl.c_namespace_end.c_str()); + fprintf(fp_netvar_def, "namespace zeek::%s { zeek::IntrusivePtr %s; }\n", + decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str()); + fprintf(fp_netvar_def, "namespace %s { zeek::%sType * %s; }\n", + decl.c_namespace_start.c_str(), type_name.c_str(), decl.bare_name.c_str()); fprintf(fp_netvar_init, "\tzeek::%s = zeek::id::find_type(\"%s\");\n", @@ -417,17 +422,14 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list fprintf(fp_zeek_init, "} "); fprintf(fp_zeek_init, "%s", $4); fprintf(fp_zeek_init, ";\n"); - if ( decl.module_name != GLOBAL_MODULE_NAME ) - fprintf(fp_netvar_h, "}; } }\n"); - else - fprintf(fp_netvar_h, "}; }\n"); + fprintf(fp_netvar_h, "}; }\n"); // Now generate the netvar's. - fprintf(fp_netvar_h, "namespace zeek { %s extern zeek::IntrusivePtr %s; %s}\n", + fprintf(fp_netvar_h, "namespace zeek::%s { extern zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "namespace zeek { %s zeek::IntrusivePtr %s; %s}\n", + fprintf(fp_netvar_def, "namespace zeek::%s { zeek::IntrusivePtr %s; %s}\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s zeek::EnumType * %s; %s\n", + fprintf(fp_netvar_def, "namespace %s { zeek::EnumType * %s; %s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_netvar_init, @@ -447,9 +449,10 @@ enum_def_1: TOK_ENUM opt_ws TOK_ID opt_ws TOK_LPB opt_ws // this is the namespace were the enumerators are defined, not where // the type is defined. // We don't support fully qualified names as enumerators. Use a module name - fprintf(fp_netvar_h, "namespace BifEnum { "); if ( decl.module_name != GLOBAL_MODULE_NAME ) - fprintf(fp_netvar_h, "namespace %s { ", decl.module_name.c_str()); + fprintf(fp_netvar_h, "namespace BifEnum::%s { ", decl.module_name.c_str()); + else + fprintf(fp_netvar_h, "namespace BifEnum { "); fprintf(fp_netvar_h, "enum %s {\n", $3); } ; @@ -480,19 +483,16 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' snprintf(accessor_smart, sizeof(accessor_smart), builtin_types[typeidx].accessor_smart, ""); - fprintf(fp_netvar_h, "namespace zeek { %s extern %s %s; %s }\n", + fprintf(fp_netvar_h, "namespace zeek::%s { extern %s %s; }\n", decl.c_namespace_start.c_str(), - builtin_types[typeidx].c_type_smart, decl.bare_name.c_str(), - decl.c_namespace_end.c_str()); + builtin_types[typeidx].c_type_smart, decl.bare_name.c_str()); - fprintf(fp_netvar_def, "namespace zeek { %s %s %s; %s }\n", + fprintf(fp_netvar_def, "namespace zeek::%s { %s %s; }\n", decl.c_namespace_start.c_str(), - builtin_types[typeidx].c_type_smart, decl.bare_name.c_str(), - decl.c_namespace_end.c_str()); - fprintf(fp_netvar_def, "%s %s %s; %s\n", + builtin_types[typeidx].c_type_smart, decl.bare_name.c_str()); + fprintf(fp_netvar_def, "namespace %s { %s %s; } \n", decl.c_namespace_start.c_str(), - builtin_types[typeidx].c_type, decl.bare_name.c_str(), - decl.c_namespace_end.c_str()); + builtin_types[typeidx].c_type, decl.bare_name.c_str()); if ( alternative_mode && ! plugin ) fprintf(fp_netvar_init, "\tzeek::detail::bif_initializers.emplace_back([]()\n"); @@ -594,7 +594,7 @@ head_1: TOK_ID opt_ws arg_begin // (e.g. ones at global scope that may be used to implement // the BIF itself). fprintf(fp_func_h, - "namespace zeek { %sextern zeek::ValPtr %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", + "namespace zeek::%s { extern zeek::ValPtr %s_bif(zeek::detail::Frame* frame, const zeek::Args*);%s }\n", decl.c_namespace_start.c_str(), decl.bare_name.c_str(), decl.c_namespace_end.c_str()); fprintf(fp_func_def, From 234726dac7dee4152ee5506d9dff63a6f31860ed Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 6 Mar 2025 12:47:29 -0700 Subject: [PATCH 238/343] bifcl: Reformat CMakeLists via pre-commit --- tools/bifcl/CMakeLists.txt | 74 +++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index 49327b4ac6..cc5f24d051 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -6,28 +6,20 @@ include(cmake/CommonCMakeConfig.cmake) find_package(BISON REQUIRED) find_package(FLEX REQUIRED) -if(MSVC) - add_compile_options(/J) # Similar to -funsigned-char on other platforms - set_property( - SOURCE bif_lex.cc - APPEND_STRING - PROPERTY COMPILE_FLAGS "/wd4018") -else() - set_property( - SOURCE bif_lex.cc - APPEND_STRING - PROPERTY COMPILE_FLAGS "-Wno-sign-compare") -endif() +if (MSVC) + add_compile_options(/J) # Similar to -funsigned-char on other platforms + set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") +else () + set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") +endif () include_directories(BEFORE ${BifCl_SOURCE_DIR}/include ${BifCl_BINARY_DIR}) set(BISON_FLAGS "--debug") # BIF parser/scanner -bison_target( - BIFParser builtin-func.y ${BifCl_BINARY_DIR}/bif_parse.cc - DEFINES_FILE ${BifCl_BINARY_DIR}/bif_parse.h - COMPILE_FLAGS "${BISON_FLAGS}") +bison_target(BIFParser builtin-func.y ${BifCl_BINARY_DIR}/bif_parse.cc + DEFINES_FILE ${BifCl_BINARY_DIR}/bif_parse.h COMPILE_FLAGS "${BISON_FLAGS}") flex_target(BIFScanner builtin-func.l ${BifCl_BINARY_DIR}/bif_lex.cc) add_flex_bison_dependency(BIFScanner BIFParser) @@ -45,35 +37,35 @@ add_executable(bifcl ${bifcl_SRCS}) target_compile_features(bifcl PRIVATE cxx_std_17) set_target_properties(bifcl PROPERTIES CXX_EXTENSIONS OFF) -if(MSVC) - # If building separately from zeek, we need to add the libunistd subdirectory - # so that linking doesn't fail. - if("${CMAKE_PROJECT_NAME}" STREQUAL "BifCl") - add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) - endif() - target_link_libraries(bifcl PRIVATE libunistd) -endif() +if (MSVC) + # If building separately from zeek, we need to add the libunistd subdirectory + # so that linking doesn't fail. + if ("${CMAKE_PROJECT_NAME}" STREQUAL "BifCl") + add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) + endif () + target_link_libraries(bifcl PRIVATE libunistd) +endif () install(TARGETS bifcl DESTINATION bin) -if(CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) -endif() +if (CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) +endif () message( - "\n====================| Bifcl Build Summary |=====================" - "\n" - "\nBuild type: ${CMAKE_BUILD_TYPE}" - "\nBuild dir: ${PROJECT_BINARY_DIR}" - "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" - "\nDebug mode: ${ENABLE_DEBUG}" - "\n" - "\nCC: ${CMAKE_C_COMPILER}" - "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" - "\nCXX: ${CMAKE_CXX_COMPILER}" - "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" - "\nCPP: ${CMAKE_CXX_COMPILER}" - "\n" - "\n================================================================\n") + "\n====================| Bifcl Build Summary |=====================" + "\n" + "\nBuild type: ${CMAKE_BUILD_TYPE}" + "\nBuild dir: ${PROJECT_BINARY_DIR}" + "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nDebug mode: ${ENABLE_DEBUG}" + "\n" + "\nCC: ${CMAKE_C_COMPILER}" + "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" + "\nCXX: ${CMAKE_CXX_COMPILER}" + "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" + "\nCPP: ${CMAKE_CXX_COMPILER}" + "\n" + "\n================================================================\n") include(UserChangedWarning) From 75a8814cee6e3d1263cbc4de9123b6aeef4c3efb Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 9 May 2025 14:56:35 -0700 Subject: [PATCH 239/343] bifcl: Switch more namespacing in generated code to nested style --- tools/bifcl/builtin-func.l | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index daba11585f..a2e73e8a46 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -277,17 +277,17 @@ void init_alternative_mode() fprintf(fp_func_init, "#include \"zeek/Func.h\"\n"); fprintf(fp_func_init, "#include \"%s.h\"\n", input_filename); fprintf(fp_func_init, "\n"); - fprintf(fp_func_init, "namespace plugin { namespace %s {\n", plugin_canon); + fprintf(fp_func_init, "namespace plugin::%s {\n", plugin_canon); fprintf(fp_func_init, "\n"); fprintf(fp_func_init, "void __bif_%s_init(zeek::plugin::Plugin* plugin)\n", name); fprintf(fp_func_init, "\t{\n"); fprintf(fp_func_register, "#include \"zeek/plugin/Manager.h\"\n"); fprintf(fp_func_register, "\n"); - fprintf(fp_func_register, "namespace plugin { namespace %s {\n", plugin_canon); + fprintf(fp_func_register, "namespace plugin::%s {\n", plugin_canon); fprintf(fp_func_register, "void __bif_%s_init(zeek::plugin::Plugin* plugin);\n", name); fprintf(fp_func_register, "zeek::plugin::detail::__RegisterBif __register_bifs_%s_%s(\"%s\", __bif_%s_init);\n", plugin_canon, name, plugin, name); - fprintf(fp_func_register, "} }\n"); + fprintf(fp_func_register, "}\n"); } } @@ -300,7 +300,7 @@ void finish_alternative_mode() { fprintf(fp_func_init, "\n"); fprintf(fp_func_init, "\t}\n"); - fprintf(fp_func_init, "} }\n"); + fprintf(fp_func_init, "}\n"); fprintf(fp_func_init, "\n"); fprintf(fp_func_init, "\n"); } From c30aa7a903bc8164688fd735b721ac25a77b7004 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 9 May 2025 15:01:03 -0700 Subject: [PATCH 240/343] bifcl: Don't do 'using namespace std' in headers, plus a little cleanup --- tools/bifcl/include/module_util.h | 10 ++++------ tools/bifcl/module_util.cc | 6 ++++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/bifcl/include/module_util.h b/tools/bifcl/include/module_util.h index fa5f24964f..7b85f81c23 100644 --- a/tools/bifcl/include/module_util.h +++ b/tools/bifcl/include/module_util.h @@ -6,14 +6,12 @@ #include -using namespace std; - static const char* GLOBAL_MODULE_NAME = "GLOBAL"; -extern string extract_module_name(const char* name); -extern string extract_var_name(const char* name); -extern string normalized_module_name(const char* module_name); // w/o :: +extern std::string extract_module_name(const char* name); +extern std::string extract_var_name(const char* name); +extern std::string normalized_module_name(const char* module_name); // w/o :: // Concatenates module_name::var_name unless var_name is already fully // qualified, in which case it is returned unmodified. -extern string make_full_var_name(const char* module_name, const char* var_name); +extern std::string make_full_var_name(const char* module_name, const char* var_name); diff --git a/tools/bifcl/module_util.cc b/tools/bifcl/module_util.cc index 27e1141fde..b3997cd1d6 100644 --- a/tools/bifcl/module_util.cc +++ b/tools/bifcl/module_util.cc @@ -3,9 +3,11 @@ #include "module_util.h" -#include +#include #include +using namespace std; + static int streq(const char* s1, const char* s2) { return ! strcmp(s1, s2); } // Returns it without trailing "::". @@ -36,7 +38,7 @@ string extract_var_name(const char* name) { string normalized_module_name(const char* module_name) { int mod_len; - if ( (mod_len = strlen(module_name)) >= 2 && streq(module_name + mod_len - 2, "::") ) + if ( mod_len = strlen(module_name); mod_len >= 2 && streq(module_name + mod_len - 2, "::") ) mod_len -= 2; return string(module_name, mod_len); From 7026938082bbd44a6a74fc669143083faf4a707c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 15 May 2025 17:21:58 -0700 Subject: [PATCH 241/343] bifcl: Pass boolean false to BuiltinFunc constructor instead of zero This fixes a modernize-use-bool-literals clang-tidy warning in the generated code. --- tools/bifcl/builtin-func.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index c8de523d24..901f7892fd 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -584,7 +584,7 @@ head_1: TOK_ID opt_ws arg_begin if ( definition_type == FUNC_DEF ) { fprintf(fp_func_init, - "\t(void) new zeek::detail::BuiltinFunc(zeek::%s_bif, \"%s\", 0);\n", + "\t(void) new zeek::detail::BuiltinFunc(zeek::%s_bif, \"%s\", false);\n", decl.c_fullname.c_str(), decl.zeek_fullname.c_str()); // This is the "canonical" version, with argument type and order From 23a5e46b8ebf43b2e16960949b7ee6218f3d5d18 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 21 May 2025 10:04:59 -0700 Subject: [PATCH 242/343] bifcl: Minor cleanup of include files --- tools/bifcl/bif_arg.cc | 9 ++------- tools/bifcl/builtin-func.l | 8 ++++---- tools/bifcl/builtin-func.y | 7 +++---- tools/bifcl/include/bif_arg.h | 3 ++- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index a0196d7bf9..920846e4a8 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -1,12 +1,7 @@ - -#include -#include -using namespace std; - -#include - #include "bif_arg.h" +#include + static struct { const char* type_enum; const char* bif_type; diff --git a/tools/bifcl/builtin-func.l b/tools/bifcl/builtin-func.l index a2e73e8a46..9b4d4628e1 100644 --- a/tools/bifcl/builtin-func.l +++ b/tools/bifcl/builtin-func.l @@ -1,15 +1,15 @@ %top{ -// Include stdint.h at the start of the generated file. Typically +// Include cstdint at the start of the generated file. Typically // MSVC will include this header later, after the definitions of // the integral type macros. MSVC then complains that about the -// redefinition of the types. Including stdint.h early avoids this. -#include +// redefinition of the types. Including cstdint early avoids this. +#include } %{ #include -#include #include +#include #include #include "bif_arg.h" #include "bif_parse.h" diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 901f7892fd..46dd4fb4fa 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -1,11 +1,10 @@ %{ +#include +#include +#include #include #include #include -#include - -#include -#include #include "module_util.h" diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index f983e89dd6..7a62d34af8 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -1,6 +1,7 @@ #pragma once -#include +#include +#include enum builtin_func_arg_type { #define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, \ From 867d91b5350879d183a6c21024f113febc793624 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 21 May 2025 10:05:10 -0700 Subject: [PATCH 243/343] bifcl: Some other minor cleanup --- tools/bifcl/builtin-func.y | 2 +- tools/bifcl/include/bif_arg.h | 2 +- tools/bifcl/include/module_util.h | 2 +- tools/bifcl/module_util.cc | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 46dd4fb4fa..453b300eb1 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -37,7 +37,7 @@ string type_name; // already been defined/written to the C++ files. static std::set events; -enum { +enum : uint8_t { C_SEGMENT_DEF, FUNC_DEF, EVENT_DEF, diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index 7a62d34af8..a9febd013b 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -3,7 +3,7 @@ #include #include -enum builtin_func_arg_type { +enum builtin_func_arg_type : uint8_t { #define DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, c_type_smart, accessor, accessor_smart, cast_smart, \ constructor, ctor_smart) \ id, diff --git a/tools/bifcl/include/module_util.h b/tools/bifcl/include/module_util.h index 7b85f81c23..30015e527c 100644 --- a/tools/bifcl/include/module_util.h +++ b/tools/bifcl/include/module_util.h @@ -6,7 +6,7 @@ #include -static const char* GLOBAL_MODULE_NAME = "GLOBAL"; +static constexpr const char* GLOBAL_MODULE_NAME = "GLOBAL"; extern std::string extract_module_name(const char* name); extern std::string extract_var_name(const char* name); diff --git a/tools/bifcl/module_util.cc b/tools/bifcl/module_util.cc index b3997cd1d6..10ee280994 100644 --- a/tools/bifcl/module_util.cc +++ b/tools/bifcl/module_util.cc @@ -16,7 +16,7 @@ string extract_module_name(const char* name) { string::size_type pos = module_name.rfind("::"); if ( pos == string::npos ) - return string(GLOBAL_MODULE_NAME); + return GLOBAL_MODULE_NAME; module_name.erase(pos); @@ -31,17 +31,17 @@ string extract_var_name(const char* name) { return var_name; if ( pos + 2 > var_name.size() ) - return string(""); + return ""; return var_name.substr(pos + 2); } string normalized_module_name(const char* module_name) { - int mod_len; + size_t mod_len; if ( mod_len = strlen(module_name); mod_len >= 2 && streq(module_name + mod_len - 2, "::") ) mod_len -= 2; - return string(module_name, mod_len); + return {module_name, mod_len}; } string make_full_var_name(const char* module_name, const char* var_name) { @@ -49,7 +49,7 @@ string make_full_var_name(const char* module_name, const char* var_name) { if ( streq(GLOBAL_MODULE_NAME, extract_module_name(var_name).c_str()) ) return extract_var_name(var_name); - return string(var_name); + return var_name; } string full_name = normalized_module_name(module_name); From c63a22057921053aef1df5fae06625550e2b1520 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 2 Jun 2025 11:12:38 -0700 Subject: [PATCH 244/343] bifcl: Add missing include of cinttypes --- tools/bifcl/builtin-func.y | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 453b300eb1..64b8899164 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -1,4 +1,5 @@ %{ +#include #include #include #include From d8d87723425fbeeb0fbbce84c53712dadf00331b Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 9 Jun 2025 17:03:45 -0700 Subject: [PATCH 245/343] bifcl: Add NOLINT for clang-tidy performance-enum-size to generated headers --- tools/bifcl/builtin-func.y | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/bifcl/builtin-func.y b/tools/bifcl/builtin-func.y index 64b8899164..239a3117b3 100644 --- a/tools/bifcl/builtin-func.y +++ b/tools/bifcl/builtin-func.y @@ -422,7 +422,7 @@ enum_def: enum_def_1 enum_list TOK_RPB opt_attr_list fprintf(fp_zeek_init, "} "); fprintf(fp_zeek_init, "%s", $4); fprintf(fp_zeek_init, ";\n"); - fprintf(fp_netvar_h, "}; }\n"); + fprintf(fp_netvar_h, "}; }\n"); // Now generate the netvar's. fprintf(fp_netvar_h, "namespace zeek::%s { extern zeek::IntrusivePtr %s; %s}\n", @@ -449,10 +449,11 @@ enum_def_1: TOK_ENUM opt_ws TOK_ID opt_ws TOK_LPB opt_ws // this is the namespace were the enumerators are defined, not where // the type is defined. // We don't support fully qualified names as enumerators. Use a module name + fprintf(fp_netvar_h, "// NOLINTNEXTLINE(performance-enum-size)\n"); if ( decl.module_name != GLOBAL_MODULE_NAME ) fprintf(fp_netvar_h, "namespace BifEnum::%s { ", decl.module_name.c_str()); - else - fprintf(fp_netvar_h, "namespace BifEnum { "); + else + fprintf(fp_netvar_h, "namespace BifEnum { "); fprintf(fp_netvar_h, "enum %s {\n", $3); } ; From f6d9696bf16b693c5e22437a7bcf0b8570a0095c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 1 May 2024 15:33:16 -0700 Subject: [PATCH 246/343] bifcl: Require C++20 for builds --- tools/bifcl/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index cc5f24d051..e422a962d1 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR) project(BifCl C CXX) include(cmake/CommonCMakeConfig.cmake) +include(cmake/RequireCXXStd.cmake) find_package(BISON REQUIRED) find_package(FLEX REQUIRED) @@ -34,8 +35,6 @@ set(bifcl_SRCS include/module_util.h) add_executable(bifcl ${bifcl_SRCS}) -target_compile_features(bifcl PRIVATE cxx_std_17) -set_target_properties(bifcl PROPERTIES CXX_EXTENSIONS OFF) if (MSVC) # If building separately from zeek, we need to add the libunistd subdirectory From c618bb7a561994428dcdaa4d8d27a7a4d51a003c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sun, 17 Aug 2025 20:43:16 -0700 Subject: [PATCH 247/343] bifcl: Remove submodule, adapt CMake configuration for Zeek build --- .gitmodules | 3 -- CMakeLists.txt | 4 +- auxil/bifcl | 1 - tools/bifcl/CMakeLists.txt | 64 +++++-------------------------- tools/bifcl/bif_arg.cc | 2 + tools/bifcl/include/bif_arg.h | 2 + tools/bifcl/include/module_util.h | 2 + 7 files changed, 18 insertions(+), 60 deletions(-) delete mode 160000 auxil/bifcl diff --git a/.gitmodules b/.gitmodules index a83702e82a..53b0f86697 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,9 +19,6 @@ [submodule "auxil/netcontrol-connectors"] path = auxil/netcontrol-connectors url = https://github.com/zeek/zeek-netcontrol -[submodule "auxil/bifcl"] - path = auxil/bifcl - url = https://github.com/zeek/bifcl [submodule "doc"] path = doc url = https://github.com/zeek/zeek-docs diff --git a/CMakeLists.txt b/CMakeLists.txt index d2b4734d54..6e146f1a2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -904,11 +904,11 @@ set(_binpac_exe_path "included") find_package(BinPAC REQUIRED) add_executable(Zeek::BinPAC ALIAS binpac) -add_subdirectory(auxil/bifcl) +add_subdirectory(tools/bifcl) add_executable(Zeek::BifCl ALIAS bifcl) # FIXME: avoid hard-coding a path for multi-config generator support. See the # TODO in ZeekPluginConfig.cmake.in. -set(BIFCL_EXE_PATH "${CMAKE_BINARY_DIR}/auxil/bifcl/bifcl${CMAKE_EXECUTABLE_SUFFIX}") +set(BIFCL_EXE_PATH "${CMAKE_BINARY_DIR}/tools/bifcl/bifcl${CMAKE_EXECUTABLE_SUFFIX}") set(_bifcl_exe_path "included") if (NOT GEN_ZAM_EXE_PATH) diff --git a/auxil/bifcl b/auxil/bifcl deleted file mode 160000 index 5947749f78..0000000000 --- a/auxil/bifcl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5947749f7850b075f11d6a2aaefe7dad4f63cb62 diff --git a/tools/bifcl/CMakeLists.txt b/tools/bifcl/CMakeLists.txt index e422a962d1..9896236429 100644 --- a/tools/bifcl/CMakeLists.txt +++ b/tools/bifcl/CMakeLists.txt @@ -1,70 +1,26 @@ -cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR) -project(BifCl C CXX) - -include(cmake/CommonCMakeConfig.cmake) -include(cmake/RequireCXXStd.cmake) - find_package(BISON REQUIRED) find_package(FLEX REQUIRED) -if (MSVC) - add_compile_options(/J) # Similar to -funsigned-char on other platforms - set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "/wd4018") -else () - set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") -endif () - -include_directories(BEFORE ${BifCl_SOURCE_DIR}/include ${BifCl_BINARY_DIR}) - set(BISON_FLAGS "--debug") # BIF parser/scanner -bison_target(BIFParser builtin-func.y ${BifCl_BINARY_DIR}/bif_parse.cc - DEFINES_FILE ${BifCl_BINARY_DIR}/bif_parse.h COMPILE_FLAGS "${BISON_FLAGS}") -flex_target(BIFScanner builtin-func.l ${BifCl_BINARY_DIR}/bif_lex.cc) +bison_target(BIFParser builtin-func.y ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.cc + DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.h COMPILE_FLAGS "${BISON_FLAGS}") +flex_target(BIFScanner builtin-func.l ${CMAKE_CURRENT_BINARY_DIR}/bif_lex.cc) add_flex_bison_dependency(BIFScanner BIFParser) -set(bifcl_SRCS - ${BISON_BIFParser_INPUT} - ${FLEX_BIFScanner_INPUT} - ${BISON_BIFParser_OUTPUTS} - ${FLEX_BIFScanner_OUTPUTS} - bif_arg.cc - include/bif_arg.h - module_util.cc - include/module_util.h) +set(bifcl_SRCS ${BISON_BIFParser_INPUT} ${FLEX_BIFScanner_INPUT} ${BISON_BIFParser_OUTPUTS} + ${FLEX_BIFScanner_OUTPUTS} bif_arg.cc module_util.cc) add_executable(bifcl ${bifcl_SRCS}) +target_include_directories(bifcl BEFORE PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) if (MSVC) - # If building separately from zeek, we need to add the libunistd subdirectory - # so that linking doesn't fail. - if ("${CMAKE_PROJECT_NAME}" STREQUAL "BifCl") - add_subdirectory(auxil/libunistd EXCLUDE_FROM_ALL) - endif () + target_compile_options(bifcl PUBLIC "/J") # Similar to -funsigned-char on other platforms + target_compile_options(bifcl PUBLIC "/wd4018") # Similar to -Wno-sign-compare on other platforms target_link_libraries(bifcl PRIVATE libunistd) +else () + target_compile_options(bifcl PUBLIC "-Wno-sign-compare") endif () install(TARGETS bifcl DESTINATION bin) - -if (CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) -endif () - -message( - "\n====================| Bifcl Build Summary |=====================" - "\n" - "\nBuild type: ${CMAKE_BUILD_TYPE}" - "\nBuild dir: ${PROJECT_BINARY_DIR}" - "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" - "\nDebug mode: ${ENABLE_DEBUG}" - "\n" - "\nCC: ${CMAKE_C_COMPILER}" - "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" - "\nCXX: ${CMAKE_CXX_COMPILER}" - "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" - "\nCPP: ${CMAKE_CXX_COMPILER}" - "\n" - "\n================================================================\n") - -include(UserChangedWarning) diff --git a/tools/bifcl/bif_arg.cc b/tools/bifcl/bif_arg.cc index 920846e4a8..a75d480b9a 100644 --- a/tools/bifcl/bif_arg.cc +++ b/tools/bifcl/bif_arg.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "bif_arg.h" #include diff --git a/tools/bifcl/include/bif_arg.h b/tools/bifcl/include/bif_arg.h index a9febd013b..57e38cbbd6 100644 --- a/tools/bifcl/include/bif_arg.h +++ b/tools/bifcl/include/bif_arg.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #pragma once #include diff --git a/tools/bifcl/include/module_util.h b/tools/bifcl/include/module_util.h index 30015e527c..92a4c7598a 100644 --- a/tools/bifcl/include/module_util.h +++ b/tools/bifcl/include/module_util.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + // // These functions are used by both Zeek and bifcl. // From c1f240295f63c077b5b062353e73657317e6fe90 Mon Sep 17 00:00:00 2001 From: Christian Kreibich Date: Tue, 15 Mar 2022 21:34:17 -0700 Subject: [PATCH 248/343] gen-zam: Move Gen-ZAM sources to src subdirectory --- tools/gen-zam/src/Gen-ZAM.cc | 2223 ++++++++++++++++++++++++++++++++++ tools/gen-zam/src/Gen-ZAM.h | 986 +++++++++++++++ 2 files changed, 3209 insertions(+) create mode 100644 tools/gen-zam/src/Gen-ZAM.cc create mode 100644 tools/gen-zam/src/Gen-ZAM.h diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc new file mode 100644 index 0000000000..92948b4d84 --- /dev/null +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -0,0 +1,2223 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "zeek/script_opt/ZAM/Gen-ZAM.h" + +#include +#include + +using namespace std; + +// Helper functions to convert dashes to underscores or vice versa. +static char dash_to_under(char c) + { + return c == '-' ? '_' : c; + } + +static char under_to_dash(char c) + { + return c == '_' ? '-' : c; + } + +// Structure for binding together Zeek script types, internal names Gen-ZAM +// uses to track them, mnemonics for referring to them in instruction names, +// the corresponding Val accessor, and whether the type requires memory +// management. +struct TypeInfo + { + string tag; + ZAM_ExprType et; + string suffix; + string accessor; // doesn't include "As" prefix or "()" suffix + bool is_managed; + }; + +static vector ZAM_type_info = { + {"TYPE_ADDR", ZAM_EXPR_TYPE_ADDR, "A", "Addr", true}, + {"TYPE_ANY", ZAM_EXPR_TYPE_ANY, "a", "Any", true}, + {"TYPE_COUNT", ZAM_EXPR_TYPE_UINT, "U", "Count", false}, + {"TYPE_DOUBLE", ZAM_EXPR_TYPE_DOUBLE, "D", "Double", false}, + {"TYPE_FILE", ZAM_EXPR_TYPE_FILE, "f", "File", true}, + {"TYPE_FUNC", ZAM_EXPR_TYPE_FUNC, "F", "Func", true}, + {"TYPE_INT", ZAM_EXPR_TYPE_INT, "I", "Int", false}, + {"TYPE_LIST", ZAM_EXPR_TYPE_LIST, "L", "List", true}, + {"TYPE_OPAQUE", ZAM_EXPR_TYPE_OPAQUE, "O", "Opaque", true}, + {"TYPE_PATTERN", ZAM_EXPR_TYPE_PATTERN, "P", "Pattern", true}, + {"TYPE_RECORD", ZAM_EXPR_TYPE_RECORD, "R", "Record", true}, + {"TYPE_STRING", ZAM_EXPR_TYPE_STRING, "S", "String", true}, + {"TYPE_SUBNET", ZAM_EXPR_TYPE_SUBNET, "N", "SubNet", true}, + {"TYPE_TABLE", ZAM_EXPR_TYPE_TABLE, "T", "Table", true}, + {"TYPE_TYPE", ZAM_EXPR_TYPE_TYPE, "t", "Type", true}, + {"TYPE_VECTOR", ZAM_EXPR_TYPE_VECTOR, "V", "Vector", true}, +}; + +// Given a ZAM_ExprType, returns the corresponding TypeInfo. +const TypeInfo& find_type_info(ZAM_ExprType et) + { + assert(et != ZAM_EXPR_TYPE_NONE); + + auto pred = [et](const TypeInfo& ti) -> bool + { + return ti.et == et; + }; + auto ti = std::find_if(ZAM_type_info.begin(), ZAM_type_info.end(), pred); + + assert(ti != ZAM_type_info.end()); + return *ti; + } + +// Given a ZAM_ExprType, return its ZVal accessor. Takes into account +// some naming inconsistencies between ZVal's and Val's. +string find_type_accessor(ZAM_ExprType et) + { + switch ( et ) + { + case ZAM_EXPR_TYPE_NONE: + return ""; + + case ZAM_EXPR_TYPE_UINT: + return "uint_val"; + + case ZAM_EXPR_TYPE_PATTERN: + return "re_val"; + + default: + { + string acc = find_type_info(et).accessor; + transform(acc.begin(), acc.end(), acc.begin(), ::tolower); + return acc + "_val"; + } + } + } + +// Maps ZAM operand types to pairs of (1) the C++ name used to declare +// the operand in a method declaration, and (2) the variable name to +// use for the operand. +unordered_map> ArgsManager::ot_to_args = { + {ZAM_OT_AUX, {"OpaqueVals*", "v"}}, + {ZAM_OT_CONSTANT, {"const ConstExpr*", "c"}}, + {ZAM_OT_EVENT_HANDLER, {"EventHandler*", "h"}}, + {ZAM_OT_INT, {"int", "i"}}, + {ZAM_OT_LIST, {"const ListExpr*", "l"}}, + {ZAM_OT_RECORD_FIELD, {"const NameExpr*", "n"}}, + {ZAM_OT_VAR, {"const NameExpr*", "n"}}, + + // The following gets special treatment. + {ZAM_OT_ASSIGN_FIELD, {"const NameExpr*", "n"}}, +}; + +ArgsManager::ArgsManager(const vector& ot, ZAM_InstClass zc) + { + int n = 0; + bool add_field = false; + + for ( const auto& ot_i : ot ) + { + if ( ot_i == ZAM_OT_NONE ) + { // it had better be the only operand type + assert(ot.size() == 1); + break; + } + + if ( n++ == 0 && zc == ZIC_COND ) + // Skip the conditional's nominal assignment slot. + continue; + + // Start off the argument info using the usual case + // of (1) same method parameter name as GenInst argument, + // and (2) not requiring a record field. + auto& arg_i = ot_to_args[ot_i]; + Arg arg = {arg_i.second, arg_i.first, arg_i.second, false}; + + if ( ot_i == ZAM_OT_ASSIGN_FIELD ) + { + arg.is_field = true; + + if ( n == 1 ) + { // special-case the parameter + arg.decl_name = "flhs"; + arg.decl_type = "const FieldLHSAssignExpr*"; + } + } + + args.emplace_back(move(arg)); + } + + Differentiate(); + } + +void ArgsManager::Differentiate() + { + // First, figure out which parameter names are used how often. + map name_count; // how often the name apepars + map usage_count; // how often the name's been used so far + for ( auto& arg : args ) + { + auto& name = arg.param_name; + if ( name_count.count(name) == 0 ) + { + name_count[name] = 1; + usage_count[name] = 0; + } + else + ++name_count[name]; + } + + // Now for each name - whether appearing as an argument or in + // a declaration - if it's used more than once, then differentiate + // it. Note, some names only appear multiple times as arguments + // when invoking methods, but not in the declarations of the methods + // themselves. + for ( auto& arg : args ) + { + auto& decl = arg.decl_name; + auto& name = arg.param_name; + bool decl_and_arg_same = decl == name; + + if ( name_count[name] == 1 ) + continue; // it's unique + + auto n = to_string(++usage_count[name]); + name += n; + if ( decl_and_arg_same ) + decl += n; + } + + // Finally, build the full versions of the declaration and parameters. + + // Tracks how many record fields we're dealing with. + int num_fields = 0; + + for ( auto& arg : args ) + { + if ( ! full_decl.empty() ) + full_decl += ", "; + + full_decl += arg.decl_type + " " + arg.decl_name; + + if ( ! full_params.empty() ) + full_params += ", "; + + full_params += arg.param_name; + params.push_back(arg.param_name); + + if ( arg.is_field ) + ++num_fields; + } + + assert(num_fields <= 2); + + // Add in additional arguments/parameters for record fields. + if ( num_fields == 1 ) + full_params += ", field"; + else if ( num_fields == 2 ) + { + full_decl += ", int field2"; + full_params += ", field1, field2"; + } + } + +ZAM_OpTemplate::ZAM_OpTemplate(ZAMGen* _g, string _base_name) : g(_g), base_name(move(_base_name)) + { + // Make the base name viable in a C++ name. + transform(base_name.begin(), base_name.end(), base_name.begin(), dash_to_under); + + cname = base_name; + transform(cname.begin(), cname.end(), cname.begin(), ::toupper); + } + +void ZAM_OpTemplate::Build() + { + op_loc = g->CurrLoc(); + + string line; + while ( g->ScanLine(line) ) + { + if ( line.size() <= 1 ) + break; + + auto words = g->SplitIntoWords(line); + if ( words.empty() ) + break; + + Parse(words[0], line, words); + } + } + +void ZAM_OpTemplate::Instantiate() + { + InstantiateOp(OperandTypes(), IncludesVectorOp()); + } + +void ZAM_OpTemplate::UnaryInstantiate() + { + // First operand is always the frame slot to which this operation + // assigns the result of the applying unary operator. + vector ots = {ZAM_OT_VAR}; + ots.resize(2); + + // Now build versions for a constant operand (maybe not actually + // needed due to constant folding, but sometimes that gets deferred + // to run-time) ... + if ( ! NoConst() ) + { + ots[1] = ZAM_OT_CONSTANT; + InstantiateOp(ots, IncludesVectorOp()); + } + + // ... and for a variable (frame-slot) operand. + ots[1] = ZAM_OT_VAR; + InstantiateOp(ots, IncludesVectorOp()); + } + +void ZAM_OpTemplate::Parse(const string& attr, const string& line, const Words& words) + { + int num_args = -1; // -1 = don't enforce + int nwords = words.size(); + + if ( attr == "type" ) + { + if ( nwords <= 1 ) + g->Gripe("missing argument", line); + + num_args = 1; + + const char* types = words[1].c_str(); + while ( *types ) + { + ZAM_OperandType ot = ZAM_OT_NONE; + switch ( *types ) + { + case 'C': + ot = ZAM_OT_CONSTANT; + break; + case 'F': + ot = ZAM_OT_ASSIGN_FIELD; + break; + case 'H': + ot = ZAM_OT_EVENT_HANDLER; + break; + case 'L': + ot = ZAM_OT_LIST; + break; + case 'O': + ot = ZAM_OT_AUX; + break; + case 'R': + ot = ZAM_OT_RECORD_FIELD; + break; + case 'V': + ot = ZAM_OT_VAR; + break; + case 'i': + ot = ZAM_OT_INT; + break; + + case 'X': + ot = ZAM_OT_NONE; + break; + + default: + g->Gripe("bad operand type", words[1]); + break; + } + + AddOpType(ot); + + ++types; + } + } + + else if ( attr == "op1-read" ) + { + num_args = 0; + SetOp1Flavor("OP1_READ"); + } + + else if ( attr == "op1-read-write" ) + { + num_args = 0; + SetOp1Flavor("OP1_READ_WRITE"); + } + + else if ( attr == "op1-internal" ) + { + num_args = 0; + SetOp1Flavor("OP1_INTERNAL"); + } + + else if ( attr == "set-type" ) + { + num_args = 1; + if ( nwords > 1 ) + SetTypeParam(ExtractTypeParam(words[1])); + } + + else if ( attr == "set-type2" ) + { + num_args = 1; + if ( nwords > 1 ) + SetType2Param(ExtractTypeParam(words[1])); + } + + else if ( attr == "custom-method" ) + SetCustomMethod(g->SkipWords(line, 1)); + + else if ( attr == "method-post" ) + SetPostMethod(g->SkipWords(line, 1)); + + else if ( attr == "side-effects" ) + { + if ( nwords == 3 ) + SetAssignmentLess(words[1], words[2]); + else + // otherwise shouldn't be any arguments + num_args = 0; + + SetHasSideEffects(); + } + + else if ( attr == "no-eval" ) + { + num_args = 0; + SetNoEval(); + } + + else if ( attr == "vector" ) + { + num_args = 0; + SetIncludesVectorOp(); + } + + else if ( attr == "assign-val" ) + { + num_args = 1; + if ( words.size() > 1 ) + SetAssignVal(words[1]); + } + + else if ( attr == "eval" ) + { + AddEval(g->SkipWords(line, 1)); + + auto addl = GatherEval(); + if ( ! addl.empty() ) + AddEval(addl); + } + + else if ( attr == "macro" ) + g->ReadMacro(line); + + else + g->Gripe("unknown template attribute", attr); + + if ( num_args >= 0 && num_args != nwords - 1 ) + g->Gripe("extraneous or missing arguments", line); + } + +string ZAM_OpTemplate::GatherEval() + { + string res; + string l; + while ( g->ScanLine(l) ) + { + if ( l.size() <= 1 || ! isspace(l.c_str()[0]) ) + { + g->PutBack(l); + return res; + } + + res += l; + } + + return res; + } + +int ZAM_OpTemplate::ExtractTypeParam(const string& arg) + { + if ( arg == "$$" ) + return 1; + + if ( arg[0] != '$' ) + g->Gripe("bad set-type parameter, should be $n", arg); + + int param = atoi(&arg[1]); + + if ( param <= 0 || param > 2 ) + g->Gripe("bad set-type parameter, should be $1 or $2", arg); + + // Convert operand to underlying instruction element, i.e., add + // one to account for the $$ assignment slot. + return param + 1; + } + +// Maps an operand type to a character mnemonic used to distinguish +// it from others. +unordered_map ZAM_OpTemplate::ot_to_char = { + {ZAM_OT_AUX, 'O'}, {ZAM_OT_CONSTANT, 'C'}, {ZAM_OT_EVENT_HANDLER, 'H'}, + {ZAM_OT_ASSIGN_FIELD, 'F'}, {ZAM_OT_INT, 'i'}, {ZAM_OT_LIST, 'L'}, + {ZAM_OT_NONE, 'X'}, {ZAM_OT_RECORD_FIELD, 'R'}, {ZAM_OT_VAR, 'V'}, +}; + +void ZAM_OpTemplate::InstantiateOp(const vector& ot, bool do_vec) + { + auto method = MethodName(ot); + + InstantiateOp(method, ot, ZIC_REGULAR); + + if ( IncludesFieldOp() ) + InstantiateOp(method, ot, ZIC_FIELD); + + if ( do_vec ) + InstantiateOp(method, ot, ZIC_VEC); + + if ( IsConditionalOp() ) + InstantiateOp(method, ot, ZIC_COND); + } + +void ZAM_OpTemplate::InstantiateOp(const string& method, const vector& ot, + ZAM_InstClass zc) + { + string suffix = ""; + + if ( zc == ZIC_FIELD ) + suffix = "_field"; + else if ( zc == ZIC_VEC ) + suffix = "_vec"; + else if ( zc == ZIC_COND ) + suffix = "_cond"; + + if ( ! IsInternalOp() ) + InstantiateMethod(method, suffix, ot, zc); + + if ( IsAssignOp() ) + InstantiateAssignOp(ot, suffix); + else + { + InstantiateEval(ot, suffix, zc); + + if ( HasAssignmentLess() ) + { + auto op_string = "_" + OpSuffix(ot); + auto op = g->GenOpCode(this, op_string); + GenAssignmentlessVersion(op); + } + } + } + +void ZAM_OpTemplate::GenAssignmentlessVersion(string op) + { + EmitTo(AssignFlavor); + Emit("assignmentless_op[" + op + "] = " + AssignmentLessOp() + ";"); + Emit("assignmentless_op_type[" + op + "] = " + AssignmentLessOpType() + ";"); + } + +void ZAM_OpTemplate::InstantiateMethod(const string& m, const string& suffix, + const vector& ot_orig, ZAM_InstClass zc) + { + if ( IsInternalOp() ) + return; + + auto ot = ot_orig; + if ( zc == ZIC_FIELD ) + // Need to make room for the field offset. + ot.emplace_back(ZAM_OT_INT); + + auto decls = MethodDeclare(ot, zc); + + EmitTo(MethodDecl); + Emit("const ZAMStmt " + m + suffix + "(" + decls + ");"); + + EmitTo(MethodDef); + Emit("const ZAMStmt ZAMCompiler::" + m + suffix + "(" + decls + ")"); + BeginBlock(); + + InstantiateMethodCore(ot, suffix, zc); + + if ( HasPostMethod() ) + Emit(GetPostMethod()); + + if ( ! HasCustomMethod() ) + Emit("return AddInst(z);"); + + EndBlock(); + NL(); + } + +void ZAM_OpTemplate::InstantiateMethodCore(const vector& ot, string suffix, + ZAM_InstClass zc) + { + if ( HasCustomMethod() ) + { + Emit(GetCustomMethod()); + return; + } + + assert(! ot.empty()); + + string full_suffix = "_" + OpSuffix(ot) + suffix; + + Emit("ZInstI z;"); + + if ( ot[0] == ZAM_OT_AUX ) + { + auto op = g->GenOpCode(this, full_suffix, zc); + Emit("z = ZInstI(" + op + ");"); + return; + } + + if ( ot[0] == ZAM_OT_NONE ) + { + auto op = g->GenOpCode(this, full_suffix, zc); + Emit("z = GenInst(" + op + ");"); + return; + } + + if ( ot.size() > 1 && ot[1] == ZAM_OT_AUX ) + { + auto op = g->GenOpCode(this, full_suffix, zc); + Emit("z = ZInstI(" + op + ", Frame1Slot(n, " + op + "));"); + return; + } + + ArgsManager args(ot, zc); + BuildInstruction(ot, args.Params(), full_suffix, zc); + + auto tp = GetTypeParam(); + if ( tp > 0 ) + Emit("z.SetType(" + args.NthParam(tp - 1) + "->GetType());"); + + auto tp2 = GetType2Param(); + if ( tp2 > 0 ) + Emit("z.t2 = " + args.NthParam(tp2 - 1) + "->GetType();"); + } + +void ZAM_OpTemplate::BuildInstruction(const vector& ot, const string& params, + const string& suffix, ZAM_InstClass zc) + { + auto op = g->GenOpCode(this, suffix, zc); + Emit("z = GenInst(" + op + ", " + params + ");"); + } + +void ZAM_OpTemplate::InstantiateEval(const vector& ot, const string& suffix, + ZAM_InstClass zc) + { + auto eval = GetEval(); + + if ( ot.size() > 1 ) + { // Check for use of "$1" to indicate the operand + string op1; + if ( ot[1] == ZAM_OT_CONSTANT ) + op1 = "z.c"; + else if ( ot[1] == ZAM_OT_VAR ) + op1 = "frame[z.v2]"; + + eval = regex_replace(eval, regex("\\$1"), op1); + } + + InstantiateEval(Eval, OpSuffix(ot) + suffix, eval, zc); + } + +void ZAM_OpTemplate::InstantiateEval(EmitTarget et, const string& op_suffix, const string& eval, + ZAM_InstClass zc) + { + auto op_code = g->GenOpCode(this, "_" + op_suffix, zc); + + EmitTo(et); + Emit("case " + op_code + ":"); + BeginBlock(); + Emit(eval); + EndBlock(); + EmitUp("break;"); + NL(); + } + +void ZAM_OpTemplate::InstantiateAssignOp(const vector& ot, const string& suffix) + { + // First, create a generic version of the operand, which the + // ZAM compiler uses to find specific-flavored versions. + auto op_string = "_" + OpSuffix(ot); + auto generic_op = g->GenOpCode(this, op_string); + auto flavor_ind = "assignment_flavor[" + generic_op + "]"; + + EmitTo(AssignFlavor); + Emit(flavor_ind + " = empty_map;"); + + auto eval = GetEval(); + auto v = GetAssignVal(); + + for ( auto& ti : ZAM_type_info ) + { + auto op = g->GenOpCode(this, op_string + "_" + ti.suffix); + + if ( IsInternalOp() ) + { + EmitTo(AssignFlavor); + Emit(flavor_ind + "[" + ti.tag + "] = " + op + ";"); + + if ( HasAssignmentLess() ) + GenAssignmentlessVersion(op); + } + + EmitTo(Eval); + Emit("case " + op + ":"); + BeginBlock(); + GenAssignOpCore(ot, eval, ti.accessor, ti.is_managed); + Emit("break;"); + EndBlock(); + } + } + +void ZAM_OpTemplate::GenAssignOpCore(const vector& ot, const string& eval, + const string& accessor, bool is_managed) + { + if ( HasAssignVal() ) + { + GenAssignOpValCore(eval, accessor, is_managed); + return; + } + + if ( ! eval.empty() ) + g->Gripe("assign-op should not have an \"eval\"", eval); + + auto lhs_field = (ot[0] == ZAM_OT_ASSIGN_FIELD); + auto rhs_field = lhs_field && ot.size() > 2 && (ot[2] == ZAM_OT_INT); + auto constant_op = (ot[1] == ZAM_OT_CONSTANT); + + string rhs = constant_op ? "z.c" : "frame[z.v2]"; + + auto acc = ".As" + accessor + "()"; + + if ( accessor == "Any" && constant_op && ! rhs_field ) + { + // "any_val = constant" or "x$any_val = constant". + // + // These require special-casing, because to avoid going + // through a CoerceToAny operation, we allow expressing + // these directly. They don't fit with the usual assignment + // paradigm since the RHS differs in type from the LHS. + Emit("auto v = z.c.ToVal(z.t);"); + + if ( lhs_field ) + { + Emit("auto r = frame[z.v1].AsRecord();"); + Emit("auto& f = r->RawField(z.v2);"); + } + else + Emit("auto& f = frame[z.v1];"); + + Emit("zeek::Unref(f.ManagedVal());"); + Emit("f = ZVal(v.release());"); + } + + else if ( rhs_field ) + { + // The following is counter-intuitive, but comes from the + // fact that we build out the instruction parameters as + // an echo of the method parameters, and for this case that + // means that the RHS field offset comes *before*, not after, + // the LHS field offset. + auto lhs_offset = constant_op ? 3 : 4; + auto rhs_offset = lhs_offset - 1; + + Emit("auto v = " + rhs + ".AsRecord()->RawOptField(z.v" + to_string(rhs_offset) + + "); // note, RHS field before LHS field"); + + Emit("if ( ! v )"); + BeginBlock(); + Emit("ZAM_run_time_error(z.loc, \"field value missing\");"); + Emit("break;"); + EndBlock(); + + auto slot = "z.v" + to_string(lhs_offset); + Emit("auto r = frame[z.v1].AsRecord();"); + Emit("auto& f = r->RawField(" + slot + "); // note, LHS field after RHS field"); + + if ( is_managed ) + { + Emit("zeek::Ref((*v)" + acc + ");"); + Emit("zeek::Unref(f.ManagedVal());"); + } + + Emit("f = *v;"); + } + + else + { + if ( is_managed ) + Emit("zeek::Ref(" + rhs + acc + ");"); + + if ( lhs_field ) + { + auto lhs_offset = constant_op ? 2 : 3; + auto slot = "z.v" + to_string(lhs_offset); + Emit("auto r = frame[z.v1].AsRecord();"); + Emit("auto& f = r->RawField(" + slot + ");"); + + if ( is_managed ) + Emit("zeek::Unref(f.ManagedVal());"); + + Emit("f = " + rhs + ";"); + } + + else + { + if ( is_managed ) + Emit("zeek::Unref(frame[z.v1].ManagedVal());"); + + Emit("frame[z.v1] = ZVal(" + rhs + acc + ");"); + } + } + + if ( lhs_field ) + Emit("r->Modified();"); + } + +void ZAM_OpTemplate::GenAssignOpValCore(const string& eval, const string& accessor, bool is_managed) + { + auto v = GetAssignVal(); + + Emit(eval); + + // Maps Zeek types to how to get the underlying value from a ValPtr. + static unordered_map val_accessors = { + {"Addr", "->AsAddrVal()"}, {"Any", ".get()"}, + {"Count", "->AsCount()"}, {"Double", "->AsDouble()"}, + {"Int", "->AsInt()"}, {"Pattern", "->AsPatternVal()"}, + {"String", "->AsStringVal()"}, {"SubNet", "->AsSubNetVal()"}, + {"Table", "->AsTableVal()"}, {"Vector", "->AsVectorVal()"}, + {"File", "->AsFile()"}, {"Func", "->AsFunc()"}, + {"List", "->AsListVal()"}, {"Opaque", "->AsOpaqueVal()"}, + {"Record", "->AsRecordVal()"}, {"Type", "->AsTypeVal()"}, + }; + + auto val_accessor = val_accessors[accessor]; + + string rhs; + if ( IsInternalOp() ) + rhs = v + val_accessor; + else + rhs = v + ".As" + accessor + "()"; + + if ( is_managed ) + { + Emit("auto rhs = " + rhs + ";"); + Emit("zeek::Ref(rhs);"); + Emit("Unref(frame[z.v1].ManagedVal());"); + Emit("frame[z.v1] = ZVal(rhs);"); + } + else + Emit("frame[z.v1] = ZVal(" + rhs + ");"); + } + +string ZAM_OpTemplate::MethodName(const vector& ot) const + { + return base_name + OpSuffix(ot); + } + +string ZAM_OpTemplate::MethodDeclare(const vector& ot, ZAM_InstClass zc) + { + ArgsManager args(ot, zc); + return args.Decls(); + } + +string ZAM_OpTemplate::OpSuffix(const vector& ot) const + { + string os; + for ( auto& o : ot ) + os += ot_to_char[o]; + return os; + } + +string ZAM_OpTemplate::SkipWS(const string& s) const + { + auto sp = s.c_str(); + while ( *sp && isspace(*sp) ) + ++sp; + + return sp; + } + +void ZAM_OpTemplate::Emit(const string& s) + { + g->Emit(curr_et, s); + } + +void ZAM_OpTemplate::EmitNoNL(const string& s) + { + g->SetNoNL(true); + Emit(s); + g->SetNoNL(false); + } + +void ZAM_OpTemplate::IndentUp() + { + g->IndentUp(); + } + +void ZAM_OpTemplate::IndentDown() + { + g->IndentDown(); + } + +void ZAM_UnaryOpTemplate::Instantiate() + { + UnaryInstantiate(); + } + +void ZAM_DirectUnaryOpTemplate::Instantiate() + { + EmitTo(DirectDef); + Emit("case EXPR_" + cname + ":\treturn " + direct + "(lhs, rhs);"); + } + +// Maps op-type mnemonics to the corresponding internal value used by Gen-ZAM. +static unordered_map expr_type_names = { + {'*', ZAM_EXPR_TYPE_DEFAULT}, {'A', ZAM_EXPR_TYPE_ADDR}, {'a', ZAM_EXPR_TYPE_ANY}, + {'D', ZAM_EXPR_TYPE_DOUBLE}, {'f', ZAM_EXPR_TYPE_FILE}, {'F', ZAM_EXPR_TYPE_FUNC}, + {'I', ZAM_EXPR_TYPE_INT}, {'L', ZAM_EXPR_TYPE_LIST}, {'X', ZAM_EXPR_TYPE_NONE}, + {'O', ZAM_EXPR_TYPE_OPAQUE}, {'P', ZAM_EXPR_TYPE_PATTERN}, {'R', ZAM_EXPR_TYPE_RECORD}, + {'S', ZAM_EXPR_TYPE_STRING}, {'N', ZAM_EXPR_TYPE_SUBNET}, {'T', ZAM_EXPR_TYPE_TABLE}, + {'t', ZAM_EXPR_TYPE_TYPE}, {'U', ZAM_EXPR_TYPE_UINT}, {'V', ZAM_EXPR_TYPE_VECTOR}, +}; + +// Inverse of the above. +static unordered_map expr_name_types; + +ZAM_ExprOpTemplate::ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name) + : ZAM_OpTemplate(_g, _base_name) + { + static bool did_map_init = false; + + if ( ! did_map_init ) + { // Create the inverse mapping. + for ( auto& tn : expr_type_names ) + expr_name_types[tn.second] = tn.first; + + did_map_init = true; + } + } + +void ZAM_ExprOpTemplate::Parse(const string& attr, const string& line, const Words& words) + { + if ( attr == "op-type" ) + { + if ( words.size() == 1 ) + g->Gripe("op-type needs arguments", line); + + for ( auto i = 1U; i < words.size(); ++i ) + { + auto& w_i = words[i]; + if ( w_i.size() != 1 ) + g->Gripe("bad op-type argument", w_i); + + auto et_c = w_i.c_str()[0]; + if ( expr_type_names.count(et_c) == 0 ) + g->Gripe("bad op-type argument", w_i); + + AddExprType(expr_type_names[et_c]); + } + } + + else if ( attr == "includes-field-op" ) + { + if ( words.size() != 1 ) + g->Gripe("includes-field-op does not take any arguments", line); + + SetIncludesFieldOp(); + } + + else if ( attr == "eval-type" ) + { + if ( words.size() < 3 ) + g->Gripe("eval-type needs type and evaluation", line); + + auto& type = words[1]; + if ( type.size() != 1 ) + g->Gripe("bad eval-type type", type); + + auto type_c = type.c_str()[0]; + if ( expr_type_names.count(type_c) == 0 ) + g->Gripe("bad eval-type type", type); + + auto et = expr_type_names[type_c]; + + if ( expr_types.count(et) == 0 ) + g->Gripe("eval-type type not present in eval-type", type); + + auto eval = g->SkipWords(line, 2); + eval += GatherEval(); + AddEvalSet(et, eval); + } + + else if ( attr == "eval-mixed" ) + { + if ( words.size() < 4 ) + g->Gripe("eval-mixed needs types and evaluation", line); + + auto& type1 = words[1]; + auto& type2 = words[2]; + if ( type1.size() != 1 || type2.size() != 1 ) + g->Gripe("bad eval-mixed types", line); + + auto type_c1 = type1.c_str()[0]; + auto type_c2 = type2.c_str()[0]; + if ( expr_type_names.count(type_c1) == 0 || expr_type_names.count(type_c2) == 0 ) + g->Gripe("bad eval-mixed types", line); + + auto et1 = expr_type_names[type_c1]; + auto et2 = expr_type_names[type_c2]; + + if ( eval_set.count(et1) > 0 ) + g->Gripe("eval-mixed uses type also included in op-type", line); + + auto eval = g->SkipWords(line, 3); + eval += GatherEval(); + AddEvalSet(et1, et2, eval); + } + + else if ( attr == "eval-pre" ) + { + if ( words.size() < 2 ) + g->Gripe("eval-pre needs evaluation", line); + + auto eval = g->SkipWords(line, 1); + eval += GatherEval(); + + SetPreEval(eval); + } + + else + // Not an attribute specific to expr-op's. + ZAM_OpTemplate::Parse(attr, line, words); + } + +void ZAM_ExprOpTemplate::Instantiate() + { + InstantiateOp(OperandTypes(), IncludesVectorOp()); + + if ( op_types.size() > 1 && op_types[1] == ZAM_OT_CONSTANT ) + InstantiateC1(op_types, op_types.size() - 1); + if ( op_types.size() > 2 && op_types[2] == ZAM_OT_CONSTANT ) + InstantiateC2(op_types, op_types.size() - 1); + if ( op_types.size() > 3 && op_types[3] == ZAM_OT_CONSTANT ) + InstantiateC3(op_types); + + bool all_var = true; + for ( auto i = 1U; i < op_types.size(); ++i ) + if ( op_types[i] != ZAM_OT_VAR ) + all_var = false; + + if ( all_var ) + InstantiateV(op_types); + + if ( op_types.size() == 3 && op_types[1] == ZAM_OT_RECORD_FIELD && op_types[2] == ZAM_OT_INT ) + InstantiateV(op_types); + } + +void ZAM_ExprOpTemplate::InstantiateC1(const vector& ots, int arity, bool do_vec) + { + string args = "lhs, r1->AsConstExpr()"; + + if ( arity == 1 && ots[0] == ZAM_OT_RECORD_FIELD ) + args += ", rhs->AsFieldExpr()->Field()"; + + else if ( arity > 1 ) + { + args += ", "; + + if ( ots[2] == ZAM_OT_RECORD_FIELD ) + args += "rhs->AsFieldExpr()->Field()"; + else + args += "r2->AsNameExpr()"; + } + + auto m = MethodName(ots); + + EmitTo(C1Def); + + EmitNoNL("case EXPR_" + cname + ":"); + + if ( do_vec ) + DoVectorCase(m, args); + else + EmitUp("return " + m + "(" + args + ");"); + + if ( IncludesFieldOp() ) + { + EmitTo(C1FieldDef); + Emit("case EXPR_" + cname + ":\treturn " + m + "_field(" + args + ", field);"); + } + } + +void ZAM_ExprOpTemplate::InstantiateC2(const vector& ots, int arity) + { + string args = "lhs, r1->AsNameExpr(), r2->AsConstExpr()"; + + if ( arity == 3 ) + args += ", r3->AsNameExpr()"; + + auto method = MethodName(ots); + auto m = method.c_str(); + + EmitTo(C2Def); + Emit("case EXPR_" + cname + ":\treturn " + m + "(" + args + ");"); + + if ( IncludesFieldOp() ) + { + EmitTo(C2FieldDef); + Emit("case EXPR_" + cname + ":\treturn " + m + "_field(" + args + ", field);"); + } + } + +void ZAM_ExprOpTemplate::InstantiateC3(const vector& ots) + { + EmitTo(C3Def); + Emit("case EXPR_" + cname + ":\treturn " + MethodName(ots) + + "(lhs, r1->AsNameExpr(), r2->AsNameExpr(), r3->AsConstExpr());"); + } + +void ZAM_ExprOpTemplate::InstantiateV(const vector& ots) + { + auto m = MethodName(ots); + + string args = "lhs, r1->AsNameExpr()"; + + if ( ots.size() >= 3 ) + { + if ( ots[2] == ZAM_OT_INT ) + { + string acc_flav = IncludesFieldOp() ? "Has" : ""; + args += ", rhs->As" + acc_flav + "FieldExpr()->Field()"; + } + else + args += ", r2->AsNameExpr()"; + + if ( ots.size() == 4 ) + args += ", r3->AsNameExpr()"; + } + + EmitTo(VDef); + EmitNoNL("case EXPR_" + cname + ":"); + + if ( IncludesVectorOp() ) + DoVectorCase(m, args); + else + EmitUp("return " + m + "(" + args + ");"); + + if ( IncludesFieldOp() ) + { + EmitTo(VFieldDef); + Emit("case EXPR_" + cname + ":\treturn " + m + "_field(" + args + ", field);"); + } + } + +void ZAM_ExprOpTemplate::DoVectorCase(const string& m, const string& args) + { + NL(); + IndentUp(); + Emit("if ( rt->Tag() == TYPE_VECTOR )"); + EmitUp("return " + m + "_vec(" + args + ");"); + Emit("else"); + EmitUp("return " + m + "(" + args + ");"); + IndentDown(); + } + +void ZAM_ExprOpTemplate::BuildInstructionCore(const string& params, const string& suffix, + ZAM_InstClass zc) + { + Emit("auto tag = t->Tag();"); + Emit("auto i_t = t->InternalType();"); + + int ncases = 0; + + for ( auto& [et1, et2_map] : eval_mixed_set ) + for ( auto& [et2, eval] : et2_map ) + GenMethodTest(et1, et2, params, suffix, ++ncases > 1, zc); + + bool do_default = false; + + for ( auto et : ExprTypes() ) + { + if ( et == ZAM_EXPR_TYPE_DEFAULT ) + do_default = true; + else + GenMethodTest(et, et, params, suffix, ++ncases > 1, zc); + } + + Emit("else"); + + if ( do_default ) + { + auto op = g->GenOpCode(this, suffix, zc); + EmitUp("z = GenInst(" + op + ", " + params + ");"); + } + + else + EmitUp("reporter->InternalError(\"bad tag when generating method core\");"); + } + +void ZAM_ExprOpTemplate::GenMethodTest(ZAM_ExprType et1, ZAM_ExprType et2, const string& params, + const string& suffix, bool do_else, ZAM_InstClass zc) + { + // Maps ZAM_ExprType's to the information needed (variable name, + // constant to compare it against) to identify using an "if" test + // that a given AST Expr node employs the given type of operand. + static map> if_tests = { + {ZAM_EXPR_TYPE_ADDR, {"i_t", "TYPE_INTERNAL_ADDR"}}, + {ZAM_EXPR_TYPE_ANY, {"tag", "TYPE_ANY"}}, + {ZAM_EXPR_TYPE_DOUBLE, {"i_t", "TYPE_INTERNAL_DOUBLE"}}, + {ZAM_EXPR_TYPE_FILE, {"tag", "TYPE_FILE"}}, + {ZAM_EXPR_TYPE_FUNC, {"tag", "TYPE_FUNC"}}, + {ZAM_EXPR_TYPE_INT, {"i_t", "TYPE_INTERNAL_INT"}}, + {ZAM_EXPR_TYPE_LIST, {"tag", "TYPE_LIST"}}, + {ZAM_EXPR_TYPE_OPAQUE, {"tag", "TYPE_OPAQUE"}}, + {ZAM_EXPR_TYPE_PATTERN, {"tag", "TYPE_PATTERN"}}, + {ZAM_EXPR_TYPE_RECORD, {"tag", "TYPE_RECORD"}}, + {ZAM_EXPR_TYPE_STRING, {"i_t", "TYPE_INTERNAL_STRING"}}, + {ZAM_EXPR_TYPE_SUBNET, {"i_t", "TYPE_INTERNAL_SUBNET"}}, + {ZAM_EXPR_TYPE_TABLE, {"tag", "TYPE_TABLE"}}, + {ZAM_EXPR_TYPE_TYPE, {"tag", "TYPE_TYPE"}}, + {ZAM_EXPR_TYPE_UINT, {"i_t", "TYPE_INTERNAL_UNSIGNED"}}, + {ZAM_EXPR_TYPE_VECTOR, {"tag", "TYPE_VECTOR"}}, + }; + + if ( if_tests.count(et1) == 0 ) + g->Gripe("bad op-type", op_loc); + + auto if_test = if_tests[et1]; + auto if_var = if_test.first; + auto if_val = if_test.second; + + string test = "if ( " + if_var + " == " + if_val + " )"; + if ( do_else ) + test = "else " + test; + + Emit(test); + + auto op_suffix = suffix + "_" + expr_name_types[et1]; + if ( et2 != et1 ) + op_suffix += expr_name_types[et2]; + + auto op = g->GenOpCode(this, op_suffix, zc); + EmitUp("z = GenInst(" + op + ", " + params + ");"); + } + +EvalInstance::EvalInstance(ZAM_ExprType _lhs_et, ZAM_ExprType _op1_et, ZAM_ExprType _op2_et, + string _eval, bool _is_def) + { + lhs_et = _lhs_et; + op1_et = _op1_et; + op2_et = _op2_et; + eval = move(_eval); + is_def = _is_def; + } + +string EvalInstance::LHSAccessor(bool is_ptr) const + { + if ( lhs_et == ZAM_EXPR_TYPE_NONE || lhs_et == ZAM_EXPR_TYPE_DEFAULT ) + return ""; + + string deref = is_ptr ? "->" : "."; + string acc = find_type_accessor(lhs_et); + + return deref + acc; + } + +string EvalInstance::Accessor(ZAM_ExprType et, bool is_ptr) const + { + if ( et == ZAM_EXPR_TYPE_NONE || et == ZAM_EXPR_TYPE_DEFAULT ) + return ""; + + string deref = is_ptr ? "->" : "."; + return deref + "As" + find_type_info(et).accessor + "()"; + } + +string EvalInstance::OpMarker() const + { + if ( op1_et == ZAM_EXPR_TYPE_DEFAULT || op1_et == ZAM_EXPR_TYPE_NONE ) + return ""; + + if ( op1_et == op2_et ) + return "_" + find_type_info(op1_et).suffix; + + return "_" + find_type_info(op1_et).suffix + find_type_info(op2_et).suffix; + } + +void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, + const string& suffix, ZAM_InstClass zc) + { + if ( expr_types.empty() ) + { // No operand types to expand over. + ZAM_OpTemplate::InstantiateEval(ot_orig, suffix, zc); + return; + } + + auto ot = ot_orig; + if ( zc == ZIC_FIELD ) + // Make room for the offset. + ot.emplace_back(ZAM_OT_INT); + + auto ot_str = OpSuffix(ot); + + // Some of these might not wind up being used, but no harm in + // initializing them in case they are. + string lhs, op1, op2; + string branch_target = "z.v"; + + EmitTarget emit_target = Eval; + + if ( zc == ZIC_VEC ) + { + lhs = "vec1[i]"; + op1 = "vec2[i]"; + op2 = "vec3[i]"; + + emit_target = Arity() == 1 ? Vec1Eval : Vec2Eval; + } + + else + { + lhs = "frame[z.v1]"; + + auto op1_offset = zc == ZIC_COND ? 1 : 2; + auto op2_offset = op1_offset + 1; + bool ot1_const = ot[1] == ZAM_OT_CONSTANT; + bool ot2_const = Arity() >= 2 && ot[2] == ZAM_OT_CONSTANT; + + if ( ot1_const ) + { + op1 = "z.c"; + --op2_offset; + branch_target += "2"; + } + else + { + op1 = "frame[z.v" + to_string(op1_offset) + "]"; + + if ( Arity() > 1 && ot[2] == ZAM_OT_VAR ) + branch_target += "3"; + else + branch_target += "2"; + } + + if ( ot2_const ) + op2 = "z.c"; + else + op2 = "frame[z.v" + to_string(op2_offset) + "]"; + + if ( zc == ZIC_FIELD ) + { + // Compute the slot holding the field offset. + + auto f = + // The first slots are taken up by the + // assignment slot and the operands ... + Arity() + 1 + + // ... and slots are numbered starting at 1. + +1; + + if ( ot1_const || ot2_const ) + // One of the operand slots won't be needed + // due to the presence of a constant. + // (It's never the case that both operands + // are constants - those instead get folded.) + --f; + + lhs += ".AsRecord()->RawField(z.v" + to_string(f) + ")"; + } + } + + vector eval_instances; + + for ( auto et : expr_types ) + { + auto is_def = eval_set.count(et) == 0; + string eval = is_def ? GetEval() : eval_set[et]; + auto lhs_et = IsConditionalOp() ? ZAM_EXPR_TYPE_INT : et; + eval_instances.emplace_back(lhs_et, et, et, eval, is_def); + } + + if ( zc != ZIC_VEC ) + for ( auto em1 : eval_mixed_set ) + { + auto et1 = em1.first; + for ( auto em2 : em1.second ) + { + auto et2 = em2.first; + + // For the LHS, either its expression type is + // ignored, or if it's a conditional, so just + // note it for the latter. + auto lhs_et = ZAM_EXPR_TYPE_INT; + eval_instances.emplace_back(lhs_et, et1, et2, em2.second, false); + } + } + + for ( auto& ei : eval_instances ) + { + auto lhs_accessor = ei.LHSAccessor(); + if ( HasExplicitResultType() ) + lhs_accessor = ""; + + string lhs_ei = lhs; + if ( zc != ZIC_VEC ) + lhs_ei += lhs_accessor; + + auto op1_ei = op1 + ei.Op1Accessor(zc == ZIC_VEC); + auto op2_ei = op2 + ei.Op2Accessor(zc == ZIC_VEC); + + auto eval = SkipWS(ei.Eval()); + + auto has_target = eval.find("$$") != string::npos; + + if ( zc == ZIC_VEC ) + { + const char* rhs; + if ( has_target ) + rhs = "\\$\\$ = ([^;\n]*)"; + else + rhs = "^[^;\n]*"; + + auto replacement = VecEvalRE(has_target); + + eval = regex_replace(eval, regex(rhs), replacement); + } + + auto is_none = ei.LHS_ET() == ZAM_EXPR_TYPE_NONE; + auto is_default = ei.LHS_ET() == ZAM_EXPR_TYPE_DEFAULT; + + if ( ! is_none && ! is_default && find_type_info(ei.LHS_ET()).is_managed && + ! HasExplicitResultType() ) + { + auto delim = zc == ZIC_VEC ? "->" : "."; + auto pre = "auto hold_lhs = " + lhs + delim + "ManagedVal();\n\t"; + auto post = "\tUnref(hold_lhs);"; + eval = pre + eval + post; + } + + eval = regex_replace(eval, regex("\\$1"), op1_ei); + eval = regex_replace(eval, regex("\\$2"), op2_ei); + + string pre = GetPreEval(); + pre = regex_replace(pre, regex("\\$1"), op1_ei); + pre = regex_replace(pre, regex("\\$2"), op2_ei); + + if ( has_target ) + eval = regex_replace(eval, regex("\\$\\$"), lhs_ei); + + else if ( zc == ZIC_COND ) + { // Aesthetics: get rid of trailing newlines. + eval = regex_replace(eval, regex("\n"), ""); + eval = "if ( ! (" + eval + ") ) " + "{ pc = " + branch_target + "; continue; }"; + } + + else if ( ! is_none && (ei.IsDefault() || IsConditionalOp()) ) + { + eval = lhs_ei + " = " + eval; + + // Ensure a single terminating semicolon. + eval = regex_replace(eval, regex(";*\n"), ";\n"); + } + + eval = pre + eval; + + auto full_suffix = ot_str + suffix + ei.OpMarker(); + + ZAM_OpTemplate::InstantiateEval(emit_target, full_suffix, eval, zc); + + if ( zc == ZIC_VEC ) + { + string dispatch_params = "frame[z.v1].AsVectorRef(), frame[z.v2].AsVector()"; + + if ( Arity() == 2 ) + dispatch_params += ", frame[z.v3].AsVector()"; + + auto op_code = g->GenOpCode(this, "_" + full_suffix); + auto dispatch = "vec_exec(" + op_code + ", z.t, " + dispatch_params + ", z);"; + + ZAM_OpTemplate::InstantiateEval(Eval, full_suffix, dispatch, zc); + } + } + } + +void ZAM_UnaryExprOpTemplate::Parse(const string& attr, const string& line, const Words& words) + { + if ( attr == "no-const" ) + { + if ( words.size() != 1 ) + g->Gripe("extraneous argument to no-const", line); + + SetNoConst(); + } + + else if ( attr == "explicit-result-type" ) + { + if ( words.size() != 1 ) + g->Gripe("extraneous argument to explicit-result-type", line); + SetHasExplicitResultType(); + } + + else + ZAM_ExprOpTemplate::Parse(attr, line, words); + } + +void ZAM_UnaryExprOpTemplate::Instantiate() + { + UnaryInstantiate(); + + vector ots = {ZAM_OT_VAR, ZAM_OT_CONSTANT}; + + if ( ! NoConst() ) + InstantiateC1(ots, 1, IncludesVectorOp()); + + ots[1] = ZAM_OT_VAR; + InstantiateV(ots); + } + +void ZAM_UnaryExprOpTemplate::BuildInstruction(const vector& ot, + const string& params, const string& suffix, + ZAM_InstClass zc) + { + const auto& ets = ExprTypes(); + + if ( ets.size() == 1 && ets.count(ZAM_EXPR_TYPE_NONE) == 1 ) + { + ZAM_ExprOpTemplate::BuildInstruction(ot, params, suffix, zc); + return; + } + + auto constant_op = ot[1] == ZAM_OT_CONSTANT; + string type_src = constant_op ? "c" : "n2"; + + if ( ot[0] == ZAM_OT_ASSIGN_FIELD ) + { + type_src = constant_op ? "n" : "n1"; + Emit("auto " + type_src + " = flhs->GetOp1()->AsNameExpr();"); + Emit("auto t = flhs->GetType();"); + Emit("int field = flhs->Field();"); + } + + else + { + if ( IsAssignOp() ) + type_src = constant_op ? "n" : "n1"; + + auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; + Emit("auto t = " + type_src + "->GetType()" + type_suffix); + } + + BuildInstructionCore(params, suffix, zc); + + if ( IsAssignOp() && IsFieldOp() ) + // These can't take the type from the LHS variable, since + // that's the enclosing record and not the field within it. + Emit("z.t = t;"); + + else if ( zc == ZIC_VEC ) + { + if ( constant_op ) + Emit("z.t = n->GetType();"); + else + Emit("z.t = n1->GetType();"); + } + } + +ZAM_AssignOpTemplate::ZAM_AssignOpTemplate(ZAMGen* _g, string _base_name) + : ZAM_UnaryExprOpTemplate(_g, _base_name) + { + // Assignments apply to every valid form of ExprType. + for ( auto& etn : expr_type_names ) + { + auto et = etn.second; + if ( et != ZAM_EXPR_TYPE_NONE && et != ZAM_EXPR_TYPE_DEFAULT ) + AddExprType(et); + } + } + +void ZAM_AssignOpTemplate::Parse(const string& attr, const string& line, const Words& words) + { + if ( attr == "field-op" ) + { + if ( words.size() != 1 ) + g->Gripe("field-op does not take any arguments", line); + + SetFieldOp(); + } + + else + ZAM_OpTemplate::Parse(attr, line, words); + } + +void ZAM_AssignOpTemplate::Instantiate() + { + if ( op_types.size() != 1 ) + g->Gripe("operation needs precisely one \"type\"", op_loc); + + vector ots; + ots.push_back(op_types[0]); + + // Build constant/variable versions ... + ots.push_back(ZAM_OT_CONSTANT); + + if ( ots[0] == ZAM_OT_RECORD_FIELD ) + ots.push_back(ZAM_OT_INT); + + InstantiateOp(ots, false); + if ( IsFieldOp() ) + InstantiateC1(ots, 1); + + ots[1] = ZAM_OT_VAR; + InstantiateOp(ots, false); + + // ... and for assignments to fields, additional field versions. + if ( ots[0] == ZAM_OT_ASSIGN_FIELD ) + { + ots.push_back(ZAM_OT_INT); + InstantiateOp(ots, false); + + ots[1] = ZAM_OT_CONSTANT; + InstantiateOp(ots, false); + } + + else if ( IsFieldOp() ) + InstantiateV(ots); + } + +void ZAM_BinaryExprOpTemplate::Instantiate() + { + // As usual, the first slot receives the operator's result. + vector ots = {ZAM_OT_VAR}; + ots.resize(3); + + // Build each combination for constant/variable operand, + // except skip constant/constant as that is always folded. + + // We only include vector operations when both operands + // are non-constants. + + ots[1] = ZAM_OT_CONSTANT; + ots[2] = ZAM_OT_VAR; + InstantiateOp(ots, false); + + if ( ! IsInternalOp() ) + InstantiateC1(ots, 2, false); + + ots[1] = ZAM_OT_VAR; + ots[2] = ZAM_OT_CONSTANT; + InstantiateOp(ots, false); + + if ( ! IsInternalOp() ) + InstantiateC2(ots, 2); + + ots[2] = ZAM_OT_VAR; + InstantiateOp(ots, IncludesVectorOp()); + + if ( ! IsInternalOp() ) + InstantiateV(ots); + } + +void ZAM_BinaryExprOpTemplate::BuildInstruction(const vector& ot, + const string& params, const string& suffix, + ZAM_InstClass zc) + { + auto constant_op = ot[1] == ZAM_OT_CONSTANT; + string type_src = constant_op ? "c" : "n2"; + auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; + Emit("auto t = " + type_src + "->GetType()" + type_suffix); + BuildInstructionCore(params, suffix, zc); + + if ( zc == ZIC_VEC ) + Emit("z.t = n1->GetType();"); + } + +void ZAM_RelationalExprOpTemplate::Instantiate() + { + ZAM_BinaryExprOpTemplate::Instantiate(); + + EmitTo(Cond); + + Emit("case EXPR_" + cname + ":"); + IndentUp(); + Emit("if ( n1 && n2 )"); + EmitUp("return " + cname + "VVV_cond(n1, n2);"); + Emit("else if ( n1 )"); + EmitUp("return " + cname + "VVC_cond(n1, c);"); + Emit("else"); + EmitUp("return " + cname + "VCV_cond(c, n2);"); + IndentDown(); + NL(); + } + +void ZAM_RelationalExprOpTemplate::BuildInstruction(const vector& ot, + const string& params, const string& suffix, + ZAM_InstClass zc) + { + string op1; + + if ( zc == ZIC_COND ) + { + if ( ot[1] == ZAM_OT_CONSTANT ) + op1 = "c"; + else if ( ot[2] == ZAM_OT_CONSTANT ) + op1 = "n"; + else + op1 = "n1"; + } + else + op1 = "n2"; + + auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; + Emit("auto t = " + op1 + "->GetType()" + type_suffix); + BuildInstructionCore(params, suffix, zc); + + if ( zc == ZIC_VEC ) + Emit("z.t = n1->GetType();"); + } + +void ZAM_InternalBinaryOpTemplate::Parse(const string& attr, const string& line, const Words& words) + { + if ( attr == "op-accessor" ) + { + if ( words.size() != 2 ) + g->Gripe("op-accessor takes one argument", line); + + SetOpAccessor(words[1]); + } + + else if ( attr == "op1-accessor" ) + { + if ( words.size() != 2 ) + g->Gripe("op-accessor1 takes one argument", line); + + SetOp1Accessor(words[1]); + } + + else if ( attr == "op2-accessor" ) + { + if ( words.size() != 2 ) + g->Gripe("op-accessor2 takes one argument", line); + + SetOp2Accessor(words[1]); + } + + else + ZAM_BinaryExprOpTemplate::Parse(attr, line, words); + } + +void ZAM_InternalBinaryOpTemplate::InstantiateEval(const vector& ot, + const string& suffix, ZAM_InstClass zc) + { + assert(ot.size() == 3); + + auto op1_const = ot[1] == ZAM_OT_CONSTANT; + auto op2_const = ot[2] == ZAM_OT_CONSTANT; + + string op1 = op1_const ? "z.c" : "frame[z.v2]"; + string op2 = op2_const ? "z.c" : (op1_const ? "frame[z.v2]" : "frame[z.v3]"); + + string prelude = "auto op1 = " + op1 + "." + op1_accessor + ";\n"; + prelude += "auto op2 = " + op2 + "." + op2_accessor + ";\n"; + + auto eval = prelude + GetEval(); + + auto& ets = ExprTypes(); + if ( ! ets.empty() ) + { + if ( ets.size() != 1 ) + g->Gripe("internal-binary-op's can have at most one op-type", op_loc); + + for ( auto& et : ets ) + { + auto acc = find_type_accessor(et); + auto lhs = "frame[z.v1]." + acc; + eval = regex_replace(eval, regex("\\$\\$"), lhs); + } + } + + ZAM_OpTemplate::InstantiateEval(Eval, OpSuffix(ot) + suffix, eval, zc); + } + +void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const Words& words) + { + if ( attr != "num-call-args" ) + { + if ( attr == "indirect-call" ) + { + if ( words.size() != 1 ) + g->Gripe("indirect-call takes one argument", line); + // Note, currently only works with a *subsequent* + // num-call-args, whose setting needs to be 'n'. + is_indirect_call = true; + } + else + ZAM_OpTemplate::Parse(attr, line, words); + + return; + } + + if ( words.size() != 2 ) + g->Gripe("num-call-args takes one argument", line); + + eval = "std::vector args;\n"; + + auto& arg = words[1]; + int n = arg == "n" ? -1 : stoi(arg); + + auto arg_offset = HasAssignVal() ? 1 : 0; + auto arg_slot = arg_offset + 1; + + string func = "z.func"; + + if ( n == 1 ) + { + eval += "args.push_back("; + if ( op_types[arg_offset] == ZAM_OT_CONSTANT ) + eval += "z.c"; + else + eval += "frame[z.v" + to_string(arg_slot) + "]"; + + eval += ".ToVal(z.t));\n"; + } + + else if ( n != 0 ) + { + eval += "auto aux = z.aux;\n"; + + if ( n < 0 ) + { + if ( is_indirect_call ) + { + func = "func"; + + eval += "auto sel = z.v" + to_string(arg_slot) + ";\n"; + eval += "auto func = (sel < 0) ? "; + eval += "aux->id_val->GetVal()->AsFunc() : "; + eval += "frame[sel].AsFunc();\n"; + } + + eval += "auto n = aux->n;\n"; + eval += "for ( auto i = 0; i < n; ++i )\n"; + eval += "\targs.push_back(aux->ToVal(frame, i));\n"; + } + + else + for ( auto i = 0; i < n; ++i ) + { + eval += "args.push_back(aux->ToVal(frame, "; + eval += to_string(i); + eval += "));\n"; + } + } + + eval += "f->SetCallLoc(z.loc);\n"; + + if ( HasAssignVal() ) + { + auto av = GetAssignVal(); + eval += "auto " + av + " = " + func + "->Invoke(&args, f);\n"; + eval += "if ( ! " + av + " ) { ZAM_error = true; break; }\n"; + } + else + eval += "(void) " + func + "->Invoke(&args, f);\n"; + } + +bool TemplateInput::ScanLine(string& line) + { + if ( ! put_back.empty() ) + { + line = put_back; + put_back.clear(); + return true; + } + + char buf[8192]; + + // Read lines, discarding comments, which have to start at the + // beginning of a line. + do + { + if ( ! fgets(buf, sizeof buf, f) ) + return false; + ++loc.line_num; + } while ( buf[0] == '#' ); + + line = buf; + return true; + } + +vector TemplateInput::SplitIntoWords(const string& line) const + { + vector words; + + for ( auto start = line.c_str(); *start && *start != '\n'; ) + { + auto end = start + 1; + while ( *end && ! isspace(*end) ) + ++end; + + words.emplace_back(string(start, end - start)); + + start = end; + while ( *start && isspace(*start) ) + ++start; + } + + return words; + } + +string TemplateInput::SkipWords(const string& line, int n) const + { + auto s = line.c_str(); + + for ( int i = 0; i < n; ++i ) + { + // Find end of current word. + while ( *s && *s != '\n' ) + { + if ( isspace(*s) ) + break; + ++s; + } + + if ( *s == '\n' ) + break; + + // Find start of next word. + while ( *s && isspace(*s) ) + ++s; + } + + return string(s); + } + +void TemplateInput::Gripe(const char* msg, const string& input) const + { + auto input_s = input.c_str(); + int n = strlen(input_s); + + fprintf(stderr, "%s, line %d: %s - %s", loc.file_name, loc.line_num, msg, input_s); + if ( n == 0 || input_s[n - 1] != '\n' ) + fprintf(stderr, "\n"); + + exit(1); + } + +void TemplateInput::Gripe(const char* msg, const InputLoc& l) const + { + fprintf(stderr, "%s, line %d: %s\n", l.file_name, l.line_num, msg); + exit(1); + } + +ZAMGen::ZAMGen(int argc, char** argv) + { + auto prog_name = argv[0]; + + if ( argc != 2 ) + { + fprintf(stderr, "usage: %s \n", prog_name); + exit(1); + } + + auto file_name = argv[1]; + auto f = strcmp(file_name, "-") ? fopen(file_name, "r") : stdin; + + if ( ! f ) + { + fprintf(stderr, "%s: cannot open \"%s\"\n", prog_name, file_name); + exit(1); + } + + ti = make_unique(f, prog_name, file_name); + + InitEmitTargets(); + + while ( ParseTemplate() ) + ; + + for ( auto& t : templates ) + t->Instantiate(); + + GenMacros(); + + CloseEmitTargets(); + } + +void ZAMGen::ReadMacro(const string& line) + { + vector mac; + mac.emplace_back(SkipWords(line, 1)); + + string s; + while ( ScanLine(s) ) + { + if ( s.size() <= 1 || ! isspace(s.c_str()[0]) ) + { + PutBack(s); + break; + } + + mac.push_back(s); + } + + macros.emplace_back(move(mac)); + } + +void ZAMGen::GenMacros() + { + for ( auto& m : macros ) + { + for ( auto i = 0U; i < m.size(); ++i ) + { + auto ms = m[i]; + if ( i == 0 ) + ms = "#define " + ms; + + if ( i < m.size() - 1 ) + ms = regex_replace(ms, regex("\n"), " \\\n"); + + Emit(EvalMacros, ms); + } + + Emit(EvalMacros, "\n"); + } + } + +string ZAMGen::GenOpCode(const ZAM_OpTemplate* ot, const string& suffix, ZAM_InstClass zc) + { + auto op = "OP_" + ot->CanonicalName() + suffix; + + static unordered_set known_opcodes; + + if ( known_opcodes.count(op) > 0 ) + // We've already done this one, don't re-define its auxiliary + // information. + return op; + + known_opcodes.insert(op); + + IndentUp(); + + // Generate the enum defining the opcode ... + Emit(OpDef, op + ","); + + // ... the "flavor" of how it treats its first operand ... + auto op_comment = ",\t// " + op; + auto op1_always_read = (zc == ZIC_FIELD || zc == ZIC_COND); + auto flavor = op1_always_read ? "OP1_READ" : ot->GetOp1Flavor(); + Emit(Op1Flavor, flavor + op_comment); + + // ... whether it has side effects ... + auto se = ot->HasSideEffects() ? "true" : "false"; + Emit(OpSideEffects, se + op_comment); + + // ... and the switch case that maps the enum to a string + // representation. + auto name = ot->BaseName(); + transform(name.begin(), name.end(), name.begin(), ::tolower); + name += suffix; + transform(name.begin(), name.end(), name.begin(), under_to_dash); + Emit(OpName, "case " + op + ":\treturn \"" + name + "\";"); + + IndentDown(); + + return op; + } + +void ZAMGen::Emit(EmitTarget et, const string& s) + { + assert(et != None); + + if ( gen_files.count(et) == 0 ) + { + fprintf(stderr, "bad generation file type\n"); + exit(1); + } + + FILE* f = gen_files[et]; + + for ( auto i = indent_level; i > 0; --i ) + fputs("\t", f); + + fputs(s.c_str(), f); + + if ( ! no_NL && (s.empty() || s.back() != '\n') ) + fputs("\n", f); + } + +void ZAMGen::InitEmitTargets() + { + // Maps an EmitTarget enum to its corresponding filename. + static const unordered_map gen_file_names = { + {None, nullptr}, + {AssignFlavor, "ZAM-AssignFlavorsDefs.h"}, + {C1Def, "ZAM-GenExprsDefsC1.h"}, + {C1FieldDef, "ZAM-GenFieldsDefsC1.h"}, + {C2Def, "ZAM-GenExprsDefsC2.h"}, + {C2FieldDef, "ZAM-GenFieldsDefsC2.h"}, + {C3Def, "ZAM-GenExprsDefsC3.h"}, + {Cond, "ZAM-Conds.h"}, + {DirectDef, "ZAM-DirectDefs.h"}, + {Eval, "ZAM-EvalDefs.h"}, + {EvalMacros, "ZAM-EvalMacros.h"}, + {MethodDecl, "ZAM-MethodDecls.h"}, + {MethodDef, "ZAM-MethodDefs.h"}, + {Op1Flavor, "ZAM-Op1FlavorsDefs.h"}, + {OpDef, "ZAM-OpsDefs.h"}, + {OpName, "ZAM-OpsNamesDefs.h"}, + {OpSideEffects, "ZAM-OpSideEffects.h"}, + {VDef, "ZAM-GenExprsDefsV.h"}, + {VFieldDef, "ZAM-GenFieldsDefsV.h"}, + {Vec1Eval, "ZAM-Vec1EvalDefs.h"}, + {Vec2Eval, "ZAM-Vec2EvalDefs.h"}, + }; + + for ( auto& gfn : gen_file_names ) + { + auto fn = gfn.second; + if ( ! fn ) + continue; + + auto f = fopen(fn, "w"); + if ( ! f ) + { + fprintf(stderr, "can't open generation file %s\n", fn); + exit(1); + } + + gen_files[gfn.first] = f; + } + + InitSwitch(C1Def, "C1 assignment"); + InitSwitch(C2Def, "C2 assignment"); + InitSwitch(C3Def, "C3 assignment"); + InitSwitch(VDef, "V assignment"); + + InitSwitch(C1FieldDef, "C1 field assignment"); + InitSwitch(C2FieldDef, "C2 field assignment"); + InitSwitch(VFieldDef, "V field assignment"); + } + +void ZAMGen::InitSwitch(EmitTarget et, string desc) + { + Emit(et, "{"); + Emit(et, "switch ( rhs->Tag() ) {"); + + switch_targets[et] = desc; + } + +void ZAMGen::CloseEmitTargets() + { + FinishSwitches(); + + for ( auto& gf : gen_files ) + fclose(gf.second); + } + +void ZAMGen::FinishSwitches() + { + for ( auto& st : switch_targets ) + { + auto et = st.first; + auto& desc = st.second; + + Emit(et, "default:"); + IndentUp(); + Emit(et, "reporter->InternalError(\"inconsistency in " + desc + + ": %s\", obj_desc(rhs).c_str());"); + IndentDown(); + Emit(et, "}"); + Emit(et, "}"); + } + } + +bool ZAMGen::ParseTemplate() + { + string line; + + if ( ! ScanLine(line) ) + return false; + + if ( line.size() <= 1 ) + // A blank line - no template to parse. + return true; + + auto words = SplitIntoWords(line); + + if ( words.size() < 2 ) + Gripe("too few words at start of template", line); + + auto op = words[0]; + + if ( op == "macro" ) + { + ReadMacro(line); + return true; + } + + auto op_name = words[1]; + + // We track issues with the wrong number of template arguments + // up front, to avoid mis-invoking constructors, but we don't + // report these until later because if the template names a + // bad operation, it's better to report that as the core problem. + const char* args_mismatch = nullptr; + + if ( op == "direct-unary-op" ) + { + if ( words.size() != 3 ) + args_mismatch = "direct-unary-op takes 2 arguments"; + } + + else if ( words.size() != 2 ) + args_mismatch = "templates take 1 argument"; + + unique_ptr t; + + if ( op == "op" ) + t = make_unique(this, op_name); + else if ( op == "unary-op" ) + t = make_unique(this, op_name); + else if ( op == "direct-unary-op" && ! args_mismatch ) + t = make_unique(this, op_name, words[2]); + else if ( op == "assign-op" ) + t = make_unique(this, op_name); + else if ( op == "expr-op" ) + t = make_unique(this, op_name); + else if ( op == "unary-expr-op" ) + t = make_unique(this, op_name); + else if ( op == "binary-expr-op" ) + t = make_unique(this, op_name); + else if ( op == "rel-expr-op" ) + t = make_unique(this, op_name); + else if ( op == "internal-binary-op" ) + t = make_unique(this, op_name); + else if ( op == "internal-op" ) + t = make_unique(this, op_name); + else if ( op == "internal-assignment-op" ) + t = make_unique(this, op_name); + + else + Gripe("bad template name", op); + + if ( args_mismatch ) + Gripe(args_mismatch, line); + + t->Build(); + templates.emplace_back(move(t)); + + return true; + } + +int main(int argc, char** argv) + { + try + { + ZAMGen zg(argc, argv); + exit(0); + } + catch ( const std::regex_error& e ) + { + fprintf(stderr, "%s: regular expression error - %s\n", argv[0], e.what()); + exit(1); + } + } diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h new file mode 100644 index 0000000000..e5f2eaec4d --- /dev/null +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -0,0 +1,986 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +// Gen-ZAM is a standalone program that takes as input a file specifying +// ZAM operations and from them generates a (large) set of C++ include +// files used to instantiate those operations as low-level ZAM instructions. +// (Those files are described in the EmitTarget enumeration below.) +// +// See Ops.in for documentation regarding the format of the ZAM templates. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +using std::string; +using std::vector; + +// An instruction can have one of four basic classes. +enum ZAM_InstClass + { + ZIC_REGULAR, // a non-complicated instruction + ZIC_COND, // a conditional branch + ZIC_VEC, // a vector operation + ZIC_FIELD, // a record field assignment + }; + +// For a given instruction operand, its general type. +enum ZAM_OperandType + { + ZAM_OT_CONSTANT, // uses the instruction's associated constant + ZAM_OT_EVENT_HANDLER, // uses the associated event handler + ZAM_OT_INT, // directly specified integer + ZAM_OT_VAR, // frame slot associated with a variable + + ZAM_OT_ASSIGN_FIELD, // record field offset to assign to + ZAM_OT_RECORD_FIELD, // record field offset to access + + // The following wind up the same in the ultimate instruction, + // but they differ in the calling sequences used to generate + // the instruction. + ZAM_OT_AUX, // uses the instruction's "aux" field + ZAM_OT_LIST, // a list, managed via the "aux" field + + ZAM_OT_NONE, // instruction has no direct operands + }; + +// For instructions corresponding to evaluating expressions, the type +// of a given operand. The generator uses these to transform the operand's +// low-level ZVal into a higher-level type expected by the associated +// evaluation code. +enum ZAM_ExprType + { + ZAM_EXPR_TYPE_ADDR, + ZAM_EXPR_TYPE_ANY, + ZAM_EXPR_TYPE_DOUBLE, + ZAM_EXPR_TYPE_FUNC, + ZAM_EXPR_TYPE_INT, + ZAM_EXPR_TYPE_PATTERN, + ZAM_EXPR_TYPE_RECORD, + ZAM_EXPR_TYPE_STRING, + ZAM_EXPR_TYPE_SUBNET, + ZAM_EXPR_TYPE_TABLE, + ZAM_EXPR_TYPE_UINT, + ZAM_EXPR_TYPE_VECTOR, + ZAM_EXPR_TYPE_FILE, + ZAM_EXPR_TYPE_OPAQUE, + ZAM_EXPR_TYPE_LIST, + ZAM_EXPR_TYPE_TYPE, + + // Used to specify "apart from the explicitly specified operand + // types, do this action for any other types". + ZAM_EXPR_TYPE_DEFAULT, + + // Used for expressions where the evaluation code for the + // expression deals directly with the operand's ZVal, rather + // than the generator providing a higher-level version. + ZAM_EXPR_TYPE_NONE, + }; + +// We only use the following in the context where the vector's elements +// are individual words from the same line. We don't use it in other +// contexts where we're tracking a bunch of strings. +using Words = vector; + +// Used for error-reporting. +struct InputLoc + { + const char* file_name; + int line_num = 0; + }; + +// An EmitTarget is a generated file to which code will be emitted. +// The different values are used to instruct the generator which target +// is currently of interest. +enum EmitTarget + { + // Indicates that no generated file has yet been specified. + None, + + // Declares/defines methods that take AST nodes and generate + // corresponding ZAM instructions. + MethodDecl, + MethodDef, + + // Switch cases for expressions that are compiled directly, using + // custom methods rather than methods produced by the generator. + DirectDef, + + // Switch cases for invoking various flavors of methods produced + // by the generator for generating ZAM instructions for AST + // expressions. C1/C2/C3 refer to the first/second/third operand + // being a constant. V refers to none of the operands being + // a constant. + C1Def, + C2Def, + C3Def, + VDef, + + // The same, but for when the expression is being assigned to + // a record field rather than a variable. There's no "C3" option + // because of how we reduce AST ternary operations. + C1FieldDef, + C2FieldDef, + VFieldDef, + + // Switch cases for compiling relational operations used in + // conditionals. + Cond, + + // Switch cases that provide the C++ code for executing specific + // individual ZAM instructions. + Eval, + + // #define's used to provide the templator's macro functionality. + EvalMacros, + + // Switch cases the provide the C++ code for executing unary + // and binary vector operations. + Vec1Eval, + Vec2Eval, + + // A set of instructions to dynamically generate maps that + // translate a generic ZAM operation (e.g., OP_LOAD_GLOBAL_VV) + // to a specific ZAM instruction, given a specific type + // (e.g., for OP_LOAD_GLOBAL_VV plus TYPE_ADDR, the map yields + // OP_LOAD_GLOBAL_VV_A). + AssignFlavor, + + // A list of values, one per ZAM instruction, that indicate whether + // that instruction writes to its first operand (the most common + // case), reads the operand but doesn't write to it, both reads it + // and writes to it, or none of these apply because the first + // operand isn't a frame variable. See the ZAMOp1Flavor enum + // defined in ZOp.h. + Op1Flavor, + + // A list of boolean values, one per ZAM instruction, that indicate + // whether the instruction has side effects, and thus should not + // be deleted even if its associated assignment is to a dead value + // (one not subsequently used). + OpSideEffects, + + // A list of names enumerating each ZAM instruction. These + // are ZAM opcodes. + OpDef, + + // A list of cases, indexed by ZAM opcode, that return a + // human-readable string of naming the opcode, for use in debugging + // output. For example, for OP_NEGATE_VV_I the corresponding + // string is "negate-VV-I". + OpName, + }; + +// A helper class for managing the (ordered) collection of ZAM_OperandType's +// associated with an instruction in order to generate C++ calling sequences +// (both parameters for declarations, and arguments for invocations). +class ArgsManager + { +public: + // Constructed by providing the various ZAM_OperandType's along + // with the instruction's class. + ArgsManager(const vector& ot, ZAM_InstClass ic); + + // Returns a string defining the parameters for a declaration; + // these have full C++ type information along with the parameter + // name. + string Decls() const { return full_decl; } + + // Returns a string for passing the parameters in a function + // call. This is a comma-separated list of the parameter names, + // with no associated C++ types. + string Params() const { return full_params; } + + // Returns the name of the given parameter, indexed starting with 0. + const string& NthParam(int n) const { return params[n]; } + +private: + // Makes sure that each parameter has a unique name. For any + // parameter 'x' that occurs more than once, renames the instances + // "x1", "x2", etc. + void Differentiate(); + + // Maps ZAM_OperandType's to their associated C++ type and + // canonical parameter name. + static std::unordered_map> ot_to_args; + + // For a single argument/parameter, tracks its declaration name, + // C++ type, and the name to use when providing it as a parameter. + // These last two names are potentially distinct when we're + // assigning to record field (which is tracked by the is_field + // member variable), hence the need to track both. + struct Arg + { + string decl_name; + string decl_type; + string param_name; + bool is_field; + }; + + // All of the argument/parameters associated with the collection + // of ZAM_OperandType's. + vector args; + + // Each of the individual parameters. + vector params; + + // See Decls() and Params() above. + string full_decl; + string full_params; + }; + +// There are two mutually interacting classes: ZAMGen is the overall +// driver for the ZAM generator, while ZAM_OpTemplate represents a +// single operation template, with subclasses for specific types of +// operations. +class ZAMGen; + +class ZAM_OpTemplate + { +public: + // Instantiated by passing in the ZAMGen driver and the generic + // name for the operation. + ZAM_OpTemplate(ZAMGen* _g, string _base_name); + virtual ~ZAM_OpTemplate() { } + + // Constructs the template's data structures by parsing its + // description (beyond the initial description of the type of + // operation). + void Build(); + + // Tells the object to generate the code/files necessary for + // each of its underlying instructions. + virtual void Instantiate(); + + // Returns the generic name for the operation. + const string& BaseName() const { return base_name; } + + // Returns the canonical name for the operation. This is a + // version of the name that, for expression-based operations, + // can be concatenated with "EXPR_" to get the name of the + // corresponding AST node. + const string& CanonicalName() const { return cname; } + + // Returns a string version of the ZAMOp1Flavor associated + // with this operation. + const string& GetOp1Flavor() const { return op1_flavor; } + + // True if this is an operation with side effects (see OpSideEffects + // above). + bool HasSideEffects() const { return has_side_effects; } + +protected: + // Append to the list of operand types associated with this operation. + void AddOpType(ZAM_OperandType ot) { op_types.push_back(ot); } + // Retrieve the list of operand types associated with this operation. + const vector& OperandTypes() const { return op_types; } + + // Specify the ZAMOp1Flavor associated with this operation. See + // GetOp1Flavor() above for the corresponding accessor. + void SetOp1Flavor(string fl) { op1_flavor = fl; } + + // Specify/fetch the parameter (operand) from which to take the + // primary type of this operation. + void SetTypeParam(int param) { type_param = param; } + int GetTypeParam() const { return type_param; } + + // Specify/fetch the parameter (operand) from which to take the + // secondary type of this operation. + void SetType2Param(int param) { type2_param = param; } + int GetType2Param() const { return type2_param; } + + // Tracking of assignment values (C++ variables that hold the + // value that should be assigned to usual frame slot). + void SetAssignVal(string _av) { av = _av; } + bool HasAssignVal() const { return ! av.empty(); } + const string& GetAssignVal() const { return av; } + + // Management of C++ evaluation blocks. These are built up + // line-by-line. + void AddEval(string line) { eval += line; } + bool HasEval() const { return ! eval.empty(); } + const string& GetEval() const { return eval; } + + // Management of custom methods to be used rather than generating + // a method. + void SetCustomMethod(string cm) { custom_method = SkipWS(cm); } + bool HasCustomMethod() const { return ! custom_method.empty(); } + const string& GetCustomMethod() const { return custom_method; } + + // Management of code to execute at the end of a generated method. + void SetPostMethod(string cm) { post_method = SkipWS(cm); } + bool HasPostMethod() const { return ! post_method.empty(); } + const string& GetPostMethod() const { return post_method; } + + // Predicates indicating whether a subclass supports a given + // property. These are whether the operation: (1) should include + // a version that assigns to a record field as well as the normal + // assigning to a frame slot, (2) is a conditional branch, (3) does + // not have a corresponding AST node, (4) is a direct assignment + // (not an assignment to an expression), (5) is a direct assignment + // to a record field. + virtual bool IncludesFieldOp() const { return false; } + virtual bool IsConditionalOp() const { return false; } + virtual bool IsInternalOp() const { return false; } + virtual bool IsAssignOp() const { return false; } + virtual bool IsFieldOp() const { return false; } + + // Whether this operation does not have any C++ evaluation associated + // with it. Used for custom methods that compile into internal + // ZAM operations. + bool NoEval() const { return no_eval; } + void SetNoEval() { no_eval = true; } + + // Whether this operation does not have a version where one of + // its operands is a constant. + bool NoConst() const { return no_const; } + void SetNoConst() { no_const = true; } + + // Whether this operation also has a vectorized form. + bool IncludesVectorOp() const { return includes_vector_op; } + void SetIncludesVectorOp() { includes_vector_op = true; } + + // Whether this operation has side effects, and thus should + // not be elided even if its result is used in a dead assignment. + void SetHasSideEffects() { has_side_effects = true; } + + // An "assignment-less" operation is one that, if its result + // is used in a dead assignment, should be converted to a different + // operation that explictly omits any assignment. + bool HasAssignmentLess() const { return ! assignment_less_op.empty(); } + void SetAssignmentLess(string op, string op_type) + { + assignment_less_op = op; + assignment_less_op_type = op_type; + } + const string& AssignmentLessOp() const { return assignment_less_op; } + const string& AssignmentLessOpType() const { return assignment_less_op_type; } + + // Builds the instructions associated with this operation, assuming + // a single operand. + void UnaryInstantiate(); + + // Parses the next line in an operation template. "attr" is + // the first word on the line, which often specifies the + // attribute specified by the line. "line" is the entire line, + // for parsing when that's necessary, and for error reporting. + // "words" is "line" split into a vector of whitespace-delimited + // words. + virtual void Parse(const string& attr, const string& line, const Words& words); + + // Scans in a C++ evaluation block, which continues until encountering + // a line that does not start with whitespace, or that's empty. + string GatherEval(); + + // Parses a $-specifier of which operand to use to associate + // a Zeek scripting type with ZAM instructions. + int ExtractTypeParam(const string& arg); + + // Generates instructions for each of the different flavors of the + // given operation. "ot" specifies the types of operands for the + // instruction, and "do_vec" whether to generate a vector version. + void InstantiateOp(const vector& ot, bool do_vec); + + // Generates one specific flavor ("zc") of the given operation, + // using a method named 'm', the given operand types, and the class. + void InstantiateOp(const string& m, const vector& ot, ZAM_InstClass zc); + + // Generates the "assignment-less" version of the given op-code. + void GenAssignmentlessVersion(string op); + + // Generates the method 'm' for an operation, where "suffix" is + // a (potentially empty) string differentiating the method from + // others for that operation, and "ot" and "zc" are the same + // as above. + void InstantiateMethod(const string& m, const string& suffix, const vector& ot, + ZAM_InstClass zc); + + // Generates the main logic of an operation's method, given the + // specific operand types, an associated suffix for differentiating + // ZAM instructions, and the instruction class. + void InstantiateMethodCore(const vector& ot, string suffix, ZAM_InstClass zc); + + // Generates the specific code to create a ZInst for the given + // operation, operands, parameters to "GenInst", and suffix and + // class per the above. + virtual void BuildInstruction(const vector& ot, const string& params, + const string& suffix, ZAM_InstClass zc); + + // Top-level driver for generating the C++ evaluation code for + // a given flavor of operation. + virtual void InstantiateEval(const vector& ot, const string& suffix, + ZAM_InstClass zc); + + // Generates the C++ case statement for evaluating the given flavor + // of operation. + void InstantiateEval(EmitTarget et, const string& op_suffix, const string& eval, + ZAM_InstClass zc); + + // Generates a set of assignment C++ evaluations, one per each + // possible Zeek scripting type of operand. + void InstantiateAssignOp(const vector& ot, const string& suffix); + + // Generates a C++ evaluation for an assignment of the type + // corresponding to "accessor". If "is_managed" is true then + // generates the associated memory management, too. + void GenAssignOpCore(const vector& ot, const string& eval, + const string& accessor, bool is_managed); + + // The same, but for when there's an explicit assignment value. + void GenAssignOpValCore(const string& eval, const string& accessor, bool is_managed); + + // Returns the name of the method associated with the particular + // list of operand types. + string MethodName(const vector& ot) const; + + // Returns the parameter declarations to use in declaring a method. + string MethodDeclare(const vector& ot, ZAM_InstClass zc); + + // Returns a suffix that differentiates an operation name for + // a specific list of operand types. + string OpSuffix(const vector& ot) const; + + // Returns a copy of the given string with leading whitespace + // removed. + string SkipWS(const string& s) const; + + // Set the target to use for subsequent code emission. + void EmitTo(EmitTarget et) { curr_et = et; } + + // Emit the given string to the currently selected EmitTarget. + void Emit(const string& s); + + // Same, but temporarily indented up. + void EmitUp(const string& s) + { + IndentUp(); + Emit(s); + IndentDown(); + } + + // Same, but reframe from inserting a newline. + void EmitNoNL(const string& s); + + // Emit a newline. Implementation doesn't actually include a + // newline since that's implicit in a call to Emit(). + void NL() { Emit(""); } + + // Increase/decrease the indentation level, with the last two + // being used for brace-delimited code blocks. + void IndentUp(); + void IndentDown(); + void BeginBlock() + { + IndentUp(); + Emit("{"); + } + void EndBlock() + { + Emit("}"); + IndentDown(); + } + + // Maps an operand type to a character mnemonic used to distinguish + // it from others. + static std::unordered_map ot_to_char; + + // The associated driver object. + ZAMGen* g; + + // See BaseName() and CanonicalName() above. + string base_name; + string cname; + + // Tracks the beginning of this operation template's definition, + // for error reporting. + InputLoc op_loc; + + // The current emission target. + EmitTarget curr_et = None; + + // The operand types for operations that have a single fixed list. + // Some operations (like those evaluating expressions) instead have + // dynamically generated range of possible operand types. + vector op_types; + + // See the description of Op1Flavor above. + string op1_flavor = "OP1_WRITE"; + + // Tracks the result of ExtractTypeParam() used for "type" and + // "type2" attributes. + int type_param = 0; // 0 = not set + int type2_param = 0; + + // If non-empty, the value to assign to the target in an assignment + // operation. + string av; + + // The C++ evaluation; may span multiple lines. + string eval; + + // Any associated custom method. + string custom_method; + + // Any associated additional code to add at the end of a + // generated method. + string post_method; + + // If true, then this operation does not have C++ evaluation + // associated with it. + bool no_eval = false; + + // If true, then this operation should not include a version + // supporting operands of constant type. + bool no_const = false; + + // If true, then this operation includes a vectorized version. + bool includes_vector_op = false; + + // If true, then this operation has side effects. + bool has_side_effects = false; + + // If non-empty, then specifies the associated operation that + // is a version of this operation but without assigning the result; + // and the operand type (like "OP_V") of that associated operation. + string assignment_less_op; + string assignment_less_op_type; + }; + +// A subclass used for "unary-op" templates. +class ZAM_UnaryOpTemplate : public ZAM_OpTemplate + { +public: + ZAM_UnaryOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, _base_name) { } + +protected: + void Instantiate() override; + }; + +// A subclass for unary operations that are directly instantiated using +// custom methods. +class ZAM_DirectUnaryOpTemplate : public ZAM_OpTemplate + { +public: + ZAM_DirectUnaryOpTemplate(ZAMGen* _g, string _base_name, string _direct) + : ZAM_OpTemplate(_g, _base_name), direct(_direct) + { + } + +protected: + void Instantiate() override; + +private: + // The ZAMCompiler method to call to compile the operation. + string direct; + }; + +// A helper class for the ZAM_ExprOpTemplate class (which follows). +// This class tracks a single instance of creating an evaluation for +// an AST expression. +class EvalInstance + { +public: + // Initialized using the types of the LHS (result) and the + // first and second operand. Often all three types are the + // same, but they can differ for some particular expressions, + // and for relationals. "eval" provides the C++ evaluation code. + // "is_def" is true if this instance is for the default catch-all + // where the operand types don't match any of the explicitly + // specified evaluations; + EvalInstance(ZAM_ExprType lhs_et, ZAM_ExprType op1_et, ZAM_ExprType op2_et, string eval, + bool is_def); + + // Returns the accessor to use for assigning to the LHS. "is_ptr" + // indicates whether the value to which we're applying the + // accessor is a pointer, rather than a ZVal. + string LHSAccessor(bool is_ptr = false) const; + + // Same but for access to the first or second operand. + string Op1Accessor(bool is_ptr = false) const { return Accessor(op1_et, is_ptr); } + string Op2Accessor(bool is_ptr = false) const { return Accessor(op2_et, is_ptr); } + + // Provides an accessor for an operand of the given type. + string Accessor(ZAM_ExprType et, bool is_ptr = false) const; + + // Returns the "marker" use to make unique the opcode for this + // flavor of expression-evaluation instruction. + string OpMarker() const; + + const string& Eval() const { return eval; } + ZAM_ExprType LHS_ET() const { return lhs_et; } + bool IsDefault() const { return is_def; } + +private: + ZAM_ExprType lhs_et; + ZAM_ExprType op1_et; + ZAM_ExprType op2_et; + string eval; + bool is_def; + }; + +// A subclass for AST "Expr" nodes in reduced form. +class ZAM_ExprOpTemplate : public ZAM_OpTemplate + { +public: + ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name); + + // The number of operands the operation takes (not including its + // assignment target). A value of 0 is used for expressions that + // require special handling. + virtual int Arity() const { return 0; } + + int HasExplicitResultType() const { return explicit_res_type; } + void SetHasExplicitResultType() { explicit_res_type = true; } + + void AddExprType(ZAM_ExprType et) { expr_types.insert(et); } + const std::unordered_set& ExprTypes() const { return expr_types; } + + void AddEvalSet(ZAM_ExprType et, string ev) { eval_set[et] += ev; } + void AddEvalSet(ZAM_ExprType et1, ZAM_ExprType et2, string ev) + { + eval_mixed_set[et1][et2] += ev; + } + + bool IncludesFieldOp() const override { return includes_field_op; } + void SetIncludesFieldOp() { includes_field_op = true; } + + bool HasPreEval() const { return ! pre_eval.empty(); } + void SetPreEval(string pe) { pre_eval = SkipWS(pe); } + const string& GetPreEval() const { return pre_eval; } + +protected: + // Returns a regular expression used to access the value of the + // expression suitable for assignment in a loop across the elements + // of a Zeek "vector" type. "have_target" is true if the template + // has an explicit "$$" assignment target. + virtual const char* VecEvalRE(bool have_target) const + { + return have_target ? "$$$$ = ZVal($1)" : "ZVal($&)"; + } + + void Parse(const string& attr, const string& line, const Words& words) override; + void Instantiate() override; + + // Instantiates versions of the operation that have a constant + // as the first, second, or third operand ... + void InstantiateC1(const vector& ots, int arity, bool do_vec = false); + void InstantiateC2(const vector& ots, int arity); + void InstantiateC3(const vector& ots); + + // ... or if all of the operands are non-constant. + void InstantiateV(const vector& ots); + + // Generates code that instantiates either the vectorized version + // of an operation, or the non-vector one, depending on whether + // the RHS of the reduced expression/assignment is a vector. + void DoVectorCase(const string& m, const string& args); + + // Iterates over the different Zeek types specified for an expression's + // operands and generates instructions for each. + void BuildInstructionCore(const string& params, const string& suffix, ZAM_InstClass zc); + + // Generates an if-else cascade element that matches one of the + // specific Zeek types associated with the instruction. + void GenMethodTest(ZAM_ExprType et1, ZAM_ExprType et2, const string& params, + const string& suffix, bool do_else, ZAM_InstClass zc); + + void InstantiateEval(const vector& ot, const string& suffix, + ZAM_InstClass zc) override; + +private: + // The Zeek types that can appear as operands for the expression. + std::unordered_set expr_types; + + // The C++ evaluation template for a given operand type. + std::unordered_map eval_set; + + // Some expressions take two operands of different types. This + // holds their C++ evaluation template. + std::unordered_map> eval_mixed_set; + + // Whether this expression's operand is a field access (and thus + // needs both the record as an operand and an additional constant + // offset into the record to get to the field). + bool includes_field_op = false; + + // If non-zero, code to generate prior to evaluating the expression. + string pre_eval; + + // If true, then the evaluations will take care of ensuring + // proper result types when assigning to $$. + bool explicit_res_type = false; + }; + +// A version of ZAM_ExprOpTemplate for unary expressions. +class ZAM_UnaryExprOpTemplate : public ZAM_ExprOpTemplate + { +public: + ZAM_UnaryExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_ExprOpTemplate(_g, _base_name) { } + + bool IncludesFieldOp() const override { return ExprTypes().count(ZAM_EXPR_TYPE_NONE) == 0; } + + int Arity() const override { return 1; } + +protected: + void Parse(const string& attr, const string& line, const Words& words) override; + void Instantiate() override; + + void BuildInstruction(const vector& ot, const string& params, + const string& suffix, ZAM_InstClass zc) override; + }; + +// A version of ZAM_UnaryExprOpTemplate where the point of the expression +// is to capture a direct assignment operation. +class ZAM_AssignOpTemplate : public ZAM_UnaryExprOpTemplate + { +public: + ZAM_AssignOpTemplate(ZAMGen* _g, string _base_name); + + bool IsAssignOp() const override { return true; } + bool IncludesFieldOp() const override { return false; } + bool IsFieldOp() const override { return field_op; } + void SetFieldOp() { field_op = true; } + +protected: + void Parse(const string& attr, const string& line, const Words& words) override; + void Instantiate() override; + +private: + bool field_op = false; + }; + +// A version of ZAM_ExprOpTemplate for binary expressions. +class ZAM_BinaryExprOpTemplate : public ZAM_ExprOpTemplate + { +public: + ZAM_BinaryExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_ExprOpTemplate(_g, _base_name) { } + + bool IncludesFieldOp() const override { return true; } + + int Arity() const override { return 2; } + +protected: + void Instantiate() override; + + void BuildInstruction(const vector& ot, const string& params, + const string& suffix, ZAM_InstClass zc) override; + }; + +// A version of ZAM_BinaryExprOpTemplate for relationals. +class ZAM_RelationalExprOpTemplate : public ZAM_BinaryExprOpTemplate + { +public: + ZAM_RelationalExprOpTemplate(ZAMGen* _g, string _base_name) + : ZAM_BinaryExprOpTemplate(_g, _base_name) + { + } + + bool IncludesFieldOp() const override { return false; } + bool IsConditionalOp() const override { return true; } + +protected: + const char* VecEvalRE(bool have_target) const override + { + if ( have_target ) + return "$$$$ = ZVal(bro_int_t($1))"; + else + return "ZVal(bro_int_t($&))"; + } + + void Instantiate() override; + + void BuildInstruction(const vector& ot, const string& params, + const string& suffix, ZAM_InstClass zc) override; + }; + +// A version of ZAM_BinaryExprOpTemplate for binary operations generated +// by custom methods rather than directly from the AST. +class ZAM_InternalBinaryOpTemplate : public ZAM_BinaryExprOpTemplate + { +public: + ZAM_InternalBinaryOpTemplate(ZAMGen* _g, string _base_name) + : ZAM_BinaryExprOpTemplate(_g, _base_name) + { + } + + bool IsInternalOp() const override { return true; } + + // The accessors used to get to the underlying Zeek script value + // of the first and second operand. + void SetOp1Accessor(string accessor) { op1_accessor = accessor; } + void SetOp2Accessor(string accessor) { op2_accessor = accessor; } + void SetOpAccessor(string accessor) + { + SetOp1Accessor(accessor); + SetOp2Accessor(accessor); + } + +protected: + void Parse(const string& attr, const string& line, const Words& words) override; + + void InstantiateEval(const vector& ot, const string& suffix, + ZAM_InstClass zc) override; + +private: + string op1_accessor; + string op2_accessor; + }; + +// A version of ZAM_OpTemplate for operations used internally (and not +// corresponding to AST elements). +class ZAM_InternalOpTemplate : public ZAM_OpTemplate + { +public: + ZAM_InternalOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, _base_name) { } + + bool IsInternalOp() const override { return true; } + +protected: + void Parse(const string& attr, const string& line, const Words& words) override; + +private: + // True if the internal operation corresponds to an indirect call, + // i.e., one through a variable rather than one directly specified. + bool is_indirect_call = false; + }; + +// An internal operation that assigns a result to a frame element. +class ZAM_InternalAssignOpTemplate : public ZAM_InternalOpTemplate + { +public: + ZAM_InternalAssignOpTemplate(ZAMGen* _g, string _base_name) + : ZAM_InternalOpTemplate(_g, _base_name) + { + } + + bool IsAssignOp() const override { return true; } + }; + +// Helper classes for managing input from the template file, including +// low-level scanning. + +class TemplateInput + { +public: + // Program name and file name are for generating error messages. + TemplateInput(FILE* _f, const char* _prog_name, const char* _file_name) + : f(_f), prog_name(_prog_name) + { + loc.file_name = _file_name; + } + + const InputLoc& CurrLoc() const { return loc; } + + // Fetch the next line of input, including trailing newline. + // Returns true on success, false on EOF or error. Skips over + // comments. + bool ScanLine(string& line); + + // Takes a line and splits it into white-space delimited words, + // returned in a vector. Removes trailing whitespace. + Words SplitIntoWords(const string& line) const; + + // Returns the line with the given number of initial words skipped. + string SkipWords(const string& line, int n) const; + + // Puts back the given line so that the next call to ScanLine will + // return it. Does not nest. + void PutBack(const string& line) { put_back = line; } + + // Report an error and exit. + [[noreturn]] void Gripe(const char* msg, const string& input) const; + [[noreturn]] void Gripe(const char* msg, const InputLoc& loc) const; + +private: + string put_back; // if non-empty, use this for the next ScanLine + + FILE* f; + const char* prog_name; + InputLoc loc; + }; + +// Driver class for the ZAM instruction generator. + +class ZAMGen + { +public: + ZAMGen(int argc, char** argv); + + // Reads in and records a macro definition, which ends upon + // encountering a blank line or a line that does not begin + // with whitespace. + void ReadMacro(const string& line); + + // Emits C++ #define's to implement the recorded macros. + void GenMacros(); + + // Generates a ZAM op-code for the given template, suffix, and + // instruction class. Also creates auxiliary information associated + // with the instruction. + string GenOpCode(const ZAM_OpTemplate* ot, const string& suffix, + ZAM_InstClass zc = ZIC_REGULAR); + + // These methods provide low-level parsing (and error-reporting) + // access to ZAM_OpTemplate objects. + const InputLoc& CurrLoc() const { return ti->CurrLoc(); } + bool ScanLine(string& line) { return ti->ScanLine(line); } + Words SplitIntoWords(const string& line) const { return ti->SplitIntoWords(line); } + string SkipWords(const string& line, int n) const { return ti->SkipWords(line, n); } + void PutBack(const string& line) { ti->PutBack(line); } + + // Methods made public to ZAM_OpTemplate objects for emitting code. + void Emit(EmitTarget et, const string& s); + + void IndentUp() { ++indent_level; } + void IndentDown() { --indent_level; } + void SetNoNL(bool _no_NL) { no_NL = _no_NL; } + + [[noreturn]] void Gripe(const char* msg, const string& input) const { ti->Gripe(msg, input); } + [[noreturn]] void Gripe(const char* msg, const InputLoc& loc) const { ti->Gripe(msg, loc); } + +private: + // Opens all of the code generation targets, and creates prologs + // for those requiring them (such as for embedding into switch + // statements). + void InitEmitTargets(); + void InitSwitch(EmitTarget et, string desc); + + // Closes all of the code generation targets, and creates epilogs + // for those requiring them. + void CloseEmitTargets(); + void FinishSwitches(); + + // Parses a single template, returning true on success and false + // if we've reached the end of the input. (Errors during parsing + // result instead in exiting.) + bool ParseTemplate(); + + // Maps code generation targets with their corresponding FILE*. + std::unordered_map gen_files; + + // Maps code generation targets to strings used to describe any + // associated switch (for error reporting). + std::unordered_map switch_targets; + + // The low-level TemplateInput object used to manage input. + std::unique_ptr ti; + + // Tracks all of the templates created so far. + vector> templates; + + // Tracks the macros recorded so far. + vector> macros; + + // Current indentation level. Maintained globally rather than + // per EmitTarget, so the caller needs to ensure it is managed + // consistently. + int indent_level = 0; + + // If true, refrain from appending a newline to any emitted lines. + bool no_NL = false; + }; From 5ea34f20b86a0c8dad241a8a4874bc0d4858d07c Mon Sep 17 00:00:00 2001 From: Christian Kreibich Date: Tue, 15 Mar 2022 21:39:34 -0700 Subject: [PATCH 249/343] gen-zam: Establish the usual environment for cmake-driven builds --- tools/gen-zam/CMakeLists.txt | 36 ++++++++++++++++++++++++++++++++++++ tools/gen-zam/README.md | 6 ++++++ 2 files changed, 42 insertions(+) create mode 100644 tools/gen-zam/CMakeLists.txt create mode 100644 tools/gen-zam/README.md diff --git a/tools/gen-zam/CMakeLists.txt b/tools/gen-zam/CMakeLists.txt new file mode 100644 index 0000000000..3f87375db6 --- /dev/null +++ b/tools/gen-zam/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +project(Gen-ZAM C CXX) + +include(cmake/CommonCMakeConfig.cmake) + +include(FindRequiredPackage) + +include(RequireCXX17) + +set(GEN_ZAM_SRCS src/Gen-ZAM.cc) +set(GEN_ZAM_HEADERS src/Gen-ZAM.h) +add_executable(gen-zam ${GEN_ZAM_SRCS} ${GEN_ZAM_HEADERS}) +install(TARGETS gen-zam DESTINATION bin) + +if (CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) +endif () + +message( + "\n===================| Gen-ZAM Build Summary |==================\n" + "\n" + "\nBuild type: ${CMAKE_BUILD_TYPE}" + "\nBuild dir: ${PROJECT_BINARY_DIR}" + "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" + "\nDebug mode: ${ENABLE_DEBUG}" + "\n" + "\nCC: ${CMAKE_C_COMPILER}" + "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" + "\nCXX: ${CMAKE_CXX_COMPILER}" + "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" + "\nCPP: ${CMAKE_CXX_COMPILER}" + "\n" + "\n================================================================\n" +) + +include(UserChangedWarning) diff --git a/tools/gen-zam/README.md b/tools/gen-zam/README.md new file mode 100644 index 0000000000..89fb4381ad --- /dev/null +++ b/tools/gen-zam/README.md @@ -0,0 +1,6 @@ +# Gen-ZAM, a templator for the Zeek Abstract Machine + +Zeek uses the `gen-zam` tool during its build, to synthesize operations in ZAM, +the Zeek Abstract Machine. The main reason for why you might want to use this +repository on its own is cross-compilation, for which you'll need `gen-zam` on +the build host, much like `bifcl` and `binpac`. From b51430c04e19d9c95f64c8aa507ba93e3db7d4af Mon Sep 17 00:00:00 2001 From: Christian Kreibich Date: Tue, 15 Mar 2022 21:44:15 -0700 Subject: [PATCH 250/343] gen-zam: Trivial source tweaks to make it build --- tools/gen-zam/src/Gen-ZAM.cc | 4 ++-- tools/gen-zam/src/Gen-ZAM.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 92948b4d84..aa43d128fb 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1,6 +1,6 @@ -// See the file "COPYING" in the main distribution directory for copyright. +// See the file "COPYING" in the toplevel directory for copyright. -#include "zeek/script_opt/ZAM/Gen-ZAM.h" +#include "Gen-ZAM.h" #include #include diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index e5f2eaec4d..d7570a3b52 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -1,4 +1,4 @@ -// See the file "COPYING" in the main distribution directory for copyright. +// See the file "COPYING" in the toplevel directory for copyright. // Gen-ZAM is a standalone program that takes as input a file specifying // ZAM operations and from them generates a (large) set of C++ include From 4a7cf8c26e754cf7783af7920ef1d3c32ea0a32e Mon Sep 17 00:00:00 2001 From: Christian Kreibich Date: Mon, 21 Mar 2022 15:12:56 -0700 Subject: [PATCH 251/343] gen-zam: Remove unnecessary include from CMakeLists.txt --- tools/gen-zam/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gen-zam/CMakeLists.txt b/tools/gen-zam/CMakeLists.txt index 3f87375db6..2cc724fc91 100644 --- a/tools/gen-zam/CMakeLists.txt +++ b/tools/gen-zam/CMakeLists.txt @@ -3,8 +3,6 @@ project(Gen-ZAM C CXX) include(cmake/CommonCMakeConfig.cmake) -include(FindRequiredPackage) - include(RequireCXX17) set(GEN_ZAM_SRCS src/Gen-ZAM.cc) From 902577b7ce47d476cc631ed1c0d4e10703bef983 Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Thu, 14 Apr 2022 17:01:41 +0100 Subject: [PATCH 252/343] gen-zam: Fix compile error on GCC-12/Ubuntu 22.04 --- tools/gen-zam/src/Gen-ZAM.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index aa43d128fb..f9b05d7f47 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -2,6 +2,7 @@ #include "Gen-ZAM.h" +#include #include #include From f330505e83e6a8a33603dd9ece0e45d7389128bf Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 28 Jun 2022 15:33:41 -0700 Subject: [PATCH 253/343] gen-zam: Deprecate bro_int_t and bro_uint_t --- tools/gen-zam/src/Gen-ZAM.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index d7570a3b52..e5278f968d 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -787,9 +787,9 @@ protected: const char* VecEvalRE(bool have_target) const override { if ( have_target ) - return "$$$$ = ZVal(bro_int_t($1))"; + return "$$$$ = ZVal(zeek_int_t($1))"; else - return "ZVal(bro_int_t($&))"; + return "ZVal(zeek_int_t($&))"; } void Instantiate() override; From 789b06b1eac1d4024b49b95f3a4de7023ae00182 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Sat, 30 Jul 2022 11:44:03 -0700 Subject: [PATCH 254/343] gen-zam: fix memory management for vector-of-strings operations --- tools/gen-zam/src/Gen-ZAM.cc | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index f9b05d7f47..11386e5cc0 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1390,9 +1390,24 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, if ( ! is_none && ! is_default && find_type_info(ei.LHS_ET()).is_managed && ! HasExplicitResultType() ) { - auto delim = zc == ZIC_VEC ? "->" : "."; - auto pre = "auto hold_lhs = " + lhs + delim + "ManagedVal();\n\t"; + auto pre = "auto hold_lhs = " + lhs; + + if ( zc == ZIC_VEC ) + // For vectors, we have to check for whether + // the previous value is present, or a hole. + pre += string(" ? ") + lhs + "->"; + else + pre += "."; + + pre += "ManagedVal()"; + + if ( zc == ZIC_VEC ) + pre += " : nullptr"; + + pre += ";\n\t"; + auto post = "\tUnref(hold_lhs);"; + eval = pre + eval + post; } From bacd56258c387a2b41fafb9c8c2c841764477839 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 5 Oct 2022 09:26:44 -0700 Subject: [PATCH 255/343] gen-zam: Fix a couple of coverity issues 1491335: AUTO_CAUSES_COPY due to a for loop using auto& instead of const auto& 1491338: AUTO_CAUSES_COPY due to a for loop using auto& instead of const auto& --- tools/gen-zam/src/Gen-ZAM.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 11386e5cc0..6af8d52851 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1339,10 +1339,10 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, } if ( zc != ZIC_VEC ) - for ( auto em1 : eval_mixed_set ) + for ( const auto& em1 : eval_mixed_set ) { auto et1 = em1.first; - for ( auto em2 : em1.second ) + for ( const auto& em2 : em1.second ) { auto et2 = em2.first; From 27d674edc0e91e0aed8b4ac519165f9ce3f99c8b Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 5 Oct 2022 09:37:11 -0700 Subject: [PATCH 256/343] gen-zam: clang-tidy: Avoid bugprone narrowing conversions --- tools/gen-zam/src/Gen-ZAM.cc | 8 ++++---- tools/gen-zam/src/Gen-ZAM.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 6af8d52851..4de18d3bd8 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -273,7 +273,7 @@ void ZAM_OpTemplate::UnaryInstantiate() void ZAM_OpTemplate::Parse(const string& attr, const string& line, const Words& words) { int num_args = -1; // -1 = don't enforce - int nwords = words.size(); + int nwords = static_cast(words.size()); if ( attr == "type" ) { @@ -1015,7 +1015,7 @@ void ZAM_ExprOpTemplate::Instantiate() InstantiateV(op_types); } -void ZAM_ExprOpTemplate::InstantiateC1(const vector& ots, int arity, bool do_vec) +void ZAM_ExprOpTemplate::InstantiateC1(const vector& ots, size_t arity, bool do_vec) { string args = "lhs, r1->AsConstExpr()"; @@ -1050,7 +1050,7 @@ void ZAM_ExprOpTemplate::InstantiateC1(const vector& ots, int a } } -void ZAM_ExprOpTemplate::InstantiateC2(const vector& ots, int arity) +void ZAM_ExprOpTemplate::InstantiateC2(const vector& ots, size_t arity) { string args = "lhs, r1->AsNameExpr(), r2->AsConstExpr()"; @@ -1909,7 +1909,7 @@ string TemplateInput::SkipWords(const string& line, int n) const void TemplateInput::Gripe(const char* msg, const string& input) const { auto input_s = input.c_str(); - int n = strlen(input_s); + size_t n = strlen(input_s); fprintf(stderr, "%s, line %d: %s - %s", loc.file_name, loc.line_num, msg, input_s); if ( n == 0 || input_s[n - 1] != '\n' ) diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index e5278f968d..724c6fdebb 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -668,8 +668,8 @@ protected: // Instantiates versions of the operation that have a constant // as the first, second, or third operand ... - void InstantiateC1(const vector& ots, int arity, bool do_vec = false); - void InstantiateC2(const vector& ots, int arity); + void InstantiateC1(const vector& ots, size_t arity, bool do_vec = false); + void InstantiateC2(const vector& ots, size_t arity); void InstantiateC3(const vector& ots); // ... or if all of the operands are non-constant. From 6ad6fd165b77e261d02954d3563c32d997557a13 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 5 Oct 2022 09:37:42 -0700 Subject: [PATCH 257/343] gen-zam: clang-tidy: Avoid copying string objects if possible --- tools/gen-zam/src/Gen-ZAM.cc | 10 +++++----- tools/gen-zam/src/Gen-ZAM.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 4de18d3bd8..5eea669078 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -505,7 +505,7 @@ void ZAM_OpTemplate::InstantiateOp(const string& method, const vector& ot, string suffix, +void ZAM_OpTemplate::InstantiateMethodCore(const vector& ot, const string& suffix, ZAM_InstClass zc) { if ( HasCustomMethod() ) @@ -885,7 +885,7 @@ static unordered_map expr_type_names = { static unordered_map expr_name_types; ZAM_ExprOpTemplate::ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name) - : ZAM_OpTemplate(_g, _base_name) + : ZAM_OpTemplate(_g, std::move(_base_name)) { static bool did_map_init = false; @@ -1539,7 +1539,7 @@ void ZAM_UnaryExprOpTemplate::BuildInstruction(const vector& ot } ZAM_AssignOpTemplate::ZAM_AssignOpTemplate(ZAMGen* _g, string _base_name) - : ZAM_UnaryExprOpTemplate(_g, _base_name) + : ZAM_UnaryExprOpTemplate(_g, std::move(_base_name)) { // Assignments apply to every valid form of ExprType. for ( auto& etn : expr_type_names ) @@ -2118,7 +2118,7 @@ void ZAMGen::InitSwitch(EmitTarget et, string desc) Emit(et, "{"); Emit(et, "switch ( rhs->Tag() ) {"); - switch_targets[et] = desc; + switch_targets[et] = std::move(desc); } void ZAMGen::CloseEmitTargets() diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index 724c6fdebb..a174392510 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -391,7 +391,7 @@ protected: void InstantiateOp(const string& m, const vector& ot, ZAM_InstClass zc); // Generates the "assignment-less" version of the given op-code. - void GenAssignmentlessVersion(string op); + void GenAssignmentlessVersion(const string& op); // Generates the method 'm' for an operation, where "suffix" is // a (potentially empty) string differentiating the method from @@ -403,7 +403,7 @@ protected: // Generates the main logic of an operation's method, given the // specific operand types, an associated suffix for differentiating // ZAM instructions, and the instruction class. - void InstantiateMethodCore(const vector& ot, string suffix, ZAM_InstClass zc); + void InstantiateMethodCore(const vector& ot, const string& suffix, ZAM_InstClass zc); // Generates the specific code to create a ZInst for the given // operation, operands, parameters to "GenInst", and suffix and From 3b3f6bbe4dfe99de5e8647388080a52f75dc6732 Mon Sep 17 00:00:00 2001 From: Tomer Lev Date: Sun, 18 Sep 2022 12:34:05 +0300 Subject: [PATCH 258/343] gen-zam: Fix a bug caused by different behaviour of std::regex_replace under MSVC. Under MSVC regex objects are multiline by default and there is no apparant way of changing this behaviour. Under clang/gcc regex is singleline unless std::regeX_constants::multiline is specificied. This behaviour is assumed in Gen-ZAM.cc when auto-generating header files. Example: https://godbolt.org/z/aP59x3EhT --- tools/gen-zam/src/Gen-ZAM.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 5eea669078..6d4704b4e7 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1381,7 +1381,7 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, auto replacement = VecEvalRE(has_target); - eval = regex_replace(eval, regex(rhs), replacement); + eval = regex_replace(eval, regex(rhs), replacement, std::regex_constants::match_not_null); } auto is_none = ei.LHS_ET() == ZAM_EXPR_TYPE_NONE; From 1e73b0297715c4e317bfc12b4b580590fb99c4a2 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Thu, 9 Feb 2023 11:23:24 -0800 Subject: [PATCH 259/343] gen-zam: better error reporting when ZAM code does a function call --- tools/gen-zam/src/Gen-ZAM.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 6d4704b4e7..066f36d077 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1825,7 +1825,7 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const } } - eval += "f->SetCallLoc(z.loc);\n"; + eval += "f->SetCall(z.call_expr);\n"; if ( HasAssignVal() ) { From b04c03ee89242c78a85632597a412199b4cbed9f Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 3 Apr 2023 16:00:42 -0700 Subject: [PATCH 260/343] gen-zam: Fix some warnings from newer compilers about unqualified std::move calls --- tools/gen-zam/src/Gen-ZAM.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 066f36d077..f08f94f089 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -140,7 +140,7 @@ ArgsManager::ArgsManager(const vector& ot, ZAM_InstClass zc) } } - args.emplace_back(move(arg)); + args.emplace_back(std::move(arg)); } Differentiate(); @@ -217,7 +217,7 @@ void ArgsManager::Differentiate() } } -ZAM_OpTemplate::ZAM_OpTemplate(ZAMGen* _g, string _base_name) : g(_g), base_name(move(_base_name)) +ZAM_OpTemplate::ZAM_OpTemplate(ZAMGen* _g, string _base_name) : g(_g), base_name(std::move(_base_name)) { // Make the base name viable in a C++ name. transform(base_name.begin(), base_name.end(), base_name.begin(), dash_to_under); @@ -1209,7 +1209,7 @@ EvalInstance::EvalInstance(ZAM_ExprType _lhs_et, ZAM_ExprType _op1_et, ZAM_ExprT lhs_et = _lhs_et; op1_et = _op1_et; op2_et = _op2_et; - eval = move(_eval); + eval = std::move(_eval); is_def = _is_def; } @@ -1975,7 +1975,7 @@ void ZAMGen::ReadMacro(const string& line) mac.push_back(s); } - macros.emplace_back(move(mac)); + macros.emplace_back(std::move(mac)); } void ZAMGen::GenMacros() @@ -2219,7 +2219,7 @@ bool ZAMGen::ParseTemplate() Gripe(args_mismatch, line); t->Build(); - templates.emplace_back(move(t)); + templates.emplace_back(std::move(t)); return true; } From 6f648e36d1fd7af3fe144500f8a4febf27568cac Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Fri, 16 Jun 2023 15:19:30 -0700 Subject: [PATCH 261/343] gen-zam: fix to make generated function calls compatible with "when" lambdas --- tools/gen-zam/src/Gen-ZAM.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index f08f94f089..96b8ed0983 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1825,7 +1825,7 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const } } - eval += "f->SetCall(z.call_expr);\n"; + eval += "f->SetOnlyCall(z.call_expr);\n"; if ( HasAssignVal() ) { From 6f8c54d69a71ae37cf53e1ca85bd53fa0aa5709f Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Thu, 20 Jul 2023 09:53:11 -0700 Subject: [PATCH 262/343] gen-zam: support for ZAM instructions using IntrusivePtr for call expression ASTs --- tools/gen-zam/src/Gen-ZAM.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 96b8ed0983..eb5e1079a3 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1825,7 +1825,7 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const } } - eval += "f->SetOnlyCall(z.call_expr);\n"; + eval += "f->SetOnlyCall(z.call_expr.get());\n"; if ( HasAssignVal() ) { From 4e07a9681d8b28374c6a58800745613f6957db3e Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Fri, 1 Dec 2023 17:01:41 -0800 Subject: [PATCH 263/343] gen-zam: fixes for generating ZAM operations relating to indirect calls --- tools/gen-zam/src/Gen-ZAM.cc | 26 +++++++++++++++++++++----- tools/gen-zam/src/Gen-ZAM.h | 3 +++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index eb5e1079a3..1f95b1cb79 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1757,13 +1757,16 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const { if ( attr != "num-call-args" ) { - if ( attr == "indirect-call" ) + if ( attr == "indirect-call" || attr == "indirect-local-call" ) { if ( words.size() != 1 ) g->Gripe("indirect-call takes one argument", line); // Note, currently only works with a *subsequent* // num-call-args, whose setting needs to be 'n'. is_indirect_call = true; + + if ( attr == "indirect-local-call" ) + is_local_indirect_call = true; } else ZAM_OpTemplate::Parse(attr, line, words); @@ -1805,10 +1808,23 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const { func = "func"; - eval += "auto sel = z.v" + to_string(arg_slot) + ";\n"; - eval += "auto func = (sel < 0) ? "; - eval += "aux->id_val->GetVal()->AsFunc() : "; - eval += "frame[sel].AsFunc();\n"; + if ( is_local_indirect_call ) + { + eval += "auto sel = z.v" + + to_string(arg_slot) + ";\n"; + eval += "auto func = frame[sel].AsFunc();\n"; + } + else + { + eval += "auto func_v = aux->id_val->GetVal();\n"; + eval += "auto func = func_v ? func_v->AsFunc() : nullptr;\n"; + } + + eval += "if ( ! func )\n"; + eval += "\t{\n"; + eval += "\tZAM_run_time_error(z.loc, \"value used but not set\");\n"; + eval += "\tbreak;\n"; + eval += "\t}\n"; } eval += "auto n = aux->n;\n"; diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index a174392510..328b37b0a3 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -847,6 +847,9 @@ private: // True if the internal operation corresponds to an indirect call, // i.e., one through a variable rather than one directly specified. bool is_indirect_call = false; + + // Refinement of is_indirect_call, when it's also via a local variable. + bool is_local_indirect_call = false; }; // An internal operation that assigns a result to a frame element. From f9385ef88d3dfed24c8dd101c9ccce430bd282a3 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Sun, 10 Mar 2024 17:16:31 -0400 Subject: [PATCH 264/343] gen-zam: hooks for supporting ZAM profiling --- tools/gen-zam/src/Gen-ZAM.cc | 16 ++++++++++++++-- tools/gen-zam/src/Gen-ZAM.h | 3 +++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 1f95b1cb79..950fe1091c 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -663,9 +663,13 @@ void ZAM_OpTemplate::InstantiateAssignOp(const vector& ot, cons Emit("case " + op + ":"); BeginBlock(); GenAssignOpCore(ot, eval, ti.accessor, ti.is_managed); + if ( ! post_eval.empty() ) + Emit(post_eval); Emit("break;"); EndBlock(); } + + post_eval.clear(); } void ZAM_OpTemplate::GenAssignOpCore(const vector& ot, const string& eval, @@ -1785,7 +1789,7 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const auto arg_offset = HasAssignVal() ? 1 : 0; auto arg_slot = arg_offset + 1; - string func = "z.func"; + string func = "z.aux->func"; if ( n == 1 ) { @@ -1841,16 +1845,24 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const } } - eval += "f->SetOnlyCall(z.call_expr.get());\n"; + eval += "f->SetOnlyCall(z.aux->call_expr.get());\n"; + eval += "ZAM_PROFILE_PRE_CALL\n"; if ( HasAssignVal() ) { auto av = GetAssignVal(); eval += "auto " + av + " = " + func + "->Invoke(&args, f);\n"; eval += "if ( ! " + av + " ) { ZAM_error = true; break; }\n"; + + // Postpone the profiling follow-up until after we process + // the assignment. + post_eval = "ZAM_PROFILE_POST_CALL\n"; } else + { eval += "(void) " + func + "->Invoke(&args, f);\n"; + eval += "ZAM_PROFILE_POST_CALL\n"; + } } bool TemplateInput::ScanLine(string& line) diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index 328b37b0a3..0a3af45d0b 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -523,6 +523,9 @@ protected: // The C++ evaluation; may span multiple lines. string eval; + // Postlog C++ code (currently only used in support of profiling). + string post_eval; + // Any associated custom method. string custom_method; From aee70af743da116ba7e773905c3922d83ce98ce6 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Fri, 19 Apr 2024 19:17:52 -0700 Subject: [PATCH 265/343] gen-zam: fix for generating relational operations with first operand being a constant --- tools/gen-zam/src/Gen-ZAM.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 950fe1091c..fc9659f71d 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1684,7 +1684,12 @@ void ZAM_RelationalExprOpTemplate::BuildInstruction(const vectorYield();" : ";"; Emit("auto t = " + op1 + "->GetType()" + type_suffix); From 4ae4548cebb71f7c0fd36b7b13a59729c718cffe Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Wed, 1 May 2024 17:06:49 -0700 Subject: [PATCH 266/343] gen-zam: gen-zam extended to read from multiple files on the command-line --- tools/gen-zam/src/Gen-ZAM.cc | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index fc9659f71d..f030d93df2 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1959,30 +1959,37 @@ void TemplateInput::Gripe(const char* msg, const InputLoc& l) const ZAMGen::ZAMGen(int argc, char** argv) { - auto prog_name = argv[0]; + auto prog_name = (argv++)[0]; - if ( argc != 2 ) + if ( --argc < 1 ) { fprintf(stderr, "usage: %s \n", prog_name); exit(1); } - auto file_name = argv[1]; - auto f = strcmp(file_name, "-") ? fopen(file_name, "r") : stdin; - - if ( ! f ) + while ( argc-- > 0 ) { - fprintf(stderr, "%s: cannot open \"%s\"\n", prog_name, file_name); - exit(1); + auto file_name = (argv++)[0]; + bool is_stdin = file_name == std::string("-"); + auto f = is_stdin ? stdin : fopen(file_name, "r"); + + if ( ! f ) + { + fprintf(stderr, "%s: cannot open \"%s\"\n", prog_name, file_name); + exit(1); + } + + ti = make_unique(f, prog_name, file_name); + + while ( ParseTemplate() ) + ; + + if ( ! is_stdin ) + fclose(f); } - ti = make_unique(f, prog_name, file_name); - InitEmitTargets(); - while ( ParseTemplate() ) - ; - for ( auto& t : templates ) t->Instantiate(); From 736eb9905486ffc572a0bb8af509898c059cb160 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Wed, 7 Aug 2024 09:32:32 +0100 Subject: [PATCH 267/343] gen-zam: extensive changes corresponding to those described in GH-3872 --- tools/gen-zam/src/Gen-ZAM.cc | 1478 ++++++++++++++++++++++------------ tools/gen-zam/src/Gen-ZAM.h | 353 ++++---- 2 files changed, 1157 insertions(+), 674 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index f030d93df2..8ba48830c2 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -26,39 +26,52 @@ static char under_to_dash(char c) struct TypeInfo { string tag; - ZAM_ExprType et; + ZAM_Type zt; string suffix; string accessor; // doesn't include "As" prefix or "()" suffix bool is_managed; }; static vector ZAM_type_info = { - {"TYPE_ADDR", ZAM_EXPR_TYPE_ADDR, "A", "Addr", true}, - {"TYPE_ANY", ZAM_EXPR_TYPE_ANY, "a", "Any", true}, - {"TYPE_COUNT", ZAM_EXPR_TYPE_UINT, "U", "Count", false}, - {"TYPE_DOUBLE", ZAM_EXPR_TYPE_DOUBLE, "D", "Double", false}, - {"TYPE_FILE", ZAM_EXPR_TYPE_FILE, "f", "File", true}, - {"TYPE_FUNC", ZAM_EXPR_TYPE_FUNC, "F", "Func", true}, - {"TYPE_INT", ZAM_EXPR_TYPE_INT, "I", "Int", false}, - {"TYPE_LIST", ZAM_EXPR_TYPE_LIST, "L", "List", true}, - {"TYPE_OPAQUE", ZAM_EXPR_TYPE_OPAQUE, "O", "Opaque", true}, - {"TYPE_PATTERN", ZAM_EXPR_TYPE_PATTERN, "P", "Pattern", true}, - {"TYPE_RECORD", ZAM_EXPR_TYPE_RECORD, "R", "Record", true}, - {"TYPE_STRING", ZAM_EXPR_TYPE_STRING, "S", "String", true}, - {"TYPE_SUBNET", ZAM_EXPR_TYPE_SUBNET, "N", "SubNet", true}, - {"TYPE_TABLE", ZAM_EXPR_TYPE_TABLE, "T", "Table", true}, - {"TYPE_TYPE", ZAM_EXPR_TYPE_TYPE, "t", "Type", true}, - {"TYPE_VECTOR", ZAM_EXPR_TYPE_VECTOR, "V", "Vector", true}, + {"TYPE_ADDR", ZAM_TYPE_ADDR, "A", "Addr", true}, + {"TYPE_ANY", ZAM_TYPE_ANY, "a", "Any", true}, + {"TYPE_COUNT", ZAM_TYPE_UINT, "U", "Count", false}, + {"TYPE_DOUBLE", ZAM_TYPE_DOUBLE, "D", "Double", false}, + {"TYPE_FILE", ZAM_TYPE_FILE, "f", "File", true}, + {"TYPE_FUNC", ZAM_TYPE_FUNC, "F", "Func", true}, + {"TYPE_INT", ZAM_TYPE_INT, "I", "Int", false}, + {"TYPE_LIST", ZAM_TYPE_LIST, "L", "List", true}, + {"TYPE_OPAQUE", ZAM_TYPE_OPAQUE, "O", "Opaque", true}, + {"TYPE_PATTERN", ZAM_TYPE_PATTERN, "P", "Pattern", true}, + {"TYPE_RECORD", ZAM_TYPE_RECORD, "R", "Record", true}, + {"TYPE_STRING", ZAM_TYPE_STRING, "S", "String", true}, + {"TYPE_SUBNET", ZAM_TYPE_SUBNET, "N", "SubNet", true}, + {"TYPE_TABLE", ZAM_TYPE_TABLE, "T", "Table", true}, + {"TYPE_TYPE", ZAM_TYPE_TYPE, "t", "Type", true}, + {"TYPE_VECTOR", ZAM_TYPE_VECTOR, "V", "Vector", true}, }; -// Given a ZAM_ExprType, returns the corresponding TypeInfo. -const TypeInfo& find_type_info(ZAM_ExprType et) - { - assert(et != ZAM_EXPR_TYPE_NONE); +// Maps op-type mnemonics to the corresponding internal value used by Gen-ZAM. +static unordered_map type_names = { + {'*', ZAM_TYPE_DEFAULT}, {'A', ZAM_TYPE_ADDR}, {'a', ZAM_TYPE_ANY}, + {'D', ZAM_TYPE_DOUBLE}, {'f', ZAM_TYPE_FILE}, {'F', ZAM_TYPE_FUNC}, + {'I', ZAM_TYPE_INT}, {'L', ZAM_TYPE_LIST}, {'X', ZAM_TYPE_NONE}, + {'O', ZAM_TYPE_OPAQUE}, {'P', ZAM_TYPE_PATTERN}, {'R', ZAM_TYPE_RECORD}, + {'S', ZAM_TYPE_STRING}, {'N', ZAM_TYPE_SUBNET}, {'T', ZAM_TYPE_TABLE}, + {'t', ZAM_TYPE_TYPE}, {'U', ZAM_TYPE_UINT}, {'V', ZAM_TYPE_VECTOR}, +}; - auto pred = [et](const TypeInfo& ti) -> bool +// Inverse of the above. +static unordered_map expr_name_types; + +// Given a ZAM_Type, returns the corresponding TypeInfo. +const TypeInfo& find_type_info(ZAM_Type zt) { - return ti.et == et; + assert(zt != ZAM_TYPE_NONE); + + auto pred = [zt](const TypeInfo& ti) -> bool + { + return ti.zt == zt; }; auto ti = std::find_if(ZAM_type_info.begin(), ZAM_type_info.end(), pred); @@ -66,73 +79,75 @@ const TypeInfo& find_type_info(ZAM_ExprType et) return *ti; } -// Given a ZAM_ExprType, return its ZVal accessor. Takes into account +// Given a ZAM_Type, return its ZVal accessor. Takes into account // some naming inconsistencies between ZVal's and Val's. -string find_type_accessor(ZAM_ExprType et) +string find_type_accessor(ZAM_Type zt, bool is_lhs) { - switch ( et ) - { - case ZAM_EXPR_TYPE_NONE: - return ""; + if ( zt == ZAM_TYPE_NONE ) + return ""; - case ZAM_EXPR_TYPE_UINT: - return "uint_val"; + string acc = string("As") + find_type_info(zt).accessor; + if ( is_lhs ) + acc += "Ref"; - case ZAM_EXPR_TYPE_PATTERN: - return "re_val"; - - default: - { - string acc = find_type_info(et).accessor; - transform(acc.begin(), acc.end(), acc.begin(), ::tolower); - return acc + "_val"; - } - } + return acc + "()"; } // Maps ZAM operand types to pairs of (1) the C++ name used to declare // the operand in a method declaration, and (2) the variable name to // use for the operand. -unordered_map> ArgsManager::ot_to_args = { - {ZAM_OT_AUX, {"OpaqueVals*", "v"}}, - {ZAM_OT_CONSTANT, {"const ConstExpr*", "c"}}, - {ZAM_OT_EVENT_HANDLER, {"EventHandler*", "h"}}, - {ZAM_OT_INT, {"int", "i"}}, - {ZAM_OT_LIST, {"const ListExpr*", "l"}}, - {ZAM_OT_RECORD_FIELD, {"const NameExpr*", "n"}}, - {ZAM_OT_VAR, {"const NameExpr*", "n"}}, +unordered_map> ArgsManager::oc_to_args = { + {ZAM_OC_AUX, {"OpaqueVals*", "v"}}, + {ZAM_OC_CONSTANT, {"const ConstExpr*", "c"}}, + {ZAM_OC_EVENT_HANDLER, {"EventHandler*", "h"}}, + {ZAM_OC_INT, {"int", "i"}}, + {ZAM_OC_BRANCH, {"int", "i"}}, + {ZAM_OC_GLOBAL, {"int", "i"}}, + {ZAM_OC_STEP_ITER, {"int", "i"}}, + {ZAM_OC_TBL_ITER, {"int", "i"}}, + {ZAM_OC_LIST, {"const ListExpr*", "l"}}, + {ZAM_OC_RECORD_FIELD, {"const NameExpr*", "n"}}, + {ZAM_OC_VAR, {"const NameExpr*", "n"}}, // The following gets special treatment. - {ZAM_OT_ASSIGN_FIELD, {"const NameExpr*", "n"}}, + {ZAM_OC_ASSIGN_FIELD, {"const NameExpr*", "n"}}, }; -ArgsManager::ArgsManager(const vector& ot, ZAM_InstClass zc) +// The different operand classes that are represented as "raw" integers +// (meaning the slot value is used directly, rather than indexing the frame). +static const set raw_int_oc( + { ZAM_OC_BRANCH, ZAM_OC_GLOBAL, ZAM_OC_INT, ZAM_OC_STEP_ITER, ZAM_OC_TBL_ITER } +); + +ArgsManager::ArgsManager(const OCVec& oc_orig, ZAM_InstClass zc) { + auto oc = oc_orig; + if ( zc == ZIC_COND ) + // Remove the final entry corresponding to the branch, as + // we'll automatically generate it subsequently. + oc.pop_back(); + int n = 0; bool add_field = false; - for ( const auto& ot_i : ot ) + for ( const auto& ot_i : oc ) { - if ( ot_i == ZAM_OT_NONE ) + if ( ot_i == ZAM_OC_NONE ) { // it had better be the only operand type - assert(ot.size() == 1); + assert(oc.size() == 1); break; } - if ( n++ == 0 && zc == ZIC_COND ) - // Skip the conditional's nominal assignment slot. - continue; + ++n; // Start off the argument info using the usual case // of (1) same method parameter name as GenInst argument, // and (2) not requiring a record field. - auto& arg_i = ot_to_args[ot_i]; - Arg arg = {arg_i.second, arg_i.first, arg_i.second, false}; + auto& arg_i = oc_to_args[ot_i]; + Arg arg = {arg_i.second, arg_i.first, arg_i.second}; - if ( ot_i == ZAM_OT_ASSIGN_FIELD ) + if ( ot_i == ZAM_OC_ASSIGN_FIELD ) { - arg.is_field = true; - if ( n == 1 ) { // special-case the parameter arg.decl_name = "flhs"; @@ -185,9 +200,6 @@ void ArgsManager::Differentiate() // Finally, build the full versions of the declaration and parameters. - // Tracks how many record fields we're dealing with. - int num_fields = 0; - for ( auto& arg : args ) { if ( ! full_decl.empty() ) @@ -200,20 +212,6 @@ void ArgsManager::Differentiate() full_params += arg.param_name; params.push_back(arg.param_name); - - if ( arg.is_field ) - ++num_fields; - } - - assert(num_fields <= 2); - - // Add in additional arguments/parameters for record fields. - if ( num_fields == 1 ) - full_params += ", field"; - else if ( num_fields == 2 ) - { - full_decl += ", int field2"; - full_params += ", field1, field2"; } } @@ -242,32 +240,127 @@ void ZAM_OpTemplate::Build() Parse(words[0], line, words); } + + if ( ! op_classes.empty() && ! op_classes_vec.empty() ) + Gripe("\"class\" and \"classes\" are mutually exclusive"); + + if ( ! op_classes.empty() || ! op_classes_vec.empty() ) + { + auto nclasses = op_classes.empty() ? + op_classes_vec[0].size() : op_classes.size(); + + for ( auto& oc : op_classes_vec ) + if ( oc.size() != nclasses ) + Gripe("size mismatch in \"classes\" specifications"); + + if ( ! op_types.empty() && op_types.size() != nclasses ) + Gripe("number of \"op-types\" elements must match \"class\"/\"classes\""); + } + + else if ( ! op_types.empty() ) + Gripe("\"op-types\" can only be used with \"class\"/\"classes\""); } void ZAM_OpTemplate::Instantiate() { - InstantiateOp(OperandTypes(), IncludesVectorOp()); + if ( IsPredicate() ) + InstantiatePredicate(); + + else if ( op_classes_vec.empty() ) + InstantiateOp(OperandClasses(), IncludesVectorOp()); + + else + for ( auto& ocs : op_classes_vec ) + InstantiateOp(ocs, IncludesVectorOp()); + } + +void ZAM_OpTemplate::InstantiatePredicate() + { + if ( ! op_classes_vec.empty() ) + Gripe("\"predicate\" cannot include \"classes\""); + + if ( op_classes.empty() ) + Gripe("\"predicate\" requires a \"class\""); + + if ( IncludesVectorOp() ) + Gripe("\"predicate\" cannot include \"vector\""); + + // Build 3 forms: an assignment to an int-value'd $$, a conditional + // if the evaluation is true, and one if it is not. + + auto orig_eval = eval; + // Remove trailing '\n' from eval. + orig_eval.pop_back(); + + auto orig_op_classes = op_classes; + bool no_classes = orig_op_classes[0] == ZAM_OC_NONE; + + // Assignment form. + op_classes.clear(); + op_classes.push_back(ZAM_OC_VAR); + if ( ! no_classes ) + op_classes.insert(op_classes.end(), orig_op_classes.begin(), orig_op_classes.end()); + + string target_accessor; + + if ( ! op_types.empty() ) + op_types.insert(op_types.begin(), ZAM_TYPE_INT); + else + target_accessor = ".AsIntRef()"; + + eval = "$$" + target_accessor + " = " + orig_eval + ";"; + + InstantiateOp(op_classes, false); + + // Conditional form - branch if not true. + + if ( ! op_types.empty() ) + { + // Remove 'V' at the beginning from the assignment form, + // and add a 'i' at the end for the branch. + op_types.erase(op_types.begin()); + op_types.push_back(ZAM_TYPE_INT); + } + + cname += "_COND"; + op1_flavor = "OP1_READ"; + if ( no_classes ) + op_classes.clear(); + else + op_classes = orig_op_classes; + + op_classes.push_back(ZAM_OC_BRANCH); + + auto branch_pos = to_string(op_classes.size()); + auto suffix = " )\n\t\t$" + branch_pos; + eval = "if ( ! (" + orig_eval + ")" + suffix; + InstantiateOp(op_classes, false); + + // Now the form that branches if true. + cname = "NOT_" + cname; + eval = "if ( (" + orig_eval + ")" + suffix; + InstantiateOp(op_classes, false); } void ZAM_OpTemplate::UnaryInstantiate() { // First operand is always the frame slot to which this operation // assigns the result of the applying unary operator. - vector ots = {ZAM_OT_VAR}; - ots.resize(2); + OCVec ocs = {ZAM_OC_VAR}; + ocs.resize(2); // Now build versions for a constant operand (maybe not actually // needed due to constant folding, but sometimes that gets deferred // to run-time) ... if ( ! NoConst() ) { - ots[1] = ZAM_OT_CONSTANT; - InstantiateOp(ots, IncludesVectorOp()); + ocs[1] = ZAM_OC_CONSTANT; + InstantiateOp(ocs, IncludesVectorOp()); } // ... and for a variable (frame-slot) operand. - ots[1] = ZAM_OT_VAR; - InstantiateOp(ots, IncludesVectorOp()); + ocs[1] = ZAM_OC_VAR; + InstantiateOp(ocs, IncludesVectorOp()); } void ZAM_OpTemplate::Parse(const string& attr, const string& line, const Words& words) @@ -275,56 +368,42 @@ void ZAM_OpTemplate::Parse(const string& attr, const string& line, const Words& int num_args = -1; // -1 = don't enforce int nwords = static_cast(words.size()); - if ( attr == "type" ) + if ( attr == "class" ) { if ( nwords <= 1 ) g->Gripe("missing argument", line); num_args = 1; + op_classes = ParseClass(words[1]); + } - const char* types = words[1].c_str(); - while ( *types ) + else if ( attr == "classes" ) + { + if ( nwords <= 1 ) + g->Gripe("missing argument", line); + + num_args = -1; + + for ( int i = 1; i < nwords; ++i ) + op_classes_vec.push_back(ParseClass(words[i])); + } + + else if ( attr == "op-types" ) + { + if ( words.size() == 1 ) + g->Gripe("op-types needs arguments", line); + + for ( auto i = 1U; i < words.size(); ++i ) { - ZAM_OperandType ot = ZAM_OT_NONE; - switch ( *types ) - { - case 'C': - ot = ZAM_OT_CONSTANT; - break; - case 'F': - ot = ZAM_OT_ASSIGN_FIELD; - break; - case 'H': - ot = ZAM_OT_EVENT_HANDLER; - break; - case 'L': - ot = ZAM_OT_LIST; - break; - case 'O': - ot = ZAM_OT_AUX; - break; - case 'R': - ot = ZAM_OT_RECORD_FIELD; - break; - case 'V': - ot = ZAM_OT_VAR; - break; - case 'i': - ot = ZAM_OT_INT; - break; + auto& w_i = words[i]; + if ( w_i.size() != 1 ) + g->Gripe("bad op-types argument", w_i); - case 'X': - ot = ZAM_OT_NONE; - break; + auto et_c = w_i.c_str()[0]; + if ( type_names.count(et_c) == 0 ) + g->Gripe("bad op-types argument", w_i); - default: - g->Gripe("bad operand type", words[1]); - break; - } - - AddOpType(ot); - - ++types; + op_types.push_back(type_names[et_c]); } } @@ -415,6 +494,71 @@ void ZAM_OpTemplate::Parse(const string& attr, const string& line, const Words& g->Gripe("extraneous or missing arguments", line); } +OCVec ZAM_OpTemplate::ParseClass(const string& spec) const + { + OCVec ocs; + + const char* types = spec.c_str(); + while ( *types ) + { + ZAM_OperandClass oc = ZAM_OC_NONE; + + switch ( *types ) + { + case 'C': + oc = ZAM_OC_CONSTANT; + break; + case 'F': + oc = ZAM_OC_ASSIGN_FIELD; + break; + case 'H': + oc = ZAM_OC_EVENT_HANDLER; + break; + case 'L': + oc = ZAM_OC_LIST; + break; + case 'O': + oc = ZAM_OC_AUX; + break; + case 'R': + oc = ZAM_OC_RECORD_FIELD; + break; + case 'V': + oc = ZAM_OC_VAR; + break; + case 'i': + oc = ZAM_OC_INT; + break; + case 'b': + oc = ZAM_OC_BRANCH; + break; + case 'f': // 'f' = "for" loop + oc = ZAM_OC_TBL_ITER; + break; + case 'g': + oc = ZAM_OC_GLOBAL; + break; + case 's': + oc = ZAM_OC_STEP_ITER; + break; + + case 'X': + oc = ZAM_OC_NONE; + break; + + default: + g->Gripe("bad operand type", spec); + break; + } + + ocs.push_back(oc); + + ++types; + } + + return ocs; + } + string ZAM_OpTemplate::GatherEval() { string res; @@ -436,7 +580,7 @@ string ZAM_OpTemplate::GatherEval() int ZAM_OpTemplate::ExtractTypeParam(const string& arg) { if ( arg == "$$" ) - return 1; + return 0; if ( arg[0] != '$' ) g->Gripe("bad set-type parameter, should be $n", arg); @@ -446,59 +590,93 @@ int ZAM_OpTemplate::ExtractTypeParam(const string& arg) if ( param <= 0 || param > 2 ) g->Gripe("bad set-type parameter, should be $1 or $2", arg); - // Convert operand to underlying instruction element, i.e., add - // one to account for the $$ assignment slot. - return param + 1; + return param; } // Maps an operand type to a character mnemonic used to distinguish // it from others. -unordered_map ZAM_OpTemplate::ot_to_char = { - {ZAM_OT_AUX, 'O'}, {ZAM_OT_CONSTANT, 'C'}, {ZAM_OT_EVENT_HANDLER, 'H'}, - {ZAM_OT_ASSIGN_FIELD, 'F'}, {ZAM_OT_INT, 'i'}, {ZAM_OT_LIST, 'L'}, - {ZAM_OT_NONE, 'X'}, {ZAM_OT_RECORD_FIELD, 'R'}, {ZAM_OT_VAR, 'V'}, +unordered_map ZAM_OpTemplate::oc_to_char = { + {ZAM_OC_AUX, 'O'}, + {ZAM_OC_CONSTANT, 'C'}, + {ZAM_OC_EVENT_HANDLER, 'H'}, + {ZAM_OC_ASSIGN_FIELD, 'F'}, + {ZAM_OC_INT, 'i'}, + {ZAM_OC_LIST, 'L'}, + {ZAM_OC_NONE, 'X'}, + {ZAM_OC_RECORD_FIELD, 'R'}, + {ZAM_OC_VAR, 'V'}, + {ZAM_OC_BRANCH, 'b'}, + {ZAM_OC_GLOBAL, 'g'}, + {ZAM_OC_STEP_ITER, 's'}, + {ZAM_OC_TBL_ITER, 'f'}, }; -void ZAM_OpTemplate::InstantiateOp(const vector& ot, bool do_vec) +void ZAM_OpTemplate::InstantiateOp(const OCVec& oc, bool do_vec) { - auto method = MethodName(ot); + auto method = MethodName(oc); - InstantiateOp(method, ot, ZIC_REGULAR); + InstantiateOp(method, oc, ZIC_REGULAR); if ( IncludesFieldOp() ) - InstantiateOp(method, ot, ZIC_FIELD); + InstantiateOp(method, oc, ZIC_FIELD); if ( do_vec ) - InstantiateOp(method, ot, ZIC_VEC); + InstantiateOp(method, oc, ZIC_VEC); if ( IsConditionalOp() ) - InstantiateOp(method, ot, ZIC_COND); + InstantiateOp(method, oc, ZIC_COND); } -void ZAM_OpTemplate::InstantiateOp(const string& method, const vector& ot, +void ZAM_OpTemplate::InstantiateOp(const string& orig_method, const OCVec& oc_orig, ZAM_InstClass zc) { + auto oc = oc_orig; string suffix = ""; if ( zc == ZIC_FIELD ) - suffix = "_field"; - else if ( zc == ZIC_VEC ) - suffix = "_vec"; + { + // Make room for the offset. + oc.push_back(ZAM_OC_INT); + suffix = NoEval() ? "" : "_field"; + } + else if ( zc == ZIC_COND ) + { + // Remove the assignment and add in the branch. + oc.erase(oc.begin()); + oc.push_back(ZAM_OC_BRANCH); suffix = "_cond"; + } + + else if ( zc == ZIC_VEC ) + { + // Don't generate versions of these for constant operands + // as those don't exist. + if ( int(oc.size()) != Arity() + 1 ) + Gripe("vector class/arity mismatch"); + + if ( oc[1] == ZAM_OC_CONSTANT ) + return; + if ( Arity() > 1 && oc[2] == ZAM_OC_CONSTANT ) + return; + + suffix = "_vec"; + } + + auto method = MethodName(oc); if ( ! IsInternalOp() ) - InstantiateMethod(method, suffix, ot, zc); + InstantiateMethod(method, suffix, oc, zc); if ( IsAssignOp() ) - InstantiateAssignOp(ot, suffix); + InstantiateAssignOp(oc, suffix); else { - InstantiateEval(ot, suffix, zc); + InstantiateEval(oc, suffix, zc); if ( HasAssignmentLess() ) { - auto op_string = "_" + OpSuffix(ot); + auto op_string = "_" + OpSuffix(oc); auto op = g->GenOpCode(this, op_string); GenAssignmentlessVersion(op); } @@ -509,21 +687,16 @@ void ZAM_OpTemplate::GenAssignmentlessVersion(const string& op) { EmitTo(AssignFlavor); Emit("assignmentless_op[" + op + "] = " + AssignmentLessOp() + ";"); - Emit("assignmentless_op_type[" + op + "] = " + AssignmentLessOpType() + ";"); + Emit("assignmentless_op_class[" + op + "] = " + AssignmentLessOpClass() + ";"); } void ZAM_OpTemplate::InstantiateMethod(const string& m, const string& suffix, - const vector& ot_orig, ZAM_InstClass zc) + const OCVec& oc, ZAM_InstClass zc) { if ( IsInternalOp() ) return; - auto ot = ot_orig; - if ( zc == ZIC_FIELD ) - // Need to make room for the field offset. - ot.emplace_back(ZAM_OT_INT); - - auto decls = MethodDeclare(ot, zc); + auto decls = MethodDeclare(oc, zc); EmitTo(MethodDecl); Emit("const ZAMStmt " + m + suffix + "(" + decls + ");"); @@ -532,7 +705,7 @@ void ZAM_OpTemplate::InstantiateMethod(const string& m, const string& suffix, Emit("const ZAMStmt ZAMCompiler::" + m + suffix + "(" + decls + ")"); BeginBlock(); - InstantiateMethodCore(ot, suffix, zc); + InstantiateMethodCore(oc, suffix, zc); if ( HasPostMethod() ) Emit(GetPostMethod()); @@ -544,7 +717,7 @@ void ZAM_OpTemplate::InstantiateMethod(const string& m, const string& suffix, NL(); } -void ZAM_OpTemplate::InstantiateMethodCore(const vector& ot, const string& suffix, +void ZAM_OpTemplate::InstantiateMethodCore(const OCVec& oc, const string& suffix, ZAM_InstClass zc) { if ( HasCustomMethod() ) @@ -553,75 +726,241 @@ void ZAM_OpTemplate::InstantiateMethodCore(const vector& ot, co return; } - assert(! ot.empty()); + assert(! oc.empty()); - string full_suffix = "_" + OpSuffix(ot) + suffix; + string full_suffix = "_" + OpSuffix(oc) + suffix; Emit("ZInstI z;"); - if ( ot[0] == ZAM_OT_AUX ) + if ( oc[0] == ZAM_OC_AUX ) { auto op = g->GenOpCode(this, full_suffix, zc); Emit("z = ZInstI(" + op + ");"); return; } - if ( ot[0] == ZAM_OT_NONE ) + if ( oc[0] == ZAM_OC_NONE ) { auto op = g->GenOpCode(this, full_suffix, zc); Emit("z = GenInst(" + op + ");"); return; } - if ( ot.size() > 1 && ot[1] == ZAM_OT_AUX ) + if ( oc.size() > 1 && oc[1] == ZAM_OC_AUX ) { auto op = g->GenOpCode(this, full_suffix, zc); Emit("z = ZInstI(" + op + ", Frame1Slot(n, " + op + "));"); return; } - ArgsManager args(ot, zc); - BuildInstruction(ot, args.Params(), full_suffix, zc); + ArgsManager args(oc, zc); + BuildInstruction(oc, args.Params(), full_suffix, zc); - auto tp = GetTypeParam(); - if ( tp > 0 ) - Emit("z.SetType(" + args.NthParam(tp - 1) + "->GetType());"); + auto& tp = GetTypeParam(); + if ( tp ) + Emit("z.SetType(" + args.NthParam(*tp) + "->GetType());"); - auto tp2 = GetType2Param(); - if ( tp2 > 0 ) - Emit("z.t2 = " + args.NthParam(tp2 - 1) + "->GetType();"); + auto& tp2 = GetType2Param(); + if ( tp2 ) + Emit("z.SetType2(" + args.NthParam(*tp2) + "->GetType());"); } -void ZAM_OpTemplate::BuildInstruction(const vector& ot, const string& params, +void ZAM_OpTemplate::BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) { auto op = g->GenOpCode(this, suffix, zc); Emit("z = GenInst(" + op + ", " + params + ");"); } -void ZAM_OpTemplate::InstantiateEval(const vector& ot, const string& suffix, - ZAM_InstClass zc) +static bool skippable_ot(ZAM_OperandClass oc) { - auto eval = GetEval(); - - if ( ot.size() > 1 ) - { // Check for use of "$1" to indicate the operand - string op1; - if ( ot[1] == ZAM_OT_CONSTANT ) - op1 = "z.c"; - else if ( ot[1] == ZAM_OT_VAR ) - op1 = "frame[z.v2]"; - - eval = regex_replace(eval, regex("\\$1"), op1); - } - - InstantiateEval(Eval, OpSuffix(ot) + suffix, eval, zc); + return oc == ZAM_OC_EVENT_HANDLER || oc == ZAM_OC_AUX || oc == ZAM_OC_LIST; } -void ZAM_OpTemplate::InstantiateEval(EmitTarget et, const string& op_suffix, const string& eval, +string ZAM_OpTemplate::ExpandParams(const OCVec& oc, string eval, const vector& accessors) const + { + auto have_target = eval.find("$$") != string::npos; + + auto fl = GetOp1Flavor(); + auto need_target = fl == "OP1_WRITE"; + + auto oc_size = oc.size(); + if ( oc_size > 0 ) + { + auto oc0 = oc[0]; + + if ( oc0 == ZAM_OC_NONE || oc0 == ZAM_OC_AUX ) + { + --oc_size; + need_target = false; + } + + else if ( raw_int_oc.count(oc0) > 0 ) + need_target = false; + } + + while ( oc_size > 0 && skippable_ot(oc[oc_size - 1]) ) + --oc_size; + + auto max_param = oc_size; + + if ( need_target && ! have_target ) + Gripe("eval missing $$:", eval); + + if ( have_target ) + { + assert(max_param > 0); + --max_param; + } + + bool has_d1 = eval.find("$1") != string::npos; + bool has_d2 = eval.find("$2") != string::npos; + bool has_d3 = eval.find("$3") != string::npos; + bool has_d4 = eval.find("$4") != string::npos; + + switch ( max_param ) { + case 4: if ( ! has_d4 ) Gripe("eval missing $4", eval); + case 3: if ( ! has_d3 ) Gripe("eval missing $3", eval); + case 2: if ( ! has_d2 ) Gripe("eval missing $2", eval); + case 1: if ( ! has_d1 ) Gripe("eval missing $1", eval); + + case 0: + break; + + default: + Gripe("unexpected param size", to_string(max_param) + " - " + eval); + break; + } + + switch ( max_param ) { + case 0: if ( has_d1 ) Gripe("extraneous $1 in eval", eval); + case 1: if ( has_d2 ) Gripe("extraneous $2 in eval", eval); + case 2: if ( has_d3 ) Gripe("extraneous $3 in eval", eval); + case 3: if ( has_d4 ) Gripe("extraneous $4 in eval", eval); + + case 4: + break; + + default: + Gripe("unexpected param size", to_string(max_param) + " - " + eval); + break; + } + + int frame_slot = 0; + bool const_seen = false; + bool int_seen = false; + + for ( size_t i = 0; i < oc_size; ++i ) + { + string op; + bool needs_accessor = true; + + switch ( oc[i] ) { + case ZAM_OC_VAR: + if ( int_seen ) + Gripe("'V' type specifier after 'i' specifier", eval); + op = "frame[z.v" + to_string(++frame_slot) + "]"; + break; + + case ZAM_OC_RECORD_FIELD: + op = "frame[z.v" + to_string(++frame_slot) + "]"; + break; + + case ZAM_OC_INT: + case ZAM_OC_BRANCH: + case ZAM_OC_GLOBAL: + case ZAM_OC_STEP_ITER: + case ZAM_OC_TBL_ITER: + op = "z.v" + to_string(++frame_slot); + int_seen = true; + needs_accessor = false; + + if ( oc[i] == ZAM_OC_BRANCH ) + op = "Branch(" + op + ")"; + else if ( oc[i] == ZAM_OC_STEP_ITER ) + op = "StepIter(" + op + ")"; + else if ( oc[i] == ZAM_OC_TBL_ITER ) + op = "TableIter(" + op + ")"; + break; + + case ZAM_OC_CONSTANT: + if ( const_seen ) + g->Gripe("double constant", eval.c_str()); + const_seen = true; + op = "z.c"; + break; + + default: + Gripe("unexpected oc type", eval); + break; + } + + if ( needs_accessor ) + { + if ( ! accessors.empty() && ! accessors[i].empty() ) + op += "." + accessors[i]; + else if ( ! op_types.empty() && op_types[i] != ZAM_TYPE_NONE ) + op += "." + find_type_accessor(op_types[i], have_target && i == 0); + } + + else if ( ! op_types.empty() && oc[i] == ZAM_OC_INT ) + { + if ( op_types[i] == ZAM_TYPE_UINT ) + op = "zeek_uint_t(" + op + ")"; + } + + string pat; + if ( i == 0 && have_target ) + pat = "\\$\\$"; + else + pat = "\\$" + to_string(have_target ? i : i + 1); + + auto orig_eval = eval; + eval = regex_replace(eval, regex(pat), op); + if ( orig_eval == eval ) + Gripe("no eval sub", pat + " - " + eval); + } + + return eval; + } + +void ZAM_OpTemplate::InstantiateEval(const OCVec& oc, const string& suffix, ZAM_InstClass zc) { - auto op_code = g->GenOpCode(this, "_" + op_suffix, zc); + if ( NoEval() ) + return; + + auto eval = ExpandParams(oc, GetEval(), accessors); + + GenEval(Eval, OpSuffix(oc), suffix, eval, zc); + } + +void ZAM_OpTemplate::GenEval(EmitTarget et, const string& oc_str, const string& op_suffix, const string& eval, ZAM_InstClass zc) + { + auto op_code = g->GenOpCode(this, "_" + oc_str + op_suffix, zc); + + if ( et == Eval ) + { + auto oc_str_copy = oc_str; + if ( zc == ZIC_COND ) + { + auto n = oc_str_copy.size(); + + if ( oc_str_copy[n-1] == 'V' ) + oc_str_copy[n-1] = 'i'; + + else if ( oc_str_copy[n-1] == 'C' ) + { + if ( oc_str_copy[n-2] != 'V' ) + Gripe("bad operator class"); + + oc_str_copy[n-2] = 'C'; + oc_str_copy[n-1] = 'i'; + } + } + + GenDesc(op_code, oc_str_copy, eval); + } EmitTo(et); Emit("case " + op_code + ":"); @@ -632,11 +971,52 @@ void ZAM_OpTemplate::InstantiateEval(EmitTarget et, const string& op_suffix, con NL(); } -void ZAM_OpTemplate::InstantiateAssignOp(const vector& ot, const string& suffix) +void ZAM_OpTemplate::GenDesc(const string& op_code, const string& oc_str, const string& eval) + { + StartDesc(op_code, oc_str); + Emit(eval); + EndDesc(); + } + +void ZAM_OpTemplate::StartDesc(const string& op_code, const string& oc_str) + { + EmitTo(Desc); + Emit("{ " + op_code + ","); + BeginBlock(); + Emit("\"" + oc_str + "\","); + + if ( op_types.empty() ) + Emit("\"\","); + else + { + string ots; + for ( auto ot : op_types ) + { + if ( ot == ZAM_TYPE_DEFAULT ) + ots += "X"; + else + ots += expr_name_types[ot]; + } + + Emit("\"" + ots + "\", "); + } + + StartString(); + } + +void ZAM_OpTemplate::EndDesc() + { + EndString(); + EndBlock(); + Emit("},"); + } + +void ZAM_OpTemplate::InstantiateAssignOp(const OCVec& oc, const string& suffix) { // First, create a generic version of the operand, which the // ZAM compiler uses to find specific-flavored versions. - auto op_string = "_" + OpSuffix(ot); + auto oc_str = OpSuffix(oc); + auto op_string = "_" + oc_str; auto generic_op = g->GenOpCode(this, op_string); auto flavor_ind = "assignment_flavor[" + generic_op + "]"; @@ -659,10 +1039,16 @@ void ZAM_OpTemplate::InstantiateAssignOp(const vector& ot, cons GenAssignmentlessVersion(op); } + StartDesc(op, oc_str); + GenAssignOpCore(oc, eval, ti.accessor, ti.is_managed); + if ( ! post_eval.empty() ) + Emit(post_eval); + EndDesc(); + EmitTo(Eval); Emit("case " + op + ":"); BeginBlock(); - GenAssignOpCore(ot, eval, ti.accessor, ti.is_managed); + GenAssignOpCore(oc, eval, ti.accessor, ti.is_managed); if ( ! post_eval.empty() ) Emit(post_eval); Emit("break;"); @@ -672,21 +1058,21 @@ void ZAM_OpTemplate::InstantiateAssignOp(const vector& ot, cons post_eval.clear(); } -void ZAM_OpTemplate::GenAssignOpCore(const vector& ot, const string& eval, +void ZAM_OpTemplate::GenAssignOpCore(const OCVec& oc, const string& eval, const string& accessor, bool is_managed) { if ( HasAssignVal() ) { - GenAssignOpValCore(eval, accessor, is_managed); + GenAssignOpValCore(oc, eval, accessor, is_managed); return; } if ( ! eval.empty() ) g->Gripe("assign-op should not have an \"eval\"", eval); - auto lhs_field = (ot[0] == ZAM_OT_ASSIGN_FIELD); - auto rhs_field = lhs_field && ot.size() > 2 && (ot[2] == ZAM_OT_INT); - auto constant_op = (ot[1] == ZAM_OT_CONSTANT); + auto lhs_field = (oc[0] == ZAM_OC_ASSIGN_FIELD); + auto rhs_field = lhs_field && oc.size() > 3 && (oc[3] == ZAM_OC_INT); + auto constant_op = (oc[1] == ZAM_OC_CONSTANT); string rhs = constant_op ? "z.c" : "frame[z.v2]"; @@ -700,12 +1086,12 @@ void ZAM_OpTemplate::GenAssignOpCore(const vector& ot, const st // through a CoerceToAny operation, we allow expressing // these directly. They don't fit with the usual assignment // paradigm since the RHS differs in type from the LHS. - Emit("auto v = z.c.ToVal(z.t);"); + Emit("auto v = z.c.ToVal(Z_TYPE);"); if ( lhs_field ) { Emit("auto r = frame[z.v1].AsRecord();"); - Emit("auto& f = r->RawField(z.v2);"); + Emit("auto& f = DirectField(r, z.v2);"); } else Emit("auto& f = frame[z.v1];"); @@ -724,18 +1110,19 @@ void ZAM_OpTemplate::GenAssignOpCore(const vector& ot, const st auto lhs_offset = constant_op ? 3 : 4; auto rhs_offset = lhs_offset - 1; - Emit("auto v = " + rhs + ".AsRecord()->RawOptField(z.v" + to_string(rhs_offset) + - "); // note, RHS field before LHS field"); + Emit("auto v = DirectOptField(" + rhs + ".AsRecord(), z.v" + to_string(rhs_offset) + + "); // note, RHS field before LHS field\n"); Emit("if ( ! v )"); BeginBlock(); - Emit("ZAM_run_time_error(z.loc, \"field value missing\");"); - Emit("break;"); + Emit("ZAM_run_time_error(Z_LOC, \"field value missing\");"); EndBlock(); + Emit("else"); + BeginBlock(); auto slot = "z.v" + to_string(lhs_offset); Emit("auto r = frame[z.v1].AsRecord();"); - Emit("auto& f = r->RawField(" + slot + "); // note, LHS field after RHS field"); + Emit("auto& f = DirectField(r, " + slot + "); // note, LHS field after RHS field\n"); if ( is_managed ) { @@ -744,6 +1131,11 @@ void ZAM_OpTemplate::GenAssignOpCore(const vector& ot, const st } Emit("f = *v;"); + + if ( lhs_field ) + Emit("r->Modified();"); + + EndBlock(); } else @@ -756,12 +1148,13 @@ void ZAM_OpTemplate::GenAssignOpCore(const vector& ot, const st auto lhs_offset = constant_op ? 2 : 3; auto slot = "z.v" + to_string(lhs_offset); Emit("auto r = frame[z.v1].AsRecord();"); - Emit("auto& f = r->RawField(" + slot + ");"); + Emit("auto& f = DirectField(r, " + slot + ");"); if ( is_managed ) Emit("zeek::Unref(f.ManagedVal());"); Emit("f = " + rhs + ";"); + Emit("r->Modified();"); } else @@ -772,17 +1165,12 @@ void ZAM_OpTemplate::GenAssignOpCore(const vector& ot, const st Emit("frame[z.v1] = ZVal(" + rhs + acc + ");"); } } - - if ( lhs_field ) - Emit("r->Modified();"); } -void ZAM_OpTemplate::GenAssignOpValCore(const string& eval, const string& accessor, bool is_managed) +void ZAM_OpTemplate::GenAssignOpValCore(const OCVec& oc, const string& orig_eval, const string& accessor, bool is_managed) { auto v = GetAssignVal(); - Emit(eval); - // Maps Zeek types to how to get the underlying value from a ValPtr. static unordered_map val_accessors = { {"Addr", "->AsAddrVal()"}, {"Any", ".get()"}, @@ -803,33 +1191,37 @@ void ZAM_OpTemplate::GenAssignOpValCore(const string& eval, const string& access else rhs = v + ".As" + accessor + "()"; + auto eval = orig_eval; + if ( is_managed ) { - Emit("auto rhs = " + rhs + ";"); - Emit("zeek::Ref(rhs);"); - Emit("Unref(frame[z.v1].ManagedVal());"); - Emit("frame[z.v1] = ZVal(rhs);"); + eval += string("auto rhs = ") + rhs + ";\n"; + eval += "zeek::Ref(rhs);\n"; + eval += "Unref($$.ManagedVal());\n"; + eval += "$$ = ZVal(rhs);\n"; } else - Emit("frame[z.v1] = ZVal(" + rhs + ");"); + eval += "$$ = ZVal(" + rhs + ");\n"; + + Emit(ExpandParams(oc, eval)); } -string ZAM_OpTemplate::MethodName(const vector& ot) const +string ZAM_OpTemplate::MethodName(const OCVec& oc) const { - return base_name + OpSuffix(ot); + return base_name + OpSuffix(oc); } -string ZAM_OpTemplate::MethodDeclare(const vector& ot, ZAM_InstClass zc) +string ZAM_OpTemplate::MethodDeclare(const OCVec& oc, ZAM_InstClass zc) { - ArgsManager args(ot, zc); + ArgsManager args(oc, zc); return args.Decls(); } -string ZAM_OpTemplate::OpSuffix(const vector& ot) const +string ZAM_OpTemplate::OpSuffix(const OCVec& oc) const { string os; - for ( auto& o : ot ) - os += ot_to_char[o]; + for ( auto& o : oc ) + os += oc_to_char[o]; return os; } @@ -864,6 +1256,27 @@ void ZAM_OpTemplate::IndentDown() g->IndentDown(); } +void ZAM_OpTemplate::StartString() + { + g->StartString(); + } + +void ZAM_OpTemplate::EndString() + { + g->EndString(); + } + +void ZAM_OpTemplate::Gripe(const char* msg) const + { + g->Gripe(msg, op_loc); + } + +void ZAM_OpTemplate::Gripe(string msg, string addl) const + { + auto full_msg = msg + ": " + addl; + Gripe(full_msg.c_str()); + } + void ZAM_UnaryOpTemplate::Instantiate() { UnaryInstantiate(); @@ -875,19 +1288,6 @@ void ZAM_DirectUnaryOpTemplate::Instantiate() Emit("case EXPR_" + cname + ":\treturn " + direct + "(lhs, rhs);"); } -// Maps op-type mnemonics to the corresponding internal value used by Gen-ZAM. -static unordered_map expr_type_names = { - {'*', ZAM_EXPR_TYPE_DEFAULT}, {'A', ZAM_EXPR_TYPE_ADDR}, {'a', ZAM_EXPR_TYPE_ANY}, - {'D', ZAM_EXPR_TYPE_DOUBLE}, {'f', ZAM_EXPR_TYPE_FILE}, {'F', ZAM_EXPR_TYPE_FUNC}, - {'I', ZAM_EXPR_TYPE_INT}, {'L', ZAM_EXPR_TYPE_LIST}, {'X', ZAM_EXPR_TYPE_NONE}, - {'O', ZAM_EXPR_TYPE_OPAQUE}, {'P', ZAM_EXPR_TYPE_PATTERN}, {'R', ZAM_EXPR_TYPE_RECORD}, - {'S', ZAM_EXPR_TYPE_STRING}, {'N', ZAM_EXPR_TYPE_SUBNET}, {'T', ZAM_EXPR_TYPE_TABLE}, - {'t', ZAM_EXPR_TYPE_TYPE}, {'U', ZAM_EXPR_TYPE_UINT}, {'V', ZAM_EXPR_TYPE_VECTOR}, -}; - -// Inverse of the above. -static unordered_map expr_name_types; - ZAM_ExprOpTemplate::ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, std::move(_base_name)) { @@ -895,7 +1295,7 @@ ZAM_ExprOpTemplate::ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name) if ( ! did_map_init ) { // Create the inverse mapping. - for ( auto& tn : expr_type_names ) + for ( auto& tn : type_names ) expr_name_types[tn.second] = tn.first; did_map_init = true; @@ -916,10 +1316,10 @@ void ZAM_ExprOpTemplate::Parse(const string& attr, const string& line, const Wor g->Gripe("bad op-type argument", w_i); auto et_c = w_i.c_str()[0]; - if ( expr_type_names.count(et_c) == 0 ) + if ( type_names.count(et_c) == 0 ) g->Gripe("bad op-type argument", w_i); - AddExprType(expr_type_names[et_c]); + AddExprType(type_names[et_c]); } } @@ -941,17 +1341,17 @@ void ZAM_ExprOpTemplate::Parse(const string& attr, const string& line, const Wor g->Gripe("bad eval-type type", type); auto type_c = type.c_str()[0]; - if ( expr_type_names.count(type_c) == 0 ) + if ( type_names.count(type_c) == 0 ) g->Gripe("bad eval-type type", type); - auto et = expr_type_names[type_c]; + auto zt = type_names[type_c]; - if ( expr_types.count(et) == 0 ) + if ( expr_types.count(zt) == 0 ) g->Gripe("eval-type type not present in eval-type", type); auto eval = g->SkipWords(line, 2); eval += GatherEval(); - AddEvalSet(et, eval); + AddEvalSet(zt, eval); } else if ( attr == "eval-mixed" ) @@ -966,11 +1366,11 @@ void ZAM_ExprOpTemplate::Parse(const string& attr, const string& line, const Wor auto type_c1 = type1.c_str()[0]; auto type_c2 = type2.c_str()[0]; - if ( expr_type_names.count(type_c1) == 0 || expr_type_names.count(type_c2) == 0 ) + if ( type_names.count(type_c1) == 0 || type_names.count(type_c2) == 0 ) g->Gripe("bad eval-mixed types", line); - auto et1 = expr_type_names[type_c1]; - auto et2 = expr_type_names[type_c2]; + auto et1 = type_names[type_c1]; + auto et2 = type_names[type_c2]; if ( eval_set.count(et1) > 0 ) g->Gripe("eval-mixed uses type also included in op-type", line); @@ -980,15 +1380,35 @@ void ZAM_ExprOpTemplate::Parse(const string& attr, const string& line, const Wor AddEvalSet(et1, et2, eval); } - else if ( attr == "eval-pre" ) + else if ( attr == "precheck" ) { if ( words.size() < 2 ) - g->Gripe("eval-pre needs evaluation", line); + g->Gripe("precheck needs evaluation", line); auto eval = g->SkipWords(line, 1); eval += GatherEval(); + eval.pop_back(); - SetPreEval(eval); + SetPreCheck(eval); + } + + else if ( attr == "precheck-action" ) + { + if ( words.size() < 2 ) + g->Gripe("precheck-action needs evaluation", line); + + auto eval = g->SkipWords(line, 1); + eval += GatherEval(); + eval.pop_back(); + + SetPreCheckAction(eval); + } + + else if ( attr == "explicit-result-type" ) + { + if ( words.size() != 1 ) + g->Gripe("extraneous argument to explicit-result-type", line); + SetHasExplicitResultType(); } else @@ -998,70 +1418,70 @@ void ZAM_ExprOpTemplate::Parse(const string& attr, const string& line, const Wor void ZAM_ExprOpTemplate::Instantiate() { - InstantiateOp(OperandTypes(), IncludesVectorOp()); + if ( ! op_classes_vec.empty() ) + Gripe("expressions cannot use \"classes\""); - if ( op_types.size() > 1 && op_types[1] == ZAM_OT_CONSTANT ) - InstantiateC1(op_types, op_types.size() - 1); - if ( op_types.size() > 2 && op_types[2] == ZAM_OT_CONSTANT ) - InstantiateC2(op_types, op_types.size() - 1); - if ( op_types.size() > 3 && op_types[3] == ZAM_OT_CONSTANT ) - InstantiateC3(op_types); + InstantiateOp(OperandClasses(), IncludesVectorOp()); + + if ( op_classes.size() > 1 && op_classes[1] == ZAM_OC_CONSTANT ) + InstantiateC1(op_classes, op_classes.size() - 1); + if ( op_classes.size() > 2 && op_classes[2] == ZAM_OC_CONSTANT ) + InstantiateC2(op_classes, op_classes.size() - 1); + if ( op_classes.size() > 3 && op_classes[3] == ZAM_OC_CONSTANT ) + InstantiateC3(op_classes); bool all_var = true; - for ( auto i = 1U; i < op_types.size(); ++i ) - if ( op_types[i] != ZAM_OT_VAR ) + for ( auto i = 1U; i < op_classes.size(); ++i ) + if ( op_classes[i] != ZAM_OC_VAR ) all_var = false; if ( all_var ) - InstantiateV(op_types); + InstantiateV(op_classes); - if ( op_types.size() == 3 && op_types[1] == ZAM_OT_RECORD_FIELD && op_types[2] == ZAM_OT_INT ) - InstantiateV(op_types); + if ( op_classes.size() == 3 && op_classes[1] == ZAM_OC_RECORD_FIELD && op_classes[2] == ZAM_OC_INT ) + InstantiateV(op_classes); } -void ZAM_ExprOpTemplate::InstantiateC1(const vector& ots, size_t arity, bool do_vec) +void ZAM_ExprOpTemplate::InstantiateC1(const OCVec& ocs, size_t arity) { string args = "lhs, r1->AsConstExpr()"; - if ( arity == 1 && ots[0] == ZAM_OT_RECORD_FIELD ) + if ( arity == 1 && ocs[0] == ZAM_OC_RECORD_FIELD ) args += ", rhs->AsFieldExpr()->Field()"; else if ( arity > 1 ) { args += ", "; - if ( ots[2] == ZAM_OT_RECORD_FIELD ) + if ( ocs[2] == ZAM_OC_RECORD_FIELD ) args += "rhs->AsFieldExpr()->Field()"; else args += "r2->AsNameExpr()"; } - auto m = MethodName(ots); + auto m = MethodName(ocs); EmitTo(C1Def); EmitNoNL("case EXPR_" + cname + ":"); - if ( do_vec ) - DoVectorCase(m, args); - else - EmitUp("return " + m + "(" + args + ");"); + EmitUp("return " + m + "(" + args + ");"); if ( IncludesFieldOp() ) { EmitTo(C1FieldDef); - Emit("case EXPR_" + cname + ":\treturn " + m + "_field(" + args + ", field);"); + Emit("case EXPR_" + cname + ":\treturn " + m + "i_field(" + args + ", field);"); } } -void ZAM_ExprOpTemplate::InstantiateC2(const vector& ots, size_t arity) +void ZAM_ExprOpTemplate::InstantiateC2(const OCVec& ocs, size_t arity) { string args = "lhs, r1->AsNameExpr(), r2->AsConstExpr()"; if ( arity == 3 ) args += ", r3->AsNameExpr()"; - auto method = MethodName(ots); + auto method = MethodName(ocs); auto m = method.c_str(); EmitTo(C2Def); @@ -1070,26 +1490,26 @@ void ZAM_ExprOpTemplate::InstantiateC2(const vector& ots, size_ if ( IncludesFieldOp() ) { EmitTo(C2FieldDef); - Emit("case EXPR_" + cname + ":\treturn " + m + "_field(" + args + ", field);"); + Emit("case EXPR_" + cname + ":\treturn " + m + "i_field(" + args + ", field);"); } } -void ZAM_ExprOpTemplate::InstantiateC3(const vector& ots) +void ZAM_ExprOpTemplate::InstantiateC3(const OCVec& ocs) { EmitTo(C3Def); - Emit("case EXPR_" + cname + ":\treturn " + MethodName(ots) + + Emit("case EXPR_" + cname + ":\treturn " + MethodName(ocs) + "(lhs, r1->AsNameExpr(), r2->AsNameExpr(), r3->AsConstExpr());"); } -void ZAM_ExprOpTemplate::InstantiateV(const vector& ots) +void ZAM_ExprOpTemplate::InstantiateV(const OCVec& ocs) { - auto m = MethodName(ots); + auto m = MethodName(ocs); string args = "lhs, r1->AsNameExpr()"; - if ( ots.size() >= 3 ) + if ( ocs.size() >= 3 ) { - if ( ots[2] == ZAM_OT_INT ) + if ( ocs[2] == ZAM_OC_INT ) { string acc_flav = IncludesFieldOp() ? "Has" : ""; args += ", rhs->As" + acc_flav + "FieldExpr()->Field()"; @@ -1097,7 +1517,7 @@ void ZAM_ExprOpTemplate::InstantiateV(const vector& ots) else args += ", r2->AsNameExpr()"; - if ( ots.size() == 4 ) + if ( ocs.size() == 4 ) args += ", r3->AsNameExpr()"; } @@ -1111,8 +1531,9 @@ void ZAM_ExprOpTemplate::InstantiateV(const vector& ots) if ( IncludesFieldOp() ) { + string suffix = NoEval() ? "" : "_field"; EmitTo(VFieldDef); - Emit("case EXPR_" + cname + ":\treturn " + m + "_field(" + args + ", field);"); + Emit("case EXPR_" + cname + ":\treturn " + m + "i" + suffix + "(" + args + ", field);"); } } @@ -1135,18 +1556,21 @@ void ZAM_ExprOpTemplate::BuildInstructionCore(const string& params, const string int ncases = 0; - for ( auto& [et1, et2_map] : eval_mixed_set ) - for ( auto& [et2, eval] : et2_map ) - GenMethodTest(et1, et2, params, suffix, ++ncases > 1, zc); + if ( zc != ZIC_VEC ) + for ( auto& [et1, et2_map] : eval_mixed_set ) + for ( auto& [et2, eval] : et2_map ) + GenMethodTest(et1, et2, params, suffix, ++ncases > 1, zc); bool do_default = false; - for ( auto et : ExprTypes() ) + for ( auto zt : ExprTypes() ) { - if ( et == ZAM_EXPR_TYPE_DEFAULT ) + if ( zt == ZAM_TYPE_DEFAULT ) do_default = true; + else if ( zt == ZAM_TYPE_NONE ) + continue; else - GenMethodTest(et, et, params, suffix, ++ncases > 1, zc); + GenMethodTest(zt, zt, params, suffix, ++ncases > 1, zc); } Emit("else"); @@ -1161,33 +1585,33 @@ void ZAM_ExprOpTemplate::BuildInstructionCore(const string& params, const string EmitUp("reporter->InternalError(\"bad tag when generating method core\");"); } -void ZAM_ExprOpTemplate::GenMethodTest(ZAM_ExprType et1, ZAM_ExprType et2, const string& params, +void ZAM_ExprOpTemplate::GenMethodTest(ZAM_Type et1, ZAM_Type et2, const string& params, const string& suffix, bool do_else, ZAM_InstClass zc) { - // Maps ZAM_ExprType's to the information needed (variable name, + // Maps ZAM_Type's to the information needed (variable name, // constant to compare it against) to identify using an "if" test // that a given AST Expr node employs the given type of operand. - static map> if_tests = { - {ZAM_EXPR_TYPE_ADDR, {"i_t", "TYPE_INTERNAL_ADDR"}}, - {ZAM_EXPR_TYPE_ANY, {"tag", "TYPE_ANY"}}, - {ZAM_EXPR_TYPE_DOUBLE, {"i_t", "TYPE_INTERNAL_DOUBLE"}}, - {ZAM_EXPR_TYPE_FILE, {"tag", "TYPE_FILE"}}, - {ZAM_EXPR_TYPE_FUNC, {"tag", "TYPE_FUNC"}}, - {ZAM_EXPR_TYPE_INT, {"i_t", "TYPE_INTERNAL_INT"}}, - {ZAM_EXPR_TYPE_LIST, {"tag", "TYPE_LIST"}}, - {ZAM_EXPR_TYPE_OPAQUE, {"tag", "TYPE_OPAQUE"}}, - {ZAM_EXPR_TYPE_PATTERN, {"tag", "TYPE_PATTERN"}}, - {ZAM_EXPR_TYPE_RECORD, {"tag", "TYPE_RECORD"}}, - {ZAM_EXPR_TYPE_STRING, {"i_t", "TYPE_INTERNAL_STRING"}}, - {ZAM_EXPR_TYPE_SUBNET, {"i_t", "TYPE_INTERNAL_SUBNET"}}, - {ZAM_EXPR_TYPE_TABLE, {"tag", "TYPE_TABLE"}}, - {ZAM_EXPR_TYPE_TYPE, {"tag", "TYPE_TYPE"}}, - {ZAM_EXPR_TYPE_UINT, {"i_t", "TYPE_INTERNAL_UNSIGNED"}}, - {ZAM_EXPR_TYPE_VECTOR, {"tag", "TYPE_VECTOR"}}, + static map> if_tests = { + {ZAM_TYPE_ADDR, {"i_t", "TYPE_INTERNAL_ADDR"}}, + {ZAM_TYPE_ANY, {"tag", "TYPE_ANY"}}, + {ZAM_TYPE_DOUBLE, {"i_t", "TYPE_INTERNAL_DOUBLE"}}, + {ZAM_TYPE_FILE, {"tag", "TYPE_FILE"}}, + {ZAM_TYPE_FUNC, {"tag", "TYPE_FUNC"}}, + {ZAM_TYPE_INT, {"i_t", "TYPE_INTERNAL_INT"}}, + {ZAM_TYPE_LIST, {"tag", "TYPE_LIST"}}, + {ZAM_TYPE_OPAQUE, {"tag", "TYPE_OPAQUE"}}, + {ZAM_TYPE_PATTERN, {"tag", "TYPE_PATTERN"}}, + {ZAM_TYPE_RECORD, {"tag", "TYPE_RECORD"}}, + {ZAM_TYPE_STRING, {"i_t", "TYPE_INTERNAL_STRING"}}, + {ZAM_TYPE_SUBNET, {"i_t", "TYPE_INTERNAL_SUBNET"}}, + {ZAM_TYPE_TABLE, {"tag", "TYPE_TABLE"}}, + {ZAM_TYPE_TYPE, {"tag", "TYPE_TYPE"}}, + {ZAM_TYPE_UINT, {"i_t", "TYPE_INTERNAL_UNSIGNED"}}, + {ZAM_TYPE_VECTOR, {"tag", "TYPE_VECTOR"}}, }; if ( if_tests.count(et1) == 0 ) - g->Gripe("bad op-type", op_loc); + Gripe("bad op-type"); auto if_test = if_tests[et1]; auto if_var = if_test.first; @@ -1207,7 +1631,7 @@ void ZAM_ExprOpTemplate::GenMethodTest(ZAM_ExprType et1, ZAM_ExprType et2, const EmitUp("z = GenInst(" + op + ", " + params + ");"); } -EvalInstance::EvalInstance(ZAM_ExprType _lhs_et, ZAM_ExprType _op1_et, ZAM_ExprType _op2_et, +EvalInstance::EvalInstance(ZAM_Type _lhs_et, ZAM_Type _op1_et, ZAM_Type _op2_et, string _eval, bool _is_def) { lhs_et = _lhs_et; @@ -1219,27 +1643,27 @@ EvalInstance::EvalInstance(ZAM_ExprType _lhs_et, ZAM_ExprType _op1_et, ZAM_ExprT string EvalInstance::LHSAccessor(bool is_ptr) const { - if ( lhs_et == ZAM_EXPR_TYPE_NONE || lhs_et == ZAM_EXPR_TYPE_DEFAULT ) + if ( lhs_et == ZAM_TYPE_NONE || lhs_et == ZAM_TYPE_DEFAULT ) return ""; string deref = is_ptr ? "->" : "."; - string acc = find_type_accessor(lhs_et); + string acc = find_type_accessor(lhs_et, true); return deref + acc; } -string EvalInstance::Accessor(ZAM_ExprType et, bool is_ptr) const +string EvalInstance::Accessor(ZAM_Type zt, bool is_ptr) const { - if ( et == ZAM_EXPR_TYPE_NONE || et == ZAM_EXPR_TYPE_DEFAULT ) + if ( zt == ZAM_TYPE_NONE || zt == ZAM_TYPE_DEFAULT ) return ""; string deref = is_ptr ? "->" : "."; - return deref + "As" + find_type_info(et).accessor + "()"; + return deref + "As" + find_type_info(zt).accessor + "()"; } string EvalInstance::OpMarker() const { - if ( op1_et == ZAM_EXPR_TYPE_DEFAULT || op1_et == ZAM_EXPR_TYPE_NONE ) + if ( op1_et == ZAM_TYPE_DEFAULT || op1_et == ZAM_TYPE_NONE ) return ""; if ( op1_et == op2_et ) @@ -1248,21 +1672,24 @@ string EvalInstance::OpMarker() const return "_" + find_type_info(op1_et).suffix + find_type_info(op2_et).suffix; } -void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, +void ZAM_ExprOpTemplate::InstantiateEval(const OCVec& oc_orig, const string& suffix, ZAM_InstClass zc) { + if ( (HasPreCheck() || HasPreCheckAction()) && + (! HasPreCheck() || ! HasPreCheckAction()) ) + Gripe("precheck and precheck-action must be used together"); + + auto oc = oc_orig; + if ( expr_types.empty() ) - { // No operand types to expand over. - ZAM_OpTemplate::InstantiateEval(ot_orig, suffix, zc); + { + // No operand types to expand over. This happens for + // some "non-uniform" operations. + ZAM_OpTemplate::InstantiateEval(oc, suffix, zc); return; } - auto ot = ot_orig; - if ( zc == ZIC_FIELD ) - // Make room for the offset. - ot.emplace_back(ZAM_OT_INT); - - auto ot_str = OpSuffix(ot); + auto oc_str = OpSuffix(oc); // Some of these might not wind up being used, but no harm in // initializing them in case they are. @@ -1284,31 +1711,40 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, { lhs = "frame[z.v1]"; - auto op1_offset = zc == ZIC_COND ? 1 : 2; - auto op2_offset = op1_offset + 1; - bool ot1_const = ot[1] == ZAM_OT_CONSTANT; - bool ot2_const = Arity() >= 2 && ot[2] == ZAM_OT_CONSTANT; + // First compute the offsets into oc for the operands. + auto op1_offset = zc == ZIC_COND ? 0 : 1; + bool oc1_const = oc[op1_offset] == ZAM_OC_CONSTANT; + bool oc2_const = + Arity() > 1 && oc[op1_offset + 1] == ZAM_OC_CONSTANT; - if ( ot1_const ) + // Now the frame slots. + auto op1_slot = op1_offset + 1; + auto op2_slot = op1_slot + 1; + + if ( oc1_const ) { op1 = "z.c"; - --op2_offset; - branch_target += "2"; + --op2_slot; + if ( zc == ZIC_COND ) + branch_target += "2"; } else { - op1 = "frame[z.v" + to_string(op1_offset) + "]"; + op1 = "frame[z.v" + to_string(op1_slot) + "]"; - if ( Arity() > 1 && ot[2] == ZAM_OT_VAR ) - branch_target += "3"; - else - branch_target += "2"; + if ( zc == ZIC_COND ) + { + if ( Arity() > 1 && ! oc2_const ) + branch_target += "3"; + else + branch_target += "2"; + } } - if ( ot2_const ) + if ( oc2_const ) op2 = "z.c"; else - op2 = "frame[z.v" + to_string(op2_offset) + "]"; + op2 = "frame[z.v" + to_string(op2_slot) + "]"; if ( zc == ZIC_FIELD ) { @@ -1316,30 +1752,35 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, auto f = // The first slots are taken up by the - // assignment slot and the operands ... + // assignment slot and the operands ... Arity() + 1 + // ... and slots are numbered starting at 1. +1; - if ( ot1_const || ot2_const ) + if ( oc1_const || oc2_const ) // One of the operand slots won't be needed // due to the presence of a constant. // (It's never the case that both operands // are constants - those instead get folded.) --f; - lhs += ".AsRecord()->RawField(z.v" + to_string(f) + ")"; + lhs = "DirectField(" + lhs + ".AsRecord(), z.v" + to_string(f) + ")"; } } vector eval_instances; - for ( auto et : expr_types ) + for ( auto zt : expr_types ) { - auto is_def = eval_set.count(et) == 0; - string eval = is_def ? GetEval() : eval_set[et]; - auto lhs_et = IsConditionalOp() ? ZAM_EXPR_TYPE_INT : et; - eval_instances.emplace_back(lhs_et, et, et, eval, is_def); + // Support for "op-type X" meaning "allow empty evaluation", + // as well as "evaluation is generic". + if ( zt == ZAM_TYPE_NONE && GetEval().empty() ) + continue; + + auto is_def = eval_set.count(zt) == 0; + string eval = is_def ? GetEval() : eval_set[zt]; + auto lhs_et = IsConditionalOp() ? ZAM_TYPE_INT : zt; + eval_instances.emplace_back(lhs_et, zt, zt, eval, is_def); } if ( zc != ZIC_VEC ) @@ -1353,21 +1794,52 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, // For the LHS, either its expression type is // ignored, or if it's a conditional, so just // note it for the latter. - auto lhs_et = ZAM_EXPR_TYPE_INT; + auto lhs_et = ZAM_TYPE_INT; eval_instances.emplace_back(lhs_et, et1, et2, em2.second, false); } } for ( auto& ei : eval_instances ) { + op_types.clear(); + auto lhs_accessor = ei.LHSAccessor(); if ( HasExplicitResultType() ) + { + op_types.push_back(ZAM_TYPE_NONE); lhs_accessor = ""; + } + else if ( zc == ZIC_FIELD ) + op_types.push_back(ZAM_TYPE_RECORD); + else if ( zc != ZIC_COND ) + op_types.push_back(ei.LHS_ET()); string lhs_ei = lhs; if ( zc != ZIC_VEC ) lhs_ei += lhs_accessor; + op_types.push_back(ei.Op1_ET()); + if ( Arity() > 1 ) + op_types.push_back(ei.Op2_ET()); + + if ( zc == ZIC_FIELD ) + op_types.push_back(ZAM_TYPE_INT); + + else if ( zc == ZIC_COND ) + op_types.push_back(ZAM_TYPE_INT); + + else if ( zc == ZIC_VEC ) + { + // Above isn't applicable, since we use helper + // functions. + op_types.clear(); + op_types.push_back(ZAM_TYPE_VECTOR); + op_types.push_back(ZAM_TYPE_VECTOR); + + if ( Arity() > 1 ) + op_types.push_back(ZAM_TYPE_VECTOR); + } + auto op1_ei = op1 + ei.Op1Accessor(zc == ZIC_VEC); auto op2_ei = op2 + ei.Op2Accessor(zc == ZIC_VEC); @@ -1388,8 +1860,8 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, eval = regex_replace(eval, regex(rhs), replacement, std::regex_constants::match_not_null); } - auto is_none = ei.LHS_ET() == ZAM_EXPR_TYPE_NONE; - auto is_default = ei.LHS_ET() == ZAM_EXPR_TYPE_DEFAULT; + auto is_none = ei.LHS_ET() == ZAM_TYPE_NONE; + auto is_default = ei.LHS_ET() == ZAM_TYPE_DEFAULT; if ( ! is_none && ! is_default && find_type_info(ei.LHS_ET()).is_managed && ! HasExplicitResultType() ) @@ -1418,7 +1890,15 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, eval = regex_replace(eval, regex("\\$1"), op1_ei); eval = regex_replace(eval, regex("\\$2"), op2_ei); - string pre = GetPreEval(); + string pre, post; + + if ( HasPreCheck() ) + { + pre = "if ( " + GetPreCheck() + ")\n\t{\n\t" + + GetPreCheckAction() + "\n\t}\n\telse\n\t{\n\t"; + post = "\n\t}"; + } + pre = regex_replace(pre, regex("\\$1"), op1_ei); pre = regex_replace(pre, regex("\\$2"), op2_ei); @@ -1426,9 +1906,12 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, eval = regex_replace(eval, regex("\\$\\$"), lhs_ei); else if ( zc == ZIC_COND ) - { // Aesthetics: get rid of trailing newlines. + { + // Aesthetics: get rid of trailing newlines. eval = regex_replace(eval, regex("\n"), ""); - eval = "if ( ! (" + eval + ") ) " + "{ pc = " + branch_target + "; continue; }"; + + eval = "if ( ! (" + eval + ") ) " + + "Branch(" + branch_target + ")"; } else if ( ! is_none && (ei.IsDefault() || IsConditionalOp()) ) @@ -1439,11 +1922,11 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, eval = regex_replace(eval, regex(";*\n"), ";\n"); } - eval = pre + eval; + eval = pre + eval + post; - auto full_suffix = ot_str + suffix + ei.OpMarker(); + auto full_suffix = suffix + ei.OpMarker(); - ZAM_OpTemplate::InstantiateEval(emit_target, full_suffix, eval, zc); + GenEval(emit_target, oc_str, full_suffix, eval, zc); if ( zc == ZIC_VEC ) { @@ -1452,10 +1935,10 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector& ot_orig, if ( Arity() == 2 ) dispatch_params += ", frame[z.v3].AsVector()"; - auto op_code = g->GenOpCode(this, "_" + full_suffix); - auto dispatch = "vec_exec(" + op_code + ", z.t, " + dispatch_params + ", z);"; + auto op_code = g->GenOpCode(this, "_" + oc_str + full_suffix); + auto dispatch = "vec_exec(" + op_code + ", Z_TYPE, " + dispatch_params + ", z);"; - ZAM_OpTemplate::InstantiateEval(Eval, full_suffix, dispatch, zc); + GenEval(Eval, oc_str, full_suffix, dispatch, zc); } } } @@ -1470,13 +1953,6 @@ void ZAM_UnaryExprOpTemplate::Parse(const string& attr, const string& line, cons SetNoConst(); } - else if ( attr == "explicit-result-type" ) - { - if ( words.size() != 1 ) - g->Gripe("extraneous argument to explicit-result-type", line); - SetHasExplicitResultType(); - } - else ZAM_ExprOpTemplate::Parse(attr, line, words); } @@ -1485,36 +1961,35 @@ void ZAM_UnaryExprOpTemplate::Instantiate() { UnaryInstantiate(); - vector ots = {ZAM_OT_VAR, ZAM_OT_CONSTANT}; + OCVec ocs = {ZAM_OC_VAR, ZAM_OC_CONSTANT}; if ( ! NoConst() ) - InstantiateC1(ots, 1, IncludesVectorOp()); + InstantiateC1(ocs, 1); - ots[1] = ZAM_OT_VAR; - InstantiateV(ots); + ocs[1] = ZAM_OC_VAR; + InstantiateV(ocs); } -void ZAM_UnaryExprOpTemplate::BuildInstruction(const vector& ot, +void ZAM_UnaryExprOpTemplate::BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) { const auto& ets = ExprTypes(); - if ( ets.size() == 1 && ets.count(ZAM_EXPR_TYPE_NONE) == 1 ) + if ( ets.size() == 1 && ets.count(ZAM_TYPE_NONE) == 1 ) { - ZAM_ExprOpTemplate::BuildInstruction(ot, params, suffix, zc); + ZAM_ExprOpTemplate::BuildInstruction(oc, params, suffix, zc); return; } - auto constant_op = ot[1] == ZAM_OT_CONSTANT; + auto constant_op = oc[1] == ZAM_OC_CONSTANT; string type_src = constant_op ? "c" : "n2"; - if ( ot[0] == ZAM_OT_ASSIGN_FIELD ) + if ( oc[0] == ZAM_OC_ASSIGN_FIELD ) { type_src = constant_op ? "n" : "n1"; Emit("auto " + type_src + " = flhs->GetOp1()->AsNameExpr();"); Emit("auto t = flhs->GetType();"); - Emit("int field = flhs->Field();"); } else @@ -1531,14 +2006,14 @@ void ZAM_UnaryExprOpTemplate::BuildInstruction(const vector& ot if ( IsAssignOp() && IsFieldOp() ) // These can't take the type from the LHS variable, since // that's the enclosing record and not the field within it. - Emit("z.t = t;"); + Emit("z.SetType(t);"); else if ( zc == ZIC_VEC ) { if ( constant_op ) - Emit("z.t = n->GetType();"); + Emit("z.SetType(n->GetType());"); else - Emit("z.t = n1->GetType();"); + Emit("z.SetType(n1->GetType());"); } } @@ -1546,11 +2021,11 @@ ZAM_AssignOpTemplate::ZAM_AssignOpTemplate(ZAMGen* _g, string _base_name) : ZAM_UnaryExprOpTemplate(_g, std::move(_base_name)) { // Assignments apply to every valid form of ExprType. - for ( auto& etn : expr_type_names ) + for ( auto& etn : type_names ) { - auto et = etn.second; - if ( et != ZAM_EXPR_TYPE_NONE && et != ZAM_EXPR_TYPE_DEFAULT ) - AddExprType(et); + auto zt = etn.second; + if ( zt != ZAM_TYPE_NONE && zt != ZAM_TYPE_DEFAULT ) + AddExprType(zt); } } @@ -1570,44 +2045,46 @@ void ZAM_AssignOpTemplate::Parse(const string& attr, const string& line, const W void ZAM_AssignOpTemplate::Instantiate() { - if ( op_types.size() != 1 ) - g->Gripe("operation needs precisely one \"type\"", op_loc); + if ( op_classes.size() != 1 ) + Gripe("operation needs precisely one \"type\""); + if ( ! op_classes_vec.empty() ) + Gripe("operation cannot use \"classes\""); - vector ots; - ots.push_back(op_types[0]); + OCVec ocs; + ocs.push_back(op_classes[0]); // Build constant/variable versions ... - ots.push_back(ZAM_OT_CONSTANT); + ocs.push_back(ZAM_OC_CONSTANT); - if ( ots[0] == ZAM_OT_RECORD_FIELD ) - ots.push_back(ZAM_OT_INT); + if ( ocs[0] == ZAM_OC_RECORD_FIELD || ocs[0] == ZAM_OC_ASSIGN_FIELD ) + ocs.push_back(ZAM_OC_INT); - InstantiateOp(ots, false); + InstantiateOp(ocs, false); if ( IsFieldOp() ) - InstantiateC1(ots, 1); + InstantiateC1(ocs, 1); - ots[1] = ZAM_OT_VAR; - InstantiateOp(ots, false); + ocs[1] = ZAM_OC_VAR; + InstantiateOp(ocs, false); // ... and for assignments to fields, additional field versions. - if ( ots[0] == ZAM_OT_ASSIGN_FIELD ) + if ( ocs[0] == ZAM_OC_ASSIGN_FIELD ) { - ots.push_back(ZAM_OT_INT); - InstantiateOp(ots, false); + ocs.push_back(ZAM_OC_INT); + InstantiateOp(ocs, false); - ots[1] = ZAM_OT_CONSTANT; - InstantiateOp(ots, false); + ocs[1] = ZAM_OC_CONSTANT; + InstantiateOp(ocs, false); } else if ( IsFieldOp() ) - InstantiateV(ots); + InstantiateV(ocs); } void ZAM_BinaryExprOpTemplate::Instantiate() { // As usual, the first slot receives the operator's result. - vector ots = {ZAM_OT_VAR}; - ots.resize(3); + OCVec ocs = {ZAM_OC_VAR}; + ocs.resize(3); // Build each combination for constant/variable operand, // except skip constant/constant as that is always folded. @@ -1615,39 +2092,39 @@ void ZAM_BinaryExprOpTemplate::Instantiate() // We only include vector operations when both operands // are non-constants. - ots[1] = ZAM_OT_CONSTANT; - ots[2] = ZAM_OT_VAR; - InstantiateOp(ots, false); + ocs[1] = ZAM_OC_CONSTANT; + ocs[2] = ZAM_OC_VAR; + InstantiateOp(ocs, false); if ( ! IsInternalOp() ) - InstantiateC1(ots, 2, false); + InstantiateC1(ocs, 2); - ots[1] = ZAM_OT_VAR; - ots[2] = ZAM_OT_CONSTANT; - InstantiateOp(ots, false); + ocs[1] = ZAM_OC_VAR; + ocs[2] = ZAM_OC_CONSTANT; + InstantiateOp(ocs, false); if ( ! IsInternalOp() ) - InstantiateC2(ots, 2); + InstantiateC2(ocs, 2); - ots[2] = ZAM_OT_VAR; - InstantiateOp(ots, IncludesVectorOp()); + ocs[2] = ZAM_OC_VAR; + InstantiateOp(ocs, IncludesVectorOp()); if ( ! IsInternalOp() ) - InstantiateV(ots); + InstantiateV(ocs); } -void ZAM_BinaryExprOpTemplate::BuildInstruction(const vector& ot, +void ZAM_BinaryExprOpTemplate::BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) { - auto constant_op = ot[1] == ZAM_OT_CONSTANT; + auto constant_op = oc[1] == ZAM_OC_CONSTANT; string type_src = constant_op ? "c" : "n2"; auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; Emit("auto t = " + type_src + "->GetType()" + type_suffix); BuildInstructionCore(params, suffix, zc); if ( zc == ZIC_VEC ) - Emit("z.t = n1->GetType();"); + Emit("z.SetType(n1->GetType());"); } void ZAM_RelationalExprOpTemplate::Instantiate() @@ -1659,16 +2136,16 @@ void ZAM_RelationalExprOpTemplate::Instantiate() Emit("case EXPR_" + cname + ":"); IndentUp(); Emit("if ( n1 && n2 )"); - EmitUp("return " + cname + "VVV_cond(n1, n2);"); + EmitUp("return " + cname + "VVb_cond(n1, n2);"); Emit("else if ( n1 )"); - EmitUp("return " + cname + "VVC_cond(n1, c);"); + EmitUp("return " + cname + "VCb_cond(n1, c);"); Emit("else"); - EmitUp("return " + cname + "VCV_cond(c, n2);"); + EmitUp("return " + cname + "CVb_cond(c, n2);"); IndentDown(); NL(); } -void ZAM_RelationalExprOpTemplate::BuildInstruction(const vector& ot, +void ZAM_RelationalExprOpTemplate::BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) { @@ -1676,16 +2153,16 @@ void ZAM_RelationalExprOpTemplate::BuildInstruction(const vectorGetType();"); - } - -void ZAM_InternalBinaryOpTemplate::Parse(const string& attr, const string& line, const Words& words) - { - if ( attr == "op-accessor" ) - { - if ( words.size() != 2 ) - g->Gripe("op-accessor takes one argument", line); - - SetOpAccessor(words[1]); - } - - else if ( attr == "op1-accessor" ) - { - if ( words.size() != 2 ) - g->Gripe("op-accessor1 takes one argument", line); - - SetOp1Accessor(words[1]); - } - - else if ( attr == "op2-accessor" ) - { - if ( words.size() != 2 ) - g->Gripe("op-accessor2 takes one argument", line); - - SetOp2Accessor(words[1]); - } - - else - ZAM_BinaryExprOpTemplate::Parse(attr, line, words); - } - -void ZAM_InternalBinaryOpTemplate::InstantiateEval(const vector& ot, - const string& suffix, ZAM_InstClass zc) - { - assert(ot.size() == 3); - - auto op1_const = ot[1] == ZAM_OT_CONSTANT; - auto op2_const = ot[2] == ZAM_OT_CONSTANT; - - string op1 = op1_const ? "z.c" : "frame[z.v2]"; - string op2 = op2_const ? "z.c" : (op1_const ? "frame[z.v2]" : "frame[z.v3]"); - - string prelude = "auto op1 = " + op1 + "." + op1_accessor + ";\n"; - prelude += "auto op2 = " + op2 + "." + op2_accessor + ";\n"; - - auto eval = prelude + GetEval(); - - auto& ets = ExprTypes(); - if ( ! ets.empty() ) - { - if ( ets.size() != 1 ) - g->Gripe("internal-binary-op's can have at most one op-type", op_loc); - - for ( auto& et : ets ) - { - auto acc = find_type_accessor(et); - auto lhs = "frame[z.v1]." + acc; - eval = regex_replace(eval, regex("\\$\\$"), lhs); - } - } - - ZAM_OpTemplate::InstantiateEval(Eval, OpSuffix(ot) + suffix, eval, zc); + Emit("z.SetType(n1->GetType());"); } void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const Words& words) { - if ( attr != "num-call-args" ) + if ( attr == "num-call-args" ) + ParseCall(line, words); + + else if ( attr == "indirect-call" || attr == "indirect-local-call" ) { - if ( attr == "indirect-call" || attr == "indirect-local-call" ) - { - if ( words.size() != 1 ) - g->Gripe("indirect-call takes one argument", line); - // Note, currently only works with a *subsequent* - // num-call-args, whose setting needs to be 'n'. - is_indirect_call = true; + if ( words.size() != 1 ) + g->Gripe("indirect-call takes one argument", line); - if ( attr == "indirect-local-call" ) - is_local_indirect_call = true; - } - else - ZAM_OpTemplate::Parse(attr, line, words); + // Note, currently only works with a *subsequent* num-call-args, + // whose setting needs to be 'n'. + is_indirect_call = true; - return; + if ( attr == "indirect-local-call" ) + is_local_indirect_call = true; } + else + ZAM_OpTemplate::Parse(attr, line, words); + } + +void ZAM_InternalOpTemplate::ParseCall(const string& line, const Words& words) + { if ( words.size() != 2 ) g->Gripe("num-call-args takes one argument", line); @@ -1794,22 +2211,14 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const auto arg_offset = HasAssignVal() ? 1 : 0; auto arg_slot = arg_offset + 1; - string func = "z.aux->func"; + string func = "Z_AUX->func"; if ( n == 1 ) - { - eval += "args.push_back("; - if ( op_types[arg_offset] == ZAM_OT_CONSTANT ) - eval += "z.c"; - else - eval += "frame[z.v" + to_string(arg_slot) + "]"; - - eval += ".ToVal(z.t));\n"; - } + eval += "args.push_back($1.ToVal(Z_TYPE));\n"; else if ( n != 0 ) { - eval += "auto aux = z.aux;\n"; + eval += "auto aux = Z_AUX;\n"; if ( n < 0 ) { @@ -1818,11 +2227,7 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const func = "func"; if ( is_local_indirect_call ) - { - eval += "auto sel = z.v" + - to_string(arg_slot) + ";\n"; - eval += "auto func = frame[sel].AsFunc();\n"; - } + eval += "auto func = $1.AsFunc();\n"; else { eval += "auto func_v = aux->id_val->GetVal();\n"; @@ -1831,7 +2236,7 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const eval += "if ( ! func )\n"; eval += "\t{\n"; - eval += "\tZAM_run_time_error(z.loc, \"value used but not set\");\n"; + eval += "\tZAM_run_time_error(Z_LOC, \"value used but not set\");\n"; eval += "\tbreak;\n"; eval += "\t}\n"; } @@ -1850,7 +2255,7 @@ void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const } } - eval += "f->SetOnlyCall(z.aux->call_expr.get());\n"; + eval += "f->SetOnlyCall(Z_AUX->call_expr.get());\n"; eval += "ZAM_PROFILE_PRE_CALL\n"; if ( HasAssignVal() ) @@ -2012,6 +2417,9 @@ void ZAMGen::ReadMacro(const string& line) break; } + if ( regex_search(s, regex("\\$[$123]")) ) + Gripe("macro has $-param", s); + mac.push_back(s); } @@ -2092,12 +2500,30 @@ void ZAMGen::Emit(EmitTarget et, const string& s) FILE* f = gen_files[et]; for ( auto i = indent_level; i > 0; --i ) - fputs("\t", f); + fputc('\t', f); - fputs(s.c_str(), f); + if ( string_lit ) + { + fputc('"', f); + for ( auto sp = s.c_str(); *sp; ++sp ) + { + if ( *sp == '\\' ) + fputs("\\\\", f); + else if ( *sp == '"' ) + fputs("\\\"", f); + else if ( *sp == '\n' ) + fputs("\\n", f); + else + fputc(*sp, f); + } + fputc('"', f); + } + + else + fputs(s.c_str(), f); if ( ! no_NL && (s.empty() || s.back() != '\n') ) - fputs("\n", f); + fputc('\n', f); } void ZAMGen::InitEmitTargets() @@ -2112,6 +2538,7 @@ void ZAMGen::InitEmitTargets() {C2FieldDef, "ZAM-GenFieldsDefsC2.h"}, {C3Def, "ZAM-GenExprsDefsC3.h"}, {Cond, "ZAM-Conds.h"}, + {Desc, "ZAM-Desc.h"}, {DirectDef, "ZAM-DirectDefs.h"}, {Eval, "ZAM-EvalDefs.h"}, {EvalMacros, "ZAM-EvalMacros.h"}, @@ -2245,10 +2672,13 @@ bool ZAMGen::ParseTemplate() t = make_unique(this, op_name); else if ( op == "rel-expr-op" ) t = make_unique(this, op_name); - else if ( op == "internal-binary-op" ) - t = make_unique(this, op_name); else if ( op == "internal-op" ) t = make_unique(this, op_name); + else if ( op == "predicate-op" ) + { + t = make_unique(this, op_name); + t->SetIsPredicate(); + } else if ( op == "internal-assignment-op" ) t = make_unique(this, op_name); diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index 0a3af45d0b..b05db91d90 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -10,7 +10,9 @@ #pragma once #include +#include #include +#include #include #include #include @@ -29,57 +31,66 @@ enum ZAM_InstClass ZIC_FIELD, // a record field assignment }; -// For a given instruction operand, its general type. -enum ZAM_OperandType +// For a given instruction operand, its general class. +enum ZAM_OperandClass { - ZAM_OT_CONSTANT, // uses the instruction's associated constant - ZAM_OT_EVENT_HANDLER, // uses the associated event handler - ZAM_OT_INT, // directly specified integer - ZAM_OT_VAR, // frame slot associated with a variable + ZAM_OC_CONSTANT, // uses the instruction's associated constant + ZAM_OC_EVENT_HANDLER, // uses the associated event handler + ZAM_OC_INT, // directly specified integer + ZAM_OC_VAR, // frame slot associated with a variable - ZAM_OT_ASSIGN_FIELD, // record field offset to assign to - ZAM_OT_RECORD_FIELD, // record field offset to access + ZAM_OC_ASSIGN_FIELD, // record field offset to assign to + ZAM_OC_RECORD_FIELD, // record field offset to access // The following wind up the same in the ultimate instruction, // but they differ in the calling sequences used to generate // the instruction. - ZAM_OT_AUX, // uses the instruction's "aux" field - ZAM_OT_LIST, // a list, managed via the "aux" field + ZAM_OC_AUX, // uses the instruction's "aux" field + ZAM_OC_LIST, // a list, managed via the "aux" field - ZAM_OT_NONE, // instruction has no direct operands + // Internal types: branches, tracking globals, step-wise iterations + // (vectors and strings), table iterations. + ZAM_OC_BRANCH, + ZAM_OC_GLOBAL, + ZAM_OC_STEP_ITER, + ZAM_OC_TBL_ITER, + + ZAM_OC_NONE, // instruction has no direct operands }; +using OCVec = vector; + // For instructions corresponding to evaluating expressions, the type // of a given operand. The generator uses these to transform the operand's // low-level ZVal into a higher-level type expected by the associated // evaluation code. -enum ZAM_ExprType +enum ZAM_Type { - ZAM_EXPR_TYPE_ADDR, - ZAM_EXPR_TYPE_ANY, - ZAM_EXPR_TYPE_DOUBLE, - ZAM_EXPR_TYPE_FUNC, - ZAM_EXPR_TYPE_INT, - ZAM_EXPR_TYPE_PATTERN, - ZAM_EXPR_TYPE_RECORD, - ZAM_EXPR_TYPE_STRING, - ZAM_EXPR_TYPE_SUBNET, - ZAM_EXPR_TYPE_TABLE, - ZAM_EXPR_TYPE_UINT, - ZAM_EXPR_TYPE_VECTOR, - ZAM_EXPR_TYPE_FILE, - ZAM_EXPR_TYPE_OPAQUE, - ZAM_EXPR_TYPE_LIST, - ZAM_EXPR_TYPE_TYPE, + ZAM_TYPE_ADDR, + ZAM_TYPE_ANY, + ZAM_TYPE_DOUBLE, + ZAM_TYPE_FUNC, + ZAM_TYPE_INT, + ZAM_TYPE_PATTERN, + ZAM_TYPE_RECORD, + ZAM_TYPE_STRING, + ZAM_TYPE_SUBNET, + ZAM_TYPE_TABLE, + ZAM_TYPE_UINT, + ZAM_TYPE_VECTOR, + ZAM_TYPE_FILE, + ZAM_TYPE_OPAQUE, + ZAM_TYPE_LIST, + ZAM_TYPE_TYPE, // Used to specify "apart from the explicitly specified operand // types, do this action for any other types". - ZAM_EXPR_TYPE_DEFAULT, + ZAM_TYPE_DEFAULT, // Used for expressions where the evaluation code for the // expression deals directly with the operand's ZVal, rather // than the generator providing a higher-level version. - ZAM_EXPR_TYPE_NONE, + ZAM_TYPE_NONE, }; // We only use the following in the context where the vector's elements @@ -132,6 +143,9 @@ enum EmitTarget // conditionals. Cond, + // Descriptions of final ZAM operations, used for validation. + Desc, + // Switch cases that provide the C++ code for executing specific // individual ZAM instructions. Eval, @@ -176,15 +190,15 @@ enum EmitTarget OpName, }; -// A helper class for managing the (ordered) collection of ZAM_OperandType's +// A helper class for managing the (ordered) collection of ZAM_OperandClass's // associated with an instruction in order to generate C++ calling sequences // (both parameters for declarations, and arguments for invocations). class ArgsManager { public: - // Constructed by providing the various ZAM_OperandType's along + // Constructed by providing the various ZAM_OperandClass's along // with the instruction's class. - ArgsManager(const vector& ot, ZAM_InstClass ic); + ArgsManager(const OCVec& oc, ZAM_InstClass ic); // Returns a string defining the parameters for a declaration; // these have full C++ type information along with the parameter @@ -205,25 +219,23 @@ private: // "x1", "x2", etc. void Differentiate(); - // Maps ZAM_OperandType's to their associated C++ type and + // Maps ZAM_OperandClass's to their associated C++ type and // canonical parameter name. - static std::unordered_map> ot_to_args; + static std::unordered_map> oc_to_args; // For a single argument/parameter, tracks its declaration name, // C++ type, and the name to use when providing it as a parameter. - // These last two names are potentially distinct when we're - // assigning to record field (which is tracked by the is_field - // member variable), hence the need to track both. + // We have two names because in some contexts record fields have + // different names in declarations vs. in parameter lists. struct Arg { string decl_name; string decl_type; string param_name; - bool is_field; }; // All of the argument/parameters associated with the collection - // of ZAM_OperandType's. + // of ZAM_OperandClass's. vector args; // Each of the individual parameters. @@ -234,10 +246,9 @@ private: string full_params; }; -// There are two mutually interacting classes: ZAMGen is the overall -// driver for the ZAM generator, while ZAM_OpTemplate represents a -// single operation template, with subclasses for specific types of -// operations. +// There are two mutually interacting classes: ZAMGen is the overall driver +// for the ZAM generator, while ZAM_OpTemplate represents a single operation +// template, with subclasses for specific types of operations. class ZAMGen; class ZAM_OpTemplate @@ -270,15 +281,25 @@ public: // with this operation. const string& GetOp1Flavor() const { return op1_flavor; } - // True if this is an operation with side effects (see OpSideEffects - // above). + // True if this operation has side effects (see OpSideEffects above). bool HasSideEffects() const { return has_side_effects; } + // True if this operation has a predicate form (i.e., yields a + // boolean value that can be used in conditionals). + void SetIsPredicate() { is_predicate = true; } + bool IsPredicate() const { return is_predicate; } + + // The number of operands the operation takes (not including its + // assignment target). A value of 0 is used for operations that + // require special handling. + virtual int Arity() const { return 0; } + protected: - // Append to the list of operand types associated with this operation. - void AddOpType(ZAM_OperandType ot) { op_types.push_back(ot); } - // Retrieve the list of operand types associated with this operation. - const vector& OperandTypes() const { return op_types; } + // Do instantiation for predicate operations. + void InstantiatePredicate(); + + // Retrieve the list of operand classes associated with this operation. + const OCVec& OperandClasses() const { return op_classes; } // Specify the ZAMOp1Flavor associated with this operation. See // GetOp1Flavor() above for the corresponding accessor. @@ -287,12 +308,12 @@ protected: // Specify/fetch the parameter (operand) from which to take the // primary type of this operation. void SetTypeParam(int param) { type_param = param; } - int GetTypeParam() const { return type_param; } + const auto& GetTypeParam() const { return type_param; } // Specify/fetch the parameter (operand) from which to take the // secondary type of this operation. void SetType2Param(int param) { type2_param = param; } - int GetType2Param() const { return type2_param; } + const auto& GetType2Param() const { return type2_param; } // Tracking of assignment values (C++ variables that hold the // value that should be assigned to usual frame slot). @@ -353,13 +374,13 @@ protected: // is used in a dead assignment, should be converted to a different // operation that explictly omits any assignment. bool HasAssignmentLess() const { return ! assignment_less_op.empty(); } - void SetAssignmentLess(string op, string op_type) + void SetAssignmentLess(string op, string op_class) { assignment_less_op = op; - assignment_less_op_type = op_type; + assignment_less_op_class = op_class; } const string& AssignmentLessOp() const { return assignment_less_op; } - const string& AssignmentLessOpType() const { return assignment_less_op_type; } + const string& AssignmentLessOpClass() const { return assignment_less_op_class; } // Builds the instructions associated with this operation, assuming // a single operand. @@ -373,6 +394,9 @@ protected: // words. virtual void Parse(const string& attr, const string& line, const Words& words); + // Helper function that parses "class" specifications. + OCVec ParseClass(const string& spec) const; + // Scans in a C++ evaluation block, which continues until encountering // a line that does not start with whitespace, or that's empty. string GatherEval(); @@ -382,68 +406,89 @@ protected: int ExtractTypeParam(const string& arg); // Generates instructions for each of the different flavors of the - // given operation. "ot" specifies the types of operands for the + // given operation. "oc" specifies the classes of operands for the // instruction, and "do_vec" whether to generate a vector version. - void InstantiateOp(const vector& ot, bool do_vec); + void InstantiateOp(const OCVec& oc, bool do_vec); // Generates one specific flavor ("zc") of the given operation, - // using a method named 'm', the given operand types, and the class. - void InstantiateOp(const string& m, const vector& ot, ZAM_InstClass zc); + // using a method named 'm', the given operand classes, and the + // instruction class. + void InstantiateOp(const string& m, const OCVec& oc, ZAM_InstClass zc); // Generates the "assignment-less" version of the given op-code. void GenAssignmentlessVersion(const string& op); // Generates the method 'm' for an operation, where "suffix" is // a (potentially empty) string differentiating the method from - // others for that operation, and "ot" and "zc" are the same + // others for that operation, and "oc" and "zc" are the same // as above. - void InstantiateMethod(const string& m, const string& suffix, const vector& ot, + void InstantiateMethod(const string& m, const string& suffix, const OCVec& oc, ZAM_InstClass zc); // Generates the main logic of an operation's method, given the - // specific operand types, an associated suffix for differentiating + // specific operand classes, an associated suffix for differentiating // ZAM instructions, and the instruction class. - void InstantiateMethodCore(const vector& ot, const string& suffix, ZAM_InstClass zc); + void InstantiateMethodCore(const OCVec& oc, const string& suffix, ZAM_InstClass zc); // Generates the specific code to create a ZInst for the given // operation, operands, parameters to "GenInst", and suffix and // class per the above. - virtual void BuildInstruction(const vector& ot, const string& params, + virtual void BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc); + // Expands $-parameters into their direct representations given the + // operand classes and associated accessors. + string ExpandParams(const OCVec& oc, string eval, const vector& accessors) const; + string ExpandParams(const OCVec& oc, string eval) const + { + vector no_accessors; + return ExpandParams(oc, std::move(eval), no_accessors); + } + // Top-level driver for generating the C++ evaluation code for // a given flavor of operation. - virtual void InstantiateEval(const vector& ot, const string& suffix, + virtual void InstantiateEval(const OCVec& oc, const string& suffix, ZAM_InstClass zc); // Generates the C++ case statement for evaluating the given flavor // of operation. - void InstantiateEval(EmitTarget et, const string& op_suffix, const string& eval, - ZAM_InstClass zc); + void GenEval(EmitTarget et, const string& ot_str, const string& op_suffix, const string& eval, + ZAM_InstClass zc); + + // Generates a description of the ZAM operation suitable for + // reflection. + void GenDesc(const string& op_code, const string& ot_str, const string& eval); + + // Generates the first part of a description, up to (but not including) + // the evaluation. + void StartDesc(const string& op_code, const string& ot_str); + + // Finishes a description, once the evaluation is done. + void EndDesc(); // Generates a set of assignment C++ evaluations, one per each // possible Zeek scripting type of operand. - void InstantiateAssignOp(const vector& ot, const string& suffix); + void InstantiateAssignOp(const OCVec& oc, const string& suffix); // Generates a C++ evaluation for an assignment of the type // corresponding to "accessor". If "is_managed" is true then // generates the associated memory management, too. - void GenAssignOpCore(const vector& ot, const string& eval, + void GenAssignOpCore(const OCVec& oc, const string& eval, const string& accessor, bool is_managed); // The same, but for when there's an explicit assignment value. - void GenAssignOpValCore(const string& eval, const string& accessor, bool is_managed); + void GenAssignOpValCore(const OCVec& oc, const string& eval, const string& accessor, bool is_managed); // Returns the name of the method associated with the particular - // list of operand types. - string MethodName(const vector& ot) const; + // list of operand classes. + string MethodName(const OCVec& oc) const; // Returns the parameter declarations to use in declaring a method. - string MethodDeclare(const vector& ot, ZAM_InstClass zc); + string MethodDeclare(const OCVec& oc, ZAM_InstClass zc); // Returns a suffix that differentiates an operation name for - // a specific list of operand types. - string OpSuffix(const vector& ot) const; + // a specific list of operand classes. + string OpSuffix(const OCVec& oc) const; // Returns a copy of the given string with leading whitespace // removed. @@ -485,9 +530,18 @@ protected: IndentDown(); } - // Maps an operand type to a character mnemonic used to distinguish + // Start/finish emiting a (likely multi-line) string literal - + // see corresponding ZAMGen methods. + void StartString(); + void EndString(); + + // Exit with an error, mainly for consistency-checking. + void Gripe(const char* msg) const; + void Gripe(string msg, string addl) const; + + // Maps an operand class to a character mnemonic used to distinguish // it from others. - static std::unordered_map ot_to_char; + static std::unordered_map oc_to_char; // The associated driver object. ZAMGen* g; @@ -503,18 +557,31 @@ protected: // The current emission target. EmitTarget curr_et = None; - // The operand types for operations that have a single fixed list. + // The operand classes for operations that have a single fixed list. // Some operations (like those evaluating expressions) instead have - // dynamically generated range of possible operand types. - vector op_types; + // dynamically generated range of possible operand classes. + OCVec op_classes; + + // For operations that have several fixed operand sets to work through. + vector op_classes_vec; + + // If non-empty, the ZAM types associated with each operand, + // left-to-right mirroring the order of the op_classes. + vector op_types; + + // The following is usually empty, but can be instantiated when + // iterating across "types" that in some instances include ZAM_OC_INT, + // in which case those will have ".int_val" accessors associated + // with those slots. + vector accessors; // See the description of Op1Flavor above. string op1_flavor = "OP1_WRITE"; // Tracks the result of ExtractTypeParam() used for "type" and // "type2" attributes. - int type_param = 0; // 0 = not set - int type2_param = 0; + std::optional type_param; + std::optional type2_param; // If non-empty, the value to assign to the target in an assignment // operation. @@ -547,11 +614,17 @@ protected: // If true, then this operation has side effects. bool has_side_effects = false; + // Whether to instantiate this operation as a predicate, which + // results in three versions: (1) assignment of the evaluation to + // a (integer-typed) target, (2) branch if the evaluation *is not* + // the case, (3) branch if the evaluation *is* the case. + bool is_predicate = false; + // If non-empty, then specifies the associated operation that // is a version of this operation but without assigning the result; - // and the operand type (like "OP_V") of that associated operation. + // and the operand class (like "OP_V") of that associated operation. string assignment_less_op; - string assignment_less_op_type; + string assignment_less_op_class; }; // A subclass used for "unary-op" templates. @@ -595,7 +668,7 @@ public: // "is_def" is true if this instance is for the default catch-all // where the operand types don't match any of the explicitly // specified evaluations; - EvalInstance(ZAM_ExprType lhs_et, ZAM_ExprType op1_et, ZAM_ExprType op2_et, string eval, + EvalInstance(ZAM_Type lhs_et, ZAM_Type op1_et, ZAM_Type op2_et, string eval, bool is_def); // Returns the accessor to use for assigning to the LHS. "is_ptr" @@ -608,20 +681,23 @@ public: string Op2Accessor(bool is_ptr = false) const { return Accessor(op2_et, is_ptr); } // Provides an accessor for an operand of the given type. - string Accessor(ZAM_ExprType et, bool is_ptr = false) const; + string Accessor(ZAM_Type zt, bool is_ptr = false) const; // Returns the "marker" use to make unique the opcode for this // flavor of expression-evaluation instruction. string OpMarker() const; const string& Eval() const { return eval; } - ZAM_ExprType LHS_ET() const { return lhs_et; } bool IsDefault() const { return is_def; } + ZAM_Type LHS_ET() const { return lhs_et; } + ZAM_Type Op1_ET() const { return op1_et; } + ZAM_Type Op2_ET() const { return op2_et; } + private: - ZAM_ExprType lhs_et; - ZAM_ExprType op1_et; - ZAM_ExprType op2_et; + ZAM_Type lhs_et; + ZAM_Type op1_et; + ZAM_Type op2_et; string eval; bool is_def; }; @@ -632,19 +708,14 @@ class ZAM_ExprOpTemplate : public ZAM_OpTemplate public: ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name); - // The number of operands the operation takes (not including its - // assignment target). A value of 0 is used for expressions that - // require special handling. - virtual int Arity() const { return 0; } - int HasExplicitResultType() const { return explicit_res_type; } void SetHasExplicitResultType() { explicit_res_type = true; } - void AddExprType(ZAM_ExprType et) { expr_types.insert(et); } - const std::unordered_set& ExprTypes() const { return expr_types; } + void AddExprType(ZAM_Type zt) { expr_types.insert(zt); } + const std::unordered_set& ExprTypes() const { return expr_types; } - void AddEvalSet(ZAM_ExprType et, string ev) { eval_set[et] += ev; } - void AddEvalSet(ZAM_ExprType et1, ZAM_ExprType et2, string ev) + void AddEvalSet(ZAM_Type zt, string ev) { eval_set[zt] += ev; } + void AddEvalSet(ZAM_Type et1, ZAM_Type et2, string ev) { eval_mixed_set[et1][et2] += ev; } @@ -652,9 +723,13 @@ public: bool IncludesFieldOp() const override { return includes_field_op; } void SetIncludesFieldOp() { includes_field_op = true; } - bool HasPreEval() const { return ! pre_eval.empty(); } - void SetPreEval(string pe) { pre_eval = SkipWS(pe); } - const string& GetPreEval() const { return pre_eval; } + bool HasPreCheck() const { return ! pre_check.empty(); } + void SetPreCheck(string pe) { pre_check = SkipWS(pe); } + const string& GetPreCheck() const { return pre_check; } + + bool HasPreCheckAction() const { return ! pre_check_action.empty(); } + void SetPreCheckAction(string pe) { pre_check_action = SkipWS(pe); } + const string& GetPreCheckAction() const { return pre_check_action; } protected: // Returns a regular expression used to access the value of the @@ -671,12 +746,12 @@ protected: // Instantiates versions of the operation that have a constant // as the first, second, or third operand ... - void InstantiateC1(const vector& ots, size_t arity, bool do_vec = false); - void InstantiateC2(const vector& ots, size_t arity); - void InstantiateC3(const vector& ots); + void InstantiateC1(const OCVec& ocs, size_t arity); + void InstantiateC2(const OCVec& ocs, size_t arity); + void InstantiateC3(const OCVec& ocs); // ... or if all of the operands are non-constant. - void InstantiateV(const vector& ots); + void InstantiateV(const OCVec& ocs); // Generates code that instantiates either the vectorized version // of an operation, or the non-vector one, depending on whether @@ -689,30 +764,34 @@ protected: // Generates an if-else cascade element that matches one of the // specific Zeek types associated with the instruction. - void GenMethodTest(ZAM_ExprType et1, ZAM_ExprType et2, const string& params, + void GenMethodTest(ZAM_Type et1, ZAM_Type et2, const string& params, const string& suffix, bool do_else, ZAM_InstClass zc); - void InstantiateEval(const vector& ot, const string& suffix, + void InstantiateEval(const OCVec& oc, const string& suffix, ZAM_InstClass zc) override; private: // The Zeek types that can appear as operands for the expression. - std::unordered_set expr_types; + std::unordered_set expr_types; // The C++ evaluation template for a given operand type. - std::unordered_map eval_set; + std::unordered_map eval_set; // Some expressions take two operands of different types. This // holds their C++ evaluation template. - std::unordered_map> eval_mixed_set; + std::unordered_map> eval_mixed_set; // Whether this expression's operand is a field access (and thus // needs both the record as an operand and an additional constant // offset into the record to get to the field). bool includes_field_op = false; - // If non-zero, code to generate prior to evaluating the expression. - string pre_eval; + // If non-empty, a check to conduct before evaluating the expression ... + string pre_check; + + // ... and the action to take if the check is true, *instead* of + // evaluating the expression. + string pre_check_action; // If true, then the evaluations will take care of ensuring // proper result types when assigning to $$. @@ -725,7 +804,7 @@ class ZAM_UnaryExprOpTemplate : public ZAM_ExprOpTemplate public: ZAM_UnaryExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_ExprOpTemplate(_g, _base_name) { } - bool IncludesFieldOp() const override { return ExprTypes().count(ZAM_EXPR_TYPE_NONE) == 0; } + bool IncludesFieldOp() const override { return ExprTypes().count(ZAM_TYPE_NONE) == 0; } int Arity() const override { return 1; } @@ -733,7 +812,7 @@ protected: void Parse(const string& attr, const string& line, const Words& words) override; void Instantiate() override; - void BuildInstruction(const vector& ot, const string& params, + void BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) override; }; @@ -770,7 +849,7 @@ public: protected: void Instantiate() override; - void BuildInstruction(const vector& ot, const string& params, + void BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) override; }; @@ -797,43 +876,10 @@ protected: void Instantiate() override; - void BuildInstruction(const vector& ot, const string& params, + void BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) override; }; -// A version of ZAM_BinaryExprOpTemplate for binary operations generated -// by custom methods rather than directly from the AST. -class ZAM_InternalBinaryOpTemplate : public ZAM_BinaryExprOpTemplate - { -public: - ZAM_InternalBinaryOpTemplate(ZAMGen* _g, string _base_name) - : ZAM_BinaryExprOpTemplate(_g, _base_name) - { - } - - bool IsInternalOp() const override { return true; } - - // The accessors used to get to the underlying Zeek script value - // of the first and second operand. - void SetOp1Accessor(string accessor) { op1_accessor = accessor; } - void SetOp2Accessor(string accessor) { op2_accessor = accessor; } - void SetOpAccessor(string accessor) - { - SetOp1Accessor(accessor); - SetOp2Accessor(accessor); - } - -protected: - void Parse(const string& attr, const string& line, const Words& words) override; - - void InstantiateEval(const vector& ot, const string& suffix, - ZAM_InstClass zc) override; - -private: - string op1_accessor; - string op2_accessor; - }; - // A version of ZAM_OpTemplate for operations used internally (and not // corresponding to AST elements). class ZAM_InternalOpTemplate : public ZAM_OpTemplate @@ -847,6 +893,8 @@ protected: void Parse(const string& attr, const string& line, const Words& words) override; private: + void ParseCall(const string& line, const Words& words); + // True if the internal operation corresponds to an indirect call, // i.e., one through a variable rather than one directly specified. bool is_indirect_call = false; @@ -944,6 +992,8 @@ public: void IndentUp() { ++indent_level; } void IndentDown() { --indent_level; } + void StartString() { string_lit = true; } + void EndString() { string_lit = false; } void SetNoNL(bool _no_NL) { no_NL = _no_NL; } [[noreturn]] void Gripe(const char* msg, const string& input) const { ti->Gripe(msg, input); } @@ -987,6 +1037,9 @@ private: // consistently. int indent_level = 0; + // If true, we're generating a string literal. + bool string_lit = false; + // If true, refrain from appending a newline to any emitted lines. bool no_NL = false; }; From a20e268f1351c752c61b1bacd8b71ce0d7c64606 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Wed, 4 Dec 2024 15:04:20 -0700 Subject: [PATCH 268/343] gen-zam: more robust dispatch that allows for eval/eval-mixed overlap --- tools/gen-zam/src/Gen-ZAM.cc | 62 ++++++++++++++++++++++++++++++------ tools/gen-zam/src/Gen-ZAM.h | 2 ++ 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 8ba48830c2..cc9047f7e5 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1372,9 +1372,6 @@ void ZAM_ExprOpTemplate::Parse(const string& attr, const string& line, const Wor auto et1 = type_names[type_c1]; auto et2 = type_names[type_c2]; - if ( eval_set.count(et1) > 0 ) - g->Gripe("eval-mixed uses type also included in op-type", line); - auto eval = g->SkipWords(line, 3); eval += GatherEval(); AddEvalSet(et1, et2, eval); @@ -1551,8 +1548,8 @@ void ZAM_ExprOpTemplate::DoVectorCase(const string& m, const string& args) void ZAM_ExprOpTemplate::BuildInstructionCore(const string& params, const string& suffix, ZAM_InstClass zc) { - Emit("auto tag = t->Tag();"); - Emit("auto i_t = t->InternalType();"); + Emit("auto tag1 = t->Tag();"); + Emit("auto i_t1 = t->InternalType();"); int ncases = 0; @@ -1610,14 +1607,24 @@ void ZAM_ExprOpTemplate::GenMethodTest(ZAM_Type et1, ZAM_Type et2, const string& {ZAM_TYPE_VECTOR, {"tag", "TYPE_VECTOR"}}, }; - if ( if_tests.count(et1) == 0 ) + if ( if_tests.count(et1) == 0 || if_tests.count(et2) == 0 ) Gripe("bad op-type"); - auto if_test = if_tests[et1]; - auto if_var = if_test.first; - auto if_val = if_test.second; + auto if_test1 = if_tests[et1]; + auto if_var1 = if_test1.first + "1"; + auto if_val1 = if_test1.second; - string test = "if ( " + if_var + " == " + if_val + " )"; + string test = if_var1 + " == " + if_val1; + + if ( Arity() > 1 ) + { + auto if_test2 = if_tests[et2]; + auto if_var2 = if_test2.first + "2"; + auto if_val2 = if_test2.second; + test = test + " && " + if_var2 + " == " + if_val2; + } + + test = "if ( " + test + " )"; if ( do_else ) test = "else " + test; @@ -2121,12 +2128,46 @@ void ZAM_BinaryExprOpTemplate::BuildInstruction(const OCVec& oc, string type_src = constant_op ? "c" : "n2"; auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; Emit("auto t = " + type_src + "->GetType()" + type_suffix); + + GenerateSecondTypeVars(oc, zc); BuildInstructionCore(params, suffix, zc); if ( zc == ZIC_VEC ) Emit("z.SetType(n1->GetType());"); } +void ZAM_BinaryExprOpTemplate::GenerateSecondTypeVars(const OCVec& oc, + ZAM_InstClass zc) + { + auto constant_op = oc[1] == ZAM_OC_CONSTANT; + auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; + + string type_src2; + + if ( zc == ZIC_COND ) + { + if ( oc[0] == ZAM_OC_CONSTANT ) + type_src2 = "n"; + else if ( oc[1] == ZAM_OC_CONSTANT ) + type_src2 = "c"; + else + type_src2 = "n2"; + } + else + { + if ( oc[1] == ZAM_OC_CONSTANT ) + type_src2 = "n2"; + else if ( oc[2] == ZAM_OC_CONSTANT ) + type_src2 = "c"; + else + type_src2 = "n3"; + } + + Emit("auto t2 = " + type_src2 + "->GetType()" + type_suffix); + Emit("auto tag2 = t2->Tag();"); + Emit("auto i_t2 = t2->InternalType();"); + } + void ZAM_RelationalExprOpTemplate::Instantiate() { ZAM_BinaryExprOpTemplate::Instantiate(); @@ -2170,6 +2211,7 @@ void ZAM_RelationalExprOpTemplate::BuildInstruction(const OCVec& oc, auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; Emit("auto t = " + op1 + "->GetType()" + type_suffix); + GenerateSecondTypeVars(oc, zc); BuildInstructionCore(params, suffix, zc); if ( zc == ZIC_VEC ) diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index b05db91d90..daa6cedea6 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -851,6 +851,8 @@ protected: void BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) override; + + void GenerateSecondTypeVars(const OCVec& oc, ZAM_InstClass zc); }; // A version of ZAM_BinaryExprOpTemplate for relationals. From 12bb2a04ebddcbb37f121db3ef88deaef3dfa2df Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 13 Dec 2024 08:10:09 -0700 Subject: [PATCH 269/343] gen-zam: Require CMake 3.15, in line with other Zeek projects --- tools/gen-zam/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gen-zam/CMakeLists.txt b/tools/gen-zam/CMakeLists.txt index 2cc724fc91..d801fda8f3 100644 --- a/tools/gen-zam/CMakeLists.txt +++ b/tools/gen-zam/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) project(Gen-ZAM C CXX) include(cmake/CommonCMakeConfig.cmake) From 53591cf2055c32811dff573b0ae2b584420e2acc Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Thu, 2 Jan 2025 15:30:40 -0800 Subject: [PATCH 270/343] gen-zam: generate descriptions of macros, akin to those already generated for operations --- tools/gen-zam/src/Gen-ZAM.cc | 22 ++++++++++++++++++++-- tools/gen-zam/src/Gen-ZAM.h | 5 ++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index cc9047f7e5..ddb1a675c3 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -980,7 +980,7 @@ void ZAM_OpTemplate::GenDesc(const string& op_code, const string& oc_str, const void ZAM_OpTemplate::StartDesc(const string& op_code, const string& oc_str) { - EmitTo(Desc); + EmitTo(OpDesc); Emit("{ " + op_code + ","); BeginBlock(); Emit("\"" + oc_str + "\","); @@ -2476,10 +2476,27 @@ void ZAMGen::GenMacros() { auto ms = m[i]; if ( i == 0 ) + { + auto name = regex_replace(ms, regex("[( ].*\n"), ""); + Emit(MacroDesc, "{ \"" + name + "\","); + ms = "#define " + ms; + } + + auto desc = ms; + desc.erase(desc.find('\n')); + desc = regex_replace(desc, regex("\\\\"), "\\\\"); + desc = regex_replace(desc, regex("\""), "\\\""); if ( i < m.size() - 1 ) + { ms = regex_replace(ms, regex("\n"), " \\\n"); + desc.append(" \\\\\\n"); + } + + Emit(MacroDesc, " \"" + desc + "\""); + if ( i == m.size() - 1 ) + Emit(MacroDesc, "},"); Emit(EvalMacros, ms); } @@ -2580,14 +2597,15 @@ void ZAMGen::InitEmitTargets() {C2FieldDef, "ZAM-GenFieldsDefsC2.h"}, {C3Def, "ZAM-GenExprsDefsC3.h"}, {Cond, "ZAM-Conds.h"}, - {Desc, "ZAM-Desc.h"}, {DirectDef, "ZAM-DirectDefs.h"}, {Eval, "ZAM-EvalDefs.h"}, {EvalMacros, "ZAM-EvalMacros.h"}, + {MacroDesc, "ZAM-MacroDesc.h"}, {MethodDecl, "ZAM-MethodDecls.h"}, {MethodDef, "ZAM-MethodDefs.h"}, {Op1Flavor, "ZAM-Op1FlavorsDefs.h"}, {OpDef, "ZAM-OpsDefs.h"}, + {OpDesc, "ZAM-OpDesc.h"}, {OpName, "ZAM-OpsNamesDefs.h"}, {OpSideEffects, "ZAM-OpSideEffects.h"}, {VDef, "ZAM-GenExprsDefsV.h"}, diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index daa6cedea6..ec09fc437c 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -144,7 +144,10 @@ enum EmitTarget Cond, // Descriptions of final ZAM operations, used for validation. - Desc, + OpDesc, + + // The same, for macros. + MacroDesc, // Switch cases that provide the C++ code for executing specific // individual ZAM instructions. From 0acd4bf04e5eb77f9fe4ad54de73d83903dcb7dc Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 9 Jun 2025 08:19:50 -0700 Subject: [PATCH 271/343] gen-zam: Fix clang-tidy bugprone-branch-clone warnings in headers --- tools/gen-zam/src/Gen-ZAM.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index ddb1a675c3..922ced8785 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -2630,6 +2630,10 @@ void ZAMGen::InitEmitTargets() gen_files[gfn.first] = f; } + // Avoid bugprone-branch-clone warnings from clang-tidy in generated code. + Emit(OpName, "// NOLINTBEGIN(bugprone-branch-clone)"); + Emit(Eval, "// NOLINTBEGIN(bugprone-branch-clone)"); + InitSwitch(C1Def, "C1 assignment"); InitSwitch(C2Def, "C2 assignment"); InitSwitch(C3Def, "C3 assignment"); @@ -2652,6 +2656,9 @@ void ZAMGen::CloseEmitTargets() { FinishSwitches(); + Emit(OpName, "// NOLINTEND(bugprone-branch-clone)"); + Emit(Eval, "// NOLINTEND(bugprone-branch-clone)"); + for ( auto& gf : gen_files ) fclose(gf.second); } From 75bba1a8f524472f69ab3251cc387701bda928c9 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 9 Jun 2025 11:10:38 -0700 Subject: [PATCH 272/343] gen-zam: Fix clang-tidy bugprone-macro-parentheses/cppcoreguidelines-macro-usage warnings in headers --- tools/gen-zam/src/Gen-ZAM.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 922ced8785..6675f430c9 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -2633,6 +2633,8 @@ void ZAMGen::InitEmitTargets() // Avoid bugprone-branch-clone warnings from clang-tidy in generated code. Emit(OpName, "// NOLINTBEGIN(bugprone-branch-clone)"); Emit(Eval, "// NOLINTBEGIN(bugprone-branch-clone)"); + Emit(EvalMacros, "// NOLINTBEGIN(bugprone-macro-parentheses)"); + Emit(EvalMacros, "// NOLINTBEGIN(cppcoreguidelines-macro-usage)"); InitSwitch(C1Def, "C1 assignment"); InitSwitch(C2Def, "C2 assignment"); @@ -2658,6 +2660,8 @@ void ZAMGen::CloseEmitTargets() Emit(OpName, "// NOLINTEND(bugprone-branch-clone)"); Emit(Eval, "// NOLINTEND(bugprone-branch-clone)"); + Emit(EvalMacros, "// NOLINTEND(cppcoreguidelines-macro-usage)"); + Emit(EvalMacros, "// NOLINTEND(bugprone-macro-parentheses)"); for ( auto& gf : gen_files ) fclose(gf.second); From 97492b4d70504c3775e463853cf8c240e948a80d Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 9 Jun 2025 17:16:14 -0700 Subject: [PATCH 273/343] gen-zam: Reserve space for args vector before pushing back items --- tools/gen-zam/src/Gen-ZAM.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 6675f430c9..5c1842ae5e 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -2284,6 +2284,7 @@ void ZAM_InternalOpTemplate::ParseCall(const string& line, const Words& words) } eval += "auto n = aux->n;\n"; + eval += "args.reserve(n);\n"; eval += "for ( auto i = 0; i < n; ++i )\n"; eval += "\targs.push_back(aux->ToVal(frame, i));\n"; } From 027c075fb0e0609187d577c8d8a0138531845ec0 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 9 Jun 2025 18:01:12 -0700 Subject: [PATCH 274/343] gen-zam: Use const references instead of copying type values --- tools/gen-zam/src/Gen-ZAM.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 5c1842ae5e..f17363e49f 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1996,7 +1996,7 @@ void ZAM_UnaryExprOpTemplate::BuildInstruction(const OCVec& oc, { type_src = constant_op ? "n" : "n1"; Emit("auto " + type_src + " = flhs->GetOp1()->AsNameExpr();"); - Emit("auto t = flhs->GetType();"); + Emit("const auto& t = flhs->GetType();"); } else @@ -2005,7 +2005,7 @@ void ZAM_UnaryExprOpTemplate::BuildInstruction(const OCVec& oc, type_src = constant_op ? "n" : "n1"; auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; - Emit("auto t = " + type_src + "->GetType()" + type_suffix); + Emit("const auto& t = " + type_src + "->GetType()" + type_suffix); } BuildInstructionCore(params, suffix, zc); @@ -2127,7 +2127,7 @@ void ZAM_BinaryExprOpTemplate::BuildInstruction(const OCVec& oc, auto constant_op = oc[1] == ZAM_OC_CONSTANT; string type_src = constant_op ? "c" : "n2"; auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; - Emit("auto t = " + type_src + "->GetType()" + type_suffix); + Emit("const auto& t = " + type_src + "->GetType()" + type_suffix); GenerateSecondTypeVars(oc, zc); BuildInstructionCore(params, suffix, zc); @@ -2163,7 +2163,7 @@ void ZAM_BinaryExprOpTemplate::GenerateSecondTypeVars(const OCVec& oc, type_src2 = "n3"; } - Emit("auto t2 = " + type_src2 + "->GetType()" + type_suffix); + Emit("const auto& t2 = " + type_src2 + "->GetType()" + type_suffix); Emit("auto tag2 = t2->Tag();"); Emit("auto i_t2 = t2->InternalType();"); } @@ -2210,7 +2210,7 @@ void ZAM_RelationalExprOpTemplate::BuildInstruction(const OCVec& oc, } auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; - Emit("auto t = " + op1 + "->GetType()" + type_suffix); + Emit("const auto& t = " + op1 + "->GetType()" + type_suffix); GenerateSecondTypeVars(oc, zc); BuildInstructionCore(params, suffix, zc); From d5cc0d513515917a8a05d77c17db5fb547450e3f Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 24 Jun 2025 16:57:28 -0700 Subject: [PATCH 275/343] gen-zam: Add cmake-format pre-commit hook --- tools/gen-zam/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/gen-zam/CMakeLists.txt b/tools/gen-zam/CMakeLists.txt index d801fda8f3..33e6902038 100644 --- a/tools/gen-zam/CMakeLists.txt +++ b/tools/gen-zam/CMakeLists.txt @@ -28,7 +28,6 @@ message( "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" "\nCPP: ${CMAKE_CXX_COMPILER}" "\n" - "\n================================================================\n" -) + "\n================================================================\n") include(UserChangedWarning) From f6f84184ed7e80773975a036249ee6c117854ab5 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 24 Jun 2025 16:58:48 -0700 Subject: [PATCH 276/343] gen-zam: Add clang-format pre-commit hook --- tools/gen-zam/src/Gen-ZAM.cc | 5081 ++++++++++++++++------------------ tools/gen-zam/src/Gen-ZAM.h | 1579 +++++------ 2 files changed, 3146 insertions(+), 3514 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index f17363e49f..bbbb67b3eb 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -2,2780 +2,2465 @@ #include "Gen-ZAM.h" -#include #include +#include #include using namespace std; // Helper functions to convert dashes to underscores or vice versa. -static char dash_to_under(char c) - { - return c == '-' ? '_' : c; - } +static char dash_to_under(char c) { return c == '-' ? '_' : c; } -static char under_to_dash(char c) - { - return c == '_' ? '-' : c; - } +static char under_to_dash(char c) { return c == '_' ? '-' : c; } // Structure for binding together Zeek script types, internal names Gen-ZAM // uses to track them, mnemonics for referring to them in instruction names, // the corresponding Val accessor, and whether the type requires memory // management. -struct TypeInfo - { - string tag; - ZAM_Type zt; - string suffix; - string accessor; // doesn't include "As" prefix or "()" suffix - bool is_managed; - }; +struct TypeInfo { + string tag; + ZAM_Type zt; + string suffix; + string accessor; // doesn't include "As" prefix or "()" suffix + bool is_managed; +}; static vector ZAM_type_info = { - {"TYPE_ADDR", ZAM_TYPE_ADDR, "A", "Addr", true}, - {"TYPE_ANY", ZAM_TYPE_ANY, "a", "Any", true}, - {"TYPE_COUNT", ZAM_TYPE_UINT, "U", "Count", false}, - {"TYPE_DOUBLE", ZAM_TYPE_DOUBLE, "D", "Double", false}, - {"TYPE_FILE", ZAM_TYPE_FILE, "f", "File", true}, - {"TYPE_FUNC", ZAM_TYPE_FUNC, "F", "Func", true}, - {"TYPE_INT", ZAM_TYPE_INT, "I", "Int", false}, - {"TYPE_LIST", ZAM_TYPE_LIST, "L", "List", true}, - {"TYPE_OPAQUE", ZAM_TYPE_OPAQUE, "O", "Opaque", true}, - {"TYPE_PATTERN", ZAM_TYPE_PATTERN, "P", "Pattern", true}, - {"TYPE_RECORD", ZAM_TYPE_RECORD, "R", "Record", true}, - {"TYPE_STRING", ZAM_TYPE_STRING, "S", "String", true}, - {"TYPE_SUBNET", ZAM_TYPE_SUBNET, "N", "SubNet", true}, - {"TYPE_TABLE", ZAM_TYPE_TABLE, "T", "Table", true}, - {"TYPE_TYPE", ZAM_TYPE_TYPE, "t", "Type", true}, - {"TYPE_VECTOR", ZAM_TYPE_VECTOR, "V", "Vector", true}, + {"TYPE_ADDR", ZAM_TYPE_ADDR, "A", "Addr", true}, {"TYPE_ANY", ZAM_TYPE_ANY, "a", "Any", true}, + {"TYPE_COUNT", ZAM_TYPE_UINT, "U", "Count", false}, {"TYPE_DOUBLE", ZAM_TYPE_DOUBLE, "D", "Double", false}, + {"TYPE_FILE", ZAM_TYPE_FILE, "f", "File", true}, {"TYPE_FUNC", ZAM_TYPE_FUNC, "F", "Func", true}, + {"TYPE_INT", ZAM_TYPE_INT, "I", "Int", false}, {"TYPE_LIST", ZAM_TYPE_LIST, "L", "List", true}, + {"TYPE_OPAQUE", ZAM_TYPE_OPAQUE, "O", "Opaque", true}, {"TYPE_PATTERN", ZAM_TYPE_PATTERN, "P", "Pattern", true}, + {"TYPE_RECORD", ZAM_TYPE_RECORD, "R", "Record", true}, {"TYPE_STRING", ZAM_TYPE_STRING, "S", "String", true}, + {"TYPE_SUBNET", ZAM_TYPE_SUBNET, "N", "SubNet", true}, {"TYPE_TABLE", ZAM_TYPE_TABLE, "T", "Table", true}, + {"TYPE_TYPE", ZAM_TYPE_TYPE, "t", "Type", true}, {"TYPE_VECTOR", ZAM_TYPE_VECTOR, "V", "Vector", true}, }; // Maps op-type mnemonics to the corresponding internal value used by Gen-ZAM. static unordered_map type_names = { - {'*', ZAM_TYPE_DEFAULT}, {'A', ZAM_TYPE_ADDR}, {'a', ZAM_TYPE_ANY}, - {'D', ZAM_TYPE_DOUBLE}, {'f', ZAM_TYPE_FILE}, {'F', ZAM_TYPE_FUNC}, - {'I', ZAM_TYPE_INT}, {'L', ZAM_TYPE_LIST}, {'X', ZAM_TYPE_NONE}, - {'O', ZAM_TYPE_OPAQUE}, {'P', ZAM_TYPE_PATTERN}, {'R', ZAM_TYPE_RECORD}, - {'S', ZAM_TYPE_STRING}, {'N', ZAM_TYPE_SUBNET}, {'T', ZAM_TYPE_TABLE}, - {'t', ZAM_TYPE_TYPE}, {'U', ZAM_TYPE_UINT}, {'V', ZAM_TYPE_VECTOR}, + {'*', ZAM_TYPE_DEFAULT}, {'A', ZAM_TYPE_ADDR}, {'a', ZAM_TYPE_ANY}, {'D', ZAM_TYPE_DOUBLE}, + {'f', ZAM_TYPE_FILE}, {'F', ZAM_TYPE_FUNC}, {'I', ZAM_TYPE_INT}, {'L', ZAM_TYPE_LIST}, + {'X', ZAM_TYPE_NONE}, {'O', ZAM_TYPE_OPAQUE}, {'P', ZAM_TYPE_PATTERN}, {'R', ZAM_TYPE_RECORD}, + {'S', ZAM_TYPE_STRING}, {'N', ZAM_TYPE_SUBNET}, {'T', ZAM_TYPE_TABLE}, {'t', ZAM_TYPE_TYPE}, + {'U', ZAM_TYPE_UINT}, {'V', ZAM_TYPE_VECTOR}, }; // Inverse of the above. static unordered_map expr_name_types; // Given a ZAM_Type, returns the corresponding TypeInfo. -const TypeInfo& find_type_info(ZAM_Type zt) - { - assert(zt != ZAM_TYPE_NONE); +const TypeInfo& find_type_info(ZAM_Type zt) { + assert(zt != ZAM_TYPE_NONE); - auto pred = [zt](const TypeInfo& ti) -> bool - { - return ti.zt == zt; - }; - auto ti = std::find_if(ZAM_type_info.begin(), ZAM_type_info.end(), pred); + auto pred = [zt](const TypeInfo& ti) -> bool { return ti.zt == zt; }; + auto ti = std::find_if(ZAM_type_info.begin(), ZAM_type_info.end(), pred); - assert(ti != ZAM_type_info.end()); - return *ti; - } + assert(ti != ZAM_type_info.end()); + return *ti; +} // Given a ZAM_Type, return its ZVal accessor. Takes into account // some naming inconsistencies between ZVal's and Val's. -string find_type_accessor(ZAM_Type zt, bool is_lhs) - { - if ( zt == ZAM_TYPE_NONE ) - return ""; +string find_type_accessor(ZAM_Type zt, bool is_lhs) { + if ( zt == ZAM_TYPE_NONE ) + return ""; - string acc = string("As") + find_type_info(zt).accessor; - if ( is_lhs ) - acc += "Ref"; + string acc = string("As") + find_type_info(zt).accessor; + if ( is_lhs ) + acc += "Ref"; - return acc + "()"; - } + return acc + "()"; +} // Maps ZAM operand types to pairs of (1) the C++ name used to declare // the operand in a method declaration, and (2) the variable name to // use for the operand. unordered_map> ArgsManager::oc_to_args = { - {ZAM_OC_AUX, {"OpaqueVals*", "v"}}, - {ZAM_OC_CONSTANT, {"const ConstExpr*", "c"}}, - {ZAM_OC_EVENT_HANDLER, {"EventHandler*", "h"}}, - {ZAM_OC_INT, {"int", "i"}}, - {ZAM_OC_BRANCH, {"int", "i"}}, - {ZAM_OC_GLOBAL, {"int", "i"}}, - {ZAM_OC_STEP_ITER, {"int", "i"}}, - {ZAM_OC_TBL_ITER, {"int", "i"}}, - {ZAM_OC_LIST, {"const ListExpr*", "l"}}, - {ZAM_OC_RECORD_FIELD, {"const NameExpr*", "n"}}, - {ZAM_OC_VAR, {"const NameExpr*", "n"}}, + {ZAM_OC_AUX, {"OpaqueVals*", "v"}}, + {ZAM_OC_CONSTANT, {"const ConstExpr*", "c"}}, + {ZAM_OC_EVENT_HANDLER, {"EventHandler*", "h"}}, + {ZAM_OC_INT, {"int", "i"}}, + {ZAM_OC_BRANCH, {"int", "i"}}, + {ZAM_OC_GLOBAL, {"int", "i"}}, + {ZAM_OC_STEP_ITER, {"int", "i"}}, + {ZAM_OC_TBL_ITER, {"int", "i"}}, + {ZAM_OC_LIST, {"const ListExpr*", "l"}}, + {ZAM_OC_RECORD_FIELD, {"const NameExpr*", "n"}}, + {ZAM_OC_VAR, {"const NameExpr*", "n"}}, - // The following gets special treatment. - {ZAM_OC_ASSIGN_FIELD, {"const NameExpr*", "n"}}, + // The following gets special treatment. + {ZAM_OC_ASSIGN_FIELD, {"const NameExpr*", "n"}}, }; // The different operand classes that are represented as "raw" integers // (meaning the slot value is used directly, rather than indexing the frame). -static const set raw_int_oc( - { ZAM_OC_BRANCH, ZAM_OC_GLOBAL, ZAM_OC_INT, ZAM_OC_STEP_ITER, ZAM_OC_TBL_ITER } -); - -ArgsManager::ArgsManager(const OCVec& oc_orig, ZAM_InstClass zc) - { - auto oc = oc_orig; - if ( zc == ZIC_COND ) - // Remove the final entry corresponding to the branch, as - // we'll automatically generate it subsequently. - oc.pop_back(); - - int n = 0; - bool add_field = false; - - for ( const auto& ot_i : oc ) - { - if ( ot_i == ZAM_OC_NONE ) - { // it had better be the only operand type - assert(oc.size() == 1); - break; - } - - ++n; - - // Start off the argument info using the usual case - // of (1) same method parameter name as GenInst argument, - // and (2) not requiring a record field. - auto& arg_i = oc_to_args[ot_i]; - Arg arg = {arg_i.second, arg_i.first, arg_i.second}; - - if ( ot_i == ZAM_OC_ASSIGN_FIELD ) - { - if ( n == 1 ) - { // special-case the parameter - arg.decl_name = "flhs"; - arg.decl_type = "const FieldLHSAssignExpr*"; - } - } - - args.emplace_back(std::move(arg)); - } - - Differentiate(); - } - -void ArgsManager::Differentiate() - { - // First, figure out which parameter names are used how often. - map name_count; // how often the name apepars - map usage_count; // how often the name's been used so far - for ( auto& arg : args ) - { - auto& name = arg.param_name; - if ( name_count.count(name) == 0 ) - { - name_count[name] = 1; - usage_count[name] = 0; - } - else - ++name_count[name]; - } - - // Now for each name - whether appearing as an argument or in - // a declaration - if it's used more than once, then differentiate - // it. Note, some names only appear multiple times as arguments - // when invoking methods, but not in the declarations of the methods - // themselves. - for ( auto& arg : args ) - { - auto& decl = arg.decl_name; - auto& name = arg.param_name; - bool decl_and_arg_same = decl == name; - - if ( name_count[name] == 1 ) - continue; // it's unique - - auto n = to_string(++usage_count[name]); - name += n; - if ( decl_and_arg_same ) - decl += n; - } - - // Finally, build the full versions of the declaration and parameters. - - for ( auto& arg : args ) - { - if ( ! full_decl.empty() ) - full_decl += ", "; - - full_decl += arg.decl_type + " " + arg.decl_name; - - if ( ! full_params.empty() ) - full_params += ", "; - - full_params += arg.param_name; - params.push_back(arg.param_name); - } - } - -ZAM_OpTemplate::ZAM_OpTemplate(ZAMGen* _g, string _base_name) : g(_g), base_name(std::move(_base_name)) - { - // Make the base name viable in a C++ name. - transform(base_name.begin(), base_name.end(), base_name.begin(), dash_to_under); - - cname = base_name; - transform(cname.begin(), cname.end(), cname.begin(), ::toupper); - } - -void ZAM_OpTemplate::Build() - { - op_loc = g->CurrLoc(); - - string line; - while ( g->ScanLine(line) ) - { - if ( line.size() <= 1 ) - break; - - auto words = g->SplitIntoWords(line); - if ( words.empty() ) - break; - - Parse(words[0], line, words); - } - - if ( ! op_classes.empty() && ! op_classes_vec.empty() ) - Gripe("\"class\" and \"classes\" are mutually exclusive"); - - if ( ! op_classes.empty() || ! op_classes_vec.empty() ) - { - auto nclasses = op_classes.empty() ? - op_classes_vec[0].size() : op_classes.size(); - - for ( auto& oc : op_classes_vec ) - if ( oc.size() != nclasses ) - Gripe("size mismatch in \"classes\" specifications"); - - if ( ! op_types.empty() && op_types.size() != nclasses ) - Gripe("number of \"op-types\" elements must match \"class\"/\"classes\""); - } - - else if ( ! op_types.empty() ) - Gripe("\"op-types\" can only be used with \"class\"/\"classes\""); - } - -void ZAM_OpTemplate::Instantiate() - { - if ( IsPredicate() ) - InstantiatePredicate(); - - else if ( op_classes_vec.empty() ) - InstantiateOp(OperandClasses(), IncludesVectorOp()); - - else - for ( auto& ocs : op_classes_vec ) - InstantiateOp(ocs, IncludesVectorOp()); - } - -void ZAM_OpTemplate::InstantiatePredicate() - { - if ( ! op_classes_vec.empty() ) - Gripe("\"predicate\" cannot include \"classes\""); - - if ( op_classes.empty() ) - Gripe("\"predicate\" requires a \"class\""); - - if ( IncludesVectorOp() ) - Gripe("\"predicate\" cannot include \"vector\""); - - // Build 3 forms: an assignment to an int-value'd $$, a conditional - // if the evaluation is true, and one if it is not. - - auto orig_eval = eval; - // Remove trailing '\n' from eval. - orig_eval.pop_back(); - - auto orig_op_classes = op_classes; - bool no_classes = orig_op_classes[0] == ZAM_OC_NONE; - - // Assignment form. - op_classes.clear(); - op_classes.push_back(ZAM_OC_VAR); - if ( ! no_classes ) - op_classes.insert(op_classes.end(), orig_op_classes.begin(), orig_op_classes.end()); - - string target_accessor; - - if ( ! op_types.empty() ) - op_types.insert(op_types.begin(), ZAM_TYPE_INT); - else - target_accessor = ".AsIntRef()"; - - eval = "$$" + target_accessor + " = " + orig_eval + ";"; - - InstantiateOp(op_classes, false); - - // Conditional form - branch if not true. - - if ( ! op_types.empty() ) - { - // Remove 'V' at the beginning from the assignment form, - // and add a 'i' at the end for the branch. - op_types.erase(op_types.begin()); - op_types.push_back(ZAM_TYPE_INT); - } - - cname += "_COND"; - op1_flavor = "OP1_READ"; - if ( no_classes ) - op_classes.clear(); - else - op_classes = orig_op_classes; - - op_classes.push_back(ZAM_OC_BRANCH); - - auto branch_pos = to_string(op_classes.size()); - auto suffix = " )\n\t\t$" + branch_pos; - eval = "if ( ! (" + orig_eval + ")" + suffix; - InstantiateOp(op_classes, false); - - // Now the form that branches if true. - cname = "NOT_" + cname; - eval = "if ( (" + orig_eval + ")" + suffix; - InstantiateOp(op_classes, false); - } - -void ZAM_OpTemplate::UnaryInstantiate() - { - // First operand is always the frame slot to which this operation - // assigns the result of the applying unary operator. - OCVec ocs = {ZAM_OC_VAR}; - ocs.resize(2); - - // Now build versions for a constant operand (maybe not actually - // needed due to constant folding, but sometimes that gets deferred - // to run-time) ... - if ( ! NoConst() ) - { - ocs[1] = ZAM_OC_CONSTANT; - InstantiateOp(ocs, IncludesVectorOp()); - } - - // ... and for a variable (frame-slot) operand. - ocs[1] = ZAM_OC_VAR; - InstantiateOp(ocs, IncludesVectorOp()); - } - -void ZAM_OpTemplate::Parse(const string& attr, const string& line, const Words& words) - { - int num_args = -1; // -1 = don't enforce - int nwords = static_cast(words.size()); - - if ( attr == "class" ) - { - if ( nwords <= 1 ) - g->Gripe("missing argument", line); - - num_args = 1; - op_classes = ParseClass(words[1]); - } - - else if ( attr == "classes" ) - { - if ( nwords <= 1 ) - g->Gripe("missing argument", line); - - num_args = -1; - - for ( int i = 1; i < nwords; ++i ) - op_classes_vec.push_back(ParseClass(words[i])); - } - - else if ( attr == "op-types" ) - { - if ( words.size() == 1 ) - g->Gripe("op-types needs arguments", line); - - for ( auto i = 1U; i < words.size(); ++i ) - { - auto& w_i = words[i]; - if ( w_i.size() != 1 ) - g->Gripe("bad op-types argument", w_i); - - auto et_c = w_i.c_str()[0]; - if ( type_names.count(et_c) == 0 ) - g->Gripe("bad op-types argument", w_i); - - op_types.push_back(type_names[et_c]); - } - } - - else if ( attr == "op1-read" ) - { - num_args = 0; - SetOp1Flavor("OP1_READ"); - } - - else if ( attr == "op1-read-write" ) - { - num_args = 0; - SetOp1Flavor("OP1_READ_WRITE"); - } - - else if ( attr == "op1-internal" ) - { - num_args = 0; - SetOp1Flavor("OP1_INTERNAL"); - } - - else if ( attr == "set-type" ) - { - num_args = 1; - if ( nwords > 1 ) - SetTypeParam(ExtractTypeParam(words[1])); - } - - else if ( attr == "set-type2" ) - { - num_args = 1; - if ( nwords > 1 ) - SetType2Param(ExtractTypeParam(words[1])); - } - - else if ( attr == "custom-method" ) - SetCustomMethod(g->SkipWords(line, 1)); - - else if ( attr == "method-post" ) - SetPostMethod(g->SkipWords(line, 1)); - - else if ( attr == "side-effects" ) - { - if ( nwords == 3 ) - SetAssignmentLess(words[1], words[2]); - else - // otherwise shouldn't be any arguments - num_args = 0; - - SetHasSideEffects(); - } - - else if ( attr == "no-eval" ) - { - num_args = 0; - SetNoEval(); - } - - else if ( attr == "vector" ) - { - num_args = 0; - SetIncludesVectorOp(); - } - - else if ( attr == "assign-val" ) - { - num_args = 1; - if ( words.size() > 1 ) - SetAssignVal(words[1]); - } - - else if ( attr == "eval" ) - { - AddEval(g->SkipWords(line, 1)); - - auto addl = GatherEval(); - if ( ! addl.empty() ) - AddEval(addl); - } - - else if ( attr == "macro" ) - g->ReadMacro(line); - - else - g->Gripe("unknown template attribute", attr); - - if ( num_args >= 0 && num_args != nwords - 1 ) - g->Gripe("extraneous or missing arguments", line); - } - -OCVec ZAM_OpTemplate::ParseClass(const string& spec) const - { - OCVec ocs; - - const char* types = spec.c_str(); - while ( *types ) - { - ZAM_OperandClass oc = ZAM_OC_NONE; - - switch ( *types ) - { - case 'C': - oc = ZAM_OC_CONSTANT; - break; - case 'F': - oc = ZAM_OC_ASSIGN_FIELD; - break; - case 'H': - oc = ZAM_OC_EVENT_HANDLER; - break; - case 'L': - oc = ZAM_OC_LIST; - break; - case 'O': - oc = ZAM_OC_AUX; - break; - case 'R': - oc = ZAM_OC_RECORD_FIELD; - break; - case 'V': - oc = ZAM_OC_VAR; - break; - case 'i': - oc = ZAM_OC_INT; - break; - case 'b': - oc = ZAM_OC_BRANCH; - break; - case 'f': // 'f' = "for" loop - oc = ZAM_OC_TBL_ITER; - break; - case 'g': - oc = ZAM_OC_GLOBAL; - break; - case 's': - oc = ZAM_OC_STEP_ITER; - break; - - case 'X': - oc = ZAM_OC_NONE; - break; - - default: - g->Gripe("bad operand type", spec); - break; - } - - ocs.push_back(oc); - - ++types; - } - - return ocs; - } - -string ZAM_OpTemplate::GatherEval() - { - string res; - string l; - while ( g->ScanLine(l) ) - { - if ( l.size() <= 1 || ! isspace(l.c_str()[0]) ) - { - g->PutBack(l); - return res; - } - - res += l; - } - - return res; - } - -int ZAM_OpTemplate::ExtractTypeParam(const string& arg) - { - if ( arg == "$$" ) - return 0; - - if ( arg[0] != '$' ) - g->Gripe("bad set-type parameter, should be $n", arg); - - int param = atoi(&arg[1]); - - if ( param <= 0 || param > 2 ) - g->Gripe("bad set-type parameter, should be $1 or $2", arg); - - return param; - } +static const set raw_int_oc({ZAM_OC_BRANCH, ZAM_OC_GLOBAL, ZAM_OC_INT, ZAM_OC_STEP_ITER, + ZAM_OC_TBL_ITER}); + +ArgsManager::ArgsManager(const OCVec& oc_orig, ZAM_InstClass zc) { + auto oc = oc_orig; + if ( zc == ZIC_COND ) + // Remove the final entry corresponding to the branch, as + // we'll automatically generate it subsequently. + oc.pop_back(); + + int n = 0; + bool add_field = false; + + for ( const auto& ot_i : oc ) { + if ( ot_i == ZAM_OC_NONE ) { // it had better be the only operand type + assert(oc.size() == 1); + break; + } + + ++n; + + // Start off the argument info using the usual case + // of (1) same method parameter name as GenInst argument, + // and (2) not requiring a record field. + auto& arg_i = oc_to_args[ot_i]; + Arg arg = {arg_i.second, arg_i.first, arg_i.second}; + + if ( ot_i == ZAM_OC_ASSIGN_FIELD ) { + if ( n == 1 ) { // special-case the parameter + arg.decl_name = "flhs"; + arg.decl_type = "const FieldLHSAssignExpr*"; + } + } + + args.emplace_back(std::move(arg)); + } + + Differentiate(); +} + +void ArgsManager::Differentiate() { + // First, figure out which parameter names are used how often. + map name_count; // how often the name apepars + map usage_count; // how often the name's been used so far + for ( auto& arg : args ) { + auto& name = arg.param_name; + if ( name_count.count(name) == 0 ) { + name_count[name] = 1; + usage_count[name] = 0; + } + else + ++name_count[name]; + } + + // Now for each name - whether appearing as an argument or in + // a declaration - if it's used more than once, then differentiate + // it. Note, some names only appear multiple times as arguments + // when invoking methods, but not in the declarations of the methods + // themselves. + for ( auto& arg : args ) { + auto& decl = arg.decl_name; + auto& name = arg.param_name; + bool decl_and_arg_same = decl == name; + + if ( name_count[name] == 1 ) + continue; // it's unique + + auto n = to_string(++usage_count[name]); + name += n; + if ( decl_and_arg_same ) + decl += n; + } + + // Finally, build the full versions of the declaration and parameters. + + for ( auto& arg : args ) { + if ( ! full_decl.empty() ) + full_decl += ", "; + + full_decl += arg.decl_type + " " + arg.decl_name; + + if ( ! full_params.empty() ) + full_params += ", "; + + full_params += arg.param_name; + params.push_back(arg.param_name); + } +} + +ZAM_OpTemplate::ZAM_OpTemplate(ZAMGen* _g, string _base_name) : g(_g), base_name(std::move(_base_name)) { + // Make the base name viable in a C++ name. + transform(base_name.begin(), base_name.end(), base_name.begin(), dash_to_under); + + cname = base_name; + transform(cname.begin(), cname.end(), cname.begin(), ::toupper); +} + +void ZAM_OpTemplate::Build() { + op_loc = g->CurrLoc(); + + string line; + while ( g->ScanLine(line) ) { + if ( line.size() <= 1 ) + break; + + auto words = g->SplitIntoWords(line); + if ( words.empty() ) + break; + + Parse(words[0], line, words); + } + + if ( ! op_classes.empty() && ! op_classes_vec.empty() ) + Gripe("\"class\" and \"classes\" are mutually exclusive"); + + if ( ! op_classes.empty() || ! op_classes_vec.empty() ) { + auto nclasses = op_classes.empty() ? op_classes_vec[0].size() : op_classes.size(); + + for ( auto& oc : op_classes_vec ) + if ( oc.size() != nclasses ) + Gripe("size mismatch in \"classes\" specifications"); + + if ( ! op_types.empty() && op_types.size() != nclasses ) + Gripe("number of \"op-types\" elements must match \"class\"/\"classes\""); + } + + else if ( ! op_types.empty() ) + Gripe("\"op-types\" can only be used with \"class\"/\"classes\""); +} + +void ZAM_OpTemplate::Instantiate() { + if ( IsPredicate() ) + InstantiatePredicate(); + + else if ( op_classes_vec.empty() ) + InstantiateOp(OperandClasses(), IncludesVectorOp()); + + else + for ( auto& ocs : op_classes_vec ) + InstantiateOp(ocs, IncludesVectorOp()); +} + +void ZAM_OpTemplate::InstantiatePredicate() { + if ( ! op_classes_vec.empty() ) + Gripe("\"predicate\" cannot include \"classes\""); + + if ( op_classes.empty() ) + Gripe("\"predicate\" requires a \"class\""); + + if ( IncludesVectorOp() ) + Gripe("\"predicate\" cannot include \"vector\""); + + // Build 3 forms: an assignment to an int-value'd $$, a conditional + // if the evaluation is true, and one if it is not. + + auto orig_eval = eval; + // Remove trailing '\n' from eval. + orig_eval.pop_back(); + + auto orig_op_classes = op_classes; + bool no_classes = orig_op_classes[0] == ZAM_OC_NONE; + + // Assignment form. + op_classes.clear(); + op_classes.push_back(ZAM_OC_VAR); + if ( ! no_classes ) + op_classes.insert(op_classes.end(), orig_op_classes.begin(), orig_op_classes.end()); + + string target_accessor; + + if ( ! op_types.empty() ) + op_types.insert(op_types.begin(), ZAM_TYPE_INT); + else + target_accessor = ".AsIntRef()"; + + eval = "$$" + target_accessor + " = " + orig_eval + ";"; + + InstantiateOp(op_classes, false); + + // Conditional form - branch if not true. + + if ( ! op_types.empty() ) { + // Remove 'V' at the beginning from the assignment form, + // and add a 'i' at the end for the branch. + op_types.erase(op_types.begin()); + op_types.push_back(ZAM_TYPE_INT); + } + + cname += "_COND"; + op1_flavor = "OP1_READ"; + if ( no_classes ) + op_classes.clear(); + else + op_classes = orig_op_classes; + + op_classes.push_back(ZAM_OC_BRANCH); + + auto branch_pos = to_string(op_classes.size()); + auto suffix = " )\n\t\t$" + branch_pos; + eval = "if ( ! (" + orig_eval + ")" + suffix; + InstantiateOp(op_classes, false); + + // Now the form that branches if true. + cname = "NOT_" + cname; + eval = "if ( (" + orig_eval + ")" + suffix; + InstantiateOp(op_classes, false); +} + +void ZAM_OpTemplate::UnaryInstantiate() { + // First operand is always the frame slot to which this operation + // assigns the result of the applying unary operator. + OCVec ocs = {ZAM_OC_VAR}; + ocs.resize(2); + + // Now build versions for a constant operand (maybe not actually + // needed due to constant folding, but sometimes that gets deferred + // to run-time) ... + if ( ! NoConst() ) { + ocs[1] = ZAM_OC_CONSTANT; + InstantiateOp(ocs, IncludesVectorOp()); + } + + // ... and for a variable (frame-slot) operand. + ocs[1] = ZAM_OC_VAR; + InstantiateOp(ocs, IncludesVectorOp()); +} + +void ZAM_OpTemplate::Parse(const string& attr, const string& line, const Words& words) { + int num_args = -1; // -1 = don't enforce + int nwords = static_cast(words.size()); + + if ( attr == "class" ) { + if ( nwords <= 1 ) + g->Gripe("missing argument", line); + + num_args = 1; + op_classes = ParseClass(words[1]); + } + + else if ( attr == "classes" ) { + if ( nwords <= 1 ) + g->Gripe("missing argument", line); + + num_args = -1; + + for ( int i = 1; i < nwords; ++i ) + op_classes_vec.push_back(ParseClass(words[i])); + } + + else if ( attr == "op-types" ) { + if ( words.size() == 1 ) + g->Gripe("op-types needs arguments", line); + + for ( auto i = 1U; i < words.size(); ++i ) { + auto& w_i = words[i]; + if ( w_i.size() != 1 ) + g->Gripe("bad op-types argument", w_i); + + auto et_c = w_i.c_str()[0]; + if ( type_names.count(et_c) == 0 ) + g->Gripe("bad op-types argument", w_i); + + op_types.push_back(type_names[et_c]); + } + } + + else if ( attr == "op1-read" ) { + num_args = 0; + SetOp1Flavor("OP1_READ"); + } + + else if ( attr == "op1-read-write" ) { + num_args = 0; + SetOp1Flavor("OP1_READ_WRITE"); + } + + else if ( attr == "op1-internal" ) { + num_args = 0; + SetOp1Flavor("OP1_INTERNAL"); + } + + else if ( attr == "set-type" ) { + num_args = 1; + if ( nwords > 1 ) + SetTypeParam(ExtractTypeParam(words[1])); + } + + else if ( attr == "set-type2" ) { + num_args = 1; + if ( nwords > 1 ) + SetType2Param(ExtractTypeParam(words[1])); + } + + else if ( attr == "custom-method" ) + SetCustomMethod(g->SkipWords(line, 1)); + + else if ( attr == "method-post" ) + SetPostMethod(g->SkipWords(line, 1)); + + else if ( attr == "side-effects" ) { + if ( nwords == 3 ) + SetAssignmentLess(words[1], words[2]); + else + // otherwise shouldn't be any arguments + num_args = 0; + + SetHasSideEffects(); + } + + else if ( attr == "no-eval" ) { + num_args = 0; + SetNoEval(); + } + + else if ( attr == "vector" ) { + num_args = 0; + SetIncludesVectorOp(); + } + + else if ( attr == "assign-val" ) { + num_args = 1; + if ( words.size() > 1 ) + SetAssignVal(words[1]); + } + + else if ( attr == "eval" ) { + AddEval(g->SkipWords(line, 1)); + + auto addl = GatherEval(); + if ( ! addl.empty() ) + AddEval(addl); + } + + else if ( attr == "macro" ) + g->ReadMacro(line); + + else + g->Gripe("unknown template attribute", attr); + + if ( num_args >= 0 && num_args != nwords - 1 ) + g->Gripe("extraneous or missing arguments", line); +} + +OCVec ZAM_OpTemplate::ParseClass(const string& spec) const { + OCVec ocs; + + const char* types = spec.c_str(); + while ( *types ) { + ZAM_OperandClass oc = ZAM_OC_NONE; + + switch ( *types ) { + case 'C': oc = ZAM_OC_CONSTANT; break; + case 'F': oc = ZAM_OC_ASSIGN_FIELD; break; + case 'H': oc = ZAM_OC_EVENT_HANDLER; break; + case 'L': oc = ZAM_OC_LIST; break; + case 'O': oc = ZAM_OC_AUX; break; + case 'R': oc = ZAM_OC_RECORD_FIELD; break; + case 'V': oc = ZAM_OC_VAR; break; + case 'i': oc = ZAM_OC_INT; break; + case 'b': oc = ZAM_OC_BRANCH; break; + case 'f': // 'f' = "for" loop + oc = ZAM_OC_TBL_ITER; + break; + case 'g': oc = ZAM_OC_GLOBAL; break; + case 's': oc = ZAM_OC_STEP_ITER; break; + + case 'X': oc = ZAM_OC_NONE; break; + + default: g->Gripe("bad operand type", spec); break; + } + + ocs.push_back(oc); + + ++types; + } + + return ocs; +} + +string ZAM_OpTemplate::GatherEval() { + string res; + string l; + while ( g->ScanLine(l) ) { + if ( l.size() <= 1 || ! isspace(l.c_str()[0]) ) { + g->PutBack(l); + return res; + } + + res += l; + } + + return res; +} + +int ZAM_OpTemplate::ExtractTypeParam(const string& arg) { + if ( arg == "$$" ) + return 0; + + if ( arg[0] != '$' ) + g->Gripe("bad set-type parameter, should be $n", arg); + + int param = atoi(&arg[1]); + + if ( param <= 0 || param > 2 ) + g->Gripe("bad set-type parameter, should be $1 or $2", arg); + + return param; +} // Maps an operand type to a character mnemonic used to distinguish // it from others. unordered_map ZAM_OpTemplate::oc_to_char = { - {ZAM_OC_AUX, 'O'}, - {ZAM_OC_CONSTANT, 'C'}, - {ZAM_OC_EVENT_HANDLER, 'H'}, - {ZAM_OC_ASSIGN_FIELD, 'F'}, - {ZAM_OC_INT, 'i'}, - {ZAM_OC_LIST, 'L'}, - {ZAM_OC_NONE, 'X'}, - {ZAM_OC_RECORD_FIELD, 'R'}, - {ZAM_OC_VAR, 'V'}, - {ZAM_OC_BRANCH, 'b'}, - {ZAM_OC_GLOBAL, 'g'}, - {ZAM_OC_STEP_ITER, 's'}, - {ZAM_OC_TBL_ITER, 'f'}, + {ZAM_OC_AUX, 'O'}, {ZAM_OC_CONSTANT, 'C'}, {ZAM_OC_EVENT_HANDLER, 'H'}, {ZAM_OC_ASSIGN_FIELD, 'F'}, + {ZAM_OC_INT, 'i'}, {ZAM_OC_LIST, 'L'}, {ZAM_OC_NONE, 'X'}, {ZAM_OC_RECORD_FIELD, 'R'}, + {ZAM_OC_VAR, 'V'}, {ZAM_OC_BRANCH, 'b'}, {ZAM_OC_GLOBAL, 'g'}, {ZAM_OC_STEP_ITER, 's'}, + {ZAM_OC_TBL_ITER, 'f'}, }; -void ZAM_OpTemplate::InstantiateOp(const OCVec& oc, bool do_vec) - { - auto method = MethodName(oc); - - InstantiateOp(method, oc, ZIC_REGULAR); - - if ( IncludesFieldOp() ) - InstantiateOp(method, oc, ZIC_FIELD); - - if ( do_vec ) - InstantiateOp(method, oc, ZIC_VEC); - - if ( IsConditionalOp() ) - InstantiateOp(method, oc, ZIC_COND); - } - -void ZAM_OpTemplate::InstantiateOp(const string& orig_method, const OCVec& oc_orig, - ZAM_InstClass zc) - { - auto oc = oc_orig; - string suffix = ""; - - if ( zc == ZIC_FIELD ) - { - // Make room for the offset. - oc.push_back(ZAM_OC_INT); - suffix = NoEval() ? "" : "_field"; - } - - else if ( zc == ZIC_COND ) - { - // Remove the assignment and add in the branch. - oc.erase(oc.begin()); - oc.push_back(ZAM_OC_BRANCH); - suffix = "_cond"; - } - - else if ( zc == ZIC_VEC ) - { - // Don't generate versions of these for constant operands - // as those don't exist. - if ( int(oc.size()) != Arity() + 1 ) - Gripe("vector class/arity mismatch"); - - if ( oc[1] == ZAM_OC_CONSTANT ) - return; - if ( Arity() > 1 && oc[2] == ZAM_OC_CONSTANT ) - return; - - suffix = "_vec"; - } - - auto method = MethodName(oc); - - if ( ! IsInternalOp() ) - InstantiateMethod(method, suffix, oc, zc); - - if ( IsAssignOp() ) - InstantiateAssignOp(oc, suffix); - else - { - InstantiateEval(oc, suffix, zc); - - if ( HasAssignmentLess() ) - { - auto op_string = "_" + OpSuffix(oc); - auto op = g->GenOpCode(this, op_string); - GenAssignmentlessVersion(op); - } - } - } - -void ZAM_OpTemplate::GenAssignmentlessVersion(const string& op) - { - EmitTo(AssignFlavor); - Emit("assignmentless_op[" + op + "] = " + AssignmentLessOp() + ";"); - Emit("assignmentless_op_class[" + op + "] = " + AssignmentLessOpClass() + ";"); - } - -void ZAM_OpTemplate::InstantiateMethod(const string& m, const string& suffix, - const OCVec& oc, ZAM_InstClass zc) - { - if ( IsInternalOp() ) - return; - - auto decls = MethodDeclare(oc, zc); - - EmitTo(MethodDecl); - Emit("const ZAMStmt " + m + suffix + "(" + decls + ");"); - - EmitTo(MethodDef); - Emit("const ZAMStmt ZAMCompiler::" + m + suffix + "(" + decls + ")"); - BeginBlock(); - - InstantiateMethodCore(oc, suffix, zc); - - if ( HasPostMethod() ) - Emit(GetPostMethod()); - - if ( ! HasCustomMethod() ) - Emit("return AddInst(z);"); - - EndBlock(); - NL(); - } - -void ZAM_OpTemplate::InstantiateMethodCore(const OCVec& oc, const string& suffix, - ZAM_InstClass zc) - { - if ( HasCustomMethod() ) - { - Emit(GetCustomMethod()); - return; - } - - assert(! oc.empty()); - - string full_suffix = "_" + OpSuffix(oc) + suffix; - - Emit("ZInstI z;"); - - if ( oc[0] == ZAM_OC_AUX ) - { - auto op = g->GenOpCode(this, full_suffix, zc); - Emit("z = ZInstI(" + op + ");"); - return; - } - - if ( oc[0] == ZAM_OC_NONE ) - { - auto op = g->GenOpCode(this, full_suffix, zc); - Emit("z = GenInst(" + op + ");"); - return; - } - - if ( oc.size() > 1 && oc[1] == ZAM_OC_AUX ) - { - auto op = g->GenOpCode(this, full_suffix, zc); - Emit("z = ZInstI(" + op + ", Frame1Slot(n, " + op + "));"); - return; - } - - ArgsManager args(oc, zc); - BuildInstruction(oc, args.Params(), full_suffix, zc); - - auto& tp = GetTypeParam(); - if ( tp ) - Emit("z.SetType(" + args.NthParam(*tp) + "->GetType());"); - - auto& tp2 = GetType2Param(); - if ( tp2 ) - Emit("z.SetType2(" + args.NthParam(*tp2) + "->GetType());"); - } - -void ZAM_OpTemplate::BuildInstruction(const OCVec& oc, const string& params, - const string& suffix, ZAM_InstClass zc) - { - auto op = g->GenOpCode(this, suffix, zc); - Emit("z = GenInst(" + op + ", " + params + ");"); - } - -static bool skippable_ot(ZAM_OperandClass oc) - { - return oc == ZAM_OC_EVENT_HANDLER || oc == ZAM_OC_AUX || oc == ZAM_OC_LIST; - } - -string ZAM_OpTemplate::ExpandParams(const OCVec& oc, string eval, const vector& accessors) const - { - auto have_target = eval.find("$$") != string::npos; - - auto fl = GetOp1Flavor(); - auto need_target = fl == "OP1_WRITE"; - - auto oc_size = oc.size(); - if ( oc_size > 0 ) - { - auto oc0 = oc[0]; - - if ( oc0 == ZAM_OC_NONE || oc0 == ZAM_OC_AUX ) - { - --oc_size; - need_target = false; - } - - else if ( raw_int_oc.count(oc0) > 0 ) - need_target = false; - } - - while ( oc_size > 0 && skippable_ot(oc[oc_size - 1]) ) - --oc_size; - - auto max_param = oc_size; - - if ( need_target && ! have_target ) - Gripe("eval missing $$:", eval); - - if ( have_target ) - { - assert(max_param > 0); - --max_param; - } - - bool has_d1 = eval.find("$1") != string::npos; - bool has_d2 = eval.find("$2") != string::npos; - bool has_d3 = eval.find("$3") != string::npos; - bool has_d4 = eval.find("$4") != string::npos; - - switch ( max_param ) { - case 4: if ( ! has_d4 ) Gripe("eval missing $4", eval); - case 3: if ( ! has_d3 ) Gripe("eval missing $3", eval); - case 2: if ( ! has_d2 ) Gripe("eval missing $2", eval); - case 1: if ( ! has_d1 ) Gripe("eval missing $1", eval); - - case 0: - break; - - default: - Gripe("unexpected param size", to_string(max_param) + " - " + eval); - break; - } - - switch ( max_param ) { - case 0: if ( has_d1 ) Gripe("extraneous $1 in eval", eval); - case 1: if ( has_d2 ) Gripe("extraneous $2 in eval", eval); - case 2: if ( has_d3 ) Gripe("extraneous $3 in eval", eval); - case 3: if ( has_d4 ) Gripe("extraneous $4 in eval", eval); - - case 4: - break; - - default: - Gripe("unexpected param size", to_string(max_param) + " - " + eval); - break; - } - - int frame_slot = 0; - bool const_seen = false; - bool int_seen = false; - - for ( size_t i = 0; i < oc_size; ++i ) - { - string op; - bool needs_accessor = true; - - switch ( oc[i] ) { - case ZAM_OC_VAR: - if ( int_seen ) - Gripe("'V' type specifier after 'i' specifier", eval); - op = "frame[z.v" + to_string(++frame_slot) + "]"; - break; - - case ZAM_OC_RECORD_FIELD: - op = "frame[z.v" + to_string(++frame_slot) + "]"; - break; - - case ZAM_OC_INT: - case ZAM_OC_BRANCH: - case ZAM_OC_GLOBAL: - case ZAM_OC_STEP_ITER: - case ZAM_OC_TBL_ITER: - op = "z.v" + to_string(++frame_slot); - int_seen = true; - needs_accessor = false; - - if ( oc[i] == ZAM_OC_BRANCH ) - op = "Branch(" + op + ")"; - else if ( oc[i] == ZAM_OC_STEP_ITER ) - op = "StepIter(" + op + ")"; - else if ( oc[i] == ZAM_OC_TBL_ITER ) - op = "TableIter(" + op + ")"; - break; - - case ZAM_OC_CONSTANT: - if ( const_seen ) - g->Gripe("double constant", eval.c_str()); - const_seen = true; - op = "z.c"; - break; - - default: - Gripe("unexpected oc type", eval); - break; - } - - if ( needs_accessor ) - { - if ( ! accessors.empty() && ! accessors[i].empty() ) - op += "." + accessors[i]; - else if ( ! op_types.empty() && op_types[i] != ZAM_TYPE_NONE ) - op += "." + find_type_accessor(op_types[i], have_target && i == 0); - } - - else if ( ! op_types.empty() && oc[i] == ZAM_OC_INT ) - { - if ( op_types[i] == ZAM_TYPE_UINT ) - op = "zeek_uint_t(" + op + ")"; - } - - string pat; - if ( i == 0 && have_target ) - pat = "\\$\\$"; - else - pat = "\\$" + to_string(have_target ? i : i + 1); - - auto orig_eval = eval; - eval = regex_replace(eval, regex(pat), op); - if ( orig_eval == eval ) - Gripe("no eval sub", pat + " - " + eval); - } - - return eval; - } - -void ZAM_OpTemplate::InstantiateEval(const OCVec& oc, const string& suffix, - ZAM_InstClass zc) - { - if ( NoEval() ) - return; - - auto eval = ExpandParams(oc, GetEval(), accessors); - - GenEval(Eval, OpSuffix(oc), suffix, eval, zc); - } - -void ZAM_OpTemplate::GenEval(EmitTarget et, const string& oc_str, const string& op_suffix, const string& eval, ZAM_InstClass zc) - { - auto op_code = g->GenOpCode(this, "_" + oc_str + op_suffix, zc); - - if ( et == Eval ) - { - auto oc_str_copy = oc_str; - if ( zc == ZIC_COND ) - { - auto n = oc_str_copy.size(); - - if ( oc_str_copy[n-1] == 'V' ) - oc_str_copy[n-1] = 'i'; - - else if ( oc_str_copy[n-1] == 'C' ) - { - if ( oc_str_copy[n-2] != 'V' ) - Gripe("bad operator class"); - - oc_str_copy[n-2] = 'C'; - oc_str_copy[n-1] = 'i'; - } - } - - GenDesc(op_code, oc_str_copy, eval); - } - - EmitTo(et); - Emit("case " + op_code + ":"); - BeginBlock(); - Emit(eval); - EndBlock(); - EmitUp("break;"); - NL(); - } - -void ZAM_OpTemplate::GenDesc(const string& op_code, const string& oc_str, const string& eval) - { - StartDesc(op_code, oc_str); - Emit(eval); - EndDesc(); - } - -void ZAM_OpTemplate::StartDesc(const string& op_code, const string& oc_str) - { - EmitTo(OpDesc); - Emit("{ " + op_code + ","); - BeginBlock(); - Emit("\"" + oc_str + "\","); - - if ( op_types.empty() ) - Emit("\"\","); - else - { - string ots; - for ( auto ot : op_types ) - { - if ( ot == ZAM_TYPE_DEFAULT ) - ots += "X"; - else - ots += expr_name_types[ot]; - } - - Emit("\"" + ots + "\", "); - } - - StartString(); - } - -void ZAM_OpTemplate::EndDesc() - { - EndString(); - EndBlock(); - Emit("},"); - } - -void ZAM_OpTemplate::InstantiateAssignOp(const OCVec& oc, const string& suffix) - { - // First, create a generic version of the operand, which the - // ZAM compiler uses to find specific-flavored versions. - auto oc_str = OpSuffix(oc); - auto op_string = "_" + oc_str; - auto generic_op = g->GenOpCode(this, op_string); - auto flavor_ind = "assignment_flavor[" + generic_op + "]"; - - EmitTo(AssignFlavor); - Emit(flavor_ind + " = empty_map;"); - - auto eval = GetEval(); - auto v = GetAssignVal(); - - for ( auto& ti : ZAM_type_info ) - { - auto op = g->GenOpCode(this, op_string + "_" + ti.suffix); - - if ( IsInternalOp() ) - { - EmitTo(AssignFlavor); - Emit(flavor_ind + "[" + ti.tag + "] = " + op + ";"); - - if ( HasAssignmentLess() ) - GenAssignmentlessVersion(op); - } - - StartDesc(op, oc_str); - GenAssignOpCore(oc, eval, ti.accessor, ti.is_managed); - if ( ! post_eval.empty() ) - Emit(post_eval); - EndDesc(); - - EmitTo(Eval); - Emit("case " + op + ":"); - BeginBlock(); - GenAssignOpCore(oc, eval, ti.accessor, ti.is_managed); - if ( ! post_eval.empty() ) - Emit(post_eval); - Emit("break;"); - EndBlock(); - } - - post_eval.clear(); - } - -void ZAM_OpTemplate::GenAssignOpCore(const OCVec& oc, const string& eval, - const string& accessor, bool is_managed) - { - if ( HasAssignVal() ) - { - GenAssignOpValCore(oc, eval, accessor, is_managed); - return; - } - - if ( ! eval.empty() ) - g->Gripe("assign-op should not have an \"eval\"", eval); - - auto lhs_field = (oc[0] == ZAM_OC_ASSIGN_FIELD); - auto rhs_field = lhs_field && oc.size() > 3 && (oc[3] == ZAM_OC_INT); - auto constant_op = (oc[1] == ZAM_OC_CONSTANT); - - string rhs = constant_op ? "z.c" : "frame[z.v2]"; - - auto acc = ".As" + accessor + "()"; - - if ( accessor == "Any" && constant_op && ! rhs_field ) - { - // "any_val = constant" or "x$any_val = constant". - // - // These require special-casing, because to avoid going - // through a CoerceToAny operation, we allow expressing - // these directly. They don't fit with the usual assignment - // paradigm since the RHS differs in type from the LHS. - Emit("auto v = z.c.ToVal(Z_TYPE);"); - - if ( lhs_field ) - { - Emit("auto r = frame[z.v1].AsRecord();"); - Emit("auto& f = DirectField(r, z.v2);"); - } - else - Emit("auto& f = frame[z.v1];"); - - Emit("zeek::Unref(f.ManagedVal());"); - Emit("f = ZVal(v.release());"); - } - - else if ( rhs_field ) - { - // The following is counter-intuitive, but comes from the - // fact that we build out the instruction parameters as - // an echo of the method parameters, and for this case that - // means that the RHS field offset comes *before*, not after, - // the LHS field offset. - auto lhs_offset = constant_op ? 3 : 4; - auto rhs_offset = lhs_offset - 1; - - Emit("auto v = DirectOptField(" + rhs + ".AsRecord(), z.v" + to_string(rhs_offset) + - "); // note, RHS field before LHS field\n"); - - Emit("if ( ! v )"); - BeginBlock(); - Emit("ZAM_run_time_error(Z_LOC, \"field value missing\");"); - EndBlock(); - - Emit("else"); - BeginBlock(); - auto slot = "z.v" + to_string(lhs_offset); - Emit("auto r = frame[z.v1].AsRecord();"); - Emit("auto& f = DirectField(r, " + slot + "); // note, LHS field after RHS field\n"); - - if ( is_managed ) - { - Emit("zeek::Ref((*v)" + acc + ");"); - Emit("zeek::Unref(f.ManagedVal());"); - } - - Emit("f = *v;"); - - if ( lhs_field ) - Emit("r->Modified();"); - - EndBlock(); - } - - else - { - if ( is_managed ) - Emit("zeek::Ref(" + rhs + acc + ");"); - - if ( lhs_field ) - { - auto lhs_offset = constant_op ? 2 : 3; - auto slot = "z.v" + to_string(lhs_offset); - Emit("auto r = frame[z.v1].AsRecord();"); - Emit("auto& f = DirectField(r, " + slot + ");"); - - if ( is_managed ) - Emit("zeek::Unref(f.ManagedVal());"); - - Emit("f = " + rhs + ";"); - Emit("r->Modified();"); - } - - else - { - if ( is_managed ) - Emit("zeek::Unref(frame[z.v1].ManagedVal());"); - - Emit("frame[z.v1] = ZVal(" + rhs + acc + ");"); - } - } - } - -void ZAM_OpTemplate::GenAssignOpValCore(const OCVec& oc, const string& orig_eval, const string& accessor, bool is_managed) - { - auto v = GetAssignVal(); - - // Maps Zeek types to how to get the underlying value from a ValPtr. - static unordered_map val_accessors = { - {"Addr", "->AsAddrVal()"}, {"Any", ".get()"}, - {"Count", "->AsCount()"}, {"Double", "->AsDouble()"}, - {"Int", "->AsInt()"}, {"Pattern", "->AsPatternVal()"}, - {"String", "->AsStringVal()"}, {"SubNet", "->AsSubNetVal()"}, - {"Table", "->AsTableVal()"}, {"Vector", "->AsVectorVal()"}, - {"File", "->AsFile()"}, {"Func", "->AsFunc()"}, - {"List", "->AsListVal()"}, {"Opaque", "->AsOpaqueVal()"}, - {"Record", "->AsRecordVal()"}, {"Type", "->AsTypeVal()"}, - }; - - auto val_accessor = val_accessors[accessor]; - - string rhs; - if ( IsInternalOp() ) - rhs = v + val_accessor; - else - rhs = v + ".As" + accessor + "()"; - - auto eval = orig_eval; - - if ( is_managed ) - { - eval += string("auto rhs = ") + rhs + ";\n"; - eval += "zeek::Ref(rhs);\n"; - eval += "Unref($$.ManagedVal());\n"; - eval += "$$ = ZVal(rhs);\n"; - } - else - eval += "$$ = ZVal(" + rhs + ");\n"; - - Emit(ExpandParams(oc, eval)); - } - -string ZAM_OpTemplate::MethodName(const OCVec& oc) const - { - return base_name + OpSuffix(oc); - } - -string ZAM_OpTemplate::MethodDeclare(const OCVec& oc, ZAM_InstClass zc) - { - ArgsManager args(oc, zc); - return args.Decls(); - } - -string ZAM_OpTemplate::OpSuffix(const OCVec& oc) const - { - string os; - for ( auto& o : oc ) - os += oc_to_char[o]; - return os; - } - -string ZAM_OpTemplate::SkipWS(const string& s) const - { - auto sp = s.c_str(); - while ( *sp && isspace(*sp) ) - ++sp; - - return sp; - } - -void ZAM_OpTemplate::Emit(const string& s) - { - g->Emit(curr_et, s); - } - -void ZAM_OpTemplate::EmitNoNL(const string& s) - { - g->SetNoNL(true); - Emit(s); - g->SetNoNL(false); - } - -void ZAM_OpTemplate::IndentUp() - { - g->IndentUp(); - } - -void ZAM_OpTemplate::IndentDown() - { - g->IndentDown(); - } - -void ZAM_OpTemplate::StartString() - { - g->StartString(); - } - -void ZAM_OpTemplate::EndString() - { - g->EndString(); - } - -void ZAM_OpTemplate::Gripe(const char* msg) const - { - g->Gripe(msg, op_loc); - } - -void ZAM_OpTemplate::Gripe(string msg, string addl) const - { - auto full_msg = msg + ": " + addl; - Gripe(full_msg.c_str()); - } - -void ZAM_UnaryOpTemplate::Instantiate() - { - UnaryInstantiate(); - } - -void ZAM_DirectUnaryOpTemplate::Instantiate() - { - EmitTo(DirectDef); - Emit("case EXPR_" + cname + ":\treturn " + direct + "(lhs, rhs);"); - } - -ZAM_ExprOpTemplate::ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name) - : ZAM_OpTemplate(_g, std::move(_base_name)) - { - static bool did_map_init = false; - - if ( ! did_map_init ) - { // Create the inverse mapping. - for ( auto& tn : type_names ) - expr_name_types[tn.second] = tn.first; - - did_map_init = true; - } - } - -void ZAM_ExprOpTemplate::Parse(const string& attr, const string& line, const Words& words) - { - if ( attr == "op-type" ) - { - if ( words.size() == 1 ) - g->Gripe("op-type needs arguments", line); - - for ( auto i = 1U; i < words.size(); ++i ) - { - auto& w_i = words[i]; - if ( w_i.size() != 1 ) - g->Gripe("bad op-type argument", w_i); - - auto et_c = w_i.c_str()[0]; - if ( type_names.count(et_c) == 0 ) - g->Gripe("bad op-type argument", w_i); - - AddExprType(type_names[et_c]); - } - } - - else if ( attr == "includes-field-op" ) - { - if ( words.size() != 1 ) - g->Gripe("includes-field-op does not take any arguments", line); - - SetIncludesFieldOp(); - } - - else if ( attr == "eval-type" ) - { - if ( words.size() < 3 ) - g->Gripe("eval-type needs type and evaluation", line); - - auto& type = words[1]; - if ( type.size() != 1 ) - g->Gripe("bad eval-type type", type); - - auto type_c = type.c_str()[0]; - if ( type_names.count(type_c) == 0 ) - g->Gripe("bad eval-type type", type); - - auto zt = type_names[type_c]; - - if ( expr_types.count(zt) == 0 ) - g->Gripe("eval-type type not present in eval-type", type); - - auto eval = g->SkipWords(line, 2); - eval += GatherEval(); - AddEvalSet(zt, eval); - } - - else if ( attr == "eval-mixed" ) - { - if ( words.size() < 4 ) - g->Gripe("eval-mixed needs types and evaluation", line); - - auto& type1 = words[1]; - auto& type2 = words[2]; - if ( type1.size() != 1 || type2.size() != 1 ) - g->Gripe("bad eval-mixed types", line); - - auto type_c1 = type1.c_str()[0]; - auto type_c2 = type2.c_str()[0]; - if ( type_names.count(type_c1) == 0 || type_names.count(type_c2) == 0 ) - g->Gripe("bad eval-mixed types", line); - - auto et1 = type_names[type_c1]; - auto et2 = type_names[type_c2]; - - auto eval = g->SkipWords(line, 3); - eval += GatherEval(); - AddEvalSet(et1, et2, eval); - } - - else if ( attr == "precheck" ) - { - if ( words.size() < 2 ) - g->Gripe("precheck needs evaluation", line); - - auto eval = g->SkipWords(line, 1); - eval += GatherEval(); - eval.pop_back(); - - SetPreCheck(eval); - } - - else if ( attr == "precheck-action" ) - { - if ( words.size() < 2 ) - g->Gripe("precheck-action needs evaluation", line); - - auto eval = g->SkipWords(line, 1); - eval += GatherEval(); - eval.pop_back(); - - SetPreCheckAction(eval); - } - - else if ( attr == "explicit-result-type" ) - { - if ( words.size() != 1 ) - g->Gripe("extraneous argument to explicit-result-type", line); - SetHasExplicitResultType(); - } - - else - // Not an attribute specific to expr-op's. - ZAM_OpTemplate::Parse(attr, line, words); - } - -void ZAM_ExprOpTemplate::Instantiate() - { - if ( ! op_classes_vec.empty() ) - Gripe("expressions cannot use \"classes\""); - - InstantiateOp(OperandClasses(), IncludesVectorOp()); - - if ( op_classes.size() > 1 && op_classes[1] == ZAM_OC_CONSTANT ) - InstantiateC1(op_classes, op_classes.size() - 1); - if ( op_classes.size() > 2 && op_classes[2] == ZAM_OC_CONSTANT ) - InstantiateC2(op_classes, op_classes.size() - 1); - if ( op_classes.size() > 3 && op_classes[3] == ZAM_OC_CONSTANT ) - InstantiateC3(op_classes); - - bool all_var = true; - for ( auto i = 1U; i < op_classes.size(); ++i ) - if ( op_classes[i] != ZAM_OC_VAR ) - all_var = false; - - if ( all_var ) - InstantiateV(op_classes); - - if ( op_classes.size() == 3 && op_classes[1] == ZAM_OC_RECORD_FIELD && op_classes[2] == ZAM_OC_INT ) - InstantiateV(op_classes); - } - -void ZAM_ExprOpTemplate::InstantiateC1(const OCVec& ocs, size_t arity) - { - string args = "lhs, r1->AsConstExpr()"; - - if ( arity == 1 && ocs[0] == ZAM_OC_RECORD_FIELD ) - args += ", rhs->AsFieldExpr()->Field()"; - - else if ( arity > 1 ) - { - args += ", "; - - if ( ocs[2] == ZAM_OC_RECORD_FIELD ) - args += "rhs->AsFieldExpr()->Field()"; - else - args += "r2->AsNameExpr()"; - } - - auto m = MethodName(ocs); - - EmitTo(C1Def); - - EmitNoNL("case EXPR_" + cname + ":"); - - EmitUp("return " + m + "(" + args + ");"); - - if ( IncludesFieldOp() ) - { - EmitTo(C1FieldDef); - Emit("case EXPR_" + cname + ":\treturn " + m + "i_field(" + args + ", field);"); - } - } - -void ZAM_ExprOpTemplate::InstantiateC2(const OCVec& ocs, size_t arity) - { - string args = "lhs, r1->AsNameExpr(), r2->AsConstExpr()"; - - if ( arity == 3 ) - args += ", r3->AsNameExpr()"; - - auto method = MethodName(ocs); - auto m = method.c_str(); - - EmitTo(C2Def); - Emit("case EXPR_" + cname + ":\treturn " + m + "(" + args + ");"); - - if ( IncludesFieldOp() ) - { - EmitTo(C2FieldDef); - Emit("case EXPR_" + cname + ":\treturn " + m + "i_field(" + args + ", field);"); - } - } - -void ZAM_ExprOpTemplate::InstantiateC3(const OCVec& ocs) - { - EmitTo(C3Def); - Emit("case EXPR_" + cname + ":\treturn " + MethodName(ocs) + - "(lhs, r1->AsNameExpr(), r2->AsNameExpr(), r3->AsConstExpr());"); - } - -void ZAM_ExprOpTemplate::InstantiateV(const OCVec& ocs) - { - auto m = MethodName(ocs); - - string args = "lhs, r1->AsNameExpr()"; - - if ( ocs.size() >= 3 ) - { - if ( ocs[2] == ZAM_OC_INT ) - { - string acc_flav = IncludesFieldOp() ? "Has" : ""; - args += ", rhs->As" + acc_flav + "FieldExpr()->Field()"; - } - else - args += ", r2->AsNameExpr()"; - - if ( ocs.size() == 4 ) - args += ", r3->AsNameExpr()"; - } - - EmitTo(VDef); - EmitNoNL("case EXPR_" + cname + ":"); - - if ( IncludesVectorOp() ) - DoVectorCase(m, args); - else - EmitUp("return " + m + "(" + args + ");"); - - if ( IncludesFieldOp() ) - { - string suffix = NoEval() ? "" : "_field"; - EmitTo(VFieldDef); - Emit("case EXPR_" + cname + ":\treturn " + m + "i" + suffix + "(" + args + ", field);"); - } - } - -void ZAM_ExprOpTemplate::DoVectorCase(const string& m, const string& args) - { - NL(); - IndentUp(); - Emit("if ( rt->Tag() == TYPE_VECTOR )"); - EmitUp("return " + m + "_vec(" + args + ");"); - Emit("else"); - EmitUp("return " + m + "(" + args + ");"); - IndentDown(); - } - -void ZAM_ExprOpTemplate::BuildInstructionCore(const string& params, const string& suffix, - ZAM_InstClass zc) - { - Emit("auto tag1 = t->Tag();"); - Emit("auto i_t1 = t->InternalType();"); - - int ncases = 0; - - if ( zc != ZIC_VEC ) - for ( auto& [et1, et2_map] : eval_mixed_set ) - for ( auto& [et2, eval] : et2_map ) - GenMethodTest(et1, et2, params, suffix, ++ncases > 1, zc); - - bool do_default = false; - - for ( auto zt : ExprTypes() ) - { - if ( zt == ZAM_TYPE_DEFAULT ) - do_default = true; - else if ( zt == ZAM_TYPE_NONE ) - continue; - else - GenMethodTest(zt, zt, params, suffix, ++ncases > 1, zc); - } - - Emit("else"); - - if ( do_default ) - { - auto op = g->GenOpCode(this, suffix, zc); - EmitUp("z = GenInst(" + op + ", " + params + ");"); - } - - else - EmitUp("reporter->InternalError(\"bad tag when generating method core\");"); - } - -void ZAM_ExprOpTemplate::GenMethodTest(ZAM_Type et1, ZAM_Type et2, const string& params, - const string& suffix, bool do_else, ZAM_InstClass zc) - { - // Maps ZAM_Type's to the information needed (variable name, - // constant to compare it against) to identify using an "if" test - // that a given AST Expr node employs the given type of operand. - static map> if_tests = { - {ZAM_TYPE_ADDR, {"i_t", "TYPE_INTERNAL_ADDR"}}, - {ZAM_TYPE_ANY, {"tag", "TYPE_ANY"}}, - {ZAM_TYPE_DOUBLE, {"i_t", "TYPE_INTERNAL_DOUBLE"}}, - {ZAM_TYPE_FILE, {"tag", "TYPE_FILE"}}, - {ZAM_TYPE_FUNC, {"tag", "TYPE_FUNC"}}, - {ZAM_TYPE_INT, {"i_t", "TYPE_INTERNAL_INT"}}, - {ZAM_TYPE_LIST, {"tag", "TYPE_LIST"}}, - {ZAM_TYPE_OPAQUE, {"tag", "TYPE_OPAQUE"}}, - {ZAM_TYPE_PATTERN, {"tag", "TYPE_PATTERN"}}, - {ZAM_TYPE_RECORD, {"tag", "TYPE_RECORD"}}, - {ZAM_TYPE_STRING, {"i_t", "TYPE_INTERNAL_STRING"}}, - {ZAM_TYPE_SUBNET, {"i_t", "TYPE_INTERNAL_SUBNET"}}, - {ZAM_TYPE_TABLE, {"tag", "TYPE_TABLE"}}, - {ZAM_TYPE_TYPE, {"tag", "TYPE_TYPE"}}, - {ZAM_TYPE_UINT, {"i_t", "TYPE_INTERNAL_UNSIGNED"}}, - {ZAM_TYPE_VECTOR, {"tag", "TYPE_VECTOR"}}, - }; - - if ( if_tests.count(et1) == 0 || if_tests.count(et2) == 0 ) - Gripe("bad op-type"); - - auto if_test1 = if_tests[et1]; - auto if_var1 = if_test1.first + "1"; - auto if_val1 = if_test1.second; - - string test = if_var1 + " == " + if_val1; - - if ( Arity() > 1 ) - { - auto if_test2 = if_tests[et2]; - auto if_var2 = if_test2.first + "2"; - auto if_val2 = if_test2.second; - test = test + " && " + if_var2 + " == " + if_val2; - } - - test = "if ( " + test + " )"; - if ( do_else ) - test = "else " + test; - - Emit(test); - - auto op_suffix = suffix + "_" + expr_name_types[et1]; - if ( et2 != et1 ) - op_suffix += expr_name_types[et2]; - - auto op = g->GenOpCode(this, op_suffix, zc); - EmitUp("z = GenInst(" + op + ", " + params + ");"); - } - -EvalInstance::EvalInstance(ZAM_Type _lhs_et, ZAM_Type _op1_et, ZAM_Type _op2_et, - string _eval, bool _is_def) - { - lhs_et = _lhs_et; - op1_et = _op1_et; - op2_et = _op2_et; - eval = std::move(_eval); - is_def = _is_def; - } - -string EvalInstance::LHSAccessor(bool is_ptr) const - { - if ( lhs_et == ZAM_TYPE_NONE || lhs_et == ZAM_TYPE_DEFAULT ) - return ""; - - string deref = is_ptr ? "->" : "."; - string acc = find_type_accessor(lhs_et, true); - - return deref + acc; - } - -string EvalInstance::Accessor(ZAM_Type zt, bool is_ptr) const - { - if ( zt == ZAM_TYPE_NONE || zt == ZAM_TYPE_DEFAULT ) - return ""; - - string deref = is_ptr ? "->" : "."; - return deref + "As" + find_type_info(zt).accessor + "()"; - } - -string EvalInstance::OpMarker() const - { - if ( op1_et == ZAM_TYPE_DEFAULT || op1_et == ZAM_TYPE_NONE ) - return ""; - - if ( op1_et == op2_et ) - return "_" + find_type_info(op1_et).suffix; - - return "_" + find_type_info(op1_et).suffix + find_type_info(op2_et).suffix; - } - -void ZAM_ExprOpTemplate::InstantiateEval(const OCVec& oc_orig, - const string& suffix, ZAM_InstClass zc) - { - if ( (HasPreCheck() || HasPreCheckAction()) && - (! HasPreCheck() || ! HasPreCheckAction()) ) - Gripe("precheck and precheck-action must be used together"); - - auto oc = oc_orig; - - if ( expr_types.empty() ) - { - // No operand types to expand over. This happens for - // some "non-uniform" operations. - ZAM_OpTemplate::InstantiateEval(oc, suffix, zc); - return; - } - - auto oc_str = OpSuffix(oc); - - // Some of these might not wind up being used, but no harm in - // initializing them in case they are. - string lhs, op1, op2; - string branch_target = "z.v"; - - EmitTarget emit_target = Eval; - - if ( zc == ZIC_VEC ) - { - lhs = "vec1[i]"; - op1 = "vec2[i]"; - op2 = "vec3[i]"; - - emit_target = Arity() == 1 ? Vec1Eval : Vec2Eval; - } - - else - { - lhs = "frame[z.v1]"; - - // First compute the offsets into oc for the operands. - auto op1_offset = zc == ZIC_COND ? 0 : 1; - bool oc1_const = oc[op1_offset] == ZAM_OC_CONSTANT; - bool oc2_const = - Arity() > 1 && oc[op1_offset + 1] == ZAM_OC_CONSTANT; - - // Now the frame slots. - auto op1_slot = op1_offset + 1; - auto op2_slot = op1_slot + 1; - - if ( oc1_const ) - { - op1 = "z.c"; - --op2_slot; - if ( zc == ZIC_COND ) - branch_target += "2"; - } - else - { - op1 = "frame[z.v" + to_string(op1_slot) + "]"; - - if ( zc == ZIC_COND ) - { - if ( Arity() > 1 && ! oc2_const ) - branch_target += "3"; - else - branch_target += "2"; - } - } - - if ( oc2_const ) - op2 = "z.c"; - else - op2 = "frame[z.v" + to_string(op2_slot) + "]"; - - if ( zc == ZIC_FIELD ) - { - // Compute the slot holding the field offset. - - auto f = - // The first slots are taken up by the - // assignment slot and the operands ... - Arity() + 1 + - // ... and slots are numbered starting at 1. - +1; - - if ( oc1_const || oc2_const ) - // One of the operand slots won't be needed - // due to the presence of a constant. - // (It's never the case that both operands - // are constants - those instead get folded.) - --f; - - lhs = "DirectField(" + lhs + ".AsRecord(), z.v" + to_string(f) + ")"; - } - } - - vector eval_instances; - - for ( auto zt : expr_types ) - { - // Support for "op-type X" meaning "allow empty evaluation", - // as well as "evaluation is generic". - if ( zt == ZAM_TYPE_NONE && GetEval().empty() ) - continue; - - auto is_def = eval_set.count(zt) == 0; - string eval = is_def ? GetEval() : eval_set[zt]; - auto lhs_et = IsConditionalOp() ? ZAM_TYPE_INT : zt; - eval_instances.emplace_back(lhs_et, zt, zt, eval, is_def); - } - - if ( zc != ZIC_VEC ) - for ( const auto& em1 : eval_mixed_set ) - { - auto et1 = em1.first; - for ( const auto& em2 : em1.second ) - { - auto et2 = em2.first; - - // For the LHS, either its expression type is - // ignored, or if it's a conditional, so just - // note it for the latter. - auto lhs_et = ZAM_TYPE_INT; - eval_instances.emplace_back(lhs_et, et1, et2, em2.second, false); - } - } - - for ( auto& ei : eval_instances ) - { - op_types.clear(); - - auto lhs_accessor = ei.LHSAccessor(); - if ( HasExplicitResultType() ) - { - op_types.push_back(ZAM_TYPE_NONE); - lhs_accessor = ""; - } - else if ( zc == ZIC_FIELD ) - op_types.push_back(ZAM_TYPE_RECORD); - else if ( zc != ZIC_COND ) - op_types.push_back(ei.LHS_ET()); - - string lhs_ei = lhs; - if ( zc != ZIC_VEC ) - lhs_ei += lhs_accessor; - - op_types.push_back(ei.Op1_ET()); - if ( Arity() > 1 ) - op_types.push_back(ei.Op2_ET()); - - if ( zc == ZIC_FIELD ) - op_types.push_back(ZAM_TYPE_INT); - - else if ( zc == ZIC_COND ) - op_types.push_back(ZAM_TYPE_INT); - - else if ( zc == ZIC_VEC ) - { - // Above isn't applicable, since we use helper - // functions. - op_types.clear(); - op_types.push_back(ZAM_TYPE_VECTOR); - op_types.push_back(ZAM_TYPE_VECTOR); - - if ( Arity() > 1 ) - op_types.push_back(ZAM_TYPE_VECTOR); - } - - auto op1_ei = op1 + ei.Op1Accessor(zc == ZIC_VEC); - auto op2_ei = op2 + ei.Op2Accessor(zc == ZIC_VEC); - - auto eval = SkipWS(ei.Eval()); - - auto has_target = eval.find("$$") != string::npos; - - if ( zc == ZIC_VEC ) - { - const char* rhs; - if ( has_target ) - rhs = "\\$\\$ = ([^;\n]*)"; - else - rhs = "^[^;\n]*"; - - auto replacement = VecEvalRE(has_target); - - eval = regex_replace(eval, regex(rhs), replacement, std::regex_constants::match_not_null); - } - - auto is_none = ei.LHS_ET() == ZAM_TYPE_NONE; - auto is_default = ei.LHS_ET() == ZAM_TYPE_DEFAULT; +void ZAM_OpTemplate::InstantiateOp(const OCVec& oc, bool do_vec) { + auto method = MethodName(oc); - if ( ! is_none && ! is_default && find_type_info(ei.LHS_ET()).is_managed && - ! HasExplicitResultType() ) - { - auto pre = "auto hold_lhs = " + lhs; + InstantiateOp(method, oc, ZIC_REGULAR); - if ( zc == ZIC_VEC ) - // For vectors, we have to check for whether - // the previous value is present, or a hole. - pre += string(" ? ") + lhs + "->"; - else - pre += "."; - - pre += "ManagedVal()"; + if ( IncludesFieldOp() ) + InstantiateOp(method, oc, ZIC_FIELD); - if ( zc == ZIC_VEC ) - pre += " : nullptr"; - - pre += ";\n\t"; + if ( do_vec ) + InstantiateOp(method, oc, ZIC_VEC); - auto post = "\tUnref(hold_lhs);"; - - eval = pre + eval + post; - } + if ( IsConditionalOp() ) + InstantiateOp(method, oc, ZIC_COND); +} - eval = regex_replace(eval, regex("\\$1"), op1_ei); - eval = regex_replace(eval, regex("\\$2"), op2_ei); +void ZAM_OpTemplate::InstantiateOp(const string& orig_method, const OCVec& oc_orig, ZAM_InstClass zc) { + auto oc = oc_orig; + string suffix = ""; - string pre, post; + if ( zc == ZIC_FIELD ) { + // Make room for the offset. + oc.push_back(ZAM_OC_INT); + suffix = NoEval() ? "" : "_field"; + } - if ( HasPreCheck() ) - { - pre = "if ( " + GetPreCheck() + ")\n\t{\n\t" + - GetPreCheckAction() + "\n\t}\n\telse\n\t{\n\t"; - post = "\n\t}"; - } + else if ( zc == ZIC_COND ) { + // Remove the assignment and add in the branch. + oc.erase(oc.begin()); + oc.push_back(ZAM_OC_BRANCH); + suffix = "_cond"; + } - pre = regex_replace(pre, regex("\\$1"), op1_ei); - pre = regex_replace(pre, regex("\\$2"), op2_ei); + else if ( zc == ZIC_VEC ) { + // Don't generate versions of these for constant operands + // as those don't exist. + if ( int(oc.size()) != Arity() + 1 ) + Gripe("vector class/arity mismatch"); - if ( has_target ) - eval = regex_replace(eval, regex("\\$\\$"), lhs_ei); + if ( oc[1] == ZAM_OC_CONSTANT ) + return; + if ( Arity() > 1 && oc[2] == ZAM_OC_CONSTANT ) + return; - else if ( zc == ZIC_COND ) - { - // Aesthetics: get rid of trailing newlines. - eval = regex_replace(eval, regex("\n"), ""); + suffix = "_vec"; + } - eval = "if ( ! (" + eval + ") ) " + - "Branch(" + branch_target + ")"; - } + auto method = MethodName(oc); + + if ( ! IsInternalOp() ) + InstantiateMethod(method, suffix, oc, zc); - else if ( ! is_none && (ei.IsDefault() || IsConditionalOp()) ) - { - eval = lhs_ei + " = " + eval; + if ( IsAssignOp() ) + InstantiateAssignOp(oc, suffix); + else { + InstantiateEval(oc, suffix, zc); - // Ensure a single terminating semicolon. - eval = regex_replace(eval, regex(";*\n"), ";\n"); - } + if ( HasAssignmentLess() ) { + auto op_string = "_" + OpSuffix(oc); + auto op = g->GenOpCode(this, op_string); + GenAssignmentlessVersion(op); + } + } +} + +void ZAM_OpTemplate::GenAssignmentlessVersion(const string& op) { + EmitTo(AssignFlavor); + Emit("assignmentless_op[" + op + "] = " + AssignmentLessOp() + ";"); + Emit("assignmentless_op_class[" + op + "] = " + AssignmentLessOpClass() + ";"); +} - eval = pre + eval + post; +void ZAM_OpTemplate::InstantiateMethod(const string& m, const string& suffix, const OCVec& oc, ZAM_InstClass zc) { + if ( IsInternalOp() ) + return; - auto full_suffix = suffix + ei.OpMarker(); + auto decls = MethodDeclare(oc, zc); - GenEval(emit_target, oc_str, full_suffix, eval, zc); + EmitTo(MethodDecl); + Emit("const ZAMStmt " + m + suffix + "(" + decls + ");"); - if ( zc == ZIC_VEC ) - { - string dispatch_params = "frame[z.v1].AsVectorRef(), frame[z.v2].AsVector()"; + EmitTo(MethodDef); + Emit("const ZAMStmt ZAMCompiler::" + m + suffix + "(" + decls + ")"); + BeginBlock(); - if ( Arity() == 2 ) - dispatch_params += ", frame[z.v3].AsVector()"; + InstantiateMethodCore(oc, suffix, zc); - auto op_code = g->GenOpCode(this, "_" + oc_str + full_suffix); - auto dispatch = "vec_exec(" + op_code + ", Z_TYPE, " + dispatch_params + ", z);"; + if ( HasPostMethod() ) + Emit(GetPostMethod()); + + if ( ! HasCustomMethod() ) + Emit("return AddInst(z);"); + + EndBlock(); + NL(); +} + +void ZAM_OpTemplate::InstantiateMethodCore(const OCVec& oc, const string& suffix, ZAM_InstClass zc) { + if ( HasCustomMethod() ) { + Emit(GetCustomMethod()); + return; + } + + assert(! oc.empty()); + + string full_suffix = "_" + OpSuffix(oc) + suffix; + + Emit("ZInstI z;"); + + if ( oc[0] == ZAM_OC_AUX ) { + auto op = g->GenOpCode(this, full_suffix, zc); + Emit("z = ZInstI(" + op + ");"); + return; + } + + if ( oc[0] == ZAM_OC_NONE ) { + auto op = g->GenOpCode(this, full_suffix, zc); + Emit("z = GenInst(" + op + ");"); + return; + } + + if ( oc.size() > 1 && oc[1] == ZAM_OC_AUX ) { + auto op = g->GenOpCode(this, full_suffix, zc); + Emit("z = ZInstI(" + op + ", Frame1Slot(n, " + op + "));"); + return; + } + + ArgsManager args(oc, zc); + BuildInstruction(oc, args.Params(), full_suffix, zc); + + auto& tp = GetTypeParam(); + if ( tp ) + Emit("z.SetType(" + args.NthParam(*tp) + "->GetType());"); + + auto& tp2 = GetType2Param(); + if ( tp2 ) + Emit("z.SetType2(" + args.NthParam(*tp2) + "->GetType());"); +} + +void ZAM_OpTemplate::BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) { + auto op = g->GenOpCode(this, suffix, zc); + Emit("z = GenInst(" + op + ", " + params + ");"); +} + +static bool skippable_ot(ZAM_OperandClass oc) { + return oc == ZAM_OC_EVENT_HANDLER || oc == ZAM_OC_AUX || oc == ZAM_OC_LIST; +} + +string ZAM_OpTemplate::ExpandParams(const OCVec& oc, string eval, const vector& accessors) const { + auto have_target = eval.find("$$") != string::npos; + + auto fl = GetOp1Flavor(); + auto need_target = fl == "OP1_WRITE"; + + auto oc_size = oc.size(); + if ( oc_size > 0 ) { + auto oc0 = oc[0]; + + if ( oc0 == ZAM_OC_NONE || oc0 == ZAM_OC_AUX ) { + --oc_size; + need_target = false; + } + + else if ( raw_int_oc.count(oc0) > 0 ) + need_target = false; + } + + while ( oc_size > 0 && skippable_ot(oc[oc_size - 1]) ) + --oc_size; + + auto max_param = oc_size; + + if ( need_target && ! have_target ) + Gripe("eval missing $$:", eval); + + if ( have_target ) { + assert(max_param > 0); + --max_param; + } + + bool has_d1 = eval.find("$1") != string::npos; + bool has_d2 = eval.find("$2") != string::npos; + bool has_d3 = eval.find("$3") != string::npos; + bool has_d4 = eval.find("$4") != string::npos; + + switch ( max_param ) { + case 4: + if ( ! has_d4 ) + Gripe("eval missing $4", eval); + case 3: + if ( ! has_d3 ) + Gripe("eval missing $3", eval); + case 2: + if ( ! has_d2 ) + Gripe("eval missing $2", eval); + case 1: + if ( ! has_d1 ) + Gripe("eval missing $1", eval); + + case 0: break; + + default: Gripe("unexpected param size", to_string(max_param) + " - " + eval); break; + } + + switch ( max_param ) { + case 0: + if ( has_d1 ) + Gripe("extraneous $1 in eval", eval); + case 1: + if ( has_d2 ) + Gripe("extraneous $2 in eval", eval); + case 2: + if ( has_d3 ) + Gripe("extraneous $3 in eval", eval); + case 3: + if ( has_d4 ) + Gripe("extraneous $4 in eval", eval); + + case 4: break; + + default: Gripe("unexpected param size", to_string(max_param) + " - " + eval); break; + } + + int frame_slot = 0; + bool const_seen = false; + bool int_seen = false; + + for ( size_t i = 0; i < oc_size; ++i ) { + string op; + bool needs_accessor = true; + + switch ( oc[i] ) { + case ZAM_OC_VAR: + if ( int_seen ) + Gripe("'V' type specifier after 'i' specifier", eval); + op = "frame[z.v" + to_string(++frame_slot) + "]"; + break; + + case ZAM_OC_RECORD_FIELD: op = "frame[z.v" + to_string(++frame_slot) + "]"; break; + + case ZAM_OC_INT: + case ZAM_OC_BRANCH: + case ZAM_OC_GLOBAL: + case ZAM_OC_STEP_ITER: + case ZAM_OC_TBL_ITER: + op = "z.v" + to_string(++frame_slot); + int_seen = true; + needs_accessor = false; + + if ( oc[i] == ZAM_OC_BRANCH ) + op = "Branch(" + op + ")"; + else if ( oc[i] == ZAM_OC_STEP_ITER ) + op = "StepIter(" + op + ")"; + else if ( oc[i] == ZAM_OC_TBL_ITER ) + op = "TableIter(" + op + ")"; + break; + + case ZAM_OC_CONSTANT: + if ( const_seen ) + g->Gripe("double constant", eval.c_str()); + const_seen = true; + op = "z.c"; + break; + + default: Gripe("unexpected oc type", eval); break; + } + + if ( needs_accessor ) { + if ( ! accessors.empty() && ! accessors[i].empty() ) + op += "." + accessors[i]; + else if ( ! op_types.empty() && op_types[i] != ZAM_TYPE_NONE ) + op += "." + find_type_accessor(op_types[i], have_target && i == 0); + } + + else if ( ! op_types.empty() && oc[i] == ZAM_OC_INT ) { + if ( op_types[i] == ZAM_TYPE_UINT ) + op = "zeek_uint_t(" + op + ")"; + } + + string pat; + if ( i == 0 && have_target ) + pat = "\\$\\$"; + else + pat = "\\$" + to_string(have_target ? i : i + 1); + + auto orig_eval = eval; + eval = regex_replace(eval, regex(pat), op); + if ( orig_eval == eval ) + Gripe("no eval sub", pat + " - " + eval); + } + + return eval; +} + +void ZAM_OpTemplate::InstantiateEval(const OCVec& oc, const string& suffix, ZAM_InstClass zc) { + if ( NoEval() ) + return; + + auto eval = ExpandParams(oc, GetEval(), accessors); + + GenEval(Eval, OpSuffix(oc), suffix, eval, zc); +} + +void ZAM_OpTemplate::GenEval(EmitTarget et, const string& oc_str, const string& op_suffix, const string& eval, + ZAM_InstClass zc) { + auto op_code = g->GenOpCode(this, "_" + oc_str + op_suffix, zc); + + if ( et == Eval ) { + auto oc_str_copy = oc_str; + if ( zc == ZIC_COND ) { + auto n = oc_str_copy.size(); + + if ( oc_str_copy[n - 1] == 'V' ) + oc_str_copy[n - 1] = 'i'; + + else if ( oc_str_copy[n - 1] == 'C' ) { + if ( oc_str_copy[n - 2] != 'V' ) + Gripe("bad operator class"); + + oc_str_copy[n - 2] = 'C'; + oc_str_copy[n - 1] = 'i'; + } + } + + GenDesc(op_code, oc_str_copy, eval); + } + + EmitTo(et); + Emit("case " + op_code + ":"); + BeginBlock(); + Emit(eval); + EndBlock(); + EmitUp("break;"); + NL(); +} + +void ZAM_OpTemplate::GenDesc(const string& op_code, const string& oc_str, const string& eval) { + StartDesc(op_code, oc_str); + Emit(eval); + EndDesc(); +} + +void ZAM_OpTemplate::StartDesc(const string& op_code, const string& oc_str) { + EmitTo(OpDesc); + Emit("{ " + op_code + ","); + BeginBlock(); + Emit("\"" + oc_str + "\","); + + if ( op_types.empty() ) + Emit("\"\","); + else { + string ots; + for ( auto ot : op_types ) { + if ( ot == ZAM_TYPE_DEFAULT ) + ots += "X"; + else + ots += expr_name_types[ot]; + } + + Emit("\"" + ots + "\", "); + } + + StartString(); +} + +void ZAM_OpTemplate::EndDesc() { + EndString(); + EndBlock(); + Emit("},"); +} + +void ZAM_OpTemplate::InstantiateAssignOp(const OCVec& oc, const string& suffix) { + // First, create a generic version of the operand, which the + // ZAM compiler uses to find specific-flavored versions. + auto oc_str = OpSuffix(oc); + auto op_string = "_" + oc_str; + auto generic_op = g->GenOpCode(this, op_string); + auto flavor_ind = "assignment_flavor[" + generic_op + "]"; + + EmitTo(AssignFlavor); + Emit(flavor_ind + " = empty_map;"); + + auto eval = GetEval(); + auto v = GetAssignVal(); + + for ( auto& ti : ZAM_type_info ) { + auto op = g->GenOpCode(this, op_string + "_" + ti.suffix); + + if ( IsInternalOp() ) { + EmitTo(AssignFlavor); + Emit(flavor_ind + "[" + ti.tag + "] = " + op + ";"); + + if ( HasAssignmentLess() ) + GenAssignmentlessVersion(op); + } + + StartDesc(op, oc_str); + GenAssignOpCore(oc, eval, ti.accessor, ti.is_managed); + if ( ! post_eval.empty() ) + Emit(post_eval); + EndDesc(); + + EmitTo(Eval); + Emit("case " + op + ":"); + BeginBlock(); + GenAssignOpCore(oc, eval, ti.accessor, ti.is_managed); + if ( ! post_eval.empty() ) + Emit(post_eval); + Emit("break;"); + EndBlock(); + } + + post_eval.clear(); +} + +void ZAM_OpTemplate::GenAssignOpCore(const OCVec& oc, const string& eval, const string& accessor, bool is_managed) { + if ( HasAssignVal() ) { + GenAssignOpValCore(oc, eval, accessor, is_managed); + return; + } + + if ( ! eval.empty() ) + g->Gripe("assign-op should not have an \"eval\"", eval); + + auto lhs_field = (oc[0] == ZAM_OC_ASSIGN_FIELD); + auto rhs_field = lhs_field && oc.size() > 3 && (oc[3] == ZAM_OC_INT); + auto constant_op = (oc[1] == ZAM_OC_CONSTANT); + + string rhs = constant_op ? "z.c" : "frame[z.v2]"; + + auto acc = ".As" + accessor + "()"; + + if ( accessor == "Any" && constant_op && ! rhs_field ) { + // "any_val = constant" or "x$any_val = constant". + // + // These require special-casing, because to avoid going + // through a CoerceToAny operation, we allow expressing + // these directly. They don't fit with the usual assignment + // paradigm since the RHS differs in type from the LHS. + Emit("auto v = z.c.ToVal(Z_TYPE);"); + + if ( lhs_field ) { + Emit("auto r = frame[z.v1].AsRecord();"); + Emit("auto& f = DirectField(r, z.v2);"); + } + else + Emit("auto& f = frame[z.v1];"); + + Emit("zeek::Unref(f.ManagedVal());"); + Emit("f = ZVal(v.release());"); + } + + else if ( rhs_field ) { + // The following is counter-intuitive, but comes from the + // fact that we build out the instruction parameters as + // an echo of the method parameters, and for this case that + // means that the RHS field offset comes *before*, not after, + // the LHS field offset. + auto lhs_offset = constant_op ? 3 : 4; + auto rhs_offset = lhs_offset - 1; + + Emit("auto v = DirectOptField(" + rhs + ".AsRecord(), z.v" + to_string(rhs_offset) + + "); // note, RHS field before LHS field\n"); + + Emit("if ( ! v )"); + BeginBlock(); + Emit("ZAM_run_time_error(Z_LOC, \"field value missing\");"); + EndBlock(); + + Emit("else"); + BeginBlock(); + auto slot = "z.v" + to_string(lhs_offset); + Emit("auto r = frame[z.v1].AsRecord();"); + Emit("auto& f = DirectField(r, " + slot + "); // note, LHS field after RHS field\n"); + + if ( is_managed ) { + Emit("zeek::Ref((*v)" + acc + ");"); + Emit("zeek::Unref(f.ManagedVal());"); + } + + Emit("f = *v;"); + + if ( lhs_field ) + Emit("r->Modified();"); + + EndBlock(); + } + + else { + if ( is_managed ) + Emit("zeek::Ref(" + rhs + acc + ");"); + + if ( lhs_field ) { + auto lhs_offset = constant_op ? 2 : 3; + auto slot = "z.v" + to_string(lhs_offset); + Emit("auto r = frame[z.v1].AsRecord();"); + Emit("auto& f = DirectField(r, " + slot + ");"); + + if ( is_managed ) + Emit("zeek::Unref(f.ManagedVal());"); + + Emit("f = " + rhs + ";"); + Emit("r->Modified();"); + } + + else { + if ( is_managed ) + Emit("zeek::Unref(frame[z.v1].ManagedVal());"); + + Emit("frame[z.v1] = ZVal(" + rhs + acc + ");"); + } + } +} + +void ZAM_OpTemplate::GenAssignOpValCore(const OCVec& oc, const string& orig_eval, const string& accessor, + bool is_managed) { + auto v = GetAssignVal(); + + // Maps Zeek types to how to get the underlying value from a ValPtr. + static unordered_map val_accessors = { + {"Addr", "->AsAddrVal()"}, {"Any", ".get()"}, + {"Count", "->AsCount()"}, {"Double", "->AsDouble()"}, + {"Int", "->AsInt()"}, {"Pattern", "->AsPatternVal()"}, + {"String", "->AsStringVal()"}, {"SubNet", "->AsSubNetVal()"}, + {"Table", "->AsTableVal()"}, {"Vector", "->AsVectorVal()"}, + {"File", "->AsFile()"}, {"Func", "->AsFunc()"}, + {"List", "->AsListVal()"}, {"Opaque", "->AsOpaqueVal()"}, + {"Record", "->AsRecordVal()"}, {"Type", "->AsTypeVal()"}, + }; + + auto val_accessor = val_accessors[accessor]; + + string rhs; + if ( IsInternalOp() ) + rhs = v + val_accessor; + else + rhs = v + ".As" + accessor + "()"; + + auto eval = orig_eval; + + if ( is_managed ) { + eval += string("auto rhs = ") + rhs + ";\n"; + eval += "zeek::Ref(rhs);\n"; + eval += "Unref($$.ManagedVal());\n"; + eval += "$$ = ZVal(rhs);\n"; + } + else + eval += "$$ = ZVal(" + rhs + ");\n"; + + Emit(ExpandParams(oc, eval)); +} + +string ZAM_OpTemplate::MethodName(const OCVec& oc) const { return base_name + OpSuffix(oc); } + +string ZAM_OpTemplate::MethodDeclare(const OCVec& oc, ZAM_InstClass zc) { + ArgsManager args(oc, zc); + return args.Decls(); +} - GenEval(Eval, oc_str, full_suffix, dispatch, zc); - } - } - } +string ZAM_OpTemplate::OpSuffix(const OCVec& oc) const { + string os; + for ( auto& o : oc ) + os += oc_to_char[o]; + return os; +} -void ZAM_UnaryExprOpTemplate::Parse(const string& attr, const string& line, const Words& words) - { - if ( attr == "no-const" ) - { - if ( words.size() != 1 ) - g->Gripe("extraneous argument to no-const", line); +string ZAM_OpTemplate::SkipWS(const string& s) const { + auto sp = s.c_str(); + while ( *sp && isspace(*sp) ) + ++sp; - SetNoConst(); - } + return sp; +} - else - ZAM_ExprOpTemplate::Parse(attr, line, words); - } +void ZAM_OpTemplate::Emit(const string& s) { g->Emit(curr_et, s); } -void ZAM_UnaryExprOpTemplate::Instantiate() - { - UnaryInstantiate(); +void ZAM_OpTemplate::EmitNoNL(const string& s) { + g->SetNoNL(true); + Emit(s); + g->SetNoNL(false); +} - OCVec ocs = {ZAM_OC_VAR, ZAM_OC_CONSTANT}; +void ZAM_OpTemplate::IndentUp() { g->IndentUp(); } - if ( ! NoConst() ) - InstantiateC1(ocs, 1); +void ZAM_OpTemplate::IndentDown() { g->IndentDown(); } + +void ZAM_OpTemplate::StartString() { g->StartString(); } - ocs[1] = ZAM_OC_VAR; - InstantiateV(ocs); - } +void ZAM_OpTemplate::EndString() { g->EndString(); } + +void ZAM_OpTemplate::Gripe(const char* msg) const { g->Gripe(msg, op_loc); } -void ZAM_UnaryExprOpTemplate::BuildInstruction(const OCVec& oc, - const string& params, const string& suffix, - ZAM_InstClass zc) - { - const auto& ets = ExprTypes(); +void ZAM_OpTemplate::Gripe(string msg, string addl) const { + auto full_msg = msg + ": " + addl; + Gripe(full_msg.c_str()); +} - if ( ets.size() == 1 && ets.count(ZAM_TYPE_NONE) == 1 ) - { - ZAM_ExprOpTemplate::BuildInstruction(oc, params, suffix, zc); - return; - } +void ZAM_UnaryOpTemplate::Instantiate() { UnaryInstantiate(); } - auto constant_op = oc[1] == ZAM_OC_CONSTANT; - string type_src = constant_op ? "c" : "n2"; - - if ( oc[0] == ZAM_OC_ASSIGN_FIELD ) - { - type_src = constant_op ? "n" : "n1"; - Emit("auto " + type_src + " = flhs->GetOp1()->AsNameExpr();"); - Emit("const auto& t = flhs->GetType();"); - } - - else - { - if ( IsAssignOp() ) - type_src = constant_op ? "n" : "n1"; - - auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; - Emit("const auto& t = " + type_src + "->GetType()" + type_suffix); - } - - BuildInstructionCore(params, suffix, zc); - - if ( IsAssignOp() && IsFieldOp() ) - // These can't take the type from the LHS variable, since - // that's the enclosing record and not the field within it. - Emit("z.SetType(t);"); - - else if ( zc == ZIC_VEC ) - { - if ( constant_op ) - Emit("z.SetType(n->GetType());"); - else - Emit("z.SetType(n1->GetType());"); - } - } +void ZAM_DirectUnaryOpTemplate::Instantiate() { + EmitTo(DirectDef); + Emit("case EXPR_" + cname + ":\treturn " + direct + "(lhs, rhs);"); +} + +ZAM_ExprOpTemplate::ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, std::move(_base_name)) { + static bool did_map_init = false; + + if ( ! did_map_init ) { // Create the inverse mapping. + for ( auto& tn : type_names ) + expr_name_types[tn.second] = tn.first; + + did_map_init = true; + } +} + +void ZAM_ExprOpTemplate::Parse(const string& attr, const string& line, const Words& words) { + if ( attr == "op-type" ) { + if ( words.size() == 1 ) + g->Gripe("op-type needs arguments", line); + + for ( auto i = 1U; i < words.size(); ++i ) { + auto& w_i = words[i]; + if ( w_i.size() != 1 ) + g->Gripe("bad op-type argument", w_i); + + auto et_c = w_i.c_str()[0]; + if ( type_names.count(et_c) == 0 ) + g->Gripe("bad op-type argument", w_i); + + AddExprType(type_names[et_c]); + } + } + + else if ( attr == "includes-field-op" ) { + if ( words.size() != 1 ) + g->Gripe("includes-field-op does not take any arguments", line); + + SetIncludesFieldOp(); + } + + else if ( attr == "eval-type" ) { + if ( words.size() < 3 ) + g->Gripe("eval-type needs type and evaluation", line); + + auto& type = words[1]; + if ( type.size() != 1 ) + g->Gripe("bad eval-type type", type); + + auto type_c = type.c_str()[0]; + if ( type_names.count(type_c) == 0 ) + g->Gripe("bad eval-type type", type); + + auto zt = type_names[type_c]; + + if ( expr_types.count(zt) == 0 ) + g->Gripe("eval-type type not present in eval-type", type); + + auto eval = g->SkipWords(line, 2); + eval += GatherEval(); + AddEvalSet(zt, eval); + } + + else if ( attr == "eval-mixed" ) { + if ( words.size() < 4 ) + g->Gripe("eval-mixed needs types and evaluation", line); + + auto& type1 = words[1]; + auto& type2 = words[2]; + if ( type1.size() != 1 || type2.size() != 1 ) + g->Gripe("bad eval-mixed types", line); + + auto type_c1 = type1.c_str()[0]; + auto type_c2 = type2.c_str()[0]; + if ( type_names.count(type_c1) == 0 || type_names.count(type_c2) == 0 ) + g->Gripe("bad eval-mixed types", line); + + auto et1 = type_names[type_c1]; + auto et2 = type_names[type_c2]; + + auto eval = g->SkipWords(line, 3); + eval += GatherEval(); + AddEvalSet(et1, et2, eval); + } + + else if ( attr == "precheck" ) { + if ( words.size() < 2 ) + g->Gripe("precheck needs evaluation", line); + + auto eval = g->SkipWords(line, 1); + eval += GatherEval(); + eval.pop_back(); + + SetPreCheck(eval); + } + + else if ( attr == "precheck-action" ) { + if ( words.size() < 2 ) + g->Gripe("precheck-action needs evaluation", line); + + auto eval = g->SkipWords(line, 1); + eval += GatherEval(); + eval.pop_back(); + + SetPreCheckAction(eval); + } + + else if ( attr == "explicit-result-type" ) { + if ( words.size() != 1 ) + g->Gripe("extraneous argument to explicit-result-type", line); + SetHasExplicitResultType(); + } + + else + // Not an attribute specific to expr-op's. + ZAM_OpTemplate::Parse(attr, line, words); +} + +void ZAM_ExprOpTemplate::Instantiate() { + if ( ! op_classes_vec.empty() ) + Gripe("expressions cannot use \"classes\""); + + InstantiateOp(OperandClasses(), IncludesVectorOp()); + + if ( op_classes.size() > 1 && op_classes[1] == ZAM_OC_CONSTANT ) + InstantiateC1(op_classes, op_classes.size() - 1); + if ( op_classes.size() > 2 && op_classes[2] == ZAM_OC_CONSTANT ) + InstantiateC2(op_classes, op_classes.size() - 1); + if ( op_classes.size() > 3 && op_classes[3] == ZAM_OC_CONSTANT ) + InstantiateC3(op_classes); + + bool all_var = true; + for ( auto i = 1U; i < op_classes.size(); ++i ) + if ( op_classes[i] != ZAM_OC_VAR ) + all_var = false; + + if ( all_var ) + InstantiateV(op_classes); + + if ( op_classes.size() == 3 && op_classes[1] == ZAM_OC_RECORD_FIELD && op_classes[2] == ZAM_OC_INT ) + InstantiateV(op_classes); +} + +void ZAM_ExprOpTemplate::InstantiateC1(const OCVec& ocs, size_t arity) { + string args = "lhs, r1->AsConstExpr()"; + + if ( arity == 1 && ocs[0] == ZAM_OC_RECORD_FIELD ) + args += ", rhs->AsFieldExpr()->Field()"; + + else if ( arity > 1 ) { + args += ", "; + + if ( ocs[2] == ZAM_OC_RECORD_FIELD ) + args += "rhs->AsFieldExpr()->Field()"; + else + args += "r2->AsNameExpr()"; + } + + auto m = MethodName(ocs); + + EmitTo(C1Def); + + EmitNoNL("case EXPR_" + cname + ":"); + + EmitUp("return " + m + "(" + args + ");"); + + if ( IncludesFieldOp() ) { + EmitTo(C1FieldDef); + Emit("case EXPR_" + cname + ":\treturn " + m + "i_field(" + args + ", field);"); + } +} + +void ZAM_ExprOpTemplate::InstantiateC2(const OCVec& ocs, size_t arity) { + string args = "lhs, r1->AsNameExpr(), r2->AsConstExpr()"; + + if ( arity == 3 ) + args += ", r3->AsNameExpr()"; + + auto method = MethodName(ocs); + auto m = method.c_str(); + + EmitTo(C2Def); + Emit("case EXPR_" + cname + ":\treturn " + m + "(" + args + ");"); + + if ( IncludesFieldOp() ) { + EmitTo(C2FieldDef); + Emit("case EXPR_" + cname + ":\treturn " + m + "i_field(" + args + ", field);"); + } +} + +void ZAM_ExprOpTemplate::InstantiateC3(const OCVec& ocs) { + EmitTo(C3Def); + Emit("case EXPR_" + cname + ":\treturn " + MethodName(ocs) + + "(lhs, r1->AsNameExpr(), r2->AsNameExpr(), r3->AsConstExpr());"); +} + +void ZAM_ExprOpTemplate::InstantiateV(const OCVec& ocs) { + auto m = MethodName(ocs); + + string args = "lhs, r1->AsNameExpr()"; + + if ( ocs.size() >= 3 ) { + if ( ocs[2] == ZAM_OC_INT ) { + string acc_flav = IncludesFieldOp() ? "Has" : ""; + args += ", rhs->As" + acc_flav + "FieldExpr()->Field()"; + } + else + args += ", r2->AsNameExpr()"; + + if ( ocs.size() == 4 ) + args += ", r3->AsNameExpr()"; + } + + EmitTo(VDef); + EmitNoNL("case EXPR_" + cname + ":"); + + if ( IncludesVectorOp() ) + DoVectorCase(m, args); + else + EmitUp("return " + m + "(" + args + ");"); + + if ( IncludesFieldOp() ) { + string suffix = NoEval() ? "" : "_field"; + EmitTo(VFieldDef); + Emit("case EXPR_" + cname + ":\treturn " + m + "i" + suffix + "(" + args + ", field);"); + } +} + +void ZAM_ExprOpTemplate::DoVectorCase(const string& m, const string& args) { + NL(); + IndentUp(); + Emit("if ( rt->Tag() == TYPE_VECTOR )"); + EmitUp("return " + m + "_vec(" + args + ");"); + Emit("else"); + EmitUp("return " + m + "(" + args + ");"); + IndentDown(); +} + +void ZAM_ExprOpTemplate::BuildInstructionCore(const string& params, const string& suffix, ZAM_InstClass zc) { + Emit("auto tag1 = t->Tag();"); + Emit("auto i_t1 = t->InternalType();"); + + int ncases = 0; + + if ( zc != ZIC_VEC ) + for ( auto& [et1, et2_map] : eval_mixed_set ) + for ( auto& [et2, eval] : et2_map ) + GenMethodTest(et1, et2, params, suffix, ++ncases > 1, zc); + + bool do_default = false; + + for ( auto zt : ExprTypes() ) { + if ( zt == ZAM_TYPE_DEFAULT ) + do_default = true; + else if ( zt == ZAM_TYPE_NONE ) + continue; + else + GenMethodTest(zt, zt, params, suffix, ++ncases > 1, zc); + } + + Emit("else"); + + if ( do_default ) { + auto op = g->GenOpCode(this, suffix, zc); + EmitUp("z = GenInst(" + op + ", " + params + ");"); + } + + else + EmitUp("reporter->InternalError(\"bad tag when generating method core\");"); +} + +void ZAM_ExprOpTemplate::GenMethodTest(ZAM_Type et1, ZAM_Type et2, const string& params, const string& suffix, + bool do_else, ZAM_InstClass zc) { + // Maps ZAM_Type's to the information needed (variable name, + // constant to compare it against) to identify using an "if" test + // that a given AST Expr node employs the given type of operand. + static map> if_tests = { + {ZAM_TYPE_ADDR, {"i_t", "TYPE_INTERNAL_ADDR"}}, + {ZAM_TYPE_ANY, {"tag", "TYPE_ANY"}}, + {ZAM_TYPE_DOUBLE, {"i_t", "TYPE_INTERNAL_DOUBLE"}}, + {ZAM_TYPE_FILE, {"tag", "TYPE_FILE"}}, + {ZAM_TYPE_FUNC, {"tag", "TYPE_FUNC"}}, + {ZAM_TYPE_INT, {"i_t", "TYPE_INTERNAL_INT"}}, + {ZAM_TYPE_LIST, {"tag", "TYPE_LIST"}}, + {ZAM_TYPE_OPAQUE, {"tag", "TYPE_OPAQUE"}}, + {ZAM_TYPE_PATTERN, {"tag", "TYPE_PATTERN"}}, + {ZAM_TYPE_RECORD, {"tag", "TYPE_RECORD"}}, + {ZAM_TYPE_STRING, {"i_t", "TYPE_INTERNAL_STRING"}}, + {ZAM_TYPE_SUBNET, {"i_t", "TYPE_INTERNAL_SUBNET"}}, + {ZAM_TYPE_TABLE, {"tag", "TYPE_TABLE"}}, + {ZAM_TYPE_TYPE, {"tag", "TYPE_TYPE"}}, + {ZAM_TYPE_UINT, {"i_t", "TYPE_INTERNAL_UNSIGNED"}}, + {ZAM_TYPE_VECTOR, {"tag", "TYPE_VECTOR"}}, + }; + + if ( if_tests.count(et1) == 0 || if_tests.count(et2) == 0 ) + Gripe("bad op-type"); + + auto if_test1 = if_tests[et1]; + auto if_var1 = if_test1.first + "1"; + auto if_val1 = if_test1.second; + + string test = if_var1 + " == " + if_val1; + + if ( Arity() > 1 ) { + auto if_test2 = if_tests[et2]; + auto if_var2 = if_test2.first + "2"; + auto if_val2 = if_test2.second; + test = test + " && " + if_var2 + " == " + if_val2; + } + + test = "if ( " + test + " )"; + if ( do_else ) + test = "else " + test; + + Emit(test); + + auto op_suffix = suffix + "_" + expr_name_types[et1]; + if ( et2 != et1 ) + op_suffix += expr_name_types[et2]; + + auto op = g->GenOpCode(this, op_suffix, zc); + EmitUp("z = GenInst(" + op + ", " + params + ");"); +} + +EvalInstance::EvalInstance(ZAM_Type _lhs_et, ZAM_Type _op1_et, ZAM_Type _op2_et, string _eval, bool _is_def) { + lhs_et = _lhs_et; + op1_et = _op1_et; + op2_et = _op2_et; + eval = std::move(_eval); + is_def = _is_def; +} + +string EvalInstance::LHSAccessor(bool is_ptr) const { + if ( lhs_et == ZAM_TYPE_NONE || lhs_et == ZAM_TYPE_DEFAULT ) + return ""; + + string deref = is_ptr ? "->" : "."; + string acc = find_type_accessor(lhs_et, true); + + return deref + acc; +} + +string EvalInstance::Accessor(ZAM_Type zt, bool is_ptr) const { + if ( zt == ZAM_TYPE_NONE || zt == ZAM_TYPE_DEFAULT ) + return ""; + + string deref = is_ptr ? "->" : "."; + return deref + "As" + find_type_info(zt).accessor + "()"; +} + +string EvalInstance::OpMarker() const { + if ( op1_et == ZAM_TYPE_DEFAULT || op1_et == ZAM_TYPE_NONE ) + return ""; + + if ( op1_et == op2_et ) + return "_" + find_type_info(op1_et).suffix; + + return "_" + find_type_info(op1_et).suffix + find_type_info(op2_et).suffix; +} + +void ZAM_ExprOpTemplate::InstantiateEval(const OCVec& oc_orig, const string& suffix, ZAM_InstClass zc) { + if ( (HasPreCheck() || HasPreCheckAction()) && (! HasPreCheck() || ! HasPreCheckAction()) ) + Gripe("precheck and precheck-action must be used together"); + + auto oc = oc_orig; + + if ( expr_types.empty() ) { + // No operand types to expand over. This happens for + // some "non-uniform" operations. + ZAM_OpTemplate::InstantiateEval(oc, suffix, zc); + return; + } + + auto oc_str = OpSuffix(oc); + + // Some of these might not wind up being used, but no harm in + // initializing them in case they are. + string lhs, op1, op2; + string branch_target = "z.v"; + + EmitTarget emit_target = Eval; + + if ( zc == ZIC_VEC ) { + lhs = "vec1[i]"; + op1 = "vec2[i]"; + op2 = "vec3[i]"; + + emit_target = Arity() == 1 ? Vec1Eval : Vec2Eval; + } + + else { + lhs = "frame[z.v1]"; + + // First compute the offsets into oc for the operands. + auto op1_offset = zc == ZIC_COND ? 0 : 1; + bool oc1_const = oc[op1_offset] == ZAM_OC_CONSTANT; + bool oc2_const = Arity() > 1 && oc[op1_offset + 1] == ZAM_OC_CONSTANT; + + // Now the frame slots. + auto op1_slot = op1_offset + 1; + auto op2_slot = op1_slot + 1; + + if ( oc1_const ) { + op1 = "z.c"; + --op2_slot; + if ( zc == ZIC_COND ) + branch_target += "2"; + } + else { + op1 = "frame[z.v" + to_string(op1_slot) + "]"; + + if ( zc == ZIC_COND ) { + if ( Arity() > 1 && ! oc2_const ) + branch_target += "3"; + else + branch_target += "2"; + } + } + + if ( oc2_const ) + op2 = "z.c"; + else + op2 = "frame[z.v" + to_string(op2_slot) + "]"; + + if ( zc == ZIC_FIELD ) { + // Compute the slot holding the field offset. + + auto f = + // The first slots are taken up by the + // assignment slot and the operands ... + Arity() + 1 + + // ... and slots are numbered starting at 1. + +1; + + if ( oc1_const || oc2_const ) + // One of the operand slots won't be needed + // due to the presence of a constant. + // (It's never the case that both operands + // are constants - those instead get folded.) + --f; + + lhs = "DirectField(" + lhs + ".AsRecord(), z.v" + to_string(f) + ")"; + } + } + + vector eval_instances; + + for ( auto zt : expr_types ) { + // Support for "op-type X" meaning "allow empty evaluation", + // as well as "evaluation is generic". + if ( zt == ZAM_TYPE_NONE && GetEval().empty() ) + continue; + + auto is_def = eval_set.count(zt) == 0; + string eval = is_def ? GetEval() : eval_set[zt]; + auto lhs_et = IsConditionalOp() ? ZAM_TYPE_INT : zt; + eval_instances.emplace_back(lhs_et, zt, zt, eval, is_def); + } + + if ( zc != ZIC_VEC ) + for ( const auto& em1 : eval_mixed_set ) { + auto et1 = em1.first; + for ( const auto& em2 : em1.second ) { + auto et2 = em2.first; + + // For the LHS, either its expression type is + // ignored, or if it's a conditional, so just + // note it for the latter. + auto lhs_et = ZAM_TYPE_INT; + eval_instances.emplace_back(lhs_et, et1, et2, em2.second, false); + } + } + + for ( auto& ei : eval_instances ) { + op_types.clear(); + + auto lhs_accessor = ei.LHSAccessor(); + if ( HasExplicitResultType() ) { + op_types.push_back(ZAM_TYPE_NONE); + lhs_accessor = ""; + } + else if ( zc == ZIC_FIELD ) + op_types.push_back(ZAM_TYPE_RECORD); + else if ( zc != ZIC_COND ) + op_types.push_back(ei.LHS_ET()); + + string lhs_ei = lhs; + if ( zc != ZIC_VEC ) + lhs_ei += lhs_accessor; + + op_types.push_back(ei.Op1_ET()); + if ( Arity() > 1 ) + op_types.push_back(ei.Op2_ET()); + + if ( zc == ZIC_FIELD ) + op_types.push_back(ZAM_TYPE_INT); + + else if ( zc == ZIC_COND ) + op_types.push_back(ZAM_TYPE_INT); + + else if ( zc == ZIC_VEC ) { + // Above isn't applicable, since we use helper + // functions. + op_types.clear(); + op_types.push_back(ZAM_TYPE_VECTOR); + op_types.push_back(ZAM_TYPE_VECTOR); + + if ( Arity() > 1 ) + op_types.push_back(ZAM_TYPE_VECTOR); + } + + auto op1_ei = op1 + ei.Op1Accessor(zc == ZIC_VEC); + auto op2_ei = op2 + ei.Op2Accessor(zc == ZIC_VEC); + + auto eval = SkipWS(ei.Eval()); + + auto has_target = eval.find("$$") != string::npos; + + if ( zc == ZIC_VEC ) { + const char* rhs; + if ( has_target ) + rhs = "\\$\\$ = ([^;\n]*)"; + else + rhs = "^[^;\n]*"; + + auto replacement = VecEvalRE(has_target); + + eval = regex_replace(eval, regex(rhs), replacement, std::regex_constants::match_not_null); + } + + auto is_none = ei.LHS_ET() == ZAM_TYPE_NONE; + auto is_default = ei.LHS_ET() == ZAM_TYPE_DEFAULT; + + if ( ! is_none && ! is_default && find_type_info(ei.LHS_ET()).is_managed && ! HasExplicitResultType() ) { + auto pre = "auto hold_lhs = " + lhs; + + if ( zc == ZIC_VEC ) + // For vectors, we have to check for whether + // the previous value is present, or a hole. + pre += string(" ? ") + lhs + "->"; + else + pre += "."; + + pre += "ManagedVal()"; + + if ( zc == ZIC_VEC ) + pre += " : nullptr"; + + pre += ";\n\t"; + + auto post = "\tUnref(hold_lhs);"; + + eval = pre + eval + post; + } + + eval = regex_replace(eval, regex("\\$1"), op1_ei); + eval = regex_replace(eval, regex("\\$2"), op2_ei); + + string pre, post; + + if ( HasPreCheck() ) { + pre = "if ( " + GetPreCheck() + ")\n\t{\n\t" + GetPreCheckAction() + "\n\t}\n\telse\n\t{\n\t"; + post = "\n\t}"; + } + + pre = regex_replace(pre, regex("\\$1"), op1_ei); + pre = regex_replace(pre, regex("\\$2"), op2_ei); + + if ( has_target ) + eval = regex_replace(eval, regex("\\$\\$"), lhs_ei); + + else if ( zc == ZIC_COND ) { + // Aesthetics: get rid of trailing newlines. + eval = regex_replace(eval, regex("\n"), ""); + + eval = "if ( ! (" + eval + ") ) " + "Branch(" + branch_target + ")"; + } + + else if ( ! is_none && (ei.IsDefault() || IsConditionalOp()) ) { + eval = lhs_ei + " = " + eval; + + // Ensure a single terminating semicolon. + eval = regex_replace(eval, regex(";*\n"), ";\n"); + } + + eval = pre + eval + post; + + auto full_suffix = suffix + ei.OpMarker(); + + GenEval(emit_target, oc_str, full_suffix, eval, zc); + + if ( zc == ZIC_VEC ) { + string dispatch_params = "frame[z.v1].AsVectorRef(), frame[z.v2].AsVector()"; + + if ( Arity() == 2 ) + dispatch_params += ", frame[z.v3].AsVector()"; + + auto op_code = g->GenOpCode(this, "_" + oc_str + full_suffix); + auto dispatch = "vec_exec(" + op_code + ", Z_TYPE, " + dispatch_params + ", z);"; + + GenEval(Eval, oc_str, full_suffix, dispatch, zc); + } + } +} + +void ZAM_UnaryExprOpTemplate::Parse(const string& attr, const string& line, const Words& words) { + if ( attr == "no-const" ) { + if ( words.size() != 1 ) + g->Gripe("extraneous argument to no-const", line); + + SetNoConst(); + } + + else + ZAM_ExprOpTemplate::Parse(attr, line, words); +} + +void ZAM_UnaryExprOpTemplate::Instantiate() { + UnaryInstantiate(); + + OCVec ocs = {ZAM_OC_VAR, ZAM_OC_CONSTANT}; + + if ( ! NoConst() ) + InstantiateC1(ocs, 1); + + ocs[1] = ZAM_OC_VAR; + InstantiateV(ocs); +} + +void ZAM_UnaryExprOpTemplate::BuildInstruction(const OCVec& oc, const string& params, const string& suffix, + ZAM_InstClass zc) { + const auto& ets = ExprTypes(); + + if ( ets.size() == 1 && ets.count(ZAM_TYPE_NONE) == 1 ) { + ZAM_ExprOpTemplate::BuildInstruction(oc, params, suffix, zc); + return; + } + + auto constant_op = oc[1] == ZAM_OC_CONSTANT; + string type_src = constant_op ? "c" : "n2"; + + if ( oc[0] == ZAM_OC_ASSIGN_FIELD ) { + type_src = constant_op ? "n" : "n1"; + Emit("auto " + type_src + " = flhs->GetOp1()->AsNameExpr();"); + Emit("const auto& t = flhs->GetType();"); + } + + else { + if ( IsAssignOp() ) + type_src = constant_op ? "n" : "n1"; + + auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; + Emit("const auto& t = " + type_src + "->GetType()" + type_suffix); + } + + BuildInstructionCore(params, suffix, zc); + + if ( IsAssignOp() && IsFieldOp() ) + // These can't take the type from the LHS variable, since + // that's the enclosing record and not the field within it. + Emit("z.SetType(t);"); + + else if ( zc == ZIC_VEC ) { + if ( constant_op ) + Emit("z.SetType(n->GetType());"); + else + Emit("z.SetType(n1->GetType());"); + } +} ZAM_AssignOpTemplate::ZAM_AssignOpTemplate(ZAMGen* _g, string _base_name) - : ZAM_UnaryExprOpTemplate(_g, std::move(_base_name)) - { - // Assignments apply to every valid form of ExprType. - for ( auto& etn : type_names ) - { - auto zt = etn.second; - if ( zt != ZAM_TYPE_NONE && zt != ZAM_TYPE_DEFAULT ) - AddExprType(zt); - } - } - -void ZAM_AssignOpTemplate::Parse(const string& attr, const string& line, const Words& words) - { - if ( attr == "field-op" ) - { - if ( words.size() != 1 ) - g->Gripe("field-op does not take any arguments", line); - - SetFieldOp(); - } - - else - ZAM_OpTemplate::Parse(attr, line, words); - } - -void ZAM_AssignOpTemplate::Instantiate() - { - if ( op_classes.size() != 1 ) - Gripe("operation needs precisely one \"type\""); - if ( ! op_classes_vec.empty() ) - Gripe("operation cannot use \"classes\""); - - OCVec ocs; - ocs.push_back(op_classes[0]); - - // Build constant/variable versions ... - ocs.push_back(ZAM_OC_CONSTANT); - - if ( ocs[0] == ZAM_OC_RECORD_FIELD || ocs[0] == ZAM_OC_ASSIGN_FIELD ) - ocs.push_back(ZAM_OC_INT); - - InstantiateOp(ocs, false); - if ( IsFieldOp() ) - InstantiateC1(ocs, 1); - - ocs[1] = ZAM_OC_VAR; - InstantiateOp(ocs, false); - - // ... and for assignments to fields, additional field versions. - if ( ocs[0] == ZAM_OC_ASSIGN_FIELD ) - { - ocs.push_back(ZAM_OC_INT); - InstantiateOp(ocs, false); - - ocs[1] = ZAM_OC_CONSTANT; - InstantiateOp(ocs, false); - } - - else if ( IsFieldOp() ) - InstantiateV(ocs); - } - -void ZAM_BinaryExprOpTemplate::Instantiate() - { - // As usual, the first slot receives the operator's result. - OCVec ocs = {ZAM_OC_VAR}; - ocs.resize(3); - - // Build each combination for constant/variable operand, - // except skip constant/constant as that is always folded. - - // We only include vector operations when both operands - // are non-constants. - - ocs[1] = ZAM_OC_CONSTANT; - ocs[2] = ZAM_OC_VAR; - InstantiateOp(ocs, false); - - if ( ! IsInternalOp() ) - InstantiateC1(ocs, 2); - - ocs[1] = ZAM_OC_VAR; - ocs[2] = ZAM_OC_CONSTANT; - InstantiateOp(ocs, false); - - if ( ! IsInternalOp() ) - InstantiateC2(ocs, 2); - - ocs[2] = ZAM_OC_VAR; - InstantiateOp(ocs, IncludesVectorOp()); - - if ( ! IsInternalOp() ) - InstantiateV(ocs); - } - -void ZAM_BinaryExprOpTemplate::BuildInstruction(const OCVec& oc, - const string& params, const string& suffix, - ZAM_InstClass zc) - { - auto constant_op = oc[1] == ZAM_OC_CONSTANT; - string type_src = constant_op ? "c" : "n2"; - auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; - Emit("const auto& t = " + type_src + "->GetType()" + type_suffix); - - GenerateSecondTypeVars(oc, zc); - BuildInstructionCore(params, suffix, zc); - - if ( zc == ZIC_VEC ) - Emit("z.SetType(n1->GetType());"); - } - -void ZAM_BinaryExprOpTemplate::GenerateSecondTypeVars(const OCVec& oc, - ZAM_InstClass zc) - { - auto constant_op = oc[1] == ZAM_OC_CONSTANT; - auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; - - string type_src2; - - if ( zc == ZIC_COND ) - { - if ( oc[0] == ZAM_OC_CONSTANT ) - type_src2 = "n"; - else if ( oc[1] == ZAM_OC_CONSTANT ) - type_src2 = "c"; - else - type_src2 = "n2"; - } - else - { - if ( oc[1] == ZAM_OC_CONSTANT ) - type_src2 = "n2"; - else if ( oc[2] == ZAM_OC_CONSTANT ) - type_src2 = "c"; - else - type_src2 = "n3"; - } - - Emit("const auto& t2 = " + type_src2 + "->GetType()" + type_suffix); - Emit("auto tag2 = t2->Tag();"); - Emit("auto i_t2 = t2->InternalType();"); - } - -void ZAM_RelationalExprOpTemplate::Instantiate() - { - ZAM_BinaryExprOpTemplate::Instantiate(); - - EmitTo(Cond); - - Emit("case EXPR_" + cname + ":"); - IndentUp(); - Emit("if ( n1 && n2 )"); - EmitUp("return " + cname + "VVb_cond(n1, n2);"); - Emit("else if ( n1 )"); - EmitUp("return " + cname + "VCb_cond(n1, c);"); - Emit("else"); - EmitUp("return " + cname + "CVb_cond(c, n2);"); - IndentDown(); - NL(); - } - -void ZAM_RelationalExprOpTemplate::BuildInstruction(const OCVec& oc, - const string& params, const string& suffix, - ZAM_InstClass zc) - { - string op1; - - if ( zc == ZIC_COND ) - { - if ( oc[0] == ZAM_OC_CONSTANT ) - op1 = "c"; - else if ( oc[1] == ZAM_OC_CONSTANT ) - op1 = "n"; - else - op1 = "n1"; - } - else - { - if ( oc[1] == ZAM_OC_CONSTANT ) - op1 = "c"; - else - op1 = "n2"; - } - - auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; - Emit("const auto& t = " + op1 + "->GetType()" + type_suffix); - GenerateSecondTypeVars(oc, zc); - BuildInstructionCore(params, suffix, zc); - - if ( zc == ZIC_VEC ) - Emit("z.SetType(n1->GetType());"); - } - -void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const Words& words) - { - if ( attr == "num-call-args" ) - ParseCall(line, words); - - else if ( attr == "indirect-call" || attr == "indirect-local-call" ) - { - if ( words.size() != 1 ) - g->Gripe("indirect-call takes one argument", line); - - // Note, currently only works with a *subsequent* num-call-args, - // whose setting needs to be 'n'. - is_indirect_call = true; - - if ( attr == "indirect-local-call" ) - is_local_indirect_call = true; - } - - else - ZAM_OpTemplate::Parse(attr, line, words); - } - -void ZAM_InternalOpTemplate::ParseCall(const string& line, const Words& words) - { - if ( words.size() != 2 ) - g->Gripe("num-call-args takes one argument", line); - - eval = "std::vector args;\n"; - - auto& arg = words[1]; - int n = arg == "n" ? -1 : stoi(arg); - - auto arg_offset = HasAssignVal() ? 1 : 0; - auto arg_slot = arg_offset + 1; - - string func = "Z_AUX->func"; - - if ( n == 1 ) - eval += "args.push_back($1.ToVal(Z_TYPE));\n"; - - else if ( n != 0 ) - { - eval += "auto aux = Z_AUX;\n"; - - if ( n < 0 ) - { - if ( is_indirect_call ) - { - func = "func"; - - if ( is_local_indirect_call ) - eval += "auto func = $1.AsFunc();\n"; - else - { - eval += "auto func_v = aux->id_val->GetVal();\n"; - eval += "auto func = func_v ? func_v->AsFunc() : nullptr;\n"; - } - - eval += "if ( ! func )\n"; - eval += "\t{\n"; - eval += "\tZAM_run_time_error(Z_LOC, \"value used but not set\");\n"; - eval += "\tbreak;\n"; - eval += "\t}\n"; - } - - eval += "auto n = aux->n;\n"; - eval += "args.reserve(n);\n"; - eval += "for ( auto i = 0; i < n; ++i )\n"; - eval += "\targs.push_back(aux->ToVal(frame, i));\n"; - } - - else - for ( auto i = 0; i < n; ++i ) - { - eval += "args.push_back(aux->ToVal(frame, "; - eval += to_string(i); - eval += "));\n"; - } - } - - eval += "f->SetOnlyCall(Z_AUX->call_expr.get());\n"; - eval += "ZAM_PROFILE_PRE_CALL\n"; - - if ( HasAssignVal() ) - { - auto av = GetAssignVal(); - eval += "auto " + av + " = " + func + "->Invoke(&args, f);\n"; - eval += "if ( ! " + av + " ) { ZAM_error = true; break; }\n"; - - // Postpone the profiling follow-up until after we process - // the assignment. - post_eval = "ZAM_PROFILE_POST_CALL\n"; - } - else - { - eval += "(void) " + func + "->Invoke(&args, f);\n"; - eval += "ZAM_PROFILE_POST_CALL\n"; - } - } - -bool TemplateInput::ScanLine(string& line) - { - if ( ! put_back.empty() ) - { - line = put_back; - put_back.clear(); - return true; - } - - char buf[8192]; - - // Read lines, discarding comments, which have to start at the - // beginning of a line. - do - { - if ( ! fgets(buf, sizeof buf, f) ) - return false; - ++loc.line_num; - } while ( buf[0] == '#' ); - - line = buf; - return true; - } - -vector TemplateInput::SplitIntoWords(const string& line) const - { - vector words; - - for ( auto start = line.c_str(); *start && *start != '\n'; ) - { - auto end = start + 1; - while ( *end && ! isspace(*end) ) - ++end; - - words.emplace_back(string(start, end - start)); - - start = end; - while ( *start && isspace(*start) ) - ++start; - } - - return words; - } - -string TemplateInput::SkipWords(const string& line, int n) const - { - auto s = line.c_str(); - - for ( int i = 0; i < n; ++i ) - { - // Find end of current word. - while ( *s && *s != '\n' ) - { - if ( isspace(*s) ) - break; - ++s; - } - - if ( *s == '\n' ) - break; - - // Find start of next word. - while ( *s && isspace(*s) ) - ++s; - } - - return string(s); - } - -void TemplateInput::Gripe(const char* msg, const string& input) const - { - auto input_s = input.c_str(); - size_t n = strlen(input_s); - - fprintf(stderr, "%s, line %d: %s - %s", loc.file_name, loc.line_num, msg, input_s); - if ( n == 0 || input_s[n - 1] != '\n' ) - fprintf(stderr, "\n"); - - exit(1); - } - -void TemplateInput::Gripe(const char* msg, const InputLoc& l) const - { - fprintf(stderr, "%s, line %d: %s\n", l.file_name, l.line_num, msg); - exit(1); - } - -ZAMGen::ZAMGen(int argc, char** argv) - { - auto prog_name = (argv++)[0]; - - if ( --argc < 1 ) - { - fprintf(stderr, "usage: %s \n", prog_name); - exit(1); - } - - while ( argc-- > 0 ) - { - auto file_name = (argv++)[0]; - bool is_stdin = file_name == std::string("-"); - auto f = is_stdin ? stdin : fopen(file_name, "r"); - - if ( ! f ) - { - fprintf(stderr, "%s: cannot open \"%s\"\n", prog_name, file_name); - exit(1); - } - - ti = make_unique(f, prog_name, file_name); - - while ( ParseTemplate() ) - ; - - if ( ! is_stdin ) - fclose(f); - } - - InitEmitTargets(); - - for ( auto& t : templates ) - t->Instantiate(); - - GenMacros(); - - CloseEmitTargets(); - } - -void ZAMGen::ReadMacro(const string& line) - { - vector mac; - mac.emplace_back(SkipWords(line, 1)); - - string s; - while ( ScanLine(s) ) - { - if ( s.size() <= 1 || ! isspace(s.c_str()[0]) ) - { - PutBack(s); - break; - } - - if ( regex_search(s, regex("\\$[$123]")) ) - Gripe("macro has $-param", s); - - mac.push_back(s); - } - - macros.emplace_back(std::move(mac)); - } - -void ZAMGen::GenMacros() - { - for ( auto& m : macros ) - { - for ( auto i = 0U; i < m.size(); ++i ) - { - auto ms = m[i]; - if ( i == 0 ) - { - auto name = regex_replace(ms, regex("[( ].*\n"), ""); - Emit(MacroDesc, "{ \"" + name + "\","); - - ms = "#define " + ms; - } - - auto desc = ms; - desc.erase(desc.find('\n')); - desc = regex_replace(desc, regex("\\\\"), "\\\\"); - desc = regex_replace(desc, regex("\""), "\\\""); - - if ( i < m.size() - 1 ) - { - ms = regex_replace(ms, regex("\n"), " \\\n"); - desc.append(" \\\\\\n"); - } - - Emit(MacroDesc, " \"" + desc + "\""); - if ( i == m.size() - 1 ) - Emit(MacroDesc, "},"); - - Emit(EvalMacros, ms); - } - - Emit(EvalMacros, "\n"); - } - } - -string ZAMGen::GenOpCode(const ZAM_OpTemplate* ot, const string& suffix, ZAM_InstClass zc) - { - auto op = "OP_" + ot->CanonicalName() + suffix; - - static unordered_set known_opcodes; - - if ( known_opcodes.count(op) > 0 ) - // We've already done this one, don't re-define its auxiliary - // information. - return op; - - known_opcodes.insert(op); - - IndentUp(); - - // Generate the enum defining the opcode ... - Emit(OpDef, op + ","); - - // ... the "flavor" of how it treats its first operand ... - auto op_comment = ",\t// " + op; - auto op1_always_read = (zc == ZIC_FIELD || zc == ZIC_COND); - auto flavor = op1_always_read ? "OP1_READ" : ot->GetOp1Flavor(); - Emit(Op1Flavor, flavor + op_comment); - - // ... whether it has side effects ... - auto se = ot->HasSideEffects() ? "true" : "false"; - Emit(OpSideEffects, se + op_comment); - - // ... and the switch case that maps the enum to a string - // representation. - auto name = ot->BaseName(); - transform(name.begin(), name.end(), name.begin(), ::tolower); - name += suffix; - transform(name.begin(), name.end(), name.begin(), under_to_dash); - Emit(OpName, "case " + op + ":\treturn \"" + name + "\";"); - - IndentDown(); - - return op; - } - -void ZAMGen::Emit(EmitTarget et, const string& s) - { - assert(et != None); - - if ( gen_files.count(et) == 0 ) - { - fprintf(stderr, "bad generation file type\n"); - exit(1); - } - - FILE* f = gen_files[et]; - - for ( auto i = indent_level; i > 0; --i ) - fputc('\t', f); - - if ( string_lit ) - { - fputc('"', f); - for ( auto sp = s.c_str(); *sp; ++sp ) - { - if ( *sp == '\\' ) - fputs("\\\\", f); - else if ( *sp == '"' ) - fputs("\\\"", f); - else if ( *sp == '\n' ) - fputs("\\n", f); - else - fputc(*sp, f); - } - fputc('"', f); - } - - else - fputs(s.c_str(), f); - - if ( ! no_NL && (s.empty() || s.back() != '\n') ) - fputc('\n', f); - } - -void ZAMGen::InitEmitTargets() - { - // Maps an EmitTarget enum to its corresponding filename. - static const unordered_map gen_file_names = { - {None, nullptr}, - {AssignFlavor, "ZAM-AssignFlavorsDefs.h"}, - {C1Def, "ZAM-GenExprsDefsC1.h"}, - {C1FieldDef, "ZAM-GenFieldsDefsC1.h"}, - {C2Def, "ZAM-GenExprsDefsC2.h"}, - {C2FieldDef, "ZAM-GenFieldsDefsC2.h"}, - {C3Def, "ZAM-GenExprsDefsC3.h"}, - {Cond, "ZAM-Conds.h"}, - {DirectDef, "ZAM-DirectDefs.h"}, - {Eval, "ZAM-EvalDefs.h"}, - {EvalMacros, "ZAM-EvalMacros.h"}, - {MacroDesc, "ZAM-MacroDesc.h"}, - {MethodDecl, "ZAM-MethodDecls.h"}, - {MethodDef, "ZAM-MethodDefs.h"}, - {Op1Flavor, "ZAM-Op1FlavorsDefs.h"}, - {OpDef, "ZAM-OpsDefs.h"}, - {OpDesc, "ZAM-OpDesc.h"}, - {OpName, "ZAM-OpsNamesDefs.h"}, - {OpSideEffects, "ZAM-OpSideEffects.h"}, - {VDef, "ZAM-GenExprsDefsV.h"}, - {VFieldDef, "ZAM-GenFieldsDefsV.h"}, - {Vec1Eval, "ZAM-Vec1EvalDefs.h"}, - {Vec2Eval, "ZAM-Vec2EvalDefs.h"}, - }; - - for ( auto& gfn : gen_file_names ) - { - auto fn = gfn.second; - if ( ! fn ) - continue; - - auto f = fopen(fn, "w"); - if ( ! f ) - { - fprintf(stderr, "can't open generation file %s\n", fn); - exit(1); - } - - gen_files[gfn.first] = f; - } - - // Avoid bugprone-branch-clone warnings from clang-tidy in generated code. - Emit(OpName, "// NOLINTBEGIN(bugprone-branch-clone)"); - Emit(Eval, "// NOLINTBEGIN(bugprone-branch-clone)"); - Emit(EvalMacros, "// NOLINTBEGIN(bugprone-macro-parentheses)"); - Emit(EvalMacros, "// NOLINTBEGIN(cppcoreguidelines-macro-usage)"); - - InitSwitch(C1Def, "C1 assignment"); - InitSwitch(C2Def, "C2 assignment"); - InitSwitch(C3Def, "C3 assignment"); - InitSwitch(VDef, "V assignment"); - - InitSwitch(C1FieldDef, "C1 field assignment"); - InitSwitch(C2FieldDef, "C2 field assignment"); - InitSwitch(VFieldDef, "V field assignment"); - } - -void ZAMGen::InitSwitch(EmitTarget et, string desc) - { - Emit(et, "{"); - Emit(et, "switch ( rhs->Tag() ) {"); - - switch_targets[et] = std::move(desc); - } - -void ZAMGen::CloseEmitTargets() - { - FinishSwitches(); - - Emit(OpName, "// NOLINTEND(bugprone-branch-clone)"); - Emit(Eval, "// NOLINTEND(bugprone-branch-clone)"); - Emit(EvalMacros, "// NOLINTEND(cppcoreguidelines-macro-usage)"); - Emit(EvalMacros, "// NOLINTEND(bugprone-macro-parentheses)"); - - for ( auto& gf : gen_files ) - fclose(gf.second); - } - -void ZAMGen::FinishSwitches() - { - for ( auto& st : switch_targets ) - { - auto et = st.first; - auto& desc = st.second; - - Emit(et, "default:"); - IndentUp(); - Emit(et, "reporter->InternalError(\"inconsistency in " + desc + - ": %s\", obj_desc(rhs).c_str());"); - IndentDown(); - Emit(et, "}"); - Emit(et, "}"); - } - } - -bool ZAMGen::ParseTemplate() - { - string line; - - if ( ! ScanLine(line) ) - return false; - - if ( line.size() <= 1 ) - // A blank line - no template to parse. - return true; - - auto words = SplitIntoWords(line); - - if ( words.size() < 2 ) - Gripe("too few words at start of template", line); - - auto op = words[0]; - - if ( op == "macro" ) - { - ReadMacro(line); - return true; - } - - auto op_name = words[1]; - - // We track issues with the wrong number of template arguments - // up front, to avoid mis-invoking constructors, but we don't - // report these until later because if the template names a - // bad operation, it's better to report that as the core problem. - const char* args_mismatch = nullptr; - - if ( op == "direct-unary-op" ) - { - if ( words.size() != 3 ) - args_mismatch = "direct-unary-op takes 2 arguments"; - } - - else if ( words.size() != 2 ) - args_mismatch = "templates take 1 argument"; - - unique_ptr t; - - if ( op == "op" ) - t = make_unique(this, op_name); - else if ( op == "unary-op" ) - t = make_unique(this, op_name); - else if ( op == "direct-unary-op" && ! args_mismatch ) - t = make_unique(this, op_name, words[2]); - else if ( op == "assign-op" ) - t = make_unique(this, op_name); - else if ( op == "expr-op" ) - t = make_unique(this, op_name); - else if ( op == "unary-expr-op" ) - t = make_unique(this, op_name); - else if ( op == "binary-expr-op" ) - t = make_unique(this, op_name); - else if ( op == "rel-expr-op" ) - t = make_unique(this, op_name); - else if ( op == "internal-op" ) - t = make_unique(this, op_name); - else if ( op == "predicate-op" ) - { - t = make_unique(this, op_name); - t->SetIsPredicate(); - } - else if ( op == "internal-assignment-op" ) - t = make_unique(this, op_name); - - else - Gripe("bad template name", op); - - if ( args_mismatch ) - Gripe(args_mismatch, line); - - t->Build(); - templates.emplace_back(std::move(t)); - - return true; - } - -int main(int argc, char** argv) - { - try - { - ZAMGen zg(argc, argv); - exit(0); - } - catch ( const std::regex_error& e ) - { - fprintf(stderr, "%s: regular expression error - %s\n", argv[0], e.what()); - exit(1); - } - } + : ZAM_UnaryExprOpTemplate(_g, std::move(_base_name)) { + // Assignments apply to every valid form of ExprType. + for ( auto& etn : type_names ) { + auto zt = etn.second; + if ( zt != ZAM_TYPE_NONE && zt != ZAM_TYPE_DEFAULT ) + AddExprType(zt); + } +} + +void ZAM_AssignOpTemplate::Parse(const string& attr, const string& line, const Words& words) { + if ( attr == "field-op" ) { + if ( words.size() != 1 ) + g->Gripe("field-op does not take any arguments", line); + + SetFieldOp(); + } + + else + ZAM_OpTemplate::Parse(attr, line, words); +} + +void ZAM_AssignOpTemplate::Instantiate() { + if ( op_classes.size() != 1 ) + Gripe("operation needs precisely one \"type\""); + if ( ! op_classes_vec.empty() ) + Gripe("operation cannot use \"classes\""); + + OCVec ocs; + ocs.push_back(op_classes[0]); + + // Build constant/variable versions ... + ocs.push_back(ZAM_OC_CONSTANT); + + if ( ocs[0] == ZAM_OC_RECORD_FIELD || ocs[0] == ZAM_OC_ASSIGN_FIELD ) + ocs.push_back(ZAM_OC_INT); + + InstantiateOp(ocs, false); + if ( IsFieldOp() ) + InstantiateC1(ocs, 1); + + ocs[1] = ZAM_OC_VAR; + InstantiateOp(ocs, false); + + // ... and for assignments to fields, additional field versions. + if ( ocs[0] == ZAM_OC_ASSIGN_FIELD ) { + ocs.push_back(ZAM_OC_INT); + InstantiateOp(ocs, false); + + ocs[1] = ZAM_OC_CONSTANT; + InstantiateOp(ocs, false); + } + + else if ( IsFieldOp() ) + InstantiateV(ocs); +} + +void ZAM_BinaryExprOpTemplate::Instantiate() { + // As usual, the first slot receives the operator's result. + OCVec ocs = {ZAM_OC_VAR}; + ocs.resize(3); + + // Build each combination for constant/variable operand, + // except skip constant/constant as that is always folded. + + // We only include vector operations when both operands + // are non-constants. + + ocs[1] = ZAM_OC_CONSTANT; + ocs[2] = ZAM_OC_VAR; + InstantiateOp(ocs, false); + + if ( ! IsInternalOp() ) + InstantiateC1(ocs, 2); + + ocs[1] = ZAM_OC_VAR; + ocs[2] = ZAM_OC_CONSTANT; + InstantiateOp(ocs, false); + + if ( ! IsInternalOp() ) + InstantiateC2(ocs, 2); + + ocs[2] = ZAM_OC_VAR; + InstantiateOp(ocs, IncludesVectorOp()); + + if ( ! IsInternalOp() ) + InstantiateV(ocs); +} + +void ZAM_BinaryExprOpTemplate::BuildInstruction(const OCVec& oc, const string& params, const string& suffix, + ZAM_InstClass zc) { + auto constant_op = oc[1] == ZAM_OC_CONSTANT; + string type_src = constant_op ? "c" : "n2"; + auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; + Emit("const auto& t = " + type_src + "->GetType()" + type_suffix); + + GenerateSecondTypeVars(oc, zc); + BuildInstructionCore(params, suffix, zc); + + if ( zc == ZIC_VEC ) + Emit("z.SetType(n1->GetType());"); +} + +void ZAM_BinaryExprOpTemplate::GenerateSecondTypeVars(const OCVec& oc, ZAM_InstClass zc) { + auto constant_op = oc[1] == ZAM_OC_CONSTANT; + auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; + + string type_src2; + + if ( zc == ZIC_COND ) { + if ( oc[0] == ZAM_OC_CONSTANT ) + type_src2 = "n"; + else if ( oc[1] == ZAM_OC_CONSTANT ) + type_src2 = "c"; + else + type_src2 = "n2"; + } + else { + if ( oc[1] == ZAM_OC_CONSTANT ) + type_src2 = "n2"; + else if ( oc[2] == ZAM_OC_CONSTANT ) + type_src2 = "c"; + else + type_src2 = "n3"; + } + + Emit("const auto& t2 = " + type_src2 + "->GetType()" + type_suffix); + Emit("auto tag2 = t2->Tag();"); + Emit("auto i_t2 = t2->InternalType();"); +} + +void ZAM_RelationalExprOpTemplate::Instantiate() { + ZAM_BinaryExprOpTemplate::Instantiate(); + + EmitTo(Cond); + + Emit("case EXPR_" + cname + ":"); + IndentUp(); + Emit("if ( n1 && n2 )"); + EmitUp("return " + cname + "VVb_cond(n1, n2);"); + Emit("else if ( n1 )"); + EmitUp("return " + cname + "VCb_cond(n1, c);"); + Emit("else"); + EmitUp("return " + cname + "CVb_cond(c, n2);"); + IndentDown(); + NL(); +} + +void ZAM_RelationalExprOpTemplate::BuildInstruction(const OCVec& oc, const string& params, const string& suffix, + ZAM_InstClass zc) { + string op1; + + if ( zc == ZIC_COND ) { + if ( oc[0] == ZAM_OC_CONSTANT ) + op1 = "c"; + else if ( oc[1] == ZAM_OC_CONSTANT ) + op1 = "n"; + else + op1 = "n1"; + } + else { + if ( oc[1] == ZAM_OC_CONSTANT ) + op1 = "c"; + else + op1 = "n2"; + } + + auto type_suffix = zc == ZIC_VEC ? "->Yield();" : ";"; + Emit("const auto& t = " + op1 + "->GetType()" + type_suffix); + GenerateSecondTypeVars(oc, zc); + BuildInstructionCore(params, suffix, zc); + + if ( zc == ZIC_VEC ) + Emit("z.SetType(n1->GetType());"); +} + +void ZAM_InternalOpTemplate::Parse(const string& attr, const string& line, const Words& words) { + if ( attr == "num-call-args" ) + ParseCall(line, words); + + else if ( attr == "indirect-call" || attr == "indirect-local-call" ) { + if ( words.size() != 1 ) + g->Gripe("indirect-call takes one argument", line); + + // Note, currently only works with a *subsequent* num-call-args, + // whose setting needs to be 'n'. + is_indirect_call = true; + + if ( attr == "indirect-local-call" ) + is_local_indirect_call = true; + } + + else + ZAM_OpTemplate::Parse(attr, line, words); +} + +void ZAM_InternalOpTemplate::ParseCall(const string& line, const Words& words) { + if ( words.size() != 2 ) + g->Gripe("num-call-args takes one argument", line); + + eval = "std::vector args;\n"; + + auto& arg = words[1]; + int n = arg == "n" ? -1 : stoi(arg); + + auto arg_offset = HasAssignVal() ? 1 : 0; + auto arg_slot = arg_offset + 1; + + string func = "Z_AUX->func"; + + if ( n == 1 ) + eval += "args.push_back($1.ToVal(Z_TYPE));\n"; + + else if ( n != 0 ) { + eval += "auto aux = Z_AUX;\n"; + + if ( n < 0 ) { + if ( is_indirect_call ) { + func = "func"; + + if ( is_local_indirect_call ) + eval += "auto func = $1.AsFunc();\n"; + else { + eval += "auto func_v = aux->id_val->GetVal();\n"; + eval += "auto func = func_v ? func_v->AsFunc() : nullptr;\n"; + } + + eval += "if ( ! func )\n"; + eval += "\t{\n"; + eval += "\tZAM_run_time_error(Z_LOC, \"value used but not set\");\n"; + eval += "\tbreak;\n"; + eval += "\t}\n"; + } + + eval += "auto n = aux->n;\n"; + eval += "args.reserve(n);\n"; + eval += "for ( auto i = 0; i < n; ++i )\n"; + eval += "\targs.push_back(aux->ToVal(frame, i));\n"; + } + + else + for ( auto i = 0; i < n; ++i ) { + eval += "args.push_back(aux->ToVal(frame, "; + eval += to_string(i); + eval += "));\n"; + } + } + + eval += "f->SetOnlyCall(Z_AUX->call_expr.get());\n"; + eval += "ZAM_PROFILE_PRE_CALL\n"; + + if ( HasAssignVal() ) { + auto av = GetAssignVal(); + eval += "auto " + av + " = " + func + "->Invoke(&args, f);\n"; + eval += "if ( ! " + av + " ) { ZAM_error = true; break; }\n"; + + // Postpone the profiling follow-up until after we process + // the assignment. + post_eval = "ZAM_PROFILE_POST_CALL\n"; + } + else { + eval += "(void) " + func + "->Invoke(&args, f);\n"; + eval += "ZAM_PROFILE_POST_CALL\n"; + } +} + +bool TemplateInput::ScanLine(string& line) { + if ( ! put_back.empty() ) { + line = put_back; + put_back.clear(); + return true; + } + + char buf[8192]; + + // Read lines, discarding comments, which have to start at the + // beginning of a line. + do { + if ( ! fgets(buf, sizeof buf, f) ) + return false; + ++loc.line_num; + } while ( buf[0] == '#' ); + + line = buf; + return true; +} + +vector TemplateInput::SplitIntoWords(const string& line) const { + vector words; + + for ( auto start = line.c_str(); *start && *start != '\n'; ) { + auto end = start + 1; + while ( *end && ! isspace(*end) ) + ++end; + + words.emplace_back(string(start, end - start)); + + start = end; + while ( *start && isspace(*start) ) + ++start; + } + + return words; +} + +string TemplateInput::SkipWords(const string& line, int n) const { + auto s = line.c_str(); + + for ( int i = 0; i < n; ++i ) { + // Find end of current word. + while ( *s && *s != '\n' ) { + if ( isspace(*s) ) + break; + ++s; + } + + if ( *s == '\n' ) + break; + + // Find start of next word. + while ( *s && isspace(*s) ) + ++s; + } + + return string(s); +} + +void TemplateInput::Gripe(const char* msg, const string& input) const { + auto input_s = input.c_str(); + size_t n = strlen(input_s); + + fprintf(stderr, "%s, line %d: %s - %s", loc.file_name, loc.line_num, msg, input_s); + if ( n == 0 || input_s[n - 1] != '\n' ) + fprintf(stderr, "\n"); + + exit(1); +} + +void TemplateInput::Gripe(const char* msg, const InputLoc& l) const { + fprintf(stderr, "%s, line %d: %s\n", l.file_name, l.line_num, msg); + exit(1); +} + +ZAMGen::ZAMGen(int argc, char** argv) { + auto prog_name = (argv++)[0]; + + if ( --argc < 1 ) { + fprintf(stderr, "usage: %s \n", prog_name); + exit(1); + } + + while ( argc-- > 0 ) { + auto file_name = (argv++)[0]; + bool is_stdin = file_name == std::string("-"); + auto f = is_stdin ? stdin : fopen(file_name, "r"); + + if ( ! f ) { + fprintf(stderr, "%s: cannot open \"%s\"\n", prog_name, file_name); + exit(1); + } + + ti = make_unique(f, prog_name, file_name); + + while ( ParseTemplate() ) + ; + + if ( ! is_stdin ) + fclose(f); + } + + InitEmitTargets(); + + for ( auto& t : templates ) + t->Instantiate(); + + GenMacros(); + + CloseEmitTargets(); +} + +void ZAMGen::ReadMacro(const string& line) { + vector mac; + mac.emplace_back(SkipWords(line, 1)); + + string s; + while ( ScanLine(s) ) { + if ( s.size() <= 1 || ! isspace(s.c_str()[0]) ) { + PutBack(s); + break; + } + + if ( regex_search(s, regex("\\$[$123]")) ) + Gripe("macro has $-param", s); + + mac.push_back(s); + } + + macros.emplace_back(std::move(mac)); +} + +void ZAMGen::GenMacros() { + for ( auto& m : macros ) { + for ( auto i = 0U; i < m.size(); ++i ) { + auto ms = m[i]; + if ( i == 0 ) { + auto name = regex_replace(ms, regex("[( ].*\n"), ""); + Emit(MacroDesc, "{ \"" + name + "\","); + + ms = "#define " + ms; + } + + auto desc = ms; + desc.erase(desc.find('\n')); + desc = regex_replace(desc, regex("\\\\"), "\\\\"); + desc = regex_replace(desc, regex("\""), "\\\""); + + if ( i < m.size() - 1 ) { + ms = regex_replace(ms, regex("\n"), " \\\n"); + desc.append(" \\\\\\n"); + } + + Emit(MacroDesc, " \"" + desc + "\""); + if ( i == m.size() - 1 ) + Emit(MacroDesc, "},"); + + Emit(EvalMacros, ms); + } + + Emit(EvalMacros, "\n"); + } +} + +string ZAMGen::GenOpCode(const ZAM_OpTemplate* ot, const string& suffix, ZAM_InstClass zc) { + auto op = "OP_" + ot->CanonicalName() + suffix; + + static unordered_set known_opcodes; + + if ( known_opcodes.count(op) > 0 ) + // We've already done this one, don't re-define its auxiliary + // information. + return op; + + known_opcodes.insert(op); + + IndentUp(); + + // Generate the enum defining the opcode ... + Emit(OpDef, op + ","); + + // ... the "flavor" of how it treats its first operand ... + auto op_comment = ",\t// " + op; + auto op1_always_read = (zc == ZIC_FIELD || zc == ZIC_COND); + auto flavor = op1_always_read ? "OP1_READ" : ot->GetOp1Flavor(); + Emit(Op1Flavor, flavor + op_comment); + + // ... whether it has side effects ... + auto se = ot->HasSideEffects() ? "true" : "false"; + Emit(OpSideEffects, se + op_comment); + + // ... and the switch case that maps the enum to a string + // representation. + auto name = ot->BaseName(); + transform(name.begin(), name.end(), name.begin(), ::tolower); + name += suffix; + transform(name.begin(), name.end(), name.begin(), under_to_dash); + Emit(OpName, "case " + op + ":\treturn \"" + name + "\";"); + + IndentDown(); + + return op; +} + +void ZAMGen::Emit(EmitTarget et, const string& s) { + assert(et != None); + + if ( gen_files.count(et) == 0 ) { + fprintf(stderr, "bad generation file type\n"); + exit(1); + } + + FILE* f = gen_files[et]; + + for ( auto i = indent_level; i > 0; --i ) + fputc('\t', f); + + if ( string_lit ) { + fputc('"', f); + for ( auto sp = s.c_str(); *sp; ++sp ) { + if ( *sp == '\\' ) + fputs("\\\\", f); + else if ( *sp == '"' ) + fputs("\\\"", f); + else if ( *sp == '\n' ) + fputs("\\n", f); + else + fputc(*sp, f); + } + fputc('"', f); + } + + else + fputs(s.c_str(), f); + + if ( ! no_NL && (s.empty() || s.back() != '\n') ) + fputc('\n', f); +} + +void ZAMGen::InitEmitTargets() { + // Maps an EmitTarget enum to its corresponding filename. + static const unordered_map gen_file_names = { + {None, nullptr}, + {AssignFlavor, "ZAM-AssignFlavorsDefs.h"}, + {C1Def, "ZAM-GenExprsDefsC1.h"}, + {C1FieldDef, "ZAM-GenFieldsDefsC1.h"}, + {C2Def, "ZAM-GenExprsDefsC2.h"}, + {C2FieldDef, "ZAM-GenFieldsDefsC2.h"}, + {C3Def, "ZAM-GenExprsDefsC3.h"}, + {Cond, "ZAM-Conds.h"}, + {DirectDef, "ZAM-DirectDefs.h"}, + {Eval, "ZAM-EvalDefs.h"}, + {EvalMacros, "ZAM-EvalMacros.h"}, + {MacroDesc, "ZAM-MacroDesc.h"}, + {MethodDecl, "ZAM-MethodDecls.h"}, + {MethodDef, "ZAM-MethodDefs.h"}, + {Op1Flavor, "ZAM-Op1FlavorsDefs.h"}, + {OpDef, "ZAM-OpsDefs.h"}, + {OpDesc, "ZAM-OpDesc.h"}, + {OpName, "ZAM-OpsNamesDefs.h"}, + {OpSideEffects, "ZAM-OpSideEffects.h"}, + {VDef, "ZAM-GenExprsDefsV.h"}, + {VFieldDef, "ZAM-GenFieldsDefsV.h"}, + {Vec1Eval, "ZAM-Vec1EvalDefs.h"}, + {Vec2Eval, "ZAM-Vec2EvalDefs.h"}, + }; + + for ( auto& gfn : gen_file_names ) { + auto fn = gfn.second; + if ( ! fn ) + continue; + + auto f = fopen(fn, "w"); + if ( ! f ) { + fprintf(stderr, "can't open generation file %s\n", fn); + exit(1); + } + + gen_files[gfn.first] = f; + } + + // Avoid bugprone-branch-clone warnings from clang-tidy in generated code. + Emit(OpName, "// NOLINTBEGIN(bugprone-branch-clone)"); + Emit(Eval, "// NOLINTBEGIN(bugprone-branch-clone)"); + Emit(EvalMacros, "// NOLINTBEGIN(bugprone-macro-parentheses)"); + Emit(EvalMacros, "// NOLINTBEGIN(cppcoreguidelines-macro-usage)"); + + InitSwitch(C1Def, "C1 assignment"); + InitSwitch(C2Def, "C2 assignment"); + InitSwitch(C3Def, "C3 assignment"); + InitSwitch(VDef, "V assignment"); + + InitSwitch(C1FieldDef, "C1 field assignment"); + InitSwitch(C2FieldDef, "C2 field assignment"); + InitSwitch(VFieldDef, "V field assignment"); +} + +void ZAMGen::InitSwitch(EmitTarget et, string desc) { + Emit(et, "{"); + Emit(et, "switch ( rhs->Tag() ) {"); + + switch_targets[et] = std::move(desc); +} + +void ZAMGen::CloseEmitTargets() { + FinishSwitches(); + + Emit(OpName, "// NOLINTEND(bugprone-branch-clone)"); + Emit(Eval, "// NOLINTEND(bugprone-branch-clone)"); + Emit(EvalMacros, "// NOLINTEND(cppcoreguidelines-macro-usage)"); + Emit(EvalMacros, "// NOLINTEND(bugprone-macro-parentheses)"); + + for ( auto& gf : gen_files ) + fclose(gf.second); +} + +void ZAMGen::FinishSwitches() { + for ( auto& st : switch_targets ) { + auto et = st.first; + auto& desc = st.second; + + Emit(et, "default:"); + IndentUp(); + Emit(et, "reporter->InternalError(\"inconsistency in " + desc + ": %s\", obj_desc(rhs).c_str());"); + IndentDown(); + Emit(et, "}"); + Emit(et, "}"); + } +} + +bool ZAMGen::ParseTemplate() { + string line; + + if ( ! ScanLine(line) ) + return false; + + if ( line.size() <= 1 ) + // A blank line - no template to parse. + return true; + + auto words = SplitIntoWords(line); + + if ( words.size() < 2 ) + Gripe("too few words at start of template", line); + + auto op = words[0]; + + if ( op == "macro" ) { + ReadMacro(line); + return true; + } + + auto op_name = words[1]; + + // We track issues with the wrong number of template arguments + // up front, to avoid mis-invoking constructors, but we don't + // report these until later because if the template names a + // bad operation, it's better to report that as the core problem. + const char* args_mismatch = nullptr; + + if ( op == "direct-unary-op" ) { + if ( words.size() != 3 ) + args_mismatch = "direct-unary-op takes 2 arguments"; + } + + else if ( words.size() != 2 ) + args_mismatch = "templates take 1 argument"; + + unique_ptr t; + + if ( op == "op" ) + t = make_unique(this, op_name); + else if ( op == "unary-op" ) + t = make_unique(this, op_name); + else if ( op == "direct-unary-op" && ! args_mismatch ) + t = make_unique(this, op_name, words[2]); + else if ( op == "assign-op" ) + t = make_unique(this, op_name); + else if ( op == "expr-op" ) + t = make_unique(this, op_name); + else if ( op == "unary-expr-op" ) + t = make_unique(this, op_name); + else if ( op == "binary-expr-op" ) + t = make_unique(this, op_name); + else if ( op == "rel-expr-op" ) + t = make_unique(this, op_name); + else if ( op == "internal-op" ) + t = make_unique(this, op_name); + else if ( op == "predicate-op" ) { + t = make_unique(this, op_name); + t->SetIsPredicate(); + } + else if ( op == "internal-assignment-op" ) + t = make_unique(this, op_name); + + else + Gripe("bad template name", op); + + if ( args_mismatch ) + Gripe(args_mismatch, line); + + t->Build(); + templates.emplace_back(std::move(t)); + + return true; +} + +int main(int argc, char** argv) { + try { + ZAMGen zg(argc, argv); + exit(0); + } catch ( const std::regex_error& e ) { + fprintf(stderr, "%s: regular expression error - %s\n", argv[0], e.what()); + exit(1); + } +} diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index ec09fc437c..90e8008d45 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -10,10 +10,10 @@ #pragma once #include -#include #include -#include #include +#include +#include #include #include #include @@ -23,40 +23,38 @@ using std::string; using std::vector; // An instruction can have one of four basic classes. -enum ZAM_InstClass - { - ZIC_REGULAR, // a non-complicated instruction - ZIC_COND, // a conditional branch - ZIC_VEC, // a vector operation - ZIC_FIELD, // a record field assignment - }; +enum ZAM_InstClass { + ZIC_REGULAR, // a non-complicated instruction + ZIC_COND, // a conditional branch + ZIC_VEC, // a vector operation + ZIC_FIELD, // a record field assignment +}; // For a given instruction operand, its general class. -enum ZAM_OperandClass - { - ZAM_OC_CONSTANT, // uses the instruction's associated constant - ZAM_OC_EVENT_HANDLER, // uses the associated event handler - ZAM_OC_INT, // directly specified integer - ZAM_OC_VAR, // frame slot associated with a variable +enum ZAM_OperandClass { + ZAM_OC_CONSTANT, // uses the instruction's associated constant + ZAM_OC_EVENT_HANDLER, // uses the associated event handler + ZAM_OC_INT, // directly specified integer + ZAM_OC_VAR, // frame slot associated with a variable - ZAM_OC_ASSIGN_FIELD, // record field offset to assign to - ZAM_OC_RECORD_FIELD, // record field offset to access + ZAM_OC_ASSIGN_FIELD, // record field offset to assign to + ZAM_OC_RECORD_FIELD, // record field offset to access - // The following wind up the same in the ultimate instruction, - // but they differ in the calling sequences used to generate - // the instruction. - ZAM_OC_AUX, // uses the instruction's "aux" field - ZAM_OC_LIST, // a list, managed via the "aux" field + // The following wind up the same in the ultimate instruction, + // but they differ in the calling sequences used to generate + // the instruction. + ZAM_OC_AUX, // uses the instruction's "aux" field + ZAM_OC_LIST, // a list, managed via the "aux" field - // Internal types: branches, tracking globals, step-wise iterations - // (vectors and strings), table iterations. - ZAM_OC_BRANCH, - ZAM_OC_GLOBAL, - ZAM_OC_STEP_ITER, - ZAM_OC_TBL_ITER, + // Internal types: branches, tracking globals, step-wise iterations + // (vectors and strings), table iterations. + ZAM_OC_BRANCH, + ZAM_OC_GLOBAL, + ZAM_OC_STEP_ITER, + ZAM_OC_TBL_ITER, - ZAM_OC_NONE, // instruction has no direct operands - }; + ZAM_OC_NONE, // instruction has no direct operands +}; using OCVec = vector; @@ -64,34 +62,33 @@ using OCVec = vector; // of a given operand. The generator uses these to transform the operand's // low-level ZVal into a higher-level type expected by the associated // evaluation code. -enum ZAM_Type - { - ZAM_TYPE_ADDR, - ZAM_TYPE_ANY, - ZAM_TYPE_DOUBLE, - ZAM_TYPE_FUNC, - ZAM_TYPE_INT, - ZAM_TYPE_PATTERN, - ZAM_TYPE_RECORD, - ZAM_TYPE_STRING, - ZAM_TYPE_SUBNET, - ZAM_TYPE_TABLE, - ZAM_TYPE_UINT, - ZAM_TYPE_VECTOR, - ZAM_TYPE_FILE, - ZAM_TYPE_OPAQUE, - ZAM_TYPE_LIST, - ZAM_TYPE_TYPE, +enum ZAM_Type { + ZAM_TYPE_ADDR, + ZAM_TYPE_ANY, + ZAM_TYPE_DOUBLE, + ZAM_TYPE_FUNC, + ZAM_TYPE_INT, + ZAM_TYPE_PATTERN, + ZAM_TYPE_RECORD, + ZAM_TYPE_STRING, + ZAM_TYPE_SUBNET, + ZAM_TYPE_TABLE, + ZAM_TYPE_UINT, + ZAM_TYPE_VECTOR, + ZAM_TYPE_FILE, + ZAM_TYPE_OPAQUE, + ZAM_TYPE_LIST, + ZAM_TYPE_TYPE, - // Used to specify "apart from the explicitly specified operand - // types, do this action for any other types". - ZAM_TYPE_DEFAULT, + // Used to specify "apart from the explicitly specified operand + // types, do this action for any other types". + ZAM_TYPE_DEFAULT, - // Used for expressions where the evaluation code for the - // expression deals directly with the operand's ZVal, rather - // than the generator providing a higher-level version. - ZAM_TYPE_NONE, - }; + // Used for expressions where the evaluation code for the + // expression deals directly with the operand's ZVal, rather + // than the generator providing a higher-level version. + ZAM_TYPE_NONE, +}; // We only use the following in the context where the vector's elements // are individual words from the same line. We don't use it in other @@ -99,952 +96,902 @@ enum ZAM_Type using Words = vector; // Used for error-reporting. -struct InputLoc - { - const char* file_name; - int line_num = 0; - }; +struct InputLoc { + const char* file_name; + int line_num = 0; +}; // An EmitTarget is a generated file to which code will be emitted. // The different values are used to instruct the generator which target // is currently of interest. -enum EmitTarget - { - // Indicates that no generated file has yet been specified. - None, +enum EmitTarget { + // Indicates that no generated file has yet been specified. + None, - // Declares/defines methods that take AST nodes and generate - // corresponding ZAM instructions. - MethodDecl, - MethodDef, + // Declares/defines methods that take AST nodes and generate + // corresponding ZAM instructions. + MethodDecl, + MethodDef, - // Switch cases for expressions that are compiled directly, using - // custom methods rather than methods produced by the generator. - DirectDef, + // Switch cases for expressions that are compiled directly, using + // custom methods rather than methods produced by the generator. + DirectDef, - // Switch cases for invoking various flavors of methods produced - // by the generator for generating ZAM instructions for AST - // expressions. C1/C2/C3 refer to the first/second/third operand - // being a constant. V refers to none of the operands being - // a constant. - C1Def, - C2Def, - C3Def, - VDef, + // Switch cases for invoking various flavors of methods produced + // by the generator for generating ZAM instructions for AST + // expressions. C1/C2/C3 refer to the first/second/third operand + // being a constant. V refers to none of the operands being + // a constant. + C1Def, + C2Def, + C3Def, + VDef, - // The same, but for when the expression is being assigned to - // a record field rather than a variable. There's no "C3" option - // because of how we reduce AST ternary operations. - C1FieldDef, - C2FieldDef, - VFieldDef, + // The same, but for when the expression is being assigned to + // a record field rather than a variable. There's no "C3" option + // because of how we reduce AST ternary operations. + C1FieldDef, + C2FieldDef, + VFieldDef, - // Switch cases for compiling relational operations used in - // conditionals. - Cond, + // Switch cases for compiling relational operations used in + // conditionals. + Cond, - // Descriptions of final ZAM operations, used for validation. - OpDesc, + // Descriptions of final ZAM operations, used for validation. + OpDesc, - // The same, for macros. - MacroDesc, + // The same, for macros. + MacroDesc, - // Switch cases that provide the C++ code for executing specific - // individual ZAM instructions. - Eval, + // Switch cases that provide the C++ code for executing specific + // individual ZAM instructions. + Eval, - // #define's used to provide the templator's macro functionality. - EvalMacros, + // #define's used to provide the templator's macro functionality. + EvalMacros, - // Switch cases the provide the C++ code for executing unary - // and binary vector operations. - Vec1Eval, - Vec2Eval, + // Switch cases the provide the C++ code for executing unary + // and binary vector operations. + Vec1Eval, + Vec2Eval, - // A set of instructions to dynamically generate maps that - // translate a generic ZAM operation (e.g., OP_LOAD_GLOBAL_VV) - // to a specific ZAM instruction, given a specific type - // (e.g., for OP_LOAD_GLOBAL_VV plus TYPE_ADDR, the map yields - // OP_LOAD_GLOBAL_VV_A). - AssignFlavor, + // A set of instructions to dynamically generate maps that + // translate a generic ZAM operation (e.g., OP_LOAD_GLOBAL_VV) + // to a specific ZAM instruction, given a specific type + // (e.g., for OP_LOAD_GLOBAL_VV plus TYPE_ADDR, the map yields + // OP_LOAD_GLOBAL_VV_A). + AssignFlavor, - // A list of values, one per ZAM instruction, that indicate whether - // that instruction writes to its first operand (the most common - // case), reads the operand but doesn't write to it, both reads it - // and writes to it, or none of these apply because the first - // operand isn't a frame variable. See the ZAMOp1Flavor enum - // defined in ZOp.h. - Op1Flavor, + // A list of values, one per ZAM instruction, that indicate whether + // that instruction writes to its first operand (the most common + // case), reads the operand but doesn't write to it, both reads it + // and writes to it, or none of these apply because the first + // operand isn't a frame variable. See the ZAMOp1Flavor enum + // defined in ZOp.h. + Op1Flavor, - // A list of boolean values, one per ZAM instruction, that indicate - // whether the instruction has side effects, and thus should not - // be deleted even if its associated assignment is to a dead value - // (one not subsequently used). - OpSideEffects, + // A list of boolean values, one per ZAM instruction, that indicate + // whether the instruction has side effects, and thus should not + // be deleted even if its associated assignment is to a dead value + // (one not subsequently used). + OpSideEffects, - // A list of names enumerating each ZAM instruction. These - // are ZAM opcodes. - OpDef, + // A list of names enumerating each ZAM instruction. These + // are ZAM opcodes. + OpDef, - // A list of cases, indexed by ZAM opcode, that return a - // human-readable string of naming the opcode, for use in debugging - // output. For example, for OP_NEGATE_VV_I the corresponding - // string is "negate-VV-I". - OpName, - }; + // A list of cases, indexed by ZAM opcode, that return a + // human-readable string of naming the opcode, for use in debugging + // output. For example, for OP_NEGATE_VV_I the corresponding + // string is "negate-VV-I". + OpName, +}; // A helper class for managing the (ordered) collection of ZAM_OperandClass's // associated with an instruction in order to generate C++ calling sequences // (both parameters for declarations, and arguments for invocations). -class ArgsManager - { +class ArgsManager { public: - // Constructed by providing the various ZAM_OperandClass's along - // with the instruction's class. - ArgsManager(const OCVec& oc, ZAM_InstClass ic); + // Constructed by providing the various ZAM_OperandClass's along + // with the instruction's class. + ArgsManager(const OCVec& oc, ZAM_InstClass ic); - // Returns a string defining the parameters for a declaration; - // these have full C++ type information along with the parameter - // name. - string Decls() const { return full_decl; } + // Returns a string defining the parameters for a declaration; + // these have full C++ type information along with the parameter + // name. + string Decls() const { return full_decl; } - // Returns a string for passing the parameters in a function - // call. This is a comma-separated list of the parameter names, - // with no associated C++ types. - string Params() const { return full_params; } + // Returns a string for passing the parameters in a function + // call. This is a comma-separated list of the parameter names, + // with no associated C++ types. + string Params() const { return full_params; } - // Returns the name of the given parameter, indexed starting with 0. - const string& NthParam(int n) const { return params[n]; } + // Returns the name of the given parameter, indexed starting with 0. + const string& NthParam(int n) const { return params[n]; } private: - // Makes sure that each parameter has a unique name. For any - // parameter 'x' that occurs more than once, renames the instances - // "x1", "x2", etc. - void Differentiate(); + // Makes sure that each parameter has a unique name. For any + // parameter 'x' that occurs more than once, renames the instances + // "x1", "x2", etc. + void Differentiate(); - // Maps ZAM_OperandClass's to their associated C++ type and - // canonical parameter name. - static std::unordered_map> oc_to_args; + // Maps ZAM_OperandClass's to their associated C++ type and + // canonical parameter name. + static std::unordered_map> oc_to_args; - // For a single argument/parameter, tracks its declaration name, - // C++ type, and the name to use when providing it as a parameter. - // We have two names because in some contexts record fields have - // different names in declarations vs. in parameter lists. - struct Arg - { - string decl_name; - string decl_type; - string param_name; - }; + // For a single argument/parameter, tracks its declaration name, + // C++ type, and the name to use when providing it as a parameter. + // We have two names because in some contexts record fields have + // different names in declarations vs. in parameter lists. + struct Arg { + string decl_name; + string decl_type; + string param_name; + }; - // All of the argument/parameters associated with the collection - // of ZAM_OperandClass's. - vector args; + // All of the argument/parameters associated with the collection + // of ZAM_OperandClass's. + vector args; - // Each of the individual parameters. - vector params; + // Each of the individual parameters. + vector params; - // See Decls() and Params() above. - string full_decl; - string full_params; - }; + // See Decls() and Params() above. + string full_decl; + string full_params; +}; // There are two mutually interacting classes: ZAMGen is the overall driver // for the ZAM generator, while ZAM_OpTemplate represents a single operation // template, with subclasses for specific types of operations. class ZAMGen; -class ZAM_OpTemplate - { +class ZAM_OpTemplate { public: - // Instantiated by passing in the ZAMGen driver and the generic - // name for the operation. - ZAM_OpTemplate(ZAMGen* _g, string _base_name); - virtual ~ZAM_OpTemplate() { } + // Instantiated by passing in the ZAMGen driver and the generic + // name for the operation. + ZAM_OpTemplate(ZAMGen* _g, string _base_name); + virtual ~ZAM_OpTemplate() {} - // Constructs the template's data structures by parsing its - // description (beyond the initial description of the type of - // operation). - void Build(); + // Constructs the template's data structures by parsing its + // description (beyond the initial description of the type of + // operation). + void Build(); - // Tells the object to generate the code/files necessary for - // each of its underlying instructions. - virtual void Instantiate(); + // Tells the object to generate the code/files necessary for + // each of its underlying instructions. + virtual void Instantiate(); - // Returns the generic name for the operation. - const string& BaseName() const { return base_name; } + // Returns the generic name for the operation. + const string& BaseName() const { return base_name; } - // Returns the canonical name for the operation. This is a - // version of the name that, for expression-based operations, - // can be concatenated with "EXPR_" to get the name of the - // corresponding AST node. - const string& CanonicalName() const { return cname; } + // Returns the canonical name for the operation. This is a + // version of the name that, for expression-based operations, + // can be concatenated with "EXPR_" to get the name of the + // corresponding AST node. + const string& CanonicalName() const { return cname; } - // Returns a string version of the ZAMOp1Flavor associated - // with this operation. - const string& GetOp1Flavor() const { return op1_flavor; } + // Returns a string version of the ZAMOp1Flavor associated + // with this operation. + const string& GetOp1Flavor() const { return op1_flavor; } - // True if this operation has side effects (see OpSideEffects above). - bool HasSideEffects() const { return has_side_effects; } + // True if this operation has side effects (see OpSideEffects above). + bool HasSideEffects() const { return has_side_effects; } - // True if this operation has a predicate form (i.e., yields a - // boolean value that can be used in conditionals). - void SetIsPredicate() { is_predicate = true; } - bool IsPredicate() const { return is_predicate; } + // True if this operation has a predicate form (i.e., yields a + // boolean value that can be used in conditionals). + void SetIsPredicate() { is_predicate = true; } + bool IsPredicate() const { return is_predicate; } - // The number of operands the operation takes (not including its - // assignment target). A value of 0 is used for operations that - // require special handling. - virtual int Arity() const { return 0; } + // The number of operands the operation takes (not including its + // assignment target). A value of 0 is used for operations that + // require special handling. + virtual int Arity() const { return 0; } protected: - // Do instantiation for predicate operations. - void InstantiatePredicate(); - - // Retrieve the list of operand classes associated with this operation. - const OCVec& OperandClasses() const { return op_classes; } - - // Specify the ZAMOp1Flavor associated with this operation. See - // GetOp1Flavor() above for the corresponding accessor. - void SetOp1Flavor(string fl) { op1_flavor = fl; } - - // Specify/fetch the parameter (operand) from which to take the - // primary type of this operation. - void SetTypeParam(int param) { type_param = param; } - const auto& GetTypeParam() const { return type_param; } - - // Specify/fetch the parameter (operand) from which to take the - // secondary type of this operation. - void SetType2Param(int param) { type2_param = param; } - const auto& GetType2Param() const { return type2_param; } - - // Tracking of assignment values (C++ variables that hold the - // value that should be assigned to usual frame slot). - void SetAssignVal(string _av) { av = _av; } - bool HasAssignVal() const { return ! av.empty(); } - const string& GetAssignVal() const { return av; } - - // Management of C++ evaluation blocks. These are built up - // line-by-line. - void AddEval(string line) { eval += line; } - bool HasEval() const { return ! eval.empty(); } - const string& GetEval() const { return eval; } - - // Management of custom methods to be used rather than generating - // a method. - void SetCustomMethod(string cm) { custom_method = SkipWS(cm); } - bool HasCustomMethod() const { return ! custom_method.empty(); } - const string& GetCustomMethod() const { return custom_method; } - - // Management of code to execute at the end of a generated method. - void SetPostMethod(string cm) { post_method = SkipWS(cm); } - bool HasPostMethod() const { return ! post_method.empty(); } - const string& GetPostMethod() const { return post_method; } - - // Predicates indicating whether a subclass supports a given - // property. These are whether the operation: (1) should include - // a version that assigns to a record field as well as the normal - // assigning to a frame slot, (2) is a conditional branch, (3) does - // not have a corresponding AST node, (4) is a direct assignment - // (not an assignment to an expression), (5) is a direct assignment - // to a record field. - virtual bool IncludesFieldOp() const { return false; } - virtual bool IsConditionalOp() const { return false; } - virtual bool IsInternalOp() const { return false; } - virtual bool IsAssignOp() const { return false; } - virtual bool IsFieldOp() const { return false; } - - // Whether this operation does not have any C++ evaluation associated - // with it. Used for custom methods that compile into internal - // ZAM operations. - bool NoEval() const { return no_eval; } - void SetNoEval() { no_eval = true; } - - // Whether this operation does not have a version where one of - // its operands is a constant. - bool NoConst() const { return no_const; } - void SetNoConst() { no_const = true; } - - // Whether this operation also has a vectorized form. - bool IncludesVectorOp() const { return includes_vector_op; } - void SetIncludesVectorOp() { includes_vector_op = true; } - - // Whether this operation has side effects, and thus should - // not be elided even if its result is used in a dead assignment. - void SetHasSideEffects() { has_side_effects = true; } - - // An "assignment-less" operation is one that, if its result - // is used in a dead assignment, should be converted to a different - // operation that explictly omits any assignment. - bool HasAssignmentLess() const { return ! assignment_less_op.empty(); } - void SetAssignmentLess(string op, string op_class) - { - assignment_less_op = op; - assignment_less_op_class = op_class; - } - const string& AssignmentLessOp() const { return assignment_less_op; } - const string& AssignmentLessOpClass() const { return assignment_less_op_class; } - - // Builds the instructions associated with this operation, assuming - // a single operand. - void UnaryInstantiate(); - - // Parses the next line in an operation template. "attr" is - // the first word on the line, which often specifies the - // attribute specified by the line. "line" is the entire line, - // for parsing when that's necessary, and for error reporting. - // "words" is "line" split into a vector of whitespace-delimited - // words. - virtual void Parse(const string& attr, const string& line, const Words& words); - - // Helper function that parses "class" specifications. - OCVec ParseClass(const string& spec) const; - - // Scans in a C++ evaluation block, which continues until encountering - // a line that does not start with whitespace, or that's empty. - string GatherEval(); - - // Parses a $-specifier of which operand to use to associate - // a Zeek scripting type with ZAM instructions. - int ExtractTypeParam(const string& arg); - - // Generates instructions for each of the different flavors of the - // given operation. "oc" specifies the classes of operands for the - // instruction, and "do_vec" whether to generate a vector version. - void InstantiateOp(const OCVec& oc, bool do_vec); - - // Generates one specific flavor ("zc") of the given operation, - // using a method named 'm', the given operand classes, and the - // instruction class. - void InstantiateOp(const string& m, const OCVec& oc, ZAM_InstClass zc); - - // Generates the "assignment-less" version of the given op-code. - void GenAssignmentlessVersion(const string& op); - - // Generates the method 'm' for an operation, where "suffix" is - // a (potentially empty) string differentiating the method from - // others for that operation, and "oc" and "zc" are the same - // as above. - void InstantiateMethod(const string& m, const string& suffix, const OCVec& oc, - ZAM_InstClass zc); - - // Generates the main logic of an operation's method, given the - // specific operand classes, an associated suffix for differentiating - // ZAM instructions, and the instruction class. - void InstantiateMethodCore(const OCVec& oc, const string& suffix, ZAM_InstClass zc); - - // Generates the specific code to create a ZInst for the given - // operation, operands, parameters to "GenInst", and suffix and - // class per the above. - virtual void BuildInstruction(const OCVec& oc, const string& params, - const string& suffix, ZAM_InstClass zc); - - // Expands $-parameters into their direct representations given the - // operand classes and associated accessors. - string ExpandParams(const OCVec& oc, string eval, const vector& accessors) const; - string ExpandParams(const OCVec& oc, string eval) const - { - vector no_accessors; - return ExpandParams(oc, std::move(eval), no_accessors); - } - - // Top-level driver for generating the C++ evaluation code for - // a given flavor of operation. - virtual void InstantiateEval(const OCVec& oc, const string& suffix, - ZAM_InstClass zc); - - // Generates the C++ case statement for evaluating the given flavor - // of operation. - void GenEval(EmitTarget et, const string& ot_str, const string& op_suffix, const string& eval, - ZAM_InstClass zc); - - // Generates a description of the ZAM operation suitable for - // reflection. - void GenDesc(const string& op_code, const string& ot_str, const string& eval); - - // Generates the first part of a description, up to (but not including) - // the evaluation. - void StartDesc(const string& op_code, const string& ot_str); - - // Finishes a description, once the evaluation is done. - void EndDesc(); - - // Generates a set of assignment C++ evaluations, one per each - // possible Zeek scripting type of operand. - void InstantiateAssignOp(const OCVec& oc, const string& suffix); - - // Generates a C++ evaluation for an assignment of the type - // corresponding to "accessor". If "is_managed" is true then - // generates the associated memory management, too. - void GenAssignOpCore(const OCVec& oc, const string& eval, - const string& accessor, bool is_managed); - - // The same, but for when there's an explicit assignment value. - void GenAssignOpValCore(const OCVec& oc, const string& eval, const string& accessor, bool is_managed); - - // Returns the name of the method associated with the particular - // list of operand classes. - string MethodName(const OCVec& oc) const; - - // Returns the parameter declarations to use in declaring a method. - string MethodDeclare(const OCVec& oc, ZAM_InstClass zc); - - // Returns a suffix that differentiates an operation name for - // a specific list of operand classes. - string OpSuffix(const OCVec& oc) const; - - // Returns a copy of the given string with leading whitespace - // removed. - string SkipWS(const string& s) const; - - // Set the target to use for subsequent code emission. - void EmitTo(EmitTarget et) { curr_et = et; } - - // Emit the given string to the currently selected EmitTarget. - void Emit(const string& s); - - // Same, but temporarily indented up. - void EmitUp(const string& s) - { - IndentUp(); - Emit(s); - IndentDown(); - } - - // Same, but reframe from inserting a newline. - void EmitNoNL(const string& s); - - // Emit a newline. Implementation doesn't actually include a - // newline since that's implicit in a call to Emit(). - void NL() { Emit(""); } - - // Increase/decrease the indentation level, with the last two - // being used for brace-delimited code blocks. - void IndentUp(); - void IndentDown(); - void BeginBlock() - { - IndentUp(); - Emit("{"); - } - void EndBlock() - { - Emit("}"); - IndentDown(); - } - - // Start/finish emiting a (likely multi-line) string literal - - // see corresponding ZAMGen methods. - void StartString(); - void EndString(); - - // Exit with an error, mainly for consistency-checking. - void Gripe(const char* msg) const; - void Gripe(string msg, string addl) const; - - // Maps an operand class to a character mnemonic used to distinguish - // it from others. - static std::unordered_map oc_to_char; - - // The associated driver object. - ZAMGen* g; - - // See BaseName() and CanonicalName() above. - string base_name; - string cname; - - // Tracks the beginning of this operation template's definition, - // for error reporting. - InputLoc op_loc; - - // The current emission target. - EmitTarget curr_et = None; - - // The operand classes for operations that have a single fixed list. - // Some operations (like those evaluating expressions) instead have - // dynamically generated range of possible operand classes. - OCVec op_classes; - - // For operations that have several fixed operand sets to work through. - vector op_classes_vec; - - // If non-empty, the ZAM types associated with each operand, - // left-to-right mirroring the order of the op_classes. - vector op_types; - - // The following is usually empty, but can be instantiated when - // iterating across "types" that in some instances include ZAM_OC_INT, - // in which case those will have ".int_val" accessors associated - // with those slots. - vector accessors; - - // See the description of Op1Flavor above. - string op1_flavor = "OP1_WRITE"; - - // Tracks the result of ExtractTypeParam() used for "type" and - // "type2" attributes. - std::optional type_param; - std::optional type2_param; - - // If non-empty, the value to assign to the target in an assignment - // operation. - string av; - - // The C++ evaluation; may span multiple lines. - string eval; - - // Postlog C++ code (currently only used in support of profiling). - string post_eval; - - // Any associated custom method. - string custom_method; - - // Any associated additional code to add at the end of a - // generated method. - string post_method; - - // If true, then this operation does not have C++ evaluation - // associated with it. - bool no_eval = false; - - // If true, then this operation should not include a version - // supporting operands of constant type. - bool no_const = false; - - // If true, then this operation includes a vectorized version. - bool includes_vector_op = false; - - // If true, then this operation has side effects. - bool has_side_effects = false; - - // Whether to instantiate this operation as a predicate, which - // results in three versions: (1) assignment of the evaluation to - // a (integer-typed) target, (2) branch if the evaluation *is not* - // the case, (3) branch if the evaluation *is* the case. - bool is_predicate = false; - - // If non-empty, then specifies the associated operation that - // is a version of this operation but without assigning the result; - // and the operand class (like "OP_V") of that associated operation. - string assignment_less_op; - string assignment_less_op_class; - }; + // Do instantiation for predicate operations. + void InstantiatePredicate(); + + // Retrieve the list of operand classes associated with this operation. + const OCVec& OperandClasses() const { return op_classes; } + + // Specify the ZAMOp1Flavor associated with this operation. See + // GetOp1Flavor() above for the corresponding accessor. + void SetOp1Flavor(string fl) { op1_flavor = fl; } + + // Specify/fetch the parameter (operand) from which to take the + // primary type of this operation. + void SetTypeParam(int param) { type_param = param; } + const auto& GetTypeParam() const { return type_param; } + + // Specify/fetch the parameter (operand) from which to take the + // secondary type of this operation. + void SetType2Param(int param) { type2_param = param; } + const auto& GetType2Param() const { return type2_param; } + + // Tracking of assignment values (C++ variables that hold the + // value that should be assigned to usual frame slot). + void SetAssignVal(string _av) { av = _av; } + bool HasAssignVal() const { return ! av.empty(); } + const string& GetAssignVal() const { return av; } + + // Management of C++ evaluation blocks. These are built up + // line-by-line. + void AddEval(string line) { eval += line; } + bool HasEval() const { return ! eval.empty(); } + const string& GetEval() const { return eval; } + + // Management of custom methods to be used rather than generating + // a method. + void SetCustomMethod(string cm) { custom_method = SkipWS(cm); } + bool HasCustomMethod() const { return ! custom_method.empty(); } + const string& GetCustomMethod() const { return custom_method; } + + // Management of code to execute at the end of a generated method. + void SetPostMethod(string cm) { post_method = SkipWS(cm); } + bool HasPostMethod() const { return ! post_method.empty(); } + const string& GetPostMethod() const { return post_method; } + + // Predicates indicating whether a subclass supports a given + // property. These are whether the operation: (1) should include + // a version that assigns to a record field as well as the normal + // assigning to a frame slot, (2) is a conditional branch, (3) does + // not have a corresponding AST node, (4) is a direct assignment + // (not an assignment to an expression), (5) is a direct assignment + // to a record field. + virtual bool IncludesFieldOp() const { return false; } + virtual bool IsConditionalOp() const { return false; } + virtual bool IsInternalOp() const { return false; } + virtual bool IsAssignOp() const { return false; } + virtual bool IsFieldOp() const { return false; } + + // Whether this operation does not have any C++ evaluation associated + // with it. Used for custom methods that compile into internal + // ZAM operations. + bool NoEval() const { return no_eval; } + void SetNoEval() { no_eval = true; } + + // Whether this operation does not have a version where one of + // its operands is a constant. + bool NoConst() const { return no_const; } + void SetNoConst() { no_const = true; } + + // Whether this operation also has a vectorized form. + bool IncludesVectorOp() const { return includes_vector_op; } + void SetIncludesVectorOp() { includes_vector_op = true; } + + // Whether this operation has side effects, and thus should + // not be elided even if its result is used in a dead assignment. + void SetHasSideEffects() { has_side_effects = true; } + + // An "assignment-less" operation is one that, if its result + // is used in a dead assignment, should be converted to a different + // operation that explictly omits any assignment. + bool HasAssignmentLess() const { return ! assignment_less_op.empty(); } + void SetAssignmentLess(string op, string op_class) { + assignment_less_op = op; + assignment_less_op_class = op_class; + } + const string& AssignmentLessOp() const { return assignment_less_op; } + const string& AssignmentLessOpClass() const { return assignment_less_op_class; } + + // Builds the instructions associated with this operation, assuming + // a single operand. + void UnaryInstantiate(); + + // Parses the next line in an operation template. "attr" is + // the first word on the line, which often specifies the + // attribute specified by the line. "line" is the entire line, + // for parsing when that's necessary, and for error reporting. + // "words" is "line" split into a vector of whitespace-delimited + // words. + virtual void Parse(const string& attr, const string& line, const Words& words); + + // Helper function that parses "class" specifications. + OCVec ParseClass(const string& spec) const; + + // Scans in a C++ evaluation block, which continues until encountering + // a line that does not start with whitespace, or that's empty. + string GatherEval(); + + // Parses a $-specifier of which operand to use to associate + // a Zeek scripting type with ZAM instructions. + int ExtractTypeParam(const string& arg); + + // Generates instructions for each of the different flavors of the + // given operation. "oc" specifies the classes of operands for the + // instruction, and "do_vec" whether to generate a vector version. + void InstantiateOp(const OCVec& oc, bool do_vec); + + // Generates one specific flavor ("zc") of the given operation, + // using a method named 'm', the given operand classes, and the + // instruction class. + void InstantiateOp(const string& m, const OCVec& oc, ZAM_InstClass zc); + + // Generates the "assignment-less" version of the given op-code. + void GenAssignmentlessVersion(const string& op); + + // Generates the method 'm' for an operation, where "suffix" is + // a (potentially empty) string differentiating the method from + // others for that operation, and "oc" and "zc" are the same + // as above. + void InstantiateMethod(const string& m, const string& suffix, const OCVec& oc, ZAM_InstClass zc); + + // Generates the main logic of an operation's method, given the + // specific operand classes, an associated suffix for differentiating + // ZAM instructions, and the instruction class. + void InstantiateMethodCore(const OCVec& oc, const string& suffix, ZAM_InstClass zc); + + // Generates the specific code to create a ZInst for the given + // operation, operands, parameters to "GenInst", and suffix and + // class per the above. + virtual void BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc); + + // Expands $-parameters into their direct representations given the + // operand classes and associated accessors. + string ExpandParams(const OCVec& oc, string eval, const vector& accessors) const; + string ExpandParams(const OCVec& oc, string eval) const { + vector no_accessors; + return ExpandParams(oc, std::move(eval), no_accessors); + } + + // Top-level driver for generating the C++ evaluation code for + // a given flavor of operation. + virtual void InstantiateEval(const OCVec& oc, const string& suffix, ZAM_InstClass zc); + + // Generates the C++ case statement for evaluating the given flavor + // of operation. + void GenEval(EmitTarget et, const string& ot_str, const string& op_suffix, const string& eval, ZAM_InstClass zc); + + // Generates a description of the ZAM operation suitable for + // reflection. + void GenDesc(const string& op_code, const string& ot_str, const string& eval); + + // Generates the first part of a description, up to (but not including) + // the evaluation. + void StartDesc(const string& op_code, const string& ot_str); + + // Finishes a description, once the evaluation is done. + void EndDesc(); + + // Generates a set of assignment C++ evaluations, one per each + // possible Zeek scripting type of operand. + void InstantiateAssignOp(const OCVec& oc, const string& suffix); + + // Generates a C++ evaluation for an assignment of the type + // corresponding to "accessor". If "is_managed" is true then + // generates the associated memory management, too. + void GenAssignOpCore(const OCVec& oc, const string& eval, const string& accessor, bool is_managed); + + // The same, but for when there's an explicit assignment value. + void GenAssignOpValCore(const OCVec& oc, const string& eval, const string& accessor, bool is_managed); + + // Returns the name of the method associated with the particular + // list of operand classes. + string MethodName(const OCVec& oc) const; + + // Returns the parameter declarations to use in declaring a method. + string MethodDeclare(const OCVec& oc, ZAM_InstClass zc); + + // Returns a suffix that differentiates an operation name for + // a specific list of operand classes. + string OpSuffix(const OCVec& oc) const; + + // Returns a copy of the given string with leading whitespace + // removed. + string SkipWS(const string& s) const; + + // Set the target to use for subsequent code emission. + void EmitTo(EmitTarget et) { curr_et = et; } + + // Emit the given string to the currently selected EmitTarget. + void Emit(const string& s); + + // Same, but temporarily indented up. + void EmitUp(const string& s) { + IndentUp(); + Emit(s); + IndentDown(); + } + + // Same, but reframe from inserting a newline. + void EmitNoNL(const string& s); + + // Emit a newline. Implementation doesn't actually include a + // newline since that's implicit in a call to Emit(). + void NL() { Emit(""); } + + // Increase/decrease the indentation level, with the last two + // being used for brace-delimited code blocks. + void IndentUp(); + void IndentDown(); + void BeginBlock() { + IndentUp(); + Emit("{"); + } + void EndBlock() { + Emit("}"); + IndentDown(); + } + + // Start/finish emiting a (likely multi-line) string literal - + // see corresponding ZAMGen methods. + void StartString(); + void EndString(); + + // Exit with an error, mainly for consistency-checking. + void Gripe(const char* msg) const; + void Gripe(string msg, string addl) const; + + // Maps an operand class to a character mnemonic used to distinguish + // it from others. + static std::unordered_map oc_to_char; + + // The associated driver object. + ZAMGen* g; + + // See BaseName() and CanonicalName() above. + string base_name; + string cname; + + // Tracks the beginning of this operation template's definition, + // for error reporting. + InputLoc op_loc; + + // The current emission target. + EmitTarget curr_et = None; + + // The operand classes for operations that have a single fixed list. + // Some operations (like those evaluating expressions) instead have + // dynamically generated range of possible operand classes. + OCVec op_classes; + + // For operations that have several fixed operand sets to work through. + vector op_classes_vec; + + // If non-empty, the ZAM types associated with each operand, + // left-to-right mirroring the order of the op_classes. + vector op_types; + + // The following is usually empty, but can be instantiated when + // iterating across "types" that in some instances include ZAM_OC_INT, + // in which case those will have ".int_val" accessors associated + // with those slots. + vector accessors; + + // See the description of Op1Flavor above. + string op1_flavor = "OP1_WRITE"; + + // Tracks the result of ExtractTypeParam() used for "type" and + // "type2" attributes. + std::optional type_param; + std::optional type2_param; + + // If non-empty, the value to assign to the target in an assignment + // operation. + string av; + + // The C++ evaluation; may span multiple lines. + string eval; + + // Postlog C++ code (currently only used in support of profiling). + string post_eval; + + // Any associated custom method. + string custom_method; + + // Any associated additional code to add at the end of a + // generated method. + string post_method; + + // If true, then this operation does not have C++ evaluation + // associated with it. + bool no_eval = false; + + // If true, then this operation should not include a version + // supporting operands of constant type. + bool no_const = false; + + // If true, then this operation includes a vectorized version. + bool includes_vector_op = false; + + // If true, then this operation has side effects. + bool has_side_effects = false; + + // Whether to instantiate this operation as a predicate, which + // results in three versions: (1) assignment of the evaluation to + // a (integer-typed) target, (2) branch if the evaluation *is not* + // the case, (3) branch if the evaluation *is* the case. + bool is_predicate = false; + + // If non-empty, then specifies the associated operation that + // is a version of this operation but without assigning the result; + // and the operand class (like "OP_V") of that associated operation. + string assignment_less_op; + string assignment_less_op_class; +}; // A subclass used for "unary-op" templates. -class ZAM_UnaryOpTemplate : public ZAM_OpTemplate - { +class ZAM_UnaryOpTemplate : public ZAM_OpTemplate { public: - ZAM_UnaryOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, _base_name) { } + ZAM_UnaryOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, _base_name) {} protected: - void Instantiate() override; - }; + void Instantiate() override; +}; // A subclass for unary operations that are directly instantiated using // custom methods. -class ZAM_DirectUnaryOpTemplate : public ZAM_OpTemplate - { +class ZAM_DirectUnaryOpTemplate : public ZAM_OpTemplate { public: - ZAM_DirectUnaryOpTemplate(ZAMGen* _g, string _base_name, string _direct) - : ZAM_OpTemplate(_g, _base_name), direct(_direct) - { - } + ZAM_DirectUnaryOpTemplate(ZAMGen* _g, string _base_name, string _direct) + : ZAM_OpTemplate(_g, _base_name), direct(_direct) {} protected: - void Instantiate() override; + void Instantiate() override; private: - // The ZAMCompiler method to call to compile the operation. - string direct; - }; + // The ZAMCompiler method to call to compile the operation. + string direct; +}; // A helper class for the ZAM_ExprOpTemplate class (which follows). // This class tracks a single instance of creating an evaluation for // an AST expression. -class EvalInstance - { +class EvalInstance { public: - // Initialized using the types of the LHS (result) and the - // first and second operand. Often all three types are the - // same, but they can differ for some particular expressions, - // and for relationals. "eval" provides the C++ evaluation code. - // "is_def" is true if this instance is for the default catch-all - // where the operand types don't match any of the explicitly - // specified evaluations; - EvalInstance(ZAM_Type lhs_et, ZAM_Type op1_et, ZAM_Type op2_et, string eval, - bool is_def); + // Initialized using the types of the LHS (result) and the + // first and second operand. Often all three types are the + // same, but they can differ for some particular expressions, + // and for relationals. "eval" provides the C++ evaluation code. + // "is_def" is true if this instance is for the default catch-all + // where the operand types don't match any of the explicitly + // specified evaluations; + EvalInstance(ZAM_Type lhs_et, ZAM_Type op1_et, ZAM_Type op2_et, string eval, bool is_def); - // Returns the accessor to use for assigning to the LHS. "is_ptr" - // indicates whether the value to which we're applying the - // accessor is a pointer, rather than a ZVal. - string LHSAccessor(bool is_ptr = false) const; + // Returns the accessor to use for assigning to the LHS. "is_ptr" + // indicates whether the value to which we're applying the + // accessor is a pointer, rather than a ZVal. + string LHSAccessor(bool is_ptr = false) const; - // Same but for access to the first or second operand. - string Op1Accessor(bool is_ptr = false) const { return Accessor(op1_et, is_ptr); } - string Op2Accessor(bool is_ptr = false) const { return Accessor(op2_et, is_ptr); } + // Same but for access to the first or second operand. + string Op1Accessor(bool is_ptr = false) const { return Accessor(op1_et, is_ptr); } + string Op2Accessor(bool is_ptr = false) const { return Accessor(op2_et, is_ptr); } - // Provides an accessor for an operand of the given type. - string Accessor(ZAM_Type zt, bool is_ptr = false) const; + // Provides an accessor for an operand of the given type. + string Accessor(ZAM_Type zt, bool is_ptr = false) const; - // Returns the "marker" use to make unique the opcode for this - // flavor of expression-evaluation instruction. - string OpMarker() const; + // Returns the "marker" use to make unique the opcode for this + // flavor of expression-evaluation instruction. + string OpMarker() const; - const string& Eval() const { return eval; } - bool IsDefault() const { return is_def; } + const string& Eval() const { return eval; } + bool IsDefault() const { return is_def; } - ZAM_Type LHS_ET() const { return lhs_et; } - ZAM_Type Op1_ET() const { return op1_et; } - ZAM_Type Op2_ET() const { return op2_et; } + ZAM_Type LHS_ET() const { return lhs_et; } + ZAM_Type Op1_ET() const { return op1_et; } + ZAM_Type Op2_ET() const { return op2_et; } private: - ZAM_Type lhs_et; - ZAM_Type op1_et; - ZAM_Type op2_et; - string eval; - bool is_def; - }; + ZAM_Type lhs_et; + ZAM_Type op1_et; + ZAM_Type op2_et; + string eval; + bool is_def; +}; // A subclass for AST "Expr" nodes in reduced form. -class ZAM_ExprOpTemplate : public ZAM_OpTemplate - { +class ZAM_ExprOpTemplate : public ZAM_OpTemplate { public: - ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name); + ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name); - int HasExplicitResultType() const { return explicit_res_type; } - void SetHasExplicitResultType() { explicit_res_type = true; } + int HasExplicitResultType() const { return explicit_res_type; } + void SetHasExplicitResultType() { explicit_res_type = true; } - void AddExprType(ZAM_Type zt) { expr_types.insert(zt); } - const std::unordered_set& ExprTypes() const { return expr_types; } + void AddExprType(ZAM_Type zt) { expr_types.insert(zt); } + const std::unordered_set& ExprTypes() const { return expr_types; } - void AddEvalSet(ZAM_Type zt, string ev) { eval_set[zt] += ev; } - void AddEvalSet(ZAM_Type et1, ZAM_Type et2, string ev) - { - eval_mixed_set[et1][et2] += ev; - } + void AddEvalSet(ZAM_Type zt, string ev) { eval_set[zt] += ev; } + void AddEvalSet(ZAM_Type et1, ZAM_Type et2, string ev) { eval_mixed_set[et1][et2] += ev; } - bool IncludesFieldOp() const override { return includes_field_op; } - void SetIncludesFieldOp() { includes_field_op = true; } + bool IncludesFieldOp() const override { return includes_field_op; } + void SetIncludesFieldOp() { includes_field_op = true; } - bool HasPreCheck() const { return ! pre_check.empty(); } - void SetPreCheck(string pe) { pre_check = SkipWS(pe); } - const string& GetPreCheck() const { return pre_check; } + bool HasPreCheck() const { return ! pre_check.empty(); } + void SetPreCheck(string pe) { pre_check = SkipWS(pe); } + const string& GetPreCheck() const { return pre_check; } - bool HasPreCheckAction() const { return ! pre_check_action.empty(); } - void SetPreCheckAction(string pe) { pre_check_action = SkipWS(pe); } - const string& GetPreCheckAction() const { return pre_check_action; } + bool HasPreCheckAction() const { return ! pre_check_action.empty(); } + void SetPreCheckAction(string pe) { pre_check_action = SkipWS(pe); } + const string& GetPreCheckAction() const { return pre_check_action; } protected: - // Returns a regular expression used to access the value of the - // expression suitable for assignment in a loop across the elements - // of a Zeek "vector" type. "have_target" is true if the template - // has an explicit "$$" assignment target. - virtual const char* VecEvalRE(bool have_target) const - { - return have_target ? "$$$$ = ZVal($1)" : "ZVal($&)"; - } + // Returns a regular expression used to access the value of the + // expression suitable for assignment in a loop across the elements + // of a Zeek "vector" type. "have_target" is true if the template + // has an explicit "$$" assignment target. + virtual const char* VecEvalRE(bool have_target) const { return have_target ? "$$$$ = ZVal($1)" : "ZVal($&)"; } - void Parse(const string& attr, const string& line, const Words& words) override; - void Instantiate() override; + void Parse(const string& attr, const string& line, const Words& words) override; + void Instantiate() override; - // Instantiates versions of the operation that have a constant - // as the first, second, or third operand ... - void InstantiateC1(const OCVec& ocs, size_t arity); - void InstantiateC2(const OCVec& ocs, size_t arity); - void InstantiateC3(const OCVec& ocs); + // Instantiates versions of the operation that have a constant + // as the first, second, or third operand ... + void InstantiateC1(const OCVec& ocs, size_t arity); + void InstantiateC2(const OCVec& ocs, size_t arity); + void InstantiateC3(const OCVec& ocs); - // ... or if all of the operands are non-constant. - void InstantiateV(const OCVec& ocs); + // ... or if all of the operands are non-constant. + void InstantiateV(const OCVec& ocs); - // Generates code that instantiates either the vectorized version - // of an operation, or the non-vector one, depending on whether - // the RHS of the reduced expression/assignment is a vector. - void DoVectorCase(const string& m, const string& args); + // Generates code that instantiates either the vectorized version + // of an operation, or the non-vector one, depending on whether + // the RHS of the reduced expression/assignment is a vector. + void DoVectorCase(const string& m, const string& args); - // Iterates over the different Zeek types specified for an expression's - // operands and generates instructions for each. - void BuildInstructionCore(const string& params, const string& suffix, ZAM_InstClass zc); + // Iterates over the different Zeek types specified for an expression's + // operands and generates instructions for each. + void BuildInstructionCore(const string& params, const string& suffix, ZAM_InstClass zc); - // Generates an if-else cascade element that matches one of the - // specific Zeek types associated with the instruction. - void GenMethodTest(ZAM_Type et1, ZAM_Type et2, const string& params, - const string& suffix, bool do_else, ZAM_InstClass zc); + // Generates an if-else cascade element that matches one of the + // specific Zeek types associated with the instruction. + void GenMethodTest(ZAM_Type et1, ZAM_Type et2, const string& params, const string& suffix, bool do_else, + ZAM_InstClass zc); - void InstantiateEval(const OCVec& oc, const string& suffix, - ZAM_InstClass zc) override; + void InstantiateEval(const OCVec& oc, const string& suffix, ZAM_InstClass zc) override; private: - // The Zeek types that can appear as operands for the expression. - std::unordered_set expr_types; + // The Zeek types that can appear as operands for the expression. + std::unordered_set expr_types; - // The C++ evaluation template for a given operand type. - std::unordered_map eval_set; + // The C++ evaluation template for a given operand type. + std::unordered_map eval_set; - // Some expressions take two operands of different types. This - // holds their C++ evaluation template. - std::unordered_map> eval_mixed_set; + // Some expressions take two operands of different types. This + // holds their C++ evaluation template. + std::unordered_map> eval_mixed_set; - // Whether this expression's operand is a field access (and thus - // needs both the record as an operand and an additional constant - // offset into the record to get to the field). - bool includes_field_op = false; + // Whether this expression's operand is a field access (and thus + // needs both the record as an operand and an additional constant + // offset into the record to get to the field). + bool includes_field_op = false; - // If non-empty, a check to conduct before evaluating the expression ... - string pre_check; + // If non-empty, a check to conduct before evaluating the expression ... + string pre_check; - // ... and the action to take if the check is true, *instead* of - // evaluating the expression. - string pre_check_action; + // ... and the action to take if the check is true, *instead* of + // evaluating the expression. + string pre_check_action; - // If true, then the evaluations will take care of ensuring - // proper result types when assigning to $$. - bool explicit_res_type = false; - }; + // If true, then the evaluations will take care of ensuring + // proper result types when assigning to $$. + bool explicit_res_type = false; +}; // A version of ZAM_ExprOpTemplate for unary expressions. -class ZAM_UnaryExprOpTemplate : public ZAM_ExprOpTemplate - { +class ZAM_UnaryExprOpTemplate : public ZAM_ExprOpTemplate { public: - ZAM_UnaryExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_ExprOpTemplate(_g, _base_name) { } + ZAM_UnaryExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_ExprOpTemplate(_g, _base_name) {} - bool IncludesFieldOp() const override { return ExprTypes().count(ZAM_TYPE_NONE) == 0; } + bool IncludesFieldOp() const override { return ExprTypes().count(ZAM_TYPE_NONE) == 0; } - int Arity() const override { return 1; } + int Arity() const override { return 1; } protected: - void Parse(const string& attr, const string& line, const Words& words) override; - void Instantiate() override; + void Parse(const string& attr, const string& line, const Words& words) override; + void Instantiate() override; - void BuildInstruction(const OCVec& oc, const string& params, - const string& suffix, ZAM_InstClass zc) override; - }; + void BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) override; +}; // A version of ZAM_UnaryExprOpTemplate where the point of the expression // is to capture a direct assignment operation. -class ZAM_AssignOpTemplate : public ZAM_UnaryExprOpTemplate - { +class ZAM_AssignOpTemplate : public ZAM_UnaryExprOpTemplate { public: - ZAM_AssignOpTemplate(ZAMGen* _g, string _base_name); + ZAM_AssignOpTemplate(ZAMGen* _g, string _base_name); - bool IsAssignOp() const override { return true; } - bool IncludesFieldOp() const override { return false; } - bool IsFieldOp() const override { return field_op; } - void SetFieldOp() { field_op = true; } + bool IsAssignOp() const override { return true; } + bool IncludesFieldOp() const override { return false; } + bool IsFieldOp() const override { return field_op; } + void SetFieldOp() { field_op = true; } protected: - void Parse(const string& attr, const string& line, const Words& words) override; - void Instantiate() override; + void Parse(const string& attr, const string& line, const Words& words) override; + void Instantiate() override; private: - bool field_op = false; - }; + bool field_op = false; +}; // A version of ZAM_ExprOpTemplate for binary expressions. -class ZAM_BinaryExprOpTemplate : public ZAM_ExprOpTemplate - { +class ZAM_BinaryExprOpTemplate : public ZAM_ExprOpTemplate { public: - ZAM_BinaryExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_ExprOpTemplate(_g, _base_name) { } + ZAM_BinaryExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_ExprOpTemplate(_g, _base_name) {} - bool IncludesFieldOp() const override { return true; } + bool IncludesFieldOp() const override { return true; } - int Arity() const override { return 2; } + int Arity() const override { return 2; } protected: - void Instantiate() override; + void Instantiate() override; - void BuildInstruction(const OCVec& oc, const string& params, - const string& suffix, ZAM_InstClass zc) override; + void BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) override; - void GenerateSecondTypeVars(const OCVec& oc, ZAM_InstClass zc); - }; + void GenerateSecondTypeVars(const OCVec& oc, ZAM_InstClass zc); +}; // A version of ZAM_BinaryExprOpTemplate for relationals. -class ZAM_RelationalExprOpTemplate : public ZAM_BinaryExprOpTemplate - { +class ZAM_RelationalExprOpTemplate : public ZAM_BinaryExprOpTemplate { public: - ZAM_RelationalExprOpTemplate(ZAMGen* _g, string _base_name) - : ZAM_BinaryExprOpTemplate(_g, _base_name) - { - } + ZAM_RelationalExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_BinaryExprOpTemplate(_g, _base_name) {} - bool IncludesFieldOp() const override { return false; } - bool IsConditionalOp() const override { return true; } + bool IncludesFieldOp() const override { return false; } + bool IsConditionalOp() const override { return true; } protected: - const char* VecEvalRE(bool have_target) const override - { - if ( have_target ) - return "$$$$ = ZVal(zeek_int_t($1))"; - else - return "ZVal(zeek_int_t($&))"; - } + const char* VecEvalRE(bool have_target) const override { + if ( have_target ) + return "$$$$ = ZVal(zeek_int_t($1))"; + else + return "ZVal(zeek_int_t($&))"; + } - void Instantiate() override; + void Instantiate() override; - void BuildInstruction(const OCVec& oc, const string& params, - const string& suffix, ZAM_InstClass zc) override; - }; + void BuildInstruction(const OCVec& oc, const string& params, const string& suffix, ZAM_InstClass zc) override; +}; // A version of ZAM_OpTemplate for operations used internally (and not // corresponding to AST elements). -class ZAM_InternalOpTemplate : public ZAM_OpTemplate - { +class ZAM_InternalOpTemplate : public ZAM_OpTemplate { public: - ZAM_InternalOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, _base_name) { } + ZAM_InternalOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, _base_name) {} - bool IsInternalOp() const override { return true; } + bool IsInternalOp() const override { return true; } protected: - void Parse(const string& attr, const string& line, const Words& words) override; + void Parse(const string& attr, const string& line, const Words& words) override; private: - void ParseCall(const string& line, const Words& words); + void ParseCall(const string& line, const Words& words); - // True if the internal operation corresponds to an indirect call, - // i.e., one through a variable rather than one directly specified. - bool is_indirect_call = false; + // True if the internal operation corresponds to an indirect call, + // i.e., one through a variable rather than one directly specified. + bool is_indirect_call = false; - // Refinement of is_indirect_call, when it's also via a local variable. - bool is_local_indirect_call = false; - }; + // Refinement of is_indirect_call, when it's also via a local variable. + bool is_local_indirect_call = false; +}; // An internal operation that assigns a result to a frame element. -class ZAM_InternalAssignOpTemplate : public ZAM_InternalOpTemplate - { +class ZAM_InternalAssignOpTemplate : public ZAM_InternalOpTemplate { public: - ZAM_InternalAssignOpTemplate(ZAMGen* _g, string _base_name) - : ZAM_InternalOpTemplate(_g, _base_name) - { - } + ZAM_InternalAssignOpTemplate(ZAMGen* _g, string _base_name) : ZAM_InternalOpTemplate(_g, _base_name) {} - bool IsAssignOp() const override { return true; } - }; + bool IsAssignOp() const override { return true; } +}; // Helper classes for managing input from the template file, including // low-level scanning. -class TemplateInput - { +class TemplateInput { public: - // Program name and file name are for generating error messages. - TemplateInput(FILE* _f, const char* _prog_name, const char* _file_name) - : f(_f), prog_name(_prog_name) - { - loc.file_name = _file_name; - } + // Program name and file name are for generating error messages. + TemplateInput(FILE* _f, const char* _prog_name, const char* _file_name) : f(_f), prog_name(_prog_name) { + loc.file_name = _file_name; + } - const InputLoc& CurrLoc() const { return loc; } + const InputLoc& CurrLoc() const { return loc; } - // Fetch the next line of input, including trailing newline. - // Returns true on success, false on EOF or error. Skips over - // comments. - bool ScanLine(string& line); + // Fetch the next line of input, including trailing newline. + // Returns true on success, false on EOF or error. Skips over + // comments. + bool ScanLine(string& line); - // Takes a line and splits it into white-space delimited words, - // returned in a vector. Removes trailing whitespace. - Words SplitIntoWords(const string& line) const; + // Takes a line and splits it into white-space delimited words, + // returned in a vector. Removes trailing whitespace. + Words SplitIntoWords(const string& line) const; - // Returns the line with the given number of initial words skipped. - string SkipWords(const string& line, int n) const; + // Returns the line with the given number of initial words skipped. + string SkipWords(const string& line, int n) const; - // Puts back the given line so that the next call to ScanLine will - // return it. Does not nest. - void PutBack(const string& line) { put_back = line; } + // Puts back the given line so that the next call to ScanLine will + // return it. Does not nest. + void PutBack(const string& line) { put_back = line; } - // Report an error and exit. - [[noreturn]] void Gripe(const char* msg, const string& input) const; - [[noreturn]] void Gripe(const char* msg, const InputLoc& loc) const; + // Report an error and exit. + [[noreturn]] void Gripe(const char* msg, const string& input) const; + [[noreturn]] void Gripe(const char* msg, const InputLoc& loc) const; private: - string put_back; // if non-empty, use this for the next ScanLine + string put_back; // if non-empty, use this for the next ScanLine - FILE* f; - const char* prog_name; - InputLoc loc; - }; + FILE* f; + const char* prog_name; + InputLoc loc; +}; // Driver class for the ZAM instruction generator. -class ZAMGen - { +class ZAMGen { public: - ZAMGen(int argc, char** argv); + ZAMGen(int argc, char** argv); - // Reads in and records a macro definition, which ends upon - // encountering a blank line or a line that does not begin - // with whitespace. - void ReadMacro(const string& line); + // Reads in and records a macro definition, which ends upon + // encountering a blank line or a line that does not begin + // with whitespace. + void ReadMacro(const string& line); - // Emits C++ #define's to implement the recorded macros. - void GenMacros(); + // Emits C++ #define's to implement the recorded macros. + void GenMacros(); - // Generates a ZAM op-code for the given template, suffix, and - // instruction class. Also creates auxiliary information associated - // with the instruction. - string GenOpCode(const ZAM_OpTemplate* ot, const string& suffix, - ZAM_InstClass zc = ZIC_REGULAR); + // Generates a ZAM op-code for the given template, suffix, and + // instruction class. Also creates auxiliary information associated + // with the instruction. + string GenOpCode(const ZAM_OpTemplate* ot, const string& suffix, ZAM_InstClass zc = ZIC_REGULAR); - // These methods provide low-level parsing (and error-reporting) - // access to ZAM_OpTemplate objects. - const InputLoc& CurrLoc() const { return ti->CurrLoc(); } - bool ScanLine(string& line) { return ti->ScanLine(line); } - Words SplitIntoWords(const string& line) const { return ti->SplitIntoWords(line); } - string SkipWords(const string& line, int n) const { return ti->SkipWords(line, n); } - void PutBack(const string& line) { ti->PutBack(line); } + // These methods provide low-level parsing (and error-reporting) + // access to ZAM_OpTemplate objects. + const InputLoc& CurrLoc() const { return ti->CurrLoc(); } + bool ScanLine(string& line) { return ti->ScanLine(line); } + Words SplitIntoWords(const string& line) const { return ti->SplitIntoWords(line); } + string SkipWords(const string& line, int n) const { return ti->SkipWords(line, n); } + void PutBack(const string& line) { ti->PutBack(line); } - // Methods made public to ZAM_OpTemplate objects for emitting code. - void Emit(EmitTarget et, const string& s); + // Methods made public to ZAM_OpTemplate objects for emitting code. + void Emit(EmitTarget et, const string& s); - void IndentUp() { ++indent_level; } - void IndentDown() { --indent_level; } - void StartString() { string_lit = true; } - void EndString() { string_lit = false; } - void SetNoNL(bool _no_NL) { no_NL = _no_NL; } + void IndentUp() { ++indent_level; } + void IndentDown() { --indent_level; } + void StartString() { string_lit = true; } + void EndString() { string_lit = false; } + void SetNoNL(bool _no_NL) { no_NL = _no_NL; } - [[noreturn]] void Gripe(const char* msg, const string& input) const { ti->Gripe(msg, input); } - [[noreturn]] void Gripe(const char* msg, const InputLoc& loc) const { ti->Gripe(msg, loc); } + [[noreturn]] void Gripe(const char* msg, const string& input) const { ti->Gripe(msg, input); } + [[noreturn]] void Gripe(const char* msg, const InputLoc& loc) const { ti->Gripe(msg, loc); } private: - // Opens all of the code generation targets, and creates prologs - // for those requiring them (such as for embedding into switch - // statements). - void InitEmitTargets(); - void InitSwitch(EmitTarget et, string desc); + // Opens all of the code generation targets, and creates prologs + // for those requiring them (such as for embedding into switch + // statements). + void InitEmitTargets(); + void InitSwitch(EmitTarget et, string desc); - // Closes all of the code generation targets, and creates epilogs - // for those requiring them. - void CloseEmitTargets(); - void FinishSwitches(); + // Closes all of the code generation targets, and creates epilogs + // for those requiring them. + void CloseEmitTargets(); + void FinishSwitches(); - // Parses a single template, returning true on success and false - // if we've reached the end of the input. (Errors during parsing - // result instead in exiting.) - bool ParseTemplate(); + // Parses a single template, returning true on success and false + // if we've reached the end of the input. (Errors during parsing + // result instead in exiting.) + bool ParseTemplate(); - // Maps code generation targets with their corresponding FILE*. - std::unordered_map gen_files; + // Maps code generation targets with their corresponding FILE*. + std::unordered_map gen_files; - // Maps code generation targets to strings used to describe any - // associated switch (for error reporting). - std::unordered_map switch_targets; + // Maps code generation targets to strings used to describe any + // associated switch (for error reporting). + std::unordered_map switch_targets; - // The low-level TemplateInput object used to manage input. - std::unique_ptr ti; + // The low-level TemplateInput object used to manage input. + std::unique_ptr ti; - // Tracks all of the templates created so far. - vector> templates; + // Tracks all of the templates created so far. + vector> templates; - // Tracks the macros recorded so far. - vector> macros; + // Tracks the macros recorded so far. + vector> macros; - // Current indentation level. Maintained globally rather than - // per EmitTarget, so the caller needs to ensure it is managed - // consistently. - int indent_level = 0; + // Current indentation level. Maintained globally rather than + // per EmitTarget, so the caller needs to ensure it is managed + // consistently. + int indent_level = 0; - // If true, we're generating a string literal. - bool string_lit = false; + // If true, we're generating a string literal. + bool string_lit = false; - // If true, refrain from appending a newline to any emitted lines. - bool no_NL = false; - }; + // If true, refrain from appending a newline to any emitted lines. + bool no_NL = false; +}; From 3845fced554d423e2b8599a0ba8466cf113027e2 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 3 Jun 2025 16:27:39 -0700 Subject: [PATCH 277/343] gen-zam: Require C++20 for builds --- tools/gen-zam/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gen-zam/CMakeLists.txt b/tools/gen-zam/CMakeLists.txt index 33e6902038..cc5bc3a32e 100644 --- a/tools/gen-zam/CMakeLists.txt +++ b/tools/gen-zam/CMakeLists.txt @@ -3,7 +3,7 @@ project(Gen-ZAM C CXX) include(cmake/CommonCMakeConfig.cmake) -include(RequireCXX17) +include(RequireCXXStd) set(GEN_ZAM_SRCS src/Gen-ZAM.cc) set(GEN_ZAM_HEADERS src/Gen-ZAM.h) From 526238299de3fd3420c00eb861100a5fe83466ef Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 21 Jul 2025 14:07:43 -0700 Subject: [PATCH 278/343] gen-zam: Fix a pile of Coverity findings --- tools/gen-zam/src/Gen-ZAM.cc | 39 ++++++++++++++++++++---------------- tools/gen-zam/src/Gen-ZAM.h | 4 ++-- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index bbbb67b3eb..8b30441b50 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -661,7 +661,7 @@ static bool skippable_ot(ZAM_OperandClass oc) { string ZAM_OpTemplate::ExpandParams(const OCVec& oc, string eval, const vector& accessors) const { auto have_target = eval.find("$$") != string::npos; - auto fl = GetOp1Flavor(); + const auto& fl = GetOp1Flavor(); auto need_target = fl == "OP1_WRITE"; auto oc_size = oc.size(); @@ -699,16 +699,19 @@ string ZAM_OpTemplate::ExpandParams(const OCVec& oc, string eval, const vectorGenOpCode(this, op_string + "_" + ti.suffix); @@ -1026,7 +1033,7 @@ void ZAM_OpTemplate::GenAssignOpCore(const OCVec& oc, const string& eval, const void ZAM_OpTemplate::GenAssignOpValCore(const OCVec& oc, const string& orig_eval, const string& accessor, bool is_managed) { - auto v = GetAssignVal(); + const auto& v = GetAssignVal(); // Maps Zeek types to how to get the underlying value from a ValPtr. static unordered_map val_accessors = { @@ -1040,7 +1047,7 @@ void ZAM_OpTemplate::GenAssignOpValCore(const OCVec& oc, const string& orig_eval {"Record", "->AsRecordVal()"}, {"Type", "->AsTypeVal()"}, }; - auto val_accessor = val_accessors[accessor]; + const auto& val_accessor = val_accessors[accessor]; string rhs; if ( IsInternalOp() ) @@ -1407,17 +1414,15 @@ void ZAM_ExprOpTemplate::GenMethodTest(ZAM_Type et1, ZAM_Type et2, const string& if ( if_tests.count(et1) == 0 || if_tests.count(et2) == 0 ) Gripe("bad op-type"); - auto if_test1 = if_tests[et1]; - auto if_var1 = if_test1.first + "1"; - auto if_val1 = if_test1.second; + const auto& [var, val] = if_tests[et1]; + auto if_var1 = var + "1"; - string test = if_var1 + " == " + if_val1; + string test = if_var1 + " == " + val; if ( Arity() > 1 ) { - auto if_test2 = if_tests[et2]; - auto if_var2 = if_test2.first + "2"; - auto if_val2 = if_test2.second; - test = test + " && " + if_var2 + " == " + if_val2; + const auto& [var2, val2] = if_tests[et2]; + auto if_var2 = var2 + "2"; + test = test + " && " + if_var2 + " == " + val2; } test = "if ( " + test + " )"; @@ -2032,7 +2037,7 @@ void ZAM_InternalOpTemplate::ParseCall(const string& line, const Words& words) { eval += "ZAM_PROFILE_PRE_CALL\n"; if ( HasAssignVal() ) { - auto av = GetAssignVal(); + const auto& av = GetAssignVal(); eval += "auto " + av + " = " + func + "->Invoke(&args, f);\n"; eval += "if ( ! " + av + " ) { ZAM_error = true; break; }\n"; @@ -2393,14 +2398,14 @@ bool ZAMGen::ParseTemplate() { if ( words.size() < 2 ) Gripe("too few words at start of template", line); - auto op = words[0]; + const auto& op = words[0]; if ( op == "macro" ) { ReadMacro(line); return true; } - auto op_name = words[1]; + const auto& op_name = words[1]; // We track issues with the wrong number of template arguments // up front, to avoid mis-invoking constructors, but we don't diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index 90e8008d45..d5a8640503 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -370,8 +370,8 @@ protected: // operation that explictly omits any assignment. bool HasAssignmentLess() const { return ! assignment_less_op.empty(); } void SetAssignmentLess(string op, string op_class) { - assignment_less_op = op; - assignment_less_op_class = op_class; + assignment_less_op = std::move(op); + assignment_less_op_class = std::move(op_class); } const string& AssignmentLessOp() const { return assignment_less_op; } const string& AssignmentLessOpClass() const { return assignment_less_op_class; } From a2f4f2adc36cbc55877a9e12dc09f3aeeab09796 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sun, 17 Aug 2025 21:01:06 -0700 Subject: [PATCH 279/343] gen-zam: Remove submodule, adapt CMake configuration for Zeek build --- .gitmodules | 3 --- CMakeLists.txt | 2 +- auxil/gen-zam | 1 - tools/gen-zam/CMakeLists.txt | 35 ++--------------------------------- tools/gen-zam/src/Gen-ZAM.cc | 2 +- tools/gen-zam/src/Gen-ZAM.h | 4 ++-- 6 files changed, 6 insertions(+), 41 deletions(-) delete mode 160000 auxil/gen-zam diff --git a/.gitmodules b/.gitmodules index 53b0f86697..dbf4e2590f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,9 +40,6 @@ [submodule "auxil/zeek-client"] path = auxil/zeek-client url = https://github.com/zeek/zeek-client -[submodule "auxil/gen-zam"] - path = auxil/gen-zam - url = https://github.com/zeek/gen-zam [submodule "auxil/c-ares"] path = auxil/c-ares url = https://github.com/c-ares/c-ares diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e146f1a2c..a4dc95c1df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -912,7 +912,7 @@ set(BIFCL_EXE_PATH "${CMAKE_BINARY_DIR}/tools/bifcl/bifcl${CMAKE_EXECUTABLE_SUFF set(_bifcl_exe_path "included") if (NOT GEN_ZAM_EXE_PATH) - add_subdirectory(auxil/gen-zam) + add_subdirectory(tools/gen-zam) endif () if (ENABLE_JEMALLOC) diff --git a/auxil/gen-zam b/auxil/gen-zam deleted file mode 160000 index 56a6db00b8..0000000000 --- a/auxil/gen-zam +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 56a6db00b887c79d26f303676677cb490d1c296d diff --git a/tools/gen-zam/CMakeLists.txt b/tools/gen-zam/CMakeLists.txt index cc5bc3a32e..29e848cc78 100644 --- a/tools/gen-zam/CMakeLists.txt +++ b/tools/gen-zam/CMakeLists.txt @@ -1,33 +1,2 @@ -cmake_minimum_required(VERSION 3.15 FATAL_ERROR) -project(Gen-ZAM C CXX) - -include(cmake/CommonCMakeConfig.cmake) - -include(RequireCXXStd) - -set(GEN_ZAM_SRCS src/Gen-ZAM.cc) -set(GEN_ZAM_HEADERS src/Gen-ZAM.h) -add_executable(gen-zam ${GEN_ZAM_SRCS} ${GEN_ZAM_HEADERS}) -install(TARGETS gen-zam DESTINATION bin) - -if (CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) -endif () - -message( - "\n===================| Gen-ZAM Build Summary |==================\n" - "\n" - "\nBuild type: ${CMAKE_BUILD_TYPE}" - "\nBuild dir: ${PROJECT_BINARY_DIR}" - "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" - "\nDebug mode: ${ENABLE_DEBUG}" - "\n" - "\nCC: ${CMAKE_C_COMPILER}" - "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" - "\nCXX: ${CMAKE_CXX_COMPILER}" - "\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}" - "\nCPP: ${CMAKE_CXX_COMPILER}" - "\n" - "\n================================================================\n") - -include(UserChangedWarning) +add_executable(gen-zam) +target_sources(gen-zam PRIVATE src/Gen-ZAM.cc) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index 8b30441b50..dc07544c3d 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -136,7 +136,7 @@ ArgsManager::ArgsManager(const OCVec& oc_orig, ZAM_InstClass zc) { void ArgsManager::Differentiate() { // First, figure out which parameter names are used how often. - map name_count; // how often the name apepars + map name_count; // how often the name appears map usage_count; // how often the name's been used so far for ( auto& arg : args ) { auto& name = arg.param_name; diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index d5a8640503..a93eabfcd4 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -367,7 +367,7 @@ protected: // An "assignment-less" operation is one that, if its result // is used in a dead assignment, should be converted to a different - // operation that explictly omits any assignment. + // operation that explicitly omits any assignment. bool HasAssignmentLess() const { return ! assignment_less_op.empty(); } void SetAssignmentLess(string op, string op_class) { assignment_less_op = std::move(op); @@ -515,7 +515,7 @@ protected: IndentDown(); } - // Start/finish emiting a (likely multi-line) string literal - + // Start/finish emitting a (likely multi-line) string literal - // see corresponding ZAMGen methods. void StartString(); void EndString(); From 32522307d9f062ee121f8906b3a4777132b0d73d Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 14 Aug 2025 10:36:57 -0700 Subject: [PATCH 280/343] gen-zam: Fix clang-tidy and pre-commit warnings --- tools/gen-zam/src/Gen-ZAM.cc | 28 +++++++++++++++------------- tools/gen-zam/src/Gen-ZAM.h | 14 ++++++-------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tools/gen-zam/src/Gen-ZAM.cc b/tools/gen-zam/src/Gen-ZAM.cc index dc07544c3d..393c2f9ff6 100644 --- a/tools/gen-zam/src/Gen-ZAM.cc +++ b/tools/gen-zam/src/Gen-ZAM.cc @@ -1,10 +1,12 @@ -// See the file "COPYING" in the toplevel directory for copyright. +// See the file "COPYING" in the main distribution directory for copyright. #include "Gen-ZAM.h" -#include +#include #include +#include #include +#include using namespace std; @@ -654,7 +656,7 @@ void ZAM_OpTemplate::BuildInstruction(const OCVec& oc, const string& params, con Emit("z = GenInst(" + op + ", " + params + ");"); } -static bool skippable_ot(ZAM_OperandClass oc) { +static bool skippable_op_type(ZAM_OperandClass oc) { return oc == ZAM_OC_EVENT_HANDLER || oc == ZAM_OC_AUX || oc == ZAM_OC_LIST; } @@ -677,7 +679,7 @@ string ZAM_OpTemplate::ExpandParams(const OCVec& oc, string eval, const vector 0 && skippable_ot(oc[oc_size - 1]) ) + while ( oc_size > 0 && skippable_op_type(oc[oc_size - 1]) ) --oc_size; auto max_param = oc_size; @@ -869,11 +871,11 @@ void ZAM_OpTemplate::StartDesc(const string& op_code, const string& oc_str) { Emit("\"\","); else { string ots; - for ( auto ot : op_types ) { - if ( ot == ZAM_TYPE_DEFAULT ) + for ( auto typ : op_types ) { + if ( typ == ZAM_TYPE_DEFAULT ) ots += "X"; else - ots += expr_name_types[ot]; + ots += expr_name_types[typ]; } Emit("\"" + ots + "\", "); @@ -2217,8 +2219,8 @@ void ZAMGen::GenMacros() { } } -string ZAMGen::GenOpCode(const ZAM_OpTemplate* ot, const string& suffix, ZAM_InstClass zc) { - auto op = "OP_" + ot->CanonicalName() + suffix; +string ZAMGen::GenOpCode(const ZAM_OpTemplate* op_templ, const string& suffix, ZAM_InstClass zc) { + auto op = "OP_" + op_templ->CanonicalName() + suffix; static unordered_set known_opcodes; @@ -2237,16 +2239,16 @@ string ZAMGen::GenOpCode(const ZAM_OpTemplate* ot, const string& suffix, ZAM_Ins // ... the "flavor" of how it treats its first operand ... auto op_comment = ",\t// " + op; auto op1_always_read = (zc == ZIC_FIELD || zc == ZIC_COND); - auto flavor = op1_always_read ? "OP1_READ" : ot->GetOp1Flavor(); + auto flavor = op1_always_read ? "OP1_READ" : op_templ->GetOp1Flavor(); Emit(Op1Flavor, flavor + op_comment); // ... whether it has side effects ... - auto se = ot->HasSideEffects() ? "true" : "false"; + auto se = op_templ->HasSideEffects() ? "true" : "false"; Emit(OpSideEffects, se + op_comment); // ... and the switch case that maps the enum to a string // representation. - auto name = ot->BaseName(); + auto name = op_templ->BaseName(); transform(name.begin(), name.end(), name.begin(), ::tolower); name += suffix; transform(name.begin(), name.end(), name.begin(), under_to_dash); @@ -2408,7 +2410,7 @@ bool ZAMGen::ParseTemplate() { const auto& op_name = words[1]; // We track issues with the wrong number of template arguments - // up front, to avoid mis-invoking constructors, but we don't + // up front, to avoid misinvoking constructors, but we don't // report these until later because if the template names a // bad operation, it's better to report that as the core problem. const char* args_mismatch = nullptr; diff --git a/tools/gen-zam/src/Gen-ZAM.h b/tools/gen-zam/src/Gen-ZAM.h index a93eabfcd4..54422c3bc4 100644 --- a/tools/gen-zam/src/Gen-ZAM.h +++ b/tools/gen-zam/src/Gen-ZAM.h @@ -1,4 +1,4 @@ -// See the file "COPYING" in the toplevel directory for copyright. +// See the file "COPYING" in the main distribution directory for copyright. // Gen-ZAM is a standalone program that takes as input a file specifying // ZAM operations and from them generates a (large) set of C++ include @@ -9,11 +9,9 @@ #pragma once -#include -#include +#include #include #include -#include #include #include #include @@ -442,15 +440,15 @@ protected: // Generates the C++ case statement for evaluating the given flavor // of operation. - void GenEval(EmitTarget et, const string& ot_str, const string& op_suffix, const string& eval, ZAM_InstClass zc); + void GenEval(EmitTarget et, const string& oc_str, const string& op_suffix, const string& eval, ZAM_InstClass zc); // Generates a description of the ZAM operation suitable for // reflection. - void GenDesc(const string& op_code, const string& ot_str, const string& eval); + void GenDesc(const string& op_code, const string& oc_str, const string& eval); // Generates the first part of a description, up to (but not including) // the evaluation. - void StartDesc(const string& op_code, const string& ot_str); + void StartDesc(const string& op_code, const string& oc_str); // Finishes a description, once the evaluation is done. void EndDesc(); @@ -929,7 +927,7 @@ public: // Generates a ZAM op-code for the given template, suffix, and // instruction class. Also creates auxiliary information associated // with the instruction. - string GenOpCode(const ZAM_OpTemplate* ot, const string& suffix, ZAM_InstClass zc = ZIC_REGULAR); + string GenOpCode(const ZAM_OpTemplate* op_templ, const string& suffix, ZAM_InstClass zc = ZIC_REGULAR); // These methods provide low-level parsing (and error-reporting) // access to ZAM_OpTemplate objects. From 742b0820bc7b62958aee22dc37004655954f600e Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Tue, 6 Dec 2016 00:10:56 +0100 Subject: [PATCH 281/343] af_packet: Imported version 1.1 of the plugin. --- src/iosource/af_packet/CMakeLists.txt | 23 ++ src/iosource/af_packet/README | 95 +++++++ src/iosource/af_packet/scripts/__load__.bro | 5 + src/iosource/af_packet/scripts/init.bro | 18 ++ src/iosource/af_packet/src/AF_Packet.cc | 288 ++++++++++++++++++++ src/iosource/af_packet/src/AF_Packet.h | 78 ++++++ src/iosource/af_packet/src/Plugin.cc | 19 ++ src/iosource/af_packet/src/Plugin.h | 22 ++ src/iosource/af_packet/src/RX_Ring.cc | 112 ++++++++ src/iosource/af_packet/src/RX_Ring.h | 46 ++++ src/iosource/af_packet/src/af_packet.bif | 16 ++ 11 files changed, 722 insertions(+) create mode 100644 src/iosource/af_packet/CMakeLists.txt create mode 100644 src/iosource/af_packet/README create mode 100644 src/iosource/af_packet/scripts/__load__.bro create mode 100644 src/iosource/af_packet/scripts/init.bro create mode 100644 src/iosource/af_packet/src/AF_Packet.cc create mode 100644 src/iosource/af_packet/src/AF_Packet.h create mode 100644 src/iosource/af_packet/src/Plugin.cc create mode 100644 src/iosource/af_packet/src/Plugin.h create mode 100644 src/iosource/af_packet/src/RX_Ring.cc create mode 100644 src/iosource/af_packet/src/RX_Ring.h create mode 100644 src/iosource/af_packet/src/af_packet.bif diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt new file mode 100644 index 0000000000..a37cd33844 --- /dev/null +++ b/src/iosource/af_packet/CMakeLists.txt @@ -0,0 +1,23 @@ + +cmake_minimum_required(VERSION 2.6.3) + +project(Plugin) + +include(BroPlugin) + +find_package(KernelHeaders) + +if ( KERNELHEADERS_FOUND ) + #TODO: Make sure the specified kernel headers are used + bro_plugin_begin(Bro AF_Packet) + bro_plugin_cc(src/Plugin.cc) + bro_plugin_cc(src/AF_Packet.cc) + bro_plugin_cc(src/RX_Ring.cc) + bro_plugin_bif(src/af_packet.bif) + bro_plugin_dist_files(broctl/af_packet.py) + bro_plugin_end() + + message(STATUS "Kernelheader prefix : ${KERNELHEADERS_ROOT_DIR}") +else () + message(FATAL_ERROR "Kernel headers not found.") +endif () diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README new file mode 100644 index 0000000000..09c39615e3 --- /dev/null +++ b/src/iosource/af_packet/README @@ -0,0 +1,95 @@ + +Bro::AF_Packet +============== + +This plugin provides native AF_Packet support +(http://man7.org/linux/man-pages/man7/packet.7.html) for Bro. + +Installation +------------ + +Make sure the kernel headers are installed and your kernel supports +PACKET_FANOUT [1]_ and TPACKET_V3. The following will then compile and +install the AF_Packet plugin alongside Bro, assuming it can find the +kernel headers in a standard location:: + + # ./configure && make && make install + +If the headers are installed somewhere non-standard, add +``--with-kernel=`` to the ``configure`` +command. If everything built and installed correctly, you should see +this:: + + # bro -NN Bro::AF_Packet + Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.1) + [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) + [Type] AF_Packet::FanoutMode + [Constant] AF_Packet::buffer_size + [Constant] AF_Packet::enable_hw_timestamping + [Constant] AF_Packet::enable_fanout + [Constant] AF_Packet::fanout_mode + [Constant] AF_Packet::fanout_id + +.. [1] Note that some kernel versions between 3.10 and 4.7 might exhibit a bug that + prevents the required symmetric hashing. The script available at + https://github.com/JustinAzoff/can-i-use-afpacket-fanout can be used to verify + whether PACKET_FANOUT works as expected. + +Usage +----- + +Once installed, you can use AF_Packet interfaces/ports by prefixing them +with ``af_packet::`` on the command line. For example, to use AF_Packet +to monitor interface ``eth0``:: + + # bro -i af_packet::eth0 + +To use AF_Packet, running Bro without root privileges, the Bro processes needs +the CAP_NET_RAW capability. You can set it with the following command (on each +sensor, after ``broctl install``):: + + # setcap cap_net_raw+eip /bin/bro + +The AF_Packet plugin automatically enables promiscuous mode on the interfaces. +As the plugin is using PACKET_ADD_MEMBERSHIP to enter the promiscuous mode +without interfering others, the PROMISC flag is not touched. To verify that the +interface entered promiscuous mode you can use ``dmesg``. + +To adapt the plugin to your needs, you can set a couple of parameters like +buffer size. See scripts/init.bro for the default values. + +Usage with ``broctl`` +--------------------- + +To use the AF_Packet plugin with ``broctl``, the ``custom`` load balance method can +be utilized. The following shows an exemplary configuration:: + + [manager] + type=manager + host=localhost + + [proxy-1] + type=proxy + host=localhost + + [worker-1] + type=worker + host=localhost + interface=af_packet::eth0 + lb_method=custom + lb_procs=8 + pin_cpus=0,1,2,3,4,5,6,7 + # Optional parameters for per node configuration: + af_packet_fanout_id=23 + af_packet_fanout_mode=FANOUT_HASH + +If all interfaces using ``lb_method=custom`` should be configured for AF_Packet, the +prefix can be globally definied by adding the following line to ``broctl.conf``:: + + lb_custom.InterfacePrefix=af_packet:: + +Limitations +----------- + +* Even using AF_Packet's ``ETH_P_ALL``, the kernel removes VLAN tags. While the tags + are provided spereately, there is no efficient way to pass them to Bro. diff --git a/src/iosource/af_packet/scripts/__load__.bro b/src/iosource/af_packet/scripts/__load__.bro new file mode 100644 index 0000000000..f77b383b48 --- /dev/null +++ b/src/iosource/af_packet/scripts/__load__.bro @@ -0,0 +1,5 @@ +# +# This is loaded unconditionally at Bro startup. +# + +@load ./init.bro diff --git a/src/iosource/af_packet/scripts/init.bro b/src/iosource/af_packet/scripts/init.bro new file mode 100644 index 0000000000..9a6abc000c --- /dev/null +++ b/src/iosource/af_packet/scripts/init.bro @@ -0,0 +1,18 @@ +##! Packet source using AF_Packet. +##! +##! Note: This module is in testing and is not yet considered stable! + +module AF_Packet; + +export { + ## Size of the ring-buffer. + const buffer_size = 128 * 1024 * 1024 &redef; + ## Toggle whether to use hardware timestamps. + const enable_hw_timestamping = F &redef; + ## Toggle whether to use PACKET_FANOUT. + const enable_fanout = T &redef; + ## Fanout Mode. + const fanout_mode = FANOUT_HASH &redef; + ## Fanout ID. + const fanout_id = 23 &redef; +} diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc new file mode 100644 index 0000000000..f46437bcd8 --- /dev/null +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -0,0 +1,288 @@ + +#include "bro-config.h" + +#include "AF_Packet.h" +#include "RX_Ring.h" + +#include "af_packet.bif.h" + +using namespace iosource::pktsrc; + +AF_PacketSource::~AF_PacketSource() + { + Close(); + } + +AF_PacketSource::AF_PacketSource(const std::string& path, bool is_live) + { + if ( ! is_live ) + Error("AF_Packet source does not support offline input"); + + current_filter = -1; + props.path = path; + props.is_live = is_live; + } + +void AF_PacketSource::Open() + { + uint64_t buffer_size = BifConst::AF_Packet::buffer_size; + bool enable_hw_timestamping = BifConst::AF_Packet::enable_hw_timestamping; + bool enable_fanout = BifConst::AF_Packet::enable_fanout; + + socket_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + + if ( socket_fd < 0 ) + { + Error(errno ? strerror(errno) : "unable to create socket"); + return; + } + + // Create RX-ring + try { + rx_ring = new RX_Ring(socket_fd, buffer_size); + } catch (RX_RingException e) { + Error(errno ? strerror(errno) : "unable to create RX-ring"); + close(socket_fd); + return; + } + + // Setup interface + if ( ! BindInterface() ) + { + Error(errno ? strerror(errno) : "unable to bind to interface"); + close(socket_fd); + return; + } + + if ( ! EnablePromiscMode() ) + { + Error(errno ? strerror(errno) : "unable enter promiscious mode"); + close(socket_fd); + return; + } + + if ( ! ConfigureFanoutGroup(enable_fanout) ) + { + Error(errno ? strerror(errno) : "failed to join fanout group"); + close(socket_fd); + return; + } + + if ( ! ConfigureHWTimestamping(enable_hw_timestamping) ) + { + Error(errno ? strerror(errno) : "failed to configure hardware timestamping"); + close(socket_fd); + return; + } + + props.netmask = NETMASK_UNKNOWN; + props.selectable_fd = socket_fd; + props.is_live = true; + props.link_type = DLT_EN10MB; // Ethernet headers + + memset(&stats, 0, sizeof(stats)); + num_discarded = 0; + + Opened(props); + } + +inline bool AF_PacketSource::BindInterface() + { + struct ifreq ifr; + struct sockaddr_ll saddr_ll; + int ret; + + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); + + ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); + if ( ret < 0 ) + return false; + + memset(&saddr_ll, 0, sizeof(saddr_ll)); + saddr_ll.sll_family = AF_PACKET; + saddr_ll.sll_protocol = htons(ETH_P_ALL); + saddr_ll.sll_ifindex = ifr.ifr_ifindex; + + ret = bind(socket_fd, (struct sockaddr *) &saddr_ll, sizeof(saddr_ll)); + return (ret >= 0); + } + +inline bool AF_PacketSource::EnablePromiscMode() + { + struct ifreq ifr; + struct packet_mreq mreq; + int ret; + + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); + + ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); + if ( ret < 0 ) + return false; + + memset(&mreq, 0, sizeof(mreq)); + mreq.mr_ifindex = ifr.ifr_ifindex; + mreq.mr_type = PACKET_MR_PROMISC; + + ret = setsockopt(socket_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + return (ret >= 0); + } + +inline bool AF_PacketSource::ConfigureFanoutGroup(bool enabled) + { + if ( enabled ) + { + uint32_t fanout_arg, fanout_id; + int ret; + + fanout_id = BifConst::AF_Packet::fanout_id; + fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode() << 16)); + + ret = setsockopt(socket_fd, SOL_PACKET, PACKET_FANOUT, + &fanout_arg, sizeof(fanout_arg)); + + if ( ret < 0 ) + return false; + } + return true; + } + +inline bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) + { + if ( enabled ) + { + struct ifreq ifr; + struct hwtstamp_config hwts_cfg; + int ret, opt; + + memset(&hwts_cfg, 0, sizeof(hwts_cfg)); + hwts_cfg.tx_type = HWTSTAMP_TX_OFF; + hwts_cfg.rx_filter = HWTSTAMP_FILTER_ALL; + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); + ifr.ifr_data = &hwts_cfg; + + ret = ioctl(socket_fd, SIOCSHWTSTAMP, &ifr); + if ( ret < 0 ) + return false; + + opt = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE; + ret = setsockopt(socket_fd, SOL_PACKET, PACKET_TIMESTAMP, + &opt, sizeof(opt)); + if( ret < 0 ) + return false; + } + return true; + } + +inline uint32_t AF_PacketSource::GetFanoutMode() + { + switch ( BifConst::AF_Packet::fanout_mode->AsEnum() ) { + case BifEnum::AF_Packet::FANOUT_CPU: return PACKET_FANOUT_CPU; + case BifEnum::AF_Packet::FANOUT_QM: return PACKET_FANOUT_QM; + default: return PACKET_FANOUT_HASH; + } + } + +void AF_PacketSource::Close() + { + if ( ! socket_fd ) + return; + + delete rx_ring; + close(socket_fd); + socket_fd = 0; + + Closed(); + } + +bool AF_PacketSource::ExtractNextPacket(Packet* pkt) + { + if ( ! socket_fd ) + return false; + + struct tpacket3_hdr *packet = 0; + const u_char *data; + struct timeval ts; + while ( true ) + { + if ( ! rx_ring->GetNextPacket(&packet) ) + return false; + + current_hdr.ts.tv_sec = packet->tp_sec; + current_hdr.ts.tv_usec = packet->tp_nsec / 1000; + current_hdr.caplen = packet->tp_snaplen; + current_hdr.len = packet->tp_len; + data = (u_char *) packet + packet->tp_mac; + + if ( !ApplyBPFFilter(current_filter, ¤t_hdr, data) ) + { + ++num_discarded; + DoneWithPacket(); + continue; + } + + pkt->Init(props.link_type, ¤t_hdr.ts, current_hdr.caplen, current_hdr.len, data); + + if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) + { + Weird("empty_af_packet_header", pkt); + return false; + } + + stats.received++; + stats.bytes_received += current_hdr.len; + return true; + } + + return false; + } + +void AF_PacketSource::DoneWithPacket() + { + rx_ring->ReleasePacket(); + } + +bool AF_PacketSource::PrecompileFilter(int index, const std::string& filter) + { + return PktSrc::PrecompileBPFFilter(index, filter); + } + +bool AF_PacketSource::SetFilter(int index) + { + current_filter = index; + return true; + } + +void AF_PacketSource::Statistics(Stats* s) + { + if ( ! socket_fd ) + { + s->received = s->bytes_received = s->link = s->dropped = 0; + return; + } + + struct tpacket_stats_v3 tp_stats; + socklen_t tp_stats_len = sizeof (struct tpacket_stats_v3); + int ret; + + ret = getsockopt(socket_fd, SOL_PACKET, PACKET_STATISTICS, &tp_stats, &tp_stats_len); + if ( ret < 0 ) + { + Error(errno ? strerror(errno) : "unable to retrieve statistics"); + s->received = s->bytes_received = s->link = s->dropped = 0; + return; + } + + stats.link += tp_stats.tp_packets; + stats.dropped += tp_stats.tp_drops; + + memcpy(s, &stats, sizeof(Stats)); + } + +iosource::PktSrc* AF_PacketSource::InstantiateAF_Packet(const std::string& path, bool is_live) + { + return new AF_PacketSource(path, is_live); + } + diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h new file mode 100644 index 0000000000..4bf7999963 --- /dev/null +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -0,0 +1,78 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef IOSOURCE_PKTSRC_AF_PACKET_SOURCE_H +#define IOSOURCE_PKTSRC_AF_PACKET_SOURCE_H + +extern "C" { +#include +#include +#include + +#include // errorno +#include // close() + +#include // ETH_P_ALL +#include // ifreq +#include // AF_PACKET, etc. +#include // SIOCSHWTSTAMP +#include // hwtstamp_config +} + +#include "iosource/PktSrc.h" +#include "RX_Ring.h" + +namespace iosource { +namespace pktsrc { + +class AF_PacketSource : public iosource::PktSrc { +public: + /** + * Constructor. + * + * path: Name of the interface to open (the AF_Packet source doesn't + * support reading from files). + * + * is_live: Must be true (the AF_Packet source doesn't support offline + * operation). + */ + AF_PacketSource(const std::string& path, bool is_live); + + /** + * Destructor. + */ + virtual ~AF_PacketSource(); + + static PktSrc* InstantiateAF_Packet(const std::string& path, bool is_live); + +protected: + // PktSrc interface. + virtual void Open(); + virtual void Close(); + virtual bool ExtractNextPacket(Packet* pkt); + virtual void DoneWithPacket(); + virtual bool PrecompileFilter(int index, const std::string& filter); + virtual bool SetFilter(int index); + virtual void Statistics(Stats* stats); + +private: + Properties props; + Stats stats; + + int current_filter; + unsigned int num_discarded; + + int socket_fd; + RX_Ring *rx_ring; + struct pcap_pkthdr current_hdr; + + bool BindInterface(); + bool EnablePromiscMode(); + bool ConfigureFanoutGroup(bool enabled); + bool ConfigureHWTimestamping(bool enabled); + uint32_t GetFanoutMode(); +}; + +} +} + +#endif diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc new file mode 100644 index 0000000000..855492fb36 --- /dev/null +++ b/src/iosource/af_packet/src/Plugin.cc @@ -0,0 +1,19 @@ + +#include "Plugin.h" +#include "AF_Packet.h" + +namespace plugin { namespace Bro_AF_Packet { Plugin plugin; } } + +using namespace plugin::Bro_AF_Packet; + +plugin::Configuration Plugin::Configure() + { + AddComponent(new ::iosource::PktSrcComponent("AF_PacketReader", "af_packet", ::iosource::PktSrcComponent::LIVE, ::iosource::pktsrc::AF_PacketSource::InstantiateAF_Packet)); + + plugin::Configuration config; + config.name = "Bro::AF_Packet"; + config.description = "Packet acquisition via AF_Packet"; + config.version.major = 1; + config.version.minor = 1; + return config; + } diff --git a/src/iosource/af_packet/src/Plugin.h b/src/iosource/af_packet/src/Plugin.h new file mode 100644 index 0000000000..e1e7e1a1e4 --- /dev/null +++ b/src/iosource/af_packet/src/Plugin.h @@ -0,0 +1,22 @@ + +#ifndef BRO_PLUGIN_BRO_AF_PACKET +#define BRO_PLUGIN_BRO_AF_PACKET + +#include + +namespace plugin { +namespace Bro_AF_Packet { + +class Plugin : public ::plugin::Plugin +{ +protected: + // Overridden from plugin::Plugin. + virtual plugin::Configuration Configure(); +}; + +extern Plugin plugin; + +} +} + +#endif diff --git a/src/iosource/af_packet/src/RX_Ring.cc b/src/iosource/af_packet/src/RX_Ring.cc new file mode 100644 index 0000000000..e7af904856 --- /dev/null +++ b/src/iosource/af_packet/src/RX_Ring.cc @@ -0,0 +1,112 @@ + +#include "RX_Ring.h" + +#include +#include + +extern "C" { +#include // AF_PACKET, etc. +#include // socketopt consts +#include // mmap +#include // sysconf +} + +RX_Ring::RX_Ring(int sock, size_t bufsize) + { + int ret, ver = TPACKET_VERSION; + + if ( sock < 0 ) + throw RX_RingException("invalid socket"); + + // Configure socket + ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &ver, sizeof(ver)); + if ( ret ) + throw RX_RingException("unable to set TPacket version"); + + InitLayout(bufsize); + ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, (uint8_t *) &layout, + sizeof(layout)); + if ( ret ) + throw RX_RingException("unable to set ring layout"); + + // Map memory + size = layout.tp_block_size * layout.tp_block_nr; + ring = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_SHARED, sock, 0); + if ( ring == MAP_FAILED ) + throw RX_RingException("unable to map ring memory"); + + block_num = packet_num = 0; + packet = NULL; + + // Init block mapping + blocks = new tpacket_block_desc*[layout.tp_block_nr]; + for ( unsigned int i = 0; i < layout.tp_block_nr; i++ ) + blocks[i] = (struct tpacket_block_desc *)(ring + + i * layout.tp_block_size); + } + +RX_Ring::~RX_Ring() + { + ReleasePacket(); + + delete[] blocks; + munmap(ring, size); + + blocks = 0; + size = 0; + } + +bool RX_Ring::GetNextPacket(tpacket3_hdr** hdr) + { + struct tpacket_hdr_v1 *block_hdr = &(blocks[block_num]->hdr.bh1); + + if ( (block_hdr->block_status & TP_STATUS_USER) == 0 ) + return false; + + if ( packet == NULL ) + { + // New block + packet_num = block_hdr->num_pkts; + if ( packet_num == 0 ) + { + NextBlock(); + return false; + } + packet = (struct tpacket3_hdr *) + ((uint8_t *) blocks[block_num] + block_hdr->offset_to_first_pkt); + } + else + // Continue with block + packet = (struct tpacket3_hdr *) + ((uint8_t *) packet + packet->tp_next_offset); + + *hdr = packet; + packet_num--; + return true; + } + +void RX_Ring::ReleasePacket() + { + if ( packet_num == 0 ) + NextBlock(); + } + +void RX_Ring::InitLayout(size_t bufsize) + { + memset(&layout, 0, sizeof(layout)); + layout.tp_block_size = sysconf(_SC_PAGE_SIZE) << 2; //TODO: get rid of magic value + layout.tp_frame_size = TPACKET_ALIGNMENT << 7; // Seems to be irrelevant for V3 + layout.tp_block_nr = bufsize / layout.tp_block_size; + layout.tp_frame_nr = (layout.tp_block_size / layout.tp_frame_size) * layout.tp_block_nr; + layout.tp_retire_blk_tov = 100; // Timeout for blocks + } + +void RX_Ring::NextBlock() + { + struct tpacket_hdr_v1 *block_hdr = &(blocks[block_num]->hdr.bh1); + + block_hdr->block_status = TP_STATUS_KERNEL; + block_num = (block_num +1) % layout.tp_block_nr; + packet = NULL; + } diff --git a/src/iosource/af_packet/src/RX_Ring.h b/src/iosource/af_packet/src/RX_Ring.h new file mode 100644 index 0000000000..370c7f333e --- /dev/null +++ b/src/iosource/af_packet/src/RX_Ring.h @@ -0,0 +1,46 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef IOSOURCE_PKTSRC_RX_RING_H +#define IOSOURCE_PKTSRC_RX_RING_H + +extern "C" { +#include // AF_PACKET, etc. +} +#include +#include + +#define TPACKET_VERSION TPACKET_V3 + +class RX_RingException : public std::runtime_error { +public: + RX_RingException(const std::string& what_arg) : std::runtime_error(what_arg) {} +}; + +class RX_Ring { +public: + /** + * Constructor + */ + RX_Ring(int sock, size_t bufsize); + ~RX_Ring(); + + bool GetNextPacket(tpacket3_hdr** hdr); + void ReleasePacket(); + +protected: + void InitLayout(size_t bufsize); + void NextBlock(); + +private: + struct tpacket_req3 layout; + struct tpacket_block_desc** blocks; + struct tpacket3_hdr* packet; + + unsigned int block_num; + unsigned int packet_num; + + uint8_t* ring; + size_t size; +}; + +#endif diff --git a/src/iosource/af_packet/src/af_packet.bif b/src/iosource/af_packet/src/af_packet.bif new file mode 100644 index 0000000000..334121ea05 --- /dev/null +++ b/src/iosource/af_packet/src/af_packet.bif @@ -0,0 +1,16 @@ + +# Options for the AF_Packet packet source. + +module AF_Packet; + +enum FanoutMode %{ + FANOUT_HASH, # PACKET_FANOUT_HASH + FANOUT_CPU, # PACKET_FANOUT_CPU + FANOUT_QM, # PACKET_FANOUT_QM +%} + +const buffer_size: count; +const enable_hw_timestamping: bool; +const enable_fanout: bool; +const fanout_mode: FanoutMode; +const fanout_id: count; From 478265b4f237cbabdc68a0410d8cdb106ffd250b Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Tue, 6 Dec 2016 03:31:10 +0100 Subject: [PATCH 282/343] af_packet: Fixed compatibility for kernel versions < 3.14. --- src/iosource/af_packet/src/AF_Packet.cc | 2 ++ src/iosource/af_packet/src/AF_Packet.h | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index f46437bcd8..7b351e8783 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -180,7 +180,9 @@ inline uint32_t AF_PacketSource::GetFanoutMode() { switch ( BifConst::AF_Packet::fanout_mode->AsEnum() ) { case BifEnum::AF_Packet::FANOUT_CPU: return PACKET_FANOUT_CPU; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) case BifEnum::AF_Packet::FANOUT_QM: return PACKET_FANOUT_QM; + #endif default: return PACKET_FANOUT_HASH; } } diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index 4bf7999963..6887514316 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -8,8 +8,9 @@ extern "C" { #include #include -#include // errorno -#include // close() +#include // errorno +#include // close() +#include // kernel version #include // ETH_P_ALL #include // ifreq From 1dfb115e35141f8bdb077790c9edf5b858193bb7 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Sun, 29 Jan 2017 20:41:00 +0100 Subject: [PATCH 283/343] af_packet: Fixed broctl example. --- src/iosource/af_packet/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 09c39615e3..87d03e8a49 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -81,7 +81,7 @@ be utilized. The following shows an exemplary configuration:: pin_cpus=0,1,2,3,4,5,6,7 # Optional parameters for per node configuration: af_packet_fanout_id=23 - af_packet_fanout_mode=FANOUT_HASH + af_packet_fanout_mode=AF_Packet::FANOUT_HASH If all interfaces using ``lb_method=custom`` should be configured for AF_Packet, the prefix can be globally definied by adding the following line to ``broctl.conf``:: From 1a107bd83831a716d9ddb08975ee503457ab7f6f Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Sun, 29 Jan 2017 23:35:32 +0100 Subject: [PATCH 284/343] af_packet: Increased version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 87d03e8a49..3bec86e962 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -21,7 +21,7 @@ command. If everything built and installed correctly, you should see this:: # bro -NN Bro::AF_Packet - Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.1) + Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.2) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 855492fb36..731800e649 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -14,6 +14,6 @@ plugin::Configuration Plugin::Configure() config.name = "Bro::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; config.version.major = 1; - config.version.minor = 1; + config.version.minor = 2; return config; } From a89379c3532885ee6225f18f2e2bd2843d332371 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Thu, 25 May 2017 23:00:01 +0200 Subject: [PATCH 285/343] af_packet: Added bro-pkg instructions to the README. --- src/iosource/af_packet/README | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 3bec86e962..b23e4c4b0a 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -8,8 +8,24 @@ This plugin provides native AF_Packet support Installation ------------ -Make sure the kernel headers are installed and your kernel supports -PACKET_FANOUT [1]_ and TPACKET_V3. The following will then compile and +Before installing the plugin, make sure the kernel headers are installed and your +kernel supports PACKET_FANOUT [1]_ and TPACKET_V3. + +Bro Package Manager +``````````````````` +The plugin is available as package for the `Bro Package Manager +`_ and can be installed using the +following command:: + + bro-pkg install bro-af_packet-plugin + +To install uncompiled plugins, Bro's source code must be available to the package manager +(see package manager's `documentation `_ for more information). + +Manual Install +`````````````` +The following will compile and install the AF_Packet plugin alongside Bro, assuming it can find the kernel headers in a standard location:: From 3adaef434bbf43c9c9f3a629431e68fd06c068d0 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Mon, 23 Oct 2017 18:08:44 +0200 Subject: [PATCH 286/343] af_packet: Added buffer_size option to broctl plugin. The buffer size can now be set in node.cfg using the af_packet_buffer_size key. --- src/iosource/af_packet/README | 1 + 1 file changed, 1 insertion(+) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index b23e4c4b0a..fe798f3712 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -98,6 +98,7 @@ be utilized. The following shows an exemplary configuration:: # Optional parameters for per node configuration: af_packet_fanout_id=23 af_packet_fanout_mode=AF_Packet::FANOUT_HASH + af_packet_buffer_size=128*1024*1024 If all interfaces using ``lb_method=custom`` should be configured for AF_Packet, the prefix can be globally definied by adding the following line to ``broctl.conf``:: From 4eaa201821f07e72eefec864a25e46690fde6994 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 22 Nov 2017 17:42:09 +0100 Subject: [PATCH 287/343] af_packet: Updated README regarding --with-latest-kernel. --- src/iosource/af_packet/README | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index fe798f3712..95eaff7d71 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -32,9 +32,10 @@ kernel headers in a standard location:: # ./configure && make && make install If the headers are installed somewhere non-standard, add -``--with-kernel=`` to the ``configure`` -command. If everything built and installed correctly, you should see -this:: +``--with-kernel=`` to the ``configure`` command. Furthermore, +``--with-latest-kernel`` will use the latest headers available instead of looking for +the headers matching the running kernel's version. If everything built and installed +correctly, you should see this:: # bro -NN Bro::AF_Packet Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.2) From b6e52b262c330c7661d5d8651dae0466cae57cf9 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 22 Nov 2017 17:58:53 +0100 Subject: [PATCH 288/343] af_packet: Increased version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 95eaff7d71..0ec26d8e2f 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -38,7 +38,7 @@ the headers matching the running kernel's version. If everything built and insta correctly, you should see this:: # bro -NN Bro::AF_Packet - Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.2) + Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.3) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 731800e649..d964755857 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -14,6 +14,6 @@ plugin::Configuration Plugin::Configure() config.name = "Bro::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; config.version.major = 1; - config.version.minor = 2; + config.version.minor = 3; return config; } From 9cc01769b45e31132d995e2f5c394975f01c060e Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 9 Jan 2019 17:47:06 +0100 Subject: [PATCH 289/343] af_packet: Minor improvements to fix compiler warnings. --- src/iosource/af_packet/src/AF_Packet.cc | 4 ++-- src/iosource/af_packet/src/Plugin.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 7b351e8783..14ae23a611 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -40,7 +40,7 @@ void AF_PacketSource::Open() // Create RX-ring try { rx_ring = new RX_Ring(socket_fd, buffer_size); - } catch (RX_RingException e) { + } catch (RX_RingException& e) { Error(errno ? strerror(errno) : "unable to create RX-ring"); close(socket_fd); return; @@ -80,7 +80,7 @@ void AF_PacketSource::Open() props.is_live = true; props.link_type = DLT_EN10MB; // Ethernet headers - memset(&stats, 0, sizeof(stats)); + stats.received = stats.dropped = stats.link = stats.bytes_received = 0; num_discarded = 0; Opened(props); diff --git a/src/iosource/af_packet/src/Plugin.h b/src/iosource/af_packet/src/Plugin.h index e1e7e1a1e4..0631053b59 100644 --- a/src/iosource/af_packet/src/Plugin.h +++ b/src/iosource/af_packet/src/Plugin.h @@ -11,7 +11,7 @@ class Plugin : public ::plugin::Plugin { protected: // Overridden from plugin::Plugin. - virtual plugin::Configuration Configure(); + plugin::Configuration Configure() override; }; extern Plugin plugin; From eb3dc4b563fe3f522951c49b23d89c5c20617224 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 9 Jan 2019 18:43:34 +0100 Subject: [PATCH 290/343] af_packet: Include info files for distribution. --- src/iosource/af_packet/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt index a37cd33844..48a3d24a7c 100644 --- a/src/iosource/af_packet/CMakeLists.txt +++ b/src/iosource/af_packet/CMakeLists.txt @@ -14,7 +14,7 @@ if ( KERNELHEADERS_FOUND ) bro_plugin_cc(src/AF_Packet.cc) bro_plugin_cc(src/RX_Ring.cc) bro_plugin_bif(src/af_packet.bif) - bro_plugin_dist_files(broctl/af_packet.py) + bro_plugin_dist_files(broctl/af_packet.py README COPYING VERSION) bro_plugin_end() message(STATUS "Kernelheader prefix : ${KERNELHEADERS_ROOT_DIR}") From 5e3ae6227b28c31be4ec86f2449cae3ecf9bcb35 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Mon, 11 Feb 2019 16:27:09 +0100 Subject: [PATCH 291/343] af_packet: Updated README. --- src/iosource/af_packet/README | 67 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 0ec26d8e2f..63629d84a6 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -2,40 +2,35 @@ Bro::AF_Packet ============== -This plugin provides native AF_Packet support -(http://man7.org/linux/man-pages/man7/packet.7.html) for Bro. +This plugin provides native AF_Packet support for Bro/Zeek +(http://man7.org/linux/man-pages/man7/packet.7.html). Installation ------------ -Before installing the plugin, make sure the kernel headers are installed and your -kernel supports PACKET_FANOUT [1]_ and TPACKET_V3. +Before installing the plugin, make sure the kernel headers are installed and +your kernel supports PACKET_FANOUT [1]_ and TPACKET_V3. -Bro Package Manager -``````````````````` -The plugin is available as package for the `Bro Package Manager -`_ and can be installed using the +Package Manager +``````````````` +The plugin is available as package for the `Bro/Zeek Package Manager +`_ and can be installed using the following command:: bro-pkg install bro-af_packet-plugin -To install uncompiled plugins, Bro's source code must be available to the package manager -(see package manager's `documentation `_ for more information). - Manual Install `````````````` -The following will compile and -install the AF_Packet plugin alongside Bro, assuming it can find the -kernel headers in a standard location:: +The following will compile and install the AF_Packet plugin alongside Bro/Zeek, +assuming it can find the kernel headers in a standard location:: # ./configure && make && make install If the headers are installed somewhere non-standard, add -``--with-kernel=`` to the ``configure`` command. Furthermore, -``--with-latest-kernel`` will use the latest headers available instead of looking for -the headers matching the running kernel's version. If everything built and installed -correctly, you should see this:: +``--with-kernel=`` to the ``configure`` command. +Furthermore, ``--with-latest-kernel`` will use the latest headers available +instead of looking for the headers matching the running kernel's version. If +everything built and installed correctly, you should see this:: # bro -NN Bro::AF_Packet Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.3) @@ -47,23 +42,23 @@ correctly, you should see this:: [Constant] AF_Packet::fanout_mode [Constant] AF_Packet::fanout_id -.. [1] Note that some kernel versions between 3.10 and 4.7 might exhibit a bug that - prevents the required symmetric hashing. The script available at - https://github.com/JustinAzoff/can-i-use-afpacket-fanout can be used to verify - whether PACKET_FANOUT works as expected. +.. [1] Note that some kernel versions between 3.10 and 4.7 might exhibit a bug + that prevents the required symmetric hashing. The script available at + https://github.com/JustinAzoff/can-i-use-afpacket-fanout can be used to + verify whether PACKET_FANOUT works as expected. Usage ----- -Once installed, you can use AF_Packet interfaces/ports by prefixing them -with ``af_packet::`` on the command line. For example, to use AF_Packet -to monitor interface ``eth0``:: +Once installed, you can use AF_Packet interfaces/ports by prefixing them with +``af_packet::`` on the command line. For example, to use AF_Packet to monitor +interface ``eth0``:: # bro -i af_packet::eth0 -To use AF_Packet, running Bro without root privileges, the Bro processes needs -the CAP_NET_RAW capability. You can set it with the following command (on each -sensor, after ``broctl install``):: +To use AF_Packet, running Bro/Zeek without root privileges, the Bro processes +need the CAP_NET_RAW capability. You can set it with the following command (on +each sensor, after ``broctl install``):: # setcap cap_net_raw+eip /bin/bro @@ -78,8 +73,8 @@ buffer size. See scripts/init.bro for the default values. Usage with ``broctl`` --------------------- -To use the AF_Packet plugin with ``broctl``, the ``custom`` load balance method can -be utilized. The following shows an exemplary configuration:: +To use the AF_Packet plugin with ``broctl``, the ``custom`` load balance method +can be utilized. The following shows an exemplary configuration:: [manager] type=manager @@ -101,13 +96,15 @@ be utilized. The following shows an exemplary configuration:: af_packet_fanout_mode=AF_Packet::FANOUT_HASH af_packet_buffer_size=128*1024*1024 -If all interfaces using ``lb_method=custom`` should be configured for AF_Packet, the -prefix can be globally definied by adding the following line to ``broctl.conf``:: +If all interfaces using ``lb_method=custom`` should be configured for +AF_Packet, the prefix can be globally definied by adding the following +line to ``broctl.conf``:: lb_custom.InterfacePrefix=af_packet:: Limitations ----------- -* Even using AF_Packet's ``ETH_P_ALL``, the kernel removes VLAN tags. While the tags - are provided spereately, there is no efficient way to pass them to Bro. +* Even using AF_Packet's ``ETH_P_ALL``, the kernel removes VLAN tags. + While the tags are provided spereately, there is no efficient way to + pass them to Bro/Zeek. From 1f1627ad738f07e84275515c4947b35d655b72ae Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Mon, 11 Feb 2019 16:52:16 +0100 Subject: [PATCH 292/343] af_packet: Increased version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 63629d84a6..897e9e469d 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -33,7 +33,7 @@ instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this:: # bro -NN Bro::AF_Packet - Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.3) + Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.4) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index d964755857..02c7a67cf8 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -14,6 +14,6 @@ plugin::Configuration Plugin::Configure() config.name = "Bro::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; config.version.major = 1; - config.version.minor = 3; + config.version.minor = 4; return config; } From a7195a7a757c704f35ab4e91eec915f5fe61283a Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sat, 1 Feb 2020 21:12:35 -0700 Subject: [PATCH 293/343] af_packet: File naming and build system changes to support deprecation changes in Zeek 3.0 --- src/iosource/af_packet/CMakeLists.txt | 28 ++++++++++------ src/iosource/af_packet/README | 32 +++++++++---------- src/iosource/af_packet/scripts/__load__.bro | 5 --- src/iosource/af_packet/scripts/__load__.zeek | 5 +++ .../af_packet/scripts/{init.bro => init.zeek} | 0 src/iosource/af_packet/src/AF_Packet.cc | 3 +- src/iosource/af_packet/src/Plugin.cc | 6 ++-- src/iosource/af_packet/src/Plugin.h | 6 ++-- 8 files changed, 46 insertions(+), 39 deletions(-) delete mode 100644 src/iosource/af_packet/scripts/__load__.bro create mode 100644 src/iosource/af_packet/scripts/__load__.zeek rename src/iosource/af_packet/scripts/{init.bro => init.zeek} (100%) diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt index 48a3d24a7c..6a01b8d691 100644 --- a/src/iosource/af_packet/CMakeLists.txt +++ b/src/iosource/af_packet/CMakeLists.txt @@ -1,23 +1,31 @@ -cmake_minimum_required(VERSION 2.6.3) +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) -project(Plugin) +project(ZeekPluginAF_Packet) -include(BroPlugin) +include(ZeekPlugin) find_package(KernelHeaders) if ( KERNELHEADERS_FOUND ) #TODO: Make sure the specified kernel headers are used - bro_plugin_begin(Bro AF_Packet) - bro_plugin_cc(src/Plugin.cc) - bro_plugin_cc(src/AF_Packet.cc) - bro_plugin_cc(src/RX_Ring.cc) - bro_plugin_bif(src/af_packet.bif) - bro_plugin_dist_files(broctl/af_packet.py README COPYING VERSION) - bro_plugin_end() + zeek_plugin_begin(Zeek AF_Packet) + zeek_plugin_cc(src/Plugin.cc) + zeek_plugin_cc(src/AF_Packet.cc) + zeek_plugin_cc(src/RX_Ring.cc) + zeek_plugin_bif(src/af_packet.bif) + zeek_plugin_dist_files(zeekctl/af_packet.py README COPYING VERSION) + zeek_plugin_end() message(STATUS "Kernelheader prefix : ${KERNELHEADERS_ROOT_DIR}") else () message(FATAL_ERROR "Kernel headers not found.") +endif() + +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1) + +if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") + # Allows building rpm/deb packages via "make package" in build dir. + include(ConfigurePackaging) + ConfigurePackaging(${VERSION}) endif () diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 897e9e469d..f54830b11f 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -1,8 +1,8 @@ -Bro::AF_Packet +Zeek::AF_Packet ============== -This plugin provides native AF_Packet support for Bro/Zeek +This plugin provides native AF_Packet support for Zeek (http://man7.org/linux/man-pages/man7/packet.7.html). Installation @@ -13,15 +13,15 @@ your kernel supports PACKET_FANOUT [1]_ and TPACKET_V3. Package Manager ``````````````` -The plugin is available as package for the `Bro/Zeek Package Manager +The plugin is available as package for the `Zeek Package Manager `_ and can be installed using the following command:: - bro-pkg install bro-af_packet-plugin + zkg install zeek-af_packet-plugin Manual Install `````````````` -The following will compile and install the AF_Packet plugin alongside Bro/Zeek, +The following will compile and install the AF_Packet plugin alongside Zeek, assuming it can find the kernel headers in a standard location:: # ./configure && make && make install @@ -32,8 +32,8 @@ Furthermore, ``--with-latest-kernel`` will use the latest headers available instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this:: - # bro -NN Bro::AF_Packet - Bro::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.4) + # zeek -NN Zeek::AF_Packet + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.4) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size @@ -54,13 +54,13 @@ Once installed, you can use AF_Packet interfaces/ports by prefixing them with ``af_packet::`` on the command line. For example, to use AF_Packet to monitor interface ``eth0``:: - # bro -i af_packet::eth0 + # zeek -i af_packet::eth0 -To use AF_Packet, running Bro/Zeek without root privileges, the Bro processes +To use AF_Packet, running Zeek without root privileges, the Zeek processes need the CAP_NET_RAW capability. You can set it with the following command (on -each sensor, after ``broctl install``):: +each sensor, after ``zeekctl install``):: - # setcap cap_net_raw+eip /bin/bro + # setcap cap_net_raw+eip /bin/zeek The AF_Packet plugin automatically enables promiscuous mode on the interfaces. As the plugin is using PACKET_ADD_MEMBERSHIP to enter the promiscuous mode @@ -68,12 +68,12 @@ without interfering others, the PROMISC flag is not touched. To verify that the interface entered promiscuous mode you can use ``dmesg``. To adapt the plugin to your needs, you can set a couple of parameters like -buffer size. See scripts/init.bro for the default values. +buffer size. See scripts/init.zeek for the default values. -Usage with ``broctl`` +Usage with ``zeekctl`` --------------------- -To use the AF_Packet plugin with ``broctl``, the ``custom`` load balance method +To use the AF_Packet plugin with ``zeekctl``, the ``custom`` load balance method can be utilized. The following shows an exemplary configuration:: [manager] @@ -98,7 +98,7 @@ can be utilized. The following shows an exemplary configuration:: If all interfaces using ``lb_method=custom`` should be configured for AF_Packet, the prefix can be globally definied by adding the following -line to ``broctl.conf``:: +line to ``zeekctl.conf``:: lb_custom.InterfacePrefix=af_packet:: @@ -107,4 +107,4 @@ Limitations * Even using AF_Packet's ``ETH_P_ALL``, the kernel removes VLAN tags. While the tags are provided spereately, there is no efficient way to - pass them to Bro/Zeek. + pass them to Zeek. diff --git a/src/iosource/af_packet/scripts/__load__.bro b/src/iosource/af_packet/scripts/__load__.bro deleted file mode 100644 index f77b383b48..0000000000 --- a/src/iosource/af_packet/scripts/__load__.bro +++ /dev/null @@ -1,5 +0,0 @@ -# -# This is loaded unconditionally at Bro startup. -# - -@load ./init.bro diff --git a/src/iosource/af_packet/scripts/__load__.zeek b/src/iosource/af_packet/scripts/__load__.zeek new file mode 100644 index 0000000000..588cabc7c4 --- /dev/null +++ b/src/iosource/af_packet/scripts/__load__.zeek @@ -0,0 +1,5 @@ +# +# This is loaded unconditionally at Zeek startup. +# + +@load ./init.zeek diff --git a/src/iosource/af_packet/scripts/init.bro b/src/iosource/af_packet/scripts/init.zeek similarity index 100% rename from src/iosource/af_packet/scripts/init.bro rename to src/iosource/af_packet/scripts/init.zeek diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 14ae23a611..41884e6409 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -1,5 +1,5 @@ -#include "bro-config.h" +#include "zeek-config.h" #include "AF_Packet.h" #include "RX_Ring.h" @@ -287,4 +287,3 @@ iosource::PktSrc* AF_PacketSource::InstantiateAF_Packet(const std::string& path, { return new AF_PacketSource(path, is_live); } - diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 02c7a67cf8..475340b2e2 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -2,16 +2,16 @@ #include "Plugin.h" #include "AF_Packet.h" -namespace plugin { namespace Bro_AF_Packet { Plugin plugin; } } +namespace plugin { namespace Zeek_AF_Packet { Plugin plugin; } } -using namespace plugin::Bro_AF_Packet; +using namespace plugin::Zeek_AF_Packet; plugin::Configuration Plugin::Configure() { AddComponent(new ::iosource::PktSrcComponent("AF_PacketReader", "af_packet", ::iosource::PktSrcComponent::LIVE, ::iosource::pktsrc::AF_PacketSource::InstantiateAF_Packet)); plugin::Configuration config; - config.name = "Bro::AF_Packet"; + config.name = "Zeek::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; config.version.major = 1; config.version.minor = 4; diff --git a/src/iosource/af_packet/src/Plugin.h b/src/iosource/af_packet/src/Plugin.h index 0631053b59..32549e2abe 100644 --- a/src/iosource/af_packet/src/Plugin.h +++ b/src/iosource/af_packet/src/Plugin.h @@ -1,11 +1,11 @@ -#ifndef BRO_PLUGIN_BRO_AF_PACKET -#define BRO_PLUGIN_BRO_AF_PACKET +#ifndef ZEEK_PLUGIN_ZEEK_AF_PACKET +#define ZEEK_PLUGIN_ZEEK_AF_PACKET #include namespace plugin { -namespace Bro_AF_Packet { +namespace Zeek_AF_Packet { class Plugin : public ::plugin::Plugin { From 8d0bc4a8044d667bf2514f57f853dab86e91eb1c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 4 Feb 2020 19:26:23 -0500 Subject: [PATCH 294/343] af_packet: Add some missing includes due to changes in Zeek 3.1 --- src/iosource/af_packet/src/AF_Packet.h | 1 + src/iosource/af_packet/src/Plugin.cc | 1 + 2 files changed, 2 insertions(+) diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index 6887514316..f1585ce702 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -17,6 +17,7 @@ extern "C" { #include // AF_PACKET, etc. #include // SIOCSHWTSTAMP #include // hwtstamp_config +#include } #include "iosource/PktSrc.h" diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 475340b2e2..46b9efdfa9 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -1,6 +1,7 @@ #include "Plugin.h" #include "AF_Packet.h" +#include "iosource/Component.h" namespace plugin { namespace Zeek_AF_Packet { Plugin plugin; } } From 8aa35fed6ff7818b4a7e3a4fb083e42f992fe86c Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Mon, 24 Feb 2020 18:15:05 +0100 Subject: [PATCH 295/343] af_packet: Add upgrade note to README. --- src/iosource/af_packet/README | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index f54830b11f..1867ba3e2c 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -5,6 +5,17 @@ Zeek::AF_Packet This plugin provides native AF_Packet support for Zeek (http://man7.org/linux/man-pages/man7/packet.7.html). +Upgrade to Zeek +--------------- + +In the context of the transition from Bro to Zeek, the plugin has been renamed. To upgrade from the Bro-version of the plugin, just remove the old version and then install the renamed one. Using the package manager the following will uninstall the old version of the plugin:: + + # zkg remove bro-af_packet-plugin + +For manually installed plugins, remove the corresponding plugin directory:: + + # rm -rf /lib/bro/plugins/Bro_AF_Packet/ + Installation ------------ From 57dd239917d176e46dd53b8f2cb2e775190bab03 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Mon, 24 Feb 2020 18:35:51 +0100 Subject: [PATCH 296/343] af_packet: Increase version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 1867ba3e2c..925f30a2fe 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -44,7 +44,7 @@ instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this:: # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 1.4) + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 2.0.0) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 46b9efdfa9..268380923b 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -14,7 +14,8 @@ plugin::Configuration Plugin::Configure() plugin::Configuration config; config.name = "Zeek::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; - config.version.major = 1; - config.version.minor = 4; + config.version.major = 2; + config.version.minor = 0; + config.version.patch = 0; return config; } From 4deb8f6402dafbe46bc56023134833516a540915 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Thu, 7 May 2020 18:53:49 +0200 Subject: [PATCH 297/343] af_packet: Add support for defragmentation of IP packets. --- src/iosource/af_packet/scripts/init.zeek | 2 ++ src/iosource/af_packet/src/AF_Packet.cc | 20 ++++++++++++++------ src/iosource/af_packet/src/AF_Packet.h | 4 ++-- src/iosource/af_packet/src/af_packet.bif | 1 + 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/iosource/af_packet/scripts/init.zeek b/src/iosource/af_packet/scripts/init.zeek index 9a6abc000c..26a7582df8 100644 --- a/src/iosource/af_packet/scripts/init.zeek +++ b/src/iosource/af_packet/scripts/init.zeek @@ -11,6 +11,8 @@ export { const enable_hw_timestamping = F &redef; ## Toggle whether to use PACKET_FANOUT. const enable_fanout = T &redef; + ## Toggle defragmentation of IP packets using PACKET_FANOUT_FLAG_DEFRAG. + const enable_defrag = F &redef; ## Fanout Mode. const fanout_mode = FANOUT_HASH &redef; ## Fanout ID. diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 41884e6409..fac05971f4 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -28,6 +28,7 @@ void AF_PacketSource::Open() uint64_t buffer_size = BifConst::AF_Packet::buffer_size; bool enable_hw_timestamping = BifConst::AF_Packet::enable_hw_timestamping; bool enable_fanout = BifConst::AF_Packet::enable_fanout; + bool enable_defrag = BifConst::AF_Packet::enable_defrag; socket_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); @@ -129,7 +130,7 @@ inline bool AF_PacketSource::EnablePromiscMode() return (ret >= 0); } -inline bool AF_PacketSource::ConfigureFanoutGroup(bool enabled) +inline bool AF_PacketSource::ConfigureFanoutGroup(bool enabled, bool defrag) { if ( enabled ) { @@ -137,7 +138,7 @@ inline bool AF_PacketSource::ConfigureFanoutGroup(bool enabled) int ret; fanout_id = BifConst::AF_Packet::fanout_id; - fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode() << 16)); + fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode(defrag) << 16)); ret = setsockopt(socket_fd, SOL_PACKET, PACKET_FANOUT, &fanout_arg, sizeof(fanout_arg)); @@ -176,15 +177,22 @@ inline bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) return true; } -inline uint32_t AF_PacketSource::GetFanoutMode() +inline uint32_t AF_PacketSource::GetFanoutMode(bool defrag) { + uint32_t fanout_mode; + switch ( BifConst::AF_Packet::fanout_mode->AsEnum() ) { - case BifEnum::AF_Packet::FANOUT_CPU: return PACKET_FANOUT_CPU; + case BifEnum::AF_Packet::FANOUT_CPU: fanout_mode = PACKET_FANOUT_CPU; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - case BifEnum::AF_Packet::FANOUT_QM: return PACKET_FANOUT_QM; + case BifEnum::AF_Packet::FANOUT_QM: fanout_mode = PACKET_FANOUT_QM; #endif - default: return PACKET_FANOUT_HASH; + default: fanout_mode = PACKET_FANOUT_HASH; } + + if ( defrag ) + fanout_mode |= PACKET_FANOUT_FLAG_DEFRAG; + + return fanout_mode; } void AF_PacketSource::Close() diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index f1585ce702..c8e9ab5d8f 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -69,9 +69,9 @@ private: bool BindInterface(); bool EnablePromiscMode(); - bool ConfigureFanoutGroup(bool enabled); + bool ConfigureFanoutGroup(bool enabled, bool defrag=false); bool ConfigureHWTimestamping(bool enabled); - uint32_t GetFanoutMode(); + uint32_t GetFanoutMode(bool defrag=false); }; } diff --git a/src/iosource/af_packet/src/af_packet.bif b/src/iosource/af_packet/src/af_packet.bif index 334121ea05..da05ec930e 100644 --- a/src/iosource/af_packet/src/af_packet.bif +++ b/src/iosource/af_packet/src/af_packet.bif @@ -12,5 +12,6 @@ enum FanoutMode %{ const buffer_size: count; const enable_hw_timestamping: bool; const enable_fanout: bool; +const enable_defrag: bool; const fanout_mode: FanoutMode; const fanout_id: count; From 130f7f727280b58edbc8acc806c3547e119533d0 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Thu, 1 Oct 2020 14:06:43 +0200 Subject: [PATCH 298/343] af_packet: Increase version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 925f30a2fe..cf93481144 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -44,7 +44,7 @@ instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this:: # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 2.0.0) + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 2.1.0) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 268380923b..542b2c18a4 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -15,7 +15,7 @@ plugin::Configuration Plugin::Configure() config.name = "Zeek::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; config.version.major = 2; - config.version.minor = 0; + config.version.minor = 1; config.version.patch = 0; return config; } From 62356c38ddaa35c6e2cac22d899438f1a2cb1a6f Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 28 Oct 2020 17:51:59 +0100 Subject: [PATCH 299/343] af_packet: Fixed test baseline to include defrag option. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index cf93481144..cccbc8fcc8 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -44,7 +44,7 @@ instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this:: # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 2.1.0) + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 2.1.1) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 542b2c18a4..0f424c8fe8 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -16,6 +16,6 @@ plugin::Configuration Plugin::Configure() config.description = "Packet acquisition via AF_Packet"; config.version.major = 2; config.version.minor = 1; - config.version.patch = 0; + config.version.patch = 1; return config; } From e3c5865684395976fe8bd1a1be10749aaae6d72b Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Sun, 1 Nov 2020 00:21:14 -0500 Subject: [PATCH 300/343] af_packet: GetFanoutMode: Fix case statement (missing breaks). Without this, you can't actually set the fanout mode to anything but HASH. --- src/iosource/af_packet/src/AF_Packet.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index fac05971f4..98619a422c 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -183,10 +183,13 @@ inline uint32_t AF_PacketSource::GetFanoutMode(bool defrag) switch ( BifConst::AF_Packet::fanout_mode->AsEnum() ) { case BifEnum::AF_Packet::FANOUT_CPU: fanout_mode = PACKET_FANOUT_CPU; + break; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) case BifEnum::AF_Packet::FANOUT_QM: fanout_mode = PACKET_FANOUT_QM; + break; #endif default: fanout_mode = PACKET_FANOUT_HASH; + break; } if ( defrag ) From 79842b25c17d8e6be79871c59e79f553eb9f7baf Mon Sep 17 00:00:00 2001 From: Michael Dopheide Date: Thu, 25 Feb 2021 13:29:04 -0600 Subject: [PATCH 301/343] af_packet: Namespace changes adding zeek:: as well as zeek/ prefix for include files. --- src/iosource/af_packet/src/AF_Packet.cc | 20 ++++++++++---------- src/iosource/af_packet/src/AF_Packet.h | 10 ++++------ src/iosource/af_packet/src/Plugin.cc | 12 ++++++------ src/iosource/af_packet/src/Plugin.h | 12 +++++------- 4 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 98619a422c..6a96930665 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -1,12 +1,12 @@ -#include "zeek-config.h" +#include "zeek/zeek-config.h" #include "AF_Packet.h" #include "RX_Ring.h" #include "af_packet.bif.h" -using namespace iosource::pktsrc; +using namespace af_packet::iosource::pktsrc; AF_PacketSource::~AF_PacketSource() { @@ -25,10 +25,10 @@ AF_PacketSource::AF_PacketSource(const std::string& path, bool is_live) void AF_PacketSource::Open() { - uint64_t buffer_size = BifConst::AF_Packet::buffer_size; - bool enable_hw_timestamping = BifConst::AF_Packet::enable_hw_timestamping; - bool enable_fanout = BifConst::AF_Packet::enable_fanout; - bool enable_defrag = BifConst::AF_Packet::enable_defrag; + uint64_t buffer_size = zeek::BifConst::AF_Packet::buffer_size; + bool enable_hw_timestamping = zeek::BifConst::AF_Packet::enable_hw_timestamping; + bool enable_fanout = zeek::BifConst::AF_Packet::enable_fanout; + bool enable_defrag = zeek::BifConst::AF_Packet::enable_defrag; socket_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); @@ -137,7 +137,7 @@ inline bool AF_PacketSource::ConfigureFanoutGroup(bool enabled, bool defrag) uint32_t fanout_arg, fanout_id; int ret; - fanout_id = BifConst::AF_Packet::fanout_id; + fanout_id = zeek::BifConst::AF_Packet::fanout_id; fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode(defrag) << 16)); ret = setsockopt(socket_fd, SOL_PACKET, PACKET_FANOUT, @@ -181,7 +181,7 @@ inline uint32_t AF_PacketSource::GetFanoutMode(bool defrag) { uint32_t fanout_mode; - switch ( BifConst::AF_Packet::fanout_mode->AsEnum() ) { + switch ( zeek::BifConst::AF_Packet::fanout_mode->AsEnum() ) { case BifEnum::AF_Packet::FANOUT_CPU: fanout_mode = PACKET_FANOUT_CPU; break; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) @@ -210,7 +210,7 @@ void AF_PacketSource::Close() Closed(); } -bool AF_PacketSource::ExtractNextPacket(Packet* pkt) +bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) { if ( ! socket_fd ) return false; @@ -294,7 +294,7 @@ void AF_PacketSource::Statistics(Stats* s) memcpy(s, &stats, sizeof(Stats)); } -iosource::PktSrc* AF_PacketSource::InstantiateAF_Packet(const std::string& path, bool is_live) +zeek::iosource::PktSrc* AF_PacketSource::InstantiateAF_Packet(const std::string& path, bool is_live) { return new AF_PacketSource(path, is_live); } diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index c8e9ab5d8f..feba868c2d 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -20,13 +20,12 @@ extern "C" { #include } -#include "iosource/PktSrc.h" +#include "zeek/iosource/PktSrc.h" #include "RX_Ring.h" -namespace iosource { -namespace pktsrc { +namespace af_packet::iosource::pktsrc { -class AF_PacketSource : public iosource::PktSrc { +class AF_PacketSource : public zeek::iosource::PktSrc { public: /** * Constructor. @@ -50,7 +49,7 @@ protected: // PktSrc interface. virtual void Open(); virtual void Close(); - virtual bool ExtractNextPacket(Packet* pkt); + virtual bool ExtractNextPacket(zeek::Packet* pkt); virtual void DoneWithPacket(); virtual bool PrecompileFilter(int index, const std::string& filter); virtual bool SetFilter(int index); @@ -74,7 +73,6 @@ private: uint32_t GetFanoutMode(bool defrag=false); }; -} } #endif diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 0f424c8fe8..ce482f60d5 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -1,17 +1,17 @@ #include "Plugin.h" #include "AF_Packet.h" -#include "iosource/Component.h" +#include "zeek/iosource/Component.h" -namespace plugin { namespace Zeek_AF_Packet { Plugin plugin; } } +namespace af_packet::plugin::Zeek_AF_Packet { Plugin plugin; } -using namespace plugin::Zeek_AF_Packet; +using namespace af_packet::plugin::Zeek_AF_Packet; -plugin::Configuration Plugin::Configure() +zeek::plugin::Configuration Plugin::Configure() { - AddComponent(new ::iosource::PktSrcComponent("AF_PacketReader", "af_packet", ::iosource::PktSrcComponent::LIVE, ::iosource::pktsrc::AF_PacketSource::InstantiateAF_Packet)); + AddComponent(new ::zeek::iosource::PktSrcComponent("AF_PacketReader", "af_packet", ::zeek::iosource::PktSrcComponent::LIVE, ::af_packet::iosource::pktsrc::AF_PacketSource::InstantiateAF_Packet)); - plugin::Configuration config; + zeek::plugin::Configuration config; config.name = "Zeek::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; config.version.major = 2; diff --git a/src/iosource/af_packet/src/Plugin.h b/src/iosource/af_packet/src/Plugin.h index 32549e2abe..ef8b0dab50 100644 --- a/src/iosource/af_packet/src/Plugin.h +++ b/src/iosource/af_packet/src/Plugin.h @@ -2,21 +2,19 @@ #ifndef ZEEK_PLUGIN_ZEEK_AF_PACKET #define ZEEK_PLUGIN_ZEEK_AF_PACKET -#include +#include -namespace plugin { -namespace Zeek_AF_Packet { +namespace af_packet::plugin::Zeek_AF_Packet { -class Plugin : public ::plugin::Plugin +class Plugin : public zeek::plugin::Plugin { protected: - // Overridden from plugin::Plugin. - plugin::Configuration Configure() override; + // Overridden from zeek::plugin::Plugin. + zeek::plugin::Configuration Configure() override; }; extern Plugin plugin; -} } #endif From e4aa85d2a630df35aa4ac81abbedd7ad398938d9 Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Mon, 10 May 2021 10:52:02 +0100 Subject: [PATCH 302/343] af_packet: Add FANOUT_CBPF and FANOUT_EBPF --- src/iosource/af_packet/src/AF_Packet.cc | 449 ++++++++++++----------- src/iosource/af_packet/src/af_packet.bif | 2 + 2 files changed, 230 insertions(+), 221 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 6a96930665..dae80820ac 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -1,4 +1,3 @@ - #include "zeek/zeek-config.h" #include "AF_Packet.h" @@ -9,292 +8,300 @@ using namespace af_packet::iosource::pktsrc; AF_PacketSource::~AF_PacketSource() - { - Close(); - } + { + Close(); + } AF_PacketSource::AF_PacketSource(const std::string& path, bool is_live) - { - if ( ! is_live ) - Error("AF_Packet source does not support offline input"); + { + if ( ! is_live ) + Error("AF_Packet source does not support offline input"); - current_filter = -1; - props.path = path; - props.is_live = is_live; - } + current_filter = -1; + props.path = path; + props.is_live = is_live; + } void AF_PacketSource::Open() - { - uint64_t buffer_size = zeek::BifConst::AF_Packet::buffer_size; - bool enable_hw_timestamping = zeek::BifConst::AF_Packet::enable_hw_timestamping; - bool enable_fanout = zeek::BifConst::AF_Packet::enable_fanout; - bool enable_defrag = zeek::BifConst::AF_Packet::enable_defrag; + { + uint64_t buffer_size = zeek::BifConst::AF_Packet::buffer_size; + bool enable_hw_timestamping = zeek::BifConst::AF_Packet::enable_hw_timestamping; + bool enable_fanout = zeek::BifConst::AF_Packet::enable_fanout; + bool enable_defrag = zeek::BifConst::AF_Packet::enable_defrag; - socket_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + socket_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if ( socket_fd < 0 ) - { - Error(errno ? strerror(errno) : "unable to create socket"); - return; - } + if ( socket_fd < 0 ) + { + Error(errno ? strerror(errno) : "unable to create socket"); + return; + } - // Create RX-ring - try { - rx_ring = new RX_Ring(socket_fd, buffer_size); - } catch (RX_RingException& e) { - Error(errno ? strerror(errno) : "unable to create RX-ring"); - close(socket_fd); - return; - } + // Create RX-ring + try { + rx_ring = new RX_Ring(socket_fd, buffer_size); + } catch (RX_RingException& e) { + Error(errno ? strerror(errno) : "unable to create RX-ring"); + close(socket_fd); + return; + } - // Setup interface - if ( ! BindInterface() ) - { - Error(errno ? strerror(errno) : "unable to bind to interface"); - close(socket_fd); - return; - } + // Setup interface + if ( ! BindInterface() ) + { + Error(errno ? strerror(errno) : "unable to bind to interface"); + close(socket_fd); + return; + } - if ( ! EnablePromiscMode() ) - { - Error(errno ? strerror(errno) : "unable enter promiscious mode"); - close(socket_fd); - return; - } + if ( ! EnablePromiscMode() ) + { + Error(errno ? strerror(errno) : "unable enter promiscious mode"); + close(socket_fd); + return; + } - if ( ! ConfigureFanoutGroup(enable_fanout) ) - { - Error(errno ? strerror(errno) : "failed to join fanout group"); - close(socket_fd); - return; - } + if ( ! ConfigureFanoutGroup(enable_fanout) ) + { + Error(errno ? strerror(errno) : "failed to join fanout group"); + close(socket_fd); + return; + } - if ( ! ConfigureHWTimestamping(enable_hw_timestamping) ) - { - Error(errno ? strerror(errno) : "failed to configure hardware timestamping"); - close(socket_fd); - return; - } + if ( ! ConfigureHWTimestamping(enable_hw_timestamping) ) + { + Error(errno ? strerror(errno) : "failed to configure hardware timestamping"); + close(socket_fd); + return; + } - props.netmask = NETMASK_UNKNOWN; - props.selectable_fd = socket_fd; - props.is_live = true; - props.link_type = DLT_EN10MB; // Ethernet headers + props.netmask = NETMASK_UNKNOWN; + props.selectable_fd = socket_fd; + props.is_live = true; + props.link_type = DLT_EN10MB; // Ethernet headers - stats.received = stats.dropped = stats.link = stats.bytes_received = 0; - num_discarded = 0; + stats.received = stats.dropped = stats.link = stats.bytes_received = 0; + num_discarded = 0; - Opened(props); - } + Opened(props); + } inline bool AF_PacketSource::BindInterface() - { - struct ifreq ifr; - struct sockaddr_ll saddr_ll; - int ret; + { + struct ifreq ifr; + struct sockaddr_ll saddr_ll; + int ret; - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); - ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); - if ( ret < 0 ) - return false; + ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); + if ( ret < 0 ) + return false; - memset(&saddr_ll, 0, sizeof(saddr_ll)); - saddr_ll.sll_family = AF_PACKET; - saddr_ll.sll_protocol = htons(ETH_P_ALL); - saddr_ll.sll_ifindex = ifr.ifr_ifindex; + memset(&saddr_ll, 0, sizeof(saddr_ll)); + saddr_ll.sll_family = AF_PACKET; + saddr_ll.sll_protocol = htons(ETH_P_ALL); + saddr_ll.sll_ifindex = ifr.ifr_ifindex; - ret = bind(socket_fd, (struct sockaddr *) &saddr_ll, sizeof(saddr_ll)); - return (ret >= 0); - } + ret = bind(socket_fd, (struct sockaddr *) &saddr_ll, sizeof(saddr_ll)); + return (ret >= 0); + } inline bool AF_PacketSource::EnablePromiscMode() - { - struct ifreq ifr; - struct packet_mreq mreq; - int ret; + { + struct ifreq ifr; + struct packet_mreq mreq; + int ret; - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); - ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); - if ( ret < 0 ) - return false; + ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); + if ( ret < 0 ) + return false; - memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = ifr.ifr_ifindex; - mreq.mr_type = PACKET_MR_PROMISC; + memset(&mreq, 0, sizeof(mreq)); + mreq.mr_ifindex = ifr.ifr_ifindex; + mreq.mr_type = PACKET_MR_PROMISC; - ret = setsockopt(socket_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); - return (ret >= 0); - } + ret = setsockopt(socket_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + return (ret >= 0); + } inline bool AF_PacketSource::ConfigureFanoutGroup(bool enabled, bool defrag) - { - if ( enabled ) - { - uint32_t fanout_arg, fanout_id; - int ret; + { + if ( enabled ) + { + uint32_t fanout_arg, fanout_id; + int ret; - fanout_id = zeek::BifConst::AF_Packet::fanout_id; - fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode(defrag) << 16)); + fanout_id = zeek::BifConst::AF_Packet::fanout_id; + fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode(defrag) << 16)); - ret = setsockopt(socket_fd, SOL_PACKET, PACKET_FANOUT, - &fanout_arg, sizeof(fanout_arg)); + ret = setsockopt(socket_fd, SOL_PACKET, PACKET_FANOUT, + &fanout_arg, sizeof(fanout_arg)); - if ( ret < 0 ) - return false; - } - return true; - } + if ( ret < 0 ) + return false; + } + return true; + } inline bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) - { - if ( enabled ) - { - struct ifreq ifr; - struct hwtstamp_config hwts_cfg; - int ret, opt; + { + if ( enabled ) + { + struct ifreq ifr; + struct hwtstamp_config hwts_cfg; + int ret, opt; - memset(&hwts_cfg, 0, sizeof(hwts_cfg)); - hwts_cfg.tx_type = HWTSTAMP_TX_OFF; - hwts_cfg.rx_filter = HWTSTAMP_FILTER_ALL; - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); - ifr.ifr_data = &hwts_cfg; + memset(&hwts_cfg, 0, sizeof(hwts_cfg)); + hwts_cfg.tx_type = HWTSTAMP_TX_OFF; + hwts_cfg.rx_filter = HWTSTAMP_FILTER_ALL; + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); + ifr.ifr_data = &hwts_cfg; - ret = ioctl(socket_fd, SIOCSHWTSTAMP, &ifr); - if ( ret < 0 ) - return false; + ret = ioctl(socket_fd, SIOCSHWTSTAMP, &ifr); + if ( ret < 0 ) + return false; - opt = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE; - ret = setsockopt(socket_fd, SOL_PACKET, PACKET_TIMESTAMP, - &opt, sizeof(opt)); - if( ret < 0 ) - return false; - } - return true; - } + opt = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE; + ret = setsockopt(socket_fd, SOL_PACKET, PACKET_TIMESTAMP, + &opt, sizeof(opt)); + if( ret < 0 ) + return false; + } + return true; + } inline uint32_t AF_PacketSource::GetFanoutMode(bool defrag) - { - uint32_t fanout_mode; + { + uint32_t fanout_mode; - switch ( zeek::BifConst::AF_Packet::fanout_mode->AsEnum() ) { - case BifEnum::AF_Packet::FANOUT_CPU: fanout_mode = PACKET_FANOUT_CPU; - break; - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - case BifEnum::AF_Packet::FANOUT_QM: fanout_mode = PACKET_FANOUT_QM; - break; - #endif - default: fanout_mode = PACKET_FANOUT_HASH; - break; - } + switch ( zeek::BifConst::AF_Packet::fanout_mode->AsEnum() ) { + case BifEnum::AF_Packet::FANOUT_CPU: fanout_mode = PACKET_FANOUT_CPU; + break; + #ifdef PACKET_FANOUT_QM + case BifEnum::AF_Packet::FANOUT_QM: fanout_mode = PACKET_FANOUT_QM; + break; + #endif + #ifdef PACKET_FANOUT_CBPF + case BifEnum::AF_Packet::FANOUT_CBPF: fanout_mode = PACKET_FANOUT_CBPF; + break; + #endif + #ifdef PACKET_FANOUT_EBPF + case BifEnum::AF_Packet::FANOUT_EBPF: fanout_mode = PACKET_FANOUT_EBPF; + break; + #endif + default: fanout_mode = PACKET_FANOUT_HASH; + break; + } - if ( defrag ) - fanout_mode |= PACKET_FANOUT_FLAG_DEFRAG; + if ( defrag ) + fanout_mode |= PACKET_FANOUT_FLAG_DEFRAG; - return fanout_mode; - } + return fanout_mode; + } void AF_PacketSource::Close() - { - if ( ! socket_fd ) - return; + { + if ( ! socket_fd ) + return; - delete rx_ring; - close(socket_fd); - socket_fd = 0; + delete rx_ring; + close(socket_fd); + socket_fd = 0; - Closed(); - } + Closed(); + } bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) - { - if ( ! socket_fd ) - return false; + { + if ( ! socket_fd ) + return false; - struct tpacket3_hdr *packet = 0; - const u_char *data; - struct timeval ts; - while ( true ) - { - if ( ! rx_ring->GetNextPacket(&packet) ) - return false; + struct tpacket3_hdr *packet = 0; + const u_char *data; + struct timeval ts; + while ( true ) + { + if ( ! rx_ring->GetNextPacket(&packet) ) + return false; - current_hdr.ts.tv_sec = packet->tp_sec; - current_hdr.ts.tv_usec = packet->tp_nsec / 1000; - current_hdr.caplen = packet->tp_snaplen; - current_hdr.len = packet->tp_len; - data = (u_char *) packet + packet->tp_mac; + current_hdr.ts.tv_sec = packet->tp_sec; + current_hdr.ts.tv_usec = packet->tp_nsec / 1000; + current_hdr.caplen = packet->tp_snaplen; + current_hdr.len = packet->tp_len; + data = (u_char *) packet + packet->tp_mac; - if ( !ApplyBPFFilter(current_filter, ¤t_hdr, data) ) - { - ++num_discarded; - DoneWithPacket(); - continue; - } + if ( !ApplyBPFFilter(current_filter, ¤t_hdr, data) ) + { + ++num_discarded; + DoneWithPacket(); + continue; + } - pkt->Init(props.link_type, ¤t_hdr.ts, current_hdr.caplen, current_hdr.len, data); + pkt->Init(props.link_type, ¤t_hdr.ts, current_hdr.caplen, current_hdr.len, data); - if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) - { - Weird("empty_af_packet_header", pkt); - return false; - } + if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) + { + Weird("empty_af_packet_header", pkt); + return false; + } - stats.received++; - stats.bytes_received += current_hdr.len; - return true; - } + stats.received++; + stats.bytes_received += current_hdr.len; + return true; + } - return false; - } + return false; + } void AF_PacketSource::DoneWithPacket() - { - rx_ring->ReleasePacket(); - } + { + rx_ring->ReleasePacket(); + } bool AF_PacketSource::PrecompileFilter(int index, const std::string& filter) - { - return PktSrc::PrecompileBPFFilter(index, filter); - } + { + return PktSrc::PrecompileBPFFilter(index, filter); + } bool AF_PacketSource::SetFilter(int index) - { - current_filter = index; - return true; - } + { + current_filter = index; + return true; + } void AF_PacketSource::Statistics(Stats* s) - { - if ( ! socket_fd ) - { - s->received = s->bytes_received = s->link = s->dropped = 0; - return; - } + { + if ( ! socket_fd ) + { + s->received = s->bytes_received = s->link = s->dropped = 0; + return; + } - struct tpacket_stats_v3 tp_stats; - socklen_t tp_stats_len = sizeof (struct tpacket_stats_v3); - int ret; + struct tpacket_stats_v3 tp_stats; + socklen_t tp_stats_len = sizeof (struct tpacket_stats_v3); + int ret; - ret = getsockopt(socket_fd, SOL_PACKET, PACKET_STATISTICS, &tp_stats, &tp_stats_len); - if ( ret < 0 ) - { - Error(errno ? strerror(errno) : "unable to retrieve statistics"); - s->received = s->bytes_received = s->link = s->dropped = 0; - return; - } + ret = getsockopt(socket_fd, SOL_PACKET, PACKET_STATISTICS, &tp_stats, &tp_stats_len); + if ( ret < 0 ) + { + Error(errno ? strerror(errno) : "unable to retrieve statistics"); + s->received = s->bytes_received = s->link = s->dropped = 0; + return; + } - stats.link += tp_stats.tp_packets; - stats.dropped += tp_stats.tp_drops; + stats.link += tp_stats.tp_packets; + stats.dropped += tp_stats.tp_drops; - memcpy(s, &stats, sizeof(Stats)); - } + memcpy(s, &stats, sizeof(Stats)); + } zeek::iosource::PktSrc* AF_PacketSource::InstantiateAF_Packet(const std::string& path, bool is_live) - { - return new AF_PacketSource(path, is_live); - } + { + return new AF_PacketSource(path, is_live); + } diff --git a/src/iosource/af_packet/src/af_packet.bif b/src/iosource/af_packet/src/af_packet.bif index da05ec930e..9660bbb25b 100644 --- a/src/iosource/af_packet/src/af_packet.bif +++ b/src/iosource/af_packet/src/af_packet.bif @@ -7,6 +7,8 @@ enum FanoutMode %{ FANOUT_HASH, # PACKET_FANOUT_HASH FANOUT_CPU, # PACKET_FANOUT_CPU FANOUT_QM, # PACKET_FANOUT_QM + FANOUT_CBPF, # PACKET_FANOUT_CBPF + FANOUT_EBPF, # PACKET_FANOUT_EBPF %} const buffer_size: count; From 45b3dbf267124dc5f55b516a5ecde38742e1f1ee Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 25 Aug 2021 17:34:58 +0200 Subject: [PATCH 303/343] af_packet: Slightly reorder README. --- src/iosource/af_packet/README | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index cccbc8fcc8..45d6276c73 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -5,17 +5,6 @@ Zeek::AF_Packet This plugin provides native AF_Packet support for Zeek (http://man7.org/linux/man-pages/man7/packet.7.html). -Upgrade to Zeek ---------------- - -In the context of the transition from Bro to Zeek, the plugin has been renamed. To upgrade from the Bro-version of the plugin, just remove the old version and then install the renamed one. Using the package manager the following will uninstall the old version of the plugin:: - - # zkg remove bro-af_packet-plugin - -For manually installed plugins, remove the corresponding plugin directory:: - - # rm -rf /lib/bro/plugins/Bro_AF_Packet/ - Installation ------------ @@ -58,6 +47,17 @@ everything built and installed correctly, you should see this:: https://github.com/JustinAzoff/can-i-use-afpacket-fanout can be used to verify whether PACKET_FANOUT works as expected. +Upgrade from Bro to Zeek +------------------------ + +In the context of the transition from Bro to Zeek, the plugin has been renamed. To upgrade from the Bro-version of the plugin, just remove the old version and then install the renamed one. Using the package manager the following will uninstall the old version of the plugin:: + + # zkg remove bro-af_packet-plugin + +For manually installed plugins, remove the corresponding plugin directory:: + + # rm -rf /lib/bro/plugins/Bro_AF_Packet/ + Usage ----- From e945e2c8bb2d7506960b860f635ee08f22b1261c Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 25 Aug 2021 17:46:19 +0200 Subject: [PATCH 304/343] af_packet: Increase version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 45d6276c73..c16244a63f 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -33,7 +33,7 @@ instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this:: # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 2.1.1) + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.0.0) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index ce482f60d5..a42ab3da5b 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -14,8 +14,8 @@ zeek::plugin::Configuration Plugin::Configure() zeek::plugin::Configuration config; config.name = "Zeek::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; - config.version.major = 2; - config.version.minor = 1; - config.version.patch = 1; + config.version.major = 3; + config.version.minor = 0; + config.version.patch = 0; return config; } From 74f9d11776c575565ed2e8c074ddbab14c723ce4 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 1 Sep 2021 19:20:21 +0200 Subject: [PATCH 305/343] af_packet: Fix Zeek version dependency. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index c16244a63f..d317bd1263 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -33,7 +33,7 @@ instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this:: # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.0.0) + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.0.1) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index a42ab3da5b..aae68f4e27 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -16,6 +16,6 @@ zeek::plugin::Configuration Plugin::Configure() config.description = "Packet acquisition via AF_Packet"; config.version.major = 3; config.version.minor = 0; - config.version.patch = 0; + config.version.patch = 1; return config; } From 96384be6898bdc6f8cf6509876907f71b1d734e3 Mon Sep 17 00:00:00 2001 From: Christian Kreibich Date: Wed, 12 Jan 2022 11:41:36 -0800 Subject: [PATCH 306/343] af_packet: Avoid Zeek script double-loading problems The plugin mechanism automatically picks up the scripts folder for plugin-related Zeek scripts. When a package's zkg.meta also declares the scripts folder the location for package-level scripts, the scripts get installed redundantly in two places. Zeek cannot recognize them as duplicates, triggering various errors relating to double-defined symbols. This moves the package-level scripts to a subdirectory with a placeholder. The placeholder avoids the zkg install-time warning, whose original fix in e3aea1 introduced this problem. --- src/iosource/af_packet/scripts/af_packet/__load__.zeek | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/iosource/af_packet/scripts/af_packet/__load__.zeek diff --git a/src/iosource/af_packet/scripts/af_packet/__load__.zeek b/src/iosource/af_packet/scripts/af_packet/__load__.zeek new file mode 100644 index 0000000000..80a869bdc3 --- /dev/null +++ b/src/iosource/af_packet/scripts/af_packet/__load__.zeek @@ -0,0 +1 @@ +# This package currently doesn't have any generic script functionality. From b38894a329bc64bfa31be6ed872a4db4ec46b5c4 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Thu, 13 Jan 2022 11:22:29 +0100 Subject: [PATCH 307/343] af_packet: Increase version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index d317bd1263..c9871be9d0 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -33,7 +33,7 @@ instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this:: # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.0.1) + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.0.2) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index aae68f4e27..6f6ab452a4 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -16,6 +16,6 @@ zeek::plugin::Configuration Plugin::Configure() config.description = "Packet acquisition via AF_Packet"; config.version.major = 3; config.version.minor = 0; - config.version.patch = 1; + config.version.patch = 2; return config; } From 1fe008945ed3a2208d96dc389d0d0893eb9d6da3 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Fri, 25 Sep 2020 18:42:47 +0200 Subject: [PATCH 308/343] af_packet: Hacked VLAN support. --- src/iosource/af_packet/src/AF_Packet.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index dae80820ac..48cb98874d 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -245,11 +245,14 @@ bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) pkt->Init(props.link_type, ¤t_hdr.ts, current_hdr.caplen, current_hdr.len, data); - if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) - { - Weird("empty_af_packet_header", pkt); - return false; - } + if ( packet->tp_status & TP_STATUS_VLAN_VALID ) + pkt->vlan = packet->hv1.tp_vlan_tci; + + if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) + { + Weird("empty_af_packet_header", pkt); + return false; + } stats.received++; stats.bytes_received += current_hdr.len; From 448e69471c34ad3a48dbe22c2771c3cfdcca2aa6 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Sun, 15 May 2022 13:10:58 +0200 Subject: [PATCH 309/343] af_packet: Convert README formatting to Markdown. --- src/iosource/af_packet/README | 121 ---------------------------------- 1 file changed, 121 deletions(-) delete mode 100644 src/iosource/af_packet/README diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README deleted file mode 100644 index c9871be9d0..0000000000 --- a/src/iosource/af_packet/README +++ /dev/null @@ -1,121 +0,0 @@ - -Zeek::AF_Packet -============== - -This plugin provides native AF_Packet support for Zeek -(http://man7.org/linux/man-pages/man7/packet.7.html). - -Installation ------------- - -Before installing the plugin, make sure the kernel headers are installed and -your kernel supports PACKET_FANOUT [1]_ and TPACKET_V3. - -Package Manager -``````````````` -The plugin is available as package for the `Zeek Package Manager -`_ and can be installed using the -following command:: - - zkg install zeek-af_packet-plugin - -Manual Install -`````````````` -The following will compile and install the AF_Packet plugin alongside Zeek, -assuming it can find the kernel headers in a standard location:: - - # ./configure && make && make install - -If the headers are installed somewhere non-standard, add -``--with-kernel=`` to the ``configure`` command. -Furthermore, ``--with-latest-kernel`` will use the latest headers available -instead of looking for the headers matching the running kernel's version. If -everything built and installed correctly, you should see this:: - - # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.0.2) - [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) - [Type] AF_Packet::FanoutMode - [Constant] AF_Packet::buffer_size - [Constant] AF_Packet::enable_hw_timestamping - [Constant] AF_Packet::enable_fanout - [Constant] AF_Packet::fanout_mode - [Constant] AF_Packet::fanout_id - -.. [1] Note that some kernel versions between 3.10 and 4.7 might exhibit a bug - that prevents the required symmetric hashing. The script available at - https://github.com/JustinAzoff/can-i-use-afpacket-fanout can be used to - verify whether PACKET_FANOUT works as expected. - -Upgrade from Bro to Zeek ------------------------- - -In the context of the transition from Bro to Zeek, the plugin has been renamed. To upgrade from the Bro-version of the plugin, just remove the old version and then install the renamed one. Using the package manager the following will uninstall the old version of the plugin:: - - # zkg remove bro-af_packet-plugin - -For manually installed plugins, remove the corresponding plugin directory:: - - # rm -rf /lib/bro/plugins/Bro_AF_Packet/ - -Usage ------ - -Once installed, you can use AF_Packet interfaces/ports by prefixing them with -``af_packet::`` on the command line. For example, to use AF_Packet to monitor -interface ``eth0``:: - - # zeek -i af_packet::eth0 - -To use AF_Packet, running Zeek without root privileges, the Zeek processes -need the CAP_NET_RAW capability. You can set it with the following command (on -each sensor, after ``zeekctl install``):: - - # setcap cap_net_raw+eip /bin/zeek - -The AF_Packet plugin automatically enables promiscuous mode on the interfaces. -As the plugin is using PACKET_ADD_MEMBERSHIP to enter the promiscuous mode -without interfering others, the PROMISC flag is not touched. To verify that the -interface entered promiscuous mode you can use ``dmesg``. - -To adapt the plugin to your needs, you can set a couple of parameters like -buffer size. See scripts/init.zeek for the default values. - -Usage with ``zeekctl`` ---------------------- - -To use the AF_Packet plugin with ``zeekctl``, the ``custom`` load balance method -can be utilized. The following shows an exemplary configuration:: - - [manager] - type=manager - host=localhost - - [proxy-1] - type=proxy - host=localhost - - [worker-1] - type=worker - host=localhost - interface=af_packet::eth0 - lb_method=custom - lb_procs=8 - pin_cpus=0,1,2,3,4,5,6,7 - # Optional parameters for per node configuration: - af_packet_fanout_id=23 - af_packet_fanout_mode=AF_Packet::FANOUT_HASH - af_packet_buffer_size=128*1024*1024 - -If all interfaces using ``lb_method=custom`` should be configured for -AF_Packet, the prefix can be globally definied by adding the following -line to ``zeekctl.conf``:: - - lb_custom.InterfacePrefix=af_packet:: - -Limitations ------------ - -* Even using AF_Packet's ``ETH_P_ALL``, the kernel removes VLAN tags. - While the tags are provided spereately, there is no efficient way to - pass them to Zeek. From 716916a97d654c44604a8f59dcf0301d0cdeec76 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Sun, 15 May 2022 13:39:08 +0200 Subject: [PATCH 310/343] af_packet: Increase version number. --- src/iosource/af_packet/src/Plugin.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 6f6ab452a4..59d7a8b1b8 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -15,7 +15,7 @@ zeek::plugin::Configuration Plugin::Configure() config.name = "Zeek::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; config.version.major = 3; - config.version.minor = 0; - config.version.patch = 2; + config.version.minor = 1; + config.version.patch = 0; return config; } From e2f40fc5b12342998669216b4fd145c51c7f4c80 Mon Sep 17 00:00:00 2001 From: Michael Dopheide Date: Tue, 17 May 2022 12:53:20 -0500 Subject: [PATCH 311/343] af_packet: Create README file which zeek's ConfigurePackaging.cmake requires --- src/iosource/af_packet/README | 90 +++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/iosource/af_packet/README diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README new file mode 100644 index 0000000000..70ad95192c --- /dev/null +++ b/src/iosource/af_packet/README @@ -0,0 +1,90 @@ + +# Zeek::AF_Packet + +This plugin provides native AF_Packet support for Zeek. For details about AF_Packet, see the corresponding [man page](http://man7.org/linux/man-pages/man7/packet.7.html). + +## Installation + +Before installing the plugin, make sure the kernel headers are installed and your kernel supports PACKET_FANOUT[^1] and TPACKET_V3. + +### Package Manager +The plugin is available as package for the [Zeek Package Manager](https://github.com/zeek/package-manager) and can be installed using the following command: + + zkg install zeek-af_packet-plugin + +### Manual Install +The following will compile and install the AF_Packet plugin alongside Zeek, assuming it can find the kernel headers in a standard location: + + # ./configure && make && make install + +If the headers are installed somewhere non-standard, add `--with-kernel=` to the `configure` command. Furthermore, `--with-latest-kernel` will use the latest headers available instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this: + + # zeek -NN Zeek::AF_Packet + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.1.0) + [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) + [Type] AF_Packet::FanoutMode + [Constant] AF_Packet::buffer_size + [Constant] AF_Packet::enable_hw_timestamping + [Constant] AF_Packet::enable_fanout + [Constant] AF_Packet::enable_defrag + [Constant] AF_Packet::fanout_mode + [Constant] AF_Packet::fanout_id + +## Upgrade from Bro to Zeek + +In the context of the transition from Bro to Zeek, the plugin has been renamed. To upgrade from the Bro-version of the plugin, just remove the old version and then install the renamed one. Using the package manager the following will uninstall the old version of the plugin: + + # zkg remove bro-af_packet-plugin + +For manually installed plugins, remove the corresponding plugin directory: + + # rm -rf /lib/bro/plugins/Bro_AF_Packet/ + +## Usage + +Once installed, you can use AF_Packet interfaces/ports by prefixing them with `af_packet::` on the command line. For example, to use AF_Packet to monitor interface `eth0`: + + # zeek -i af_packet::eth0 + +To use AF_Packet, running Zeek without root privileges, the Zeek processes need the CAP_NET_RAW capability. You can set it with the following command (on each sensor, after `zeekctl install`): + + # setcap cap_net_raw+eip /bin/zeek + +The AF_Packet plugin automatically enables promiscuous mode on the interfaces. As the plugin is using PACKET_ADD_MEMBERSHIP to enter the promiscuous mode without interfering others, the PROMISC flag is not touched. To verify that the interface entered promiscuous mode you can use `dmesg`. + +To adapt the plugin to your needs, you can set a couple of parameters like buffer size. See [init.zeek](scripts/init.zeek) for the default values. + +## Usage with `zeekctl` + +To use the AF_Packet plugin with `zeekctl`, the `custom` load balance method can be utilized. The following shows an exemplary configuration: + + [manager] + type=manager + host=localhost + + [proxy-1] + type=proxy + host=localhost + + [worker-1] + type=worker + host=localhost + interface=af_packet::eth0 + lb_method=custom + lb_procs=8 + pin_cpus=0,1,2,3,4,5,6,7 + # Optional parameters for per node configuration: + af_packet_fanout_id=23 + af_packet_fanout_mode=AF_Packet::FANOUT_HASH + af_packet_buffer_size=128*1024*1024 + +If all interfaces using `lb_method=custom` should be configured for AF_Packet, the prefix can be globally definied by adding the following line to `zeekctl.conf`: + + lb_custom.InterfacePrefix=af_packet:: + +## Limitations + +* __VLAN tagging is now supported.__ Even using AF_Packet's ``ETH_P_ALL``, the kernel removes VLAN tags from packets. + ~~While the tags are provided spereately, there is no efficient way to pass them to Zeek.~~ Applying knowledge about the internal data structures used by Zeek, the plugin now forwards VLAN tag control information to Zeek. Both IEEE 802.1Q and IEEE 802.1ad (QinQ) will be handled as expected. + +[^1]: Note that some kernel versions between 3.10 and 4.7 might exhibit a bug that prevents the required symmetric hashing. The script available at https://github.com/JustinAzoff/can-i-use-afpacket-fanout can be used to verify whether PACKET_FANOUT works as expected. From 7be67782c2aeaafc90685a69382276d526a4bd22 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 18 May 2022 13:10:39 +0200 Subject: [PATCH 312/343] af_packet: Increase version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 70ad95192c..9ef1cc9328 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -20,7 +20,7 @@ The following will compile and install the AF_Packet plugin alongside Zeek, assu If the headers are installed somewhere non-standard, add `--with-kernel=` to the `configure` command. Furthermore, `--with-latest-kernel` will use the latest headers available instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this: # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.1.0) + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.1.1) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 59d7a8b1b8..f318d4af44 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -16,6 +16,6 @@ zeek::plugin::Configuration Plugin::Configure() config.description = "Packet acquisition via AF_Packet"; config.version.major = 3; config.version.minor = 1; - config.version.patch = 0; + config.version.patch = 1; return config; } From 630d1edff9e0e83b618c6ad3230950f9da64e649 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Fri, 15 Jul 2022 00:51:35 +0200 Subject: [PATCH 313/343] af_packet: Make link type configurable. --- src/iosource/af_packet/README | 1 + src/iosource/af_packet/scripts/init.zeek | 2 ++ src/iosource/af_packet/src/AF_Packet.cc | 19 ++++++++++--------- src/iosource/af_packet/src/af_packet.bif | 1 + 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 9ef1cc9328..7a9a0932a7 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -29,6 +29,7 @@ If the headers are installed somewhere non-standard, add `--with-kernel= Date: Mon, 18 Jul 2022 04:51:47 +0200 Subject: [PATCH 314/343] af_packet: Increase version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 7a9a0932a7..31350ec41d 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -20,7 +20,7 @@ The following will compile and install the AF_Packet plugin alongside Zeek, assu If the headers are installed somewhere non-standard, add `--with-kernel=` to the `configure` command. Furthermore, `--with-latest-kernel` will use the latest headers available instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this: # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.1.1) + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.2.0) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Constant] AF_Packet::buffer_size diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index f318d4af44..c512c0e367 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -15,7 +15,7 @@ zeek::plugin::Configuration Plugin::Configure() config.name = "Zeek::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; config.version.major = 3; - config.version.minor = 1; - config.version.patch = 1; + config.version.minor = 2; + config.version.patch = 0; return config; } From 1dc671862177ab2969f811ca0e1cb8b3050c775d Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 7 Sep 2022 10:52:38 +0200 Subject: [PATCH 315/343] af_packet: Remove FindKernelHeaders, not needed There's been some wondering why kernel headers are required to compile this plugin as it's not providing a kernel module or otherwise provides functionality related to kernel APIs. AF_PACKET sockets are provided through user-space APIs. There may have been historical reasons, but let's move forward and remove the dependency. Fixes #29 #24 --- src/iosource/af_packet/CMakeLists.txt | 23 +++++++---------------- src/iosource/af_packet/README | 8 +++++--- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt index 6a01b8d691..66bf28de1d 100644 --- a/src/iosource/af_packet/CMakeLists.txt +++ b/src/iosource/af_packet/CMakeLists.txt @@ -5,22 +5,13 @@ project(ZeekPluginAF_Packet) include(ZeekPlugin) -find_package(KernelHeaders) - -if ( KERNELHEADERS_FOUND ) - #TODO: Make sure the specified kernel headers are used - zeek_plugin_begin(Zeek AF_Packet) - zeek_plugin_cc(src/Plugin.cc) - zeek_plugin_cc(src/AF_Packet.cc) - zeek_plugin_cc(src/RX_Ring.cc) - zeek_plugin_bif(src/af_packet.bif) - zeek_plugin_dist_files(zeekctl/af_packet.py README COPYING VERSION) - zeek_plugin_end() - - message(STATUS "Kernelheader prefix : ${KERNELHEADERS_ROOT_DIR}") -else () - message(FATAL_ERROR "Kernel headers not found.") -endif() +zeek_plugin_begin(Zeek AF_Packet) +zeek_plugin_cc(src/Plugin.cc) +zeek_plugin_cc(src/AF_Packet.cc) +zeek_plugin_cc(src/RX_Ring.cc) +zeek_plugin_bif(src/af_packet.bif) +zeek_plugin_dist_files(zeekctl/af_packet.py README COPYING VERSION) +zeek_plugin_end() file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 31350ec41d..506f5485c7 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -5,19 +5,21 @@ This plugin provides native AF_Packet support for Zeek. For details about AF_Pac ## Installation -Before installing the plugin, make sure the kernel headers are installed and your kernel supports PACKET_FANOUT[^1] and TPACKET_V3. +Before installing the plugin, make sure your kernel supports PACKET_FANOUT[^1] and TPACKET_V3. ### Package Manager + The plugin is available as package for the [Zeek Package Manager](https://github.com/zeek/package-manager) and can be installed using the following command: zkg install zeek-af_packet-plugin ### Manual Install -The following will compile and install the AF_Packet plugin alongside Zeek, assuming it can find the kernel headers in a standard location: + +The following will compile and install the AF_Packet plugin alongside Zeek:: # ./configure && make && make install -If the headers are installed somewhere non-standard, add `--with-kernel=` to the `configure` command. Furthermore, `--with-latest-kernel` will use the latest headers available instead of looking for the headers matching the running kernel's version. If everything built and installed correctly, you should see this: +If everything built and installed correctly, you should see this:: # zeek -NN Zeek::AF_Packet Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.2.0) From 62b28177ee3d5053af39e68595383af73e50ea6b Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 7 Sep 2022 11:22:06 +0200 Subject: [PATCH 316/343] af_packet: Remove linux/version.h include Not sure why this is needed. On my system it defines LINUX_VERSION_CODE and KERNEL_VERSION and neither is used within the plugin. --- src/iosource/af_packet/src/AF_Packet.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index feba868c2d..372ac390fc 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -10,7 +10,6 @@ extern "C" { #include // errorno #include // close() -#include // kernel version #include // ETH_P_ALL #include // ifreq From 41331e56052ff1fb2ade0f4407623cc895e7e2dc Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Fri, 16 Sep 2022 14:37:58 +0200 Subject: [PATCH 317/343] af_packet: Fix enable_defrag Seems enable_defrag was never actually passed down to the relevant functions. Remove the default parameters to ensure we properly pass it down. --- src/iosource/af_packet/src/AF_Packet.cc | 12 ++++++------ src/iosource/af_packet/src/AF_Packet.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 0fe909abcb..5c02b17c72 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -62,12 +62,12 @@ void AF_PacketSource::Open() return; } - if ( ! ConfigureFanoutGroup(enable_fanout) ) - { - Error(errno ? strerror(errno) : "failed to join fanout group"); - close(socket_fd); - return; - } + if ( ! ConfigureFanoutGroup(enable_fanout, enable_defrag) ) + { + Error(errno ? strerror(errno) : "failed to join fanout group"); + close(socket_fd); + return; + } if ( ! ConfigureHWTimestamping(enable_hw_timestamping) ) { diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index 372ac390fc..cd7123f3ee 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -67,9 +67,9 @@ private: bool BindInterface(); bool EnablePromiscMode(); - bool ConfigureFanoutGroup(bool enabled, bool defrag=false); + bool ConfigureFanoutGroup(bool enabled, bool defrag); bool ConfigureHWTimestamping(bool enabled); - uint32_t GetFanoutMode(bool defrag=false); + uint32_t GetFanoutMode(bool defrag); }; } From 6ad8e3ed2440a50c5db47f332ab640164f0f3ae0 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Fri, 16 Sep 2022 14:43:36 +0200 Subject: [PATCH 318/343] af_packet: Add -Wunused and -Werror This would've found the enable_defrag issue and also points out another unused variable. --- src/iosource/af_packet/CMakeLists.txt | 2 ++ src/iosource/af_packet/src/AF_Packet.cc | 13 ++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt index 66bf28de1d..50b37967ae 100644 --- a/src/iosource/af_packet/CMakeLists.txt +++ b/src/iosource/af_packet/CMakeLists.txt @@ -5,6 +5,8 @@ project(ZeekPluginAF_Packet) include(ZeekPlugin) +add_compile_options(-Wunused -Werror) + zeek_plugin_begin(Zeek AF_Packet) zeek_plugin_cc(src/Plugin.cc) zeek_plugin_cc(src/AF_Packet.cc) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 5c02b17c72..5e54130a31 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -223,13 +223,12 @@ bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) if ( ! socket_fd ) return false; - struct tpacket3_hdr *packet = 0; - const u_char *data; - struct timeval ts; - while ( true ) - { - if ( ! rx_ring->GetNextPacket(&packet) ) - return false; + struct tpacket3_hdr *packet = 0; + const u_char *data; + while ( true ) + { + if ( ! rx_ring->GetNextPacket(&packet) ) + return false; current_hdr.ts.tv_sec = packet->tp_sec; current_hdr.ts.tv_usec = packet->tp_nsec / 1000; From ffbb2823daf8eb4c6c56636157796cec1eb93a25 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Mon, 19 Sep 2022 14:34:04 +0200 Subject: [PATCH 319/343] af_packet: Remove compile_options() again This seems to trickle through to base Zeek code when done like that. https://cirrus-ci.com/task/4788073346105344?logs=build#L2298 --- src/iosource/af_packet/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt index 50b37967ae..66bf28de1d 100644 --- a/src/iosource/af_packet/CMakeLists.txt +++ b/src/iosource/af_packet/CMakeLists.txt @@ -5,8 +5,6 @@ project(ZeekPluginAF_Packet) include(ZeekPlugin) -add_compile_options(-Wunused -Werror) - zeek_plugin_begin(Zeek AF_Packet) zeek_plugin_cc(src/Plugin.cc) zeek_plugin_cc(src/AF_Packet.cc) From cd297e13ddd01d25e0d2f5cf760566261eb66250 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Mon, 9 Mar 2020 12:27:31 -0400 Subject: [PATCH 320/343] af_packet: Support checksum offloading (requires Zeek 5.1). --- src/iosource/af_packet/scripts/init.zeek | 13 +++++++ src/iosource/af_packet/src/AF_Packet.cc | 44 +++++++++++++++++++++--- src/iosource/af_packet/src/AF_Packet.h | 1 + src/iosource/af_packet/src/af_packet.bif | 7 ++++ 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/iosource/af_packet/scripts/init.zeek b/src/iosource/af_packet/scripts/init.zeek index dc5cfabf2a..9de7322bb4 100644 --- a/src/iosource/af_packet/scripts/init.zeek +++ b/src/iosource/af_packet/scripts/init.zeek @@ -5,6 +5,17 @@ module AF_Packet; export { + # The various modes of checksum offloading. OFF means we will set the + # checksum variables to true, trusting that they are correct no matter + # what the kernel or zeek thinks. ON means we will ignore the kernel + # checksums and let Zeek check them. KERNEL means we will trust the + # kernel checksums and let Zeek skip checking them. + type Checksum_Mode : enum { + OFF, + ON, + KERNEL + }; + ## Size of the ring-buffer. const buffer_size = 128 * 1024 * 1024 &redef; ## Toggle whether to use hardware timestamps. @@ -19,4 +30,6 @@ export { const fanout_id = 23 &redef; ## Link type (default Ethernet). const link_type = 1 &redef; + ## Checksum offloading option. + const checksum_offloading_mode: Checksum_Mode = KERNEL &redef; } diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 5e54130a31..5f987efa6b 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -17,15 +17,18 @@ AF_PacketSource::AF_PacketSource(const std::string& path, bool is_live) if ( ! is_live ) Error("AF_Packet source does not support offline input"); - current_filter = -1; - props.path = path; - props.is_live = is_live; - } + current_filter = -1; + props.path = path; + props.is_live = is_live; + + checksum_mode = zeek::BifConst::AF_Packet::checksum_offloading_mode->AsEnum(); + } void AF_PacketSource::Open() { uint64_t buffer_size = zeek::BifConst::AF_Packet::buffer_size; int link_type = zeek::BifConst::AF_Packet::link_type; + bool enable_hw_timestamping = zeek::BifConst::AF_Packet::enable_hw_timestamping; bool enable_fanout = zeek::BifConst::AF_Packet::enable_fanout; bool enable_defrag = zeek::BifConst::AF_Packet::enable_defrag; @@ -248,6 +251,39 @@ bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) if ( packet->tp_status & TP_STATUS_VLAN_VALID ) pkt->vlan = packet->hv1.tp_vlan_tci; +#if ZEEK_VERSION_NUMBER >= 50100 + switch ( checksum_mode ) + { + case BifEnum::AF_Packet::CHECKSUM_OFF: + { + // If set to off, just accept whatever checksum in the packet is correct and + // skip checking it here and in Zeek. + pkt->l4_checksummed = true; + break; + } + case BifEnum::AF_Packet::CHECKSUM_KERNEL: + { + // If set to kernel, check whether the kernel thinks the checksum is valid. If it + // does, tell Zeek to skip checking by itself. + if ( ( (packet->tp_status & TP_STATUS_CSUM_VALID) != 0 ) || + ( (packet->tp_status & TP_STATUS_CSUMNOTREADY) != 0 ) ) + pkt->l4_checksummed = true; + else + pkt->l4_checksummed = false; + break; + } + case BifEnum::AF_Packet::CHECKSUM_ON: + default: + { + // Let Zeek handle it. + pkt->l4_checksummed = false; + break; + } + } +#else + fprintf(stderr, "bad version?\n"); +#endif + if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) { Weird("empty_af_packet_header", pkt); diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index cd7123f3ee..104a70ed97 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -60,6 +60,7 @@ private: int current_filter; unsigned int num_discarded; + int checksum_mode; int socket_fd; RX_Ring *rx_ring; diff --git a/src/iosource/af_packet/src/af_packet.bif b/src/iosource/af_packet/src/af_packet.bif index a8e687b313..9a309b5986 100644 --- a/src/iosource/af_packet/src/af_packet.bif +++ b/src/iosource/af_packet/src/af_packet.bif @@ -11,6 +11,12 @@ enum FanoutMode %{ FANOUT_EBPF, # PACKET_FANOUT_EBPF %} +enum ChecksumMode %{ + CHECKSUM_OFF, + CHECKSUM_ON, + CHECKSUM_KERNEL, +%} + const buffer_size: count; const enable_hw_timestamping: bool; const enable_fanout: bool; @@ -18,3 +24,4 @@ const enable_defrag: bool; const fanout_mode: FanoutMode; const fanout_id: count; const link_type: count; +const checksum_offloading_mode: ChecksumMode; \ No newline at end of file From 8d2979e93535ae62f8f1660c48f3dd54cd128517 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Mon, 26 Sep 2022 12:17:47 +0200 Subject: [PATCH 321/343] af_packet: Cleanup checksum offloading support. --- src/iosource/af_packet/README | 4 +++- src/iosource/af_packet/scripts/init.zeek | 17 +++-------------- src/iosource/af_packet/src/AF_Packet.cc | 4 +--- src/iosource/af_packet/src/af_packet.bif | 10 ++++++++-- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 506f5485c7..2de9cc9d35 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -25,13 +25,15 @@ If everything built and installed correctly, you should see this:: Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.2.0) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode + [Type] AF_Packet::ChecksumMode [Constant] AF_Packet::buffer_size [Constant] AF_Packet::enable_hw_timestamping - [Constant] AF_Packet::enable_fanout [Constant] AF_Packet::enable_defrag + [Constant] AF_Packet::enable_fanout [Constant] AF_Packet::fanout_mode [Constant] AF_Packet::fanout_id [Constant] AF_Packet::link_type + [Constant] AF_Packet::checksum_validation_mode ## Upgrade from Bro to Zeek diff --git a/src/iosource/af_packet/scripts/init.zeek b/src/iosource/af_packet/scripts/init.zeek index 9de7322bb4..41f8d0a206 100644 --- a/src/iosource/af_packet/scripts/init.zeek +++ b/src/iosource/af_packet/scripts/init.zeek @@ -5,17 +5,6 @@ module AF_Packet; export { - # The various modes of checksum offloading. OFF means we will set the - # checksum variables to true, trusting that they are correct no matter - # what the kernel or zeek thinks. ON means we will ignore the kernel - # checksums and let Zeek check them. KERNEL means we will trust the - # kernel checksums and let Zeek skip checking them. - type Checksum_Mode : enum { - OFF, - ON, - KERNEL - }; - ## Size of the ring-buffer. const buffer_size = 128 * 1024 * 1024 &redef; ## Toggle whether to use hardware timestamps. @@ -24,12 +13,12 @@ export { const enable_fanout = T &redef; ## Toggle defragmentation of IP packets using PACKET_FANOUT_FLAG_DEFRAG. const enable_defrag = F &redef; - ## Fanout Mode. + ## Fanout mode. const fanout_mode = FANOUT_HASH &redef; ## Fanout ID. const fanout_id = 23 &redef; ## Link type (default Ethernet). const link_type = 1 &redef; - ## Checksum offloading option. - const checksum_offloading_mode: Checksum_Mode = KERNEL &redef; + ## Checksum validation mode. + const checksum_validation_mode: ChecksumMode = CHECKSUM_ON &redef; } diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 5f987efa6b..cfce30af95 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -21,7 +21,7 @@ AF_PacketSource::AF_PacketSource(const std::string& path, bool is_live) props.path = path; props.is_live = is_live; - checksum_mode = zeek::BifConst::AF_Packet::checksum_offloading_mode->AsEnum(); + checksum_mode = zeek::BifConst::AF_Packet::checksum_validation_mode->AsEnum(); } void AF_PacketSource::Open() @@ -280,8 +280,6 @@ bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) break; } } -#else - fprintf(stderr, "bad version?\n"); #endif if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) diff --git a/src/iosource/af_packet/src/af_packet.bif b/src/iosource/af_packet/src/af_packet.bif index 9a309b5986..32e737b16b 100644 --- a/src/iosource/af_packet/src/af_packet.bif +++ b/src/iosource/af_packet/src/af_packet.bif @@ -3,6 +3,7 @@ module AF_Packet; +## Available fanout modes. enum FanoutMode %{ FANOUT_HASH, # PACKET_FANOUT_HASH FANOUT_CPU, # PACKET_FANOUT_CPU @@ -11,17 +12,22 @@ enum FanoutMode %{ FANOUT_EBPF, # PACKET_FANOUT_EBPF %} +## Available checksum validation modes. enum ChecksumMode %{ + ## Ignore checksums, i.e. always assume they are correct. CHECKSUM_OFF, + ## Let Zeek compute and verify checksums. CHECKSUM_ON, + ## Let the kernel handle checksum offloading. + ## Note: Semantics may depend on the kernel and driver version. CHECKSUM_KERNEL, %} const buffer_size: count; const enable_hw_timestamping: bool; -const enable_fanout: bool; const enable_defrag: bool; +const enable_fanout: bool; const fanout_mode: FanoutMode; const fanout_id: count; const link_type: count; -const checksum_offloading_mode: ChecksumMode; \ No newline at end of file +const checksum_validation_mode: ChecksumMode; From 90d61cae72ae4aa901ee59ae30e70599c8454d7e Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Fri, 16 Sep 2022 14:23:33 +0200 Subject: [PATCH 322/343] af_packet: Make block_size and block_timeout configurable This lowers the default timeout from 100msec to 10msec and increases the default block_size from 16KB to 32KB. Both are aligned with what Suricata uses as defaults. The block_size is likely too conservative for high-performance, tuning guides recommend starting with 1MB block size. Fixes #37. --- src/iosource/af_packet/README | 2 ++ src/iosource/af_packet/scripts/init.zeek | 5 +++++ src/iosource/af_packet/src/AF_Packet.cc | 18 ++++++++++-------- src/iosource/af_packet/src/RX_Ring.cc | 10 +++++----- src/iosource/af_packet/src/RX_Ring.h | 4 ++-- src/iosource/af_packet/src/af_packet.bif | 2 ++ 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 2de9cc9d35..ed17d4be53 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -27,6 +27,8 @@ If everything built and installed correctly, you should see this:: [Type] AF_Packet::FanoutMode [Type] AF_Packet::ChecksumMode [Constant] AF_Packet::buffer_size + [Constant] AF_Packet::block_size + [Constant] AF_Packet::block_timeout [Constant] AF_Packet::enable_hw_timestamping [Constant] AF_Packet::enable_defrag [Constant] AF_Packet::enable_fanout diff --git a/src/iosource/af_packet/scripts/init.zeek b/src/iosource/af_packet/scripts/init.zeek index 41f8d0a206..234ba19821 100644 --- a/src/iosource/af_packet/scripts/init.zeek +++ b/src/iosource/af_packet/scripts/init.zeek @@ -7,6 +7,11 @@ module AF_Packet; export { ## Size of the ring-buffer. const buffer_size = 128 * 1024 * 1024 &redef; + ## Size of an individual block. Needs to be a multiple of page size. + ## Defaults to 32KB. + const block_size = 4096 * 8 &redef; + ## Retire timeout for a single block. Default is 10msec. + const block_timeout = 10msec &redef; ## Toggle whether to use hardware timestamps. const enable_hw_timestamping = F &redef; ## Toggle whether to use PACKET_FANOUT. diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index cfce30af95..ed39feab54 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -27,6 +27,8 @@ AF_PacketSource::AF_PacketSource(const std::string& path, bool is_live) void AF_PacketSource::Open() { uint64_t buffer_size = zeek::BifConst::AF_Packet::buffer_size; + uint64_t block_size = zeek::BifConst::AF_Packet::block_size; + int block_timeout_msec = static_cast(zeek::BifConst::AF_Packet::block_timeout * 1000.0); int link_type = zeek::BifConst::AF_Packet::link_type; bool enable_hw_timestamping = zeek::BifConst::AF_Packet::enable_hw_timestamping; @@ -41,14 +43,14 @@ void AF_PacketSource::Open() return; } - // Create RX-ring - try { - rx_ring = new RX_Ring(socket_fd, buffer_size); - } catch (RX_RingException& e) { - Error(errno ? strerror(errno) : "unable to create RX-ring"); - close(socket_fd); - return; - } + // Create RX-ring + try { + rx_ring = new RX_Ring(socket_fd, buffer_size, block_size, block_timeout_msec); + } catch (RX_RingException& e) { + Error(errno ? strerror(errno) : "unable to create RX-ring"); + close(socket_fd); + return; + } // Setup interface if ( ! BindInterface() ) diff --git a/src/iosource/af_packet/src/RX_Ring.cc b/src/iosource/af_packet/src/RX_Ring.cc index e7af904856..f364d2d827 100644 --- a/src/iosource/af_packet/src/RX_Ring.cc +++ b/src/iosource/af_packet/src/RX_Ring.cc @@ -11,7 +11,7 @@ extern "C" { #include // sysconf } -RX_Ring::RX_Ring(int sock, size_t bufsize) +RX_Ring::RX_Ring(int sock, size_t bufsize, size_t blocksize, int blocktimeout_msec) { int ret, ver = TPACKET_VERSION; @@ -23,7 +23,7 @@ RX_Ring::RX_Ring(int sock, size_t bufsize) if ( ret ) throw RX_RingException("unable to set TPacket version"); - InitLayout(bufsize); + InitLayout(bufsize, blocksize, blocktimeout_msec); ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, (uint8_t *) &layout, sizeof(layout)); if ( ret ) @@ -92,14 +92,14 @@ void RX_Ring::ReleasePacket() NextBlock(); } -void RX_Ring::InitLayout(size_t bufsize) +void RX_Ring::InitLayout(size_t bufsize, size_t blocksize, int blocktimeout_msec) { memset(&layout, 0, sizeof(layout)); - layout.tp_block_size = sysconf(_SC_PAGE_SIZE) << 2; //TODO: get rid of magic value + layout.tp_block_size = blocksize; layout.tp_frame_size = TPACKET_ALIGNMENT << 7; // Seems to be irrelevant for V3 layout.tp_block_nr = bufsize / layout.tp_block_size; layout.tp_frame_nr = (layout.tp_block_size / layout.tp_frame_size) * layout.tp_block_nr; - layout.tp_retire_blk_tov = 100; // Timeout for blocks + layout.tp_retire_blk_tov = blocktimeout_msec; } void RX_Ring::NextBlock() diff --git a/src/iosource/af_packet/src/RX_Ring.h b/src/iosource/af_packet/src/RX_Ring.h index 370c7f333e..91cb3f1d14 100644 --- a/src/iosource/af_packet/src/RX_Ring.h +++ b/src/iosource/af_packet/src/RX_Ring.h @@ -21,14 +21,14 @@ public: /** * Constructor */ - RX_Ring(int sock, size_t bufsize); + RX_Ring(int sock, size_t bufsize, size_t blocksize, int blocktimeout_msec); ~RX_Ring(); bool GetNextPacket(tpacket3_hdr** hdr); void ReleasePacket(); protected: - void InitLayout(size_t bufsize); + void InitLayout(size_t bufsize, size_t blocksize, int blocktimeout_msec); void NextBlock(); private: diff --git a/src/iosource/af_packet/src/af_packet.bif b/src/iosource/af_packet/src/af_packet.bif index 32e737b16b..d3f81febce 100644 --- a/src/iosource/af_packet/src/af_packet.bif +++ b/src/iosource/af_packet/src/af_packet.bif @@ -24,6 +24,8 @@ enum ChecksumMode %{ %} const buffer_size: count; +const block_size: count; +const block_timeout: interval; const enable_hw_timestamping: bool; const enable_defrag: bool; const enable_fanout: bool; From 7d0841ae319f56214501596e775b8c5181b1382c Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Mon, 26 Sep 2022 19:41:36 +0200 Subject: [PATCH 323/343] af_packet: Improve the README. --- src/iosource/af_packet/README | 55 ++++++++++++++++++------ src/iosource/af_packet/scripts/init.zeek | 3 +- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index ed17d4be53..2f1736b193 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -37,29 +37,32 @@ If everything built and installed correctly, you should see this:: [Constant] AF_Packet::link_type [Constant] AF_Packet::checksum_validation_mode -## Upgrade from Bro to Zeek - -In the context of the transition from Bro to Zeek, the plugin has been renamed. To upgrade from the Bro-version of the plugin, just remove the old version and then install the renamed one. Using the package manager the following will uninstall the old version of the plugin: - - # zkg remove bro-af_packet-plugin - -For manually installed plugins, remove the corresponding plugin directory: - - # rm -rf /lib/bro/plugins/Bro_AF_Packet/ - ## Usage Once installed, you can use AF_Packet interfaces/ports by prefixing them with `af_packet::` on the command line. For example, to use AF_Packet to monitor interface `eth0`: # zeek -i af_packet::eth0 +### Permissions + To use AF_Packet, running Zeek without root privileges, the Zeek processes need the CAP_NET_RAW capability. You can set it with the following command (on each sensor, after `zeekctl install`): # setcap cap_net_raw+eip /bin/zeek The AF_Packet plugin automatically enables promiscuous mode on the interfaces. As the plugin is using PACKET_ADD_MEMBERSHIP to enter the promiscuous mode without interfering others, the PROMISC flag is not touched. To verify that the interface entered promiscuous mode you can use `dmesg`. -To adapt the plugin to your needs, you can set a couple of parameters like buffer size. See [init.zeek](scripts/init.zeek) for the default values. +### Offloading + +Remember to disable any offloading features provided by the Network Interface Card (NIC) or Linux networking stack that interfere with Zeek. In general, Zeek expects to see network packets as they arrive on the wire. See this [blog post](https://blog.securityonion.net/2011/10/when-is-full-packet-capture-not-full.html) for more background. Toggling offloading features can be done with the `ethtool -K` command, for example: + + # IFACE=eth0 + # for offload in rx tx sg tso ufo gso gro lro; do + # ethtool -K $IFACE $offload off + # done + +For more details around the involved offloads consult the [ethtool manpage](https://man7.org/linux/man-pages/man8/ethtool.8.html). In addition, `ethtool -S` can be used to gather statistics at the interface level. + +While all offloading should usually be disabled, the plugin supports to outsource certain tasks like checksum validation. See the [configuration section](#advanced-configuration) for further information. ## Usage with `zeekctl` @@ -68,11 +71,11 @@ To use the AF_Packet plugin with `zeekctl`, the `custom` load balance method can [manager] type=manager host=localhost - + [proxy-1] type=proxy host=localhost - + [worker-1] type=worker host=localhost @@ -89,9 +92,33 @@ If all interfaces using `lb_method=custom` should be configured for AF_Packet, t lb_custom.InterfacePrefix=af_packet:: +## Advanced Configuration + +While the plugin aims at providing a "plug and play" user experience, it exposes several configuration options of the underlying API for customization (see [init.zeek](scripts/init.zeek) for the default values): + +* `buffer_size`: Set the overall buffer size allocated per socket. As the buffer is divided into blocks, this should be a multiple of the block size. +* `block_size`: Set the size of a block in the buffer. Instead of ingesting packet by packet into the application, packets are aggregated in blocks to improve performance. The block size **must** be a multiple of the system's page size (see `getconf PAGE_SIZE`). +* `block_timeout`: Set the timeout in milliseconds for passing a block to the application. This can be useful to reduce latency on less busy links. +* `enable_hw_timestamping`: Enable support for hardware timestamping. Please note that this is an experimental feature. +* `enable_defrag`: Enable defragmentation of IP packets before packets are load-balanced. This can be useful to prevent different fragments from being sent to different workers. +* `enable_fanout`: Enable packet fanout for load-balancing across multiple workers. The load-balancing strategy is determined by the fanout mode. +* `fanout_mode`: Set the load-balancing strategy. See [af_packet.bif](src/af_packet.bif) for the supported fanout modes. +* `fanout_id`: Set the fanout ID that identifies a load-balancing group. When monitoring multiple interfaces, a separate ID has to be configured for each interface. +* `link_type`: Set the link layer protocol. +* `checksum_validation_mode`: Set how checksums are calculated and verified. See [af_packet.bif](src/af_packet.bif) for the supported validation modes. + +> **Note**: +> Setting `checksum_validation_mode` will not have any effect when used with Zeek prior version 5.1. + +For further details on the above configuration options see the [kernel documentation](https://docs.kernel.org/networking/packet_mmap.html). Actual performance tuning is rather an art. For in-depth guidance, see the following resources, which can be transferred to Zeek: +* [Suricata Extreme Performance Tuning guide](https://github.com/pevma/SEPTun) +* [Suricata Extreme Performance Tuning guide - Mark II](https://github.com/pevma/SEPTun-Mark-II) + ## Limitations * __VLAN tagging is now supported.__ Even using AF_Packet's ``ETH_P_ALL``, the kernel removes VLAN tags from packets. ~~While the tags are provided spereately, there is no efficient way to pass them to Zeek.~~ Applying knowledge about the internal data structures used by Zeek, the plugin now forwards VLAN tag control information to Zeek. Both IEEE 802.1Q and IEEE 802.1ad (QinQ) will be handled as expected. +* Zeek workers crashing or restarting can, for a short period of time, disturb load balancing due to their packet + sockets being removed and later rejoining the fanout group. This may be visible in Zeek logs as gaps and/or duplicated connection entries produced by different Zeek workers. -[^1]: Note that some kernel versions between 3.10 and 4.7 might exhibit a bug that prevents the required symmetric hashing. The script available at https://github.com/JustinAzoff/can-i-use-afpacket-fanout can be used to verify whether PACKET_FANOUT works as expected. +[^1]: Note that some kernel versions between 3.10 and 4.7 might exhibit a bug that prevents the required symmetric hashing. The script available at https://github.com/JustinAzoff/can-i-use-afpacket-fanout can be used to verify whether PACKET_FANOUT works as expected. This issue should have been fixed in all stable kernels by now. diff --git a/src/iosource/af_packet/scripts/init.zeek b/src/iosource/af_packet/scripts/init.zeek index 234ba19821..c8d4f8a560 100644 --- a/src/iosource/af_packet/scripts/init.zeek +++ b/src/iosource/af_packet/scripts/init.zeek @@ -8,9 +8,8 @@ export { ## Size of the ring-buffer. const buffer_size = 128 * 1024 * 1024 &redef; ## Size of an individual block. Needs to be a multiple of page size. - ## Defaults to 32KB. const block_size = 4096 * 8 &redef; - ## Retire timeout for a single block. Default is 10msec. + ## Retire timeout for a single block. const block_timeout = 10msec &redef; ## Toggle whether to use hardware timestamps. const enable_hw_timestamping = F &redef; From e0d7dba1130603822381d475181397a6826367f4 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Thu, 13 Oct 2022 11:32:51 +0200 Subject: [PATCH 324/343] af_packet: Define TP_STATUS_CSUM_VALID when not defined On some older Linux distributions (CentOS 7), the if_packet.h header does not yet include TP_STATUS_CSUM_VALID (introduced in March 2015). Simply define it if it's not there. --- src/iosource/af_packet/src/AF_Packet.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index ed39feab54..387c1da646 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -5,7 +5,13 @@ #include "af_packet.bif.h" -using namespace af_packet::iosource::pktsrc; +// CentOS 7 if_packet.h does not yet have this define, provide it +// explicitly if missing. +#ifndef TP_STATUS_CSUM_VALID +#define TP_STATUS_CSUM_VALID (1 << 7) +#endif + +using namespace zeek::iosource::pktsrc; AF_PacketSource::~AF_PacketSource() { From 61a3538106010a7ac5e1ce7f0734ae20773da653 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Thu, 13 Oct 2022 13:07:21 +0200 Subject: [PATCH 325/343] af_packet: Add info if TP_STATUS_CSUM_VALID is not defined. --- src/iosource/af_packet/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt index 66bf28de1d..d8a47ab4dc 100644 --- a/src/iosource/af_packet/CMakeLists.txt +++ b/src/iosource/af_packet/CMakeLists.txt @@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(ZeekPluginAF_Packet) include(ZeekPlugin) +include(CheckSymbolExists) zeek_plugin_begin(Zeek AF_Packet) zeek_plugin_cc(src/Plugin.cc) @@ -13,6 +14,11 @@ zeek_plugin_bif(src/af_packet.bif) zeek_plugin_dist_files(zeekctl/af_packet.py README COPYING VERSION) zeek_plugin_end() +check_symbol_exists(TP_STATUS_CSUM_VALID linux/if_packet.h HAVE_TP_STATUS_CSUM_VALID) +if (NOT HAVE_TP_STATUS_CSUM_VALID) + message(STATUS "Checksum offloading to the kernel might not be fully supported.") +endif () + file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1) if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") From 165d60236c875501815f05018b852207b06d08e8 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Wed, 26 Oct 2022 21:19:54 +0200 Subject: [PATCH 326/343] af_packet: Increase version number. --- src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/Plugin.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 2f1736b193..2c601f508b 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -22,7 +22,7 @@ The following will compile and install the AF_Packet plugin alongside Zeek:: If everything built and installed correctly, you should see this:: # zeek -NN Zeek::AF_Packet - Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 3.2.0) + Zeek::AF_Packet - Packet acquisition via AF_Packet (dynamic, version 4.0.0) [Packet Source] AF_PacketReader (interface prefix "af_packet"; supports live input) [Type] AF_Packet::FanoutMode [Type] AF_Packet::ChecksumMode diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index c512c0e367..5dc08730b1 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -14,8 +14,8 @@ zeek::plugin::Configuration Plugin::Configure() zeek::plugin::Configuration config; config.name = "Zeek::AF_Packet"; config.description = "Packet acquisition via AF_Packet"; - config.version.major = 3; - config.version.minor = 2; + config.version.major = 4; + config.version.minor = 0; config.version.patch = 0; return config; } From 67d3b0697fc3f44e7af567ef9dee4c9e1ca9396a Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Sat, 29 Oct 2022 16:03:33 +0200 Subject: [PATCH 327/343] af_packet: RX_Ring: Add include for string When compiling with clang and libc++ like done when using Google's hongfuzz in the oss-fuzz setup, the following errors are produced: Step #3 - "compile-honggfuzz-address-x86_64": /src/zeek/auxil/zeek-af_packet-plugin/src/RX_Ring.cc:19:9: error: no matching conversion for functional-style cast from 'const char[15]' to 'RX_RingException' Step #3 - "compile-honggfuzz-address-x86_64": throw RX_RingException("invalid socket"); Step #3 - "compile-honggfuzz-address-x86_64": ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Step #3 - "compile-honggfuzz-address-x86_64": /src/zeek/auxil/zeek-af_packet-plugin/src/RX_Ring.h:14:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const char[15]' to 'const RX_RingException' for 1st argument Step #3 - "compile-honggfuzz-address-x86_64": class RX_RingException : public std::runtime_error { Step #3 - "compile-honggfuzz-address-x86_64": ^ Step #3 - "compile-honggfuzz-address-x86_64": /src/zeek/auxil/zeek-af_packet-plugin/src/RX_Ring.h:14:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'const char[15]' to 'RX_RingException' for 1st argument Step #3 - "compile-honggfuzz-address-x86_64": /src/zeek/auxil/zeek-af_packet-plugin/src/RX_Ring.h:16:2: note: candidate constructor not viable: no known conversion from 'const char[15]' to 'const std::string' (aka 'const basic_string, allocator>') for 1st argument Step #3 - "compile-honggfuzz-address-x86_64": RX_RingException(const std::string& what_arg) : std::runtime_error(what_arg) {} Step #3 - "compile-honggfuzz-address-x86_64": The problem can be reproduced outside of hongfuzz by compiling this plugin with with clang/libc++: export CXX=clang++-14 export CXXFLAGS=-stdlib=libc++ ./configure make Include in RX_Ring.h to ensure the required const char * to std::string conversion are available to any users of RX_RingException. --- src/iosource/af_packet/src/RX_Ring.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/iosource/af_packet/src/RX_Ring.h b/src/iosource/af_packet/src/RX_Ring.h index 91cb3f1d14..893d086d81 100644 --- a/src/iosource/af_packet/src/RX_Ring.h +++ b/src/iosource/af_packet/src/RX_Ring.h @@ -8,6 +8,7 @@ extern "C" { } #include #include +#include #define TPACKET_VERSION TPACKET_V3 From d9d7b76c5df7ba063270a9431ad40672c04f109f Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 22 Feb 2023 12:15:44 +0100 Subject: [PATCH 328/343] af_packet: Add guarded zeek/zeek-version.h include. With zeek/zeek#2802, zeek-config.h will not provide ZEEK_VERSION_NUMBER when a plugin is compiled as a builtin/static plugin into Zeek. This is done to avoid tree-wide ccache busting when just the version changes. --- src/iosource/af_packet/src/AF_Packet.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 387c1da646..ad27e8e9f4 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -1,5 +1,12 @@ #include "zeek/zeek-config.h" +// Starting with Zeek 6.0, zeek-config.h does not provide the +// ZEEK_VERSION_NUMBER macro anymore when compiling a included +// plugin. Use the new zeek/zeek-version.h header if it exists. +#if __has_include("zeek/zeek-version.h") +#include "zeek/zeek-version.h" +#endif + #include "AF_Packet.h" #include "RX_Ring.h" From 17d60e4ab977440a51248d13e77291d3d23ba4c9 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 29 Mar 2023 13:09:33 +0200 Subject: [PATCH 329/343] af_packet: AF_Packet: Remove usages of inline ...not sure why they are marked inline. --- src/iosource/af_packet/src/AF_Packet.cc | 52 ++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index ad27e8e9f4..05441d6e74 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -105,11 +105,11 @@ void AF_PacketSource::Open() Opened(props); } -inline bool AF_PacketSource::BindInterface() - { - struct ifreq ifr; - struct sockaddr_ll saddr_ll; - int ret; +bool AF_PacketSource::BindInterface() + { + struct ifreq ifr; + struct sockaddr_ll saddr_ll; + int ret; memset(&ifr, 0, sizeof(ifr)); snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); @@ -127,11 +127,11 @@ inline bool AF_PacketSource::BindInterface() return (ret >= 0); } -inline bool AF_PacketSource::EnablePromiscMode() - { - struct ifreq ifr; - struct packet_mreq mreq; - int ret; +bool AF_PacketSource::EnablePromiscMode() + { + struct ifreq ifr; + struct packet_mreq mreq; + int ret; memset(&ifr, 0, sizeof(ifr)); snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); @@ -148,12 +148,12 @@ inline bool AF_PacketSource::EnablePromiscMode() return (ret >= 0); } -inline bool AF_PacketSource::ConfigureFanoutGroup(bool enabled, bool defrag) - { - if ( enabled ) - { - uint32_t fanout_arg, fanout_id; - int ret; +bool AF_PacketSource::ConfigureFanoutGroup(bool enabled, bool defrag) + { + if ( enabled ) + { + uint32_t fanout_arg, fanout_id; + int ret; fanout_id = zeek::BifConst::AF_Packet::fanout_id; fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode(defrag) << 16)); @@ -167,13 +167,13 @@ inline bool AF_PacketSource::ConfigureFanoutGroup(bool enabled, bool defrag) return true; } -inline bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) - { - if ( enabled ) - { - struct ifreq ifr; - struct hwtstamp_config hwts_cfg; - int ret, opt; +bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) + { + if ( enabled ) + { + struct ifreq ifr; + struct hwtstamp_config hwts_cfg; + int ret, opt; memset(&hwts_cfg, 0, sizeof(hwts_cfg)); hwts_cfg.tx_type = HWTSTAMP_TX_OFF; @@ -195,9 +195,9 @@ inline bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) return true; } -inline uint32_t AF_PacketSource::GetFanoutMode(bool defrag) - { - uint32_t fanout_mode; +uint32_t AF_PacketSource::GetFanoutMode(bool defrag) + { + uint32_t fanout_mode; switch ( zeek::BifConst::AF_Packet::fanout_mode->AsEnum() ) { case BifEnum::AF_Packet::FANOUT_CPU: fanout_mode = PACKET_FANOUT_CPU; From df4beb60548aaec87b61d3a116afb333a7f01ec9 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 29 Mar 2023 15:38:28 +0200 Subject: [PATCH 330/343] af_packet: AF_Packet: Use negative socket_fd for error indication Technically, socket() can return 0, so shouldn't use it as an indication of a non existent / closed socket. I'm not 100% sure about the Close() contract here: If something goes haywire with a packet source Zeek calls FatalError without calling Close() nor properly destructing the PktSrc. Oh yikes. --- src/iosource/af_packet/src/AF_Packet.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 05441d6e74..aa649f5491 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -34,6 +34,9 @@ AF_PacketSource::AF_PacketSource(const std::string& path, bool is_live) props.path = path; props.is_live = is_live; + socket_fd = -1; + rx_ring = nullptr; + checksum_mode = zeek::BifConst::AF_Packet::checksum_validation_mode->AsEnum(); } @@ -225,13 +228,15 @@ uint32_t AF_PacketSource::GetFanoutMode(bool defrag) } void AF_PacketSource::Close() - { - if ( ! socket_fd ) - return; + { + if ( socket_fd < 0 ) + return; - delete rx_ring; - close(socket_fd); - socket_fd = 0; + delete rx_ring; + rx_ring = nullptr; + + close(socket_fd); + socket_fd = -1; Closed(); } From c3a13304cb2c7e1a30934180ff04ad81c57c1673 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 29 Mar 2023 15:40:04 +0200 Subject: [PATCH 331/343] af_packet: AF_Packet: Check interface for upness When using af_packet with an interface that was not up, the following non-informative error was reported: $ /opt/zeek-5.2/bin/zeek -i af_packet::replay fatal error: problem with interface af_packet::replay (Invalid argument) With this change, the error now includes information about the interface being down: $ ZEEK_PLUGIN_PATH=$(pwd)/build zeek -Ci af_packet::replay fatal error: problem with interface af_packet::replay (interface is down) Fixes #51 --- src/iosource/af_packet/src/AF_Packet.cc | 100 +++++++++++++++--------- src/iosource/af_packet/src/AF_Packet.h | 13 ++- 2 files changed, 74 insertions(+), 39 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index aa649f5491..1813600f78 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -59,6 +59,24 @@ void AF_PacketSource::Open() return; } + auto info = GetInterfaceInfo(props.path); + + if ( ! info.Valid() ) + { + Error(errno ? strerror(errno) : "unable to get interface information"); + close(socket_fd); + socket_fd = -1; + return; + } + + if ( ! info.IsUp() ) + { + Error("interface is down"); + close(socket_fd); + socket_fd = -1; + return; + } + // Create RX-ring try { rx_ring = new RX_Ring(socket_fd, buffer_size, block_size, block_timeout_msec); @@ -68,20 +86,20 @@ void AF_PacketSource::Open() return; } - // Setup interface - if ( ! BindInterface() ) - { - Error(errno ? strerror(errno) : "unable to bind to interface"); - close(socket_fd); - return; - } + // Setup interface + if ( ! BindInterface(info) ) + { + Error(errno ? strerror(errno) : "unable to bind to interface"); + close(socket_fd); + return; + } - if ( ! EnablePromiscMode() ) - { - Error(errno ? strerror(errno) : "unable enter promiscious mode"); - close(socket_fd); - return; - } + if ( ! EnablePromiscMode(info) ) + { + Error(errno ? strerror(errno) : "unable enter promiscious mode"); + close(socket_fd); + return; + } if ( ! ConfigureFanoutGroup(enable_fanout, enable_defrag) ) { @@ -108,44 +126,52 @@ void AF_PacketSource::Open() Opened(props); } -bool AF_PacketSource::BindInterface() +AF_PacketSource::InterfaceInfo AF_PacketSource::GetInterfaceInfo(const std::string& path) { + AF_PacketSource::InterfaceInfo info; struct ifreq ifr; + int ret; + + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", path.c_str()); + + ret = ioctl(socket_fd, SIOCGIFFLAGS, &ifr); + if ( ret < 0 ) + return info; + + info.flags = ifr.ifr_flags; + + ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); + if ( ret < 0 ) + return info; + + info.index = ifr.ifr_ifindex; + + return info; + } + +bool AF_PacketSource::BindInterface(const AF_PacketSource::InterfaceInfo& info) + { struct sockaddr_ll saddr_ll; int ret; - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); - - ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); - if ( ret < 0 ) - return false; - - memset(&saddr_ll, 0, sizeof(saddr_ll)); - saddr_ll.sll_family = AF_PACKET; - saddr_ll.sll_protocol = htons(ETH_P_ALL); - saddr_ll.sll_ifindex = ifr.ifr_ifindex; + memset(&saddr_ll, 0, sizeof(saddr_ll)); + saddr_ll.sll_family = AF_PACKET; + saddr_ll.sll_protocol = htons(ETH_P_ALL); + saddr_ll.sll_ifindex = info.index; ret = bind(socket_fd, (struct sockaddr *) &saddr_ll, sizeof(saddr_ll)); return (ret >= 0); } -bool AF_PacketSource::EnablePromiscMode() +bool AF_PacketSource::EnablePromiscMode(const AF_PacketSource::InterfaceInfo& info) { - struct ifreq ifr; struct packet_mreq mreq; int ret; - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); - - ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); - if ( ret < 0 ) - return false; - - memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = ifr.ifr_ifindex; - mreq.mr_type = PACKET_MR_PROMISC; + memset(&mreq, 0, sizeof(mreq)); + mreq.mr_ifindex = info.index; + mreq.mr_type = PACKET_MR_PROMISC; ret = setsockopt(socket_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); return (ret >= 0); diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index 104a70ed97..9c19e36632 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -66,8 +66,17 @@ private: RX_Ring *rx_ring; struct pcap_pkthdr current_hdr; - bool BindInterface(); - bool EnablePromiscMode(); + struct InterfaceInfo { + int index = -1; + int flags = 0; + + bool Valid () { return index >= 0; } + bool IsUp() { return flags & IFF_UP; } + }; + + InterfaceInfo GetInterfaceInfo(const std::string& path); + bool BindInterface(const InterfaceInfo& info); + bool EnablePromiscMode(const InterfaceInfo& info); bool ConfigureFanoutGroup(bool enabled, bool defrag); bool ConfigureHWTimestamping(bool enabled); uint32_t GetFanoutMode(bool defrag); From aefa52821c3e11cca4d46bdbf096d4bd0a83475b Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Sat, 22 Apr 2023 12:08:32 +0200 Subject: [PATCH 332/343] af_packet: AF_Packet: Fix wrong vlan when PCP or DEI bits are set in tp_vlan_tci A user reported vlan ids > 4095 being logged by Zeek [1]. For populating packet->vlan, mask away Priority Code Point (PCP) and Drop Eligible Indicator (DEI) bits from the tp_vlan_tci field, else we're not setting the correct value on the packet. Fixes #60 [1] https://community.zeek.org/t/zeek-reporting-vlan-ids-above-4095-bug-found/7000 --- src/iosource/af_packet/src/AF_Packet.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 1813600f78..1d4155b949 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -295,7 +295,7 @@ bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) pkt->Init(props.link_type, ¤t_hdr.ts, current_hdr.caplen, current_hdr.len, data); if ( packet->tp_status & TP_STATUS_VLAN_VALID ) - pkt->vlan = packet->hv1.tp_vlan_tci; + pkt->vlan = packet->hv1.tp_vlan_tci & 0x0fff; #if ZEEK_VERSION_NUMBER >= 50100 switch ( checksum_mode ) From 69cae88bb0ecead74ca750ad170208e6eb705306 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 25 Apr 2023 08:44:28 -0700 Subject: [PATCH 333/343] af_packet: Use 'pragma once' instead of include guards --- src/iosource/af_packet/src/AF_Packet.h | 5 +---- src/iosource/af_packet/src/Plugin.h | 6 +----- src/iosource/af_packet/src/RX_Ring.h | 5 +---- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index 9c19e36632..1c176faf7d 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -1,7 +1,6 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef IOSOURCE_PKTSRC_AF_PACKET_SOURCE_H -#define IOSOURCE_PKTSRC_AF_PACKET_SOURCE_H +#pragma once extern "C" { #include @@ -83,5 +82,3 @@ private: }; } - -#endif diff --git a/src/iosource/af_packet/src/Plugin.h b/src/iosource/af_packet/src/Plugin.h index ef8b0dab50..511b943857 100644 --- a/src/iosource/af_packet/src/Plugin.h +++ b/src/iosource/af_packet/src/Plugin.h @@ -1,6 +1,4 @@ - -#ifndef ZEEK_PLUGIN_ZEEK_AF_PACKET -#define ZEEK_PLUGIN_ZEEK_AF_PACKET +#pragma once #include @@ -16,5 +14,3 @@ protected: extern Plugin plugin; } - -#endif diff --git a/src/iosource/af_packet/src/RX_Ring.h b/src/iosource/af_packet/src/RX_Ring.h index 893d086d81..39b79bdfca 100644 --- a/src/iosource/af_packet/src/RX_Ring.h +++ b/src/iosource/af_packet/src/RX_Ring.h @@ -1,7 +1,6 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef IOSOURCE_PKTSRC_RX_RING_H -#define IOSOURCE_PKTSRC_RX_RING_H +#pragma once extern "C" { #include // AF_PACKET, etc. @@ -43,5 +42,3 @@ private: uint8_t* ring; size_t size; }; - -#endif From ba15e3e3b2957c16539703d91f0ca366aaacbff1 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 25 Apr 2023 08:44:45 -0700 Subject: [PATCH 334/343] af_packet: Use override for overriding parent methods --- src/iosource/af_packet/src/AF_Packet.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index 1c176faf7d..b6e0e8a41d 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -39,19 +39,19 @@ public: /** * Destructor. */ - virtual ~AF_PacketSource(); + ~AF_PacketSource() override; static PktSrc* InstantiateAF_Packet(const std::string& path, bool is_live); protected: // PktSrc interface. - virtual void Open(); - virtual void Close(); - virtual bool ExtractNextPacket(zeek::Packet* pkt); - virtual void DoneWithPacket(); - virtual bool PrecompileFilter(int index, const std::string& filter); - virtual bool SetFilter(int index); - virtual void Statistics(Stats* stats); + void Open() override; + void Close() override; + bool ExtractNextPacket(zeek::Packet* pkt) override; + void DoneWithPacket() override; + bool PrecompileFilter(int index, const std::string& filter) override; + bool SetFilter(int index) override; + void Statistics(Stats* stats) override; private: Properties props; From c55fad5094b5164b1ba59fe18b5721c4b47ecdab Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 25 Apr 2023 08:45:03 -0700 Subject: [PATCH 335/343] af_packet: Use cstdint instead of stdint.h --- src/iosource/af_packet/src/RX_Ring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iosource/af_packet/src/RX_Ring.h b/src/iosource/af_packet/src/RX_Ring.h index 39b79bdfca..7f26aedb06 100644 --- a/src/iosource/af_packet/src/RX_Ring.h +++ b/src/iosource/af_packet/src/RX_Ring.h @@ -5,7 +5,7 @@ extern "C" { #include // AF_PACKET, etc. } -#include +#include #include #include From a4cd5dd452894ce9f20d561e2c3a34edd5027933 Mon Sep 17 00:00:00 2001 From: Jan Grashoefer Date: Mon, 10 Jul 2023 18:35:42 +0200 Subject: [PATCH 336/343] af_packet: Note that Zeek ships with a built-in version. Closes #64. --- src/iosource/af_packet/README | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index 2c601f508b..ecf9c991ce 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -3,6 +3,9 @@ This plugin provides native AF_Packet support for Zeek. For details about AF_Packet, see the corresponding [man page](http://man7.org/linux/man-pages/man7/packet.7.html). +> **Note**: +> Starting with Zeek version 5.2, Zeek ships with a built-in version of this plugin. + ## Installation Before installing the plugin, make sure your kernel supports PACKET_FANOUT[^1] and TPACKET_V3. From 1f7c2f42bc76614ce8c096c99e20e5501f221597 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 21 Sep 2023 09:19:57 -0700 Subject: [PATCH 337/343] af_packet: Require CMake 3.15 to match Zeek's requirement --- src/iosource/af_packet/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt index d8a47ab4dc..fae83bbeb7 100644 --- a/src/iosource/af_packet/CMakeLists.txt +++ b/src/iosource/af_packet/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) project(ZeekPluginAF_Packet) From f92bffcfd99faf1570325ae0e37022368888a0b7 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sun, 13 Jul 2025 20:00:13 -0700 Subject: [PATCH 338/343] af_packet: Ensure all of the member fields get initialized --- src/iosource/af_packet/src/AF_Packet.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index b6e0e8a41d..b5253e7af7 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -57,13 +57,13 @@ private: Properties props; Stats stats; - int current_filter; - unsigned int num_discarded; - int checksum_mode; + int current_filter = 0; + unsigned int num_discarded = 0; + int checksum_mode = 0; - int socket_fd; - RX_Ring *rx_ring; - struct pcap_pkthdr current_hdr; + int socket_fd = -1; + RX_Ring *rx_ring = nullptr; + struct pcap_pkthdr current_hdr = {0}; struct InterfaceInfo { int index = -1; From 709f876947bcd95a99ce8c8898e64c5effd4f6b7 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 22 Jul 2025 10:23:35 -0700 Subject: [PATCH 339/343] af_packet: Fix initialization --- src/iosource/af_packet/src/AF_Packet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index b5253e7af7..971c468459 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -63,7 +63,7 @@ private: int socket_fd = -1; RX_Ring *rx_ring = nullptr; - struct pcap_pkthdr current_hdr = {0}; + struct pcap_pkthdr current_hdr = {}; struct InterfaceInfo { int index = -1; From 62e27ee6f763f2e8eda58c86fa6602ba18c4781c Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sun, 17 Aug 2025 21:33:37 -0700 Subject: [PATCH 340/343] af_packet: pre-commit fixes --- src/iosource/af_packet/CMakeLists.txt | 1 - src/iosource/af_packet/README | 2 +- src/iosource/af_packet/src/AF_Packet.cc | 424 +++++++++++------------- src/iosource/af_packet/src/AF_Packet.h | 111 +++---- src/iosource/af_packet/src/Plugin.cc | 32 +- src/iosource/af_packet/src/Plugin.h | 11 +- src/iosource/af_packet/src/RX_Ring.cc | 160 +++++---- src/iosource/af_packet/src/RX_Ring.h | 34 +- 8 files changed, 362 insertions(+), 413 deletions(-) diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt index fae83bbeb7..3cb19806f6 100644 --- a/src/iosource/af_packet/CMakeLists.txt +++ b/src/iosource/af_packet/CMakeLists.txt @@ -1,4 +1,3 @@ - cmake_minimum_required(VERSION 3.15 FATAL_ERROR) project(ZeekPluginAF_Packet) diff --git a/src/iosource/af_packet/README b/src/iosource/af_packet/README index ecf9c991ce..e882f6e9fb 100644 --- a/src/iosource/af_packet/README +++ b/src/iosource/af_packet/README @@ -91,7 +91,7 @@ To use the AF_Packet plugin with `zeekctl`, the `custom` load balance method can af_packet_fanout_mode=AF_Packet::FANOUT_HASH af_packet_buffer_size=128*1024*1024 -If all interfaces using `lb_method=custom` should be configured for AF_Packet, the prefix can be globally definied by adding the following line to `zeekctl.conf`: +If all interfaces using `lb_method=custom` should be configured for AF_Packet, the prefix can be globally defined by adding the following line to `zeekctl.conf`: lb_custom.InterfacePrefix=af_packet:: diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/src/AF_Packet.cc index 1d4155b949..ba8fcddd47 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/src/AF_Packet.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "zeek/zeek-config.h" // Starting with Zeek 6.0, zeek-config.h does not provide the @@ -9,7 +11,6 @@ #include "AF_Packet.h" #include "RX_Ring.h" - #include "af_packet.bif.h" // CentOS 7 if_packet.h does not yet have this define, provide it @@ -20,189 +21,169 @@ using namespace zeek::iosource::pktsrc; -AF_PacketSource::~AF_PacketSource() - { - Close(); - } +AF_PacketSource::~AF_PacketSource() { Close(); } -AF_PacketSource::AF_PacketSource(const std::string& path, bool is_live) - { +AF_PacketSource::AF_PacketSource(const std::string& path, bool is_live) { if ( ! is_live ) Error("AF_Packet source does not support offline input"); - current_filter = -1; - props.path = path; - props.is_live = is_live; + current_filter = -1; + props.path = path; + props.is_live = is_live; - socket_fd = -1; - rx_ring = nullptr; + socket_fd = -1; + rx_ring = nullptr; - checksum_mode = zeek::BifConst::AF_Packet::checksum_validation_mode->AsEnum(); - } + checksum_mode = zeek::BifConst::AF_Packet::checksum_validation_mode->AsEnum(); +} -void AF_PacketSource::Open() - { - uint64_t buffer_size = zeek::BifConst::AF_Packet::buffer_size; - uint64_t block_size = zeek::BifConst::AF_Packet::block_size; - int block_timeout_msec = static_cast(zeek::BifConst::AF_Packet::block_timeout * 1000.0); - int link_type = zeek::BifConst::AF_Packet::link_type; +void AF_PacketSource::Open() { + uint64_t buffer_size = zeek::BifConst::AF_Packet::buffer_size; + uint64_t block_size = zeek::BifConst::AF_Packet::block_size; + int block_timeout_msec = static_cast(zeek::BifConst::AF_Packet::block_timeout * 1000.0); + int link_type = zeek::BifConst::AF_Packet::link_type; - bool enable_hw_timestamping = zeek::BifConst::AF_Packet::enable_hw_timestamping; - bool enable_fanout = zeek::BifConst::AF_Packet::enable_fanout; - bool enable_defrag = zeek::BifConst::AF_Packet::enable_defrag; + bool enable_hw_timestamping = zeek::BifConst::AF_Packet::enable_hw_timestamping; + bool enable_fanout = zeek::BifConst::AF_Packet::enable_fanout; + bool enable_defrag = zeek::BifConst::AF_Packet::enable_defrag; socket_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if ( socket_fd < 0 ) - { + if ( socket_fd < 0 ) { Error(errno ? strerror(errno) : "unable to create socket"); return; - } + } - auto info = GetInterfaceInfo(props.path); + auto info = GetInterfaceInfo(props.path); - if ( ! info.Valid() ) - { - Error(errno ? strerror(errno) : "unable to get interface information"); - close(socket_fd); - socket_fd = -1; - return; - } + if ( ! info.Valid() ) { + Error(errno ? strerror(errno) : "unable to get interface information"); + close(socket_fd); + socket_fd = -1; + return; + } - if ( ! info.IsUp() ) - { - Error("interface is down"); - close(socket_fd); - socket_fd = -1; - return; - } + if ( ! info.IsUp() ) { + Error("interface is down"); + close(socket_fd); + socket_fd = -1; + return; + } - // Create RX-ring - try { - rx_ring = new RX_Ring(socket_fd, buffer_size, block_size, block_timeout_msec); - } catch (RX_RingException& e) { - Error(errno ? strerror(errno) : "unable to create RX-ring"); - close(socket_fd); - return; - } + // Create RX-ring + try { + rx_ring = new RX_Ring(socket_fd, buffer_size, block_size, block_timeout_msec); + } catch ( RX_RingException& e ) { + Error(errno ? strerror(errno) : "unable to create RX-ring"); + close(socket_fd); + return; + } - // Setup interface - if ( ! BindInterface(info) ) - { - Error(errno ? strerror(errno) : "unable to bind to interface"); - close(socket_fd); - return; - } + // Setup interface + if ( ! BindInterface(info) ) { + Error(errno ? strerror(errno) : "unable to bind to interface"); + close(socket_fd); + return; + } - if ( ! EnablePromiscMode(info) ) - { - Error(errno ? strerror(errno) : "unable enter promiscious mode"); - close(socket_fd); - return; - } + if ( ! EnablePromiscMode(info) ) { + Error(errno ? strerror(errno) : "unable enter promiscuous mode"); + close(socket_fd); + return; + } - if ( ! ConfigureFanoutGroup(enable_fanout, enable_defrag) ) - { - Error(errno ? strerror(errno) : "failed to join fanout group"); - close(socket_fd); - return; - } + if ( ! ConfigureFanoutGroup(enable_fanout, enable_defrag) ) { + Error(errno ? strerror(errno) : "failed to join fanout group"); + close(socket_fd); + return; + } - if ( ! ConfigureHWTimestamping(enable_hw_timestamping) ) - { + if ( ! ConfigureHWTimestamping(enable_hw_timestamping) ) { Error(errno ? strerror(errno) : "failed to configure hardware timestamping"); close(socket_fd); return; - } + } - props.netmask = NETMASK_UNKNOWN; - props.selectable_fd = socket_fd; - props.is_live = true; - props.link_type = link_type; + props.netmask = NETMASK_UNKNOWN; + props.selectable_fd = socket_fd; + props.is_live = true; + props.link_type = link_type; stats.received = stats.dropped = stats.link = stats.bytes_received = 0; num_discarded = 0; Opened(props); - } +} -AF_PacketSource::InterfaceInfo AF_PacketSource::GetInterfaceInfo(const std::string& path) - { - AF_PacketSource::InterfaceInfo info; - struct ifreq ifr; - int ret; +AF_PacketSource::InterfaceInfo AF_PacketSource::GetInterfaceInfo(const std::string& path) { + AF_PacketSource::InterfaceInfo info; + struct ifreq ifr; + int ret; - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", path.c_str()); + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", path.c_str()); - ret = ioctl(socket_fd, SIOCGIFFLAGS, &ifr); - if ( ret < 0 ) - return info; + ret = ioctl(socket_fd, SIOCGIFFLAGS, &ifr); + if ( ret < 0 ) + return info; - info.flags = ifr.ifr_flags; + info.flags = ifr.ifr_flags; - ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); - if ( ret < 0 ) - return info; + ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); + if ( ret < 0 ) + return info; - info.index = ifr.ifr_ifindex; + info.index = ifr.ifr_ifindex; - return info; - } + return info; +} -bool AF_PacketSource::BindInterface(const AF_PacketSource::InterfaceInfo& info) - { - struct sockaddr_ll saddr_ll; - int ret; +bool AF_PacketSource::BindInterface(const AF_PacketSource::InterfaceInfo& info) { + struct sockaddr_ll saddr_ll; + int ret; - memset(&saddr_ll, 0, sizeof(saddr_ll)); - saddr_ll.sll_family = AF_PACKET; - saddr_ll.sll_protocol = htons(ETH_P_ALL); - saddr_ll.sll_ifindex = info.index; + memset(&saddr_ll, 0, sizeof(saddr_ll)); + saddr_ll.sll_family = AF_PACKET; + saddr_ll.sll_protocol = htons(ETH_P_ALL); + saddr_ll.sll_ifindex = info.index; - ret = bind(socket_fd, (struct sockaddr *) &saddr_ll, sizeof(saddr_ll)); + ret = bind(socket_fd, (struct sockaddr*)&saddr_ll, sizeof(saddr_ll)); return (ret >= 0); - } +} -bool AF_PacketSource::EnablePromiscMode(const AF_PacketSource::InterfaceInfo& info) - { - struct packet_mreq mreq; - int ret; +bool AF_PacketSource::EnablePromiscMode(const AF_PacketSource::InterfaceInfo& info) { + struct packet_mreq mreq; + int ret; - memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = info.index; - mreq.mr_type = PACKET_MR_PROMISC; + memset(&mreq, 0, sizeof(mreq)); + mreq.mr_ifindex = info.index; + mreq.mr_type = PACKET_MR_PROMISC; ret = setsockopt(socket_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); return (ret >= 0); - } +} -bool AF_PacketSource::ConfigureFanoutGroup(bool enabled, bool defrag) - { - if ( enabled ) - { - uint32_t fanout_arg, fanout_id; - int ret; +bool AF_PacketSource::ConfigureFanoutGroup(bool enabled, bool defrag) { + if ( enabled ) { + uint32_t fanout_arg, fanout_id; + int ret; fanout_id = zeek::BifConst::AF_Packet::fanout_id; fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode(defrag) << 16)); - ret = setsockopt(socket_fd, SOL_PACKET, PACKET_FANOUT, - &fanout_arg, sizeof(fanout_arg)); + ret = setsockopt(socket_fd, SOL_PACKET, PACKET_FANOUT, &fanout_arg, sizeof(fanout_arg)); if ( ret < 0 ) return false; - } - return true; } + return true; +} -bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) - { - if ( enabled ) - { - struct ifreq ifr; - struct hwtstamp_config hwts_cfg; - int ret, opt; +bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) { + if ( enabled ) { + struct ifreq ifr; + struct hwtstamp_config hwts_cfg; + int ret, opt; memset(&hwts_cfg, 0, sizeof(hwts_cfg)); hwts_cfg.tx_type = HWTSTAMP_TX_OFF; @@ -216,175 +197,150 @@ bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) return false; opt = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE; - ret = setsockopt(socket_fd, SOL_PACKET, PACKET_TIMESTAMP, - &opt, sizeof(opt)); - if( ret < 0 ) + ret = setsockopt(socket_fd, SOL_PACKET, PACKET_TIMESTAMP, &opt, sizeof(opt)); + if ( ret < 0 ) return false; - } - return true; } + return true; +} -uint32_t AF_PacketSource::GetFanoutMode(bool defrag) - { - uint32_t fanout_mode; +uint32_t AF_PacketSource::GetFanoutMode(bool defrag) { + uint32_t fanout_mode; switch ( zeek::BifConst::AF_Packet::fanout_mode->AsEnum() ) { - case BifEnum::AF_Packet::FANOUT_CPU: fanout_mode = PACKET_FANOUT_CPU; - break; - #ifdef PACKET_FANOUT_QM - case BifEnum::AF_Packet::FANOUT_QM: fanout_mode = PACKET_FANOUT_QM; - break; - #endif - #ifdef PACKET_FANOUT_CBPF - case BifEnum::AF_Packet::FANOUT_CBPF: fanout_mode = PACKET_FANOUT_CBPF; - break; - #endif - #ifdef PACKET_FANOUT_EBPF - case BifEnum::AF_Packet::FANOUT_EBPF: fanout_mode = PACKET_FANOUT_EBPF; - break; - #endif - default: fanout_mode = PACKET_FANOUT_HASH; - break; + case BifEnum::AF_Packet::FANOUT_CPU: fanout_mode = PACKET_FANOUT_CPU; break; +#ifdef PACKET_FANOUT_QM + case BifEnum::AF_Packet::FANOUT_QM: fanout_mode = PACKET_FANOUT_QM; break; +#endif +#ifdef PACKET_FANOUT_CBPF + case BifEnum::AF_Packet::FANOUT_CBPF: fanout_mode = PACKET_FANOUT_CBPF; break; +#endif +#ifdef PACKET_FANOUT_EBPF + case BifEnum::AF_Packet::FANOUT_EBPF: fanout_mode = PACKET_FANOUT_EBPF; break; +#endif + default: fanout_mode = PACKET_FANOUT_HASH; break; } if ( defrag ) fanout_mode |= PACKET_FANOUT_FLAG_DEFRAG; return fanout_mode; - } +} -void AF_PacketSource::Close() - { - if ( socket_fd < 0 ) - return; +void AF_PacketSource::Close() { + if ( socket_fd < 0 ) + return; - delete rx_ring; - rx_ring = nullptr; + delete rx_ring; + rx_ring = nullptr; - close(socket_fd); - socket_fd = -1; + close(socket_fd); + socket_fd = -1; Closed(); - } +} -bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) - { +bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) { if ( ! socket_fd ) return false; - struct tpacket3_hdr *packet = 0; - const u_char *data; - while ( true ) - { - if ( ! rx_ring->GetNextPacket(&packet) ) - return false; + struct tpacket3_hdr* packet = 0; + const u_char* data; + while ( true ) { + if ( ! rx_ring->GetNextPacket(&packet) ) + return false; current_hdr.ts.tv_sec = packet->tp_sec; current_hdr.ts.tv_usec = packet->tp_nsec / 1000; current_hdr.caplen = packet->tp_snaplen; current_hdr.len = packet->tp_len; - data = (u_char *) packet + packet->tp_mac; + data = (u_char*)packet + packet->tp_mac; - if ( !ApplyBPFFilter(current_filter, ¤t_hdr, data) ) - { + if ( ! ApplyBPFFilter(current_filter, ¤t_hdr, data) ) { ++num_discarded; DoneWithPacket(); continue; - } + } pkt->Init(props.link_type, ¤t_hdr.ts, current_hdr.caplen, current_hdr.len, data); - if ( packet->tp_status & TP_STATUS_VLAN_VALID ) - pkt->vlan = packet->hv1.tp_vlan_tci & 0x0fff; + if ( packet->tp_status & TP_STATUS_VLAN_VALID ) + pkt->vlan = packet->hv1.tp_vlan_tci & 0x0fff; #if ZEEK_VERSION_NUMBER >= 50100 - switch ( checksum_mode ) - { - case BifEnum::AF_Packet::CHECKSUM_OFF: - { - // If set to off, just accept whatever checksum in the packet is correct and - // skip checking it here and in Zeek. - pkt->l4_checksummed = true; - break; - } - case BifEnum::AF_Packet::CHECKSUM_KERNEL: - { - // If set to kernel, check whether the kernel thinks the checksum is valid. If it - // does, tell Zeek to skip checking by itself. - if ( ( (packet->tp_status & TP_STATUS_CSUM_VALID) != 0 ) || - ( (packet->tp_status & TP_STATUS_CSUMNOTREADY) != 0 ) ) - pkt->l4_checksummed = true; - else - pkt->l4_checksummed = false; - break; - } - case BifEnum::AF_Packet::CHECKSUM_ON: - default: - { - // Let Zeek handle it. - pkt->l4_checksummed = false; - break; - } - } + switch ( checksum_mode ) { + case BifEnum::AF_Packet::CHECKSUM_OFF: { + // If set to off, just accept whatever checksum in the packet is correct and + // skip checking it here and in Zeek. + pkt->l4_checksummed = true; + break; + } + case BifEnum::AF_Packet::CHECKSUM_KERNEL: { + // If set to kernel, check whether the kernel thinks the checksum is valid. If it + // does, tell Zeek to skip checking by itself. + if ( ((packet->tp_status & TP_STATUS_CSUM_VALID) != 0) || + ((packet->tp_status & TP_STATUS_CSUMNOTREADY) != 0) ) + pkt->l4_checksummed = true; + else + pkt->l4_checksummed = false; + break; + } + case BifEnum::AF_Packet::CHECKSUM_ON: + default: { + // Let Zeek handle it. + pkt->l4_checksummed = false; + break; + } + } #endif - if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) - { - Weird("empty_af_packet_header", pkt); - return false; - } + if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) { + Weird("empty_af_packet_header", pkt); + return false; + } stats.received++; stats.bytes_received += current_hdr.len; return true; - } + } return false; - } +} -void AF_PacketSource::DoneWithPacket() - { - rx_ring->ReleasePacket(); - } +void AF_PacketSource::DoneWithPacket() { rx_ring->ReleasePacket(); } -bool AF_PacketSource::PrecompileFilter(int index, const std::string& filter) - { +bool AF_PacketSource::PrecompileFilter(int index, const std::string& filter) { return PktSrc::PrecompileBPFFilter(index, filter); - } +} -bool AF_PacketSource::SetFilter(int index) - { +bool AF_PacketSource::SetFilter(int index) { current_filter = index; return true; - } +} -void AF_PacketSource::Statistics(Stats* s) - { - if ( ! socket_fd ) - { +void AF_PacketSource::Statistics(Stats* s) { + if ( ! socket_fd ) { s->received = s->bytes_received = s->link = s->dropped = 0; return; - } + } struct tpacket_stats_v3 tp_stats; - socklen_t tp_stats_len = sizeof (struct tpacket_stats_v3); + socklen_t tp_stats_len = sizeof(struct tpacket_stats_v3); int ret; ret = getsockopt(socket_fd, SOL_PACKET, PACKET_STATISTICS, &tp_stats, &tp_stats_len); - if ( ret < 0 ) - { + if ( ret < 0 ) { Error(errno ? strerror(errno) : "unable to retrieve statistics"); s->received = s->bytes_received = s->link = s->dropped = 0; return; - } + } stats.link += tp_stats.tp_packets; stats.dropped += tp_stats.tp_drops; memcpy(s, &stats, sizeof(Stats)); - } +} -zeek::iosource::PktSrc* AF_PacketSource::InstantiateAF_Packet(const std::string& path, bool is_live) - { +zeek::iosource::PktSrc* AF_PacketSource::InstantiateAF_Packet(const std::string& path, bool is_live) { return new AF_PacketSource(path, is_live); - } +} diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/src/AF_Packet.h index 971c468459..fe6ecb15f7 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/src/AF_Packet.h @@ -3,82 +3,81 @@ #pragma once extern "C" { -#include -#include -#include - -#include // errorno -#include // close() - -#include // ETH_P_ALL -#include // ifreq -#include // AF_PACKET, etc. -#include // SIOCSHWTSTAMP -#include // hwtstamp_config +#include // errorno +#include // ifreq +#include // AF_PACKET, etc. +#include // hwtstamp_config +#include // SIOCSHWTSTAMP +#include // ETH_P_ALL #include +#include +#include +#include +#include // close() } #include "zeek/iosource/PktSrc.h" + #include "RX_Ring.h" namespace af_packet::iosource::pktsrc { class AF_PacketSource : public zeek::iosource::PktSrc { public: - /** - * Constructor. - * - * path: Name of the interface to open (the AF_Packet source doesn't - * support reading from files). - * - * is_live: Must be true (the AF_Packet source doesn't support offline - * operation). - */ - AF_PacketSource(const std::string& path, bool is_live); + /** + * Constructor. + * + * path: Name of the interface to open (the AF_Packet source doesn't + * support reading from files). + * + * is_live: Must be true (the AF_Packet source doesn't support offline + * operation). + */ + AF_PacketSource(const std::string& path, bool is_live); - /** - * Destructor. - */ - ~AF_PacketSource() override; + /** + * Destructor. + */ + ~AF_PacketSource() override; - static PktSrc* InstantiateAF_Packet(const std::string& path, bool is_live); + static PktSrc* InstantiateAF_Packet(const std::string& path, bool is_live); protected: - // PktSrc interface. - void Open() override; - void Close() override; - bool ExtractNextPacket(zeek::Packet* pkt) override; - void DoneWithPacket() override; - bool PrecompileFilter(int index, const std::string& filter) override; - bool SetFilter(int index) override; - void Statistics(Stats* stats) override; + // PktSrc interface. + void Open() override; + void Close() override; + bool ExtractNextPacket(zeek::Packet* pkt) override; + void DoneWithPacket() override; + bool PrecompileFilter(int index, const std::string& filter) override; + bool SetFilter(int index) override; + void Statistics(Stats* stats) override; private: - Properties props; - Stats stats; + Properties props; + Stats stats; - int current_filter = 0; - unsigned int num_discarded = 0; - int checksum_mode = 0; + int current_filter = 0; + unsigned int num_discarded = 0; + int checksum_mode = 0; - int socket_fd = -1; - RX_Ring *rx_ring = nullptr; - struct pcap_pkthdr current_hdr = {}; + int socket_fd = -1; + RX_Ring* rx_ring = nullptr; + struct pcap_pkthdr current_hdr = {}; - struct InterfaceInfo { - int index = -1; - int flags = 0; + struct InterfaceInfo { + int index = -1; + int flags = 0; - bool Valid () { return index >= 0; } - bool IsUp() { return flags & IFF_UP; } - }; + bool Valid() { return index >= 0; } + bool IsUp() { return flags & IFF_UP; } + }; - InterfaceInfo GetInterfaceInfo(const std::string& path); - bool BindInterface(const InterfaceInfo& info); - bool EnablePromiscMode(const InterfaceInfo& info); - bool ConfigureFanoutGroup(bool enabled, bool defrag); - bool ConfigureHWTimestamping(bool enabled); - uint32_t GetFanoutMode(bool defrag); + InterfaceInfo GetInterfaceInfo(const std::string& path); + bool BindInterface(const InterfaceInfo& info); + bool EnablePromiscMode(const InterfaceInfo& info); + bool ConfigureFanoutGroup(bool enabled, bool defrag); + bool ConfigureHWTimestamping(bool enabled); + uint32_t GetFanoutMode(bool defrag); }; -} +} // namespace zeek::iosource::pktsrc diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc index 5dc08730b1..ca8aa96ac3 100644 --- a/src/iosource/af_packet/src/Plugin.cc +++ b/src/iosource/af_packet/src/Plugin.cc @@ -1,21 +1,27 @@ +// See the file "COPYING" in the main distribution directory for copyright. #include "Plugin.h" -#include "AF_Packet.h" + #include "zeek/iosource/Component.h" -namespace af_packet::plugin::Zeek_AF_Packet { Plugin plugin; } +#include "AF_Packet.h" + +namespace plugin::Zeek_AF_Packet { +Plugin plugin; +} using namespace af_packet::plugin::Zeek_AF_Packet; -zeek::plugin::Configuration Plugin::Configure() - { - AddComponent(new ::zeek::iosource::PktSrcComponent("AF_PacketReader", "af_packet", ::zeek::iosource::PktSrcComponent::LIVE, ::af_packet::iosource::pktsrc::AF_PacketSource::InstantiateAF_Packet)); +zeek::plugin::Configuration Plugin::Configure() { + AddComponent( + new ::zeek::iosource::PktSrcComponent("AF_PacketReader", "af_packet", ::zeek::iosource::PktSrcComponent::LIVE, + ::zeek::iosource::pktsrc::AF_PacketSource::InstantiateAF_Packet)); - zeek::plugin::Configuration config; - config.name = "Zeek::AF_Packet"; - config.description = "Packet acquisition via AF_Packet"; - config.version.major = 4; - config.version.minor = 0; - config.version.patch = 0; - return config; - } + zeek::plugin::Configuration config; + config.name = "Zeek::AF_Packet"; + config.description = "Packet acquisition via AF_Packet"; + config.version.major = 4; + config.version.minor = 0; + config.version.patch = 0; + return config; +} diff --git a/src/iosource/af_packet/src/Plugin.h b/src/iosource/af_packet/src/Plugin.h index 511b943857..ad2961a379 100644 --- a/src/iosource/af_packet/src/Plugin.h +++ b/src/iosource/af_packet/src/Plugin.h @@ -1,16 +1,17 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #pragma once #include namespace af_packet::plugin::Zeek_AF_Packet { -class Plugin : public zeek::plugin::Plugin -{ +class Plugin : public zeek::plugin::Plugin { protected: - // Overridden from zeek::plugin::Plugin. - zeek::plugin::Configuration Configure() override; + // Overridden from zeek::plugin::Plugin. + zeek::plugin::Configuration Configure() override; }; extern Plugin plugin; -} +} // namespace plugin::Zeek_AF_Packet diff --git a/src/iosource/af_packet/src/RX_Ring.cc b/src/iosource/af_packet/src/RX_Ring.cc index f364d2d827..99c38912b3 100644 --- a/src/iosource/af_packet/src/RX_Ring.cc +++ b/src/iosource/af_packet/src/RX_Ring.cc @@ -1,3 +1,4 @@ +// See the file "COPYING" in the main distribution directory for copyright. #include "RX_Ring.h" @@ -5,108 +6,95 @@ #include extern "C" { -#include // AF_PACKET, etc. -#include // socketopt consts -#include // mmap -#include // sysconf +#include // AF_PACKET, etc. +#include // mmap +#include // socketopt consts +#include // sysconf } -RX_Ring::RX_Ring(int sock, size_t bufsize, size_t blocksize, int blocktimeout_msec) - { - int ret, ver = TPACKET_VERSION; +RX_Ring::RX_Ring(int sock, size_t bufsize, size_t blocksize, int blocktimeout_msec) { + int ret, ver = TPACKET_VERSION; - if ( sock < 0 ) - throw RX_RingException("invalid socket"); + if ( sock < 0 ) + throw RX_RingException("invalid socket"); - // Configure socket - ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &ver, sizeof(ver)); - if ( ret ) - throw RX_RingException("unable to set TPacket version"); + // Configure socket + ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &ver, sizeof(ver)); + if ( ret ) + throw RX_RingException("unable to set TPacket version"); - InitLayout(bufsize, blocksize, blocktimeout_msec); - ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, (uint8_t *) &layout, - sizeof(layout)); - if ( ret ) - throw RX_RingException("unable to set ring layout"); + InitLayout(bufsize, blocksize, blocktimeout_msec); + ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, (uint8_t*)&layout, sizeof(layout)); + if ( ret ) + throw RX_RingException("unable to set ring layout"); - // Map memory - size = layout.tp_block_size * layout.tp_block_nr; - ring = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_SHARED, sock, 0); - if ( ring == MAP_FAILED ) - throw RX_RingException("unable to map ring memory"); + // Map memory + size = layout.tp_block_size * layout.tp_block_nr; + ring = (uint8_t*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, sock, 0); + if ( ring == MAP_FAILED ) + throw RX_RingException("unable to map ring memory"); - block_num = packet_num = 0; - packet = NULL; + block_num = packet_num = 0; + packet = NULL; - // Init block mapping - blocks = new tpacket_block_desc*[layout.tp_block_nr]; - for ( unsigned int i = 0; i < layout.tp_block_nr; i++ ) - blocks[i] = (struct tpacket_block_desc *)(ring + - i * layout.tp_block_size); - } + // Init block mapping + blocks = new tpacket_block_desc*[layout.tp_block_nr]; + for ( unsigned int i = 0; i < layout.tp_block_nr; i++ ) + blocks[i] = (struct tpacket_block_desc*)(ring + i * layout.tp_block_size); +} -RX_Ring::~RX_Ring() - { - ReleasePacket(); +RX_Ring::~RX_Ring() { + ReleasePacket(); - delete[] blocks; - munmap(ring, size); + delete[] blocks; + munmap(ring, size); - blocks = 0; - size = 0; - } + blocks = 0; + size = 0; +} -bool RX_Ring::GetNextPacket(tpacket3_hdr** hdr) - { - struct tpacket_hdr_v1 *block_hdr = &(blocks[block_num]->hdr.bh1); +bool RX_Ring::GetNextPacket(tpacket3_hdr** hdr) { + struct tpacket_hdr_v1* block_hdr = &(blocks[block_num]->hdr.bh1); - if ( (block_hdr->block_status & TP_STATUS_USER) == 0 ) - return false; + if ( (block_hdr->block_status & TP_STATUS_USER) == 0 ) + return false; - if ( packet == NULL ) - { - // New block - packet_num = block_hdr->num_pkts; - if ( packet_num == 0 ) - { - NextBlock(); - return false; - } - packet = (struct tpacket3_hdr *) - ((uint8_t *) blocks[block_num] + block_hdr->offset_to_first_pkt); - } - else - // Continue with block - packet = (struct tpacket3_hdr *) - ((uint8_t *) packet + packet->tp_next_offset); + if ( packet == NULL ) { + // New block + packet_num = block_hdr->num_pkts; + if ( packet_num == 0 ) { + NextBlock(); + return false; + } + packet = (struct tpacket3_hdr*)((uint8_t*)blocks[block_num] + block_hdr->offset_to_first_pkt); + } + else + // Continue with block + packet = (struct tpacket3_hdr*)((uint8_t*)packet + packet->tp_next_offset); - *hdr = packet; - packet_num--; - return true; - } + *hdr = packet; + packet_num--; + return true; +} -void RX_Ring::ReleasePacket() - { - if ( packet_num == 0 ) - NextBlock(); - } +void RX_Ring::ReleasePacket() { + if ( packet_num == 0 ) + NextBlock(); +} -void RX_Ring::InitLayout(size_t bufsize, size_t blocksize, int blocktimeout_msec) - { - memset(&layout, 0, sizeof(layout)); - layout.tp_block_size = blocksize; - layout.tp_frame_size = TPACKET_ALIGNMENT << 7; // Seems to be irrelevant for V3 - layout.tp_block_nr = bufsize / layout.tp_block_size; - layout.tp_frame_nr = (layout.tp_block_size / layout.tp_frame_size) * layout.tp_block_nr; - layout.tp_retire_blk_tov = blocktimeout_msec; - } +void RX_Ring::InitLayout(size_t bufsize, size_t blocksize, int blocktimeout_msec) { + memset(&layout, 0, sizeof(layout)); + layout.tp_block_size = blocksize; + layout.tp_frame_size = TPACKET_ALIGNMENT << 7; // Seems to be irrelevant for V3 + layout.tp_block_nr = bufsize / layout.tp_block_size; + layout.tp_frame_nr = (layout.tp_block_size / layout.tp_frame_size) * layout.tp_block_nr; + layout.tp_retire_blk_tov = blocktimeout_msec; +} -void RX_Ring::NextBlock() - { - struct tpacket_hdr_v1 *block_hdr = &(blocks[block_num]->hdr.bh1); +void RX_Ring::NextBlock() { + struct tpacket_hdr_v1* block_hdr = &(blocks[block_num]->hdr.bh1); - block_hdr->block_status = TP_STATUS_KERNEL; - block_num = (block_num +1) % layout.tp_block_nr; - packet = NULL; - } + block_hdr->block_status = TP_STATUS_KERNEL; + block_num = (block_num + 1) % layout.tp_block_nr; + packet = NULL; +} diff --git a/src/iosource/af_packet/src/RX_Ring.h b/src/iosource/af_packet/src/RX_Ring.h index 7f26aedb06..c11e7140ef 100644 --- a/src/iosource/af_packet/src/RX_Ring.h +++ b/src/iosource/af_packet/src/RX_Ring.h @@ -13,32 +13,32 @@ extern "C" { class RX_RingException : public std::runtime_error { public: - RX_RingException(const std::string& what_arg) : std::runtime_error(what_arg) {} + RX_RingException(const std::string& what_arg) : std::runtime_error(what_arg) {} }; class RX_Ring { public: - /** - * Constructor - */ - RX_Ring(int sock, size_t bufsize, size_t blocksize, int blocktimeout_msec); - ~RX_Ring(); + /** + * Constructor + */ + RX_Ring(int sock, size_t bufsize, size_t blocksize, int blocktimeout_msec); + ~RX_Ring(); - bool GetNextPacket(tpacket3_hdr** hdr); - void ReleasePacket(); + bool GetNextPacket(tpacket3_hdr** hdr); + void ReleasePacket(); protected: - void InitLayout(size_t bufsize, size_t blocksize, int blocktimeout_msec); - void NextBlock(); + void InitLayout(size_t bufsize, size_t blocksize, int blocktimeout_msec); + void NextBlock(); private: - struct tpacket_req3 layout; - struct tpacket_block_desc** blocks; - struct tpacket3_hdr* packet; + struct tpacket_req3 layout; + struct tpacket_block_desc** blocks; + struct tpacket3_hdr* packet; - unsigned int block_num; - unsigned int packet_num; + unsigned int block_num; + unsigned int packet_num; - uint8_t* ring; - size_t size; + uint8_t* ring; + size_t size; }; From 6002f63a37abaed62b0aa641179597112642c045 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Sun, 17 Aug 2025 21:39:49 -0700 Subject: [PATCH 341/343] af_packet: Remove submodule, adapt CMake/code for Zeek build --- .gitmodules | 3 -- CMakeLists.txt | 13 +----- auxil/zeek-af_packet-plugin | 1 - scripts/base/init-bare.zeek | 25 +++++++++++ src/iosource/CMakeLists.txt | 1 + src/iosource/af_packet/{src => }/AF_Packet.cc | 42 +++++-------------- src/iosource/af_packet/{src => }/AF_Packet.h | 7 ++-- src/iosource/af_packet/CMakeLists.txt | 28 ++----------- src/iosource/af_packet/Plugin.cc | 27 ++++++++++++ src/iosource/af_packet/{src => }/RX_Ring.cc | 27 ++++++------ src/iosource/af_packet/{src => }/RX_Ring.h | 7 +++- src/iosource/af_packet/af_packet.bif | 16 +++++++ src/iosource/af_packet/scripts/__load__.zeek | 5 --- .../af_packet/scripts/af_packet/__load__.zeek | 1 - src/iosource/af_packet/scripts/init.zeek | 28 ------------- src/iosource/af_packet/src/Plugin.cc | 27 ------------ src/iosource/af_packet/src/Plugin.h | 17 -------- src/iosource/af_packet/src/af_packet.bif | 35 ---------------- src/types.bif | 22 ++++++++++ 19 files changed, 128 insertions(+), 204 deletions(-) delete mode 160000 auxil/zeek-af_packet-plugin rename src/iosource/af_packet/{src => }/AF_Packet.cc (88%) rename src/iosource/af_packet/{src => }/AF_Packet.h (94%) create mode 100644 src/iosource/af_packet/Plugin.cc rename src/iosource/af_packet/{src => }/RX_Ring.cc (80%) rename src/iosource/af_packet/{src => }/RX_Ring.h (85%) create mode 100644 src/iosource/af_packet/af_packet.bif delete mode 100644 src/iosource/af_packet/scripts/__load__.zeek delete mode 100644 src/iosource/af_packet/scripts/af_packet/__load__.zeek delete mode 100644 src/iosource/af_packet/scripts/init.zeek delete mode 100644 src/iosource/af_packet/src/Plugin.cc delete mode 100644 src/iosource/af_packet/src/Plugin.h delete mode 100644 src/iosource/af_packet/src/af_packet.bif diff --git a/.gitmodules b/.gitmodules index dbf4e2590f..a6008cdc49 100644 --- a/.gitmodules +++ b/.gitmodules @@ -49,9 +49,6 @@ [submodule "auxil/spicy"] path = auxil/spicy url = https://github.com/zeek/spicy -[submodule "auxil/zeek-af_packet-plugin"] - path = auxil/zeek-af_packet-plugin - url = https://github.com/zeek/zeek-af_packet-plugin.git [submodule "auxil/libunistd"] path = auxil/libunistd url = https://github.com/zeek/libunistd diff --git a/CMakeLists.txt b/CMakeLists.txt index a4dc95c1df..497c7d188b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1189,18 +1189,6 @@ endif () # Tell the plugin code that we're building as part of the main tree. set(ZEEK_PLUGIN_INTERNAL_BUILD true CACHE INTERNAL "" FORCE) -set(ZEEK_HAVE_AF_PACKET no) -if (${CMAKE_SYSTEM_NAME} MATCHES Linux) - if (NOT DISABLE_AF_PACKET) - if (NOT AF_PACKET_PLUGIN_PATH) - set(AF_PACKET_PLUGIN_PATH ${CMAKE_SOURCE_DIR}/auxil/zeek-af_packet-plugin) - endif () - - list(APPEND ZEEK_INCLUDE_PLUGINS ${AF_PACKET_PLUGIN_PATH}) - set(ZEEK_HAVE_AF_PACKET yes) - endif () -endif () - set(ZEEK_HAVE_JAVASCRIPT no) if (NOT DISABLE_JAVASCRIPT) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/auxil/zeekjs/cmake) @@ -1220,6 +1208,7 @@ if (NOT DISABLE_JAVASCRIPT) endif () endif () +set(ZEEK_HAVE_AF_PACKET no CACHE INTERNAL "Zeek has AF_PACKET support") set(ZEEK_HAVE_JAVASCRIPT ${ZEEK_HAVE_JAVASCRIPT} CACHE INTERNAL "Zeek has JavaScript support") set(DEFAULT_ZEEKPATH_PATHS diff --git a/auxil/zeek-af_packet-plugin b/auxil/zeek-af_packet-plugin deleted file mode 160000 index b89a6f6412..0000000000 --- a/auxil/zeek-af_packet-plugin +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b89a6f64123f778090d1dd6ec48e6b8e8906ea11 diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index c77c96f472..82217a20d8 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -5691,6 +5691,31 @@ export { }; } +module AF_Packet; + +export { + ## Size of the ring-buffer. + const buffer_size = 128 * 1024 * 1024 &redef; + ## Size of an individual block. Needs to be a multiple of page size. + const block_size = 4096 * 8 &redef; + ## Retire timeout for a single block. + const block_timeout = 10msec &redef; + ## Toggle whether to use hardware timestamps. + const enable_hw_timestamping = F &redef; + ## Toggle whether to use PACKET_FANOUT. + const enable_fanout = T &redef; + ## Toggle defragmentation of IP packets using PACKET_FANOUT_FLAG_DEFRAG. + const enable_defrag = F &redef; + ## Fanout mode. + const fanout_mode = FANOUT_HASH &redef; + ## Fanout ID. + const fanout_id = 23 &redef; + ## Link type (default Ethernet). + const link_type = 1 &redef; + ## Checksum validation mode. + const checksum_validation_mode: ChecksumMode = CHECKSUM_ON &redef; +} + module DCE_RPC; export { diff --git a/src/iosource/CMakeLists.txt b/src/iosource/CMakeLists.txt index aef7ca8752..6e320c9c75 100644 --- a/src/iosource/CMakeLists.txt +++ b/src/iosource/CMakeLists.txt @@ -13,3 +13,4 @@ zeek_add_subdir_library( PktSrc.cc) add_subdirectory(pcap) +add_subdirectory(af_packet) diff --git a/src/iosource/af_packet/src/AF_Packet.cc b/src/iosource/af_packet/AF_Packet.cc similarity index 88% rename from src/iosource/af_packet/src/AF_Packet.cc rename to src/iosource/af_packet/AF_Packet.cc index ba8fcddd47..0a53dee8ce 100644 --- a/src/iosource/af_packet/src/AF_Packet.cc +++ b/src/iosource/af_packet/AF_Packet.cc @@ -1,25 +1,15 @@ // See the file "COPYING" in the main distribution directory for copyright. -#include "zeek/zeek-config.h" +#include "zeek/iosource/af_packet/AF_Packet.h" -// Starting with Zeek 6.0, zeek-config.h does not provide the -// ZEEK_VERSION_NUMBER macro anymore when compiling a included -// plugin. Use the new zeek/zeek-version.h header if it exists. -#if __has_include("zeek/zeek-version.h") -#include "zeek/zeek-version.h" -#endif +#include "zeek/iosource/af_packet/RX_Ring.h" +#include "zeek/iosource/af_packet/af_packet.bif.h" -#include "AF_Packet.h" -#include "RX_Ring.h" -#include "af_packet.bif.h" - -// CentOS 7 if_packet.h does not yet have this define, provide it -// explicitly if missing. #ifndef TP_STATUS_CSUM_VALID #define TP_STATUS_CSUM_VALID (1 << 7) #endif -using namespace zeek::iosource::pktsrc; +using namespace zeek::iosource::af_packet; AF_PacketSource::~AF_PacketSource() { Close(); } @@ -165,15 +155,10 @@ bool AF_PacketSource::EnablePromiscMode(const AF_PacketSource::InterfaceInfo& in bool AF_PacketSource::ConfigureFanoutGroup(bool enabled, bool defrag) { if ( enabled ) { - uint32_t fanout_arg, fanout_id; - int ret; + uint32_t fanout_id = zeek::BifConst::AF_Packet::fanout_id; + uint32_t fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode(defrag) << 16)); - fanout_id = zeek::BifConst::AF_Packet::fanout_id; - fanout_arg = ((fanout_id & 0xffff) | (GetFanoutMode(defrag) << 16)); - - ret = setsockopt(socket_fd, SOL_PACKET, PACKET_FANOUT, &fanout_arg, sizeof(fanout_arg)); - - if ( ret < 0 ) + if ( setsockopt(socket_fd, SOL_PACKET, PACKET_FANOUT, &fanout_arg, sizeof(fanout_arg)) < 0 ) return false; } return true; @@ -183,7 +168,6 @@ bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) { if ( enabled ) { struct ifreq ifr; struct hwtstamp_config hwts_cfg; - int ret, opt; memset(&hwts_cfg, 0, sizeof(hwts_cfg)); hwts_cfg.tx_type = HWTSTAMP_TX_OFF; @@ -192,13 +176,11 @@ bool AF_PacketSource::ConfigureHWTimestamping(bool enabled) { snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", props.path.c_str()); ifr.ifr_data = &hwts_cfg; - ret = ioctl(socket_fd, SIOCSHWTSTAMP, &ifr); - if ( ret < 0 ) + if ( ioctl(socket_fd, SIOCSHWTSTAMP, &ifr) < 0 ) return false; - opt = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE; - ret = setsockopt(socket_fd, SOL_PACKET, PACKET_TIMESTAMP, &opt, sizeof(opt)); - if ( ret < 0 ) + int opt = SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE; + if ( setsockopt(socket_fd, SOL_PACKET, PACKET_TIMESTAMP, &opt, sizeof(opt)) < 0 ) return false; } return true; @@ -244,7 +226,7 @@ bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) { if ( ! socket_fd ) return false; - struct tpacket3_hdr* packet = 0; + struct tpacket3_hdr* packet = nullptr; const u_char* data; while ( true ) { if ( ! rx_ring->GetNextPacket(&packet) ) @@ -267,7 +249,6 @@ bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) { if ( packet->tp_status & TP_STATUS_VLAN_VALID ) pkt->vlan = packet->hv1.tp_vlan_tci & 0x0fff; -#if ZEEK_VERSION_NUMBER >= 50100 switch ( checksum_mode ) { case BifEnum::AF_Packet::CHECKSUM_OFF: { // If set to off, just accept whatever checksum in the packet is correct and @@ -292,7 +273,6 @@ bool AF_PacketSource::ExtractNextPacket(zeek::Packet* pkt) { break; } } -#endif if ( current_hdr.len == 0 || current_hdr.caplen == 0 ) { Weird("empty_af_packet_header", pkt); diff --git a/src/iosource/af_packet/src/AF_Packet.h b/src/iosource/af_packet/AF_Packet.h similarity index 94% rename from src/iosource/af_packet/src/AF_Packet.h rename to src/iosource/af_packet/AF_Packet.h index fe6ecb15f7..37fd10a252 100644 --- a/src/iosource/af_packet/src/AF_Packet.h +++ b/src/iosource/af_packet/AF_Packet.h @@ -17,10 +17,9 @@ extern "C" { } #include "zeek/iosource/PktSrc.h" +#include "zeek/iosource/af_packet/RX_Ring.h" -#include "RX_Ring.h" - -namespace af_packet::iosource::pktsrc { +namespace zeek::iosource::af_packet { class AF_PacketSource : public zeek::iosource::PktSrc { public: @@ -80,4 +79,4 @@ private: uint32_t GetFanoutMode(bool defrag); }; -} // namespace zeek::iosource::pktsrc +} // namespace zeek::iosource::af_packet diff --git a/src/iosource/af_packet/CMakeLists.txt b/src/iosource/af_packet/CMakeLists.txt index 3cb19806f6..da9de5498d 100644 --- a/src/iosource/af_packet/CMakeLists.txt +++ b/src/iosource/af_packet/CMakeLists.txt @@ -1,27 +1,5 @@ -cmake_minimum_required(VERSION 3.15 FATAL_ERROR) +if (${CMAKE_SYSTEM_NAME} MATCHES Linux) + set(ZEEK_HAVE_AF_PACKET yes CACHE INTERNAL "") -project(ZeekPluginAF_Packet) - -include(ZeekPlugin) -include(CheckSymbolExists) - -zeek_plugin_begin(Zeek AF_Packet) -zeek_plugin_cc(src/Plugin.cc) -zeek_plugin_cc(src/AF_Packet.cc) -zeek_plugin_cc(src/RX_Ring.cc) -zeek_plugin_bif(src/af_packet.bif) -zeek_plugin_dist_files(zeekctl/af_packet.py README COPYING VERSION) -zeek_plugin_end() - -check_symbol_exists(TP_STATUS_CSUM_VALID linux/if_packet.h HAVE_TP_STATUS_CSUM_VALID) -if (NOT HAVE_TP_STATUS_CSUM_VALID) - message(STATUS "Checksum offloading to the kernel might not be fully supported.") -endif () - -file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1) - -if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") - # Allows building rpm/deb packages via "make package" in build dir. - include(ConfigurePackaging) - ConfigurePackaging(${VERSION}) + zeek_add_plugin(Zeek AF_Packet SOURCES Plugin.cc AF_Packet.cc RX_Ring.cc BIFS af_packet.bif) endif () diff --git a/src/iosource/af_packet/Plugin.cc b/src/iosource/af_packet/Plugin.cc new file mode 100644 index 0000000000..3c5ad7fe16 --- /dev/null +++ b/src/iosource/af_packet/Plugin.cc @@ -0,0 +1,27 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "zeek/plugin/Plugin.h" + +#include "zeek/iosource/Component.h" +#include "zeek/iosource/af_packet/AF_Packet.h" + +namespace zeek::plugin::Zeek_AF_Packet { + +class Plugin : public plugin::Plugin { + plugin::Configuration Configure() override { + AddComponent( + new ::zeek::iosource::PktSrcComponent("AF_PacketReader", "af_packet", + ::zeek::iosource::PktSrcComponent::LIVE, + ::zeek::iosource::af_packet::AF_PacketSource::InstantiateAF_Packet)); + + zeek::plugin::Configuration config; + config.name = "Zeek::AF_Packet"; + config.description = "Packet acquisition via AF_Packet"; + config.version.major = 4; + config.version.minor = 0; + config.version.patch = 0; + return config; + } +} plugin; + +} // namespace zeek::plugin::Zeek_AF_Packet diff --git a/src/iosource/af_packet/src/RX_Ring.cc b/src/iosource/af_packet/RX_Ring.cc similarity index 80% rename from src/iosource/af_packet/src/RX_Ring.cc rename to src/iosource/af_packet/RX_Ring.cc index 99c38912b3..2a1c1e10af 100644 --- a/src/iosource/af_packet/src/RX_Ring.cc +++ b/src/iosource/af_packet/RX_Ring.cc @@ -1,6 +1,6 @@ // See the file "COPYING" in the main distribution directory for copyright. -#include "RX_Ring.h" +#include "zeek/iosource/af_packet/RX_Ring.h" #include #include @@ -12,34 +12,33 @@ extern "C" { #include // sysconf } -RX_Ring::RX_Ring(int sock, size_t bufsize, size_t blocksize, int blocktimeout_msec) { - int ret, ver = TPACKET_VERSION; +using namespace zeek::iosource::af_packet; +RX_Ring::RX_Ring(int sock, size_t bufsize, size_t blocksize, int blocktimeout_msec) { if ( sock < 0 ) throw RX_RingException("invalid socket"); // Configure socket - ret = setsockopt(sock, SOL_PACKET, PACKET_VERSION, &ver, sizeof(ver)); - if ( ret ) + int ver = TPACKET_VERSION; + if ( setsockopt(sock, SOL_PACKET, PACKET_VERSION, &ver, sizeof(ver)) != 0 ) throw RX_RingException("unable to set TPacket version"); InitLayout(bufsize, blocksize, blocktimeout_msec); - ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, (uint8_t*)&layout, sizeof(layout)); - if ( ret ) + if ( setsockopt(sock, SOL_PACKET, PACKET_RX_RING, (uint8_t*)&layout, sizeof(layout)) != 0 ) throw RX_RingException("unable to set ring layout"); // Map memory - size = layout.tp_block_size * layout.tp_block_nr; - ring = (uint8_t*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, sock, 0); + size = static_cast(layout.tp_block_size) * layout.tp_block_nr; + ring = (uint8_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, sock, 0); if ( ring == MAP_FAILED ) throw RX_RingException("unable to map ring memory"); block_num = packet_num = 0; - packet = NULL; + packet = nullptr; // Init block mapping blocks = new tpacket_block_desc*[layout.tp_block_nr]; - for ( unsigned int i = 0; i < layout.tp_block_nr; i++ ) + for ( size_t i = 0; i < layout.tp_block_nr; i++ ) blocks[i] = (struct tpacket_block_desc*)(ring + i * layout.tp_block_size); } @@ -49,7 +48,7 @@ RX_Ring::~RX_Ring() { delete[] blocks; munmap(ring, size); - blocks = 0; + blocks = nullptr; size = 0; } @@ -59,7 +58,7 @@ bool RX_Ring::GetNextPacket(tpacket3_hdr** hdr) { if ( (block_hdr->block_status & TP_STATUS_USER) == 0 ) return false; - if ( packet == NULL ) { + if ( packet == nullptr ) { // New block packet_num = block_hdr->num_pkts; if ( packet_num == 0 ) { @@ -96,5 +95,5 @@ void RX_Ring::NextBlock() { block_hdr->block_status = TP_STATUS_KERNEL; block_num = (block_num + 1) % layout.tp_block_nr; - packet = NULL; + packet = nullptr; } diff --git a/src/iosource/af_packet/src/RX_Ring.h b/src/iosource/af_packet/RX_Ring.h similarity index 85% rename from src/iosource/af_packet/src/RX_Ring.h rename to src/iosource/af_packet/RX_Ring.h index c11e7140ef..6056ec5d40 100644 --- a/src/iosource/af_packet/src/RX_Ring.h +++ b/src/iosource/af_packet/RX_Ring.h @@ -5,14 +5,17 @@ extern "C" { #include // AF_PACKET, etc. } + #include #include -#include #define TPACKET_VERSION TPACKET_V3 +namespace zeek::iosource::af_packet { + class RX_RingException : public std::runtime_error { public: + RX_RingException(const char* what_arg) : std::runtime_error(what_arg) {} RX_RingException(const std::string& what_arg) : std::runtime_error(what_arg) {} }; @@ -42,3 +45,5 @@ private: uint8_t* ring; size_t size; }; + +} // namespace zeek::iosource::af_packet diff --git a/src/iosource/af_packet/af_packet.bif b/src/iosource/af_packet/af_packet.bif new file mode 100644 index 0000000000..5daee0c4c0 --- /dev/null +++ b/src/iosource/af_packet/af_packet.bif @@ -0,0 +1,16 @@ +# See the file "COPYING" in the main distribution directory for copyright. + +# Options for the AF_Packet packet source. + +module AF_Packet; + +const buffer_size: count; +const block_size: count; +const block_timeout: interval; +const enable_hw_timestamping: bool; +const enable_defrag: bool; +const enable_fanout: bool; +const fanout_mode: FanoutMode; +const fanout_id: count; +const link_type: count; +const checksum_validation_mode: ChecksumMode; diff --git a/src/iosource/af_packet/scripts/__load__.zeek b/src/iosource/af_packet/scripts/__load__.zeek deleted file mode 100644 index 588cabc7c4..0000000000 --- a/src/iosource/af_packet/scripts/__load__.zeek +++ /dev/null @@ -1,5 +0,0 @@ -# -# This is loaded unconditionally at Zeek startup. -# - -@load ./init.zeek diff --git a/src/iosource/af_packet/scripts/af_packet/__load__.zeek b/src/iosource/af_packet/scripts/af_packet/__load__.zeek deleted file mode 100644 index 80a869bdc3..0000000000 --- a/src/iosource/af_packet/scripts/af_packet/__load__.zeek +++ /dev/null @@ -1 +0,0 @@ -# This package currently doesn't have any generic script functionality. diff --git a/src/iosource/af_packet/scripts/init.zeek b/src/iosource/af_packet/scripts/init.zeek deleted file mode 100644 index c8d4f8a560..0000000000 --- a/src/iosource/af_packet/scripts/init.zeek +++ /dev/null @@ -1,28 +0,0 @@ -##! Packet source using AF_Packet. -##! -##! Note: This module is in testing and is not yet considered stable! - -module AF_Packet; - -export { - ## Size of the ring-buffer. - const buffer_size = 128 * 1024 * 1024 &redef; - ## Size of an individual block. Needs to be a multiple of page size. - const block_size = 4096 * 8 &redef; - ## Retire timeout for a single block. - const block_timeout = 10msec &redef; - ## Toggle whether to use hardware timestamps. - const enable_hw_timestamping = F &redef; - ## Toggle whether to use PACKET_FANOUT. - const enable_fanout = T &redef; - ## Toggle defragmentation of IP packets using PACKET_FANOUT_FLAG_DEFRAG. - const enable_defrag = F &redef; - ## Fanout mode. - const fanout_mode = FANOUT_HASH &redef; - ## Fanout ID. - const fanout_id = 23 &redef; - ## Link type (default Ethernet). - const link_type = 1 &redef; - ## Checksum validation mode. - const checksum_validation_mode: ChecksumMode = CHECKSUM_ON &redef; -} diff --git a/src/iosource/af_packet/src/Plugin.cc b/src/iosource/af_packet/src/Plugin.cc deleted file mode 100644 index ca8aa96ac3..0000000000 --- a/src/iosource/af_packet/src/Plugin.cc +++ /dev/null @@ -1,27 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#include "Plugin.h" - -#include "zeek/iosource/Component.h" - -#include "AF_Packet.h" - -namespace plugin::Zeek_AF_Packet { -Plugin plugin; -} - -using namespace af_packet::plugin::Zeek_AF_Packet; - -zeek::plugin::Configuration Plugin::Configure() { - AddComponent( - new ::zeek::iosource::PktSrcComponent("AF_PacketReader", "af_packet", ::zeek::iosource::PktSrcComponent::LIVE, - ::zeek::iosource::pktsrc::AF_PacketSource::InstantiateAF_Packet)); - - zeek::plugin::Configuration config; - config.name = "Zeek::AF_Packet"; - config.description = "Packet acquisition via AF_Packet"; - config.version.major = 4; - config.version.minor = 0; - config.version.patch = 0; - return config; -} diff --git a/src/iosource/af_packet/src/Plugin.h b/src/iosource/af_packet/src/Plugin.h deleted file mode 100644 index ad2961a379..0000000000 --- a/src/iosource/af_packet/src/Plugin.h +++ /dev/null @@ -1,17 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#pragma once - -#include - -namespace af_packet::plugin::Zeek_AF_Packet { - -class Plugin : public zeek::plugin::Plugin { -protected: - // Overridden from zeek::plugin::Plugin. - zeek::plugin::Configuration Configure() override; -}; - -extern Plugin plugin; - -} // namespace plugin::Zeek_AF_Packet diff --git a/src/iosource/af_packet/src/af_packet.bif b/src/iosource/af_packet/src/af_packet.bif deleted file mode 100644 index d3f81febce..0000000000 --- a/src/iosource/af_packet/src/af_packet.bif +++ /dev/null @@ -1,35 +0,0 @@ - -# Options for the AF_Packet packet source. - -module AF_Packet; - -## Available fanout modes. -enum FanoutMode %{ - FANOUT_HASH, # PACKET_FANOUT_HASH - FANOUT_CPU, # PACKET_FANOUT_CPU - FANOUT_QM, # PACKET_FANOUT_QM - FANOUT_CBPF, # PACKET_FANOUT_CBPF - FANOUT_EBPF, # PACKET_FANOUT_EBPF -%} - -## Available checksum validation modes. -enum ChecksumMode %{ - ## Ignore checksums, i.e. always assume they are correct. - CHECKSUM_OFF, - ## Let Zeek compute and verify checksums. - CHECKSUM_ON, - ## Let the kernel handle checksum offloading. - ## Note: Semantics may depend on the kernel and driver version. - CHECKSUM_KERNEL, -%} - -const buffer_size: count; -const block_size: count; -const block_timeout: interval; -const enable_hw_timestamping: bool; -const enable_defrag: bool; -const enable_fanout: bool; -const fanout_mode: FanoutMode; -const fanout_id: count; -const link_type: count; -const checksum_validation_mode: ChecksumMode; diff --git a/src/types.bif b/src/types.bif index 9797e3e08c..9c3fa82686 100644 --- a/src/types.bif +++ b/src/types.bif @@ -247,4 +247,26 @@ enum Level %{ ERROR = 2, %} +module AF_Packet; + +## Available fanout modes. +enum FanoutMode %{ + FANOUT_HASH, # PACKET_FANOUT_HASH + FANOUT_CPU, # PACKET_FANOUT_CPU + FANOUT_QM, # PACKET_FANOUT_QM + FANOUT_CBPF, # PACKET_FANOUT_CBPF + FANOUT_EBPF, # PACKET_FANOUT_EBPF +%} + +## Available checksum validation modes. +enum ChecksumMode %{ + ## Ignore checksums, i.e. always assume they are correct. + CHECKSUM_OFF, + ## Let Zeek compute and verify checksums. + CHECKSUM_ON, + ## Let the kernel handle checksum offloading. + ## Note: Semantics may depend on the kernel and driver version. + CHECKSUM_KERNEL, +%} + module GLOBAL; From 95ea468db1166eeb27aa4eab42ac9d0737153911 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 19 Aug 2025 15:53:20 -0700 Subject: [PATCH 342/343] Remove configure --with-gen-zam argument and the CMake summaries --- CMakeLists.txt | 7 +------ configure | 5 ----- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 497c7d188b..56b8ec4b9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -911,9 +911,7 @@ add_executable(Zeek::BifCl ALIAS bifcl) set(BIFCL_EXE_PATH "${CMAKE_BINARY_DIR}/tools/bifcl/bifcl${CMAKE_EXECUTABLE_SUFFIX}") set(_bifcl_exe_path "included") -if (NOT GEN_ZAM_EXE_PATH) - add_subdirectory(tools/gen-zam) -endif () +add_subdirectory(tools/gen-zam) if (ENABLE_JEMALLOC) if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") @@ -1547,11 +1545,8 @@ message("") output_summary_bool("AF_PACKET" ${ZEEK_HAVE_AF_PACKET}) output_summary_bool("Aux. Tools" ${INSTALL_AUX_TOOLS}) -output_summary_line("BifCL" ${_bifcl_exe_path}) -output_summary_line("BinPAC" ${_binpac_exe_path}) output_summary_bool("BTest" ${INSTALL_BTEST}) output_summary_line("BTest tooling" ${_install_btest_tools_msg}) -output_summary_line("Gen-ZAM" ${_gen_zam_exe_path}) output_summary_bool("JavaScript" ${ZEEK_HAVE_JAVASCRIPT}) output_summary_line("Spicy" ${_spicy}) output_summary_bool("Spicy analyzers" ${USE_SPICY_ANALYZERS}) diff --git a/configure b/configure index d407343ad0..751769992b 100755 --- a/configure +++ b/configure @@ -93,8 +93,6 @@ Usage: $0 [OPTION]... [VAR=VALUE]... --with-bison=PATH path to bison executable --with-broker=PATH path to Broker install root (Zeek uses an embedded version by default) - --with-gen-zam=PATH path to Gen-ZAM code generator - (Zeek uses an embedded version by default) --with-flex=PATH path to flex executable --with-libkqueue=PATH path to libkqueue install root (Zeek uses an embedded version by default) @@ -378,9 +376,6 @@ while [ $# -ne 0 ]; do --with-flex=*) append_cache_entry FLEX_EXECUTABLE PATH $optarg ;; - --with-gen-zam=*) - append_cache_entry GEN_ZAM_EXE_PATH PATH $optarg - ;; --with-geoip=*) append_cache_entry LibMMDB_ROOT_DIR PATH $optarg ;; From 469bd8d562c9baededc02ec5ed2d94e0b92ff591 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 19 Aug 2025 15:54:05 -0700 Subject: [PATCH 343/343] Add NEWS entries for submodule moves --- NEWS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS b/NEWS index 7b21393a74..8d656df55c 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,15 @@ Breaking Changes - The ``&optional`` script attribute will now error when applied to anything that's not a record field. Previously, this would have surprising behavior. +- The BinPAC, Bifcl, and Gen-ZAM tools have all moved directly into the Zeek repo, which + should ease maintenance on them a bit. They were moved from the ``auxil`` directory to the + tools directory. Along with this, the ``--gen-zam`` argument for ``configure`` was + removed and the internal version will always be used. + +- The zeek-af_packet-plugin git submodule was moved directly into the Zeek repo. This used + to live in the ``auxil`` directory, after having moved there from an external plugin. + It is now built as part of main Zeek build whenever building on Linux. + New Functionality -----------------