mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
binpac: Reformat C++ code in Spicy style
This commit is contained in:
parent
716bf016a1
commit
3297de477b
89 changed files with 7887 additions and 9733 deletions
|
@ -1,28 +1,24 @@
|
|||
#ifndef binpac_an_h
|
||||
#define binpac_an_h
|
||||
|
||||
namespace binpac
|
||||
{
|
||||
namespace binpac {
|
||||
|
||||
// TODO: Add the Done() function
|
||||
|
||||
// The interface for a connection analyzer
|
||||
class ConnectionAnalyzer
|
||||
{
|
||||
class ConnectionAnalyzer {
|
||||
public:
|
||||
virtual ~ConnectionAnalyzer() { }
|
||||
virtual void NewData(bool is_orig, const unsigned char* begin_of_data,
|
||||
const unsigned char* end_of_data) = 0;
|
||||
};
|
||||
virtual ~ConnectionAnalyzer() {}
|
||||
virtual void NewData(bool is_orig, const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0;
|
||||
};
|
||||
|
||||
// The interface for a flow analyzer
|
||||
class FlowAnalyzer
|
||||
{
|
||||
class FlowAnalyzer {
|
||||
public:
|
||||
virtual ~FlowAnalyzer() { }
|
||||
virtual ~FlowAnalyzer() {}
|
||||
virtual void NewData(const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace binpac
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_an_h
|
||||
|
|
|
@ -7,16 +7,14 @@
|
|||
#include "binpac.h"
|
||||
#include "binpac_buffer.h"
|
||||
|
||||
namespace binpac
|
||||
{
|
||||
namespace binpac {
|
||||
|
||||
extern double network_time();
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
const unsigned char CR = '\r';
|
||||
const unsigned char LF = '\n';
|
||||
}
|
||||
} // namespace
|
||||
|
||||
binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = {
|
||||
// max_capacity
|
||||
|
@ -27,8 +25,7 @@ binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = {
|
|||
2 * 1024 * 1024,
|
||||
};
|
||||
|
||||
FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style)
|
||||
{
|
||||
FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) {
|
||||
buffer_length_ = 0;
|
||||
buffer_ = nullptr;
|
||||
|
||||
|
@ -51,31 +48,22 @@ FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style)
|
|||
buffer_n_ = 0;
|
||||
|
||||
NewMessage();
|
||||
}
|
||||
}
|
||||
|
||||
FlowBuffer::~FlowBuffer()
|
||||
{
|
||||
FlowBuffer::~FlowBuffer() {
|
||||
if ( buffer_ )
|
||||
free(buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::NewMessage()
|
||||
{
|
||||
void FlowBuffer::NewMessage() {
|
||||
BINPAC_ASSERT(frame_length_ >= 0);
|
||||
|
||||
int bytes_to_advance = 0;
|
||||
if ( buffer_n_ == 0 )
|
||||
{
|
||||
switch ( mode_ )
|
||||
{
|
||||
case LINE_MODE:
|
||||
bytes_to_advance = (frame_length_ + (linebreak_style_ == STRICT_CRLF ? 2 : 1));
|
||||
break;
|
||||
case FRAME_MODE:
|
||||
bytes_to_advance = frame_length_;
|
||||
break;
|
||||
case UNKNOWN_MODE:
|
||||
break;
|
||||
if ( buffer_n_ == 0 ) {
|
||||
switch ( mode_ ) {
|
||||
case LINE_MODE: bytes_to_advance = (frame_length_ + (linebreak_style_ == STRICT_CRLF ? 2 : 1)); break;
|
||||
case FRAME_MODE: bytes_to_advance = frame_length_; break;
|
||||
case UNKNOWN_MODE: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,28 +73,18 @@ void FlowBuffer::NewMessage()
|
|||
buffer_n_ = 0;
|
||||
message_complete_ = false;
|
||||
ContractBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::ResetLineState()
|
||||
{
|
||||
switch ( linebreak_style_ )
|
||||
{
|
||||
case CR_OR_LF:
|
||||
state_ = CR_OR_LF_0;
|
||||
break;
|
||||
case STRICT_CRLF:
|
||||
state_ = STRICT_CRLF_0;
|
||||
break;
|
||||
case LINE_BREAKER:
|
||||
break; // Nothing to reset
|
||||
default:
|
||||
BINPAC_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
void FlowBuffer::ResetLineState() {
|
||||
switch ( linebreak_style_ ) {
|
||||
case CR_OR_LF: state_ = CR_OR_LF_0; break;
|
||||
case STRICT_CRLF: state_ = STRICT_CRLF_0; break;
|
||||
case LINE_BREAKER: break; // Nothing to reset
|
||||
default: BINPAC_ASSERT(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::ExpandBuffer(int length)
|
||||
{
|
||||
void FlowBuffer::ExpandBuffer(int length) {
|
||||
if ( buffer_length_ >= length )
|
||||
return;
|
||||
|
||||
|
@ -116,8 +94,7 @@ void FlowBuffer::ExpandBuffer(int length)
|
|||
if ( 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);
|
||||
throw ExceptionFlowBufferAlloc(reason.c_str());
|
||||
}
|
||||
|
@ -130,10 +107,9 @@ void FlowBuffer::ExpandBuffer(int length)
|
|||
throw ExceptionFlowBufferAlloc("expand realloc OOM");
|
||||
|
||||
buffer_ = new_buf;
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::ContractBuffer()
|
||||
{
|
||||
void FlowBuffer::ContractBuffer() {
|
||||
if ( buffer_length_ < policy.contract_threshold )
|
||||
return;
|
||||
|
||||
|
@ -144,22 +120,17 @@ void FlowBuffer::ContractBuffer()
|
|||
throw ExceptionFlowBufferAlloc("contract realloc OOM");
|
||||
|
||||
buffer_ = new_buf;
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::SetLineBreaker(unsigned char* lbreaker)
|
||||
{
|
||||
void FlowBuffer::SetLineBreaker(unsigned char* lbreaker) {
|
||||
linebreaker_ = *lbreaker;
|
||||
linebreak_style_default = linebreak_style_;
|
||||
linebreak_style_ = LINE_BREAKER;
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::UnsetLineBreaker()
|
||||
{
|
||||
linebreak_style_ = linebreak_style_default;
|
||||
}
|
||||
void FlowBuffer::UnsetLineBreaker() { linebreak_style_ = linebreak_style_default; }
|
||||
|
||||
void FlowBuffer::NewLine()
|
||||
{
|
||||
void FlowBuffer::NewLine() {
|
||||
FlowBuffer::NewMessage();
|
||||
mode_ = LINE_MODE;
|
||||
frame_length_ = 0;
|
||||
|
@ -168,33 +139,27 @@ void FlowBuffer::NewLine()
|
|||
if ( state_ == FRAME_0 )
|
||||
ResetLineState();
|
||||
MarkOrCopyLine();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::NewFrame(int frame_length, bool chunked)
|
||||
{
|
||||
void FlowBuffer::NewFrame(int frame_length, bool chunked) {
|
||||
FlowBuffer::NewMessage();
|
||||
mode_ = FRAME_MODE;
|
||||
frame_length_ = frame_length;
|
||||
chunked_ = chunked;
|
||||
have_pending_request_ = true;
|
||||
MarkOrCopyFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::BufferData(const_byteptr data, const_byteptr end)
|
||||
{
|
||||
void FlowBuffer::BufferData(const_byteptr data, const_byteptr end) {
|
||||
mode_ = FRAME_MODE;
|
||||
frame_length_ += (end - data);
|
||||
MarkOrCopyFrame();
|
||||
NewData(data, end);
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::FinishBuffer()
|
||||
{
|
||||
message_complete_ = true;
|
||||
}
|
||||
void FlowBuffer::FinishBuffer() { message_complete_ = true; }
|
||||
|
||||
void FlowBuffer::GrowFrame(int length)
|
||||
{
|
||||
void FlowBuffer::GrowFrame(int length) {
|
||||
BINPAC_ASSERT(frame_length_ >= 0);
|
||||
if ( length <= frame_length_ )
|
||||
return;
|
||||
|
@ -202,10 +167,9 @@ void FlowBuffer::GrowFrame(int length)
|
|||
mode_ = FRAME_MODE;
|
||||
frame_length_ = length;
|
||||
MarkOrCopyFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::DiscardData()
|
||||
{
|
||||
void FlowBuffer::DiscardData() {
|
||||
mode_ = UNKNOWN_MODE;
|
||||
message_complete_ = false;
|
||||
have_pending_request_ = false;
|
||||
|
@ -214,20 +178,18 @@ void FlowBuffer::DiscardData()
|
|||
buffer_n_ = 0;
|
||||
frame_length_ = 0;
|
||||
ContractBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::set_eof()
|
||||
{
|
||||
void FlowBuffer::set_eof() {
|
||||
// fprintf(stderr, "EOF\n");
|
||||
eof_ = true;
|
||||
if ( chunked_ )
|
||||
frame_length_ = orig_data_end_ - orig_data_begin_;
|
||||
if ( frame_length_ < 0 )
|
||||
frame_length_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::NewData(const_byteptr begin, const_byteptr end)
|
||||
{
|
||||
void FlowBuffer::NewData(const_byteptr begin, const_byteptr end) {
|
||||
BINPAC_ASSERT(begin <= end);
|
||||
|
||||
ClearPreviousData();
|
||||
|
@ -239,51 +201,37 @@ void FlowBuffer::NewData(const_byteptr begin, const_byteptr end)
|
|||
data_seq_at_orig_data_end_ += (end - begin);
|
||||
|
||||
MarkOrCopy();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::MarkOrCopy()
|
||||
{
|
||||
if ( ! message_complete_ )
|
||||
{
|
||||
switch ( mode_ )
|
||||
{
|
||||
case LINE_MODE:
|
||||
MarkOrCopyLine();
|
||||
break;
|
||||
void FlowBuffer::MarkOrCopy() {
|
||||
if ( ! message_complete_ ) {
|
||||
switch ( mode_ ) {
|
||||
case LINE_MODE: MarkOrCopyLine(); break;
|
||||
|
||||
case FRAME_MODE:
|
||||
MarkOrCopyFrame();
|
||||
break;
|
||||
case FRAME_MODE: MarkOrCopyFrame(); break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::ClearPreviousData()
|
||||
{
|
||||
void FlowBuffer::ClearPreviousData() {
|
||||
// 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);
|
||||
if ( chunked_ )
|
||||
{
|
||||
if ( frame_length_ > 0 )
|
||||
{
|
||||
if ( chunked_ ) {
|
||||
if ( frame_length_ > 0 ) {
|
||||
frame_length_ -= (orig_data_end_ - orig_data_begin_);
|
||||
}
|
||||
orig_data_begin_ = orig_data_end_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::NewGap(int length)
|
||||
{
|
||||
void FlowBuffer::NewGap(int length) {
|
||||
ClearPreviousData();
|
||||
|
||||
if ( chunked_ && frame_length_ >= 0 )
|
||||
{
|
||||
if ( chunked_ && frame_length_ >= 0 ) {
|
||||
frame_length_ -= length;
|
||||
if ( frame_length_ < 0 )
|
||||
frame_length_ = 0;
|
||||
|
@ -291,26 +239,16 @@ void FlowBuffer::NewGap(int length)
|
|||
|
||||
orig_data_begin_ = orig_data_end_ = nullptr;
|
||||
MarkOrCopy();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::MarkOrCopyLine()
|
||||
{
|
||||
switch ( linebreak_style_ )
|
||||
{
|
||||
case CR_OR_LF:
|
||||
MarkOrCopyLine_CR_OR_LF();
|
||||
break;
|
||||
case STRICT_CRLF:
|
||||
MarkOrCopyLine_STRICT_CRLF();
|
||||
break;
|
||||
case LINE_BREAKER:
|
||||
MarkOrCopyLine_LINEBREAK();
|
||||
break;
|
||||
default:
|
||||
BINPAC_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
void FlowBuffer::MarkOrCopyLine() {
|
||||
switch ( linebreak_style_ ) {
|
||||
case CR_OR_LF: MarkOrCopyLine_CR_OR_LF(); break;
|
||||
case STRICT_CRLF: MarkOrCopyLine_STRICT_CRLF(); break;
|
||||
case LINE_BREAKER: MarkOrCopyLine_LINEBREAK(); break;
|
||||
default: BINPAC_ASSERT(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Finite state automaton for CR_OR_LF:
|
||||
|
@ -327,25 +265,19 @@ CR_OR_LF_1:
|
|||
.: CR_OR_LF_0 *
|
||||
*/
|
||||
|
||||
void FlowBuffer::MarkOrCopyLine_CR_OR_LF()
|
||||
{
|
||||
void FlowBuffer::MarkOrCopyLine_CR_OR_LF() {
|
||||
if ( ! (orig_data_begin_ && orig_data_end_) )
|
||||
return;
|
||||
|
||||
if ( state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF )
|
||||
{
|
||||
if ( state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF ) {
|
||||
state_ = CR_OR_LF_0;
|
||||
++orig_data_begin_;
|
||||
}
|
||||
|
||||
const_byteptr data;
|
||||
for ( data = orig_data_begin_; data < orig_data_end_; ++data )
|
||||
{
|
||||
switch ( *data )
|
||||
{
|
||||
case CR:
|
||||
state_ = CR_OR_LF_1;
|
||||
goto found_end_of_line;
|
||||
for ( data = orig_data_begin_; data < orig_data_end_; ++data ) {
|
||||
switch ( *data ) {
|
||||
case CR: state_ = CR_OR_LF_1; goto found_end_of_line;
|
||||
|
||||
case LF:
|
||||
// state_ = CR_OR_LF_0;
|
||||
|
@ -361,12 +293,10 @@ void FlowBuffer::MarkOrCopyLine_CR_OR_LF()
|
|||
return;
|
||||
|
||||
found_end_of_line:
|
||||
if ( buffer_n_ == 0 )
|
||||
{
|
||||
if ( buffer_n_ == 0 ) {
|
||||
frame_length_ = data - orig_data_begin_;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
|
||||
// But eliminate the last CR or LF
|
||||
--buffer_n_;
|
||||
|
@ -377,7 +307,7 @@ found_end_of_line:
|
|||
fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(),
|
||||
string((const char*)begin(), (const char*)end()).c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Finite state automaton and STRICT_CRLF:
|
||||
|
@ -394,28 +324,20 @@ STRICT_CRLF_1:
|
|||
.: STRICT_CRLF_0 *
|
||||
*/
|
||||
|
||||
void FlowBuffer::MarkOrCopyLine_STRICT_CRLF()
|
||||
{
|
||||
void FlowBuffer::MarkOrCopyLine_STRICT_CRLF() {
|
||||
const_byteptr data;
|
||||
for ( data = orig_data_begin_; data < orig_data_end_; ++data )
|
||||
{
|
||||
switch ( *data )
|
||||
{
|
||||
case CR:
|
||||
state_ = STRICT_CRLF_1;
|
||||
break;
|
||||
for ( data = orig_data_begin_; data < orig_data_end_; ++data ) {
|
||||
switch ( *data ) {
|
||||
case CR: state_ = STRICT_CRLF_1; break;
|
||||
|
||||
case LF:
|
||||
if ( state_ == STRICT_CRLF_1 )
|
||||
{
|
||||
if ( state_ == STRICT_CRLF_1 ) {
|
||||
state_ = STRICT_CRLF_0;
|
||||
goto found_end_of_line;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
state_ = STRICT_CRLF_0;
|
||||
break;
|
||||
default: state_ = STRICT_CRLF_0; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,12 +345,10 @@ void FlowBuffer::MarkOrCopyLine_STRICT_CRLF()
|
|||
return;
|
||||
|
||||
found_end_of_line:
|
||||
if ( buffer_n_ == 0 )
|
||||
{
|
||||
if ( buffer_n_ == 0 ) {
|
||||
frame_length_ = data - 1 - orig_data_begin_;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
|
||||
// Pop the preceding CR and LF from the buffer
|
||||
buffer_n_ -= 2;
|
||||
|
@ -440,16 +360,14 @@ found_end_of_line:
|
|||
fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(),
|
||||
string((const char*)begin(), (const char*)end()).c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::MarkOrCopyLine_LINEBREAK()
|
||||
{
|
||||
void FlowBuffer::MarkOrCopyLine_LINEBREAK() {
|
||||
if ( ! (orig_data_begin_ && orig_data_end_) )
|
||||
return;
|
||||
|
||||
const_byteptr data;
|
||||
for ( data = orig_data_begin_; data < orig_data_end_; ++data )
|
||||
{
|
||||
for ( data = orig_data_begin_; data < orig_data_end_; ++data ) {
|
||||
if ( *data == linebreaker_ )
|
||||
goto found_end_of_line;
|
||||
}
|
||||
|
@ -458,14 +376,12 @@ void FlowBuffer::MarkOrCopyLine_LINEBREAK()
|
|||
return;
|
||||
|
||||
found_end_of_line:
|
||||
if ( buffer_n_ == 0 )
|
||||
{
|
||||
if ( buffer_n_ == 0 ) {
|
||||
frame_length_ = data - orig_data_begin_;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
|
||||
// But eliminate the last CR or LF
|
||||
// But eliminate the last 'linebreaker' character
|
||||
--buffer_n_;
|
||||
}
|
||||
message_complete_ = true;
|
||||
|
@ -474,7 +390,7 @@ found_end_of_line:
|
|||
fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(),
|
||||
string((const char*)begin(), (const char*)end()).c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Invariants:
|
||||
//
|
||||
|
@ -484,42 +400,33 @@ found_end_of_line:
|
|||
// When buffer_n_ > 0:
|
||||
// Frame = [0..buffer_n_][orig_data_begin_..]
|
||||
|
||||
void FlowBuffer::MarkOrCopyFrame()
|
||||
{
|
||||
if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ )
|
||||
{
|
||||
void FlowBuffer::MarkOrCopyFrame() {
|
||||
if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ ) {
|
||||
// Skip the lingering LF
|
||||
if ( *orig_data_begin_ == LF )
|
||||
{
|
||||
if ( *orig_data_begin_ == LF ) {
|
||||
++orig_data_begin_;
|
||||
}
|
||||
state_ = FRAME_0;
|
||||
}
|
||||
|
||||
if ( buffer_n_ == 0 )
|
||||
{
|
||||
if ( buffer_n_ == 0 ) {
|
||||
// If there is enough data
|
||||
if ( frame_length_ >= 0 && orig_data_end_ - orig_data_begin_ >= frame_length_ )
|
||||
{
|
||||
if ( frame_length_ >= 0 && orig_data_end_ - orig_data_begin_ >= frame_length_ ) {
|
||||
// Do nothing except setting the message complete flag
|
||||
message_complete_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ! chunked_ )
|
||||
{
|
||||
else {
|
||||
if ( ! chunked_ ) {
|
||||
AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_);
|
||||
}
|
||||
message_complete_ = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
BINPAC_ASSERT(! chunked_);
|
||||
int bytes_to_copy = orig_data_end_ - orig_data_begin_;
|
||||
message_complete_ = false;
|
||||
if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ )
|
||||
{
|
||||
if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ ) {
|
||||
bytes_to_copy = frame_length_ - buffer_n_;
|
||||
message_complete_ = true;
|
||||
}
|
||||
|
@ -527,16 +434,14 @@ void FlowBuffer::MarkOrCopyFrame()
|
|||
}
|
||||
|
||||
#if DEBUG_FLOW_BUFFER
|
||||
if ( message_complete_ )
|
||||
{
|
||||
if ( message_complete_ ) {
|
||||
fprintf(stderr, "%.6f frame complete: [%s]\n", network_time(),
|
||||
string((const char*)begin(), (const char*)end()).c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::AppendToBuffer(const_byteptr data, int len)
|
||||
{
|
||||
void FlowBuffer::AppendToBuffer(const_byteptr data, int len) {
|
||||
if ( len <= 0 )
|
||||
return;
|
||||
|
||||
|
@ -547,6 +452,6 @@ void FlowBuffer::AppendToBuffer(const_byteptr data, int len)
|
|||
|
||||
orig_data_begin_ += len;
|
||||
BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace binpac
|
||||
} // namespace binpac
|
||||
|
|
|
@ -5,21 +5,17 @@
|
|||
|
||||
#include "binpac.h"
|
||||
|
||||
namespace binpac
|
||||
{
|
||||
namespace binpac {
|
||||
|
||||
class FlowBuffer
|
||||
{
|
||||
class FlowBuffer {
|
||||
public:
|
||||
struct Policy
|
||||
{
|
||||
struct Policy {
|
||||
int max_capacity;
|
||||
int min_capacity;
|
||||
int contract_threshold;
|
||||
};
|
||||
|
||||
enum LineBreakStyle
|
||||
{
|
||||
enum LineBreakStyle {
|
||||
CR_OR_LF, // CR or LF or CRLF
|
||||
STRICT_CRLF, // CR followed by LF
|
||||
CR_LF_NUL, // CR or LF or CR-LF or CR-NUL
|
||||
|
@ -46,17 +42,14 @@ public:
|
|||
// Whether there is enough data for the frame
|
||||
bool ready() const { return message_complete_ || mode_ == UNKNOWN_MODE; }
|
||||
|
||||
inline const_byteptr begin() const
|
||||
{
|
||||
inline const_byteptr begin() const {
|
||||
BINPAC_ASSERT(ready());
|
||||
return (buffer_n_ == 0) ? orig_data_begin_ : buffer_;
|
||||
}
|
||||
|
||||
inline const_byteptr end() const
|
||||
{
|
||||
inline const_byteptr end() const {
|
||||
BINPAC_ASSERT(ready());
|
||||
if ( buffer_n_ == 0 )
|
||||
{
|
||||
if ( buffer_n_ == 0 ) {
|
||||
BINPAC_ASSERT(frame_length_ >= 0);
|
||||
const_byteptr end = orig_data_begin_ + frame_length_;
|
||||
BINPAC_ASSERT(end <= orig_data_end_);
|
||||
|
@ -66,8 +59,7 @@ public:
|
|||
return buffer_ + buffer_n_;
|
||||
}
|
||||
|
||||
inline int data_length() const
|
||||
{
|
||||
inline int data_length() const {
|
||||
if ( buffer_n_ > 0 )
|
||||
return buffer_n_;
|
||||
|
||||
|
@ -77,10 +69,7 @@ public:
|
|||
return frame_length_;
|
||||
}
|
||||
|
||||
inline bool data_available() const
|
||||
{
|
||||
return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_;
|
||||
}
|
||||
inline bool data_available() const { return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; }
|
||||
|
||||
void SetLineBreaker(unsigned char* lbreaker);
|
||||
void UnsetLineBreaker();
|
||||
|
@ -89,10 +78,8 @@ public:
|
|||
void NewFrame(int frame_length, bool chunked_);
|
||||
void GrowFrame(int new_frame_length);
|
||||
|
||||
int data_seq() const
|
||||
{
|
||||
int data_seq_at_orig_data_begin = data_seq_at_orig_data_end_ -
|
||||
(orig_data_end_ - orig_data_begin_);
|
||||
int data_seq() const {
|
||||
int data_seq_at_orig_data_begin = data_seq_at_orig_data_end_ - (orig_data_end_ - orig_data_begin_);
|
||||
if ( buffer_n_ > 0 )
|
||||
return data_seq_at_orig_data_begin;
|
||||
else
|
||||
|
@ -153,15 +140,13 @@ protected:
|
|||
LineBreakStyle linebreak_style_default;
|
||||
unsigned char linebreaker_;
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
UNKNOWN_MODE,
|
||||
LINE_MODE,
|
||||
FRAME_MODE,
|
||||
} mode_;
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
CR_OR_LF_0,
|
||||
CR_OR_LF_1,
|
||||
STRICT_CRLF_0,
|
||||
|
@ -174,10 +159,10 @@ protected:
|
|||
bool have_pending_request_;
|
||||
|
||||
static Policy policy;
|
||||
};
|
||||
};
|
||||
|
||||
typedef FlowBuffer* flow_buffer_t;
|
||||
|
||||
} // namespace binpac
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_buffer_h
|
||||
|
|
|
@ -4,22 +4,12 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace binpac
|
||||
{
|
||||
namespace binpac {
|
||||
|
||||
std::string std_string(bytestring const* s)
|
||||
{
|
||||
return std::string((const char*)s->begin(), (const char*)s->end());
|
||||
}
|
||||
std::string std_string(bytestring const* s) { return std::string((const char*)s->begin(), (const char*)s->end()); }
|
||||
|
||||
int bytestring_to_int(bytestring const* s)
|
||||
{
|
||||
return atoi((const char*)s->begin());
|
||||
}
|
||||
int bytestring_to_int(bytestring const* s) { return atoi((const char*)s->begin()); }
|
||||
|
||||
double bytestring_to_double(bytestring const* s)
|
||||
{
|
||||
return atof((const char*)s->begin());
|
||||
}
|
||||
double bytestring_to_double(bytestring const* s) { return atof((const char*)s->begin()); }
|
||||
|
||||
} // namespace binpac
|
||||
} // namespace binpac
|
||||
|
|
|
@ -6,24 +6,23 @@
|
|||
|
||||
#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:
|
||||
const_datastring() : begin_(0), end_(0) { }
|
||||
const_datastring() : begin_(0), end_(0) {}
|
||||
|
||||
const_datastring(T const* data, int length) : begin_(data), end_(data + length) { }
|
||||
const_datastring(T const* data, int length) : begin_(data), end_(data + length) {}
|
||||
|
||||
const_datastring(const T* begin, const T* end) : begin_(begin), end_(end) { }
|
||||
const_datastring(const T* begin, const T* end) : begin_(begin), end_(end) {}
|
||||
|
||||
const_datastring(datastring<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;
|
||||
end_ = data + length;
|
||||
}
|
||||
|
@ -34,8 +33,7 @@ public:
|
|||
|
||||
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() )
|
||||
return false;
|
||||
return memcmp((const void*)begin(), (const void*)s.begin(), sizeof(T) * length()) == 0;
|
||||
|
@ -47,12 +45,12 @@ public:
|
|||
private:
|
||||
T const* begin_;
|
||||
T const* end_;
|
||||
};
|
||||
};
|
||||
|
||||
typedef const_datastring<uint8> const_bytestring;
|
||||
|
||||
template <class T> class datastring
|
||||
{
|
||||
template<class T>
|
||||
class datastring {
|
||||
public:
|
||||
datastring() { clear(); }
|
||||
|
||||
|
@ -60,31 +58,27 @@ public:
|
|||
|
||||
datastring(T const* begin, T const* end) { set_const(begin, end - begin); }
|
||||
|
||||
datastring(datastring<T> const& x) : data_(x.data()), length_(x.length()) { }
|
||||
datastring(datastring<T> const& x) : data_(x.data()), length_(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_);
|
||||
set(x.data(), x.length());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void init(T const* begin, int length)
|
||||
{
|
||||
void init(T const* begin, int length) {
|
||||
BINPAC_ASSERT(! data_);
|
||||
set_const(begin, length);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
void clear() {
|
||||
data_ = 0;
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
void free()
|
||||
{
|
||||
void free() {
|
||||
if ( data_ )
|
||||
delete[] data_;
|
||||
clear();
|
||||
|
@ -92,8 +86,7 @@ public:
|
|||
|
||||
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_);
|
||||
set_const(x.begin(), x.length());
|
||||
return *this;
|
||||
|
@ -108,14 +101,12 @@ public:
|
|||
T const* end() const { return data_ + length_; }
|
||||
|
||||
private:
|
||||
void set(T* data, int len)
|
||||
{
|
||||
void set(T* data, int len) {
|
||||
data_ = data;
|
||||
length_ = len;
|
||||
}
|
||||
|
||||
void set_const(T const* data, int len)
|
||||
{
|
||||
void set_const(T const* data, int len) {
|
||||
length_ = len;
|
||||
data_ = new T[len + 1];
|
||||
memcpy(data_, data, sizeof(T) * len);
|
||||
|
@ -124,37 +115,28 @@ private:
|
|||
|
||||
T* data_;
|
||||
int length_;
|
||||
};
|
||||
};
|
||||
|
||||
typedef datastring<uint8> bytestring;
|
||||
|
||||
inline const char* c_str(bytestring const& s)
|
||||
{
|
||||
return (const char*)s.begin();
|
||||
}
|
||||
inline const char* c_str(bytestring const& s) { return (const char*)s.begin(); }
|
||||
|
||||
inline std::string std_str(const_bytestring const& s)
|
||||
{
|
||||
inline std::string std_str(const_bytestring const& s) {
|
||||
return std::string((const char*)s.begin(), (const char*)s.end());
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator==(bytestring const& s1, const char* s2)
|
||||
{
|
||||
return strcmp(c_str(s1), s2) == 0;
|
||||
}
|
||||
inline bool operator==(bytestring const& s1, const char* s2) { return strcmp(c_str(s1), s2) == 0; }
|
||||
|
||||
inline void get_pointers(const_bytestring const& s, uint8 const** pbegin, uint8 const** pend)
|
||||
{
|
||||
inline void get_pointers(const_bytestring const& s, uint8 const** pbegin, uint8 const** pend) {
|
||||
*pbegin = s.begin();
|
||||
*pend = s.end();
|
||||
}
|
||||
}
|
||||
|
||||
inline void get_pointers(bytestring const* s, uint8 const** pbegin, uint8 const** pend)
|
||||
{
|
||||
inline void get_pointers(bytestring const* s, uint8 const** pbegin, uint8 const** pend) {
|
||||
*pbegin = s->begin();
|
||||
*pend = s->end();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace binpac
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_bytestring_h
|
||||
|
|
|
@ -4,14 +4,11 @@
|
|||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace binpac
|
||||
{
|
||||
namespace binpac {
|
||||
|
||||
class Exception
|
||||
{
|
||||
class Exception {
|
||||
public:
|
||||
Exception(const char* m = 0) : msg_("binpac exception: ")
|
||||
{
|
||||
Exception(const char* m = 0) : msg_("binpac exception: ") {
|
||||
if ( m )
|
||||
append(m);
|
||||
// abort();
|
||||
|
@ -23,32 +20,24 @@ public:
|
|||
|
||||
protected:
|
||||
string msg_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionEnforceViolation : public Exception
|
||||
{
|
||||
class ExceptionEnforceViolation : public Exception {
|
||||
public:
|
||||
ExceptionEnforceViolation(const char* where)
|
||||
{
|
||||
append(binpac_fmt("&enforce violation : %s", where));
|
||||
}
|
||||
};
|
||||
ExceptionEnforceViolation(const char* where) { append(binpac_fmt("&enforce violation : %s", where)); }
|
||||
};
|
||||
|
||||
class ExceptionOutOfBound : public Exception
|
||||
{
|
||||
class ExceptionOutOfBound : public Exception {
|
||||
public:
|
||||
ExceptionOutOfBound(const char* where, int len_needed, int len_given)
|
||||
{
|
||||
ExceptionOutOfBound(const char* where, int len_needed, int len_given) {
|
||||
append(binpac_fmt("out_of_bound: %s: %d > %d", where, len_needed, len_given));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionInvalidCase : public Exception
|
||||
{
|
||||
class ExceptionInvalidCase : public Exception {
|
||||
public:
|
||||
ExceptionInvalidCase(const char* location, int64_t index, const char* expected)
|
||||
: location_(location), index_(index), expected_(expected)
|
||||
{
|
||||
: location_(location), index_(index), expected_(expected) {
|
||||
append(binpac_fmt("invalid case: %s: %" PRIi64 " (%s)", location, index, expected));
|
||||
}
|
||||
|
||||
|
@ -56,65 +45,51 @@ protected:
|
|||
const char* location_;
|
||||
int64_t index_;
|
||||
string expected_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionInvalidCaseIndex : public Exception
|
||||
{
|
||||
class ExceptionInvalidCaseIndex : public Exception {
|
||||
public:
|
||||
ExceptionInvalidCaseIndex(const char* location, int64_t index)
|
||||
: location_(location), index_(index)
|
||||
{
|
||||
ExceptionInvalidCaseIndex(const char* location, int64_t index) : location_(location), index_(index) {
|
||||
append(binpac_fmt("invalid index for case: %s: %" PRIi64, location, index));
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* location_;
|
||||
int64_t index_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionInvalidOffset : public Exception
|
||||
{
|
||||
class ExceptionInvalidOffset : public Exception {
|
||||
public:
|
||||
ExceptionInvalidOffset(const char* location, int min_offset, int offset)
|
||||
: location_(location), min_offset_(min_offset), offset_(offset)
|
||||
{
|
||||
append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", location, min_offset,
|
||||
offset));
|
||||
: location_(location), min_offset_(min_offset), offset_(offset) {
|
||||
append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", location, min_offset, offset));
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* location_;
|
||||
int min_offset_, offset_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionStringMismatch : public Exception
|
||||
{
|
||||
class ExceptionStringMismatch : public Exception {
|
||||
public:
|
||||
ExceptionStringMismatch(const char* location, const char* expected, const char* actual_data)
|
||||
{
|
||||
append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"",
|
||||
location, expected, actual_data));
|
||||
ExceptionStringMismatch(const char* location, const char* expected, const char* actual_data) {
|
||||
append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"", location, expected,
|
||||
actual_data));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionInvalidStringLength : public Exception
|
||||
{
|
||||
class ExceptionInvalidStringLength : public Exception {
|
||||
public:
|
||||
ExceptionInvalidStringLength(const char* location, int len)
|
||||
{
|
||||
ExceptionInvalidStringLength(const char* location, int len) {
|
||||
append(binpac_fmt("invalid length string: %s: %d", location, len));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionFlowBufferAlloc : public Exception
|
||||
{
|
||||
class ExceptionFlowBufferAlloc : public Exception {
|
||||
public:
|
||||
ExceptionFlowBufferAlloc(const char* reason)
|
||||
{
|
||||
append(binpac_fmt("flowbuffer allocation failed: %s", reason));
|
||||
}
|
||||
};
|
||||
ExceptionFlowBufferAlloc(const char* reason) { append(binpac_fmt("flowbuffer allocation failed: %s", reason)); }
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_exception_h
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
|
||||
#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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,11 @@
|
|||
|
||||
#include "binpac.h"
|
||||
|
||||
namespace zeek
|
||||
{
|
||||
namespace zeek {
|
||||
class RE_Matcher;
|
||||
}
|
||||
}
|
||||
|
||||
namespace binpac
|
||||
{
|
||||
namespace binpac {
|
||||
|
||||
// Must be called before any binpac functionality is used.
|
||||
//
|
||||
|
@ -23,11 +21,9 @@ inline void init(FlowBuffer::Policy* fbp = 0);
|
|||
// Internal vector recording not yet compiled matchers.
|
||||
extern std::vector<zeek::RE_Matcher*>* uncompiled_re_matchers;
|
||||
|
||||
class RegExMatcher
|
||||
{
|
||||
class RegExMatcher {
|
||||
public:
|
||||
RegExMatcher(const char* pattern) : pattern_(pattern)
|
||||
{
|
||||
RegExMatcher(const char* pattern) : pattern_(pattern) {
|
||||
if ( ! uncompiled_re_matchers )
|
||||
uncompiled_re_matchers = new std::vector<zeek::RE_Matcher*>;
|
||||
|
||||
|
@ -48,33 +44,29 @@ private:
|
|||
|
||||
string pattern_;
|
||||
zeek::RE_Matcher* re_matcher_;
|
||||
};
|
||||
};
|
||||
|
||||
inline void RegExMatcher::init()
|
||||
{
|
||||
inline void RegExMatcher::init() {
|
||||
if ( ! uncompiled_re_matchers )
|
||||
return;
|
||||
|
||||
for ( size_t i = 0; i < uncompiled_re_matchers->size(); ++i )
|
||||
{
|
||||
if ( ! (*uncompiled_re_matchers)[i]->Compile() )
|
||||
{
|
||||
for ( size_t i = 0; i < uncompiled_re_matchers->size(); ++i ) {
|
||||
if ( ! (*uncompiled_re_matchers)[i]->Compile() ) {
|
||||
fprintf(stderr, "binpac: cannot compile regular expression\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uncompiled_re_matchers->clear();
|
||||
}
|
||||
}
|
||||
|
||||
inline void init(FlowBuffer::Policy* fbp)
|
||||
{
|
||||
inline void init(FlowBuffer::Policy* fbp) {
|
||||
RegExMatcher::init();
|
||||
|
||||
if ( fbp )
|
||||
FlowBuffer::init(*fbp);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace binpac
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_regex_h
|
||||
|
|
|
@ -9,38 +9,28 @@
|
|||
#include "pac_utils.h"
|
||||
|
||||
AnalyzerAction::AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code)
|
||||
: AnalyzerElement(ACTION), action_id_(action_id), when_(when), param_(param), code_(code),
|
||||
analyzer_(nullptr)
|
||||
{
|
||||
}
|
||||
: AnalyzerElement(ACTION), action_id_(action_id), when_(when), param_(param), code_(code), analyzer_(nullptr) {}
|
||||
|
||||
AnalyzerAction::~AnalyzerAction()
|
||||
{
|
||||
AnalyzerAction::~AnalyzerAction() {
|
||||
delete action_id_;
|
||||
delete param_;
|
||||
delete code_;
|
||||
}
|
||||
}
|
||||
|
||||
string AnalyzerAction::action_function() const
|
||||
{
|
||||
return strfmt("Action_%s", action_id_->Name());
|
||||
}
|
||||
string AnalyzerAction::action_function() const { return strfmt("Action_%s", action_id_->Name()); }
|
||||
|
||||
void AnalyzerAction::InstallHook(AnalyzerDecl* analyzer)
|
||||
{
|
||||
void AnalyzerAction::InstallHook(AnalyzerDecl* analyzer) {
|
||||
ASSERT(0);
|
||||
analyzer_ = analyzer;
|
||||
// param_->MainDataType()->InstallAction(this);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerAction::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl)
|
||||
{
|
||||
void AnalyzerAction::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) {
|
||||
Env action_func_env(decl->env(), this);
|
||||
action_func_env.AddID(param_->id(), TEMP_VAR, param_->DataType());
|
||||
action_func_env.SetEvaluated(param_->id());
|
||||
|
||||
string action_func_proto = strfmt("%s(%s)", action_function().c_str(),
|
||||
ParamDecls(&action_func_env).c_str());
|
||||
string action_func_proto = strfmt("%s(%s)", action_function().c_str(), ParamDecls(&action_func_env).c_str());
|
||||
|
||||
out_h->println("void %s;", action_func_proto.c_str());
|
||||
|
||||
|
@ -54,48 +44,37 @@ void AnalyzerAction::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl)
|
|||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
out_cc->println("");
|
||||
}
|
||||
}
|
||||
|
||||
string AnalyzerAction::ParamDecls(Env* env) const
|
||||
{
|
||||
return param_->DeclStr(env);
|
||||
}
|
||||
string AnalyzerAction::ParamDecls(Env* env) const { return param_->DeclStr(env); }
|
||||
|
||||
Type* ActionParam::MainDataType() const
|
||||
{
|
||||
Type* ActionParam::MainDataType() const {
|
||||
// Note: this is not equal to DataType()
|
||||
Type* main_type = TypeDecl::LookUpType(type()->type_id());
|
||||
|
||||
if ( ! main_type )
|
||||
{
|
||||
if ( ! main_type ) {
|
||||
throw Exception(type()->type_id(), "type not defined");
|
||||
}
|
||||
|
||||
return main_type;
|
||||
}
|
||||
}
|
||||
|
||||
Type* ActionParam::DataType() const
|
||||
{
|
||||
Type* ActionParam::DataType() const {
|
||||
Type* main_type = MainDataType();
|
||||
|
||||
if ( ! type()->field_id() )
|
||||
{
|
||||
if ( ! type()->field_id() ) {
|
||||
return main_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
Type* member_type = main_type->MemberDataType(type()->field_id());
|
||||
if ( ! member_type )
|
||||
{
|
||||
throw Exception(type()->field_id(),
|
||||
strfmt("cannot find member type for `%s.%s'", type()->type_id()->Name(),
|
||||
if ( ! member_type ) {
|
||||
throw Exception(type()->field_id(), strfmt("cannot find member type for `%s.%s'", type()->type_id()->Name(),
|
||||
type()->field_id()->Name()));
|
||||
}
|
||||
return member_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string ActionParam::DeclStr(Env* env) const
|
||||
{
|
||||
string ActionParam::DeclStr(Env* env) const {
|
||||
return strfmt("%s %s", DataType()->DataTypeStr().c_str(), env->LValue(id()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,14 +6,9 @@
|
|||
#include "pac_analyzer.h"
|
||||
#include "pac_common.h"
|
||||
|
||||
class AnalyzerAction : public AnalyzerElement
|
||||
{
|
||||
class AnalyzerAction : public AnalyzerElement {
|
||||
public:
|
||||
enum When
|
||||
{
|
||||
BEFORE,
|
||||
AFTER
|
||||
};
|
||||
enum When { BEFORE, AFTER };
|
||||
|
||||
AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code);
|
||||
|
||||
|
@ -39,12 +34,11 @@ private:
|
|||
ActionParam* param_;
|
||||
EmbeddedCode* code_;
|
||||
AnalyzerDecl* analyzer_;
|
||||
};
|
||||
};
|
||||
|
||||
class ActionParam
|
||||
{
|
||||
class ActionParam {
|
||||
public:
|
||||
ActionParam(const ID* id, ActionParamType* type) : id_(id), type_(type) { }
|
||||
ActionParam(const ID* id, ActionParamType* type) : id_(id), type_(type) {}
|
||||
|
||||
const ID* id() const { return id_; }
|
||||
ActionParamType* type() const { return type_; }
|
||||
|
@ -56,21 +50,17 @@ public:
|
|||
private:
|
||||
const ID* id_;
|
||||
ActionParamType* type_;
|
||||
};
|
||||
};
|
||||
|
||||
class ActionParamType
|
||||
{
|
||||
class ActionParamType {
|
||||
public:
|
||||
ActionParamType(const ID* type_id, const ID* field_id = 0)
|
||||
: type_id_(type_id), field_id_(field_id)
|
||||
{
|
||||
}
|
||||
ActionParamType(const ID* type_id, const ID* field_id = 0) : type_id_(type_id), field_id_(field_id) {}
|
||||
|
||||
const ID* type_id() const { return type_id_; }
|
||||
const ID* field_id() const { return field_id_; }
|
||||
|
||||
protected:
|
||||
const ID *type_id_, *field_id_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_action_h
|
||||
|
|
|
@ -14,9 +14,7 @@
|
|||
#include "pac_type.h"
|
||||
#include "pac_varfield.h"
|
||||
|
||||
AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params)
|
||||
: TypeDecl(id, params, new DummyType())
|
||||
{
|
||||
AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params) : TypeDecl(id, params, new DummyType()) {
|
||||
decl_type_ = decl_type;
|
||||
|
||||
statevars_ = new StateVarList();
|
||||
|
@ -31,10 +29,9 @@ AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params)
|
|||
SetAnalyzerContext();
|
||||
|
||||
env_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AnalyzerDecl::~AnalyzerDecl()
|
||||
{
|
||||
AnalyzerDecl::~AnalyzerDecl() {
|
||||
delete_list(StateVarList, statevars_);
|
||||
delete_list(AnalyzerActionList, actions_);
|
||||
delete_list(AnalyzerHelperList, helpers_);
|
||||
|
@ -43,132 +40,94 @@ AnalyzerDecl::~AnalyzerDecl()
|
|||
delete_list(AnalyzerHelperList, constructor_helpers_);
|
||||
delete_list(AnalyzerHelperList, destructor_helpers_);
|
||||
delete_list(AnalyzerHelperList, eof_helpers_);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::AddElements(AnalyzerElementList* elemlist)
|
||||
{
|
||||
void AnalyzerDecl::AddElements(AnalyzerElementList* elemlist) {
|
||||
ASSERT(! env_);
|
||||
foreach (i, AnalyzerElementList, elemlist)
|
||||
{
|
||||
foreach (i, AnalyzerElementList, elemlist) {
|
||||
AnalyzerElement* elem = *i;
|
||||
switch ( elem->type() )
|
||||
{
|
||||
case AnalyzerElement::STATE:
|
||||
{
|
||||
switch ( elem->type() ) {
|
||||
case AnalyzerElement::STATE: {
|
||||
ASSERT(0);
|
||||
AnalyzerState* state_elem = (AnalyzerState*)elem;
|
||||
statevars_->insert(statevars_->end(), state_elem->statevars()->begin(),
|
||||
state_elem->statevars()->end());
|
||||
}
|
||||
break;
|
||||
case AnalyzerElement::ACTION:
|
||||
{
|
||||
statevars_->insert(statevars_->end(), state_elem->statevars()->begin(), state_elem->statevars()->end());
|
||||
} break;
|
||||
case AnalyzerElement::ACTION: {
|
||||
ASSERT(0);
|
||||
AnalyzerAction* action_elem = (AnalyzerAction*)elem;
|
||||
actions_->push_back(action_elem);
|
||||
}
|
||||
break;
|
||||
case AnalyzerElement::HELPER:
|
||||
{
|
||||
} break;
|
||||
case AnalyzerElement::HELPER: {
|
||||
AnalyzerHelper* helper_elem = (AnalyzerHelper*)elem;
|
||||
|
||||
switch ( helper_elem->helper_type() )
|
||||
{
|
||||
case AnalyzerHelper::INIT_CODE:
|
||||
constructor_helpers_->push_back(helper_elem);
|
||||
break;
|
||||
case AnalyzerHelper::CLEANUP_CODE:
|
||||
destructor_helpers_->push_back(helper_elem);
|
||||
break;
|
||||
case AnalyzerHelper::EOF_CODE:
|
||||
eof_helpers_->push_back(helper_elem);
|
||||
break;
|
||||
default:
|
||||
helpers_->push_back(helper_elem);
|
||||
switch ( helper_elem->helper_type() ) {
|
||||
case AnalyzerHelper::INIT_CODE: constructor_helpers_->push_back(helper_elem); break;
|
||||
case AnalyzerHelper::CLEANUP_CODE: destructor_helpers_->push_back(helper_elem); break;
|
||||
case AnalyzerHelper::EOF_CODE: eof_helpers_->push_back(helper_elem); break;
|
||||
default: helpers_->push_back(helper_elem);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AnalyzerElement::FUNCTION:
|
||||
{
|
||||
} break;
|
||||
case AnalyzerElement::FUNCTION: {
|
||||
AnalyzerFunction* func_elem = (AnalyzerFunction*)elem;
|
||||
Function* func = func_elem->function();
|
||||
func->set_analyzer_decl(this);
|
||||
functions_->push_back(func);
|
||||
}
|
||||
break;
|
||||
case AnalyzerElement::FLOW:
|
||||
{
|
||||
} break;
|
||||
case AnalyzerElement::FLOW: {
|
||||
AnalyzerFlow* flow_elem = (AnalyzerFlow*)elem;
|
||||
ProcessFlowElement(flow_elem);
|
||||
}
|
||||
break;
|
||||
case AnalyzerElement::DATAUNIT:
|
||||
{
|
||||
} break;
|
||||
case AnalyzerElement::DATAUNIT: {
|
||||
AnalyzerDataUnit* dataunit_elem = (AnalyzerDataUnit*)elem;
|
||||
ProcessDataUnitElement(dataunit_elem);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string AnalyzerDecl::class_name() const
|
||||
{
|
||||
return id_->Name();
|
||||
}
|
||||
string AnalyzerDecl::class_name() const { return id_->Name(); }
|
||||
|
||||
void AnalyzerDecl::Prepare()
|
||||
{
|
||||
void AnalyzerDecl::Prepare() {
|
||||
TypeDecl::Prepare();
|
||||
|
||||
ASSERT(statevars_->empty());
|
||||
ASSERT(actions_->empty());
|
||||
|
||||
foreach (i, FunctionList, functions_)
|
||||
{
|
||||
foreach (i, FunctionList, functions_) {
|
||||
Function* function = *i;
|
||||
function->Prepare(env_);
|
||||
}
|
||||
foreach (i, StateVarList, statevars_)
|
||||
{
|
||||
foreach (i, StateVarList, statevars_) {
|
||||
StateVar* statevar = *i;
|
||||
env_->AddID(statevar->id(), STATE_VAR, statevar->type());
|
||||
}
|
||||
foreach (i, AnalyzerActionList, actions_)
|
||||
{
|
||||
foreach (i, AnalyzerActionList, actions_) {
|
||||
AnalyzerAction* action = *i;
|
||||
action->InstallHook(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenForwardDeclaration(Output* out_h)
|
||||
{
|
||||
void AnalyzerDecl::GenForwardDeclaration(Output* out_h) {
|
||||
out_h->println("class %s;", class_name().c_str());
|
||||
foreach (i, FunctionList, functions_)
|
||||
{
|
||||
foreach (i, FunctionList, functions_) {
|
||||
Function* function = *i;
|
||||
function->GenForwardDeclaration(out_h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenActions(Output* out_h, Output* out_cc)
|
||||
{
|
||||
foreach (i, AnalyzerActionList, actions_)
|
||||
{
|
||||
void AnalyzerDecl::GenActions(Output* out_h, Output* out_cc) {
|
||||
foreach (i, AnalyzerActionList, actions_) {
|
||||
(*i)->GenCode(out_h, out_cc, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenHelpers(Output* out_h, Output* out_cc)
|
||||
{
|
||||
foreach (i, AnalyzerHelperList, helpers_)
|
||||
{
|
||||
void AnalyzerDecl::GenHelpers(Output* out_h, Output* out_cc) {
|
||||
foreach (i, AnalyzerHelperList, helpers_) {
|
||||
(*i)->GenCode(out_h, out_cc, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc) {
|
||||
TypeDecl::GenPubDecls(out_h, out_cc);
|
||||
|
||||
GenProcessFunc(out_h, out_cc);
|
||||
|
@ -176,136 +135,103 @@ void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc)
|
|||
GenEOFFunc(out_h, out_cc);
|
||||
out_h->println("");
|
||||
|
||||
if ( ! functions_->empty() )
|
||||
{
|
||||
if ( ! functions_->empty() ) {
|
||||
out_h->println("// Functions");
|
||||
GenFunctions(out_h, out_cc);
|
||||
out_h->println("");
|
||||
}
|
||||
|
||||
// TODO: export public state variables
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenPrivDecls(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void AnalyzerDecl::GenPrivDecls(Output* out_h, Output* out_cc) {
|
||||
TypeDecl::GenPrivDecls(out_h, out_cc);
|
||||
|
||||
if ( ! helpers_->empty() )
|
||||
{
|
||||
if ( ! helpers_->empty() ) {
|
||||
out_h->println("");
|
||||
out_h->println("// Additional members");
|
||||
GenHelpers(out_h, out_cc);
|
||||
}
|
||||
|
||||
// TODO: declare state variables
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenInitCode(Output* out_cc)
|
||||
{
|
||||
void AnalyzerDecl::GenInitCode(Output* out_cc) {
|
||||
TypeDecl::GenInitCode(out_cc);
|
||||
foreach (i, AnalyzerHelperList, constructor_helpers_)
|
||||
{
|
||||
foreach (i, AnalyzerHelperList, constructor_helpers_) {
|
||||
(*i)->GenCode(nullptr, out_cc, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenCleanUpCode(Output* out_cc)
|
||||
{
|
||||
void AnalyzerDecl::GenCleanUpCode(Output* out_cc) {
|
||||
TypeDecl::GenCleanUpCode(out_cc);
|
||||
foreach (i, AnalyzerHelperList, destructor_helpers_)
|
||||
{
|
||||
foreach (i, AnalyzerHelperList, destructor_helpers_) {
|
||||
(*i)->GenCode(nullptr, out_cc, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenStateVarDecls(Output* out_h)
|
||||
{
|
||||
foreach (i, StateVarList, statevars_)
|
||||
{
|
||||
void AnalyzerDecl::GenStateVarDecls(Output* out_h) {
|
||||
foreach (i, StateVarList, statevars_) {
|
||||
StateVar* var = *i;
|
||||
var->GenDecl(out_h, env_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenStateVarSetFunctions(Output* out_h)
|
||||
{
|
||||
foreach (i, StateVarList, statevars_)
|
||||
{
|
||||
void AnalyzerDecl::GenStateVarSetFunctions(Output* out_h) {
|
||||
foreach (i, StateVarList, statevars_) {
|
||||
StateVar* var = *i;
|
||||
var->GenSetFunction(out_h, env_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenStateVarInitCode(Output* out_cc)
|
||||
{
|
||||
foreach (i, StateVarList, statevars_)
|
||||
{
|
||||
void AnalyzerDecl::GenStateVarInitCode(Output* out_cc) {
|
||||
foreach (i, StateVarList, statevars_) {
|
||||
StateVar* var = *i;
|
||||
var->GenInitCode(out_cc, env_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenStateVarCleanUpCode(Output* out_cc)
|
||||
{
|
||||
foreach (i, StateVarList, statevars_)
|
||||
{
|
||||
void AnalyzerDecl::GenStateVarCleanUpCode(Output* out_cc) {
|
||||
foreach (i, StateVarList, statevars_) {
|
||||
StateVar* var = *i;
|
||||
var->GenCleanUpCode(out_cc, env_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDecl::GenFunctions(Output* out_h, Output* out_cc)
|
||||
{
|
||||
foreach (i, FunctionList, functions_)
|
||||
{
|
||||
void AnalyzerDecl::GenFunctions(Output* out_h, Output* out_cc) {
|
||||
foreach (i, FunctionList, functions_) {
|
||||
Function* function = *i;
|
||||
function->GenCode(out_h, out_cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnalyzerState::~AnalyzerState()
|
||||
{
|
||||
AnalyzerState::~AnalyzerState() {
|
||||
// Note: do not delete elements of statevars_, because they
|
||||
// are referenced by the AnalyzerDecl.
|
||||
delete statevars_;
|
||||
}
|
||||
}
|
||||
|
||||
AnalyzerHelper::~AnalyzerHelper()
|
||||
{
|
||||
delete code_;
|
||||
}
|
||||
AnalyzerHelper::~AnalyzerHelper() { delete code_; }
|
||||
|
||||
void AnalyzerHelper::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl)
|
||||
{
|
||||
void AnalyzerHelper::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) {
|
||||
Output* out = nullptr;
|
||||
switch ( helper_type_ )
|
||||
{
|
||||
case MEMBER_DECLS:
|
||||
out = out_h;
|
||||
break;
|
||||
switch ( helper_type_ ) {
|
||||
case MEMBER_DECLS: out = out_h; break;
|
||||
case INIT_CODE:
|
||||
case CLEANUP_CODE:
|
||||
case EOF_CODE:
|
||||
out = out_cc;
|
||||
break;
|
||||
case EOF_CODE: out = out_cc; break;
|
||||
}
|
||||
ASSERT(out);
|
||||
code()->GenCode(out, decl->env());
|
||||
}
|
||||
}
|
||||
|
||||
FlowField::FlowField(ID* flow_id, ParameterizedType* flow_type)
|
||||
: Field(FLOW_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, flow_id, flow_type)
|
||||
{
|
||||
}
|
||||
: Field(FLOW_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, flow_id, flow_type) {}
|
||||
|
||||
void FlowField::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
type_->GenPreParsing(out_cc, env);
|
||||
}
|
||||
void FlowField::GenInitCode(Output* out_cc, Env* env) { type_->GenPreParsing(out_cc, env); }
|
||||
|
||||
AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params)
|
||||
: AnalyzerElement(FLOW), dir_(dir), type_id_(type_id)
|
||||
{
|
||||
: AnalyzerElement(FLOW), dir_(dir), type_id_(type_id) {
|
||||
if ( ! params )
|
||||
params = new ExprList();
|
||||
|
||||
|
@ -319,25 +245,19 @@ AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params)
|
|||
flow_field_ = new FlowField(flow_id, flow_type);
|
||||
|
||||
flow_decl_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AnalyzerFlow::~AnalyzerFlow()
|
||||
{
|
||||
delete flow_field_;
|
||||
}
|
||||
AnalyzerFlow::~AnalyzerFlow() { delete flow_field_; }
|
||||
|
||||
FlowDecl* AnalyzerFlow::flow_decl()
|
||||
{
|
||||
FlowDecl* AnalyzerFlow::flow_decl() {
|
||||
DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name());
|
||||
if ( ! flow_decl_ )
|
||||
{
|
||||
if ( ! flow_decl_ ) {
|
||||
Decl* decl = Decl::LookUpDecl(type_id_);
|
||||
if ( decl && decl->decl_type() == Decl::FLOW )
|
||||
flow_decl_ = static_cast<FlowDecl*>(decl);
|
||||
if ( ! flow_decl_ )
|
||||
{
|
||||
if ( ! flow_decl_ ) {
|
||||
throw Exception(this, "cannot find the flow declaration");
|
||||
}
|
||||
}
|
||||
return flow_decl_;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,7 @@ class FlowDecl;
|
|||
typedef vector<AnalyzerHelper*> AnalyzerHelperList;
|
||||
typedef vector<Function*> FunctionList;
|
||||
|
||||
class AnalyzerDecl : public TypeDecl
|
||||
{
|
||||
class AnalyzerDecl : public TypeDecl {
|
||||
public:
|
||||
AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params);
|
||||
~AnalyzerDecl() override;
|
||||
|
@ -79,57 +78,43 @@ protected:
|
|||
AnalyzerHelperList* constructor_helpers_;
|
||||
AnalyzerHelperList* destructor_helpers_;
|
||||
AnalyzerHelperList* eof_helpers_;
|
||||
};
|
||||
};
|
||||
|
||||
class AnalyzerElement : public Object
|
||||
{
|
||||
class AnalyzerElement : public Object {
|
||||
public:
|
||||
enum ElementType
|
||||
{
|
||||
STATE,
|
||||
ACTION,
|
||||
FUNCTION,
|
||||
HELPER,
|
||||
FLOW,
|
||||
DATAUNIT
|
||||
};
|
||||
AnalyzerElement(ElementType type) : type_(type) { }
|
||||
virtual ~AnalyzerElement() { }
|
||||
enum ElementType { STATE, ACTION, FUNCTION, HELPER, FLOW, DATAUNIT };
|
||||
AnalyzerElement(ElementType type) : type_(type) {}
|
||||
virtual ~AnalyzerElement() {}
|
||||
|
||||
ElementType type() const { return type_; }
|
||||
|
||||
private:
|
||||
ElementType type_;
|
||||
};
|
||||
};
|
||||
|
||||
// A collection of variables representing analyzer states.
|
||||
class AnalyzerState : public AnalyzerElement
|
||||
{
|
||||
class AnalyzerState : public AnalyzerElement {
|
||||
public:
|
||||
AnalyzerState(StateVarList* statevars) : AnalyzerElement(STATE), statevars_(statevars) { }
|
||||
AnalyzerState(StateVarList* statevars) : AnalyzerElement(STATE), statevars_(statevars) {}
|
||||
~AnalyzerState() override;
|
||||
|
||||
StateVarList* statevars() const { return statevars_; }
|
||||
|
||||
private:
|
||||
StateVarList* statevars_;
|
||||
};
|
||||
};
|
||||
|
||||
// A collection of embedded C++ code
|
||||
class AnalyzerHelper : public AnalyzerElement
|
||||
{
|
||||
class AnalyzerHelper : public AnalyzerElement {
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
enum Type {
|
||||
MEMBER_DECLS,
|
||||
INIT_CODE,
|
||||
CLEANUP_CODE,
|
||||
EOF_CODE,
|
||||
};
|
||||
AnalyzerHelper(Type helper_type, EmbeddedCode* code)
|
||||
: AnalyzerElement(HELPER), helper_type_(helper_type), code_(code)
|
||||
{
|
||||
}
|
||||
: AnalyzerElement(HELPER), helper_type_(helper_type), code_(code) {}
|
||||
~AnalyzerHelper() override;
|
||||
|
||||
Type helper_type() const { return helper_type_; }
|
||||
|
@ -141,25 +126,19 @@ public:
|
|||
private:
|
||||
Type helper_type_;
|
||||
EmbeddedCode* code_;
|
||||
};
|
||||
};
|
||||
|
||||
// The type and parameters of (uni-directional) flows of a connection.
|
||||
|
||||
class FlowField : public Field
|
||||
{
|
||||
class FlowField : public Field {
|
||||
public:
|
||||
FlowField(ID* flow_id, ParameterizedType* flow_type);
|
||||
void GenInitCode(Output* out, Env* env) override;
|
||||
};
|
||||
};
|
||||
|
||||
class AnalyzerFlow : public AnalyzerElement
|
||||
{
|
||||
class AnalyzerFlow : public AnalyzerElement {
|
||||
public:
|
||||
enum Direction
|
||||
{
|
||||
UP,
|
||||
DOWN
|
||||
};
|
||||
enum Direction { UP, DOWN };
|
||||
AnalyzerFlow(Direction dir, ID* type_id, ExprList* params);
|
||||
~AnalyzerFlow() override;
|
||||
|
||||
|
@ -173,6 +152,6 @@ private:
|
|||
ID* type_id_;
|
||||
FlowField* flow_field_;
|
||||
FlowDecl* flow_decl_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_analyzer_h
|
||||
|
|
|
@ -11,32 +11,25 @@
|
|||
#include "pac_utils.h"
|
||||
#include "pac_varfield.h"
|
||||
|
||||
ArrayType::ArrayType(Type* elemtype, Expr* length)
|
||||
: Type(ARRAY), elemtype_(elemtype), length_(length)
|
||||
{
|
||||
ArrayType::ArrayType(Type* elemtype, Expr* length) : Type(ARRAY), elemtype_(elemtype), length_(length) {
|
||||
init();
|
||||
|
||||
switch ( elemtype_->tot() )
|
||||
{
|
||||
switch ( elemtype_->tot() ) {
|
||||
case BUILTIN:
|
||||
case PARAMETERIZED:
|
||||
case STRING:
|
||||
case EXTERN:
|
||||
break;
|
||||
case EXTERN: break;
|
||||
|
||||
case ARRAY:
|
||||
case CASE:
|
||||
case DUMMY:
|
||||
case EMPTY:
|
||||
case RECORD:
|
||||
case UNDEF:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
case UNDEF: ASSERT(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::init()
|
||||
{
|
||||
void ArrayType::init() {
|
||||
arraylength_var_field_ = nullptr;
|
||||
elem_it_var_field_ = nullptr;
|
||||
elem_var_field_ = nullptr;
|
||||
|
@ -54,10 +47,9 @@ void ArrayType::init()
|
|||
attr_generic_until_expr_ = nullptr;
|
||||
attr_until_element_expr_ = nullptr;
|
||||
attr_until_input_expr_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayType::~ArrayType()
|
||||
{
|
||||
ArrayType::~ArrayType() {
|
||||
delete arraylength_var_field_;
|
||||
delete elem_it_var_field_;
|
||||
delete elem_var_field_;
|
||||
|
@ -65,140 +57,101 @@ ArrayType::~ArrayType()
|
|||
delete elem_input_var_field_;
|
||||
|
||||
delete elem_dataptr_until_expr_;
|
||||
}
|
||||
}
|
||||
|
||||
Type* ArrayType::DoClone() const
|
||||
{
|
||||
Type* ArrayType::DoClone() const {
|
||||
Type* elemtype = elemtype_->Clone();
|
||||
if ( ! elemtype )
|
||||
return nullptr;
|
||||
return new ArrayType(elemtype, length_);
|
||||
}
|
||||
}
|
||||
|
||||
bool ArrayType::DefineValueVar() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool ArrayType::DefineValueVar() const { return true; }
|
||||
|
||||
string ArrayType::DataTypeStr() const
|
||||
{
|
||||
return datatype_str_;
|
||||
}
|
||||
string ArrayType::DataTypeStr() const { return datatype_str_; }
|
||||
|
||||
Type* ArrayType::ElementDataType() const
|
||||
{
|
||||
return elemtype_;
|
||||
}
|
||||
Type* ArrayType::ElementDataType() const { return elemtype_; }
|
||||
|
||||
string ArrayType::EvalElement(const string& array, const string& index) const
|
||||
{
|
||||
string ArrayType::EvalElement(const string& array, const string& index) const {
|
||||
if ( attr_transient_ )
|
||||
throw Exception(this, "cannot access element in &transient array");
|
||||
|
||||
return strfmt("(*(%s))[%s]", array.c_str(), index.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
const ID* ArrayType::arraylength_var() const
|
||||
{
|
||||
return arraylength_var_field_ ? arraylength_var_field_->id() : nullptr;
|
||||
}
|
||||
const ID* ArrayType::arraylength_var() const { return arraylength_var_field_ ? arraylength_var_field_->id() : nullptr; }
|
||||
|
||||
const ID* ArrayType::elem_it_var() const
|
||||
{
|
||||
return elem_it_var_field_ ? elem_it_var_field_->id() : nullptr;
|
||||
}
|
||||
const ID* ArrayType::elem_it_var() const { return elem_it_var_field_ ? elem_it_var_field_->id() : nullptr; }
|
||||
|
||||
const ID* ArrayType::elem_var() const
|
||||
{
|
||||
return elem_var_field_ ? elem_var_field_->id() : nullptr;
|
||||
}
|
||||
const ID* ArrayType::elem_var() const { 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;
|
||||
}
|
||||
}
|
||||
|
||||
const ID* ArrayType::elem_input_var() const
|
||||
{
|
||||
return elem_input_var_field_ ? elem_input_var_field_->id() : nullptr;
|
||||
}
|
||||
const ID* ArrayType::elem_input_var() const { return elem_input_var_field_ ? elem_input_var_field_->id() : nullptr; }
|
||||
|
||||
void ArrayType::ProcessAttr(Attr* a)
|
||||
{
|
||||
void ArrayType::ProcessAttr(Attr* a) {
|
||||
Type::ProcessAttr(a);
|
||||
|
||||
switch ( a->type() )
|
||||
{
|
||||
case ATTR_RESTOFDATA:
|
||||
{
|
||||
if ( elemtype_->StaticSize(env()) != 1 )
|
||||
{
|
||||
throw Exception(elemtype_, "&restofdata can be applied"
|
||||
switch ( a->type() ) {
|
||||
case ATTR_RESTOFDATA: {
|
||||
if ( elemtype_->StaticSize(env()) != 1 ) {
|
||||
throw Exception(elemtype_,
|
||||
"&restofdata can be applied"
|
||||
" to only byte arrays");
|
||||
}
|
||||
if ( length_ )
|
||||
{
|
||||
throw Exception(length_, "&restofdata cannot be applied"
|
||||
if ( length_ ) {
|
||||
throw Exception(length_,
|
||||
"&restofdata cannot be applied"
|
||||
" to arrays with specified length");
|
||||
}
|
||||
attr_restofdata_ = true;
|
||||
// As the array automatically extends to the end of
|
||||
// data, we do not have to check boundary.
|
||||
SetBoundaryChecked();
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ATTR_RESTOFFLOW:
|
||||
attr_restofflow_ = true;
|
||||
// TODO: handle &restofflow
|
||||
break;
|
||||
|
||||
case ATTR_UNTIL:
|
||||
{
|
||||
case ATTR_UNTIL: {
|
||||
bool ref_element = a->expr()->HasReference(element_macro_id);
|
||||
bool ref_input = a->expr()->HasReference(input_macro_id);
|
||||
if ( ref_element && ref_input )
|
||||
{
|
||||
throw Exception(a->expr(), "cannot reference both $element and $input "
|
||||
if ( ref_element && ref_input ) {
|
||||
throw Exception(a->expr(),
|
||||
"cannot reference both $element and $input "
|
||||
"in the same &until---please separate them.");
|
||||
}
|
||||
|
||||
if ( ref_element )
|
||||
{
|
||||
if ( attr_until_element_expr_ )
|
||||
{
|
||||
if ( ref_element ) {
|
||||
if ( attr_until_element_expr_ ) {
|
||||
throw Exception(a->expr(), "multiple &until on $element");
|
||||
}
|
||||
attr_until_element_expr_ = a->expr();
|
||||
}
|
||||
else if ( ref_input )
|
||||
{
|
||||
if ( attr_until_input_expr_ )
|
||||
{
|
||||
else if ( ref_input ) {
|
||||
if ( attr_until_input_expr_ ) {
|
||||
throw Exception(a->expr(), "multiple &until on $input");
|
||||
}
|
||||
attr_until_input_expr_ = a->expr();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( attr_generic_until_expr_ )
|
||||
{
|
||||
else {
|
||||
if ( attr_generic_until_expr_ ) {
|
||||
throw Exception(a->expr(), "multiple &until condition");
|
||||
}
|
||||
attr_generic_until_expr_ = a->expr();
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::Prepare(Env* env, int flags)
|
||||
{
|
||||
if ( flags & TO_BE_PARSED )
|
||||
{
|
||||
void ArrayType::Prepare(Env* env, int flags) {
|
||||
if ( flags & TO_BE_PARSED ) {
|
||||
ID* arraylength_var = new ID(strfmt("%s__arraylength", value_var()->Name()));
|
||||
ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name()));
|
||||
ID* elem_it_var = new ID(strfmt("%s__it", elem_var->Name()));
|
||||
|
@ -206,16 +159,14 @@ void ArrayType::Prepare(Env* env, int flags)
|
|||
elem_var_field_ = new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_);
|
||||
AddField(elem_var_field_);
|
||||
|
||||
if ( incremental_parsing() )
|
||||
{
|
||||
if ( incremental_parsing() ) {
|
||||
arraylength_var_field_ = new PrivVarField(arraylength_var, extern_type_int->Clone());
|
||||
elem_it_var_field_ = new PrivVarField(elem_it_var, extern_type_int->Clone());
|
||||
|
||||
AddField(arraylength_var_field_);
|
||||
AddField(elem_it_var_field_);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
arraylength_var_field_ = new TempVarField(arraylength_var, extern_type_int->Clone());
|
||||
elem_it_var_field_ = new TempVarField(elem_it_var, extern_type_int->Clone());
|
||||
|
||||
|
@ -224,17 +175,15 @@ void ArrayType::Prepare(Env* env, int flags)
|
|||
|
||||
// Add elem_dataptr_var only when not parsing incrementally
|
||||
ID* elem_dataptr_var = new ID(strfmt("%s__dataptr", elem_var->Name()));
|
||||
elem_dataptr_var_field_ = new TempVarField(elem_dataptr_var,
|
||||
extern_type_const_byteptr->Clone());
|
||||
elem_dataptr_var_field_ = new TempVarField(elem_dataptr_var, extern_type_const_byteptr->Clone());
|
||||
elem_dataptr_var_field_->Prepare(env);
|
||||
|
||||
// until(dataptr >= end_of_data)
|
||||
elem_dataptr_until_expr_ = new Expr(Expr::EXPR_GE, new Expr(elem_dataptr_var->clone()),
|
||||
new Expr(end_of_data->clone()));
|
||||
elem_dataptr_until_expr_ =
|
||||
new Expr(Expr::EXPR_GE, new Expr(elem_dataptr_var->clone()), new Expr(end_of_data->clone()));
|
||||
}
|
||||
|
||||
if ( attr_until_input_expr_ )
|
||||
{
|
||||
if ( attr_until_input_expr_ ) {
|
||||
elemtype_->SetUntilCheck(this);
|
||||
}
|
||||
|
||||
|
@ -242,23 +191,20 @@ void ArrayType::Prepare(Env* env, int flags)
|
|||
}
|
||||
|
||||
Type::Prepare(env, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data)
|
||||
{
|
||||
void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data) {
|
||||
if ( env->Evaluated(arraylength_var()) )
|
||||
return;
|
||||
|
||||
if ( ! incremental_parsing() )
|
||||
{
|
||||
if ( ! incremental_parsing() ) {
|
||||
arraylength_var_field_->GenTempDecls(out_cc, env);
|
||||
// This is about to get initialized below, don't initialize it twice.
|
||||
if ( ! length_ && ! attr_restofdata_ )
|
||||
arraylength_var_field_->GenInitCode(out_cc, env);
|
||||
}
|
||||
|
||||
if ( length_ )
|
||||
{
|
||||
if ( length_ ) {
|
||||
out_cc->println("%s = %s;", env->LValue(arraylength_var()), length_->EvalExpr(out_cc, env));
|
||||
|
||||
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->println("{");
|
||||
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str());
|
||||
out_cc->println(" %s, (%s) - (%s));", env->LValue(arraylength_var()),
|
||||
env->RValue(end_of_data), env->RValue(begin_of_data));
|
||||
out_cc->println(" %s, (%s) - (%s));", env->LValue(arraylength_var()), env->RValue(end_of_data),
|
||||
env->RValue(begin_of_data));
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
|
||||
int element_size;
|
||||
|
||||
if ( elemtype_->StaticSize(env) == -1 )
|
||||
{
|
||||
if ( elemtype_->StaticSize(env) == -1 ) {
|
||||
// Check for overlong array quantity. We cap it at the maximum
|
||||
// array size (assume 1-byte elements * array length) as we can't
|
||||
// possibly store more elements. e.g. this helps prevent
|
||||
|
@ -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());
|
||||
element_size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Boundary check the entire array if elements have static size.
|
||||
out_cc->println("// Check bounds for static-size array: %s", data_id_str_.c_str());
|
||||
elemtype_->SetBoundaryChecked();
|
||||
element_size = elemtype_->StaticSize(env);
|
||||
|
||||
if ( element_size == 0 )
|
||||
{
|
||||
if ( element_size == 0 ) {
|
||||
// If we know we have an array of empty elements, probably
|
||||
// better to structure the parser as just a single empty
|
||||
// field to avoid DoS vulnerability of allocating
|
||||
// arbitrary number of empty records (i.e. cheap for them,
|
||||
// but costly for us unless we have special optimization
|
||||
// for this scenario to forgo the usual allocation).
|
||||
throw Exception(
|
||||
this, "using an array of known-to-be-empty elements is possibly a bad idea");
|
||||
throw Exception(this, "using an array of known-to-be-empty elements is possibly a bad idea");
|
||||
}
|
||||
}
|
||||
|
||||
const char* array_ptr_expr = data.ptr_expr();
|
||||
string max_elements_available = strfmt("((%s - %s) / %d)", env->RValue(end_of_data),
|
||||
array_ptr_expr, element_size);
|
||||
string max_elements_available =
|
||||
strfmt("((%s - %s) / %d)", env->RValue(end_of_data), array_ptr_expr, element_size);
|
||||
|
||||
out_cc->println("if ( %s > %s )", env->RValue(arraylength_var()),
|
||||
max_elements_available.c_str());
|
||||
out_cc->println("if ( %s > %s )", env->RValue(arraylength_var()), max_elements_available.c_str());
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str());
|
||||
out_cc->println(" %s, (%s) - (%s));", env->RValue(arraylength_var()),
|
||||
env->RValue(end_of_data), array_ptr_expr);
|
||||
out_cc->println(" %s, (%s) - (%s));", env->RValue(arraylength_var()), env->RValue(end_of_data),
|
||||
array_ptr_expr);
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
else if ( attr_restofdata_ )
|
||||
{
|
||||
else if ( attr_restofdata_ ) {
|
||||
ASSERT(elemtype_->StaticSize(env) == 1);
|
||||
out_cc->println("%s = (%s) - (%s);", env->LValue(arraylength_var()),
|
||||
env->RValue(end_of_data), data.ptr_expr());
|
||||
out_cc->println("%s = (%s) - (%s);", env->LValue(arraylength_var()), env->RValue(end_of_data), data.ptr_expr());
|
||||
env->SetEvaluated(arraylength_var());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::GenPubDecls(Output* out_h, Env* env)
|
||||
{
|
||||
void ArrayType::GenPubDecls(Output* out_h, Env* env) {
|
||||
Type::GenPubDecls(out_h, env);
|
||||
|
||||
if ( declared_as_type() )
|
||||
{
|
||||
if ( declared_as_type() ) {
|
||||
if ( attr_transient_ )
|
||||
throw Exception(this, "cannot access element in &transient array");
|
||||
|
||||
out_h->println("int size() const { return %s ? %s->size() : 0; }",
|
||||
env->RValue(value_var()), env->RValue(value_var()));
|
||||
out_h->println("%s operator[](int index) const { BINPAC_ASSERT(%s); return (*%s)[index]; }",
|
||||
elemtype_->DataTypeConstRefStr().c_str(), env->RValue(value_var()),
|
||||
out_h->println("int size() const { return %s ? %s->size() : 0; }", env->RValue(value_var()),
|
||||
env->RValue(value_var()));
|
||||
out_h->println("%s operator[](int index) const { BINPAC_ASSERT(%s); return (*%s)[index]; }",
|
||||
elemtype_->DataTypeConstRefStr().c_str(), env->RValue(value_var()), env->RValue(value_var()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::GenPrivDecls(Output* out_h, Env* env)
|
||||
{
|
||||
void ArrayType::GenPrivDecls(Output* out_h, Env* env) {
|
||||
ASSERT(elem_var_field_->type() == elemtype_);
|
||||
ASSERT(elemtype_->value_var());
|
||||
Type::GenPrivDecls(out_h, env);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void ArrayType::GenInitCode(Output* out_cc, Env* env) {
|
||||
// Do not initiate the array here
|
||||
// out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str());
|
||||
out_cc->println("%s = nullptr;", lvalue());
|
||||
|
||||
Type::GenInitCode(out_cc, env);
|
||||
if ( incremental_parsing() )
|
||||
{
|
||||
if ( incremental_parsing() ) {
|
||||
out_cc->println("%s = -1;", env->LValue(elem_it_var()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::GenCleanUpCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void ArrayType::GenCleanUpCode(Output* out_cc, Env* env) {
|
||||
Type::GenCleanUpCode(out_cc, env);
|
||||
if ( elemtype_->NeedsCleanUp() )
|
||||
{
|
||||
if ( ! elem_var_field_ )
|
||||
{
|
||||
if ( elemtype_->NeedsCleanUp() ) {
|
||||
if ( ! elem_var_field_ ) {
|
||||
ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name()));
|
||||
elem_var_field_ = new ParseVarField(Field::NOT_CLASS_MEMBER, elem_var, elemtype_);
|
||||
elem_var_field_->Prepare(env);
|
||||
|
@ -383,8 +313,7 @@ void ArrayType::GenCleanUpCode(Output* out_cc, Env* env)
|
|||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
|
||||
out_cc->println("for ( auto* %s : *%s )", env->LValue(elem_var()),
|
||||
env->RValue(value_var()));
|
||||
out_cc->println("for ( auto* %s : *%s )", env->LValue(elem_var()), env->RValue(value_var()));
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
elemtype_->GenCleanUpCode(out_cc, env);
|
||||
|
@ -395,15 +324,13 @@ void ArrayType::GenCleanUpCode(Output* out_cc, Env* env)
|
|||
out_cc->dec_indent();
|
||||
}
|
||||
out_cc->println("delete %s;", lvalue());
|
||||
}
|
||||
}
|
||||
|
||||
string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length)
|
||||
{
|
||||
string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length) {
|
||||
string array_str;
|
||||
|
||||
array_str = lvalue();
|
||||
if ( incremental_parsing() )
|
||||
{
|
||||
if ( incremental_parsing() ) {
|
||||
out_cc->println("if ( %s < 0 )", env->LValue(elem_it_var()));
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
|
@ -413,49 +340,39 @@ string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length
|
|||
|
||||
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()));
|
||||
}
|
||||
|
||||
if ( incremental_parsing() )
|
||||
{
|
||||
if ( incremental_parsing() ) {
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
|
||||
return array_str;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::GenElementAssignment(Output* out_cc, Env* env, string const& array_str,
|
||||
bool use_vector)
|
||||
{
|
||||
if ( attr_transient_ )
|
||||
{
|
||||
void ArrayType::GenElementAssignment(Output* out_cc, Env* env, string const& array_str, bool use_vector) {
|
||||
if ( attr_transient_ ) {
|
||||
// Just discard.
|
||||
out_cc->println("delete %s;", env->LValue(elem_var()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign the element
|
||||
if ( ! use_vector )
|
||||
{
|
||||
out_cc->println("%s[%s] = %s;", array_str.c_str(), env->LValue(elem_it_var()),
|
||||
env->LValue(elem_var()));
|
||||
if ( ! use_vector ) {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Otherwise these variables are declared as member variables
|
||||
if ( ! incremental_parsing() )
|
||||
{
|
||||
if ( ! incremental_parsing() ) {
|
||||
// Declare and initialize temporary variables
|
||||
elem_var_field_->GenInitCode(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;
|
||||
|
||||
if ( incremental_input() )
|
||||
{
|
||||
if ( incremental_input() ) {
|
||||
// Do not compute size_var on incremental input
|
||||
compute_size_var = false;
|
||||
|
||||
if ( ! incremental_parsing() &&
|
||||
(StaticSize(env) >= 0 ||
|
||||
(env->Evaluated(arraylength_var()) && elemtype_->StaticSize(env) >= 0)) )
|
||||
{
|
||||
(StaticSize(env) >= 0 || (env->Evaluated(arraylength_var()) && elemtype_->StaticSize(env) >= 0)) ) {
|
||||
GenBoundaryCheck(out_cc, env, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
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);
|
||||
|
||||
if ( elem_dataptr_var() )
|
||||
{
|
||||
if ( elem_dataptr_var() ) {
|
||||
out_cc->println("const_byteptr %s = %s;", env->LValue(elem_dataptr_var()), data.ptr_expr());
|
||||
env->SetEvaluated(elem_dataptr_var());
|
||||
|
||||
elem_data = DataPtr(env, elem_dataptr_var(), 0);
|
||||
}
|
||||
|
||||
string for_condition = known_array_length ? strfmt("%s < %s", env->LValue(elem_it_var()),
|
||||
env->RValue(arraylength_var()))
|
||||
: "/* forever */";
|
||||
string for_condition = known_array_length ?
|
||||
strfmt("%s < %s", env->LValue(elem_it_var()), env->RValue(arraylength_var())) :
|
||||
"/* forever */";
|
||||
|
||||
out_cc->println("for (; %s; ++%s)", for_condition.c_str(), env->LValue(elem_it_var()));
|
||||
out_cc->inc_indent();
|
||||
|
@ -521,10 +433,8 @@ void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, in
|
|||
if ( attr_generic_until_expr_ )
|
||||
GenUntilCheck(out_cc, env, attr_generic_until_expr_, true);
|
||||
|
||||
if ( elem_dataptr_var() )
|
||||
{
|
||||
if ( length_ )
|
||||
{
|
||||
if ( elem_dataptr_var() ) {
|
||||
if ( length_ ) {
|
||||
// Array has a known-length expression like uint16[4] vs. uint16[].
|
||||
// Here, arriving at the end of the data buffer should not be a
|
||||
// valid loop-termination condition (which is what the
|
||||
|
@ -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
|
||||
// there's insufficient data in the buffer.
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
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_->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->inc_indent();
|
||||
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);
|
||||
|
||||
if ( elem_dataptr_var() )
|
||||
{
|
||||
if ( elem_dataptr_var() ) {
|
||||
out_cc->println("%s += %s;", env->LValue(elem_dataptr_var()),
|
||||
elemtype_->DataSize(nullptr, env, elem_data).c_str());
|
||||
out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(elem_dataptr_var()),
|
||||
env->RValue(end_of_data));
|
||||
out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(elem_dataptr_var()), env->RValue(end_of_data));
|
||||
}
|
||||
|
||||
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->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
|
||||
out_cc->println("%s = %s - (%s);", env->LValue(size_var()), env->RValue(elem_dataptr_var()),
|
||||
data.ptr_expr());
|
||||
out_cc->println("%s = %s - (%s);", env->LValue(size_var()), env->RValue(elem_dataptr_var()), data.ptr_expr());
|
||||
env->SetEvaluated(size_var());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::GenUntilInputCheck(Output* out_cc, Env* env)
|
||||
{
|
||||
void ArrayType::GenUntilInputCheck(Output* out_cc, Env* env) {
|
||||
ID* elem_input_var_id = new ID(strfmt("%s__elem_input", value_var()->Name()));
|
||||
elem_input_var_field_ = new TempVarField(elem_input_var_id,
|
||||
extern_type_const_bytestring->Clone());
|
||||
elem_input_var_field_ = new TempVarField(elem_input_var_id, extern_type_const_bytestring->Clone());
|
||||
elem_input_var_field_->Prepare(env);
|
||||
|
||||
out_cc->println("%s %s(%s, %s);", extern_type_const_bytestring->DataTypeStr().c_str(),
|
||||
env->LValue(elem_input_var()), env->RValue(begin_of_data),
|
||||
env->RValue(end_of_data));
|
||||
env->LValue(elem_input_var()), env->RValue(begin_of_data), env->RValue(end_of_data));
|
||||
env->SetEvaluated(elem_input_var());
|
||||
|
||||
GenUntilCheck(out_cc, env, attr_until_input_expr_, true);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool delete_elem)
|
||||
{
|
||||
void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool delete_elem) {
|
||||
ASSERT(until_expr);
|
||||
|
||||
Env check_env(env, this);
|
||||
check_env.AddMacro(element_macro_id, new Expr(elem_var()->clone()));
|
||||
if ( elem_input_var() )
|
||||
{
|
||||
if ( elem_input_var() ) {
|
||||
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->inc_indent();
|
||||
out_cc->println("{");
|
||||
if ( parsing_complete_var() )
|
||||
{
|
||||
if ( parsing_complete_var() ) {
|
||||
out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
|
||||
}
|
||||
|
||||
if ( elemtype_->IsPointerType() )
|
||||
{
|
||||
if ( elemtype_->IsPointerType() ) {
|
||||
if ( delete_elem )
|
||||
elemtype_->GenCleanUpCode(out_cc, env);
|
||||
else
|
||||
|
@ -628,36 +525,30 @@ void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool d
|
|||
out_cc->println("goto %s;", end_of_array_loop_label_.c_str());
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
|
||||
{
|
||||
void ArrayType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) {
|
||||
ASSERT(! incremental_input());
|
||||
DEBUG_MSG("Generating dynamic size for array `%s'\n", value_var()->Name());
|
||||
|
||||
int elem_w = elemtype_->StaticSize(env);
|
||||
if ( elem_w >= 0 && ! attr_until_element_expr_ && ! attr_until_input_expr_ &&
|
||||
(length_ || attr_restofdata_) )
|
||||
{
|
||||
if ( elem_w >= 0 && ! attr_until_element_expr_ && ! attr_until_input_expr_ && (length_ || attr_restofdata_) ) {
|
||||
// If the elements have a fixed size,
|
||||
// we only need to compute the number of elements
|
||||
bool compute_size_var = AddSizeVar(out_cc, env);
|
||||
ASSERT(compute_size_var);
|
||||
GenArrayLength(out_cc, env, data);
|
||||
ASSERT(env->Evaluated(arraylength_var()));
|
||||
out_cc->println("%s = %d * %s;", env->LValue(size_var()), elem_w,
|
||||
env->RValue(arraylength_var()));
|
||||
out_cc->println("%s = %d * %s;", env->LValue(size_var()), elem_w, env->RValue(arraylength_var()));
|
||||
env->SetEvaluated(size_var());
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Otherwise we need parse the array dynamically
|
||||
GenParseCode(out_cc, env, data, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ArrayType::StaticSize(Env* env) const
|
||||
{
|
||||
int ArrayType::StaticSize(Env* env) const {
|
||||
int num = 0;
|
||||
|
||||
if ( ! length_ || ! length_->ConstFold(env, &num) )
|
||||
|
@ -670,14 +561,12 @@ int ArrayType::StaticSize(Env* env) const
|
|||
DEBUG_MSG("static size of %s:%s = %d * %d\n", decl_id()->Name(), lvalue(), elem_w, num);
|
||||
|
||||
return num * elem_w;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::SetBoundaryChecked()
|
||||
{
|
||||
void ArrayType::SetBoundaryChecked() {
|
||||
Type::SetBoundaryChecked();
|
||||
|
||||
if ( attr_length_expr_ )
|
||||
{
|
||||
if ( attr_length_expr_ ) {
|
||||
// When using &length on an array, only treat its elements as
|
||||
// already-bounds-checked if they are a single byte in length.
|
||||
if ( elemtype_->StaticSize(env()) == 1 )
|
||||
|
@ -687,21 +576,16 @@ void ArrayType::SetBoundaryChecked()
|
|||
}
|
||||
|
||||
elemtype_->SetBoundaryChecked();
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayType::DoMarkIncrementalInput()
|
||||
{
|
||||
elemtype_->MarkIncrementalInput();
|
||||
}
|
||||
void ArrayType::DoMarkIncrementalInput() { elemtype_->MarkIncrementalInput(); }
|
||||
|
||||
bool ArrayType::RequiresAnalyzerContext()
|
||||
{
|
||||
bool ArrayType::RequiresAnalyzerContext() {
|
||||
return Type::RequiresAnalyzerContext() || (length_ && length_->RequiresAnalyzerContext()) ||
|
||||
elemtype_->RequiresAnalyzerContext();
|
||||
}
|
||||
}
|
||||
|
||||
bool ArrayType::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
bool ArrayType::DoTraverse(DataDepVisitor* visitor) {
|
||||
if ( ! Type::DoTraverse(visitor) )
|
||||
return false;
|
||||
|
||||
|
@ -712,4 +596,4 @@ bool ArrayType::DoTraverse(DataDepVisitor* visitor)
|
|||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
// Fixed-length array and variable length sequence with an ending pattern
|
||||
|
||||
class ArrayType : public Type
|
||||
{
|
||||
class ArrayType : public Type {
|
||||
public:
|
||||
ArrayType(Type* arg_elemtype, Expr* arg_length = nullptr);
|
||||
~ArrayType() override;
|
||||
|
@ -82,6 +81,6 @@ private:
|
|||
Expr* attr_generic_until_expr_;
|
||||
Expr* attr_until_element_expr_;
|
||||
Expr* attr_until_input_expr_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_array_h
|
||||
|
|
|
@ -2,60 +2,47 @@
|
|||
|
||||
#include "pac_expr.h"
|
||||
|
||||
bool Attr::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
bool Attr::DoTraverse(DataDepVisitor* visitor) {
|
||||
if ( expr_ && ! expr_->Traverse(visitor) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Attr::RequiresAnalyzerContext() const
|
||||
{
|
||||
return (expr_ && expr_->RequiresAnalyzerContext());
|
||||
}
|
||||
bool Attr::RequiresAnalyzerContext() const { return (expr_ && expr_->RequiresAnalyzerContext()); }
|
||||
|
||||
void Attr::init()
|
||||
{
|
||||
void Attr::init() {
|
||||
expr_ = nullptr;
|
||||
seqend_ = nullptr;
|
||||
delete_expr_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
Attr::Attr(AttrType type) : DataDepElement(DataDepElement::ATTR)
|
||||
{
|
||||
Attr::Attr(AttrType type) : DataDepElement(DataDepElement::ATTR) {
|
||||
type_ = type;
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
Attr::Attr(AttrType type, Expr* expr) : DataDepElement(DataDepElement::ATTR)
|
||||
{
|
||||
Attr::Attr(AttrType type, Expr* expr) : DataDepElement(DataDepElement::ATTR) {
|
||||
type_ = type;
|
||||
init();
|
||||
expr_ = expr;
|
||||
}
|
||||
}
|
||||
|
||||
Attr::Attr(AttrType type, ExprList* exprlist) : DataDepElement(DataDepElement::ATTR)
|
||||
{
|
||||
Attr::Attr(AttrType type, ExprList* exprlist) : DataDepElement(DataDepElement::ATTR) {
|
||||
type_ = type;
|
||||
init();
|
||||
expr_ = new Expr(exprlist);
|
||||
delete_expr_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
Attr::Attr(AttrType type, SeqEnd* seqend) : DataDepElement(DataDepElement::ATTR)
|
||||
{
|
||||
Attr::Attr(AttrType type, SeqEnd* seqend) : DataDepElement(DataDepElement::ATTR) {
|
||||
type_ = type;
|
||||
init();
|
||||
seqend_ = seqend;
|
||||
}
|
||||
}
|
||||
|
||||
Attr::~Attr()
|
||||
{
|
||||
Attr::~Attr() {
|
||||
if ( delete_expr_ )
|
||||
delete expr_;
|
||||
}
|
||||
}
|
||||
|
||||
LetAttr::LetAttr(FieldList* letfields) : Attr(ATTR_LET)
|
||||
{
|
||||
letfields_ = letfields;
|
||||
}
|
||||
LetAttr::LetAttr(FieldList* letfields) : Attr(ATTR_LET) { letfields_ = letfields; }
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include "pac_common.h"
|
||||
#include "pac_datadep.h"
|
||||
|
||||
enum AttrType
|
||||
{
|
||||
enum AttrType {
|
||||
ATTR_BYTEORDER,
|
||||
ATTR_CHECK,
|
||||
ATTR_CHUNKED,
|
||||
|
@ -23,10 +22,9 @@ enum AttrType
|
|||
ATTR_RESTOFFLOW,
|
||||
ATTR_TRANSIENT,
|
||||
ATTR_UNTIL,
|
||||
};
|
||||
};
|
||||
|
||||
class Attr : public Object, public DataDepElement
|
||||
{
|
||||
class Attr : public Object, public DataDepElement {
|
||||
public:
|
||||
Attr(AttrType type);
|
||||
Attr(AttrType type, Expr* expr);
|
||||
|
@ -51,16 +49,15 @@ protected:
|
|||
Expr* expr_;
|
||||
SeqEnd* seqend_;
|
||||
bool delete_expr_;
|
||||
};
|
||||
};
|
||||
|
||||
class LetAttr : public Attr
|
||||
{
|
||||
class LetAttr : public Attr {
|
||||
public:
|
||||
LetAttr(FieldList* letfields);
|
||||
FieldList* letfields() const { return letfields_; }
|
||||
|
||||
private:
|
||||
FieldList* letfields_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_attr_h
|
||||
|
|
|
@ -4,22 +4,17 @@
|
|||
#include "pac_id.h"
|
||||
#include "pac_output.h"
|
||||
|
||||
Type* BuiltInType::DoClone() const
|
||||
{
|
||||
return new BuiltInType(bit_type());
|
||||
}
|
||||
Type* BuiltInType::DoClone() const { return new BuiltInType(bit_type()); }
|
||||
|
||||
bool BuiltInType::IsNumericType() const
|
||||
{
|
||||
bool BuiltInType::IsNumericType() const {
|
||||
BITType t = bit_type();
|
||||
return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || t == UINT8 || t == UINT16 ||
|
||||
t == UINT32 || t == UINT64);
|
||||
}
|
||||
return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || t == UINT8 || t == UINT16 || t == UINT32 ||
|
||||
t == UINT64);
|
||||
}
|
||||
|
||||
bool BuiltInType::CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2)
|
||||
{
|
||||
bool BuiltInType::CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2) {
|
||||
return type1->IsNumericType() && type2->IsNumericType();
|
||||
}
|
||||
}
|
||||
|
||||
static const char* basic_pactype_name[] = {
|
||||
#define TYPE_DEF(name, pactype, ctype, size) pactype,
|
||||
|
@ -28,22 +23,19 @@ static const char* basic_pactype_name[] = {
|
|||
nullptr,
|
||||
};
|
||||
|
||||
void BuiltInType::static_init()
|
||||
{
|
||||
for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type )
|
||||
{
|
||||
void BuiltInType::static_init() {
|
||||
for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type ) {
|
||||
Type::AddPredefinedType(basic_pactype_name[bit_type], new BuiltInType((BITType)bit_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BuiltInType::LookUpByName(const char* name)
|
||||
{
|
||||
int BuiltInType::LookUpByName(const char* name) {
|
||||
ASSERT(0);
|
||||
for ( int i = 0; basic_pactype_name[i]; ++i )
|
||||
if ( strcmp(basic_pactype_name[i], name) == 0 )
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* basic_ctype_name[] = {
|
||||
#define TYPE_DEF(name, pactype, ctype, size) ctype,
|
||||
|
@ -52,18 +44,11 @@ static const char* basic_ctype_name[] = {
|
|||
nullptr,
|
||||
};
|
||||
|
||||
bool BuiltInType::DefineValueVar() const
|
||||
{
|
||||
return bit_type_ != EMPTY;
|
||||
}
|
||||
bool BuiltInType::DefineValueVar() const { return bit_type_ != EMPTY; }
|
||||
|
||||
string BuiltInType::DataTypeStr() const
|
||||
{
|
||||
return basic_ctype_name[bit_type_];
|
||||
}
|
||||
string BuiltInType::DataTypeStr() const { return basic_ctype_name[bit_type_]; }
|
||||
|
||||
int BuiltInType::StaticSize(Env* /* env */) const
|
||||
{
|
||||
int BuiltInType::StaticSize(Env* /* env */) const {
|
||||
static const size_t basic_type_size[] = {
|
||||
#define TYPE_DEF(name, pactype, ctype, size) size,
|
||||
#include "pac_type.def"
|
||||
|
@ -71,30 +56,26 @@ int BuiltInType::StaticSize(Env* /* env */) const
|
|||
};
|
||||
|
||||
return basic_type_size[bit_type_];
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltInType::DoMarkIncrementalInput()
|
||||
{
|
||||
void BuiltInType::DoMarkIncrementalInput() {
|
||||
if ( bit_type_ == EMPTY )
|
||||
return;
|
||||
Type::DoMarkIncrementalInput();
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltInType::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void BuiltInType::GenInitCode(Output* out_cc, Env* env) {
|
||||
if ( bit_type_ != EMPTY )
|
||||
out_cc->println("%s = 0;", env->LValue(value_var()));
|
||||
Type::GenInitCode(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
|
||||
{
|
||||
void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) {
|
||||
/* should never be called */
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
|
||||
{
|
||||
void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) {
|
||||
if ( bit_type_ == EMPTY )
|
||||
return;
|
||||
|
||||
|
@ -106,16 +87,14 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data,
|
|||
if ( anonymous_value_var() )
|
||||
return;
|
||||
|
||||
switch ( bit_type_ )
|
||||
{
|
||||
switch ( bit_type_ ) {
|
||||
case EMPTY:
|
||||
// do nothing
|
||||
break;
|
||||
|
||||
case INT8:
|
||||
case UINT8:
|
||||
out_cc->println("%s = *((%s const *) (%s));", lvalue(), DataTypeStr().c_str(),
|
||||
data.ptr_expr());
|
||||
out_cc->println("%s = *((%s const *) (%s));", lvalue(), DataTypeStr().c_str(), data.ptr_expr());
|
||||
break;
|
||||
case INT16:
|
||||
case UINT16:
|
||||
|
@ -131,9 +110,8 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data,
|
|||
EvalByteOrder(out_cc, env).c_str());
|
||||
#else
|
||||
out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", lvalue(),
|
||||
EvalByteOrder(out_cc, env).c_str(), DataTypeStr().c_str(),
|
||||
data.ptr_expr());
|
||||
EvalByteOrder(out_cc, env).c_str(), DataTypeStr().c_str(), data.ptr_expr());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
|
||||
#include "pac_type.h"
|
||||
|
||||
class BuiltInType : public Type
|
||||
{
|
||||
class BuiltInType : public Type {
|
||||
public:
|
||||
enum BITType
|
||||
{
|
||||
enum BITType {
|
||||
#define TYPE_DEF(name, pactype, ctype, size) name,
|
||||
#include "pac_type.def"
|
||||
#undef TYPE_DEF
|
||||
|
@ -15,10 +13,7 @@ public:
|
|||
|
||||
static int LookUpByName(const char* name);
|
||||
|
||||
BuiltInType(BITType bit_type)
|
||||
: Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN), bit_type_(bit_type)
|
||||
{
|
||||
}
|
||||
BuiltInType(BITType bit_type) : Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN), bit_type_(bit_type) {}
|
||||
|
||||
BITType bit_type() const { return bit_type_; }
|
||||
|
||||
|
@ -48,6 +43,6 @@ protected:
|
|||
public:
|
||||
static void static_init();
|
||||
static bool CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2);
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_btype_h
|
||||
|
|
|
@ -12,59 +12,45 @@
|
|||
#include "pac_typedecl.h"
|
||||
#include "pac_utils.h"
|
||||
|
||||
CaseType::CaseType(Expr* index_expr, CaseFieldList* cases)
|
||||
: Type(CASE), index_expr_(index_expr), cases_(cases)
|
||||
{
|
||||
CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) : Type(CASE), index_expr_(index_expr), cases_(cases) {
|
||||
index_var_ = nullptr;
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
AddField(*i);
|
||||
}
|
||||
}
|
||||
|
||||
CaseType::~CaseType()
|
||||
{
|
||||
CaseType::~CaseType() {
|
||||
delete index_var_;
|
||||
delete index_expr_;
|
||||
delete cases_;
|
||||
}
|
||||
}
|
||||
|
||||
void CaseType::AddCaseField(CaseField* f)
|
||||
{
|
||||
void CaseType::AddCaseField(CaseField* f) {
|
||||
// All fields must be added before Prepare()
|
||||
ASSERT(! env());
|
||||
|
||||
AddField(f);
|
||||
cases_->push_back(f);
|
||||
}
|
||||
}
|
||||
|
||||
bool CaseType::DefineValueVar() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool CaseType::DefineValueVar() const { return false; }
|
||||
|
||||
string CaseType::DataTypeStr() const
|
||||
{
|
||||
string CaseType::DataTypeStr() const {
|
||||
ASSERT(type_decl());
|
||||
return strfmt("%s *", type_decl()->class_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Type* CaseType::ValueType() const
|
||||
{
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
{
|
||||
Type* CaseType::ValueType() const {
|
||||
foreach (i, CaseFieldList, cases_) {
|
||||
CaseField* c = *i;
|
||||
return c->type();
|
||||
}
|
||||
ASSERT(0);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
string CaseType::DefaultValue() const
|
||||
{
|
||||
return ValueType()->DefaultValue();
|
||||
}
|
||||
string CaseType::DefaultValue() const { return ValueType()->DefaultValue(); }
|
||||
|
||||
void CaseType::Prepare(Env* env, int flags)
|
||||
{
|
||||
void CaseType::Prepare(Env* env, int flags) {
|
||||
ASSERT(flags & TO_BE_PARSED);
|
||||
|
||||
index_var_ = new ID(strfmt("%s_case_index", value_var()->Name()));
|
||||
|
@ -76,35 +62,30 @@ void CaseType::Prepare(Env* env, int flags)
|
|||
CaseFieldList::iterator default_case_it = cases_->end(); // to avoid warning
|
||||
CaseField* default_case = nullptr;
|
||||
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
{
|
||||
foreach (i, CaseFieldList, cases_) {
|
||||
CaseField* c = *i;
|
||||
if ( ! c->index() )
|
||||
{
|
||||
if ( ! c->index() ) {
|
||||
if ( default_case )
|
||||
throw Exception(c, "duplicate default case");
|
||||
default_case_it = i;
|
||||
default_case = c;
|
||||
}
|
||||
}
|
||||
if ( default_case )
|
||||
{
|
||||
if ( default_case ) {
|
||||
cases_->erase(default_case_it);
|
||||
cases_->push_back(default_case);
|
||||
}
|
||||
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
{
|
||||
foreach (i, CaseFieldList, cases_) {
|
||||
CaseField* c = *i;
|
||||
c->set_index_var(index_var_);
|
||||
c->set_case_type(this);
|
||||
}
|
||||
|
||||
Type::Prepare(env, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void CaseType::GenPrivDecls(Output* out_h, Env* env)
|
||||
{
|
||||
void CaseType::GenPrivDecls(Output* out_h, Env* env) {
|
||||
Type* t = index_expr_->DataType(env);
|
||||
|
||||
if ( t->tot() != Type::BUILTIN )
|
||||
|
@ -114,10 +95,9 @@ void CaseType::GenPrivDecls(Output* out_h, Env* env)
|
|||
|
||||
out_h->println("%s %s;", t->DataTypeStr().c_str(), env->LValue(index_var_));
|
||||
Type::GenPrivDecls(out_h, env);
|
||||
}
|
||||
}
|
||||
|
||||
void CaseType::GenPubDecls(Output* out_h, Env* env)
|
||||
{
|
||||
void CaseType::GenPubDecls(Output* out_h, Env* env) {
|
||||
Type* t = index_expr_->DataType(env);
|
||||
|
||||
if ( t->tot() != Type::BUILTIN )
|
||||
|
@ -126,34 +106,30 @@ void CaseType::GenPubDecls(Output* out_h, Env* env)
|
|||
out_h->println("%s %s const { return %s; }", t->DataTypeStr().c_str(), env->RValue(index_var_),
|
||||
env->LValue(index_var_));
|
||||
Type::GenPubDecls(out_h, env);
|
||||
}
|
||||
}
|
||||
|
||||
void CaseType::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void CaseType::GenInitCode(Output* out_cc, Env* env) {
|
||||
out_cc->println("%s = -1;", env->LValue(index_var_));
|
||||
Type::GenInitCode(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
void CaseType::GenCleanUpCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void CaseType::GenCleanUpCode(Output* out_cc, Env* env) {
|
||||
Type::GenCleanUpCode(out_cc, env);
|
||||
|
||||
env->set_in_branch(true);
|
||||
out_cc->println("switch ( %s )", env->RValue(index_var_));
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
{
|
||||
foreach (i, CaseFieldList, cases_) {
|
||||
CaseField* c = *i;
|
||||
c->GenCleanUpCode(out_cc, env);
|
||||
}
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
env->set_in_branch(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
|
||||
{
|
||||
void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) {
|
||||
if ( StaticSize(env) >= 0 )
|
||||
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->println("{");
|
||||
bool has_default_case = false;
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
{
|
||||
foreach (i, CaseFieldList, cases_) {
|
||||
CaseField* c = *i;
|
||||
c->GenParseCode(out_cc, env, data, compute_size_var ? size_var() : nullptr);
|
||||
if ( c->IsDefaultCase() )
|
||||
has_default_case = true;
|
||||
}
|
||||
|
||||
if ( ! has_default_case )
|
||||
{
|
||||
if ( ! has_default_case ) {
|
||||
out_cc->println("default:");
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);",
|
||||
decl_id()->Name(), env->RValue(index_var_));
|
||||
out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", decl_id()->Name(),
|
||||
env->RValue(index_var_));
|
||||
out_cc->println("break;");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
|
@ -193,18 +167,13 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int
|
|||
|
||||
if ( compute_size_var )
|
||||
env->SetEvaluated(size_var());
|
||||
}
|
||||
}
|
||||
|
||||
void CaseType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
|
||||
{
|
||||
GenParseCode(out_cc, env, data, 0);
|
||||
}
|
||||
void CaseType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { GenParseCode(out_cc, env, data, 0); }
|
||||
|
||||
int CaseType::StaticSize(Env* env) const
|
||||
{
|
||||
int CaseType::StaticSize(Env* env) const {
|
||||
int static_w = -1;
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
{
|
||||
foreach (i, CaseFieldList, cases_) {
|
||||
CaseField* c = *i;
|
||||
int w = c->StaticSize(env);
|
||||
if ( w < 0 || (static_w >= 0 && w != static_w) )
|
||||
|
@ -212,58 +181,45 @@ int CaseType::StaticSize(Env* env) const
|
|||
static_w = w;
|
||||
}
|
||||
return static_w;
|
||||
}
|
||||
}
|
||||
|
||||
void CaseType::SetBoundaryChecked()
|
||||
{
|
||||
void CaseType::SetBoundaryChecked() {
|
||||
Type::SetBoundaryChecked();
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
{
|
||||
foreach (i, CaseFieldList, cases_) {
|
||||
CaseField* c = *i;
|
||||
c->SetBoundaryChecked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaseType::DoMarkIncrementalInput()
|
||||
{
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
{
|
||||
void CaseType::DoMarkIncrementalInput() {
|
||||
foreach (i, CaseFieldList, cases_) {
|
||||
CaseField* c = *i;
|
||||
c->type()->MarkIncrementalInput();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CaseType::ByteOrderSensitive() const
|
||||
{
|
||||
foreach (i, CaseFieldList, cases_)
|
||||
{
|
||||
bool CaseType::ByteOrderSensitive() const {
|
||||
foreach (i, CaseFieldList, cases_) {
|
||||
CaseField* c = *i;
|
||||
if ( c->RequiresByteOrder() )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CaseField::CaseField(ExprList* index, ID* id, Type* type)
|
||||
: Field(CASE_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), index_(index)
|
||||
{
|
||||
: Field(CASE_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), index_(index) {
|
||||
ASSERT(type_);
|
||||
type_->set_value_var(id, MEMBER_VAR);
|
||||
case_type_ = nullptr;
|
||||
index_var_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
CaseField::~CaseField()
|
||||
{
|
||||
delete_list(ExprList, index_);
|
||||
}
|
||||
CaseField::~CaseField() { delete_list(ExprList, index_); }
|
||||
|
||||
void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_type)
|
||||
{
|
||||
if ( index_list )
|
||||
{
|
||||
foreach (i, ExprList, index_list)
|
||||
{
|
||||
void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_type) {
|
||||
if ( index_list ) {
|
||||
foreach (i, ExprList, index_list) {
|
||||
Expr* index_expr = *i;
|
||||
|
||||
Type* case_type = index_expr->DataType(env);
|
||||
|
@ -287,44 +243,40 @@ void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_typ
|
|||
if ( case_type->tot() == Type::BUILTIN )
|
||||
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;
|
||||
|
||||
if ( switch_type_width == 1 )
|
||||
{
|
||||
if ( st->bit_type() == BuiltInType::INT8 )
|
||||
{
|
||||
if ( switch_type_width == 1 ) {
|
||||
if ( st->bit_type() == BuiltInType::INT8 ) {
|
||||
if ( index_const < std::numeric_limits<int8_t>::min() )
|
||||
throw ExceptionInvalidCaseLimitExpr(index_expr);
|
||||
if ( index_const > std::numeric_limits<int8_t>::max() )
|
||||
throw ExceptionInvalidCaseLimitExpr(index_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
if ( index_const < std::numeric_limits<uint8_t>::min() )
|
||||
throw ExceptionInvalidCaseLimitExpr(index_expr);
|
||||
if ( index_const > std::numeric_limits<uint8_t>::max() )
|
||||
throw ExceptionInvalidCaseLimitExpr(index_expr);
|
||||
}
|
||||
}
|
||||
else if ( switch_type_width == 2 )
|
||||
{
|
||||
if ( st->bit_type() == BuiltInType::INT16 )
|
||||
{
|
||||
else if ( switch_type_width == 2 ) {
|
||||
if ( st->bit_type() == BuiltInType::INT16 ) {
|
||||
if ( index_const < std::numeric_limits<int16_t>::min() )
|
||||
throw ExceptionInvalidCaseLimitExpr(index_expr);
|
||||
if ( index_const > std::numeric_limits<int16_t>::max() )
|
||||
throw ExceptionInvalidCaseLimitExpr(index_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
if ( index_const < std::numeric_limits<uint16_t>::min() )
|
||||
throw ExceptionInvalidCaseLimitExpr(index_expr);
|
||||
if ( index_const > std::numeric_limits<uint16_t>::max() )
|
||||
throw ExceptionInvalidCaseLimitExpr(index_expr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
out_cc->println("default:");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaseField::Prepare(Env* env)
|
||||
{
|
||||
void CaseField::Prepare(Env* env) {
|
||||
ASSERT(index_var_);
|
||||
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)) )
|
||||
return;
|
||||
|
||||
|
@ -361,8 +310,7 @@ void CaseField::GenPubDecls(Output* out_h, Env* env)
|
|||
|
||||
if ( ! index_ )
|
||||
out_h->println("return %s;", lvalue());
|
||||
else
|
||||
{
|
||||
else {
|
||||
out_h->println("switch ( %s )", env->RValue(index_var_));
|
||||
out_h->inc_indent();
|
||||
out_h->println("{");
|
||||
|
@ -373,8 +321,8 @@ void CaseField::GenPubDecls(Output* out_h, Env* env)
|
|||
|
||||
out_h->println("default:");
|
||||
out_h->inc_indent();
|
||||
out_h->println("throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");",
|
||||
id_->LocName(), env->RValue(index_var_), OrigExprList(index_).c_str());
|
||||
out_h->println("throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");", id_->LocName(),
|
||||
env->RValue(index_var_), OrigExprList(index_).c_str());
|
||||
out_h->println("break;");
|
||||
out_h->dec_indent();
|
||||
|
||||
|
@ -386,10 +334,9 @@ void CaseField::GenPubDecls(Output* out_h, Env* env)
|
|||
|
||||
out_h->println("}");
|
||||
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);
|
||||
// out_cc->inc_indent();
|
||||
// out_cc->println("{");
|
||||
|
@ -398,10 +345,9 @@ void CaseField::GenInitCode(Output* out_cc, Env* env)
|
|||
// out_cc->println("}");
|
||||
// out_cc->println("break;");
|
||||
// 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));
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("// Clean up \"%s\"", id_->Name());
|
||||
|
@ -411,10 +357,9 @@ void CaseField::GenCleanUpCode(Output* out_cc, Env* env)
|
|||
out_cc->println("}");
|
||||
out_cc->println("break;");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
||||
void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, const ID* size_var)
|
||||
{
|
||||
void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, const ID* size_var) {
|
||||
GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env));
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("// Parse \"%s\"", id_->Name());
|
||||
|
@ -425,13 +370,10 @@ void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, cons
|
|||
|
||||
type_->GenPreParsing(out_cc, &case_env);
|
||||
type_->GenParseCode(out_cc, &case_env, data, 0);
|
||||
if ( size_var )
|
||||
{
|
||||
out_cc->println("%s = %s;", case_env.LValue(size_var),
|
||||
type_->DataSize(out_cc, &case_env, data).c_str());
|
||||
if ( size_var ) {
|
||||
out_cc->println("%s = %s;", case_env.LValue(size_var), type_->DataSize(out_cc, &case_env, data).c_str());
|
||||
}
|
||||
if ( type_->incremental_input() )
|
||||
{
|
||||
if ( type_->incremental_input() ) {
|
||||
ASSERT(case_type()->parsing_complete_var());
|
||||
out_cc->println("%s = %s;", case_env.LValue(case_type()->parsing_complete_var()),
|
||||
case_env.RValue(type_->parsing_complete_var()));
|
||||
|
@ -441,14 +383,10 @@ void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, cons
|
|||
|
||||
out_cc->println("break;");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
||||
bool CaseField::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
return Field::DoTraverse(visitor) && type()->Traverse(visitor);
|
||||
}
|
||||
bool CaseField::DoTraverse(DataDepVisitor* visitor) { return Field::DoTraverse(visitor) && type()->Traverse(visitor); }
|
||||
|
||||
bool CaseField::RequiresAnalyzerContext() const
|
||||
{
|
||||
bool CaseField::RequiresAnalyzerContext() const {
|
||||
return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
#include "pac_id.h"
|
||||
#include "pac_type.h"
|
||||
|
||||
class CaseType : public Type
|
||||
{
|
||||
class CaseType : public Type {
|
||||
public:
|
||||
CaseType(Expr* index, CaseFieldList* cases);
|
||||
~CaseType() override;
|
||||
|
@ -50,10 +49,9 @@ protected:
|
|||
|
||||
typedef map<const ID*, CaseField*, ID_ptr_cmp> member_map_t;
|
||||
member_map_t member_map_;
|
||||
};
|
||||
};
|
||||
|
||||
class CaseField : public Field
|
||||
{
|
||||
class CaseField : public Field {
|
||||
public:
|
||||
CaseField(ExprList* index, ID* id, Type* type);
|
||||
~CaseField() override;
|
||||
|
@ -91,7 +89,7 @@ protected:
|
|||
CaseType* case_type_;
|
||||
ExprList* index_;
|
||||
const ID* index_var_;
|
||||
};
|
||||
};
|
||||
|
||||
// Generate a list of "case X:" lines from index_list. Each index
|
||||
// expression must be constant foldable.
|
||||
|
|
|
@ -24,8 +24,7 @@ typedef vector<CVariable*> CVariableList;
|
|||
//
|
||||
// 3. We do not check repeated names.
|
||||
|
||||
class CClass
|
||||
{
|
||||
class CClass {
|
||||
public:
|
||||
CClass(const string& class_name);
|
||||
|
||||
|
@ -39,10 +38,9 @@ protected:
|
|||
string class_name_;
|
||||
CClassMemberList* members_;
|
||||
CClassMethodList* methods_;
|
||||
};
|
||||
};
|
||||
|
||||
class CVariable
|
||||
{
|
||||
class CVariable {
|
||||
public:
|
||||
CClassMember(const string& name, CType* type);
|
||||
|
||||
|
@ -52,10 +50,9 @@ public:
|
|||
protected:
|
||||
string name_;
|
||||
CType* type_;
|
||||
};
|
||||
};
|
||||
|
||||
class CClassMember
|
||||
{
|
||||
class CClassMember {
|
||||
public:
|
||||
CClassMember(CVariable* var);
|
||||
void GenCode(Output* out_h, Output* out_cc);
|
||||
|
@ -64,10 +61,9 @@ public:
|
|||
|
||||
protected:
|
||||
CVariable* var_;
|
||||
};
|
||||
};
|
||||
|
||||
class CClassMethod
|
||||
{
|
||||
class CClassMethod {
|
||||
public:
|
||||
CClassMethod(CVariable* var, CVariableList* params);
|
||||
|
||||
|
@ -76,6 +72,6 @@ public:
|
|||
protected:
|
||||
CVariable* var_;
|
||||
CVariableList* params_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_cclass_h
|
||||
|
|
|
@ -20,17 +20,15 @@ extern int line_number;
|
|||
// representing language elements -- identifiers, types, expressions,
|
||||
// etc.
|
||||
|
||||
class Object
|
||||
{
|
||||
class Object {
|
||||
public:
|
||||
Object()
|
||||
{
|
||||
Object() {
|
||||
filename = input_filename;
|
||||
line_num = line_number;
|
||||
location = strfmt("%s:%d", filename.c_str(), line_number);
|
||||
}
|
||||
|
||||
~Object() { }
|
||||
~Object() {}
|
||||
|
||||
const char* Location() const { return location.c_str(); }
|
||||
|
||||
|
@ -38,7 +36,7 @@ protected:
|
|||
string filename;
|
||||
int line_num;
|
||||
string location;
|
||||
};
|
||||
};
|
||||
|
||||
class ActionParam;
|
||||
class ActionParamType;
|
||||
|
|
|
@ -11,27 +11,23 @@
|
|||
#include "pac_type.h"
|
||||
|
||||
ConnDecl::ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist)
|
||||
: AnalyzerDecl(conn_id, CONN, params)
|
||||
{
|
||||
: AnalyzerDecl(conn_id, CONN, params) {
|
||||
flows_[0] = flows_[1] = nullptr;
|
||||
AddElements(elemlist);
|
||||
data_type_ = new ParameterizedType(conn_id->clone(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
ConnDecl::~ConnDecl()
|
||||
{
|
||||
ConnDecl::~ConnDecl() {
|
||||
delete flows_[0];
|
||||
delete flows_[1];
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
void ConnDecl::ProcessFlowElement(AnalyzerFlow* flow_elem)
|
||||
{
|
||||
void ConnDecl::ProcessFlowElement(AnalyzerFlow* flow_elem) {
|
||||
int flow_index;
|
||||
|
||||
if ( flow_elem->dir() == AnalyzerFlow::UP )
|
||||
|
@ -39,41 +35,30 @@ void ConnDecl::ProcessFlowElement(AnalyzerFlow* flow_elem)
|
|||
else
|
||||
flow_index = 1;
|
||||
|
||||
if ( flows_[flow_index] )
|
||||
{
|
||||
throw Exception(flow_elem,
|
||||
strfmt("%sflow already defined", flow_index == 0 ? "up" : "down"));
|
||||
if ( flows_[flow_index] ) {
|
||||
throw Exception(flow_elem, strfmt("%sflow already defined", flow_index == 0 ? "up" : "down"));
|
||||
}
|
||||
|
||||
flows_[flow_index] = flow_elem;
|
||||
type_->AddField(flow_elem->flow_field());
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
void ConnDecl::Prepare()
|
||||
{
|
||||
void ConnDecl::Prepare() {
|
||||
AnalyzerDecl::Prepare();
|
||||
|
||||
flows_[0]->flow_decl()->set_conn_decl(this);
|
||||
flows_[1]->flow_decl()->set_conn_decl(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnDecl::GenPubDecls(Output* out_h, Output* out_cc)
|
||||
{
|
||||
AnalyzerDecl::GenPubDecls(out_h, out_cc);
|
||||
}
|
||||
void ConnDecl::GenPubDecls(Output* out_h, Output* out_cc) { AnalyzerDecl::GenPubDecls(out_h, out_cc); }
|
||||
|
||||
void ConnDecl::GenPrivDecls(Output* out_h, Output* out_cc)
|
||||
{
|
||||
AnalyzerDecl::GenPrivDecls(out_h, out_cc);
|
||||
}
|
||||
void ConnDecl::GenPrivDecls(Output* out_h, Output* out_cc) { AnalyzerDecl::GenPrivDecls(out_h, out_cc); }
|
||||
|
||||
void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc) {
|
||||
string proto = strfmt("%s(bool is_orig)", kFlowEOF);
|
||||
|
||||
out_h->println("void %s;", proto.c_str());
|
||||
|
@ -90,8 +75,7 @@ void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc)
|
|||
out_cc->inc_indent();
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -100,10 +84,9 @@ void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc)
|
|||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
out_cc->println("");
|
||||
}
|
||||
}
|
||||
|
||||
void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc) {
|
||||
string proto = strfmt("%s(bool is_orig, int gap_length)", kFlowGap);
|
||||
|
||||
out_h->println("void %s;", proto.c_str());
|
||||
|
@ -124,10 +107,9 @@ void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc)
|
|||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
out_cc->println("");
|
||||
}
|
||||
}
|
||||
|
||||
void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc) {
|
||||
string proto = strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)", kNewData);
|
||||
|
||||
out_h->println("void %s;", proto.c_str());
|
||||
|
@ -148,4 +130,4 @@ void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc)
|
|||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
out_cc->println("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include "pac_analyzer.h"
|
||||
#include "pac_decl.h"
|
||||
|
||||
class ConnDecl : public AnalyzerDecl
|
||||
{
|
||||
class ConnDecl : public AnalyzerDecl {
|
||||
public:
|
||||
ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist);
|
||||
~ConnDecl() override;
|
||||
|
@ -29,6 +28,6 @@ protected:
|
|||
|
||||
AnalyzerFlow* flows_[2];
|
||||
Type* data_type_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_conn_h
|
||||
|
|
|
@ -12,34 +12,26 @@
|
|||
#include "pac_utils.h"
|
||||
|
||||
ContextField::ContextField(ID* id, Type* type)
|
||||
: Field(CONTEXT_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type)
|
||||
{
|
||||
}
|
||||
: Field(CONTEXT_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) {}
|
||||
|
||||
AnalyzerContextDecl* AnalyzerContextDecl::current_analyzer_context_ = nullptr;
|
||||
|
||||
namespace
|
||||
{
|
||||
ParamList* ContextFieldsToParams(ContextFieldList* context_fields)
|
||||
{
|
||||
namespace {
|
||||
ParamList* ContextFieldsToParams(ContextFieldList* context_fields) {
|
||||
// Convert context fields to parameters
|
||||
ParamList* params = new ParamList();
|
||||
foreach (i, ContextFieldList, context_fields)
|
||||
{
|
||||
foreach (i, ContextFieldList, context_fields) {
|
||||
ContextField* f = *i;
|
||||
params->push_back(new Param(f->id()->clone(), f->type()));
|
||||
}
|
||||
return params;
|
||||
}
|
||||
} // namespace private
|
||||
}
|
||||
} // namespace
|
||||
|
||||
AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_fields)
|
||||
: TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields),
|
||||
new DummyType())
|
||||
{
|
||||
: TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields), new DummyType()) {
|
||||
context_name_id_ = id;
|
||||
if ( current_analyzer_context_ != nullptr )
|
||||
{
|
||||
if ( current_analyzer_context_ != nullptr ) {
|
||||
throw Exception(this, strfmt("multiple declaration of analyzer context; "
|
||||
"the previous one is `%s'",
|
||||
current_analyzer_context_->id()->Name()));
|
||||
|
@ -54,57 +46,49 @@ AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_field
|
|||
flow_buffer_added_ = false;
|
||||
|
||||
DEBUG_MSG("Context type: %s\n", param_type()->class_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
AnalyzerContextDecl::~AnalyzerContextDecl()
|
||||
{
|
||||
AnalyzerContextDecl::~AnalyzerContextDecl() {
|
||||
delete context_name_id_;
|
||||
delete param_type_;
|
||||
delete_list(ContextFieldList, context_fields_);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h)
|
||||
{
|
||||
void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h) {
|
||||
GenNamespaceBegin(out_h);
|
||||
TypeDecl::GenForwardDeclaration(out_h);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerContextDecl::GenCode(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void AnalyzerContextDecl::GenCode(Output* out_h, Output* out_cc) {
|
||||
GenNamespaceBegin(out_h);
|
||||
GenNamespaceBegin(out_cc);
|
||||
TypeDecl::GenCode(out_h, out_cc);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerContextDecl::GenNamespaceBegin(Output* out) const
|
||||
{
|
||||
void AnalyzerContextDecl::GenNamespaceBegin(Output* out) const {
|
||||
out->println("namespace %s {", context_name_id()->Name());
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerContextDecl::GenNamespaceEnd(Output* out) const
|
||||
{
|
||||
void AnalyzerContextDecl::GenNamespaceEnd(Output* out) const {
|
||||
out->println("} // namespace %s", context_name_id()->Name());
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerContextDecl::AddFlowBuffer()
|
||||
{
|
||||
void AnalyzerContextDecl::AddFlowBuffer() {
|
||||
if ( flow_buffer_added_ )
|
||||
return;
|
||||
|
||||
AddParam(new Param(new ID(kFlowBufferVar), FlowDecl::flow_buffer_type()->Clone()));
|
||||
|
||||
flow_buffer_added_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
string AnalyzerContextDecl::mb_buffer(Env* env)
|
||||
{
|
||||
string AnalyzerContextDecl::mb_buffer(Env* env) {
|
||||
// A hack. The orthodox way would be to build an Expr of
|
||||
// context.flow_buffer_var, and then EvalExpr.
|
||||
return strfmt("%s->%s()", env->RValue(analyzer_context_id), kFlowBufferVar);
|
||||
}
|
||||
}
|
||||
|
||||
Type* DummyType::DoClone() const
|
||||
{
|
||||
Type* DummyType::DoClone() const {
|
||||
// Fields will be copied in Type::Clone().
|
||||
return new DummyType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,14 +23,12 @@
|
|||
// accessed as members of the cookie, such as
|
||||
// ``binpac_context.connection''.
|
||||
|
||||
class ContextField : public Field
|
||||
{
|
||||
class ContextField : public Field {
|
||||
public:
|
||||
ContextField(ID* id, Type* type);
|
||||
};
|
||||
};
|
||||
|
||||
class AnalyzerContextDecl : public TypeDecl
|
||||
{
|
||||
class AnalyzerContextDecl : public TypeDecl {
|
||||
public:
|
||||
AnalyzerContextDecl(ID* id, ContextFieldList* context_fields);
|
||||
~AnalyzerContextDecl() override;
|
||||
|
@ -62,38 +60,31 @@ public:
|
|||
|
||||
private:
|
||||
static AnalyzerContextDecl* current_analyzer_context_;
|
||||
};
|
||||
};
|
||||
|
||||
class DummyType : public Type
|
||||
{
|
||||
class DummyType : public Type {
|
||||
public:
|
||||
DummyType() : Type(DUMMY) { }
|
||||
DummyType() : Type(DUMMY) {}
|
||||
|
||||
bool DefineValueVar() const override { return false; }
|
||||
string DataTypeStr() const override
|
||||
{
|
||||
string DataTypeStr() const override {
|
||||
ASSERT(0);
|
||||
return "";
|
||||
}
|
||||
|
||||
int StaticSize(Env* env) const override
|
||||
{
|
||||
int StaticSize(Env* env) const override {
|
||||
ASSERT(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ByteOrderSensitive() const override { return false; }
|
||||
|
||||
bool IsPointerType() const override
|
||||
{
|
||||
bool IsPointerType() const override {
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override { ASSERT(0); }
|
||||
|
||||
// Generate code for computing the dynamic size of the type
|
||||
void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override { ASSERT(0); }
|
||||
|
@ -101,6 +92,6 @@ public:
|
|||
protected:
|
||||
Type* DoClone() const override;
|
||||
void DoMarkIncrementalInput() override { ASSERT(0); }
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_context_h
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
#include "pac_dbg.h"
|
||||
#include "pac_exception.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
|
||||
class EscapeException
|
||||
{
|
||||
class EscapeException {
|
||||
public:
|
||||
explicit EscapeException(const string& s) { msg_ = s; }
|
||||
|
||||
|
@ -15,27 +13,18 @@ public:
|
|||
|
||||
private:
|
||||
string msg_;
|
||||
};
|
||||
};
|
||||
|
||||
// Copied from util.cc of Zeek
|
||||
int expand_escape(const char*& s)
|
||||
{
|
||||
switch ( *(s++) )
|
||||
{
|
||||
case 'b':
|
||||
return '\b';
|
||||
case 'f':
|
||||
return '\f';
|
||||
case 'n':
|
||||
return '\n';
|
||||
case 'r':
|
||||
return '\r';
|
||||
case 't':
|
||||
return '\t';
|
||||
case 'a':
|
||||
return '\a';
|
||||
case 'v':
|
||||
return '\v';
|
||||
int expand_escape(const char*& s) {
|
||||
switch ( *(s++) ) {
|
||||
case 'b': return '\b';
|
||||
case 'f': return '\f';
|
||||
case 'n': return '\n';
|
||||
case 'r': return '\r';
|
||||
case 't': return '\t';
|
||||
case 'a': return '\a';
|
||||
case 'v': return '\v';
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
|
@ -44,8 +33,7 @@ int expand_escape(const char*& s)
|
|||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
{ // \<octal>{1,3}
|
||||
case '7': { // \<octal>{1,3}
|
||||
--s; // put back the first octal digit
|
||||
const char* start = s;
|
||||
|
||||
|
@ -67,8 +55,7 @@ int expand_escape(const char*& s)
|
|||
return result;
|
||||
}
|
||||
|
||||
case 'x':
|
||||
{ /* \x<hex> */
|
||||
case 'x': { /* \x<hex> */
|
||||
const char* start = s;
|
||||
|
||||
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
|
||||
|
@ -82,18 +69,15 @@ int expand_escape(const char*& s)
|
|||
return result;
|
||||
}
|
||||
|
||||
default:
|
||||
return s[-1];
|
||||
}
|
||||
default: 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
|
||||
try
|
||||
{
|
||||
try {
|
||||
const char* text = str_.c_str();
|
||||
int len = strlen(text) + 1;
|
||||
int i = 0;
|
||||
|
@ -101,16 +85,13 @@ ConstString::ConstString(const string& s) : str_(s)
|
|||
char* new_s = new char[len];
|
||||
|
||||
// Skip leading quote.
|
||||
for ( ++text; *text; ++text )
|
||||
{
|
||||
if ( *text == '\\' )
|
||||
{
|
||||
for ( ++text; *text; ++text ) {
|
||||
if ( *text == '\\' ) {
|
||||
++text; // skip '\'
|
||||
new_s[i++] = expand_escape(text);
|
||||
--text; // point to end of sequence
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
new_s[i++] = *text;
|
||||
}
|
||||
}
|
||||
|
@ -122,10 +103,8 @@ ConstString::ConstString(const string& s) : str_(s)
|
|||
|
||||
unescaped_ = new_s;
|
||||
delete[] new_s;
|
||||
}
|
||||
catch ( EscapeException const& e )
|
||||
{
|
||||
} catch ( EscapeException const& e ) {
|
||||
// Throw again with the object
|
||||
throw Exception(this, e.msg().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
#include "pac_common.h"
|
||||
|
||||
class ConstString : public Object
|
||||
{
|
||||
class ConstString : public Object {
|
||||
public:
|
||||
ConstString(const string& s);
|
||||
|
||||
|
@ -18,6 +17,6 @@ public:
|
|||
private:
|
||||
string str_;
|
||||
string unescaped_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_cstr_h
|
||||
|
|
|
@ -1,21 +1,13 @@
|
|||
#include "pac_ctype.h"
|
||||
|
||||
string CType::DeclareInstance(const string& var) const
|
||||
{
|
||||
return strfmt("%s %s", name().c_str(), var.c_str());
|
||||
}
|
||||
string CType::DeclareInstance(const string& var) const { return strfmt("%s %s", name().c_str(), var.c_str()); }
|
||||
|
||||
string CType::DeclareConstReference(const string& var) const
|
||||
{
|
||||
string CType::DeclareConstReference(const string& var) const {
|
||||
return strfmt("%s const &%s", name().c_str(), var.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
string CType::DeclareConstPointer(const string& var) const
|
||||
{
|
||||
string CType::DeclareConstPointer(const string& var) const {
|
||||
return strfmt("%s const *%s", name().c_str(), var.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
string CType::DeclarePointer(const string& var) const
|
||||
{
|
||||
return strfmt("%s *%s", name().c_str(), var.c_str());
|
||||
}
|
||||
string CType::DeclarePointer(const string& var) const { return strfmt("%s *%s", name().c_str(), var.c_str()); }
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include "pac_common.h"
|
||||
|
||||
// Represents a C++ type
|
||||
class CType
|
||||
{
|
||||
class CType {
|
||||
public:
|
||||
CType(const string& name);
|
||||
|
||||
|
@ -18,6 +17,6 @@ public:
|
|||
|
||||
protected:
|
||||
string name_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_ctype_h
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
#include "pac_id.h"
|
||||
#include "pac_type.h"
|
||||
|
||||
DataDepElement::DataDepElement(DDE_Type type) : dde_type_(type), in_traversal(false) { }
|
||||
DataDepElement::DataDepElement(DDE_Type type) : dde_type_(type), in_traversal(false) {}
|
||||
|
||||
bool DataDepElement::Traverse(DataDepVisitor* visitor)
|
||||
{
|
||||
bool DataDepElement::Traverse(DataDepVisitor* visitor) {
|
||||
// Avoid infinite loop
|
||||
if ( in_traversal )
|
||||
return true;
|
||||
|
@ -23,51 +22,33 @@ bool DataDepElement::Traverse(DataDepVisitor* visitor)
|
|||
if ( ! visitor->PostProcess(this) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Expr* DataDepElement::expr()
|
||||
{
|
||||
return static_cast<Expr*>(this);
|
||||
}
|
||||
Expr* DataDepElement::expr() { return static_cast<Expr*>(this); }
|
||||
|
||||
Type* DataDepElement::type()
|
||||
{
|
||||
return static_cast<Type*>(this);
|
||||
}
|
||||
Type* DataDepElement::type() { return static_cast<Type*>(this); }
|
||||
|
||||
bool RequiresAnalyzerContext::PreProcess(DataDepElement* element)
|
||||
{
|
||||
switch ( element->dde_type() )
|
||||
{
|
||||
case DataDepElement::EXPR:
|
||||
ProcessExpr(element->expr());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
bool RequiresAnalyzerContext::PreProcess(DataDepElement* element) {
|
||||
switch ( element->dde_type() ) {
|
||||
case DataDepElement::EXPR: ProcessExpr(element->expr()); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Continue traversal until we know the answer is 'yes'
|
||||
return ! requires_analyzer_context_;
|
||||
}
|
||||
}
|
||||
|
||||
bool RequiresAnalyzerContext::PostProcess(DataDepElement* element)
|
||||
{
|
||||
return ! requires_analyzer_context_;
|
||||
}
|
||||
bool RequiresAnalyzerContext::PostProcess(DataDepElement* element) { return ! requires_analyzer_context_; }
|
||||
|
||||
void RequiresAnalyzerContext::ProcessExpr(Expr* expr)
|
||||
{
|
||||
if ( expr->expr_type() == Expr::EXPR_ID )
|
||||
{
|
||||
requires_analyzer_context_ = (requires_analyzer_context_ ||
|
||||
*expr->id() == *analyzer_context_id ||
|
||||
*expr->id() == *context_macro_id);
|
||||
}
|
||||
void RequiresAnalyzerContext::ProcessExpr(Expr* expr) {
|
||||
if ( expr->expr_type() == Expr::EXPR_ID ) {
|
||||
requires_analyzer_context_ =
|
||||
(requires_analyzer_context_ || *expr->id() == *analyzer_context_id || *expr->id() == *context_macro_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool RequiresAnalyzerContext::compute(DataDepElement* element)
|
||||
{
|
||||
bool RequiresAnalyzerContext::compute(DataDepElement* element) {
|
||||
RequiresAnalyzerContext visitor;
|
||||
element->Traverse(&visitor);
|
||||
return visitor.requires_analyzer_context_;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,9 @@
|
|||
|
||||
class DataDepVisitor;
|
||||
|
||||
class DataDepElement
|
||||
{
|
||||
class DataDepElement {
|
||||
public:
|
||||
enum DDE_Type
|
||||
{
|
||||
enum DDE_Type {
|
||||
ATTR,
|
||||
CASEEXPR,
|
||||
EXPR,
|
||||
|
@ -24,7 +22,7 @@ public:
|
|||
};
|
||||
|
||||
DataDepElement(DDE_Type type);
|
||||
virtual ~DataDepElement() { }
|
||||
virtual ~DataDepElement() {}
|
||||
|
||||
// Returns whether to continue traversal
|
||||
bool Traverse(DataDepVisitor* visitor);
|
||||
|
@ -39,21 +37,19 @@ public:
|
|||
protected:
|
||||
DDE_Type dde_type_;
|
||||
bool in_traversal;
|
||||
};
|
||||
};
|
||||
|
||||
class DataDepVisitor
|
||||
{
|
||||
class DataDepVisitor {
|
||||
public:
|
||||
virtual ~DataDepVisitor() { }
|
||||
virtual ~DataDepVisitor() {}
|
||||
// Returns whether to continue traversal
|
||||
virtual bool PreProcess(DataDepElement* element) = 0;
|
||||
virtual bool PostProcess(DataDepElement* element) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
class RequiresAnalyzerContext : public DataDepVisitor
|
||||
{
|
||||
class RequiresAnalyzerContext : public DataDepVisitor {
|
||||
public:
|
||||
RequiresAnalyzerContext() : requires_analyzer_context_(false) { }
|
||||
RequiresAnalyzerContext() : requires_analyzer_context_(false) {}
|
||||
|
||||
// Returns whether to continue traversal
|
||||
bool PreProcess(DataDepElement* element) override;
|
||||
|
@ -67,6 +63,6 @@ protected:
|
|||
void ProcessExpr(Expr* expr);
|
||||
|
||||
bool requires_analyzer_context_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_datadep_h
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
#include "pac_output.h"
|
||||
#include "pac_utils.h"
|
||||
|
||||
DataPtr::DataPtr(Env* env, const ID* id, const int offset) : id_(id), offset_(offset)
|
||||
{
|
||||
if ( id_ )
|
||||
{
|
||||
DataPtr::DataPtr(Env* env, const ID* id, const int offset) : id_(id), offset_(offset) {
|
||||
if ( id_ ) {
|
||||
if ( ! env->Evaluated(id_) )
|
||||
throw ExceptionIDNotEvaluated(id_);
|
||||
|
||||
|
@ -19,29 +17,23 @@ DataPtr::DataPtr(Env* env, const ID* id, const int offset) : id_(id), offset_(of
|
|||
}
|
||||
else
|
||||
ptr_expr_ = "(null id)";
|
||||
}
|
||||
}
|
||||
|
||||
int DataPtr::AbsOffset(const ID* base_ptr) const
|
||||
{
|
||||
return (id() == base_ptr) ? offset() : -1;
|
||||
}
|
||||
int DataPtr::AbsOffset(const ID* base_ptr) const { return (id() == base_ptr) ? offset() : -1; }
|
||||
|
||||
char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const
|
||||
{
|
||||
char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const {
|
||||
if ( AbsOffset(base_ptr) >= 0 )
|
||||
return nfmt("%d", offset());
|
||||
else
|
||||
return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr));
|
||||
}
|
||||
}
|
||||
|
||||
void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size,
|
||||
const char* data_name) const
|
||||
{
|
||||
void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size, const char* data_name) const {
|
||||
ASSERT(id_);
|
||||
|
||||
out_cc->println("// Checking out-of-bound for \"%s\"", data_name);
|
||||
out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", ptr_expr(), data_size,
|
||||
env->RValue(end_of_data), ptr_expr(), data_size, ptr_expr());
|
||||
out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", ptr_expr(), data_size, env->RValue(end_of_data),
|
||||
ptr_expr(), data_size, ptr_expr());
|
||||
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
|
@ -57,4 +49,4 @@ void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size,
|
|||
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,14 +9,12 @@
|
|||
// A data pointer is represented by an data pointer variable
|
||||
// plus a constant offset.
|
||||
|
||||
class DataPtr
|
||||
{
|
||||
class DataPtr {
|
||||
public:
|
||||
DataPtr(Env* env, const ID* arg_id, const int arg_off);
|
||||
DataPtr(DataPtr const& x) { *this = x; }
|
||||
|
||||
DataPtr const& operator=(DataPtr const& x)
|
||||
{
|
||||
DataPtr const& operator=(DataPtr const& x) {
|
||||
id_ = x.id();
|
||||
offset_ = x.offset();
|
||||
ptr_expr_ = x.ptr_expr();
|
||||
|
@ -27,8 +25,7 @@ public:
|
|||
const ID* id() const { return id_; }
|
||||
int offset() const { return offset_; }
|
||||
|
||||
const char* ptr_expr() const
|
||||
{
|
||||
const char* ptr_expr() const {
|
||||
ASSERT(id_);
|
||||
return ptr_expr_.c_str();
|
||||
}
|
||||
|
@ -36,13 +33,12 @@ public:
|
|||
int AbsOffset(const ID* base_ptr) const;
|
||||
char* AbsOffsetExpr(Env* env, const ID* base_ptr) const;
|
||||
|
||||
void GenBoundaryCheck(Output* out, Env* env, const char* data_size,
|
||||
const char* data_name) const;
|
||||
void GenBoundaryCheck(Output* out, Env* env, const char* data_size, const char* data_name) const;
|
||||
|
||||
protected:
|
||||
const ID* id_;
|
||||
int offset_;
|
||||
string ptr_expr_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_dataptr_h
|
||||
|
|
|
@ -5,41 +5,33 @@
|
|||
#include "pac_paramtype.h"
|
||||
#include "pac_varfield.h"
|
||||
|
||||
AnalyzerDataUnit::AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params,
|
||||
ExprList* context_params)
|
||||
: AnalyzerElement(DATAUNIT), type_(type), id_(id), type_params_(type_params),
|
||||
context_params_(context_params)
|
||||
{
|
||||
AnalyzerDataUnit::AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params)
|
||||
: AnalyzerElement(DATAUNIT), type_(type), id_(id), type_params_(type_params), context_params_(context_params) {
|
||||
data_type_ = new ParameterizedType(id_, type_params_);
|
||||
context_type_ = new ParameterizedType(
|
||||
AnalyzerContextDecl::current_analyzer_context()->id()->clone(), context_params_);
|
||||
context_type_ =
|
||||
new ParameterizedType(AnalyzerContextDecl::current_analyzer_context()->id()->clone(), context_params_);
|
||||
|
||||
dataunit_var_field_ = new ParseVarField(Field::CLASS_MEMBER, dataunit_id->clone(), data_type());
|
||||
context_var_field_ = new PrivVarField(analyzer_context_id->clone(), context_type());
|
||||
}
|
||||
}
|
||||
|
||||
AnalyzerDataUnit::~AnalyzerDataUnit()
|
||||
{
|
||||
AnalyzerDataUnit::~AnalyzerDataUnit() {
|
||||
delete dataunit_var_field_;
|
||||
delete context_var_field_;
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDataUnit::Prepare(Env* env)
|
||||
{
|
||||
void AnalyzerDataUnit::Prepare(Env* env) {
|
||||
dataunit_var_field_->Prepare(env);
|
||||
context_var_field_->Prepare(env);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyzerDataUnit::GenNewDataUnit(Output* out_cc, Env* env)
|
||||
{
|
||||
void AnalyzerDataUnit::GenNewDataUnit(Output* out_cc, Env* env) {
|
||||
out_cc->println("%s = new %s(%s);", env->LValue(dataunit_id), data_type()->class_name().c_str(),
|
||||
data_type()->EvalParameters(out_cc, env).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
void AnalyzerDataUnit::GenNewContext(Output* out_cc, Env* env) {
|
||||
out_cc->println("%s = new %s(%s);", env->LValue(analyzer_context_id), context_type()->class_name().c_str(),
|
||||
context_type()->EvalParameters(out_cc, env).c_str());
|
||||
env->SetEvaluated(analyzer_context_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,14 +6,9 @@
|
|||
// The type and parameters of input data unit of a flow. For instance, the
|
||||
// data unit of a DCE/RPC flow is DCE_RPC_PDU.
|
||||
|
||||
class AnalyzerDataUnit : public AnalyzerElement
|
||||
{
|
||||
class AnalyzerDataUnit : public AnalyzerElement {
|
||||
public:
|
||||
enum DataUnitType
|
||||
{
|
||||
DATAGRAM,
|
||||
FLOWUNIT
|
||||
};
|
||||
enum DataUnitType { DATAGRAM, FLOWUNIT };
|
||||
AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params);
|
||||
~AnalyzerDataUnit() override;
|
||||
|
||||
|
@ -44,6 +39,6 @@ private:
|
|||
ParameterizedType* context_type_;
|
||||
Field* dataunit_var_field_;
|
||||
Field* context_var_field_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_dataunit_h
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
extern bool FLAGS_pac_debug;
|
||||
|
||||
#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 */
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
DeclList* Decl::decl_list_ = nullptr;
|
||||
Decl::DeclMap Decl::decl_map_;
|
||||
|
||||
Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(nullptr)
|
||||
{
|
||||
Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(nullptr) {
|
||||
decl_map_[id_] = this;
|
||||
if ( ! decl_list_ )
|
||||
decl_list_ = new DeclList();
|
||||
|
@ -27,55 +26,44 @@ Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlis
|
|||
DEBUG_MSG("Finished Decl %s\n", id_->Name());
|
||||
|
||||
analyzer_context_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Decl::~Decl()
|
||||
{
|
||||
Decl::~Decl() {
|
||||
delete id_;
|
||||
delete_list(AttrList, attrlist_);
|
||||
}
|
||||
}
|
||||
|
||||
void Decl::AddAttrs(AttrList* attrs)
|
||||
{
|
||||
void Decl::AddAttrs(AttrList* attrs) {
|
||||
if ( ! attrs )
|
||||
return;
|
||||
if ( ! attrlist_ )
|
||||
attrlist_ = new AttrList();
|
||||
foreach (i, AttrList, attrs)
|
||||
{
|
||||
foreach (i, AttrList, attrs) {
|
||||
attrlist_->push_back(*i);
|
||||
ProcessAttr(*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Decl::ProcessAttr(Attr* attr)
|
||||
{
|
||||
throw Exception(attr, "unhandled attribute");
|
||||
}
|
||||
void Decl::ProcessAttr(Attr* attr) { throw Exception(attr, "unhandled attribute"); }
|
||||
|
||||
void Decl::SetAnalyzerContext()
|
||||
{
|
||||
void Decl::SetAnalyzerContext() {
|
||||
analyzer_context_ = AnalyzerContextDecl::current_analyzer_context();
|
||||
if ( ! analyzer_context_ )
|
||||
{
|
||||
if ( ! analyzer_context_ ) {
|
||||
throw Exception(this, "analyzer context not defined");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Decl::ProcessDecls(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void Decl::ProcessDecls(Output* out_h, Output* out_cc) {
|
||||
if ( ! decl_list_ )
|
||||
return;
|
||||
|
||||
foreach (i, DeclList, decl_list_)
|
||||
{
|
||||
foreach (i, DeclList, decl_list_) {
|
||||
Decl* decl = *i;
|
||||
current_decl_id = decl->id();
|
||||
decl->Prepare();
|
||||
}
|
||||
|
||||
foreach (i, DeclList, decl_list_)
|
||||
{
|
||||
foreach (i, DeclList, decl_list_) {
|
||||
Decl* decl = *i;
|
||||
current_decl_id = decl->id();
|
||||
decl->GenExternDeclaration(out_h);
|
||||
|
@ -86,8 +74,7 @@ void Decl::ProcessDecls(Output* out_h, Output* out_cc)
|
|||
|
||||
AnalyzerContextDecl* analyzer_context = AnalyzerContextDecl::current_analyzer_context();
|
||||
|
||||
foreach (i, DeclList, decl_list_)
|
||||
{
|
||||
foreach (i, DeclList, decl_list_) {
|
||||
Decl* decl = *i;
|
||||
current_decl_id = decl->id();
|
||||
decl->GenForwardDeclaration(out_h);
|
||||
|
@ -98,58 +85,51 @@ void Decl::ProcessDecls(Output* out_h, Output* out_cc)
|
|||
|
||||
out_h->println("");
|
||||
|
||||
foreach (i, DeclList, decl_list_)
|
||||
{
|
||||
foreach (i, DeclList, decl_list_) {
|
||||
Decl* decl = *i;
|
||||
current_decl_id = decl->id();
|
||||
decl->GenCode(out_h, out_cc);
|
||||
}
|
||||
|
||||
if ( analyzer_context )
|
||||
{
|
||||
if ( analyzer_context ) {
|
||||
analyzer_context->GenNamespaceEnd(out_h);
|
||||
analyzer_context->GenNamespaceEnd(out_cc);
|
||||
}
|
||||
|
||||
out_h->println("} // namespace binpac");
|
||||
out_cc->println("} // namespace binpac");
|
||||
}
|
||||
}
|
||||
|
||||
Decl* Decl::LookUpDecl(const ID* id)
|
||||
{
|
||||
Decl* Decl::LookUpDecl(const ID* id) {
|
||||
DeclMap::iterator it = decl_map_.find(id);
|
||||
if ( it == decl_map_.end() )
|
||||
return nullptr;
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
int HelperDecl::helper_id_seq = 0;
|
||||
|
||||
HelperDecl::HelperDecl(HelperType helper_type, ID* context_id, EmbeddedCode* code)
|
||||
: Decl(new ID(strfmt("helper_%d", ++helper_id_seq)), HELPER), helper_type_(helper_type),
|
||||
context_id_(context_id), code_(code)
|
||||
{
|
||||
}
|
||||
: Decl(new ID(strfmt("helper_%d", ++helper_id_seq)), HELPER),
|
||||
helper_type_(helper_type),
|
||||
context_id_(context_id),
|
||||
code_(code) {}
|
||||
|
||||
HelperDecl::~HelperDecl()
|
||||
{
|
||||
HelperDecl::~HelperDecl() {
|
||||
delete context_id_;
|
||||
delete code_;
|
||||
}
|
||||
}
|
||||
|
||||
void HelperDecl::Prepare()
|
||||
{
|
||||
void HelperDecl::Prepare() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
void HelperDecl::GenExternDeclaration(Output* out_h)
|
||||
{
|
||||
void HelperDecl::GenExternDeclaration(Output* out_h) {
|
||||
if ( helper_type_ == EXTERN )
|
||||
code_->GenCode(out_h, global_env());
|
||||
}
|
||||
}
|
||||
|
||||
void HelperDecl::GenCode(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void HelperDecl::GenCode(Output* out_h, Output* out_cc) {
|
||||
Env* env = global_env();
|
||||
|
||||
#if 0
|
||||
|
@ -180,4 +160,4 @@ void HelperDecl::GenCode(Output* out_h, Output* out_cc)
|
|||
; // do nothing
|
||||
else
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,23 +4,11 @@
|
|||
#include "pac_common.h"
|
||||
#include "pac_id.h"
|
||||
|
||||
class Decl : public Object
|
||||
{
|
||||
class Decl : public Object {
|
||||
public:
|
||||
// Note: ANALYZER is not for AnalyzerDecl (which is an
|
||||
// abstract class) , but for AnalyzerContextDecl.
|
||||
enum DeclType
|
||||
{
|
||||
ENUM,
|
||||
LET,
|
||||
TYPE,
|
||||
FUNC,
|
||||
CONN,
|
||||
FLOW,
|
||||
ANALYZER,
|
||||
HELPER,
|
||||
REGEX
|
||||
};
|
||||
enum DeclType { ENUM, LET, TYPE, FUNC, CONN, FLOW, ANALYZER, HELPER, REGEX };
|
||||
|
||||
Decl(ID* id, DeclType decl_type);
|
||||
virtual ~Decl();
|
||||
|
@ -35,8 +23,7 @@ public:
|
|||
virtual void Prepare() = 0;
|
||||
|
||||
// Generate declarations out of the "binpac" namespace
|
||||
virtual void GenExternDeclaration(Output* out_h)
|
||||
{ /* do nothing */
|
||||
virtual void GenExternDeclaration(Output* out_h) { /* do nothing */
|
||||
}
|
||||
|
||||
// Generate declarations before definition of classes
|
||||
|
@ -64,13 +51,11 @@ private:
|
|||
static DeclList* decl_list_;
|
||||
typedef map<const ID*, Decl*, ID_ptr_cmp> DeclMap;
|
||||
static DeclMap decl_map_;
|
||||
};
|
||||
};
|
||||
|
||||
class HelperDecl : public Decl
|
||||
{
|
||||
class HelperDecl : public Decl {
|
||||
public:
|
||||
enum HelperType
|
||||
{
|
||||
enum HelperType {
|
||||
HEADER,
|
||||
CODE,
|
||||
EXTERN,
|
||||
|
@ -80,8 +65,7 @@ public:
|
|||
|
||||
void Prepare() override;
|
||||
void GenExternDeclaration(Output* out_h) override;
|
||||
void GenForwardDeclaration(Output* out_h) override
|
||||
{ /* do nothing */
|
||||
void GenForwardDeclaration(Output* out_h) override { /* do nothing */
|
||||
}
|
||||
void GenCode(Output* out_h, Output* out_cc) override;
|
||||
|
||||
|
@ -91,6 +75,6 @@ private:
|
|||
EmbeddedCode* code_;
|
||||
|
||||
static int helper_id_seq;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_decl_h
|
||||
|
|
|
@ -4,57 +4,36 @@
|
|||
#include "pac_output.h"
|
||||
#include "pac_primitive.h"
|
||||
|
||||
EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(nullptr) { }
|
||||
EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(nullptr) {}
|
||||
|
||||
EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive* primitive)
|
||||
: s_(""), primitive_(primitive) { }
|
||||
EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive* primitive) : s_(""), primitive_(primitive) {}
|
||||
|
||||
EmbeddedCodeSegment::~EmbeddedCodeSegment()
|
||||
{
|
||||
delete primitive_;
|
||||
}
|
||||
EmbeddedCodeSegment::~EmbeddedCodeSegment() { delete primitive_; }
|
||||
|
||||
string EmbeddedCodeSegment::ToCode(Env* env)
|
||||
{
|
||||
string EmbeddedCodeSegment::ToCode(Env* env) {
|
||||
if ( primitive_ && s_.empty() )
|
||||
s_ = primitive_->ToCode(env);
|
||||
return s_;
|
||||
}
|
||||
}
|
||||
|
||||
EmbeddedCode::EmbeddedCode()
|
||||
{
|
||||
segments_ = new EmbeddedCodeSegmentList();
|
||||
}
|
||||
EmbeddedCode::EmbeddedCode() { segments_ = new EmbeddedCodeSegmentList(); }
|
||||
|
||||
EmbeddedCode::~EmbeddedCode()
|
||||
{
|
||||
delete_list(EmbeddedCodeSegmentList, segments_);
|
||||
}
|
||||
EmbeddedCode::~EmbeddedCode() { delete_list(EmbeddedCodeSegmentList, segments_); }
|
||||
|
||||
void EmbeddedCode::Append(int atom)
|
||||
{
|
||||
current_segment_ += static_cast<char>(atom);
|
||||
}
|
||||
void EmbeddedCode::Append(int atom) { current_segment_ += static_cast<char>(atom); }
|
||||
|
||||
void EmbeddedCode::Append(const char* str)
|
||||
{
|
||||
current_segment_ += str;
|
||||
}
|
||||
void EmbeddedCode::Append(const char* str) { current_segment_ += str; }
|
||||
|
||||
void EmbeddedCode::Append(PacPrimitive* primitive)
|
||||
{
|
||||
if ( ! current_segment_.empty() )
|
||||
{
|
||||
void EmbeddedCode::Append(PacPrimitive* primitive) {
|
||||
if ( ! current_segment_.empty() ) {
|
||||
segments_->push_back(new EmbeddedCodeSegment(current_segment_));
|
||||
current_segment_ = "";
|
||||
}
|
||||
segments_->push_back(new EmbeddedCodeSegment(primitive));
|
||||
}
|
||||
}
|
||||
|
||||
void EmbeddedCode::GenCode(Output* out, Env* env)
|
||||
{
|
||||
if ( ! current_segment_.empty() )
|
||||
{
|
||||
void EmbeddedCode::GenCode(Output* out, Env* env) {
|
||||
if ( ! current_segment_.empty() ) {
|
||||
segments_->push_back(new EmbeddedCodeSegment(current_segment_));
|
||||
current_segment_ = "";
|
||||
}
|
||||
|
@ -66,12 +45,11 @@ void EmbeddedCode::GenCode(Output* out, Env* env)
|
|||
// ID's name is used as its RValue
|
||||
env->set_allow_undefined_id(true);
|
||||
|
||||
foreach (i, EmbeddedCodeSegmentList, segments_)
|
||||
{
|
||||
foreach (i, EmbeddedCodeSegmentList, segments_) {
|
||||
EmbeddedCodeSegment* segment = *i;
|
||||
out->print("%s", segment->ToCode(env).c_str());
|
||||
}
|
||||
|
||||
env->set_allow_undefined_id(false);
|
||||
out->print("\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
#include "pac_common.h"
|
||||
|
||||
class EmbeddedCodeSegment
|
||||
{
|
||||
class EmbeddedCodeSegment {
|
||||
public:
|
||||
explicit EmbeddedCodeSegment(const string& s);
|
||||
explicit EmbeddedCodeSegment(PacPrimitive* primitive);
|
||||
|
@ -15,12 +14,11 @@ public:
|
|||
private:
|
||||
string s_;
|
||||
PacPrimitive* primitive_;
|
||||
};
|
||||
};
|
||||
|
||||
typedef vector<EmbeddedCodeSegment*> EmbeddedCodeSegmentList;
|
||||
|
||||
class EmbeddedCode : public Object
|
||||
{
|
||||
class EmbeddedCode : public Object {
|
||||
public:
|
||||
EmbeddedCode();
|
||||
~EmbeddedCode();
|
||||
|
@ -37,6 +35,6 @@ public:
|
|||
private:
|
||||
string current_segment_;
|
||||
EmbeddedCodeSegmentList* segments_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_embedded_h
|
||||
|
|
|
@ -6,19 +6,16 @@
|
|||
#include "pac_output.h"
|
||||
#include "pac_typedecl.h"
|
||||
|
||||
Enum::Enum(ID* id, Expr* expr) : id_(id), expr_(expr) { }
|
||||
Enum::Enum(ID* id, Expr* expr) : id_(id), expr_(expr) {}
|
||||
|
||||
Enum::~Enum()
|
||||
{
|
||||
Enum::~Enum() {
|
||||
delete id_;
|
||||
delete expr_;
|
||||
}
|
||||
}
|
||||
|
||||
void Enum::GenHeader(Output* out_h, int* pval)
|
||||
{
|
||||
void Enum::GenHeader(Output* out_h, int* pval) {
|
||||
ASSERT(pval);
|
||||
if ( expr_ )
|
||||
{
|
||||
if ( expr_ ) {
|
||||
if ( ! expr_->ConstFold(global_env(), pval) )
|
||||
throw ExceptionNonConstExpr(expr_);
|
||||
out_h->println("%s = %d,", id_->Name(), *pval);
|
||||
|
@ -26,41 +23,35 @@ void Enum::GenHeader(Output* out_h, int* pval)
|
|||
else
|
||||
out_h->println("%s,", id_->Name());
|
||||
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();
|
||||
datatype_ = new ExternType(type_id, ExternType::NUMBER);
|
||||
extern_typedecl_ = new TypeDecl(type_id, nullptr, datatype_);
|
||||
}
|
||||
}
|
||||
|
||||
EnumDecl::~EnumDecl()
|
||||
{
|
||||
EnumDecl::~EnumDecl() {
|
||||
delete_list(EnumList, enumlist_);
|
||||
delete extern_typedecl_;
|
||||
}
|
||||
}
|
||||
|
||||
void EnumDecl::Prepare()
|
||||
{
|
||||
void EnumDecl::Prepare() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
void EnumDecl::GenForwardDeclaration(Output* out_h)
|
||||
{
|
||||
void EnumDecl::GenForwardDeclaration(Output* out_h) {
|
||||
out_h->println("enum %s {", id_->Name());
|
||||
out_h->inc_indent();
|
||||
int c = 0;
|
||||
foreach (i, EnumList, enumlist_)
|
||||
{
|
||||
foreach (i, EnumList, enumlist_) {
|
||||
(*i)->GenHeader(out_h, &c);
|
||||
++c;
|
||||
}
|
||||
out_h->dec_indent();
|
||||
out_h->println("};");
|
||||
}
|
||||
}
|
||||
|
||||
void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */)
|
||||
{
|
||||
void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
#include "pac_decl.h"
|
||||
|
||||
class Enum
|
||||
{
|
||||
class Enum {
|
||||
public:
|
||||
Enum(ID* id, Expr* expr = 0);
|
||||
~Enum();
|
||||
|
@ -14,10 +13,9 @@ public:
|
|||
private:
|
||||
ID* id_;
|
||||
Expr* expr_;
|
||||
};
|
||||
};
|
||||
|
||||
class EnumDecl : public Decl
|
||||
{
|
||||
class EnumDecl : public Decl {
|
||||
public:
|
||||
EnumDecl(ID* id, EnumList* enumlist);
|
||||
~EnumDecl() override;
|
||||
|
@ -32,6 +30,6 @@ private:
|
|||
EnumList* enumlist_;
|
||||
Type* datatype_;
|
||||
TypeDecl* extern_typedecl_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_enum_h
|
||||
|
|
|
@ -4,75 +4,58 @@
|
|||
#include "pac_id.h"
|
||||
#include "pac_utils.h"
|
||||
|
||||
Exception::Exception(const Object* o, string msg)
|
||||
{
|
||||
if ( o )
|
||||
{
|
||||
Exception::Exception(const Object* o, string msg) {
|
||||
if ( o ) {
|
||||
msg_ = o->Location();
|
||||
msg_ += ": error : ";
|
||||
}
|
||||
|
||||
msg_ += msg;
|
||||
|
||||
if ( FLAGS_pac_debug )
|
||||
{
|
||||
if ( FLAGS_pac_debug ) {
|
||||
DEBUG_MSG("Exception: %s\n", msg_.c_str());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) : Exception(id), id_(id)
|
||||
{
|
||||
ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) : Exception(id), id_(id) {
|
||||
append(strfmt("`%s' undeclared", id_->Name()));
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) : Exception(id), id_(id)
|
||||
{
|
||||
ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) : Exception(id), id_(id) {
|
||||
append(strfmt("`%s' redefined", id_->Name()));
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) : Exception(id), id_(id)
|
||||
{
|
||||
ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) : Exception(id), id_(id) {
|
||||
append(strfmt("ID `%s' not evaluated before used", id->Name()));
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionIDNotField::ExceptionIDNotField(const ID* id) : Exception(id), id_(id)
|
||||
{
|
||||
ExceptionIDNotField::ExceptionIDNotField(const ID* id) : Exception(id), id_(id) {
|
||||
append(strfmt("ID `%s' is not a field", id_->Name()));
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id, const ID* member_id)
|
||||
: 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()));
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) : Exception(id), id_(id)
|
||||
{
|
||||
ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) : Exception(id), id_(id) {
|
||||
append(strfmt("cyclic dependence through `%s'", id_->Name()));
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) : Exception(o)
|
||||
{
|
||||
append(msg.c_str());
|
||||
}
|
||||
ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) : Exception(o) { append(msg.c_str()); }
|
||||
|
||||
ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) : Exception(expr), expr(expr)
|
||||
{
|
||||
ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) : Exception(expr), expr(expr) {
|
||||
append(strfmt("Expression `%s' is not constant", expr->orig()));
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr)
|
||||
: Exception(expr), expr(expr)
|
||||
{
|
||||
append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index",
|
||||
expr->orig()));
|
||||
}
|
||||
ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr) : Exception(expr), expr(expr) {
|
||||
append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index", expr->orig()));
|
||||
}
|
||||
|
||||
ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr)
|
||||
: Exception(expr), expr(expr)
|
||||
{
|
||||
append(strfmt("Expression `%s' as a case index is outside the numeric limit of the type used "
|
||||
ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr) : Exception(expr), expr(expr) {
|
||||
append(
|
||||
strfmt("Expression `%s' as a case index is outside the numeric limit of the type used "
|
||||
"for the switch expression",
|
||||
expr->orig()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@ using namespace std;
|
|||
|
||||
#include "pac_common.h"
|
||||
|
||||
class Exception
|
||||
{
|
||||
class Exception {
|
||||
public:
|
||||
Exception(const Object* o, string msg = "");
|
||||
|
||||
|
@ -16,98 +15,88 @@ public:
|
|||
|
||||
private:
|
||||
string msg_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionIDNotFound : public Exception
|
||||
{
|
||||
class ExceptionIDNotFound : public Exception {
|
||||
public:
|
||||
ExceptionIDNotFound(const ID* id);
|
||||
const ID* id() const { return id_; }
|
||||
|
||||
private:
|
||||
const ID* id_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionIDRedefinition : public Exception
|
||||
{
|
||||
class ExceptionIDRedefinition : public Exception {
|
||||
public:
|
||||
ExceptionIDRedefinition(const ID* id);
|
||||
const ID* id() const { return id_; }
|
||||
|
||||
private:
|
||||
const ID* id_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionIDNotEvaluated : public Exception
|
||||
{
|
||||
class ExceptionIDNotEvaluated : public Exception {
|
||||
public:
|
||||
ExceptionIDNotEvaluated(const ID* id);
|
||||
const ID* id() const { return id_; }
|
||||
|
||||
private:
|
||||
const ID* id_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionCyclicDependence : public Exception
|
||||
{
|
||||
class ExceptionCyclicDependence : public Exception {
|
||||
public:
|
||||
ExceptionCyclicDependence(const ID* id);
|
||||
const ID* id() const { return id_; }
|
||||
|
||||
private:
|
||||
const ID* id_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionPaddingError : public Exception
|
||||
{
|
||||
class ExceptionPaddingError : public Exception {
|
||||
public:
|
||||
ExceptionPaddingError(const Object* o, string msg);
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionIDNotField : public Exception
|
||||
{
|
||||
class ExceptionIDNotField : public Exception {
|
||||
public:
|
||||
ExceptionIDNotField(const ID* id);
|
||||
const ID* id() const { return id_; }
|
||||
|
||||
private:
|
||||
const ID* id_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionMemberNotFound : public Exception
|
||||
{
|
||||
class ExceptionMemberNotFound : public Exception {
|
||||
public:
|
||||
ExceptionMemberNotFound(const ID* type_id, const ID* member_id);
|
||||
|
||||
private:
|
||||
const ID *type_id_, *member_id_;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionNonConstExpr : public Exception
|
||||
{
|
||||
class ExceptionNonConstExpr : public Exception {
|
||||
public:
|
||||
ExceptionNonConstExpr(const Expr* expr);
|
||||
|
||||
private:
|
||||
const Expr* expr;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionInvalidCaseSizeExpr : public Exception
|
||||
{
|
||||
class ExceptionInvalidCaseSizeExpr : public Exception {
|
||||
public:
|
||||
ExceptionInvalidCaseSizeExpr(const Expr* expr);
|
||||
|
||||
private:
|
||||
const Expr* expr;
|
||||
};
|
||||
};
|
||||
|
||||
class ExceptionInvalidCaseLimitExpr : public Exception
|
||||
{
|
||||
class ExceptionInvalidCaseLimitExpr : public Exception {
|
||||
public:
|
||||
ExceptionInvalidCaseLimitExpr(const Expr* expr);
|
||||
|
||||
private:
|
||||
const Expr* expr;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* pac_exception_h */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,11 +6,9 @@
|
|||
|
||||
class CaseExpr;
|
||||
|
||||
class Expr : public Object, public DataDepElement
|
||||
{
|
||||
class Expr : public Object, public DataDepElement {
|
||||
public:
|
||||
enum ExprType
|
||||
{
|
||||
enum ExprType {
|
||||
#define EXPR_DEF(type, x, y) type,
|
||||
#include "pac_expr.def"
|
||||
#undef EXPR_DEF
|
||||
|
@ -110,15 +108,14 @@ private:
|
|||
void GenStrFromFormat(Env* env);
|
||||
void GenEval(Output* out, Env* env);
|
||||
void GenCaseEval(Output* out_cc, Env* env);
|
||||
};
|
||||
};
|
||||
|
||||
string OrigExprList(ExprList* exprlist);
|
||||
string EvalExprList(ExprList* exprlist, Output* out, Env* env);
|
||||
|
||||
// An entry of the case expression, consisting of one or more constant
|
||||
// expressions for the case index and a value expression.
|
||||
class CaseExpr : public Object, public DataDepElement
|
||||
{
|
||||
class CaseExpr : public Object, public DataDepElement {
|
||||
public:
|
||||
CaseExpr(ExprList* index, Expr* value);
|
||||
~CaseExpr() override;
|
||||
|
@ -135,6 +132,6 @@ protected:
|
|||
private:
|
||||
ExprList* index_;
|
||||
Expr* value_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_expr_h
|
||||
|
|
|
@ -4,66 +4,42 @@
|
|||
#include "pac_id.h"
|
||||
#include "pac_output.h"
|
||||
|
||||
bool ExternType::DefineValueVar() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool ExternType::DefineValueVar() const { return true; }
|
||||
|
||||
string ExternType::DataTypeStr() const
|
||||
{
|
||||
switch ( ext_type_ )
|
||||
{
|
||||
string ExternType::DataTypeStr() const {
|
||||
switch ( ext_type_ ) {
|
||||
case PLAIN:
|
||||
case NUMBER:
|
||||
return id_->Name();
|
||||
case POINTER:
|
||||
return string(id_->Name()) + " *";
|
||||
default:
|
||||
ASSERT(0);
|
||||
return "";
|
||||
}
|
||||
case NUMBER: return id_->Name();
|
||||
case POINTER: return string(id_->Name()) + " *";
|
||||
default: ASSERT(0); return "";
|
||||
}
|
||||
}
|
||||
|
||||
int ExternType::StaticSize(Env* env) const
|
||||
{
|
||||
int ExternType::StaticSize(Env* env) const {
|
||||
ASSERT(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool ExternType::ByteOrderSensitive() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool ExternType::ByteOrderSensitive() const { return false; }
|
||||
|
||||
string ExternType::EvalMember(const ID* member_id) const
|
||||
{
|
||||
string ExternType::EvalMember(const ID* member_id) const {
|
||||
return strfmt("%s%s", ext_type_ == POINTER ? "->" : ".", member_id->Name());
|
||||
}
|
||||
}
|
||||
|
||||
void ExternType::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void ExternType::GenInitCode(Output* out_cc, Env* env) {
|
||||
if ( IsNumericType() )
|
||||
out_cc->println("%s = 0;", env->LValue(value_var()));
|
||||
else if ( IsPointerType() )
|
||||
out_cc->println("%s = nullptr;", env->LValue(value_var()));
|
||||
|
||||
Type::GenInitCode(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
void ExternType::DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags)
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
void ExternType::DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) { ASSERT(0); }
|
||||
|
||||
void ExternType::GenDynamicSize(Output* out, Env* env, const DataPtr& data)
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
void ExternType::GenDynamicSize(Output* out, Env* env, const DataPtr& data) { ASSERT(0); }
|
||||
|
||||
Type* ExternType::DoClone() const
|
||||
{
|
||||
return new ExternType(id_->clone(), ext_type_);
|
||||
}
|
||||
Type* ExternType::DoClone() const { return new ExternType(id_->clone(), ext_type_); }
|
||||
|
||||
// Definitions of pre-defined external types
|
||||
|
||||
|
@ -71,8 +47,7 @@ Type* ExternType::DoClone() const
|
|||
#include "pac_externtype.def"
|
||||
#undef EXTERNTYPE
|
||||
|
||||
void ExternType::static_init()
|
||||
{
|
||||
void ExternType::static_init() {
|
||||
ID* id;
|
||||
// TypeDecl *decl;
|
||||
// decl = new TypeDecl(id, 0, extern_type_##name);
|
||||
|
@ -83,4 +58,4 @@ void ExternType::static_init()
|
|||
Type::AddPredefinedType(#name, extern_type_##name);
|
||||
#include "pac_externtype.def"
|
||||
#undef EXTERNTYPE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,16 +8,10 @@
|
|||
// spefication, e.g., in a record field). The type name is copied
|
||||
// literally to the compiled code.
|
||||
|
||||
class ExternType : public Type
|
||||
{
|
||||
class ExternType : public Type {
|
||||
public:
|
||||
enum EXTType
|
||||
{
|
||||
PLAIN,
|
||||
NUMBER,
|
||||
POINTER
|
||||
};
|
||||
ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) { }
|
||||
enum EXTType { PLAIN, NUMBER, POINTER };
|
||||
ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) {}
|
||||
|
||||
bool DefineValueVar() const override;
|
||||
string DataTypeStr() const override;
|
||||
|
@ -42,7 +36,7 @@ private:
|
|||
|
||||
public:
|
||||
static void static_init();
|
||||
};
|
||||
};
|
||||
|
||||
#define EXTERNTYPE(name, ctype, exttype) extern ExternType* extern_type_##name;
|
||||
#include "pac_externtype.def"
|
||||
|
|
|
@ -7,30 +7,25 @@
|
|||
#include "pac_type.h"
|
||||
|
||||
Field::Field(FieldType tof, int flags, ID* id, Type* type)
|
||||
: DataDepElement(DataDepElement::FIELD), tof_(tof), flags_(flags), id_(id), type_(type)
|
||||
{
|
||||
: DataDepElement(DataDepElement::FIELD), tof_(tof), flags_(flags), id_(id), type_(type) {
|
||||
decl_id_ = current_decl_id;
|
||||
field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name());
|
||||
attrs_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Field::~Field()
|
||||
{
|
||||
Field::~Field() {
|
||||
delete id_;
|
||||
delete type_;
|
||||
delete_list(AttrList, attrs_);
|
||||
}
|
||||
}
|
||||
|
||||
void Field::AddAttr(AttrList* attrs)
|
||||
{
|
||||
void Field::AddAttr(AttrList* attrs) {
|
||||
bool delete_attrs = false;
|
||||
|
||||
if ( ! attrs_ )
|
||||
{
|
||||
if ( ! attrs_ ) {
|
||||
attrs_ = attrs;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
attrs_->insert(attrs_->end(), attrs->begin(), attrs->end());
|
||||
delete_attrs = true;
|
||||
}
|
||||
|
@ -40,44 +35,35 @@ void Field::AddAttr(AttrList* attrs)
|
|||
|
||||
if ( delete_attrs )
|
||||
delete attrs;
|
||||
}
|
||||
}
|
||||
|
||||
void Field::ProcessAttr(Attr* a)
|
||||
{
|
||||
switch ( a->type() )
|
||||
{
|
||||
void Field::ProcessAttr(Attr* a) {
|
||||
switch ( a->type() ) {
|
||||
case ATTR_IF:
|
||||
if ( tof() != LET_FIELD && tof() != WITHINPUT_FIELD )
|
||||
{
|
||||
throw Exception(a, "&if can only be applied to a "
|
||||
if ( tof() != LET_FIELD && tof() != WITHINPUT_FIELD ) {
|
||||
throw Exception(a,
|
||||
"&if can only be applied to a "
|
||||
"let field");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if ( type_ )
|
||||
type_->ProcessAttr(a);
|
||||
}
|
||||
}
|
||||
|
||||
bool Field::anonymous_field() const
|
||||
{
|
||||
return type_ && type_->anonymous_value_var();
|
||||
}
|
||||
bool Field::anonymous_field() const { return type_ && type_->anonymous_value_var(); }
|
||||
|
||||
int Field::ValueVarType() const
|
||||
{
|
||||
int Field::ValueVarType() const {
|
||||
if ( flags_ & CLASS_MEMBER )
|
||||
return (flags_ & PUBLIC_READABLE) ? MEMBER_VAR : PRIV_MEMBER_VAR;
|
||||
else
|
||||
return TEMP_VAR;
|
||||
}
|
||||
}
|
||||
|
||||
void Field::Prepare(Env* env)
|
||||
{
|
||||
if ( type_ )
|
||||
{
|
||||
void Field::Prepare(Env* env) {
|
||||
if ( type_ ) {
|
||||
if ( anonymous_field() )
|
||||
flags_ &= ~(CLASS_MEMBER | PUBLIC_READABLE);
|
||||
if ( ! type_->persistent() )
|
||||
|
@ -87,42 +73,36 @@ void Field::Prepare(Env* env)
|
|||
type_->Prepare(env, flags_ & TYPE_TO_BE_PARSED ? Type::TO_BE_PARSED : 0);
|
||||
env->SetField(id(), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Field::GenPubDecls(Output* out_h, Env* env)
|
||||
{
|
||||
void Field::GenPubDecls(Output* out_h, Env* env) {
|
||||
if ( type_ && (flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER) )
|
||||
type_->GenPubDecls(out_h, env);
|
||||
}
|
||||
}
|
||||
|
||||
void Field::GenPrivDecls(Output* out_h, Env* env)
|
||||
{
|
||||
void Field::GenPrivDecls(Output* out_h, Env* env) {
|
||||
// Generate private declaration only if it is a class member
|
||||
if ( type_ && (flags_ & CLASS_MEMBER) )
|
||||
type_->GenPrivDecls(out_h, env);
|
||||
}
|
||||
}
|
||||
|
||||
void Field::GenTempDecls(Output* out_h, Env* env)
|
||||
{
|
||||
void Field::GenTempDecls(Output* out_h, Env* env) {
|
||||
// Generate temp field
|
||||
if ( type_ && ! (flags_ & CLASS_MEMBER) )
|
||||
type_->GenPrivDecls(out_h, env);
|
||||
}
|
||||
}
|
||||
|
||||
void Field::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void Field::GenInitCode(Output* out_cc, Env* env) {
|
||||
if ( type_ && ! anonymous_field() )
|
||||
type_->GenInitCode(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
void Field::GenCleanUpCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void Field::GenCleanUpCode(Output* out_cc, Env* env) {
|
||||
if ( type_ && ! anonymous_field() )
|
||||
type_->GenCleanUpCode(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
bool Field::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
bool Field::DoTraverse(DataDepVisitor* visitor) {
|
||||
// Check parameterized type
|
||||
if ( type_ && ! type_->Traverse(visitor) )
|
||||
return false;
|
||||
|
@ -130,10 +110,9 @@ bool Field::DoTraverse(DataDepVisitor* visitor)
|
|||
if ( ! (*i)->Traverse(visitor) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Field::RequiresAnalyzerContext() const
|
||||
{
|
||||
bool Field::RequiresAnalyzerContext() const {
|
||||
// Check parameterized type
|
||||
if ( type_ && type_->RequiresAnalyzerContext() )
|
||||
return true;
|
||||
|
@ -141,4 +120,4 @@ bool Field::RequiresAnalyzerContext() const
|
|||
if ( (*i)->RequiresAnalyzerContext() )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
// A "field" is a member of class.
|
||||
|
||||
enum FieldType
|
||||
{
|
||||
enum FieldType {
|
||||
CASE_FIELD,
|
||||
CONTEXT_FIELD,
|
||||
FLOW_FIELD,
|
||||
|
@ -20,10 +19,9 @@ enum FieldType
|
|||
PUB_VAR_FIELD,
|
||||
TEMP_VAR_FIELD,
|
||||
WITHINPUT_FIELD,
|
||||
};
|
||||
};
|
||||
|
||||
class Field : public Object, public DataDepElement
|
||||
{
|
||||
class Field : public Object, public DataDepElement {
|
||||
public:
|
||||
Field(FieldType tof, int flags, ID* id, Type* type);
|
||||
// Field flags
|
||||
|
@ -80,6 +78,6 @@ protected:
|
|||
const ID* decl_id_;
|
||||
string field_id_str_;
|
||||
AttrList* attrs_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_field_h
|
||||
|
|
|
@ -15,56 +15,43 @@
|
|||
#include "pac_type.h"
|
||||
#include "pac_varfield.h"
|
||||
|
||||
FlowDecl::FlowDecl(ID* id, ParamList* params, AnalyzerElementList* elemlist)
|
||||
: AnalyzerDecl(id, FLOW, params)
|
||||
{
|
||||
FlowDecl::FlowDecl(ID* id, ParamList* params, AnalyzerElementList* elemlist) : AnalyzerDecl(id, FLOW, params) {
|
||||
dataunit_ = nullptr;
|
||||
conn_decl_ = nullptr;
|
||||
flow_buffer_var_field_ = nullptr;
|
||||
AddElements(elemlist);
|
||||
}
|
||||
}
|
||||
|
||||
FlowDecl::~FlowDecl()
|
||||
{
|
||||
FlowDecl::~FlowDecl() {
|
||||
delete flow_buffer_var_field_;
|
||||
delete dataunit_;
|
||||
}
|
||||
}
|
||||
|
||||
ParameterizedType* FlowDecl::flow_buffer_type_ = nullptr;
|
||||
|
||||
ParameterizedType* FlowDecl::flow_buffer_type()
|
||||
{
|
||||
if ( ! flow_buffer_type_ )
|
||||
{
|
||||
ParameterizedType* FlowDecl::flow_buffer_type() {
|
||||
if ( ! flow_buffer_type_ ) {
|
||||
flow_buffer_type_ = new ParameterizedType(new ID(kFlowBufferClass), nullptr);
|
||||
}
|
||||
return flow_buffer_type_;
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::AddBaseClass(vector<string>* base_classes) const
|
||||
{
|
||||
base_classes->push_back("binpac::FlowAnalyzer");
|
||||
}
|
||||
void FlowDecl::AddBaseClass(vector<string>* base_classes) const { 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");
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem)
|
||||
{
|
||||
if ( dataunit_ )
|
||||
{
|
||||
void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) {
|
||||
if ( dataunit_ ) {
|
||||
throw Exception(dataunit_elem, "dataunit already defined");
|
||||
}
|
||||
dataunit_ = dataunit_elem;
|
||||
|
||||
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT )
|
||||
{
|
||||
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) {
|
||||
dataunit_->data_type()->MarkIncrementalInput();
|
||||
|
||||
flow_buffer_var_field_ = new PubVarField(flow_buffer_id->clone(),
|
||||
FlowDecl::flow_buffer_type()->Clone());
|
||||
flow_buffer_var_field_ = new PubVarField(flow_buffer_id->clone(), FlowDecl::flow_buffer_type()->Clone());
|
||||
type_->AddField(flow_buffer_var_field_);
|
||||
|
||||
ASSERT(AnalyzerContextDecl::current_analyzer_context());
|
||||
|
@ -73,13 +60,11 @@ void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem)
|
|||
// Add an argument to the context initiation
|
||||
dataunit_->context_type()->AddParamArg(new Expr(flow_buffer_var_field_->id()->clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::Prepare()
|
||||
{
|
||||
void FlowDecl::Prepare() {
|
||||
// Add the connection parameter
|
||||
if ( ! conn_decl_ )
|
||||
{
|
||||
if ( ! conn_decl_ ) {
|
||||
throw Exception(this, "no connection is not declared for the flow");
|
||||
}
|
||||
|
||||
|
@ -91,15 +76,11 @@ void FlowDecl::Prepare()
|
|||
AnalyzerDecl::Prepare();
|
||||
|
||||
dataunit_->Prepare(env_);
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenPubDecls(Output* out_h, Output* out_cc)
|
||||
{
|
||||
AnalyzerDecl::GenPubDecls(out_h, out_cc);
|
||||
}
|
||||
void FlowDecl::GenPubDecls(Output* out_h, Output* out_cc) { AnalyzerDecl::GenPubDecls(out_h, out_cc); }
|
||||
|
||||
void FlowDecl::GenPrivDecls(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenPrivDecls(Output* out_h, Output* out_cc) {
|
||||
// Declare the data unit
|
||||
dataunit_->dataunit_var_field()->GenPrivDecls(out_h, env_);
|
||||
|
||||
|
@ -107,30 +88,26 @@ void FlowDecl::GenPrivDecls(Output* out_h, Output* out_cc)
|
|||
dataunit_->context_var_field()->GenPrivDecls(out_h, env_);
|
||||
|
||||
AnalyzerDecl::GenPrivDecls(out_h, out_cc);
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenInitCode(Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenInitCode(Output* out_cc) {
|
||||
AnalyzerDecl::GenInitCode(out_cc);
|
||||
|
||||
out_cc->println("%s = nullptr;", env_->LValue(dataunit_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_);
|
||||
env_->SetEvaluated(flow_buffer_var_field_->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenCleanUpCode(Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenCleanUpCode(Output* out_cc) {
|
||||
GenDeleteDataUnit(out_cc);
|
||||
AnalyzerDecl::GenCleanUpCode(out_cc);
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc) {
|
||||
string proto = strfmt("%s()", kFlowEOF);
|
||||
|
||||
out_h->println("void %s;", proto.c_str());
|
||||
|
@ -139,23 +116,20 @@ void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc)
|
|||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
|
||||
foreach (i, AnalyzerHelperList, eof_helpers_)
|
||||
{
|
||||
foreach (i, AnalyzerHelperList, eof_helpers_) {
|
||||
(*i)->GenCode(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(nullptr, nullptr);", kNewData);
|
||||
}
|
||||
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc) {
|
||||
string proto = strfmt("%s(int gap_length)", kFlowGap);
|
||||
|
||||
out_h->println("void %s;", proto.c_str());
|
||||
|
@ -164,22 +138,20 @@ void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc)
|
|||
out_cc->inc_indent();
|
||||
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("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc) {
|
||||
env_->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr);
|
||||
env_->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr);
|
||||
|
||||
string proto = strfmt("%s(const_byteptr %s, const_byteptr %s)", kNewData,
|
||||
env_->LValue(begin_of_data), env_->LValue(end_of_data));
|
||||
string proto = strfmt("%s(const_byteptr %s, const_byteptr %s)", kNewData, env_->LValue(begin_of_data),
|
||||
env_->LValue(end_of_data));
|
||||
|
||||
out_h->println("void %s;", proto.c_str());
|
||||
|
||||
|
@ -194,16 +166,10 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc)
|
|||
env_->SetEvaluated(begin_of_data);
|
||||
env_->SetEvaluated(end_of_data);
|
||||
|
||||
switch ( dataunit_->type() )
|
||||
{
|
||||
case AnalyzerDataUnit::DATAGRAM:
|
||||
GenCodeDatagram(out_cc);
|
||||
break;
|
||||
case AnalyzerDataUnit::FLOWUNIT:
|
||||
GenCodeFlowUnit(out_cc);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
switch ( dataunit_->type() ) {
|
||||
case AnalyzerDataUnit::DATAGRAM: GenCodeDatagram(out_cc); break;
|
||||
case AnalyzerDataUnit::FLOWUNIT: GenCodeFlowUnit(out_cc); break;
|
||||
default: ASSERT(0);
|
||||
}
|
||||
|
||||
out_cc->println("}");
|
||||
|
@ -213,8 +179,7 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc)
|
|||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
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("throw e;");
|
||||
|
@ -224,39 +189,35 @@ void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc)
|
|||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
out_cc->println("");
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenNewDataUnit(Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenNewDataUnit(Output* out_cc) {
|
||||
Type* unit_datatype = dataunit_->data_type();
|
||||
// dataunit_->data_type()->GenPreParsing(out_cc, env_);
|
||||
dataunit_->GenNewDataUnit(out_cc, env_);
|
||||
if ( unit_datatype->buffer_input() && unit_datatype->buffer_mode() == Type::BUFFER_BY_LENGTH )
|
||||
{
|
||||
if ( unit_datatype->buffer_input() && unit_datatype->buffer_mode() == Type::BUFFER_BY_LENGTH ) {
|
||||
out_cc->println("%s->NewFrame(0, false);", env_->LValue(flow_buffer_id));
|
||||
}
|
||||
dataunit_->GenNewContext(out_cc, env_);
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenDeleteDataUnit(Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenDeleteDataUnit(Output* out_cc) {
|
||||
// Do not just delete dataunit, because we may just want to Unref it.
|
||||
// out_cc->println("delete %s;", env_->LValue(dataunit_id));
|
||||
dataunit_->data_type()->GenCleanUpCode(out_cc, env_);
|
||||
dataunit_->context_type()->GenCleanUpCode(out_cc, env_);
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenCodeFlowUnit(Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenCodeFlowUnit(Output* out_cc) {
|
||||
Type* unit_datatype = dataunit_->data_type();
|
||||
|
||||
out_cc->println("%s->NewData(%s, %s);", env_->LValue(flow_buffer_id),
|
||||
env_->RValue(begin_of_data), env_->RValue(end_of_data));
|
||||
out_cc->println("%s->NewData(%s, %s);", env_->LValue(flow_buffer_id), env_->RValue(begin_of_data),
|
||||
env_->RValue(end_of_data));
|
||||
|
||||
out_cc->println("while ( %s->data_available() && ", env_->LValue(flow_buffer_id));
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("( !%s->have_pending_request() || %s->ready() ) )",
|
||||
env_->LValue(flow_buffer_id), env_->LValue(flow_buffer_id));
|
||||
out_cc->println("( !%s->have_pending_request() || %s->ready() ) )", env_->LValue(flow_buffer_id),
|
||||
env_->LValue(flow_buffer_id));
|
||||
out_cc->println("{");
|
||||
|
||||
// Generate a new dataunit if necessary
|
||||
|
@ -290,17 +251,15 @@ void FlowDecl::GenCodeFlowUnit(Output* out_cc)
|
|||
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowDecl::GenCodeDatagram(Output* out_cc)
|
||||
{
|
||||
void FlowDecl::GenCodeDatagram(Output* out_cc) {
|
||||
Type* unit_datatype = dataunit_->data_type();
|
||||
GenNewDataUnit(out_cc);
|
||||
|
||||
string parse_params = strfmt("%s, %s", env_->RValue(begin_of_data), env_->RValue(end_of_data));
|
||||
|
||||
if ( RequiresAnalyzerContext::compute(unit_datatype) )
|
||||
{
|
||||
if ( RequiresAnalyzerContext::compute(unit_datatype) ) {
|
||||
parse_params += ", ";
|
||||
parse_params += env_->RValue(analyzer_context_id);
|
||||
}
|
||||
|
@ -309,4 +268,4 @@ void FlowDecl::GenCodeDatagram(Output* out_cc)
|
|||
unit_datatype->GenParseCode(out_cc, env_, dataptr, 0);
|
||||
|
||||
GenDeleteDataUnit(out_cc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
#include "pac_analyzer.h"
|
||||
|
||||
class FlowDecl : public AnalyzerDecl
|
||||
{
|
||||
class FlowDecl : public AnalyzerDecl {
|
||||
public:
|
||||
FlowDecl(ID* flow_id, ParamList* params, AnalyzerElementList* elemlist);
|
||||
~FlowDecl() override;
|
||||
|
@ -42,6 +41,6 @@ private:
|
|||
Field* flow_buffer_var_field_;
|
||||
|
||||
static ParameterizedType* flow_buffer_type_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_flow_h
|
||||
|
|
|
@ -7,72 +7,62 @@
|
|||
#include "pac_type.h"
|
||||
|
||||
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;
|
||||
env_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Function::~Function()
|
||||
{
|
||||
Function::~Function() {
|
||||
delete id_;
|
||||
delete type_;
|
||||
delete_list(ParamList, params_);
|
||||
delete env_;
|
||||
delete expr_;
|
||||
delete code_;
|
||||
}
|
||||
}
|
||||
|
||||
void Function::Prepare(Env* env)
|
||||
{
|
||||
void Function::Prepare(Env* env) {
|
||||
env->AddID(id_, FUNC_ID, type_);
|
||||
env->SetEvaluated(id_);
|
||||
|
||||
env_ = new Env(env, this);
|
||||
|
||||
foreach (i, ParamList, params_)
|
||||
{
|
||||
foreach (i, ParamList, params_) {
|
||||
Param* p = *i;
|
||||
env_->AddID(p->id(), FUNC_PARAM, p->type());
|
||||
env_->SetEvaluated(p->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Function::GenForwardDeclaration(Output* out_h)
|
||||
{
|
||||
void Function::GenForwardDeclaration(Output* out_h) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
void Function::GenCode(Output* out_h, Output* out_cc)
|
||||
{
|
||||
out_h->println("%s %s(%s);", type_->DataTypeStr().c_str(), id_->Name(),
|
||||
ParamDecls(params_).c_str());
|
||||
void Function::GenCode(Output* out_h, Output* out_cc) {
|
||||
out_h->println("%s %s(%s);", type_->DataTypeStr().c_str(), id_->Name(), ParamDecls(params_).c_str());
|
||||
|
||||
string class_str = "";
|
||||
if ( analyzer_decl_ )
|
||||
class_str = strfmt("%s::", analyzer_decl_->id()->Name());
|
||||
|
||||
string proto_str = strfmt("%s %s%s(%s)", type_->DataTypeStr().c_str(), class_str.c_str(),
|
||||
id_->Name(), ParamDecls(params_).c_str());
|
||||
string proto_str = strfmt("%s %s%s(%s)", type_->DataTypeStr().c_str(), class_str.c_str(), id_->Name(),
|
||||
ParamDecls(params_).c_str());
|
||||
|
||||
ASSERT(! (expr_ && code_));
|
||||
|
||||
if ( expr_ )
|
||||
{
|
||||
if ( expr_ ) {
|
||||
out_cc->println("%s", proto_str.c_str());
|
||||
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
|
||||
out_cc->println("return static_cast<%s>(%s);", type_->DataTypeStr().c_str(),
|
||||
expr_->EvalExpr(out_cc, env_));
|
||||
out_cc->println("return static_cast<%s>(%s);", type_->DataTypeStr().c_str(), expr_->EvalExpr(out_cc, env_));
|
||||
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
|
||||
else if ( code_ )
|
||||
{
|
||||
else if ( code_ ) {
|
||||
out_cc->println("%s", proto_str.c_str());
|
||||
|
||||
out_cc->inc_indent();
|
||||
|
@ -85,31 +75,18 @@ void Function::GenCode(Output* out_h, Output* out_cc)
|
|||
}
|
||||
|
||||
out_cc->println("");
|
||||
}
|
||||
}
|
||||
|
||||
FuncDecl::FuncDecl(Function* function) : Decl(function->id()->clone(), FUNC), function_(function)
|
||||
{
|
||||
FuncDecl::FuncDecl(Function* function) : Decl(function->id()->clone(), FUNC), function_(function) {
|
||||
function_->Prepare(global_env());
|
||||
}
|
||||
}
|
||||
|
||||
FuncDecl::~FuncDecl()
|
||||
{
|
||||
delete function_;
|
||||
}
|
||||
FuncDecl::~FuncDecl() { delete function_; }
|
||||
|
||||
void FuncDecl::Prepare() { }
|
||||
void FuncDecl::Prepare() {}
|
||||
|
||||
void FuncDecl::GenForwardDeclaration(Output* out_h)
|
||||
{
|
||||
function_->GenForwardDeclaration(out_h);
|
||||
}
|
||||
void FuncDecl::GenForwardDeclaration(Output* out_h) { function_->GenForwardDeclaration(out_h); }
|
||||
|
||||
void FuncDecl::GenCode(Output* out_h, Output* out_cc)
|
||||
{
|
||||
function_->GenCode(out_h, out_cc);
|
||||
}
|
||||
void FuncDecl::GenCode(Output* out_h, Output* out_cc) { function_->GenCode(out_h, out_cc); }
|
||||
|
||||
AnalyzerFunction::AnalyzerFunction(Function* function)
|
||||
: AnalyzerElement(FUNCTION), function_(function)
|
||||
{
|
||||
}
|
||||
AnalyzerFunction::AnalyzerFunction(Function* function) : AnalyzerElement(FUNCTION), function_(function) {}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include "pac_analyzer.h"
|
||||
#include "pac_decl.h"
|
||||
|
||||
class Function : public Object
|
||||
{
|
||||
class Function : public Object {
|
||||
public:
|
||||
Function(ID* id, Type* type, ParamList* params);
|
||||
~Function();
|
||||
|
@ -36,10 +35,9 @@ private:
|
|||
|
||||
Expr* expr_;
|
||||
EmbeddedCode* code_;
|
||||
};
|
||||
};
|
||||
|
||||
class FuncDecl : public Decl
|
||||
{
|
||||
class FuncDecl : public Decl {
|
||||
public:
|
||||
FuncDecl(Function* function);
|
||||
~FuncDecl() override;
|
||||
|
@ -52,10 +50,9 @@ public:
|
|||
|
||||
private:
|
||||
Function* function_;
|
||||
};
|
||||
};
|
||||
|
||||
class AnalyzerFunction : public AnalyzerElement
|
||||
{
|
||||
class AnalyzerFunction : public AnalyzerElement {
|
||||
public:
|
||||
AnalyzerFunction(Function* function);
|
||||
|
||||
|
@ -63,6 +60,6 @@ public:
|
|||
|
||||
private:
|
||||
Function* function_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_func_h
|
||||
|
|
|
@ -38,21 +38,18 @@ const ID* buffering_state_id = nullptr;
|
|||
|
||||
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->anonymous_id_ = true;
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
IDRecord::IDRecord(Env* arg_env, const ID* arg_id, IDType arg_id_type)
|
||||
: env(arg_env), id(arg_id), id_type(arg_id_type)
|
||||
{
|
||||
: env(arg_env), id(arg_id), id_type(arg_id_type) {
|
||||
eval = nullptr;
|
||||
evaluated = in_evaluation = false;
|
||||
setfunc = ""; // except for STATE_VAR
|
||||
switch ( id_type )
|
||||
{
|
||||
switch ( id_type ) {
|
||||
case MEMBER_VAR:
|
||||
rvalue = strfmt("%s()", id->Name());
|
||||
lvalue = strfmt("%s_", id->Name());
|
||||
|
@ -96,45 +93,39 @@ IDRecord::IDRecord(Env* arg_env, const ID* arg_id, IDType arg_id_type)
|
|||
field = nullptr;
|
||||
constant = constant_set = false;
|
||||
macro = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IDRecord::~IDRecord() { }
|
||||
IDRecord::~IDRecord() {}
|
||||
|
||||
void IDRecord::SetConstant(int c)
|
||||
{
|
||||
void IDRecord::SetConstant(int c) {
|
||||
ASSERT(id_type == CONST);
|
||||
constant_set = true;
|
||||
constant = c;
|
||||
}
|
||||
}
|
||||
|
||||
bool IDRecord::GetConstant(int* pc) const
|
||||
{
|
||||
bool IDRecord::GetConstant(int* pc) const {
|
||||
if ( constant_set )
|
||||
*pc = constant;
|
||||
return constant_set;
|
||||
}
|
||||
}
|
||||
|
||||
void IDRecord::SetMacro(Expr* e)
|
||||
{
|
||||
void IDRecord::SetMacro(Expr* e) {
|
||||
ASSERT(id_type == MACRO);
|
||||
macro = e;
|
||||
}
|
||||
}
|
||||
|
||||
Expr* IDRecord::GetMacro() const
|
||||
{
|
||||
Expr* IDRecord::GetMacro() const {
|
||||
ASSERT(id_type == MACRO);
|
||||
return macro;
|
||||
}
|
||||
}
|
||||
|
||||
void IDRecord::SetEvaluated(bool v)
|
||||
{
|
||||
void IDRecord::SetEvaluated(bool v) {
|
||||
if ( v )
|
||||
ASSERT(! evaluated);
|
||||
evaluated = v;
|
||||
}
|
||||
}
|
||||
|
||||
void IDRecord::Evaluate(Output* out, Env* env)
|
||||
{
|
||||
void IDRecord::Evaluate(Output* out, Env* env) {
|
||||
if ( evaluated )
|
||||
return;
|
||||
|
||||
|
@ -152,10 +143,9 @@ void IDRecord::Evaluate(Output* out, Env* env)
|
|||
in_evaluation = false;
|
||||
|
||||
evaluated = true;
|
||||
}
|
||||
}
|
||||
|
||||
const char* IDRecord::RValue() const
|
||||
{
|
||||
const char* IDRecord::RValue() const {
|
||||
if ( id_type == MACRO )
|
||||
return macro->EvalExpr(nullptr, env);
|
||||
|
||||
|
@ -163,36 +153,29 @@ const char* IDRecord::RValue() const
|
|||
throw ExceptionIDNotEvaluated(id);
|
||||
|
||||
return rvalue.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
const char* IDRecord::LValue() const
|
||||
{
|
||||
const char* IDRecord::LValue() const {
|
||||
ASSERT(id_type != MACRO && id_type != FUNC_ID);
|
||||
return lvalue.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
Env::Env(Env* parent_env, Object* context_object)
|
||||
: parent(parent_env), context_object_(context_object)
|
||||
{
|
||||
Env::Env(Env* parent_env, Object* context_object) : parent(parent_env), context_object_(context_object) {
|
||||
allow_undefined_id_ = false;
|
||||
in_branch_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
Env::~Env()
|
||||
{
|
||||
for ( id_map_t::iterator it = id_map.begin(); it != id_map.end(); ++it )
|
||||
{
|
||||
Env::~Env() {
|
||||
for ( id_map_t::iterator it = id_map.begin(); it != id_map.end(); ++it ) {
|
||||
delete it->second;
|
||||
it->second = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Env::AddID(const ID* id, IDType id_type, Type* data_type)
|
||||
{
|
||||
void Env::AddID(const ID* id, IDType id_type, Type* data_type) {
|
||||
DEBUG_MSG("To add ID `%s'...\n", id->Name());
|
||||
id_map_t::iterator it = id_map.find(id);
|
||||
if ( it != id_map.end() )
|
||||
{
|
||||
if ( it != id_map.end() ) {
|
||||
DEBUG_MSG("Duplicate definition: `%s'\n", it->first->Name());
|
||||
throw ExceptionIDRedefinition(id);
|
||||
}
|
||||
|
@ -200,33 +183,29 @@ void Env::AddID(const ID* id, IDType id_type, Type* data_type)
|
|||
// TODO: figure out when data_type must be non-NULL
|
||||
// ASSERT(data_type);
|
||||
SetDataType(id, data_type);
|
||||
}
|
||||
}
|
||||
|
||||
void Env::AddConstID(const ID* id, const int c, Type* type)
|
||||
{
|
||||
void Env::AddConstID(const ID* id, const int c, Type* type) {
|
||||
if ( ! type )
|
||||
type = extern_type_int;
|
||||
AddID(id, CONST, type);
|
||||
SetConstant(id, c);
|
||||
SetEvaluated(id); // a constant is always evaluated
|
||||
}
|
||||
}
|
||||
|
||||
void Env::AddMacro(const ID* id, Expr* macro)
|
||||
{
|
||||
void Env::AddMacro(const ID* id, Expr* macro) {
|
||||
AddID(id, MACRO, macro->DataType(this));
|
||||
SetMacro(id, macro);
|
||||
SetEvaluated(id);
|
||||
}
|
||||
}
|
||||
|
||||
ID* Env::AddTempID(Type* type)
|
||||
{
|
||||
ID* Env::AddTempID(Type* type) {
|
||||
ID* id = ID::NewAnonymousID("t_var_");
|
||||
AddID(id, TEMP_VAR, type);
|
||||
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);
|
||||
|
||||
id_map_t::const_iterator it = id_map.find(id);
|
||||
|
@ -240,61 +219,45 @@ IDRecord* Env::lookup(const ID* id, bool recursive, bool raise_exception) const
|
|||
throw ExceptionIDNotFound(id);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IDType Env::GetIDType(const ID* id) const
|
||||
{
|
||||
return lookup(id, true, true)->GetType();
|
||||
}
|
||||
IDType Env::GetIDType(const ID* id) const { 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);
|
||||
if ( r )
|
||||
return r->RValue();
|
||||
else
|
||||
{
|
||||
else {
|
||||
if ( allow_undefined_id() )
|
||||
return id->Name();
|
||||
else
|
||||
throw ExceptionIDNotFound(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* Env::LValue(const ID* id) const
|
||||
{
|
||||
return lookup(id, true, true)->LValue();
|
||||
}
|
||||
const char* Env::LValue(const ID* id) const { return lookup(id, true, true)->LValue(); }
|
||||
|
||||
void Env::SetEvalMethod(const ID* id, Evaluatable* eval)
|
||||
{
|
||||
lookup(id, true, true)->SetEvalMethod(eval);
|
||||
}
|
||||
void Env::SetEvalMethod(const ID* id, Evaluatable* 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());
|
||||
if ( r )
|
||||
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());
|
||||
if ( r )
|
||||
return r->Evaluated();
|
||||
else
|
||||
// Assume undefined variables are already evaluated
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Env::SetEvaluated(const ID* id, bool v)
|
||||
{
|
||||
if ( in_branch() )
|
||||
{
|
||||
void Env::SetEvaluated(const ID* id, bool v) {
|
||||
if ( in_branch() ) {
|
||||
Field* f = GetField(id);
|
||||
if ( f && f->tof() == LET_FIELD )
|
||||
{
|
||||
if ( f && f->tof() == LET_FIELD ) {
|
||||
throw Exception(context_object_, strfmt("INTERNAL ERROR: "
|
||||
"evaluating let field '%s' in a branch! "
|
||||
"To work around this problem, "
|
||||
|
@ -312,47 +275,32 @@ void Env::SetEvaluated(const ID* id, bool v)
|
|||
parent->SetEvaluated(id, v);
|
||||
else
|
||||
throw ExceptionIDNotFound(id);
|
||||
}
|
||||
}
|
||||
|
||||
void Env::SetField(const ID* id, Field* field)
|
||||
{
|
||||
lookup(id, false, true)->SetField(field);
|
||||
}
|
||||
void Env::SetField(const ID* id, Field* field) { lookup(id, false, true)->SetField(field); }
|
||||
|
||||
Field* Env::GetField(const ID* id) const
|
||||
{
|
||||
return lookup(id, true, true)->GetField();
|
||||
}
|
||||
Field* Env::GetField(const ID* id) const { return lookup(id, true, true)->GetField(); }
|
||||
|
||||
void Env::SetDataType(const ID* id, Type* type)
|
||||
{
|
||||
lookup(id, true, true)->SetDataType(type);
|
||||
}
|
||||
void Env::SetDataType(const ID* id, Type* 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);
|
||||
if ( r )
|
||||
return r->GetDataType();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
string Env::DataTypeStr(const ID* id) const
|
||||
{
|
||||
string Env::DataTypeStr(const ID* id) const {
|
||||
Type* type = GetDataType(id);
|
||||
if ( ! type )
|
||||
throw Exception(id, "data type not defined");
|
||||
return type->DataTypeStr();
|
||||
}
|
||||
}
|
||||
|
||||
void Env::SetConstant(const ID* id, int constant)
|
||||
{
|
||||
lookup(id, false, true)->SetConstant(constant);
|
||||
}
|
||||
void Env::SetConstant(const ID* id, int 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);
|
||||
// lookup without raising exception
|
||||
IDRecord* r = lookup(id, true, false);
|
||||
|
@ -360,20 +308,13 @@ bool Env::GetConstant(const ID* id, int* pc) const
|
|||
return r->GetConstant(pc);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Env::SetMacro(const ID* id, Expr* macro)
|
||||
{
|
||||
lookup(id, true, true)->SetMacro(macro);
|
||||
}
|
||||
void Env::SetMacro(const ID* id, Expr* macro) { lookup(id, true, true)->SetMacro(macro); }
|
||||
|
||||
Expr* Env::GetMacro(const ID* id) const
|
||||
{
|
||||
return lookup(id, true, true)->GetMacro();
|
||||
}
|
||||
Expr* Env::GetMacro(const ID* id) const { return lookup(id, true, true)->GetMacro(); }
|
||||
|
||||
void init_builtin_identifiers()
|
||||
{
|
||||
void init_builtin_identifiers() {
|
||||
default_value_var = new ID("val");
|
||||
null_id = new ID("NULL");
|
||||
null_byteseg_id = new ID("null_byteseg");
|
||||
|
@ -402,14 +343,12 @@ void init_builtin_identifiers()
|
|||
|
||||
null_decl_id = new ID("<null-decl>");
|
||||
current_decl_id = null_decl_id;
|
||||
}
|
||||
}
|
||||
|
||||
Env* global_env()
|
||||
{
|
||||
Env* global_env() {
|
||||
static Env* the_global_env = nullptr;
|
||||
|
||||
if ( ! the_global_env )
|
||||
{
|
||||
if ( ! the_global_env ) {
|
||||
the_global_env = new Env(nullptr, nullptr);
|
||||
|
||||
// These two are defined in binpac.h, so we do not need to
|
||||
|
@ -431,9 +370,6 @@ Env* global_env()
|
|||
}
|
||||
|
||||
return the_global_env;
|
||||
}
|
||||
}
|
||||
|
||||
string set_function(const ID* id)
|
||||
{
|
||||
return strfmt("set_%s", id->Name());
|
||||
}
|
||||
string set_function(const ID* id) { return strfmt("set_%s", id->Name()); }
|
||||
|
|
|
@ -22,8 +22,7 @@ using namespace std;
|
|||
// Env -- a mapping from ID names to their L/R-value expressions and evaluation
|
||||
// methods.
|
||||
|
||||
enum IDType
|
||||
{
|
||||
enum IDType {
|
||||
CONST,
|
||||
GLOBAL_VAR,
|
||||
TEMP_VAR,
|
||||
|
@ -34,20 +33,16 @@ enum IDType
|
|||
MACRO,
|
||||
FUNC_ID,
|
||||
FUNC_PARAM,
|
||||
};
|
||||
};
|
||||
|
||||
class ID;
|
||||
class IDRecord;
|
||||
class Env;
|
||||
class Evaluatable;
|
||||
|
||||
class ID : public Object
|
||||
{
|
||||
class ID : public Object {
|
||||
public:
|
||||
ID(string arg_name) : name(arg_name), anonymous_id_(false)
|
||||
{
|
||||
locname = nfmt("%s:%s", Location(), Name());
|
||||
}
|
||||
ID(string arg_name) : name(arg_name), anonymous_id_(false) { locname = nfmt("%s:%s", Location(), Name()); }
|
||||
~ID() { delete[] locname; }
|
||||
|
||||
bool operator==(ID const& x) const { return name == x.Name(); }
|
||||
|
@ -69,22 +64,19 @@ public:
|
|||
|
||||
private:
|
||||
static int anonymous_id_seq;
|
||||
};
|
||||
};
|
||||
|
||||
// A comparison operator for pointers to ID's.
|
||||
class ID_ptr_cmp
|
||||
{
|
||||
class ID_ptr_cmp {
|
||||
public:
|
||||
bool operator()(const ID* const& id1, const ID* const& id2) const
|
||||
{
|
||||
bool operator()(const ID* const& id1, const ID* const& id2) const {
|
||||
ASSERT(id1);
|
||||
ASSERT(id2);
|
||||
return id1->name < id2->name;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class IDRecord
|
||||
{
|
||||
class IDRecord {
|
||||
public:
|
||||
IDRecord(Env* env, const ID* id, IDType id_type);
|
||||
~IDRecord();
|
||||
|
@ -132,17 +124,15 @@ protected:
|
|||
bool evaluated;
|
||||
bool in_evaluation; // to detect cyclic dependence
|
||||
Evaluatable* eval;
|
||||
};
|
||||
};
|
||||
|
||||
class Evaluatable
|
||||
{
|
||||
class Evaluatable {
|
||||
public:
|
||||
virtual ~Evaluatable() { }
|
||||
virtual ~Evaluatable() {}
|
||||
virtual void GenEval(Output* out, Env* env) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
class Env
|
||||
{
|
||||
class Env {
|
||||
public:
|
||||
Env(Env* parent_env, Object* context_object);
|
||||
~Env();
|
||||
|
@ -204,7 +194,7 @@ private:
|
|||
id_map_t id_map;
|
||||
bool allow_undefined_id_;
|
||||
bool in_branch_;
|
||||
};
|
||||
};
|
||||
|
||||
extern const ID* default_value_var;
|
||||
extern const ID* null_id;
|
||||
|
|
|
@ -6,33 +6,28 @@
|
|||
#include "pac_output.h"
|
||||
#include "pac_type.h"
|
||||
|
||||
InputBuffer::InputBuffer(Expr* expr) : DataDepElement(INPUT_BUFFER), expr_(expr) { }
|
||||
InputBuffer::InputBuffer(Expr* expr) : DataDepElement(INPUT_BUFFER), expr_(expr) {}
|
||||
|
||||
bool InputBuffer::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
bool InputBuffer::DoTraverse(DataDepVisitor* visitor) {
|
||||
if ( expr_ && ! expr_->Traverse(visitor) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool InputBuffer::RequiresAnalyzerContext() const
|
||||
{
|
||||
return expr_->RequiresAnalyzerContext();
|
||||
}
|
||||
bool InputBuffer::RequiresAnalyzerContext() const { return expr_->RequiresAnalyzerContext(); }
|
||||
|
||||
DataPtr InputBuffer::GenDataBeginEnd(Output* out_cc, Env* env)
|
||||
{
|
||||
DataPtr InputBuffer::GenDataBeginEnd(Output* out_cc, Env* env) {
|
||||
env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr);
|
||||
env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr);
|
||||
|
||||
out_cc->println("%s %s, %s;", extern_type_const_byteptr->DataTypeStr().c_str(),
|
||||
env->LValue(begin_of_data), env->LValue(end_of_data));
|
||||
out_cc->println("%s %s, %s;", extern_type_const_byteptr->DataTypeStr().c_str(), env->LValue(begin_of_data),
|
||||
env->LValue(end_of_data));
|
||||
|
||||
out_cc->println("get_pointers(%s, &%s, &%s);", expr_->EvalExpr(out_cc, env),
|
||||
env->LValue(begin_of_data), env->LValue(end_of_data));
|
||||
out_cc->println("get_pointers(%s, &%s, &%s);", expr_->EvalExpr(out_cc, env), env->LValue(begin_of_data),
|
||||
env->LValue(end_of_data));
|
||||
|
||||
env->SetEvaluated(begin_of_data);
|
||||
env->SetEvaluated(end_of_data);
|
||||
|
||||
return DataPtr(env, begin_of_data, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
class Expr;
|
||||
|
||||
class InputBuffer : public Object, public DataDepElement
|
||||
{
|
||||
class InputBuffer : public Object, public DataDepElement {
|
||||
public:
|
||||
InputBuffer(Expr* expr);
|
||||
|
||||
|
@ -19,6 +18,6 @@ protected:
|
|||
|
||||
private:
|
||||
Expr* expr_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_inputbuf_h
|
||||
|
|
|
@ -5,39 +5,27 @@
|
|||
#include "pac_output.h"
|
||||
#include "pac_type.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
|
||||
void GenLetEval(const ID* id, Expr* expr, string prefix, Output* out, Env* env) { }
|
||||
void GenLetEval(const ID* id, Expr* expr, string prefix, Output* out, Env* env) {}
|
||||
|
||||
} // private namespace
|
||||
} // namespace
|
||||
|
||||
LetField::LetField(ID* id, Type* type, Expr* expr)
|
||||
: Field(LET_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type),
|
||||
expr_(expr)
|
||||
{
|
||||
: Field(LET_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), expr_(expr) {
|
||||
ASSERT(expr_);
|
||||
}
|
||||
}
|
||||
|
||||
LetField::~LetField()
|
||||
{
|
||||
delete expr_;
|
||||
}
|
||||
LetField::~LetField() { delete expr_; }
|
||||
|
||||
bool LetField::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
return Field::DoTraverse(visitor) && expr()->Traverse(visitor);
|
||||
}
|
||||
bool LetField::DoTraverse(DataDepVisitor* visitor) { return Field::DoTraverse(visitor) && expr()->Traverse(visitor); }
|
||||
|
||||
bool LetField::RequiresAnalyzerContext() const
|
||||
{
|
||||
bool LetField::RequiresAnalyzerContext() const {
|
||||
return Field::RequiresAnalyzerContext() || (expr() && expr()->RequiresAnalyzerContext());
|
||||
}
|
||||
}
|
||||
|
||||
void LetField::Prepare(Env* env)
|
||||
{
|
||||
if ( ! type_ )
|
||||
{
|
||||
void LetField::Prepare(Env* env) {
|
||||
if ( ! type_ ) {
|
||||
ASSERT(expr_);
|
||||
type_ = expr_->DataType(env);
|
||||
if ( type_ )
|
||||
|
@ -51,27 +39,23 @@ void LetField::Prepare(Env* env)
|
|||
|
||||
Field::Prepare(env);
|
||||
env->SetEvalMethod(id_, this);
|
||||
}
|
||||
}
|
||||
|
||||
void LetField::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void LetField::GenInitCode(Output* out_cc, Env* env) {
|
||||
int v;
|
||||
if ( expr_ && expr_->ConstFold(env, &v) )
|
||||
{
|
||||
if ( expr_ && expr_->ConstFold(env, &v) ) {
|
||||
DEBUG_MSG("Folding const for `%s'\n", id_->Name());
|
||||
GenEval(out_cc, env);
|
||||
}
|
||||
else
|
||||
type_->GenInitCode(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
void LetField::GenParseCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void LetField::GenParseCode(Output* out_cc, Env* env) {
|
||||
if ( env->Evaluated(id_) )
|
||||
return;
|
||||
|
||||
if ( type_->attr_if_expr() )
|
||||
{
|
||||
if ( type_->attr_if_expr() ) {
|
||||
// A conditional field
|
||||
|
||||
env->Evaluate(out_cc, type_->has_value_var());
|
||||
|
@ -88,22 +72,16 @@ void LetField::GenParseCode(Output* out_cc, Env* env)
|
|||
if ( ! env->Evaluated(id_) )
|
||||
env->SetEvaluated(id_);
|
||||
|
||||
if ( type_->attr_if_expr() )
|
||||
{
|
||||
if ( type_->attr_if_expr() ) {
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LetField::GenEval(Output* out_cc, Env* env)
|
||||
{
|
||||
GenParseCode(out_cc, env);
|
||||
}
|
||||
void LetField::GenEval(Output* out_cc, Env* env) { GenParseCode(out_cc, env); }
|
||||
|
||||
LetDecl::LetDecl(ID* id, Type* type, Expr* expr) : Decl(id, LET), type_(type), expr_(expr)
|
||||
{
|
||||
if ( ! type_ )
|
||||
{
|
||||
LetDecl::LetDecl(ID* id, Type* type, Expr* expr) : Decl(id, LET), type_(type), expr_(expr) {
|
||||
if ( ! type_ ) {
|
||||
ASSERT(expr_);
|
||||
type_ = expr_->DataType(global_env());
|
||||
if ( type_ )
|
||||
|
@ -118,30 +96,27 @@ LetDecl::LetDecl(ID* id, Type* type, Expr* expr) : Decl(id, LET), type_(type), e
|
|||
env->AddConstID(id_, c, type);
|
||||
else
|
||||
env->AddID(id_, GLOBAL_VAR, type_);
|
||||
}
|
||||
}
|
||||
|
||||
LetDecl::~LetDecl()
|
||||
{
|
||||
LetDecl::~LetDecl() {
|
||||
delete type_;
|
||||
delete expr_;
|
||||
}
|
||||
}
|
||||
|
||||
void LetDecl::Prepare() { }
|
||||
void LetDecl::Prepare() {}
|
||||
|
||||
void LetDecl::GenForwardDeclaration(Output* out_h) { }
|
||||
void LetDecl::GenForwardDeclaration(Output* out_h) {}
|
||||
|
||||
void LetDecl::GenCode(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void LetDecl::GenCode(Output* out_h, Output* out_cc) {
|
||||
out_h->println("extern %s const %s;", type_->DataTypeStr().c_str(), global_env()->RValue(id_));
|
||||
GenEval(out_cc, global_env());
|
||||
}
|
||||
}
|
||||
|
||||
void LetDecl::GenEval(Output* out_cc, Env* /* env */)
|
||||
{
|
||||
void LetDecl::GenEval(Output* out_cc, Env* /* env */) {
|
||||
Env* env = global_env();
|
||||
string tmp = strfmt("%s const", type_->DataTypeStr().c_str());
|
||||
out_cc->println("%s %s = %s;", tmp.c_str(), env->LValue(id_), expr_->EvalExpr(out_cc, env));
|
||||
|
||||
if ( ! env->Evaluated(id_) )
|
||||
env->SetEvaluated(id_);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include "pac_decl.h"
|
||||
#include "pac_field.h"
|
||||
|
||||
class LetField : public Field, Evaluatable
|
||||
{
|
||||
class LetField : public Field, Evaluatable {
|
||||
public:
|
||||
LetField(ID* arg_id, Type* type, Expr* arg_expr);
|
||||
~LetField() override;
|
||||
|
@ -25,10 +24,9 @@ protected:
|
|||
|
||||
protected:
|
||||
Expr* expr_;
|
||||
};
|
||||
};
|
||||
|
||||
class LetDecl : public Decl, Evaluatable
|
||||
{
|
||||
class LetDecl : public Decl, Evaluatable {
|
||||
public:
|
||||
LetDecl(ID* id, Type* type, Expr* expr);
|
||||
~LetDecl() override;
|
||||
|
@ -43,6 +41,6 @@ public:
|
|||
private:
|
||||
Type* type_;
|
||||
Expr* expr_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_let_h
|
||||
|
|
|
@ -25,11 +25,9 @@ vector<string> FLAGS_include_directories;
|
|||
Output* header_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;
|
||||
while ( dir_begin < dirs.length() )
|
||||
{
|
||||
while ( dir_begin < dirs.length() ) {
|
||||
for ( dir_end = dir_begin; dir_end < dirs.length(); ++dir_end )
|
||||
if ( dirs[dir_end] == ':' )
|
||||
break;
|
||||
|
@ -43,21 +41,18 @@ void add_to_include_directories(string dirs)
|
|||
FLAGS_include_directories.push_back(dir);
|
||||
dir_begin = dir_end + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pac_init()
|
||||
{
|
||||
void pac_init() {
|
||||
init_builtin_identifiers();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void insert_basictype_defs(Output* out)
|
||||
{
|
||||
void insert_basictype_defs(Output* out) {
|
||||
out->println("#ifndef pac_type_defs");
|
||||
out->println("#define pac_type_defs");
|
||||
out->println("");
|
||||
|
@ -74,18 +69,16 @@ void insert_basictype_defs(Output* out)
|
|||
out->println("");
|
||||
out->println("#endif /* pac_type_defs */");
|
||||
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 FixByteOrder32(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap32(x))");
|
||||
out->println("#define FixByteOrder64(x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap64(x))");
|
||||
out->println("");
|
||||
}
|
||||
}
|
||||
|
||||
const char* to_id(const char* s)
|
||||
{
|
||||
const char* to_id(const char* s) {
|
||||
static char t[1024];
|
||||
int i;
|
||||
for ( i = 0; s[i] && i < (int)sizeof(t) - 1; ++i )
|
||||
|
@ -94,13 +87,11 @@ const char* to_id(const char* s)
|
|||
t[0] = '_';
|
||||
t[i] = '\0';
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
int compile(const char* filename)
|
||||
{
|
||||
int compile(const char* filename) {
|
||||
FILE* fp_input = fopen(filename, "r");
|
||||
if ( ! fp_input )
|
||||
{
|
||||
if ( ! fp_input ) {
|
||||
string tmp = strfmt("Error in opening %s", filename);
|
||||
perror(tmp.c_str());
|
||||
return -1;
|
||||
|
@ -109,8 +100,7 @@ int compile(const char* filename)
|
|||
|
||||
string basename;
|
||||
|
||||
if ( ! FLAGS_output_directory.empty() )
|
||||
{
|
||||
if ( ! FLAGS_output_directory.empty() ) {
|
||||
// Strip leading directories of filename
|
||||
const char* last_slash = strrchr(filename, '/');
|
||||
if ( last_slash )
|
||||
|
@ -123,8 +113,7 @@ int compile(const char* filename)
|
|||
basename = filename;
|
||||
|
||||
// If the file name ends with ".pac"
|
||||
if ( basename.length() > 4 && basename.substr(basename.length() - 4) == ".pac" )
|
||||
{
|
||||
if ( basename.length() > 4 && basename.substr(basename.length() - 4) == ".pac" ) {
|
||||
basename = basename.substr(0, basename.length() - 4);
|
||||
}
|
||||
|
||||
|
@ -134,8 +123,7 @@ int compile(const char* filename)
|
|||
|
||||
int ret = 0;
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
switch_to_file(fp_input);
|
||||
if ( yyparse() )
|
||||
return 1;
|
||||
|
@ -170,14 +158,10 @@ int compile(const char* filename)
|
|||
Decl::ProcessDecls(&out_h, &out_cc);
|
||||
|
||||
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());
|
||||
ret = 1;
|
||||
}
|
||||
catch ( Exception& e )
|
||||
{
|
||||
} catch ( Exception& e ) {
|
||||
fprintf(stderr, "%s\n", e.msg());
|
||||
exit(1);
|
||||
}
|
||||
|
@ -188,10 +172,9 @@ int compile(const char* filename)
|
|||
fclose(fp_input);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
void usage() {
|
||||
#ifdef BINPAC_VERSION
|
||||
fprintf(stderr, "binpac version %s\n", BINPAC_VERSION);
|
||||
#endif
|
||||
|
@ -203,7 +186,7 @@ void usage()
|
|||
fprintf(stderr, " -h | show command line help\n");
|
||||
fprintf(stderr, " -I <dir> | include <dir> in input file search path\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// GCC uses __SANITIZE_ADDRESS__, Clang uses __has_feature
|
||||
#if defined(__SANITIZE_ADDRESS__)
|
||||
|
@ -224,8 +207,7 @@ void usage()
|
|||
#define BINPAC_LSAN_DISABLE()
|
||||
#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
|
||||
// projects that use it, like Zeek, only have their build tripped up
|
||||
// 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;
|
||||
#endif
|
||||
int o;
|
||||
while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 )
|
||||
{
|
||||
switch ( o )
|
||||
{
|
||||
case 'D':
|
||||
yydebug = 1;
|
||||
FLAGS_pac_debug = true;
|
||||
while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 ) {
|
||||
switch ( o ) {
|
||||
case 'D': yydebug = 1; FLAGS_pac_debug = true;
|
||||
#ifdef HAVE_MALLOC_OPTIONS
|
||||
malloc_options = "A";
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
FLAGS_quiet = true;
|
||||
break;
|
||||
case 'q': FLAGS_quiet = true; break;
|
||||
|
||||
case 'I':
|
||||
// Add to FLAGS_include_directories
|
||||
add_to_include_directories(optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
FLAGS_output_directory = optarg;
|
||||
break;
|
||||
case 'd': FLAGS_output_directory = optarg; break;
|
||||
|
||||
case 'h':
|
||||
usage();
|
||||
break;
|
||||
case 'h': usage(); break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -288,4 +259,4 @@ int main(int argc, char* argv[])
|
|||
ret = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,17 +3,16 @@
|
|||
|
||||
#include "pac_common.h"
|
||||
|
||||
class Number : public Object
|
||||
{
|
||||
class Number : public Object {
|
||||
public:
|
||||
Number(int arg_n) : s(strfmt("%d", arg_n)), n(arg_n) { }
|
||||
Number(const char* arg_s, int arg_n) : s(arg_s), n(arg_n) { }
|
||||
Number(int arg_n) : s(strfmt("%d", arg_n)), n(arg_n) {}
|
||||
Number(const char* arg_s, int arg_n) : s(arg_s), n(arg_n) {}
|
||||
const char* Str() const { return s.c_str(); }
|
||||
int Num() const { return n; }
|
||||
|
||||
protected:
|
||||
const string s;
|
||||
const int n;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_number_h
|
||||
|
|
|
@ -7,58 +7,48 @@
|
|||
|
||||
#include "pac_utils.h"
|
||||
|
||||
OutputException::OutputException(const char* arg_msg)
|
||||
{
|
||||
msg = arg_msg;
|
||||
}
|
||||
OutputException::OutputException(const char* arg_msg) { msg = arg_msg; }
|
||||
|
||||
OutputException::~OutputException() { }
|
||||
OutputException::~OutputException() {}
|
||||
|
||||
Output::Output(string filename)
|
||||
{
|
||||
Output::Output(string filename) {
|
||||
fp = fopen(filename.c_str(), "w");
|
||||
if ( ! fp )
|
||||
throw OutputException(strerror(errno));
|
||||
indent_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Output::~Output()
|
||||
{
|
||||
Output::~Output() {
|
||||
if ( 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);
|
||||
if ( r == -1 )
|
||||
throw OutputException(strerror(errno));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
int Output::print(const char* fmt, ...)
|
||||
{
|
||||
int Output::print(const char* fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int r = -1;
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
r = print(fmt, ap);
|
||||
}
|
||||
|
||||
catch ( ... )
|
||||
{
|
||||
catch ( ... ) {
|
||||
va_end(ap);
|
||||
throw;
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
int Output::println(const char* fmt, ...)
|
||||
{
|
||||
int Output::println(const char* fmt, ...) {
|
||||
for ( int i = 0; i < indent(); ++i )
|
||||
fprintf(fp, "\t");
|
||||
|
||||
|
@ -66,13 +56,11 @@ int Output::println(const char* fmt, ...)
|
|||
va_start(ap, fmt);
|
||||
int r = -1;
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
r = print(fmt, ap);
|
||||
}
|
||||
|
||||
catch ( ... )
|
||||
{
|
||||
catch ( ... ) {
|
||||
va_end(ap);
|
||||
throw;
|
||||
}
|
||||
|
@ -80,4 +68,4 @@ int Output::println(const char* fmt, ...)
|
|||
va_end(ap);
|
||||
fprintf(fp, "\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
class OutputException
|
||||
{
|
||||
class OutputException {
|
||||
public:
|
||||
OutputException(const char* arg_msg);
|
||||
~OutputException();
|
||||
|
@ -16,10 +15,9 @@ public:
|
|||
|
||||
protected:
|
||||
string msg;
|
||||
};
|
||||
};
|
||||
|
||||
class Output
|
||||
{
|
||||
class Output {
|
||||
public:
|
||||
Output(string filename);
|
||||
~Output();
|
||||
|
@ -37,6 +35,6 @@ protected:
|
|||
|
||||
FILE* fp;
|
||||
int indent_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* pac_output_h */
|
||||
|
|
|
@ -8,31 +8,27 @@
|
|||
#include "pac_type.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_ )
|
||||
type_ = extern_type_int->Clone();
|
||||
|
||||
decl_str_ = strfmt("%s %s", type_->DataTypeConstRefStr().c_str(), id_->Name());
|
||||
|
||||
param_field_ = new ParamField(this);
|
||||
}
|
||||
}
|
||||
|
||||
Param::~Param() { }
|
||||
Param::~Param() {}
|
||||
|
||||
const string& Param::decl_str() const
|
||||
{
|
||||
const string& Param::decl_str() const {
|
||||
ASSERT(! decl_str_.empty());
|
||||
return decl_str_;
|
||||
}
|
||||
}
|
||||
|
||||
string ParamDecls(ParamList* params)
|
||||
{
|
||||
string ParamDecls(ParamList* params) {
|
||||
string param_decls;
|
||||
|
||||
int first = 1;
|
||||
foreach (i, ParamList, params)
|
||||
{
|
||||
foreach (i, ParamList, params) {
|
||||
Param* p = *i;
|
||||
const char* decl_str = p->decl_str().c_str();
|
||||
if ( first )
|
||||
|
@ -42,21 +38,16 @@ string ParamDecls(ParamList* params)
|
|||
param_decls += decl_str;
|
||||
}
|
||||
return param_decls;
|
||||
}
|
||||
}
|
||||
|
||||
ParamField::ParamField(const Param* param)
|
||||
: Field(PARAM_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, param->id(),
|
||||
param->type())
|
||||
{
|
||||
}
|
||||
: Field(PARAM_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, param->id(), param->type()) {}
|
||||
|
||||
void ParamField::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void ParamField::GenInitCode(Output* out_cc, Env* env) {
|
||||
out_cc->println("%s = %s;", env->LValue(id()), id()->Name());
|
||||
env->SetEvaluated(id());
|
||||
}
|
||||
}
|
||||
|
||||
void ParamField::GenCleanUpCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void ParamField::GenCleanUpCode(Output* out_cc, Env* env) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include "pac_common.h"
|
||||
#include "pac_field.h"
|
||||
|
||||
class Param : public Object
|
||||
{
|
||||
class Param : public Object {
|
||||
public:
|
||||
Param(ID* id, Type* type);
|
||||
~Param();
|
||||
|
@ -20,16 +19,15 @@ private:
|
|||
Type* type_;
|
||||
string decl_str_;
|
||||
Field* param_field_;
|
||||
};
|
||||
};
|
||||
|
||||
class ParamField : public Field
|
||||
{
|
||||
class ParamField : public Field {
|
||||
public:
|
||||
ParamField(const Param* param);
|
||||
|
||||
void GenInitCode(Output* out, Env* env) override;
|
||||
void GenCleanUpCode(Output* out, Env* env) override;
|
||||
};
|
||||
};
|
||||
|
||||
// Returns the string with a list of param declarations separated by ','.
|
||||
string ParamDecls(ParamList* params);
|
||||
|
|
|
@ -8,81 +8,56 @@
|
|||
#include "pac_typedecl.h"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
ParameterizedType::~ParameterizedType() { }
|
||||
ParameterizedType::~ParameterizedType() {}
|
||||
|
||||
string ParameterizedType::EvalMember(const ID* member_id) const
|
||||
{
|
||||
string ParameterizedType::EvalMember(const ID* member_id) const {
|
||||
Type* ty = ReferredDataType(true);
|
||||
return strfmt("->%s", ty->env()->RValue(member_id));
|
||||
}
|
||||
}
|
||||
|
||||
string ParameterizedType::class_name() const
|
||||
{
|
||||
return type_id_->Name();
|
||||
}
|
||||
string ParameterizedType::class_name() const { return type_id_->Name(); }
|
||||
|
||||
Type* ParameterizedType::DoClone() const
|
||||
{
|
||||
return new ParameterizedType(type_id_->clone(), args_);
|
||||
}
|
||||
Type* ParameterizedType::DoClone() const { return new ParameterizedType(type_id_->clone(), args_); }
|
||||
|
||||
void ParameterizedType::AddParamArg(Expr* arg)
|
||||
{
|
||||
args_->push_back(arg);
|
||||
}
|
||||
void ParameterizedType::AddParamArg(Expr* arg) { args_->push_back(arg); }
|
||||
|
||||
bool ParameterizedType::DefineValueVar() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool ParameterizedType::DefineValueVar() const { return true; }
|
||||
|
||||
string ParameterizedType::DataTypeStr() const
|
||||
{
|
||||
return strfmt("%s *", type_id_->Name());
|
||||
}
|
||||
string ParameterizedType::DataTypeStr() const { return strfmt("%s *", type_id_->Name()); }
|
||||
|
||||
Type* ParameterizedType::MemberDataType(const ID* member_id) const
|
||||
{
|
||||
Type* ParameterizedType::MemberDataType(const ID* member_id) const {
|
||||
Type* ref_type = TypeDecl::LookUpType(type_id_);
|
||||
if ( ! ref_type )
|
||||
return nullptr;
|
||||
return ref_type->MemberDataType(member_id);
|
||||
}
|
||||
}
|
||||
|
||||
Type* ParameterizedType::ReferredDataType(bool throw_exception) const
|
||||
{
|
||||
Type* ParameterizedType::ReferredDataType(bool throw_exception) const {
|
||||
Type* type = TypeDecl::LookUpType(type_id_);
|
||||
if ( ! type )
|
||||
{
|
||||
if ( ! type ) {
|
||||
DEBUG_MSG("WARNING: cannot find referenced type for %s\n", type_id_->Name());
|
||||
if ( throw_exception )
|
||||
throw ExceptionIDNotFound(type_id_);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
int ParameterizedType::StaticSize(Env* env) const
|
||||
{
|
||||
return ReferredDataType(true)->StaticSize(env);
|
||||
}
|
||||
int ParameterizedType::StaticSize(Env* env) const { return ReferredDataType(true)->StaticSize(env); }
|
||||
|
||||
void ParameterizedType::DoMarkIncrementalInput()
|
||||
{
|
||||
void ParameterizedType::DoMarkIncrementalInput() {
|
||||
Type* ty = ReferredDataType(true);
|
||||
|
||||
ty->MarkIncrementalInput();
|
||||
|
||||
buffer_input_ = ty->buffer_input();
|
||||
incremental_parsing_ = ty->incremental_parsing();
|
||||
}
|
||||
}
|
||||
|
||||
Type::BufferMode ParameterizedType::buffer_mode() const
|
||||
{
|
||||
Type::BufferMode ParameterizedType::buffer_mode() const {
|
||||
// Note that the precedence is on attributes (&oneline or &length)
|
||||
// specified on the parameterized type directly than on the type
|
||||
// declaration.
|
||||
|
@ -101,15 +76,11 @@ Type::BufferMode ParameterizedType::buffer_mode() const
|
|||
return BUFFER_BY_LINE;
|
||||
|
||||
return NOT_BUFFERABLE;
|
||||
}
|
||||
}
|
||||
|
||||
bool ParameterizedType::ByteOrderSensitive() const
|
||||
{
|
||||
return ReferredDataType(true)->RequiresByteOrder();
|
||||
}
|
||||
bool ParameterizedType::ByteOrderSensitive() const { return ReferredDataType(true)->RequiresByteOrder(); }
|
||||
|
||||
bool ParameterizedType::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
bool ParameterizedType::DoTraverse(DataDepVisitor* visitor) {
|
||||
if ( ! Type::DoTraverse(visitor) )
|
||||
return false;
|
||||
|
||||
|
@ -122,10 +93,9 @@ bool ParameterizedType::DoTraverse(DataDepVisitor* visitor)
|
|||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ParameterizedType::RequiresAnalyzerContext()
|
||||
{
|
||||
bool ParameterizedType::RequiresAnalyzerContext() {
|
||||
if ( checking_requires_analyzer_context_ )
|
||||
return false;
|
||||
checking_requires_analyzer_context_ = true;
|
||||
|
@ -133,15 +103,13 @@ bool ParameterizedType::RequiresAnalyzerContext()
|
|||
bool ret = false;
|
||||
// If any argument expression refers to analyzer context
|
||||
foreach (i, ExprList, args_)
|
||||
if ( (*i)->RequiresAnalyzerContext() )
|
||||
{
|
||||
if ( (*i)->RequiresAnalyzerContext() ) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
ret = ret || Type::RequiresAnalyzerContext();
|
||||
|
||||
if ( ! ret )
|
||||
{
|
||||
if ( ! ret ) {
|
||||
Type* ty = ReferredDataType(false);
|
||||
if ( ty )
|
||||
ret = ty->RequiresAnalyzerContext();
|
||||
|
@ -149,17 +117,15 @@ bool ParameterizedType::RequiresAnalyzerContext()
|
|||
|
||||
checking_requires_analyzer_context_ = false;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void ParameterizedType::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void ParameterizedType::GenInitCode(Output* out_cc, Env* env) {
|
||||
ASSERT(persistent());
|
||||
out_cc->println("%s = nullptr;", env->LValue(value_var()));
|
||||
Type::GenInitCode(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env) {
|
||||
Type* ty = ReferredDataType(false);
|
||||
if ( ty && ty->attr_refcount() )
|
||||
out_cc->println("Unref(%s);", lvalue());
|
||||
|
@ -167,15 +133,13 @@ void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env)
|
|||
out_cc->println("delete %s;", lvalue());
|
||||
out_cc->println("%s = nullptr;", lvalue());
|
||||
Type::GenCleanUpCode(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
string ParameterizedType::EvalParameters(Output* out_cc, Env* env) const
|
||||
{
|
||||
string ParameterizedType::EvalParameters(Output* out_cc, Env* env) const {
|
||||
string arg_str;
|
||||
|
||||
int first = 1;
|
||||
foreach (i, ExprList, args_)
|
||||
{
|
||||
foreach (i, ExprList, args_) {
|
||||
Expr* e = *i;
|
||||
if ( first )
|
||||
first = 0;
|
||||
|
@ -185,16 +149,13 @@ string ParameterizedType::EvalParameters(Output* out_cc, Env* env) const
|
|||
}
|
||||
|
||||
return arg_str;
|
||||
}
|
||||
}
|
||||
|
||||
void ParameterizedType::GenNewInstance(Output* out_cc, Env* env)
|
||||
{
|
||||
out_cc->println("%s = new %s(%s);", lvalue(), type_id_->Name(),
|
||||
EvalParameters(out_cc, env).c_str());
|
||||
}
|
||||
void ParameterizedType::GenNewInstance(Output* out_cc, Env* env) {
|
||||
out_cc->println("%s = new %s(%s);", lvalue(), type_id_->Name(), EvalParameters(out_cc, env).c_str());
|
||||
}
|
||||
|
||||
void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
|
||||
{
|
||||
void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) {
|
||||
DEBUG_MSG("DoGenParseCode for %s\n", type_id_->Name());
|
||||
|
||||
Type* ref_type = ReferredDataType(true);
|
||||
|
@ -202,30 +163,25 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr&
|
|||
const char* parse_func;
|
||||
string parse_params;
|
||||
|
||||
if ( buffer_mode() == BUFFER_NOTHING )
|
||||
{
|
||||
if ( buffer_mode() == BUFFER_NOTHING ) {
|
||||
ASSERT(! ref_type->incremental_input());
|
||||
parse_func = kParseFuncWithoutBuffer;
|
||||
parse_params = "nullptr, nullptr";
|
||||
}
|
||||
else if ( ref_type->incremental_input() )
|
||||
{
|
||||
else if ( ref_type->incremental_input() ) {
|
||||
parse_func = kParseFuncWithBuffer;
|
||||
parse_params = env->RValue(flow_buffer_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
parse_func = kParseFuncWithoutBuffer;
|
||||
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));
|
||||
}
|
||||
|
||||
if ( ref_type->RequiresByteOrder() )
|
||||
{
|
||||
if ( ref_type->RequiresByteOrder() ) {
|
||||
env->Evaluate(out_cc, 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
|
||||
parse_func, parse_params.c_str());
|
||||
|
||||
if ( incremental_input() )
|
||||
{
|
||||
if ( buffer_mode() == BUFFER_NOTHING )
|
||||
{
|
||||
if ( incremental_input() ) {
|
||||
if ( buffer_mode() == BUFFER_NOTHING ) {
|
||||
out_cc->println("%s;", call_parse_func.c_str());
|
||||
out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
ASSERT(parsing_complete_var());
|
||||
out_cc->println("%s = %s;", env->LValue(parsing_complete_var()),
|
||||
call_parse_func.c_str());
|
||||
out_cc->println("%s = %s;", env->LValue(parsing_complete_var()), call_parse_func.c_str());
|
||||
|
||||
// parsing_complete_var might have been already
|
||||
// evaluated when set to false
|
||||
|
@ -253,21 +205,17 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr&
|
|||
env->SetEvaluated(parsing_complete_var());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( AddSizeVar(out_cc, env) )
|
||||
{
|
||||
else {
|
||||
if ( AddSizeVar(out_cc, env) ) {
|
||||
out_cc->println("%s = %s;", env->LValue(size_var()), call_parse_func.c_str());
|
||||
env->SetEvaluated(size_var());
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include "pac_type.h"
|
||||
|
||||
// An instantiated type: ID + expression list
|
||||
class ParameterizedType : public Type
|
||||
{
|
||||
class ParameterizedType : public Type {
|
||||
public:
|
||||
ParameterizedType(ID* type_id, ExprList* args);
|
||||
~ParameterizedType() override;
|
||||
|
@ -56,6 +55,6 @@ private:
|
|||
|
||||
void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) override;
|
||||
void GenDynamicSize(Output* out, Env* env, const DataPtr& data) override;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_paramtype_h
|
||||
|
|
|
@ -5,30 +5,26 @@
|
|||
#include "pac_id.h"
|
||||
#include "pac_type.h"
|
||||
|
||||
string PPVal::ToCode(Env* env)
|
||||
{
|
||||
string PPVal::ToCode(Env* env) {
|
||||
ASSERT(expr_);
|
||||
return string(expr_->EvalExpr(nullptr, env));
|
||||
}
|
||||
}
|
||||
|
||||
string PPSet::ToCode(Env* env)
|
||||
{
|
||||
string PPSet::ToCode(Env* env) {
|
||||
ASSERT(expr_);
|
||||
return expr_->SetFunc(nullptr, env);
|
||||
}
|
||||
}
|
||||
|
||||
string PPType::ToCode(Env* env)
|
||||
{
|
||||
string PPType::ToCode(Env* env) {
|
||||
Type* type = expr_->DataType(env);
|
||||
return type->DataTypeStr();
|
||||
}
|
||||
}
|
||||
|
||||
string PPConstDef::ToCode(Env* env)
|
||||
{
|
||||
string PPConstDef::ToCode(Env* env) {
|
||||
Type* type = expr_->DataType(env);
|
||||
env->AddID(id_, TEMP_VAR, type);
|
||||
env->SetEvaluated(id_);
|
||||
|
||||
string type_str = type->DataTypeStr();
|
||||
return strfmt("%s %s = %s", type_str.c_str(), env->LValue(id_), expr_->EvalExpr(nullptr, env));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,19 +3,12 @@
|
|||
|
||||
#include "pac_common.h"
|
||||
|
||||
class PacPrimitive
|
||||
{
|
||||
class PacPrimitive {
|
||||
public:
|
||||
enum PrimitiveType
|
||||
{
|
||||
VAL,
|
||||
SET,
|
||||
TYPE,
|
||||
CONST_DEF
|
||||
};
|
||||
enum PrimitiveType { VAL, SET, TYPE, CONST_DEF };
|
||||
|
||||
explicit PacPrimitive(PrimitiveType type) : type_(type) { }
|
||||
virtual ~PacPrimitive() { }
|
||||
explicit PacPrimitive(PrimitiveType type) : type_(type) {}
|
||||
virtual ~PacPrimitive() {}
|
||||
|
||||
PrimitiveType type() const { return type_; }
|
||||
|
||||
|
@ -23,48 +16,44 @@ public:
|
|||
|
||||
private:
|
||||
PrimitiveType type_;
|
||||
};
|
||||
};
|
||||
|
||||
class PPVal : public PacPrimitive
|
||||
{
|
||||
class PPVal : public PacPrimitive {
|
||||
public:
|
||||
PPVal(Expr* expr) : PacPrimitive(VAL), expr_(expr) { }
|
||||
PPVal(Expr* expr) : PacPrimitive(VAL), expr_(expr) {}
|
||||
Expr* expr() const { return expr_; }
|
||||
|
||||
string ToCode(Env* env) override;
|
||||
|
||||
private:
|
||||
Expr* expr_;
|
||||
};
|
||||
};
|
||||
|
||||
class PPSet : public PacPrimitive
|
||||
{
|
||||
class PPSet : public PacPrimitive {
|
||||
public:
|
||||
PPSet(Expr* expr) : PacPrimitive(SET), expr_(expr) { }
|
||||
PPSet(Expr* expr) : PacPrimitive(SET), expr_(expr) {}
|
||||
Expr* expr() const { return expr_; }
|
||||
|
||||
string ToCode(Env* env) override;
|
||||
|
||||
private:
|
||||
Expr* expr_;
|
||||
};
|
||||
};
|
||||
|
||||
class PPType : public PacPrimitive
|
||||
{
|
||||
class PPType : public PacPrimitive {
|
||||
public:
|
||||
PPType(Expr* expr) : PacPrimitive(TYPE), expr_(expr) { }
|
||||
PPType(Expr* expr) : PacPrimitive(TYPE), expr_(expr) {}
|
||||
Expr* expr() const { return expr_; }
|
||||
|
||||
string ToCode(Env* env) override;
|
||||
|
||||
private:
|
||||
Expr* expr_;
|
||||
};
|
||||
};
|
||||
|
||||
class PPConstDef : public PacPrimitive
|
||||
{
|
||||
class PPConstDef : public PacPrimitive {
|
||||
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_; }
|
||||
Expr* expr() const { return expr_; }
|
||||
|
||||
|
@ -73,6 +62,6 @@ public:
|
|||
private:
|
||||
const ID* id_;
|
||||
Expr* expr_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_primitive_h
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
#include "pac_utils.h"
|
||||
#include "pac_varfield.h"
|
||||
|
||||
RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD)
|
||||
{
|
||||
RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD) {
|
||||
// Here we assume that the type is a standalone type.
|
||||
value_var_ = nullptr;
|
||||
|
||||
|
@ -25,49 +24,40 @@ RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD)
|
|||
record_fields_ = record_fields;
|
||||
|
||||
parsing_dataptr_var_field_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RecordType::~RecordType()
|
||||
{
|
||||
RecordType::~RecordType() {
|
||||
// Do not delete_list(RecordFieldList, record_fields_)
|
||||
// because the fields are also in fields_.
|
||||
delete record_fields_;
|
||||
delete parsing_dataptr_var_field_;
|
||||
}
|
||||
}
|
||||
|
||||
const ID* RecordType::parsing_dataptr_var() const
|
||||
{
|
||||
const ID* RecordType::parsing_dataptr_var() const {
|
||||
return parsing_dataptr_var_field_ ? parsing_dataptr_var_field_->id() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordType::DefineValueVar() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool RecordType::DefineValueVar() const { return false; }
|
||||
|
||||
string RecordType::DataTypeStr() const
|
||||
{
|
||||
string RecordType::DataTypeStr() const {
|
||||
ASSERT(type_decl());
|
||||
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);
|
||||
|
||||
RecordField* prev = nullptr;
|
||||
int offset = 0;
|
||||
int seq = 0;
|
||||
foreach (i, RecordFieldList, record_fields_)
|
||||
{
|
||||
foreach (i, RecordFieldList, record_fields_) {
|
||||
RecordField* f = *i;
|
||||
f->set_record_type(this);
|
||||
f->set_prev(prev);
|
||||
if ( prev )
|
||||
prev->set_next(f);
|
||||
prev = f;
|
||||
if ( offset >= 0 )
|
||||
{
|
||||
if ( offset >= 0 ) {
|
||||
f->set_static_offset(offset);
|
||||
int w = f->StaticSize(env, offset);
|
||||
if ( w < 0 )
|
||||
|
@ -79,8 +69,7 @@ void RecordType::Prepare(Env* env, int flags)
|
|||
f->set_parsing_state_seq(seq);
|
||||
}
|
||||
|
||||
if ( incremental_parsing() )
|
||||
{
|
||||
if ( incremental_parsing() ) {
|
||||
#if 0
|
||||
ASSERT(! parsing_state_var_field_);
|
||||
ID *parsing_state_var_id = new ID("parsing_state");
|
||||
|
@ -96,41 +85,26 @@ void RecordType::Prepare(Env* env, int flags)
|
|||
}
|
||||
|
||||
Type::Prepare(env, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void RecordType::GenPubDecls(Output* out_h, Env* env)
|
||||
{
|
||||
Type::GenPubDecls(out_h, env);
|
||||
}
|
||||
void RecordType::GenPubDecls(Output* out_h, Env* env) { Type::GenPubDecls(out_h, env); }
|
||||
|
||||
void RecordType::GenPrivDecls(Output* out_h, Env* env)
|
||||
{
|
||||
Type::GenPrivDecls(out_h, env);
|
||||
}
|
||||
void RecordType::GenPrivDecls(Output* out_h, Env* env) { Type::GenPrivDecls(out_h, env); }
|
||||
|
||||
void RecordType::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
Type::GenInitCode(out_cc, env);
|
||||
}
|
||||
void RecordType::GenInitCode(Output* out_cc, Env* env) { Type::GenInitCode(out_cc, env); }
|
||||
|
||||
void RecordType::GenCleanUpCode(Output* out_cc, Env* env)
|
||||
{
|
||||
Type::GenCleanUpCode(out_cc, env);
|
||||
}
|
||||
void RecordType::GenCleanUpCode(Output* out_cc, Env* env) { Type::GenCleanUpCode(out_cc, env); }
|
||||
|
||||
void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
|
||||
{
|
||||
void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) {
|
||||
if ( ! incremental_input() && StaticSize(env) >= 0 )
|
||||
GenBoundaryCheck(out_cc, env, data);
|
||||
|
||||
if ( incremental_parsing() )
|
||||
{
|
||||
if ( incremental_parsing() ) {
|
||||
out_cc->println("switch ( %s ) {", env->LValue(parsing_state_id));
|
||||
|
||||
out_cc->println("case 0:");
|
||||
out_cc->inc_indent();
|
||||
foreach (i, RecordFieldList, record_fields_)
|
||||
{
|
||||
foreach (i, RecordFieldList, record_fields_) {
|
||||
RecordField* f = *i;
|
||||
f->GenParseCode(out_cc, env);
|
||||
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->println("}");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
ASSERT(data.id() == begin_of_data && data.offset() == 0);
|
||||
foreach (i, RecordFieldList, record_fields_)
|
||||
{
|
||||
foreach (i, RecordFieldList, record_fields_) {
|
||||
RecordField* f = *i;
|
||||
f->GenParseCode(out_cc, env);
|
||||
out_cc->println("");
|
||||
}
|
||||
if ( incremental_input() )
|
||||
{
|
||||
if ( incremental_input() ) {
|
||||
ASSERT(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);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
if ( ! boundary_checked() )
|
||||
{
|
||||
if ( ! boundary_checked() ) {
|
||||
RecordField* last_field = record_fields_->back();
|
||||
if ( ! last_field->BoundaryChecked() )
|
||||
GenBoundaryCheck(out_cc, env, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RecordType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
|
||||
{
|
||||
GenParseCode(out_cc, env, data, 0);
|
||||
}
|
||||
void RecordType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) { GenParseCode(out_cc, env, data, 0); }
|
||||
|
||||
int RecordType::StaticSize(Env* env) const
|
||||
{
|
||||
int RecordType::StaticSize(Env* env) const {
|
||||
int tot_w = 0;
|
||||
foreach (i, RecordFieldList, record_fields_)
|
||||
{
|
||||
foreach (i, RecordFieldList, record_fields_) {
|
||||
RecordField* f = *i;
|
||||
int w = f->StaticSize(env, tot_w);
|
||||
if ( w < 0 )
|
||||
|
@ -190,10 +154,9 @@ int RecordType::StaticSize(Env* env) const
|
|||
tot_w += w;
|
||||
}
|
||||
return tot_w;
|
||||
}
|
||||
}
|
||||
|
||||
void RecordType::SetBoundaryChecked()
|
||||
{
|
||||
void RecordType::SetBoundaryChecked() {
|
||||
Type::SetBoundaryChecked();
|
||||
|
||||
if ( StaticSize(env()) < 0 || attr_length_expr_ )
|
||||
|
@ -202,41 +165,32 @@ void RecordType::SetBoundaryChecked()
|
|||
// (whose value is not necessarily trustworthy).
|
||||
return;
|
||||
|
||||
foreach (i, RecordFieldList, record_fields_)
|
||||
{
|
||||
foreach (i, RecordFieldList, record_fields_) {
|
||||
RecordField* f = *i;
|
||||
f->SetBoundaryChecked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RecordType::DoMarkIncrementalInput()
|
||||
{
|
||||
foreach (i, RecordFieldList, record_fields_)
|
||||
{
|
||||
void RecordType::DoMarkIncrementalInput() {
|
||||
foreach (i, RecordFieldList, record_fields_) {
|
||||
RecordField* f = *i;
|
||||
f->type()->MarkIncrementalInput();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordType::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
return Type::DoTraverse(visitor);
|
||||
}
|
||||
bool RecordType::DoTraverse(DataDepVisitor* visitor) { return Type::DoTraverse(visitor); }
|
||||
|
||||
bool RecordType::ByteOrderSensitive() const
|
||||
{
|
||||
foreach (i, RecordFieldList, record_fields_)
|
||||
{
|
||||
bool RecordType::ByteOrderSensitive() const {
|
||||
foreach (i, RecordFieldList, record_fields_) {
|
||||
RecordField* f = *i;
|
||||
if ( f->RequiresByteOrder() )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RecordField::RecordField(FieldType tof, ID* id, Type* type)
|
||||
: Field(tof, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type)
|
||||
{
|
||||
: Field(tof, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) {
|
||||
begin_of_field_dataptr = nullptr;
|
||||
end_of_field_dataptr = nullptr;
|
||||
field_size_expr = nullptr;
|
||||
|
@ -248,52 +202,44 @@ RecordField::RecordField(FieldType tof, ID* id, Type* type)
|
|||
static_offset_ = -1;
|
||||
parsing_state_seq_ = 0;
|
||||
boundary_checked_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
RecordField::~RecordField()
|
||||
{
|
||||
RecordField::~RecordField() {
|
||||
delete begin_of_field_dataptr;
|
||||
delete end_of_field_dataptr;
|
||||
delete[] field_size_expr;
|
||||
delete[] field_offset_expr;
|
||||
delete end_of_field_dataptr_var;
|
||||
}
|
||||
}
|
||||
|
||||
const DataPtr& RecordField::getFieldBegin(Output* out_cc, Env* env)
|
||||
{
|
||||
const DataPtr& RecordField::getFieldBegin(Output* out_cc, Env* env) {
|
||||
if ( prev() )
|
||||
return prev()->getFieldEnd(out_cc, env);
|
||||
else
|
||||
{
|
||||
else {
|
||||
// The first field
|
||||
if ( ! begin_of_field_dataptr )
|
||||
{
|
||||
if ( ! begin_of_field_dataptr ) {
|
||||
begin_of_field_dataptr = new DataPtr(env, begin_of_data, 0);
|
||||
}
|
||||
return *begin_of_field_dataptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env)
|
||||
{
|
||||
const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env) {
|
||||
if ( end_of_field_dataptr )
|
||||
return *end_of_field_dataptr;
|
||||
|
||||
const DataPtr& begin_ptr = getFieldBegin(out_cc, env);
|
||||
|
||||
if ( record_type()->incremental_parsing() )
|
||||
{
|
||||
if ( record_type()->incremental_parsing() ) {
|
||||
ASSERT(0);
|
||||
if ( ! end_of_field_dataptr )
|
||||
{
|
||||
if ( ! end_of_field_dataptr ) {
|
||||
const ID* dataptr_var = record_type()->parsing_dataptr_var();
|
||||
ASSERT(dataptr_var);
|
||||
|
||||
end_of_field_dataptr = new DataPtr(env, dataptr_var, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
int field_offset;
|
||||
if ( begin_ptr.id() == begin_of_data )
|
||||
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);
|
||||
if ( field_size >= 0 ) // can be statically determinted
|
||||
{
|
||||
end_of_field_dataptr = new DataPtr(env, begin_ptr.id(),
|
||||
begin_ptr.offset() + field_size);
|
||||
end_of_field_dataptr = new DataPtr(env, begin_ptr.id(), begin_ptr.offset() + field_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// If not, we add a variable for the offset after the field
|
||||
end_of_field_dataptr_var = new ID(strfmt("dataptr_after_%s", id()->Name()));
|
||||
env->AddID(end_of_field_dataptr_var, TEMP_VAR, extern_type_const_byteptr);
|
||||
|
@ -319,10 +263,9 @@ const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env)
|
|||
}
|
||||
|
||||
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 )
|
||||
return field_size_expr;
|
||||
|
||||
|
@ -333,10 +276,9 @@ const char* RecordField::FieldSize(Output* out_cc, Env* env)
|
|||
else
|
||||
field_size_expr = nfmt("(%s - %s)", end.ptr_expr(), begin.ptr_expr());
|
||||
return field_size_expr;
|
||||
}
|
||||
}
|
||||
|
||||
const char* RecordField::FieldOffset(Output* out_cc, Env* env)
|
||||
{
|
||||
const char* RecordField::FieldOffset(Output* out_cc, Env* env) {
|
||||
if ( field_offset_expr )
|
||||
return field_offset_expr;
|
||||
|
||||
|
@ -346,13 +288,12 @@ const char* RecordField::FieldOffset(Output* out_cc, Env* env)
|
|||
else
|
||||
field_offset_expr = nfmt("(%s - %s)", begin.ptr_expr(), env->RValue(begin_of_data));
|
||||
return field_offset_expr;
|
||||
}
|
||||
}
|
||||
|
||||
// The reasoning behind AttemptBoundaryCheck is: "If my next field
|
||||
// can check its boundary, then I don't have to check mine, and it
|
||||
// will save me a boundary-check."
|
||||
bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env)
|
||||
{
|
||||
bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env) {
|
||||
if ( boundary_checked_ )
|
||||
return true;
|
||||
|
||||
|
@ -364,8 +305,7 @@ bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env)
|
|||
return false;
|
||||
|
||||
// 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
|
||||
SetBoundaryChecked();
|
||||
return true;
|
||||
|
@ -373,24 +313,19 @@ bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env)
|
|||
else
|
||||
// If it fails, then I can still try to do it by myself
|
||||
return GenBoundaryCheck(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
RecordDataField::RecordDataField(ID* id, Type* type) : RecordField(RECORD_FIELD, id, type)
|
||||
{
|
||||
ASSERT(type_);
|
||||
}
|
||||
RecordDataField::RecordDataField(ID* id, Type* type) : RecordField(RECORD_FIELD, id, type) { ASSERT(type_); }
|
||||
|
||||
RecordDataField::~RecordDataField() { }
|
||||
RecordDataField::~RecordDataField() {}
|
||||
|
||||
void RecordDataField::Prepare(Env* env)
|
||||
{
|
||||
void RecordDataField::Prepare(Env* env) {
|
||||
Field::Prepare(env);
|
||||
env->SetEvalMethod(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()) )
|
||||
return;
|
||||
|
||||
|
@ -400,8 +335,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
|
|||
prev()->GenParseCode(out_cc, env);
|
||||
|
||||
DataPtr data(env, nullptr, 0);
|
||||
if ( ! record_type()->incremental_parsing() )
|
||||
{
|
||||
if ( ! record_type()->incremental_parsing() ) {
|
||||
data = getFieldBegin(out_cc, env);
|
||||
|
||||
Expr* len_expr = record_type()->attr_length_expr();
|
||||
|
@ -417,8 +351,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
|
|||
id_->Name());
|
||||
#endif
|
||||
type_->GenPreParsing(out_cc, env);
|
||||
if ( type_->incremental_input() )
|
||||
{
|
||||
if ( type_->incremental_input() ) {
|
||||
// The enclosing record type must be incrementally parsed
|
||||
out_cc->println("%s = %d;", env->LValue(parsing_state_id), parsing_state_seq());
|
||||
out_cc->println("/* fall through */");
|
||||
|
@ -430,8 +363,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
|
|||
|
||||
type_->GenParseCode(out_cc, env, data, 0);
|
||||
|
||||
if ( record_type()->incremental_parsing() )
|
||||
{
|
||||
if ( record_type()->incremental_parsing() ) {
|
||||
ASSERT(type_->incremental_input());
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if ( record_type()->incremental_parsing() )
|
||||
{
|
||||
if ( record_type()->incremental_parsing() ) {
|
||||
#if 0
|
||||
const ID *dataptr_var =
|
||||
record_type()->parsing_dataptr_var();
|
||||
|
@ -454,31 +385,24 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
|
|||
}
|
||||
|
||||
SetBoundaryChecked();
|
||||
}
|
||||
}
|
||||
|
||||
void RecordDataField::GenEval(Output* out_cc, Env* env)
|
||||
{
|
||||
GenParseCode(out_cc, env);
|
||||
}
|
||||
void RecordDataField::GenEval(Output* out_cc, Env* env) { GenParseCode(out_cc, env); }
|
||||
|
||||
void RecordDataField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin)
|
||||
{
|
||||
void RecordDataField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin) {
|
||||
out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var),
|
||||
field_begin.ptr_expr(), type_->DataSize(out_cc, env, field_begin).c_str());
|
||||
env->SetEvaluated(end_of_field_dataptr_var);
|
||||
|
||||
out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(end_of_field_dataptr_var),
|
||||
env->RValue(end_of_data));
|
||||
}
|
||||
out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(end_of_field_dataptr_var), env->RValue(end_of_data));
|
||||
}
|
||||
|
||||
void RecordDataField::SetBoundaryChecked()
|
||||
{
|
||||
void RecordDataField::SetBoundaryChecked() {
|
||||
RecordField::SetBoundaryChecked();
|
||||
type_->SetBoundaryChecked();
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env)
|
||||
{
|
||||
bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env) {
|
||||
if ( boundary_checked_ )
|
||||
return true;
|
||||
|
||||
|
@ -486,54 +410,43 @@ bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env)
|
|||
|
||||
SetBoundaryChecked();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordDataField::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
return Field::DoTraverse(visitor);
|
||||
}
|
||||
bool RecordDataField::DoTraverse(DataDepVisitor* visitor) { return Field::DoTraverse(visitor); }
|
||||
|
||||
bool RecordDataField::RequiresAnalyzerContext() const
|
||||
{
|
||||
bool RecordDataField::RequiresAnalyzerContext() const {
|
||||
return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext();
|
||||
}
|
||||
}
|
||||
|
||||
RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr)
|
||||
: RecordField(PADDING_FIELD, id, nullptr), ptype_(ptype), expr_(expr)
|
||||
{
|
||||
: RecordField(PADDING_FIELD, id, nullptr), ptype_(ptype), expr_(expr) {
|
||||
wordsize_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
RecordPaddingField::~RecordPaddingField() { }
|
||||
RecordPaddingField::~RecordPaddingField() {}
|
||||
|
||||
void RecordPaddingField::Prepare(Env* env)
|
||||
{
|
||||
void RecordPaddingField::Prepare(Env* env) {
|
||||
Field::Prepare(env);
|
||||
if ( ptype_ == PAD_TO_NEXT_WORD )
|
||||
{
|
||||
if ( ptype_ == PAD_TO_NEXT_WORD ) {
|
||||
if ( ! expr_->ConstFold(env, &wordsize_) )
|
||||
throw ExceptionPaddingError(this, strfmt("padding word size not a constant"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RecordPaddingField::GenParseCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void RecordPaddingField::GenParseCode(Output* out_cc, Env* env) {
|
||||
// Always evaluate record fields in order if parsing
|
||||
// is incremental.
|
||||
if ( record_type()->incremental_parsing() && prev() )
|
||||
prev()->GenParseCode(out_cc, env);
|
||||
}
|
||||
}
|
||||
|
||||
int RecordPaddingField::StaticSize(Env* env, int offset) const
|
||||
{
|
||||
int RecordPaddingField::StaticSize(Env* env, int offset) const {
|
||||
int length;
|
||||
int target_offset;
|
||||
int offset_in_word;
|
||||
|
||||
switch ( ptype_ )
|
||||
{
|
||||
case PAD_BY_LENGTH:
|
||||
return expr_->ConstFold(env, &length) ? length : -1;
|
||||
switch ( ptype_ ) {
|
||||
case PAD_BY_LENGTH: return expr_->ConstFold(env, &length) ? length : -1;
|
||||
|
||||
case PAD_TO_OFFSET:
|
||||
// If the current offset cannot be statically
|
||||
|
@ -563,18 +476,15 @@ int RecordPaddingField::StaticSize(Env* env, int offset) const
|
|||
}
|
||||
|
||||
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));
|
||||
|
||||
char* padding_var;
|
||||
switch ( ptype_ )
|
||||
{
|
||||
switch ( ptype_ ) {
|
||||
case PAD_BY_LENGTH:
|
||||
out_cc->println("if ( (%s) < 0 ) // check for negative pad length",
|
||||
expr_->EvalExpr(out_cc, env));
|
||||
out_cc->println("if ( (%s) < 0 ) // check for negative pad length", expr_->EvalExpr(out_cc, env));
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(),
|
||||
|
@ -583,20 +493,17 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi
|
|||
out_cc->dec_indent();
|
||||
out_cc->println("");
|
||||
|
||||
out_cc->println("const_byteptr const %s = %s + (%s);",
|
||||
env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(),
|
||||
expr_->EvalExpr(out_cc, env));
|
||||
out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var),
|
||||
field_begin.ptr_expr(), expr_->EvalExpr(out_cc, env));
|
||||
|
||||
out_cc->println("// Checking out-of-bound padding for \"%s\"", field_id_str_.c_str());
|
||||
out_cc->println("if ( %s > %s || %s < %s )", env->LValue(end_of_field_dataptr_var),
|
||||
env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var),
|
||||
field_begin.ptr_expr());
|
||||
env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr());
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str());
|
||||
out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env));
|
||||
out_cc->println(" (%s) - (%s));", env->RValue(end_of_data),
|
||||
env->LValue(end_of_field_dataptr_var));
|
||||
out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var));
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
out_cc->println("");
|
||||
|
@ -605,25 +512,20 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi
|
|||
case PAD_TO_OFFSET:
|
||||
out_cc->println("const_byteptr %s = %s + (%s);", env->LValue(end_of_field_dataptr_var),
|
||||
env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env));
|
||||
out_cc->println("if ( %s < %s )", env->LValue(end_of_field_dataptr_var),
|
||||
field_begin.ptr_expr());
|
||||
out_cc->println("if ( %s < %s )", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr());
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);",
|
||||
id_->LocName(), field_begin.ptr_expr(), env->RValue(begin_of_data),
|
||||
expr_->EvalExpr(out_cc, env));
|
||||
out_cc->println("%s = %s;", env->LValue(end_of_field_dataptr_var),
|
||||
field_begin.ptr_expr());
|
||||
out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);", id_->LocName(),
|
||||
field_begin.ptr_expr(), env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env));
|
||||
out_cc->println("%s = %s;", env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr());
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
out_cc->println("if ( %s > %s )", env->LValue(end_of_field_dataptr_var),
|
||||
env->RValue(end_of_data));
|
||||
out_cc->println("if ( %s > %s )", env->LValue(end_of_field_dataptr_var), env->RValue(end_of_data));
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str());
|
||||
out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env));
|
||||
out_cc->println(" (%s) - (%s));", env->RValue(end_of_data),
|
||||
env->LValue(end_of_field_dataptr_var));
|
||||
out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var));
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
break;
|
||||
|
@ -632,20 +534,17 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi
|
|||
padding_var = nfmt("%s__size", id()->Name());
|
||||
out_cc->println("int %s = (%s - %s) %% %d;", padding_var, field_begin.ptr_expr(),
|
||||
env->RValue(begin_of_data), wordsize_);
|
||||
out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", padding_var, padding_var, wordsize_,
|
||||
padding_var);
|
||||
out_cc->println("const_byteptr const %s = %s + %s;",
|
||||
env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(),
|
||||
padding_var);
|
||||
out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", padding_var, padding_var, wordsize_, padding_var);
|
||||
out_cc->println("const_byteptr const %s = %s + %s;", env->LValue(end_of_field_dataptr_var),
|
||||
field_begin.ptr_expr(), padding_var);
|
||||
delete[] padding_var;
|
||||
break;
|
||||
}
|
||||
|
||||
env->SetEvaluated(end_of_field_dataptr_var);
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env)
|
||||
{
|
||||
bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env) {
|
||||
if ( boundary_checked_ )
|
||||
return true;
|
||||
|
||||
|
@ -662,9 +561,8 @@ bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env)
|
|||
|
||||
SetBoundaryChecked();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordPaddingField::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
bool RecordPaddingField::DoTraverse(DataDepVisitor* visitor) {
|
||||
return Field::DoTraverse(visitor) && (! expr_ || expr_->Traverse(visitor));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
#include "pac_let.h"
|
||||
#include "pac_type.h"
|
||||
|
||||
class RecordType : public Type
|
||||
{
|
||||
class RecordType : public Type {
|
||||
public:
|
||||
RecordType(RecordFieldList* fields);
|
||||
~RecordType() override;
|
||||
|
@ -30,8 +29,7 @@ public:
|
|||
|
||||
const ID* parsing_dataptr_var() const;
|
||||
|
||||
bool IsPointerType() const override
|
||||
{
|
||||
bool IsPointerType() const override {
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
@ -50,14 +48,13 @@ protected:
|
|||
private:
|
||||
Field* parsing_dataptr_var_field_;
|
||||
RecordFieldList* record_fields_;
|
||||
};
|
||||
};
|
||||
|
||||
// A data field of a record type. A RecordField corresponds to a
|
||||
// segment of input data, and therefore RecordField's are ordered---each
|
||||
// of them has a known previous and next field.
|
||||
|
||||
class RecordField : public Field
|
||||
{
|
||||
class RecordField : public Field {
|
||||
public:
|
||||
RecordField(FieldType tof, ID* id, Type* type);
|
||||
~RecordField() override;
|
||||
|
@ -109,10 +106,9 @@ protected:
|
|||
|
||||
bool AttemptBoundaryCheck(Output* out_cc, Env* env);
|
||||
virtual bool GenBoundaryCheck(Output* out_cc, Env* env) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
class RecordDataField : public RecordField, public Evaluatable
|
||||
{
|
||||
class RecordDataField : public RecordField, public Evaluatable {
|
||||
public:
|
||||
RecordDataField(ID* arg_id, Type* arg_type);
|
||||
~RecordDataField() override;
|
||||
|
@ -135,35 +131,25 @@ protected:
|
|||
void GenFieldEnd(Output* out, Env* env, const DataPtr& begin) override;
|
||||
bool GenBoundaryCheck(Output* out_cc, Env* env) override;
|
||||
bool DoTraverse(DataDepVisitor* visitor) override;
|
||||
};
|
||||
};
|
||||
|
||||
enum PaddingType
|
||||
{
|
||||
PAD_BY_LENGTH,
|
||||
PAD_TO_OFFSET,
|
||||
PAD_TO_NEXT_WORD
|
||||
};
|
||||
enum PaddingType { PAD_BY_LENGTH, PAD_TO_OFFSET, PAD_TO_NEXT_WORD };
|
||||
|
||||
class RecordPaddingField : public RecordField
|
||||
{
|
||||
class RecordPaddingField : public RecordField {
|
||||
public:
|
||||
RecordPaddingField(ID* id, PaddingType ptype, Expr* expr);
|
||||
~RecordPaddingField() override;
|
||||
|
||||
void Prepare(Env* env) override;
|
||||
|
||||
void GenPubDecls(Output* out, Env* env) override
|
||||
{ /* nothing */
|
||||
void GenPubDecls(Output* out, Env* env) override { /* nothing */
|
||||
}
|
||||
void GenPrivDecls(Output* out, Env* env) override
|
||||
{ /* nothing */
|
||||
void GenPrivDecls(Output* out, Env* env) override { /* nothing */
|
||||
}
|
||||
|
||||
void GenInitCode(Output* out, Env* env) override
|
||||
{ /* nothing */
|
||||
void GenInitCode(Output* out, Env* env) override { /* nothing */
|
||||
}
|
||||
void GenCleanUpCode(Output* out, Env* env) override
|
||||
{ /* nothing */
|
||||
void GenCleanUpCode(Output* out, Env* env) override { /* nothing */
|
||||
}
|
||||
void GenParseCode(Output* out, Env* env) override;
|
||||
|
||||
|
@ -180,6 +166,6 @@ private:
|
|||
PaddingType ptype_;
|
||||
Expr* expr_;
|
||||
int wordsize_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_record_h
|
||||
|
|
|
@ -9,28 +9,23 @@
|
|||
#include "pac_type.h"
|
||||
#include "pac_typedecl.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
|
||||
Decl* find_decl(const ID* id)
|
||||
{
|
||||
Decl* find_decl(const ID* id) {
|
||||
Decl* decl = Decl::LookUpDecl(id);
|
||||
if ( ! decl )
|
||||
{
|
||||
if ( ! decl ) {
|
||||
throw Exception(id, strfmt("cannot find declaration for %s", id->Name()));
|
||||
}
|
||||
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Decl* ProcessTypeRedef(const ID* id, FieldList* fieldlist)
|
||||
{
|
||||
Decl* ProcessTypeRedef(const ID* id, FieldList* fieldlist) {
|
||||
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()));
|
||||
}
|
||||
|
||||
|
@ -38,35 +33,29 @@ Decl* ProcessTypeRedef(const ID* id, FieldList* fieldlist)
|
|||
ASSERT(type_decl);
|
||||
Type* type = type_decl->type();
|
||||
|
||||
foreach (i, FieldList, fieldlist)
|
||||
{
|
||||
foreach (i, FieldList, fieldlist) {
|
||||
Field* f = *i;
|
||||
|
||||
// One cannot change data layout in 'redef'.
|
||||
// Only 'let' or 'action' can be added
|
||||
if ( f->tof() == LET_FIELD || f->tof() == WITHINPUT_FIELD )
|
||||
{
|
||||
if ( f->tof() == LET_FIELD || f->tof() == WITHINPUT_FIELD ) {
|
||||
type->AddField(f);
|
||||
}
|
||||
else if ( f->tof() == RECORD_FIELD || f->tof() == PADDING_FIELD )
|
||||
{
|
||||
else if ( f->tof() == RECORD_FIELD || f->tof() == PADDING_FIELD ) {
|
||||
throw Exception(f, "cannot change data layout in redef");
|
||||
}
|
||||
else if ( f->tof() == CASE_FIELD )
|
||||
{
|
||||
else if ( f->tof() == CASE_FIELD ) {
|
||||
throw Exception(f, "use 'redef case' adding cases");
|
||||
}
|
||||
}
|
||||
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
|
||||
Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist)
|
||||
{
|
||||
Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist) {
|
||||
Decl* decl = find_decl(id);
|
||||
|
||||
if ( decl->decl_type() != Decl::TYPE )
|
||||
{
|
||||
if ( decl->decl_type() != Decl::TYPE ) {
|
||||
throw Exception(id, strfmt("not a type declaration: %s", id->Name()));
|
||||
}
|
||||
|
||||
|
@ -74,29 +63,25 @@ Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist)
|
|||
ASSERT(type_decl);
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
CaseType* casetype = static_cast<CaseType*>(type);
|
||||
ASSERT(casetype);
|
||||
|
||||
foreach (i, CaseFieldList, casefieldlist)
|
||||
{
|
||||
foreach (i, CaseFieldList, casefieldlist) {
|
||||
CaseField* f = *i;
|
||||
casetype->AddCaseField(f);
|
||||
}
|
||||
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
|
||||
Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist)
|
||||
{
|
||||
Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist) {
|
||||
Decl* decl = find_decl(id);
|
||||
|
||||
if ( decl->decl_type() != Decl::FUNC )
|
||||
{
|
||||
if ( decl->decl_type() != Decl::FUNC ) {
|
||||
throw Exception(id, strfmt("not a function declaration: %s", id->Name()));
|
||||
}
|
||||
|
||||
|
@ -104,26 +89,22 @@ Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist)
|
|||
ASSERT(func_decl);
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
foreach (i, CaseExprList, caseexprlist)
|
||||
{
|
||||
foreach (i, CaseExprList, caseexprlist) {
|
||||
CaseExpr* e = *i;
|
||||
expr->AddCaseExpr(e);
|
||||
}
|
||||
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
|
||||
Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerElementList* elements)
|
||||
{
|
||||
Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerElementList* elements) {
|
||||
Decl* decl = find_decl(id);
|
||||
|
||||
if ( decl->decl_type() != decl_type )
|
||||
{
|
||||
if ( decl->decl_type() != decl_type ) {
|
||||
throw Exception(id, strfmt("not a connection/flow declaration: %s", id->Name()));
|
||||
}
|
||||
|
||||
|
@ -133,14 +114,12 @@ Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerEleme
|
|||
analyzer_decl->AddElements(elements);
|
||||
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
|
||||
Decl* ProcessTypeAttrRedef(const ID* id, AttrList* attrlist)
|
||||
{
|
||||
Decl* ProcessTypeAttrRedef(const ID* id, AttrList* attrlist) {
|
||||
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()));
|
||||
}
|
||||
|
||||
|
@ -150,4 +129,4 @@ Decl* ProcessTypeAttrRedef(const ID* id, AttrList* attrlist)
|
|||
type_decl->AddAttrs(attrlist);
|
||||
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,16 +9,12 @@
|
|||
const char* RegEx::kREMatcherType = "RegExMatcher";
|
||||
const char* RegEx::kMatchPrefix = "MatchPrefix";
|
||||
|
||||
string escape_char(const string& s)
|
||||
{
|
||||
string escape_char(const string& s) {
|
||||
char* buf = new char[s.length() * 2 + 1];
|
||||
int j = 0;
|
||||
for ( int i = 0; i < (int)s.length(); ++i )
|
||||
{
|
||||
if ( s[i] == '\\' )
|
||||
{
|
||||
if ( i + 1 < (int)s.length() )
|
||||
{
|
||||
for ( int i = 0; i < (int)s.length(); ++i ) {
|
||||
if ( s[i] == '\\' ) {
|
||||
if ( i + 1 < (int)s.length() ) {
|
||||
buf[j++] = '\\';
|
||||
if ( s[i + 1] == '/' )
|
||||
buf[j - 1] = s[++i];
|
||||
|
@ -28,13 +24,11 @@ string escape_char(const string& s)
|
|||
buf[j++] = '\\';
|
||||
}
|
||||
}
|
||||
else if ( s[i] == '"' )
|
||||
{
|
||||
else if ( s[i] == '"' ) {
|
||||
buf[j++] = '\\';
|
||||
buf[j++] = '"';
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
buf[j++] = s[i];
|
||||
}
|
||||
}
|
||||
|
@ -44,36 +38,26 @@ string escape_char(const string& s)
|
|||
string rval = buf;
|
||||
delete[] buf;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
RegEx::RegEx(const string& s)
|
||||
{
|
||||
RegEx::RegEx(const string& s) {
|
||||
str_ = escape_char(s);
|
||||
string prefix = strfmt("%s_re_", current_decl_id->Name());
|
||||
matcher_id_ = ID::NewAnonymousID(prefix);
|
||||
decl_ = new RegExDecl(this);
|
||||
}
|
||||
}
|
||||
|
||||
RegEx::~RegEx() { }
|
||||
RegEx::~RegEx() {}
|
||||
|
||||
RegExDecl::RegExDecl(RegEx* regex) : Decl(regex->matcher_id(), REGEX)
|
||||
{
|
||||
regex_ = regex;
|
||||
}
|
||||
RegExDecl::RegExDecl(RegEx* regex) : Decl(regex->matcher_id(), REGEX) { regex_ = regex; }
|
||||
|
||||
void RegExDecl::Prepare()
|
||||
{
|
||||
global_env()->AddID(id(), GLOBAL_VAR, extern_type_re_matcher);
|
||||
}
|
||||
void RegExDecl::Prepare() { global_env()->AddID(id(), GLOBAL_VAR, extern_type_re_matcher); }
|
||||
|
||||
void RegExDecl::GenForwardDeclaration(Output* out_h)
|
||||
{
|
||||
out_h->println("extern %s %s;\n", RegEx::kREMatcherType,
|
||||
global_env()->LValue(regex_->matcher_id()));
|
||||
}
|
||||
void RegExDecl::GenForwardDeclaration(Output* out_h) {
|
||||
out_h->println("extern %s %s;\n", RegEx::kREMatcherType, global_env()->LValue(regex_->matcher_id()));
|
||||
}
|
||||
|
||||
void RegExDecl::GenCode(Output* out_h, Output* out_cc)
|
||||
{
|
||||
out_cc->println("%s %s(\"%s\");\n", RegEx::kREMatcherType,
|
||||
global_env()->LValue(regex_->matcher_id()), regex_->str().c_str());
|
||||
}
|
||||
void RegExDecl::GenCode(Output* out_h, Output* out_cc) {
|
||||
out_cc->println("%s %s(\"%s\");\n", RegEx::kREMatcherType, global_env()->LValue(regex_->matcher_id()),
|
||||
regex_->str().c_str());
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
class RegExDecl;
|
||||
|
||||
class RegEx : public Object
|
||||
{
|
||||
class RegEx : public Object {
|
||||
public:
|
||||
RegEx(const string& str);
|
||||
~RegEx();
|
||||
|
@ -23,10 +22,9 @@ private:
|
|||
public:
|
||||
static const char* kREMatcherType;
|
||||
static const char* kMatchPrefix;
|
||||
};
|
||||
};
|
||||
|
||||
class RegExDecl : public Decl
|
||||
{
|
||||
class RegExDecl : public Decl {
|
||||
public:
|
||||
RegExDecl(RegEx* regex);
|
||||
|
||||
|
@ -36,6 +34,6 @@ public:
|
|||
|
||||
private:
|
||||
RegEx* regex_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_regex_h
|
||||
|
|
|
@ -4,23 +4,20 @@
|
|||
#include "pac_output.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_));
|
||||
}
|
||||
}
|
||||
|
||||
void StateVar::GenAccessFunction(Output* out_h, Env* env)
|
||||
{
|
||||
out_h->println("%s %s const { return %s; }", type_->DataTypeConstRefStr().c_str(),
|
||||
env->RValue(id_), env->LValue(id_));
|
||||
}
|
||||
void StateVar::GenAccessFunction(Output* out_h, Env* env) {
|
||||
out_h->println("%s %s const { return %s; }", type_->DataTypeConstRefStr().c_str(), env->RValue(id_),
|
||||
env->LValue(id_));
|
||||
}
|
||||
|
||||
void StateVar::GenSetFunction(Output* out_h, Env* env)
|
||||
{
|
||||
out_h->println("void %s(%s x) { %s = x; }", set_function(id_).c_str(),
|
||||
type_->DataTypeConstRefStr().c_str(), env->LValue(id_));
|
||||
}
|
||||
void StateVar::GenSetFunction(Output* out_h, Env* env) {
|
||||
out_h->println("void %s(%s x) { %s = x; }", set_function(id_).c_str(), type_->DataTypeConstRefStr().c_str(),
|
||||
env->LValue(id_));
|
||||
}
|
||||
|
||||
void StateVar::GenInitCode(Output* out_cc, Env* env) { }
|
||||
void StateVar::GenInitCode(Output* out_cc, Env* env) {}
|
||||
|
||||
void StateVar::GenCleanUpCode(Output* out_cc, Env* env) { }
|
||||
void StateVar::GenCleanUpCode(Output* out_cc, Env* env) {}
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
|
||||
#include "pac_common.h"
|
||||
|
||||
class StateVar
|
||||
{
|
||||
class StateVar {
|
||||
public:
|
||||
StateVar(ID* id, Type* type) : id_(id), type_(type) { }
|
||||
StateVar(ID* id, Type* type) : id_(id), type_(type) {}
|
||||
|
||||
const ID* id() const { return id_; }
|
||||
Type* type() const { return type_; }
|
||||
|
@ -22,6 +21,6 @@ public:
|
|||
private:
|
||||
ID* id_;
|
||||
Type* type_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_state_h
|
||||
|
|
|
@ -15,32 +15,24 @@
|
|||
const char* StringType::kStringTypeName = "bytestring";
|
||||
const char* StringType::kConstStringTypeName = "const_bytestring";
|
||||
|
||||
StringType::StringType(StringTypeEnum anystr)
|
||||
: Type(STRING), type_(ANYSTR), str_(nullptr), regex_(nullptr)
|
||||
{
|
||||
StringType::StringType(StringTypeEnum anystr) : Type(STRING), type_(ANYSTR), str_(nullptr), regex_(nullptr) {
|
||||
ASSERT(anystr == ANYSTR);
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(nullptr)
|
||||
{
|
||||
init();
|
||||
}
|
||||
StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(nullptr) { init(); }
|
||||
|
||||
StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(nullptr), regex_(regex)
|
||||
{
|
||||
StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(nullptr), regex_(regex) {
|
||||
ASSERT(regex_);
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
void StringType::init()
|
||||
{
|
||||
void StringType::init() {
|
||||
string_length_var_field_ = nullptr;
|
||||
elem_datatype_ = new BuiltInType(BuiltInType::UINT8);
|
||||
}
|
||||
}
|
||||
|
||||
StringType::~StringType()
|
||||
{
|
||||
StringType::~StringType() {
|
||||
// TODO: Unref for Objects
|
||||
// Question: why Unref?
|
||||
//
|
||||
|
@ -49,169 +41,118 @@ StringType::~StringType()
|
|||
|
||||
delete string_length_var_field_;
|
||||
delete elem_datatype_;
|
||||
}
|
||||
}
|
||||
|
||||
Type* StringType::DoClone() const
|
||||
{
|
||||
Type* StringType::DoClone() const {
|
||||
StringType* clone;
|
||||
|
||||
switch ( type_ )
|
||||
{
|
||||
case ANYSTR:
|
||||
clone = new StringType(ANYSTR);
|
||||
break;
|
||||
case CSTR:
|
||||
clone = new StringType(str_);
|
||||
break;
|
||||
case REGEX:
|
||||
clone = new StringType(regex_);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
return nullptr;
|
||||
switch ( type_ ) {
|
||||
case ANYSTR: clone = new StringType(ANYSTR); break;
|
||||
case CSTR: clone = new StringType(str_); break;
|
||||
case REGEX: clone = new StringType(regex_); break;
|
||||
default: ASSERT(0); return nullptr;
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
bool StringType::DefineValueVar() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool StringType::DefineValueVar() const { return true; }
|
||||
|
||||
string StringType::DataTypeStr() const
|
||||
{
|
||||
return strfmt("%s", persistent() ? kStringTypeName : kConstStringTypeName);
|
||||
}
|
||||
string StringType::DataTypeStr() const { return strfmt("%s", persistent() ? kStringTypeName : kConstStringTypeName); }
|
||||
|
||||
Type* StringType::ElementDataType() const
|
||||
{
|
||||
return elem_datatype_;
|
||||
}
|
||||
Type* StringType::ElementDataType() const { return elem_datatype_; }
|
||||
|
||||
void StringType::ProcessAttr(Attr* a)
|
||||
{
|
||||
void StringType::ProcessAttr(Attr* a) {
|
||||
Type::ProcessAttr(a);
|
||||
|
||||
switch ( a->type() )
|
||||
{
|
||||
case ATTR_CHUNKED:
|
||||
{
|
||||
if ( type_ != ANYSTR )
|
||||
{
|
||||
throw Exception(a, "&chunked can be applied"
|
||||
switch ( a->type() ) {
|
||||
case ATTR_CHUNKED: {
|
||||
if ( type_ != ANYSTR ) {
|
||||
throw Exception(a,
|
||||
"&chunked can be applied"
|
||||
" to only type bytestring");
|
||||
}
|
||||
attr_chunked_ = true;
|
||||
SetBoundaryChecked();
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ATTR_RESTOFDATA:
|
||||
{
|
||||
if ( type_ != ANYSTR )
|
||||
{
|
||||
throw Exception(a, "&restofdata can be applied"
|
||||
case ATTR_RESTOFDATA: {
|
||||
if ( type_ != ANYSTR ) {
|
||||
throw Exception(a,
|
||||
"&restofdata can be applied"
|
||||
" to only type bytestring");
|
||||
}
|
||||
attr_restofdata_ = true;
|
||||
// As the string automatically extends to the end of
|
||||
// data, we do not have to check boundary.
|
||||
SetBoundaryChecked();
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ATTR_RESTOFFLOW:
|
||||
{
|
||||
if ( type_ != ANYSTR )
|
||||
{
|
||||
throw Exception(a, "&restofflow can be applied"
|
||||
case ATTR_RESTOFFLOW: {
|
||||
if ( type_ != ANYSTR ) {
|
||||
throw Exception(a,
|
||||
"&restofflow can be applied"
|
||||
" to only type bytestring");
|
||||
}
|
||||
attr_restofflow_ = true;
|
||||
// As the string automatically extends to the end of
|
||||
// flow, we do not have to check boundary.
|
||||
SetBoundaryChecked();
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void StringType::Prepare(Env* env, int flags)
|
||||
{
|
||||
if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 )
|
||||
{
|
||||
ID* string_length_var = new ID(
|
||||
strfmt("%s_string_length", value_var() ? value_var()->Name() : "val"));
|
||||
void StringType::Prepare(Env* env, int flags) {
|
||||
if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 ) {
|
||||
ID* string_length_var = new ID(strfmt("%s_string_length", value_var() ? value_var()->Name() : "val"));
|
||||
string_length_var_field_ = new TempVarField(string_length_var, extern_type_int->Clone());
|
||||
string_length_var_field_->Prepare(env);
|
||||
}
|
||||
Type::Prepare(env, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void StringType::GenPubDecls(Output* out_h, Env* env)
|
||||
{
|
||||
Type::GenPubDecls(out_h, env);
|
||||
}
|
||||
void StringType::GenPubDecls(Output* out_h, Env* env) { Type::GenPubDecls(out_h, env); }
|
||||
|
||||
void StringType::GenPrivDecls(Output* out_h, Env* env)
|
||||
{
|
||||
Type::GenPrivDecls(out_h, env);
|
||||
}
|
||||
void StringType::GenPrivDecls(Output* out_h, Env* env) { Type::GenPrivDecls(out_h, env); }
|
||||
|
||||
void StringType::GenInitCode(Output* out_cc, Env* env)
|
||||
{
|
||||
Type::GenInitCode(out_cc, env);
|
||||
}
|
||||
void StringType::GenInitCode(Output* out_cc, Env* env) { Type::GenInitCode(out_cc, env); }
|
||||
|
||||
void StringType::GenCleanUpCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void StringType::GenCleanUpCode(Output* out_cc, Env* env) {
|
||||
Type::GenCleanUpCode(out_cc, env);
|
||||
if ( persistent() )
|
||||
out_cc->println("%s.free();", env->LValue(value_var()));
|
||||
}
|
||||
}
|
||||
|
||||
void StringType::DoMarkIncrementalInput()
|
||||
{
|
||||
if ( attr_restofflow_ )
|
||||
{
|
||||
void StringType::DoMarkIncrementalInput() {
|
||||
if ( attr_restofflow_ ) {
|
||||
// Do nothing
|
||||
ASSERT(type_ == ANYSTR);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
Type::DoMarkIncrementalInput();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int StringType::StaticSize(Env* env) const
|
||||
{
|
||||
switch ( type_ )
|
||||
{
|
||||
int StringType::StaticSize(Env* env) const {
|
||||
switch ( type_ ) {
|
||||
case CSTR:
|
||||
// Use length of the unescaped string
|
||||
return str_->unescaped().length();
|
||||
case REGEX:
|
||||
// TODO: static size for a regular expression?
|
||||
case ANYSTR:
|
||||
return -1;
|
||||
case ANYSTR: return -1;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
return -1;
|
||||
}
|
||||
default: 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;
|
||||
}
|
||||
}
|
||||
|
||||
void StringType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
|
||||
{
|
||||
void StringType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data) {
|
||||
ASSERT(StaticSize(env) < 0);
|
||||
DEBUG_MSG("Generating dynamic size for string `%s'\n", value_var()->Name());
|
||||
|
||||
|
@ -220,92 +161,70 @@ void StringType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
|
|||
|
||||
string_length_var_field_->GenTempDecls(out_cc, env);
|
||||
|
||||
switch ( type_ )
|
||||
{
|
||||
case ANYSTR:
|
||||
GenDynamicSizeAnyStr(out_cc, env, data);
|
||||
break;
|
||||
case CSTR:
|
||||
ASSERT(0);
|
||||
break;
|
||||
switch ( type_ ) {
|
||||
case ANYSTR: GenDynamicSizeAnyStr(out_cc, env, data); break;
|
||||
case CSTR: ASSERT(0); break;
|
||||
case REGEX:
|
||||
// TODO: static size for a regular expression?
|
||||
GenDynamicSizeRegEx(out_cc, env, data);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! incremental_input() && AddSizeVar(out_cc, env) )
|
||||
{
|
||||
if ( ! incremental_input() && AddSizeVar(out_cc, env) ) {
|
||||
out_cc->println("%s = %s;", env->LValue(size_var()), env->RValue(string_length_var()));
|
||||
env->SetEvaluated(size_var());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string StringType::GenStringSize(Output* out_cc, Env* env, const DataPtr& data)
|
||||
{
|
||||
string StringType::GenStringSize(Output* out_cc, Env* env, const DataPtr& data) {
|
||||
int static_size = StaticSize(env);
|
||||
if ( static_size >= 0 )
|
||||
return strfmt("%d", static_size);
|
||||
GenDynamicSize(out_cc, env, data);
|
||||
return env->RValue(string_length_var());
|
||||
}
|
||||
}
|
||||
|
||||
void StringType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
|
||||
{
|
||||
void StringType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags) {
|
||||
string str_size = GenStringSize(out_cc, env, data);
|
||||
|
||||
// Generate additional checking
|
||||
switch ( type_ )
|
||||
{
|
||||
case CSTR:
|
||||
GenCheckingCStr(out_cc, env, data, str_size);
|
||||
break;
|
||||
switch ( type_ ) {
|
||||
case CSTR: GenCheckingCStr(out_cc, env, data, str_size); break;
|
||||
case REGEX:
|
||||
case ANYSTR:
|
||||
break;
|
||||
case ANYSTR: break;
|
||||
}
|
||||
|
||||
if ( ! anonymous_value_var() )
|
||||
{
|
||||
if ( ! anonymous_value_var() ) {
|
||||
// Set the value variable
|
||||
|
||||
int len;
|
||||
|
||||
if ( type_ == ANYSTR && attr_length_expr_ && attr_length_expr_->ConstFold(env, &len) )
|
||||
{
|
||||
if ( type_ == ANYSTR && attr_length_expr_ && attr_length_expr_->ConstFold(env, &len) ) {
|
||||
// can check for a negative length now
|
||||
if ( len < 0 )
|
||||
throw Exception(this, "negative &length on string");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
out_cc->println("// check for negative sizes");
|
||||
out_cc->println("if ( %s < 0 )", str_size.c_str());
|
||||
out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(),
|
||||
str_size.c_str());
|
||||
out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(), str_size.c_str());
|
||||
}
|
||||
|
||||
out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), data.ptr_expr(),
|
||||
str_size.c_str());
|
||||
out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), data.ptr_expr(), str_size.c_str());
|
||||
}
|
||||
|
||||
if ( parsing_complete_var() )
|
||||
{
|
||||
if ( parsing_complete_var() ) {
|
||||
out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StringType::GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern)
|
||||
{
|
||||
string tmp = strfmt("string((const char *) (%s), (const char *) %s).c_str()", data.ptr_expr(),
|
||||
env->RValue(end_of_data));
|
||||
out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", Location(),
|
||||
pattern.c_str(), tmp.c_str());
|
||||
}
|
||||
void StringType::GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern) {
|
||||
string tmp =
|
||||
strfmt("string((const char *) (%s), (const char *) %s).c_str()", data.ptr_expr(), env->RValue(end_of_data));
|
||||
out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", Location(), pattern.c_str(), tmp.c_str());
|
||||
}
|
||||
|
||||
void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data,
|
||||
const string& str_size)
|
||||
{
|
||||
void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data, const string& str_size) {
|
||||
// TODO: extend it for dynamic strings
|
||||
ASSERT(type_ == CSTR);
|
||||
|
||||
|
@ -314,17 +233,15 @@ void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data,
|
|||
string str_val = str_->str();
|
||||
|
||||
// Compare the string and report error on mismatch
|
||||
out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", data.ptr_expr(), str_val.c_str(),
|
||||
str_size.c_str());
|
||||
out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", data.ptr_expr(), str_val.c_str(), str_size.c_str());
|
||||
out_cc->inc_indent();
|
||||
out_cc->println("{");
|
||||
GenStringMismatch(out_cc, env, data, str_val);
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
||||
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 =
|
||||
// matcher.match_prefix(
|
||||
// begin,
|
||||
|
@ -351,52 +268,40 @@ void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& da
|
|||
GenStringMismatch(out_cc, env, data, tmp);
|
||||
out_cc->println("}");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
||||
void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data)
|
||||
{
|
||||
void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data) {
|
||||
ASSERT(type_ == ANYSTR);
|
||||
|
||||
if ( attr_restofdata_ || attr_oneline_ )
|
||||
{
|
||||
out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()),
|
||||
env->RValue(end_of_data), data.ptr_expr());
|
||||
if ( attr_restofdata_ || attr_oneline_ ) {
|
||||
out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), env->RValue(end_of_data),
|
||||
data.ptr_expr());
|
||||
}
|
||||
else if ( attr_restofflow_ )
|
||||
{
|
||||
out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()),
|
||||
env->RValue(end_of_data), data.ptr_expr());
|
||||
else if ( attr_restofflow_ ) {
|
||||
out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()), env->RValue(end_of_data),
|
||||
data.ptr_expr());
|
||||
}
|
||||
else if ( attr_length_expr_ )
|
||||
{
|
||||
out_cc->println("%s = %s;", env->LValue(string_length_var()),
|
||||
attr_length_expr_->EvalExpr(out_cc, env));
|
||||
else if ( attr_length_expr_ ) {
|
||||
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");
|
||||
}
|
||||
|
||||
env->SetEvaluated(string_length_var());
|
||||
}
|
||||
}
|
||||
|
||||
bool StringType::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
bool StringType::DoTraverse(DataDepVisitor* visitor) {
|
||||
if ( ! Type::DoTraverse(visitor) )
|
||||
return false;
|
||||
|
||||
switch ( type_ )
|
||||
{
|
||||
switch ( type_ ) {
|
||||
case ANYSTR:
|
||||
case CSTR:
|
||||
case REGEX:
|
||||
break;
|
||||
case REGEX: break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void StringType::static_init()
|
||||
{
|
||||
Type::AddPredefinedType("bytestring", new StringType(ANYSTR));
|
||||
}
|
||||
void StringType::static_init() { Type::AddPredefinedType("bytestring", new StringType(ANYSTR)); }
|
||||
|
|
|
@ -4,15 +4,9 @@
|
|||
#include "pac_type.h"
|
||||
|
||||
// TODO: question: shall we merge it with ArrayType?
|
||||
class StringType : public Type
|
||||
{
|
||||
class StringType : public Type {
|
||||
public:
|
||||
enum StringTypeEnum
|
||||
{
|
||||
CSTR,
|
||||
REGEX,
|
||||
ANYSTR
|
||||
};
|
||||
enum StringTypeEnum { CSTR, REGEX, ANYSTR };
|
||||
|
||||
explicit StringType(StringTypeEnum anystr);
|
||||
explicit StringType(ConstString* str);
|
||||
|
@ -81,6 +75,6 @@ public:
|
|||
private:
|
||||
static const char* kStringTypeName;
|
||||
static const char* kConstStringTypeName;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_strtype_h
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -8,11 +8,9 @@ using namespace std;
|
|||
#include "pac_datadep.h"
|
||||
#include "pac_dbg.h"
|
||||
|
||||
class Type : public Object, public DataDepElement
|
||||
{
|
||||
class Type : public Object, public DataDepElement {
|
||||
public:
|
||||
enum TypeType
|
||||
{
|
||||
enum TypeType {
|
||||
UNDEF = -1,
|
||||
EMPTY,
|
||||
BUILTIN,
|
||||
|
@ -100,8 +98,7 @@ public:
|
|||
|
||||
void AddField(Field* f);
|
||||
|
||||
void AddCheck(Expr* expr)
|
||||
{ /* TODO */
|
||||
void AddCheck(Expr* expr) { /* TODO */
|
||||
}
|
||||
|
||||
virtual bool DefineValueVar() const = 0;
|
||||
|
@ -111,8 +108,7 @@ public:
|
|||
|
||||
// Returns const reference of the C++ data type (unless the type
|
||||
// is numeric or pointer)
|
||||
string DataTypeConstRefStr() const
|
||||
{
|
||||
string DataTypeConstRefStr() const {
|
||||
string data_type = DataTypeStr();
|
||||
if ( ! IsPointerType() && ! IsNumericType() )
|
||||
data_type += " const &";
|
||||
|
@ -120,8 +116,7 @@ public:
|
|||
}
|
||||
|
||||
// Returns a default value for the type
|
||||
virtual string DefaultValue() const
|
||||
{
|
||||
virtual string DefaultValue() const {
|
||||
ASSERT(0);
|
||||
return "@@@";
|
||||
}
|
||||
|
@ -204,8 +199,7 @@ public:
|
|||
bool BufferableWithLineBreaker() const;
|
||||
Expr* LineBreaker() const;
|
||||
|
||||
enum BufferMode
|
||||
{
|
||||
enum BufferMode {
|
||||
NOT_BUFFERABLE,
|
||||
BUFFER_NOTHING, // for type "empty"
|
||||
BUFFER_BY_LENGTH,
|
||||
|
@ -218,7 +212,7 @@ public:
|
|||
int InitialBufferLength() const;
|
||||
|
||||
protected:
|
||||
virtual void GenNewInstance(Output* out, Env* env) { }
|
||||
virtual void GenNewInstance(Output* out, Env* env) {}
|
||||
|
||||
virtual bool ByteOrderSensitive() const = 0;
|
||||
|
||||
|
@ -306,6 +300,6 @@ public:
|
|||
protected:
|
||||
typedef map<string, Type*> type_map_t;
|
||||
static type_map_t type_map_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_type_h
|
||||
|
|
|
@ -16,35 +16,27 @@
|
|||
#include "pac_type.h"
|
||||
#include "pac_utils.h"
|
||||
|
||||
TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type)
|
||||
: Decl(id, TYPE), params_(params), type_(type)
|
||||
{
|
||||
TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type) : Decl(id, TYPE), params_(params), type_(type) {
|
||||
env_ = nullptr;
|
||||
type_->set_type_decl(this, true);
|
||||
}
|
||||
}
|
||||
|
||||
TypeDecl::~TypeDecl()
|
||||
{
|
||||
TypeDecl::~TypeDecl() {
|
||||
delete env_;
|
||||
delete type_;
|
||||
|
||||
delete_list(ParamList, params_);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDecl::ProcessAttr(Attr* a)
|
||||
{
|
||||
type_->ProcessAttr(a);
|
||||
}
|
||||
void TypeDecl::ProcessAttr(Attr* a) { type_->ProcessAttr(a); }
|
||||
|
||||
void TypeDecl::AddParam(Param* param)
|
||||
{
|
||||
void TypeDecl::AddParam(Param* param) {
|
||||
// Cannot work after Prepare()
|
||||
ASSERT(! env_);
|
||||
params_->push_back(param);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDecl::Prepare()
|
||||
{
|
||||
void TypeDecl::Prepare() {
|
||||
DEBUG_MSG("Preparing type %s\n", id()->Name());
|
||||
|
||||
if ( type_->tot() != Type::EXTERN && type_->tot() != Type::DUMMY )
|
||||
|
@ -57,47 +49,38 @@ void TypeDecl::Prepare()
|
|||
|
||||
env_ = new Env(global_env(), this);
|
||||
|
||||
foreach (i, ParamList, params_)
|
||||
{
|
||||
foreach (i, ParamList, params_) {
|
||||
Param* p = *i;
|
||||
// p->Prepare(env_);
|
||||
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());
|
||||
type_->AddField(
|
||||
new LetField(byteorder_id->clone(), extern_type_int, type_->attr_byteorder_expr()));
|
||||
type_->AddField(new LetField(byteorder_id->clone(), extern_type_int, type_->attr_byteorder_expr()));
|
||||
}
|
||||
|
||||
type_->Prepare(env_, Type::TO_BE_PARSED);
|
||||
}
|
||||
}
|
||||
|
||||
string TypeDecl::class_name() const
|
||||
{
|
||||
return id_->Name();
|
||||
}
|
||||
string TypeDecl::class_name() const { return id_->Name(); }
|
||||
|
||||
void TypeDecl::GenForwardDeclaration(Output* out_h)
|
||||
{
|
||||
void TypeDecl::GenForwardDeclaration(Output* out_h) {
|
||||
// Do not generate declaration for external types
|
||||
if ( type_->tot() == Type::EXTERN )
|
||||
return;
|
||||
out_h->println("class %s;", class_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDecl::GenCode(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void TypeDecl::GenCode(Output* out_h, Output* out_cc) {
|
||||
// Do not generate code for external types
|
||||
if ( type_->tot() == Type::EXTERN || type_->tot() == Type::STRING )
|
||||
return;
|
||||
|
||||
if ( !FLAGS_quiet )
|
||||
if ( ! FLAGS_quiet )
|
||||
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());
|
||||
Type* param_type = analyzer_context()->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"
|
||||
if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() )
|
||||
{
|
||||
if ( type_->RequiresByteOrder() && ! type_->attr_byteorder_expr() ) {
|
||||
env_->AddID(byteorder_id, TEMP_VAR, extern_type_int);
|
||||
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());
|
||||
bool first = true;
|
||||
vector<string>::iterator i;
|
||||
for ( i = (&base_classes)->begin(); i != (&base_classes)->end(); ++i )
|
||||
{
|
||||
if ( first )
|
||||
{
|
||||
for ( i = base_classes.begin(); i != base_classes.end(); ++i ) {
|
||||
if ( first ) {
|
||||
out_h->print(" : public %s", i->c_str());
|
||||
first = false;
|
||||
}
|
||||
|
@ -165,24 +145,21 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc)
|
|||
|
||||
out_h->dec_indent();
|
||||
out_h->println("};\n");
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDecl::GenPubDecls(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void TypeDecl::GenPubDecls(Output* out_h, Output* out_cc) {
|
||||
// GenParamPubDecls(params_, out_h, env_);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDecl::GenPrivDecls(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void TypeDecl::GenPrivDecls(Output* out_h, Output* out_cc) {
|
||||
// GenParamPrivDecls(params_, out_h, env_);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDecl::GenInitCode(Output* out_cc) { }
|
||||
void TypeDecl::GenInitCode(Output* out_cc) {}
|
||||
|
||||
void TypeDecl::GenCleanUpCode(Output* out_cc) { }
|
||||
void TypeDecl::GenCleanUpCode(Output* out_cc) {}
|
||||
|
||||
void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc)
|
||||
{
|
||||
void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc) {
|
||||
string params_str = ParamDecls(params_);
|
||||
|
||||
string proto = strfmt("%s(%s)", class_name().c_str(), params_str.c_str());
|
||||
|
@ -201,10 +178,9 @@ void TypeDecl::GenConstructorFunc(Output* out_h, Output* out_cc)
|
|||
|
||||
out_cc->println("}\n");
|
||||
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());
|
||||
|
||||
out_h->println("%s;", proto.c_str());
|
||||
|
@ -218,66 +194,55 @@ void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc)
|
|||
|
||||
out_cc->println("}\n");
|
||||
out_cc->dec_indent();
|
||||
}
|
||||
}
|
||||
|
||||
string TypeDecl::ParseFuncPrototype(Env* env)
|
||||
{
|
||||
string TypeDecl::ParseFuncPrototype(Env* env) {
|
||||
const char* func_name = nullptr;
|
||||
const char* return_type = nullptr;
|
||||
string params;
|
||||
|
||||
if ( type_->incremental_input() )
|
||||
{
|
||||
if ( type_->incremental_input() ) {
|
||||
func_name = kParseFuncWithBuffer;
|
||||
return_type = "bool";
|
||||
params = strfmt("flow_buffer_t %s", env->LValue(flow_buffer_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
func_name = kParseFuncWithoutBuffer;
|
||||
return_type = "int";
|
||||
params = strfmt("const_byteptr const %s, const_byteptr const %s",
|
||||
env->LValue(begin_of_data), env->LValue(end_of_data));
|
||||
params = strfmt("const_byteptr const %s, const_byteptr const %s", env->LValue(begin_of_data),
|
||||
env->LValue(end_of_data));
|
||||
}
|
||||
|
||||
if ( RequiresAnalyzerContext::compute(type_) )
|
||||
{
|
||||
if ( RequiresAnalyzerContext::compute(type_) ) {
|
||||
Type* param_type = analyzer_context()->param_type();
|
||||
params += strfmt(", %s %s", param_type->DataTypeConstRefStr().c_str(),
|
||||
env->LValue(analyzer_context_id));
|
||||
params += strfmt(", %s %s", param_type->DataTypeConstRefStr().c_str(), env->LValue(analyzer_context_id));
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// Returns "<return type> %s<func name>(<params>)%s".
|
||||
return strfmt("%s %%s%s(%s)%%s", return_type, func_name, params.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDecl::GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data)
|
||||
{
|
||||
void TypeDecl::GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data) {
|
||||
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_1 = "false";
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
ret_val_0 = type_->DataSize(nullptr, env, data).c_str();
|
||||
ret_val_1 = "@@@";
|
||||
|
||||
out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", env->RValue(begin_of_data),
|
||||
ret_val_0.c_str(), env->RValue(end_of_data));
|
||||
out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", env->RValue(begin_of_data), ret_val_0.c_str(),
|
||||
env->RValue(end_of_data));
|
||||
}
|
||||
|
||||
if ( type_->incremental_parsing() &&
|
||||
(type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY) )
|
||||
{
|
||||
if ( type_->incremental_parsing() && (type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY) ) {
|
||||
// In which case parsing may jump to label
|
||||
// "need_more_data" ...
|
||||
out_cc->println("BINPAC_ASSERT(%s);", type_->parsing_complete(env).c_str());
|
||||
|
@ -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("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());
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
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 )
|
||||
return;
|
||||
|
||||
|
@ -309,13 +271,11 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc)
|
|||
Env p_func_env(env_, this);
|
||||
Env* env = &p_func_env;
|
||||
|
||||
if ( type_->incremental_input() )
|
||||
{
|
||||
if ( type_->incremental_input() ) {
|
||||
env->AddID(flow_buffer_id, TEMP_VAR, extern_type_flowbuffer);
|
||||
env->SetEvaluated(flow_buffer_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr);
|
||||
env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr);
|
||||
|
||||
|
@ -356,10 +316,9 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc)
|
|||
|
||||
out_cc->println("}\n");
|
||||
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);
|
||||
|
||||
int init_buffer_length = type_->InitialBufferLength();
|
||||
|
@ -372,22 +331,17 @@ void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc)
|
|||
}
|
||||
|
||||
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);
|
||||
if ( ! decl )
|
||||
return nullptr;
|
||||
switch ( decl->decl_type() )
|
||||
{
|
||||
switch ( decl->decl_type() ) {
|
||||
case TYPE:
|
||||
case CONN:
|
||||
case FLOW:
|
||||
return static_cast<TypeDecl*>(decl)->type();
|
||||
case ENUM:
|
||||
return static_cast<EnumDecl*>(decl)->DataType();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
case FLOW: return static_cast<TypeDecl*>(decl)->type();
|
||||
case ENUM: return static_cast<EnumDecl*>(decl)->DataType();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
#include "pac_decl.h"
|
||||
|
||||
class TypeDecl : public Decl
|
||||
{
|
||||
class TypeDecl : public Decl {
|
||||
public:
|
||||
TypeDecl(ID* arg_id, ParamList* arg_params, Type* arg_type);
|
||||
~TypeDecl() override;
|
||||
|
@ -19,7 +18,7 @@ public:
|
|||
|
||||
protected:
|
||||
void AddParam(Param* param);
|
||||
virtual void AddBaseClass(vector<string>* base_classes) const { }
|
||||
virtual void AddBaseClass(vector<string>* base_classes) const {}
|
||||
void ProcessAttr(Attr* a) override;
|
||||
|
||||
virtual void GenPubDecls(Output* out_h, Output* out_cc);
|
||||
|
@ -42,6 +41,6 @@ protected:
|
|||
|
||||
ParamList* params_;
|
||||
Type* type_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_typedecl_h
|
||||
|
|
|
@ -4,39 +4,34 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char* copy_string(const char* s)
|
||||
{
|
||||
char* copy_string(const char* s) {
|
||||
char* c = new char[strlen(s) + 1];
|
||||
strcpy(c, s);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
|
||||
const char* do_fmt(const char* format, va_list ap)
|
||||
{
|
||||
const char* do_fmt(const char* format, va_list ap) {
|
||||
static char buf[1024];
|
||||
vsnprintf(buf, sizeof(buf), format, ap);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
string strfmt(const char* format, ...)
|
||||
{
|
||||
string strfmt(const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
const char* r = do_fmt(format, ap);
|
||||
va_end(ap);
|
||||
return string(r);
|
||||
}
|
||||
}
|
||||
|
||||
char* nfmt(const char* format, ...)
|
||||
{
|
||||
char* nfmt(const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
const char* r = do_fmt(format, ap);
|
||||
va_end(ap);
|
||||
return copy_string(r);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#include "pac_varfield.h"
|
||||
|
||||
void PrivVarField::Prepare(Env* env)
|
||||
{
|
||||
Field::Prepare(env);
|
||||
}
|
||||
void PrivVarField::Prepare(Env* env) { Field::Prepare(env); }
|
||||
|
|
|
@ -4,54 +4,37 @@
|
|||
#include "pac_field.h"
|
||||
|
||||
// A private variable evaluated with parsing
|
||||
class ParseVarField : public Field
|
||||
{
|
||||
class ParseVarField : public Field {
|
||||
public:
|
||||
ParseVarField(int is_class_member, ID* id, Type* type)
|
||||
: Field(PARSE_VAR_FIELD, TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, id,
|
||||
type)
|
||||
{
|
||||
: Field(PARSE_VAR_FIELD, TYPE_TO_BE_PARSED | is_class_member | NOT_PUBLIC_READABLE, id, type) {}
|
||||
void GenPubDecls(Output* out, Env* env) override { /* do nothing */
|
||||
}
|
||||
void GenPubDecls(Output* out, Env* env) override
|
||||
{ /* do nothing */
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// A public variable
|
||||
class PubVarField : public Field
|
||||
{
|
||||
class PubVarField : public Field {
|
||||
public:
|
||||
PubVarField(ID* id, Type* type)
|
||||
: Field(PUB_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type)
|
||||
{
|
||||
}
|
||||
~PubVarField() override { }
|
||||
};
|
||||
: Field(PUB_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type) {}
|
||||
~PubVarField() override {}
|
||||
};
|
||||
|
||||
// A private variable
|
||||
class PrivVarField : public Field
|
||||
{
|
||||
class PrivVarField : public Field {
|
||||
public:
|
||||
PrivVarField(ID* id, Type* type)
|
||||
: Field(PRIV_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, id,
|
||||
type)
|
||||
{
|
||||
}
|
||||
~PrivVarField() override { }
|
||||
: Field(PRIV_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | NOT_PUBLIC_READABLE, id, type) {}
|
||||
~PrivVarField() override {}
|
||||
|
||||
void GenPubDecls(Output* out, Env* env) override
|
||||
{ /* do nothing */
|
||||
void GenPubDecls(Output* out, Env* env) override { /* do nothing */
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class TempVarField : public Field
|
||||
{
|
||||
class TempVarField : public Field {
|
||||
public:
|
||||
TempVarField(ID* id, Type* type)
|
||||
: Field(TEMP_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, id, type)
|
||||
{
|
||||
}
|
||||
~TempVarField() override { }
|
||||
};
|
||||
TempVarField(ID* id, Type* type) : Field(TEMP_VAR_FIELD, TYPE_NOT_TO_BE_PARSED | NOT_CLASS_MEMBER, id, type) {}
|
||||
~TempVarField() override {}
|
||||
};
|
||||
|
||||
#endif // pac_varfield_h
|
||||
|
|
|
@ -7,48 +7,36 @@
|
|||
#include "pac_type.h"
|
||||
|
||||
WithInputField::WithInputField(ID* id, Type* type, InputBuffer* input)
|
||||
: Field(WITHINPUT_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type),
|
||||
input_(input)
|
||||
{
|
||||
: Field(WITHINPUT_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), input_(input) {
|
||||
ASSERT(type_);
|
||||
ASSERT(input_);
|
||||
}
|
||||
}
|
||||
|
||||
WithInputField::~WithInputField()
|
||||
{
|
||||
delete input_;
|
||||
}
|
||||
WithInputField::~WithInputField() { delete input_; }
|
||||
|
||||
bool WithInputField::DoTraverse(DataDepVisitor* visitor)
|
||||
{
|
||||
bool WithInputField::DoTraverse(DataDepVisitor* visitor) {
|
||||
return Field::DoTraverse(visitor) && input()->Traverse(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
bool WithInputField::RequiresAnalyzerContext() const
|
||||
{
|
||||
bool WithInputField::RequiresAnalyzerContext() const {
|
||||
return Field::RequiresAnalyzerContext() || (input() && input()->RequiresAnalyzerContext());
|
||||
}
|
||||
}
|
||||
|
||||
void WithInputField::Prepare(Env* env)
|
||||
{
|
||||
void WithInputField::Prepare(Env* env) {
|
||||
Field::Prepare(env);
|
||||
env->SetEvalMethod(id_, this);
|
||||
}
|
||||
}
|
||||
|
||||
void WithInputField::GenEval(Output* out_cc, Env* env)
|
||||
{
|
||||
void WithInputField::GenEval(Output* out_cc, Env* 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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WithInputField::GenParseCode(Output* out_cc, Env* env)
|
||||
{
|
||||
void WithInputField::GenParseCode(Output* out_cc, Env* env) {
|
||||
out_cc->println("// Parse \"%s\"", id_->Name());
|
||||
if ( type_->attr_if_expr() )
|
||||
{
|
||||
if ( type_->attr_if_expr() ) {
|
||||
// A conditional field
|
||||
env->Evaluate(out_cc, type_->has_value_var());
|
||||
out_cc->println("if ( %s )", env->RValue(type_->has_value_var()));
|
||||
|
@ -63,11 +51,10 @@ void WithInputField::GenParseCode(Output* out_cc, Env* env)
|
|||
type_->GenPreParsing(out_cc, &field_env);
|
||||
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->dec_indent();
|
||||
}
|
||||
else
|
||||
out_cc->println("}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
#include "pac_decl.h"
|
||||
#include "pac_field.h"
|
||||
|
||||
class WithInputField : public Field, public Evaluatable
|
||||
{
|
||||
class WithInputField : public Field, public Evaluatable {
|
||||
public:
|
||||
WithInputField(ID* id, Type* type, InputBuffer* input);
|
||||
~WithInputField() override;
|
||||
|
@ -33,6 +32,6 @@ protected:
|
|||
|
||||
protected:
|
||||
InputBuffer* input_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // pac_withinput_h
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue