binpac: Reformat C++ code in Spicy style

This commit is contained in:
Tim Wojtulewicz 2023-10-30 13:15:14 -07:00
parent 716bf016a1
commit 3297de477b
89 changed files with 7887 additions and 9733 deletions

View file

@ -1,23 +1,19 @@
#ifndef binpac_an_h #ifndef binpac_an_h
#define binpac_an_h #define binpac_an_h
namespace binpac namespace binpac {
{
// TODO: Add the Done() function // TODO: Add the Done() function
// The interface for a connection analyzer // The interface for a connection analyzer
class ConnectionAnalyzer class ConnectionAnalyzer {
{
public: public:
virtual ~ConnectionAnalyzer() {} virtual ~ConnectionAnalyzer() {}
virtual void NewData(bool is_orig, const unsigned char* begin_of_data, virtual void NewData(bool is_orig, const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0;
const unsigned char* end_of_data) = 0;
}; };
// The interface for a flow analyzer // The interface for a flow analyzer
class FlowAnalyzer class FlowAnalyzer {
{
public: public:
virtual ~FlowAnalyzer() {} virtual ~FlowAnalyzer() {}
virtual void NewData(const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0; virtual void NewData(const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0;

View file

@ -7,16 +7,14 @@
#include "binpac.h" #include "binpac.h"
#include "binpac_buffer.h" #include "binpac_buffer.h"
namespace binpac namespace binpac {
{
extern double network_time(); extern double network_time();
namespace namespace {
{
const unsigned char CR = '\r'; const unsigned char CR = '\r';
const unsigned char LF = '\n'; const unsigned char LF = '\n';
} } // namespace
binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = { binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = {
// max_capacity // max_capacity
@ -27,8 +25,7 @@ binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = {
2 * 1024 * 1024, 2 * 1024 * 1024,
}; };
FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) {
{
buffer_length_ = 0; buffer_length_ = 0;
buffer_ = nullptr; buffer_ = nullptr;
@ -53,29 +50,20 @@ FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style)
NewMessage(); NewMessage();
} }
FlowBuffer::~FlowBuffer() FlowBuffer::~FlowBuffer() {
{
if ( buffer_ ) if ( buffer_ )
free(buffer_); free(buffer_);
} }
void FlowBuffer::NewMessage() void FlowBuffer::NewMessage() {
{
BINPAC_ASSERT(frame_length_ >= 0); BINPAC_ASSERT(frame_length_ >= 0);
int bytes_to_advance = 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 ? 2 : 1)); break;
{ case FRAME_MODE: bytes_to_advance = frame_length_; break;
case LINE_MODE: case UNKNOWN_MODE: break;
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;
} }
} }
@ -87,26 +75,16 @@ void FlowBuffer::NewMessage()
ContractBuffer(); ContractBuffer();
} }
void FlowBuffer::ResetLineState() void FlowBuffer::ResetLineState() {
{ switch ( linebreak_style_ ) {
switch ( linebreak_style_ ) case CR_OR_LF: state_ = CR_OR_LF_0; break;
{ case STRICT_CRLF: state_ = STRICT_CRLF_0; break;
case CR_OR_LF: case LINE_BREAKER: break; // Nothing to reset
state_ = CR_OR_LF_0; default: BINPAC_ASSERT(0); break;
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) void FlowBuffer::ExpandBuffer(int length) {
{
if ( buffer_length_ >= length ) if ( buffer_length_ >= length )
return; return;
@ -116,8 +94,7 @@ void FlowBuffer::ExpandBuffer(int length)
if ( length < buffer_length_ * 2 ) if ( length < buffer_length_ * 2 )
length = buffer_length_ * 2; length = buffer_length_ * 2;
if ( length > policy.max_capacity ) 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()); throw ExceptionFlowBufferAlloc(reason.c_str());
} }
@ -132,8 +109,7 @@ void FlowBuffer::ExpandBuffer(int length)
buffer_ = new_buf; buffer_ = new_buf;
} }
void FlowBuffer::ContractBuffer() void FlowBuffer::ContractBuffer() {
{
if ( buffer_length_ < policy.contract_threshold ) if ( buffer_length_ < policy.contract_threshold )
return; return;
@ -146,20 +122,15 @@ void FlowBuffer::ContractBuffer()
buffer_ = new_buf; buffer_ = new_buf;
} }
void FlowBuffer::SetLineBreaker(unsigned char* lbreaker) void FlowBuffer::SetLineBreaker(unsigned char* lbreaker) {
{
linebreaker_ = *lbreaker; linebreaker_ = *lbreaker;
linebreak_style_default = linebreak_style_; linebreak_style_default = linebreak_style_;
linebreak_style_ = LINE_BREAKER; linebreak_style_ = LINE_BREAKER;
} }
void FlowBuffer::UnsetLineBreaker() void FlowBuffer::UnsetLineBreaker() { linebreak_style_ = linebreak_style_default; }
{
linebreak_style_ = linebreak_style_default;
}
void FlowBuffer::NewLine() void FlowBuffer::NewLine() {
{
FlowBuffer::NewMessage(); FlowBuffer::NewMessage();
mode_ = LINE_MODE; mode_ = LINE_MODE;
frame_length_ = 0; frame_length_ = 0;
@ -170,8 +141,7 @@ void FlowBuffer::NewLine()
MarkOrCopyLine(); MarkOrCopyLine();
} }
void FlowBuffer::NewFrame(int frame_length, bool chunked) void FlowBuffer::NewFrame(int frame_length, bool chunked) {
{
FlowBuffer::NewMessage(); FlowBuffer::NewMessage();
mode_ = FRAME_MODE; mode_ = FRAME_MODE;
frame_length_ = frame_length; frame_length_ = frame_length;
@ -180,21 +150,16 @@ void FlowBuffer::NewFrame(int frame_length, bool chunked)
MarkOrCopyFrame(); MarkOrCopyFrame();
} }
void FlowBuffer::BufferData(const_byteptr data, const_byteptr end) void FlowBuffer::BufferData(const_byteptr data, const_byteptr end) {
{
mode_ = FRAME_MODE; mode_ = FRAME_MODE;
frame_length_ += (end - data); frame_length_ += (end - data);
MarkOrCopyFrame(); MarkOrCopyFrame();
NewData(data, end); NewData(data, end);
} }
void FlowBuffer::FinishBuffer() void FlowBuffer::FinishBuffer() { message_complete_ = true; }
{
message_complete_ = true;
}
void FlowBuffer::GrowFrame(int length) void FlowBuffer::GrowFrame(int length) {
{
BINPAC_ASSERT(frame_length_ >= 0); BINPAC_ASSERT(frame_length_ >= 0);
if ( length <= frame_length_ ) if ( length <= frame_length_ )
return; return;
@ -204,8 +169,7 @@ void FlowBuffer::GrowFrame(int length)
MarkOrCopyFrame(); MarkOrCopyFrame();
} }
void FlowBuffer::DiscardData() void FlowBuffer::DiscardData() {
{
mode_ = UNKNOWN_MODE; mode_ = UNKNOWN_MODE;
message_complete_ = false; message_complete_ = false;
have_pending_request_ = false; have_pending_request_ = false;
@ -216,8 +180,7 @@ void FlowBuffer::DiscardData()
ContractBuffer(); ContractBuffer();
} }
void FlowBuffer::set_eof() void FlowBuffer::set_eof() {
{
// fprintf(stderr, "EOF\n"); // fprintf(stderr, "EOF\n");
eof_ = true; eof_ = true;
if ( chunked_ ) if ( chunked_ )
@ -226,8 +189,7 @@ void FlowBuffer::set_eof()
frame_length_ = 0; frame_length_ = 0;
} }
void FlowBuffer::NewData(const_byteptr begin, const_byteptr end) void FlowBuffer::NewData(const_byteptr begin, const_byteptr end) {
{
BINPAC_ASSERT(begin <= end); BINPAC_ASSERT(begin <= end);
ClearPreviousData(); ClearPreviousData();
@ -241,36 +203,24 @@ void FlowBuffer::NewData(const_byteptr begin, const_byteptr end)
MarkOrCopy(); MarkOrCopy();
} }
void FlowBuffer::MarkOrCopy() void FlowBuffer::MarkOrCopy() {
{ if ( ! message_complete_ ) {
if ( ! message_complete_ ) switch ( mode_ ) {
{ case LINE_MODE: MarkOrCopyLine(); break;
switch ( mode_ )
{
case LINE_MODE:
MarkOrCopyLine();
break;
case FRAME_MODE: case FRAME_MODE: MarkOrCopyFrame(); break;
MarkOrCopyFrame();
break;
default: default: break;
break;
} }
} }
} }
void FlowBuffer::ClearPreviousData() void FlowBuffer::ClearPreviousData() {
{
// All previous data must have been processed or buffered already // All previous data must have been processed or buffered already
if ( orig_data_begin_ < orig_data_end_ ) if ( orig_data_begin_ < orig_data_end_ ) {
{
BINPAC_ASSERT(buffer_n_ == 0); BINPAC_ASSERT(buffer_n_ == 0);
if ( chunked_ ) if ( chunked_ ) {
{ if ( frame_length_ > 0 ) {
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_; orig_data_begin_ = orig_data_end_;
@ -278,12 +228,10 @@ void FlowBuffer::ClearPreviousData()
} }
} }
void FlowBuffer::NewGap(int length) void FlowBuffer::NewGap(int length) {
{
ClearPreviousData(); ClearPreviousData();
if ( chunked_ && frame_length_ >= 0 ) if ( chunked_ && frame_length_ >= 0 ) {
{
frame_length_ -= length; frame_length_ -= length;
if ( frame_length_ < 0 ) if ( frame_length_ < 0 )
frame_length_ = 0; frame_length_ = 0;
@ -293,22 +241,12 @@ void FlowBuffer::NewGap(int length)
MarkOrCopy(); MarkOrCopy();
} }
void FlowBuffer::MarkOrCopyLine() void FlowBuffer::MarkOrCopyLine() {
{ switch ( linebreak_style_ ) {
switch ( linebreak_style_ ) case CR_OR_LF: MarkOrCopyLine_CR_OR_LF(); break;
{ case STRICT_CRLF: MarkOrCopyLine_STRICT_CRLF(); break;
case CR_OR_LF: case LINE_BREAKER: MarkOrCopyLine_LINEBREAK(); break;
MarkOrCopyLine_CR_OR_LF(); default: BINPAC_ASSERT(0); break;
break;
case STRICT_CRLF:
MarkOrCopyLine_STRICT_CRLF();
break;
case LINE_BREAKER:
MarkOrCopyLine_LINEBREAK();
break;
default:
BINPAC_ASSERT(0);
break;
} }
} }
@ -327,25 +265,19 @@ CR_OR_LF_1:
.: CR_OR_LF_0 * .: CR_OR_LF_0 *
*/ */
void FlowBuffer::MarkOrCopyLine_CR_OR_LF() void FlowBuffer::MarkOrCopyLine_CR_OR_LF() {
{
if ( ! (orig_data_begin_ && orig_data_end_) ) if ( ! (orig_data_begin_ && orig_data_end_) )
return; 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; state_ = CR_OR_LF_0;
++orig_data_begin_; ++orig_data_begin_;
} }
const_byteptr data; const_byteptr data;
for ( data = orig_data_begin_; data < orig_data_end_; ++data ) for ( data = orig_data_begin_; data < orig_data_end_; ++data ) {
{ switch ( *data ) {
switch ( *data ) case CR: state_ = CR_OR_LF_1; goto found_end_of_line;
{
case CR:
state_ = CR_OR_LF_1;
goto found_end_of_line;
case LF: case LF:
// state_ = CR_OR_LF_0; // state_ = CR_OR_LF_0;
@ -361,12 +293,10 @@ void FlowBuffer::MarkOrCopyLine_CR_OR_LF()
return; return;
found_end_of_line: found_end_of_line:
if ( buffer_n_ == 0 ) if ( buffer_n_ == 0 ) {
{
frame_length_ = data - orig_data_begin_; frame_length_ = data - orig_data_begin_;
} }
else else {
{
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
// But eliminate the last CR or LF // But eliminate the last CR or LF
--buffer_n_; --buffer_n_;
@ -394,28 +324,20 @@ STRICT_CRLF_1:
.: STRICT_CRLF_0 * .: STRICT_CRLF_0 *
*/ */
void FlowBuffer::MarkOrCopyLine_STRICT_CRLF() void FlowBuffer::MarkOrCopyLine_STRICT_CRLF() {
{
const_byteptr data; const_byteptr data;
for ( data = orig_data_begin_; data < orig_data_end_; ++data ) for ( data = orig_data_begin_; data < orig_data_end_; ++data ) {
{ switch ( *data ) {
switch ( *data ) case CR: state_ = STRICT_CRLF_1; break;
{
case CR:
state_ = STRICT_CRLF_1;
break;
case LF: case LF:
if ( state_ == STRICT_CRLF_1 ) if ( state_ == STRICT_CRLF_1 ) {
{
state_ = STRICT_CRLF_0; state_ = STRICT_CRLF_0;
goto found_end_of_line; goto found_end_of_line;
} }
break; break;
default: default: state_ = STRICT_CRLF_0; break;
state_ = STRICT_CRLF_0;
break;
} }
} }
@ -423,12 +345,10 @@ void FlowBuffer::MarkOrCopyLine_STRICT_CRLF()
return; return;
found_end_of_line: found_end_of_line:
if ( buffer_n_ == 0 ) if ( buffer_n_ == 0 ) {
{
frame_length_ = data - 1 - orig_data_begin_; frame_length_ = data - 1 - orig_data_begin_;
} }
else else {
{
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
// Pop the preceding CR and LF from the buffer // Pop the preceding CR and LF from the buffer
buffer_n_ -= 2; buffer_n_ -= 2;
@ -442,14 +362,12 @@ found_end_of_line:
#endif #endif
} }
void FlowBuffer::MarkOrCopyLine_LINEBREAK() void FlowBuffer::MarkOrCopyLine_LINEBREAK() {
{
if ( ! (orig_data_begin_ && orig_data_end_) ) if ( ! (orig_data_begin_ && orig_data_end_) )
return; return;
const_byteptr data; const_byteptr data;
for ( data = orig_data_begin_; data < orig_data_end_; ++data ) for ( data = orig_data_begin_; data < orig_data_end_; ++data ) {
{
if ( *data == linebreaker_ ) if ( *data == linebreaker_ )
goto found_end_of_line; goto found_end_of_line;
} }
@ -458,14 +376,12 @@ void FlowBuffer::MarkOrCopyLine_LINEBREAK()
return; return;
found_end_of_line: found_end_of_line:
if ( buffer_n_ == 0 ) if ( buffer_n_ == 0 ) {
{
frame_length_ = data - orig_data_begin_; frame_length_ = data - orig_data_begin_;
} }
else else {
{
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_); AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
// But eliminate the last CR or LF // But eliminate the last 'linebreaker' character
--buffer_n_; --buffer_n_;
} }
message_complete_ = true; message_complete_ = true;
@ -484,42 +400,33 @@ found_end_of_line:
// When buffer_n_ > 0: // When buffer_n_ > 0:
// Frame = [0..buffer_n_][orig_data_begin_..] // Frame = [0..buffer_n_][orig_data_begin_..]
void FlowBuffer::MarkOrCopyFrame() 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 // Skip the lingering LF
if ( *orig_data_begin_ == LF ) if ( *orig_data_begin_ == LF ) {
{
++orig_data_begin_; ++orig_data_begin_;
} }
state_ = FRAME_0; state_ = FRAME_0;
} }
if ( buffer_n_ == 0 ) if ( buffer_n_ == 0 ) {
{
// If there is enough data // 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 // Do nothing except setting the message complete flag
message_complete_ = true; message_complete_ = true;
} }
else else {
{ if ( ! chunked_ ) {
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; message_complete_ = false;
} }
} }
else else {
{
BINPAC_ASSERT(! chunked_); BINPAC_ASSERT(! chunked_);
int bytes_to_copy = orig_data_end_ - orig_data_begin_; int bytes_to_copy = orig_data_end_ - orig_data_begin_;
message_complete_ = false; 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_; bytes_to_copy = frame_length_ - buffer_n_;
message_complete_ = true; message_complete_ = true;
} }
@ -527,16 +434,14 @@ void FlowBuffer::MarkOrCopyFrame()
} }
#if DEBUG_FLOW_BUFFER #if DEBUG_FLOW_BUFFER
if ( message_complete_ ) if ( message_complete_ ) {
{
fprintf(stderr, "%.6f frame complete: [%s]\n", network_time(), fprintf(stderr, "%.6f frame complete: [%s]\n", network_time(),
string((const char*)begin(), (const char*)end()).c_str()); string((const char*)begin(), (const char*)end()).c_str());
} }
#endif #endif
} }
void FlowBuffer::AppendToBuffer(const_byteptr data, int len) void FlowBuffer::AppendToBuffer(const_byteptr data, int len) {
{
if ( len <= 0 ) if ( len <= 0 )
return; return;

View file

@ -5,21 +5,17 @@
#include "binpac.h" #include "binpac.h"
namespace binpac namespace binpac {
{
class FlowBuffer class FlowBuffer {
{
public: public:
struct Policy struct Policy {
{
int max_capacity; int max_capacity;
int min_capacity; int min_capacity;
int contract_threshold; int contract_threshold;
}; };
enum LineBreakStyle enum LineBreakStyle {
{
CR_OR_LF, // CR or LF or CRLF CR_OR_LF, // CR or LF or CRLF
STRICT_CRLF, // CR followed by LF STRICT_CRLF, // CR followed by LF
CR_LF_NUL, // CR or LF or CR-LF or CR-NUL CR_LF_NUL, // CR or LF or CR-LF or CR-NUL
@ -46,17 +42,14 @@ public:
// Whether there is enough data for the frame // 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 inline const_byteptr begin() const {
{
BINPAC_ASSERT(ready()); BINPAC_ASSERT(ready());
return (buffer_n_ == 0) ? orig_data_begin_ : buffer_; return (buffer_n_ == 0) ? orig_data_begin_ : buffer_;
} }
inline const_byteptr end() const inline const_byteptr end() const {
{
BINPAC_ASSERT(ready()); BINPAC_ASSERT(ready());
if ( buffer_n_ == 0 ) if ( buffer_n_ == 0 ) {
{
BINPAC_ASSERT(frame_length_ >= 0); BINPAC_ASSERT(frame_length_ >= 0);
const_byteptr end = orig_data_begin_ + frame_length_; const_byteptr end = orig_data_begin_ + frame_length_;
BINPAC_ASSERT(end <= orig_data_end_); BINPAC_ASSERT(end <= orig_data_end_);
@ -66,8 +59,7 @@ public:
return buffer_ + buffer_n_; return buffer_ + buffer_n_;
} }
inline int data_length() const inline int data_length() const {
{
if ( buffer_n_ > 0 ) if ( buffer_n_ > 0 )
return buffer_n_; return buffer_n_;
@ -77,10 +69,7 @@ public:
return frame_length_; return frame_length_;
} }
inline bool data_available() const inline bool data_available() const { return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; }
{
return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_;
}
void SetLineBreaker(unsigned char* lbreaker); void SetLineBreaker(unsigned char* lbreaker);
void UnsetLineBreaker(); void UnsetLineBreaker();
@ -89,10 +78,8 @@ public:
void NewFrame(int frame_length, bool chunked_); void NewFrame(int frame_length, bool chunked_);
void GrowFrame(int new_frame_length); void GrowFrame(int new_frame_length);
int data_seq() const 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 ) if ( buffer_n_ > 0 )
return data_seq_at_orig_data_begin; return data_seq_at_orig_data_begin;
else else
@ -153,15 +140,13 @@ protected:
LineBreakStyle linebreak_style_default; LineBreakStyle linebreak_style_default;
unsigned char linebreaker_; unsigned char linebreaker_;
enum enum {
{
UNKNOWN_MODE, UNKNOWN_MODE,
LINE_MODE, LINE_MODE,
FRAME_MODE, FRAME_MODE,
} mode_; } mode_;
enum enum {
{
CR_OR_LF_0, CR_OR_LF_0,
CR_OR_LF_1, CR_OR_LF_1,
STRICT_CRLF_0, STRICT_CRLF_0,

View file

@ -4,22 +4,12 @@
#include <stdlib.h> #include <stdlib.h>
namespace binpac namespace binpac {
{
std::string std_string(bytestring const* s) std::string std_string(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());
}
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

View file

@ -6,13 +6,13 @@
#include "binpac.h" #include "binpac.h"
namespace binpac namespace binpac {
{
template <class T> class datastring; template<class T>
class datastring;
template <class T> class const_datastring template<class T>
{ class const_datastring {
public: public:
const_datastring() : begin_(0), end_(0) {} const_datastring() : begin_(0), end_(0) {}
@ -22,8 +22,7 @@ public:
const_datastring(datastring<T> const& s) : begin_(s.begin()), end_(s.end()) {} const_datastring(datastring<T> const& s) : begin_(s.begin()), end_(s.end()) {}
void init(const T* data, int length) void init(const T* data, int length) {
{
begin_ = data; begin_ = data;
end_ = data + length; end_ = data + length;
} }
@ -34,8 +33,7 @@ public:
T const& operator[](int index) const { return begin()[index]; } T const& operator[](int index) const { return begin()[index]; }
bool operator==(const_datastring<T> const& s) bool operator==(const_datastring<T> const& s) {
{
if ( length() != s.length() ) if ( length() != s.length() )
return false; 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;
@ -51,8 +49,8 @@ private:
typedef const_datastring<uint8> const_bytestring; typedef const_datastring<uint8> const_bytestring;
template <class T> class datastring template<class T>
{ class datastring {
public: public:
datastring() { clear(); } datastring() { clear(); }
@ -64,27 +62,23 @@ public:
explicit datastring(const_datastring<T> const& x) { set_const(x.begin(), x.length()); } explicit datastring(const_datastring<T> const& x) { set_const(x.begin(), x.length()); }
datastring const& operator=(datastring<T> const& x) datastring const& operator=(datastring<T> const& x) {
{
BINPAC_ASSERT(! data_); BINPAC_ASSERT(! data_);
set(x.data(), x.length()); set(x.data(), x.length());
return *this; 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); set_const(begin, length);
} }
void clear() void clear() {
{
data_ = 0; data_ = 0;
length_ = 0; length_ = 0;
} }
void free() void free() {
{
if ( data_ ) if ( data_ )
delete[] data_; delete[] data_;
clear(); clear();
@ -92,8 +86,7 @@ public:
void clone() { set_const(begin(), length()); } void clone() { set_const(begin(), length()); }
datastring const& operator=(const_datastring<T> const& x) datastring const& operator=(const_datastring<T> const& x) {
{
BINPAC_ASSERT(! data_); BINPAC_ASSERT(! data_);
set_const(x.begin(), x.length()); set_const(x.begin(), x.length());
return *this; return *this;
@ -108,14 +101,12 @@ public:
T const* end() const { return data_ + length_; } T const* end() const { return data_ + length_; }
private: private:
void set(T* data, int len) void set(T* data, int len) {
{
data_ = data; data_ = data;
length_ = len; length_ = len;
} }
void set_const(T const* data, int len) void set_const(T const* data, int len) {
{
length_ = len; length_ = len;
data_ = new T[len + 1]; data_ = new T[len + 1];
memcpy(data_, data, sizeof(T) * len); memcpy(data_, data, sizeof(T) * len);
@ -128,29 +119,20 @@ private:
typedef datastring<uint8> bytestring; typedef datastring<uint8> 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; }
{
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(); *pbegin = s.begin();
*pend = s.end(); *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(); *pbegin = s->begin();
*pend = s->end(); *pend = s->end();
} }

View file

@ -4,14 +4,11 @@
#include <inttypes.h> #include <inttypes.h>
#include <stdint.h> #include <stdint.h>
namespace binpac namespace binpac {
{
class Exception class Exception {
{
public: public:
Exception(const char* m = 0) : msg_("binpac exception: ") Exception(const char* m = 0) : msg_("binpac exception: ") {
{
if ( m ) if ( m )
append(m); append(m);
// abort(); // abort();
@ -25,30 +22,22 @@ protected:
string msg_; string msg_;
}; };
class ExceptionEnforceViolation : public Exception class ExceptionEnforceViolation : public Exception {
{
public: public:
ExceptionEnforceViolation(const char* where) ExceptionEnforceViolation(const char* where) { append(binpac_fmt("&enforce violation : %s", where)); }
{
append(binpac_fmt("&enforce violation : %s", where));
}
}; };
class ExceptionOutOfBound : public Exception class ExceptionOutOfBound : public Exception {
{
public: public:
ExceptionOutOfBound(const char* where, int len_needed, int 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)); append(binpac_fmt("out_of_bound: %s: %d > %d", where, len_needed, len_given));
} }
}; };
class ExceptionInvalidCase : public Exception class ExceptionInvalidCase : public Exception {
{
public: public:
ExceptionInvalidCase(const char* location, int64_t index, const char* expected) ExceptionInvalidCase(const char* location, int64_t index, const char* expected)
: location_(location), index_(index), expected_(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));
} }
@ -58,12 +47,9 @@ protected:
string expected_; string expected_;
}; };
class ExceptionInvalidCaseIndex : public Exception class ExceptionInvalidCaseIndex : public Exception {
{
public: public:
ExceptionInvalidCaseIndex(const char* location, int64_t index) ExceptionInvalidCaseIndex(const char* location, int64_t index) : location_(location), index_(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));
} }
@ -72,14 +58,11 @@ protected:
int64_t index_; int64_t index_;
}; };
class ExceptionInvalidOffset : public Exception class ExceptionInvalidOffset : public Exception {
{
public: public:
ExceptionInvalidOffset(const char* location, int min_offset, int offset) ExceptionInvalidOffset(const char* location, int min_offset, int offset)
: location_(location), min_offset_(min_offset), offset_(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: protected:
@ -87,34 +70,26 @@ protected:
int min_offset_, offset_; int min_offset_, offset_;
}; };
class ExceptionStringMismatch : public Exception class ExceptionStringMismatch : public Exception {
{
public: 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,
append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"", actual_data));
location, expected, actual_data));
} }
}; };
class ExceptionInvalidStringLength : public Exception class ExceptionInvalidStringLength : public Exception {
{
public: public:
ExceptionInvalidStringLength(const char* location, int len) 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 class ExceptionFlowBufferAlloc : public Exception {
{
public: public:
ExceptionFlowBufferAlloc(const char* reason) ExceptionFlowBufferAlloc(const char* reason) { append(binpac_fmt("flowbuffer allocation failed: %s", reason)); }
{
append(binpac_fmt("flowbuffer allocation failed: %s", reason));
}
}; };
} } // namespace binpac
#endif // binpac_exception_h #endif // binpac_exception_h

View file

@ -1,10 +1,11 @@
#include <vector> #include <vector>
namespace zeek { class RE_Matcher; } namespace zeek {
class RE_Matcher;
}
namespace binpac namespace binpac {
{
std::vector<zeek::RE_Matcher*>* uncompiled_re_matchers = nullptr; std::vector<zeek::RE_Matcher*>* uncompiled_re_matchers = nullptr;

View file

@ -5,13 +5,11 @@
#include "binpac.h" #include "binpac.h"
namespace zeek namespace zeek {
{
class RE_Matcher; class RE_Matcher;
} }
namespace binpac namespace binpac {
{
// Must be called before any binpac functionality is used. // Must be called before any binpac functionality is used.
// //
@ -23,11 +21,9 @@ inline void init(FlowBuffer::Policy* fbp = 0);
// Internal vector recording not yet compiled matchers. // Internal vector recording not yet compiled matchers.
extern std::vector<zeek::RE_Matcher*>* uncompiled_re_matchers; extern std::vector<zeek::RE_Matcher*>* uncompiled_re_matchers;
class RegExMatcher class RegExMatcher {
{
public: public:
RegExMatcher(const char* pattern) : pattern_(pattern) RegExMatcher(const char* pattern) : pattern_(pattern) {
{
if ( ! uncompiled_re_matchers ) if ( ! uncompiled_re_matchers )
uncompiled_re_matchers = new std::vector<zeek::RE_Matcher*>; uncompiled_re_matchers = new std::vector<zeek::RE_Matcher*>;
@ -50,15 +46,12 @@ private:
zeek::RE_Matcher* re_matcher_; zeek::RE_Matcher* re_matcher_;
}; };
inline void RegExMatcher::init() inline void RegExMatcher::init() {
{
if ( ! uncompiled_re_matchers ) if ( ! uncompiled_re_matchers )
return; return;
for ( size_t i = 0; i < uncompiled_re_matchers->size(); ++i ) for ( size_t i = 0; i < uncompiled_re_matchers->size(); ++i ) {
{ if ( ! (*uncompiled_re_matchers)[i]->Compile() ) {
if ( ! (*uncompiled_re_matchers)[i]->Compile() )
{
fprintf(stderr, "binpac: cannot compile regular expression\n"); fprintf(stderr, "binpac: cannot compile regular expression\n");
exit(1); exit(1);
} }
@ -67,8 +60,7 @@ inline void RegExMatcher::init()
uncompiled_re_matchers->clear(); uncompiled_re_matchers->clear();
} }
inline void init(FlowBuffer::Policy* fbp) inline void init(FlowBuffer::Policy* fbp) {
{
RegExMatcher::init(); RegExMatcher::init();
if ( fbp ) if ( fbp )

View file

@ -9,38 +9,28 @@
#include "pac_utils.h" #include "pac_utils.h"
AnalyzerAction::AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code) AnalyzerAction::AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code)
: AnalyzerElement(ACTION), action_id_(action_id), when_(when), param_(param), code_(code), : AnalyzerElement(ACTION), action_id_(action_id), when_(when), param_(param), code_(code), analyzer_(nullptr) {}
analyzer_(nullptr)
{
}
AnalyzerAction::~AnalyzerAction() AnalyzerAction::~AnalyzerAction() {
{
delete action_id_; delete action_id_;
delete param_; delete param_;
delete code_; delete code_;
} }
string AnalyzerAction::action_function() const string AnalyzerAction::action_function() const { return strfmt("Action_%s", action_id_->Name()); }
{
return strfmt("Action_%s", action_id_->Name());
}
void AnalyzerAction::InstallHook(AnalyzerDecl* analyzer) void AnalyzerAction::InstallHook(AnalyzerDecl* analyzer) {
{
ASSERT(0); ASSERT(0);
analyzer_ = analyzer; analyzer_ = analyzer;
// param_->MainDataType()->InstallAction(this); // 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); 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()); action_func_env.SetEvaluated(param_->id());
string action_func_proto = strfmt("%s(%s)", action_function().c_str(), string action_func_proto = strfmt("%s(%s)", action_function().c_str(), ParamDecls(&action_func_env).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());
@ -56,46 +46,35 @@ void AnalyzerAction::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl)
out_cc->println(""); out_cc->println("");
} }
string AnalyzerAction::ParamDecls(Env* env) const string AnalyzerAction::ParamDecls(Env* env) const { return param_->DeclStr(env); }
{
return param_->DeclStr(env);
}
Type* ActionParam::MainDataType() const Type* ActionParam::MainDataType() const {
{
// Note: this is not equal to DataType() // 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 ) if ( ! main_type ) {
{
throw Exception(type()->type_id(), "type not defined"); throw Exception(type()->type_id(), "type not defined");
} }
return main_type; return main_type;
} }
Type* ActionParam::DataType() const Type* ActionParam::DataType() const {
{
Type* main_type = MainDataType(); Type* main_type = MainDataType();
if ( ! type()->field_id() ) if ( ! type()->field_id() ) {
{
return main_type; return main_type;
} }
else else {
{
Type* member_type = main_type->MemberDataType(type()->field_id()); Type* member_type = main_type->MemberDataType(type()->field_id());
if ( ! member_type ) if ( ! member_type ) {
{ throw Exception(type()->field_id(), strfmt("cannot find member type for `%s.%s'", type()->type_id()->Name(),
throw Exception(type()->field_id(),
strfmt("cannot find member type for `%s.%s'", type()->type_id()->Name(),
type()->field_id()->Name())); type()->field_id()->Name()));
} }
return member_type; 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()));
} }

View file

@ -6,14 +6,9 @@
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_common.h" #include "pac_common.h"
class AnalyzerAction : public AnalyzerElement class AnalyzerAction : public AnalyzerElement {
{
public: public:
enum When enum When { BEFORE, AFTER };
{
BEFORE,
AFTER
};
AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code); AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code);
@ -41,8 +36,7 @@ private:
AnalyzerDecl* analyzer_; AnalyzerDecl* analyzer_;
}; };
class ActionParam class ActionParam {
{
public: public:
ActionParam(const ID* id, ActionParamType* type) : id_(id), type_(type) {} ActionParam(const ID* id, ActionParamType* type) : id_(id), type_(type) {}
@ -58,13 +52,9 @@ private:
ActionParamType* type_; ActionParamType* type_;
}; };
class ActionParamType class ActionParamType {
{
public: public:
ActionParamType(const ID* type_id, const ID* field_id = 0) ActionParamType(const ID* type_id, const ID* field_id = 0) : type_id_(type_id), field_id_(field_id) {}
: type_id_(type_id), field_id_(field_id)
{
}
const ID* type_id() const { return type_id_; } const ID* type_id() const { return type_id_; }
const ID* field_id() const { return field_id_; } const ID* field_id() const { return field_id_; }

View file

@ -14,9 +14,7 @@
#include "pac_type.h" #include "pac_type.h"
#include "pac_varfield.h" #include "pac_varfield.h"
AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params) AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params) : TypeDecl(id, params, new DummyType()) {
: TypeDecl(id, params, new DummyType())
{
decl_type_ = decl_type; decl_type_ = decl_type;
statevars_ = new StateVarList(); statevars_ = new StateVarList();
@ -33,8 +31,7 @@ AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params)
env_ = nullptr; env_ = nullptr;
} }
AnalyzerDecl::~AnalyzerDecl() AnalyzerDecl::~AnalyzerDecl() {
{
delete_list(StateVarList, statevars_); delete_list(StateVarList, statevars_);
delete_list(AnalyzerActionList, actions_); delete_list(AnalyzerActionList, actions_);
delete_list(AnalyzerHelperList, helpers_); delete_list(AnalyzerHelperList, helpers_);
@ -45,130 +42,92 @@ AnalyzerDecl::~AnalyzerDecl()
delete_list(AnalyzerHelperList, eof_helpers_); delete_list(AnalyzerHelperList, eof_helpers_);
} }
void AnalyzerDecl::AddElements(AnalyzerElementList* elemlist) void AnalyzerDecl::AddElements(AnalyzerElementList* elemlist) {
{
ASSERT(! env_); ASSERT(! env_);
foreach (i, AnalyzerElementList, elemlist) foreach (i, AnalyzerElementList, elemlist) {
{
AnalyzerElement* elem = *i; AnalyzerElement* elem = *i;
switch ( elem->type() ) switch ( elem->type() ) {
{ case AnalyzerElement::STATE: {
case AnalyzerElement::STATE:
{
ASSERT(0); ASSERT(0);
AnalyzerState* state_elem = (AnalyzerState*)elem; AnalyzerState* state_elem = (AnalyzerState*)elem;
statevars_->insert(statevars_->end(), state_elem->statevars()->begin(), statevars_->insert(statevars_->end(), state_elem->statevars()->begin(), state_elem->statevars()->end());
state_elem->statevars()->end()); } break;
} case AnalyzerElement::ACTION: {
break;
case AnalyzerElement::ACTION:
{
ASSERT(0); ASSERT(0);
AnalyzerAction* action_elem = (AnalyzerAction*)elem; AnalyzerAction* action_elem = (AnalyzerAction*)elem;
actions_->push_back(action_elem); actions_->push_back(action_elem);
} } break;
break; case AnalyzerElement::HELPER: {
case AnalyzerElement::HELPER:
{
AnalyzerHelper* helper_elem = (AnalyzerHelper*)elem; AnalyzerHelper* helper_elem = (AnalyzerHelper*)elem;
switch ( helper_elem->helper_type() ) switch ( helper_elem->helper_type() ) {
{ case AnalyzerHelper::INIT_CODE: constructor_helpers_->push_back(helper_elem); break;
case AnalyzerHelper::INIT_CODE: case AnalyzerHelper::CLEANUP_CODE: destructor_helpers_->push_back(helper_elem); break;
constructor_helpers_->push_back(helper_elem); case AnalyzerHelper::EOF_CODE: eof_helpers_->push_back(helper_elem); break;
break; default: helpers_->push_back(helper_elem);
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;
break; case AnalyzerElement::FUNCTION: {
case AnalyzerElement::FUNCTION:
{
AnalyzerFunction* func_elem = (AnalyzerFunction*)elem; AnalyzerFunction* func_elem = (AnalyzerFunction*)elem;
Function* func = func_elem->function(); Function* func = func_elem->function();
func->set_analyzer_decl(this); func->set_analyzer_decl(this);
functions_->push_back(func); functions_->push_back(func);
} } break;
break; case AnalyzerElement::FLOW: {
case AnalyzerElement::FLOW:
{
AnalyzerFlow* flow_elem = (AnalyzerFlow*)elem; AnalyzerFlow* flow_elem = (AnalyzerFlow*)elem;
ProcessFlowElement(flow_elem); ProcessFlowElement(flow_elem);
} } break;
break; case AnalyzerElement::DATAUNIT: {
case AnalyzerElement::DATAUNIT:
{
AnalyzerDataUnit* dataunit_elem = (AnalyzerDataUnit*)elem; AnalyzerDataUnit* dataunit_elem = (AnalyzerDataUnit*)elem;
ProcessDataUnitElement(dataunit_elem); ProcessDataUnitElement(dataunit_elem);
} } break;
break;
} }
} }
} }
string AnalyzerDecl::class_name() const string AnalyzerDecl::class_name() const { return id_->Name(); }
{
return id_->Name();
}
void AnalyzerDecl::Prepare() void AnalyzerDecl::Prepare() {
{
TypeDecl::Prepare(); TypeDecl::Prepare();
ASSERT(statevars_->empty()); ASSERT(statevars_->empty());
ASSERT(actions_->empty()); ASSERT(actions_->empty());
foreach (i, FunctionList, functions_) foreach (i, FunctionList, functions_) {
{
Function* function = *i; Function* function = *i;
function->Prepare(env_); 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()); 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); action->InstallHook(this);
} }
} }
void AnalyzerDecl::GenForwardDeclaration(Output* out_h) void AnalyzerDecl::GenForwardDeclaration(Output* out_h) {
{
out_h->println("class %s;", class_name().c_str()); 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); 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); (*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); (*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); TypeDecl::GenPubDecls(out_h, out_cc);
GenProcessFunc(out_h, out_cc); GenProcessFunc(out_h, out_cc);
@ -176,8 +135,7 @@ void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc)
GenEOFFunc(out_h, out_cc); GenEOFFunc(out_h, out_cc);
out_h->println(""); out_h->println("");
if ( ! functions_->empty() ) if ( ! functions_->empty() ) {
{
out_h->println("// Functions"); out_h->println("// Functions");
GenFunctions(out_h, out_cc); GenFunctions(out_h, out_cc);
out_h->println(""); out_h->println("");
@ -186,12 +144,10 @@ void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc)
// TODO: export public state variables // 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); TypeDecl::GenPrivDecls(out_h, out_cc);
if ( ! helpers_->empty() ) if ( ! helpers_->empty() ) {
{
out_h->println(""); out_h->println("");
out_h->println("// Additional members"); out_h->println("// Additional members");
GenHelpers(out_h, out_cc); GenHelpers(out_h, out_cc);
@ -200,112 +156,82 @@ void AnalyzerDecl::GenPrivDecls(Output* out_h, Output* out_cc)
// TODO: declare state variables // TODO: declare state variables
} }
void AnalyzerDecl::GenInitCode(Output* out_cc) void AnalyzerDecl::GenInitCode(Output* out_cc) {
{
TypeDecl::GenInitCode(out_cc); TypeDecl::GenInitCode(out_cc);
foreach (i, AnalyzerHelperList, constructor_helpers_) foreach (i, AnalyzerHelperList, constructor_helpers_) {
{
(*i)->GenCode(nullptr, out_cc, this); (*i)->GenCode(nullptr, out_cc, this);
} }
} }
void AnalyzerDecl::GenCleanUpCode(Output* out_cc) void AnalyzerDecl::GenCleanUpCode(Output* out_cc) {
{
TypeDecl::GenCleanUpCode(out_cc); TypeDecl::GenCleanUpCode(out_cc);
foreach (i, AnalyzerHelperList, destructor_helpers_) foreach (i, AnalyzerHelperList, destructor_helpers_) {
{
(*i)->GenCode(nullptr, out_cc, this); (*i)->GenCode(nullptr, 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_); 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_); 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_); 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_); 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); function->GenCode(out_h, out_cc);
} }
} }
AnalyzerState::~AnalyzerState() AnalyzerState::~AnalyzerState() {
{
// Note: do not delete elements of statevars_, because they // Note: do not delete elements of statevars_, because they
// are referenced by the AnalyzerDecl. // are referenced by the AnalyzerDecl.
delete statevars_; delete statevars_;
} }
AnalyzerHelper::~AnalyzerHelper() AnalyzerHelper::~AnalyzerHelper() { delete code_; }
{
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 = nullptr; Output* out = nullptr;
switch ( helper_type_ ) switch ( helper_type_ ) {
{ case MEMBER_DECLS: out = out_h; break;
case MEMBER_DECLS:
out = out_h;
break;
case INIT_CODE: case INIT_CODE:
case CLEANUP_CODE: case CLEANUP_CODE:
case EOF_CODE: case EOF_CODE: out = out_cc; break;
out = out_cc;
break;
} }
ASSERT(out); ASSERT(out);
code()->GenCode(out, decl->env()); code()->GenCode(out, decl->env());
} }
FlowField::FlowField(ID* flow_id, ParameterizedType* 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) : 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); }
{
type_->GenPreParsing(out_cc, env);
}
AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params) AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params)
: AnalyzerElement(FLOW), dir_(dir), type_id_(type_id) : AnalyzerElement(FLOW), dir_(dir), type_id_(type_id) {
{
if ( ! params ) if ( ! params )
params = new ExprList(); params = new ExprList();
@ -321,21 +247,15 @@ AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params)
flow_decl_ = nullptr; flow_decl_ = nullptr;
} }
AnalyzerFlow::~AnalyzerFlow() AnalyzerFlow::~AnalyzerFlow() { delete flow_field_; }
{
delete flow_field_;
}
FlowDecl* AnalyzerFlow::flow_decl() FlowDecl* AnalyzerFlow::flow_decl() {
{
DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name()); DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name());
if ( ! flow_decl_ ) if ( ! flow_decl_ ) {
{
Decl* decl = Decl::LookUpDecl(type_id_); Decl* decl = Decl::LookUpDecl(type_id_);
if ( decl && decl->decl_type() == Decl::FLOW ) if ( decl && decl->decl_type() == Decl::FLOW )
flow_decl_ = static_cast<FlowDecl*>(decl); flow_decl_ = static_cast<FlowDecl*>(decl);
if ( ! flow_decl_ ) if ( ! flow_decl_ ) {
{
throw Exception(this, "cannot find the flow declaration"); throw Exception(this, "cannot find the flow declaration");
} }
} }

View file

@ -17,8 +17,7 @@ class FlowDecl;
typedef vector<AnalyzerHelper*> AnalyzerHelperList; typedef vector<AnalyzerHelper*> AnalyzerHelperList;
typedef vector<Function*> FunctionList; typedef vector<Function*> FunctionList;
class AnalyzerDecl : public TypeDecl class AnalyzerDecl : public TypeDecl {
{
public: public:
AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params); AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params);
~AnalyzerDecl() override; ~AnalyzerDecl() override;
@ -81,18 +80,9 @@ protected:
AnalyzerHelperList* eof_helpers_; AnalyzerHelperList* eof_helpers_;
}; };
class AnalyzerElement : public Object class AnalyzerElement : public Object {
{
public: public:
enum ElementType enum ElementType { STATE, ACTION, FUNCTION, HELPER, FLOW, DATAUNIT };
{
STATE,
ACTION,
FUNCTION,
HELPER,
FLOW,
DATAUNIT
};
AnalyzerElement(ElementType type) : type_(type) {} AnalyzerElement(ElementType type) : type_(type) {}
virtual ~AnalyzerElement() {} virtual ~AnalyzerElement() {}
@ -103,8 +93,7 @@ private:
}; };
// A collection of variables representing analyzer states. // A collection of variables representing analyzer states.
class AnalyzerState : public AnalyzerElement class AnalyzerState : public AnalyzerElement {
{
public: public:
AnalyzerState(StateVarList* statevars) : AnalyzerElement(STATE), statevars_(statevars) {} AnalyzerState(StateVarList* statevars) : AnalyzerElement(STATE), statevars_(statevars) {}
~AnalyzerState() override; ~AnalyzerState() override;
@ -116,20 +105,16 @@ private:
}; };
// A collection of embedded C++ code // A collection of embedded C++ code
class AnalyzerHelper : public AnalyzerElement class AnalyzerHelper : public AnalyzerElement {
{
public: public:
enum Type enum Type {
{
MEMBER_DECLS, MEMBER_DECLS,
INIT_CODE, INIT_CODE,
CLEANUP_CODE, CLEANUP_CODE,
EOF_CODE, EOF_CODE,
}; };
AnalyzerHelper(Type helper_type, EmbeddedCode* code) AnalyzerHelper(Type helper_type, EmbeddedCode* code)
: AnalyzerElement(HELPER), helper_type_(helper_type), code_(code) : AnalyzerElement(HELPER), helper_type_(helper_type), code_(code) {}
{
}
~AnalyzerHelper() override; ~AnalyzerHelper() override;
Type helper_type() const { return helper_type_; } Type helper_type() const { return helper_type_; }
@ -145,21 +130,15 @@ private:
// The type and parameters of (uni-directional) flows of a connection. // The type and parameters of (uni-directional) flows of a connection.
class FlowField : public Field class FlowField : public Field {
{
public: public:
FlowField(ID* flow_id, ParameterizedType* flow_type); FlowField(ID* flow_id, ParameterizedType* flow_type);
void GenInitCode(Output* out, Env* env) override; void GenInitCode(Output* out, Env* env) override;
}; };
class AnalyzerFlow : public AnalyzerElement class AnalyzerFlow : public AnalyzerElement {
{
public: public:
enum Direction enum Direction { UP, DOWN };
{
UP,
DOWN
};
AnalyzerFlow(Direction dir, ID* type_id, ExprList* params); AnalyzerFlow(Direction dir, ID* type_id, ExprList* params);
~AnalyzerFlow() override; ~AnalyzerFlow() override;

View file

@ -11,32 +11,25 @@
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_varfield.h" #include "pac_varfield.h"
ArrayType::ArrayType(Type* elemtype, Expr* length) ArrayType::ArrayType(Type* elemtype, Expr* length) : Type(ARRAY), elemtype_(elemtype), length_(length) {
: Type(ARRAY), elemtype_(elemtype), length_(length)
{
init(); init();
switch ( elemtype_->tot() ) switch ( elemtype_->tot() ) {
{
case BUILTIN: case BUILTIN:
case PARAMETERIZED: case PARAMETERIZED:
case STRING: case STRING:
case EXTERN: case EXTERN: break;
break;
case ARRAY: case ARRAY:
case CASE: case CASE:
case DUMMY: case DUMMY:
case EMPTY: case EMPTY:
case RECORD: case RECORD:
case UNDEF: case UNDEF: ASSERT(0); break;
ASSERT(0);
break;
} }
} }
void ArrayType::init() void ArrayType::init() {
{
arraylength_var_field_ = nullptr; arraylength_var_field_ = nullptr;
elem_it_var_field_ = nullptr; elem_it_var_field_ = nullptr;
elem_var_field_ = nullptr; elem_var_field_ = nullptr;
@ -56,8 +49,7 @@ void ArrayType::init()
attr_until_input_expr_ = nullptr; attr_until_input_expr_ = nullptr;
} }
ArrayType::~ArrayType() ArrayType::~ArrayType() {
{
delete arraylength_var_field_; delete arraylength_var_field_;
delete elem_it_var_field_; delete elem_it_var_field_;
delete elem_var_field_; delete elem_var_field_;
@ -67,138 +59,99 @@ ArrayType::~ArrayType()
delete elem_dataptr_until_expr_; delete elem_dataptr_until_expr_;
} }
Type* ArrayType::DoClone() const Type* ArrayType::DoClone() const {
{
Type* elemtype = elemtype_->Clone(); Type* elemtype = elemtype_->Clone();
if ( ! elemtype ) if ( ! elemtype )
return nullptr; return nullptr;
return new ArrayType(elemtype, length_); return new ArrayType(elemtype, length_);
} }
bool ArrayType::DefineValueVar() const bool ArrayType::DefineValueVar() const { return true; }
{
return true;
}
string ArrayType::DataTypeStr() const string ArrayType::DataTypeStr() const { return datatype_str_; }
{
return datatype_str_;
}
Type* ArrayType::ElementDataType() const Type* ArrayType::ElementDataType() const { return elemtype_; }
{
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_ ) 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()); 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() : nullptr; }
{
return arraylength_var_field_ ? arraylength_var_field_->id() : nullptr;
}
const ID* ArrayType::elem_it_var() const const ID* ArrayType::elem_it_var() const { return elem_it_var_field_ ? elem_it_var_field_->id() : nullptr; }
{
return elem_it_var_field_ ? elem_it_var_field_->id() : nullptr;
}
const ID* ArrayType::elem_var() const const ID* ArrayType::elem_var() const { return elem_var_field_ ? elem_var_field_->id() : nullptr; }
{
return elem_var_field_ ? elem_var_field_->id() : nullptr;
}
const ID* ArrayType::elem_dataptr_var() const const ID* ArrayType::elem_dataptr_var() const {
{
return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : nullptr; return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : nullptr;
} }
const ID* ArrayType::elem_input_var() const const ID* ArrayType::elem_input_var() const { return elem_input_var_field_ ? elem_input_var_field_->id() : nullptr; }
{
return elem_input_var_field_ ? elem_input_var_field_->id() : nullptr;
}
void ArrayType::ProcessAttr(Attr* a) void ArrayType::ProcessAttr(Attr* a) {
{
Type::ProcessAttr(a); Type::ProcessAttr(a);
switch ( a->type() ) switch ( a->type() ) {
{ case ATTR_RESTOFDATA: {
case ATTR_RESTOFDATA: if ( elemtype_->StaticSize(env()) != 1 ) {
{ throw Exception(elemtype_,
if ( elemtype_->StaticSize(env()) != 1 ) "&restofdata can be applied"
{
throw Exception(elemtype_, "&restofdata can be applied"
" to only byte arrays"); " to only byte arrays");
} }
if ( length_ ) if ( length_ ) {
{ throw Exception(length_,
throw Exception(length_, "&restofdata cannot be applied" "&restofdata cannot be applied"
" to arrays with specified length"); " to arrays with specified length");
} }
attr_restofdata_ = true; 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. // data, we do not have to check boundary.
SetBoundaryChecked(); SetBoundaryChecked();
} } break;
break;
case ATTR_RESTOFFLOW: case ATTR_RESTOFFLOW:
attr_restofflow_ = true; attr_restofflow_ = true;
// TODO: handle &restofflow // TODO: handle &restofflow
break; break;
case ATTR_UNTIL: case ATTR_UNTIL: {
{
bool ref_element = a->expr()->HasReference(element_macro_id); bool ref_element = a->expr()->HasReference(element_macro_id);
bool ref_input = a->expr()->HasReference(input_macro_id); bool ref_input = a->expr()->HasReference(input_macro_id);
if ( ref_element && ref_input ) if ( ref_element && ref_input ) {
{ throw Exception(a->expr(),
throw Exception(a->expr(), "cannot reference both $element and $input " "cannot reference both $element and $input "
"in the same &until---please separate them."); "in the same &until---please separate them.");
} }
if ( ref_element ) if ( ref_element ) {
{ if ( attr_until_element_expr_ ) {
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(); attr_until_element_expr_ = a->expr();
} }
else if ( ref_input ) else if ( ref_input ) {
{ if ( attr_until_input_expr_ ) {
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(); attr_until_input_expr_ = a->expr();
} }
else else {
{ if ( attr_generic_until_expr_ ) {
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(); attr_generic_until_expr_ = a->expr();
} }
} } break;
break;
default: default: break;
break;
} }
} }
void ArrayType::Prepare(Env* env, int flags) void ArrayType::Prepare(Env* env, int flags) {
{ if ( flags & TO_BE_PARSED ) {
if ( flags & TO_BE_PARSED )
{
ID* arraylength_var = new ID(strfmt("%s__arraylength", value_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_var = new ID(strfmt("%s__elem", value_var()->Name()));
ID* elem_it_var = new ID(strfmt("%s__it", elem_var->Name())); ID* elem_it_var = new ID(strfmt("%s__it", elem_var->Name()));
@ -206,16 +159,14 @@ void ArrayType::Prepare(Env* env, int flags)
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_); AddField(elem_var_field_);
if ( incremental_parsing() ) if ( incremental_parsing() ) {
{
arraylength_var_field_ = new PrivVarField(arraylength_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()); elem_it_var_field_ = new PrivVarField(elem_it_var, extern_type_int->Clone());
AddField(arraylength_var_field_); AddField(arraylength_var_field_);
AddField(elem_it_var_field_); AddField(elem_it_var_field_);
} }
else else {
{
arraylength_var_field_ = new TempVarField(arraylength_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()); elem_it_var_field_ = new TempVarField(elem_it_var, extern_type_int->Clone());
@ -224,17 +175,15 @@ void ArrayType::Prepare(Env* env, int flags)
// Add elem_dataptr_var only when not parsing incrementally // Add elem_dataptr_var only when not parsing incrementally
ID* elem_dataptr_var = new ID(strfmt("%s__dataptr", elem_var->Name())); ID* elem_dataptr_var = new ID(strfmt("%s__dataptr", elem_var->Name()));
elem_dataptr_var_field_ = new TempVarField(elem_dataptr_var, elem_dataptr_var_field_ = new TempVarField(elem_dataptr_var, extern_type_const_byteptr->Clone());
extern_type_const_byteptr->Clone());
elem_dataptr_var_field_->Prepare(env); elem_dataptr_var_field_->Prepare(env);
// until(dataptr >= end_of_data) // until(dataptr >= end_of_data)
elem_dataptr_until_expr_ = new Expr(Expr::EXPR_GE, new Expr(elem_dataptr_var->clone()), elem_dataptr_until_expr_ =
new Expr(end_of_data->clone())); new Expr(Expr::EXPR_GE, new Expr(elem_dataptr_var->clone()), new Expr(end_of_data->clone()));
} }
if ( attr_until_input_expr_ ) if ( attr_until_input_expr_ ) {
{
elemtype_->SetUntilCheck(this); elemtype_->SetUntilCheck(this);
} }
@ -244,21 +193,18 @@ void ArrayType::Prepare(Env* env, int flags)
Type::Prepare(env, 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()) ) if ( env->Evaluated(arraylength_var()) )
return; return;
if ( ! incremental_parsing() ) if ( ! incremental_parsing() ) {
{
arraylength_var_field_->GenTempDecls(out_cc, env); arraylength_var_field_->GenTempDecls(out_cc, env);
// This is about to get initialized below, don't initialize it twice. // This is about to get initialized below, don't initialize it twice.
if ( ! length_ && ! attr_restofdata_ ) if ( ! length_ && ! attr_restofdata_ )
arraylength_var_field_->GenInitCode(out_cc, env); arraylength_var_field_->GenInitCode(out_cc, env);
} }
if ( length_ ) 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()); env->SetEvaluated(arraylength_var());
@ -268,15 +214,14 @@ void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str());
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),
env->RValue(end_of_data), env->RValue(begin_of_data)); env->RValue(begin_of_data));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
int element_size; int element_size;
if ( elemtype_->StaticSize(env) == -1 ) if ( elemtype_->StaticSize(env) == -1 ) {
{
// Check for overlong array quantity. We cap it at the maximum // Check for overlong array quantity. We cap it at the maximum
// array size (assume 1-byte elements * array length) as we can't // array size (assume 1-byte elements * array length) as we can't
// possibly store more elements. e.g. this helps prevent // possibly store more elements. e.g. this helps prevent
@ -289,91 +234,76 @@ void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data)
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; element_size = 1;
} }
else else {
{
// Boundary check the entire array if elements have static size. // 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(); elemtype_->SetBoundaryChecked();
element_size = elemtype_->StaticSize(env); element_size = elemtype_->StaticSize(env);
if ( element_size == 0 ) if ( element_size == 0 ) {
{
// If we know we have an array of empty elements, probably // If we know we have an array of empty elements, probably
// better to structure the parser as just a single empty // better to structure the parser as just a single empty
// field to avoid DoS vulnerability of allocating // field to avoid DoS vulnerability of allocating
// arbitrary number of empty records (i.e. cheap for them, // arbitrary number of empty records (i.e. cheap for them,
// but costly for us unless we have special optimization // but costly for us unless we have special optimization
// for this scenario to forgo the usual allocation). // for this scenario to forgo the usual allocation).
throw Exception( throw Exception(this, "using an array of known-to-be-empty elements is possibly a bad idea");
this, "using an array of known-to-be-empty elements is possibly a bad idea");
} }
} }
const char* array_ptr_expr = data.ptr_expr(); const char* array_ptr_expr = data.ptr_expr();
string max_elements_available = strfmt("((%s - %s) / %d)", env->RValue(end_of_data), string max_elements_available =
array_ptr_expr, element_size); 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());
max_elements_available.c_str());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str()); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str());
out_cc->println(" %s, (%s) - (%s));", env->RValue(arraylength_var()), out_cc->println(" %s, (%s) - (%s));", env->RValue(arraylength_var()), env->RValue(end_of_data),
env->RValue(end_of_data), array_ptr_expr); array_ptr_expr);
out_cc->dec_indent(); out_cc->dec_indent();
} }
else if ( attr_restofdata_ ) else if ( attr_restofdata_ ) {
{
ASSERT(elemtype_->StaticSize(env) == 1); 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->RValue(end_of_data), data.ptr_expr());
env->SetEvaluated(arraylength_var()); 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); Type::GenPubDecls(out_h, env);
if ( declared_as_type() ) if ( declared_as_type() ) {
{
if ( attr_transient_ ) 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; }", out_h->println("int size() const { return %s ? %s->size() : 0; }", 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())); 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) void ArrayType::GenPrivDecls(Output* out_h, Env* env) {
{
ASSERT(elem_var_field_->type() == elemtype_); ASSERT(elem_var_field_->type() == elemtype_);
ASSERT(elemtype_->value_var()); ASSERT(elemtype_->value_var());
Type::GenPrivDecls(out_h, env); 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 // Do not initiate the array here
// out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); // out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str());
out_cc->println("%s = nullptr;", lvalue()); out_cc->println("%s = nullptr;", lvalue());
Type::GenInitCode(out_cc, env); Type::GenInitCode(out_cc, env);
if ( incremental_parsing() ) 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); Type::GenCleanUpCode(out_cc, env);
if ( elemtype_->NeedsCleanUp() ) if ( elemtype_->NeedsCleanUp() ) {
{ if ( ! elem_var_field_ ) {
if ( ! elem_var_field_ )
{
ID* elem_var = new ID(strfmt("%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, elem_var, elemtype_); elem_var_field_ = new ParseVarField(Field::NOT_CLASS_MEMBER, elem_var, elemtype_);
elem_var_field_->Prepare(env); elem_var_field_->Prepare(env);
@ -383,8 +313,7 @@ void ArrayType::GenCleanUpCode(Output* out_cc, Env* env)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("for ( auto* %s : *%s )", env->LValue(elem_var()), out_cc->println("for ( auto* %s : *%s )", env->LValue(elem_var()), env->RValue(value_var()));
env->RValue(value_var()));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
elemtype_->GenCleanUpCode(out_cc, env); elemtype_->GenCleanUpCode(out_cc, env);
@ -397,13 +326,11 @@ void ArrayType::GenCleanUpCode(Output* out_cc, Env* env)
out_cc->println("delete %s;", lvalue()); 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; string array_str;
array_str = lvalue(); array_str = lvalue();
if ( incremental_parsing() ) 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->inc_indent();
out_cc->println("{"); out_cc->println("{");
@ -413,13 +340,11 @@ string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length
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 ) 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() ) if ( incremental_parsing() ) {
{
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
} }
@ -427,35 +352,27 @@ string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length
return array_str; return array_str;
} }
void ArrayType::GenElementAssignment(Output* out_cc, Env* env, string const& array_str, void ArrayType::GenElementAssignment(Output* out_cc, Env* env, string const& array_str, bool use_vector) {
bool use_vector) if ( attr_transient_ ) {
{
if ( attr_transient_ )
{
// Just discard. // Just discard.
out_cc->println("delete %s;", env->LValue(elem_var())); out_cc->println("delete %s;", env->LValue(elem_var()));
return; return;
} }
// Assign the element // Assign the element
if ( ! use_vector ) 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 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); GenArrayLength(out_cc, env, data);
// Otherwise these variables are declared as member variables // Otherwise these variables are declared as member variables
if ( ! incremental_parsing() ) if ( ! incremental_parsing() ) {
{
// Declare and initialize temporary variables // Declare and initialize temporary variables
elem_var_field_->GenInitCode(out_cc, env); elem_var_field_->GenInitCode(out_cc, env);
elem_it_var_field_->GenTempDecls(out_cc, env); elem_it_var_field_->GenTempDecls(out_cc, env);
@ -476,20 +393,16 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in
bool compute_size_var = false; bool compute_size_var = false;
if ( incremental_input() ) if ( incremental_input() ) {
{
// Do not compute size_var on incremental input // Do not compute size_var on incremental input
compute_size_var = false; compute_size_var = false;
if ( ! incremental_parsing() && if ( ! incremental_parsing() &&
(StaticSize(env) >= 0 || (StaticSize(env) >= 0 || (env->Evaluated(arraylength_var()) && elemtype_->StaticSize(env) >= 0)) ) {
(env->Evaluated(arraylength_var()) && elemtype_->StaticSize(env) >= 0)) )
{
GenBoundaryCheck(out_cc, env, data); GenBoundaryCheck(out_cc, env, data);
} }
} }
else else {
{
compute_size_var = AddSizeVar(out_cc, env); compute_size_var = AddSizeVar(out_cc, env);
} }
@ -502,17 +415,16 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in
DataPtr elem_data(env, nullptr, 0); DataPtr elem_data(env, nullptr, 0);
if ( elem_dataptr_var() ) 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()); env->SetEvaluated(elem_dataptr_var());
elem_data = DataPtr(env, elem_dataptr_var(), 0); elem_data = DataPtr(env, elem_dataptr_var(), 0);
} }
string for_condition = known_array_length ? strfmt("%s < %s", env->LValue(elem_it_var()), string for_condition = known_array_length ?
env->RValue(arraylength_var())) strfmt("%s < %s", env->LValue(elem_it_var()), env->RValue(arraylength_var())) :
: "/* forever */"; "/* 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->inc_indent();
@ -521,10 +433,8 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in
if ( attr_generic_until_expr_ ) if ( attr_generic_until_expr_ )
GenUntilCheck(out_cc, env, attr_generic_until_expr_, true); GenUntilCheck(out_cc, env, attr_generic_until_expr_, true);
if ( elem_dataptr_var() ) if ( elem_dataptr_var() ) {
{ if ( length_ ) {
if ( length_ )
{
// Array has a known-length expression like uint16[4] vs. uint16[]. // Array has a known-length expression like uint16[4] vs. uint16[].
// Here, arriving at the end of the data buffer should not be a // Here, arriving at the end of the data buffer should not be a
// valid loop-termination condition (which is what the // valid loop-termination condition (which is what the
@ -533,8 +443,7 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in
// generated for each element should throw an OOB exception if // generated for each element should throw an OOB exception if
// there's insufficient data in the buffer. // there's insufficient data in the buffer.
} }
else else {
{
GenUntilCheck(out_cc, env, elem_dataptr_until_expr_, false); GenUntilCheck(out_cc, env, elem_dataptr_until_expr_, false);
} }
} }
@ -542,8 +451,7 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in
elemtype_->GenPreParsing(out_cc, env); elemtype_->GenPreParsing(out_cc, env);
elemtype_->GenParseCode(out_cc, env, elem_data, flags); elemtype_->GenParseCode(out_cc, env, elem_data, flags);
if ( incremental_parsing() ) 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->inc_indent();
out_cc->println("goto %s;", kNeedMoreData); out_cc->println("goto %s;", kNeedMoreData);
@ -552,12 +460,10 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in
GenElementAssignment(out_cc, env, array_str, use_vector); GenElementAssignment(out_cc, env, array_str, use_vector);
if ( elem_dataptr_var() ) 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(nullptr, 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()), out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(elem_dataptr_var()), env->RValue(end_of_data));
env->RValue(end_of_data));
} }
if ( attr_until_element_expr_ ) if ( attr_until_element_expr_ )
@ -573,38 +479,31 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in
out_cc->println("%s: ;", end_of_array_loop_label_.c_str()); out_cc->println("%s: ;", end_of_array_loop_label_.c_str());
out_cc->inc_indent(); out_cc->inc_indent();
if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) ) if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) ) {
{
// Compute the data size // Compute the data size
out_cc->println("%s = %s - (%s);", env->LValue(size_var()), env->RValue(elem_dataptr_var()), out_cc->println("%s = %s - (%s);", env->LValue(size_var()), env->RValue(elem_dataptr_var()), data.ptr_expr());
data.ptr_expr());
env->SetEvaluated(size_var()); 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())); ID* elem_input_var_id = new ID(strfmt("%s__elem_input", value_var()->Name()));
elem_input_var_field_ = new TempVarField(elem_input_var_id, elem_input_var_field_ = new TempVarField(elem_input_var_id, extern_type_const_bytestring->Clone());
extern_type_const_bytestring->Clone());
elem_input_var_field_->Prepare(env); elem_input_var_field_->Prepare(env);
out_cc->println("%s %s(%s, %s);", extern_type_const_bytestring->DataTypeStr().c_str(), 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->LValue(elem_input_var()), env->RValue(begin_of_data), env->RValue(end_of_data));
env->RValue(end_of_data));
env->SetEvaluated(elem_input_var()); env->SetEvaluated(elem_input_var());
GenUntilCheck(out_cc, env, attr_until_input_expr_, true); 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); ASSERT(until_expr);
Env check_env(env, this); 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() ) 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()));
} }
@ -612,13 +511,11 @@ void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool d
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->inc_indent();
out_cc->println("{"); out_cc->println("{");
if ( parsing_complete_var() ) 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() ) if ( elemtype_->IsPointerType() ) {
{
if ( delete_elem ) if ( delete_elem )
elemtype_->GenCleanUpCode(out_cc, env); elemtype_->GenCleanUpCode(out_cc, env);
else else
@ -630,34 +527,28 @@ void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool d
out_cc->dec_indent(); 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()); 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); int elem_w = elemtype_->StaticSize(env);
if ( elem_w >= 0 && ! attr_until_element_expr_ && ! attr_until_input_expr_ && if ( elem_w >= 0 && ! attr_until_element_expr_ && ! attr_until_input_expr_ && (length_ || attr_restofdata_) ) {
(length_ || attr_restofdata_) )
{
// If the elements have a fixed size, // If the elements have a fixed size,
// we only need to compute the number of elements // we only need to compute the number of elements
bool compute_size_var = AddSizeVar(out_cc, env); bool compute_size_var = AddSizeVar(out_cc, env);
ASSERT(compute_size_var); ASSERT(compute_size_var);
GenArrayLength(out_cc, env, data); GenArrayLength(out_cc, env, data);
ASSERT(env->Evaluated(arraylength_var())); ASSERT(env->Evaluated(arraylength_var()));
out_cc->println("%s = %d * %s;", env->LValue(size_var()), elem_w, out_cc->println("%s = %d * %s;", env->LValue(size_var()), elem_w, env->RValue(arraylength_var()));
env->RValue(arraylength_var()));
env->SetEvaluated(size_var()); env->SetEvaluated(size_var());
} }
else else {
{
// Otherwise we need parse the array dynamically // Otherwise we need parse the array dynamically
GenParseCode(out_cc, env, data, 0); GenParseCode(out_cc, env, data, 0);
} }
} }
int ArrayType::StaticSize(Env* env) const int ArrayType::StaticSize(Env* env) const {
{
int num = 0; int num = 0;
if ( ! length_ || ! length_->ConstFold(env, &num) ) if ( ! length_ || ! length_->ConstFold(env, &num) )
@ -672,12 +563,10 @@ int ArrayType::StaticSize(Env* env) const
return num * elem_w; return num * elem_w;
} }
void ArrayType::SetBoundaryChecked() void ArrayType::SetBoundaryChecked() {
{
Type::SetBoundaryChecked(); Type::SetBoundaryChecked();
if ( attr_length_expr_ ) if ( attr_length_expr_ ) {
{
// When using &length on an array, only treat its elements as // When using &length on an array, only treat its elements as
// already-bounds-checked if they are a single byte in length. // already-bounds-checked if they are a single byte in length.
if ( elemtype_->StaticSize(env()) == 1 ) if ( elemtype_->StaticSize(env()) == 1 )
@ -689,19 +578,14 @@ void ArrayType::SetBoundaryChecked()
elemtype_->SetBoundaryChecked(); elemtype_->SetBoundaryChecked();
} }
void ArrayType::DoMarkIncrementalInput() void ArrayType::DoMarkIncrementalInput() { elemtype_->MarkIncrementalInput(); }
{
elemtype_->MarkIncrementalInput();
}
bool ArrayType::RequiresAnalyzerContext() bool ArrayType::RequiresAnalyzerContext() {
{
return Type::RequiresAnalyzerContext() || (length_ && length_->RequiresAnalyzerContext()) || return Type::RequiresAnalyzerContext() || (length_ && length_->RequiresAnalyzerContext()) ||
elemtype_->RequiresAnalyzerContext(); elemtype_->RequiresAnalyzerContext();
} }
bool ArrayType::DoTraverse(DataDepVisitor* visitor) bool ArrayType::DoTraverse(DataDepVisitor* visitor) {
{
if ( ! Type::DoTraverse(visitor) ) if ( ! Type::DoTraverse(visitor) )
return false; return false;

View file

@ -6,8 +6,7 @@
// Fixed-length array and variable length sequence with an ending pattern // Fixed-length array and variable length sequence with an ending pattern
class ArrayType : public Type class ArrayType : public Type {
{
public: public:
ArrayType(Type* arg_elemtype, Expr* arg_length = nullptr); ArrayType(Type* arg_elemtype, Expr* arg_length = nullptr);
~ArrayType() override; ~ArrayType() override;

View file

@ -2,60 +2,47 @@
#include "pac_expr.h" #include "pac_expr.h"
bool Attr::DoTraverse(DataDepVisitor* visitor) bool Attr::DoTraverse(DataDepVisitor* visitor) {
{
if ( expr_ && ! expr_->Traverse(visitor) ) if ( expr_ && ! expr_->Traverse(visitor) )
return false; return false;
return true; return true;
} }
bool Attr::RequiresAnalyzerContext() const bool Attr::RequiresAnalyzerContext() const { return (expr_ && expr_->RequiresAnalyzerContext()); }
{
return (expr_ && expr_->RequiresAnalyzerContext());
}
void Attr::init() void Attr::init() {
{
expr_ = nullptr; expr_ = nullptr;
seqend_ = nullptr; seqend_ = nullptr;
delete_expr_ = false; delete_expr_ = false;
} }
Attr::Attr(AttrType type) : DataDepElement(DataDepElement::ATTR) Attr::Attr(AttrType type) : DataDepElement(DataDepElement::ATTR) {
{
type_ = type; type_ = type;
init(); init();
} }
Attr::Attr(AttrType type, Expr* expr) : DataDepElement(DataDepElement::ATTR) Attr::Attr(AttrType type, Expr* expr) : DataDepElement(DataDepElement::ATTR) {
{
type_ = type; type_ = type;
init(); init();
expr_ = expr; expr_ = expr;
} }
Attr::Attr(AttrType type, ExprList* exprlist) : DataDepElement(DataDepElement::ATTR) Attr::Attr(AttrType type, ExprList* exprlist) : DataDepElement(DataDepElement::ATTR) {
{
type_ = type; type_ = type;
init(); init();
expr_ = new Expr(exprlist); expr_ = new Expr(exprlist);
delete_expr_ = true; delete_expr_ = true;
} }
Attr::Attr(AttrType type, SeqEnd* seqend) : DataDepElement(DataDepElement::ATTR) Attr::Attr(AttrType type, SeqEnd* seqend) : DataDepElement(DataDepElement::ATTR) {
{
type_ = type; type_ = type;
init(); init();
seqend_ = seqend; seqend_ = seqend;
} }
Attr::~Attr() Attr::~Attr() {
{
if ( delete_expr_ ) if ( delete_expr_ )
delete expr_; delete expr_;
} }
LetAttr::LetAttr(FieldList* letfields) : Attr(ATTR_LET) LetAttr::LetAttr(FieldList* letfields) : Attr(ATTR_LET) { letfields_ = letfields; }
{
letfields_ = letfields;
}

View file

@ -4,8 +4,7 @@
#include "pac_common.h" #include "pac_common.h"
#include "pac_datadep.h" #include "pac_datadep.h"
enum AttrType enum AttrType {
{
ATTR_BYTEORDER, ATTR_BYTEORDER,
ATTR_CHECK, ATTR_CHECK,
ATTR_CHUNKED, ATTR_CHUNKED,
@ -25,8 +24,7 @@ enum AttrType
ATTR_UNTIL, ATTR_UNTIL,
}; };
class Attr : public Object, public DataDepElement class Attr : public Object, public DataDepElement {
{
public: public:
Attr(AttrType type); Attr(AttrType type);
Attr(AttrType type, Expr* expr); Attr(AttrType type, Expr* expr);
@ -53,8 +51,7 @@ protected:
bool delete_expr_; bool delete_expr_;
}; };
class LetAttr : public Attr class LetAttr : public Attr {
{
public: public:
LetAttr(FieldList* letfields); LetAttr(FieldList* letfields);
FieldList* letfields() const { return letfields_; } FieldList* letfields() const { return letfields_; }

View file

@ -4,20 +4,15 @@
#include "pac_id.h" #include "pac_id.h"
#include "pac_output.h" #include "pac_output.h"
Type* BuiltInType::DoClone() const Type* BuiltInType::DoClone() const { return new BuiltInType(bit_type()); }
{
return new BuiltInType(bit_type());
}
bool BuiltInType::IsNumericType() const bool BuiltInType::IsNumericType() const {
{
BITType t = bit_type(); BITType t = bit_type();
return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || t == UINT8 || t == UINT16 || return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || t == UINT8 || t == UINT16 || t == UINT32 ||
t == UINT32 || t == UINT64); t == UINT64);
} }
bool BuiltInType::CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2) bool BuiltInType::CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2) {
{
return type1->IsNumericType() && type2->IsNumericType(); return type1->IsNumericType() && type2->IsNumericType();
} }
@ -28,16 +23,13 @@ static const char* basic_pactype_name[] = {
nullptr, nullptr,
}; };
void BuiltInType::static_init() void BuiltInType::static_init() {
{ for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type ) {
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));
} }
} }
int BuiltInType::LookUpByName(const char* name) int BuiltInType::LookUpByName(const char* name) {
{
ASSERT(0); ASSERT(0);
for ( int i = 0; basic_pactype_name[i]; ++i ) for ( int i = 0; basic_pactype_name[i]; ++i )
if ( strcmp(basic_pactype_name[i], name) == 0 ) if ( strcmp(basic_pactype_name[i], name) == 0 )
@ -52,18 +44,11 @@ static const char* basic_ctype_name[] = {
nullptr, nullptr,
}; };
bool BuiltInType::DefineValueVar() const bool BuiltInType::DefineValueVar() const { return bit_type_ != EMPTY; }
{
return bit_type_ != EMPTY;
}
string BuiltInType::DataTypeStr() const string BuiltInType::DataTypeStr() const { return basic_ctype_name[bit_type_]; }
{
return basic_ctype_name[bit_type_];
}
int BuiltInType::StaticSize(Env* /* env */) const int BuiltInType::StaticSize(Env* /* env */) const {
{
static const size_t basic_type_size[] = { static const size_t basic_type_size[] = {
#define TYPE_DEF(name, pactype, ctype, size) size, #define TYPE_DEF(name, pactype, ctype, size) size,
#include "pac_type.def" #include "pac_type.def"
@ -73,28 +58,24 @@ int BuiltInType::StaticSize(Env* /* env */) const
return basic_type_size[bit_type_]; return basic_type_size[bit_type_];
} }
void BuiltInType::DoMarkIncrementalInput() void BuiltInType::DoMarkIncrementalInput() {
{
if ( bit_type_ == EMPTY ) if ( bit_type_ == EMPTY )
return; return;
Type::DoMarkIncrementalInput(); Type::DoMarkIncrementalInput();
} }
void BuiltInType::GenInitCode(Output* out_cc, Env* env) void BuiltInType::GenInitCode(Output* out_cc, Env* env) {
{
if ( bit_type_ != EMPTY ) if ( bit_type_ != EMPTY )
out_cc->println("%s = 0;", env->LValue(value_var())); out_cc->println("%s = 0;", env->LValue(value_var()));
Type::GenInitCode(out_cc, env); Type::GenInitCode(out_cc, env);
} }
void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) {
{
/* should never be called */ /* should never be called */
ASSERT(0); 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 ) if ( bit_type_ == EMPTY )
return; return;
@ -106,16 +87,14 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data,
if ( anonymous_value_var() ) if ( anonymous_value_var() )
return; return;
switch ( bit_type_ ) switch ( bit_type_ ) {
{
case EMPTY: case EMPTY:
// do nothing // do nothing
break; break;
case INT8: case INT8:
case UINT8: case UINT8:
out_cc->println("%s = *((%s const *) (%s));", lvalue(), DataTypeStr().c_str(), out_cc->println("%s = *((%s const *) (%s));", lvalue(), DataTypeStr().c_str(), data.ptr_expr());
data.ptr_expr());
break; break;
case INT16: case INT16:
case UINT16: case UINT16:
@ -131,8 +110,7 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data,
EvalByteOrder(out_cc, env).c_str()); EvalByteOrder(out_cc, env).c_str());
#else #else
out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", lvalue(), out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", lvalue(),
EvalByteOrder(out_cc, env).c_str(), DataTypeStr().c_str(), EvalByteOrder(out_cc, env).c_str(), DataTypeStr().c_str(), data.ptr_expr());
data.ptr_expr());
#endif #endif
break; break;
} }

View file

@ -3,11 +3,9 @@
#include "pac_type.h" #include "pac_type.h"
class BuiltInType : public Type class BuiltInType : public Type {
{
public: public:
enum BITType enum BITType {
{
#define TYPE_DEF(name, pactype, ctype, size) name, #define TYPE_DEF(name, pactype, ctype, size) name,
#include "pac_type.def" #include "pac_type.def"
#undef TYPE_DEF #undef TYPE_DEF
@ -15,10 +13,7 @@ public:
static int LookUpByName(const char* name); static int LookUpByName(const char* name);
BuiltInType(BITType bit_type) 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_; }

View file

@ -12,23 +12,19 @@
#include "pac_typedecl.h" #include "pac_typedecl.h"
#include "pac_utils.h" #include "pac_utils.h"
CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) : Type(CASE), index_expr_(index_expr), cases_(cases) {
: Type(CASE), index_expr_(index_expr), cases_(cases)
{
index_var_ = nullptr; index_var_ = nullptr;
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
AddField(*i); AddField(*i);
} }
CaseType::~CaseType() CaseType::~CaseType() {
{
delete index_var_; delete index_var_;
delete index_expr_; delete index_expr_;
delete cases_; delete cases_;
} }
void CaseType::AddCaseField(CaseField* f) void CaseType::AddCaseField(CaseField* f) {
{
// All fields must be added before Prepare() // All fields must be added before Prepare()
ASSERT(! env()); ASSERT(! env());
@ -36,21 +32,15 @@ void CaseType::AddCaseField(CaseField* f)
cases_->push_back(f); cases_->push_back(f);
} }
bool CaseType::DefineValueVar() const bool CaseType::DefineValueVar() const { return false; }
{
return false;
}
string CaseType::DataTypeStr() const string CaseType::DataTypeStr() const {
{
ASSERT(type_decl()); 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 Type* CaseType::ValueType() const {
{ foreach (i, CaseFieldList, cases_) {
foreach (i, CaseFieldList, cases_)
{
CaseField* c = *i; CaseField* c = *i;
return c->type(); return c->type();
} }
@ -58,13 +48,9 @@ Type* CaseType::ValueType() const
return nullptr; return nullptr;
} }
string CaseType::DefaultValue() const string CaseType::DefaultValue() const { return ValueType()->DefaultValue(); }
{
return ValueType()->DefaultValue();
}
void CaseType::Prepare(Env* env, int flags) void CaseType::Prepare(Env* env, int flags) {
{
ASSERT(flags & TO_BE_PARSED); ASSERT(flags & TO_BE_PARSED);
index_var_ = new ID(strfmt("%s_case_index", value_var()->Name())); index_var_ = new ID(strfmt("%s_case_index", value_var()->Name()));
@ -76,25 +62,21 @@ void CaseType::Prepare(Env* env, int flags)
CaseFieldList::iterator default_case_it = cases_->end(); // to avoid warning CaseFieldList::iterator default_case_it = cases_->end(); // to avoid warning
CaseField* default_case = nullptr; CaseField* default_case = nullptr;
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_) {
{
CaseField* c = *i; CaseField* c = *i;
if ( ! c->index() ) if ( ! c->index() ) {
{
if ( default_case ) if ( default_case )
throw Exception(c, "duplicate default case"); throw Exception(c, "duplicate default case");
default_case_it = i; default_case_it = i;
default_case = c; default_case = c;
} }
} }
if ( default_case ) if ( default_case ) {
{
cases_->erase(default_case_it); cases_->erase(default_case_it);
cases_->push_back(default_case); cases_->push_back(default_case);
} }
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_) {
{
CaseField* c = *i; CaseField* c = *i;
c->set_index_var(index_var_); c->set_index_var(index_var_);
c->set_case_type(this); c->set_case_type(this);
@ -103,8 +85,7 @@ void CaseType::Prepare(Env* env, int flags)
Type::Prepare(env, flags); Type::Prepare(env, flags);
} }
void CaseType::GenPrivDecls(Output* out_h, Env* env) void CaseType::GenPrivDecls(Output* out_h, Env* env) {
{
Type* t = index_expr_->DataType(env); Type* t = index_expr_->DataType(env);
if ( t->tot() != Type::BUILTIN ) if ( t->tot() != Type::BUILTIN )
@ -116,8 +97,7 @@ void CaseType::GenPrivDecls(Output* out_h, Env* env)
Type::GenPrivDecls(out_h, env); Type::GenPrivDecls(out_h, env);
} }
void CaseType::GenPubDecls(Output* out_h, Env* env) void CaseType::GenPubDecls(Output* out_h, Env* env) {
{
Type* t = index_expr_->DataType(env); Type* t = index_expr_->DataType(env);
if ( t->tot() != Type::BUILTIN ) if ( t->tot() != Type::BUILTIN )
@ -128,22 +108,19 @@ void CaseType::GenPubDecls(Output* out_h, Env* env)
Type::GenPubDecls(out_h, env); Type::GenPubDecls(out_h, env);
} }
void CaseType::GenInitCode(Output* out_cc, Env* env) void CaseType::GenInitCode(Output* out_cc, Env* env) {
{
out_cc->println("%s = -1;", env->LValue(index_var_)); out_cc->println("%s = -1;", env->LValue(index_var_));
Type::GenInitCode(out_cc, env); Type::GenInitCode(out_cc, env);
} }
void CaseType::GenCleanUpCode(Output* out_cc, Env* env) void CaseType::GenCleanUpCode(Output* out_cc, Env* env) {
{
Type::GenCleanUpCode(out_cc, env); Type::GenCleanUpCode(out_cc, env);
env->set_in_branch(true); 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->inc_indent();
out_cc->println("{"); out_cc->println("{");
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_) {
{
CaseField* c = *i; CaseField* c = *i;
c->GenCleanUpCode(out_cc, env); c->GenCleanUpCode(out_cc, env);
} }
@ -152,8 +129,7 @@ void CaseType::GenCleanUpCode(Output* out_cc, Env* env)
env->set_in_branch(false); 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 ) if ( StaticSize(env) >= 0 )
GenBoundaryCheck(out_cc, env, data); GenBoundaryCheck(out_cc, env, data);
@ -170,20 +146,18 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
bool has_default_case = false; bool has_default_case = false;
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_) {
{
CaseField* c = *i; CaseField* c = *i;
c->GenParseCode(out_cc, env, data, compute_size_var ? size_var() : nullptr); c->GenParseCode(out_cc, env, data, compute_size_var ? size_var() : nullptr);
if ( c->IsDefaultCase() ) if ( c->IsDefaultCase() )
has_default_case = true; has_default_case = true;
} }
if ( ! has_default_case ) if ( ! has_default_case ) {
{
out_cc->println("default:"); out_cc->println("default:");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", decl_id()->Name(),
decl_id()->Name(), env->RValue(index_var_)); env->RValue(index_var_));
out_cc->println("break;"); out_cc->println("break;");
out_cc->dec_indent(); out_cc->dec_indent();
} }
@ -195,16 +169,11 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int
env->SetEvaluated(size_var()); 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); }
{
GenParseCode(out_cc, env, data, 0);
}
int CaseType::StaticSize(Env* env) const int CaseType::StaticSize(Env* env) const {
{
int static_w = -1; int static_w = -1;
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_) {
{
CaseField* c = *i; CaseField* c = *i;
int w = c->StaticSize(env); int w = c->StaticSize(env);
if ( w < 0 || (static_w >= 0 && w != static_w) ) if ( w < 0 || (static_w >= 0 && w != static_w) )
@ -214,29 +183,23 @@ int CaseType::StaticSize(Env* env) const
return static_w; return static_w;
} }
void CaseType::SetBoundaryChecked() void CaseType::SetBoundaryChecked() {
{
Type::SetBoundaryChecked(); Type::SetBoundaryChecked();
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_) {
{
CaseField* c = *i; CaseField* c = *i;
c->SetBoundaryChecked(); c->SetBoundaryChecked();
} }
} }
void CaseType::DoMarkIncrementalInput() void CaseType::DoMarkIncrementalInput() {
{ foreach (i, CaseFieldList, cases_) {
foreach (i, CaseFieldList, cases_)
{
CaseField* c = *i; CaseField* c = *i;
c->type()->MarkIncrementalInput(); c->type()->MarkIncrementalInput();
} }
} }
bool CaseType::ByteOrderSensitive() const bool CaseType::ByteOrderSensitive() const {
{ foreach (i, CaseFieldList, cases_) {
foreach (i, CaseFieldList, cases_)
{
CaseField* c = *i; CaseField* c = *i;
if ( c->RequiresByteOrder() ) if ( c->RequiresByteOrder() )
return true; return true;
@ -245,25 +208,18 @@ bool CaseType::ByteOrderSensitive() const
} }
CaseField::CaseField(ExprList* index, ID* id, Type* type) 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_); ASSERT(type_);
type_->set_value_var(id, MEMBER_VAR); type_->set_value_var(id, MEMBER_VAR);
case_type_ = nullptr; case_type_ = nullptr;
index_var_ = nullptr; index_var_ = nullptr;
} }
CaseField::~CaseField() CaseField::~CaseField() { delete_list(ExprList, index_); }
{
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 ) {
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); Type* case_type = index_expr->DataType(env);
@ -287,44 +243,40 @@ void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_typ
if ( case_type->tot() == Type::BUILTIN ) if ( case_type->tot() == Type::BUILTIN )
case_type_width = case_type->StaticSize(env); case_type_width = case_type->StaticSize(env);
if ( case_type_width > switch_type_width ) if ( case_type_width > switch_type_width ) {
{
BuiltInType* st = (BuiltInType*)switch_type; BuiltInType* st = (BuiltInType*)switch_type;
if ( switch_type_width == 1 ) if ( switch_type_width == 1 ) {
{ if ( st->bit_type() == BuiltInType::INT8 ) {
if ( st->bit_type() == BuiltInType::INT8 )
{
if ( index_const < std::numeric_limits<int8_t>::min() ) if ( index_const < std::numeric_limits<int8_t>::min() )
throw ExceptionInvalidCaseLimitExpr(index_expr); throw ExceptionInvalidCaseLimitExpr(index_expr);
if ( index_const > std::numeric_limits<int8_t>::max() ) if ( index_const > std::numeric_limits<int8_t>::max() )
throw ExceptionInvalidCaseLimitExpr(index_expr); throw ExceptionInvalidCaseLimitExpr(index_expr);
} }
else else {
{
if ( index_const < std::numeric_limits<uint8_t>::min() ) if ( index_const < std::numeric_limits<uint8_t>::min() )
throw ExceptionInvalidCaseLimitExpr(index_expr); throw ExceptionInvalidCaseLimitExpr(index_expr);
if ( index_const > std::numeric_limits<uint8_t>::max() ) if ( index_const > std::numeric_limits<uint8_t>::max() )
throw ExceptionInvalidCaseLimitExpr(index_expr); throw ExceptionInvalidCaseLimitExpr(index_expr);
} }
} }
else if ( switch_type_width == 2 ) else if ( switch_type_width == 2 ) {
{ if ( st->bit_type() == BuiltInType::INT16 ) {
if ( st->bit_type() == BuiltInType::INT16 )
{
if ( index_const < std::numeric_limits<int16_t>::min() ) if ( index_const < std::numeric_limits<int16_t>::min() )
throw ExceptionInvalidCaseLimitExpr(index_expr); throw ExceptionInvalidCaseLimitExpr(index_expr);
if ( index_const > std::numeric_limits<int16_t>::max() ) if ( index_const > std::numeric_limits<int16_t>::max() )
throw ExceptionInvalidCaseLimitExpr(index_expr); throw ExceptionInvalidCaseLimitExpr(index_expr);
} }
else else {
{
if ( index_const < std::numeric_limits<uint16_t>::min() ) if ( index_const < std::numeric_limits<uint16_t>::min() )
throw ExceptionInvalidCaseLimitExpr(index_expr); throw ExceptionInvalidCaseLimitExpr(index_expr);
if ( index_const > std::numeric_limits<uint16_t>::max() ) if ( index_const > std::numeric_limits<uint16_t>::max() )
throw ExceptionInvalidCaseLimitExpr(index_expr); throw ExceptionInvalidCaseLimitExpr(index_expr);
} }
} }
else {
assert(0);
}
} }
// We're always using "int" for storage, so ok to just // We're always using "int" for storage, so ok to just
@ -333,20 +285,17 @@ void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_typ
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 else {
{
out_cc->println("default:"); out_cc->println("default:");
} }
} }
void CaseField::Prepare(Env* env) void CaseField::Prepare(Env* env) {
{
ASSERT(index_var_); ASSERT(index_var_);
Field::Prepare(env); Field::Prepare(env);
} }
void CaseField::GenPubDecls(Output* out_h, Env* env) void CaseField::GenPubDecls(Output* out_h, Env* env) {
{
if ( ! ((flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER)) ) if ( ! ((flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER)) )
return; return;
@ -361,8 +310,7 @@ void CaseField::GenPubDecls(Output* out_h, Env* env)
if ( ! index_ ) if ( ! index_ )
out_h->println("return %s;", lvalue()); out_h->println("return %s;", lvalue());
else 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->inc_indent();
out_h->println("{"); out_h->println("{");
@ -373,8 +321,8 @@ void CaseField::GenPubDecls(Output* out_h, Env* env)
out_h->println("default:"); out_h->println("default:");
out_h->inc_indent(); out_h->inc_indent();
out_h->println("throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");", out_h->println("throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");", id_->LocName(),
id_->LocName(), env->RValue(index_var_), OrigExprList(index_).c_str()); env->RValue(index_var_), OrigExprList(index_).c_str());
out_h->println("break;"); out_h->println("break;");
out_h->dec_indent(); out_h->dec_indent();
@ -388,8 +336,7 @@ void CaseField::GenPubDecls(Output* out_h, Env* env)
out_h->dec_indent(); out_h->dec_indent();
} }
void CaseField::GenInitCode(Output* out_cc, Env* env) void CaseField::GenInitCode(Output* out_cc, Env* env) {
{
// GenCaseStr(index_, out_cc, env); // GenCaseStr(index_, out_cc, env);
// out_cc->inc_indent(); // out_cc->inc_indent();
// out_cc->println("{"); // out_cc->println("{");
@ -400,8 +347,7 @@ void CaseField::GenInitCode(Output* out_cc, Env* env)
// out_cc->dec_indent(); // out_cc->dec_indent();
} }
void CaseField::GenCleanUpCode(Output* out_cc, Env* env) void CaseField::GenCleanUpCode(Output* out_cc, Env* env) {
{
GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("// Clean up \"%s\"", id_->Name()); out_cc->println("// Clean up \"%s\"", id_->Name());
@ -413,8 +359,7 @@ void CaseField::GenCleanUpCode(Output* out_cc, Env* env)
out_cc->dec_indent(); 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)); GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("// Parse \"%s\"", id_->Name()); out_cc->println("// Parse \"%s\"", id_->Name());
@ -425,13 +370,10 @@ void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, cons
type_->GenPreParsing(out_cc, &case_env); type_->GenPreParsing(out_cc, &case_env);
type_->GenParseCode(out_cc, &case_env, data, 0); type_->GenParseCode(out_cc, &case_env, data, 0);
if ( size_var ) if ( size_var ) {
{ out_cc->println("%s = %s;", case_env.LValue(size_var), type_->DataSize(out_cc, &case_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() ) if ( type_->incremental_input() ) {
{
ASSERT(case_type()->parsing_complete_var()); ASSERT(case_type()->parsing_complete_var());
out_cc->println("%s = %s;", case_env.LValue(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())); case_env.RValue(type_->parsing_complete_var()));
@ -443,12 +385,8 @@ void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, cons
out_cc->dec_indent(); out_cc->dec_indent();
} }
bool CaseField::DoTraverse(DataDepVisitor* visitor) bool CaseField::DoTraverse(DataDepVisitor* visitor) { return Field::DoTraverse(visitor) && type()->Traverse(visitor); }
{
return Field::DoTraverse(visitor) && type()->Traverse(visitor);
}
bool CaseField::RequiresAnalyzerContext() const bool CaseField::RequiresAnalyzerContext() const {
{
return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext(); return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext();
} }

View file

@ -6,8 +6,7 @@
#include "pac_id.h" #include "pac_id.h"
#include "pac_type.h" #include "pac_type.h"
class CaseType : public Type class CaseType : public Type {
{
public: public:
CaseType(Expr* index, CaseFieldList* cases); CaseType(Expr* index, CaseFieldList* cases);
~CaseType() override; ~CaseType() override;
@ -52,8 +51,7 @@ protected:
member_map_t member_map_; member_map_t member_map_;
}; };
class CaseField : public Field class CaseField : public Field {
{
public: public:
CaseField(ExprList* index, ID* id, Type* type); CaseField(ExprList* index, ID* id, Type* type);
~CaseField() override; ~CaseField() override;

View file

@ -24,8 +24,7 @@ typedef vector<CVariable*> CVariableList;
// //
// 3. We do not check repeated names. // 3. We do not check repeated names.
class CClass class CClass {
{
public: public:
CClass(const string& class_name); CClass(const string& class_name);
@ -41,8 +40,7 @@ protected:
CClassMethodList* methods_; CClassMethodList* methods_;
}; };
class CVariable class CVariable {
{
public: public:
CClassMember(const string& name, CType* type); CClassMember(const string& name, CType* type);
@ -54,8 +52,7 @@ protected:
CType* type_; CType* type_;
}; };
class CClassMember class CClassMember {
{
public: public:
CClassMember(CVariable* var); CClassMember(CVariable* var);
void GenCode(Output* out_h, Output* out_cc); void GenCode(Output* out_h, Output* out_cc);
@ -66,8 +63,7 @@ protected:
CVariable* var_; CVariable* var_;
}; };
class CClassMethod class CClassMethod {
{
public: public:
CClassMethod(CVariable* var, CVariableList* params); CClassMethod(CVariable* var, CVariableList* params);

View file

@ -20,11 +20,9 @@ extern int line_number;
// representing language elements -- identifiers, types, expressions, // representing language elements -- identifiers, types, expressions,
// etc. // etc.
class Object class Object {
{
public: public:
Object() Object() {
{
filename = input_filename; filename = input_filename;
line_num = line_number; line_num = line_number;
location = strfmt("%s:%d", filename.c_str(), line_number); location = strfmt("%s:%d", filename.c_str(), line_number);

View file

@ -11,27 +11,23 @@
#include "pac_type.h" #include "pac_type.h"
ConnDecl::ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist) ConnDecl::ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist)
: AnalyzerDecl(conn_id, CONN, params) : AnalyzerDecl(conn_id, CONN, params) {
{
flows_[0] = flows_[1] = nullptr; flows_[0] = flows_[1] = nullptr;
AddElements(elemlist); AddElements(elemlist);
data_type_ = new ParameterizedType(conn_id->clone(), nullptr); data_type_ = new ParameterizedType(conn_id->clone(), nullptr);
} }
ConnDecl::~ConnDecl() ConnDecl::~ConnDecl() {
{
delete flows_[0]; delete flows_[0];
delete flows_[1]; delete flows_[1];
delete data_type_; delete data_type_;
} }
void ConnDecl::AddBaseClass(vector<string>* base_classes) const void ConnDecl::AddBaseClass(vector<string>* 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; int flow_index;
if ( flow_elem->dir() == AnalyzerFlow::UP ) if ( flow_elem->dir() == AnalyzerFlow::UP )
@ -39,41 +35,30 @@ void ConnDecl::ProcessFlowElement(AnalyzerFlow* flow_elem)
else else
flow_index = 1; flow_index = 1;
if ( flows_[flow_index] ) if ( flows_[flow_index] ) {
{ throw Exception(flow_elem, strfmt("%sflow already defined", flow_index == 0 ? "up" : "down"));
throw Exception(flow_elem,
strfmt("%sflow already defined", flow_index == 0 ? "up" : "down"));
} }
flows_[flow_index] = flow_elem; flows_[flow_index] = flow_elem;
type_->AddField(flow_elem->flow_field()); 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() void ConnDecl::Prepare() {
{
AnalyzerDecl::Prepare(); AnalyzerDecl::Prepare();
flows_[0]->flow_decl()->set_conn_decl(this); flows_[0]->flow_decl()->set_conn_decl(this);
flows_[1]->flow_decl()->set_conn_decl(this); 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); }
{
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); }
{
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); string proto = strfmt("%s(bool is_orig)", kFlowEOF);
out_h->println("void %s;", proto.c_str()); out_h->println("void %s;", proto.c_str());
@ -90,8 +75,7 @@ void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc)
out_cc->inc_indent(); 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(nullptr, out_cc, this); (*i)->GenCode(nullptr, out_cc, this);
} }
@ -102,8 +86,7 @@ void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc)
out_cc->println(""); 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); 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());
@ -126,8 +109,7 @@ void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc)
out_cc->println(""); 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()); out_h->println("void %s;", proto.c_str());

View file

@ -4,8 +4,7 @@
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_decl.h" #include "pac_decl.h"
class ConnDecl : public AnalyzerDecl class ConnDecl : public AnalyzerDecl {
{
public: public:
ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist); ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist);
~ConnDecl() override; ~ConnDecl() override;

View file

@ -12,34 +12,26 @@
#include "pac_utils.h" #include "pac_utils.h"
ContextField::ContextField(ID* id, Type* type) 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; AnalyzerContextDecl* AnalyzerContextDecl::current_analyzer_context_ = nullptr;
namespace namespace {
{ ParamList* ContextFieldsToParams(ContextFieldList* context_fields) {
ParamList* ContextFieldsToParams(ContextFieldList* context_fields)
{
// Convert context fields to parameters // Convert context fields to parameters
ParamList* params = new ParamList(); ParamList* params = new ParamList();
foreach (i, ContextFieldList, context_fields) foreach (i, ContextFieldList, context_fields) {
{
ContextField* f = *i; ContextField* f = *i;
params->push_back(new Param(f->id()->clone(), f->type())); params->push_back(new Param(f->id()->clone(), f->type()));
} }
return params; return params;
} }
} // namespace private } // namespace
AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_fields) AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_fields)
: TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields), : TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields), new DummyType()) {
new DummyType())
{
context_name_id_ = id; context_name_id_ = id;
if ( current_analyzer_context_ != nullptr ) if ( current_analyzer_context_ != nullptr ) {
{
throw Exception(this, strfmt("multiple declaration of analyzer context; " throw Exception(this, strfmt("multiple declaration of analyzer context; "
"the previous one is `%s'", "the previous one is `%s'",
current_analyzer_context_->id()->Name())); current_analyzer_context_->id()->Name()));
@ -56,38 +48,32 @@ AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_field
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() AnalyzerContextDecl::~AnalyzerContextDecl() {
{
delete context_name_id_; delete context_name_id_;
delete param_type_; delete param_type_;
delete_list(ContextFieldList, context_fields_); delete_list(ContextFieldList, context_fields_);
} }
void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h) void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h) {
{
GenNamespaceBegin(out_h); GenNamespaceBegin(out_h);
TypeDecl::GenForwardDeclaration(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_h);
GenNamespaceBegin(out_cc); GenNamespaceBegin(out_cc);
TypeDecl::GenCode(out_h, 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()); 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()); out->println("} // namespace %s", context_name_id()->Name());
} }
void AnalyzerContextDecl::AddFlowBuffer() void AnalyzerContextDecl::AddFlowBuffer() {
{
if ( flow_buffer_added_ ) if ( flow_buffer_added_ )
return; return;
@ -96,15 +82,13 @@ void AnalyzerContextDecl::AddFlowBuffer()
flow_buffer_added_ = true; 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 // A hack. The orthodox way would be to build an Expr of
// context.flow_buffer_var, and then EvalExpr. // 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(). // Fields will be copied in Type::Clone().
return new DummyType(); return new DummyType();
} }

View file

@ -23,14 +23,12 @@
// accessed as members of the cookie, such as // accessed as members of the cookie, such as
// ``binpac_context.connection''. // ``binpac_context.connection''.
class ContextField : public Field class ContextField : public Field {
{
public: public:
ContextField(ID* id, Type* type); ContextField(ID* id, Type* type);
}; };
class AnalyzerContextDecl : public TypeDecl class AnalyzerContextDecl : public TypeDecl {
{
public: public:
AnalyzerContextDecl(ID* id, ContextFieldList* context_fields); AnalyzerContextDecl(ID* id, ContextFieldList* context_fields);
~AnalyzerContextDecl() override; ~AnalyzerContextDecl() override;
@ -64,36 +62,29 @@ private:
static AnalyzerContextDecl* current_analyzer_context_; static AnalyzerContextDecl* current_analyzer_context_;
}; };
class DummyType : public Type class DummyType : public Type {
{
public: public:
DummyType() : Type(DUMMY) {} DummyType() : Type(DUMMY) {}
bool DefineValueVar() const override { return false; } bool DefineValueVar() const override { return false; }
string DataTypeStr() const override string DataTypeStr() const override {
{
ASSERT(0); ASSERT(0);
return ""; return "";
} }
int StaticSize(Env* env) const override int StaticSize(Env* env) const override {
{
ASSERT(0); ASSERT(0);
return -1; return -1;
} }
bool ByteOrderSensitive() const override { return false; } bool ByteOrderSensitive() const override { return false; }
bool IsPointerType() const override bool IsPointerType() const override {
{
ASSERT(0); ASSERT(0);
return false; return false;
} }
void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override { ASSERT(0); }
{
ASSERT(0);
}
// Generate code for computing the dynamic size of the type // Generate code for computing the dynamic size of the type
void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override { ASSERT(0); } void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override { ASSERT(0); }

View file

@ -3,11 +3,9 @@
#include "pac_dbg.h" #include "pac_dbg.h"
#include "pac_exception.h" #include "pac_exception.h"
namespace namespace {
{
class EscapeException class EscapeException {
{
public: public:
explicit EscapeException(const string& s) { msg_ = s; } explicit EscapeException(const string& s) { msg_ = s; }
@ -18,24 +16,15 @@ private:
}; };
// Copied from util.cc of Zeek // Copied from util.cc of Zeek
int expand_escape(const char*& s) int expand_escape(const char*& s) {
{ switch ( *(s++) ) {
switch ( *(s++) ) case 'b': return '\b';
{ case 'f': return '\f';
case 'b': case 'n': return '\n';
return '\b'; case 'r': return '\r';
case 'f': case 't': return '\t';
return '\f'; case 'a': return '\a';
case 'n': case 'v': return '\v';
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'a':
return '\a';
case 'v':
return '\v';
case '0': case '0':
case '1': case '1':
@ -44,8 +33,7 @@ int expand_escape(const char*& s)
case '4': case '4':
case '5': case '5':
case '6': case '6':
case '7': case '7': { // \<octal>{1,3}
{ // \<octal>{1,3}
--s; // put back the first octal digit --s; // put back the first octal digit
const char* start = s; const char* start = s;
@ -67,8 +55,7 @@ int expand_escape(const char*& s)
return result; return result;
} }
case 'x': case 'x': { /* \x<hex> */
{ /* \x<hex> */
const char* start = s; const char* start = s;
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir". // Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
@ -82,18 +69,15 @@ int expand_escape(const char*& s)
return result; return result;
} }
default: default: return s[-1];
return s[-1];
} }
} }
} // private namespace } // namespace
ConstString::ConstString(const string& s) : str_(s) ConstString::ConstString(const string& s) : str_(s) {
{
// Copied from scan.l of Zeek // Copied from scan.l of Zeek
try try {
{
const char* text = str_.c_str(); const char* text = str_.c_str();
int len = strlen(text) + 1; int len = strlen(text) + 1;
int i = 0; int i = 0;
@ -101,16 +85,13 @@ ConstString::ConstString(const string& s) : str_(s)
char* new_s = new char[len]; char* new_s = new char[len];
// Skip leading quote. // Skip leading quote.
for ( ++text; *text; ++text ) for ( ++text; *text; ++text ) {
{ if ( *text == '\\' ) {
if ( *text == '\\' )
{
++text; // skip '\' ++text; // skip '\'
new_s[i++] = expand_escape(text); new_s[i++] = expand_escape(text);
--text; // point to end of sequence --text; // point to end of sequence
} }
else else {
{
new_s[i++] = *text; new_s[i++] = *text;
} }
} }
@ -122,9 +103,7 @@ ConstString::ConstString(const string& s) : str_(s)
unescaped_ = new_s; unescaped_ = new_s;
delete[] new_s; delete[] new_s;
} } catch ( EscapeException const& e ) {
catch ( EscapeException const& e )
{
// Throw again with the object // Throw again with the object
throw Exception(this, e.msg().c_str()); throw Exception(this, e.msg().c_str());
} }

View file

@ -3,8 +3,7 @@
#include "pac_common.h" #include "pac_common.h"
class ConstString : public Object class ConstString : public Object {
{
public: public:
ConstString(const string& s); ConstString(const string& s);

View file

@ -1,21 +1,13 @@
#include "pac_ctype.h" #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()); }
{
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()); 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()); 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()); }
{
return strfmt("%s *%s", name().c_str(), var.c_str());
}

View file

@ -4,8 +4,7 @@
#include "pac_common.h" #include "pac_common.h"
// Represents a C++ type // Represents a C++ type
class CType class CType {
{
public: public:
CType(const string& name); CType(const string& name);

View file

@ -6,8 +6,7 @@
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 // Avoid infinite loop
if ( in_traversal ) if ( in_traversal )
return true; return true;
@ -25,48 +24,30 @@ bool DataDepElement::Traverse(DataDepVisitor* visitor)
return true; return true;
} }
Expr* DataDepElement::expr() Expr* DataDepElement::expr() { return static_cast<Expr*>(this); }
{
return static_cast<Expr*>(this);
}
Type* DataDepElement::type() Type* DataDepElement::type() { return static_cast<Type*>(this); }
{
return static_cast<Type*>(this);
}
bool RequiresAnalyzerContext::PreProcess(DataDepElement* element) bool RequiresAnalyzerContext::PreProcess(DataDepElement* element) {
{ switch ( element->dde_type() ) {
switch ( element->dde_type() ) case DataDepElement::EXPR: ProcessExpr(element->expr()); break;
{ default: break;
case DataDepElement::EXPR:
ProcessExpr(element->expr());
break;
default:
break;
} }
// Continue traversal until we know the answer is 'yes' // Continue traversal until we know the answer is 'yes'
return ! requires_analyzer_context_; return ! requires_analyzer_context_;
} }
bool RequiresAnalyzerContext::PostProcess(DataDepElement* element) bool RequiresAnalyzerContext::PostProcess(DataDepElement* element) { return ! requires_analyzer_context_; }
{
return ! requires_analyzer_context_;
}
void RequiresAnalyzerContext::ProcessExpr(Expr* expr) void RequiresAnalyzerContext::ProcessExpr(Expr* expr) {
{ if ( expr->expr_type() == Expr::EXPR_ID ) {
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; RequiresAnalyzerContext visitor;
element->Traverse(&visitor); element->Traverse(&visitor);
return visitor.requires_analyzer_context_; return visitor.requires_analyzer_context_;

View file

@ -9,11 +9,9 @@
class DataDepVisitor; class DataDepVisitor;
class DataDepElement class DataDepElement {
{
public: public:
enum DDE_Type enum DDE_Type {
{
ATTR, ATTR,
CASEEXPR, CASEEXPR,
EXPR, EXPR,
@ -41,8 +39,7 @@ protected:
bool in_traversal; bool in_traversal;
}; };
class DataDepVisitor class DataDepVisitor {
{
public: public:
virtual ~DataDepVisitor() {} virtual ~DataDepVisitor() {}
// Returns whether to continue traversal // Returns whether to continue traversal
@ -50,8 +47,7 @@ public:
virtual bool PostProcess(DataDepElement* element) = 0; virtual bool PostProcess(DataDepElement* element) = 0;
}; };
class RequiresAnalyzerContext : public DataDepVisitor class RequiresAnalyzerContext : public DataDepVisitor {
{
public: public:
RequiresAnalyzerContext() : requires_analyzer_context_(false) {} RequiresAnalyzerContext() : requires_analyzer_context_(false) {}

View file

@ -5,10 +5,8 @@
#include "pac_output.h" #include "pac_output.h"
#include "pac_utils.h" #include "pac_utils.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_ ) {
if ( id_ )
{
if ( ! env->Evaluated(id_) ) if ( ! env->Evaluated(id_) )
throw ExceptionIDNotEvaluated(id_); throw ExceptionIDNotEvaluated(id_);
@ -21,27 +19,21 @@ DataPtr::DataPtr(Env* env, const ID* id, const int offset) : id_(id), offset_(of
ptr_expr_ = "(null id)"; ptr_expr_ = "(null id)";
} }
int DataPtr::AbsOffset(const ID* base_ptr) const 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 char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const {
{
if ( AbsOffset(base_ptr) >= 0 ) if ( AbsOffset(base_ptr) >= 0 )
return nfmt("%d", offset()); return nfmt("%d", offset());
else else
return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr)); return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr));
} }
void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size, void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size, const char* data_name) const {
const char* data_name) const
{
ASSERT(id_); ASSERT(id_);
out_cc->println("// Checking out-of-bound for \"%s\"", data_name); 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, 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()); ptr_expr(), data_size, ptr_expr());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");

View file

@ -9,14 +9,12 @@
// A data pointer is represented by an data pointer variable // A data pointer is represented by an data pointer variable
// plus a constant offset. // plus a constant offset.
class DataPtr class DataPtr {
{
public: public:
DataPtr(Env* env, const ID* arg_id, const int arg_off); DataPtr(Env* env, const ID* arg_id, const int arg_off);
DataPtr(DataPtr const& x) { *this = x; } DataPtr(DataPtr const& x) { *this = x; }
DataPtr const& operator=(DataPtr const& x) DataPtr const& operator=(DataPtr const& x) {
{
id_ = x.id(); id_ = x.id();
offset_ = x.offset(); offset_ = x.offset();
ptr_expr_ = x.ptr_expr(); ptr_expr_ = x.ptr_expr();
@ -27,8 +25,7 @@ public:
const ID* id() const { return id_; } const ID* id() const { return id_; }
int offset() const { return offset_; } int offset() const { return offset_; }
const char* ptr_expr() const const char* ptr_expr() const {
{
ASSERT(id_); ASSERT(id_);
return ptr_expr_.c_str(); return ptr_expr_.c_str();
} }
@ -36,8 +33,7 @@ public:
int AbsOffset(const ID* base_ptr) const; int AbsOffset(const ID* base_ptr) const;
char* AbsOffsetExpr(Env* env, const ID* base_ptr) const; char* AbsOffsetExpr(Env* env, const ID* base_ptr) const;
void GenBoundaryCheck(Output* out, Env* env, const char* data_size, void GenBoundaryCheck(Output* out, Env* env, const char* data_size, const char* data_name) const;
const char* data_name) const;
protected: protected:
const ID* id_; const ID* id_;

View file

@ -5,41 +5,33 @@
#include "pac_paramtype.h" #include "pac_paramtype.h"
#include "pac_varfield.h" #include "pac_varfield.h"
AnalyzerDataUnit::AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, AnalyzerDataUnit::AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params)
ExprList* context_params) : AnalyzerElement(DATAUNIT), type_(type), id_(id), type_params_(type_params), context_params_(context_params) {
: AnalyzerElement(DATAUNIT), type_(type), id_(id), type_params_(type_params),
context_params_(context_params)
{
data_type_ = new ParameterizedType(id_, type_params_); data_type_ = new ParameterizedType(id_, type_params_);
context_type_ = new ParameterizedType( context_type_ =
AnalyzerContextDecl::current_analyzer_context()->id()->clone(), context_params_); new ParameterizedType(AnalyzerContextDecl::current_analyzer_context()->id()->clone(), context_params_);
dataunit_var_field_ = new ParseVarField(Field::CLASS_MEMBER, dataunit_id->clone(), data_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()); context_var_field_ = new PrivVarField(analyzer_context_id->clone(), context_type());
} }
AnalyzerDataUnit::~AnalyzerDataUnit() AnalyzerDataUnit::~AnalyzerDataUnit() {
{
delete dataunit_var_field_; delete dataunit_var_field_;
delete context_var_field_; delete context_var_field_;
} }
void AnalyzerDataUnit::Prepare(Env* env) void AnalyzerDataUnit::Prepare(Env* env) {
{
dataunit_var_field_->Prepare(env); dataunit_var_field_->Prepare(env);
context_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(), 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()); 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(),
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()); context_type()->EvalParameters(out_cc, env).c_str());
env->SetEvaluated(analyzer_context_id); env->SetEvaluated(analyzer_context_id);
} }

View file

@ -6,14 +6,9 @@
// The type and parameters of input data unit of a flow. For instance, the // 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. // data unit of a DCE/RPC flow is DCE_RPC_PDU.
class AnalyzerDataUnit : public AnalyzerElement class AnalyzerDataUnit : public AnalyzerElement {
{
public: public:
enum DataUnitType enum DataUnitType { DATAGRAM, FLOWUNIT };
{
DATAGRAM,
FLOWUNIT
};
AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params); AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params);
~AnalyzerDataUnit() override; ~AnalyzerDataUnit() override;

View file

@ -7,6 +7,8 @@
extern bool FLAGS_pac_debug; extern bool FLAGS_pac_debug;
#define ASSERT(x) assert(x) #define ASSERT(x) assert(x)
#define DEBUG_MSG(...) if ( FLAGS_pac_debug ) fprintf(stderr, __VA_ARGS__) #define DEBUG_MSG(...) \
if ( FLAGS_pac_debug ) \
fprintf(stderr, __VA_ARGS__)
#endif /* pac_dbg_h */ #endif /* pac_dbg_h */

View file

@ -17,8 +17,7 @@
DeclList* Decl::decl_list_ = nullptr; DeclList* Decl::decl_list_ = nullptr;
Decl::DeclMap Decl::decl_map_; Decl::DeclMap Decl::decl_map_;
Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(nullptr) Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(nullptr) {
{
decl_map_[id_] = this; decl_map_[id_] = this;
if ( ! decl_list_ ) if ( ! decl_list_ )
decl_list_ = new DeclList(); decl_list_ = new DeclList();
@ -29,53 +28,42 @@ Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlis
analyzer_context_ = nullptr; analyzer_context_ = nullptr;
} }
Decl::~Decl() Decl::~Decl() {
{
delete id_; delete id_;
delete_list(AttrList, attrlist_); delete_list(AttrList, attrlist_);
} }
void Decl::AddAttrs(AttrList* attrs) void Decl::AddAttrs(AttrList* attrs) {
{
if ( ! attrs ) if ( ! attrs )
return; return;
if ( ! attrlist_ ) if ( ! attrlist_ )
attrlist_ = new AttrList(); attrlist_ = new AttrList();
foreach (i, AttrList, attrs) foreach (i, AttrList, attrs) {
{
attrlist_->push_back(*i); attrlist_->push_back(*i);
ProcessAttr(*i); ProcessAttr(*i);
} }
} }
void Decl::ProcessAttr(Attr* attr) void Decl::ProcessAttr(Attr* attr) { throw Exception(attr, "unhandled attribute"); }
{
throw Exception(attr, "unhandled attribute");
}
void Decl::SetAnalyzerContext() void Decl::SetAnalyzerContext() {
{
analyzer_context_ = AnalyzerContextDecl::current_analyzer_context(); analyzer_context_ = AnalyzerContextDecl::current_analyzer_context();
if ( ! 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_ ) if ( ! decl_list_ )
return; return;
foreach (i, DeclList, decl_list_) foreach (i, DeclList, decl_list_) {
{
Decl* decl = *i; Decl* decl = *i;
current_decl_id = decl->id(); current_decl_id = decl->id();
decl->Prepare(); decl->Prepare();
} }
foreach (i, DeclList, decl_list_) foreach (i, DeclList, decl_list_) {
{
Decl* decl = *i; Decl* decl = *i;
current_decl_id = decl->id(); current_decl_id = decl->id();
decl->GenExternDeclaration(out_h); decl->GenExternDeclaration(out_h);
@ -86,8 +74,7 @@ void Decl::ProcessDecls(Output* out_h, Output* out_cc)
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(); current_decl_id = decl->id();
decl->GenForwardDeclaration(out_h); decl->GenForwardDeclaration(out_h);
@ -98,15 +85,13 @@ void Decl::ProcessDecls(Output* out_h, Output* out_cc)
out_h->println(""); out_h->println("");
foreach (i, DeclList, decl_list_) foreach (i, DeclList, decl_list_) {
{
Decl* decl = *i; Decl* decl = *i;
current_decl_id = decl->id(); current_decl_id = decl->id();
decl->GenCode(out_h, out_cc); decl->GenCode(out_h, out_cc);
} }
if ( analyzer_context ) if ( analyzer_context ) {
{
analyzer_context->GenNamespaceEnd(out_h); analyzer_context->GenNamespaceEnd(out_h);
analyzer_context->GenNamespaceEnd(out_cc); analyzer_context->GenNamespaceEnd(out_cc);
} }
@ -115,8 +100,7 @@ void Decl::ProcessDecls(Output* out_h, Output* out_cc)
out_cc->println("} // namespace binpac"); out_cc->println("} // namespace binpac");
} }
Decl* Decl::LookUpDecl(const ID* id) Decl* Decl::LookUpDecl(const ID* id) {
{
DeclMap::iterator it = decl_map_.find(id); DeclMap::iterator it = decl_map_.find(id);
if ( it == decl_map_.end() ) if ( it == decl_map_.end() )
return nullptr; return nullptr;
@ -126,30 +110,26 @@ Decl* Decl::LookUpDecl(const ID* id)
int HelperDecl::helper_id_seq = 0; int HelperDecl::helper_id_seq = 0;
HelperDecl::HelperDecl(HelperType helper_type, ID* context_id, EmbeddedCode* 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), : Decl(new ID(strfmt("helper_%d", ++helper_id_seq)), HELPER),
context_id_(context_id), code_(code) helper_type_(helper_type),
{ context_id_(context_id),
} code_(code) {}
HelperDecl::~HelperDecl() HelperDecl::~HelperDecl() {
{
delete context_id_; delete context_id_;
delete code_; delete code_;
} }
void HelperDecl::Prepare() void HelperDecl::Prepare() {
{
// Do nothing // Do nothing
} }
void HelperDecl::GenExternDeclaration(Output* out_h) void HelperDecl::GenExternDeclaration(Output* out_h) {
{
if ( helper_type_ == EXTERN ) if ( helper_type_ == EXTERN )
code_->GenCode(out_h, global_env()); 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 0

View file

@ -4,23 +4,11 @@
#include "pac_common.h" #include "pac_common.h"
#include "pac_id.h" #include "pac_id.h"
class Decl : public Object class Decl : public Object {
{
public: public:
// Note: ANALYZER is not for AnalyzerDecl (which is an // Note: ANALYZER is not for AnalyzerDecl (which is an
// abstract class) , but for AnalyzerContextDecl. // abstract class) , but for AnalyzerContextDecl.
enum DeclType enum DeclType { ENUM, LET, TYPE, FUNC, CONN, FLOW, ANALYZER, HELPER, REGEX };
{
ENUM,
LET,
TYPE,
FUNC,
CONN,
FLOW,
ANALYZER,
HELPER,
REGEX
};
Decl(ID* id, DeclType decl_type); Decl(ID* id, DeclType decl_type);
virtual ~Decl(); virtual ~Decl();
@ -35,8 +23,7 @@ public:
virtual void Prepare() = 0; virtual void Prepare() = 0;
// Generate declarations out of the "binpac" namespace // Generate declarations out of the "binpac" namespace
virtual void GenExternDeclaration(Output* out_h) virtual void GenExternDeclaration(Output* out_h) { /* do nothing */
{ /* do nothing */
} }
// Generate declarations before definition of classes // Generate declarations before definition of classes
@ -66,11 +53,9 @@ private:
static DeclMap decl_map_; static DeclMap decl_map_;
}; };
class HelperDecl : public Decl class HelperDecl : public Decl {
{
public: public:
enum HelperType enum HelperType {
{
HEADER, HEADER,
CODE, CODE,
EXTERN, EXTERN,
@ -80,8 +65,7 @@ public:
void Prepare() override; void Prepare() override;
void GenExternDeclaration(Output* out_h) override; void GenExternDeclaration(Output* out_h) override;
void GenForwardDeclaration(Output* out_h) override void GenForwardDeclaration(Output* out_h) override { /* do nothing */
{ /* do nothing */
} }
void GenCode(Output* out_h, Output* out_cc) override; void GenCode(Output* out_h, Output* out_cc) override;

View file

@ -6,55 +6,34 @@
EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(nullptr) {} EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(nullptr) {}
EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive* primitive) EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive* primitive) : s_(""), primitive_(primitive) {}
: s_(""), primitive_(primitive) { }
EmbeddedCodeSegment::~EmbeddedCodeSegment() EmbeddedCodeSegment::~EmbeddedCodeSegment() { delete primitive_; }
{
delete primitive_;
}
string EmbeddedCodeSegment::ToCode(Env* env) string EmbeddedCodeSegment::ToCode(Env* env) {
{
if ( primitive_ && s_.empty() ) if ( primitive_ && s_.empty() )
s_ = primitive_->ToCode(env); s_ = primitive_->ToCode(env);
return s_; return s_;
} }
EmbeddedCode::EmbeddedCode() EmbeddedCode::EmbeddedCode() { segments_ = new EmbeddedCodeSegmentList(); }
{
segments_ = new EmbeddedCodeSegmentList();
}
EmbeddedCode::~EmbeddedCode() EmbeddedCode::~EmbeddedCode() { delete_list(EmbeddedCodeSegmentList, segments_); }
{
delete_list(EmbeddedCodeSegmentList, segments_);
}
void EmbeddedCode::Append(int atom) void EmbeddedCode::Append(int atom) { current_segment_ += static_cast<char>(atom); }
{
current_segment_ += static_cast<char>(atom);
}
void EmbeddedCode::Append(const char* str) void EmbeddedCode::Append(const char* str) { current_segment_ += str; }
{
current_segment_ += str;
}
void EmbeddedCode::Append(PacPrimitive* primitive) void EmbeddedCode::Append(PacPrimitive* primitive) {
{ if ( ! current_segment_.empty() ) {
if ( ! current_segment_.empty() )
{
segments_->push_back(new EmbeddedCodeSegment(current_segment_)); segments_->push_back(new EmbeddedCodeSegment(current_segment_));
current_segment_ = ""; current_segment_ = "";
} }
segments_->push_back(new EmbeddedCodeSegment(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() ) {
if ( ! current_segment_.empty() )
{
segments_->push_back(new EmbeddedCodeSegment(current_segment_)); segments_->push_back(new EmbeddedCodeSegment(current_segment_));
current_segment_ = ""; current_segment_ = "";
} }
@ -66,8 +45,7 @@ void EmbeddedCode::GenCode(Output* out, Env* env)
// ID's name is used as its RValue // ID's name is used as its RValue
env->set_allow_undefined_id(true); 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()); out->print("%s", segment->ToCode(env).c_str());
} }

View file

@ -3,8 +3,7 @@
#include "pac_common.h" #include "pac_common.h"
class EmbeddedCodeSegment class EmbeddedCodeSegment {
{
public: public:
explicit EmbeddedCodeSegment(const string& s); explicit EmbeddedCodeSegment(const string& s);
explicit EmbeddedCodeSegment(PacPrimitive* primitive); explicit EmbeddedCodeSegment(PacPrimitive* primitive);
@ -19,8 +18,7 @@ private:
typedef vector<EmbeddedCodeSegment*> EmbeddedCodeSegmentList; typedef vector<EmbeddedCodeSegment*> EmbeddedCodeSegmentList;
class EmbeddedCode : public Object class EmbeddedCode : public Object {
{
public: public:
EmbeddedCode(); EmbeddedCode();
~EmbeddedCode(); ~EmbeddedCode();

View file

@ -8,17 +8,14 @@
Enum::Enum(ID* id, Expr* expr) : id_(id), expr_(expr) {} Enum::Enum(ID* id, Expr* expr) : id_(id), expr_(expr) {}
Enum::~Enum() Enum::~Enum() {
{
delete id_; delete id_;
delete expr_; delete expr_;
} }
void Enum::GenHeader(Output* out_h, int* pval) void Enum::GenHeader(Output* out_h, int* pval) {
{
ASSERT(pval); ASSERT(pval);
if ( expr_ ) if ( expr_ ) {
{
if ( ! expr_->ConstFold(global_env(), pval) ) if ( ! expr_->ConstFold(global_env(), pval) )
throw ExceptionNonConstExpr(expr_); throw ExceptionNonConstExpr(expr_);
out_h->println("%s = %d,", id_->Name(), *pval); out_h->println("%s = %d,", id_->Name(), *pval);
@ -28,31 +25,26 @@ void Enum::GenHeader(Output* out_h, int* pval)
global_env()->AddConstID(id_, *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); datatype_ = new ExternType(type_id, ExternType::NUMBER);
extern_typedecl_ = new TypeDecl(type_id, nullptr, datatype_); extern_typedecl_ = new TypeDecl(type_id, nullptr, datatype_);
} }
EnumDecl::~EnumDecl() EnumDecl::~EnumDecl() {
{
delete_list(EnumList, enumlist_); delete_list(EnumList, enumlist_);
delete extern_typedecl_; delete extern_typedecl_;
} }
void EnumDecl::Prepare() void EnumDecl::Prepare() {
{
// Do nothing // Do nothing
} }
void EnumDecl::GenForwardDeclaration(Output* out_h) void EnumDecl::GenForwardDeclaration(Output* out_h) {
{
out_h->println("enum %s {", id_->Name()); out_h->println("enum %s {", id_->Name());
out_h->inc_indent(); out_h->inc_indent();
int c = 0; int c = 0;
foreach (i, EnumList, enumlist_) foreach (i, EnumList, enumlist_) {
{
(*i)->GenHeader(out_h, &c); (*i)->GenHeader(out_h, &c);
++c; ++c;
} }
@ -60,7 +52,6 @@ void EnumDecl::GenForwardDeclaration(Output* out_h)
out_h->println("};"); out_h->println("};");
} }
void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */) void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */) {
{
// Do nothing // Do nothing
} }

View file

@ -3,8 +3,7 @@
#include "pac_decl.h" #include "pac_decl.h"
class Enum class Enum {
{
public: public:
Enum(ID* id, Expr* expr = 0); Enum(ID* id, Expr* expr = 0);
~Enum(); ~Enum();
@ -16,8 +15,7 @@ private:
Expr* expr_; Expr* expr_;
}; };
class EnumDecl : public Decl class EnumDecl : public Decl {
{
public: public:
EnumDecl(ID* id, EnumList* enumlist); EnumDecl(ID* id, EnumList* enumlist);
~EnumDecl() override; ~EnumDecl() override;

View file

@ -4,75 +4,58 @@
#include "pac_id.h" #include "pac_id.h"
#include "pac_utils.h" #include "pac_utils.h"
Exception::Exception(const Object* o, string msg) Exception::Exception(const Object* o, string msg) {
{ if ( o ) {
if ( o )
{
msg_ = o->Location(); msg_ = o->Location();
msg_ += ": error : "; msg_ += ": error : ";
} }
msg_ += msg; msg_ += msg;
if ( FLAGS_pac_debug ) if ( FLAGS_pac_debug ) {
{
DEBUG_MSG("Exception: %s\n", msg_.c_str()); DEBUG_MSG("Exception: %s\n", msg_.c_str());
abort(); 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())); 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())); 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())); 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())); 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) : 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())); 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()); }
{
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())); append(strfmt("Expression `%s' is not constant", expr->orig()));
} }
ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr) ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr) : Exception(expr), 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) ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr) : Exception(expr), expr(expr) {
: Exception(expr), expr(expr) append(
{ strfmt("Expression `%s' as a case index is outside the numeric limit of the type used "
append(strfmt("Expression `%s' as a case index is outside the numeric limit of the type used "
"for the switch expression", "for the switch expression",
expr->orig())); expr->orig()));
} }

View file

@ -6,8 +6,7 @@ using namespace std;
#include "pac_common.h" #include "pac_common.h"
class Exception class Exception {
{
public: public:
Exception(const Object* o, string msg = ""); Exception(const Object* o, string msg = "");
@ -18,8 +17,7 @@ private:
string msg_; string msg_;
}; };
class ExceptionIDNotFound : public Exception class ExceptionIDNotFound : public Exception {
{
public: public:
ExceptionIDNotFound(const ID* id); ExceptionIDNotFound(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
@ -28,8 +26,7 @@ private:
const ID* id_; const ID* id_;
}; };
class ExceptionIDRedefinition : public Exception class ExceptionIDRedefinition : public Exception {
{
public: public:
ExceptionIDRedefinition(const ID* id); ExceptionIDRedefinition(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
@ -38,8 +35,7 @@ private:
const ID* id_; const ID* id_;
}; };
class ExceptionIDNotEvaluated : public Exception class ExceptionIDNotEvaluated : public Exception {
{
public: public:
ExceptionIDNotEvaluated(const ID* id); ExceptionIDNotEvaluated(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
@ -48,8 +44,7 @@ private:
const ID* id_; const ID* id_;
}; };
class ExceptionCyclicDependence : public Exception class ExceptionCyclicDependence : public Exception {
{
public: public:
ExceptionCyclicDependence(const ID* id); ExceptionCyclicDependence(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
@ -58,14 +53,12 @@ private:
const ID* id_; const ID* id_;
}; };
class ExceptionPaddingError : public Exception class ExceptionPaddingError : public Exception {
{
public: public:
ExceptionPaddingError(const Object* o, string msg); ExceptionPaddingError(const Object* o, string msg);
}; };
class ExceptionIDNotField : public Exception class ExceptionIDNotField : public Exception {
{
public: public:
ExceptionIDNotField(const ID* id); ExceptionIDNotField(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
@ -74,8 +67,7 @@ private:
const ID* id_; const ID* id_;
}; };
class ExceptionMemberNotFound : public Exception class ExceptionMemberNotFound : public Exception {
{
public: public:
ExceptionMemberNotFound(const ID* type_id, const ID* member_id); ExceptionMemberNotFound(const ID* type_id, const ID* member_id);
@ -83,8 +75,7 @@ private:
const ID *type_id_, *member_id_; const ID *type_id_, *member_id_;
}; };
class ExceptionNonConstExpr : public Exception class ExceptionNonConstExpr : public Exception {
{
public: public:
ExceptionNonConstExpr(const Expr* expr); ExceptionNonConstExpr(const Expr* expr);
@ -92,8 +83,7 @@ private:
const Expr* expr; const Expr* expr;
}; };
class ExceptionInvalidCaseSizeExpr : public Exception class ExceptionInvalidCaseSizeExpr : public Exception {
{
public: public:
ExceptionInvalidCaseSizeExpr(const Expr* expr); ExceptionInvalidCaseSizeExpr(const Expr* expr);
@ -101,8 +91,7 @@ private:
const Expr* expr; const Expr* expr;
}; };
class ExceptionInvalidCaseLimitExpr : public Exception class ExceptionInvalidCaseLimitExpr : public Exception {
{
public: public:
ExceptionInvalidCaseLimitExpr(const Expr* expr); ExceptionInvalidCaseLimitExpr(const Expr* expr);

File diff suppressed because it is too large Load diff

View file

@ -6,11 +6,9 @@
class CaseExpr; class CaseExpr;
class Expr : public Object, public DataDepElement class Expr : public Object, public DataDepElement {
{
public: public:
enum ExprType enum ExprType {
{
#define EXPR_DEF(type, x, y) type, #define EXPR_DEF(type, x, y) type,
#include "pac_expr.def" #include "pac_expr.def"
#undef EXPR_DEF #undef EXPR_DEF
@ -117,8 +115,7 @@ string EvalExprList(ExprList* exprlist, Output* out, Env* env);
// An entry of the case expression, consisting of one or more constant // An entry of the case expression, consisting of one or more constant
// expressions for the case index and a value expression. // expressions for the case index and a value expression.
class CaseExpr : public Object, public DataDepElement class CaseExpr : public Object, public DataDepElement {
{
public: public:
CaseExpr(ExprList* index, Expr* value); CaseExpr(ExprList* index, Expr* value);
~CaseExpr() override; ~CaseExpr() override;

View file

@ -4,44 +4,29 @@
#include "pac_id.h" #include "pac_id.h"
#include "pac_output.h" #include "pac_output.h"
bool ExternType::DefineValueVar() const bool ExternType::DefineValueVar() const { return true; }
{
return true;
}
string ExternType::DataTypeStr() const string ExternType::DataTypeStr() const {
{ switch ( ext_type_ ) {
switch ( ext_type_ )
{
case PLAIN: case PLAIN:
case NUMBER: case NUMBER: return id_->Name();
return id_->Name(); case POINTER: return string(id_->Name()) + " *";
case POINTER: default: ASSERT(0); return "";
return string(id_->Name()) + " *";
default:
ASSERT(0);
return "";
} }
} }
int ExternType::StaticSize(Env* env) const int ExternType::StaticSize(Env* env) const {
{
ASSERT(0); ASSERT(0);
return -1; return -1;
} }
bool ExternType::ByteOrderSensitive() const bool ExternType::ByteOrderSensitive() const { return false; }
{
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) void ExternType::GenInitCode(Output* out_cc, Env* env) {
{
if ( IsNumericType() ) if ( IsNumericType() )
out_cc->println("%s = 0;", env->LValue(value_var())); out_cc->println("%s = 0;", env->LValue(value_var()));
else if ( IsPointerType() ) else if ( IsPointerType() )
@ -50,20 +35,11 @@ void ExternType::GenInitCode(Output* out_cc, Env* env)
Type::GenInitCode(out_cc, env); Type::GenInitCode(out_cc, env);
} }
void ExternType::DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) void ExternType::DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) { ASSERT(0); }
{
ASSERT(0);
}
void ExternType::GenDynamicSize(Output* out, Env* env, const DataPtr& data) void ExternType::GenDynamicSize(Output* out, Env* env, const DataPtr& data) { ASSERT(0); }
{
ASSERT(0);
}
Type* ExternType::DoClone() const Type* ExternType::DoClone() const { return new ExternType(id_->clone(), ext_type_); }
{
return new ExternType(id_->clone(), ext_type_);
}
// Definitions of pre-defined external types // Definitions of pre-defined external types
@ -71,8 +47,7 @@ Type* ExternType::DoClone() const
#include "pac_externtype.def" #include "pac_externtype.def"
#undef EXTERNTYPE #undef EXTERNTYPE
void ExternType::static_init() void ExternType::static_init() {
{
ID* id; ID* id;
// TypeDecl *decl; // TypeDecl *decl;
// decl = new TypeDecl(id, 0, extern_type_##name); // decl = new TypeDecl(id, 0, extern_type_##name);

View file

@ -8,15 +8,9 @@
// spefication, e.g., in a record field). The type name is copied // spefication, e.g., in a record field). The type name is copied
// literally to the compiled code. // literally to the compiled code.
class ExternType : public Type class ExternType : public Type {
{
public: public:
enum EXTType enum EXTType { PLAIN, NUMBER, POINTER };
{
PLAIN,
NUMBER,
POINTER
};
ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) {} ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) {}
bool DefineValueVar() const override; bool DefineValueVar() const override;

View file

@ -7,30 +7,25 @@
#include "pac_type.h" #include "pac_type.h"
Field::Field(FieldType tof, int 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) : DataDepElement(DataDepElement::FIELD), tof_(tof), flags_(flags), id_(id), type_(type) {
{
decl_id_ = current_decl_id; decl_id_ = current_decl_id;
field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name()); field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name());
attrs_ = nullptr; attrs_ = nullptr;
} }
Field::~Field() Field::~Field() {
{
delete id_; delete id_;
delete type_; delete type_;
delete_list(AttrList, attrs_); delete_list(AttrList, attrs_);
} }
void Field::AddAttr(AttrList* attrs) void Field::AddAttr(AttrList* attrs) {
{
bool delete_attrs = false; bool delete_attrs = false;
if ( ! attrs_ ) if ( ! attrs_ ) {
{
attrs_ = attrs; attrs_ = attrs;
} }
else else {
{
attrs_->insert(attrs_->end(), attrs->begin(), attrs->end()); attrs_->insert(attrs_->end(), attrs->begin(), attrs->end());
delete_attrs = true; delete_attrs = true;
} }
@ -42,42 +37,33 @@ void Field::AddAttr(AttrList* attrs)
delete attrs; delete attrs;
} }
void Field::ProcessAttr(Attr* a) void Field::ProcessAttr(Attr* a) {
{ switch ( a->type() ) {
switch ( a->type() )
{
case ATTR_IF: case ATTR_IF:
if ( tof() != LET_FIELD && tof() != WITHINPUT_FIELD ) if ( tof() != LET_FIELD && tof() != WITHINPUT_FIELD ) {
{ throw Exception(a,
throw Exception(a, "&if can only be applied to a " "&if can only be applied to a "
"let field"); "let field");
} }
break; break;
default: default: break;
break;
} }
if ( type_ ) if ( type_ )
type_->ProcessAttr(a); type_->ProcessAttr(a);
} }
bool Field::anonymous_field() const bool Field::anonymous_field() const { return type_ && type_->anonymous_value_var(); }
{
return type_ && type_->anonymous_value_var();
}
int Field::ValueVarType() const int Field::ValueVarType() const {
{
if ( flags_ & CLASS_MEMBER ) if ( flags_ & CLASS_MEMBER )
return (flags_ & PUBLIC_READABLE) ? MEMBER_VAR : PRIV_MEMBER_VAR; return (flags_ & PUBLIC_READABLE) ? MEMBER_VAR : PRIV_MEMBER_VAR;
else else
return TEMP_VAR; return TEMP_VAR;
} }
void Field::Prepare(Env* env) void Field::Prepare(Env* env) {
{ if ( type_ ) {
if ( type_ )
{
if ( anonymous_field() ) if ( anonymous_field() )
flags_ &= ~(CLASS_MEMBER | PUBLIC_READABLE); flags_ &= ~(CLASS_MEMBER | PUBLIC_READABLE);
if ( ! type_->persistent() ) if ( ! type_->persistent() )
@ -89,40 +75,34 @@ void Field::Prepare(Env* env)
} }
} }
void Field::GenPubDecls(Output* out_h, Env* env) void Field::GenPubDecls(Output* out_h, Env* env) {
{
if ( type_ && (flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER) ) if ( type_ && (flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER) )
type_->GenPubDecls(out_h, env); type_->GenPubDecls(out_h, env);
} }
void Field::GenPrivDecls(Output* out_h, Env* env) void Field::GenPrivDecls(Output* out_h, Env* env) {
{
// Generate private declaration only if it is a class member // Generate private declaration only if it is a class member
if ( type_ && (flags_ & CLASS_MEMBER) ) if ( type_ && (flags_ & CLASS_MEMBER) )
type_->GenPrivDecls(out_h, env); type_->GenPrivDecls(out_h, env);
} }
void Field::GenTempDecls(Output* out_h, Env* env) void Field::GenTempDecls(Output* out_h, Env* env) {
{
// Generate temp field // Generate temp field
if ( type_ && ! (flags_ & CLASS_MEMBER) ) if ( type_ && ! (flags_ & CLASS_MEMBER) )
type_->GenPrivDecls(out_h, env); type_->GenPrivDecls(out_h, env);
} }
void Field::GenInitCode(Output* out_cc, Env* env) void Field::GenInitCode(Output* out_cc, Env* env) {
{
if ( type_ && ! anonymous_field() ) if ( type_ && ! anonymous_field() )
type_->GenInitCode(out_cc, env); type_->GenInitCode(out_cc, env);
} }
void Field::GenCleanUpCode(Output* out_cc, Env* env) void Field::GenCleanUpCode(Output* out_cc, Env* env) {
{
if ( type_ && ! anonymous_field() ) if ( type_ && ! anonymous_field() )
type_->GenCleanUpCode(out_cc, env); type_->GenCleanUpCode(out_cc, env);
} }
bool Field::DoTraverse(DataDepVisitor* visitor) bool Field::DoTraverse(DataDepVisitor* visitor) {
{
// Check parameterized type // Check parameterized type
if ( type_ && ! type_->Traverse(visitor) ) if ( type_ && ! type_->Traverse(visitor) )
return false; return false;
@ -132,8 +112,7 @@ bool Field::DoTraverse(DataDepVisitor* visitor)
return true; return true;
} }
bool Field::RequiresAnalyzerContext() const bool Field::RequiresAnalyzerContext() const {
{
// Check parameterized type // Check parameterized type
if ( type_ && type_->RequiresAnalyzerContext() ) if ( type_ && type_->RequiresAnalyzerContext() )
return true; return true;

View file

@ -6,8 +6,7 @@
// A "field" is a member of class. // A "field" is a member of class.
enum FieldType enum FieldType {
{
CASE_FIELD, CASE_FIELD,
CONTEXT_FIELD, CONTEXT_FIELD,
FLOW_FIELD, FLOW_FIELD,
@ -22,8 +21,7 @@ enum FieldType
WITHINPUT_FIELD, WITHINPUT_FIELD,
}; };
class Field : public Object, public DataDepElement class Field : public Object, public DataDepElement {
{
public: public:
Field(FieldType tof, int flags, ID* id, Type* type); Field(FieldType tof, int flags, ID* id, Type* type);
// Field flags // Field flags

View file

@ -15,56 +15,43 @@
#include "pac_type.h" #include "pac_type.h"
#include "pac_varfield.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) {
: AnalyzerDecl(id, FLOW, params)
{
dataunit_ = nullptr; dataunit_ = nullptr;
conn_decl_ = nullptr; conn_decl_ = nullptr;
flow_buffer_var_field_ = nullptr; flow_buffer_var_field_ = nullptr;
AddElements(elemlist); AddElements(elemlist);
} }
FlowDecl::~FlowDecl() FlowDecl::~FlowDecl() {
{
delete flow_buffer_var_field_; delete flow_buffer_var_field_;
delete dataunit_; delete dataunit_;
} }
ParameterizedType* FlowDecl::flow_buffer_type_ = nullptr; ParameterizedType* FlowDecl::flow_buffer_type_ = nullptr;
ParameterizedType* FlowDecl::flow_buffer_type() ParameterizedType* FlowDecl::flow_buffer_type() {
{ if ( ! flow_buffer_type_ ) {
if ( ! flow_buffer_type_ )
{
flow_buffer_type_ = new ParameterizedType(new ID(kFlowBufferClass), nullptr); flow_buffer_type_ = new ParameterizedType(new ID(kFlowBufferClass), nullptr);
} }
return flow_buffer_type_; return flow_buffer_type_;
} }
void FlowDecl::AddBaseClass(vector<string>* base_classes) const void FlowDecl::AddBaseClass(vector<string>* base_classes) const { base_classes->push_back("binpac::FlowAnalyzer"); }
{
base_classes->push_back("binpac::FlowAnalyzer");
}
void FlowDecl::ProcessFlowElement(AnalyzerFlow* flow_elem) void FlowDecl::ProcessFlowElement(AnalyzerFlow* flow_elem) {
{
throw Exception(flow_elem, "flow should be defined in only a connection declaration"); throw Exception(flow_elem, "flow should be defined in only a connection declaration");
} }
void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) {
{ if ( dataunit_ ) {
if ( dataunit_ )
{
throw Exception(dataunit_elem, "dataunit already defined"); throw Exception(dataunit_elem, "dataunit already defined");
} }
dataunit_ = dataunit_elem; dataunit_ = dataunit_elem;
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) {
{
dataunit_->data_type()->MarkIncrementalInput(); dataunit_->data_type()->MarkIncrementalInput();
flow_buffer_var_field_ = new PubVarField(flow_buffer_id->clone(), flow_buffer_var_field_ = new PubVarField(flow_buffer_id->clone(), FlowDecl::flow_buffer_type()->Clone());
FlowDecl::flow_buffer_type()->Clone());
type_->AddField(flow_buffer_var_field_); type_->AddField(flow_buffer_var_field_);
ASSERT(AnalyzerContextDecl::current_analyzer_context()); ASSERT(AnalyzerContextDecl::current_analyzer_context());
@ -75,11 +62,9 @@ void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem)
} }
} }
void FlowDecl::Prepare() void FlowDecl::Prepare() {
{
// Add the connection parameter // Add the connection parameter
if ( ! conn_decl_ ) 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");
} }
@ -93,13 +78,9 @@ void FlowDecl::Prepare()
dataunit_->Prepare(env_); 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); }
{
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 // Declare the data unit
dataunit_->dataunit_var_field()->GenPrivDecls(out_h, env_); dataunit_->dataunit_var_field()->GenPrivDecls(out_h, env_);
@ -109,28 +90,24 @@ void FlowDecl::GenPrivDecls(Output* out_h, Output* out_cc)
AnalyzerDecl::GenPrivDecls(out_h, out_cc); AnalyzerDecl::GenPrivDecls(out_h, out_cc);
} }
void FlowDecl::GenInitCode(Output* out_cc) void FlowDecl::GenInitCode(Output* out_cc) {
{
AnalyzerDecl::GenInitCode(out_cc); AnalyzerDecl::GenInitCode(out_cc);
out_cc->println("%s = nullptr;", env_->LValue(dataunit_id)); 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(analyzer_context_id));
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) {
{
flow_buffer_var_field_->type()->GenPreParsing(out_cc, env_); flow_buffer_var_field_->type()->GenPreParsing(out_cc, env_);
env_->SetEvaluated(flow_buffer_var_field_->id()); env_->SetEvaluated(flow_buffer_var_field_->id());
} }
} }
void FlowDecl::GenCleanUpCode(Output* out_cc) void FlowDecl::GenCleanUpCode(Output* out_cc) {
{
GenDeleteDataUnit(out_cc); GenDeleteDataUnit(out_cc);
AnalyzerDecl::GenCleanUpCode(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); string proto = strfmt("%s()", kFlowEOF);
out_h->println("void %s;", proto.c_str()); out_h->println("void %s;", proto.c_str());
@ -139,13 +116,11 @@ void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
foreach (i, AnalyzerHelperList, eof_helpers_) foreach (i, AnalyzerHelperList, eof_helpers_) {
{
(*i)->GenCode(nullptr, out_cc, this); (*i)->GenCode(nullptr, out_cc, this);
} }
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) 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(nullptr, nullptr);", kNewData); out_cc->println("%s(nullptr, nullptr);", kNewData);
} }
@ -154,8 +129,7 @@ void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc)
out_cc->dec_indent(); 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); string proto = strfmt("%s(int gap_length)", kFlowGap);
out_h->println("void %s;", proto.c_str()); out_h->println("void %s;", proto.c_str());
@ -164,8 +138,7 @@ void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) 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));
} }
@ -173,13 +146,12 @@ void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc)
out_cc->dec_indent(); 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(begin_of_data, TEMP_VAR, extern_type_const_byteptr);
env_->AddID(end_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, string proto = strfmt("%s(const_byteptr %s, const_byteptr %s)", kNewData, env_->LValue(begin_of_data),
env_->LValue(begin_of_data), env_->LValue(end_of_data)); env_->LValue(end_of_data));
out_h->println("void %s;", proto.c_str()); out_h->println("void %s;", proto.c_str());
@ -194,16 +166,10 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc)
env_->SetEvaluated(begin_of_data); env_->SetEvaluated(begin_of_data);
env_->SetEvaluated(end_of_data); env_->SetEvaluated(end_of_data);
switch ( dataunit_->type() ) switch ( dataunit_->type() ) {
{ case AnalyzerDataUnit::DATAGRAM: GenCodeDatagram(out_cc); break;
case AnalyzerDataUnit::DATAGRAM: case AnalyzerDataUnit::FLOWUNIT: GenCodeFlowUnit(out_cc); break;
GenCodeDatagram(out_cc); default: ASSERT(0);
break;
case AnalyzerDataUnit::FLOWUNIT:
GenCodeFlowUnit(out_cc);
break;
default:
ASSERT(0);
} }
out_cc->println("}"); out_cc->println("}");
@ -213,8 +179,7 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
GenCleanUpCode(out_cc); GenCleanUpCode(out_cc);
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) 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 e;"); out_cc->println("throw e;");
@ -226,37 +191,33 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc)
out_cc->println(""); 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_->data_type()->GenPreParsing(out_cc, env_);
dataunit_->GenNewDataUnit(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_); 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. // Do not just delete dataunit, because we may just want to Unref it.
// out_cc->println("delete %s;", env_->LValue(dataunit_id)); // out_cc->println("delete %s;", env_->LValue(dataunit_id));
dataunit_->data_type()->GenCleanUpCode(out_cc, env_); dataunit_->data_type()->GenCleanUpCode(out_cc, env_);
dataunit_->context_type()->GenCleanUpCode(out_cc, env_); 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), out_cc->println("%s->NewData(%s, %s);", env_->LValue(flow_buffer_id), env_->RValue(begin_of_data),
env_->RValue(begin_of_data), env_->RValue(end_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->inc_indent();
out_cc->println("( !%s->have_pending_request() || %s->ready() ) )", 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("{"); out_cc->println("{");
// Generate a new dataunit if necessary // Generate a new dataunit if necessary
@ -292,15 +253,13 @@ void FlowDecl::GenCodeFlowUnit(Output* out_cc)
out_cc->dec_indent(); 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); 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) ) if ( RequiresAnalyzerContext::compute(unit_datatype) ) {
{
parse_params += ", "; parse_params += ", ";
parse_params += env_->RValue(analyzer_context_id); parse_params += env_->RValue(analyzer_context_id);
} }

View file

@ -3,8 +3,7 @@
#include "pac_analyzer.h" #include "pac_analyzer.h"
class FlowDecl : public AnalyzerDecl class FlowDecl : public AnalyzerDecl {
{
public: public:
FlowDecl(ID* flow_id, ParamList* params, AnalyzerElementList* elemlist); FlowDecl(ID* flow_id, ParamList* params, AnalyzerElementList* elemlist);
~FlowDecl() override; ~FlowDecl() override;

View file

@ -7,14 +7,12 @@
#include "pac_type.h" #include "pac_type.h"
Function::Function(ID* id, Type* type, ParamList* params) Function::Function(ID* id, Type* type, ParamList* params)
: id_(id), type_(type), params_(params), expr_(nullptr), code_(nullptr) : id_(id), type_(type), params_(params), expr_(nullptr), code_(nullptr) {
{
analyzer_decl_ = nullptr; analyzer_decl_ = nullptr;
env_ = nullptr; env_ = nullptr;
} }
Function::~Function() Function::~Function() {
{
delete id_; delete id_;
delete type_; delete type_;
delete_list(ParamList, params_); delete_list(ParamList, params_);
@ -23,56 +21,48 @@ Function::~Function()
delete code_; delete code_;
} }
void Function::Prepare(Env* env) void Function::Prepare(Env* env) {
{
env->AddID(id_, FUNC_ID, type_); env->AddID(id_, FUNC_ID, type_);
env->SetEvaluated(id_); env->SetEvaluated(id_);
env_ = new Env(env, this); 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_->AddID(p->id(), FUNC_PARAM, p->type());
env_->SetEvaluated(p->id()); env_->SetEvaluated(p->id());
} }
} }
void Function::GenForwardDeclaration(Output* out_h) void Function::GenForwardDeclaration(Output* out_h) {
{
// Do nothing // Do nothing
} }
void Function::GenCode(Output* out_h, Output* out_cc) 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 = ""; string class_str = "";
if ( analyzer_decl_ ) if ( analyzer_decl_ )
class_str = strfmt("%s::", analyzer_decl_->id()->Name()); class_str = strfmt("%s::", analyzer_decl_->id()->Name());
string proto_str = strfmt("%s %s%s(%s)", type_->DataTypeStr().c_str(), class_str.c_str(), string proto_str = strfmt("%s %s%s(%s)", type_->DataTypeStr().c_str(), class_str.c_str(), id_->Name(),
id_->Name(), ParamDecls(params_).c_str()); ParamDecls(params_).c_str());
ASSERT(! (expr_ && code_)); ASSERT(! (expr_ && code_));
if ( expr_ ) if ( expr_ ) {
{
out_cc->println("%s", proto_str.c_str()); out_cc->println("%s", proto_str.c_str());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("return static_cast<%s>(%s);", type_->DataTypeStr().c_str(), out_cc->println("return static_cast<%s>(%s);", type_->DataTypeStr().c_str(), expr_->EvalExpr(out_cc, env_));
expr_->EvalExpr(out_cc, env_));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
} }
else if ( code_ ) 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->inc_indent();
@ -87,29 +77,16 @@ void Function::GenCode(Output* out_h, Output* out_cc)
out_cc->println(""); 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()); function_->Prepare(global_env());
} }
FuncDecl::~FuncDecl() FuncDecl::~FuncDecl() { delete function_; }
{
delete function_;
}
void FuncDecl::Prepare() {} void FuncDecl::Prepare() {}
void FuncDecl::GenForwardDeclaration(Output* out_h) void FuncDecl::GenForwardDeclaration(Output* out_h) { function_->GenForwardDeclaration(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); }
{
function_->GenCode(out_h, out_cc);
}
AnalyzerFunction::AnalyzerFunction(Function* function) AnalyzerFunction::AnalyzerFunction(Function* function) : AnalyzerElement(FUNCTION), function_(function) {}
: AnalyzerElement(FUNCTION), function_(function)
{
}

View file

@ -4,8 +4,7 @@
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_decl.h" #include "pac_decl.h"
class Function : public Object class Function : public Object {
{
public: public:
Function(ID* id, Type* type, ParamList* params); Function(ID* id, Type* type, ParamList* params);
~Function(); ~Function();
@ -38,8 +37,7 @@ private:
EmbeddedCode* code_; EmbeddedCode* code_;
}; };
class FuncDecl : public Decl class FuncDecl : public Decl {
{
public: public:
FuncDecl(Function* function); FuncDecl(Function* function);
~FuncDecl() override; ~FuncDecl() override;
@ -54,8 +52,7 @@ private:
Function* function_; Function* function_;
}; };
class AnalyzerFunction : public AnalyzerElement class AnalyzerFunction : public AnalyzerElement {
{
public: public:
AnalyzerFunction(Function* function); AnalyzerFunction(Function* function);

View file

@ -38,21 +38,18 @@ const ID* buffering_state_id = nullptr;
int ID::anonymous_id_seq = 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; id->anonymous_id_ = true;
return id; 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) : env(arg_env), id(arg_id), id_type(arg_id_type) {
{
eval = nullptr; eval = nullptr;
evaluated = in_evaluation = false; evaluated = in_evaluation = false;
setfunc = ""; // except for STATE_VAR setfunc = ""; // except for STATE_VAR
switch ( id_type ) switch ( id_type ) {
{
case MEMBER_VAR: case MEMBER_VAR:
rvalue = strfmt("%s()", id->Name()); rvalue = strfmt("%s()", id->Name());
lvalue = strfmt("%s_", id->Name()); lvalue = strfmt("%s_", id->Name());
@ -100,41 +97,35 @@ IDRecord::IDRecord(Env* arg_env, const ID* arg_id, IDType arg_id_type)
IDRecord::~IDRecord() {} IDRecord::~IDRecord() {}
void IDRecord::SetConstant(int c) void IDRecord::SetConstant(int c) {
{
ASSERT(id_type == CONST); ASSERT(id_type == CONST);
constant_set = true; constant_set = true;
constant = c; constant = c;
} }
bool IDRecord::GetConstant(int* pc) const bool IDRecord::GetConstant(int* pc) const {
{
if ( constant_set ) if ( constant_set )
*pc = constant; *pc = constant;
return constant_set; return constant_set;
} }
void IDRecord::SetMacro(Expr* e) void IDRecord::SetMacro(Expr* e) {
{
ASSERT(id_type == MACRO); ASSERT(id_type == MACRO);
macro = e; macro = e;
} }
Expr* IDRecord::GetMacro() const Expr* IDRecord::GetMacro() const {
{
ASSERT(id_type == MACRO); ASSERT(id_type == MACRO);
return macro; return macro;
} }
void IDRecord::SetEvaluated(bool v) void IDRecord::SetEvaluated(bool v) {
{
if ( v ) if ( v )
ASSERT(! evaluated); ASSERT(! evaluated);
evaluated = v; evaluated = v;
} }
void IDRecord::Evaluate(Output* out, Env* env) void IDRecord::Evaluate(Output* out, Env* env) {
{
if ( evaluated ) if ( evaluated )
return; return;
@ -154,8 +145,7 @@ void IDRecord::Evaluate(Output* out, Env* env)
evaluated = true; evaluated = true;
} }
const char* IDRecord::RValue() const const char* IDRecord::RValue() const {
{
if ( id_type == MACRO ) if ( id_type == MACRO )
return macro->EvalExpr(nullptr, env); return macro->EvalExpr(nullptr, env);
@ -165,34 +155,27 @@ const char* IDRecord::RValue() const
return rvalue.c_str(); return rvalue.c_str();
} }
const char* IDRecord::LValue() const const char* IDRecord::LValue() const {
{
ASSERT(id_type != MACRO && id_type != FUNC_ID); ASSERT(id_type != MACRO && id_type != FUNC_ID);
return lvalue.c_str(); return lvalue.c_str();
} }
Env::Env(Env* parent_env, Object* context_object) Env::Env(Env* parent_env, Object* context_object) : parent(parent_env), context_object_(context_object) {
: parent(parent_env), context_object_(context_object)
{
allow_undefined_id_ = false; allow_undefined_id_ = false;
in_branch_ = false; in_branch_ = false;
} }
Env::~Env() Env::~Env() {
{ for ( id_map_t::iterator it = id_map.begin(); it != id_map.end(); ++it ) {
for ( id_map_t::iterator it = id_map.begin(); it != id_map.end(); ++it )
{
delete it->second; delete it->second;
it->second = 0; it->second = 0;
} }
} }
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()); DEBUG_MSG("To add ID `%s'...\n", id->Name());
id_map_t::iterator it = id_map.find(id); id_map_t::iterator it = id_map.find(id);
if ( it != id_map.end() ) if ( it != id_map.end() ) {
{
DEBUG_MSG("Duplicate definition: `%s'\n", it->first->Name()); DEBUG_MSG("Duplicate definition: `%s'\n", it->first->Name());
throw ExceptionIDRedefinition(id); throw ExceptionIDRedefinition(id);
} }
@ -202,8 +185,7 @@ void Env::AddID(const ID* id, IDType id_type, Type* data_type)
SetDataType(id, 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 ) if ( ! type )
type = extern_type_int; type = extern_type_int;
AddID(id, CONST, type); AddID(id, CONST, type);
@ -211,22 +193,19 @@ void Env::AddConstID(const ID* id, const int c, Type* type)
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)); AddID(id, MACRO, macro->DataType(this));
SetMacro(id, macro); SetMacro(id, macro);
SetEvaluated(id); 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); AddID(id, TEMP_VAR, type);
return id; return id;
} }
IDRecord* Env::lookup(const ID* id, bool recursive, bool raise_exception) const IDRecord* Env::lookup(const ID* id, bool recursive, bool raise_exception) const {
{
ASSERT(id); ASSERT(id);
id_map_t::const_iterator it = id_map.find(id); id_map_t::const_iterator it = id_map.find(id);
@ -242,18 +221,13 @@ IDRecord* Env::lookup(const ID* id, bool recursive, bool raise_exception) const
return nullptr; return nullptr;
} }
IDType Env::GetIDType(const ID* id) const IDType Env::GetIDType(const ID* id) const { return lookup(id, true, true)->GetType(); }
{
return lookup(id, true, true)->GetType();
}
const char* Env::RValue(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 ) if ( r )
return r->RValue(); return r->RValue();
else else {
{
if ( allow_undefined_id() ) if ( allow_undefined_id() )
return id->Name(); return id->Name();
else else
@ -261,25 +235,17 @@ const char* Env::RValue(const ID* id) const
} }
} }
const char* Env::LValue(const ID* id) const const char* Env::LValue(const ID* id) const { return lookup(id, true, true)->LValue(); }
{
return lookup(id, true, true)->LValue();
}
void Env::SetEvalMethod(const ID* id, Evaluatable* eval) void Env::SetEvalMethod(const ID* id, Evaluatable* eval) { lookup(id, true, true)->SetEvalMethod(eval); }
{
lookup(id, true, true)->SetEvalMethod(eval);
}
void Env::Evaluate(Output* out, const ID* id) 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 ) if ( r )
r->Evaluate(out, this); r->Evaluate(out, this);
} }
bool Env::Evaluated(const ID* id) const 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 ) if ( r )
return r->Evaluated(); return r->Evaluated();
@ -288,13 +254,10 @@ bool Env::Evaluated(const ID* id) const
return true; return true;
} }
void Env::SetEvaluated(const ID* id, bool v) void Env::SetEvaluated(const ID* id, bool v) {
{ if ( in_branch() ) {
if ( in_branch() )
{
Field* f = GetField(id); Field* f = GetField(id);
if ( f && f->tof() == LET_FIELD ) if ( f && f->tof() == LET_FIELD ) {
{
throw Exception(context_object_, strfmt("INTERNAL ERROR: " throw Exception(context_object_, strfmt("INTERNAL ERROR: "
"evaluating let field '%s' in a branch! " "evaluating let field '%s' in a branch! "
"To work around this problem, " "To work around this problem, "
@ -314,23 +277,13 @@ void Env::SetEvaluated(const ID* id, bool v)
throw ExceptionIDNotFound(id); throw ExceptionIDNotFound(id);
} }
void Env::SetField(const ID* id, Field* field) void Env::SetField(const ID* id, Field* field) { lookup(id, false, true)->SetField(field); }
{
lookup(id, false, true)->SetField(field);
}
Field* Env::GetField(const ID* id) const Field* Env::GetField(const ID* id) const { return lookup(id, true, true)->GetField(); }
{
return lookup(id, true, true)->GetField();
}
void Env::SetDataType(const ID* id, Type* type) void Env::SetDataType(const ID* id, Type* type) { lookup(id, true, true)->SetDataType(type); }
{
lookup(id, true, true)->SetDataType(type);
}
Type* Env::GetDataType(const ID* id) const Type* Env::GetDataType(const ID* id) const {
{
IDRecord* r = lookup(id, true, false); IDRecord* r = lookup(id, true, false);
if ( r ) if ( r )
return r->GetDataType(); return r->GetDataType();
@ -338,21 +291,16 @@ Type* Env::GetDataType(const ID* id) const
return nullptr; return nullptr;
} }
string Env::DataTypeStr(const ID* id) const string Env::DataTypeStr(const ID* id) const {
{
Type* type = GetDataType(id); Type* type = GetDataType(id);
if ( ! type ) if ( ! type )
throw Exception(id, "data type not defined"); throw Exception(id, "data type not defined");
return type->DataTypeStr(); return type->DataTypeStr();
} }
void Env::SetConstant(const ID* id, int constant) void Env::SetConstant(const ID* id, int constant) { lookup(id, false, true)->SetConstant(constant); }
{
lookup(id, false, true)->SetConstant(constant);
}
bool Env::GetConstant(const ID* id, int* pc) const bool Env::GetConstant(const ID* id, int* pc) const {
{
ASSERT(pc); ASSERT(pc);
// lookup without raising exception // lookup without raising exception
IDRecord* r = lookup(id, true, false); IDRecord* r = lookup(id, true, false);
@ -362,18 +310,11 @@ bool Env::GetConstant(const ID* id, int* pc) const
return false; return false;
} }
void Env::SetMacro(const ID* id, Expr* macro) void Env::SetMacro(const ID* id, Expr* macro) { lookup(id, true, true)->SetMacro(macro); }
{
lookup(id, true, true)->SetMacro(macro);
}
Expr* Env::GetMacro(const ID* id) const Expr* Env::GetMacro(const ID* id) const { return lookup(id, true, true)->GetMacro(); }
{
return lookup(id, true, true)->GetMacro();
}
void init_builtin_identifiers() void init_builtin_identifiers() {
{
default_value_var = new ID("val"); default_value_var = new ID("val");
null_id = new ID("NULL"); null_id = new ID("NULL");
null_byteseg_id = new ID("null_byteseg"); null_byteseg_id = new ID("null_byteseg");
@ -404,12 +345,10 @@ void init_builtin_identifiers()
current_decl_id = null_decl_id; current_decl_id = null_decl_id;
} }
Env* global_env() Env* global_env() {
{
static Env* the_global_env = nullptr; static Env* the_global_env = nullptr;
if ( ! the_global_env ) if ( ! the_global_env ) {
{
the_global_env = new Env(nullptr, nullptr); the_global_env = new Env(nullptr, nullptr);
// These two are defined in binpac.h, so we do not need to // These two are defined in binpac.h, so we do not need to
@ -433,7 +372,4 @@ Env* global_env()
return the_global_env; return the_global_env;
} }
string set_function(const ID* id) string set_function(const ID* id) { return strfmt("set_%s", id->Name()); }
{
return strfmt("set_%s", id->Name());
}

View file

@ -22,8 +22,7 @@ using namespace std;
// Env -- a mapping from ID names to their L/R-value expressions and evaluation // Env -- a mapping from ID names to their L/R-value expressions and evaluation
// methods. // methods.
enum IDType enum IDType {
{
CONST, CONST,
GLOBAL_VAR, GLOBAL_VAR,
TEMP_VAR, TEMP_VAR,
@ -41,13 +40,9 @@ class IDRecord;
class Env; class Env;
class Evaluatable; class Evaluatable;
class ID : public Object class ID : public Object {
{
public: 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()); }
{
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(); }
@ -72,19 +67,16 @@ private:
}; };
// A comparison operator for pointers to ID's. // A comparison operator for pointers to ID's.
class ID_ptr_cmp class ID_ptr_cmp {
{
public: 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(id1);
ASSERT(id2); ASSERT(id2);
return id1->name < id2->name; return id1->name < id2->name;
} }
}; };
class IDRecord class IDRecord {
{
public: public:
IDRecord(Env* env, const ID* id, IDType id_type); IDRecord(Env* env, const ID* id, IDType id_type);
~IDRecord(); ~IDRecord();
@ -134,15 +126,13 @@ protected:
Evaluatable* eval; Evaluatable* eval;
}; };
class Evaluatable class Evaluatable {
{
public: public:
virtual ~Evaluatable() {} virtual ~Evaluatable() {}
virtual void GenEval(Output* out, Env* env) = 0; virtual void GenEval(Output* out, Env* env) = 0;
}; };
class Env class Env {
{
public: public:
Env(Env* parent_env, Object* context_object); Env(Env* parent_env, Object* context_object);
~Env(); ~Env();

View file

@ -8,28 +8,23 @@
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) ) if ( expr_ && ! expr_->Traverse(visitor) )
return false; return false;
return true; return true;
} }
bool InputBuffer::RequiresAnalyzerContext() const bool InputBuffer::RequiresAnalyzerContext() const { return expr_->RequiresAnalyzerContext(); }
{
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(begin_of_data, TEMP_VAR, extern_type_const_byteptr);
env->AddID(end_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(), out_cc->println("%s %s, %s;", extern_type_const_byteptr->DataTypeStr().c_str(), env->LValue(begin_of_data),
env->LValue(begin_of_data), env->LValue(end_of_data)); env->LValue(end_of_data));
out_cc->println("get_pointers(%s, &%s, &%s);", expr_->EvalExpr(out_cc, env), out_cc->println("get_pointers(%s, &%s, &%s);", expr_->EvalExpr(out_cc, env), env->LValue(begin_of_data),
env->LValue(begin_of_data), env->LValue(end_of_data)); env->LValue(end_of_data));
env->SetEvaluated(begin_of_data); env->SetEvaluated(begin_of_data);
env->SetEvaluated(end_of_data); env->SetEvaluated(end_of_data);

View file

@ -6,8 +6,7 @@
class Expr; class Expr;
class InputBuffer : public Object, public DataDepElement class InputBuffer : public Object, public DataDepElement {
{
public: public:
InputBuffer(Expr* expr); InputBuffer(Expr* expr);

View file

@ -5,39 +5,27 @@
#include "pac_output.h" #include "pac_output.h"
#include "pac_type.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) LetField::LetField(ID* id, Type* type, Expr* expr)
: Field(LET_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), : Field(LET_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), expr_(expr) {
expr_(expr)
{
ASSERT(expr_); ASSERT(expr_);
} }
LetField::~LetField() LetField::~LetField() { delete expr_; }
{
delete expr_;
}
bool LetField::DoTraverse(DataDepVisitor* visitor) bool LetField::DoTraverse(DataDepVisitor* visitor) { return Field::DoTraverse(visitor) && expr()->Traverse(visitor); }
{
return Field::DoTraverse(visitor) && expr()->Traverse(visitor);
}
bool LetField::RequiresAnalyzerContext() const bool LetField::RequiresAnalyzerContext() const {
{
return Field::RequiresAnalyzerContext() || (expr() && expr()->RequiresAnalyzerContext()); return Field::RequiresAnalyzerContext() || (expr() && expr()->RequiresAnalyzerContext());
} }
void LetField::Prepare(Env* env) void LetField::Prepare(Env* env) {
{ if ( ! type_ ) {
if ( ! type_ )
{
ASSERT(expr_); ASSERT(expr_);
type_ = expr_->DataType(env); type_ = expr_->DataType(env);
if ( type_ ) if ( type_ )
@ -53,11 +41,9 @@ void LetField::Prepare(Env* env)
env->SetEvalMethod(id_, this); env->SetEvalMethod(id_, this);
} }
void LetField::GenInitCode(Output* out_cc, Env* env) void LetField::GenInitCode(Output* out_cc, Env* env) {
{
int v; int v;
if ( expr_ && expr_->ConstFold(env, &v) ) if ( expr_ && expr_->ConstFold(env, &v) ) {
{
DEBUG_MSG("Folding const for `%s'\n", id_->Name()); DEBUG_MSG("Folding const for `%s'\n", id_->Name());
GenEval(out_cc, env); GenEval(out_cc, env);
} }
@ -65,13 +51,11 @@ void LetField::GenInitCode(Output* out_cc, Env* env)
type_->GenInitCode(out_cc, env); type_->GenInitCode(out_cc, env);
} }
void LetField::GenParseCode(Output* out_cc, Env* env) void LetField::GenParseCode(Output* out_cc, Env* env) {
{
if ( env->Evaluated(id_) ) if ( env->Evaluated(id_) )
return; return;
if ( type_->attr_if_expr() ) if ( type_->attr_if_expr() ) {
{
// A conditional field // A conditional field
env->Evaluate(out_cc, type_->has_value_var()); env->Evaluate(out_cc, type_->has_value_var());
@ -88,22 +72,16 @@ void LetField::GenParseCode(Output* out_cc, Env* env)
if ( ! env->Evaluated(id_) ) if ( ! env->Evaluated(id_) )
env->SetEvaluated(id_); env->SetEvaluated(id_);
if ( type_->attr_if_expr() ) if ( type_->attr_if_expr() ) {
{
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
} }
} }
void LetField::GenEval(Output* out_cc, Env* env) void LetField::GenEval(Output* out_cc, Env* env) { GenParseCode(out_cc, 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_ ) {
if ( ! type_ )
{
ASSERT(expr_); ASSERT(expr_);
type_ = expr_->DataType(global_env()); type_ = expr_->DataType(global_env());
if ( type_ ) if ( type_ )
@ -120,8 +98,7 @@ LetDecl::LetDecl(ID* id, Type* type, Expr* expr) : Decl(id, LET), type_(type), e
env->AddID(id_, GLOBAL_VAR, type_); env->AddID(id_, GLOBAL_VAR, type_);
} }
LetDecl::~LetDecl() LetDecl::~LetDecl() {
{
delete type_; delete type_;
delete expr_; delete expr_;
} }
@ -130,14 +107,12 @@ 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()); 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()); 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));

View file

@ -4,8 +4,7 @@
#include "pac_decl.h" #include "pac_decl.h"
#include "pac_field.h" #include "pac_field.h"
class LetField : public Field, Evaluatable class LetField : public Field, Evaluatable {
{
public: public:
LetField(ID* arg_id, Type* type, Expr* arg_expr); LetField(ID* arg_id, Type* type, Expr* arg_expr);
~LetField() override; ~LetField() override;
@ -27,8 +26,7 @@ protected:
Expr* expr_; Expr* expr_;
}; };
class LetDecl : public Decl, Evaluatable class LetDecl : public Decl, Evaluatable {
{
public: public:
LetDecl(ID* id, Type* type, Expr* expr); LetDecl(ID* id, Type* type, Expr* expr);
~LetDecl() override; ~LetDecl() override;

View file

@ -25,11 +25,9 @@ vector<string> FLAGS_include_directories;
Output* header_output = nullptr; Output* header_output = nullptr;
Output* source_output = nullptr; Output* source_output = nullptr;
void add_to_include_directories(string dirs) void add_to_include_directories(string dirs) {
{
unsigned int dir_begin = 0, dir_end; unsigned int dir_begin = 0, dir_end;
while ( dir_begin < dirs.length() ) 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] == ':' ) if ( dirs[dir_end] == ':' )
break; break;
@ -45,19 +43,16 @@ void add_to_include_directories(string dirs)
} }
} }
void pac_init() void pac_init() {
{
init_builtin_identifiers(); init_builtin_identifiers();
Type::init(); Type::init();
} }
void insert_comments(Output* out, const char* source_filename) 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) void insert_basictype_defs(Output* out) {
{
out->println("#ifndef pac_type_defs"); out->println("#ifndef pac_type_defs");
out->println("#define pac_type_defs"); out->println("#define pac_type_defs");
out->println(""); out->println("");
@ -76,16 +71,14 @@ void insert_basictype_defs(Output* out)
out->println(""); out->println("");
} }
void insert_byteorder_macros(Output* out) void insert_byteorder_macros(Output* out) {
{
out->println("#define FixByteOrder16(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap16(x))"); 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 FixByteOrder32(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap32(x))");
out->println("#define FixByteOrder64(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap64(x))"); out->println("#define FixByteOrder64(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap64(x))");
out->println(""); out->println("");
} }
const char* to_id(const char* s) const char* to_id(const char* s) {
{
static char t[1024]; static char t[1024];
int i; int i;
for ( i = 0; s[i] && i < (int)sizeof(t) - 1; ++i ) for ( i = 0; s[i] && i < (int)sizeof(t) - 1; ++i )
@ -96,11 +89,9 @@ const char* to_id(const char* s)
return t; return t;
} }
int compile(const char* filename) int compile(const char* filename) {
{
FILE* fp_input = fopen(filename, "r"); FILE* fp_input = fopen(filename, "r");
if ( ! fp_input ) if ( ! fp_input ) {
{
string tmp = strfmt("Error in opening %s", filename); string tmp = strfmt("Error in opening %s", filename);
perror(tmp.c_str()); perror(tmp.c_str());
return -1; return -1;
@ -109,8 +100,7 @@ int compile(const char* filename)
string basename; string basename;
if ( ! FLAGS_output_directory.empty() ) if ( ! FLAGS_output_directory.empty() ) {
{
// Strip leading directories of filename // Strip leading directories of filename
const char* last_slash = strrchr(filename, '/'); const char* last_slash = strrchr(filename, '/');
if ( last_slash ) if ( last_slash )
@ -123,8 +113,7 @@ int compile(const char* filename)
basename = filename; basename = filename;
// If the file name ends with ".pac" // 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); basename = basename.substr(0, basename.length() - 4);
} }
@ -134,8 +123,7 @@ int compile(const char* filename)
int ret = 0; int ret = 0;
try try {
{
switch_to_file(fp_input); switch_to_file(fp_input);
if ( yyparse() ) if ( yyparse() )
return 1; return 1;
@ -170,14 +158,10 @@ int compile(const char* filename)
Decl::ProcessDecls(&out_h, &out_cc); Decl::ProcessDecls(&out_h, &out_cc);
out_h.println("#endif /* %s_h */", filename_id); out_h.println("#endif /* %s_h */", filename_id);
} } catch ( OutputException& e ) {
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; ret = 1;
} } catch ( Exception& e ) {
catch ( Exception& e )
{
fprintf(stderr, "%s\n", e.msg()); fprintf(stderr, "%s\n", e.msg());
exit(1); exit(1);
} }
@ -190,8 +174,7 @@ int compile(const char* filename)
return ret; return ret;
} }
void usage() void usage() {
{
#ifdef BINPAC_VERSION #ifdef BINPAC_VERSION
fprintf(stderr, "binpac version %s\n", BINPAC_VERSION); fprintf(stderr, "binpac version %s\n", BINPAC_VERSION);
#endif #endif
@ -224,8 +207,7 @@ void usage()
#define BINPAC_LSAN_DISABLE() #define BINPAC_LSAN_DISABLE()
#endif #endif
int main(int argc, char* argv[]) int main(int argc, char* argv[]) {
{
// We generally do not care at all if binpac is leaking and other // 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 // projects that use it, like Zeek, only have their build tripped up
// by the default behavior of LSAN to treat leaks as errors. // by the default behavior of LSAN to treat leaks as errors.
@ -235,40 +217,29 @@ int main(int argc, char* argv[])
extern char* malloc_options; extern char* malloc_options;
#endif #endif
int o; int o;
while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 ) while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 ) {
{ switch ( o ) {
switch ( o ) case 'D': yydebug = 1; FLAGS_pac_debug = true;
{
case 'D':
yydebug = 1;
FLAGS_pac_debug = true;
#ifdef HAVE_MALLOC_OPTIONS #ifdef HAVE_MALLOC_OPTIONS
malloc_options = "A"; malloc_options = "A";
#endif #endif
break; break;
case 'q': case 'q': FLAGS_quiet = true; break;
FLAGS_quiet = true;
break;
case 'I': case 'I':
// Add to FLAGS_include_directories // Add to FLAGS_include_directories
add_to_include_directories(optarg); add_to_include_directories(optarg);
break; break;
case 'd': case 'd': FLAGS_output_directory = optarg; break;
FLAGS_output_directory = optarg;
break;
case 'h': case 'h': usage(); break;
usage();
break;
} }
} }
// Strip the trailing '/'s // 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);
} }

View file

@ -3,8 +3,7 @@
#include "pac_common.h" #include "pac_common.h"
class Number : public Object class Number : public Object {
{
public: public:
Number(int arg_n) : s(strfmt("%d", arg_n)), n(arg_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) {} Number(const char* arg_s, int arg_n) : s(arg_s), n(arg_n) {}

View file

@ -7,48 +7,39 @@
#include "pac_utils.h" #include "pac_utils.h"
OutputException::OutputException(const char* arg_msg) OutputException::OutputException(const char* arg_msg) { msg = arg_msg; }
{
msg = arg_msg;
}
OutputException::~OutputException() {} OutputException::~OutputException() {}
Output::Output(string filename) Output::Output(string filename) {
{
fp = fopen(filename.c_str(), "w"); fp = fopen(filename.c_str(), "w");
if ( ! fp ) if ( ! fp )
throw OutputException(strerror(errno)); throw OutputException(strerror(errno));
indent_ = 0; indent_ = 0;
} }
Output::~Output() Output::~Output() {
{
if ( fp ) if ( fp )
fclose(fp); fclose(fp);
} }
int Output::print(const char* fmt, va_list ap) int Output::print(const char* fmt, va_list ap) {
{
int r = vfprintf(fp, fmt, ap); int r = vfprintf(fp, fmt, ap);
if ( r == -1 ) if ( r == -1 )
throw OutputException(strerror(errno)); throw OutputException(strerror(errno));
return r; return r;
} }
int Output::print(const char* fmt, ...) int Output::print(const char* fmt, ...) {
{
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
int r = -1; int r = -1;
try try {
{
r = print(fmt, ap); r = print(fmt, ap);
} }
catch ( ... ) catch ( ... ) {
{
va_end(ap); va_end(ap);
throw; throw;
} }
@ -57,8 +48,7 @@ int Output::print(const char* fmt, ...)
return r; return r;
} }
int Output::println(const char* fmt, ...) int Output::println(const char* fmt, ...) {
{
for ( int i = 0; i < indent(); ++i ) for ( int i = 0; i < indent(); ++i )
fprintf(fp, "\t"); fprintf(fp, "\t");
@ -66,13 +56,11 @@ int Output::println(const char* fmt, ...)
va_start(ap, fmt); va_start(ap, fmt);
int r = -1; int r = -1;
try try {
{
r = print(fmt, ap); r = print(fmt, ap);
} }
catch ( ... ) catch ( ... ) {
{
va_end(ap); va_end(ap);
throw; throw;
} }

View file

@ -7,8 +7,7 @@
using namespace std; using namespace std;
class OutputException class OutputException {
{
public: public:
OutputException(const char* arg_msg); OutputException(const char* arg_msg);
~OutputException(); ~OutputException();
@ -18,8 +17,7 @@ protected:
string msg; string msg;
}; };
class Output class Output {
{
public: public:
Output(string filename); Output(string filename);
~Output(); ~Output();

View file

@ -8,8 +8,7 @@
#include "pac_type.h" #include "pac_type.h"
#include "pac_utils.h" #include "pac_utils.h"
Param::Param(ID* id, Type* type) : id_(id), type_(type) Param::Param(ID* id, Type* type) : id_(id), type_(type) {
{
if ( ! type_ ) if ( ! type_ )
type_ = extern_type_int->Clone(); type_ = extern_type_int->Clone();
@ -20,19 +19,16 @@ Param::Param(ID* id, Type* type) : id_(id), type_(type)
Param::~Param() {} Param::~Param() {}
const string& Param::decl_str() const const string& Param::decl_str() const {
{
ASSERT(! decl_str_.empty()); ASSERT(! decl_str_.empty());
return decl_str_; return decl_str_;
} }
string ParamDecls(ParamList* params) string ParamDecls(ParamList* params) {
{
string param_decls; string param_decls;
int first = 1; int first = 1;
foreach (i, ParamList, params) foreach (i, ParamList, params) {
{
Param* p = *i; Param* p = *i;
const char* decl_str = p->decl_str().c_str(); const char* decl_str = p->decl_str().c_str();
if ( first ) if ( first )
@ -45,18 +41,13 @@ string ParamDecls(ParamList* params)
} }
ParamField::ParamField(const Param* param) ParamField::ParamField(const Param* param)
: Field(PARAM_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, param->id(), : Field(PARAM_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, param->id(), param->type()) {}
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()); env->SetEvaluated(id());
} }
void ParamField::GenCleanUpCode(Output* out_cc, Env* env) void ParamField::GenCleanUpCode(Output* out_cc, Env* env) {
{
// Do nothing // Do nothing
} }

View file

@ -4,8 +4,7 @@
#include "pac_common.h" #include "pac_common.h"
#include "pac_field.h" #include "pac_field.h"
class Param : public Object class Param : public Object {
{
public: public:
Param(ID* id, Type* type); Param(ID* id, Type* type);
~Param(); ~Param();
@ -22,8 +21,7 @@ private:
Field* param_field_; Field* param_field_;
}; };
class ParamField : public Field class ParamField : public Field {
{
public: public:
ParamField(const Param* param); ParamField(const Param* param);

View file

@ -8,57 +8,37 @@
#include "pac_typedecl.h" #include "pac_typedecl.h"
ParameterizedType::ParameterizedType(ID* type_id, ExprList* args) ParameterizedType::ParameterizedType(ID* type_id, ExprList* args)
: Type(PARAMETERIZED), type_id_(type_id), args_(args) : Type(PARAMETERIZED), type_id_(type_id), args_(args) {
{
checking_requires_analyzer_context_ = false; 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)); return strfmt("->%s", ty->env()->RValue(member_id));
} }
string ParameterizedType::class_name() const 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_); }
{
return new ParameterizedType(type_id_->clone(), args_);
}
void ParameterizedType::AddParamArg(Expr* arg) void ParameterizedType::AddParamArg(Expr* arg) { args_->push_back(arg); }
{
args_->push_back(arg);
}
bool ParameterizedType::DefineValueVar() const bool ParameterizedType::DefineValueVar() const { return true; }
{
return true;
}
string ParameterizedType::DataTypeStr() const string ParameterizedType::DataTypeStr() const { return strfmt("%s *", type_id_->Name()); }
{
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 ) if ( ! ref_type )
return nullptr; return nullptr;
return ref_type->MemberDataType(member_id); 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_); Type* type = TypeDecl::LookUpType(type_id_);
if ( ! type ) 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 ) if ( throw_exception )
throw ExceptionIDNotFound(type_id_); throw ExceptionIDNotFound(type_id_);
@ -66,13 +46,9 @@ Type* ParameterizedType::ReferredDataType(bool throw_exception) const
return type; return type;
} }
int ParameterizedType::StaticSize(Env* env) const int ParameterizedType::StaticSize(Env* env) const { return ReferredDataType(true)->StaticSize(env); }
{
return ReferredDataType(true)->StaticSize(env);
}
void ParameterizedType::DoMarkIncrementalInput() void ParameterizedType::DoMarkIncrementalInput() {
{
Type* ty = ReferredDataType(true); Type* ty = ReferredDataType(true);
ty->MarkIncrementalInput(); ty->MarkIncrementalInput();
@ -81,8 +57,7 @@ void ParameterizedType::DoMarkIncrementalInput()
incremental_parsing_ = ty->incremental_parsing(); incremental_parsing_ = ty->incremental_parsing();
} }
Type::BufferMode ParameterizedType::buffer_mode() const 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 // specified on the parameterized type directly than on the type
// declaration. // declaration.
@ -103,13 +78,9 @@ Type::BufferMode ParameterizedType::buffer_mode() const
return NOT_BUFFERABLE; return NOT_BUFFERABLE;
} }
bool ParameterizedType::ByteOrderSensitive() const bool ParameterizedType::ByteOrderSensitive() const { return ReferredDataType(true)->RequiresByteOrder(); }
{
return ReferredDataType(true)->RequiresByteOrder();
}
bool ParameterizedType::DoTraverse(DataDepVisitor* visitor) bool ParameterizedType::DoTraverse(DataDepVisitor* visitor) {
{
if ( ! Type::DoTraverse(visitor) ) if ( ! Type::DoTraverse(visitor) )
return false; return false;
@ -124,8 +95,7 @@ bool ParameterizedType::DoTraverse(DataDepVisitor* visitor)
return true; return true;
} }
bool ParameterizedType::RequiresAnalyzerContext() bool ParameterizedType::RequiresAnalyzerContext() {
{
if ( checking_requires_analyzer_context_ ) if ( checking_requires_analyzer_context_ )
return false; return false;
checking_requires_analyzer_context_ = true; checking_requires_analyzer_context_ = true;
@ -133,15 +103,13 @@ bool ParameterizedType::RequiresAnalyzerContext()
bool ret = false; bool ret = false;
// If any argument expression refers to analyzer context // If any argument expression refers to analyzer context
foreach (i, ExprList, args_) foreach (i, ExprList, args_)
if ( (*i)->RequiresAnalyzerContext() ) if ( (*i)->RequiresAnalyzerContext() ) {
{
ret = true; ret = true;
break; break;
} }
ret = ret || Type::RequiresAnalyzerContext(); ret = ret || Type::RequiresAnalyzerContext();
if ( ! ret ) if ( ! ret ) {
{
Type* ty = ReferredDataType(false); Type* ty = ReferredDataType(false);
if ( ty ) if ( ty )
ret = ty->RequiresAnalyzerContext(); ret = ty->RequiresAnalyzerContext();
@ -151,15 +119,13 @@ bool ParameterizedType::RequiresAnalyzerContext()
return ret; return ret;
} }
void ParameterizedType::GenInitCode(Output* out_cc, Env* env) void ParameterizedType::GenInitCode(Output* out_cc, Env* env) {
{
ASSERT(persistent()); ASSERT(persistent());
out_cc->println("%s = nullptr;", env->LValue(value_var())); out_cc->println("%s = nullptr;", env->LValue(value_var()));
Type::GenInitCode(out_cc, env); Type::GenInitCode(out_cc, env);
} }
void ParameterizedType::GenCleanUpCode(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() ) if ( ty && ty->attr_refcount() )
out_cc->println("Unref(%s);", lvalue()); out_cc->println("Unref(%s);", lvalue());
@ -169,13 +135,11 @@ void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env)
Type::GenCleanUpCode(out_cc, 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; string arg_str;
int first = 1; int first = 1;
foreach (i, ExprList, args_) foreach (i, ExprList, args_) {
{
Expr* e = *i; Expr* e = *i;
if ( first ) if ( first )
first = 0; first = 0;
@ -187,14 +151,11 @@ string ParameterizedType::EvalParameters(Output* out_cc, Env* env) const
return arg_str; 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()); DEBUG_MSG("DoGenParseCode for %s\n", type_id_->Name());
Type* ref_type = ReferredDataType(true); Type* ref_type = ReferredDataType(true);
@ -202,30 +163,25 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr&
const char* parse_func; const char* parse_func;
string parse_params; string parse_params;
if ( buffer_mode() == BUFFER_NOTHING ) if ( buffer_mode() == BUFFER_NOTHING ) {
{
ASSERT(! ref_type->incremental_input()); ASSERT(! ref_type->incremental_input());
parse_func = kParseFuncWithoutBuffer; parse_func = kParseFuncWithoutBuffer;
parse_params = "nullptr, nullptr"; parse_params = "nullptr, nullptr";
} }
else if ( ref_type->incremental_input() ) else if ( ref_type->incremental_input() ) {
{
parse_func = kParseFuncWithBuffer; parse_func = kParseFuncWithBuffer;
parse_params = env->RValue(flow_buffer_id); parse_params = env->RValue(flow_buffer_id);
} }
else else {
{
parse_func = kParseFuncWithoutBuffer; 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) ) if ( RequiresAnalyzerContext::compute(ref_type) ) {
{
parse_params += strfmt(", %s", env->RValue(analyzer_context_id)); parse_params += strfmt(", %s", env->RValue(analyzer_context_id));
} }
if ( ref_type->RequiresByteOrder() ) if ( ref_type->RequiresByteOrder() ) {
{
env->Evaluate(out_cc, byteorder_id); env->Evaluate(out_cc, byteorder_id);
parse_params += strfmt(", %s", env->RValue(byteorder_id)); parse_params += strfmt(", %s", env->RValue(byteorder_id));
} }
@ -234,18 +190,14 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr&
lvalue(), // parse() needs an LValue lvalue(), // parse() needs an LValue
parse_func, parse_params.c_str()); parse_func, parse_params.c_str());
if ( incremental_input() ) if ( incremental_input() ) {
{ if ( buffer_mode() == BUFFER_NOTHING ) {
if ( buffer_mode() == BUFFER_NOTHING )
{
out_cc->println("%s;", call_parse_func.c_str()); out_cc->println("%s;", call_parse_func.c_str());
out_cc->println("%s = true;", env->LValue(parsing_complete_var())); out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
} }
else else {
{
ASSERT(parsing_complete_var()); ASSERT(parsing_complete_var());
out_cc->println("%s = %s;", env->LValue(parsing_complete_var()), out_cc->println("%s = %s;", env->LValue(parsing_complete_var()), call_parse_func.c_str());
call_parse_func.c_str());
// parsing_complete_var might have been already // parsing_complete_var might have been already
// evaluated when set to false // evaluated when set to false
@ -253,21 +205,17 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr&
env->SetEvaluated(parsing_complete_var()); env->SetEvaluated(parsing_complete_var());
} }
} }
else else {
{ if ( AddSizeVar(out_cc, env) ) {
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()); env->SetEvaluated(size_var());
} }
else 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); GenParseCode(out_cc, env, data, 0);
} }

View file

@ -4,8 +4,7 @@
#include "pac_type.h" #include "pac_type.h"
// An instantiated type: ID + expression list // An instantiated type: ID + expression list
class ParameterizedType : public Type class ParameterizedType : public Type {
{
public: public:
ParameterizedType(ID* type_id, ExprList* args); ParameterizedType(ID* type_id, ExprList* args);
~ParameterizedType() override; ~ParameterizedType() override;

View file

@ -5,26 +5,22 @@
#include "pac_id.h" #include "pac_id.h"
#include "pac_type.h" #include "pac_type.h"
string PPVal::ToCode(Env* env) string PPVal::ToCode(Env* env) {
{
ASSERT(expr_); ASSERT(expr_);
return string(expr_->EvalExpr(nullptr, env)); return string(expr_->EvalExpr(nullptr, env));
} }
string PPSet::ToCode(Env* env) string PPSet::ToCode(Env* env) {
{
ASSERT(expr_); ASSERT(expr_);
return expr_->SetFunc(nullptr, env); return expr_->SetFunc(nullptr, env);
} }
string PPType::ToCode(Env* env) string PPType::ToCode(Env* env) {
{
Type* type = expr_->DataType(env); Type* type = expr_->DataType(env);
return type->DataTypeStr(); 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->AddID(id_, TEMP_VAR, type);
env->SetEvaluated(id_); env->SetEvaluated(id_);

View file

@ -3,16 +3,9 @@
#include "pac_common.h" #include "pac_common.h"
class PacPrimitive class PacPrimitive {
{
public: public:
enum PrimitiveType enum PrimitiveType { VAL, SET, TYPE, CONST_DEF };
{
VAL,
SET,
TYPE,
CONST_DEF
};
explicit PacPrimitive(PrimitiveType type) : type_(type) {} explicit PacPrimitive(PrimitiveType type) : type_(type) {}
virtual ~PacPrimitive() {} virtual ~PacPrimitive() {}
@ -25,8 +18,7 @@ private:
PrimitiveType type_; PrimitiveType type_;
}; };
class PPVal : public PacPrimitive class PPVal : public PacPrimitive {
{
public: public:
PPVal(Expr* expr) : PacPrimitive(VAL), expr_(expr) {} PPVal(Expr* expr) : PacPrimitive(VAL), expr_(expr) {}
Expr* expr() const { return expr_; } Expr* expr() const { return expr_; }
@ -37,8 +29,7 @@ private:
Expr* expr_; Expr* expr_;
}; };
class PPSet : public PacPrimitive class PPSet : public PacPrimitive {
{
public: public:
PPSet(Expr* expr) : PacPrimitive(SET), expr_(expr) {} PPSet(Expr* expr) : PacPrimitive(SET), expr_(expr) {}
Expr* expr() const { return expr_; } Expr* expr() const { return expr_; }
@ -49,8 +40,7 @@ private:
Expr* expr_; Expr* expr_;
}; };
class PPType : public PacPrimitive class PPType : public PacPrimitive {
{
public: public:
PPType(Expr* expr) : PacPrimitive(TYPE), expr_(expr) {} PPType(Expr* expr) : PacPrimitive(TYPE), expr_(expr) {}
Expr* expr() const { return expr_; } Expr* expr() const { return expr_; }
@ -61,8 +51,7 @@ private:
Expr* expr_; Expr* expr_;
}; };
class PPConstDef : public PacPrimitive class PPConstDef : public PacPrimitive {
{
public: public:
PPConstDef(const ID* id, Expr* expr) : PacPrimitive(CONST_DEF), id_(id), expr_(expr) {} PPConstDef(const ID* id, Expr* expr) : PacPrimitive(CONST_DEF), id_(id), expr_(expr) {}
const ID* id() const { return id_; } const ID* id() const { return id_; }

View file

@ -12,8 +12,7 @@
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_varfield.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. // Here we assume that the type is a standalone type.
value_var_ = nullptr; value_var_ = nullptr;
@ -27,47 +26,38 @@ RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD)
parsing_dataptr_var_field_ = nullptr; parsing_dataptr_var_field_ = nullptr;
} }
RecordType::~RecordType() RecordType::~RecordType() {
{
// Do not delete_list(RecordFieldList, record_fields_) // Do not delete_list(RecordFieldList, record_fields_)
// because the fields are also in fields_. // because the fields are also in fields_.
delete record_fields_; delete record_fields_;
delete parsing_dataptr_var_field_; delete parsing_dataptr_var_field_;
} }
const ID* RecordType::parsing_dataptr_var() const const ID* RecordType::parsing_dataptr_var() const {
{
return parsing_dataptr_var_field_ ? parsing_dataptr_var_field_->id() : nullptr; return parsing_dataptr_var_field_ ? parsing_dataptr_var_field_->id() : nullptr;
} }
bool RecordType::DefineValueVar() const bool RecordType::DefineValueVar() const { return false; }
{
return false;
}
string RecordType::DataTypeStr() const string RecordType::DataTypeStr() const {
{
ASSERT(type_decl()); 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) void RecordType::Prepare(Env* env, int flags) {
{
ASSERT(flags & TO_BE_PARSED); ASSERT(flags & TO_BE_PARSED);
RecordField* prev = nullptr; RecordField* prev = nullptr;
int offset = 0; int offset = 0;
int seq = 0; int seq = 0;
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_) {
{
RecordField* f = *i; RecordField* f = *i;
f->set_record_type(this); f->set_record_type(this);
f->set_prev(prev); f->set_prev(prev);
if ( prev ) if ( prev )
prev->set_next(f); prev->set_next(f);
prev = f; prev = f;
if ( offset >= 0 ) if ( offset >= 0 ) {
{
f->set_static_offset(offset); f->set_static_offset(offset);
int w = f->StaticSize(env, offset); int w = f->StaticSize(env, offset);
if ( w < 0 ) if ( w < 0 )
@ -79,8 +69,7 @@ void RecordType::Prepare(Env* env, int flags)
f->set_parsing_state_seq(seq); f->set_parsing_state_seq(seq);
} }
if ( incremental_parsing() ) if ( incremental_parsing() ) {
{
#if 0 #if 0
ASSERT(! parsing_state_var_field_); ASSERT(! parsing_state_var_field_);
ID *parsing_state_var_id = new ID("parsing_state"); ID *parsing_state_var_id = new ID("parsing_state");
@ -98,39 +87,24 @@ void RecordType::Prepare(Env* env, int flags)
Type::Prepare(env, flags); Type::Prepare(env, flags);
} }
void RecordType::GenPubDecls(Output* out_h, Env* env) void RecordType::GenPubDecls(Output* out_h, Env* env) { Type::GenPubDecls(out_h, env); }
{
Type::GenPubDecls(out_h, env);
}
void RecordType::GenPrivDecls(Output* out_h, Env* env) void RecordType::GenPrivDecls(Output* out_h, Env* env) { Type::GenPrivDecls(out_h, env); }
{
Type::GenPrivDecls(out_h, env);
}
void RecordType::GenInitCode(Output* out_cc, Env* env) void RecordType::GenInitCode(Output* out_cc, Env* env) { Type::GenInitCode(out_cc, env); }
{
Type::GenInitCode(out_cc, env);
}
void RecordType::GenCleanUpCode(Output* out_cc, Env* env) void RecordType::GenCleanUpCode(Output* out_cc, Env* env) { Type::GenCleanUpCode(out_cc, 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); GenBoundaryCheck(out_cc, env, data);
if ( incremental_parsing() ) 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->println("case 0:");
out_cc->inc_indent(); out_cc->inc_indent();
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_) {
{
RecordField* f = *i; RecordField* f = *i;
f->GenParseCode(out_cc, env); f->GenParseCode(out_cc, env);
out_cc->println(""); out_cc->println("");
@ -140,24 +114,20 @@ void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, i
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("}"); out_cc->println("}");
} }
else else {
{
ASSERT(data.id() == begin_of_data && data.offset() == 0); ASSERT(data.id() == begin_of_data && data.offset() == 0);
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_) {
{
RecordField* f = *i; RecordField* f = *i;
f->GenParseCode(out_cc, env); f->GenParseCode(out_cc, env);
out_cc->println(""); out_cc->println("");
} }
if ( incremental_input() ) if ( incremental_input() ) {
{
ASSERT(parsing_complete_var()); 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) ) 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(), out_cc->println("%s = %s - %s;", env->LValue(size_var()), end_of_record_dataptr.ptr_expr(),
@ -165,24 +135,18 @@ void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, i
env->SetEvaluated(size_var()); env->SetEvaluated(size_var());
} }
if ( ! boundary_checked() ) if ( ! boundary_checked() ) {
{
RecordField* last_field = record_fields_->back(); RecordField* last_field = record_fields_->back();
if ( ! last_field->BoundaryChecked() ) if ( ! last_field->BoundaryChecked() )
GenBoundaryCheck(out_cc, env, data); 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); }
{
GenParseCode(out_cc, env, data, 0);
}
int RecordType::StaticSize(Env* env) const int RecordType::StaticSize(Env* env) const {
{
int tot_w = 0; int tot_w = 0;
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_) {
{
RecordField* f = *i; RecordField* f = *i;
int w = f->StaticSize(env, tot_w); int w = f->StaticSize(env, tot_w);
if ( w < 0 ) if ( w < 0 )
@ -192,8 +156,7 @@ int RecordType::StaticSize(Env* env) const
return tot_w; return tot_w;
} }
void RecordType::SetBoundaryChecked() void RecordType::SetBoundaryChecked() {
{
Type::SetBoundaryChecked(); Type::SetBoundaryChecked();
if ( StaticSize(env()) < 0 || attr_length_expr_ ) if ( StaticSize(env()) < 0 || attr_length_expr_ )
@ -202,31 +165,23 @@ void RecordType::SetBoundaryChecked()
// (whose value is not necessarily trustworthy). // (whose value is not necessarily trustworthy).
return; return;
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_) {
{
RecordField* f = *i; RecordField* f = *i;
f->SetBoundaryChecked(); f->SetBoundaryChecked();
} }
} }
void RecordType::DoMarkIncrementalInput() void RecordType::DoMarkIncrementalInput() {
{ foreach (i, RecordFieldList, record_fields_) {
foreach (i, RecordFieldList, record_fields_)
{
RecordField* f = *i; RecordField* f = *i;
f->type()->MarkIncrementalInput(); f->type()->MarkIncrementalInput();
} }
} }
bool RecordType::DoTraverse(DataDepVisitor* visitor) bool RecordType::DoTraverse(DataDepVisitor* visitor) { return Type::DoTraverse(visitor); }
{
return Type::DoTraverse(visitor);
}
bool RecordType::ByteOrderSensitive() const bool RecordType::ByteOrderSensitive() const {
{ foreach (i, RecordFieldList, record_fields_) {
foreach (i, RecordFieldList, record_fields_)
{
RecordField* f = *i; RecordField* f = *i;
if ( f->RequiresByteOrder() ) if ( f->RequiresByteOrder() )
return true; return true;
@ -235,8 +190,7 @@ bool RecordType::ByteOrderSensitive() const
} }
RecordField::RecordField(FieldType tof, ID* id, Type* type) RecordField::RecordField(FieldType tof, ID* id, Type* type)
: Field(tof, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) : Field(tof, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) {
{
begin_of_field_dataptr = nullptr; begin_of_field_dataptr = nullptr;
end_of_field_dataptr = nullptr; end_of_field_dataptr = nullptr;
field_size_expr = nullptr; field_size_expr = nullptr;
@ -250,8 +204,7 @@ RecordField::RecordField(FieldType tof, ID* id, Type* type)
boundary_checked_ = false; boundary_checked_ = false;
} }
RecordField::~RecordField() RecordField::~RecordField() {
{
delete begin_of_field_dataptr; delete begin_of_field_dataptr;
delete end_of_field_dataptr; delete end_of_field_dataptr;
delete[] field_size_expr; delete[] field_size_expr;
@ -259,41 +212,34 @@ RecordField::~RecordField()
delete end_of_field_dataptr_var; delete end_of_field_dataptr_var;
} }
const DataPtr& RecordField::getFieldBegin(Output* out_cc, Env* env) const DataPtr& RecordField::getFieldBegin(Output* out_cc, Env* env) {
{
if ( prev() ) if ( prev() )
return prev()->getFieldEnd(out_cc, env); return prev()->getFieldEnd(out_cc, env);
else else {
{
// The first field // The first field
if ( ! begin_of_field_dataptr ) 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; return *begin_of_field_dataptr;
} }
} }
const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) {
{
if ( end_of_field_dataptr ) if ( end_of_field_dataptr )
return *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() ) if ( record_type()->incremental_parsing() ) {
{
ASSERT(0); ASSERT(0);
if ( ! end_of_field_dataptr ) 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); ASSERT(dataptr_var);
end_of_field_dataptr = new DataPtr(env, dataptr_var, 0); end_of_field_dataptr = new DataPtr(env, dataptr_var, 0);
} }
} }
else else {
{
int field_offset; int field_offset;
if ( begin_ptr.id() == begin_of_data ) if ( begin_ptr.id() == begin_of_data )
field_offset = begin_ptr.offset(); field_offset = begin_ptr.offset();
@ -303,11 +249,9 @@ const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env)
int field_size = StaticSize(env, field_offset); 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(), end_of_field_dataptr = new DataPtr(env, begin_ptr.id(), begin_ptr.offset() + field_size);
begin_ptr.offset() + field_size);
} }
else else {
{
// If not, we add a variable for the offset after the field // 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())); 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); env->AddID(end_of_field_dataptr_var, TEMP_VAR, extern_type_const_byteptr);
@ -321,8 +265,7 @@ const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env)
return *end_of_field_dataptr; return *end_of_field_dataptr;
} }
const char* RecordField::FieldSize(Output* out_cc, Env* env) const char* RecordField::FieldSize(Output* out_cc, Env* env) {
{
if ( field_size_expr ) if ( field_size_expr )
return field_size_expr; return field_size_expr;
@ -335,8 +278,7 @@ const char* RecordField::FieldSize(Output* out_cc, Env* env)
return field_size_expr; return field_size_expr;
} }
const char* RecordField::FieldOffset(Output* out_cc, Env* env) const char* RecordField::FieldOffset(Output* out_cc, Env* env) {
{
if ( field_offset_expr ) if ( field_offset_expr )
return field_offset_expr; return field_offset_expr;
@ -351,8 +293,7 @@ const char* RecordField::FieldOffset(Output* out_cc, Env* env)
// The reasoning behind AttemptBoundaryCheck is: "If my next field // The reasoning behind AttemptBoundaryCheck is: "If my next field
// can check its boundary, then I don't have to check mine, and it // can check its boundary, then I don't have to check mine, and it
// will save me a boundary-check." // will save me a boundary-check."
bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env) bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env) {
{
if ( boundary_checked_ ) if ( boundary_checked_ )
return true; return true;
@ -364,8 +305,7 @@ bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env)
return false; return false;
// Now we ask the next field to check its boundary. // Now we ask the next field to check its boundary.
if ( next() && next()->AttemptBoundaryCheck(out_cc, env) ) if ( next() && next()->AttemptBoundaryCheck(out_cc, env) ) {
{
// If it works, we are all set // If it works, we are all set
SetBoundaryChecked(); SetBoundaryChecked();
return true; return true;
@ -375,22 +315,17 @@ bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env)
return GenBoundaryCheck(out_cc, 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_); }
{
ASSERT(type_);
}
RecordDataField::~RecordDataField() {} RecordDataField::~RecordDataField() {}
void RecordDataField::Prepare(Env* env) void RecordDataField::Prepare(Env* env) {
{
Field::Prepare(env); Field::Prepare(env);
env->SetEvalMethod(id_, this); env->SetEvalMethod(id_, this);
env->SetField(id_, this); env->SetField(id_, this);
} }
void RecordDataField::GenParseCode(Output* out_cc, Env* env) void RecordDataField::GenParseCode(Output* out_cc, Env* env) {
{
if ( env->Evaluated(id()) ) if ( env->Evaluated(id()) )
return; return;
@ -400,8 +335,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
prev()->GenParseCode(out_cc, env); prev()->GenParseCode(out_cc, env);
DataPtr data(env, nullptr, 0); DataPtr data(env, nullptr, 0);
if ( ! record_type()->incremental_parsing() ) if ( ! record_type()->incremental_parsing() ) {
{
data = getFieldBegin(out_cc, env); data = getFieldBegin(out_cc, env);
Expr* len_expr = record_type()->attr_length_expr(); Expr* len_expr = record_type()->attr_length_expr();
@ -417,8 +351,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
id_->Name()); id_->Name());
#endif #endif
type_->GenPreParsing(out_cc, env); type_->GenPreParsing(out_cc, env);
if ( type_->incremental_input() ) if ( type_->incremental_input() ) {
{
// The enclosing record type must be incrementally parsed // 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->println("/* fall through */");
@ -430,8 +363,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
type_->GenParseCode(out_cc, env, data, 0); type_->GenParseCode(out_cc, env, data, 0);
if ( record_type()->incremental_parsing() ) if ( record_type()->incremental_parsing() ) {
{
ASSERT(type_->incremental_input()); 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());
@ -440,8 +372,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
out_cc->dec_indent(); out_cc->dec_indent();
} }
if ( record_type()->incremental_parsing() ) if ( record_type()->incremental_parsing() ) {
{
#if 0 #if 0
const ID *dataptr_var = const ID *dataptr_var =
record_type()->parsing_dataptr_var(); record_type()->parsing_dataptr_var();
@ -456,29 +387,22 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
SetBoundaryChecked(); SetBoundaryChecked();
} }
void RecordDataField::GenEval(Output* out_cc, Env* env) void RecordDataField::GenEval(Output* out_cc, Env* env) { GenParseCode(out_cc, 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), 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()); field_begin.ptr_expr(), type_->DataSize(out_cc, env, field_begin).c_str());
env->SetEvaluated(end_of_field_dataptr_var); env->SetEvaluated(end_of_field_dataptr_var);
out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(end_of_field_dataptr_var), out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(end_of_field_dataptr_var), env->RValue(end_of_data));
env->RValue(end_of_data));
} }
void RecordDataField::SetBoundaryChecked() void RecordDataField::SetBoundaryChecked() {
{
RecordField::SetBoundaryChecked(); RecordField::SetBoundaryChecked();
type_->SetBoundaryChecked(); type_->SetBoundaryChecked();
} }
bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env) bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env) {
{
if ( boundary_checked_ ) if ( boundary_checked_ )
return true; return true;
@ -488,52 +412,41 @@ bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env)
return true; return true;
} }
bool RecordDataField::DoTraverse(DataDepVisitor* visitor) bool RecordDataField::DoTraverse(DataDepVisitor* visitor) { return Field::DoTraverse(visitor); }
{
return Field::DoTraverse(visitor);
}
bool RecordDataField::RequiresAnalyzerContext() const bool RecordDataField::RequiresAnalyzerContext() const {
{
return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext(); return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext();
} }
RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr) RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr)
: RecordField(PADDING_FIELD, id, nullptr), ptype_(ptype), expr_(expr) : RecordField(PADDING_FIELD, id, nullptr), ptype_(ptype), expr_(expr) {
{
wordsize_ = -1; wordsize_ = -1;
} }
RecordPaddingField::~RecordPaddingField() {} RecordPaddingField::~RecordPaddingField() {}
void RecordPaddingField::Prepare(Env* env) void RecordPaddingField::Prepare(Env* env) {
{
Field::Prepare(env); Field::Prepare(env);
if ( ptype_ == PAD_TO_NEXT_WORD ) if ( ptype_ == PAD_TO_NEXT_WORD ) {
{
if ( ! expr_->ConstFold(env, &wordsize_) ) 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"));
} }
} }
void RecordPaddingField::GenParseCode(Output* out_cc, Env* env) void RecordPaddingField::GenParseCode(Output* out_cc, Env* env) {
{
// Always evaluate record fields in order if parsing // Always evaluate record fields in order if parsing
// is incremental. // is incremental.
if ( record_type()->incremental_parsing() && prev() ) if ( record_type()->incremental_parsing() && prev() )
prev()->GenParseCode(out_cc, env); prev()->GenParseCode(out_cc, env);
} }
int RecordPaddingField::StaticSize(Env* env, int offset) const int RecordPaddingField::StaticSize(Env* env, int offset) const {
{
int length; int length;
int target_offset; int target_offset;
int offset_in_word; int offset_in_word;
switch ( ptype_ ) switch ( ptype_ ) {
{ case PAD_BY_LENGTH: return expr_->ConstFold(env, &length) ? length : -1;
case PAD_BY_LENGTH:
return expr_->ConstFold(env, &length) ? length : -1;
case PAD_TO_OFFSET: case PAD_TO_OFFSET:
// If the current offset cannot be statically // If the current offset cannot be statically
@ -565,16 +478,13 @@ int RecordPaddingField::StaticSize(Env* env, int offset) const
return -1; return -1;
} }
void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin) void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin) {
{
ASSERT(! env->Evaluated(end_of_field_dataptr_var)); ASSERT(! env->Evaluated(end_of_field_dataptr_var));
char* padding_var; char* padding_var;
switch ( ptype_ ) switch ( ptype_ ) {
{
case PAD_BY_LENGTH: case PAD_BY_LENGTH:
out_cc->println("if ( (%s) < 0 ) // check for negative pad length", out_cc->println("if ( (%s) < 0 ) // check for negative pad length", expr_->EvalExpr(out_cc, env));
expr_->EvalExpr(out_cc, env));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(),
@ -583,20 +493,17 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println(""); out_cc->println("");
out_cc->println("const_byteptr const %s = %s + (%s);", out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var),
env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(), field_begin.ptr_expr(), expr_->EvalExpr(out_cc, env));
expr_->EvalExpr(out_cc, env));
out_cc->println("// Checking out-of-bound padding for \"%s\"", field_id_str_.c_str()); 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), env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr());
field_begin.ptr_expr());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); 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), ", expr_->EvalExpr(out_cc, env));
out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var));
env->LValue(end_of_field_dataptr_var));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println(""); out_cc->println("");
@ -605,25 +512,20 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi
case PAD_TO_OFFSET: case PAD_TO_OFFSET:
out_cc->println("const_byteptr %s = %s + (%s);", env->LValue(end_of_field_dataptr_var), 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)); env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env));
out_cc->println("if ( %s < %s )", env->LValue(end_of_field_dataptr_var), out_cc->println("if ( %s < %s )", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr());
field_begin.ptr_expr());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);", out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);", id_->LocName(),
id_->LocName(), field_begin.ptr_expr(), env->RValue(begin_of_data), field_begin.ptr_expr(), env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env));
expr_->EvalExpr(out_cc, env)); out_cc->println("%s = %s;", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr());
out_cc->println("%s = %s;", env->LValue(end_of_field_dataptr_var),
field_begin.ptr_expr());
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("if ( %s > %s )", env->LValue(end_of_field_dataptr_var), out_cc->println("if ( %s > %s )", env->LValue(end_of_field_dataptr_var), env->RValue(end_of_data));
env->RValue(end_of_data));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); 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), ", expr_->EvalExpr(out_cc, env));
out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var));
env->LValue(end_of_field_dataptr_var));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
break; break;
@ -632,11 +534,9 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi
padding_var = nfmt("%s__size", id()->Name()); padding_var = nfmt("%s__size", id()->Name());
out_cc->println("int %s = (%s - %s) %% %d;", padding_var, field_begin.ptr_expr(), out_cc->println("int %s = (%s - %s) %% %d;", padding_var, field_begin.ptr_expr(),
env->RValue(begin_of_data), wordsize_); env->RValue(begin_of_data), wordsize_);
out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", padding_var, padding_var, wordsize_, out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", padding_var, padding_var, wordsize_, padding_var);
padding_var); out_cc->println("const_byteptr const %s = %s + %s;", env->LValue(end_of_field_dataptr_var),
out_cc->println("const_byteptr const %s = %s + %s;", field_begin.ptr_expr(), padding_var);
env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(),
padding_var);
delete[] padding_var; delete[] padding_var;
break; break;
} }
@ -644,8 +544,7 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi
env->SetEvaluated(end_of_field_dataptr_var); env->SetEvaluated(end_of_field_dataptr_var);
} }
bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env) bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env) {
{
if ( boundary_checked_ ) if ( boundary_checked_ )
return true; return true;
@ -664,7 +563,6 @@ bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env)
return true; return true;
} }
bool RecordPaddingField::DoTraverse(DataDepVisitor* visitor) bool RecordPaddingField::DoTraverse(DataDepVisitor* visitor) {
{
return Field::DoTraverse(visitor) && (! expr_ || expr_->Traverse(visitor)); return Field::DoTraverse(visitor) && (! expr_ || expr_->Traverse(visitor));
} }

View file

@ -7,8 +7,7 @@
#include "pac_let.h" #include "pac_let.h"
#include "pac_type.h" #include "pac_type.h"
class RecordType : public Type class RecordType : public Type {
{
public: public:
RecordType(RecordFieldList* fields); RecordType(RecordFieldList* fields);
~RecordType() override; ~RecordType() override;
@ -30,8 +29,7 @@ public:
const ID* parsing_dataptr_var() const; const ID* parsing_dataptr_var() const;
bool IsPointerType() const override bool IsPointerType() const override {
{
ASSERT(0); ASSERT(0);
return false; return false;
} }
@ -56,8 +54,7 @@ private:
// segment of input data, and therefore RecordField's are ordered---each // segment of input data, and therefore RecordField's are ordered---each
// of them has a known previous and next field. // of them has a known previous and next field.
class RecordField : public Field class RecordField : public Field {
{
public: public:
RecordField(FieldType tof, ID* id, Type* type); RecordField(FieldType tof, ID* id, Type* type);
~RecordField() override; ~RecordField() override;
@ -111,8 +108,7 @@ protected:
virtual bool GenBoundaryCheck(Output* out_cc, Env* env) = 0; virtual bool GenBoundaryCheck(Output* out_cc, Env* env) = 0;
}; };
class RecordDataField : public RecordField, public Evaluatable class RecordDataField : public RecordField, public Evaluatable {
{
public: public:
RecordDataField(ID* arg_id, Type* arg_type); RecordDataField(ID* arg_id, Type* arg_type);
~RecordDataField() override; ~RecordDataField() override;
@ -137,33 +133,23 @@ protected:
bool DoTraverse(DataDepVisitor* visitor) override; bool DoTraverse(DataDepVisitor* visitor) override;
}; };
enum PaddingType enum PaddingType { PAD_BY_LENGTH, PAD_TO_OFFSET, PAD_TO_NEXT_WORD };
{
PAD_BY_LENGTH,
PAD_TO_OFFSET,
PAD_TO_NEXT_WORD
};
class RecordPaddingField : public RecordField class RecordPaddingField : public RecordField {
{
public: public:
RecordPaddingField(ID* id, PaddingType ptype, Expr* expr); RecordPaddingField(ID* id, PaddingType ptype, Expr* expr);
~RecordPaddingField() override; ~RecordPaddingField() override;
void Prepare(Env* env) override; void Prepare(Env* env) override;
void GenPubDecls(Output* out, Env* env) override void GenPubDecls(Output* out, Env* env) override { /* nothing */
{ /* nothing */
} }
void GenPrivDecls(Output* out, Env* env) override void GenPrivDecls(Output* out, Env* env) override { /* nothing */
{ /* nothing */
} }
void GenInitCode(Output* out, Env* env) override void GenInitCode(Output* out, Env* env) override { /* nothing */
{ /* nothing */
} }
void GenCleanUpCode(Output* out, Env* env) override void GenCleanUpCode(Output* out, Env* env) override { /* nothing */
{ /* nothing */
} }
void GenParseCode(Output* out, Env* env) override; void GenParseCode(Output* out, Env* env) override;

View file

@ -9,28 +9,23 @@
#include "pac_type.h" #include "pac_type.h"
#include "pac_typedecl.h" #include "pac_typedecl.h"
namespace namespace {
{
Decl* find_decl(const ID* id) Decl* find_decl(const ID* id) {
{
Decl* decl = Decl::LookUpDecl(id); Decl* decl = Decl::LookUpDecl(id);
if ( ! decl ) 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; return decl;
} }
} } // namespace
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 ) 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()));
} }
@ -38,22 +33,18 @@ Decl* ProcessTypeRedef(const ID* id, FieldList* fieldlist)
ASSERT(type_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'. // One cannot change data layout in 'redef'.
// Only 'let' or 'action' can be added // 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); 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 ) else if ( f->tof() == CASE_FIELD ) {
{
throw Exception(f, "use 'redef case' adding cases"); throw Exception(f, "use 'redef case' adding cases");
} }
} }
@ -61,12 +52,10 @@ Decl* ProcessTypeRedef(const ID* id, FieldList* fieldlist)
return decl; 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 ) 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()));
} }
@ -74,16 +63,14 @@ Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist)
ASSERT(type_decl); ASSERT(type_decl);
Type* type = type_decl->type(); Type* type = type_decl->type();
if ( type->tot() != Type::CASE ) 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<CaseType*>(type); CaseType* casetype = static_cast<CaseType*>(type);
ASSERT(casetype); ASSERT(casetype);
foreach (i, CaseFieldList, casefieldlist) foreach (i, CaseFieldList, casefieldlist) {
{
CaseField* f = *i; CaseField* f = *i;
casetype->AddCaseField(f); casetype->AddCaseField(f);
} }
@ -91,12 +78,10 @@ Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist)
return decl; 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 ) 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()));
} }
@ -104,13 +89,11 @@ Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist)
ASSERT(func_decl); ASSERT(func_decl);
Expr* expr = func_decl->function()->expr(); Expr* expr = func_decl->function()->expr();
if ( ! expr || expr->expr_type() != Expr::EXPR_CASE ) 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); expr->AddCaseExpr(e);
} }
@ -118,12 +101,10 @@ Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist)
return decl; 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 ) 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()));
} }
@ -135,12 +116,10 @@ Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerEleme
return decl; 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 ) 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()));
} }

View file

@ -9,16 +9,12 @@
const char* RegEx::kREMatcherType = "RegExMatcher"; const char* RegEx::kREMatcherType = "RegExMatcher";
const char* RegEx::kMatchPrefix = "MatchPrefix"; 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]; char* buf = new char[s.length() * 2 + 1];
int j = 0; 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 ( s[i] == '\\' ) if ( i + 1 < (int)s.length() ) {
{
if ( i + 1 < (int)s.length() )
{
buf[j++] = '\\'; buf[j++] = '\\';
if ( s[i + 1] == '/' ) if ( s[i + 1] == '/' )
buf[j - 1] = s[++i]; buf[j - 1] = s[++i];
@ -28,13 +24,11 @@ string escape_char(const string& s)
buf[j++] = '\\'; buf[j++] = '\\';
} }
} }
else if ( s[i] == '"' ) else if ( s[i] == '"' ) {
{
buf[j++] = '\\'; buf[j++] = '\\';
buf[j++] = '"'; buf[j++] = '"';
} }
else else {
{
buf[j++] = s[i]; buf[j++] = s[i];
} }
} }
@ -46,8 +40,7 @@ string escape_char(const string& s)
return rval; return rval;
} }
RegEx::RegEx(const string& s) RegEx::RegEx(const string& s) {
{
str_ = escape_char(s); str_ = escape_char(s);
string prefix = strfmt("%s_re_", current_decl_id->Name()); string prefix = strfmt("%s_re_", current_decl_id->Name());
matcher_id_ = ID::NewAnonymousID(prefix); matcher_id_ = ID::NewAnonymousID(prefix);
@ -56,24 +49,15 @@ RegEx::RegEx(const string& s)
RegEx::~RegEx() {} RegEx::~RegEx() {}
RegExDecl::RegExDecl(RegEx* regex) : Decl(regex->matcher_id(), REGEX) RegExDecl::RegExDecl(RegEx* regex) : Decl(regex->matcher_id(), REGEX) { regex_ = 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::Prepare() void RegExDecl::GenCode(Output* out_h, Output* out_cc) {
{ out_cc->println("%s %s(\"%s\");\n", RegEx::kREMatcherType, global_env()->LValue(regex_->matcher_id()),
global_env()->AddID(id(), GLOBAL_VAR, extern_type_re_matcher); regex_->str().c_str());
}
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());
} }

View file

@ -6,8 +6,7 @@
class RegExDecl; class RegExDecl;
class RegEx : public Object class RegEx : public Object {
{
public: public:
RegEx(const string& str); RegEx(const string& str);
~RegEx(); ~RegEx();
@ -25,8 +24,7 @@ public:
static const char* kMatchPrefix; static const char* kMatchPrefix;
}; };
class RegExDecl : public Decl class RegExDecl : public Decl {
{
public: public:
RegExDecl(RegEx* regex); RegExDecl(RegEx* regex);

View file

@ -4,21 +4,18 @@
#include "pac_output.h" #include "pac_output.h"
#include "pac_type.h" #include "pac_type.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_),
out_h->println("%s %s const { return %s; }", type_->DataTypeConstRefStr().c_str(), env->LValue(id_));
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(),
out_h->println("void %s(%s x) { %s = x; }", set_function(id_).c_str(), env->LValue(id_));
type_->DataTypeConstRefStr().c_str(), env->LValue(id_));
} }
void StateVar::GenInitCode(Output* out_cc, Env* env) {} void StateVar::GenInitCode(Output* out_cc, Env* env) {}

View file

@ -5,8 +5,7 @@
#include "pac_common.h" #include "pac_common.h"
class StateVar class StateVar {
{
public: public:
StateVar(ID* id, Type* type) : id_(id), type_(type) {} StateVar(ID* id, Type* type) : id_(id), type_(type) {}

View file

@ -15,32 +15,24 @@
const char* StringType::kStringTypeName = "bytestring"; const char* StringType::kStringTypeName = "bytestring";
const char* StringType::kConstStringTypeName = "const_bytestring"; const char* StringType::kConstStringTypeName = "const_bytestring";
StringType::StringType(StringTypeEnum anystr) StringType::StringType(StringTypeEnum anystr) : Type(STRING), type_(ANYSTR), str_(nullptr), regex_(nullptr) {
: Type(STRING), type_(ANYSTR), str_(nullptr), regex_(nullptr)
{
ASSERT(anystr == ANYSTR); ASSERT(anystr == ANYSTR);
init(); init();
} }
StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(nullptr) StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(nullptr) { init(); }
{
init();
}
StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(nullptr), regex_(regex) StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(nullptr), regex_(regex) {
{
ASSERT(regex_); ASSERT(regex_);
init(); init();
} }
void StringType::init() void StringType::init() {
{
string_length_var_field_ = nullptr; string_length_var_field_ = nullptr;
elem_datatype_ = new BuiltInType(BuiltInType::UINT8); elem_datatype_ = new BuiltInType(BuiltInType::UINT8);
} }
StringType::~StringType() StringType::~StringType() {
{
// TODO: Unref for Objects // TODO: Unref for Objects
// Question: why Unref? // Question: why Unref?
// //
@ -51,167 +43,116 @@ StringType::~StringType()
delete elem_datatype_; delete elem_datatype_;
} }
Type* StringType::DoClone() const Type* StringType::DoClone() const {
{
StringType* clone; StringType* clone;
switch ( type_ ) switch ( type_ ) {
{ case ANYSTR: clone = new StringType(ANYSTR); break;
case ANYSTR: case CSTR: clone = new StringType(str_); break;
clone = new StringType(ANYSTR); case REGEX: clone = new StringType(regex_); break;
break; default: ASSERT(0); return nullptr;
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 bool StringType::DefineValueVar() const { return true; }
{
return true;
}
string StringType::DataTypeStr() 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_; }
{
return elem_datatype_;
}
void StringType::ProcessAttr(Attr* a) void StringType::ProcessAttr(Attr* a) {
{
Type::ProcessAttr(a); Type::ProcessAttr(a);
switch ( a->type() ) switch ( a->type() ) {
{ case ATTR_CHUNKED: {
case ATTR_CHUNKED: if ( type_ != ANYSTR ) {
{ throw Exception(a,
if ( type_ != ANYSTR ) "&chunked can be applied"
{
throw Exception(a, "&chunked can be applied"
" to only type bytestring"); " to only type bytestring");
} }
attr_chunked_ = true; attr_chunked_ = true;
SetBoundaryChecked(); SetBoundaryChecked();
} } break;
break;
case ATTR_RESTOFDATA: case ATTR_RESTOFDATA: {
{ if ( type_ != ANYSTR ) {
if ( type_ != ANYSTR ) throw Exception(a,
{ "&restofdata can be applied"
throw Exception(a, "&restofdata can be applied"
" to only type bytestring"); " to only type bytestring");
} }
attr_restofdata_ = true; 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. // data, we do not have to check boundary.
SetBoundaryChecked(); SetBoundaryChecked();
} } break;
break;
case ATTR_RESTOFFLOW: case ATTR_RESTOFFLOW: {
{ if ( type_ != ANYSTR ) {
if ( type_ != ANYSTR ) throw Exception(a,
{ "&restofflow can be applied"
throw Exception(a, "&restofflow can be applied"
" to only type bytestring"); " to only type bytestring");
} }
attr_restofflow_ = true; 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. // flow, we do not have to check boundary.
SetBoundaryChecked(); SetBoundaryChecked();
} } break;
break;
default: default: break;
break;
} }
} }
void StringType::Prepare(Env* env, int flags) void StringType::Prepare(Env* env, int flags) {
{ if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 ) {
if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 ) ID* string_length_var = new ID(strfmt("%s_string_length", value_var() ? value_var()->Name() : "val"));
{
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_ = new TempVarField(string_length_var, extern_type_int->Clone());
string_length_var_field_->Prepare(env); string_length_var_field_->Prepare(env);
} }
Type::Prepare(env, flags); Type::Prepare(env, flags);
} }
void StringType::GenPubDecls(Output* out_h, Env* env) void StringType::GenPubDecls(Output* out_h, Env* env) { Type::GenPubDecls(out_h, env); }
{
Type::GenPubDecls(out_h, env);
}
void StringType::GenPrivDecls(Output* out_h, Env* env) void StringType::GenPrivDecls(Output* out_h, Env* env) { Type::GenPrivDecls(out_h, env); }
{
Type::GenPrivDecls(out_h, env);
}
void StringType::GenInitCode(Output* out_cc, Env* env) void StringType::GenInitCode(Output* out_cc, Env* env) { Type::GenInitCode(out_cc, env); }
{
Type::GenInitCode(out_cc, env);
}
void StringType::GenCleanUpCode(Output* out_cc, Env* env) void StringType::GenCleanUpCode(Output* out_cc, Env* env) {
{
Type::GenCleanUpCode(out_cc, env); Type::GenCleanUpCode(out_cc, env);
if ( persistent() ) if ( persistent() )
out_cc->println("%s.free();", env->LValue(value_var())); out_cc->println("%s.free();", env->LValue(value_var()));
} }
void StringType::DoMarkIncrementalInput() void StringType::DoMarkIncrementalInput() {
{ if ( attr_restofflow_ ) {
if ( attr_restofflow_ )
{
// Do nothing // Do nothing
ASSERT(type_ == ANYSTR); ASSERT(type_ == ANYSTR);
} }
else else {
{
Type::DoMarkIncrementalInput(); Type::DoMarkIncrementalInput();
} }
} }
int StringType::StaticSize(Env* env) const int StringType::StaticSize(Env* env) const {
{ switch ( type_ ) {
switch ( type_ )
{
case CSTR: case CSTR:
// Use length of the unescaped string // Use length of the unescaped string
return str_->unescaped().length(); return str_->unescaped().length();
case REGEX: case REGEX:
// TODO: static size for a regular expression? // TODO: static size for a regular expression?
case ANYSTR: case ANYSTR: return -1;
return -1;
default: default: ASSERT(0); return -1;
ASSERT(0);
return -1;
} }
} }
const ID* StringType::string_length_var() const const ID* StringType::string_length_var() const {
{
return string_length_var_field_ ? string_length_var_field_->id() : nullptr; return string_length_var_field_ ? string_length_var_field_->id() : nullptr;
} }
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); 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());
@ -220,29 +161,22 @@ void StringType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
string_length_var_field_->GenTempDecls(out_cc, env); string_length_var_field_->GenTempDecls(out_cc, env);
switch ( type_ ) switch ( type_ ) {
{ case ANYSTR: GenDynamicSizeAnyStr(out_cc, env, data); break;
case ANYSTR: case CSTR: ASSERT(0); break;
GenDynamicSizeAnyStr(out_cc, env, data);
break;
case CSTR:
ASSERT(0);
break;
case REGEX: case REGEX:
// TODO: static size for a regular expression? // TODO: static size for a regular expression?
GenDynamicSizeRegEx(out_cc, env, data); GenDynamicSizeRegEx(out_cc, env, data);
break; break;
} }
if ( ! incremental_input() && AddSizeVar(out_cc, 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()); 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); int static_size = StaticSize(env);
if ( static_size >= 0 ) if ( static_size >= 0 )
return strfmt("%d", static_size); return strfmt("%d", static_size);
@ -250,62 +184,47 @@ string StringType::GenStringSize(Output* out_cc, Env* env, const DataPtr& data)
return env->RValue(string_length_var()); 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); string str_size = GenStringSize(out_cc, env, data);
// Generate additional checking // Generate additional checking
switch ( type_ ) switch ( type_ ) {
{ case CSTR: GenCheckingCStr(out_cc, env, data, str_size); break;
case CSTR:
GenCheckingCStr(out_cc, env, data, str_size);
break;
case REGEX: case REGEX:
case ANYSTR: case ANYSTR: break;
break;
} }
if ( ! anonymous_value_var() ) if ( ! anonymous_value_var() ) {
{
// Set the value variable // Set the value variable
int len; 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 // can check for a negative length now
if ( len < 0 ) if ( len < 0 )
throw Exception(this, "negative &length on string"); throw Exception(this, "negative &length on string");
} }
else else {
{
out_cc->println("// check for negative sizes"); out_cc->println("// check for negative sizes");
out_cc->println("if ( %s < 0 )", str_size.c_str()); out_cc->println("if ( %s < 0 )", str_size.c_str());
out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), str_size.c_str());
str_size.c_str());
} }
out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), data.ptr_expr(), out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), data.ptr_expr(), str_size.c_str());
str_size.c_str());
} }
if ( parsing_complete_var() ) 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 =
string tmp = strfmt("string((const char *) (%s), (const char *) %s).c_str()", data.ptr_expr(), strfmt("string((const char *) (%s), (const char *) %s).c_str()", data.ptr_expr(), env->RValue(end_of_data));
env->RValue(end_of_data)); out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", Location(), pattern.c_str(), tmp.c_str());
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, void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data, const string& str_size) {
const string& str_size)
{
// TODO: extend it for dynamic strings // TODO: extend it for dynamic strings
ASSERT(type_ == CSTR); ASSERT(type_ == CSTR);
@ -314,8 +233,7 @@ void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data,
string str_val = str_->str(); string str_val = str_->str();
// Compare the string and report error on mismatch // Compare the string and report error on mismatch
out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", data.ptr_expr(), str_val.c_str(), out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", data.ptr_expr(), str_val.c_str(), str_size.c_str());
str_size.c_str());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
GenStringMismatch(out_cc, env, data, str_val); GenStringMismatch(out_cc, env, data, str_val);
@ -323,8 +241,7 @@ void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data,
out_cc->dec_indent(); 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( // matcher.match_prefix(
// begin, // begin,
@ -353,50 +270,38 @@ void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& da
out_cc->dec_indent(); 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); ASSERT(type_ == ANYSTR);
if ( attr_restofdata_ || attr_oneline_ ) if ( attr_restofdata_ || attr_oneline_ ) {
{ out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), env->RValue(end_of_data),
out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), data.ptr_expr());
env->RValue(end_of_data), data.ptr_expr());
} }
else if ( attr_restofflow_ ) else if ( attr_restofflow_ ) {
{ out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), env->RValue(end_of_data),
out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), data.ptr_expr());
env->RValue(end_of_data), data.ptr_expr());
} }
else if ( attr_length_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 else {
{
throw Exception(this, "cannot determine length of bytestring"); throw Exception(this, "cannot determine length of bytestring");
} }
env->SetEvaluated(string_length_var()); env->SetEvaluated(string_length_var());
} }
bool StringType::DoTraverse(DataDepVisitor* visitor) bool StringType::DoTraverse(DataDepVisitor* visitor) {
{
if ( ! Type::DoTraverse(visitor) ) if ( ! Type::DoTraverse(visitor) )
return false; return false;
switch ( type_ ) switch ( type_ ) {
{
case ANYSTR: case ANYSTR:
case CSTR: case CSTR:
case REGEX: case REGEX: break;
break;
} }
return true; return true;
} }
void StringType::static_init() void StringType::static_init() { Type::AddPredefinedType("bytestring", new StringType(ANYSTR)); }
{
Type::AddPredefinedType("bytestring", new StringType(ANYSTR));
}

View file

@ -4,15 +4,9 @@
#include "pac_type.h" #include "pac_type.h"
// TODO: question: shall we merge it with ArrayType? // TODO: question: shall we merge it with ArrayType?
class StringType : public Type class StringType : public Type {
{
public: public:
enum StringTypeEnum enum StringTypeEnum { CSTR, REGEX, ANYSTR };
{
CSTR,
REGEX,
ANYSTR
};
explicit StringType(StringTypeEnum anystr); explicit StringType(StringTypeEnum anystr);
explicit StringType(ConstString* str); explicit StringType(ConstString* str);

File diff suppressed because it is too large Load diff

View file

@ -8,11 +8,9 @@ using namespace std;
#include "pac_datadep.h" #include "pac_datadep.h"
#include "pac_dbg.h" #include "pac_dbg.h"
class Type : public Object, public DataDepElement class Type : public Object, public DataDepElement {
{
public: public:
enum TypeType enum TypeType {
{
UNDEF = -1, UNDEF = -1,
EMPTY, EMPTY,
BUILTIN, BUILTIN,
@ -100,8 +98,7 @@ public:
void AddField(Field* f); void AddField(Field* f);
void AddCheck(Expr* expr) void AddCheck(Expr* expr) { /* TODO */
{ /* TODO */
} }
virtual bool DefineValueVar() const = 0; virtual bool DefineValueVar() const = 0;
@ -111,8 +108,7 @@ public:
// Returns const reference of the C++ data type (unless the type // Returns const reference of the C++ data type (unless the type
// is numeric or pointer) // is numeric or pointer)
string DataTypeConstRefStr() const string DataTypeConstRefStr() const {
{
string data_type = DataTypeStr(); string data_type = DataTypeStr();
if ( ! IsPointerType() && ! IsNumericType() ) if ( ! IsPointerType() && ! IsNumericType() )
data_type += " const &"; data_type += " const &";
@ -120,8 +116,7 @@ public:
} }
// Returns a default value for the type // Returns a default value for the type
virtual string DefaultValue() const virtual string DefaultValue() const {
{
ASSERT(0); ASSERT(0);
return "@@@"; return "@@@";
} }
@ -204,8 +199,7 @@ public:
bool BufferableWithLineBreaker() const; bool BufferableWithLineBreaker() const;
Expr* LineBreaker() const; Expr* LineBreaker() const;
enum BufferMode enum BufferMode {
{
NOT_BUFFERABLE, NOT_BUFFERABLE,
BUFFER_NOTHING, // for type "empty" BUFFER_NOTHING, // for type "empty"
BUFFER_BY_LENGTH, BUFFER_BY_LENGTH,

View file

@ -16,35 +16,27 @@
#include "pac_type.h" #include "pac_type.h"
#include "pac_utils.h" #include "pac_utils.h"
TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type) TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type) : Decl(id, TYPE), params_(params), type_(type) {
: Decl(id, TYPE), params_(params), type_(type)
{
env_ = nullptr; env_ = nullptr;
type_->set_type_decl(this, true); type_->set_type_decl(this, true);
} }
TypeDecl::~TypeDecl() TypeDecl::~TypeDecl() {
{
delete env_; delete env_;
delete type_; delete type_;
delete_list(ParamList, params_); delete_list(ParamList, params_);
} }
void TypeDecl::ProcessAttr(Attr* a) void TypeDecl::ProcessAttr(Attr* a) { type_->ProcessAttr(a); }
{
type_->ProcessAttr(a);
}
void TypeDecl::AddParam(Param* param) void TypeDecl::AddParam(Param* param) {
{
// Cannot work after Prepare() // Cannot work after Prepare()
ASSERT(! env_); ASSERT(! env_);
params_->push_back(param); params_->push_back(param);
} }
void TypeDecl::Prepare() void TypeDecl::Prepare() {
{
DEBUG_MSG("Preparing type %s\n", id()->Name()); DEBUG_MSG("Preparing type %s\n", id()->Name());
if ( type_->tot() != Type::EXTERN && type_->tot() != Type::DUMMY ) if ( type_->tot() != Type::EXTERN && type_->tot() != Type::DUMMY )
@ -57,38 +49,30 @@ void TypeDecl::Prepare()
env_ = new Env(global_env(), this); env_ = new Env(global_env(), this);
foreach (i, ParamList, params_) foreach (i, ParamList, params_) {
{
Param* p = *i; Param* p = *i;
// p->Prepare(env_); // p->Prepare(env_);
type_->AddField(p->param_field()); type_->AddField(p->param_field());
} }
if ( type_->attr_byteorder_expr() ) if ( type_->attr_byteorder_expr() ) {
{
DEBUG_MSG("Adding byteorder field to %s\n", id()->Name()); DEBUG_MSG("Adding byteorder field to %s\n", id()->Name());
type_->AddField( type_->AddField(new LetField(byteorder_id->clone(), extern_type_int, type_->attr_byteorder_expr()));
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 string TypeDecl::class_name() const { return id_->Name(); }
{
return id_->Name();
}
void TypeDecl::GenForwardDeclaration(Output* out_h) void TypeDecl::GenForwardDeclaration(Output* out_h) {
{
// Do not generate declaration for external types // Do not generate declaration for external types
if ( type_->tot() == Type::EXTERN ) if ( type_->tot() == Type::EXTERN )
return; return;
out_h->println("class %s;", class_name().c_str()); out_h->println("class %s;", class_name().c_str());
} }
void TypeDecl::GenCode(Output* out_h, Output* out_cc) void TypeDecl::GenCode(Output* out_h, Output* out_cc) {
{
// Do not generate code for external types // Do not generate code for external types
if ( type_->tot() == Type::EXTERN || type_->tot() == Type::STRING ) if ( type_->tot() == Type::EXTERN || type_->tot() == Type::STRING )
return; return;
@ -96,8 +80,7 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc)
if ( ! FLAGS_quiet ) if ( ! FLAGS_quiet )
fprintf(stderr, "Generating code for %s\n", class_name().c_str()); fprintf(stderr, "Generating code for %s\n", class_name().c_str());
if ( RequiresAnalyzerContext::compute(type_) ) if ( RequiresAnalyzerContext::compute(type_) ) {
{
DEBUG_MSG("%s requires analyzer context\n", id()->Name()); DEBUG_MSG("%s requires analyzer context\n", id()->Name());
Type* param_type = analyzer_context()->param_type(); Type* param_type = analyzer_context()->param_type();
env_->AddID(analyzer_context_id, TEMP_VAR, param_type); env_->AddID(analyzer_context_id, TEMP_VAR, param_type);
@ -106,8 +89,7 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc)
} }
// Add parameter "byteorder" // Add parameter "byteorder"
if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) {
{
env_->AddID(byteorder_id, TEMP_VAR, extern_type_int); env_->AddID(byteorder_id, TEMP_VAR, extern_type_int);
env_->SetEvaluated(byteorder_id); env_->SetEvaluated(byteorder_id);
} }
@ -124,10 +106,8 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc)
out_h->print("class %s final", class_name().c_str()); out_h->print("class %s final", class_name().c_str());
bool first = true; bool first = true;
vector<string>::iterator i; vector<string>::iterator i;
for ( i = (&base_classes)->begin(); i != (&base_classes)->end(); ++i ) for ( i = base_classes.begin(); i != base_classes.end(); ++i ) {
{ if ( first ) {
if ( first )
{
out_h->print(" : public %s", i->c_str()); out_h->print(" : public %s", i->c_str());
first = false; first = false;
} }
@ -167,13 +147,11 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc)
out_h->println("};\n"); 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_); // 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_); // GenParamPrivDecls(params_, out_h, env_);
} }
@ -181,8 +159,7 @@ 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) void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc) {
{
string params_str = ParamDecls(params_); 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());
@ -203,8 +180,7 @@ void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc)
out_cc->dec_indent(); out_cc->dec_indent();
} }
void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc) {
{
string proto = strfmt("~%s()", class_name().c_str()); string proto = strfmt("~%s()", class_name().c_str());
out_h->println("%s;", proto.c_str()); out_h->println("%s;", proto.c_str());
@ -220,36 +196,30 @@ void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc)
out_cc->dec_indent(); out_cc->dec_indent();
} }
string TypeDecl::ParseFuncPrototype(Env* env) string TypeDecl::ParseFuncPrototype(Env* env) {
{
const char* func_name = nullptr; const char* func_name = nullptr;
const char* return_type = nullptr; const char* return_type = nullptr;
string params; string params;
if ( type_->incremental_input() ) if ( type_->incremental_input() ) {
{
func_name = kParseFuncWithBuffer; func_name = kParseFuncWithBuffer;
return_type = "bool"; 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 else {
{
func_name = kParseFuncWithoutBuffer; func_name = kParseFuncWithoutBuffer;
return_type = "int"; return_type = "int";
params = strfmt("const_byteptr const %s, const_byteptr const %s", params = strfmt("const_byteptr const %s, const_byteptr const %s", env->LValue(begin_of_data),
env->LValue(begin_of_data), env->LValue(end_of_data)); env->LValue(end_of_data));
} }
if ( RequiresAnalyzerContext::compute(type_) ) if ( RequiresAnalyzerContext::compute(type_) ) {
{
Type* param_type = analyzer_context()->param_type(); Type* param_type = analyzer_context()->param_type();
params += strfmt(", %s %s", param_type->DataTypeConstRefStr().c_str(), params += strfmt(", %s %s", param_type->DataTypeConstRefStr().c_str(), env->LValue(analyzer_context_id));
env->LValue(analyzer_context_id));
} }
// Add parameter "byteorder" // Add parameter "byteorder"
if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) {
{
params += strfmt(", int %s", env->LValue(byteorder_id)); params += strfmt(", int %s", env->LValue(byteorder_id));
} }
@ -257,27 +227,22 @@ string TypeDecl::ParseFuncPrototype(Env* env)
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; string ret_val_0, ret_val_1;
if ( type_->incremental_input() ) if ( type_->incremental_input() ) {
{
ret_val_0 = type_->parsing_complete(env).c_str(); ret_val_0 = type_->parsing_complete(env).c_str();
ret_val_1 = "false"; ret_val_1 = "false";
} }
else else {
{
ret_val_0 = type_->DataSize(nullptr, env, data).c_str(); ret_val_0 = type_->DataSize(nullptr, env, data).c_str();
ret_val_1 = "@@@"; ret_val_1 = "@@@";
out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", env->RValue(begin_of_data), out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", env->RValue(begin_of_data), ret_val_0.c_str(),
ret_val_0.c_str(), env->RValue(end_of_data)); env->RValue(end_of_data));
} }
if ( type_->incremental_parsing() && if ( type_->incremental_parsing() && (type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY) ) {
(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" ... // "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());
@ -290,18 +255,15 @@ void TypeDecl::GenParsingEnd(Output* out_cc, Env* env, const DataPtr& 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_1.c_str()); out_cc->println("return %s;", ret_val_1.c_str());
} }
else if ( type_->incremental_input() ) else if ( type_->incremental_input() ) {
{
out_cc->println("return %s;", ret_val_0.c_str()); out_cc->println("return %s;", ret_val_0.c_str());
} }
else else {
{
out_cc->println("return %s;", ret_val_0.c_str()); out_cc->println("return %s;", ret_val_0.c_str());
} }
} }
void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc) {
{
if ( type_->tot() == Type::DUMMY ) if ( type_->tot() == Type::DUMMY )
return; return;
@ -309,13 +271,11 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc)
Env p_func_env(env_, this); Env p_func_env(env_, this);
Env* env = &p_func_env; Env* env = &p_func_env;
if ( type_->incremental_input() ) if ( type_->incremental_input() ) {
{
env->AddID(flow_buffer_id, TEMP_VAR, extern_type_flowbuffer); env->AddID(flow_buffer_id, TEMP_VAR, extern_type_flowbuffer);
env->SetEvaluated(flow_buffer_id); env->SetEvaluated(flow_buffer_id);
} }
else else {
{
env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr);
env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr);
@ -358,8 +318,7 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc)
out_cc->dec_indent(); out_cc->dec_indent();
} }
void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc) void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc) {
{
string func(kInitialBufferLengthFunc); string func(kInitialBufferLengthFunc);
int init_buffer_length = type_->InitialBufferLength(); int init_buffer_length = type_->InitialBufferLength();
@ -374,20 +333,15 @@ void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc)
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 ) if ( ! decl )
return nullptr; return nullptr;
switch ( decl->decl_type() ) switch ( decl->decl_type() ) {
{
case TYPE: case TYPE:
case CONN: case CONN:
case FLOW: case FLOW: return static_cast<TypeDecl*>(decl)->type();
return static_cast<TypeDecl*>(decl)->type(); case ENUM: return static_cast<EnumDecl*>(decl)->DataType();
case ENUM: default: return nullptr;
return static_cast<EnumDecl*>(decl)->DataType();
default:
return nullptr;
} }
} }

View file

@ -3,8 +3,7 @@
#include "pac_decl.h" #include "pac_decl.h"
class TypeDecl : public Decl class TypeDecl : public Decl {
{
public: public:
TypeDecl(ID* arg_id, ParamList* arg_params, Type* arg_type); TypeDecl(ID* arg_id, ParamList* arg_params, Type* arg_type);
~TypeDecl() override; ~TypeDecl() override;

View file

@ -4,27 +4,23 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
char* copy_string(const char* s) char* copy_string(const char* s) {
{
char* c = new char[strlen(s) + 1]; char* c = new char[strlen(s) + 1];
strcpy(c, s); strcpy(c, s);
return c; return c;
} }
namespace namespace {
{
const char* do_fmt(const char* format, va_list ap) const char* do_fmt(const char* format, va_list ap) {
{
static char buf[1024]; static char buf[1024];
vsnprintf(buf, sizeof(buf), format, ap); vsnprintf(buf, sizeof(buf), format, ap);
return buf; return buf;
} }
} } // namespace
string strfmt(const char* format, ...) string strfmt(const char* format, ...) {
{
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
const char* r = do_fmt(format, ap); const char* r = do_fmt(format, ap);
@ -32,8 +28,7 @@ string strfmt(const char* format, ...)
return string(r); return string(r);
} }
char* nfmt(const char* format, ...) char* nfmt(const char* format, ...) {
{
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
const char* r = do_fmt(format, ap); const char* r = do_fmt(format, ap);

View file

@ -1,6 +1,3 @@
#include "pac_varfield.h" #include "pac_varfield.h"
void PrivVarField::Prepare(Env* env) void PrivVarField::Prepare(Env* env) { Field::Prepare(env); }
{
Field::Prepare(env);
}

View file

@ -4,53 +4,36 @@
#include "pac_field.h" #include "pac_field.h"
// A private variable evaluated with parsing // A private variable evaluated with parsing
class ParseVarField : public Field class ParseVarField : public Field {
{
public: public:
ParseVarField(int is_class_member, ID* id, Type* type) ParseVarField(int is_class_member, ID* id, Type* type)
: Field(PARSE_VAR_FIELD, TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, id, : Field(PARSE_VAR_FIELD, TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, id, type) {}
type) void GenPubDecls(Output* out, Env* env) override { /* do nothing */
{
}
void GenPubDecls(Output* out, Env* env) override
{ /* do nothing */
} }
}; };
// A public variable // A public variable
class PubVarField : public Field class PubVarField : public Field {
{
public: public:
PubVarField(ID* id, Type* type) PubVarField(ID* id, Type* type)
: Field(PUB_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) : Field(PUB_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) {}
{
}
~PubVarField() override {} ~PubVarField() override {}
}; };
// A private variable // A private variable
class PrivVarField : public Field class PrivVarField : public Field {
{
public: public:
PrivVarField(ID* id, Type* type) PrivVarField(ID* id, Type* type)
: Field(PRIV_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, id, : Field(PRIV_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, id, type) {}
type)
{
}
~PrivVarField() override {} ~PrivVarField() override {}
void GenPubDecls(Output* out, Env* env) override void GenPubDecls(Output* out, Env* env) override { /* do nothing */
{ /* do nothing */
} }
}; };
class TempVarField : public Field class TempVarField : public Field {
{
public: public:
TempVarField(ID* id, Type* type) TempVarField(ID* id, Type* type) : Field(TEMP_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, id, type) {}
: Field(TEMP_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, id, type)
{
}
~TempVarField() override {} ~TempVarField() override {}
}; };

View file

@ -7,48 +7,36 @@
#include "pac_type.h" #include "pac_type.h"
WithInputField::WithInputField(ID* id, Type* type, InputBuffer* input) WithInputField::WithInputField(ID* id, Type* type, InputBuffer* input)
: Field(WITHINPUT_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), : Field(WITHINPUT_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), input_(input) {
input_(input)
{
ASSERT(type_); ASSERT(type_);
ASSERT(input_); ASSERT(input_);
} }
WithInputField::~WithInputField() WithInputField::~WithInputField() { delete input_; }
{
delete input_;
}
bool WithInputField::DoTraverse(DataDepVisitor* visitor) bool WithInputField::DoTraverse(DataDepVisitor* visitor) {
{
return Field::DoTraverse(visitor) && input()->Traverse(visitor); return Field::DoTraverse(visitor) && input()->Traverse(visitor);
} }
bool WithInputField::RequiresAnalyzerContext() const bool WithInputField::RequiresAnalyzerContext() const {
{
return Field::RequiresAnalyzerContext() || (input() && input()->RequiresAnalyzerContext()); return Field::RequiresAnalyzerContext() || (input() && input()->RequiresAnalyzerContext());
} }
void WithInputField::Prepare(Env* env) void WithInputField::Prepare(Env* env) {
{
Field::Prepare(env); Field::Prepare(env);
env->SetEvalMethod(id_, this); env->SetEvalMethod(id_, this);
} }
void WithInputField::GenEval(Output* out_cc, Env* env) void WithInputField::GenEval(Output* out_cc, Env* env) {
{
GenParseCode(out_cc, env); GenParseCode(out_cc, env);
if ( type_->attr_if_expr() ) 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) void WithInputField::GenParseCode(Output* out_cc, Env* env) {
{
out_cc->println("// Parse \"%s\"", id_->Name()); out_cc->println("// Parse \"%s\"", id_->Name());
if ( type_->attr_if_expr() ) if ( type_->attr_if_expr() ) {
{
// A conditional field // A conditional field
env->Evaluate(out_cc, type_->has_value_var()); 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()));
@ -63,8 +51,7 @@ void WithInputField::GenParseCode(Output* out_cc, Env* env)
type_->GenPreParsing(out_cc, &field_env); 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() ) if ( type_->attr_if_expr() ) {
{
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
} }

View file

@ -5,8 +5,7 @@
#include "pac_decl.h" #include "pac_decl.h"
#include "pac_field.h" #include "pac_field.h"
class WithInputField : public Field, public Evaluatable class WithInputField : public Field, public Evaluatable {
{
public: public:
WithInputField(ID* id, Type* type, InputBuffer* input); WithInputField(ID* id, Type* type, InputBuffer* input);
~WithInputField() override; ~WithInputField() override;