binpac: Add pre-commit hooks and run clang-format on everything

This commit is contained in:
Tim Wojtulewicz 2022-07-07 11:49:24 -07:00
parent 090ac0a6e0
commit 090325df40
91 changed files with 3086 additions and 3665 deletions

View file

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

View file

@ -1,20 +1,22 @@
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> // for memcpy #include <stdlib.h>
#include <string.h> // for memcpy
#define binpac_regex_h #define binpac_regex_h
#include "binpac.h" #include "binpac.h"
#include "binpac_buffer.h" #include "binpac_buffer.h"
namespace binpac { namespace binpac
{
extern double network_time(); extern double network_time();
namespace { namespace
const unsigned char CR = '\r'; {
const unsigned char LF = '\n'; const unsigned char CR = '\r';
} const unsigned char LF = '\n';
}
binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = { binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = {
// max_capacity // max_capacity
@ -67,9 +69,7 @@ void FlowBuffer::NewMessage()
switch ( mode_ ) switch ( mode_ )
{ {
case LINE_MODE: case LINE_MODE:
bytes_to_advance = (frame_length_ + bytes_to_advance = (frame_length_ + (linebreak_style_ == STRICT_CRLF ? 2 : 1));
(linebreak_style_ == STRICT_CRLF ?
2 : 1));
break; break;
case FRAME_MODE: case FRAME_MODE:
bytes_to_advance = frame_length_; bytes_to_advance = frame_length_;
@ -118,14 +118,13 @@ void FlowBuffer::ExpandBuffer(int length)
if ( length > policy.max_capacity ) if ( length > policy.max_capacity )
{ {
std::string reason = strfmt("expand past max capacity %d/%d", std::string reason = strfmt("expand past max capacity %d/%d", length, policy.max_capacity);
length, policy.max_capacity);
throw ExceptionFlowBufferAlloc(reason.c_str()); throw ExceptionFlowBufferAlloc(reason.c_str());
} }
// Allocate a new buffer and copy the existing contents // Allocate a new buffer and copy the existing contents
buffer_length_ = length; buffer_length_ = length;
unsigned char* new_buf = (unsigned char *) realloc(buffer_, buffer_length_); unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_);
if ( ! new_buf ) if ( ! new_buf )
throw ExceptionFlowBufferAlloc("expand realloc OOM"); throw ExceptionFlowBufferAlloc("expand realloc OOM");
@ -139,7 +138,7 @@ void FlowBuffer::ContractBuffer()
return; return;
buffer_length_ = policy.min_capacity; buffer_length_ = policy.min_capacity;
unsigned char* new_buf = (unsigned char *) realloc(buffer_, buffer_length_); unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_);
if ( ! new_buf ) if ( ! new_buf )
throw ExceptionFlowBufferAlloc("contract realloc OOM"); throw ExceptionFlowBufferAlloc("contract realloc OOM");
@ -233,8 +232,7 @@ void FlowBuffer::NewData(const_byteptr begin, const_byteptr end)
ClearPreviousData(); ClearPreviousData();
BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || orig_data_begin_ == orig_data_end_);
orig_data_begin_ == orig_data_end_);
orig_data_begin_ = begin; orig_data_begin_ = begin;
orig_data_end_ = end; orig_data_end_ = end;
@ -273,8 +271,7 @@ void FlowBuffer::ClearPreviousData()
{ {
if ( frame_length_ > 0 ) if ( frame_length_ > 0 )
{ {
frame_length_ -= frame_length_ -= (orig_data_end_ - orig_data_begin_);
(orig_data_end_ - orig_data_begin_);
} }
orig_data_begin_ = orig_data_end_; orig_data_begin_ = orig_data_end_;
} }
@ -320,14 +317,14 @@ Finite state automaton for CR_OR_LF:
(!--line is complete, *--add to buffer) (!--line is complete, *--add to buffer)
CR_OR_LF_0: CR_OR_LF_0:
CR: CR_OR_LF_1 ! CR: CR_OR_LF_1 !
LF: CR_OR_LF_0 ! LF: CR_OR_LF_0 !
.: CR_OR_LF_0 * .: CR_OR_LF_0 *
CR_OR_LF_1: CR_OR_LF_1:
CR: CR_OR_LF_1 ! CR: CR_OR_LF_1 !
LF: CR_OR_LF_0 LF: CR_OR_LF_0
.: CR_OR_LF_0 * .: CR_OR_LF_0 *
*/ */
void FlowBuffer::MarkOrCopyLine_CR_OR_LF() void FlowBuffer::MarkOrCopyLine_CR_OR_LF()
@ -335,8 +332,7 @@ void FlowBuffer::MarkOrCopyLine_CR_OR_LF()
if ( ! (orig_data_begin_ && orig_data_end_) ) if ( ! (orig_data_begin_ && orig_data_end_) )
return; return;
if ( state_ == CR_OR_LF_1 && if ( state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF )
orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF )
{ {
state_ = CR_OR_LF_0; state_ = CR_OR_LF_0;
++orig_data_begin_; ++orig_data_begin_;
@ -378,9 +374,8 @@ found_end_of_line:
message_complete_ = true; message_complete_ = true;
#if DEBUG_FLOW_BUFFER #if DEBUG_FLOW_BUFFER
fprintf(stderr, "%.6f Line complete: [%s]\n", fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(),
network_time(), string((const char*)begin(), (const char*)end()).c_str());
string((const char *) begin(), (const char *) end()).c_str());
#endif #endif
} }
@ -389,14 +384,14 @@ Finite state automaton and STRICT_CRLF:
(!--line is complete, *--add to buffer) (!--line is complete, *--add to buffer)
STRICT_CRLF_0: STRICT_CRLF_0:
CR: STRICT_CRLF_1 * CR: STRICT_CRLF_1 *
LF: STRICT_CRLF_0 * LF: STRICT_CRLF_0 *
.: STRICT_CRLF_0 * .: STRICT_CRLF_0 *
STRICT_CRLF_1: STRICT_CRLF_1:
CR: STRICT_CRLF_1 * CR: STRICT_CRLF_1 *
LF: STRICT_CRLF_0 ! (--buffer_n_) LF: STRICT_CRLF_0 ! (--buffer_n_)
.: STRICT_CRLF_0 * .: STRICT_CRLF_0 *
*/ */
void FlowBuffer::MarkOrCopyLine_STRICT_CRLF() void FlowBuffer::MarkOrCopyLine_STRICT_CRLF()
@ -442,9 +437,8 @@ found_end_of_line:
message_complete_ = true; message_complete_ = true;
#if DEBUG_FLOW_BUFFER #if DEBUG_FLOW_BUFFER
fprintf(stderr, "%.6f Line complete: [%s]\n", fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(),
network_time(), string((const char*)begin(), (const char*)end()).c_str());
string((const char *) begin(), (const char *) end()).c_str());
#endif #endif
} }
@ -477,13 +471,11 @@ found_end_of_line:
message_complete_ = true; message_complete_ = true;
#if DEBUG_FLOW_BUFFER #if DEBUG_FLOW_BUFFER
fprintf(stderr, "%.6f Line complete: [%s]\n", fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(),
network_time(), string((const char*)begin(), (const char*)end()).c_str());
string((const char *) begin(), (const char *) end()).c_str());
#endif #endif
} }
// Invariants: // Invariants:
// //
// When buffer_n_ == 0: // When buffer_n_ == 0:
@ -494,8 +486,7 @@ found_end_of_line:
void FlowBuffer::MarkOrCopyFrame() void FlowBuffer::MarkOrCopyFrame()
{ {
if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ )
orig_data_begin_ < orig_data_end_ )
{ {
// Skip the lingering LF // Skip the lingering LF
if ( *orig_data_begin_ == LF ) if ( *orig_data_begin_ == LF )
@ -508,8 +499,7 @@ void FlowBuffer::MarkOrCopyFrame()
if ( buffer_n_ == 0 ) if ( buffer_n_ == 0 )
{ {
// If there is enough data // If there is enough data
if ( frame_length_ >= 0 && if ( frame_length_ >= 0 && orig_data_end_ - orig_data_begin_ >= frame_length_ )
orig_data_end_ - orig_data_begin_ >= frame_length_ )
{ {
// Do nothing except setting the message complete flag // Do nothing except setting the message complete flag
message_complete_ = true; message_complete_ = true;
@ -518,15 +508,14 @@ void FlowBuffer::MarkOrCopyFrame()
{ {
if ( ! chunked_ ) if ( ! chunked_ )
{ {
AppendToBuffer(orig_data_begin_, AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_);
orig_data_end_ - orig_data_begin_);
} }
message_complete_ = false; message_complete_ = false;
} }
} }
else else
{ {
BINPAC_ASSERT(!chunked_); BINPAC_ASSERT(! chunked_);
int bytes_to_copy = orig_data_end_ - orig_data_begin_; int bytes_to_copy = orig_data_end_ - orig_data_begin_;
message_complete_ = false; message_complete_ = false;
if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ ) if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ )
@ -540,10 +529,8 @@ void FlowBuffer::MarkOrCopyFrame()
#if DEBUG_FLOW_BUFFER #if DEBUG_FLOW_BUFFER
if ( message_complete_ ) if ( message_complete_ )
{ {
fprintf(stderr, "%.6f frame complete: [%s]\n", fprintf(stderr, "%.6f frame complete: [%s]\n", network_time(),
network_time(), string((const char*)begin(), (const char*)end()).c_str());
string((const char *) begin(),
(const char *) end()).c_str());
} }
#endif #endif
} }
@ -562,4 +549,4 @@ void FlowBuffer::AppendToBuffer(const_byteptr data, int len)
BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_); BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_);
} }
} // namespace binpac } // namespace binpac

View file

@ -2,24 +2,29 @@
#define binpac_buffer_h #define binpac_buffer_h
#include <sys/types.h> #include <sys/types.h>
#include "binpac.h" #include "binpac.h"
namespace binpac { namespace binpac
{
class FlowBuffer { class FlowBuffer
{
public: public:
struct Policy { struct Policy
{
int max_capacity; int max_capacity;
int min_capacity; int min_capacity;
int contract_threshold; int contract_threshold;
}; };
enum LineBreakStyle { enum LineBreakStyle
CR_OR_LF, // CR or LF or CRLF {
STRICT_CRLF, // CR followed by LF CR_OR_LF, // CR or LF or CRLF
CR_LF_NUL, // CR or LF or CR-LF or CR-NUL STRICT_CRLF, // CR followed by LF
LINE_BREAKER, // User specified linebreaker CR_LF_NUL, // CR or LF or CR-LF or CR-NUL
}; LINE_BREAKER, // User specified linebreaker
};
FlowBuffer(LineBreakStyle linebreak_style = CR_OR_LF); FlowBuffer(LineBreakStyle linebreak_style = CR_OR_LF);
virtual ~FlowBuffer(); virtual ~FlowBuffer();
@ -39,13 +44,12 @@ public:
void DiscardData(); void DiscardData();
// Whether there is enough data for the frame // Whether there is enough data for the frame
bool ready() const{ return message_complete_ || mode_ == UNKNOWN_MODE; } bool ready() const { return message_complete_ || mode_ == UNKNOWN_MODE; }
inline const_byteptr begin() const inline const_byteptr begin() const
{ {
BINPAC_ASSERT(ready()); BINPAC_ASSERT(ready());
return ( buffer_n_ == 0 ) ? return (buffer_n_ == 0) ? orig_data_begin_ : buffer_;
orig_data_begin_ : buffer_;
} }
inline const_byteptr end() const inline const_byteptr end() const
@ -67,15 +71,14 @@ public:
if ( buffer_n_ > 0 ) if ( buffer_n_ > 0 )
return buffer_n_; return buffer_n_;
if ( frame_length_ < 0 || if ( frame_length_ < 0 || orig_data_begin_ + frame_length_ > orig_data_end_ )
orig_data_begin_ + frame_length_ > orig_data_end_ )
return orig_data_end_ - orig_data_begin_; return orig_data_end_ - orig_data_begin_;
else else
return frame_length_; return frame_length_;
} }
inline bool data_available() const inline bool data_available() const
{ {
return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_;
} }
@ -88,21 +91,19 @@ public:
int data_seq() const int data_seq() const
{ {
int data_seq_at_orig_data_begin = int data_seq_at_orig_data_begin = data_seq_at_orig_data_end_ -
data_seq_at_orig_data_end_ - (orig_data_end_ - orig_data_begin_);
(orig_data_end_ - orig_data_begin_);
if ( buffer_n_ > 0 ) if ( buffer_n_ > 0 )
return data_seq_at_orig_data_begin; return data_seq_at_orig_data_begin;
else else
return data_seq_at_orig_data_begin + data_length(); return data_seq_at_orig_data_begin + data_length();
} }
bool eof() const { return eof_; } bool eof() const { return eof_; }
void set_eof(); void set_eof();
bool have_pending_request() const { return have_pending_request_; } bool have_pending_request() const { return have_pending_request_; }
static void init(Policy p) static void init(Policy p) { policy = p; }
{ policy = p; }
protected: protected:
// Reset the buffer for a new message // Reset the buffer for a new message
@ -140,41 +141,43 @@ protected:
void MarkOrCopyLine_STRICT_CRLF(); void MarkOrCopyLine_STRICT_CRLF();
void MarkOrCopyLine_LINEBREAK(); void MarkOrCopyLine_LINEBREAK();
int buffer_n_; // number of bytes in the buffer int buffer_n_; // number of bytes in the buffer
int buffer_length_; // size of the buffer int buffer_length_; // size of the buffer
unsigned char* buffer_; unsigned char* buffer_;
bool message_complete_; bool message_complete_;
int frame_length_; int frame_length_;
bool chunked_; bool chunked_;
const_byteptr orig_data_begin_, orig_data_end_; const_byteptr orig_data_begin_, orig_data_end_;
LineBreakStyle linebreak_style_; LineBreakStyle linebreak_style_;
LineBreakStyle linebreak_style_default; LineBreakStyle linebreak_style_default;
unsigned char linebreaker_; unsigned char linebreaker_;
enum { enum
{
UNKNOWN_MODE, UNKNOWN_MODE,
LINE_MODE, LINE_MODE,
FRAME_MODE, FRAME_MODE,
} mode_; } mode_;
enum { enum
{
CR_OR_LF_0, CR_OR_LF_0,
CR_OR_LF_1, CR_OR_LF_1,
STRICT_CRLF_0, STRICT_CRLF_0,
STRICT_CRLF_1, STRICT_CRLF_1,
FRAME_0, FRAME_0,
} state_; } state_;
int data_seq_at_orig_data_end_; int data_seq_at_orig_data_end_;
bool eof_; bool eof_;
bool have_pending_request_; bool have_pending_request_;
static Policy policy; static Policy policy;
}; };
typedef FlowBuffer *flow_buffer_t; typedef FlowBuffer* flow_buffer_t;
} // namespace binpac } // namespace binpac
#endif // binpac_buffer_h #endif // binpac_buffer_h

View file

@ -1,24 +1,25 @@
#define binpac_regex_h #define binpac_regex_h
#include <stdlib.h>
#include "binpac_bytestring.h" #include "binpac_bytestring.h"
#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) int bytestring_to_int(bytestring const* s)
{ {
return atoi((const char *) s->begin()); return atoi((const char*)s->begin());
} }
double bytestring_to_double(bytestring const *s) double bytestring_to_double(bytestring const* s)
{ {
return atof((const char *) s->begin()); return atof((const char*)s->begin());
} }
} // namespace binpac } // namespace binpac

View file

@ -3,155 +3,118 @@
#include <string.h> #include <string.h>
#include <string> #include <string>
#include "binpac.h" #include "binpac.h"
namespace binpac namespace binpac
{ {
template<class T> class datastring; template <class T> class datastring;
template <class T> template <class T> class const_datastring
class const_datastring {
{
public: public:
const_datastring() const_datastring() : begin_(0), end_(0) { }
: begin_(0), end_(0)
{
}
const_datastring(T const *data, int length) const_datastring(T const* data, int length) : begin_(data), end_(data + length) { }
: begin_(data), end_(data + length)
{
}
const_datastring(const T *begin, const T *end) const_datastring(const T* begin, const T* end) : begin_(begin), end_(end) { }
: begin_(begin), end_(end)
{
}
const_datastring(datastring<T> const &s) const_datastring(datastring<T> const& s) : begin_(s.begin()), end_(s.end()) { }
: begin_(s.begin()), end_(s.end())
{
}
void init(const T *data, int length) void init(const T* data, int length)
{ {
begin_ = data; begin_ = data;
end_ = data + length; end_ = data + length;
} }
T const *begin() const { return begin_; } T const* begin() const { return begin_; }
T const *end() const { return end_; } T const* end() const { return end_; }
int length() const { return end_ - begin_; } int length() const { return end_ - begin_; }
T const &operator[](int index) const T const& operator[](int index) const { return begin()[index]; }
{
return begin()[index];
}
bool operator==(const_datastring<T> const &s) bool operator==(const_datastring<T> const& s)
{ {
if ( length() != s.length() ) if ( length() != s.length() )
return false; return false;
return memcmp((const void *) begin(), (const void *) s.begin(), return memcmp((const void*)begin(), (const void*)s.begin(), sizeof(T) * length()) == 0;
sizeof(T) * length()) == 0;
} }
void set_begin(T const *begin) { begin_ = begin; } void set_begin(T const* begin) { begin_ = begin; }
void set_end(T const *end) { end_ = end; } void set_end(T const* end) { end_ = end; }
private: private:
T const *begin_; T const* begin_;
T const *end_; T const* end_;
}; };
typedef const_datastring<uint8> const_bytestring; typedef const_datastring<uint8> const_bytestring;
template<class T> template <class T> class datastring
class datastring {
{
public: public:
datastring() datastring() { clear(); }
{
clear();
}
datastring(T *data, int len) datastring(T* data, int len) { set(data, len); }
{
set(data, len);
}
datastring(T const *begin, T const *end) datastring(T const* begin, T const* end) { set_const(begin, end - begin); }
{
set_const(begin, end - begin);
}
datastring(datastring<T> const &x) datastring(datastring<T> const& x) : data_(x.data()), length_(x.length()) { }
: data_(x.data()), length_(x.length())
{
}
explicit datastring(const_datastring<T> const &x) explicit datastring(const_datastring<T> const& x) { set_const(x.begin(), x.length()); }
{
set_const(x.begin(), x.length());
}
datastring const &operator=(datastring<T> const &x) datastring const& operator=(datastring<T> const& x)
{ {
BINPAC_ASSERT(!data_); BINPAC_ASSERT(! data_);
set(x.data(), x.length()); set(x.data(), x.length());
return *this; return *this;
} }
void init(T const *begin, int length) void init(T const* begin, int length)
{ {
BINPAC_ASSERT(!data_); BINPAC_ASSERT(! data_);
set_const(begin, length); set_const(begin, length);
} }
void clear() void clear()
{ {
data_ = 0; length_ = 0; data_ = 0;
length_ = 0;
} }
void free() void free()
{ {
if ( data_ ) if ( data_ )
delete [] data_; delete[] data_;
clear(); clear();
} }
void clone() void clone() { set_const(begin(), length()); }
{
set_const(begin(), length());
}
datastring const &operator=(const_datastring<T> const &x) datastring const& operator=(const_datastring<T> const& x)
{ {
BINPAC_ASSERT(!data_); BINPAC_ASSERT(! data_);
set_const(x.begin(), x.length()); set_const(x.begin(), x.length());
return *this; return *this;
} }
T const &operator[](int index) const T const& operator[](int index) const { return begin()[index]; }
{
return begin()[index];
}
T *data() const { return data_; } T* data() const { return data_; }
int length() const { return length_; } int length() const { return length_; }
T const *begin() const { return data_; } T const* begin() const { return data_; }
T const *end() const { return data_ + length_; } T const* end() const { return data_ + length_; }
private: private:
void set(T *data, int len) void set(T* data, int len)
{ {
data_ = data; data_ = data;
length_ = len; length_ = len;
} }
void set_const(T const *data, int len) void set_const(T const* data, int len)
{ {
length_ = len; length_ = len;
data_ = new T[len + 1]; data_ = new T[len + 1];
@ -159,41 +122,39 @@ private:
data_[len] = 0; data_[len] = 0;
} }
T * data_; T* data_;
int length_; int length_;
}; };
typedef datastring<uint8> bytestring; typedef datastring<uint8> bytestring;
inline const char *c_str(bytestring const &s) inline const char* c_str(bytestring const& s)
{ {
return (const char *) s.begin(); return (const char*)s.begin();
} }
inline std::string std_str(const_bytestring const &s) inline std::string std_str(const_bytestring const& s)
{ {
return std::string((const char *) s.begin(), (const char *) s.end()); return std::string((const char*)s.begin(), (const char*)s.end());
} }
inline bool operator==(bytestring const &s1, const char *s2) inline bool operator==(bytestring const& s1, const char* s2)
{ {
return strcmp(c_str(s1), s2) == 0; return strcmp(c_str(s1), s2) == 0;
} }
inline void get_pointers(const_bytestring const &s, inline void get_pointers(const_bytestring const& s, uint8 const** pbegin, uint8 const** pend)
uint8 const **pbegin, uint8 const **pend)
{ {
*pbegin = s.begin(); *pbegin = s.begin();
*pend = s.end(); *pend = s.end();
} }
inline void get_pointers(bytestring const *s, inline void get_pointers(bytestring const* s, uint8 const** pbegin, uint8 const** pend)
uint8 const **pbegin, uint8 const **pend)
{ {
*pbegin = s->begin(); *pbegin = s->begin();
*pend = s->end(); *pend = s->end();
} }
} // namespace binpac } // namespace binpac
#endif // binpac_bytestring_h #endif // binpac_bytestring_h

View file

@ -1,133 +1,120 @@
#ifndef binpac_exception_h #ifndef binpac_exception_h
#define binpac_exception_h #define binpac_exception_h
#include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdint.h>
namespace binpac { namespace binpac
{
class Exception class Exception
{ {
public: public:
Exception(const char* m = 0) Exception(const char* m = 0) : msg_("binpac exception: ")
: msg_("binpac exception: ")
{ {
if ( m ) if ( m )
append(m); append(m);
// abort(); // abort();
} }
void append(string m) { msg_ += m; } void append(string m) { msg_ += m; }
string msg() const { return msg_; } string msg() const { return msg_; }
const char* c_msg() const { return msg_.c_str(); } const char* c_msg() const { return msg_.c_str(); }
protected: protected:
string msg_; string msg_;
}; };
class ExceptionEnforceViolation : public Exception class ExceptionEnforceViolation : public Exception
{ {
public: public:
ExceptionEnforceViolation(const char* where) ExceptionEnforceViolation(const char* where)
{ {
append(binpac_fmt("&enforce violation : %s", where)); append(binpac_fmt("&enforce violation : %s", where));
} }
}; };
class ExceptionOutOfBound : public Exception class ExceptionOutOfBound : public Exception
{ {
public: public:
ExceptionOutOfBound(const char* where, int len_needed, int len_given) ExceptionOutOfBound(const char* where, int len_needed, int len_given)
{ {
append(binpac_fmt("out_of_bound: %s: %d > %d", append(binpac_fmt("out_of_bound: %s: %d > %d", where, len_needed, len_given));
where, len_needed, len_given));
} }
}; };
class ExceptionInvalidCase : public Exception class ExceptionInvalidCase : public Exception
{ {
public: public:
ExceptionInvalidCase(const char* location, ExceptionInvalidCase(const char* location, int64_t index, const char* expected)
int64_t index, : location_(location), index_(index), expected_(expected)
const char *expected)
: location_(location),
index_(index),
expected_(expected)
{ {
append(binpac_fmt("invalid case: %s: %" PRIi64 " (%s)", append(binpac_fmt("invalid case: %s: %" PRIi64 " (%s)", location, index, expected));
location, index, expected));
} }
protected: protected:
const char* location_; const char* location_;
int64_t index_; int64_t index_;
string expected_; string expected_;
}; };
class ExceptionInvalidCaseIndex : public Exception class ExceptionInvalidCaseIndex : public Exception
{ {
public: public:
ExceptionInvalidCaseIndex(const char* location, ExceptionInvalidCaseIndex(const char* location, int64_t index)
int64_t index) : location_(location), index_(index)
: location_(location),
index_(index)
{ {
append(binpac_fmt("invalid index for case: %s: %" PRIi64, append(binpac_fmt("invalid index for case: %s: %" PRIi64, location, index));
location, index));
} }
protected: protected:
const char* location_; const char* location_;
int64_t index_; int64_t index_;
}; };
class ExceptionInvalidOffset : public Exception class ExceptionInvalidOffset : public Exception
{ {
public: public:
ExceptionInvalidOffset(const char* location, ExceptionInvalidOffset(const char* location, int min_offset, int offset)
int min_offset, int offset) : location_(location), min_offset_(min_offset), offset_(offset)
: location_(location),
min_offset_(min_offset), offset_(offset)
{ {
append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", location, min_offset,
location, min_offset, offset)); offset));
} }
protected: protected:
const char* location_; const char* location_;
int min_offset_, offset_; int min_offset_, offset_;
}; };
class ExceptionStringMismatch : public Exception class ExceptionStringMismatch : public Exception
{ {
public: public:
ExceptionStringMismatch(const char* location, ExceptionStringMismatch(const char* location, const char* expected, const char* actual_data)
const char *expected, const char *actual_data)
{ {
append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"", append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"",
location, expected, actual_data)); location, expected, actual_data));
} }
}; };
class ExceptionInvalidStringLength : public Exception class ExceptionInvalidStringLength : public Exception
{ {
public: public:
ExceptionInvalidStringLength(const char* location, int len) ExceptionInvalidStringLength(const char* location, int len)
{ {
append(binpac_fmt("invalid length string: %s: %d", append(binpac_fmt("invalid length string: %s: %d", location, len));
location, len));
} }
}; };
class ExceptionFlowBufferAlloc : public Exception class ExceptionFlowBufferAlloc : public Exception
{ {
public: public:
ExceptionFlowBufferAlloc(const char* reason) ExceptionFlowBufferAlloc(const char* reason)
{ {
append(binpac_fmt("flowbuffer allocation failed: %s", reason)); append(binpac_fmt("flowbuffer allocation failed: %s", reason));
} }
}; };
} }
#endif // binpac_exception_h #endif // binpac_exception_h

View file

@ -3,8 +3,9 @@
class RE_Matcher; class RE_Matcher;
namespace binpac { namespace binpac
{
std::vector<RE_Matcher*>* uncompiled_re_matchers = 0; std::vector<RE_Matcher*>* uncompiled_re_matchers = 0;
} }

View file

@ -1,13 +1,17 @@
#ifndef binpac_regex_h #ifndef binpac_regex_h
#define binpac_regex_h #define binpac_regex_h
#include "binpac.h"
#include "zeek/RE.h" #include "zeek/RE.h"
namespace zeek { class RE_Matcher; } #include "binpac.h"
namespace zeek
{
class RE_Matcher;
}
namespace binpac namespace binpac
{ {
// Must be called before any binpac functionality is used. // Must be called before any binpac functionality is used.
// //
@ -19,10 +23,10 @@ inline void init(FlowBuffer::Policy* fbp = 0);
// Internal vector recording not yet compiled matchers. // Internal vector recording not yet compiled matchers.
extern std::vector<zeek::RE_Matcher*>* uncompiled_re_matchers; extern std::vector<zeek::RE_Matcher*>* uncompiled_re_matchers;
class RegExMatcher { class RegExMatcher
{
public: public:
RegExMatcher(const char *pattern) RegExMatcher(const char* pattern) : pattern_(pattern)
: pattern_(pattern)
{ {
if ( ! uncompiled_re_matchers ) if ( ! uncompiled_re_matchers )
uncompiled_re_matchers = new std::vector<zeek::RE_Matcher*>; uncompiled_re_matchers = new std::vector<zeek::RE_Matcher*>;
@ -31,16 +35,10 @@ public:
uncompiled_re_matchers->push_back(re_matcher_); uncompiled_re_matchers->push_back(re_matcher_);
} }
~RegExMatcher() ~RegExMatcher() { delete re_matcher_; }
{
delete re_matcher_;
}
// Returns the length of longest match, or -1 on mismatch. // Returns the length of longest match, or -1 on mismatch.
int MatchPrefix(const_byteptr data, int len) int MatchPrefix(const_byteptr data, int len) { return re_matcher_->MatchPrefix(data, len); }
{
return re_matcher_->MatchPrefix(data, len);
}
private: private:
friend void ::binpac::init(FlowBuffer::Policy*); friend void ::binpac::init(FlowBuffer::Policy*);
@ -49,8 +47,8 @@ private:
static void init(); static void init();
string pattern_; string pattern_;
zeek::RE_Matcher *re_matcher_; zeek::RE_Matcher* re_matcher_;
}; };
inline void RegExMatcher::init() inline void RegExMatcher::init()
{ {
@ -77,6 +75,6 @@ inline void init(FlowBuffer::Policy* fbp)
FlowBuffer::init(*fbp); FlowBuffer::init(*fbp);
} }
} // namespace binpac } // namespace binpac
#endif // binpac_regex_h #endif // binpac_regex_h

View file

@ -1,3 +1,5 @@
#include "pac_action.h"
#include "pac_embedded.h" #include "pac_embedded.h"
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_id.h" #include "pac_id.h"
@ -6,17 +8,8 @@
#include "pac_typedecl.h" #include "pac_typedecl.h"
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_action.h" AnalyzerAction::AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code)
: AnalyzerElement(ACTION), action_id_(action_id), when_(when), param_(param), code_(code),
AnalyzerAction::AnalyzerAction(ID *action_id,
When when,
ActionParam *param,
EmbeddedCode *code)
: AnalyzerElement(ACTION),
action_id_(action_id),
when_(when),
param_(param),
code_(code),
analyzer_(0) analyzer_(0)
{ {
} }
@ -33,31 +26,25 @@ string AnalyzerAction::action_function() const
return strfmt("Action_%s", action_id_->Name()); return strfmt("Action_%s", action_id_->Name());
} }
void AnalyzerAction::InstallHook(AnalyzerDecl *analyzer) void AnalyzerAction::InstallHook(AnalyzerDecl* analyzer)
{ {
ASSERT(0); ASSERT(0);
analyzer_ = analyzer; analyzer_ = analyzer;
// param_->MainDataType()->InstallAction(this); // param_->MainDataType()->InstallAction(this);
} }
void AnalyzerAction::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl) void AnalyzerAction::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl)
{ {
Env action_func_env(decl->env(), this); Env action_func_env(decl->env(), this);
action_func_env.AddID(param_->id(), action_func_env.AddID(param_->id(), TEMP_VAR, param_->DataType());
TEMP_VAR,
param_->DataType());
action_func_env.SetEvaluated(param_->id()); action_func_env.SetEvaluated(param_->id());
string action_func_proto = string action_func_proto = strfmt("%s(%s)", action_function().c_str(),
strfmt("%s(%s)", ParamDecls(&action_func_env).c_str());
action_function().c_str(),
ParamDecls(&action_func_env).c_str());
out_h->println("void %s;", action_func_proto.c_str()); out_h->println("void %s;", action_func_proto.c_str());
out_cc->println("void %s::%s", out_cc->println("void %s::%s", decl->class_name().c_str(), action_func_proto.c_str());
decl->class_name().c_str(),
action_func_proto.c_str());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
@ -69,28 +56,27 @@ void AnalyzerAction::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl)
out_cc->println(""); out_cc->println("");
} }
string AnalyzerAction::ParamDecls(Env *env) const string AnalyzerAction::ParamDecls(Env* env) const
{ {
return param_->DeclStr(env); return param_->DeclStr(env);
} }
Type *ActionParam::MainDataType() const Type* ActionParam::MainDataType() const
{ {
// Note: this is not equal to DataType() // Note: this is not equal to DataType()
Type *main_type = TypeDecl::LookUpType(type()->type_id()); Type* main_type = TypeDecl::LookUpType(type()->type_id());
if ( ! main_type ) if ( ! main_type )
{ {
throw Exception(type()->type_id(), throw Exception(type()->type_id(), "type not defined");
"type not defined");
} }
return main_type; return main_type;
} }
Type *ActionParam::DataType() const Type* ActionParam::DataType() const
{ {
Type *main_type = MainDataType(); Type* main_type = MainDataType();
if ( ! type()->field_id() ) if ( ! type()->field_id() )
{ {
@ -98,22 +84,18 @@ Type *ActionParam::DataType() const
} }
else else
{ {
Type *member_type = Type* member_type = main_type->MemberDataType(type()->field_id());
main_type->MemberDataType(type()->field_id());
if ( ! member_type ) if ( ! member_type )
{ {
throw Exception(type()->field_id(), throw Exception(type()->field_id(),
strfmt("cannot find member type for `%s.%s'", strfmt("cannot find member type for `%s.%s'", type()->type_id()->Name(),
type()->type_id()->Name(), type()->field_id()->Name()));
type()->field_id()->Name()));
} }
return member_type; return member_type;
} }
} }
string ActionParam::DeclStr(Env *env) const string ActionParam::DeclStr(Env* env) const
{ {
return strfmt("%s %s", return strfmt("%s %s", DataType()->DataTypeStr().c_str(), env->LValue(id()));
DataType()->DataTypeStr().c_str(),
env->LValue(id()));
} }

View file

@ -3,72 +3,74 @@
// Classes representing analyzer actions. // Classes representing analyzer actions.
#include "pac_common.h"
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_common.h"
class AnalyzerAction : public AnalyzerElement class AnalyzerAction : public AnalyzerElement
{ {
public: public:
enum When { BEFORE, AFTER }; enum When
{
BEFORE,
AFTER
};
AnalyzerAction(ID *action_id, AnalyzerAction(ID* action_id, When when, ActionParam* param, EmbeddedCode* code);
When when,
ActionParam *param,
EmbeddedCode *code);
~AnalyzerAction(); ~AnalyzerAction();
When when() const { return when_; } When when() const { return when_; }
ActionParam *param() const { return param_; } ActionParam* param() const { return param_; }
AnalyzerDecl *analyzer() const { return analyzer_; } AnalyzerDecl* analyzer() const { return analyzer_; }
string action_function() const; string action_function() const;
// Generate function prototype and code for the action // Generate function prototype and code for the action
void GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl); void GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl);
// Install the hook at the corresponding data type parsing // Install the hook at the corresponding data type parsing
// function to invoke the action. // function to invoke the action.
void InstallHook(AnalyzerDecl *analyzer); void InstallHook(AnalyzerDecl* analyzer);
private: private:
string ParamDecls(Env *env) const; string ParamDecls(Env* env) const;
ID *action_id_; ID* action_id_;
When when_; When when_;
ActionParam *param_; ActionParam* param_;
EmbeddedCode *code_; EmbeddedCode* code_;
AnalyzerDecl *analyzer_; AnalyzerDecl* analyzer_;
}; };
class ActionParam class ActionParam
{ {
public: public:
ActionParam(const ID *id, ActionParamType *type) ActionParam(const ID* id, ActionParamType* type) : id_(id), type_(type) { }
: id_(id), type_(type) {}
const ID *id() const { return id_; } const ID* id() const { return id_; }
ActionParamType *type() const { return type_; } ActionParamType* type() const { return type_; }
Type *MainDataType() const; Type* MainDataType() const;
Type *DataType() const; Type* DataType() const;
string DeclStr(Env *env) const; string DeclStr(Env* env) const;
private: private:
const ID *id_; const ID* id_;
ActionParamType *type_; ActionParamType* type_;
}; };
class ActionParamType class ActionParamType
{ {
public: public:
ActionParamType(const ID *type_id, const ID *field_id = 0) ActionParamType(const ID* type_id, const ID* field_id = 0)
: type_id_(type_id), field_id_(field_id) {} : type_id_(type_id), field_id_(field_id)
{
}
const ID *type_id() const { return type_id_; } const ID* type_id() const { return type_id_; }
const ID *field_id() const { return field_id_; } const ID* field_id() const { return field_id_; }
protected: protected:
const ID *type_id_, *field_id_; const ID *type_id_, *field_id_;
}; };
#endif // pac_action_h #endif // pac_action_h

View file

@ -1,3 +1,5 @@
#include "pac_analyzer.h"
#include "pac_action.h" #include "pac_action.h"
#include "pac_context.h" #include "pac_context.h"
#include "pac_embedded.h" #include "pac_embedded.h"
@ -12,11 +14,7 @@
#include "pac_type.h" #include "pac_type.h"
#include "pac_varfield.h" #include "pac_varfield.h"
#include "pac_analyzer.h" AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params)
AnalyzerDecl::AnalyzerDecl(ID *id,
DeclType decl_type,
ParamList *params)
: TypeDecl(id, params, new DummyType()) : TypeDecl(id, params, new DummyType())
{ {
decl_type_ = decl_type; decl_type_ = decl_type;
@ -47,74 +45,66 @@ AnalyzerDecl::~AnalyzerDecl()
delete_list(AnalyzerHelperList, eof_helpers_); delete_list(AnalyzerHelperList, eof_helpers_);
} }
void AnalyzerDecl::AddElements(AnalyzerElementList *elemlist) void AnalyzerDecl::AddElements(AnalyzerElementList* elemlist)
{ {
ASSERT(! env_); ASSERT(! env_);
foreach(i, AnalyzerElementList, elemlist) foreach (i, AnalyzerElementList, elemlist)
{ {
AnalyzerElement *elem = *i; AnalyzerElement* elem = *i;
switch ( elem->type() ) switch ( elem->type() )
{ {
case AnalyzerElement::STATE: case AnalyzerElement::STATE:
{ {
ASSERT(0); ASSERT(0);
AnalyzerState *state_elem = AnalyzerState* state_elem = (AnalyzerState*)elem;
(AnalyzerState *) elem; statevars_->insert(statevars_->end(), state_elem->statevars()->begin(),
statevars_->insert( state_elem->statevars()->end());
statevars_->end(),
state_elem->statevars()->begin(),
state_elem->statevars()->end());
} }
break; break;
case AnalyzerElement::ACTION: case AnalyzerElement::ACTION:
{ {
ASSERT(0); ASSERT(0);
AnalyzerAction *action_elem = AnalyzerAction* action_elem = (AnalyzerAction*)elem;
(AnalyzerAction *) elem;
actions_->push_back(action_elem); actions_->push_back(action_elem);
} }
break; break;
case AnalyzerElement::HELPER: case AnalyzerElement::HELPER:
{ {
AnalyzerHelper *helper_elem = AnalyzerHelper* helper_elem = (AnalyzerHelper*)elem;
(AnalyzerHelper *) elem;
switch ( helper_elem->helper_type() ) switch ( helper_elem->helper_type() )
{ {
case AnalyzerHelper::INIT_CODE: case AnalyzerHelper::INIT_CODE:
constructor_helpers_->push_back(helper_elem); constructor_helpers_->push_back(helper_elem);
break; break;
case AnalyzerHelper::CLEANUP_CODE: case AnalyzerHelper::CLEANUP_CODE:
destructor_helpers_->push_back(helper_elem); destructor_helpers_->push_back(helper_elem);
break; break;
case AnalyzerHelper::EOF_CODE: case AnalyzerHelper::EOF_CODE:
eof_helpers_->push_back(helper_elem); eof_helpers_->push_back(helper_elem);
break; break;
default: default:
helpers_->push_back(helper_elem); helpers_->push_back(helper_elem);
} }
} }
break; break;
case AnalyzerElement::FUNCTION: case AnalyzerElement::FUNCTION:
{ {
AnalyzerFunction *func_elem = AnalyzerFunction* func_elem = (AnalyzerFunction*)elem;
(AnalyzerFunction *) elem; Function* func = func_elem->function();
Function *func = func_elem->function();
func->set_analyzer_decl(this); func->set_analyzer_decl(this);
functions_->push_back(func); functions_->push_back(func);
} }
break; break;
case AnalyzerElement::FLOW: case AnalyzerElement::FLOW:
{ {
AnalyzerFlow *flow_elem = AnalyzerFlow* flow_elem = (AnalyzerFlow*)elem;
(AnalyzerFlow *) elem;
ProcessFlowElement(flow_elem); ProcessFlowElement(flow_elem);
} }
break; break;
case AnalyzerElement::DATAUNIT: case AnalyzerElement::DATAUNIT:
{ {
AnalyzerDataUnit *dataunit_elem = AnalyzerDataUnit* dataunit_elem = (AnalyzerDataUnit*)elem;
(AnalyzerDataUnit *) elem;
ProcessDataUnitElement(dataunit_elem); ProcessDataUnitElement(dataunit_elem);
} }
break; break;
@ -134,19 +124,19 @@ void AnalyzerDecl::Prepare()
ASSERT(statevars_->empty()); ASSERT(statevars_->empty());
ASSERT(actions_->empty()); ASSERT(actions_->empty());
foreach(i, FunctionList, functions_) foreach (i, FunctionList, functions_)
{ {
Function *function = *i; Function* function = *i;
function->Prepare(env_); function->Prepare(env_);
} }
foreach(i, StateVarList, statevars_) foreach (i, StateVarList, statevars_)
{ {
StateVar *statevar = *i; StateVar* statevar = *i;
env_->AddID(statevar->id(), STATE_VAR, statevar->type()); env_->AddID(statevar->id(), STATE_VAR, statevar->type());
} }
foreach(i, AnalyzerActionList, actions_) foreach (i, AnalyzerActionList, actions_)
{ {
AnalyzerAction *action = *i; AnalyzerAction* action = *i;
action->InstallHook(this); action->InstallHook(this);
} }
} }
@ -154,30 +144,30 @@ void AnalyzerDecl::Prepare()
void AnalyzerDecl::GenForwardDeclaration(Output* out_h) void AnalyzerDecl::GenForwardDeclaration(Output* out_h)
{ {
out_h->println("class %s;", class_name().c_str()); out_h->println("class %s;", class_name().c_str());
foreach(i, FunctionList, functions_) foreach (i, FunctionList, functions_)
{ {
Function *function = *i; Function* function = *i;
function->GenForwardDeclaration(out_h); function->GenForwardDeclaration(out_h);
} }
} }
void AnalyzerDecl::GenActions(Output *out_h, Output *out_cc) void AnalyzerDecl::GenActions(Output* out_h, Output* out_cc)
{ {
foreach(i, AnalyzerActionList, actions_) foreach (i, AnalyzerActionList, actions_)
{ {
(*i)->GenCode(out_h, out_cc, this); (*i)->GenCode(out_h, out_cc, this);
} }
} }
void AnalyzerDecl::GenHelpers(Output *out_h, Output *out_cc) void AnalyzerDecl::GenHelpers(Output* out_h, Output* out_cc)
{ {
foreach(i, AnalyzerHelperList, helpers_) foreach (i, AnalyzerHelperList, helpers_)
{ {
(*i)->GenCode(out_h, out_cc, this); (*i)->GenCode(out_h, out_cc, this);
} }
} }
void AnalyzerDecl::GenPubDecls(Output *out_h, Output *out_cc) void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc)
{ {
TypeDecl::GenPubDecls(out_h, out_cc); TypeDecl::GenPubDecls(out_h, out_cc);
@ -196,7 +186,7 @@ void AnalyzerDecl::GenPubDecls(Output *out_h, Output *out_cc)
// TODO: export public state variables // TODO: export public state variables
} }
void AnalyzerDecl::GenPrivDecls(Output *out_h, Output *out_cc) void AnalyzerDecl::GenPrivDecls(Output* out_h, Output* out_cc)
{ {
TypeDecl::GenPrivDecls(out_h, out_cc); TypeDecl::GenPrivDecls(out_h, out_cc);
@ -210,65 +200,65 @@ void AnalyzerDecl::GenPrivDecls(Output *out_h, Output *out_cc)
// TODO: declare state variables // TODO: declare state variables
} }
void AnalyzerDecl::GenInitCode(Output *out_cc) void AnalyzerDecl::GenInitCode(Output* out_cc)
{ {
TypeDecl::GenInitCode(out_cc); TypeDecl::GenInitCode(out_cc);
foreach(i, AnalyzerHelperList, constructor_helpers_) foreach (i, AnalyzerHelperList, constructor_helpers_)
{ {
(*i)->GenCode(0, out_cc, this); (*i)->GenCode(0, out_cc, this);
} }
} }
void AnalyzerDecl::GenCleanUpCode(Output *out_cc) void AnalyzerDecl::GenCleanUpCode(Output* out_cc)
{ {
TypeDecl::GenCleanUpCode(out_cc); TypeDecl::GenCleanUpCode(out_cc);
foreach(i, AnalyzerHelperList, destructor_helpers_) foreach (i, AnalyzerHelperList, destructor_helpers_)
{ {
(*i)->GenCode(0, out_cc, this); (*i)->GenCode(0, out_cc, this);
} }
} }
void AnalyzerDecl::GenStateVarDecls(Output *out_h) void AnalyzerDecl::GenStateVarDecls(Output* out_h)
{ {
foreach(i, StateVarList, statevars_) foreach (i, StateVarList, statevars_)
{ {
StateVar *var = *i; StateVar* var = *i;
var->GenDecl(out_h, env_); var->GenDecl(out_h, env_);
} }
} }
void AnalyzerDecl::GenStateVarSetFunctions(Output *out_h) void AnalyzerDecl::GenStateVarSetFunctions(Output* out_h)
{ {
foreach(i, StateVarList, statevars_) foreach (i, StateVarList, statevars_)
{ {
StateVar *var = *i; StateVar* var = *i;
var->GenSetFunction(out_h, env_); var->GenSetFunction(out_h, env_);
} }
} }
void AnalyzerDecl::GenStateVarInitCode(Output *out_cc) void AnalyzerDecl::GenStateVarInitCode(Output* out_cc)
{ {
foreach(i, StateVarList, statevars_) foreach (i, StateVarList, statevars_)
{ {
StateVar *var = *i; StateVar* var = *i;
var->GenInitCode(out_cc, env_); var->GenInitCode(out_cc, env_);
} }
} }
void AnalyzerDecl::GenStateVarCleanUpCode(Output *out_cc) void AnalyzerDecl::GenStateVarCleanUpCode(Output* out_cc)
{ {
foreach(i, StateVarList, statevars_) foreach (i, StateVarList, statevars_)
{ {
StateVar *var = *i; StateVar* var = *i;
var->GenCleanUpCode(out_cc, env_); var->GenCleanUpCode(out_cc, env_);
} }
} }
void AnalyzerDecl::GenFunctions(Output *out_h, Output *out_cc) void AnalyzerDecl::GenFunctions(Output* out_h, Output* out_cc)
{ {
foreach(i, FunctionList, functions_) foreach (i, FunctionList, functions_)
{ {
Function *function = *i; Function* function = *i;
function->GenCode(out_h, out_cc); function->GenCode(out_h, out_cc);
} }
} }
@ -285,9 +275,9 @@ AnalyzerHelper::~AnalyzerHelper()
delete code_; delete code_;
} }
void AnalyzerHelper::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl) void AnalyzerHelper::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl)
{ {
Output *out = 0; Output* out = 0;
switch ( helper_type_ ) switch ( helper_type_ )
{ {
case MEMBER_DECLS: case MEMBER_DECLS:
@ -303,22 +293,18 @@ void AnalyzerHelper::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl)
code()->GenCode(out, decl->env()); code()->GenCode(out, decl->env());
} }
FlowField::FlowField(ID *flow_id, ParameterizedType *flow_type) FlowField::FlowField(ID* flow_id, ParameterizedType* flow_type)
: Field(FLOW_FIELD, : Field(FLOW_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, flow_id, flow_type)
TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE,
flow_id, flow_type)
{ {
} }
void FlowField::GenInitCode(Output *out_cc, Env *env) void FlowField::GenInitCode(Output* out_cc, Env* env)
{ {
type_->GenPreParsing(out_cc, env); type_->GenPreParsing(out_cc, env);
} }
AnalyzerFlow::AnalyzerFlow(Direction dir, ID *type_id, ExprList *params) AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params)
: AnalyzerElement(FLOW), : AnalyzerElement(FLOW), dir_(dir), type_id_(type_id)
dir_(dir),
type_id_(type_id)
{ {
if ( ! params ) if ( ! params )
params = new ExprList(); params = new ExprList();
@ -326,9 +312,9 @@ AnalyzerFlow::AnalyzerFlow(Direction dir, ID *type_id, ExprList *params)
// Add "this" to the list of params // Add "this" to the list of params
params->insert(params->begin(), new Expr(this_id->clone())); params->insert(params->begin(), new Expr(this_id->clone()));
ID *flow_id = ((dir == UP) ? upflow_id : downflow_id)->clone(); ID* flow_id = ((dir == UP) ? upflow_id : downflow_id)->clone();
ParameterizedType *flow_type = new ParameterizedType(type_id_, params); ParameterizedType* flow_type = new ParameterizedType(type_id_, params);
flow_field_ = new FlowField(flow_id, flow_type); flow_field_ = new FlowField(flow_id, flow_type);
@ -340,18 +326,17 @@ AnalyzerFlow::~AnalyzerFlow()
delete flow_field_; delete flow_field_;
} }
FlowDecl *AnalyzerFlow::flow_decl() FlowDecl* AnalyzerFlow::flow_decl()
{ {
DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name()); DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name());
if ( ! flow_decl_ ) if ( ! flow_decl_ )
{ {
Decl *decl = Decl::LookUpDecl(type_id_); Decl* decl = Decl::LookUpDecl(type_id_);
if ( decl && decl->decl_type() == Decl::FLOW ) if ( decl && decl->decl_type() == Decl::FLOW )
flow_decl_ = static_cast<FlowDecl *>(decl); flow_decl_ = static_cast<FlowDecl*>(decl);
if ( ! flow_decl_ ) if ( ! flow_decl_ )
{ {
throw Exception(this, throw Exception(this, "cannot find the flow declaration");
"cannot find the flow declaration");
} }
} }
return flow_decl_; return flow_decl_;

View file

@ -7,162 +7,172 @@
class AnalyzerElement; class AnalyzerElement;
class AnalyzerState; class AnalyzerState;
class AnalyzerAction; // defined in pac_action.h class AnalyzerAction; // defined in pac_action.h
class AnalyzerHelper; class AnalyzerHelper;
class AnalyzerFlow; class AnalyzerFlow;
class AnalyzerDataUnit; class AnalyzerDataUnit;
class AnalyzerFunction; class AnalyzerFunction;
class ConnDecl; class ConnDecl;
class FlowDecl; class FlowDecl;
typedef vector<AnalyzerHelper *> AnalyzerHelperList; typedef vector<AnalyzerHelper*> AnalyzerHelperList;
typedef vector<Function *> FunctionList; typedef vector<Function*> FunctionList;
class AnalyzerDecl : public TypeDecl class AnalyzerDecl : public TypeDecl
{ {
public: public:
AnalyzerDecl(ID *id, DeclType decl_type, ParamList *params); AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params);
~AnalyzerDecl(); ~AnalyzerDecl();
void AddElements(AnalyzerElementList *elemlist); void AddElements(AnalyzerElementList* elemlist);
void Prepare(); void Prepare();
void GenForwardDeclaration(Output *out_h); void GenForwardDeclaration(Output* out_h);
// void GenCode(Output *out_h, Output *out_cc); // void GenCode(Output *out_h, Output *out_cc);
void GenInitCode(Output *out_cc); void GenInitCode(Output* out_cc);
void GenCleanUpCode(Output *out_cc); void GenCleanUpCode(Output* out_cc);
string class_name() const; string class_name() const;
// string cookie_name() const; // string cookie_name() const;
protected: protected:
virtual void ProcessFlowElement(AnalyzerFlow *flow_elem) = 0; virtual void ProcessFlowElement(AnalyzerFlow* flow_elem) = 0;
virtual void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) = 0; virtual void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem) = 0;
// Generate public/private declarations for member functions and // Generate public/private declarations for member functions and
// variables // variables
void GenPubDecls(Output *out_h, Output *out_cc); void GenPubDecls(Output* out_h, Output* out_cc);
void GenPrivDecls(Output *out_h, Output *out_cc); void GenPrivDecls(Output* out_h, Output* out_cc);
// Generate the NewData() function // Generate the NewData() function
virtual void GenProcessFunc(Output *out_h, Output *out_cc) = 0; virtual void GenProcessFunc(Output* out_h, Output* out_cc) = 0;
// Generate the NewGap() function // Generate the NewGap() function
virtual void GenGapFunc(Output *out_h, Output *out_cc) = 0; virtual void GenGapFunc(Output* out_h, Output* out_cc) = 0;
// Generate the FlowEOF() function // Generate the FlowEOF() function
virtual void GenEOFFunc(Output *out_h, Output *out_cc) = 0; virtual void GenEOFFunc(Output* out_h, Output* out_cc) = 0;
// Generate the functions // Generate the functions
void GenFunctions(Output *out_h, Output *out_cc); void GenFunctions(Output* out_h, Output* out_cc);
// Generate the action functions // Generate the action functions
void GenActions(Output *out_h, Output *out_cc); void GenActions(Output* out_h, Output* out_cc);
// Generate the helper code segments // Generate the helper code segments
void GenHelpers(Output *out_h, Output *out_cc); void GenHelpers(Output* out_h, Output* out_cc);
// Generate declarations for state variables and their set functions // Generate declarations for state variables and their set functions
void GenStateVarDecls(Output *out_h); void GenStateVarDecls(Output* out_h);
void GenStateVarSetFunctions(Output *out_h); void GenStateVarSetFunctions(Output* out_h);
// Generate code for initializing and cleaning up (including // Generate code for initializing and cleaning up (including
// memory de-allocating) state variables // memory de-allocating) state variables
void GenStateVarInitCode(Output *out_cc); void GenStateVarInitCode(Output* out_cc);
void GenStateVarCleanUpCode(Output *out_cc); void GenStateVarCleanUpCode(Output* out_cc);
StateVarList *statevars_; StateVarList* statevars_;
AnalyzerActionList *actions_; AnalyzerActionList* actions_;
AnalyzerHelperList *helpers_; AnalyzerHelperList* helpers_;
FunctionList *functions_; FunctionList* functions_;
AnalyzerHelperList *constructor_helpers_; AnalyzerHelperList* constructor_helpers_;
AnalyzerHelperList *destructor_helpers_; AnalyzerHelperList* destructor_helpers_;
AnalyzerHelperList *eof_helpers_; AnalyzerHelperList* eof_helpers_;
}; };
class AnalyzerElement : public Object class AnalyzerElement : public Object
{ {
public: public:
enum ElementType { STATE, ACTION, FUNCTION, HELPER, FLOW, DATAUNIT }; enum ElementType
AnalyzerElement(ElementType type) {
: type_(type) {} STATE,
virtual ~AnalyzerElement() {} ACTION,
FUNCTION,
HELPER,
FLOW,
DATAUNIT
};
AnalyzerElement(ElementType type) : type_(type) { }
virtual ~AnalyzerElement() { }
ElementType type() const { return type_; } ElementType type() const { return type_; }
private: private:
ElementType type_; ElementType type_;
}; };
// A collection of variables representing analyzer states. // A collection of variables representing analyzer states.
class AnalyzerState : public AnalyzerElement class AnalyzerState : public AnalyzerElement
{ {
public: public:
AnalyzerState(StateVarList *statevars) AnalyzerState(StateVarList* statevars) : AnalyzerElement(STATE), statevars_(statevars) { }
: AnalyzerElement(STATE),
statevars_(statevars) {}
~AnalyzerState(); ~AnalyzerState();
StateVarList *statevars() const { return statevars_; } StateVarList* statevars() const { return statevars_; }
private: private:
StateVarList *statevars_; StateVarList* statevars_;
}; };
// A collection of embedded C++ code // A collection of embedded C++ code
class AnalyzerHelper : public AnalyzerElement class AnalyzerHelper : public AnalyzerElement
{ {
public: public:
enum Type { enum Type
{
MEMBER_DECLS, MEMBER_DECLS,
INIT_CODE, INIT_CODE,
CLEANUP_CODE, CLEANUP_CODE,
EOF_CODE, EOF_CODE,
}; };
AnalyzerHelper(Type helper_type, EmbeddedCode *code) AnalyzerHelper(Type helper_type, EmbeddedCode* code)
: AnalyzerElement(HELPER), : AnalyzerElement(HELPER), helper_type_(helper_type), code_(code)
helper_type_(helper_type), {
code_(code) {} }
~AnalyzerHelper(); ~AnalyzerHelper();
Type helper_type() const { return helper_type_; } Type helper_type() const { return helper_type_; }
void GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl); void GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl);
EmbeddedCode *code() const { return code_; } EmbeddedCode* code() const { return code_; }
private: private:
Type helper_type_; Type helper_type_;
EmbeddedCode *code_; EmbeddedCode* code_;
}; };
// The type and parameters of (uni-directional) flows of a connection. // The type and parameters of (uni-directional) flows of a connection.
class FlowField : public Field class FlowField : public Field
{ {
public: public:
FlowField(ID *flow_id, ParameterizedType *flow_type); FlowField(ID* flow_id, ParameterizedType* flow_type);
void GenInitCode(Output *out, Env *env); void GenInitCode(Output* out, Env* env);
}; };
class AnalyzerFlow : public AnalyzerElement class AnalyzerFlow : public AnalyzerElement
{ {
public: public:
enum Direction { UP, DOWN }; enum Direction
AnalyzerFlow(Direction dir, ID *type_id, ExprList *params); {
UP,
DOWN
};
AnalyzerFlow(Direction dir, ID* type_id, ExprList* params);
~AnalyzerFlow(); ~AnalyzerFlow();
Direction dir() const { return dir_; } Direction dir() const { return dir_; }
FlowField *flow_field() const { return flow_field_; } FlowField* flow_field() const { return flow_field_; }
FlowDecl *flow_decl(); FlowDecl* flow_decl();
private: private:
Direction dir_; Direction dir_;
ID *type_id_; ID* type_id_;
FlowField *flow_field_; FlowField* flow_field_;
FlowDecl *flow_decl_; FlowDecl* flow_decl_;
}; };
#endif // pac_analyzer_h #endif // pac_analyzer_h

View file

@ -1,3 +1,5 @@
#include "pac_array.h"
#include "pac_attr.h" #include "pac_attr.h"
#include "pac_dataptr.h" #include "pac_dataptr.h"
#include "pac_exception.h" #include "pac_exception.h"
@ -9,9 +11,7 @@
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_varfield.h" #include "pac_varfield.h"
#include "pac_array.h" ArrayType::ArrayType(Type* elemtype, Expr* length)
ArrayType::ArrayType(Type *elemtype, Expr *length)
: Type(ARRAY), elemtype_(elemtype), length_(length) : Type(ARRAY), elemtype_(elemtype), length_(length)
{ {
init(); init();
@ -67,9 +67,9 @@ ArrayType::~ArrayType()
delete elem_dataptr_until_expr_; delete elem_dataptr_until_expr_;
} }
Type *ArrayType::DoClone() const Type* ArrayType::DoClone() const
{ {
Type *elemtype = elemtype_->Clone(); Type* elemtype = elemtype_->Clone();
if ( ! elemtype ) if ( ! elemtype )
return 0; return 0;
return new ArrayType(elemtype, length_); return new ArrayType(elemtype, length_);
@ -85,45 +85,45 @@ string ArrayType::DataTypeStr() const
return datatype_str_; return datatype_str_;
} }
Type *ArrayType::ElementDataType() const Type* ArrayType::ElementDataType() const
{ {
return elemtype_; return elemtype_;
} }
string ArrayType::EvalElement(const string &array, const string &index) const string ArrayType::EvalElement(const string& array, const string& index) const
{ {
if ( attr_transient_ ) if ( attr_transient_ )
throw Exception(this, "cannot access element in &transient array"); throw Exception(this, "cannot access element in &transient array");
return strfmt("(*(%s))[%s]", array.c_str(), index.c_str()); return strfmt("(*(%s))[%s]", array.c_str(), index.c_str());
} }
const ID *ArrayType::arraylength_var() const const ID* ArrayType::arraylength_var() const
{ {
return arraylength_var_field_ ? arraylength_var_field_->id() : 0; return arraylength_var_field_ ? arraylength_var_field_->id() : 0;
} }
const ID *ArrayType::elem_it_var() const const ID* ArrayType::elem_it_var() const
{ {
return elem_it_var_field_ ? elem_it_var_field_->id() : 0; return elem_it_var_field_ ? elem_it_var_field_->id() : 0;
} }
const ID *ArrayType::elem_var() const const ID* ArrayType::elem_var() const
{ {
return elem_var_field_ ? elem_var_field_->id() : 0; return elem_var_field_ ? elem_var_field_->id() : 0;
} }
const ID *ArrayType::elem_dataptr_var() const const ID* ArrayType::elem_dataptr_var() const
{ {
return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : 0; return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : 0;
} }
const ID *ArrayType::elem_input_var() const const ID* ArrayType::elem_input_var() const
{ {
return elem_input_var_field_ ? elem_input_var_field_->id() : 0; return elem_input_var_field_ ? elem_input_var_field_->id() : 0;
} }
void ArrayType::ProcessAttr(Attr *a) void ArrayType::ProcessAttr(Attr* a)
{ {
Type::ProcessAttr(a); Type::ProcessAttr(a);
@ -133,15 +133,13 @@ void ArrayType::ProcessAttr(Attr *a)
{ {
if ( elemtype_->StaticSize(env()) != 1 ) if ( elemtype_->StaticSize(env()) != 1 )
{ {
throw Exception(elemtype_, throw Exception(elemtype_, "&restofdata can be applied"
"&restofdata can be applied" " to only byte arrays");
" to only byte arrays");
} }
if ( length_ ) if ( length_ )
{ {
throw Exception(length_, throw Exception(length_, "&restofdata cannot be applied"
"&restofdata cannot be applied" " to arrays with specified length");
" to arrays with specified length");
} }
attr_restofdata_ = true; attr_restofdata_ = true;
// As the array automatically extends to the end of // As the array automatically extends to the end of
@ -161,17 +159,15 @@ void ArrayType::ProcessAttr(Attr *a)
bool ref_input = a->expr()->HasReference(input_macro_id); bool ref_input = a->expr()->HasReference(input_macro_id);
if ( ref_element && ref_input ) if ( ref_element && ref_input )
{ {
throw Exception(a->expr(), throw Exception(a->expr(), "cannot reference both $element and $input "
"cannot reference both $element and $input " "in the same &until---please separate them.");
"in the same &until---please separate them.");
} }
if ( ref_element ) if ( ref_element )
{ {
if ( attr_until_element_expr_ ) if ( attr_until_element_expr_ )
{ {
throw Exception(a->expr(), throw Exception(a->expr(), "multiple &until on $element");
"multiple &until on $element");
} }
attr_until_element_expr_ = a->expr(); attr_until_element_expr_ = a->expr();
} }
@ -179,8 +175,7 @@ void ArrayType::ProcessAttr(Attr *a)
{ {
if ( attr_until_input_expr_ ) if ( attr_until_input_expr_ )
{ {
throw Exception(a->expr(), throw Exception(a->expr(), "multiple &until on $input");
"multiple &until on $input");
} }
attr_until_input_expr_ = a->expr(); attr_until_input_expr_ = a->expr();
} }
@ -188,8 +183,7 @@ void ArrayType::ProcessAttr(Attr *a)
{ {
if ( attr_generic_until_expr_ ) if ( attr_generic_until_expr_ )
{ {
throw Exception(a->expr(), throw Exception(a->expr(), "multiple &until condition");
"multiple &until condition");
} }
attr_generic_until_expr_ = a->expr(); attr_generic_until_expr_ = a->expr();
} }
@ -201,51 +195,42 @@ void ArrayType::ProcessAttr(Attr *a)
} }
} }
void ArrayType::Prepare(Env *env, int flags) void ArrayType::Prepare(Env* env, int flags)
{ {
if ( flags & TO_BE_PARSED ) if ( flags & TO_BE_PARSED )
{ {
ID *arraylength_var = new ID(strfmt("%s__arraylength", value_var()->Name())); ID* arraylength_var = new ID(strfmt("%s__arraylength", value_var()->Name()));
ID *elem_var = new ID(strfmt("%s__elem", value_var()->Name())); ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name()));
ID *elem_it_var = new ID(strfmt("%s__it", elem_var->Name())); ID* elem_it_var = new ID(strfmt("%s__it", elem_var->Name()));
elem_var_field_ = elem_var_field_ = new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_);
new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_);
AddField(elem_var_field_); AddField(elem_var_field_);
if ( incremental_parsing() ) if ( incremental_parsing() )
{ {
arraylength_var_field_ = arraylength_var_field_ = new PrivVarField(arraylength_var, extern_type_int->Clone());
new PrivVarField(arraylength_var, extern_type_int->Clone()); elem_it_var_field_ = new PrivVarField(elem_it_var, extern_type_int->Clone());
elem_it_var_field_ =
new PrivVarField(elem_it_var, extern_type_int->Clone());
AddField(arraylength_var_field_); AddField(arraylength_var_field_);
AddField(elem_it_var_field_); AddField(elem_it_var_field_);
} }
else else
{ {
arraylength_var_field_ = arraylength_var_field_ = new TempVarField(arraylength_var, extern_type_int->Clone());
new TempVarField(arraylength_var, extern_type_int->Clone()); elem_it_var_field_ = new TempVarField(elem_it_var, extern_type_int->Clone());
elem_it_var_field_ =
new TempVarField(elem_it_var, extern_type_int->Clone());
arraylength_var_field_->Prepare(env); arraylength_var_field_->Prepare(env);
elem_it_var_field_->Prepare(env); elem_it_var_field_->Prepare(env);
// Add elem_dataptr_var only when not parsing incrementally // Add elem_dataptr_var only when not parsing incrementally
ID *elem_dataptr_var = ID* elem_dataptr_var = new ID(strfmt("%s__dataptr", elem_var->Name()));
new ID(strfmt("%s__dataptr", elem_var->Name())); elem_dataptr_var_field_ = new TempVarField(elem_dataptr_var,
elem_dataptr_var_field_ = new TempVarField( extern_type_const_byteptr->Clone());
elem_dataptr_var,
extern_type_const_byteptr->Clone());
elem_dataptr_var_field_->Prepare(env); elem_dataptr_var_field_->Prepare(env);
// until(dataptr >= end_of_data) // until(dataptr >= end_of_data)
elem_dataptr_until_expr_ = new Expr( elem_dataptr_until_expr_ = new Expr(Expr::EXPR_GE, new Expr(elem_dataptr_var->clone()),
Expr::EXPR_GE, new Expr(end_of_data->clone()));
new Expr(elem_dataptr_var->clone()),
new Expr(end_of_data->clone()));
} }
if ( attr_until_input_expr_ ) if ( attr_until_input_expr_ )
@ -259,7 +244,7 @@ void ArrayType::Prepare(Env *env, int flags)
Type::Prepare(env, flags); Type::Prepare(env, flags);
} }
void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data) void ArrayType::GenArrayLength(Output* out_cc, Env* env, const DataPtr& data)
{ {
if ( env->Evaluated(arraylength_var()) ) if ( env->Evaluated(arraylength_var()) )
return; return;
@ -272,23 +257,17 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data)
if ( length_ ) if ( length_ )
{ {
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(arraylength_var()), length_->EvalExpr(out_cc, env));
env->LValue(arraylength_var()),
length_->EvalExpr(out_cc, env));
env->SetEvaluated(arraylength_var()); env->SetEvaluated(arraylength_var());
// Check negative array length // Check negative array length
out_cc->println("if ( %s < 0 )", out_cc->println("if ( %s < 0 )", env->LValue(arraylength_var()));
env->LValue(arraylength_var()));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str());
data_id_str_.c_str()); out_cc->println(" %s, (%s) - (%s));", env->LValue(arraylength_var()),
out_cc->println(" %s, (%s) - (%s));", env->RValue(end_of_data), env->RValue(begin_of_data));
env->LValue(arraylength_var()),
env->RValue(end_of_data),
env->RValue(begin_of_data));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
@ -305,15 +284,13 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data)
// with it. Note that this check is *not* looking for whether the // with it. Note that this check is *not* looking for whether the
// contents of the array will extend past the end of the data // contents of the array will extend past the end of the data
// buffer. // buffer.
out_cc->println("// Check array element quantity: %s", out_cc->println("// Check array element quantity: %s", data_id_str_.c_str());
data_id_str_.c_str());
element_size = 1; element_size = 1;
} }
else else
{ {
// Boundary check the entire array if elements have static size. // Boundary check the entire array if elements have static size.
out_cc->println("// Check bounds for static-size array: %s", out_cc->println("// Check bounds for static-size array: %s", data_id_str_.c_str());
data_id_str_.c_str());
elemtype_->SetBoundaryChecked(); elemtype_->SetBoundaryChecked();
element_size = elemtype_->StaticSize(env); element_size = elemtype_->StaticSize(env);
@ -325,66 +302,57 @@ void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data)
// arbitrary number of empty records (i.e. cheap for them, // arbitrary number of empty records (i.e. cheap for them,
// but costly for us unless we have special optimization // but costly for us unless we have special optimization
// for this scenario to forgo the usual allocation). // for this scenario to forgo the usual allocation).
throw Exception(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(); const char* array_ptr_expr = data.ptr_expr();
string max_elements_available = strfmt("((%s - %s) / %d)", string max_elements_available = strfmt("((%s - %s) / %d)", env->RValue(end_of_data),
env->RValue(end_of_data), array_ptr_expr, element_size);
array_ptr_expr,
element_size);
out_cc->println("if ( %s > %s )", out_cc->println("if ( %s > %s )", env->RValue(arraylength_var()),
env->RValue(arraylength_var()),
max_elements_available.c_str()); max_elements_available.c_str());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_id_str_.c_str());
data_id_str_.c_str()); out_cc->println(" %s, (%s) - (%s));", env->RValue(arraylength_var()),
out_cc->println(" %s, (%s) - (%s));", env->RValue(end_of_data), array_ptr_expr);
env->RValue(arraylength_var()),
env->RValue(end_of_data),
array_ptr_expr);
out_cc->dec_indent(); out_cc->dec_indent();
} }
else if ( attr_restofdata_ ) else if ( attr_restofdata_ )
{ {
ASSERT(elemtype_->StaticSize(env) == 1); ASSERT(elemtype_->StaticSize(env) == 1);
out_cc->println("%s = (%s) - (%s);", out_cc->println("%s = (%s) - (%s);", env->LValue(arraylength_var()),
env->LValue(arraylength_var()), env->RValue(end_of_data), data.ptr_expr());
env->RValue(end_of_data),
data.ptr_expr());
env->SetEvaluated(arraylength_var()); env->SetEvaluated(arraylength_var());
} }
} }
void ArrayType::GenPubDecls(Output *out_h, Env *env) void ArrayType::GenPubDecls(Output* out_h, Env* env)
{ {
Type::GenPubDecls(out_h, env); Type::GenPubDecls(out_h, env);
if ( declared_as_type() ) if ( declared_as_type() )
{ {
if ( attr_transient_ ) if ( attr_transient_ )
throw Exception(this, "cannot access element in &transient array"); throw Exception(this, "cannot access element in &transient array");
out_h->println("int size() const { return %s ? %s->size() : 0; }", out_h->println("int size() const { return %s ? %s->size() : 0; }",
env->RValue(value_var()), env->RValue(value_var()), env->RValue(value_var()));
env->RValue(value_var()));
out_h->println("%s operator[](int index) const { BINPAC_ASSERT(%s); return (*%s)[index]; }", out_h->println("%s operator[](int index) const { BINPAC_ASSERT(%s); return (*%s)[index]; }",
elemtype_->DataTypeConstRefStr().c_str(), elemtype_->DataTypeConstRefStr().c_str(), env->RValue(value_var()),
env->RValue(value_var()), env->RValue(value_var()));
env->RValue(value_var()));
} }
} }
void ArrayType::GenPrivDecls(Output *out_h, Env *env) void ArrayType::GenPrivDecls(Output* out_h, Env* env)
{ {
ASSERT(elem_var_field_->type() == elemtype_); ASSERT(elem_var_field_->type() == elemtype_);
ASSERT(elemtype_->value_var()); ASSERT(elemtype_->value_var());
Type::GenPrivDecls(out_h, env); Type::GenPrivDecls(out_h, env);
} }
void ArrayType::GenInitCode(Output *out_cc, Env *env) void ArrayType::GenInitCode(Output* out_cc, Env* env)
{ {
// Do not initiate the array here // Do not initiate the array here
// out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str()); // out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str());
@ -393,24 +361,19 @@ void ArrayType::GenInitCode(Output *out_cc, Env *env)
Type::GenInitCode(out_cc, env); Type::GenInitCode(out_cc, env);
if ( incremental_parsing() ) if ( incremental_parsing() )
{ {
out_cc->println("%s = -1;", out_cc->println("%s = -1;", env->LValue(elem_it_var()));
env->LValue(elem_it_var()));
} }
} }
void ArrayType::GenCleanUpCode(Output *out_cc, Env *env) void ArrayType::GenCleanUpCode(Output* out_cc, Env* env)
{ {
Type::GenCleanUpCode(out_cc, env); Type::GenCleanUpCode(out_cc, env);
if ( elemtype_->NeedsCleanUp() ) if ( elemtype_->NeedsCleanUp() )
{ {
if ( ! elem_var_field_ ) if ( ! elem_var_field_ )
{ {
ID *elem_var = new ID(strfmt("%s__elem", value_var()->Name())); ID* elem_var = new ID(strfmt("%s__elem", value_var()->Name()));
elem_var_field_ = elem_var_field_ = new ParseVarField(Field::NOT_CLASS_MEMBER, elem_var, elemtype_);
new ParseVarField(
Field::NOT_CLASS_MEMBER,
elem_var,
elemtype_);
elem_var_field_->Prepare(env); elem_var_field_->Prepare(env);
} }
@ -418,14 +381,11 @@ void ArrayType::GenCleanUpCode(Output *out_cc, Env *env)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("for ( int i = 0; i < (int) %s->size(); ++i )", out_cc->println("for ( int i = 0; i < (int) %s->size(); ++i )", env->RValue(value_var()));
env->RValue(value_var()));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("%s %s = (*%s)[i];", out_cc->println("%s %s = (*%s)[i];", elemtype_->DataTypeStr().c_str(),
elemtype_->DataTypeStr().c_str(), env->LValue(elem_var()), lvalue());
env->LValue(elem_var()),
lvalue());
elemtype_->GenCleanUpCode(out_cc, env); elemtype_->GenCleanUpCode(out_cc, env);
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
@ -436,28 +396,25 @@ void ArrayType::GenCleanUpCode(Output *out_cc, Env *env)
out_cc->println("delete %s;", lvalue()); out_cc->println("delete %s;", lvalue());
} }
string ArrayType::GenArrayInit(Output *out_cc, Env *env, bool known_array_length) string ArrayType::GenArrayInit(Output* out_cc, Env* env, bool known_array_length)
{ {
string array_str; string array_str;
array_str = lvalue(); array_str = lvalue();
if ( incremental_parsing() ) if ( incremental_parsing() )
{ {
out_cc->println("if ( %s < 0 )", out_cc->println("if ( %s < 0 )", env->LValue(elem_it_var()));
env->LValue(elem_it_var()));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("// Initialize only once"); out_cc->println("// Initialize only once");
out_cc->println("%s = 0;", env->LValue(elem_it_var())); out_cc->println("%s = 0;", env->LValue(elem_it_var()));
} }
out_cc->println("%s = new %s;", out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str());
lvalue(), vector_str_.c_str());
if ( known_array_length ) if ( known_array_length )
{ {
out_cc->println("%s->reserve(%s);", out_cc->println("%s->reserve(%s);", lvalue(), env->RValue(arraylength_var()));
lvalue(), env->RValue(arraylength_var()));
} }
if ( incremental_parsing() ) if ( incremental_parsing() )
@ -469,34 +426,29 @@ string ArrayType::GenArrayInit(Output *out_cc, Env *env, bool known_array_length
return array_str; return array_str;
} }
void ArrayType::GenElementAssignment(Output *out_cc, Env *env, void ArrayType::GenElementAssignment(Output* out_cc, Env* env, string const& array_str,
string const &array_str, bool use_vector) bool use_vector)
{ {
if ( attr_transient_ ) if ( attr_transient_ )
{ {
// Just discard. // Just discard.
out_cc->println("delete %s;", env->LValue(elem_var())); out_cc->println("delete %s;", env->LValue(elem_var()));
return; return;
} }
// Assign the element // Assign the element
if ( ! use_vector ) if ( ! use_vector )
{ {
out_cc->println("%s[%s] = %s;", out_cc->println("%s[%s] = %s;", array_str.c_str(), env->LValue(elem_it_var()),
array_str.c_str(), env->LValue(elem_var()));
env->LValue(elem_it_var()),
env->LValue(elem_var()));
} }
else else
{ {
out_cc->println("%s->push_back(%s);", out_cc->println("%s->push_back(%s);", array_str.c_str(), env->LValue(elem_var()));
array_str.c_str(),
env->LValue(elem_var()));
} }
} }
void ArrayType::DoGenParseCode(Output *out_cc, Env *env, void ArrayType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
const DataPtr& data, int flags)
{ {
GenArrayLength(out_cc, env, data); GenArrayLength(out_cc, env, data);
@ -518,7 +470,7 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env,
There are two cases when the input length can be determined: There are two cases when the input length can be determined:
1. The array has a static size; 1. The array has a static size;
2. The array length can be computed before parsing and 2. The array length can be computed before parsing and
each element is of constant size. each element is of constant size.
*/ */
bool compute_size_var = false; bool compute_size_var = false;
@ -529,9 +481,8 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env,
compute_size_var = false; compute_size_var = false;
if ( ! incremental_parsing() && if ( ! incremental_parsing() &&
( StaticSize(env) >= 0 || (StaticSize(env) >= 0 ||
( env->Evaluated(arraylength_var()) && (env->Evaluated(arraylength_var()) && elemtype_->StaticSize(env) >= 0)) )
elemtype_->StaticSize(env) >= 0 ) ) )
{ {
GenBoundaryCheck(out_cc, env, data); GenBoundaryCheck(out_cc, env, data);
} }
@ -552,22 +503,17 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env,
if ( elem_dataptr_var() ) if ( elem_dataptr_var() )
{ {
out_cc->println("const_byteptr %s = %s;", out_cc->println("const_byteptr %s = %s;", env->LValue(elem_dataptr_var()), data.ptr_expr());
env->LValue(elem_dataptr_var()), data.ptr_expr());
env->SetEvaluated(elem_dataptr_var()); env->SetEvaluated(elem_dataptr_var());
elem_data = DataPtr(env, elem_dataptr_var(), 0); elem_data = DataPtr(env, elem_dataptr_var(), 0);
} }
string for_condition = known_array_length ? string for_condition = known_array_length ? strfmt("%s < %s", env->LValue(elem_it_var()),
strfmt("%s < %s", env->RValue(arraylength_var()))
env->LValue(elem_it_var()), : "/* forever */";
env->RValue(arraylength_var())) :
"/* forever */";
out_cc->println("for (; %s; ++%s)", out_cc->println("for (; %s; ++%s)", for_condition.c_str(), env->LValue(elem_it_var()));
for_condition.c_str(),
env->LValue(elem_it_var()));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
@ -597,8 +543,7 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env,
if ( incremental_parsing() ) if ( incremental_parsing() )
{ {
out_cc->println("if ( ! %s )", out_cc->println("if ( ! %s )", elemtype_->parsing_complete(env).c_str());
elemtype_->parsing_complete(env).c_str());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("goto %s;", kNeedMoreData); out_cc->println("goto %s;", kNeedMoreData);
out_cc->dec_indent(); out_cc->dec_indent();
@ -608,12 +553,10 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env,
if ( elem_dataptr_var() ) if ( elem_dataptr_var() )
{ {
out_cc->println("%s += %s;", out_cc->println("%s += %s;", env->LValue(elem_dataptr_var()),
env->LValue(elem_dataptr_var()), elemtype_->DataSize(0, env, elem_data).c_str());
elemtype_->DataSize(0, env, elem_data).c_str()); out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(elem_dataptr_var()),
out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(end_of_data));
env->RValue(elem_dataptr_var()),
env->RValue(end_of_data));
} }
if ( attr_until_element_expr_ ) if ( attr_until_element_expr_ )
@ -632,55 +575,45 @@ void ArrayType::DoGenParseCode(Output *out_cc, Env *env,
if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) ) if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) )
{ {
// Compute the data size // Compute the data size
out_cc->println("%s = %s - (%s);", out_cc->println("%s = %s - (%s);", env->LValue(size_var()), env->RValue(elem_dataptr_var()),
env->LValue(size_var()), data.ptr_expr());
env->RValue(elem_dataptr_var()),
data.ptr_expr());
env->SetEvaluated(size_var()); env->SetEvaluated(size_var());
} }
} }
void ArrayType::GenUntilInputCheck(Output *out_cc, Env *env) void ArrayType::GenUntilInputCheck(Output* out_cc, Env* env)
{ {
ID *elem_input_var_id = new ID( ID* elem_input_var_id = new ID(strfmt("%s__elem_input", value_var()->Name()));
strfmt("%s__elem_input", value_var()->Name())); elem_input_var_field_ = new TempVarField(elem_input_var_id,
elem_input_var_field_ = new TempVarField( extern_type_const_bytestring->Clone());
elem_input_var_id, extern_type_const_bytestring->Clone());
elem_input_var_field_->Prepare(env); elem_input_var_field_->Prepare(env);
out_cc->println("%s %s(%s, %s);", out_cc->println("%s %s(%s, %s);", extern_type_const_bytestring->DataTypeStr().c_str(),
extern_type_const_bytestring->DataTypeStr().c_str(), env->LValue(elem_input_var()), env->RValue(begin_of_data),
env->LValue(elem_input_var()), env->RValue(end_of_data));
env->RValue(begin_of_data),
env->RValue(end_of_data));
env->SetEvaluated(elem_input_var()); env->SetEvaluated(elem_input_var());
GenUntilCheck(out_cc, env, attr_until_input_expr_, true); GenUntilCheck(out_cc, env, attr_until_input_expr_, true);
} }
void ArrayType::GenUntilCheck(Output *out_cc, Env *env, void ArrayType::GenUntilCheck(Output* out_cc, Env* env, Expr* until_expr, bool delete_elem)
Expr *until_expr, bool delete_elem)
{ {
ASSERT(until_expr); ASSERT(until_expr);
Env check_env(env, this); Env check_env(env, this);
check_env.AddMacro(element_macro_id, check_env.AddMacro(element_macro_id, new Expr(elem_var()->clone()));
new Expr(elem_var()->clone()));
if ( elem_input_var() ) if ( elem_input_var() )
{ {
check_env.AddMacro(input_macro_id, check_env.AddMacro(input_macro_id, new Expr(elem_input_var()->clone()));
new Expr(elem_input_var()->clone()));
} }
out_cc->println("// Check &until(%s)", until_expr->orig()); out_cc->println("// Check &until(%s)", until_expr->orig());
out_cc->println("if ( %s )", out_cc->println("if ( %s )", until_expr->EvalExpr(out_cc, &check_env));
until_expr->EvalExpr(out_cc, &check_env));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
if ( parsing_complete_var() ) if ( parsing_complete_var() )
{ {
out_cc->println("%s = true;", out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
env->LValue(parsing_complete_var()));
} }
if ( elemtype_->IsPointerType() ) if ( elemtype_->IsPointerType() )
@ -696,18 +629,14 @@ void ArrayType::GenUntilCheck(Output *out_cc, Env *env,
out_cc->dec_indent(); out_cc->dec_indent();
} }
void ArrayType::GenDynamicSize(Output *out_cc, Env *env, void ArrayType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
const DataPtr& data)
{ {
ASSERT(! incremental_input()); ASSERT(! incremental_input());
DEBUG_MSG("Generating dynamic size for array `%s'\n", DEBUG_MSG("Generating dynamic size for array `%s'\n", value_var()->Name());
value_var()->Name());
int elem_w = elemtype_->StaticSize(env); int elem_w = elemtype_->StaticSize(env);
if ( elem_w >= 0 && if ( elem_w >= 0 && ! attr_until_element_expr_ && ! attr_until_input_expr_ &&
! attr_until_element_expr_ && (length_ || attr_restofdata_) )
! attr_until_input_expr_ &&
( length_ || attr_restofdata_ ) )
{ {
// If the elements have a fixed size, // If the elements have a fixed size,
// we only need to compute the number of elements // we only need to compute the number of elements
@ -715,8 +644,8 @@ void ArrayType::GenDynamicSize(Output *out_cc, Env *env,
ASSERT(compute_size_var); ASSERT(compute_size_var);
GenArrayLength(out_cc, env, data); GenArrayLength(out_cc, env, data);
ASSERT(env->Evaluated(arraylength_var())); ASSERT(env->Evaluated(arraylength_var()));
out_cc->println("%s = %d * %s;", out_cc->println("%s = %d * %s;", env->LValue(size_var()), elem_w,
env->LValue(size_var()), elem_w, env->RValue(arraylength_var())); env->RValue(arraylength_var()));
env->SetEvaluated(size_var()); env->SetEvaluated(size_var());
} }
else else
@ -726,7 +655,7 @@ void ArrayType::GenDynamicSize(Output *out_cc, Env *env,
} }
} }
int ArrayType::StaticSize(Env *env) const int ArrayType::StaticSize(Env* env) const
{ {
int num = 0; int num = 0;
@ -737,8 +666,7 @@ int ArrayType::StaticSize(Env *env) const
if ( elem_w < 0 ) if ( elem_w < 0 )
return -1; return -1;
DEBUG_MSG("static size of %s:%s = %d * %d\n", DEBUG_MSG("static size of %s:%s = %d * %d\n", decl_id()->Name(), lvalue(), elem_w, num);
decl_id()->Name(), lvalue(), elem_w, num);
return num * elem_w; return num * elem_w;
} }
@ -767,12 +695,11 @@ void ArrayType::DoMarkIncrementalInput()
bool ArrayType::RequiresAnalyzerContext() bool ArrayType::RequiresAnalyzerContext()
{ {
return Type::RequiresAnalyzerContext() || return Type::RequiresAnalyzerContext() || (length_ && length_->RequiresAnalyzerContext()) ||
( length_ && length_->RequiresAnalyzerContext() ) ||
elemtype_->RequiresAnalyzerContext(); elemtype_->RequiresAnalyzerContext();
} }
bool ArrayType::DoTraverse(DataDepVisitor *visitor) bool ArrayType::DoTraverse(DataDepVisitor* visitor)
{ {
if ( ! Type::DoTraverse(visitor) ) if ( ! Type::DoTraverse(visitor) )
return false; return false;

View file

@ -7,86 +7,81 @@
// Fixed-length array and variable length sequence with an ending pattern // Fixed-length array and variable length sequence with an ending pattern
class ArrayType : public Type class ArrayType : public Type
{ {
public: public:
ArrayType(Type *arg_elemtype, Expr *arg_length = 0); ArrayType(Type* arg_elemtype, Expr* arg_length = 0);
~ArrayType(); ~ArrayType();
bool DefineValueVar() const; bool DefineValueVar() const;
string DataTypeStr() const; string DataTypeStr() const;
string DefaultValue() const { return "0"; } string DefaultValue() const { return "0"; }
Type *ElementDataType() const; Type* ElementDataType() const;
string EvalElement(const string &array, const string &index) const; string EvalElement(const string& array, const string& index) const;
void ProcessAttr(Attr *a); void ProcessAttr(Attr* a);
void Prepare(Env *env, int flags); void Prepare(Env* env, int flags);
void GenPubDecls(Output *out, Env *env); void GenPubDecls(Output* out, Env* env);
void GenPrivDecls(Output *out, Env *env); void GenPrivDecls(Output* out, Env* env);
void GenInitCode(Output *out, Env *env); void GenInitCode(Output* out, Env* env);
void GenCleanUpCode(Output *out, Env *env); void GenCleanUpCode(Output* out, Env* env);
int StaticSize(Env *env) const; int StaticSize(Env* env) const;
void SetBoundaryChecked(); void SetBoundaryChecked();
void GenUntilInputCheck(Output *out_cc, Env *env); void GenUntilInputCheck(Output* out_cc, Env* env);
bool IsPointerType() const { return true; } bool IsPointerType() const { return true; }
protected: protected:
void init(); void init();
void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags);
void GenDynamicSize(Output *out, Env *env, const DataPtr& data); void GenDynamicSize(Output* out, Env* env, const DataPtr& data);
void GenArrayLength(Output *out_cc, Env *env, const DataPtr& data); void GenArrayLength(Output* out_cc, Env* env, const DataPtr& data);
string GenArrayInit(Output *out_cc, Env *env, bool known_array_length); string GenArrayInit(Output* out_cc, Env* env, bool known_array_length);
void GenElementAssignment(Output *out_cc, Env *env, void GenElementAssignment(Output* out_cc, Env* env, string const& array_str, bool use_vector);
string const &array_str, bool use_vector); void GenUntilCheck(Output* out_cc, Env* env, Expr* until_condition, bool delete_elem);
void GenUntilCheck(Output *out_cc, Env *env,
Expr *until_condition, bool delete_elem);
bool ByteOrderSensitive() const bool ByteOrderSensitive() const { return elemtype_->RequiresByteOrder(); }
{
return elemtype_->RequiresByteOrder();
}
bool RequiresAnalyzerContext(); bool RequiresAnalyzerContext();
Type *DoClone() const; Type* DoClone() const;
void DoMarkIncrementalInput(); void DoMarkIncrementalInput();
const ID *arraylength_var() const; const ID* arraylength_var() const;
const ID *elem_it_var() const; const ID* elem_it_var() const;
const ID *elem_var() const; const ID* elem_var() const;
const ID *elem_dataptr_var() const; const ID* elem_dataptr_var() const;
const ID *elem_input_var() const; const ID* elem_input_var() const;
protected: protected:
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
private: private:
Type *elemtype_; Type* elemtype_;
Expr *length_; Expr* length_;
string vector_str_; string vector_str_;
string datatype_str_; string datatype_str_;
string end_of_array_loop_label_; string end_of_array_loop_label_;
Field *arraylength_var_field_; Field* arraylength_var_field_;
Field *elem_it_var_field_; Field* elem_it_var_field_;
Field *elem_var_field_; Field* elem_var_field_;
Field *elem_dataptr_var_field_; Field* elem_dataptr_var_field_;
Field *elem_input_var_field_; Field* elem_input_var_field_;
// This does not come from &until, but is internally generated // This does not come from &until, but is internally generated
Expr *elem_dataptr_until_expr_; Expr* elem_dataptr_until_expr_;
Expr *attr_generic_until_expr_; Expr* attr_generic_until_expr_;
Expr *attr_until_element_expr_; Expr* attr_until_element_expr_;
Expr *attr_until_input_expr_; Expr* attr_until_input_expr_;
}; };
#endif // pac_array_h #endif // pac_array_h

View file

@ -1,7 +1,8 @@
#include "pac_attr.h" #include "pac_attr.h"
#include "pac_expr.h" #include "pac_expr.h"
bool Attr::DoTraverse(DataDepVisitor *visitor) bool Attr::DoTraverse(DataDepVisitor* visitor)
{ {
if ( expr_ && ! expr_->Traverse(visitor) ) if ( expr_ && ! expr_->Traverse(visitor) )
return false; return false;
@ -20,23 +21,20 @@ void Attr::init()
delete_expr_ = false; delete_expr_ = false;
} }
Attr::Attr(AttrType type) Attr::Attr(AttrType type) : DataDepElement(DataDepElement::ATTR)
: DataDepElement(DataDepElement::ATTR)
{ {
type_ = type; type_ = type;
init(); init();
} }
Attr::Attr(AttrType type, Expr *expr) Attr::Attr(AttrType type, Expr* expr) : DataDepElement(DataDepElement::ATTR)
: DataDepElement(DataDepElement::ATTR)
{ {
type_ = type; type_ = type;
init(); init();
expr_ = expr; expr_ = expr;
} }
Attr::Attr(AttrType type, ExprList *exprlist) Attr::Attr(AttrType type, ExprList* exprlist) : DataDepElement(DataDepElement::ATTR)
: DataDepElement(DataDepElement::ATTR)
{ {
type_ = type; type_ = type;
init(); init();
@ -44,8 +42,7 @@ Attr::Attr(AttrType type, ExprList *exprlist)
delete_expr_ = true; delete_expr_ = true;
} }
Attr::Attr(AttrType type, SeqEnd *seqend) Attr::Attr(AttrType type, SeqEnd* seqend) : DataDepElement(DataDepElement::ATTR)
: DataDepElement(DataDepElement::ATTR)
{ {
type_ = type; type_ = type;
init(); init();
@ -58,8 +55,7 @@ Attr::~Attr()
delete expr_; delete expr_;
} }
LetAttr::LetAttr(FieldList *letfields) LetAttr::LetAttr(FieldList* letfields) : Attr(ATTR_LET)
: Attr(ATTR_LET)
{ {
letfields_ = letfields; letfields_ = letfields;
} }

View file

@ -4,7 +4,8 @@
#include "pac_common.h" #include "pac_common.h"
#include "pac_datadep.h" #include "pac_datadep.h"
enum AttrType { enum AttrType
{
ATTR_BYTEORDER, ATTR_BYTEORDER,
ATTR_CHECK, ATTR_CHECK,
ATTR_CHUNKED, ATTR_CHUNKED,
@ -22,44 +23,44 @@ enum AttrType {
ATTR_RESTOFFLOW, ATTR_RESTOFFLOW,
ATTR_TRANSIENT, ATTR_TRANSIENT,
ATTR_UNTIL, ATTR_UNTIL,
}; };
class Attr : public Object, public DataDepElement class Attr : public Object, public DataDepElement
{ {
public: public:
Attr(AttrType type); Attr(AttrType type);
Attr(AttrType type, Expr *expr); Attr(AttrType type, Expr* expr);
Attr(AttrType type, ExprList *exprlist); Attr(AttrType type, ExprList* exprlist);
Attr(AttrType type, SeqEnd *seqend); Attr(AttrType type, SeqEnd* seqend);
virtual ~Attr(); virtual ~Attr();
AttrType type() const { return type_; } AttrType type() const { return type_; }
Expr *expr() const { return expr_; } Expr* expr() const { return expr_; }
SeqEnd *seqend() const { return seqend_; } SeqEnd* seqend() const { return seqend_; }
bool RequiresAnalyzerContext() const; bool RequiresAnalyzerContext() const;
protected: protected:
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
protected: protected:
void init(); void init();
AttrType type_; AttrType type_;
Expr *expr_; Expr* expr_;
SeqEnd *seqend_; SeqEnd* seqend_;
bool delete_expr_; bool delete_expr_;
}; };
class LetAttr : public Attr class LetAttr : public Attr
{ {
public: public:
LetAttr(FieldList *letfields); LetAttr(FieldList* letfields);
FieldList *letfields() const { return letfields_; } FieldList* letfields() const { return letfields_; }
private: private:
FieldList *letfields_; FieldList* letfields_;
}; };
#endif // pac_attr_h #endif // pac_attr_h

View file

@ -1,9 +1,10 @@
#include "pac_btype.h" #include "pac_btype.h"
#include "pac_dataptr.h" #include "pac_dataptr.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_output.h" #include "pac_output.h"
Type *BuiltInType::DoClone() const Type* BuiltInType::DoClone() const
{ {
return new BuiltInType(bit_type()); return new BuiltInType(bit_type());
} }
@ -11,20 +12,19 @@ Type *BuiltInType::DoClone() const
bool BuiltInType::IsNumericType() const bool BuiltInType::IsNumericType() const
{ {
BITType t = bit_type(); BITType t = bit_type();
return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || return (t == INT8 || t == INT16 || t == INT32 || t == INT64 || t == UINT8 || t == UINT16 ||
t == UINT8 || t == UINT16 || t == UINT32 || t == UINT64); t == UINT32 || t == UINT64);
} }
bool BuiltInType::CompatibleBuiltInTypes(BuiltInType *type1, bool BuiltInType::CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2)
BuiltInType *type2)
{ {
return type1->IsNumericType() && type2->IsNumericType(); return type1->IsNumericType() && type2->IsNumericType();
} }
static const char* basic_pactype_name[] = { static const char* basic_pactype_name[] = {
# define TYPE_DEF(name, pactype, ctype, size) pactype, #define TYPE_DEF(name, pactype, ctype, size) pactype,
# include "pac_type.def" #include "pac_type.def"
# undef TYPE_DEF #undef TYPE_DEF
0, 0,
}; };
@ -32,9 +32,7 @@ void BuiltInType::static_init()
{ {
for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type ) for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type )
{ {
Type::AddPredefinedType( Type::AddPredefinedType(basic_pactype_name[bit_type], new BuiltInType((BITType)bit_type));
basic_pactype_name[bit_type],
new BuiltInType((BITType) bit_type));
} }
} }
@ -48,9 +46,9 @@ int BuiltInType::LookUpByName(const char* name)
} }
static const char* basic_ctype_name[] = { static const char* basic_ctype_name[] = {
# define TYPE_DEF(name, pactype, ctype, size) ctype, #define TYPE_DEF(name, pactype, ctype, size) ctype,
# include "pac_type.def" #include "pac_type.def"
# undef TYPE_DEF #undef TYPE_DEF
0, 0,
}; };
@ -66,12 +64,11 @@ string BuiltInType::DataTypeStr() const
int BuiltInType::StaticSize(Env* /* env */) const int BuiltInType::StaticSize(Env* /* env */) const
{ {
static const size_t basic_type_size[] = static const size_t basic_type_size[] = {
{ #define TYPE_DEF(name, pactype, ctype, size) size,
# define TYPE_DEF(name, pactype, ctype, size) size, #include "pac_type.def"
# include "pac_type.def" #undef TYPE_DEF
# undef TYPE_DEF };
};
return basic_type_size[bit_type_]; return basic_type_size[bit_type_];
} }
@ -96,8 +93,7 @@ void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
ASSERT(0); ASSERT(0);
} }
void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, void BuiltInType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
const DataPtr& data, int flags)
{ {
if ( bit_type_ == EMPTY ) if ( bit_type_ == EMPTY )
return; return;
@ -118,8 +114,8 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env,
case INT8: case INT8:
case UINT8: case UINT8:
out_cc->println("%s = *((%s const *) (%s));", out_cc->println("%s = *((%s const *) (%s));", lvalue(), DataTypeStr().c_str(),
lvalue(), DataTypeStr().c_str(), data.ptr_expr()); data.ptr_expr());
break; break;
case INT16: case INT16:
case UINT16: case UINT16:
@ -134,13 +130,10 @@ void BuiltInType::DoGenParseCode(Output* out_cc, Env* env,
data.ptr_expr(), data.ptr_expr(),
EvalByteOrder(out_cc, env).c_str()); EvalByteOrder(out_cc, env).c_str());
#else #else
out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));", lvalue(),
lvalue(), EvalByteOrder(out_cc, env).c_str(), DataTypeStr().c_str(),
EvalByteOrder(out_cc, env).c_str(), data.ptr_expr());
DataTypeStr().c_str(),
data.ptr_expr());
#endif #endif
break; break;
} }
} }

View file

@ -4,49 +4,50 @@
#include "pac_type.h" #include "pac_type.h"
class BuiltInType : public Type class BuiltInType : public Type
{ {
public: public:
enum BITType { enum BITType
# define TYPE_DEF(name, pactype, ctype, size) name, {
# include "pac_type.def" #define TYPE_DEF(name, pactype, ctype, size) name,
# undef TYPE_DEF #include "pac_type.def"
}; #undef TYPE_DEF
};
static int LookUpByName(const char *name); static int LookUpByName(const char* name);
BuiltInType(BITType bit_type) BuiltInType(BITType bit_type)
: Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN), : Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN), bit_type_(bit_type)
bit_type_(bit_type) {} {
}
BITType bit_type() const { return bit_type_; } BITType bit_type() const { return bit_type_; }
bool IsNumericType() const; bool IsNumericType() const;
bool DefineValueVar() const; bool DefineValueVar() const;
string DataTypeStr() const; string DataTypeStr() const;
string DefaultValue() const { return "0"; } string DefaultValue() const { return "0"; }
int StaticSize(Env *env) const; int StaticSize(Env* env) const;
bool IsPointerType() const { return false; } bool IsPointerType() const { return false; }
bool ByteOrderSensitive() const { return StaticSize(0) >= 2; } bool ByteOrderSensitive() const { return StaticSize(0) >= 2; }
void GenInitCode(Output *out_cc, Env *env); void GenInitCode(Output* out_cc, Env* env);
void DoMarkIncrementalInput(); void DoMarkIncrementalInput();
protected: protected:
void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags);
void GenDynamicSize(Output *out, Env *env, const DataPtr& data); void GenDynamicSize(Output* out, Env* env, const DataPtr& data);
Type *DoClone() const; Type* DoClone() const;
BITType bit_type_; BITType bit_type_;
public: public:
static void static_init(); static void static_init();
static bool CompatibleBuiltInTypes(BuiltInType *type1, static bool CompatibleBuiltInTypes(BuiltInType* type1, BuiltInType* type2);
BuiltInType *type2); };
};
#endif // pac_btype_h #endif // pac_btype_h

View file

@ -1,3 +1,9 @@
#include "pac_case.h"
#include <stdint.h>
#include <limits>
#include "pac_btype.h"
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_exttype.h" #include "pac_exttype.h"
@ -5,18 +11,12 @@
#include "pac_output.h" #include "pac_output.h"
#include "pac_typedecl.h" #include "pac_typedecl.h"
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_btype.h"
#include "pac_case.h"
#include <limits>
#include <stdint.h>
CaseType::CaseType(Expr* index_expr, CaseFieldList* cases) CaseType::CaseType(Expr* index_expr, CaseFieldList* cases)
: Type(CASE), index_expr_(index_expr), cases_(cases) : Type(CASE), index_expr_(index_expr), cases_(cases)
{ {
index_var_ = 0; index_var_ = 0;
foreach(i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
AddField(*i); AddField(*i);
} }
@ -27,10 +27,10 @@ CaseType::~CaseType()
delete cases_; delete cases_;
} }
void CaseType::AddCaseField(CaseField *f) void CaseType::AddCaseField(CaseField* f)
{ {
// All fields must be added before Prepare() // All fields must be added before Prepare()
ASSERT(!env()); ASSERT(! env());
AddField(f); AddField(f);
cases_->push_back(f); cases_->push_back(f);
@ -47,11 +47,11 @@ string CaseType::DataTypeStr() const
return strfmt("%s *", type_decl()->class_name().c_str()); return strfmt("%s *", type_decl()->class_name().c_str());
} }
Type *CaseType::ValueType() const Type* CaseType::ValueType() const
{ {
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
{ {
CaseField *c = *i; CaseField* c = *i;
return c->type(); return c->type();
} }
ASSERT(0); ASSERT(0);
@ -73,13 +73,12 @@ void CaseType::Prepare(Env* env, int flags)
env->AddID(index_var_, MEMBER_VAR, 0); env->AddID(index_var_, MEMBER_VAR, 0);
// Sort the cases_ to put the default case at the end of the list // Sort the cases_ to put the default case at the end of the list
CaseFieldList::iterator default_case_it = CaseFieldList::iterator default_case_it = cases_->end(); // to avoid warning
cases_->end(); // to avoid warning CaseField* default_case = 0;
CaseField *default_case = 0;
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
{ {
CaseField *c = *i; CaseField* c = *i;
if ( ! c->index() ) if ( ! c->index() )
{ {
if ( default_case ) if ( default_case )
@ -96,7 +95,7 @@ void CaseType::Prepare(Env* env, int flags)
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
{ {
CaseField *c = *i; CaseField* c = *i;
c->set_index_var(index_var_); c->set_index_var(index_var_);
c->set_case_type(this); c->set_case_type(this);
} }
@ -124,8 +123,8 @@ void CaseType::GenPubDecls(Output* out_h, Env* env)
if ( t->tot() != Type::BUILTIN ) if ( t->tot() != Type::BUILTIN )
t = extern_type_int; t = extern_type_int;
out_h->println("%s %s const { return %s; }", t->DataTypeStr().c_str(), out_h->println("%s %s const { return %s; }", t->DataTypeStr().c_str(), env->RValue(index_var_),
env->RValue(index_var_), env->LValue(index_var_)); env->LValue(index_var_));
Type::GenPubDecls(out_h, env); Type::GenPubDecls(out_h, env);
} }
@ -145,7 +144,7 @@ void CaseType::GenCleanUpCode(Output* out_cc, Env* env)
out_cc->println("{"); out_cc->println("{");
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
{ {
CaseField *c = *i; CaseField* c = *i;
c->GenCleanUpCode(out_cc, env); c->GenCleanUpCode(out_cc, env);
} }
out_cc->println("}"); out_cc->println("}");
@ -153,8 +152,7 @@ void CaseType::GenCleanUpCode(Output* out_cc, Env* env)
env->set_in_branch(false); env->set_in_branch(false);
} }
void CaseType::DoGenParseCode(Output* out_cc, Env* env, void CaseType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
const DataPtr& data, int flags)
{ {
if ( StaticSize(env) >= 0 ) if ( StaticSize(env) >= 0 )
GenBoundaryCheck(out_cc, env, data); GenBoundaryCheck(out_cc, env, data);
@ -164,8 +162,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env,
if ( ! incremental_input() ) if ( ! incremental_input() )
compute_size_var = AddSizeVar(out_cc, env); compute_size_var = AddSizeVar(out_cc, env);
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(index_var_), index_expr_->EvalExpr(out_cc, env));
env->LValue(index_var_), index_expr_->EvalExpr(out_cc, env));
env->SetEvaluated(index_var_); env->SetEvaluated(index_var_);
env->set_in_branch(true); env->set_in_branch(true);
@ -175,9 +172,8 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env,
bool has_default_case = false; bool has_default_case = false;
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
{ {
CaseField *c = *i; CaseField* c = *i;
c->GenParseCode(out_cc, env, data, c->GenParseCode(out_cc, env, data, compute_size_var ? size_var() : 0);
compute_size_var ? size_var() : 0);
if ( c->IsDefaultCase() ) if ( c->IsDefaultCase() )
has_default_case = true; has_default_case = true;
} }
@ -187,7 +183,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env,
out_cc->println("default:"); out_cc->println("default:");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);",
decl_id()->Name(), env->RValue(index_var_)); decl_id()->Name(), env->RValue(index_var_));
out_cc->println("break;"); out_cc->println("break;");
out_cc->dec_indent(); out_cc->dec_indent();
} }
@ -199,8 +195,7 @@ void CaseType::DoGenParseCode(Output* out_cc, Env* env,
env->SetEvaluated(size_var()); env->SetEvaluated(size_var());
} }
void CaseType::GenDynamicSize(Output* out_cc, Env* env, void CaseType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
const DataPtr& data)
{ {
GenParseCode(out_cc, env, data, 0); GenParseCode(out_cc, env, data, 0);
} }
@ -210,9 +205,9 @@ int CaseType::StaticSize(Env* env) const
int static_w = -1; int static_w = -1;
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
{ {
CaseField *c = *i; CaseField* c = *i;
int w = c->StaticSize(env); int w = c->StaticSize(env);
if ( w < 0 || ( static_w >= 0 && w != static_w ) ) if ( w < 0 || (static_w >= 0 && w != static_w) )
return -1; return -1;
static_w = w; static_w = w;
} }
@ -224,7 +219,7 @@ void CaseType::SetBoundaryChecked()
Type::SetBoundaryChecked(); Type::SetBoundaryChecked();
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
{ {
CaseField *c = *i; CaseField* c = *i;
c->SetBoundaryChecked(); c->SetBoundaryChecked();
} }
} }
@ -233,7 +228,7 @@ void CaseType::DoMarkIncrementalInput()
{ {
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
{ {
CaseField *c = *i; CaseField* c = *i;
c->type()->MarkIncrementalInput(); c->type()->MarkIncrementalInput();
} }
} }
@ -242,7 +237,7 @@ bool CaseType::ByteOrderSensitive() const
{ {
foreach (i, CaseFieldList, cases_) foreach (i, CaseFieldList, cases_)
{ {
CaseField *c = *i; CaseField* c = *i;
if ( c->RequiresByteOrder() ) if ( c->RequiresByteOrder() )
return true; return true;
} }
@ -250,10 +245,7 @@ bool CaseType::ByteOrderSensitive() const
} }
CaseField::CaseField(ExprList* index, ID* id, Type* type) CaseField::CaseField(ExprList* index, ID* id, Type* type)
: Field(CASE_FIELD, : Field(CASE_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type), index_(index)
TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE,
id, type),
index_(index)
{ {
ASSERT(type_); ASSERT(type_);
type_->set_value_var(id, MEMBER_VAR); type_->set_value_var(id, MEMBER_VAR);
@ -266,13 +258,13 @@ CaseField::~CaseField()
delete_list(ExprList, index_); delete_list(ExprList, index_);
} }
void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env, Type* switch_type) void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_type)
{ {
if ( index_list ) if ( index_list )
{ {
foreach(i, ExprList, index_list) foreach (i, ExprList, index_list)
{ {
Expr *index_expr = *i; Expr* index_expr = *i;
Type* case_type = index_expr->DataType(env); Type* case_type = index_expr->DataType(env);
@ -338,8 +330,7 @@ void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env, Type* switch_typ
// We're always using "int" for storage, so ok to just // We're always using "int" for storage, so ok to just
// cast into the type used by the switch statement since // cast into the type used by the switch statement since
// some unsafe stuff is already checked above. // some unsafe stuff is already checked above.
out_cc->println("case ((%s) %d):", out_cc->println("case ((%s) %d):", switch_type->DataTypeStr().c_str(), index_const);
switch_type->DataTypeStr().c_str(), index_const);
} }
} }
else else
@ -363,8 +354,7 @@ void CaseField::GenPubDecls(Output* out_h, Env* env)
if ( type_->DataTypeStr().empty() ) if ( type_->DataTypeStr().empty() )
return; return;
out_h->println("%s %s const", out_h->println("%s %s const", type_->DataTypeConstRefStr().c_str(), env->RValue(id_));
type_->DataTypeConstRefStr().c_str(), env->RValue(id_));
out_h->inc_indent(); out_h->inc_indent();
out_h->println("{"); out_h->println("{");
@ -383,11 +373,8 @@ void CaseField::GenPubDecls(Output* out_h, Env* env)
out_h->println("default:"); out_h->println("default:");
out_h->inc_indent(); out_h->inc_indent();
out_h->println( out_h->println("throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");",
"throw binpac::ExceptionInvalidCase(\"%s\", (int64)%s, \"%s\");", id_->LocName(), env->RValue(index_var_), OrigExprList(index_).c_str());
id_->LocName(),
env->RValue(index_var_),
OrigExprList(index_).c_str());
out_h->println("break;"); out_h->println("break;");
out_h->dec_indent(); out_h->dec_indent();
@ -426,47 +413,42 @@ void CaseField::GenCleanUpCode(Output* out_cc, Env* env)
out_cc->dec_indent(); out_cc->dec_indent();
} }
void CaseField::GenParseCode(Output* out_cc, Env* env, void CaseField::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, const ID* size_var)
const DataPtr& data, const ID* size_var)
{ {
GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env)); GenCaseStr(index_, out_cc, env, case_type()->IndexExpr()->DataType(env));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("// Parse \"%s\"", id_->Name()); out_cc->println("// Parse \"%s\"", id_->Name());
out_cc->println("{"); out_cc->println("{");
{ {
Env case_env(env, this); Env case_env(env, this);
type_->GenPreParsing(out_cc, &case_env); type_->GenPreParsing(out_cc, &case_env);
type_->GenParseCode(out_cc, &case_env, data, 0); type_->GenParseCode(out_cc, &case_env, data, 0);
if ( size_var ) if ( size_var )
{ {
out_cc->println("%s = %s;", out_cc->println("%s = %s;", case_env.LValue(size_var),
case_env.LValue(size_var), type_->DataSize(out_cc, &case_env, data).c_str());
type_->DataSize(out_cc, &case_env, data).c_str()); }
if ( type_->incremental_input() )
{
ASSERT(case_type()->parsing_complete_var());
out_cc->println("%s = %s;", case_env.LValue(case_type()->parsing_complete_var()),
case_env.RValue(type_->parsing_complete_var()));
}
out_cc->println("}");
} }
if ( type_->incremental_input() )
{
ASSERT(case_type()->parsing_complete_var());
out_cc->println("%s = %s;",
case_env.LValue(case_type()->parsing_complete_var()),
case_env.RValue(type_->parsing_complete_var()));
}
out_cc->println("}");
}
out_cc->println("break;"); out_cc->println("break;");
out_cc->dec_indent(); out_cc->dec_indent();
} }
bool CaseField::DoTraverse(DataDepVisitor *visitor) bool CaseField::DoTraverse(DataDepVisitor* visitor)
{ {
return Field::DoTraverse(visitor) && return Field::DoTraverse(visitor) && type()->Traverse(visitor);
type()->Traverse(visitor);
} }
bool CaseField::RequiresAnalyzerContext() const bool CaseField::RequiresAnalyzerContext() const
{ {
return Field::RequiresAnalyzerContext() || return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext();
type()->RequiresAnalyzerContext();
} }

View file

@ -7,95 +7,94 @@
#include "pac_type.h" #include "pac_type.h"
class CaseType : public Type class CaseType : public Type
{ {
public: public:
CaseType(Expr *index, CaseFieldList *cases); CaseType(Expr* index, CaseFieldList* cases);
~CaseType(); ~CaseType();
void AddCaseField(CaseField *f); void AddCaseField(CaseField* f);
bool DefineValueVar() const; bool DefineValueVar() const;
string DataTypeStr() const; string DataTypeStr() const;
string DefaultValue() const; string DefaultValue() const;
void Prepare(Env *env, int flags); void Prepare(Env* env, int flags);
void GenPubDecls(Output *out, Env *env); void GenPubDecls(Output* out, Env* env);
void GenPrivDecls(Output *out, Env *env); void GenPrivDecls(Output* out, Env* env);
void GenInitCode(Output *out, Env *env); void GenInitCode(Output* out, Env* env);
void GenCleanUpCode(Output *out, Env *env); void GenCleanUpCode(Output* out, Env* env);
int StaticSize(Env *env) const; int StaticSize(Env* env) const;
void SetBoundaryChecked(); void SetBoundaryChecked();
Type *ValueType() const; Type* ValueType() const;
Expr* IndexExpr() const { return index_expr_; } Expr* IndexExpr() const { return index_expr_; }
bool IsPointerType() const { return ValueType()->IsPointerType(); } bool IsPointerType() const { return ValueType()->IsPointerType(); }
protected: protected:
void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags);
void GenDynamicSize(Output *out, Env *env, const DataPtr& data); void GenDynamicSize(Output* out, Env* env, const DataPtr& data);
Type *DoClone() const { return 0; } Type* DoClone() const { return 0; }
void DoMarkIncrementalInput(); void DoMarkIncrementalInput();
bool ByteOrderSensitive() const; bool ByteOrderSensitive() const;
Expr *index_expr_; Expr* index_expr_;
ID *index_var_; ID* index_var_;
CaseFieldList *cases_; CaseFieldList* cases_;
typedef map<const ID*, CaseField*, ID_ptr_cmp> member_map_t; typedef map<const ID*, CaseField*, ID_ptr_cmp> member_map_t;
member_map_t member_map_; member_map_t member_map_;
}; };
class CaseField : public Field class CaseField : public Field
{ {
public: public:
CaseField(ExprList *index, ID *id, Type *type); CaseField(ExprList* index, ID* id, Type* type);
~CaseField(); ~CaseField();
CaseType *case_type() const { return case_type_; } CaseType* case_type() const { return case_type_; }
void set_case_type(CaseType *t) { case_type_ = t; } void set_case_type(CaseType* t) { case_type_ = t; }
ExprList *index() const { return index_; } ExprList* index() const { return index_; }
const char *lvalue() const { return type_->lvalue(); } const char* lvalue() const { return type_->lvalue(); }
const char *CaseStr(Env *env); const char* CaseStr(Env* env);
void set_index_var(const ID *var) { index_var_ = var; } void set_index_var(const ID* var) { index_var_ = var; }
void Prepare(Env *env); void Prepare(Env* env);
void GenPubDecls(Output *out, Env *env); void GenPubDecls(Output* out, Env* env);
void GenInitCode(Output *out, Env *env); void GenInitCode(Output* out, Env* env);
void GenCleanUpCode(Output *out, Env *env); void GenCleanUpCode(Output* out, Env* env);
void GenParseCode(Output *out, Env *env, void GenParseCode(Output* out, Env* env, const DataPtr& data, const ID* size_var);
const DataPtr& data, const ID *size_var);
int StaticSize(Env *env) const { return type_->StaticSize(env); } int StaticSize(Env* env) const { return type_->StaticSize(env); }
bool IsDefaultCase() const { return ! index_; } bool IsDefaultCase() const { return ! index_; }
void SetBoundaryChecked() { type_->SetBoundaryChecked(); } void SetBoundaryChecked() { type_->SetBoundaryChecked(); }
bool RequiresByteOrder() const { return type_->RequiresByteOrder(); } bool RequiresByteOrder() const { return type_->RequiresByteOrder(); }
bool RequiresAnalyzerContext() const; bool RequiresAnalyzerContext() const;
protected: protected:
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
protected: protected:
CaseType *case_type_; CaseType* case_type_;
ExprList *index_; ExprList* index_;
const ID *index_var_; const ID* index_var_;
}; };
// Generate a list of "case X:" lines from index_list. Each index // Generate a list of "case X:" lines from index_list. Each index
// expression must be constant foldable. // expression must be constant foldable.
void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env, Type* switch_type); void GenCaseStr(ExprList* index_list, Output* out_cc, Env* env, Type* switch_type);
#endif // pac_case_h #endif // pac_case_h

View file

@ -7,9 +7,9 @@ class CClassMethod;
class CType; class CType;
class CVariable; class CVariable;
typedef vector<CClassMember *> CClassMemberList; typedef vector<CClassMember*> CClassMemberList;
typedef vector<CClassMethod *> CClassMethodList; typedef vector<CClassMethod*> CClassMethodList;
typedef vector<CVariable *> CVariableList; typedef vector<CVariable*> CVariableList;
#include "pac_common.h" #include "pac_common.h"
@ -25,57 +25,57 @@ typedef vector<CVariable *> CVariableList;
// 3. We do not check repeated names. // 3. We do not check repeated names.
class CClass class CClass
{ {
public: public:
CClass(const string &class_name); CClass(const string& class_name);
void AddMember(CClassMember *member); void AddMember(CClassMember* member);
void AddMethod(CClassMember *method); void AddMethod(CClassMember* method);
void GenForwardDeclaration(Output *out_h); void GenForwardDeclaration(Output* out_h);
void GenCode(Output *out_h, Output *out_cc); void GenCode(Output* out_h, Output* out_cc);
protected: protected:
string class_name_; string class_name_;
CClassMemberList *members_; CClassMemberList* members_;
CClassMethodList *methods_; CClassMethodList* methods_;
}; };
class CVariable class CVariable
{ {
public: public:
CClassMember(const string &name, CType *type); CClassMember(const string& name, CType* type);
string name() const { return name_; } string name() const { return name_; }
CType *type() const { return type_; } CType* type() const { return type_; }
protected: protected:
string name_; string name_;
CType *type_; CType* type_;
}; };
class CClassMember class CClassMember
{ {
public: public:
CClassMember(CVariable *var); CClassMember(CVariable* var);
void GenCode(Output *out_h, Output *out_cc); void GenCode(Output* out_h, Output* out_cc);
string decl() const; string decl() const;
protected: protected:
CVariable *var_; CVariable* var_;
}; };
class CClassMethod class CClassMethod
{ {
public: public:
CClassMethod(CVariable *var, CVariableList *params); CClassMethod(CVariable* var, CVariableList* params);
string decl() const; string decl() const;
protected: protected:
CVariable *var_; CVariable* var_;
CVariableList *params_; CVariableList* params_;
}; };
#endif // pac_cclass_h #endif // pac_cclass_h

View file

@ -1,13 +1,12 @@
#ifndef pac_common_h #ifndef pac_common_h
#define pac_common_h #define pac_common_h
#include "pac_utils.h" #include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <vector> #include <vector>
#include <ctype.h> #include "pac_utils.h"
#include <string.h>
#include <stdlib.h>
using namespace std; using namespace std;
@ -22,7 +21,7 @@ extern int line_number;
// etc. // etc.
class Object class Object
{ {
public: public:
Object() Object()
{ {
@ -31,17 +30,15 @@ public:
location = strfmt("%s:%d", filename.c_str(), line_number); location = strfmt("%s:%d", filename.c_str(), line_number);
} }
~Object() ~Object() { }
{
}
const char* Location() const { return location.c_str(); } const char* Location() const { return location.c_str(); }
protected: protected:
string filename; string filename;
int line_num; int line_num;
string location; string location;
}; };
class ActionParam; class ActionParam;
class ActionParamType; class ActionParamType;
@ -89,47 +86,47 @@ class WithInputField;
// The ID of the current declaration. // The ID of the current declaration.
extern const ID* current_decl_id; extern const ID* current_decl_id;
typedef vector<ActionParam*> ActionParamList; typedef vector<ActionParam*> ActionParamList;
typedef vector<AnalyzerAction*> AnalyzerActionList; typedef vector<AnalyzerAction*> AnalyzerActionList;
typedef vector<AnalyzerElement*> AnalyzerElementList; typedef vector<AnalyzerElement*> AnalyzerElementList;
typedef vector<Attr*> AttrList; typedef vector<Attr*> AttrList;
typedef vector<CaseExpr*> CaseExprList; typedef vector<CaseExpr*> CaseExprList;
typedef vector<CaseField*> CaseFieldList; typedef vector<CaseField*> CaseFieldList;
typedef vector<ContextField*> ContextFieldList; typedef vector<ContextField*> ContextFieldList;
typedef vector<Decl*> DeclList; typedef vector<Decl*> DeclList;
typedef vector<Enum*> EnumList; typedef vector<Enum*> EnumList;
typedef vector<Expr*> ExprList; typedef vector<Expr*> ExprList;
typedef vector<Field*> FieldList; typedef vector<Field*> FieldList;
typedef vector<LetField*> LetFieldList; typedef vector<LetField*> LetFieldList;
typedef vector<Number*> NumList; typedef vector<Number*> NumList;
typedef vector<Param*> ParamList; typedef vector<Param*> ParamList;
typedef vector<RecordField*> RecordFieldList; typedef vector<RecordField*> RecordFieldList;
typedef vector<StateVar*> StateVarList; typedef vector<StateVar*> StateVarList;
#define foreach(i, ct, pc) \ #define foreach(i, ct, pc) \
if ( pc ) \ if ( pc ) \
for ( ct::iterator i = (pc)->begin(); i != (pc)->end(); ++i ) for ( ct::iterator i = (pc)->begin(); i != (pc)->end(); ++i )
#define delete_list(ct, pc) \ #define delete_list(ct, pc) \
{ \ { \
foreach(delete_list_i, ct, pc) \ foreach (delete_list_i, ct, pc) \
delete *delete_list_i; \ delete *delete_list_i; \
delete pc; \ delete pc; \
pc = 0; \ pc = 0; \
} }
// Constants // Constants
const char * const kComputeFrameLength = "compute_frame_length"; const char* const kComputeFrameLength = "compute_frame_length";
const char * const kFlowBufferClass = "FlowBuffer"; const char* const kFlowBufferClass = "FlowBuffer";
const char * const kFlowBufferVar = "flow_buffer"; const char* const kFlowBufferVar = "flow_buffer";
const char * const kFlowEOF = "FlowEOF"; const char* const kFlowEOF = "FlowEOF";
const char * const kFlowGap = "NewGap"; const char* const kFlowGap = "NewGap";
const char * const kInitialBufferLengthFunc = "initial_buffer_length"; const char* const kInitialBufferLengthFunc = "initial_buffer_length";
const char * const kNeedMoreData = "need_more_data"; const char* const kNeedMoreData = "need_more_data";
const char * const kNewData = "NewData"; const char* const kNewData = "NewData";
const char * const kParseFuncWithBuffer = "ParseBuffer"; const char* const kParseFuncWithBuffer = "ParseBuffer";
const char * const kParseFuncWithoutBuffer = "Parse"; const char* const kParseFuncWithoutBuffer = "Parse";
const char * const kRefCountClass = "binpac::RefCount"; const char* const kRefCountClass = "binpac::RefCount";
const char * const kTypeWithLengthClass = "binpac::TypeWithLength"; const char* const kTypeWithLengthClass = "binpac::TypeWithLength";
#endif // pac_common_h #endif // pac_common_h

View file

@ -1,3 +1,5 @@
#include "pac_conn.h"
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_dataunit.h" #include "pac_dataunit.h"
#include "pac_embedded.h" #include "pac_embedded.h"
@ -8,11 +10,7 @@
#include "pac_paramtype.h" #include "pac_paramtype.h"
#include "pac_type.h" #include "pac_type.h"
#include "pac_conn.h" ConnDecl::ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist)
ConnDecl::ConnDecl(ID *conn_id,
ParamList *params,
AnalyzerElementList *elemlist)
: AnalyzerDecl(conn_id, CONN, params) : AnalyzerDecl(conn_id, CONN, params)
{ {
flows_[0] = flows_[1] = 0; flows_[0] = flows_[1] = 0;
@ -27,12 +25,12 @@ ConnDecl::~ConnDecl()
delete data_type_; delete data_type_;
} }
void ConnDecl::AddBaseClass(vector<string> *base_classes) const void ConnDecl::AddBaseClass(vector<string>* base_classes) const
{ {
base_classes->push_back("binpac::ConnectionAnalyzer"); base_classes->push_back("binpac::ConnectionAnalyzer");
} }
void ConnDecl::ProcessFlowElement(AnalyzerFlow *flow_elem) void ConnDecl::ProcessFlowElement(AnalyzerFlow* flow_elem)
{ {
int flow_index; int flow_index;
@ -44,19 +42,16 @@ void ConnDecl::ProcessFlowElement(AnalyzerFlow *flow_elem)
if ( flows_[flow_index] ) if ( flows_[flow_index] )
{ {
throw Exception(flow_elem, throw Exception(flow_elem,
strfmt("%sflow already defined", strfmt("%sflow already defined", flow_index == 0 ? "up" : "down"));
flow_index == 0 ? "up" : "down"));
} }
flows_[flow_index] = flow_elem; flows_[flow_index] = flow_elem;
type_->AddField(flow_elem->flow_field()); type_->AddField(flow_elem->flow_field());
} }
void ConnDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) void ConnDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem)
{ {
throw Exception( throw Exception(dataunit_elem, "dataunit should be defined in only a flow declaration");
dataunit_elem,
"dataunit should be defined in only a flow declaration");
} }
void ConnDecl::Prepare() void ConnDecl::Prepare()
@ -67,17 +62,17 @@ void ConnDecl::Prepare()
flows_[1]->flow_decl()->set_conn_decl(this); flows_[1]->flow_decl()->set_conn_decl(this);
} }
void ConnDecl::GenPubDecls(Output *out_h, Output *out_cc) void ConnDecl::GenPubDecls(Output* out_h, Output* out_cc)
{ {
AnalyzerDecl::GenPubDecls(out_h, out_cc); AnalyzerDecl::GenPubDecls(out_h, out_cc);
} }
void ConnDecl::GenPrivDecls(Output *out_h, Output *out_cc) void ConnDecl::GenPrivDecls(Output* out_h, Output* out_cc)
{ {
AnalyzerDecl::GenPrivDecls(out_h, out_cc); AnalyzerDecl::GenPrivDecls(out_h, out_cc);
} }
void ConnDecl::GenEOFFunc(Output *out_h, Output *out_cc) void ConnDecl::GenEOFFunc(Output* out_h, Output* out_cc)
{ {
string proto = strfmt("%s(bool is_orig)", kFlowEOF); string proto = strfmt("%s(bool is_orig)", kFlowEOF);
@ -89,17 +84,13 @@ void ConnDecl::GenEOFFunc(Output *out_h, Output *out_cc)
out_cc->println("if ( is_orig )"); out_cc->println("if ( is_orig )");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("%s->%s();", out_cc->println("%s->%s();", env_->LValue(upflow_id), kFlowEOF);
env_->LValue(upflow_id),
kFlowEOF);
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("else"); out_cc->println("else");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("%s->%s();", out_cc->println("%s->%s();", env_->LValue(downflow_id), kFlowEOF);
env_->LValue(downflow_id),
kFlowEOF);
foreach(i, AnalyzerHelperList, eof_helpers_) foreach (i, AnalyzerHelperList, eof_helpers_)
{ {
(*i)->GenCode(0, out_cc, this); (*i)->GenCode(0, out_cc, this);
} }
@ -111,7 +102,7 @@ void ConnDecl::GenEOFFunc(Output *out_h, Output *out_cc)
out_cc->println(""); out_cc->println("");
} }
void ConnDecl::GenGapFunc(Output *out_h, Output *out_cc) void ConnDecl::GenGapFunc(Output* out_h, Output* out_cc)
{ {
string proto = strfmt("%s(bool is_orig, int gap_length)", kFlowGap); string proto = strfmt("%s(bool is_orig, int gap_length)", kFlowGap);
@ -123,15 +114,11 @@ void ConnDecl::GenGapFunc(Output *out_h, Output *out_cc)
out_cc->println("if ( is_orig )"); out_cc->println("if ( is_orig )");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("%s->%s(gap_length);", out_cc->println("%s->%s(gap_length);", env_->LValue(upflow_id), kFlowGap);
env_->LValue(upflow_id),
kFlowGap);
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("else"); out_cc->println("else");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("%s->%s(gap_length);", out_cc->println("%s->%s(gap_length);", env_->LValue(downflow_id), kFlowGap);
env_->LValue(downflow_id),
kFlowGap);
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("}"); out_cc->println("}");
@ -139,11 +126,9 @@ void ConnDecl::GenGapFunc(Output *out_h, Output *out_cc)
out_cc->println(""); out_cc->println("");
} }
void ConnDecl::GenProcessFunc(Output *out_h, Output *out_cc) void ConnDecl::GenProcessFunc(Output* out_h, Output* out_cc)
{ {
string proto = string proto = strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)", kNewData);
strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)",
kNewData);
out_h->println("void %s;", proto.c_str()); out_h->println("void %s;", proto.c_str());
@ -153,15 +138,11 @@ void ConnDecl::GenProcessFunc(Output *out_h, Output *out_cc)
out_cc->println("if ( is_orig )"); out_cc->println("if ( is_orig )");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("%s->%s(begin, end);", out_cc->println("%s->%s(begin, end);", env_->LValue(upflow_id), kNewData);
env_->LValue(upflow_id),
kNewData);
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("else"); out_cc->println("else");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("%s->%s(begin, end);", out_cc->println("%s->%s(begin, end);", env_->LValue(downflow_id), kNewData);
env_->LValue(downflow_id),
kNewData);
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("}"); out_cc->println("}");

View file

@ -1,34 +1,34 @@
#ifndef pac_conn_h #ifndef pac_conn_h
#define pac_conn_h #define pac_conn_h
#include "pac_decl.h"
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_decl.h"
class ConnDecl : public AnalyzerDecl class ConnDecl : public AnalyzerDecl
{ {
public: public:
ConnDecl(ID *conn_id, ParamList *params, AnalyzerElementList *elemlist); ConnDecl(ID* conn_id, ParamList* params, AnalyzerElementList* elemlist);
~ConnDecl(); ~ConnDecl();
void Prepare(); void Prepare();
Type* DataType() const { return data_type_; } Type* DataType() const { return data_type_; }
protected: protected:
void AddBaseClass(vector<string> *base_classes) const; void AddBaseClass(vector<string>* base_classes) const;
void GenProcessFunc(Output *out_h, Output *out_cc); void GenProcessFunc(Output* out_h, Output* out_cc);
void GenGapFunc(Output *out_h, Output *out_cc); void GenGapFunc(Output* out_h, Output* out_cc);
void GenEOFFunc(Output *out_h, Output *out_cc); void GenEOFFunc(Output* out_h, Output* out_cc);
void GenPubDecls(Output *out_h, Output *out_cc); void GenPubDecls(Output* out_h, Output* out_cc);
void GenPrivDecls(Output *out_h, Output *out_cc); void GenPrivDecls(Output* out_h, Output* out_cc);
void ProcessFlowElement(AnalyzerFlow *flow_elem); void ProcessFlowElement(AnalyzerFlow* flow_elem);
void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem); void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem);
AnalyzerFlow *flows_[2]; AnalyzerFlow* flows_[2];
Type *data_type_; Type* data_type_;
}; };
#endif // pac_conn_h #endif // pac_conn_h

View file

@ -1,3 +1,5 @@
#include "pac_context.h"
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_exttype.h" #include "pac_exttype.h"
@ -9,47 +11,38 @@
#include "pac_type.h" #include "pac_type.h"
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_context.h" ContextField::ContextField(ID* id, Type* type)
: Field(CONTEXT_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type)
ContextField::ContextField(ID *id, Type *type)
: Field(CONTEXT_FIELD,
TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE,
id, type)
{ {
} }
AnalyzerContextDecl *AnalyzerContextDecl::current_analyzer_context_ = 0; AnalyzerContextDecl* AnalyzerContextDecl::current_analyzer_context_ = 0;
namespace { namespace
ParamList *ContextFieldsToParams(ContextFieldList *context_fields) {
ParamList* ContextFieldsToParams(ContextFieldList* context_fields)
{
// Convert context fields to parameters
ParamList* params = new ParamList();
foreach (i, ContextFieldList, context_fields)
{ {
// Convert context fields to parameters ContextField* f = *i;
ParamList *params = new ParamList(); params->push_back(new Param(f->id()->clone(), f->type()));
foreach(i, ContextFieldList, context_fields)
{
ContextField *f = *i;
params->push_back(
new Param(f->id()->clone(),
f->type()));
}
return params;
} }
} // namespace private return params;
}
} // namespace private
AnalyzerContextDecl::AnalyzerContextDecl( AnalyzerContextDecl::AnalyzerContextDecl(ID* id, ContextFieldList* context_fields)
ID *id, : TypeDecl(new ID(strfmt("Context%s", id->Name())), ContextFieldsToParams(context_fields),
ContextFieldList *context_fields) new DummyType())
: TypeDecl(new ID(strfmt("Context%s", id->Name())),
ContextFieldsToParams(context_fields),
new DummyType())
{ {
context_name_id_ = id; context_name_id_ = id;
if ( current_analyzer_context_ != 0 ) if ( current_analyzer_context_ != 0 )
{ {
throw Exception(this, throw Exception(this, strfmt("multiple declaration of analyzer context; "
strfmt("multiple declaration of analyzer context; " "the previous one is `%s'",
"the previous one is `%s'", current_analyzer_context_->id()->Name()));
current_analyzer_context_->id()->Name()));
} }
else else
current_analyzer_context_ = this; current_analyzer_context_ = this;
@ -70,25 +63,25 @@ AnalyzerContextDecl::~AnalyzerContextDecl()
delete_list(ContextFieldList, context_fields_); delete_list(ContextFieldList, context_fields_);
} }
void AnalyzerContextDecl::GenForwardDeclaration(Output *out_h) void AnalyzerContextDecl::GenForwardDeclaration(Output* out_h)
{ {
GenNamespaceBegin(out_h); GenNamespaceBegin(out_h);
TypeDecl::GenForwardDeclaration(out_h); TypeDecl::GenForwardDeclaration(out_h);
} }
void AnalyzerContextDecl::GenCode(Output *out_h, Output *out_cc) void AnalyzerContextDecl::GenCode(Output* out_h, Output* out_cc)
{ {
GenNamespaceBegin(out_h); GenNamespaceBegin(out_h);
GenNamespaceBegin(out_cc); GenNamespaceBegin(out_cc);
TypeDecl::GenCode(out_h, out_cc); TypeDecl::GenCode(out_h, out_cc);
} }
void AnalyzerContextDecl::GenNamespaceBegin(Output *out) const void AnalyzerContextDecl::GenNamespaceBegin(Output* out) const
{ {
out->println("namespace %s {", context_name_id()->Name()); out->println("namespace %s {", context_name_id()->Name());
} }
void AnalyzerContextDecl::GenNamespaceEnd(Output *out) const void AnalyzerContextDecl::GenNamespaceEnd(Output* out) const
{ {
out->println("} // namespace %s", context_name_id()->Name()); out->println("} // namespace %s", context_name_id()->Name());
} }
@ -98,23 +91,19 @@ void AnalyzerContextDecl::AddFlowBuffer()
if ( flow_buffer_added_ ) if ( flow_buffer_added_ )
return; return;
AddParam(new Param( AddParam(new Param(new ID(kFlowBufferVar), FlowDecl::flow_buffer_type()->Clone()));
new ID(kFlowBufferVar),
FlowDecl::flow_buffer_type()->Clone()));
flow_buffer_added_ = true; flow_buffer_added_ = true;
} }
string AnalyzerContextDecl::mb_buffer(Env *env) string AnalyzerContextDecl::mb_buffer(Env* env)
{ {
// A hack. The orthodox way would be to build an Expr of // A hack. The orthodox way would be to build an Expr of
// context.flow_buffer_var, and then EvalExpr. // context.flow_buffer_var, and then EvalExpr.
return strfmt("%s->%s()", return strfmt("%s->%s()", env->RValue(analyzer_context_id), kFlowBufferVar);
env->RValue(analyzer_context_id),
kFlowBufferVar);
} }
Type *DummyType::DoClone() const Type* DummyType::DoClone() const
{ {
// Fields will be copied in Type::Clone(). // Fields will be copied in Type::Clone().
return new DummyType(); return new DummyType();

View file

@ -24,74 +24,80 @@
// ``binpac_context.connection''. // ``binpac_context.connection''.
class ContextField : public Field class ContextField : public Field
{ {
public: public:
ContextField(ID *id, Type *type); ContextField(ID* id, Type* type);
}; };
class AnalyzerContextDecl : public TypeDecl class AnalyzerContextDecl : public TypeDecl
{ {
public: public:
AnalyzerContextDecl(ID *id, ContextFieldList *context_fields); AnalyzerContextDecl(ID* id, ContextFieldList* context_fields);
~AnalyzerContextDecl(); ~AnalyzerContextDecl();
void AddFlowBuffer(); void AddFlowBuffer();
const ID *context_name_id() const { return context_name_id_; } const ID* context_name_id() const { return context_name_id_; }
// The type of analyzer context as a parameter // The type of analyzer context as a parameter
ParameterizedType *param_type() const { return param_type_; } ParameterizedType* param_type() const { return param_type_; }
void GenForwardDeclaration(Output *out_h); void GenForwardDeclaration(Output* out_h);
void GenCode(Output *out_h, Output *out_cc); void GenCode(Output* out_h, Output* out_cc);
void GenNamespaceBegin(Output *out) const; void GenNamespaceBegin(Output* out) const;
void GenNamespaceEnd(Output *out) const; void GenNamespaceEnd(Output* out) const;
private: private:
ID *context_name_id_; ID* context_name_id_;
ContextFieldList *context_fields_; ContextFieldList* context_fields_;
ParameterizedType *param_type_; ParameterizedType* param_type_;
bool flow_buffer_added_; bool flow_buffer_added_;
// static members // static members
public: public:
static AnalyzerContextDecl *current_analyzer_context() static AnalyzerContextDecl* current_analyzer_context() { return current_analyzer_context_; }
{
return current_analyzer_context_;
}
static string mb_buffer(Env *env); static string mb_buffer(Env* env);
private: private:
static AnalyzerContextDecl *current_analyzer_context_; static AnalyzerContextDecl* current_analyzer_context_;
}; };
class DummyType : public Type class DummyType : public Type
{ {
public: public:
DummyType() : Type(DUMMY) {} DummyType() : Type(DUMMY) { }
bool DefineValueVar() const { return false; } bool DefineValueVar() const { return false; }
string DataTypeStr() const { ASSERT(0); return ""; } string DataTypeStr() const
{
ASSERT(0);
return "";
}
int StaticSize(Env* env) const { ASSERT(0); return -1; } int StaticSize(Env* env) const
{
ASSERT(0);
return -1;
}
bool ByteOrderSensitive() const { return false; } bool ByteOrderSensitive() const { return false; }
bool IsPointerType() const { ASSERT(0); return false; } bool IsPointerType() const
{
ASSERT(0);
return false;
}
void DoGenParseCode(Output* out, Env* env, void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) { ASSERT(0); }
const DataPtr& data, int flags)
{ ASSERT(0); }
// Generate code for computing the dynamic size of the type // Generate code for computing the dynamic size of the type
void GenDynamicSize(Output* out, Env* env, const DataPtr& data) void GenDynamicSize(Output* out, Env* env, const DataPtr& data) { ASSERT(0); }
{ ASSERT(0); }
protected: protected:
Type *DoClone() const; Type* DoClone() const;
void DoMarkIncrementalInput() { ASSERT(0); } void DoMarkIncrementalInput() { ASSERT(0); }
}; };
#endif // pac_context_h #endif // pac_context_h

View file

@ -1,84 +1,95 @@
#include "pac_cstr.h" #include "pac_cstr.h"
#include "pac_dbg.h" #include "pac_dbg.h"
#include "pac_exception.h" #include "pac_exception.h"
namespace { namespace
{
class EscapeException class EscapeException
{ {
public: public:
explicit EscapeException(const string &s) explicit EscapeException(const string& s) { msg_ = s; }
{
msg_ = s;
}
const string &msg() const { return msg_; } const string& msg() const { return msg_; }
private: private:
string msg_; string msg_;
}; };
// Copied from util.cc of Zeek // Copied from util.cc of Zeek
int expand_escape(const char*& s) int expand_escape(const char*& s)
{ {
switch ( *(s++) ) { switch ( *(s++) )
case 'b': return '\b'; {
case 'f': return '\f'; case 'b':
case 'n': return '\n'; return '\b';
case 'r': return '\r'; case 'f':
case 't': return '\t'; return '\f';
case 'a': return '\a'; case 'n':
case 'v': return '\v'; return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'a':
return '\a';
case 'v':
return '\v';
case '0': case '1': case '2': case '3': case '4': case '0':
case '5': case '6': case '7': case '1':
{ // \<octal>{1,3} case '2':
--s; // put back the first octal digit case '3':
const char* start = s; case '4':
case '5':
case '6':
case '7':
{ // \<octal>{1,3}
--s; // put back the first octal digit
const char* start = s;
// Don't increment inside loop control // Don't increment inside loop control
// because if isdigit() is a macro it might // because if isdigit() is a macro it might
// expand into multiple increments ... // expand into multiple increments ...
// Here we define a maximum length for escape sequence // Here we define a maximum length for escape sequence
// to allow easy handling of string like: "^H0" as // to allow easy handling of string like: "^H0" as
// "\0100". // "\0100".
for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s); ++s, ++len) for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s); ++s, ++len )
; ;
int result; int result;
if ( sscanf(start, "%3o", &result) != 1 ) if ( sscanf(start, "%3o", &result) != 1 )
throw EscapeException(strfmt("bad octal escape: \"%s", start)); throw EscapeException(strfmt("bad octal escape: \"%s", start));
return result; return result;
}
case 'x':
{ /* \x<hex> */
const char* start = s;
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s); ++s, ++len )
;
int result;
if ( sscanf(start, "%2x", &result) != 1 )
throw EscapeException(strfmt("bad hexadecimal escape: \"%s", start));
return result;
}
default:
return s[-1];
} }
case 'x':
{ /* \x<hex> */
const char* start = s;
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s);
++s, ++len)
;
int result;
if ( sscanf(start, "%2x", &result) != 1 )
throw EscapeException(strfmt("bad hexadecimal escape: \"%s", start));
return result;
}
default:
return s[-1];
}
} }
} // private namespace } // private namespace
ConstString::ConstString(const string &s) ConstString::ConstString(const string& s) : str_(s)
: str_(s)
{ {
// Copied from scan.l of Zeek // Copied from scan.l of Zeek
try try
@ -94,9 +105,9 @@ ConstString::ConstString(const string &s)
{ {
if ( *text == '\\' ) if ( *text == '\\' )
{ {
++text; // skip '\' ++text; // skip '\'
new_s[i++] = expand_escape(text); new_s[i++] = expand_escape(text);
--text; // point to end of sequence --text; // point to end of sequence
} }
else else
{ {
@ -106,16 +117,15 @@ ConstString::ConstString(const string &s)
ASSERT(i < len); ASSERT(i < len);
// Get rid of trailing quote. // Get rid of trailing quote.
ASSERT(new_s[i-1] == '"'); ASSERT(new_s[i - 1] == '"');
new_s[i-1] = '\0'; new_s[i - 1] = '\0';
unescaped_ = new_s; unescaped_ = new_s;
delete [] new_s; delete[] new_s;
} }
catch(EscapeException const &e) catch ( EscapeException const& e )
{ {
// Throw again with the object // Throw again with the object
throw Exception(this, e.msg().c_str()); throw Exception(this, e.msg().c_str());
} }
} }

View file

@ -4,20 +4,20 @@
#include "pac_common.h" #include "pac_common.h"
class ConstString : public Object class ConstString : public Object
{ {
public: public:
ConstString(const string &s); ConstString(const string& s);
// The string in its escaped form, with surrounding '"'s // The string in its escaped form, with surrounding '"'s
const string &str() const { return str_; } const string& str() const { return str_; }
const char *c_str() const { return str_.c_str(); } const char* c_str() const { return str_.c_str(); }
// The unescaped string, without surrounding '"'s // The unescaped string, without surrounding '"'s
const string &unescaped() const { return unescaped_; } const string& unescaped() const { return unescaped_; }
private: private:
string str_; string str_;
string unescaped_; string unescaped_;
}; };
#endif // pac_cstr_h #endif // pac_cstr_h

View file

@ -1,21 +1,21 @@
#include "pac_ctype.h" #include "pac_ctype.h"
string CType::DeclareInstance(const string &var) const string CType::DeclareInstance(const string& var) const
{ {
return strfmt("%s %s", name().c_str(), var.c_str()); return strfmt("%s %s", name().c_str(), var.c_str());
} }
string CType::DeclareConstReference(const string &var) const string CType::DeclareConstReference(const string& var) const
{ {
return strfmt("%s const &%s", name().c_str(), var.c_str()); return strfmt("%s const &%s", name().c_str(), var.c_str());
} }
string CType::DeclareConstPointer(const string &var) const string CType::DeclareConstPointer(const string& var) const
{ {
return strfmt("%s const *%s", name().c_str(), var.c_str()); return strfmt("%s const *%s", name().c_str(), var.c_str());
} }
string CType::DeclarePointer(const string &var) const string CType::DeclarePointer(const string& var) const
{ {
return strfmt("%s *%s", name().c_str(), var.c_str()); return strfmt("%s *%s", name().c_str(), var.c_str());
} }

View file

@ -5,19 +5,19 @@
// Represents a C++ type // Represents a C++ type
class CType class CType
{ {
public: public:
CType(const string &name); CType(const string& name);
string name() const { return name_; } string name() const { return name_; }
string DeclareInstance(const string &var) const; string DeclareInstance(const string& var) const;
string DeclareConstReference(const string &var) const; string DeclareConstReference(const string& var) const;
string DeclareConstPointer(const string &var) const; string DeclareConstPointer(const string& var) const;
string DeclarePointer(const string &var) const; string DeclarePointer(const string& var) const;
protected: protected:
string name_; string name_;
}; };
#endif // pac_ctype_h #endif // pac_ctype_h

View file

@ -1,14 +1,12 @@
#include "pac_datadep.h" #include "pac_datadep.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_type.h" #include "pac_type.h"
DataDepElement::DataDepElement(DDE_Type type) DataDepElement::DataDepElement(DDE_Type type) : dde_type_(type), in_traversal(false) { }
: dde_type_(type), in_traversal(false)
{
}
bool DataDepElement::Traverse(DataDepVisitor *visitor) bool DataDepElement::Traverse(DataDepVisitor* visitor)
{ {
// Avoid infinite loop // Avoid infinite loop
if ( in_traversal ) if ( in_traversal )
@ -27,17 +25,17 @@ bool DataDepElement::Traverse(DataDepVisitor *visitor)
return true; return true;
} }
Expr *DataDepElement::expr() Expr* DataDepElement::expr()
{ {
return static_cast<Expr *>(this); return static_cast<Expr*>(this);
} }
Type *DataDepElement::type() Type* DataDepElement::type()
{ {
return static_cast<Type *>(this); return static_cast<Type*>(this);
} }
bool RequiresAnalyzerContext::PreProcess(DataDepElement *element) bool RequiresAnalyzerContext::PreProcess(DataDepElement* element)
{ {
switch ( element->dde_type() ) switch ( element->dde_type() )
{ {
@ -52,23 +50,22 @@ bool RequiresAnalyzerContext::PreProcess(DataDepElement *element)
return ! requires_analyzer_context_; return ! requires_analyzer_context_;
} }
bool RequiresAnalyzerContext::PostProcess(DataDepElement *element) bool RequiresAnalyzerContext::PostProcess(DataDepElement* element)
{ {
return ! requires_analyzer_context_; return ! requires_analyzer_context_;
} }
void RequiresAnalyzerContext::ProcessExpr(Expr *expr) void RequiresAnalyzerContext::ProcessExpr(Expr* expr)
{ {
if ( expr->expr_type() == Expr::EXPR_ID ) if ( expr->expr_type() == Expr::EXPR_ID )
{ {
requires_analyzer_context_ = requires_analyzer_context_ = (requires_analyzer_context_ ||
(requires_analyzer_context_ || *expr->id() == *analyzer_context_id ||
*expr->id() == *analyzer_context_id || *expr->id() == *context_macro_id);
*expr->id() == *context_macro_id);
} }
} }
bool RequiresAnalyzerContext::compute(DataDepElement *element) bool RequiresAnalyzerContext::compute(DataDepElement* element)
{ {
RequiresAnalyzerContext visitor; RequiresAnalyzerContext visitor;
element->Traverse(&visitor); element->Traverse(&visitor);

View file

@ -9,9 +9,11 @@
class DataDepVisitor; class DataDepVisitor;
class DataDepElement { class DataDepElement
{
public: public:
enum DDE_Type { enum DDE_Type
{
ATTR, ATTR,
CASEEXPR, CASEEXPR,
EXPR, EXPR,
@ -19,53 +21,52 @@ public:
INPUT_BUFFER, INPUT_BUFFER,
PARAM, PARAM,
TYPE, TYPE,
}; };
DataDepElement(DDE_Type type); DataDepElement(DDE_Type type);
virtual ~DataDepElement() {} virtual ~DataDepElement() { }
// Returns whether to continue traversal // Returns whether to continue traversal
bool Traverse(DataDepVisitor *visitor); bool Traverse(DataDepVisitor* visitor);
// Returns whether to continue traversal // Returns whether to continue traversal
virtual bool DoTraverse(DataDepVisitor *visitor) = 0; virtual bool DoTraverse(DataDepVisitor* visitor) = 0;
DDE_Type dde_type() const { return dde_type_; } DDE_Type dde_type() const { return dde_type_; }
Expr *expr(); Expr* expr();
Type *type(); Type* type();
protected: protected:
DDE_Type dde_type_; DDE_Type dde_type_;
bool in_traversal; bool in_traversal;
}; };
class DataDepVisitor { class DataDepVisitor
{
public: public:
virtual ~DataDepVisitor() {} virtual ~DataDepVisitor() { }
// Returns whether to continue traversal // Returns whether to continue traversal
virtual bool PreProcess(DataDepElement *element) = 0; virtual bool PreProcess(DataDepElement* element) = 0;
virtual bool PostProcess(DataDepElement *element) = 0; virtual bool PostProcess(DataDepElement* element) = 0;
}; };
class RequiresAnalyzerContext : public DataDepVisitor { class RequiresAnalyzerContext : public DataDepVisitor
{
public: public:
RequiresAnalyzerContext() : requires_analyzer_context_(false) {} RequiresAnalyzerContext() : requires_analyzer_context_(false) { }
// Returns whether to continue traversal // Returns whether to continue traversal
bool PreProcess(DataDepElement *element); bool PreProcess(DataDepElement* element);
bool PostProcess(DataDepElement *element); bool PostProcess(DataDepElement* element);
bool requires_analyzer_context() const bool requires_analyzer_context() const { return requires_analyzer_context_; }
{
return requires_analyzer_context_;
}
static bool compute(DataDepElement *element); static bool compute(DataDepElement* element);
protected: protected:
void ProcessExpr(Expr *expr); void ProcessExpr(Expr* expr);
bool requires_analyzer_context_; bool requires_analyzer_context_;
}; };
#endif // pac_datadep_h #endif // pac_datadep_h

View file

@ -1,12 +1,11 @@
#include "pac_dataptr.h"
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_dataptr.h" DataPtr::DataPtr(Env* env, const ID* id, const int offset) : id_(id), offset_(offset)
DataPtr::DataPtr(Env* env, const ID* id, const int offset)
: id_(id), offset_(offset)
{ {
if ( id_ ) if ( id_ )
{ {
@ -24,7 +23,7 @@ DataPtr::DataPtr(Env* env, const ID* id, const int offset)
int DataPtr::AbsOffset(const ID* base_ptr) const int DataPtr::AbsOffset(const ID* base_ptr) const
{ {
return ( id() == base_ptr ) ? offset() : -1; return (id() == base_ptr) ? offset() : -1;
} }
char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const
@ -35,19 +34,14 @@ char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const
return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr)); return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr));
} }
void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env, const char* data_size,
const char* data_size, const char* data_name) const const char* data_name) const
{ {
ASSERT(id_); ASSERT(id_);
out_cc->println("// Checking out-of-bound for \"%s\"", data_name); out_cc->println("// Checking out-of-bound for \"%s\"", data_name);
out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", out_cc->println("if ( %s + (%s) > %s || %s + (%s) < %s )", ptr_expr(), data_size,
ptr_expr(), env->RValue(end_of_data), ptr_expr(), data_size, ptr_expr());
data_size,
env->RValue(end_of_data),
ptr_expr(),
data_size,
ptr_expr());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
@ -56,14 +50,11 @@ void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env,
out_cc->println("// Handle out-of-bound condition"); out_cc->println("// Handle out-of-bound condition");
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_name); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", data_name);
out_cc->println(" (%s) + (%s), ", out_cc->println(" (%s) + (%s), ", data_offset, data_size);
data_offset, data_size); out_cc->println(" (%s) - (%s));", env->RValue(end_of_data), env->RValue(begin_of_data));
out_cc->println(" (%s) - (%s));",
env->RValue(end_of_data), env->RValue(begin_of_data));
delete [] data_offset; delete[] data_offset;
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
} }

View file

@ -2,18 +2,20 @@
#define pac_dataptr_h #define pac_dataptr_h
#include <string> #include <string>
#include "pac_common.h" #include "pac_common.h"
#include "pac_dbg.h"
// A data pointer is represented by an data pointer variable // A data pointer is represented by an data pointer variable
// plus a constant offset. // plus a constant offset.
class DataPtr class DataPtr
{ {
public: public:
DataPtr(Env* env, const ID* arg_id, const int arg_off); DataPtr(Env* env, const ID* arg_id, const int arg_off);
DataPtr(DataPtr const& x) { *this = x; } DataPtr(DataPtr const& x) { *this = x; }
DataPtr const &operator=(DataPtr const &x) DataPtr const& operator=(DataPtr const& x)
{ {
id_ = x.id(); id_ = x.id();
offset_ = x.offset(); offset_ = x.offset();
@ -22,8 +24,8 @@ public:
return *this; return *this;
} }
const ID* id() const { return id_; } const ID* id() const { return id_; }
int offset() const { return offset_; } int offset() const { return offset_; }
const char* ptr_expr() const const char* ptr_expr() const
{ {
@ -34,15 +36,13 @@ public:
int AbsOffset(const ID* base_ptr) const; int AbsOffset(const ID* base_ptr) const;
char* AbsOffsetExpr(Env* env, const ID* base_ptr) const; char* AbsOffsetExpr(Env* env, const ID* base_ptr) const;
void GenBoundaryCheck(Output* out, void GenBoundaryCheck(Output* out, Env* env, const char* data_size,
Env* env, const char* data_name) const;
const char* data_size,
const char* data_name) const;
protected: protected:
const ID* id_; const ID* id_;
int offset_; int offset_;
string ptr_expr_; string ptr_expr_;
}; };
#endif // pac_dataptr_h #endif // pac_dataptr_h

View file

@ -1,32 +1,21 @@
#include "pac_context.h"
#include "pac_dataunit.h" #include "pac_dataunit.h"
#include "pac_context.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_paramtype.h" #include "pac_paramtype.h"
#include "pac_varfield.h" #include "pac_varfield.h"
AnalyzerDataUnit::AnalyzerDataUnit( AnalyzerDataUnit::AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params,
DataUnitType type, ExprList* context_params)
ID *id, : AnalyzerElement(DATAUNIT), type_(type), id_(id), type_params_(type_params),
ExprList *type_params,
ExprList *context_params)
: AnalyzerElement(DATAUNIT),
type_(type),
id_(id),
type_params_(type_params),
context_params_(context_params) context_params_(context_params)
{ {
data_type_ = new ParameterizedType(id_, type_params_); data_type_ = new ParameterizedType(id_, type_params_);
context_type_ = new ParameterizedType( context_type_ = new ParameterizedType(
AnalyzerContextDecl::current_analyzer_context()->id()->clone(), AnalyzerContextDecl::current_analyzer_context()->id()->clone(), context_params_);
context_params_);
dataunit_var_field_ = new ParseVarField( dataunit_var_field_ = new ParseVarField(Field::CLASS_MEMBER, dataunit_id->clone(), data_type());
Field::CLASS_MEMBER, context_var_field_ = new PrivVarField(analyzer_context_id->clone(), context_type());
dataunit_id->clone(),
data_type());
context_var_field_ = new PrivVarField(
analyzer_context_id->clone(),
context_type());
} }
AnalyzerDataUnit::~AnalyzerDataUnit() AnalyzerDataUnit::~AnalyzerDataUnit()
@ -35,26 +24,22 @@ AnalyzerDataUnit::~AnalyzerDataUnit()
delete context_var_field_; delete context_var_field_;
} }
void AnalyzerDataUnit::Prepare(Env *env) void AnalyzerDataUnit::Prepare(Env* env)
{ {
dataunit_var_field_->Prepare(env); dataunit_var_field_->Prepare(env);
context_var_field_->Prepare(env); context_var_field_->Prepare(env);
} }
void AnalyzerDataUnit::GenNewDataUnit(Output *out_cc, Env *env) void AnalyzerDataUnit::GenNewDataUnit(Output* out_cc, Env* env)
{ {
out_cc->println("%s = new %s(%s);", out_cc->println("%s = new %s(%s);", env->LValue(dataunit_id), data_type()->class_name().c_str(),
env->LValue(dataunit_id), data_type()->EvalParameters(out_cc, env).c_str());
data_type()->class_name().c_str(),
data_type()->EvalParameters(out_cc, env).c_str());
} }
void AnalyzerDataUnit::GenNewContext(Output *out_cc, Env *env) void AnalyzerDataUnit::GenNewContext(Output* out_cc, Env* env)
{ {
out_cc->println("%s = new %s(%s);", out_cc->println("%s = new %s(%s);", env->LValue(analyzer_context_id),
env->LValue(analyzer_context_id), context_type()->class_name().c_str(),
context_type()->class_name().c_str(), context_type()->EvalParameters(out_cc, env).c_str());
context_type()->EvalParameters(out_cc, env).c_str());
env->SetEvaluated(analyzer_context_id); env->SetEvaluated(analyzer_context_id);
} }

View file

@ -7,43 +7,43 @@
// data unit of a DCE/RPC flow is DCE_RPC_PDU. // data unit of a DCE/RPC flow is DCE_RPC_PDU.
class AnalyzerDataUnit : public AnalyzerElement class AnalyzerDataUnit : public AnalyzerElement
{ {
public: public:
enum DataUnitType { DATAGRAM, FLOWUNIT }; enum DataUnitType
AnalyzerDataUnit( {
DataUnitType type, DATAGRAM,
ID *id, FLOWUNIT
ExprList *type_params, };
ExprList *context_params); AnalyzerDataUnit(DataUnitType type, ID* id, ExprList* type_params, ExprList* context_params);
~AnalyzerDataUnit(); ~AnalyzerDataUnit();
void Prepare(Env *env); void Prepare(Env* env);
// Initializes dataunit_id // Initializes dataunit_id
void GenNewDataUnit(Output *out_cc, Env *env); void GenNewDataUnit(Output* out_cc, Env* env);
// Initializes analyzer_context_id // Initializes analyzer_context_id
void GenNewContext(Output *out_cc, Env *env); void GenNewContext(Output* out_cc, Env* env);
DataUnitType type() const { return type_; } DataUnitType type() const { return type_; }
const ID *id() const { return id_; } const ID* id() const { return id_; }
ExprList *type_params() const { return type_params_; } ExprList* type_params() const { return type_params_; }
ExprList *context_params() const { return context_params_; } ExprList* context_params() const { return context_params_; }
ParameterizedType *data_type() const { return data_type_; } ParameterizedType* data_type() const { return data_type_; }
ParameterizedType *context_type() const { return context_type_; } ParameterizedType* context_type() const { return context_type_; }
Field *dataunit_var_field() const { return dataunit_var_field_; } Field* dataunit_var_field() const { return dataunit_var_field_; }
Field *context_var_field() const { return context_var_field_; } Field* context_var_field() const { return context_var_field_; }
private: private:
DataUnitType type_; DataUnitType type_;
ID *id_; ID* id_;
ExprList *type_params_; ExprList* type_params_;
ExprList *context_params_; ExprList* context_params_;
ParameterizedType *data_type_; ParameterizedType* data_type_;
ParameterizedType *context_type_; ParameterizedType* context_type_;
Field *dataunit_var_field_; Field* dataunit_var_field_;
Field *context_var_field_; Field* context_var_field_;
}; };
#endif // pac_dataunit_h #endif // pac_dataunit_h

View file

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

View file

@ -3,4 +3,4 @@
#include "pac_id.h" #include "pac_id.h"
#endif // pac_decl_inl_h #endif // pac_decl_inl_h

View file

@ -1,3 +1,5 @@
#include "pac_decl.h"
#include "pac_attr.h" #include "pac_attr.h"
#include "pac_context.h" #include "pac_context.h"
#include "pac_dataptr.h" #include "pac_dataptr.h"
@ -12,13 +14,10 @@
#include "pac_type.h" #include "pac_type.h"
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_decl.h" DeclList* Decl::decl_list_ = 0;
DeclList *Decl::decl_list_ = 0;
Decl::DeclMap Decl::decl_map_; Decl::DeclMap Decl::decl_map_;
Decl::Decl(ID* id, DeclType decl_type) Decl::Decl(ID* id, DeclType decl_type) : id_(id), decl_type_(decl_type), attrlist_(0)
: id_(id), decl_type_(decl_type), attrlist_(0)
{ {
decl_map_[id_] = this; decl_map_[id_] = this;
if ( ! decl_list_ ) if ( ! decl_list_ )
@ -42,44 +41,42 @@ void Decl::AddAttrs(AttrList* attrs)
return; return;
if ( ! attrlist_ ) if ( ! attrlist_ )
attrlist_ = new AttrList(); attrlist_ = new AttrList();
foreach ( i, AttrList, attrs ) foreach (i, AttrList, attrs)
{ {
attrlist_->push_back(*i); attrlist_->push_back(*i);
ProcessAttr(*i); ProcessAttr(*i);
} }
} }
void Decl::ProcessAttr(Attr *attr) void Decl::ProcessAttr(Attr* attr)
{ {
throw Exception(attr, "unhandled attribute"); throw Exception(attr, "unhandled attribute");
} }
void Decl::SetAnalyzerContext() void Decl::SetAnalyzerContext()
{ {
analyzer_context_ = analyzer_context_ = AnalyzerContextDecl::current_analyzer_context();
AnalyzerContextDecl::current_analyzer_context();
if ( ! analyzer_context_ ) if ( ! analyzer_context_ )
{ {
throw Exception(this, throw Exception(this, "analyzer context not defined");
"analyzer context not defined");
} }
} }
void Decl::ProcessDecls(Output *out_h, Output *out_cc) void Decl::ProcessDecls(Output* out_h, Output* out_cc)
{ {
if ( ! decl_list_ ) if ( ! decl_list_ )
return; return;
foreach(i, DeclList, decl_list_) foreach (i, DeclList, decl_list_)
{ {
Decl *decl = *i; Decl* decl = *i;
current_decl_id = decl->id(); current_decl_id = decl->id();
decl->Prepare(); decl->Prepare();
} }
foreach(i, DeclList, decl_list_) foreach (i, DeclList, decl_list_)
{ {
Decl *decl = *i; Decl* decl = *i;
current_decl_id = decl->id(); current_decl_id = decl->id();
decl->GenExternDeclaration(out_h); decl->GenExternDeclaration(out_h);
} }
@ -87,12 +84,11 @@ void Decl::ProcessDecls(Output *out_h, Output *out_cc)
out_h->println("namespace binpac {\n"); out_h->println("namespace binpac {\n");
out_cc->println("namespace binpac {\n"); out_cc->println("namespace binpac {\n");
AnalyzerContextDecl *analyzer_context = AnalyzerContextDecl* analyzer_context = AnalyzerContextDecl::current_analyzer_context();
AnalyzerContextDecl::current_analyzer_context();
foreach(i, DeclList, decl_list_) foreach (i, DeclList, decl_list_)
{ {
Decl *decl = *i; Decl* decl = *i;
current_decl_id = decl->id(); current_decl_id = decl->id();
decl->GenForwardDeclaration(out_h); decl->GenForwardDeclaration(out_h);
} }
@ -102,9 +98,9 @@ void Decl::ProcessDecls(Output *out_h, Output *out_cc)
out_h->println(""); out_h->println("");
foreach(i, DeclList, decl_list_) foreach (i, DeclList, decl_list_)
{ {
Decl *decl = *i; Decl* decl = *i;
current_decl_id = decl->id(); current_decl_id = decl->id();
decl->GenCode(out_h, out_cc); decl->GenCode(out_h, out_cc);
} }
@ -129,13 +125,9 @@ Decl* Decl::LookUpDecl(const ID* id)
int HelperDecl::helper_id_seq = 0; int HelperDecl::helper_id_seq = 0;
HelperDecl::HelperDecl(HelperType helper_type, HelperDecl::HelperDecl(HelperType helper_type, ID* context_id, EmbeddedCode* code)
ID* context_id, : Decl(new ID(strfmt("helper_%d", ++helper_id_seq)), HELPER), helper_type_(helper_type),
EmbeddedCode* code) 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)
{ {
} }
@ -150,15 +142,15 @@ void HelperDecl::Prepare()
// Do nothing // Do nothing
} }
void HelperDecl::GenExternDeclaration(Output *out_h) void HelperDecl::GenExternDeclaration(Output* out_h)
{ {
if ( helper_type_ == EXTERN ) if ( helper_type_ == EXTERN )
code_->GenCode(out_h, global_env()); code_->GenCode(out_h, global_env());
} }
void HelperDecl::GenCode(Output *out_h, Output *out_cc) void HelperDecl::GenCode(Output* out_h, Output* out_cc)
{ {
Env *env = global_env(); Env* env = global_env();
#if 0 #if 0
if ( context_id_ ) if ( context_id_ )

View file

@ -5,75 +5,92 @@
#include "pac_id.h" #include "pac_id.h"
class Decl : public Object class Decl : public Object
{ {
public: public:
// Note: ANALYZER is not for AnalyzerDecl (which is an // Note: ANALYZER is not for AnalyzerDecl (which is an
// abstract class) , but for AnalyzerContextDecl. // abstract class) , but for AnalyzerContextDecl.
enum DeclType { ENUM, LET, TYPE, FUNC, CONN, FLOW, ANALYZER, HELPER, REGEX }; enum DeclType
{
ENUM,
LET,
TYPE,
FUNC,
CONN,
FLOW,
ANALYZER,
HELPER,
REGEX
};
Decl(ID *id, DeclType decl_type); Decl(ID* id, DeclType decl_type);
virtual ~Decl(); virtual ~Decl();
const ID *id() const { return id_; } const ID* id() const { return id_; }
DeclType decl_type() const { return decl_type_; } DeclType decl_type() const { return decl_type_; }
AnalyzerContextDecl *analyzer_context() const AnalyzerContextDecl* analyzer_context() const { return analyzer_context_; }
{ return analyzer_context_; }
// NULL except for TypeDecl or AnalyzerDecl // NULL except for TypeDecl or AnalyzerDecl
virtual Env *env() const { return 0; } virtual Env* env() const { return 0; }
virtual void Prepare() = 0; virtual void Prepare() = 0;
// Generate declarations out of the "binpac" namespace // Generate declarations out of the "binpac" namespace
virtual void GenExternDeclaration(Output *out_h) { /* do nothing */ } virtual void GenExternDeclaration(Output* out_h)
{ /* do nothing */
}
// Generate declarations before definition of classes // Generate declarations before definition of classes
virtual void GenForwardDeclaration(Output *out_h) = 0; virtual void GenForwardDeclaration(Output* out_h) = 0;
virtual void GenCode(Output *out_h, Output *out_cc) = 0; virtual void GenCode(Output* out_h, Output* out_cc) = 0;
void TakeExprList(); void TakeExprList();
void AddAttrs(AttrList *attrlist); void AddAttrs(AttrList* attrlist);
void SetAnalyzerContext(); void SetAnalyzerContext();
protected: protected:
virtual void ProcessAttr(Attr *a); virtual void ProcessAttr(Attr* a);
ID *id_; ID* id_;
DeclType decl_type_; DeclType decl_type_;
AttrList *attrlist_; AttrList* attrlist_;
AnalyzerContextDecl *analyzer_context_; AnalyzerContextDecl* analyzer_context_;
public: public:
static void ProcessDecls(Output *out_h, Output *out_cc); static void ProcessDecls(Output* out_h, Output* out_cc);
static Decl *LookUpDecl(const ID *id); static Decl* LookUpDecl(const ID* id);
private: private:
static DeclList *decl_list_; static DeclList* decl_list_;
typedef map<const ID *, Decl*, ID_ptr_cmp> DeclMap; typedef map<const ID*, Decl*, ID_ptr_cmp> DeclMap;
static DeclMap decl_map_; static DeclMap decl_map_;
}; };
class HelperDecl : public Decl class HelperDecl : public Decl
{ {
public: public:
enum HelperType { enum HelperType
HEADER, CODE, EXTERN, {
}; HEADER,
HelperDecl(HelperType type, ID *context_id, EmbeddedCode *code); CODE,
EXTERN,
};
HelperDecl(HelperType type, ID* context_id, EmbeddedCode* code);
~HelperDecl(); ~HelperDecl();
void Prepare(); void Prepare();
void GenExternDeclaration(Output *out_h); void GenExternDeclaration(Output* out_h);
void GenForwardDeclaration(Output *out_h) { /* do nothing */ } void GenForwardDeclaration(Output* out_h)
void GenCode(Output *out_h, Output *out_cc); { /* do nothing */
}
void GenCode(Output* out_h, Output* out_cc);
private: private:
HelperType helper_type_; HelperType helper_type_;
ID *context_id_; ID* context_id_;
EmbeddedCode *code_; EmbeddedCode* code_;
static int helper_id_seq; static int helper_id_seq;
}; };
#endif // pac_decl_h #endif // pac_decl_h

View file

@ -1,27 +1,22 @@
#include "pac_id.h"
#include "pac_primitive.h"
#include "pac_output.h"
#include "pac_embedded.h" #include "pac_embedded.h"
EmbeddedCodeSegment::EmbeddedCodeSegment(const string &s) #include "pac_id.h"
: s_(s), primitive_(0) #include "pac_output.h"
{ #include "pac_primitive.h"
}
EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive *primitive) EmbeddedCodeSegment::EmbeddedCodeSegment(const string& s) : s_(s), primitive_(0) { }
: s_(""), primitive_(primitive)
{ EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive* primitive)
} : s_(""), primitive_(primitive) { }
EmbeddedCodeSegment::~EmbeddedCodeSegment() EmbeddedCodeSegment::~EmbeddedCodeSegment()
{ {
delete primitive_; delete primitive_;
} }
string EmbeddedCodeSegment::ToCode(Env *env) string EmbeddedCodeSegment::ToCode(Env* env)
{ {
if ( primitive_ && s_.empty() ) if ( primitive_ && s_.empty() )
s_ = primitive_->ToCode(env); s_ = primitive_->ToCode(env);
return s_; return s_;
} }
@ -41,12 +36,12 @@ void EmbeddedCode::Append(int atom)
current_segment_ += static_cast<char>(atom); current_segment_ += static_cast<char>(atom);
} }
void EmbeddedCode::Append(const char *str) void EmbeddedCode::Append(const char* str)
{ {
current_segment_ += str; current_segment_ += str;
} }
void EmbeddedCode::Append(PacPrimitive *primitive) void EmbeddedCode::Append(PacPrimitive* primitive)
{ {
if ( ! current_segment_.empty() ) if ( ! current_segment_.empty() )
{ {
@ -56,7 +51,7 @@ void EmbeddedCode::Append(PacPrimitive *primitive)
segments_->push_back(new EmbeddedCodeSegment(primitive)); segments_->push_back(new EmbeddedCodeSegment(primitive));
} }
void EmbeddedCode::GenCode(Output *out, Env *env) void EmbeddedCode::GenCode(Output* out, Env* env)
{ {
if ( ! current_segment_.empty() ) if ( ! current_segment_.empty() )
{ {
@ -71,9 +66,9 @@ void EmbeddedCode::GenCode(Output *out, Env *env)
// ID's name is used as its RValue // ID's name is used as its RValue
env->set_allow_undefined_id(true); env->set_allow_undefined_id(true);
foreach(i, EmbeddedCodeSegmentList, segments_) foreach (i, EmbeddedCodeSegmentList, segments_)
{ {
EmbeddedCodeSegment *segment = *i; EmbeddedCodeSegment* segment = *i;
out->print("%s", segment->ToCode(env).c_str()); out->print("%s", segment->ToCode(env).c_str());
} }

View file

@ -4,39 +4,39 @@
#include "pac_common.h" #include "pac_common.h"
class EmbeddedCodeSegment class EmbeddedCodeSegment
{ {
public: public:
explicit EmbeddedCodeSegment(const string &s); explicit EmbeddedCodeSegment(const string& s);
explicit EmbeddedCodeSegment(PacPrimitive *primitive); explicit EmbeddedCodeSegment(PacPrimitive* primitive);
~EmbeddedCodeSegment(); ~EmbeddedCodeSegment();
string ToCode(Env *env); string ToCode(Env* env);
private: private:
string s_; string s_;
PacPrimitive *primitive_; PacPrimitive* primitive_;
}; };
typedef vector<EmbeddedCodeSegment *> EmbeddedCodeSegmentList; typedef vector<EmbeddedCodeSegment*> EmbeddedCodeSegmentList;
class EmbeddedCode : public Object class EmbeddedCode : public Object
{ {
public: public:
EmbeddedCode(); EmbeddedCode();
~EmbeddedCode(); ~EmbeddedCode();
// Append a character // Append a character
void Append(int atom); void Append(int atom);
void Append(const char *str); void Append(const char* str);
// Append a PAC primitive // Append a PAC primitive
void Append(PacPrimitive *primitive); void Append(PacPrimitive* primitive);
void GenCode(Output *out, Env *env); void GenCode(Output* out, Env* env);
private: private:
string current_segment_; string current_segment_;
EmbeddedCodeSegmentList *segments_; EmbeddedCodeSegmentList* segments_;
}; };
#endif // pac_embedded_h #endif // pac_embedded_h

View file

@ -1,14 +1,12 @@
#include "pac_exception.h"
#include "pac_enum.h" #include "pac_enum.h"
#include "pac_exception.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_typedecl.h" #include "pac_typedecl.h"
Enum::Enum(ID* id, Expr* expr) Enum::Enum(ID* id, Expr* expr) : id_(id), expr_(expr) { }
: id_(id), expr_(expr)
{
}
Enum::~Enum() Enum::~Enum()
{ {
@ -16,7 +14,7 @@ Enum::~Enum()
delete expr_; delete expr_;
} }
void Enum::GenHeader(Output* out_h, int *pval) void Enum::GenHeader(Output* out_h, int* pval)
{ {
ASSERT(pval); ASSERT(pval);
if ( expr_ ) if ( expr_ )
@ -30,10 +28,9 @@ void Enum::GenHeader(Output* out_h, int *pval)
global_env()->AddConstID(id_, *pval); global_env()->AddConstID(id_, *pval);
} }
EnumDecl::EnumDecl(ID *id, EnumList *enumlist) EnumDecl::EnumDecl(ID* id, EnumList* enumlist) : Decl(id, ENUM), enumlist_(enumlist)
: Decl(id, ENUM), enumlist_(enumlist)
{ {
ID *type_id = id->clone(); ID* type_id = id->clone();
datatype_ = new ExternType(type_id, ExternType::NUMBER); datatype_ = new ExternType(type_id, ExternType::NUMBER);
extern_typedecl_ = new TypeDecl(type_id, 0, datatype_); extern_typedecl_ = new TypeDecl(type_id, 0, datatype_);
} }
@ -49,12 +46,12 @@ void EnumDecl::Prepare()
// Do nothing // Do nothing
} }
void EnumDecl::GenForwardDeclaration(Output *out_h) void EnumDecl::GenForwardDeclaration(Output* out_h)
{ {
out_h->println("enum %s {", id_->Name()); out_h->println("enum %s {", id_->Name());
out_h->inc_indent(); out_h->inc_indent();
int c = 0; int c = 0;
foreach(i, EnumList, enumlist_) foreach (i, EnumList, enumlist_)
{ {
(*i)->GenHeader(out_h, &c); (*i)->GenHeader(out_h, &c);
++c; ++c;
@ -67,4 +64,3 @@ void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */)
{ {
// Do nothing // Do nothing
} }

View file

@ -4,34 +4,34 @@
#include "pac_decl.h" #include "pac_decl.h"
class Enum class Enum
{ {
public: public:
Enum(ID *id, Expr *expr = 0); Enum(ID* id, Expr* expr = 0);
~Enum(); ~Enum();
void GenHeader(Output *out_h, int *pval); void GenHeader(Output* out_h, int* pval);
private: private:
ID *id_; ID* id_;
Expr *expr_; Expr* expr_;
}; };
class EnumDecl : public Decl class EnumDecl : public Decl
{ {
public: public:
EnumDecl(ID *id, EnumList *enumlist); EnumDecl(ID* id, EnumList* enumlist);
~EnumDecl(); ~EnumDecl();
Type *DataType() const { return datatype_; } Type* DataType() const { return datatype_; }
void Prepare(); void Prepare();
void GenForwardDeclaration(Output *out_h); void GenForwardDeclaration(Output* out_h);
void GenCode(Output *out_h, Output *out_cc); void GenCode(Output* out_h, Output* out_cc);
private: private:
EnumList *enumlist_; EnumList* enumlist_;
Type *datatype_; Type* datatype_;
TypeDecl *extern_typedecl_; TypeDecl* extern_typedecl_;
}; };
#endif // pac_enum_h #endif // pac_enum_h

View file

@ -1,4 +1,5 @@
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_utils.h" #include "pac_utils.h"
@ -20,52 +21,43 @@ Exception::Exception(const Object* o, string msg)
} }
} }
ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) : Exception(id), id_(id)
: Exception(id), id_(id)
{ {
append(strfmt("`%s' undeclared", id_->Name())); append(strfmt("`%s' undeclared", id_->Name()));
} }
ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) : Exception(id), id_(id)
: Exception(id), id_(id)
{ {
append(strfmt("`%s' redefined", id_->Name())); append(strfmt("`%s' redefined", id_->Name()));
} }
ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) : Exception(id), id_(id)
: Exception(id), id_(id)
{ {
append(strfmt("ID `%s' not evaluated before used", id->Name())); append(strfmt("ID `%s' not evaluated before used", id->Name()));
} }
ExceptionIDNotField::ExceptionIDNotField(const ID* id) ExceptionIDNotField::ExceptionIDNotField(const ID* id) : Exception(id), id_(id)
: Exception(id), id_(id)
{ {
append(strfmt("ID `%s' is not a field", id_->Name())); append(strfmt("ID `%s' is not a field", id_->Name()));
} }
ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id, ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id, const ID* member_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'", append(strfmt("type %s does not have member `%s'", type_id_->Name(), member_id_->Name()));
type_id_->Name(), member_id_->Name()));
} }
ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) : Exception(id), id_(id)
: Exception(id), id_(id)
{ {
append(strfmt("cyclic dependence through `%s'", id_->Name())); append(strfmt("cyclic dependence through `%s'", id_->Name()));
} }
ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) : Exception(o)
: Exception(o)
{ {
append(msg.c_str()); append(msg.c_str());
} }
ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) : Exception(expr), expr(expr)
: Exception(expr), expr(expr)
{ {
append(strfmt("Expression `%s' is not constant", expr->orig())); append(strfmt("Expression `%s' is not constant", expr->orig()));
} }
@ -73,11 +65,14 @@ ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr)
ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr) ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr)
: Exception(expr), expr(expr) : Exception(expr), expr(expr)
{ {
append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index", expr->orig())); append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index",
expr->orig()));
} }
ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr) ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr)
: Exception(expr), expr(expr) : Exception(expr), expr(expr)
{ {
append(strfmt("Expression `%s' as a case index is outside the numeric limit of the type used for the switch expression", expr->orig())); append(strfmt("Expression `%s' as a case index is outside the numeric limit of the type used "
"for the switch expression",
expr->orig()));
} }

View file

@ -7,107 +7,107 @@ using namespace std;
#include "pac_common.h" #include "pac_common.h"
class Exception class Exception
{ {
public: public:
Exception(const Object* o, string msg = ""); Exception(const Object* o, string msg = "");
const char* msg() const { return msg_.c_str(); } const char* msg() const { return msg_.c_str(); }
void append(string s) { msg_ += s; } void append(string s) { msg_ += s; }
private: private:
string msg_; string msg_;
}; };
class ExceptionIDNotFound : public Exception class ExceptionIDNotFound : public Exception
{ {
public: public:
ExceptionIDNotFound(const ID* id); ExceptionIDNotFound(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
private: private:
const ID* id_; const ID* id_;
}; };
class ExceptionIDRedefinition : public Exception class ExceptionIDRedefinition : public Exception
{ {
public: public:
ExceptionIDRedefinition(const ID* id); ExceptionIDRedefinition(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
private: private:
const ID* id_; const ID* id_;
}; };
class ExceptionIDNotEvaluated : public Exception class ExceptionIDNotEvaluated : public Exception
{ {
public: public:
ExceptionIDNotEvaluated(const ID* id); ExceptionIDNotEvaluated(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
private: private:
const ID* id_; const ID* id_;
}; };
class ExceptionCyclicDependence : public Exception class ExceptionCyclicDependence : public Exception
{ {
public: public:
ExceptionCyclicDependence(const ID* id); ExceptionCyclicDependence(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
private: private:
const ID* id_; const ID* id_;
}; };
class ExceptionPaddingError : public Exception class ExceptionPaddingError : public Exception
{ {
public: public:
ExceptionPaddingError(const Object* o, string msg); ExceptionPaddingError(const Object* o, string msg);
}; };
class ExceptionIDNotField : public Exception class ExceptionIDNotField : public Exception
{ {
public: public:
ExceptionIDNotField(const ID* id); ExceptionIDNotField(const ID* id);
const ID* id() const { return id_; } const ID* id() const { return id_; }
private: private:
const ID* id_; const ID* id_;
}; };
class ExceptionMemberNotFound : public Exception class ExceptionMemberNotFound : public Exception
{ {
public: public:
ExceptionMemberNotFound(const ID* type_id, const ID *member_id); ExceptionMemberNotFound(const ID* type_id, const ID* member_id);
private: private:
const ID *type_id_, *member_id_; const ID *type_id_, *member_id_;
}; };
class ExceptionNonConstExpr : public Exception class ExceptionNonConstExpr : public Exception
{ {
public: public:
ExceptionNonConstExpr(const Expr* expr); ExceptionNonConstExpr(const Expr* expr);
private: private:
const Expr *expr; const Expr* expr;
}; };
class ExceptionInvalidCaseSizeExpr : public Exception class ExceptionInvalidCaseSizeExpr : public Exception
{ {
public: public:
ExceptionInvalidCaseSizeExpr(const Expr* expr); ExceptionInvalidCaseSizeExpr(const Expr* expr);
private: private:
const Expr *expr; const Expr* expr;
}; };
class ExceptionInvalidCaseLimitExpr : public Exception class ExceptionInvalidCaseLimitExpr : public Exception
{ {
public: public:
ExceptionInvalidCaseLimitExpr(const Expr* expr); ExceptionInvalidCaseLimitExpr(const Expr* expr);
private: private:
const Expr *expr; const Expr* expr;
}; };
#endif /* pac_exception_h */ #endif /* pac_exception_h */

View file

@ -1,7 +1,8 @@
#include "pac_expr.h"
#include "pac_case.h" #include "pac_case.h"
#include "pac_cstr.h" #include "pac_cstr.h"
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_expr.h"
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_number.h" #include "pac_number.h"
@ -12,13 +13,13 @@
#include "pac_typedecl.h" #include "pac_typedecl.h"
#include "pac_utils.h" #include "pac_utils.h"
string OrigExprList(ExprList *list) string OrigExprList(ExprList* list)
{ {
bool first = true; bool first = true;
string str; string str;
foreach(i, ExprList, list) foreach (i, ExprList, list)
{ {
Expr *expr = *i; Expr* expr = *i;
if ( first ) if ( first )
first = false; first = false;
else else
@ -28,12 +29,12 @@ string OrigExprList(ExprList *list)
return str; return str;
} }
string EvalExprList(ExprList *exprlist, Output *out, Env *env) string EvalExprList(ExprList* exprlist, Output* out, Env* env)
{ {
string val_list(""); string val_list("");
bool first = true; bool first = true;
foreach(i, ExprList, exprlist) foreach (i, ExprList, exprlist)
{ {
if ( ! first ) if ( ! first )
val_list += ", "; val_list += ", ";
@ -44,11 +45,10 @@ string EvalExprList(ExprList *exprlist, Output *out, Env *env)
return val_list; return val_list;
} }
static const char* expr_fmt[] = static const char* expr_fmt[] = {
{ #define EXPR_DEF(type, num_op, fmt) fmt,
# define EXPR_DEF(type, num_op, fmt) fmt, #include "pac_expr.def"
# include "pac_expr.def" #undef EXPR_DEF
# undef EXPR_DEF
}; };
void Expr::init() void Expr::init()
@ -65,8 +65,7 @@ void Expr::init()
cases_ = 0; cases_ = 0;
} }
Expr::Expr(ID* arg_id) Expr::Expr(ID* arg_id) : DataDepElement(EXPR)
: DataDepElement(EXPR)
{ {
init(); init();
expr_type_ = EXPR_ID; expr_type_ = EXPR_ID;
@ -75,8 +74,7 @@ Expr::Expr(ID* arg_id)
orig_ = strfmt("%s", id_->Name()); orig_ = strfmt("%s", id_->Name());
} }
Expr::Expr(Number* arg_num) Expr::Expr(Number* arg_num) : DataDepElement(EXPR)
: DataDepElement(EXPR)
{ {
init(); init();
expr_type_ = EXPR_NUM; expr_type_ = EXPR_NUM;
@ -85,8 +83,7 @@ Expr::Expr(Number* arg_num)
orig_ = strfmt("((int) %s)", num_->Str()); orig_ = strfmt("((int) %s)", num_->Str());
} }
Expr::Expr(ConstString *cstr) Expr::Expr(ConstString* cstr) : DataDepElement(EXPR)
: DataDepElement(EXPR)
{ {
init(); init();
expr_type_ = EXPR_CSTR; expr_type_ = EXPR_CSTR;
@ -95,8 +92,7 @@ Expr::Expr(ConstString *cstr)
orig_ = cstr_->str(); orig_ = cstr_->str();
} }
Expr::Expr(RegEx *regex) Expr::Expr(RegEx* regex) : DataDepElement(EXPR)
: DataDepElement(EXPR)
{ {
init(); init();
expr_type_ = EXPR_REGEX; expr_type_ = EXPR_REGEX;
@ -105,8 +101,7 @@ Expr::Expr(RegEx *regex)
orig_ = strfmt("/%s/", regex_->str().c_str()); orig_ = strfmt("/%s/", regex_->str().c_str());
} }
Expr::Expr(ExprType arg_type, Expr* op1) Expr::Expr(ExprType arg_type, Expr* op1) : DataDepElement(EXPR)
: DataDepElement(EXPR)
{ {
init(); init();
expr_type_ = arg_type; expr_type_ = arg_type;
@ -115,8 +110,7 @@ Expr::Expr(ExprType arg_type, Expr* op1)
orig_ = strfmt(expr_fmt[expr_type_], op1->orig()); orig_ = strfmt(expr_fmt[expr_type_], op1->orig());
} }
Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2) : DataDepElement(EXPR)
: DataDepElement(EXPR)
{ {
init(); init();
expr_type_ = arg_type; expr_type_ = arg_type;
@ -127,8 +121,7 @@ Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2)
orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig()); orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig());
} }
Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3) : DataDepElement(EXPR)
: DataDepElement(EXPR)
{ {
init(); init();
expr_type_ = arg_type; expr_type_ = arg_type;
@ -139,8 +132,7 @@ Expr::Expr(ExprType arg_type, Expr* op1, Expr* op2, Expr* op3)
orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig(), op3->orig()); orig_ = strfmt(expr_fmt[expr_type_], op1->orig(), op2->orig(), op3->orig());
} }
Expr::Expr(ExprList *args) Expr::Expr(ExprList* args) : DataDepElement(EXPR)
: DataDepElement(EXPR)
{ {
init(); init();
expr_type_ = EXPR_CALLARGS; expr_type_ = EXPR_CALLARGS;
@ -150,8 +142,7 @@ Expr::Expr(ExprList *args)
orig_ = OrigExprList(args_); orig_ = OrigExprList(args_);
} }
Expr::Expr(Expr *index, CaseExprList *cases) Expr::Expr(Expr* index, CaseExprList* cases) : DataDepElement(EXPR)
: DataDepElement(EXPR)
{ {
init(); init();
expr_type_ = EXPR_CASE; expr_type_ = EXPR_CASE;
@ -160,12 +151,10 @@ Expr::Expr(Expr *index, CaseExprList *cases)
cases_ = cases; cases_ = cases;
orig_ = strfmt("case %s of { ", index->orig()); orig_ = strfmt("case %s of { ", index->orig());
foreach(i, CaseExprList, cases_) foreach (i, CaseExprList, cases_)
{ {
CaseExpr *c = *i; CaseExpr* c = *i;
orig_ += strfmt("%s => %s; ", orig_ += strfmt("%s => %s; ", OrigExprList(c->index()).c_str(), c->value()->orig());
OrigExprList(c->index()).c_str(),
c->value()->orig());
} }
orig_ += "}"; orig_ += "}";
} }
@ -180,7 +169,7 @@ Expr::~Expr()
delete_list(CaseExprList, cases_); delete_list(CaseExprList, cases_);
} }
void Expr::AddCaseExpr(CaseExpr *case_expr) void Expr::AddCaseExpr(CaseExpr* case_expr)
{ {
ASSERT(str_.empty()); ASSERT(str_.empty());
ASSERT(expr_type_ == EXPR_CASE); ASSERT(expr_type_ == EXPR_CASE);
@ -188,7 +177,7 @@ void Expr::AddCaseExpr(CaseExpr *case_expr)
cases_->push_back(case_expr); cases_->push_back(case_expr);
} }
void Expr::GenStrFromFormat(Env *env) void Expr::GenStrFromFormat(Env* env)
{ {
// The format != "@custom@" // The format != "@custom@"
ASSERT(*expr_fmt[expr_type_] != '@'); ASSERT(*expr_fmt[expr_type_] != '@');
@ -196,19 +185,14 @@ void Expr::GenStrFromFormat(Env *env)
switch ( num_operands_ ) switch ( num_operands_ )
{ {
case 1: case 1:
str_ = strfmt(expr_fmt[expr_type_], str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str());
operand_[0]->str());
break; break;
case 2: case 2:
str_ = strfmt(expr_fmt[expr_type_], str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str());
operand_[0]->str(),
operand_[1]->str());
break; break;
case 3: case 3:
str_ = strfmt(expr_fmt[expr_type_], str_ = strfmt(expr_fmt[expr_type_], operand_[0]->str(), operand_[1]->str(),
operand_[0]->str(), operand_[2]->str());
operand_[1]->str(),
operand_[2]->str());
break; break;
default: default:
DEBUG_MSG("num_operands_ = %d, orig = %s\n", num_operands_, orig()); DEBUG_MSG("num_operands_ = %d, orig = %s\n", num_operands_, orig());
@ -217,43 +201,41 @@ void Expr::GenStrFromFormat(Env *env)
} }
} }
namespace { namespace
{
RecordField *GetRecordField(const ID *id, Env *env) RecordField* GetRecordField(const ID* id, Env* env)
{ {
Field* field = env->GetField(id); Field* field = env->GetField(id);
ASSERT(field); ASSERT(field);
if ( field->tof() != RECORD_FIELD && if ( field->tof() != RECORD_FIELD && field->tof() != PADDING_FIELD )
field->tof() != PADDING_FIELD ) throw Exception(id, "not a record field");
throw Exception(id, "not a record field"); RecordField* r = static_cast<RecordField*>(field);
RecordField *r = static_cast<RecordField *>(field); ASSERT(r);
ASSERT(r); return r;
return r; }
}
} // private namespace } // private namespace
void Expr::GenCaseEval(Output *out_cc, Env *env) void Expr::GenCaseEval(Output* out_cc, Env* env)
{ {
ASSERT(expr_type_ == EXPR_CASE); ASSERT(expr_type_ == EXPR_CASE);
ASSERT(operand_[0]); ASSERT(operand_[0]);
ASSERT(cases_); ASSERT(cases_);
Type *val_type = DataType(env); Type* val_type = DataType(env);
ID *val_var = env->AddTempID(val_type); ID* val_var = env->AddTempID(val_type);
// DataType(env) can return a null pointer if an enum value is not // DataType(env) can return a null pointer if an enum value is not
// defined. // defined.
if ( ! val_type ) if ( ! val_type )
throw Exception(this, "undefined case value"); throw Exception(this, "undefined case value");
out_cc->println("%s %s;", out_cc->println("%s %s;", val_type->DataTypeStr().c_str(), env->LValue(val_var));
val_type->DataTypeStr().c_str(),
env->LValue(val_var));
// force evaluation of IDs appearing in case stmt // force evaluation of IDs appearing in case stmt
operand_[0]->ForceIDEval(out_cc, env); operand_[0]->ForceIDEval(out_cc, env);
foreach(i, CaseExprList, cases_) foreach (i, CaseExprList, cases_)
(*i)->value()->ForceIDEval(out_cc, env); (*i)->value()->ForceIDEval(out_cc, env);
out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env)); out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env));
@ -262,11 +244,11 @@ void Expr::GenCaseEval(Output *out_cc, Env *env)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
CaseExpr *default_case = 0; CaseExpr* default_case = 0;
foreach(i, CaseExprList, cases_) foreach (i, CaseExprList, cases_)
{ {
CaseExpr *c = *i; CaseExpr* c = *i;
ExprList *index = c->index(); ExprList* index = c->index();
if ( ! index ) if ( ! index )
{ {
if ( default_case ) if ( default_case )
@ -277,9 +259,7 @@ void Expr::GenCaseEval(Output *out_cc, Env *env)
{ {
GenCaseStr(index, out_cc, env, switch_type); GenCaseStr(index, out_cc, env, switch_type);
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(val_var), c->value()->EvalExpr(out_cc, env));
env->LValue(val_var),
c->value()->EvalExpr(out_cc, env));
out_cc->println("break;"); out_cc->println("break;");
out_cc->dec_indent(); out_cc->dec_indent();
} }
@ -290,14 +270,13 @@ void Expr::GenCaseEval(Output *out_cc, Env *env)
out_cc->inc_indent(); out_cc->inc_indent();
if ( default_case ) if ( default_case )
{ {
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(val_var),
env->LValue(val_var),
default_case->value()->EvalExpr(out_cc, env)); default_case->value()->EvalExpr(out_cc, env));
} }
else else
{ {
out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", out_cc->println("throw binpac::ExceptionInvalidCaseIndex(\"%s\", (int64)%s);", Location(),
Location(), operand_[0]->EvalExpr(out_cc, env)); operand_[0]->EvalExpr(out_cc, env));
} }
out_cc->println("break;"); out_cc->println("break;");
out_cc->dec_indent(); out_cc->dec_indent();
@ -333,20 +312,17 @@ void Expr::GenEval(Output* out_cc, Env* env)
*/ */
operand_[0]->GenEval(out_cc, env); operand_[0]->GenEval(out_cc, env);
Type *ty0 = operand_[0]->DataType(env); Type* ty0 = operand_[0]->DataType(env);
if ( ty0 ) if ( ty0 )
{ {
str_ = strfmt("%s%s", str_ = strfmt("%s%s", operand_[0]->EvalExpr(out_cc, env),
operand_[0]->EvalExpr(out_cc, env),
ty0->EvalMember(operand_[1]->id()).c_str()); ty0->EvalMember(operand_[1]->id()).c_str());
} }
else else
{ {
string tmp = strfmt("->%s()", operand_[1]->id()->Name()); string tmp = strfmt("->%s()", operand_[1]->id()->Name());
str_ = strfmt("%s%s", str_ = strfmt("%s%s", operand_[0]->EvalExpr(out_cc, env), tmp.c_str());
operand_[0]->EvalExpr(out_cc, env),
tmp.c_str());
} }
} }
break; break;
@ -359,7 +335,7 @@ void Expr::GenEval(Output* out_cc, Env* env)
string v0 = operand_[0]->EvalExpr(out_cc, env); string v0 = operand_[0]->EvalExpr(out_cc, env);
string v1 = operand_[1]->EvalExpr(out_cc, env); string v1 = operand_[1]->EvalExpr(out_cc, env);
Type *ty0 = operand_[0]->DataType(env); Type* ty0 = operand_[0]->DataType(env);
if ( ty0 ) if ( ty0 )
str_ = ty0->EvalElement(v0, v1); str_ = ty0->EvalElement(v0, v1);
else else
@ -369,9 +345,9 @@ void Expr::GenEval(Output* out_cc, Env* env)
case EXPR_SIZEOF: case EXPR_SIZEOF:
{ {
const ID *id = operand_[0]->id(); const ID* id = operand_[0]->id();
RecordField *rf; RecordField* rf;
Type *ty; Type* ty;
try try
{ {
@ -380,7 +356,7 @@ void Expr::GenEval(Output* out_cc, Env* env)
str_ = strfmt("%s", rf->FieldSize(out_cc, env)); str_ = strfmt("%s", rf->FieldSize(out_cc, env));
} }
} }
catch ( ExceptionIDNotFound &e ) catch ( ExceptionIDNotFound& e )
{ {
if ( (ty = TypeDecl::LookUpType(id)) != 0 ) if ( (ty = TypeDecl::LookUpType(id)) != 0 )
{ {
@ -398,8 +374,8 @@ void Expr::GenEval(Output* out_cc, Env* env)
case EXPR_OFFSETOF: case EXPR_OFFSETOF:
{ {
const ID *id = operand_[0]->id(); const ID* id = operand_[0]->id();
RecordField *rf = GetRecordField(id, env); RecordField* rf = GetRecordField(id, env);
str_ = strfmt("%s", rf->FieldOffset(out_cc, env)); str_ = strfmt("%s", rf->FieldOffset(out_cc, env));
} }
break; break;
@ -423,7 +399,7 @@ void Expr::GenEval(Output* out_cc, Env* env)
} }
void Expr::ForceIDEval(Output* out_cc, Env* env) void Expr::ForceIDEval(Output* out_cc, Env* env)
{ {
switch ( expr_type_ ) switch ( expr_type_ )
{ {
case EXPR_NUM: case EXPR_NUM:
@ -441,18 +417,18 @@ void Expr::ForceIDEval(Output* out_cc, Env* env)
break; break;
case EXPR_CALLARGS: case EXPR_CALLARGS:
{ {
foreach(i, ExprList, args_) foreach (i, ExprList, args_)
(*i)->ForceIDEval(out_cc, env); (*i)->ForceIDEval(out_cc, env);
} }
break; break;
case EXPR_CASE: case EXPR_CASE:
{ {
operand_[0]->ForceIDEval(out_cc, env); operand_[0]->ForceIDEval(out_cc, env);
foreach(i, CaseExprList, cases_) foreach (i, CaseExprList, cases_)
(*i)->value()->ForceIDEval(out_cc, env); (*i)->value()->ForceIDEval(out_cc, env);
} }
break; break;
default: default:
@ -464,16 +440,15 @@ void Expr::ForceIDEval(Output* out_cc, Env* env)
} }
} }
const char* Expr::EvalExpr(Output* out_cc, Env* env) const char* Expr::EvalExpr(Output* out_cc, Env* env)
{ {
GenEval(out_cc, env); GenEval(out_cc, env);
return str(); return str();
} }
Type *Expr::DataType(Env *env) const Type* Expr::DataType(Env* env) const
{ {
Type *data_type; Type* data_type;
switch ( expr_type_ ) switch ( expr_type_ )
{ {
@ -484,7 +459,7 @@ Type *Expr::DataType(Env *env) const
case EXPR_MEMBER: case EXPR_MEMBER:
{ {
// Get type of the parent // Get type of the parent
Type *parent_type = operand_[0]->DataType(env); Type* parent_type = operand_[0]->DataType(env);
if ( ! parent_type ) if ( ! parent_type )
return 0; return 0;
data_type = parent_type->MemberDataType(operand_[1]->id()); data_type = parent_type->MemberDataType(operand_[1]->id());
@ -494,7 +469,7 @@ Type *Expr::DataType(Env *env) const
case EXPR_SUBSCRIPT: case EXPR_SUBSCRIPT:
{ {
// Get type of the parent // Get type of the parent
Type *parent_type = operand_[0]->DataType(env); Type* parent_type = operand_[0]->DataType(env);
data_type = parent_type->ElementDataType(); data_type = parent_type->ElementDataType();
} }
break; break;
@ -505,14 +480,13 @@ Type *Expr::DataType(Env *env) const
case EXPR_COND: case EXPR_COND:
{ {
Type *type1 = operand_[1]->DataType(env); Type* type1 = operand_[1]->DataType(env);
Type *type2 = operand_[2]->DataType(env); Type* type2 = operand_[2]->DataType(env);
if ( ! Type::CompatibleTypes(type1, type2) ) if ( ! Type::CompatibleTypes(type1, type2) )
{ {
throw Exception(this, throw Exception(this,
strfmt("type mismatch: %s vs %s", strfmt("type mismatch: %s vs %s", type1->DataTypeStr().c_str(),
type1->DataTypeStr().c_str(), type2->DataTypeStr().c_str()));
type2->DataTypeStr().c_str()));
} }
data_type = type1; data_type = type1;
} }
@ -526,20 +500,17 @@ Type *Expr::DataType(Env *env) const
{ {
if ( cases_ && ! cases_->empty() ) if ( cases_ && ! cases_->empty() )
{ {
Type *type1 = Type* type1 = cases_->front()->value()->DataType(env);
cases_->front()->value()->DataType(env);
Type* numeric_with_largest_width = 0; Type* numeric_with_largest_width = 0;
foreach(i, CaseExprList, cases_) foreach (i, CaseExprList, cases_)
{ {
Type *type2 = Type* type2 = (*i)->value()->DataType(env);
(*i)->value()->DataType(env);
if ( ! Type::CompatibleTypes(type1, type2) ) if ( ! Type::CompatibleTypes(type1, type2) )
{ {
throw Exception(this, throw Exception(this, strfmt("type mismatch: %s vs %s",
strfmt("type mismatch: %s vs %s", type1->DataTypeStr().c_str(),
type1->DataTypeStr().c_str(), type2->DataTypeStr().c_str()));
type2->DataTypeStr().c_str()));
} }
if ( type1 == extern_type_nullptr ) if ( type1 == extern_type_nullptr )
type1 = type2; type1 = type2;
@ -611,21 +582,19 @@ Type *Expr::DataType(Env *env) const
return data_type; return data_type;
} }
string Expr::DataTypeStr(Env *env) const string Expr::DataTypeStr(Env* env) const
{ {
Type *type = DataType(env); Type* type = DataType(env);
if ( ! type ) if ( ! type )
{ {
throw Exception(this, throw Exception(this, strfmt("cannot find data type for expression `%s'", orig()));
strfmt("cannot find data type for expression `%s'",
orig()));
} }
return type->DataTypeStr(); return type->DataTypeStr();
} }
string Expr::SetFunc(Output *out, Env *env) string Expr::SetFunc(Output* out, Env* env)
{ {
switch ( expr_type_ ) switch ( expr_type_ )
{ {
@ -635,15 +604,13 @@ string Expr::SetFunc(Output *out, Env *env)
{ {
// Evaluate the parent // Evaluate the parent
string parent_val(operand_[0]->EvalExpr(out, env)); string parent_val(operand_[0]->EvalExpr(out, env));
return parent_val return parent_val + "->" + set_function(operand_[1]->id());
+ "->"
+ set_function(operand_[1]->id());
} }
break; break;
default: default:
throw Exception(this, throw Exception(this, strfmt("cannot generate set function "
strfmt("cannot generate set function " "for expression `%s'",
"for expression `%s'", orig())); orig()));
break; break;
} }
} }
@ -664,143 +631,141 @@ bool Expr::ConstFold(Env* env, int* pn) const
} }
// TODO: build a generic data dependency extraction process // TODO: build a generic data dependency extraction process
namespace { namespace
{
// Maximum of two minimal header sizes // Maximum of two minimal header sizes
int mhs_max(int h1, int h2) int mhs_max(int h1, int h2)
{
if ( h1 < 0 || h2 < 0 )
return -1;
else
{ {
if ( h1 < 0 || h2 < 0 ) // return max(h1, h2);
return -1; return h1 > h2 ? h1 : h2;
else }
}
// MHS required to evaluate the field
int mhs_letfield(Env* env, LetField* field)
{
return field->expr()->MinimalHeaderSize(env);
}
int mhs_recordfield(Env* env, RecordField* field)
{
int offset = field->static_offset();
if ( offset < 0 ) // offset cannot be statically determined
return -1;
int size = field->StaticSize(env, offset);
if ( size < 0 ) // size cannot be statically determined
return -1;
return offset + size;
}
int mhs_casefield(Env* env, CaseField* field)
{
// TODO: deal with the index
int size = field->StaticSize(env);
if ( size < 0 ) // size cannot be statically determined
return -1;
return size;
}
int mhs_field(Env* env, Field* field)
{
int mhs = -1;
switch ( field->tof() )
{
case LET_FIELD:
{ {
// return max(h1, h2); LetField* f = static_cast<LetField*>(field);
return h1 > h2 ? h1 : h2; ASSERT(f);
mhs = mhs_letfield(env, f);
} }
} break;
// MHS required to evaluate the field case CONTEXT_FIELD:
int mhs_letfield(Env* env, LetField* field) case FLOW_FIELD:
{ ASSERT(0);
return field->expr()->MinimalHeaderSize(env); break;
}
int mhs_recordfield(Env* env, RecordField* field) case PARAM_FIELD:
{ mhs = 0;
int offset = field->static_offset(); break;
if ( offset < 0 ) // offset cannot be statically determined
return -1;
int size = field->StaticSize(env, offset);
if ( size < 0 ) // size cannot be statically determined
return -1;
return offset + size;
}
int mhs_casefield(Env* env, CaseField* field) case RECORD_FIELD:
{ case PADDING_FIELD:
// TODO: deal with the index
int size = field->StaticSize(env);
if ( size < 0 ) // size cannot be statically determined
return -1;
return size;
}
int mhs_field(Env* env, Field* field)
{
int mhs = -1;
switch ( field->tof() )
{ {
case LET_FIELD: RecordField* f = static_cast<RecordField*>(field);
{ ASSERT(f);
LetField *f = mhs = mhs_recordfield(env, f);
static_cast<LetField *>(field);
ASSERT(f);
mhs = mhs_letfield(env, f);
}
break;
case CONTEXT_FIELD:
case FLOW_FIELD:
ASSERT(0);
break;
case PARAM_FIELD:
mhs = 0;
break;
case RECORD_FIELD:
case PADDING_FIELD:
{
RecordField *f =
static_cast<RecordField *>(field);
ASSERT(f);
mhs = mhs_recordfield(env, f);
}
break;
case CASE_FIELD:
{
CaseField *f =
static_cast<CaseField *>(field);
ASSERT(f);
mhs = mhs_casefield(env, f);
}
break;
case PARSE_VAR_FIELD:
case PRIV_VAR_FIELD:
case PUB_VAR_FIELD:
case TEMP_VAR_FIELD:
mhs = 0;
break;
case WITHINPUT_FIELD:
{
// ### TODO: fix this
mhs = -1;
}
break;
} }
return mhs; break;
}
int mhs_id(Env *env, const ID *id) case CASE_FIELD:
{
int mhs = -1;
switch ( env->GetIDType(id) )
{ {
case CONST: CaseField* f = static_cast<CaseField*>(field);
case GLOBAL_VAR: ASSERT(f);
case TEMP_VAR: mhs = mhs_casefield(env, f);
case STATE_VAR:
case FUNC_ID:
case FUNC_PARAM:
mhs = 0;
break;
case MEMBER_VAR:
case PRIV_MEMBER_VAR:
{
Field* field = env->GetField(id);
if ( ! field )
throw ExceptionIDNotField(id);
mhs = mhs_field(env, field);
}
break;
case UNION_VAR:
// TODO: deal with UNION_VAR
mhs = -1;
break;
case MACRO:
{
Expr *e = env->GetMacro(id);
mhs = e->MinimalHeaderSize(env);
}
break;
} }
return mhs; break;
}
}
int Expr::MinimalHeaderSize(Env *env) case PARSE_VAR_FIELD:
case PRIV_VAR_FIELD:
case PUB_VAR_FIELD:
case TEMP_VAR_FIELD:
mhs = 0;
break;
case WITHINPUT_FIELD:
{
// ### TODO: fix this
mhs = -1;
}
break;
}
return mhs;
}
int mhs_id(Env* env, const ID* id)
{
int mhs = -1;
switch ( env->GetIDType(id) )
{
case CONST:
case GLOBAL_VAR:
case TEMP_VAR:
case STATE_VAR:
case FUNC_ID:
case FUNC_PARAM:
mhs = 0;
break;
case MEMBER_VAR:
case PRIV_MEMBER_VAR:
{
Field* field = env->GetField(id);
if ( ! field )
throw ExceptionIDNotField(id);
mhs = mhs_field(env, field);
}
break;
case UNION_VAR:
// TODO: deal with UNION_VAR
mhs = -1;
break;
case MACRO:
{
Expr* e = env->GetMacro(id);
mhs = e->MinimalHeaderSize(env);
}
break;
}
return mhs;
}
}
int Expr::MinimalHeaderSize(Env* env)
{ {
int mhs; int mhs;
@ -826,11 +791,10 @@ int Expr::MinimalHeaderSize(Env *env)
case EXPR_SUBSCRIPT: case EXPR_SUBSCRIPT:
{ {
int index; int index;
Type *array_type = operand_[0]->DataType(env); Type* array_type = operand_[0]->DataType(env);
Type *elem_type = array_type->ElementDataType(); Type* elem_type = array_type->ElementDataType();
int elem_size = elem_type->StaticSize(env); int elem_size = elem_type->StaticSize(env);
if ( elem_size >= 0 && if ( elem_size >= 0 && operand_[1]->ConstFold(env, &index) )
operand_[1]->ConstFold(env, &index) )
{ {
mhs = elem_size * index; mhs = elem_size * index;
} }
@ -845,8 +809,8 @@ int Expr::MinimalHeaderSize(Env *env)
{ {
const ID* id = operand_[0]->id(); const ID* id = operand_[0]->id();
ASSERT(id); ASSERT(id);
RecordField *rf; RecordField* rf;
Type *ty; Type* ty;
if ( (rf = GetRecordField(id, env)) != 0 ) if ( (rf = GetRecordField(id, env)) != 0 )
{ {
@ -870,7 +834,7 @@ int Expr::MinimalHeaderSize(Env *env)
{ {
const ID* id = operand_[0]->id(); const ID* id = operand_[0]->id();
ASSERT(id); ASSERT(id);
RecordField *field = GetRecordField(id, env); RecordField* field = GetRecordField(id, env);
mhs = field->static_offset(); mhs = field->static_offset();
if ( mhs < 0 ) if ( mhs < 0 )
@ -885,21 +849,21 @@ int Expr::MinimalHeaderSize(Env *env)
break; break;
case EXPR_CALLARGS: case EXPR_CALLARGS:
{ {
mhs = 0; mhs = 0;
if ( args_ ) if ( args_ )
for ( unsigned int i = 0; i < args_->size(); ++i ) for ( unsigned int i = 0; i < args_->size(); ++i )
mhs = mhs_max(mhs, (*args_)[i]->MinimalHeaderSize(env)); mhs = mhs_max(mhs, (*args_)[i]->MinimalHeaderSize(env));
} }
break; break;
case EXPR_CASE: case EXPR_CASE:
{ {
mhs = operand_[0]->MinimalHeaderSize(env); mhs = operand_[0]->MinimalHeaderSize(env);
for ( unsigned int i = 0; i < cases_->size(); ++i ) for ( unsigned int i = 0; i < cases_->size(); ++i )
{ {
CaseExpr * ce = (*cases_)[i]; CaseExpr* ce = (*cases_)[i];
if ( ce->index() ) if ( ce->index() )
for ( unsigned int j = 0; j < ce->index()->size(); ++j ) for ( unsigned int j = 0; j < ce->index()->size(); ++j )
mhs = mhs_max(mhs, (*ce->index())[j]->MinimalHeaderSize(env)); mhs = mhs_max(mhs, (*ce->index())[j]->MinimalHeaderSize(env));
mhs = mhs_max(mhs, ce->value()->MinimalHeaderSize(env)); mhs = mhs_max(mhs, ce->value()->MinimalHeaderSize(env));
} }
@ -917,7 +881,7 @@ int Expr::MinimalHeaderSize(Env *env)
return mhs; return mhs;
} }
bool Expr::HasReference(const ID *id) const bool Expr::HasReference(const ID* id) const
{ {
switch ( expr_type_ ) switch ( expr_type_ )
{ {
@ -929,7 +893,7 @@ bool Expr::HasReference(const ID *id) const
case EXPR_CALLARGS: case EXPR_CALLARGS:
{ {
foreach(i, ExprList, args_) foreach (i, ExprList, args_)
if ( (*i)->HasReference(id) ) if ( (*i)->HasReference(id) )
return true; return true;
} }
@ -937,7 +901,7 @@ bool Expr::HasReference(const ID *id) const
case EXPR_CASE: case EXPR_CASE:
{ {
foreach(i, CaseExprList, cases_) foreach (i, CaseExprList, cases_)
if ( (*i)->HasReference(id) ) if ( (*i)->HasReference(id) )
return true; return true;
} }
@ -947,8 +911,7 @@ bool Expr::HasReference(const ID *id) const
// Evaluate every operand by default // Evaluate every operand by default
for ( int i = 0; i < 3; ++i ) for ( int i = 0; i < 3; ++i )
{ {
if ( operand_[i] && if ( operand_[i] && operand_[i]->HasReference(id) )
operand_[i]->HasReference(id) )
{ {
return true; return true;
} }
@ -957,7 +920,7 @@ bool Expr::HasReference(const ID *id) const
} }
} }
bool Expr::DoTraverse(DataDepVisitor *visitor) bool Expr::DoTraverse(DataDepVisitor* visitor)
{ {
switch ( expr_type_ ) switch ( expr_type_ )
{ {
@ -977,7 +940,7 @@ bool Expr::DoTraverse(DataDepVisitor *visitor)
case EXPR_CALLARGS: case EXPR_CALLARGS:
{ {
foreach(i, ExprList, args_) foreach (i, ExprList, args_)
if ( ! (*i)->Traverse(visitor) ) if ( ! (*i)->Traverse(visitor) )
return false; return false;
} }
@ -985,7 +948,7 @@ bool Expr::DoTraverse(DataDepVisitor *visitor)
case EXPR_CASE: case EXPR_CASE:
{ {
foreach(i, CaseExprList, cases_) foreach (i, CaseExprList, cases_)
if ( ! (*i)->Traverse(visitor) ) if ( ! (*i)->Traverse(visitor) )
return false; return false;
} }
@ -995,8 +958,7 @@ bool Expr::DoTraverse(DataDepVisitor *visitor)
// Evaluate every operand by default // Evaluate every operand by default
for ( int i = 0; i < 3; ++i ) for ( int i = 0; i < 3; ++i )
{ {
if ( operand_[i] && if ( operand_[i] && ! operand_[i]->Traverse(visitor) )
! operand_[i]->Traverse(visitor) )
{ {
return false; return false;
} }
@ -1025,7 +987,7 @@ bool Expr::RequiresAnalyzerContext() const
case EXPR_CALLARGS: case EXPR_CALLARGS:
{ {
foreach(i, ExprList, args_) foreach (i, ExprList, args_)
if ( (*i)->RequiresAnalyzerContext() ) if ( (*i)->RequiresAnalyzerContext() )
return true; return true;
} }
@ -1033,7 +995,7 @@ bool Expr::RequiresAnalyzerContext() const
case EXPR_CASE: case EXPR_CASE:
{ {
foreach(i, CaseExprList, cases_) foreach (i, CaseExprList, cases_)
if ( (*i)->RequiresAnalyzerContext() ) if ( (*i)->RequiresAnalyzerContext() )
return true; return true;
} }
@ -1042,8 +1004,7 @@ bool Expr::RequiresAnalyzerContext() const
default: default:
// Evaluate every operand by default // Evaluate every operand by default
for ( int i = 0; i < 3; ++i ) for ( int i = 0; i < 3; ++i )
if ( operand_[i] && if ( operand_[i] && operand_[i]->RequiresAnalyzerContext() )
operand_[i]->RequiresAnalyzerContext() )
{ {
DEBUG_MSG("'%s' requires analyzer context\n", operand_[i]->orig()); DEBUG_MSG("'%s' requires analyzer context\n", operand_[i]->orig());
return true; return true;
@ -1052,9 +1013,8 @@ bool Expr::RequiresAnalyzerContext() const
} }
} }
CaseExpr::CaseExpr(ExprList *index, Expr *value) CaseExpr::CaseExpr(ExprList* index, Expr* value)
: DataDepElement(DataDepElement::CASEEXPR), : DataDepElement(DataDepElement::CASEEXPR), index_(index), value_(value)
index_(index), value_(value)
{ {
} }
@ -1064,15 +1024,15 @@ CaseExpr::~CaseExpr()
delete value_; delete value_;
} }
bool CaseExpr::DoTraverse(DataDepVisitor *visitor) bool CaseExpr::DoTraverse(DataDepVisitor* visitor)
{ {
foreach(i, ExprList, index_) foreach (i, ExprList, index_)
if ( ! (*i)->Traverse(visitor) ) if ( ! (*i)->Traverse(visitor) )
return false; return false;
return value_->Traverse(visitor); return value_->Traverse(visitor);
} }
bool CaseExpr::HasReference(const ID *id) const bool CaseExpr::HasReference(const ID* id) const
{ {
return value_->HasReference(id); return value_->HasReference(id);
} }

View file

@ -7,42 +7,43 @@
class CaseExpr; class CaseExpr;
class Expr : public Object, public DataDepElement class Expr : public Object, public DataDepElement
{ {
public: public:
enum ExprType { enum ExprType
# define EXPR_DEF(type, x, y) type, {
# include "pac_expr.def" #define EXPR_DEF(type, x, y) type,
# undef EXPR_DEF #include "pac_expr.def"
}; #undef EXPR_DEF
};
void init(); void init();
Expr(ID *id); Expr(ID* id);
Expr(Number *num); Expr(Number* num);
Expr(ConstString *s); Expr(ConstString* s);
Expr(RegEx *regex); Expr(RegEx* regex);
Expr(ExprList *args); // for EXPR_CALLARGS Expr(ExprList* args); // for EXPR_CALLARGS
Expr(Expr *index, CaseExprList *cases); Expr(Expr* index, CaseExprList* cases);
Expr(ExprType type, Expr *op1); Expr(ExprType type, Expr* op1);
Expr(ExprType type, Expr *op1, Expr *op2); Expr(ExprType type, Expr* op1, Expr* op2);
Expr(ExprType type, Expr *op1, Expr *op2, Expr *op3); Expr(ExprType type, Expr* op1, Expr* op2, Expr* op3);
virtual ~Expr(); virtual ~Expr();
const char *orig() const { return orig_.c_str(); } const char* orig() const { return orig_.c_str(); }
const ID *id() const { return id_; } const ID* id() const { return id_; }
const char *str() const { return str_.c_str(); } const char* str() const { return str_.c_str(); }
ExprType expr_type() const { return expr_type_; } ExprType expr_type() const { return expr_type_; }
void AddCaseExpr(CaseExpr *case_expr); void AddCaseExpr(CaseExpr* case_expr);
// Returns the data "type" of the expression. Here we only // Returns the data "type" of the expression. Here we only
// do a serious job for the EXPR_MEMBER and EXPR_SUBSCRIPT // do a serious job for the EXPR_MEMBER and EXPR_SUBSCRIPT
// operators. For arithmetic operations, we fall back // operators. For arithmetic operations, we fall back
// to "int". // to "int".
Type *DataType(Env *env) const; Type* DataType(Env* env) const;
string DataTypeStr(Env *env) const; string DataTypeStr(Env* env) const;
// Note: EvalExpr() may generate C++ statements in order to evaluate // Note: EvalExpr() may generate C++ statements in order to evaluate
// variables in the expression, so the following is wrong: // variables in the expression, so the following is wrong:
@ -54,24 +55,24 @@ public:
// //
// out->println("int x = %s", expr->EvalExpr(out, env)); // out->println("int x = %s", expr->EvalExpr(out, env));
// //
const char *EvalExpr(Output *out, Env *env); const char* EvalExpr(Output* out, Env* env);
// force evaulation of IDs contained in this expression; // force evaulation of IDs contained in this expression;
// necessary with case expr and conditional let fields (&if) // necessary with case expr and conditional let fields (&if)
// for correct parsing of fields // for correct parsing of fields
void ForceIDEval(Output *out_cc, Env *env); void ForceIDEval(Output* out_cc, Env* env);
// Returns the set_* function of the expression. // Returns the set_* function of the expression.
// The expression must be of form ID or x.ID. // The expression must be of form ID or x.ID.
string SetFunc(Output *out, Env *env); string SetFunc(Output* out, Env* env);
// Returns true if the expression folds to an integer // Returns true if the expression folds to an integer
// constant with env, and puts the constant in *pn. // constant with env, and puts the constant in *pn.
// //
bool ConstFold(Env *env, int *pn) const; bool ConstFold(Env* env, int* pn) const;
// Whether id is referenced in the expression // Whether id is referenced in the expression
bool HasReference(const ID *id) const; bool HasReference(const ID* id) const;
// Suppose the data for type might be incomplete, what is // Suppose the data for type might be incomplete, what is
// the minimal number of bytes from data head required to // the minimal number of bytes from data head required to
@ -82,58 +83,58 @@ public:
// //
// Returns -1 if the number is not a constant. // Returns -1 if the number is not a constant.
// //
int MinimalHeaderSize(Env *env); int MinimalHeaderSize(Env* env);
// Whether evaluation of the expression requires the analyzer context // Whether evaluation of the expression requires the analyzer context
bool RequiresAnalyzerContext() const; bool RequiresAnalyzerContext() const;
protected: protected:
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
private: private:
ExprType expr_type_; ExprType expr_type_;
int num_operands_; int num_operands_;
Expr *operand_[3]; Expr* operand_[3];
ID *id_; // EXPR_ID ID* id_; // EXPR_ID
Number *num_; // EXPR_NUM Number* num_; // EXPR_NUM
ConstString *cstr_; // EXPR_CSTR ConstString* cstr_; // EXPR_CSTR
RegEx *regex_; // EXPR_REGEX RegEx* regex_; // EXPR_REGEX
ExprList *args_; // EXPR_CALLARGS ExprList* args_; // EXPR_CALLARGS
CaseExprList *cases_; // EXPR_CASE CaseExprList* cases_; // EXPR_CASE
string str_; // value string string str_; // value string
string orig_; // original string for debugging info string orig_; // original string for debugging info
void GenStrFromFormat(Env *env); void GenStrFromFormat(Env* env);
void GenEval(Output *out, Env *env); void GenEval(Output* out, Env* env);
void GenCaseEval(Output *out_cc, Env *env); void GenCaseEval(Output* out_cc, Env* env);
}; };
string OrigExprList(ExprList *exprlist); string OrigExprList(ExprList* exprlist);
string EvalExprList(ExprList *exprlist, Output *out, Env *env); string EvalExprList(ExprList* exprlist, Output* out, Env* env);
// An entry of the case expression, consisting of one or more constant // An entry of the case expression, consisting of one or more constant
// expressions for the case index and a value expression. // expressions for the case index and a value expression.
class CaseExpr : public Object, public DataDepElement class CaseExpr : public Object, public DataDepElement
{ {
public: public:
CaseExpr(ExprList *index, Expr *value); CaseExpr(ExprList* index, Expr* value);
virtual ~CaseExpr(); virtual ~CaseExpr();
ExprList *index() const { return index_; } ExprList* index() const { return index_; }
Expr *value() const { return value_; } Expr* value() const { return value_; }
bool HasReference(const ID *id) const; bool HasReference(const ID* id) const;
bool RequiresAnalyzerContext() const; bool RequiresAnalyzerContext() const;
protected: protected:
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
private: private:
ExprList *index_; ExprList* index_;
Expr *value_; Expr* value_;
}; };
#endif // pac_expr_h #endif // pac_expr_h

View file

@ -1,6 +1,7 @@
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_id.h"
#include "pac_decl.h" #include "pac_decl.h"
#include "pac_id.h"
#include "pac_output.h" #include "pac_output.h"
bool ExternType::DefineValueVar() const bool ExternType::DefineValueVar() const
@ -34,11 +35,9 @@ bool ExternType::ByteOrderSensitive() const
return false; return false;
} }
string ExternType::EvalMember(const ID *member_id) const string ExternType::EvalMember(const ID* member_id) const
{ {
return strfmt("%s%s", return strfmt("%s%s", ext_type_ == POINTER ? "->" : ".", member_id->Name());
ext_type_ == POINTER ? "->" : ".",
member_id->Name());
} }
void ExternType::GenInitCode(Output* out_cc, Env* env) void ExternType::GenInitCode(Output* out_cc, Env* env)
@ -58,26 +57,26 @@ void ExternType::GenDynamicSize(Output* out, Env* env, const DataPtr& data)
ASSERT(0); ASSERT(0);
} }
Type *ExternType::DoClone() const Type* ExternType::DoClone() const
{ {
return new ExternType(id_->clone(), ext_type_); return new ExternType(id_->clone(), ext_type_);
} }
// Definitions of pre-defined external types // Definitions of pre-defined external types
#define EXTERNTYPE(name, ctype, exttype) ExternType *extern_type_##name = 0; #define EXTERNTYPE(name, ctype, exttype) ExternType* extern_type_##name = 0;
#include "pac_externtype.def" #include "pac_externtype.def"
#undef EXTERNTYPE #undef EXTERNTYPE
void ExternType::static_init() void ExternType::static_init()
{ {
ID *id; ID* id;
// TypeDecl *decl; // TypeDecl *decl;
// decl = new TypeDecl(id, 0, extern_type_##name); // decl = new TypeDecl(id, 0, extern_type_##name);
#define EXTERNTYPE(name, ctype, exttype) \ #define EXTERNTYPE(name, ctype, exttype) \
id = new ID(#ctype); \ id = new ID(#ctype); \
extern_type_##name = new ExternType(id, ExternType::exttype); \ extern_type_##name = new ExternType(id, ExternType::exttype); \
Type::AddPredefinedType(#name, extern_type_##name); Type::AddPredefinedType(#name, extern_type_##name);
#include "pac_externtype.def" #include "pac_externtype.def"
#undef EXTERNTYPE #undef EXTERNTYPE

View file

@ -9,41 +9,43 @@
// literally to the compiled code. // literally to the compiled code.
class ExternType : public Type class ExternType : public Type
{ {
public: public:
enum EXTType { PLAIN, NUMBER, POINTER }; enum EXTType
ExternType(const ID *id, EXTType ext_type) {
: Type(EXTERN), PLAIN,
id_(id), NUMBER,
ext_type_(ext_type) {} POINTER
};
ExternType(const ID* id, EXTType ext_type) : Type(EXTERN), id_(id), ext_type_(ext_type) { }
bool DefineValueVar() const; bool DefineValueVar() const;
string DataTypeStr() const; string DataTypeStr() const;
int StaticSize(Env *env) const; int StaticSize(Env* env) const;
bool ByteOrderSensitive() const; bool ByteOrderSensitive() const;
string EvalMember(const ID *member_id) const; string EvalMember(const ID* member_id) const;
bool IsNumericType() const { return ext_type_ == NUMBER; } bool IsNumericType() const { return ext_type_ == NUMBER; }
bool IsPointerType() const { return ext_type_ == POINTER; } bool IsPointerType() const { return ext_type_ == POINTER; }
void GenInitCode(Output *out_cc, Env *env); void GenInitCode(Output* out_cc, Env* env);
protected: protected:
void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags);
void GenDynamicSize(Output *out, Env *env, const DataPtr& data); void GenDynamicSize(Output* out, Env* env, const DataPtr& data);
Type *DoClone() const; Type* DoClone() const;
private: private:
const ID *id_; const ID* id_;
EXTType ext_type_; EXTType ext_type_;
public: public:
static void static_init(); static void static_init();
}; };
#define EXTERNTYPE(name, ctype, exttype) extern ExternType *extern_type_##name; #define EXTERNTYPE(name, ctype, exttype) extern ExternType* extern_type_##name;
#include "pac_externtype.def" #include "pac_externtype.def"
#undef EXTERNTYPE #undef EXTERNTYPE
#endif // pac_exttype_h #endif // pac_exttype_h

View file

@ -1,13 +1,13 @@
#include "pac_field.h"
#include "pac_attr.h" #include "pac_attr.h"
#include "pac_common.h" #include "pac_common.h"
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_field.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_type.h" #include "pac_type.h"
Field::Field(FieldType tof, int flags, ID *id, Type *type) Field::Field(FieldType tof, int flags, ID* id, Type* type)
: DataDepElement(DataDepElement::FIELD), : DataDepElement(DataDepElement::FIELD), tof_(tof), flags_(flags), id_(id), type_(type)
tof_(tof), flags_(flags), id_(id), type_(type)
{ {
decl_id_ = current_decl_id; decl_id_ = current_decl_id;
field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name()); field_id_str_ = strfmt("%s:%s", decl_id()->Name(), id_->Name());
@ -35,24 +35,22 @@ void Field::AddAttr(AttrList* attrs)
delete_attrs = true; delete_attrs = true;
} }
foreach(i, AttrList, attrs) foreach (i, AttrList, attrs)
ProcessAttr(*i); ProcessAttr(*i);
if ( delete_attrs ) if ( delete_attrs )
delete attrs; delete attrs;
} }
void Field::ProcessAttr(Attr *a) void Field::ProcessAttr(Attr* a)
{ {
switch ( a->type() ) switch ( a->type() )
{ {
case ATTR_IF: case ATTR_IF:
if ( tof() != LET_FIELD && if ( tof() != LET_FIELD && tof() != WITHINPUT_FIELD )
tof() != WITHINPUT_FIELD )
{ {
throw Exception(a, throw Exception(a, "&if can only be applied to a "
"&if can only be applied to a " "let field");
"let field");
} }
break; break;
default: default:
@ -76,7 +74,7 @@ int Field::ValueVarType() const
return TEMP_VAR; return TEMP_VAR;
} }
void Field::Prepare(Env *env) void Field::Prepare(Env* env)
{ {
if ( type_ ) if ( type_ )
{ {
@ -86,9 +84,7 @@ void Field::Prepare(Env *env)
flags_ &= (~PUBLIC_READABLE); flags_ &= (~PUBLIC_READABLE);
type_->set_value_var(id(), ValueVarType()); type_->set_value_var(id(), ValueVarType());
type_->Prepare(env, type_->Prepare(env, flags_ & TYPE_TO_BE_PARSED ? Type::TO_BE_PARSED : 0);
flags_ & TYPE_TO_BE_PARSED ?
Type::TO_BE_PARSED : 0);
env->SetField(id(), this); env->SetField(id(), this);
} }
} }
@ -109,7 +105,7 @@ void Field::GenPrivDecls(Output* out_h, Env* env)
void Field::GenTempDecls(Output* out_h, Env* env) void Field::GenTempDecls(Output* out_h, Env* env)
{ {
// Generate temp field // Generate temp field
if ( type_ && !(flags_ & CLASS_MEMBER) ) if ( type_ && ! (flags_ & CLASS_MEMBER) )
type_->GenPrivDecls(out_h, env); type_->GenPrivDecls(out_h, env);
} }
@ -125,12 +121,12 @@ void Field::GenCleanUpCode(Output* out_cc, Env* env)
type_->GenCleanUpCode(out_cc, env); type_->GenCleanUpCode(out_cc, env);
} }
bool Field::DoTraverse(DataDepVisitor *visitor) bool Field::DoTraverse(DataDepVisitor* visitor)
{ {
// Check parameterized type // Check parameterized type
if ( type_ && ! type_->Traverse(visitor) ) if ( type_ && ! type_->Traverse(visitor) )
return false; return false;
foreach(i, AttrList, attrs_) foreach (i, AttrList, attrs_)
if ( ! (*i)->Traverse(visitor) ) if ( ! (*i)->Traverse(visitor) )
return false; return false;
return true; return true;
@ -141,7 +137,7 @@ bool Field::RequiresAnalyzerContext() const
// Check parameterized type // Check parameterized type
if ( type_ && type_->RequiresAnalyzerContext() ) if ( type_ && type_->RequiresAnalyzerContext() )
return true; return true;
foreach(i, AttrList, attrs_) foreach (i, AttrList, attrs_)
if ( (*i)->RequiresAnalyzerContext() ) if ( (*i)->RequiresAnalyzerContext() )
return true; return true;
return false; return false;

View file

@ -6,7 +6,8 @@
// A "field" is a member of class. // A "field" is a member of class.
enum FieldType { enum FieldType
{
CASE_FIELD, CASE_FIELD,
CONTEXT_FIELD, CONTEXT_FIELD,
FLOW_FIELD, FLOW_FIELD,
@ -19,12 +20,12 @@ enum FieldType {
PUB_VAR_FIELD, PUB_VAR_FIELD,
TEMP_VAR_FIELD, TEMP_VAR_FIELD,
WITHINPUT_FIELD, WITHINPUT_FIELD,
}; };
class Field : public Object, public DataDepElement class Field : public Object, public DataDepElement
{ {
public: public:
Field(FieldType tof, int flags, ID *id, Type *type); Field(FieldType tof, int flags, ID* id, Type* type);
// Field flags // Field flags
// Whether the field will be evaluated by calling the Parse() // Whether the field will be evaluated by calling the Parse()
@ -43,17 +44,17 @@ public:
virtual ~Field(); virtual ~Field();
FieldType tof() const { return tof_; } FieldType tof() const { return tof_; }
const ID* id() const { return id_; } const ID* id() const { return id_; }
Type *type() const { return type_; } Type* type() const { return type_; }
const ID* decl_id() const { return decl_id_; } const ID* decl_id() const { return decl_id_; }
bool anonymous_field() const; bool anonymous_field() const;
void AddAttr(AttrList* attrs); void AddAttr(AttrList* attrs);
// The field interface // The field interface
virtual void ProcessAttr(Attr *attr); virtual void ProcessAttr(Attr* attr);
virtual void Prepare(Env* env); virtual void Prepare(Env* env);
virtual void GenPubDecls(Output* out, Env* env); virtual void GenPubDecls(Output* out, Env* env);
@ -69,16 +70,16 @@ protected:
int ValueVarType() const; int ValueVarType() const;
bool ToBeParsed() const; bool ToBeParsed() const;
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
protected: protected:
FieldType tof_; FieldType tof_;
int flags_; int flags_;
ID* id_; ID* id_;
Type *type_; Type* type_;
const ID* decl_id_; const ID* decl_id_;
string field_id_str_; string field_id_str_;
AttrList* attrs_; AttrList* attrs_;
}; };
#endif // pac_field_h #endif // pac_field_h

View file

@ -1,3 +1,5 @@
#include "pac_flow.h"
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_conn.h" #include "pac_conn.h"
#include "pac_context.h" #include "pac_context.h"
@ -7,17 +9,13 @@
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_flow.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_param.h" #include "pac_param.h"
#include "pac_paramtype.h" #include "pac_paramtype.h"
#include "pac_type.h" #include "pac_type.h"
#include "pac_varfield.h" #include "pac_varfield.h"
FlowDecl::FlowDecl(ID* id, ParamList* params, AnalyzerElementList* elemlist)
FlowDecl::FlowDecl(ID *id,
ParamList *params,
AnalyzerElementList *elemlist)
: AnalyzerDecl(id, FLOW, params) : AnalyzerDecl(id, FLOW, params)
{ {
dataunit_ = 0; dataunit_ = 0;
@ -32,9 +30,9 @@ FlowDecl::~FlowDecl()
delete dataunit_; delete dataunit_;
} }
ParameterizedType *FlowDecl::flow_buffer_type_ = 0; ParameterizedType* FlowDecl::flow_buffer_type_ = 0;
ParameterizedType *FlowDecl::flow_buffer_type() ParameterizedType* FlowDecl::flow_buffer_type()
{ {
if ( ! flow_buffer_type_ ) if ( ! flow_buffer_type_ )
{ {
@ -43,24 +41,21 @@ ParameterizedType *FlowDecl::flow_buffer_type()
return flow_buffer_type_; return flow_buffer_type_;
} }
void FlowDecl::AddBaseClass(vector<string> *base_classes) const void FlowDecl::AddBaseClass(vector<string>* base_classes) const
{ {
base_classes->push_back("binpac::FlowAnalyzer"); base_classes->push_back("binpac::FlowAnalyzer");
} }
void FlowDecl::ProcessFlowElement(AnalyzerFlow *flow_elem) void FlowDecl::ProcessFlowElement(AnalyzerFlow* flow_elem)
{ {
throw Exception( throw Exception(flow_elem, "flow should be defined in only a connection declaration");
flow_elem,
"flow should be defined in only a connection declaration");
} }
void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem)
{ {
if ( dataunit_ ) if ( dataunit_ )
{ {
throw Exception(dataunit_elem, throw Exception(dataunit_elem, "dataunit already defined");
"dataunit already defined");
} }
dataunit_ = dataunit_elem; dataunit_ = dataunit_elem;
@ -68,17 +63,15 @@ void FlowDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem)
{ {
dataunit_->data_type()->MarkIncrementalInput(); dataunit_->data_type()->MarkIncrementalInput();
flow_buffer_var_field_ = new PubVarField( flow_buffer_var_field_ = new PubVarField(flow_buffer_id->clone(),
flow_buffer_id->clone(), FlowDecl::flow_buffer_type()->Clone());
FlowDecl::flow_buffer_type()->Clone());
type_->AddField(flow_buffer_var_field_); type_->AddField(flow_buffer_var_field_);
ASSERT(AnalyzerContextDecl::current_analyzer_context()); ASSERT(AnalyzerContextDecl::current_analyzer_context());
AnalyzerContextDecl::current_analyzer_context()->AddFlowBuffer(); AnalyzerContextDecl::current_analyzer_context()->AddFlowBuffer();
// Add an argument to the context initiation // Add an argument to the context initiation
dataunit_->context_type()->AddParamArg( dataunit_->context_type()->AddParamArg(new Expr(flow_buffer_var_field_->id()->clone()));
new Expr(flow_buffer_var_field_->id()->clone()));
} }
} }
@ -87,28 +80,25 @@ void FlowDecl::Prepare()
// Add the connection parameter // Add the connection parameter
if ( ! conn_decl_ ) if ( ! conn_decl_ )
{ {
throw Exception(this, throw Exception(this, "no connection is not declared for the flow");
"no connection is not declared for the flow");
} }
if ( ! params_ ) if ( ! params_ )
params_ = new ParamList(); params_ = new ParamList();
params_->insert(params_->begin(), params_->insert(params_->begin(), new Param(connection_id->clone(), conn_decl_->DataType()));
new Param(connection_id->clone(),
conn_decl_->DataType()));
AnalyzerDecl::Prepare(); AnalyzerDecl::Prepare();
dataunit_->Prepare(env_); dataunit_->Prepare(env_);
} }
void FlowDecl::GenPubDecls(Output *out_h, Output *out_cc) void FlowDecl::GenPubDecls(Output* out_h, Output* out_cc)
{ {
AnalyzerDecl::GenPubDecls(out_h, out_cc); AnalyzerDecl::GenPubDecls(out_h, out_cc);
} }
void FlowDecl::GenPrivDecls(Output *out_h, Output *out_cc) void FlowDecl::GenPrivDecls(Output* out_h, Output* out_cc)
{ {
// Declare the data unit // Declare the data unit
dataunit_->dataunit_var_field()->GenPrivDecls(out_h, env_); dataunit_->dataunit_var_field()->GenPrivDecls(out_h, env_);
@ -119,14 +109,12 @@ void FlowDecl::GenPrivDecls(Output *out_h, Output *out_cc)
AnalyzerDecl::GenPrivDecls(out_h, out_cc); AnalyzerDecl::GenPrivDecls(out_h, out_cc);
} }
void FlowDecl::GenInitCode(Output *out_cc) void FlowDecl::GenInitCode(Output* out_cc)
{ {
AnalyzerDecl::GenInitCode(out_cc); AnalyzerDecl::GenInitCode(out_cc);
out_cc->println("%s = 0;", out_cc->println("%s = 0;", env_->LValue(dataunit_id));
env_->LValue(dataunit_id)); out_cc->println("%s = 0;", env_->LValue(analyzer_context_id));
out_cc->println("%s = 0;",
env_->LValue(analyzer_context_id));
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT )
{ {
@ -135,13 +123,13 @@ void FlowDecl::GenInitCode(Output *out_cc)
} }
} }
void FlowDecl::GenCleanUpCode(Output *out_cc) void FlowDecl::GenCleanUpCode(Output* out_cc)
{ {
GenDeleteDataUnit(out_cc); GenDeleteDataUnit(out_cc);
AnalyzerDecl::GenCleanUpCode(out_cc); AnalyzerDecl::GenCleanUpCode(out_cc);
} }
void FlowDecl::GenEOFFunc(Output *out_h, Output *out_cc) void FlowDecl::GenEOFFunc(Output* out_h, Output* out_cc)
{ {
string proto = strfmt("%s()", kFlowEOF); string proto = strfmt("%s()", kFlowEOF);
@ -151,15 +139,14 @@ void FlowDecl::GenEOFFunc(Output *out_h, Output *out_cc)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
foreach(i, AnalyzerHelperList, eof_helpers_) foreach (i, AnalyzerHelperList, eof_helpers_)
{ {
(*i)->GenCode(0, out_cc, this); (*i)->GenCode(0, out_cc, this);
} }
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT )
{ {
out_cc->println("%s->set_eof();", out_cc->println("%s->set_eof();", env_->LValue(flow_buffer_id));
env_->LValue(flow_buffer_id));
out_cc->println("%s(0, 0);", kNewData); out_cc->println("%s(0, 0);", kNewData);
} }
@ -167,7 +154,7 @@ void FlowDecl::GenEOFFunc(Output *out_h, Output *out_cc)
out_cc->dec_indent(); out_cc->dec_indent();
} }
void FlowDecl::GenGapFunc(Output *out_h, Output *out_cc) void FlowDecl::GenGapFunc(Output* out_h, Output* out_cc)
{ {
string proto = strfmt("%s(int gap_length)", kFlowGap); string proto = strfmt("%s(int gap_length)", kFlowGap);
@ -179,24 +166,20 @@ void FlowDecl::GenGapFunc(Output *out_h, Output *out_cc)
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT )
{ {
out_cc->println("%s->NewGap(gap_length);", out_cc->println("%s->NewGap(gap_length);", env_->LValue(flow_buffer_id));
env_->LValue(flow_buffer_id));
} }
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
} }
void FlowDecl::GenProcessFunc(Output *out_h, Output *out_cc) void FlowDecl::GenProcessFunc(Output* out_h, Output* out_cc)
{ {
env_->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); env_->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr);
env_->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); env_->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr);
string proto = string proto = strfmt("%s(const_byteptr %s, const_byteptr %s)", kNewData,
strfmt("%s(const_byteptr %s, const_byteptr %s)", env_->LValue(begin_of_data), env_->LValue(end_of_data));
kNewData,
env_->LValue(begin_of_data),
env_->LValue(end_of_data));
out_h->println("void %s;", proto.c_str()); out_h->println("void %s;", proto.c_str());
@ -232,8 +215,7 @@ void FlowDecl::GenProcessFunc(Output *out_h, Output *out_cc)
GenCleanUpCode(out_cc); GenCleanUpCode(out_cc);
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT ) if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT )
{ {
out_cc->println("%s->DiscardData();", out_cc->println("%s->DiscardData();", env_->LValue(flow_buffer_id));
env_->LValue(flow_buffer_id));
} }
out_cc->println("throw;"); out_cc->println("throw;");
out_cc->println("}"); out_cc->println("}");
@ -244,21 +226,19 @@ void FlowDecl::GenProcessFunc(Output *out_h, Output *out_cc)
out_cc->println(""); out_cc->println("");
} }
void FlowDecl::GenNewDataUnit(Output *out_cc) void FlowDecl::GenNewDataUnit(Output* out_cc)
{ {
Type *unit_datatype = dataunit_->data_type(); Type* unit_datatype = dataunit_->data_type();
// dataunit_->data_type()->GenPreParsing(out_cc, env_); // dataunit_->data_type()->GenPreParsing(out_cc, env_);
dataunit_->GenNewDataUnit(out_cc, env_); dataunit_->GenNewDataUnit(out_cc, env_);
if ( unit_datatype->buffer_input() && if ( unit_datatype->buffer_input() && unit_datatype->buffer_mode() == Type::BUFFER_BY_LENGTH )
unit_datatype->buffer_mode() == Type::BUFFER_BY_LENGTH )
{ {
out_cc->println("%s->NewFrame(0, false);", out_cc->println("%s->NewFrame(0, false);", env_->LValue(flow_buffer_id));
env_->LValue(flow_buffer_id));
} }
dataunit_->GenNewContext(out_cc, env_); dataunit_->GenNewContext(out_cc, env_);
} }
void FlowDecl::GenDeleteDataUnit(Output *out_cc) void FlowDecl::GenDeleteDataUnit(Output* out_cc)
{ {
// Do not just delete dataunit, because we may just want to Unref it. // Do not just delete dataunit, because we may just want to Unref it.
// out_cc->println("delete %s;", env_->LValue(dataunit_id)); // out_cc->println("delete %s;", env_->LValue(dataunit_id));
@ -266,28 +246,24 @@ void FlowDecl::GenDeleteDataUnit(Output *out_cc)
dataunit_->context_type()->GenCleanUpCode(out_cc, env_); dataunit_->context_type()->GenCleanUpCode(out_cc, env_);
} }
void FlowDecl::GenCodeFlowUnit(Output *out_cc) void FlowDecl::GenCodeFlowUnit(Output* out_cc)
{ {
Type *unit_datatype = dataunit_->data_type(); Type* unit_datatype = dataunit_->data_type();
out_cc->println("%s->NewData(%s, %s);", out_cc->println("%s->NewData(%s, %s);", env_->LValue(flow_buffer_id),
env_->LValue(flow_buffer_id), env_->RValue(begin_of_data), env_->RValue(end_of_data));
env_->RValue(begin_of_data),
env_->RValue(end_of_data));
out_cc->println("while ( %s->data_available() && ", out_cc->println("while ( %s->data_available() && ", env_->LValue(flow_buffer_id));
env_->LValue(flow_buffer_id));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("( !%s->have_pending_request() || %s->ready() ) )", out_cc->println("( !%s->have_pending_request() || %s->ready() ) )",
env_->LValue(flow_buffer_id), env_->LValue(flow_buffer_id)); env_->LValue(flow_buffer_id), env_->LValue(flow_buffer_id));
out_cc->println("{"); out_cc->println("{");
// Generate a new dataunit if necessary // Generate a new dataunit if necessary
out_cc->println("if ( ! %s )", env_->LValue(dataunit_id)); out_cc->println("if ( ! %s )", env_->LValue(dataunit_id));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("BINPAC_ASSERT(!%s);", out_cc->println("BINPAC_ASSERT(!%s);", env_->LValue(analyzer_context_id));
env_->LValue(analyzer_context_id));
GenNewDataUnit(out_cc); GenNewDataUnit(out_cc);
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
@ -295,8 +271,7 @@ void FlowDecl::GenCodeFlowUnit(Output *out_cc)
DataPtr data(env_, 0, 0); DataPtr data(env_, 0, 0);
unit_datatype->GenParseCode(out_cc, env_, data, 0); unit_datatype->GenParseCode(out_cc, env_, data, 0);
out_cc->println("if ( %s )", out_cc->println("if ( %s )", unit_datatype->parsing_complete(env_).c_str());
unit_datatype->parsing_complete(env_).c_str());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("// Clean up the flow unit after parsing"); out_cc->println("// Clean up the flow unit after parsing");
@ -308,8 +283,7 @@ void FlowDecl::GenCodeFlowUnit(Output *out_cc)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("// Resume upon next input segment"); out_cc->println("// Resume upon next input segment");
out_cc->println("BINPAC_ASSERT(!%s->ready());", out_cc->println("BINPAC_ASSERT(!%s->ready());", env_->RValue(flow_buffer_id));
env_->RValue(flow_buffer_id));
out_cc->println("break;"); out_cc->println("break;");
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
@ -318,14 +292,12 @@ void FlowDecl::GenCodeFlowUnit(Output *out_cc)
out_cc->dec_indent(); out_cc->dec_indent();
} }
void FlowDecl::GenCodeDatagram(Output *out_cc) void FlowDecl::GenCodeDatagram(Output* out_cc)
{ {
Type *unit_datatype = dataunit_->data_type(); Type* unit_datatype = dataunit_->data_type();
GenNewDataUnit(out_cc); GenNewDataUnit(out_cc);
string parse_params = strfmt("%s, %s", string parse_params = strfmt("%s, %s", env_->RValue(begin_of_data), env_->RValue(end_of_data));
env_->RValue(begin_of_data),
env_->RValue(end_of_data));
if ( RequiresAnalyzerContext::compute(unit_datatype) ) if ( RequiresAnalyzerContext::compute(unit_datatype) )
{ {

View file

@ -4,44 +4,44 @@
#include "pac_analyzer.h" #include "pac_analyzer.h"
class FlowDecl : public AnalyzerDecl class FlowDecl : public AnalyzerDecl
{ {
public: public:
FlowDecl(ID *flow_id, ParamList *params, AnalyzerElementList *elemlist); FlowDecl(ID* flow_id, ParamList* params, AnalyzerElementList* elemlist);
~FlowDecl(); ~FlowDecl();
void Prepare(); void Prepare();
void set_conn_decl(ConnDecl *c) { conn_decl_ = c; } void set_conn_decl(ConnDecl* c) { conn_decl_ = c; }
static ParameterizedType *flow_buffer_type(); static ParameterizedType* flow_buffer_type();
protected: protected:
void AddBaseClass(vector<string> *base_classes) const; void AddBaseClass(vector<string>* base_classes) const;
void GenInitCode(Output *out_cc); void GenInitCode(Output* out_cc);
void GenCleanUpCode(Output *out_cc); void GenCleanUpCode(Output* out_cc);
void GenProcessFunc(Output *out_h, Output *out_cc); void GenProcessFunc(Output* out_h, Output* out_cc);
void GenEOFFunc(Output *out_h, Output *out_cc); void GenEOFFunc(Output* out_h, Output* out_cc);
void GenGapFunc(Output *out_h, Output *out_cc); void GenGapFunc(Output* out_h, Output* out_cc);
void GenPubDecls(Output *out_h, Output *out_cc); void GenPubDecls(Output* out_h, Output* out_cc);
void GenPrivDecls(Output *out_h, Output *out_cc); void GenPrivDecls(Output* out_h, Output* out_cc);
void ProcessFlowElement(AnalyzerFlow *flow_elem); void ProcessFlowElement(AnalyzerFlow* flow_elem);
void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem); void ProcessDataUnitElement(AnalyzerDataUnit* dataunit_elem);
private: private:
void GenNewDataUnit(Output *out_cc); void GenNewDataUnit(Output* out_cc);
void GenDeleteDataUnit(Output *out_cc); void GenDeleteDataUnit(Output* out_cc);
void GenCodeFlowUnit(Output *out_cc); void GenCodeFlowUnit(Output* out_cc);
void GenCodeDatagram(Output *out_cc); void GenCodeDatagram(Output* out_cc);
AnalyzerDataUnit *dataunit_; AnalyzerDataUnit* dataunit_;
ConnDecl *conn_decl_; ConnDecl* conn_decl_;
Field *flow_buffer_var_field_; Field* flow_buffer_var_field_;
static ParameterizedType *flow_buffer_type_; static ParameterizedType* flow_buffer_type_;
}; };
#endif // pac_flow_h #endif // pac_flow_h

View file

@ -1,12 +1,13 @@
#include "pac_func.h"
#include "pac_embedded.h" #include "pac_embedded.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_func.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_param.h" #include "pac_param.h"
#include "pac_type.h" #include "pac_type.h"
Function::Function(ID *id, Type *type, ParamList *params) Function::Function(ID* id, Type* type, ParamList* params)
: id_(id), type_(type), params_(params), expr_(0), code_(0) : id_(id), type_(type), params_(params), expr_(0), code_(0)
{ {
analyzer_decl_ = 0; analyzer_decl_ = 0;
env_ = 0; env_ = 0;
@ -22,16 +23,16 @@ Function::~Function()
delete code_; delete code_;
} }
void Function::Prepare(Env *env) void Function::Prepare(Env* env)
{ {
env->AddID(id_, FUNC_ID, type_); env->AddID(id_, FUNC_ID, type_);
env->SetEvaluated(id_); env->SetEvaluated(id_);
env_ = new Env(env, this); env_ = new Env(env, this);
foreach(i, ParamList, params_) foreach (i, ParamList, params_)
{ {
Param *p = *i; Param* p = *i;
env_->AddID(p->id(), FUNC_PARAM, p->type()); env_->AddID(p->id(), FUNC_PARAM, p->type());
env_->SetEvaluated(p->id()); env_->SetEvaluated(p->id());
} }
@ -44,22 +45,17 @@ void Function::GenForwardDeclaration(Output* out_h)
void Function::GenCode(Output* out_h, Output* out_cc) void Function::GenCode(Output* out_h, Output* out_cc)
{ {
out_h->println("%s %s(%s);", out_h->println("%s %s(%s);", type_->DataTypeStr().c_str(), id_->Name(),
type_->DataTypeStr().c_str(), ParamDecls(params_).c_str());
id_->Name(),
ParamDecls(params_).c_str());
string class_str = ""; string class_str = "";
if ( analyzer_decl_ ) if ( analyzer_decl_ )
class_str = strfmt("%s::", analyzer_decl_->id()->Name()); class_str = strfmt("%s::", analyzer_decl_->id()->Name());
string proto_str = strfmt("%s %s%s(%s)", string proto_str = strfmt("%s %s%s(%s)", type_->DataTypeStr().c_str(), class_str.c_str(),
type_->DataTypeStr().c_str(), id_->Name(), ParamDecls(params_).c_str());
class_str.c_str(),
id_->Name(),
ParamDecls(params_).c_str());
ASSERT(!(expr_ && code_)); ASSERT(! (expr_ && code_));
if ( expr_ ) if ( expr_ )
{ {
@ -68,9 +64,8 @@ void Function::GenCode(Output* out_h, Output* out_cc)
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("return static_cast<%s>(%s);", out_cc->println("return static_cast<%s>(%s);", type_->DataTypeStr().c_str(),
type_->DataTypeStr().c_str(), expr_->EvalExpr(out_cc, env_));
expr_->EvalExpr(out_cc, env_));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
@ -92,8 +87,7 @@ void Function::GenCode(Output* out_h, Output* out_cc)
out_cc->println(""); out_cc->println("");
} }
FuncDecl::FuncDecl(Function *function) FuncDecl::FuncDecl(Function* function) : Decl(function->id()->clone(), FUNC), function_(function)
: Decl(function->id()->clone(), FUNC), function_(function)
{ {
function_->Prepare(global_env()); function_->Prepare(global_env());
} }
@ -103,21 +97,19 @@ FuncDecl::~FuncDecl()
delete function_; delete function_;
} }
void FuncDecl::Prepare() void FuncDecl::Prepare() { }
{
}
void FuncDecl::GenForwardDeclaration(Output *out_h) void FuncDecl::GenForwardDeclaration(Output* out_h)
{ {
function_->GenForwardDeclaration(out_h); function_->GenForwardDeclaration(out_h);
} }
void FuncDecl::GenCode(Output *out_h, Output *out_cc) void FuncDecl::GenCode(Output* out_h, Output* out_cc)
{ {
function_->GenCode(out_h, out_cc); function_->GenCode(out_h, out_cc);
} }
AnalyzerFunction::AnalyzerFunction(Function *function) AnalyzerFunction::AnalyzerFunction(Function* function)
: AnalyzerElement(FUNCTION), function_(function) : AnalyzerElement(FUNCTION), function_(function)
{ {
} }

View file

@ -1,68 +1,68 @@
#ifndef pac_func_h #ifndef pac_func_h
#define pac_func_h #define pac_func_h
#include "pac_decl.h"
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_decl.h"
class Function : public Object class Function : public Object
{ {
public: public:
Function(ID *id, Type *type, ParamList *params); Function(ID* id, Type* type, ParamList* params);
~Function(); ~Function();
ID *id() const { return id_; } ID* id() const { return id_; }
AnalyzerDecl *analyzer_decl() const { return analyzer_decl_; } AnalyzerDecl* analyzer_decl() const { return analyzer_decl_; }
void set_analyzer_decl(AnalyzerDecl *decl) { analyzer_decl_ = decl; } void set_analyzer_decl(AnalyzerDecl* decl) { analyzer_decl_ = decl; }
Expr *expr() const { return expr_; } Expr* expr() const { return expr_; }
void set_expr(Expr *expr) { expr_ = expr; } void set_expr(Expr* expr) { expr_ = expr; }
EmbeddedCode *code() const { return code_; } EmbeddedCode* code() const { return code_; }
void set_code(EmbeddedCode *code) { code_ = code; } void set_code(EmbeddedCode* code) { code_ = code; }
void Prepare(Env *env); void Prepare(Env* env);
void GenForwardDeclaration(Output *out_h); void GenForwardDeclaration(Output* out_h);
void GenCode(Output *out_h, Output *out_cc); void GenCode(Output* out_h, Output* out_cc);
private: private:
Env *env_; Env* env_;
ID *id_; ID* id_;
Type *type_; Type* type_;
ParamList *params_; ParamList* params_;
AnalyzerDecl *analyzer_decl_; AnalyzerDecl* analyzer_decl_;
Expr *expr_; Expr* expr_;
EmbeddedCode *code_; EmbeddedCode* code_;
}; };
class FuncDecl : public Decl class FuncDecl : public Decl
{ {
public: public:
FuncDecl(Function *function); FuncDecl(Function* function);
~FuncDecl(); ~FuncDecl();
Function *function() const { return function_; } Function* function() const { return function_; }
void Prepare(); void Prepare();
void GenForwardDeclaration(Output *out_h); void GenForwardDeclaration(Output* out_h);
void GenCode(Output *out_h, Output *out_cc); void GenCode(Output* out_h, Output* out_cc);
private: private:
Function *function_; Function* function_;
}; };
class AnalyzerFunction : public AnalyzerElement class AnalyzerFunction : public AnalyzerElement
{ {
public: public:
AnalyzerFunction(Function *function); AnalyzerFunction(Function* function);
Function *function() const { return function_; } Function* function() const { return function_; }
private: private:
Function *function_; Function* function_;
}; };
#endif // pac_func_h #endif // pac_func_h

View file

@ -1,56 +1,57 @@
#include "pac_id.h"
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_field.h" #include "pac_field.h"
#include "pac_id.h"
#include "pac_type.h" #include "pac_type.h"
#include "pac_utils.h" #include "pac_utils.h"
const ID *default_value_var = 0; const ID* default_value_var = 0;
const ID *null_id = 0; const ID* null_id = 0;
const ID *null_byteseg_id = 0; const ID* null_byteseg_id = 0;
const ID *null_decl_id = 0; const ID* null_decl_id = 0;
const ID *begin_of_data = 0; const ID* begin_of_data = 0;
const ID *end_of_data = 0; const ID* end_of_data = 0;
const ID *len_of_data = 0; const ID* len_of_data = 0;
const ID *byteorder_id = 0; const ID* byteorder_id = 0;
const ID *bigendian_id = 0; const ID* bigendian_id = 0;
const ID *littleendian_id = 0; const ID* littleendian_id = 0;
const ID *unspecified_byteorder_id = 0; const ID* unspecified_byteorder_id = 0;
const ID *const_true_id = 0; const ID* const_true_id = 0;
const ID *const_false_id = 0; const ID* const_false_id = 0;
const ID *analyzer_context_id = 0; const ID* analyzer_context_id = 0;
const ID *context_macro_id = 0; const ID* context_macro_id = 0;
const ID *this_id = 0; const ID* this_id = 0;
const ID *sourcedata_id = 0; const ID* sourcedata_id = 0;
const ID *connection_id = 0; const ID* connection_id = 0;
const ID *upflow_id = 0; const ID* upflow_id = 0;
const ID *downflow_id = 0; const ID* downflow_id = 0;
const ID *dataunit_id = 0; const ID* dataunit_id = 0;
const ID *flow_buffer_id = 0; const ID* flow_buffer_id = 0;
const ID *element_macro_id = 0; const ID* element_macro_id = 0;
const ID *input_macro_id = 0; const ID* input_macro_id = 0;
const ID *cxt_connection_id = 0; const ID* cxt_connection_id = 0;
const ID *cxt_flow_id = 0; const ID* cxt_flow_id = 0;
const ID *parsing_state_id = 0; const ID* parsing_state_id = 0;
const ID *buffering_state_id = 0; const ID* buffering_state_id = 0;
int ID::anonymous_id_seq = 0; int ID::anonymous_id_seq = 0;
ID *ID::NewAnonymousID(const string &prefix) ID* ID::NewAnonymousID(const string& prefix)
{ {
ID *id = new ID(strfmt("%s%03d", prefix.c_str(), ++anonymous_id_seq)); ID* id = new ID(strfmt("%s%03d", prefix.c_str(), ++anonymous_id_seq));
id->anonymous_id_ = true; id->anonymous_id_ = true;
return id; return id;
} }
IDRecord::IDRecord(Env *arg_env, const ID* arg_id, IDType arg_id_type) IDRecord::IDRecord(Env* arg_env, const ID* arg_id, IDType arg_id_type)
: env(arg_env), id(arg_id), id_type(arg_id_type) : env(arg_env), id(arg_id), id_type(arg_id_type)
{ {
eval = 0; eval = 0;
evaluated = in_evaluation = false; evaluated = in_evaluation = false;
setfunc = ""; // except for STATE_VAR setfunc = ""; // except for STATE_VAR
switch (id_type) switch ( id_type )
{ {
case MEMBER_VAR: case MEMBER_VAR:
rvalue = strfmt("%s()", id->Name()); rvalue = strfmt("%s()", id->Name());
@ -96,9 +97,7 @@ IDRecord::IDRecord(Env *arg_env, const ID* arg_id, IDType arg_id_type)
macro = 0; macro = 0;
} }
IDRecord::~IDRecord() IDRecord::~IDRecord() { }
{
}
void IDRecord::SetConstant(int c) void IDRecord::SetConstant(int c)
{ {
@ -107,20 +106,20 @@ void IDRecord::SetConstant(int c)
constant = c; constant = c;
} }
bool IDRecord::GetConstant(int *pc) const bool IDRecord::GetConstant(int* pc) const
{ {
if ( constant_set ) if ( constant_set )
*pc = constant; *pc = constant;
return constant_set; return constant_set;
} }
void IDRecord::SetMacro(Expr *e) void IDRecord::SetMacro(Expr* e)
{ {
ASSERT(id_type == MACRO); ASSERT(id_type == MACRO);
macro = e; macro = e;
} }
Expr *IDRecord::GetMacro() const Expr* IDRecord::GetMacro() const
{ {
ASSERT(id_type == MACRO); ASSERT(id_type == MACRO);
return macro; return macro;
@ -187,7 +186,7 @@ Env::~Env()
} }
} }
void Env::AddID(const ID* id, IDType id_type, Type *data_type) void Env::AddID(const ID* id, IDType id_type, Type* data_type)
{ {
DEBUG_MSG("To add ID `%s'...\n", id->Name()); DEBUG_MSG("To add ID `%s'...\n", id->Name());
id_map_t::iterator it = id_map.find(id); id_map_t::iterator it = id_map.find(id);
@ -202,25 +201,25 @@ void Env::AddID(const ID* id, IDType id_type, Type *data_type)
SetDataType(id, data_type); SetDataType(id, data_type);
} }
void Env::AddConstID(const ID* id, const int c, Type *type) void Env::AddConstID(const ID* id, const int c, Type* type)
{ {
if ( ! type ) if ( ! type )
type = extern_type_int; type = extern_type_int;
AddID(id, CONST, type); AddID(id, CONST, type);
SetConstant(id, c); SetConstant(id, c);
SetEvaluated(id); // a constant is always evaluated SetEvaluated(id); // a constant is always evaluated
} }
void Env::AddMacro(const ID *id, Expr *macro) void Env::AddMacro(const ID* id, Expr* macro)
{ {
AddID(id, MACRO, macro->DataType(this)); AddID(id, MACRO, macro->DataType(this));
SetMacro(id, macro); SetMacro(id, macro);
SetEvaluated(id); SetEvaluated(id);
} }
ID *Env::AddTempID(Type *type) ID* Env::AddTempID(Type* type)
{ {
ID *id = ID::NewAnonymousID("t_var_"); ID* id = ID::NewAnonymousID("t_var_");
AddID(id, TEMP_VAR, type); AddID(id, TEMP_VAR, type);
return id; return id;
} }
@ -249,7 +248,7 @@ IDType Env::GetIDType(const ID* id) const
const char* Env::RValue(const ID* id) const const char* Env::RValue(const ID* id) const
{ {
IDRecord *r = lookup(id, true, false); IDRecord* r = lookup(id, true, false);
if ( r ) if ( r )
return r->RValue(); return r->RValue();
else else
@ -273,14 +272,14 @@ void Env::SetEvalMethod(const ID* id, Evaluatable* eval)
void Env::Evaluate(Output* out, const ID* id) void Env::Evaluate(Output* out, const ID* id)
{ {
IDRecord *r = lookup(id, true, !allow_undefined_id()); IDRecord* r = lookup(id, true, ! allow_undefined_id());
if ( r ) if ( r )
r->Evaluate(out, this); r->Evaluate(out, this);
} }
bool Env::Evaluated(const ID* id) const bool Env::Evaluated(const ID* id) const
{ {
IDRecord *r = lookup(id, true, !allow_undefined_id()); IDRecord* r = lookup(id, true, ! allow_undefined_id());
if ( r ) if ( r )
return r->Evaluated(); return r->Evaluated();
else else
@ -292,23 +291,20 @@ void Env::SetEvaluated(const ID* id, bool v)
{ {
if ( in_branch() ) if ( in_branch() )
{ {
Field *f = GetField(id); Field* f = GetField(id);
if (f && f->tof() == LET_FIELD) if ( f && f->tof() == LET_FIELD )
{ {
throw Exception( throw Exception(context_object_, strfmt("INTERNAL ERROR: "
context_object_, "evaluating let field '%s' in a branch! "
strfmt("INTERNAL ERROR: " "To work around this problem, "
"evaluating let field '%s' in a branch! " "add '&requires(%s)' to the case type. "
"To work around this problem, " "Sorry for the inconvenience.\n",
"add '&requires(%s)' to the case type. " id->Name(), id->Name()));
"Sorry for the inconvenience.\n",
id->Name(),
id->Name()));
ASSERT(0); ASSERT(0);
} }
} }
IDRecord *r = lookup(id, false, false); IDRecord* r = lookup(id, false, false);
if ( r ) if ( r )
r->SetEvaluated(v); r->SetEvaluated(v);
else if ( parent ) else if ( parent )
@ -334,16 +330,16 @@ void Env::SetDataType(const ID* id, Type* type)
Type* Env::GetDataType(const ID* id) const Type* Env::GetDataType(const ID* id) const
{ {
IDRecord *r = lookup(id, true, false); IDRecord* r = lookup(id, true, false);
if ( r ) if ( r )
return r->GetDataType(); return r->GetDataType();
else else
return 0; return 0;
} }
string Env::DataTypeStr(const ID *id) const string Env::DataTypeStr(const ID* id) const
{ {
Type *type = GetDataType(id); Type* type = GetDataType(id);
if ( ! type ) if ( ! type )
throw Exception(id, "data type not defined"); throw Exception(id, "data type not defined");
return type->DataTypeStr(); return type->DataTypeStr();
@ -365,7 +361,7 @@ bool Env::GetConstant(const ID* id, int* pc) const
return false; return false;
} }
void Env::SetMacro(const ID* id, Expr *macro) void Env::SetMacro(const ID* id, Expr* macro)
{ {
lookup(id, true, true)->SetMacro(macro); lookup(id, true, true)->SetMacro(macro);
} }
@ -409,7 +405,7 @@ void init_builtin_identifiers()
Env* global_env() Env* global_env()
{ {
static Env *the_global_env = 0; static Env* the_global_env = 0;
if ( ! the_global_env ) if ( ! the_global_env )
{ {
@ -436,7 +432,7 @@ Env* global_env()
return the_global_env; return the_global_env;
} }
string set_function(const ID *id) string set_function(const ID* id)
{ {
return strfmt("set_%s", id->Name()); return strfmt("set_%s", id->Name());
} }

View file

@ -22,7 +22,8 @@ using namespace std;
// Env -- a mapping from ID names to their L/R-value expressions and evaluation // Env -- a mapping from ID names to their L/R-value expressions and evaluation
// methods. // methods.
enum IDType { enum IDType
{
CONST, CONST,
GLOBAL_VAR, GLOBAL_VAR,
TEMP_VAR, TEMP_VAR,
@ -33,7 +34,7 @@ enum IDType {
MACRO, MACRO,
FUNC_ID, FUNC_ID,
FUNC_PARAM, FUNC_PARAM,
}; };
class ID; class ID;
class IDRecord; class IDRecord;
@ -41,206 +42,201 @@ class Env;
class Evaluatable; class Evaluatable;
class ID : public Object class ID : public Object
{ {
public: public:
ID(string arg_name) ID(string arg_name) : name(arg_name), anonymous_id_(false)
: name(arg_name), anonymous_id_(false)
{ {
locname = nfmt("%s:%s", Location(), Name()); locname = nfmt("%s:%s", Location(), Name());
} }
~ID() ~ID() { delete[] locname; }
{
delete [] locname;
}
bool operator==(ID const &x) const { return name == x.Name(); } bool operator==(ID const& x) const { return name == x.Name(); }
const char *Name() const { return name.c_str(); } const char* Name() const { return name.c_str(); }
const char *LocName() const { return locname; } const char* LocName() const { return locname; }
bool is_anonymous() const { return anonymous_id_; } bool is_anonymous() const { return anonymous_id_; }
ID *clone() const { return new ID(Name()); } ID* clone() const { return new ID(Name()); }
protected: protected:
string name; string name;
bool anonymous_id_; bool anonymous_id_;
char *locname; char* locname;
friend class ID_ptr_cmp; friend class ID_ptr_cmp;
public: public:
static ID *NewAnonymousID(const string &prefix); static ID* NewAnonymousID(const string& prefix);
private: private:
static int anonymous_id_seq; static int anonymous_id_seq;
}; };
// A comparison operator for pointers to ID's. // A comparison operator for pointers to ID's.
class ID_ptr_cmp class ID_ptr_cmp
{ {
public: public:
bool operator()(const ID *const & id1, const ID *const & id2) const bool operator()(const ID* const& id1, const ID* const& id2) const
{ {
ASSERT(id1); ASSERT(id1);
ASSERT(id2); ASSERT(id2);
return id1->name < id2->name; return id1->name < id2->name;
} }
}; };
class IDRecord class IDRecord
{ {
public: public:
IDRecord(Env *env, const ID *id, IDType id_type); IDRecord(Env* env, const ID* id, IDType id_type);
~IDRecord(); ~IDRecord();
IDType GetType() const { return id_type; } IDType GetType() const { return id_type; }
void SetDataType(Type *type) { data_type = type; } void SetDataType(Type* type) { data_type = type; }
Type *GetDataType() const { return data_type; } Type* GetDataType() const { return data_type; }
void SetEvalMethod(Evaluatable *arg_eval) { eval = arg_eval; } void SetEvalMethod(Evaluatable* arg_eval) { eval = arg_eval; }
void Evaluate(Output *out, Env *env); void Evaluate(Output* out, Env* env);
void SetEvaluated(bool v); void SetEvaluated(bool v);
bool Evaluated() const { return evaluated; } bool Evaluated() const { return evaluated; }
void SetField(Field *f) { field = f; } void SetField(Field* f) { field = f; }
Field *GetField() const { return field; } Field* GetField() const { return field; }
void SetConstant(int c); void SetConstant(int c);
bool GetConstant(int *pc) const; bool GetConstant(int* pc) const;
void SetMacro(Expr *expr); void SetMacro(Expr* expr);
Expr *GetMacro() const; Expr* GetMacro() const;
const char * RValue() const; const char* RValue() const;
const char * LValue() const; const char* LValue() const;
protected: protected:
Env *env; Env* env;
const ID *id; const ID* id;
IDType id_type; IDType id_type;
string rvalue; string rvalue;
string lvalue; string lvalue;
string setfunc; string setfunc;
Type *data_type; Type* data_type;
Field *field; Field* field;
int constant; int constant;
bool constant_set; bool constant_set;
Expr *macro; Expr* macro;
bool evaluated; bool evaluated;
bool in_evaluation; // to detect cyclic dependence bool in_evaluation; // to detect cyclic dependence
Evaluatable *eval; Evaluatable* eval;
}; };
class Evaluatable class Evaluatable
{ {
public: public:
virtual ~Evaluatable() {} virtual ~Evaluatable() { }
virtual void GenEval(Output *out, Env *env) = 0; virtual void GenEval(Output* out, Env* env) = 0;
}; };
class Env class Env
{ {
public: public:
Env(Env *parent_env, Object *context_object); Env(Env* parent_env, Object* context_object);
~Env(); ~Env();
bool allow_undefined_id() const { return allow_undefined_id_; } bool allow_undefined_id() const { return allow_undefined_id_; }
void set_allow_undefined_id(bool x) { allow_undefined_id_ = x; } void set_allow_undefined_id(bool x) { allow_undefined_id_ = x; }
bool in_branch() const { return in_branch_; } bool in_branch() const { return in_branch_; }
void set_in_branch(bool x) { in_branch_ = x; } void set_in_branch(bool x) { in_branch_ = x; }
void AddID(const ID *id, IDType id_type, Type *type); void AddID(const ID* id, IDType id_type, Type* type);
void AddConstID(const ID *id, const int c, Type *type = 0); void AddConstID(const ID* id, const int c, Type* type = 0);
void AddMacro(const ID *id, Expr *expr); void AddMacro(const ID* id, Expr* expr);
// Generate a temp ID with a unique name // Generate a temp ID with a unique name
ID *AddTempID(Type *type); ID* AddTempID(Type* type);
IDType GetIDType(const ID *id) const; IDType GetIDType(const ID* id) const;
const char * RValue(const ID *id) const; const char* RValue(const ID* id) const;
const char * LValue(const ID *id) const; const char* LValue(const ID* id) const;
// const char *SetFunc(const ID *id) const; // const char *SetFunc(const ID *id) const;
// Set evaluation method for the ID // Set evaluation method for the ID
void SetEvalMethod(const ID *id, Evaluatable *eval); void SetEvalMethod(const ID* id, Evaluatable* eval);
// Evaluate the ID according to the evaluation method. It // Evaluate the ID according to the evaluation method. It
// assumes the ID has an evaluation emthod. It does nothing // assumes the ID has an evaluation emthod. It does nothing
// if the ID has already been evaluated. // if the ID has already been evaluated.
void Evaluate(Output *out, const ID *id); void Evaluate(Output* out, const ID* id);
// Whether the ID has already been evaluated. // Whether the ID has already been evaluated.
bool Evaluated(const ID *id) const; bool Evaluated(const ID* id) const;
// Set the ID as evaluated (or not). // Set the ID as evaluated (or not).
void SetEvaluated(const ID *id, bool v = true); void SetEvaluated(const ID* id, bool v = true);
void SetField(const ID *id, Field *field); void SetField(const ID* id, Field* field);
Field *GetField(const ID *id) const; Field* GetField(const ID* id) const;
bool GetConstant(const ID *id, int *pc) const; bool GetConstant(const ID* id, int* pc) const;
Expr *GetMacro(const ID *id) const; Expr* GetMacro(const ID* id) const;
Type *GetDataType(const ID *id) const; Type* GetDataType(const ID* id) const;
string DataTypeStr(const ID *id) const; string DataTypeStr(const ID* id) const;
protected: protected:
IDRecord *lookup(const ID *id, IDRecord* lookup(const ID* id, bool recursive, bool raise_exception) const;
bool recursive,
bool raise_exception) const;
void SetDataType(const ID *id, Type *type); void SetDataType(const ID* id, Type* type);
void SetConstant(const ID *id, int constant); void SetConstant(const ID* id, int constant);
void SetMacro(const ID *id, Expr *macro); void SetMacro(const ID* id, Expr* macro);
private: private:
Env *parent; Env* parent;
Object *context_object_; Object* context_object_;
typedef map<const ID*, IDRecord*, ID_ptr_cmp> id_map_t; typedef map<const ID*, IDRecord*, ID_ptr_cmp> id_map_t;
id_map_t id_map; id_map_t id_map;
bool allow_undefined_id_; bool allow_undefined_id_;
bool in_branch_; bool in_branch_;
}; };
extern const ID *default_value_var; extern const ID* default_value_var;
extern const ID *null_id; extern const ID* null_id;
extern const ID *null_byteseg_id; extern const ID* null_byteseg_id;
extern const ID *begin_of_data; extern const ID* begin_of_data;
extern const ID *end_of_data; extern const ID* end_of_data;
extern const ID *len_of_data; extern const ID* len_of_data;
extern const ID *byteorder_id; extern const ID* byteorder_id;
extern const ID *bigendian_id; extern const ID* bigendian_id;
extern const ID *littleendian_id; extern const ID* littleendian_id;
extern const ID *unspecified_byteorder_id; extern const ID* unspecified_byteorder_id;
extern const ID *analyzer_context_id; extern const ID* analyzer_context_id;
extern const ID *context_macro_id; extern const ID* context_macro_id;
extern const ID *this_id; extern const ID* this_id;
extern const ID *sourcedata_id; extern const ID* sourcedata_id;
// extern const ID *sourcedata_begin_id; // extern const ID *sourcedata_begin_id;
// extern const ID *sourcedata_end_id; // extern const ID *sourcedata_end_id;
extern const ID *connection_id; extern const ID* connection_id;
extern const ID *upflow_id; extern const ID* upflow_id;
extern const ID *downflow_id; extern const ID* downflow_id;
extern const ID *dataunit_id; extern const ID* dataunit_id;
extern const ID *flow_buffer_id; extern const ID* flow_buffer_id;
extern const ID *element_macro_id; extern const ID* element_macro_id;
extern const ID *cxt_connection_id; extern const ID* cxt_connection_id;
extern const ID *cxt_flow_id; extern const ID* cxt_flow_id;
extern const ID *input_macro_id; extern const ID* input_macro_id;
extern const ID *parsing_state_id; extern const ID* parsing_state_id;
extern const ID *buffering_state_id; extern const ID* buffering_state_id;
extern void init_builtin_identifiers(); extern void init_builtin_identifiers();
extern Env *global_env(); extern Env* global_env();
extern string set_function(const ID *id); extern string set_function(const ID* id);
#endif // pac_id_h #endif // pac_id_h

View file

@ -1,16 +1,14 @@
#include "pac_inputbuf.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_inputbuf.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_type.h" #include "pac_type.h"
InputBuffer::InputBuffer(Expr *expr) InputBuffer::InputBuffer(Expr* expr) : DataDepElement(INPUT_BUFFER), expr_(expr) { }
: DataDepElement(INPUT_BUFFER), expr_(expr)
{
}
bool InputBuffer::DoTraverse(DataDepVisitor *visitor) bool InputBuffer::DoTraverse(DataDepVisitor* visitor)
{ {
if ( expr_ && ! expr_->Traverse(visitor) ) if ( expr_ && ! expr_->Traverse(visitor) )
return false; return false;
@ -22,20 +20,16 @@ bool InputBuffer::RequiresAnalyzerContext() const
return expr_->RequiresAnalyzerContext(); return expr_->RequiresAnalyzerContext();
} }
DataPtr InputBuffer::GenDataBeginEnd(Output *out_cc, Env *env) DataPtr InputBuffer::GenDataBeginEnd(Output* out_cc, Env* env)
{ {
env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr);
env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr);
out_cc->println("%s %s, %s;", out_cc->println("%s %s, %s;", extern_type_const_byteptr->DataTypeStr().c_str(),
extern_type_const_byteptr->DataTypeStr().c_str(), env->LValue(begin_of_data), env->LValue(end_of_data));
env->LValue(begin_of_data),
env->LValue(end_of_data));
out_cc->println("get_pointers(%s, &%s, &%s);", out_cc->println("get_pointers(%s, &%s, &%s);", expr_->EvalExpr(out_cc, env),
expr_->EvalExpr(out_cc, env), env->LValue(begin_of_data), env->LValue(end_of_data));
env->LValue(begin_of_data),
env->LValue(end_of_data));
env->SetEvaluated(begin_of_data); env->SetEvaluated(begin_of_data);
env->SetEvaluated(end_of_data); env->SetEvaluated(end_of_data);

View file

@ -7,18 +7,18 @@
class Expr; class Expr;
class InputBuffer : public Object, public DataDepElement class InputBuffer : public Object, public DataDepElement
{ {
public: public:
InputBuffer(Expr *expr); InputBuffer(Expr* expr);
bool RequiresAnalyzerContext() const; bool RequiresAnalyzerContext() const;
DataPtr GenDataBeginEnd(Output *out_cc, Env *env); DataPtr GenDataBeginEnd(Output* out_cc, Env* env);
protected: protected:
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
private: private:
Expr *expr_; Expr* expr_;
}; };
#endif // pac_inputbuf_h #endif // pac_inputbuf_h

View file

@ -1,21 +1,19 @@
#include "pac_let.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_let.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_type.h" #include "pac_type.h"
namespace { namespace
void GenLetEval(const ID *id, Expr *expr, string prefix, Output* out, Env* env)
{ {
}
} // private namespace void GenLetEval(const ID* id, Expr* expr, string prefix, Output* out, Env* env) { }
LetField::LetField(ID* id, Type *type, Expr* expr) } // private namespace
: Field(LET_FIELD,
TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, LetField::LetField(ID* id, Type* type, Expr* expr)
id, type), : Field(LET_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type),
expr_(expr) expr_(expr)
{ {
ASSERT(expr_); ASSERT(expr_);
@ -26,16 +24,14 @@ LetField::~LetField()
delete expr_; delete expr_;
} }
bool LetField::DoTraverse(DataDepVisitor *visitor) bool LetField::DoTraverse(DataDepVisitor* visitor)
{ {
return Field::DoTraverse(visitor) && return Field::DoTraverse(visitor) && expr()->Traverse(visitor);
expr()->Traverse(visitor);
} }
bool LetField::RequiresAnalyzerContext() const bool LetField::RequiresAnalyzerContext() const
{ {
return Field::RequiresAnalyzerContext() || return Field::RequiresAnalyzerContext() || (expr() && expr()->RequiresAnalyzerContext());
(expr() && expr()->RequiresAnalyzerContext());
} }
void LetField::Prepare(Env* env) void LetField::Prepare(Env* env)
@ -49,7 +45,7 @@ void LetField::Prepare(Env* env)
else else
type_ = extern_type_int->Clone(); type_ = extern_type_int->Clone();
foreach(i, AttrList, attrs_) foreach (i, AttrList, attrs_)
ProcessAttr(*i); ProcessAttr(*i);
} }
@ -83,15 +79,12 @@ void LetField::GenParseCode(Output* out_cc, Env* env)
// force evaluation of IDs contained in this expr // force evaluation of IDs contained in this expr
expr()->ForceIDEval(out_cc, env); expr()->ForceIDEval(out_cc, env);
out_cc->println("if ( %s )", out_cc->println("if ( %s )", env->RValue(type_->has_value_var()));
env->RValue(type_->has_value_var()));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
} }
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(id_), expr()->EvalExpr(out_cc, env));
env->LValue(id_),
expr()->EvalExpr(out_cc, env));
if ( ! env->Evaluated(id_) ) if ( ! env->Evaluated(id_) )
env->SetEvaluated(id_); env->SetEvaluated(id_);
@ -107,20 +100,19 @@ void LetField::GenEval(Output* out_cc, Env* env)
GenParseCode(out_cc, env); GenParseCode(out_cc, env);
} }
LetDecl::LetDecl(ID *id, Type *type, Expr *expr) LetDecl::LetDecl(ID* id, Type* type, Expr* expr) : Decl(id, LET), type_(type), expr_(expr)
: Decl(id, LET), type_(type), expr_(expr)
{ {
if ( ! type_ ) if ( ! type_ )
{ {
ASSERT(expr_); ASSERT(expr_);
type_ = expr_->DataType(global_env()); type_ = expr_->DataType(global_env());
if ( type_ ) if ( type_ )
type_ = type_->Clone(); type_ = type_->Clone();
else else
type_ = extern_type_int->Clone(); type_ = extern_type_int->Clone();
} }
Env *env = global_env(); Env* env = global_env();
int c; int c;
if ( expr_ && expr_->ConstFold(env, &c) ) if ( expr_ && expr_->ConstFold(env, &c) )
env->AddConstID(id_, c, type); env->AddConstID(id_, c, type);
@ -134,30 +126,21 @@ LetDecl::~LetDecl()
delete expr_; 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;", out_h->println("extern %s const %s;", type_->DataTypeStr().c_str(), global_env()->RValue(id_));
type_->DataTypeStr().c_str(),
global_env()->RValue(id_));
GenEval(out_cc, global_env()); GenEval(out_cc, global_env());
} }
void LetDecl::GenEval(Output *out_cc, Env * /* env */) void LetDecl::GenEval(Output* out_cc, Env* /* env */)
{ {
Env *env = global_env(); Env* env = global_env();
string tmp = strfmt("%s const", type_->DataTypeStr().c_str()); string tmp = strfmt("%s const", type_->DataTypeStr().c_str());
out_cc->println("%s %s = %s;", out_cc->println("%s %s = %s;", tmp.c_str(), env->LValue(id_), expr_->EvalExpr(out_cc, env));
tmp.c_str(),
env->LValue(id_),
expr_->EvalExpr(out_cc, env));
if ( ! env->Evaluated(id_) ) if ( ! env->Evaluated(id_) )
env->SetEvaluated(id_); env->SetEvaluated(id_);

View file

@ -5,12 +5,12 @@
#include "pac_field.h" #include "pac_field.h"
class LetField : public Field, Evaluatable class LetField : public Field, Evaluatable
{ {
public: public:
LetField(ID* arg_id, Type *type, Expr* arg_expr); LetField(ID* arg_id, Type* type, Expr* arg_expr);
~LetField(); ~LetField();
Expr *expr() const { return expr_; } Expr* expr() const { return expr_; }
void Prepare(Env* env); void Prepare(Env* env);
@ -21,28 +21,28 @@ public:
bool RequiresAnalyzerContext() const; bool RequiresAnalyzerContext() const;
protected: protected:
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
protected: protected:
Expr* expr_; Expr* expr_;
}; };
class LetDecl : public Decl, Evaluatable class LetDecl : public Decl, Evaluatable
{ {
public: public:
LetDecl(ID *id, Type *type, Expr *expr); LetDecl(ID* id, Type* type, Expr* expr);
~LetDecl(); ~LetDecl();
Expr *expr() const { return expr_; } Expr* expr() const { return expr_; }
void Prepare(); void Prepare();
void GenForwardDeclaration(Output *out_h); void GenForwardDeclaration(Output* out_h);
void GenCode(Output *out_h, Output *out_cc); void GenCode(Output* out_h, Output* out_cc);
void GenEval(Output* out, Env* env); void GenEval(Output* out, Env* env);
private: private:
Type *type_; Type* type_;
Expr *expr_; Expr* expr_;
}; };
#endif // pac_let_h #endif // pac_let_h

View file

@ -1,17 +1,16 @@
#include <unistd.h>
#include <ctype.h> #include <ctype.h>
#include <unistd.h>
#include "config.h"
#include "pac_common.h" #include "pac_common.h"
#include "pac_decl.h" #include "pac_decl.h"
#include "pac_exception.h"
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_parse.h" #include "pac_parse.h"
#include "pac_type.h" #include "pac_type.h"
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_exception.h"
#include "config.h"
extern int yydebug; extern int yydebug;
extern int yyparse(); extern int yyparse();
@ -31,7 +30,7 @@ void add_to_include_directories(string dirs)
unsigned int dir_begin = 0, dir_end; unsigned int dir_begin = 0, dir_end;
while ( dir_begin < dirs.length() ) while ( dir_begin < dirs.length() )
{ {
for ( dir_end = dir_begin; dir_end < dirs.length(); ++dir_end) for ( dir_end = dir_begin; dir_end < dirs.length(); ++dir_end )
if ( dirs[dir_end] == ':' ) if ( dirs[dir_end] == ':' )
break; break;
@ -54,8 +53,7 @@ void pac_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", out->println("// This file is automatically generated from %s.\n", source_filename);
source_filename);
} }
void insert_basictype_defs(Output* out) void insert_basictype_defs(Output* out)
@ -90,7 +88,7 @@ const char* to_id(const char* s)
{ {
static char t[1024]; static char t[1024];
int i; int i;
for ( i = 0; s[i] && i < (int) sizeof(t) - 1; ++i ) for ( i = 0; s[i] && i < (int)sizeof(t) - 1; ++i )
t[i] = isalnum(s[i]) ? s[i] : '_'; t[i] = isalnum(s[i]) ? s[i] : '_';
if ( isdigit(t[0]) ) if ( isdigit(t[0]) )
t[0] = '_'; t[0] = '_';
@ -114,7 +112,7 @@ int compile(const char* filename)
if ( ! FLAGS_output_directory.empty() ) if ( ! FLAGS_output_directory.empty() )
{ {
// Strip leading directories of filename // Strip leading directories of filename
const char *last_slash = strrchr(filename, '/'); const char* last_slash = strrchr(filename, '/');
if ( last_slash ) if ( last_slash )
basename = last_slash + 1; basename = last_slash + 1;
else else
@ -125,8 +123,7 @@ int compile(const char* filename)
basename = filename; basename = filename;
// If the file name ends with ".pac" // If the file name ends with ".pac"
if ( basename.length() > 4 && if ( basename.length() > 4 && basename.substr(basename.length() - 4) == ".pac" )
basename.substr(basename.length() - 4) == ".pac" )
{ {
basename = basename.substr(0, basename.length() - 4); basename = basename.substr(0, basename.length() - 4);
} }
@ -176,8 +173,7 @@ int compile(const char* filename)
} }
catch ( OutputException& e ) catch ( OutputException& e )
{ {
fprintf(stderr, "Error in compiling %s: %s\n", fprintf(stderr, "Error in compiling %s: %s\n", filename, e.errmsg());
filename, e.errmsg());
ret = 1; ret = 1;
} }
catch ( Exception& e ) catch ( Exception& e )
@ -211,21 +207,21 @@ void usage()
// GCC uses __SANITIZE_ADDRESS__, Clang uses __has_feature // GCC uses __SANITIZE_ADDRESS__, Clang uses __has_feature
#if defined(__SANITIZE_ADDRESS__) #if defined(__SANITIZE_ADDRESS__)
#define USING_ASAN #define USING_ASAN
#endif #endif
#if defined(__has_feature) #if defined(__has_feature)
#if __has_feature(address_sanitizer) #if __has_feature(address_sanitizer)
#define USING_ASAN #define USING_ASAN
#endif #endif
#endif #endif
// FreeBSD doesn't support LeakSanitizer // FreeBSD doesn't support LeakSanitizer
#if defined(USING_ASAN) && !defined(__FreeBSD__) #if defined(USING_ASAN) && ! defined(__FreeBSD__)
#include <sanitizer/lsan_interface.h> #include <sanitizer/lsan_interface.h>
#define BINPAC_LSAN_DISABLE(x) __lsan_disable(x) #define BINPAC_LSAN_DISABLE(x) __lsan_disable(x)
#else #else
#define BINPAC_LSAN_DISABLE(x) #define BINPAC_LSAN_DISABLE(x)
#endif #endif
int main(int argc, char* argv[]) int main(int argc, char* argv[])
@ -236,12 +232,12 @@ int main(int argc, char* argv[])
BINPAC_LSAN_DISABLE(); BINPAC_LSAN_DISABLE();
#ifdef HAVE_MALLOC_OPTIONS #ifdef HAVE_MALLOC_OPTIONS
extern char *malloc_options; extern char* malloc_options;
#endif #endif
int o; int o;
while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 ) while ( (o = getopt(argc, argv, "DqI:d:h")) != -1 )
{ {
switch(o) switch ( o )
{ {
case 'D': case 'D':
yydebug = 1; yydebug = 1;
@ -271,10 +267,9 @@ int main(int argc, char* argv[])
} }
// Strip the trailing '/'s // Strip the trailing '/'s
while ( ! FLAGS_output_directory.empty() && while ( ! FLAGS_output_directory.empty() && *(FLAGS_output_directory.end() - 1) == '/' )
*(FLAGS_output_directory.end() - 1) == '/' )
{ {
FLAGS_output_directory.erase(FLAGS_output_directory.end()-1); FLAGS_output_directory.erase(FLAGS_output_directory.end() - 1);
} }
// Add the current directory to FLAGS_include_directories // Add the current directory to FLAGS_include_directories
@ -294,4 +289,3 @@ int main(int argc, char* argv[])
return ret; return ret;
} }

View file

@ -4,18 +4,16 @@
#include "pac_common.h" #include "pac_common.h"
class Number : public Object class Number : public Object
{ {
public: public:
Number(int arg_n) Number(int arg_n) : s(strfmt("%d", arg_n)), n(arg_n) { }
: s(strfmt("%d", arg_n)), n(arg_n) {} Number(const char* arg_s, int arg_n) : s(arg_s), n(arg_n) { }
Number(const char* arg_s, int arg_n) const char* Str() const { return s.c_str(); }
: s(arg_s), n(arg_n) {} int Num() const { return n; }
const char* Str() const { return s.c_str(); }
int Num() const { return n; }
protected: protected:
const string s; const string s;
const int n; const int n;
}; };
#endif // pac_number_h #endif // pac_number_h

View file

@ -1,19 +1,18 @@
#include <string.h> #include "pac_output.h"
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_output.h"
OutputException::OutputException(const char* arg_msg) OutputException::OutputException(const char* arg_msg)
{ {
msg = arg_msg; msg = arg_msg;
} }
OutputException::~OutputException() OutputException::~OutputException() { }
{
}
Output::Output(string filename) Output::Output(string filename)
{ {

View file

@ -1,13 +1,14 @@
#ifndef pac_output_h #ifndef pac_output_h
#define pac_output_h #define pac_output_h
#include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h>
#include <string> #include <string>
using namespace std; using namespace std;
class OutputException { class OutputException
{
public: public:
OutputException(const char* arg_msg); OutputException(const char* arg_msg);
~OutputException(); ~OutputException();
@ -15,9 +16,10 @@ public:
protected: protected:
string msg; string msg;
}; };
class Output { class Output
{
public: public:
Output(string filename); Output(string filename);
~Output(); ~Output();
@ -35,6 +37,6 @@ protected:
FILE* fp; FILE* fp;
int indent_; int indent_;
}; };
#endif /* pac_output_h */ #endif /* pac_output_h */

View file

@ -1,3 +1,5 @@
#include "pac_param.h"
#include "pac_decl.h" #include "pac_decl.h"
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_field.h" #include "pac_field.h"
@ -6,61 +8,51 @@
#include "pac_type.h" #include "pac_type.h"
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_param.h" Param::Param(ID* id, Type* type) : id_(id), type_(type)
Param::Param(ID* id, Type *type)
: id_(id), type_(type)
{ {
if ( ! type_ ) if ( ! type_ )
type_ = extern_type_int->Clone(); type_ = extern_type_int->Clone();
decl_str_ = strfmt("%s %s", decl_str_ = strfmt("%s %s", type_->DataTypeConstRefStr().c_str(), id_->Name());
type_->DataTypeConstRefStr().c_str(),
id_->Name());
param_field_ = new ParamField(this); param_field_ = new ParamField(this);
} }
Param::~Param() Param::~Param() { }
{
}
const string &Param::decl_str() const const string& Param::decl_str() const
{ {
ASSERT(!decl_str_.empty()); ASSERT(! decl_str_.empty());
return decl_str_; return decl_str_;
} }
string ParamDecls(ParamList *params) string ParamDecls(ParamList* params)
{ {
string param_decls; string param_decls;
int first = 1; int first = 1;
foreach (i, ParamList, params) foreach (i, ParamList, params)
{ {
Param* p = *i; Param* p = *i;
const char* decl_str = p->decl_str().c_str(); const char* decl_str = p->decl_str().c_str();
if ( first ) if ( first )
first = 0; first = 0;
else else
param_decls += ", "; param_decls += ", ";
param_decls += decl_str; param_decls += decl_str;
} }
return param_decls; return param_decls;
} }
ParamField::ParamField(const Param *param) ParamField::ParamField(const Param* param)
: Field(PARAM_FIELD, : Field(PARAM_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, param->id(),
TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, param->type())
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;", out_cc->println("%s = %s;", env->LValue(id()), id()->Name());
env->LValue(id()), id()->Name());
env->SetEvaluated(id()); env->SetEvaluated(id());
} }

View file

@ -5,34 +5,34 @@
#include "pac_field.h" #include "pac_field.h"
class Param : public Object class Param : public Object
{ {
public: public:
Param(ID* id, Type* type); Param(ID* id, Type* type);
~Param(); ~Param();
ID *id() const { return id_; } ID* id() const { return id_; }
Type *type() const { return type_; } Type* type() const { return type_; }
const string & decl_str() const; const string& decl_str() const;
Field *param_field() const { return param_field_; } Field* param_field() const { return param_field_; }
private: private:
ID* id_; ID* id_;
Type* type_; Type* type_;
string decl_str_; string decl_str_;
Field *param_field_; Field* param_field_;
}; };
class ParamField : public Field class ParamField : public Field
{ {
public: public:
ParamField(const Param *param); ParamField(const Param* param);
void GenInitCode(Output *out, Env *env); void GenInitCode(Output* out, Env* env);
void GenCleanUpCode(Output* out, Env* env); void GenCleanUpCode(Output* out, Env* env);
}; };
// Returns the string with a list of param declarations separated by ','. // Returns the string with a list of param declarations separated by ','.
string ParamDecls(ParamList *params); string ParamDecls(ParamList* params);
#if 0 #if 0
// Generate assignments to parameters, in the form of "%s_ = %s;" % (id, id). // Generate assignments to parameters, in the form of "%s_ = %s;" % (id, id).
@ -45,4 +45,4 @@ void GenParamPubDecls(ParamList *params, Output *out_h, Env *env);
void GenParamPrivDecls(ParamList *params, Output *out_h, Env *env); void GenParamPrivDecls(ParamList *params, Output *out_h, Env *env);
#endif #endif
#endif // pac_param_h #endif // pac_param_h

View file

@ -1,9 +1,10 @@
#include "pac_paramtype.h"
#include "pac_context.h" #include "pac_context.h"
#include "pac_dataptr.h" #include "pac_dataptr.h"
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_paramtype.h"
#include "pac_typedecl.h" #include "pac_typedecl.h"
ParameterizedType::ParameterizedType(ID* type_id, ExprList* args) ParameterizedType::ParameterizedType(ID* type_id, ExprList* args)
@ -12,13 +13,11 @@ ParameterizedType::ParameterizedType(ID* type_id, ExprList* args)
checking_requires_analyzer_context_ = false; checking_requires_analyzer_context_ = false;
} }
ParameterizedType::~ParameterizedType() ParameterizedType::~ParameterizedType() { }
{
}
string ParameterizedType::EvalMember(const ID *member_id) const string ParameterizedType::EvalMember(const ID* member_id) const
{ {
Type *ty = ReferredDataType(true); Type* ty = ReferredDataType(true);
return strfmt("->%s", ty->env()->RValue(member_id)); return strfmt("->%s", ty->env()->RValue(member_id));
} }
@ -27,12 +26,12 @@ string ParameterizedType::class_name() const
return type_id_->Name(); return type_id_->Name();
} }
Type *ParameterizedType::DoClone() const Type* ParameterizedType::DoClone() const
{ {
return new ParameterizedType(type_id_->clone(), args_); return new ParameterizedType(type_id_->clone(), args_);
} }
void ParameterizedType::AddParamArg(Expr *arg) void ParameterizedType::AddParamArg(Expr* arg)
{ {
args_->push_back(arg); args_->push_back(arg);
} }
@ -47,21 +46,20 @@ string ParameterizedType::DataTypeStr() const
return strfmt("%s *", type_id_->Name()); return strfmt("%s *", type_id_->Name());
} }
Type *ParameterizedType::MemberDataType(const ID *member_id) const Type* ParameterizedType::MemberDataType(const ID* member_id) const
{ {
Type *ref_type = TypeDecl::LookUpType(type_id_); Type* ref_type = TypeDecl::LookUpType(type_id_);
if ( ! ref_type ) if ( ! ref_type )
return 0; return 0;
return ref_type->MemberDataType(member_id); return ref_type->MemberDataType(member_id);
} }
Type *ParameterizedType::ReferredDataType(bool throw_exception) const Type* ParameterizedType::ReferredDataType(bool throw_exception) const
{ {
Type* type = TypeDecl::LookUpType(type_id_); Type* type = TypeDecl::LookUpType(type_id_);
if ( ! type ) if ( ! type )
{ {
DEBUG_MSG("WARNING: cannot find referenced type for %s\n", DEBUG_MSG("WARNING: cannot find referenced type for %s\n", type_id_->Name());
type_id_->Name());
if ( throw_exception ) if ( throw_exception )
throw ExceptionIDNotFound(type_id_); throw ExceptionIDNotFound(type_id_);
} }
@ -75,7 +73,7 @@ int ParameterizedType::StaticSize(Env* env) const
void ParameterizedType::DoMarkIncrementalInput() void ParameterizedType::DoMarkIncrementalInput()
{ {
Type *ty = ReferredDataType(true); Type* ty = ReferredDataType(true);
ty->MarkIncrementalInput(); ty->MarkIncrementalInput();
@ -93,7 +91,7 @@ Type::BufferMode ParameterizedType::buffer_mode() const
// use &length. // use &length.
// //
BufferMode mode = Type::buffer_mode(); BufferMode mode = Type::buffer_mode();
Type *ty = ReferredDataType(true); Type* ty = ReferredDataType(true);
if ( mode != NOT_BUFFERABLE ) if ( mode != NOT_BUFFERABLE )
return mode; return mode;
@ -110,16 +108,16 @@ bool ParameterizedType::ByteOrderSensitive() const
return ReferredDataType(true)->RequiresByteOrder(); return ReferredDataType(true)->RequiresByteOrder();
} }
bool ParameterizedType::DoTraverse(DataDepVisitor *visitor) bool ParameterizedType::DoTraverse(DataDepVisitor* visitor)
{ {
if ( ! Type::DoTraverse(visitor) ) if ( ! Type::DoTraverse(visitor) )
return false; return false;
foreach(i, ExprList, args_) foreach (i, ExprList, args_)
if ( ! (*i)->Traverse(visitor) ) if ( ! (*i)->Traverse(visitor) )
return false; return false;
Type *ty = ReferredDataType(false); Type* ty = ReferredDataType(false);
if ( ty && ! ty->Traverse(visitor) ) if ( ty && ! ty->Traverse(visitor) )
return false; return false;
@ -134,20 +132,19 @@ bool ParameterizedType::RequiresAnalyzerContext()
bool ret = false; bool ret = false;
// If any argument expression refers to analyzer context // If any argument expression refers to analyzer context
foreach(i, ExprList, args_) foreach (i, ExprList, args_)
if ( (*i)->RequiresAnalyzerContext() ) if ( (*i)->RequiresAnalyzerContext() )
{ {
ret = true; ret = true;
break; break;
} }
ret = ret || ret = ret || Type::RequiresAnalyzerContext();
Type::RequiresAnalyzerContext();
if ( ! ret ) if ( ! ret )
{ {
Type *ty = ReferredDataType(false); Type* ty = ReferredDataType(false);
if ( ty ) if ( ty )
ret = ty->RequiresAnalyzerContext(); ret = ty->RequiresAnalyzerContext();
} }
checking_requires_analyzer_context_ = false; checking_requires_analyzer_context_ = false;
@ -163,7 +160,7 @@ void ParameterizedType::GenInitCode(Output* out_cc, Env* env)
void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env) void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env)
{ {
Type *ty = ReferredDataType(false); Type* ty = ReferredDataType(false);
if ( ty && ty->attr_refcount() ) if ( ty && ty->attr_refcount() )
out_cc->println("Unref(%s);", lvalue()); out_cc->println("Unref(%s);", lvalue());
else else
@ -172,7 +169,7 @@ void ParameterizedType::GenCleanUpCode(Output* out_cc, Env* env)
Type::GenCleanUpCode(out_cc, env); Type::GenCleanUpCode(out_cc, env);
} }
string ParameterizedType::EvalParameters(Output* out_cc, Env *env) const string ParameterizedType::EvalParameters(Output* out_cc, Env* env) const
{ {
string arg_str; string arg_str;
@ -190,27 +187,24 @@ string ParameterizedType::EvalParameters(Output* out_cc, Env *env) const
return arg_str; return arg_str;
} }
void ParameterizedType::GenNewInstance(Output *out_cc, Env *env) void ParameterizedType::GenNewInstance(Output* out_cc, Env* env)
{ {
out_cc->println("%s = new %s(%s);", out_cc->println("%s = new %s(%s);", lvalue(), type_id_->Name(),
lvalue(), EvalParameters(out_cc, env).c_str());
type_id_->Name(),
EvalParameters(out_cc, env).c_str());
} }
void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
const DataPtr& data, int flags)
{ {
DEBUG_MSG("DoGenParseCode for %s\n", type_id_->Name()); DEBUG_MSG("DoGenParseCode for %s\n", type_id_->Name());
Type *ref_type = ReferredDataType(true); Type* ref_type = ReferredDataType(true);
const char *parse_func; const char* parse_func;
string parse_params; string parse_params;
if ( buffer_mode() == BUFFER_NOTHING ) if ( buffer_mode() == BUFFER_NOTHING )
{ {
ASSERT(!ref_type->incremental_input()); ASSERT(! ref_type->incremental_input());
parse_func = kParseFuncWithoutBuffer; parse_func = kParseFuncWithoutBuffer;
parse_params = "0, 0"; parse_params = "0, 0";
} }
@ -222,9 +216,7 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env,
else else
{ {
parse_func = kParseFuncWithoutBuffer; parse_func = kParseFuncWithoutBuffer;
parse_params = strfmt("%s, %s", parse_params = strfmt("%s, %s", data.ptr_expr(), env->RValue(end_of_data));
data.ptr_expr(),
env->RValue(end_of_data));
} }
if ( RequiresAnalyzerContext::compute(ref_type) ) if ( RequiresAnalyzerContext::compute(ref_type) )
@ -239,51 +231,43 @@ void ParameterizedType::DoGenParseCode(Output* out_cc, Env* env,
} }
string call_parse_func = strfmt("%s->%s(%s)", string call_parse_func = strfmt("%s->%s(%s)",
lvalue(), // parse() needs an LValue lvalue(), // parse() needs an LValue
parse_func, parse_func, parse_params.c_str());
parse_params.c_str());
if ( incremental_input() ) if ( incremental_input() )
{ {
if ( buffer_mode() == BUFFER_NOTHING ) if ( buffer_mode() == BUFFER_NOTHING )
{ {
out_cc->println("%s;", call_parse_func.c_str()); out_cc->println("%s;", call_parse_func.c_str());
out_cc->println("%s = true;", out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
env->LValue(parsing_complete_var()));
} }
else else
{ {
ASSERT(parsing_complete_var()); ASSERT(parsing_complete_var());
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(parsing_complete_var()),
env->LValue(parsing_complete_var()), call_parse_func.c_str());
call_parse_func.c_str());
// parsing_complete_var might have been already // parsing_complete_var might have been already
// evaluated when set to false // evaluated when set to false
if ( ! env->Evaluated(parsing_complete_var()) ) if ( ! env->Evaluated(parsing_complete_var()) )
env->SetEvaluated(parsing_complete_var()); env->SetEvaluated(parsing_complete_var());
} }
} }
else else
{ {
if ( AddSizeVar(out_cc, env) ) if ( AddSizeVar(out_cc, env) )
{ {
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(size_var()), call_parse_func.c_str());
env->LValue(size_var()),
call_parse_func.c_str());
env->SetEvaluated(size_var()); env->SetEvaluated(size_var());
} }
else else
{ {
out_cc->println("%s;", out_cc->println("%s;", call_parse_func.c_str());
call_parse_func.c_str());
} }
} }
} }
void ParameterizedType::GenDynamicSize(Output* out_cc, Env* env, void ParameterizedType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
const DataPtr& data)
{ {
GenParseCode(out_cc, env, data, 0); GenParseCode(out_cc, env, data, 0);
} }

View file

@ -5,57 +5,57 @@
// An instantiated type: ID + expression list // An instantiated type: ID + expression list
class ParameterizedType : public Type class ParameterizedType : public Type
{ {
public: public:
ParameterizedType(ID *type_id, ExprList *args); ParameterizedType(ID* type_id, ExprList* args);
~ParameterizedType(); ~ParameterizedType();
Type *clone() const; Type* clone() const;
string EvalMember(const ID *member_id) const; string EvalMember(const ID* member_id) const;
// Env *member_env() const; // Env *member_env() const;
void AddParamArg(Expr *arg); void AddParamArg(Expr* arg);
bool DefineValueVar() const; bool DefineValueVar() const;
string DataTypeStr() const; string DataTypeStr() const;
string DefaultValue() const { return "0"; } string DefaultValue() const { return "0"; }
Type *MemberDataType(const ID *member_id) const; Type* MemberDataType(const ID* member_id) const;
// "throw_exception" specifies whether to throw an exception // "throw_exception" specifies whether to throw an exception
// if the referred data type is not found // if the referred data type is not found
Type *ReferredDataType(bool throw_exception) const; Type* ReferredDataType(bool throw_exception) const;
void GenCleanUpCode(Output *out, Env *env); void GenCleanUpCode(Output* out, Env* env);
int StaticSize(Env *env) const; int StaticSize(Env* env) const;
bool IsPointerType() const { return true; } bool IsPointerType() const { return true; }
bool ByteOrderSensitive() const; bool ByteOrderSensitive() const;
bool RequiresAnalyzerContext(); bool RequiresAnalyzerContext();
void GenInitCode(Output *out_cc, Env *env); void GenInitCode(Output* out_cc, Env* env);
string class_name() const; string class_name() const;
string EvalParameters(Output *out_cc, Env *env) const; string EvalParameters(Output* out_cc, Env* env) const;
BufferMode buffer_mode() const; BufferMode buffer_mode() const;
protected: protected:
void GenNewInstance(Output *out, Env *env); void GenNewInstance(Output* out, Env* env);
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
Type *DoClone() const; Type* DoClone() const;
void DoMarkIncrementalInput(); void DoMarkIncrementalInput();
private: private:
ID *type_id_; ID* type_id_;
ExprList *args_; ExprList* args_;
bool checking_requires_analyzer_context_; bool checking_requires_analyzer_context_;
void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags); void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags);
void GenDynamicSize(Output *out, Env *env, const DataPtr& data); void GenDynamicSize(Output* out, Env* env, const DataPtr& data);
}; };
#endif // pac_paramtype_h #endif // pac_paramtype_h

View file

@ -1,36 +1,34 @@
#include "pac_primitive.h"
#include "pac_dbg.h" #include "pac_dbg.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_primitive.h"
#include "pac_type.h" #include "pac_type.h"
string PPVal::ToCode(Env *env) string PPVal::ToCode(Env* env)
{ {
ASSERT(expr_); ASSERT(expr_);
return string(expr_->EvalExpr(0, env)); return string(expr_->EvalExpr(0, env));
} }
string PPSet::ToCode(Env *env) string PPSet::ToCode(Env* env)
{ {
ASSERT(expr_); ASSERT(expr_);
return expr_->SetFunc(0, env); return expr_->SetFunc(0, env);
} }
string PPType::ToCode(Env *env) string PPType::ToCode(Env* env)
{ {
Type *type = expr_->DataType(env); Type* type = expr_->DataType(env);
return type->DataTypeStr(); return type->DataTypeStr();
} }
string PPConstDef::ToCode(Env *env) string PPConstDef::ToCode(Env* env)
{ {
Type *type = expr_->DataType(env); Type* type = expr_->DataType(env);
env->AddID(id_, TEMP_VAR, type); env->AddID(id_, TEMP_VAR, type);
env->SetEvaluated(id_); env->SetEvaluated(id_);
string type_str = type->DataTypeStr(); string type_str = type->DataTypeStr();
return strfmt("%s %s = %s", return strfmt("%s %s = %s", type_str.c_str(), env->LValue(id_), expr_->EvalExpr(0, env));
type_str.c_str(),
env->LValue(id_),
expr_->EvalExpr(0, env));
} }

View file

@ -4,72 +4,75 @@
#include "pac_common.h" #include "pac_common.h"
class PacPrimitive class PacPrimitive
{ {
public: public:
enum PrimitiveType { VAL, SET, TYPE, CONST_DEF }; enum PrimitiveType
{
VAL,
SET,
TYPE,
CONST_DEF
};
explicit PacPrimitive(PrimitiveType type) : type_(type) {} explicit PacPrimitive(PrimitiveType type) : type_(type) { }
virtual ~PacPrimitive() {} virtual ~PacPrimitive() { }
PrimitiveType type() const { return type_; } PrimitiveType type() const { return type_; }
virtual string ToCode(Env *env) = 0; virtual string ToCode(Env* env) = 0;
private: private:
PrimitiveType type_; PrimitiveType type_;
}; };
class PPVal : public PacPrimitive class PPVal : public PacPrimitive
{ {
public: public:
PPVal(Expr *expr) : PacPrimitive(VAL), expr_(expr) {} PPVal(Expr* expr) : PacPrimitive(VAL), expr_(expr) { }
Expr *expr() const { return expr_; } Expr* expr() const { return expr_; }
string ToCode(Env *env); string ToCode(Env* env);
private: private:
Expr *expr_; Expr* expr_;
}; };
class PPSet : public PacPrimitive class PPSet : public PacPrimitive
{ {
public: public:
PPSet(Expr *expr) : PacPrimitive(SET), expr_(expr) {} PPSet(Expr* expr) : PacPrimitive(SET), expr_(expr) { }
Expr *expr() const { return expr_; } Expr* expr() const { return expr_; }
string ToCode(Env *env); string ToCode(Env* env);
private: private:
Expr *expr_; Expr* expr_;
}; };
class PPType : public PacPrimitive class PPType : public PacPrimitive
{ {
public: public:
PPType(Expr *expr) : PacPrimitive(TYPE), expr_(expr) {} PPType(Expr* expr) : PacPrimitive(TYPE), expr_(expr) { }
Expr *expr() const { return expr_; } Expr* expr() const { return expr_; }
string ToCode(Env *env); string ToCode(Env* env);
private: private:
Expr *expr_; Expr* expr_;
}; };
class PPConstDef : public PacPrimitive class PPConstDef : public PacPrimitive
{ {
public: public:
PPConstDef(const ID *id, Expr *expr) PPConstDef(const ID* id, Expr* expr) : PacPrimitive(CONST_DEF), id_(id), expr_(expr) { }
: PacPrimitive(CONST_DEF), const ID* id() const { return id_; }
id_(id), Expr* expr() const { return expr_; }
expr_(expr) {}
const ID *id() const { return id_; }
Expr *expr() const { return expr_; }
string ToCode(Env *env); string ToCode(Env* env);
private: private:
const ID *id_; const ID* id_;
Expr *expr_; Expr* expr_;
}; };
#endif // pac_primitive_h #endif // pac_primitive_h

View file

@ -1,3 +1,5 @@
#include "pac_record.h"
#include "pac_attr.h" #include "pac_attr.h"
#include "pac_dataptr.h" #include "pac_dataptr.h"
#include "pac_exception.h" #include "pac_exception.h"
@ -5,15 +7,12 @@
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_field.h" #include "pac_field.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_record.h"
#include "pac_type.h" #include "pac_type.h"
#include "pac_typedecl.h" #include "pac_typedecl.h"
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_varfield.h" #include "pac_varfield.h"
RecordType::RecordType(RecordFieldList* record_fields) : Type(RECORD)
RecordType::RecordType(RecordFieldList* record_fields)
: Type(RECORD)
{ {
// Here we assume that the type is a standalone type. // Here we assume that the type is a standalone type.
value_var_ = 0; value_var_ = 0;
@ -36,10 +35,9 @@ RecordType::~RecordType()
delete parsing_dataptr_var_field_; delete parsing_dataptr_var_field_;
} }
const ID *RecordType::parsing_dataptr_var() const const ID* RecordType::parsing_dataptr_var() const
{ {
return parsing_dataptr_var_field_ ? return parsing_dataptr_var_field_ ? parsing_dataptr_var_field_->id() : 0;
parsing_dataptr_var_field_->id() : 0;
} }
bool RecordType::DefineValueVar() const bool RecordType::DefineValueVar() const
@ -57,12 +55,12 @@ void RecordType::Prepare(Env* env, int flags)
{ {
ASSERT(flags & TO_BE_PARSED); ASSERT(flags & TO_BE_PARSED);
RecordField *prev = 0; RecordField* prev = 0;
int offset = 0; int offset = 0;
int seq = 0; int seq = 0;
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_)
{ {
RecordField *f = *i; RecordField* f = *i;
f->set_record_type(this); f->set_record_type(this);
f->set_prev(prev); f->set_prev(prev);
if ( prev ) if ( prev )
@ -120,71 +118,62 @@ void RecordType::GenCleanUpCode(Output* out_cc, Env* env)
Type::GenCleanUpCode(out_cc, env); Type::GenCleanUpCode(out_cc, env);
} }
void RecordType::DoGenParseCode(Output* out_cc, Env* env, void RecordType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
const DataPtr& data, int flags)
{ {
if ( !incremental_input() && StaticSize(env) >= 0 ) if ( ! incremental_input() && StaticSize(env) >= 0 )
GenBoundaryCheck(out_cc, env, data); GenBoundaryCheck(out_cc, env, data);
if ( incremental_parsing() ) if ( incremental_parsing() )
{ {
out_cc->println("switch ( %s ) {", out_cc->println("switch ( %s ) {", env->LValue(parsing_state_id));
env->LValue(parsing_state_id));
out_cc->println("case 0:"); out_cc->println("case 0:");
out_cc->inc_indent(); out_cc->inc_indent();
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_)
{ {
RecordField *f = *i; RecordField* f = *i;
f->GenParseCode(out_cc, env); f->GenParseCode(out_cc, env);
out_cc->println(""); out_cc->println("");
} }
out_cc->println(""); out_cc->println("");
out_cc->println("%s = true;", out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
env->LValue(parsing_complete_var()));
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("}"); out_cc->println("}");
} }
else else
{ {
ASSERT( data.id() == begin_of_data && ASSERT(data.id() == begin_of_data && data.offset() == 0);
data.offset() == 0 );
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_)
{ {
RecordField *f = *i; RecordField* f = *i;
f->GenParseCode(out_cc, env); f->GenParseCode(out_cc, env);
out_cc->println(""); out_cc->println("");
} }
if ( incremental_input() ) if ( incremental_input() )
{ {
ASSERT(parsing_complete_var()); ASSERT(parsing_complete_var());
out_cc->println("%s = true;", out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
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 = const DataPtr& end_of_record_dataptr = record_fields_->back()->getFieldEnd(out_cc, env);
record_fields_->back()->getFieldEnd(out_cc, env);
out_cc->println("%s = %s - %s;", out_cc->println("%s = %s - %s;", env->LValue(size_var()), end_of_record_dataptr.ptr_expr(),
env->LValue(size_var()), env->RValue(begin_of_data));
end_of_record_dataptr.ptr_expr(),
env->RValue(begin_of_data));
env->SetEvaluated(size_var()); env->SetEvaluated(size_var());
} }
if ( ! boundary_checked() ) if ( ! boundary_checked() )
{ {
RecordField *last_field = record_fields_->back(); RecordField* last_field = record_fields_->back();
if ( ! last_field->BoundaryChecked() ) if ( ! last_field->BoundaryChecked() )
GenBoundaryCheck(out_cc, env, data); GenBoundaryCheck(out_cc, env, data);
} }
} }
void RecordType::GenDynamicSize(Output* out_cc, Env* env, void RecordType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
const DataPtr& data)
{ {
GenParseCode(out_cc, env, data, 0); GenParseCode(out_cc, env, data, 0);
} }
@ -194,7 +183,7 @@ int RecordType::StaticSize(Env* env) const
int tot_w = 0; int tot_w = 0;
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_)
{ {
RecordField *f = *i; RecordField* f = *i;
int w = f->StaticSize(env, tot_w); int w = f->StaticSize(env, tot_w);
if ( w < 0 ) if ( w < 0 )
return -1; return -1;
@ -215,7 +204,7 @@ void RecordType::SetBoundaryChecked()
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_)
{ {
RecordField *f = *i; RecordField* f = *i;
f->SetBoundaryChecked(); f->SetBoundaryChecked();
} }
} }
@ -224,12 +213,12 @@ void RecordType::DoMarkIncrementalInput()
{ {
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_)
{ {
RecordField *f = *i; RecordField* f = *i;
f->type()->MarkIncrementalInput(); f->type()->MarkIncrementalInput();
} }
} }
bool RecordType::DoTraverse(DataDepVisitor *visitor) bool RecordType::DoTraverse(DataDepVisitor* visitor)
{ {
return Type::DoTraverse(visitor); return Type::DoTraverse(visitor);
} }
@ -238,17 +227,15 @@ bool RecordType::ByteOrderSensitive() const
{ {
foreach (i, RecordFieldList, record_fields_) foreach (i, RecordFieldList, record_fields_)
{ {
RecordField *f = *i; RecordField* f = *i;
if ( f->RequiresByteOrder() ) if ( f->RequiresByteOrder() )
return true; return true;
} }
return false; return false;
} }
RecordField::RecordField(FieldType tof, ID *id, Type *type) RecordField::RecordField(FieldType tof, ID* id, Type* type)
: Field(tof, : Field(tof, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type)
TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE,
id, type)
{ {
begin_of_field_dataptr = 0; begin_of_field_dataptr = 0;
end_of_field_dataptr = 0; end_of_field_dataptr = 0;
@ -267,8 +254,8 @@ RecordField::~RecordField()
{ {
delete begin_of_field_dataptr; delete begin_of_field_dataptr;
delete end_of_field_dataptr; delete end_of_field_dataptr;
delete [] field_size_expr; delete[] field_size_expr;
delete [] field_offset_expr; delete[] field_offset_expr;
delete end_of_field_dataptr_var; delete end_of_field_dataptr_var;
} }
@ -281,8 +268,7 @@ const DataPtr& RecordField::getFieldBegin(Output* out_cc, Env* env)
// The first field // The first field
if ( ! begin_of_field_dataptr ) if ( ! begin_of_field_dataptr )
{ {
begin_of_field_dataptr = begin_of_field_dataptr = new DataPtr(env, begin_of_data, 0);
new DataPtr(env, begin_of_data, 0);
} }
return *begin_of_field_dataptr; return *begin_of_field_dataptr;
} }
@ -300,12 +286,10 @@ const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env)
ASSERT(0); ASSERT(0);
if ( ! end_of_field_dataptr ) if ( ! end_of_field_dataptr )
{ {
const ID *dataptr_var = const ID* dataptr_var = record_type()->parsing_dataptr_var();
record_type()->parsing_dataptr_var();
ASSERT(dataptr_var); ASSERT(dataptr_var);
end_of_field_dataptr = end_of_field_dataptr = new DataPtr(env, dataptr_var, 0);
new DataPtr(env, dataptr_var, 0);
} }
} }
else else
@ -314,31 +298,23 @@ const DataPtr& RecordField::getFieldEnd(Output* out_cc, Env* env)
if ( begin_ptr.id() == begin_of_data ) if ( begin_ptr.id() == begin_of_data )
field_offset = begin_ptr.offset(); field_offset = begin_ptr.offset();
else else
field_offset = -1; // unknown field_offset = -1; // unknown
int field_size = StaticSize(env, field_offset); int field_size = StaticSize(env, field_offset);
if ( field_size >= 0 ) // can be statically determinted if ( field_size >= 0 ) // can be statically determinted
{ {
end_of_field_dataptr = new DataPtr( end_of_field_dataptr = new DataPtr(env, begin_ptr.id(),
env, begin_ptr.offset() + field_size);
begin_ptr.id(),
begin_ptr.offset() + field_size);
} }
else else
{ {
// If not, we add a variable for the offset after the field // If not, we add a variable for the offset after the field
end_of_field_dataptr_var = new ID( end_of_field_dataptr_var = new ID(strfmt("dataptr_after_%s", id()->Name()));
strfmt("dataptr_after_%s", id()->Name())); env->AddID(end_of_field_dataptr_var, TEMP_VAR, extern_type_const_byteptr);
env->AddID(end_of_field_dataptr_var,
TEMP_VAR,
extern_type_const_byteptr);
GenFieldEnd(out_cc, env, begin_ptr); GenFieldEnd(out_cc, env, begin_ptr);
end_of_field_dataptr = new DataPtr( end_of_field_dataptr = new DataPtr(env, end_of_field_dataptr_var, 0);
env,
end_of_field_dataptr_var,
0);
} }
} }
@ -368,8 +344,7 @@ const char* RecordField::FieldOffset(Output* out_cc, Env* env)
if ( begin.id() == begin_of_data ) if ( begin.id() == begin_of_data )
field_offset_expr = nfmt("%d", begin.offset()); field_offset_expr = nfmt("%d", begin.offset());
else else
field_offset_expr = nfmt("(%s - %s)", field_offset_expr = nfmt("(%s - %s)", begin.ptr_expr(), env->RValue(begin_of_data));
begin.ptr_expr(), env->RValue(begin_of_data));
return field_offset_expr; return field_offset_expr;
} }
@ -400,15 +375,12 @@ bool RecordField::AttemptBoundaryCheck(Output* out_cc, Env* env)
return GenBoundaryCheck(out_cc, env); return GenBoundaryCheck(out_cc, env);
} }
RecordDataField::RecordDataField(ID* id, Type* type) RecordDataField::RecordDataField(ID* id, Type* type) : RecordField(RECORD_FIELD, id, type)
: RecordField(RECORD_FIELD, id, type)
{ {
ASSERT(type_); ASSERT(type_);
} }
RecordDataField::~RecordDataField() RecordDataField::~RecordDataField() { }
{
}
void RecordDataField::Prepare(Env* env) void RecordDataField::Prepare(Env* env)
{ {
@ -435,8 +407,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
Expr* len_expr = record_type()->attr_length_expr(); Expr* len_expr = record_type()->attr_length_expr();
int len; int len;
if ( ! record_type()->buffer_input() || if ( ! record_type()->buffer_input() || (len_expr && len_expr->ConstFold(env, &len)) )
(len_expr && len_expr->ConstFold(env, &len)) )
AttemptBoundaryCheck(out_cc, env); AttemptBoundaryCheck(out_cc, env);
} }
@ -449,9 +420,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
if ( type_->incremental_input() ) if ( type_->incremental_input() )
{ {
// The enclosing record type must be incrementally parsed // The enclosing record type must be incrementally parsed
out_cc->println("%s = %d;", out_cc->println("%s = %d;", env->LValue(parsing_state_id), parsing_state_seq());
env->LValue(parsing_state_id),
parsing_state_seq());
out_cc->println("/* fall through */"); out_cc->println("/* fall through */");
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("case %d:", parsing_state_seq()); out_cc->println("case %d:", parsing_state_seq());
@ -465,8 +434,7 @@ void RecordDataField::GenParseCode(Output* out_cc, Env* env)
{ {
ASSERT(type_->incremental_input()); ASSERT(type_->incremental_input());
out_cc->println("if ( ! (%s) )", out_cc->println("if ( ! (%s) )", type_->parsing_complete(env).c_str());
type_->parsing_complete(env).c_str());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("goto %s;", kNeedMoreData); out_cc->println("goto %s;", kNeedMoreData);
out_cc->dec_indent(); out_cc->dec_indent();
@ -493,18 +461,14 @@ void RecordDataField::GenEval(Output* out_cc, Env* env)
GenParseCode(out_cc, env); GenParseCode(out_cc, env);
} }
void RecordDataField::GenFieldEnd(Output* out_cc, Env* env, void RecordDataField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& field_begin)
const DataPtr& field_begin)
{ {
out_cc->println("const_byteptr const %s = %s + (%s);", out_cc->println("const_byteptr const %s = %s + (%s);", env->LValue(end_of_field_dataptr_var),
env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(), type_->DataSize(out_cc, env, field_begin).c_str());
field_begin.ptr_expr(),
type_->DataSize(out_cc, env, field_begin).c_str());
env->SetEvaluated(end_of_field_dataptr_var); env->SetEvaluated(end_of_field_dataptr_var);
out_cc->println("BINPAC_ASSERT(%s <= %s);", out_cc->println("BINPAC_ASSERT(%s <= %s);", env->RValue(end_of_field_dataptr_var),
env->RValue(end_of_field_dataptr_var), env->RValue(end_of_data));
env->RValue(end_of_data));
} }
void RecordDataField::SetBoundaryChecked() void RecordDataField::SetBoundaryChecked()
@ -524,15 +488,14 @@ bool RecordDataField::GenBoundaryCheck(Output* out_cc, Env* env)
return true; return true;
} }
bool RecordDataField::DoTraverse(DataDepVisitor *visitor) bool RecordDataField::DoTraverse(DataDepVisitor* visitor)
{ {
return Field::DoTraverse(visitor); return Field::DoTraverse(visitor);
} }
bool RecordDataField::RequiresAnalyzerContext() const bool RecordDataField::RequiresAnalyzerContext() const
{ {
return Field::RequiresAnalyzerContext() || return Field::RequiresAnalyzerContext() || type()->RequiresAnalyzerContext();
type()->RequiresAnalyzerContext();
} }
RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr) RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr)
@ -541,9 +504,7 @@ RecordPaddingField::RecordPaddingField(ID* id, PaddingType ptype, Expr* expr)
wordsize_ = -1; wordsize_ = -1;
} }
RecordPaddingField::~RecordPaddingField() RecordPaddingField::~RecordPaddingField() { }
{
}
void RecordPaddingField::Prepare(Env* env) void RecordPaddingField::Prepare(Env* env)
{ {
@ -551,8 +512,7 @@ void RecordPaddingField::Prepare(Env* env)
if ( ptype_ == PAD_TO_NEXT_WORD ) if ( ptype_ == PAD_TO_NEXT_WORD )
{ {
if ( ! expr_->ConstFold(env, &wordsize_) ) if ( ! expr_->ConstFold(env, &wordsize_) )
throw ExceptionPaddingError(this, throw ExceptionPaddingError(this, strfmt("padding word size not a constant"));
strfmt("padding word size not a constant"));
} }
} }
@ -589,11 +549,9 @@ int RecordPaddingField::StaticSize(Env* env, int offset) const
// can be statically computed, we can get its // can be statically computed, we can get its
// static size // static size
if ( offset > target_offset ) if ( offset > target_offset )
throw ExceptionPaddingError( throw ExceptionPaddingError(this, strfmt("current offset = %d, "
this, "target offset = %d",
strfmt("current offset = %d, " offset, target_offset));
"target offset = %d",
offset, target_offset));
return target_offset - offset; return target_offset - offset;
case PAD_TO_NEXT_WORD: case PAD_TO_NEXT_WORD:
@ -601,8 +559,7 @@ int RecordPaddingField::StaticSize(Env* env, int offset) const
return -1; return -1;
offset_in_word = offset % wordsize_; offset_in_word = offset % wordsize_;
return ( offset_in_word == 0 ) ? return (offset_in_word == 0) ? 0 : wordsize_ - offset_in_word;
0 : wordsize_ - offset_in_word;
} }
return -1; return -1;
@ -620,86 +577,67 @@ void RecordPaddingField::GenFieldEnd(Output* out_cc, Env* env, const DataPtr& fi
expr_->EvalExpr(out_cc, env)); expr_->EvalExpr(out_cc, env));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(),
Location(), expr_->EvalExpr(out_cc, env)); expr_->EvalExpr(out_cc, env));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println(""); out_cc->println("");
out_cc->println("const_byteptr const %s = %s + (%s);", out_cc->println("const_byteptr const %s = %s + (%s);",
env->LValue(end_of_field_dataptr_var), env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(),
field_begin.ptr_expr(), expr_->EvalExpr(out_cc, env));
expr_->EvalExpr(out_cc, env));
out_cc->println("// Checking out-of-bound padding for \"%s\"", field_id_str_.c_str()); out_cc->println("// Checking out-of-bound padding for \"%s\"", field_id_str_.c_str());
out_cc->println("if ( %s > %s || %s < %s )", out_cc->println("if ( %s > %s || %s < %s )", env->LValue(end_of_field_dataptr_var),
env->LValue(end_of_field_dataptr_var), env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var),
env->RValue(end_of_data),
env->LValue(end_of_field_dataptr_var),
field_begin.ptr_expr()); field_begin.ptr_expr());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str());
out_cc->println(" (%s), ", out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env));
expr_->EvalExpr(out_cc, env)); out_cc->println(" (%s) - (%s));", env->RValue(end_of_data),
out_cc->println(" (%s) - (%s));", env->LValue(end_of_field_dataptr_var));
env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println(""); out_cc->println("");
break; break;
case PAD_TO_OFFSET: case PAD_TO_OFFSET:
out_cc->println("const_byteptr %s = %s + (%s);", out_cc->println("const_byteptr %s = %s + (%s);", env->LValue(end_of_field_dataptr_var),
env->LValue(end_of_field_dataptr_var), env->RValue(begin_of_data), expr_->EvalExpr(out_cc, env));
env->RValue(begin_of_data), out_cc->println("if ( %s < %s )", env->LValue(end_of_field_dataptr_var),
expr_->EvalExpr(out_cc, env)); 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->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);", out_cc->println("// throw binpac::ExceptionInvalidOffset(\"%s\", %s - %s, %s);",
id_->LocName(), id_->LocName(), field_begin.ptr_expr(), env->RValue(begin_of_data),
field_begin.ptr_expr(), expr_->EvalExpr(out_cc, env));
env->RValue(begin_of_data), out_cc->println("%s = %s;", env->LValue(end_of_field_dataptr_var),
expr_->EvalExpr(out_cc, env)); field_begin.ptr_expr());
out_cc->println("%s = %s;",
env->LValue(end_of_field_dataptr_var),
field_begin.ptr_expr());
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("if ( %s > %s )", out_cc->println("if ( %s > %s )", env->LValue(end_of_field_dataptr_var),
env->LValue(end_of_field_dataptr_var), env->RValue(end_of_data));
env->RValue(end_of_data));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str()); out_cc->println("throw binpac::ExceptionOutOfBound(\"%s\",", field_id_str_.c_str());
out_cc->println(" (%s), ", out_cc->println(" (%s), ", expr_->EvalExpr(out_cc, env));
expr_->EvalExpr(out_cc, env)); out_cc->println(" (%s) - (%s));", env->RValue(end_of_data),
out_cc->println(" (%s) - (%s));", env->LValue(end_of_field_dataptr_var));
env->RValue(end_of_data), env->LValue(end_of_field_dataptr_var));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
break; break;
case PAD_TO_NEXT_WORD: case PAD_TO_NEXT_WORD:
padding_var = nfmt("%s__size", id()->Name()); padding_var = nfmt("%s__size", id()->Name());
out_cc->println("int %s = (%s - %s) %% %d;", out_cc->println("int %s = (%s - %s) %% %d;", padding_var, field_begin.ptr_expr(),
padding_var, env->RValue(begin_of_data), wordsize_);
field_begin.ptr_expr(), out_cc->println("%s = (%s == 0) ? 0 : %d - %s;", padding_var, padding_var, wordsize_,
env->RValue(begin_of_data), padding_var);
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;", out_cc->println("const_byteptr const %s = %s + %s;",
env->LValue(end_of_field_dataptr_var), env->LValue(end_of_field_dataptr_var), field_begin.ptr_expr(),
field_begin.ptr_expr(), padding_var);
padding_var); delete[] padding_var;
delete [] padding_var;
break; break;
} }
@ -715,20 +653,18 @@ bool RecordPaddingField::GenBoundaryCheck(Output* out_cc, Env* env)
char* size; char* size;
int ss = StaticSize(env, begin.AbsOffset(begin_of_data)); int ss = StaticSize(env, begin.AbsOffset(begin_of_data));
ASSERT ( ss >= 0 ); ASSERT(ss >= 0);
size = nfmt("%d", ss); size = nfmt("%d", ss);
begin.GenBoundaryCheck(out_cc, env, size, field_id_str_.c_str()); begin.GenBoundaryCheck(out_cc, env, size, field_id_str_.c_str());
delete [] size; delete[] size;
SetBoundaryChecked(); SetBoundaryChecked();
return true; return true;
} }
bool RecordPaddingField::DoTraverse(DataDepVisitor *visitor) bool RecordPaddingField::DoTraverse(DataDepVisitor* visitor)
{ {
return Field::DoTraverse(visitor) && return Field::DoTraverse(visitor) && (! expr_ || expr_->Traverse(visitor));
(! expr_ || expr_->Traverse(visitor));
} }

View file

@ -8,7 +8,7 @@
#include "pac_type.h" #include "pac_type.h"
class RecordType : public Type class RecordType : public Type
{ {
public: public:
RecordType(RecordFieldList* fields); RecordType(RecordFieldList* fields);
~RecordType(); ~RecordType();
@ -28,58 +28,62 @@ public:
void SetBoundaryChecked(); void SetBoundaryChecked();
const ID *parsing_dataptr_var() const; const ID* parsing_dataptr_var() const;
bool IsPointerType() const { ASSERT(0); return false; } bool IsPointerType() const
{
ASSERT(0);
return false;
}
protected: protected:
void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags);
void GenDynamicSize(Output* out, Env* env, const DataPtr& data); void GenDynamicSize(Output* out, Env* env, const DataPtr& data);
Type *DoClone() const { return 0; } Type* DoClone() const { return 0; }
void DoMarkIncrementalInput(); void DoMarkIncrementalInput();
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
bool ByteOrderSensitive() const; bool ByteOrderSensitive() const;
private: private:
Field *parsing_dataptr_var_field_; Field* parsing_dataptr_var_field_;
RecordFieldList* record_fields_; RecordFieldList* record_fields_;
}; };
// A data field of a record type. A RecordField corresponds to a // A data field of a record type. A RecordField corresponds to a
// segment of input data, and therefore RecordField's are ordered---each // segment of input data, and therefore RecordField's are ordered---each
// of them has a known previous and next field. // of them has a known previous and next field.
class RecordField : public Field class RecordField : public Field
{ {
public: public:
RecordField(FieldType tof, ID* id, Type *type); RecordField(FieldType tof, ID* id, Type* type);
~RecordField(); ~RecordField();
RecordType *record_type() const { return record_type_; } RecordType* record_type() const { return record_type_; }
void set_record_type(RecordType* ty) { record_type_ = ty; } void set_record_type(RecordType* ty) { record_type_ = ty; }
virtual void GenParseCode(Output* out, Env* env) = 0; virtual void GenParseCode(Output* out, Env* env) = 0;
RecordField* prev() const { return prev_; } RecordField* prev() const { return prev_; }
RecordField* next() const { return next_; } RecordField* next() const { return next_; }
void set_prev(RecordField* f) { prev_ = f; } void set_prev(RecordField* f) { prev_ = f; }
void set_next(RecordField* f) { next_ = f; } void set_next(RecordField* f) { next_ = f; }
int static_offset() const { return static_offset_; } int static_offset() const { return static_offset_; }
void set_static_offset(int offset) { static_offset_ = offset; } void set_static_offset(int offset) { static_offset_ = offset; }
int parsing_state_seq() const { return parsing_state_seq_; } int parsing_state_seq() const { return parsing_state_seq_; }
void set_parsing_state_seq(int x) { parsing_state_seq_ = x; } void set_parsing_state_seq(int x) { parsing_state_seq_ = x; }
virtual int StaticSize(Env* env, int offset) const = 0; virtual int StaticSize(Env* env, int offset) const = 0;
const char* FieldSize(Output* out, Env* env); const char* FieldSize(Output* out, Env* env);
const char* FieldOffset(Output* out, Env* env); const char* FieldOffset(Output* out, Env* env);
virtual bool BoundaryChecked() const { return boundary_checked_; } virtual bool BoundaryChecked() const { return boundary_checked_; }
virtual void SetBoundaryChecked() { boundary_checked_ = true; } virtual void SetBoundaryChecked() { boundary_checked_ = true; }
virtual bool RequiresByteOrder() const = 0; virtual bool RequiresByteOrder() const = 0;
@ -105,10 +109,10 @@ protected:
bool AttemptBoundaryCheck(Output* out_cc, Env* env); bool AttemptBoundaryCheck(Output* out_cc, Env* env);
virtual bool GenBoundaryCheck(Output* out_cc, Env* env) = 0; virtual bool GenBoundaryCheck(Output* out_cc, Env* env) = 0;
}; };
class RecordDataField : public RecordField, public Evaluatable class RecordDataField : public RecordField, public Evaluatable
{ {
public: public:
RecordDataField(ID* arg_id, Type* arg_type); RecordDataField(ID* arg_id, Type* arg_type);
~RecordDataField(); ~RecordDataField();
@ -120,50 +124,62 @@ public:
// Instantiates abstract class Evaluatable // Instantiates abstract class Evaluatable
void GenEval(Output* out, Env* env); void GenEval(Output* out, Env* env);
int StaticSize(Env* env, int) const { return type()->StaticSize(env); } int StaticSize(Env* env, int) const { return type()->StaticSize(env); }
void SetBoundaryChecked(); void SetBoundaryChecked();
bool RequiresByteOrder() const bool RequiresByteOrder() const { return type()->RequiresByteOrder(); }
{ return type()->RequiresByteOrder(); }
bool RequiresAnalyzerContext() const; bool RequiresAnalyzerContext() const;
protected: protected:
void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); void GenFieldEnd(Output* out, Env* env, const DataPtr& begin);
bool GenBoundaryCheck(Output* out_cc, Env* env); bool GenBoundaryCheck(Output* out_cc, Env* env);
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
}; };
enum PaddingType { PAD_BY_LENGTH, PAD_TO_OFFSET, PAD_TO_NEXT_WORD }; enum PaddingType
{
PAD_BY_LENGTH,
PAD_TO_OFFSET,
PAD_TO_NEXT_WORD
};
class RecordPaddingField : public RecordField class RecordPaddingField : public RecordField
{ {
public: public:
RecordPaddingField(ID* id, PaddingType ptype, Expr* expr); RecordPaddingField(ID* id, PaddingType ptype, Expr* expr);
~RecordPaddingField(); ~RecordPaddingField();
void Prepare(Env* env); void Prepare(Env* env);
void GenPubDecls(Output* out, Env* env) { /* nothing */ } void GenPubDecls(Output* out, Env* env)
void GenPrivDecls(Output* out, Env* env) { /* nothing */ } { /* nothing */
}
void GenPrivDecls(Output* out, Env* env)
{ /* nothing */
}
void GenInitCode(Output* out, Env* env) { /* nothing */ } void GenInitCode(Output* out, Env* env)
void GenCleanUpCode(Output* out, Env* env) { /* nothing */ } { /* nothing */
}
void GenCleanUpCode(Output* out, Env* env)
{ /* nothing */
}
void GenParseCode(Output* out, Env* env); void GenParseCode(Output* out, Env* env);
int StaticSize(Env* env, int offset) const; int StaticSize(Env* env, int offset) const;
bool RequiresByteOrder() const { return false; } bool RequiresByteOrder() const { return false; }
protected: protected:
void GenFieldEnd(Output* out, Env* env, const DataPtr& begin); void GenFieldEnd(Output* out, Env* env, const DataPtr& begin);
bool GenBoundaryCheck(Output* out_cc, Env* env); bool GenBoundaryCheck(Output* out_cc, Env* env);
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
private: private:
PaddingType ptype_; PaddingType ptype_;
Expr* expr_; Expr* expr_;
int wordsize_; int wordsize_;
}; };
#endif // pac_record_h #endif // pac_record_h

View file

@ -1,151 +1,133 @@
#include "pac_redef.h"
#include "pac_analyzer.h" #include "pac_analyzer.h"
#include "pac_case.h" #include "pac_case.h"
#include "pac_exception.h" #include "pac_exception.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_func.h" #include "pac_func.h"
#include "pac_record.h" #include "pac_record.h"
#include "pac_redef.h"
#include "pac_type.h" #include "pac_type.h"
#include "pac_typedecl.h" #include "pac_typedecl.h"
namespace { namespace
Decl *find_decl(const ID *id)
{ {
Decl *decl = Decl::LookUpDecl(id);
Decl* find_decl(const ID* id)
{
Decl* decl = Decl::LookUpDecl(id);
if ( ! decl ) if ( ! decl )
{ {
throw Exception(id, throw Exception(id, strfmt("cannot find declaration for %s", id->Name()));
strfmt("cannot find declaration for %s",
id->Name()));
} }
return decl; return decl;
} }
} }
Decl *ProcessTypeRedef(const ID *id, FieldList *fieldlist) Decl* ProcessTypeRedef(const ID* id, FieldList* fieldlist)
{ {
Decl *decl = find_decl(id); Decl* decl = find_decl(id);
if ( decl->decl_type() != Decl::TYPE ) if ( decl->decl_type() != Decl::TYPE )
{ {
throw Exception(id, throw Exception(id, strfmt("not a type declaration: %s", id->Name()));
strfmt("not a type declaration: %s",
id->Name()));
} }
TypeDecl *type_decl = static_cast<TypeDecl *>(decl); TypeDecl* type_decl = static_cast<TypeDecl*>(decl);
ASSERT(type_decl); ASSERT(type_decl);
Type *type = type_decl->type(); Type* type = type_decl->type();
foreach(i, FieldList, fieldlist) foreach (i, FieldList, fieldlist)
{ {
Field *f = *i; Field* f = *i;
// One cannot change data layout in 'redef'. // One cannot change data layout in 'redef'.
// Only 'let' or 'action' can be added // Only 'let' or 'action' can be added
if ( f->tof() == LET_FIELD || if ( f->tof() == LET_FIELD || f->tof() == WITHINPUT_FIELD )
f->tof() == WITHINPUT_FIELD )
{ {
type->AddField(f); type->AddField(f);
} }
else if ( f->tof() == RECORD_FIELD || else if ( f->tof() == RECORD_FIELD || f->tof() == PADDING_FIELD )
f->tof() == PADDING_FIELD )
{ {
throw Exception(f, throw Exception(f, "cannot change data layout in redef");
"cannot change data layout in redef");
} }
else if ( f->tof() == CASE_FIELD ) else if ( f->tof() == CASE_FIELD )
{ {
throw Exception(f, throw Exception(f, "use 'redef case' adding cases");
"use 'redef case' adding cases");
} }
} }
return decl; return decl;
} }
Decl *ProcessCaseTypeRedef(const ID *id, CaseFieldList *casefieldlist) Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist)
{ {
Decl *decl = find_decl(id); Decl* decl = find_decl(id);
if ( decl->decl_type() != Decl::TYPE ) if ( decl->decl_type() != Decl::TYPE )
{ {
throw Exception(id, throw Exception(id, strfmt("not a type declaration: %s", id->Name()));
strfmt("not a type declaration: %s",
id->Name()));
} }
TypeDecl *type_decl = static_cast<TypeDecl *>(decl); TypeDecl* type_decl = static_cast<TypeDecl*>(decl);
ASSERT(type_decl); ASSERT(type_decl);
Type *type = type_decl->type(); Type* type = type_decl->type();
if ( type->tot() != Type::CASE ) if ( type->tot() != Type::CASE )
{ {
throw Exception(id, throw Exception(id, strfmt("not a case type: %s", id->Name()));
strfmt("not a case type: %s",
id->Name()));
} }
CaseType *casetype = static_cast<CaseType*>(type); CaseType* casetype = static_cast<CaseType*>(type);
ASSERT(casetype); ASSERT(casetype);
foreach(i, CaseFieldList, casefieldlist) foreach (i, CaseFieldList, casefieldlist)
{ {
CaseField *f = *i; CaseField* f = *i;
casetype->AddCaseField(f); casetype->AddCaseField(f);
} }
return decl; return decl;
} }
Decl *ProcessCaseExprRedef(const ID *id, CaseExprList *caseexprlist) Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist)
{ {
Decl *decl = find_decl(id); Decl* decl = find_decl(id);
if ( decl->decl_type() != Decl::FUNC ) if ( decl->decl_type() != Decl::FUNC )
{ {
throw Exception(id, throw Exception(id, strfmt("not a function declaration: %s", id->Name()));
strfmt("not a function declaration: %s",
id->Name()));
} }
FuncDecl *func_decl = static_cast<FuncDecl *>(decl); FuncDecl* func_decl = static_cast<FuncDecl*>(decl);
ASSERT(func_decl); ASSERT(func_decl);
Expr *expr = func_decl->function()->expr(); Expr* expr = func_decl->function()->expr();
if ( ! expr ||expr->expr_type() != Expr::EXPR_CASE ) if ( ! expr || expr->expr_type() != Expr::EXPR_CASE )
{ {
throw Exception(id, throw Exception(id, strfmt("function not defined by a case expression: %s", id->Name()));
strfmt("function not defined by a case expression: %s",
id->Name()));
} }
foreach(i, CaseExprList, caseexprlist) foreach (i, CaseExprList, caseexprlist)
{ {
CaseExpr *e = *i; CaseExpr* e = *i;
expr->AddCaseExpr(e); expr->AddCaseExpr(e);
} }
return decl; return decl;
} }
Decl *ProcessAnalyzerRedef(const ID *id, Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerElementList* elements)
Decl::DeclType decl_type,
AnalyzerElementList *elements)
{ {
Decl *decl = find_decl(id); Decl* decl = find_decl(id);
if ( decl->decl_type() != decl_type ) if ( decl->decl_type() != decl_type )
{ {
throw Exception(id, throw Exception(id, strfmt("not a connection/flow declaration: %s", id->Name()));
strfmt("not a connection/flow declaration: %s",
id->Name()));
} }
AnalyzerDecl *analyzer_decl = static_cast<AnalyzerDecl *>(decl); AnalyzerDecl* analyzer_decl = static_cast<AnalyzerDecl*>(decl);
ASSERT(analyzer_decl); ASSERT(analyzer_decl);
analyzer_decl->AddElements(elements); analyzer_decl->AddElements(elements);
@ -153,18 +135,16 @@ Decl *ProcessAnalyzerRedef(const ID *id,
return decl; return decl;
} }
Decl *ProcessTypeAttrRedef(const ID *id, AttrList *attrlist) Decl* ProcessTypeAttrRedef(const ID* id, AttrList* attrlist)
{ {
Decl *decl = find_decl(id); Decl* decl = find_decl(id);
if ( decl->decl_type() != Decl::TYPE ) if ( decl->decl_type() != Decl::TYPE )
{ {
throw Exception(id, throw Exception(id, strfmt("not a type declaration: %s", id->Name()));
strfmt("not a type declaration: %s",
id->Name()));
} }
TypeDecl *type_decl = static_cast<TypeDecl *>(decl); TypeDecl* type_decl = static_cast<TypeDecl*>(decl);
ASSERT(type_decl); ASSERT(type_decl);
type_decl->AddAttrs(attrlist); type_decl->AddAttrs(attrlist);

View file

@ -3,11 +3,9 @@
#include "pac_decl.h" #include "pac_decl.h"
Decl *ProcessCaseTypeRedef(const ID *id, CaseFieldList *casefieldlist); Decl* ProcessCaseTypeRedef(const ID* id, CaseFieldList* casefieldlist);
Decl *ProcessCaseExprRedef(const ID *id, CaseExprList *caseexprlist); Decl* ProcessCaseExprRedef(const ID* id, CaseExprList* caseexprlist);
Decl *ProcessAnalyzerRedef(const ID *id, Decl* ProcessAnalyzerRedef(const ID* id, Decl::DeclType decl_type, AnalyzerElementList* elements);
Decl::DeclType decl_type, Decl* ProcessTypeAttrRedef(const ID* id, AttrList* attrlist);
AnalyzerElementList *elements);
Decl *ProcessTypeAttrRedef(const ID *id, AttrList *attrlist);
#endif // pac_redef_h #endif // pac_redef_h

View file

@ -1,27 +1,28 @@
#include "pac_regex.h"
#include "pac_exttype.h" #include "pac_exttype.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_regex.h"
#include "pac_type.h" #include "pac_type.h"
// Depends on the regular expression library we are using // Depends on the regular expression library we are using
const char *RegEx::kREMatcherType = "RegExMatcher"; const char* RegEx::kREMatcherType = "RegExMatcher";
const char *RegEx::kMatchPrefix = "MatchPrefix"; const char* RegEx::kMatchPrefix = "MatchPrefix";
string escape_char(const string &s) string escape_char(const string& s)
{ {
char* buf = new char[s.length() * 2 + 1]; char* buf = new char[s.length() * 2 + 1];
int j = 0; int j = 0;
for ( int i = 0; i < (int) s.length(); ++i ) for ( int i = 0; i < (int)s.length(); ++i )
{ {
if ( s[i] == '\\' ) if ( s[i] == '\\' )
{ {
if ( i + 1 < (int) s.length() ) if ( i + 1 < (int)s.length() )
{ {
buf[j++] = '\\'; buf[j++] = '\\';
if ( s[i+1] == '/' ) if ( s[i + 1] == '/' )
buf[j-1] = s[++i]; buf[j - 1] = s[++i];
else if ( s[i+1] == '/' || s[i+1] == '\\' || s[i+1] == '"' ) else if ( s[i + 1] == '/' || s[i + 1] == '\\' || s[i + 1] == '"' )
buf[j++] = s[++i]; buf[j++] = s[++i];
else else
buf[j++] = '\\'; buf[j++] = '\\';
@ -41,11 +42,11 @@ string escape_char(const string &s)
buf[j++] = '\0'; buf[j++] = '\0';
string rval = buf; string rval = buf;
delete [] buf; delete[] buf;
return rval; return rval;
} }
RegEx::RegEx(const string &s) RegEx::RegEx(const string& s)
{ {
str_ = escape_char(s); str_ = escape_char(s);
string prefix = strfmt("%s_re_", current_decl_id->Name()); string prefix = strfmt("%s_re_", current_decl_id->Name());
@ -53,12 +54,9 @@ RegEx::RegEx(const string &s)
decl_ = new RegExDecl(this); decl_ = new RegExDecl(this);
} }
RegEx::~RegEx() RegEx::~RegEx() { }
{
}
RegExDecl::RegExDecl(RegEx *regex) RegExDecl::RegExDecl(RegEx* regex) : Decl(regex->matcher_id(), REGEX)
: Decl(regex->matcher_id(), REGEX)
{ {
regex_ = regex; regex_ = regex;
} }
@ -68,17 +66,14 @@ void RegExDecl::Prepare()
global_env()->AddID(id(), GLOBAL_VAR, extern_type_re_matcher); global_env()->AddID(id(), GLOBAL_VAR, extern_type_re_matcher);
} }
void RegExDecl::GenForwardDeclaration(Output *out_h) void RegExDecl::GenForwardDeclaration(Output* out_h)
{ {
out_h->println("extern %s %s;\n", out_h->println("extern %s %s;\n", RegEx::kREMatcherType,
RegEx::kREMatcherType, global_env()->LValue(regex_->matcher_id()));
global_env()->LValue(regex_->matcher_id()));
} }
void RegExDecl::GenCode(Output *out_h, Output *out_cc) void RegExDecl::GenCode(Output* out_h, Output* out_cc)
{ {
out_cc->println("%s %s(\"%s\");\n", out_cc->println("%s %s(\"%s\");\n", RegEx::kREMatcherType,
RegEx::kREMatcherType, global_env()->LValue(regex_->matcher_id()), regex_->str().c_str());
global_env()->LValue(regex_->matcher_id()),
regex_->str().c_str());
} }

View file

@ -7,35 +7,35 @@
class RegExDecl; class RegExDecl;
class RegEx : public Object class RegEx : public Object
{ {
public: public:
RegEx(const string &str); RegEx(const string& str);
~RegEx(); ~RegEx();
const string &str() const { return str_; } const string& str() const { return str_; }
ID *matcher_id() const { return matcher_id_; } ID* matcher_id() const { return matcher_id_; }
private: private:
string str_; string str_;
ID *matcher_id_; ID* matcher_id_;
RegExDecl *decl_; RegExDecl* decl_;
public: public:
static const char *kREMatcherType; static const char* kREMatcherType;
static const char *kMatchPrefix; static const char* kMatchPrefix;
}; };
class RegExDecl : public Decl class RegExDecl : public Decl
{ {
public: public:
RegExDecl(RegEx *regex); RegExDecl(RegEx* regex);
void Prepare(); void Prepare();
void GenForwardDeclaration(Output *out_h); void GenForwardDeclaration(Output* out_h);
void GenCode(Output *out_h, Output *out_cc); void GenCode(Output* out_h, Output* out_cc);
private: private:
RegEx *regex_; RegEx* regex_;
}; };
#endif // pac_regex_h #endif // pac_regex_h

View file

@ -1,36 +1,26 @@
#include "pac_state.h"
#include "pac_id.h" #include "pac_id.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_type.h" #include "pac_type.h"
#include "pac_state.h" void StateVar::GenDecl(Output* out_h, Env* env)
void StateVar::GenDecl(Output *out_h, Env *env)
{ {
out_h->println("%s %s;", out_h->println("%s %s;", type_->DataTypeStr().c_str(), env->LValue(id_));
type_->DataTypeStr().c_str(),
env->LValue(id_));
} }
void StateVar::GenAccessFunction(Output *out_h, Env *env) void StateVar::GenAccessFunction(Output* out_h, Env* env)
{ {
out_h->println("%s %s const { return %s; }", out_h->println("%s %s const { return %s; }", type_->DataTypeConstRefStr().c_str(),
type_->DataTypeConstRefStr().c_str(), env->RValue(id_), env->LValue(id_));
env->RValue(id_),
env->LValue(id_));
} }
void StateVar::GenSetFunction(Output *out_h, Env *env) void StateVar::GenSetFunction(Output* out_h, Env* env)
{ {
out_h->println("void %s(%s x) { %s = x; }", out_h->println("void %s(%s x) { %s = x; }", set_function(id_).c_str(),
set_function(id_).c_str(), type_->DataTypeConstRefStr().c_str(), env->LValue(id_));
type_->DataTypeConstRefStr().c_str(),
env->LValue(id_));
} }
void StateVar::GenInitCode(Output *out_cc, Env *env) void StateVar::GenInitCode(Output* out_cc, Env* env) { }
{
}
void StateVar::GenCleanUpCode(Output *out_cc, Env *env) void StateVar::GenCleanUpCode(Output* out_cc, Env* env) { }
{
}

View file

@ -6,23 +6,22 @@
#include "pac_common.h" #include "pac_common.h"
class StateVar class StateVar
{ {
public: public:
StateVar(ID *id, Type *type) StateVar(ID* id, Type* type) : id_(id), type_(type) { }
: id_(id), type_(type) {}
const ID *id() const { return id_; } const ID* id() const { return id_; }
Type *type() const { return type_; } Type* type() const { return type_; }
void GenDecl(Output *out_h, Env *env); void GenDecl(Output* out_h, Env* env);
void GenAccessFunction(Output *out_h, Env *env); void GenAccessFunction(Output* out_h, Env* env);
void GenSetFunction(Output *out_h, Env *env); void GenSetFunction(Output* out_h, Env* env);
void GenInitCode(Output *out_cc, Env *env); void GenInitCode(Output* out_cc, Env* env);
void GenCleanUpCode(Output *out_cc, Env *env); void GenCleanUpCode(Output* out_cc, Env* env);
private: private:
ID *id_; ID* id_;
Type *type_; Type* type_;
}; };
#endif // pac_state_h #endif // pac_state_h

View file

@ -1,3 +1,5 @@
#include "pac_strtype.h"
#include "pac_attr.h" #include "pac_attr.h"
#include "pac_btype.h" #include "pac_btype.h"
#include "pac_cstr.h" #include "pac_cstr.h"
@ -8,27 +10,23 @@
#include "pac_id.h" #include "pac_id.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_regex.h" #include "pac_regex.h"
#include "pac_strtype.h"
#include "pac_varfield.h" #include "pac_varfield.h"
const char *StringType::kStringTypeName = "bytestring"; const char* StringType::kStringTypeName = "bytestring";
const char *StringType::kConstStringTypeName = "const_bytestring"; const char* StringType::kConstStringTypeName = "const_bytestring";
StringType::StringType(StringTypeEnum anystr) StringType::StringType(StringTypeEnum anystr) : Type(STRING), type_(ANYSTR), str_(0), regex_(0)
: Type(STRING), type_(ANYSTR), str_(0), regex_(0)
{ {
ASSERT(anystr == ANYSTR); ASSERT(anystr == ANYSTR);
init(); init();
} }
StringType::StringType(ConstString *str) StringType::StringType(ConstString* str) : Type(STRING), type_(CSTR), str_(str), regex_(0)
: Type(STRING), type_(CSTR), str_(str), regex_(0)
{ {
init(); init();
} }
StringType::StringType(RegEx *regex) StringType::StringType(RegEx* regex) : Type(STRING), type_(REGEX), str_(0), regex_(regex)
: Type(STRING), type_(REGEX), str_(0), regex_(regex)
{ {
ASSERT(regex_); ASSERT(regex_);
init(); init();
@ -52,9 +50,9 @@ StringType::~StringType()
delete elem_datatype_; delete elem_datatype_;
} }
Type *StringType::DoClone() const Type* StringType::DoClone() const
{ {
StringType *clone; StringType* clone;
switch ( type_ ) switch ( type_ )
{ {
@ -82,16 +80,15 @@ bool StringType::DefineValueVar() const
string StringType::DataTypeStr() const string StringType::DataTypeStr() const
{ {
return strfmt("%s", return strfmt("%s", persistent() ? kStringTypeName : kConstStringTypeName);
persistent() ? kStringTypeName : kConstStringTypeName);
} }
Type *StringType::ElementDataType() const Type* StringType::ElementDataType() const
{ {
return elem_datatype_; return elem_datatype_;
} }
void StringType::ProcessAttr(Attr *a) void StringType::ProcessAttr(Attr* a)
{ {
Type::ProcessAttr(a); Type::ProcessAttr(a);
@ -101,9 +98,8 @@ void StringType::ProcessAttr(Attr *a)
{ {
if ( type_ != ANYSTR ) if ( type_ != ANYSTR )
{ {
throw Exception(a, throw Exception(a, "&chunked can be applied"
"&chunked can be applied" " to only type bytestring");
" to only type bytestring");
} }
attr_chunked_ = true; attr_chunked_ = true;
SetBoundaryChecked(); SetBoundaryChecked();
@ -114,9 +110,8 @@ void StringType::ProcessAttr(Attr *a)
{ {
if ( type_ != ANYSTR ) if ( type_ != ANYSTR )
{ {
throw Exception(a, throw Exception(a, "&restofdata can be applied"
"&restofdata can be applied" " to only type bytestring");
" to only type bytestring");
} }
attr_restofdata_ = true; attr_restofdata_ = true;
// As the string automatically extends to the end of // As the string automatically extends to the end of
@ -129,9 +124,8 @@ void StringType::ProcessAttr(Attr *a)
{ {
if ( type_ != ANYSTR ) if ( type_ != ANYSTR )
{ {
throw Exception(a, throw Exception(a, "&restofflow can be applied"
"&restofflow can be applied" " to only type bytestring");
" to only type bytestring");
} }
attr_restofflow_ = true; attr_restofflow_ = true;
// As the string automatically extends to the end of // As the string automatically extends to the end of
@ -149,10 +143,9 @@ void StringType::Prepare(Env* env, int flags)
{ {
if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 ) if ( (flags & TO_BE_PARSED) && StaticSize(env) < 0 )
{ {
ID *string_length_var = new ID(strfmt("%s_string_length", ID* string_length_var = new ID(
value_var() ? value_var()->Name() : "val")); strfmt("%s_string_length", value_var() ? value_var()->Name() : "val"));
string_length_var_field_ = new TempVarField( string_length_var_field_ = new TempVarField(string_length_var, extern_type_int->Clone());
string_length_var, extern_type_int->Clone());
string_length_var_field_->Prepare(env); string_length_var_field_->Prepare(env);
} }
Type::Prepare(env, flags); Type::Prepare(env, flags);
@ -211,17 +204,15 @@ int StringType::StaticSize(Env* env) const
} }
} }
const ID *StringType::string_length_var() const const ID* StringType::string_length_var() const
{ {
return string_length_var_field_ ? string_length_var_field_->id() : 0; return string_length_var_field_ ? string_length_var_field_->id() : 0;
} }
void StringType::GenDynamicSize(Output* out_cc, Env* env, void StringType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
const DataPtr& data)
{ {
ASSERT(StaticSize(env) < 0); ASSERT(StaticSize(env) < 0);
DEBUG_MSG("Generating dynamic size for string `%s'\n", DEBUG_MSG("Generating dynamic size for string `%s'\n", value_var()->Name());
value_var()->Name());
if ( env->Evaluated(string_length_var()) ) if ( env->Evaluated(string_length_var()) )
return; return;
@ -244,15 +235,12 @@ void StringType::GenDynamicSize(Output* out_cc, Env* env,
if ( ! incremental_input() && AddSizeVar(out_cc, env) ) if ( ! incremental_input() && AddSizeVar(out_cc, env) )
{ {
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(size_var()), env->RValue(string_length_var()));
env->LValue(size_var()),
env->RValue(string_length_var()));
env->SetEvaluated(size_var()); env->SetEvaluated(size_var());
} }
} }
string StringType::GenStringSize(Output* out_cc, Env* env, string StringType::GenStringSize(Output* out_cc, Env* env, const DataPtr& data)
const DataPtr& data)
{ {
int static_size = StaticSize(env); int static_size = StaticSize(env);
if ( static_size >= 0 ) if ( static_size >= 0 )
@ -261,8 +249,7 @@ string StringType::GenStringSize(Output* out_cc, Env* env,
return env->RValue(string_length_var()); return env->RValue(string_length_var());
} }
void StringType::DoGenParseCode(Output* out_cc, Env* env, void StringType::DoGenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags)
const DataPtr& data, int flags)
{ {
string str_size = GenStringSize(out_cc, env, data); string str_size = GenStringSize(out_cc, env, data);
@ -283,8 +270,7 @@ void StringType::DoGenParseCode(Output* out_cc, Env* env,
int len; int len;
if ( type_ == ANYSTR && attr_length_expr_ && if ( type_ == ANYSTR && attr_length_expr_ && attr_length_expr_->ConstFold(env, &len) )
attr_length_expr_->ConstFold(env, &len) )
{ {
// can check for a negative length now // can check for a negative length now
if ( len < 0 ) if ( len < 0 )
@ -293,41 +279,31 @@ void StringType::DoGenParseCode(Output* out_cc, Env* env,
else else
{ {
out_cc->println("// check for negative sizes"); out_cc->println("// check for negative sizes");
out_cc->println("if ( %s < 0 )", out_cc->println("if ( %s < 0 )", str_size.c_str());
str_size.c_str()); out_cc->println("throw binpac::ExceptionInvalidStringLength(\"%s\", %s);", Location(),
out_cc->println( str_size.c_str());
"throw binpac::ExceptionInvalidStringLength(\"%s\", %s);",
Location(), str_size.c_str());
} }
out_cc->println("%s.init(%s, %s);", out_cc->println("%s.init(%s, %s);", env->LValue(value_var()), data.ptr_expr(),
env->LValue(value_var()), str_size.c_str());
data.ptr_expr(),
str_size.c_str());
} }
if ( parsing_complete_var() ) if ( parsing_complete_var() )
{ {
out_cc->println("%s = true;", out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
env->LValue(parsing_complete_var()));
} }
} }
void StringType::GenStringMismatch(Output* out_cc, Env* env, void StringType::GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern)
const DataPtr& data, string pattern)
{ {
string tmp = string tmp = strfmt("string((const char *) (%s), (const char *) %s).c_str()", data.ptr_expr(),
strfmt("string((const char *) (%s), (const char *) %s).c_str()", env->RValue(end_of_data));
data.ptr_expr(), out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);", Location(),
env->RValue(end_of_data)); pattern.c_str(), tmp.c_str());
out_cc->println("throw binpac::ExceptionStringMismatch(\"%s\", %s, %s);",
Location(),
pattern.c_str(),
tmp.c_str());
} }
void StringType::GenCheckingCStr(Output* out_cc, Env* env, void StringType::GenCheckingCStr(Output* out_cc, Env* env, const DataPtr& data,
const DataPtr& data, const string &str_size) const string& str_size)
{ {
// TODO: extend it for dynamic strings // TODO: extend it for dynamic strings
ASSERT(type_ == CSTR); ASSERT(type_ == CSTR);
@ -337,10 +313,8 @@ void StringType::GenCheckingCStr(Output* out_cc, Env* env,
string str_val = str_->str(); string str_val = str_->str();
// Compare the string and report error on mismatch // Compare the string and report error on mismatch
out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", out_cc->println("if ( memcmp(%s, %s, %s) != 0 )", data.ptr_expr(), str_val.c_str(),
data.ptr_expr(), str_size.c_str());
str_val.c_str(),
str_size.c_str());
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
GenStringMismatch(out_cc, env, data, str_val); GenStringMismatch(out_cc, env, data, str_val);
@ -348,36 +322,28 @@ void StringType::GenCheckingCStr(Output* out_cc, Env* env,
out_cc->dec_indent(); out_cc->dec_indent();
} }
void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data)
const DataPtr& data)
{ {
// string_length_var = // string_length_var =
// matcher.match_prefix( // matcher.match_prefix(
// begin, // begin,
// end); // end);
out_cc->println("%s = ", out_cc->println("%s = ", env->LValue(string_length_var()));
env->LValue(string_length_var()));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("%s.%s(", out_cc->println("%s.%s(", env->RValue(regex_->matcher_id()), RegEx::kMatchPrefix);
env->RValue(regex_->matcher_id()),
RegEx::kMatchPrefix);
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("%s,", out_cc->println("%s,", data.ptr_expr());
data.ptr_expr()); out_cc->println("%s - %s);", env->RValue(end_of_data), data.ptr_expr());
out_cc->println("%s - %s);",
env->RValue(end_of_data),
data.ptr_expr());
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->dec_indent(); out_cc->dec_indent();
env->SetEvaluated(string_length_var()); env->SetEvaluated(string_length_var());
out_cc->println("if ( %s < 0 )", out_cc->println("if ( %s < 0 )", env->RValue(string_length_var()));
env->RValue(string_length_var()));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
string tmp = strfmt("\"%s\"", regex_->str().c_str()); string tmp = strfmt("\"%s\"", regex_->str().c_str());
@ -386,41 +352,34 @@ void StringType::GenDynamicSizeRegEx(Output* out_cc, Env* env,
out_cc->dec_indent(); out_cc->dec_indent();
} }
void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, void StringType::GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data)
const DataPtr& data)
{ {
ASSERT(type_ == ANYSTR); ASSERT(type_ == ANYSTR);
if ( attr_restofdata_ || attr_oneline_ ) if ( attr_restofdata_ || attr_oneline_ )
{ {
out_cc->println("%s = (%s) - (%s);", out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()),
env->LValue(string_length_var()), env->RValue(end_of_data), data.ptr_expr());
env->RValue(end_of_data),
data.ptr_expr());
} }
else if ( attr_restofflow_ ) else if ( attr_restofflow_ )
{ {
out_cc->println("%s = (%s) - (%s);", out_cc->println("%s = (%s) - (%s);", env->LValue(string_length_var()),
env->LValue(string_length_var()), env->RValue(end_of_data), data.ptr_expr());
env->RValue(end_of_data),
data.ptr_expr());
} }
else if ( attr_length_expr_ ) else if ( attr_length_expr_ )
{ {
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(string_length_var()),
env->LValue(string_length_var()), attr_length_expr_->EvalExpr(out_cc, env));
attr_length_expr_->EvalExpr(out_cc, env));
} }
else else
{ {
throw Exception(this, throw Exception(this, "cannot determine length of bytestring");
"cannot determine length of bytestring");
} }
env->SetEvaluated(string_length_var()); env->SetEvaluated(string_length_var());
} }
bool StringType::DoTraverse(DataDepVisitor *visitor) bool StringType::DoTraverse(DataDepVisitor* visitor)
{ {
if ( ! Type::DoTraverse(visitor) ) if ( ! Type::DoTraverse(visitor) )
return false; return false;

View file

@ -5,19 +5,24 @@
// TODO: question: shall we merge it with ArrayType? // TODO: question: shall we merge it with ArrayType?
class StringType : public Type class StringType : public Type
{ {
public: public:
enum StringTypeEnum { CSTR, REGEX, ANYSTR }; enum StringTypeEnum
{
CSTR,
REGEX,
ANYSTR
};
explicit StringType(StringTypeEnum anystr); explicit StringType(StringTypeEnum anystr);
explicit StringType(ConstString *str); explicit StringType(ConstString* str);
explicit StringType(RegEx *regex); explicit StringType(RegEx* regex);
~StringType(); ~StringType();
bool DefineValueVar() const; bool DefineValueVar() const;
string DataTypeStr() const; string DataTypeStr() const;
string DefaultValue() const { return "0"; } string DefaultValue() const { return "0"; }
Type *ElementDataType() const; Type* ElementDataType() const;
void Prepare(Env* env, int flags); void Prepare(Env* env, int flags);
@ -31,9 +36,9 @@ public:
int StaticSize(Env* env) const; int StaticSize(Env* env) const;
bool IsPointerType() const { return false; } bool IsPointerType() const { return false; }
void ProcessAttr(Attr *a); void ProcessAttr(Attr* a);
protected: protected:
void init(); void init();
@ -43,40 +48,39 @@ protected:
string GenStringSize(Output* out_cc, Env* env, const DataPtr& data); string GenStringSize(Output* out_cc, Env* env, const DataPtr& data);
// Generate a string mismatch exception // Generate a string mismatch exception
void GenStringMismatch(Output* out_cc, Env* env, void GenStringMismatch(Output* out_cc, Env* env, const DataPtr& data, string pattern);
const DataPtr& data, string pattern);
void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags); void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags);
void GenCheckingCStr(Output* out, Env* env, void GenCheckingCStr(Output* out, Env* env, const DataPtr& data, const string& str_size);
const DataPtr& data, const string &str_size);
void GenDynamicSize(Output* out, Env* env, const DataPtr& data); void GenDynamicSize(Output* out, Env* env, const DataPtr& data);
void GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data); void GenDynamicSizeAnyStr(Output* out_cc, Env* env, const DataPtr& data);
void GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data); void GenDynamicSizeRegEx(Output* out_cc, Env* env, const DataPtr& data);
Type *DoClone() const; Type* DoClone() const;
// TODO: insensitive towards byte order till we support unicode // TODO: insensitive towards byte order till we support unicode
bool ByteOrderSensitive() const { return false; } bool ByteOrderSensitive() const { return false; }
protected: protected:
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
private: private:
const ID *string_length_var() const; const ID* string_length_var() const;
StringTypeEnum type_; StringTypeEnum type_;
ConstString *str_; ConstString* str_;
RegEx *regex_; RegEx* regex_;
Field *string_length_var_field_; Field* string_length_var_field_;
Type *elem_datatype_; Type* elem_datatype_;
public: public:
static void static_init(); static void static_init();
private:
static const char *kStringTypeName;
static const char *kConstStringTypeName;
};
#endif // pac_strtype_h private:
static const char* kStringTypeName;
static const char* kConstStringTypeName;
};
#endif // pac_strtype_h

View file

@ -1,3 +1,5 @@
#include "pac_type.h"
#include "pac_action.h" #include "pac_action.h"
#include "pac_array.h" #include "pac_array.h"
#include "pac_attr.h" #include "pac_attr.h"
@ -14,16 +16,13 @@
#include "pac_output.h" #include "pac_output.h"
#include "pac_paramtype.h" #include "pac_paramtype.h"
#include "pac_strtype.h" #include "pac_strtype.h"
#include "pac_type.h"
#include "pac_utils.h" #include "pac_utils.h"
#include "pac_varfield.h" #include "pac_varfield.h"
#include "pac_withinput.h" #include "pac_withinput.h"
Type::type_map_t Type::type_map_; Type::type_map_t Type::type_map_;
Type::Type(TypeType tot) Type::Type(TypeType tot) : DataDepElement(DataDepElement::TYPE), tot_(tot)
: DataDepElement(DataDepElement::TYPE), tot_(tot)
{ {
type_decl_ = 0; type_decl_ = 0;
type_decl_id_ = current_decl_id; type_decl_id_ = current_decl_id;
@ -75,7 +74,7 @@ Type::~Type()
delete parsing_state_var_field_; delete parsing_state_var_field_;
delete buffering_state_var_field_; delete buffering_state_var_field_;
delete has_value_field_; delete has_value_field_;
delete [] size_expr_; delete[] size_expr_;
delete_list(FieldList, fields_); delete_list(FieldList, fields_);
delete attrs_; delete attrs_;
delete attr_byteorder_expr_; delete attr_byteorder_expr_;
@ -86,43 +85,43 @@ Type::~Type()
delete_list(ExprList, attr_requires_); delete_list(ExprList, attr_requires_);
} }
Type *Type::Clone() const Type* Type::Clone() const
{ {
Type *clone = DoClone(); Type* clone = DoClone();
if ( clone ) if ( clone )
{ {
foreach(i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
Field *f = *i; Field* f = *i;
clone->AddField(f); clone->AddField(f);
} }
foreach(i, AttrList, attrs_) foreach (i, AttrList, attrs_)
{ {
Attr *a = *i; Attr* a = *i;
clone->ProcessAttr(a); clone->ProcessAttr(a);
} }
} }
return clone; return clone;
} }
string Type::EvalMember(const ID *member_id) const string Type::EvalMember(const ID* member_id) const
{ {
ASSERT(0); ASSERT(0);
return "@@@"; return "@@@";
} }
string Type::EvalElement(const string &array, const string &index) const string Type::EvalElement(const string& array, const string& index) const
{ {
return strfmt("%s[%s]", array.c_str(), index.c_str()); return strfmt("%s[%s]", array.c_str(), index.c_str());
} }
const ID *Type::decl_id() const const ID* Type::decl_id() const
{ {
return type_decl_id_; return type_decl_id_;
} }
void Type::set_type_decl(const TypeDecl *decl, bool declared_as_type) void Type::set_type_decl(const TypeDecl* decl, bool declared_as_type)
{ {
type_decl_ = decl; type_decl_ = decl;
type_decl_id_ = decl->id(); type_decl_id_ = decl->id();
@ -130,7 +129,7 @@ void Type::set_type_decl(const TypeDecl *decl, bool declared_as_type)
} }
void Type::set_value_var(const ID* arg_id, int arg_id_type) void Type::set_value_var(const ID* arg_id, int arg_id_type)
{ {
value_var_ = arg_id; value_var_ = arg_id;
value_var_type_ = arg_id_type; value_var_type_ = arg_id_type;
@ -138,12 +137,12 @@ void Type::set_value_var(const ID* arg_id, int arg_id_type)
anonymous_value_var_ = value_var_->is_anonymous(); anonymous_value_var_ = value_var_->is_anonymous();
} }
const ID *Type::size_var() const const ID* Type::size_var() const
{ {
return size_var_field_ ? size_var_field_->id() : 0; return size_var_field_ ? size_var_field_->id() : 0;
} }
void Type::AddField(Field *f) void Type::AddField(Field* f)
{ {
ASSERT(f); ASSERT(f);
fields_->push_back(f); fields_->push_back(f);
@ -179,23 +178,22 @@ void Type::ProcessAttr(Attr* a)
case ATTR_LET: case ATTR_LET:
{ {
LetAttr *letattr = static_cast<LetAttr *>(a); LetAttr* letattr = static_cast<LetAttr*>(a);
if ( ! attr_letfields_ ) if ( ! attr_letfields_ )
attr_letfields_ = letattr->letfields(); attr_letfields_ = letattr->letfields();
else else
{ {
// Append to attr_letfields_ // Append to attr_letfields_
attr_letfields_->insert( attr_letfields_->insert(attr_letfields_->end(), letattr->letfields()->begin(),
attr_letfields_->end(), letattr->letfields()->end());
letattr->letfields()->begin(),
letattr->letfields()->end());
} }
} }
break; break;
case ATTR_LINEBREAKER: case ATTR_LINEBREAKER:
if (strlen(a->expr()->orig()) != 6 ) if ( strlen(a->expr()->orig()) != 6 )
throw Exception(this, "invalid line breaker length, must be a single ASCII character. (Ex: \"\\001\".)"); throw Exception(this, "invalid line breaker length, must be a single ASCII "
"character. (Ex: \"\\001\".)");
attr_linebreaker_ = a->expr(); attr_linebreaker_ = a->expr();
break; break;
@ -232,7 +230,7 @@ void Type::ProcessAttr(Attr* a)
attrs_->push_back(a); attrs_->push_back(a);
} }
string Type::EvalByteOrder(Output *out_cc, Env *env) const string Type::EvalByteOrder(Output* out_cc, Env* env) const
{ {
// If &byteorder is specified for a field, rather // If &byteorder is specified for a field, rather
// than a type declaration, we do not add a byteorder variable // than a type declaration, we do not add a byteorder variable
@ -251,8 +249,7 @@ void Type::Prepare(Env* env, int flags)
// The name of the value variable // The name of the value variable
if ( value_var() ) if ( value_var() )
{ {
data_id_str_ = strfmt("%s:%s", data_id_str_ = strfmt("%s:%s", decl_id()->Name(), value_var()->Name());
decl_id()->Name(), value_var()->Name());
} }
else else
{ {
@ -261,13 +258,11 @@ void Type::Prepare(Env* env, int flags)
if ( value_var() ) if ( value_var() )
{ {
env_->AddID(value_var(), env_->AddID(value_var(), static_cast<IDType>(value_var_type_), this);
static_cast<IDType>(value_var_type_),
this);
lvalue_ = strfmt("%s", env_->LValue(value_var())); lvalue_ = strfmt("%s", env_->LValue(value_var()));
} }
foreach(i, FieldList, attr_letfields_) foreach (i, FieldList, attr_letfields_)
{ {
AddField(*i); AddField(*i);
} }
@ -275,55 +270,47 @@ void Type::Prepare(Env* env, int flags)
if ( attr_exportsourcedata_ ) if ( attr_exportsourcedata_ )
{ {
ASSERT(flags & TO_BE_PARSED); ASSERT(flags & TO_BE_PARSED);
AddField(new PubVarField(sourcedata_id->clone(), AddField(new PubVarField(sourcedata_id->clone(), extern_type_const_bytestring->Clone()));
extern_type_const_bytestring->Clone()));
} }
// An optional field // An optional field
if ( attr_if_expr() ) if ( attr_if_expr() )
{ {
ASSERT(value_var()); ASSERT(value_var());
ID *has_value_id = new ID(strfmt("has_%s", value_var()->Name())); ID* has_value_id = new ID(strfmt("has_%s", value_var()->Name()));
has_value_field_ = new LetField(has_value_id, has_value_field_ = new LetField(has_value_id, extern_type_bool->Clone(), attr_if_expr());
extern_type_bool->Clone(),
attr_if_expr());
AddField(has_value_field_); AddField(has_value_field_);
} }
if ( incremental_input() ) if ( incremental_input() )
{ {
ASSERT(flags & TO_BE_PARSED); ASSERT(flags & TO_BE_PARSED);
ID *parsing_complete_var = ID* parsing_complete_var = new ID(
new ID(strfmt("%s_parsing_complete", strfmt("%s_parsing_complete", value_var() ? value_var()->Name() : "val"));
value_var() ? value_var()->Name() : "val")); DEBUG_MSG("Adding parsing complete var: %s\n", parsing_complete_var->Name());
DEBUG_MSG("Adding parsing complete var: %s\n", parsing_complete_var_field_ = new TempVarField(parsing_complete_var,
parsing_complete_var->Name()); extern_type_bool->Clone());
parsing_complete_var_field_ = new TempVarField(
parsing_complete_var, extern_type_bool->Clone());
parsing_complete_var_field_->Prepare(env); parsing_complete_var_field_->Prepare(env);
if ( NeedsBufferingStateVar() && if ( NeedsBufferingStateVar() && ! env->GetDataType(buffering_state_id) )
! env->GetDataType(buffering_state_id) )
{ {
buffering_state_var_field_ = new PrivVarField( buffering_state_var_field_ = new PrivVarField(buffering_state_id->clone(),
buffering_state_id->clone(), extern_type_int->Clone());
extern_type_int->Clone());
AddField(buffering_state_var_field_); AddField(buffering_state_var_field_);
} }
if ( incremental_parsing() && tot_ == RECORD ) if ( incremental_parsing() && tot_ == RECORD )
{ {
ASSERT(! parsing_state_var_field_); ASSERT(! parsing_state_var_field_);
parsing_state_var_field_ = new PrivVarField( parsing_state_var_field_ = new PrivVarField(parsing_state_id->clone(),
parsing_state_id->clone(), extern_type_int->Clone());
extern_type_int->Clone());
AddField(parsing_state_var_field_); AddField(parsing_state_var_field_);
} }
} }
foreach (i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
Field *f = *i; Field* f = *i;
f->Prepare(env); f->Prepare(env);
} }
} }
@ -333,19 +320,17 @@ void Type::GenPubDecls(Output* out_h, Env* env)
if ( DefineValueVar() ) if ( DefineValueVar() )
{ {
if ( attr_if_expr_ ) if ( attr_if_expr_ )
out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }", out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }",
DataTypeConstRefStr().c_str(), DataTypeConstRefStr().c_str(), env->RValue(value_var()),
env->RValue(value_var()), env->RValue(has_value_var()), lvalue());
env->RValue(has_value_var()), lvalue());
else else
out_h->println("%s %s const { return %s; }", out_h->println("%s %s const { return %s; }", DataTypeConstRefStr().c_str(),
DataTypeConstRefStr().c_str(), env->RValue(value_var()), lvalue());
env->RValue(value_var()), lvalue());
} }
foreach (i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
Field *f = *i; Field* f = *i;
f->GenPubDecls(out_h, env); f->GenPubDecls(out_h, env);
} }
} }
@ -354,14 +339,12 @@ void Type::GenPrivDecls(Output* out_h, Env* env)
{ {
if ( DefineValueVar() ) if ( DefineValueVar() )
{ {
out_h->println("%s %s;", out_h->println("%s %s;", DataTypeStr().c_str(), env->LValue(value_var()));
DataTypeStr().c_str(),
env->LValue(value_var()));
} }
foreach (i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
Field *f = *i; Field* f = *i;
f->GenPrivDecls(out_h, env); f->GenPrivDecls(out_h, env);
} }
} }
@ -370,20 +353,18 @@ void Type::GenInitCode(Output* out_cc, Env* env)
{ {
foreach (i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
Field *f = *i; Field* f = *i;
f->GenInitCode(out_cc, env); f->GenInitCode(out_cc, env);
} }
if ( parsing_state_var_field_ ) if ( parsing_state_var_field_ )
{ {
out_cc->println("%s = 0;", out_cc->println("%s = 0;", env->LValue(parsing_state_var_field_->id()));
env->LValue(parsing_state_var_field_->id()));
} }
if ( buffering_state_var_field_ ) if ( buffering_state_var_field_ )
{ {
out_cc->println("%s = 0;", out_cc->println("%s = 0;", env->LValue(buffering_state_var_field_->id()));
env->LValue(buffering_state_var_field_->id()));
} }
} }
@ -391,13 +372,13 @@ void Type::GenCleanUpCode(Output* out_cc, Env* env)
{ {
foreach (i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
Field *f = *i; Field* f = *i;
if ( f->tof() != CASE_FIELD ) if ( f->tof() != CASE_FIELD )
f->GenCleanUpCode(out_cc, env); f->GenCleanUpCode(out_cc, env);
} }
} }
void Type::GenBufferConfiguration(Output *out_cc, Env *env) void Type::GenBufferConfiguration(Output* out_cc, Env* env)
{ {
ASSERT(buffer_input()); ASSERT(buffer_input());
@ -410,12 +391,11 @@ void Type::GenBufferConfiguration(Output *out_cc, Env *env)
case BUFFER_BY_LENGTH: case BUFFER_BY_LENGTH:
if ( ! NeedsBufferingStateVar() ) if ( ! NeedsBufferingStateVar() )
break; break;
if ( buffering_state_var_field_ ) if ( buffering_state_var_field_ )
{ {
out_cc->println("if ( %s == 0 )", out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id));
env->RValue(buffering_state_id));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
} }
@ -435,36 +415,30 @@ void Type::GenBufferConfiguration(Output *out_cc, Env *env)
ASSERT(0); ASSERT(0);
} }
out_cc->println("%s->NewFrame(%s, %s);", out_cc->println("%s->NewFrame(%s, %s);", env->LValue(flow_buffer_id),
env->LValue(flow_buffer_id), frame_buffer_arg.c_str(), attr_chunked() ? "true" : "false");
frame_buffer_arg.c_str(),
attr_chunked() ? "true" : "false");
if ( buffering_state_var_field_ ) if ( buffering_state_var_field_ )
{ {
out_cc->println("%s = 1;", out_cc->println("%s = 1;", env->LValue(buffering_state_id));
env->LValue(buffering_state_id));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
} }
break; break;
case BUFFER_BY_LINE: case BUFFER_BY_LINE:
out_cc->println("if ( %s == 0 )", out_cc->println("if ( %s == 0 )", env->RValue(buffering_state_id));
env->RValue(buffering_state_id));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
if ( BufferableWithLineBreaker() ) if ( BufferableWithLineBreaker() )
out_cc->println("%s->SetLineBreaker((unsigned char*)%s);", out_cc->println("%s->SetLineBreaker((unsigned char*)%s);",
env->LValue(flow_buffer_id), LineBreaker()->orig()); env->LValue(flow_buffer_id), LineBreaker()->orig());
else else
out_cc->println("%s->UnsetLineBreaker();", out_cc->println("%s->UnsetLineBreaker();", env->LValue(flow_buffer_id));
env->LValue(flow_buffer_id));
out_cc->println("%s->NewLine();",
env->LValue(flow_buffer_id));
out_cc->println("%s = 1;", out_cc->println("%s->NewLine();", env->LValue(flow_buffer_id));
env->LValue(buffering_state_id));
out_cc->println("%s = 1;", env->LValue(buffering_state_id));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
break; break;
@ -475,7 +449,7 @@ void Type::GenBufferConfiguration(Output *out_cc, Env *env)
} }
} }
void Type::GenPreParsing(Output *out_cc, Env *env) void Type::GenPreParsing(Output* out_cc, Env* env)
{ {
if ( incremental_input() && IsPointerType() ) if ( incremental_input() && IsPointerType() )
{ {
@ -519,14 +493,12 @@ void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags
{ {
parsing_complete_var_field_->GenTempDecls(out_cc, env); parsing_complete_var_field_->GenTempDecls(out_cc, env);
out_cc->println("%s = false;", out_cc->println("%s = false;", env->LValue(parsing_complete_var()));
env->LValue(parsing_complete_var()));
env->SetEvaluated(parsing_complete_var()); env->SetEvaluated(parsing_complete_var());
if ( buffer_mode() == BUFFER_NOTHING ) if ( buffer_mode() == BUFFER_NOTHING )
{ {
out_cc->println("%s = true;", out_cc->println("%s = true;", env->LValue(parsing_complete_var()));
env->LValue(parsing_complete_var()));
} }
else if ( buffer_input() ) else if ( buffer_input() )
{ {
@ -540,20 +512,17 @@ void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags
} }
else else
{ {
if ( attr_length_expr_) if ( attr_length_expr_ )
{ {
EvalLengthExpr(out_cc, env); EvalLengthExpr(out_cc, env);
GenBoundaryCheck(out_cc, env, data); GenBoundaryCheck(out_cc, env, data);
out_cc->println("{"); out_cc->println("{");
out_cc->println("// Setting %s with &length", out_cc->println("// Setting %s with &length", env->RValue(end_of_data));
env->RValue(end_of_data)); out_cc->println("%s %s = %s + %s;", extern_type_const_byteptr->DataTypeStr().c_str(),
out_cc->println("%s %s = %s + %s;", env->LValue(end_of_data), data.ptr_expr(),
extern_type_const_byteptr->DataTypeStr().c_str(), EvalLengthExpr(out_cc, env).c_str());
env->LValue(end_of_data),
data.ptr_expr(),
EvalLengthExpr(out_cc, env).c_str());
GenParseCode2(out_cc, env, data, flags); GenParseCode2(out_cc, env, data, flags);
@ -568,9 +537,8 @@ void Type::GenParseCode(Output* out_cc, Env* env, const DataPtr& data, int flags
void Type::GenBufferingLoop(Output* out_cc, Env* env, int flags) void Type::GenBufferingLoop(Output* out_cc, Env* env, int flags)
{ {
out_cc->println("while ( ! %s && %s->ready() )", out_cc->println("while ( ! %s && %s->ready() )", env->LValue(parsing_complete_var()),
env->LValue(parsing_complete_var()), env->LValue(flow_buffer_id));
env->LValue(flow_buffer_id));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
@ -586,22 +554,18 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags)
{ {
ASSERT(incremental_input()); ASSERT(incremental_input());
const ID *data_begin; const ID* data_begin;
if ( ! incremental_parsing() ) if ( ! incremental_parsing() )
{ {
env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr); env->AddID(begin_of_data, TEMP_VAR, extern_type_const_byteptr);
env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr); env->AddID(end_of_data, TEMP_VAR, extern_type_const_byteptr);
out_cc->println("%s %s = %s->begin();", out_cc->println("%s %s = %s->begin();", env->DataTypeStr(begin_of_data).c_str(),
env->DataTypeStr(begin_of_data).c_str(), env->LValue(begin_of_data), env->RValue(flow_buffer_id));
env->LValue(begin_of_data),
env->RValue(flow_buffer_id));
out_cc->println("%s %s = %s->end();", out_cc->println("%s %s = %s->end();", env->DataTypeStr(end_of_data).c_str(),
env->DataTypeStr(end_of_data).c_str(), env->LValue(end_of_data), env->RValue(flow_buffer_id));
env->LValue(end_of_data),
env->RValue(flow_buffer_id));
env->SetEvaluated(begin_of_data); env->SetEvaluated(begin_of_data);
env->SetEvaluated(end_of_data); env->SetEvaluated(end_of_data);
@ -615,9 +579,8 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags)
{ {
if ( incremental_parsing() ) if ( incremental_parsing() )
{ {
throw Exception(this, throw Exception(this, "cannot handle &until($input...) "
"cannot handle &until($input...) " "for incrementally parsed type");
"for incrementally parsed type");
} }
array_until_input_->GenUntilInputCheck(out_cc, env); array_until_input_->GenUntilInputCheck(out_cc, env);
} }
@ -627,8 +590,7 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags)
if ( attr_length_expr() ) if ( attr_length_expr() )
{ {
ASSERT(buffer_mode() == BUFFER_BY_LENGTH); ASSERT(buffer_mode() == BUFFER_BY_LENGTH);
out_cc->println("switch ( %s )", out_cc->println("switch ( %s )", env->LValue(buffering_state_id));
env->LValue(buffering_state_id));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
out_cc->println("case 0:"); out_cc->println("case 0:");
@ -646,9 +608,8 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags)
out_cc->println("%s = 2;", env->LValue(buffering_state_id)); out_cc->println("%s = 2;", env->LValue(buffering_state_id));
Env frame_length_env(env, this); Env frame_length_env(env, this);
out_cc->println("%s->GrowFrame(%s);", out_cc->println("%s->GrowFrame(%s);", env->LValue(flow_buffer_id),
env->LValue(flow_buffer_id), attr_length_expr_->EvalExpr(out_cc, &frame_length_env));
attr_length_expr_->EvalExpr(out_cc, &frame_length_env));
out_cc->println("}"); out_cc->println("}");
out_cc->println("break;"); out_cc->println("break;");
@ -656,20 +617,16 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags)
out_cc->println("case 2:"); out_cc->println("case 2:");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("BINPAC_ASSERT(%s->ready());", out_cc->println("BINPAC_ASSERT(%s->ready());", env->RValue(flow_buffer_id));
env->RValue(flow_buffer_id)); out_cc->println("if ( %s->ready() )", env->RValue(flow_buffer_id));
out_cc->println("if ( %s->ready() )",
env->RValue(flow_buffer_id));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
Env parse_env(env, this); Env parse_env(env, this);
GenParseCode2(out_cc, &parse_env, data, 0); GenParseCode2(out_cc, &parse_env, data, 0);
out_cc->println("BINPAC_ASSERT(%s);", out_cc->println("BINPAC_ASSERT(%s);", parsing_complete(env).c_str());
parsing_complete(env).c_str()); out_cc->println("%s = 0;", env->LValue(buffering_state_id));
out_cc->println("%s = 0;",
env->LValue(buffering_state_id));
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
@ -679,8 +636,7 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags)
out_cc->println("default:"); out_cc->println("default:");
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("BINPAC_ASSERT(%s <= 2);", out_cc->println("BINPAC_ASSERT(%s <= 2);", env->LValue(buffering_state_id));
env->LValue(buffering_state_id));
out_cc->println("break;"); out_cc->println("break;");
out_cc->dec_indent(); out_cc->dec_indent();
@ -689,8 +645,7 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags)
} }
else if ( attr_restofflow_ ) else if ( attr_restofflow_ )
{ {
out_cc->println("BINPAC_ASSERT(%s->eof());", out_cc->println("BINPAC_ASSERT(%s->eof());", env->RValue(flow_buffer_id));
env->RValue(flow_buffer_id));
GenParseCode2(out_cc, env, data, 0); GenParseCode2(out_cc, env, data, 0);
} }
else if ( buffer_mode() == BUFFER_BY_LINE ) else if ( buffer_mode() == BUFFER_BY_LINE )
@ -702,8 +657,7 @@ void Type::GenParseBuffer(Output* out_cc, Env* env, int flags)
GenParseCode2(out_cc, env, data, 0); GenParseCode2(out_cc, env, data, 0);
} }
void Type::GenParseCode2(Output* out_cc, Env* env, void Type::GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags)
const DataPtr& data, int flags)
{ {
DEBUG_MSG("GenParseCode2 for %s\n", data_id_str_.c_str()); DEBUG_MSG("GenParseCode2 for %s\n", data_id_str_.c_str());
@ -711,23 +665,18 @@ void Type::GenParseCode2(Output* out_cc, Env* env,
{ {
if ( incremental_parsing() ) if ( incremental_parsing() )
{ {
throw Exception(this, throw Exception(this, "cannot export raw data for incrementally parsed types");
"cannot export raw data for incrementally parsed types");
} }
out_cc->println("%s = const_bytestring(%s, %s);", out_cc->println("%s = const_bytestring(%s, %s);", env->LValue(sourcedata_id),
env->LValue(sourcedata_id), data.ptr_expr(), env->RValue(end_of_data));
data.ptr_expr(),
env->RValue(end_of_data));
env->SetEvaluated(sourcedata_id); env->SetEvaluated(sourcedata_id);
GenParseCode3(out_cc, env, data, flags); GenParseCode3(out_cc, env, data, flags);
string datasize_str = DataSize(out_cc, env, data); string datasize_str = DataSize(out_cc, env, data);
out_cc->println("%s.set_end(%s + %s);", out_cc->println("%s.set_end(%s + %s);", env->LValue(sourcedata_id), data.ptr_expr(),
env->LValue(sourcedata_id), datasize_str.c_str());
data.ptr_expr(),
datasize_str.c_str());
} }
else else
{ {
@ -737,15 +686,15 @@ void Type::GenParseCode2(Output* out_cc, Env* env,
void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags) void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags)
{ {
foreach(i, ExprList, attr_requires_) foreach (i, ExprList, attr_requires_)
{ {
Expr *req = *i; Expr* req = *i;
req->EvalExpr(out_cc, env); req->EvalExpr(out_cc, env);
} }
foreach(i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
Field *f = *i; Field* f = *i;
f->GenTempDecls(out_cc, env); f->GenTempDecls(out_cc, env);
} }
@ -759,17 +708,17 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag
} }
out_cc->println("// Evaluate 'let' and 'withinput' fields"); out_cc->println("// Evaluate 'let' and 'withinput' fields");
foreach(i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
Field *f = *i; Field* f = *i;
if ( f->tof() == LET_FIELD ) if ( f->tof() == LET_FIELD )
{ {
LetField *lf = static_cast<LetField *>(f); LetField* lf = static_cast<LetField*>(f);
lf->GenParseCode(out_cc, env); lf->GenParseCode(out_cc, env);
} }
else if ( f->tof() == WITHINPUT_FIELD ) else if ( f->tof() == WITHINPUT_FIELD )
{ {
WithInputField *af = static_cast<WithInputField *>(f); WithInputField* af = static_cast<WithInputField*>(f);
af->GenParseCode(out_cc, env); af->GenParseCode(out_cc, env);
} }
} }
@ -791,7 +740,7 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag
if ( size_var() ) if ( size_var() )
ASSERT(env->Evaluated(size_var())); ASSERT(env->Evaluated(size_var()));
foreach(i, ExprList, attr_enforces_) foreach (i, ExprList, attr_enforces_)
{ {
Expr* enforce = *i; Expr* enforce = *i;
const char* enforce_expr = enforce->EvalExpr(out_cc, env); const char* enforce_expr = enforce->EvalExpr(out_cc, env);
@ -803,20 +752,19 @@ void Type::GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flag
out_cc->println("}"); out_cc->println("}");
out_cc->dec_indent(); out_cc->dec_indent();
} }
} }
Type *Type::MemberDataType(const ID *member_id) const Type* Type::MemberDataType(const ID* member_id) const
{ {
DEBUG_MSG("MemberDataType: %s::%s\n", type_decl_id_->Name(), member_id->Name()); DEBUG_MSG("MemberDataType: %s::%s\n", type_decl_id_->Name(), member_id->Name());
ASSERT(env_); ASSERT(env_);
env_->set_allow_undefined_id(true); env_->set_allow_undefined_id(true);
Type *t = env_->GetDataType(member_id); Type* t = env_->GetDataType(member_id);
env_->set_allow_undefined_id(false); env_->set_allow_undefined_id(false);
return t; return t;
} }
Type *Type::ElementDataType() const Type* Type::ElementDataType() const
{ {
return 0; return 0;
} }
@ -837,13 +785,12 @@ bool Type::AddSizeVar(Output* out_cc, Env* env)
ASSERT(! incremental_input()); ASSERT(! incremental_input());
ID *size_var_id = new ID(strfmt("%s__size", ID* size_var_id = new ID(
value_var() ? value_var()->Name() : decl_id()->Name())); strfmt("%s__size", value_var() ? value_var()->Name() : decl_id()->Name()));
DEBUG_MSG("adding size var `%s' to env %p\n", size_var_id->Name(), env); DEBUG_MSG("adding size var `%s' to env %p\n", size_var_id->Name(), env);
size_var_field_ = new TempVarField( size_var_field_ = new TempVarField(size_var_id, extern_type_int->Clone());
size_var_id, extern_type_int->Clone());
size_var_field_->Prepare(env); size_var_field_->Prepare(env);
size_var_field_->GenTempDecls(out_cc, env); size_var_field_->GenTempDecls(out_cc, env);
@ -852,7 +799,7 @@ bool Type::AddSizeVar(Output* out_cc, Env* env)
string Type::EvalLengthExpr(Output* out_cc, Env* env) string Type::EvalLengthExpr(Output* out_cc, Env* env)
{ {
ASSERT(!incremental_input()); ASSERT(! incremental_input());
ASSERT(attr_length_expr_); ASSERT(attr_length_expr_);
int static_length; int static_length;
if ( attr_length_expr_->ConstFold(env, &static_length) ) if ( attr_length_expr_->ConstFold(env, &static_length) )
@ -860,9 +807,8 @@ string Type::EvalLengthExpr(Output* out_cc, Env* env)
// How do we make sure size_var is evaluated with attr_length_expr_? // How do we make sure size_var is evaluated with attr_length_expr_?
if ( AddSizeVar(out_cc, env) ) if ( AddSizeVar(out_cc, env) )
{ {
out_cc->println("%s = %s;", out_cc->println("%s = %s;", env->LValue(size_var()),
env->LValue(size_var()), attr_length_expr_->EvalExpr(out_cc, env));
attr_length_expr_->EvalExpr(out_cc, env));
env->SetEvaluated(size_var()); env->SetEvaluated(size_var());
} }
return env->RValue(size_var()); return env->RValue(size_var());
@ -890,15 +836,12 @@ string Type::DataSize(Output* out_cc, Env* env, const DataPtr& data)
} }
} }
void Type::GenBoundaryCheck(Output* out_cc, Env* env, void Type::GenBoundaryCheck(Output* out_cc, Env* env, const DataPtr& data)
const DataPtr& data)
{ {
if ( boundary_checked() ) if ( boundary_checked() )
return; return;
data.GenBoundaryCheck(out_cc, env, data.GenBoundaryCheck(out_cc, env, DataSize(out_cc, env, data).c_str(), data_id_str_.c_str());
DataSize(out_cc, env, data).c_str(),
data_id_str_.c_str());
SetBoundaryChecked(); SetBoundaryChecked();
} }
@ -928,7 +871,7 @@ bool Type::RequiresByteOrder() const
bool Type::NeedsBufferingStateVar() const bool Type::NeedsBufferingStateVar() const
{ {
if ( !incremental_input() ) if ( ! incremental_input() )
return false; return false;
switch ( buffer_mode() ) switch ( buffer_mode() )
{ {
@ -938,14 +881,14 @@ bool Type::NeedsBufferingStateVar() const
case BUFFER_BY_LINE: case BUFFER_BY_LINE:
return true; return true;
case BUFFER_BY_LENGTH: case BUFFER_BY_LENGTH:
return ( attr_length_expr_ || attr_restofflow_ ); return (attr_length_expr_ || attr_restofflow_);
default: default:
ASSERT(0); ASSERT(0);
return false; return false;
} }
} }
bool Type::DoTraverse(DataDepVisitor *visitor) bool Type::DoTraverse(DataDepVisitor* visitor)
{ {
foreach (i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
@ -953,7 +896,7 @@ bool Type::DoTraverse(DataDepVisitor *visitor)
return false; return false;
} }
foreach(i, AttrList, attrs_) foreach (i, AttrList, attrs_)
{ {
if ( ! (*i)->Traverse(visitor) ) if ( ! (*i)->Traverse(visitor) )
return false; return false;
@ -971,12 +914,12 @@ bool Type::RequiresAnalyzerContext()
foreach (i, FieldList, fields_) foreach (i, FieldList, fields_)
{ {
Field *f = *i; Field* f = *i;
if ( f->RequiresAnalyzerContext() ) if ( f->RequiresAnalyzerContext() )
return true; return true;
} }
foreach(i, AttrList, attrs_) foreach (i, AttrList, attrs_)
if ( (*i)->RequiresAnalyzerContext() ) if ( (*i)->RequiresAnalyzerContext() )
return true; return true;
@ -985,14 +928,13 @@ bool Type::RequiresAnalyzerContext()
bool Type::IsEmptyType() const bool Type::IsEmptyType() const
{ {
return ( StaticSize(global_env()) == 0 ); return (StaticSize(global_env()) == 0);
} }
void Type::MarkIncrementalInput() void Type::MarkIncrementalInput()
{ {
DEBUG_MSG("Handle incremental input for %s.%s\n", DEBUG_MSG("Handle incremental input for %s.%s\n", decl_id()->Name(),
decl_id()->Name(), value_var() ? value_var()->Name() : "*");
value_var() ? value_var()->Name() : "*");
incremental_input_ = true; incremental_input_ = true;
if ( Bufferable() ) if ( Bufferable() )
@ -1049,7 +991,7 @@ Type::BufferMode Type::buffer_mode() const
return NOT_BUFFERABLE; return NOT_BUFFERABLE;
} }
const ID *Type::parsing_complete_var() const const ID* Type::parsing_complete_var() const
{ {
if ( parsing_complete_var_field_ ) if ( parsing_complete_var_field_ )
return parsing_complete_var_field_->id(); return parsing_complete_var_field_->id();
@ -1057,13 +999,13 @@ const ID *Type::parsing_complete_var() const
return 0; return 0;
} }
string Type::parsing_complete(Env *env) const string Type::parsing_complete(Env* env) const
{ {
ASSERT(parsing_complete_var()); ASSERT(parsing_complete_var());
return env->RValue(parsing_complete_var()); return env->RValue(parsing_complete_var());
} }
const ID *Type::has_value_var() const const ID* Type::has_value_var() const
{ {
if ( has_value_field_ ) if ( has_value_field_ )
return has_value_field_->id(); return has_value_field_->id();
@ -1078,7 +1020,7 @@ int Type::InitialBufferLength() const
return attr_length_expr_->MinimalHeaderSize(env()); return attr_length_expr_->MinimalHeaderSize(env());
} }
bool Type::CompatibleTypes(Type *type1, Type *type2) bool Type::CompatibleTypes(Type* type1, Type* type2)
{ {
// If we cannot deduce one of the data types, assume that // If we cannot deduce one of the data types, assume that
// they are compatible. // they are compatible.
@ -1097,17 +1039,15 @@ bool Type::CompatibleTypes(Type *type1, Type *type2)
return false; return false;
} }
switch( type1->tot() ) switch ( type1->tot() )
{ {
case UNDEF: case UNDEF:
case EMPTY: case EMPTY:
return true; return true;
case BUILTIN: case BUILTIN:
{ {
BuiltInType *t1 = BuiltInType* t1 = static_cast<BuiltInType*>(type1);
static_cast<BuiltInType *>(type1); BuiltInType* t2 = static_cast<BuiltInType*>(type2);
BuiltInType *t2 =
static_cast<BuiltInType *>(type2);
return BuiltInType::CompatibleBuiltInTypes(t1, t2); return BuiltInType::CompatibleBuiltInTypes(t1, t2);
} }
@ -1120,12 +1060,9 @@ bool Type::CompatibleTypes(Type *type1, Type *type2)
case ARRAY: case ARRAY:
{ {
ArrayType *t1 = ArrayType* t1 = static_cast<ArrayType*>(type1);
static_cast<ArrayType *>(type1); ArrayType* t2 = static_cast<ArrayType*>(type2);
ArrayType *t2 = return CompatibleTypes(t1->ElementDataType(), t2->ElementDataType());
static_cast<ArrayType *>(type2);
return CompatibleTypes(t1->ElementDataType(),
t2->ElementDataType());
} }
default: default:
@ -1134,7 +1071,7 @@ bool Type::CompatibleTypes(Type *type1, Type *type2)
} }
} }
Type *Type::LookUpByID(ID *id) Type* Type::LookUpByID(ID* id)
{ {
// 1. Is it a pre-defined type? // 1. Is it a pre-defined type?
string name = id->Name(); string name = id->Name();
@ -1144,7 +1081,7 @@ Type *Type::LookUpByID(ID *id)
} }
// 2. Is it a simple declared type? // 2. Is it a simple declared type?
Type *type = TypeDecl::LookUpType(id); Type* type = TypeDecl::LookUpType(id);
if ( type ) if ( type )
{ {
// Note: as a Type is always associated with a variable, // Note: as a Type is always associated with a variable,
@ -1153,10 +1090,10 @@ Type *Type::LookUpByID(ID *id)
{ {
case Type::BUILTIN: case Type::BUILTIN:
case Type::EXTERN: case Type::EXTERN:
case Type::STRING: case Type::STRING:
return type->Clone(); return type->Clone();
case Type::ARRAY: case Type::ARRAY:
default: default:
break; break;
} }
@ -1165,7 +1102,7 @@ Type *Type::LookUpByID(ID *id)
return new ParameterizedType(id, 0); return new ParameterizedType(id, 0);
} }
void Type::AddPredefinedType(const string &type_name, Type *type) void Type::AddPredefinedType(const string& type_name, Type* type)
{ {
ASSERT(type_map_.find(type_name) == type_map_.end()); ASSERT(type_map_.find(type_name) == type_map_.end());
type_map_[type_name] = type; type_map_[type_name] = type;

View file

@ -9,9 +9,10 @@ using namespace std;
#include "pac_dbg.h" #include "pac_dbg.h"
class Type : public Object, public DataDepElement class Type : public Object, public DataDepElement
{ {
public: public:
enum TypeType { enum TypeType
{
UNDEF = -1, UNDEF = -1,
EMPTY, EMPTY,
BUILTIN, BUILTIN,
@ -22,31 +23,31 @@ public:
STRING, STRING,
EXTERN, EXTERN,
DUMMY, DUMMY,
}; };
explicit Type(TypeType tot); explicit Type(TypeType tot);
virtual ~Type(); virtual ~Type();
Type *Clone() const; Type* Clone() const;
// Type of type // Type of type
TypeType tot() const { return tot_; } TypeType tot() const { return tot_; }
//////////////////////////////////////// ////////////////////////////////////////
// Code generation // Code generation
virtual void Prepare(Env *env, int flags); virtual void Prepare(Env* env, int flags);
// Flag(s) for Prepare() // Flag(s) for Prepare()
static const int TO_BE_PARSED = 1; static const int TO_BE_PARSED = 1;
virtual void GenPubDecls(Output *out, Env *env); virtual void GenPubDecls(Output* out, Env* env);
virtual void GenPrivDecls(Output *out, Env *env); virtual void GenPrivDecls(Output* out, Env* env);
virtual void GenInitCode(Output *out, Env *env); virtual void GenInitCode(Output* out, Env* env);
virtual void GenCleanUpCode(Output *out, Env *env); virtual void GenCleanUpCode(Output* out, Env* env);
void GenPreParsing(Output *out, Env *env); void GenPreParsing(Output* out, Env* env);
void GenParseCode(Output *out, Env *env, const DataPtr& data, int flags); void GenParseCode(Output* out, Env* env, const DataPtr& data, int flags);
//////////////////////////////////////// ////////////////////////////////////////
// TODO: organize the various methods below // TODO: organize the various methods below
@ -57,50 +58,51 @@ public:
// if the type appears in a type decl, then the lvalue is the // if the type appears in a type decl, then the lvalue is the
// default value var. // default value var.
// //
const char *lvalue() const { return lvalue_.c_str(); } const char* lvalue() const { return lvalue_.c_str(); }
// The TypeDecl that defined the type. // The TypeDecl that defined the type.
// //
const TypeDecl *type_decl() const { return type_decl_; } const TypeDecl* type_decl() const { return type_decl_; }
void set_type_decl(const TypeDecl *decl, bool declared_as_type); void set_type_decl(const TypeDecl* decl, bool declared_as_type);
// Returns whether the type appears in a type declaration // Returns whether the type appears in a type declaration
// (true) or as type specification of a field (false). // (true) or as type specification of a field (false).
// //
bool declared_as_type() const { return declared_as_type_; } bool declared_as_type() const { return declared_as_type_; }
// The ID of the decl in which the type appear. // The ID of the decl in which the type appear.
// //
const ID *decl_id() const; const ID* decl_id() const;
Env *env() const { return env_; } Env* env() const { return env_; }
string EvalByteOrder(Output *out_cc, Env *env) const; string EvalByteOrder(Output* out_cc, Env* env) const;
virtual string EvalMember(const ID *member_id) const; virtual string EvalMember(const ID* member_id) const;
virtual string EvalElement(const string &array, virtual string EvalElement(const string& array, const string& index) const;
const string &index) const;
// The variable defined by the type // The variable defined by the type
const ID *value_var() const { return value_var_; } const ID* value_var() const { return value_var_; }
void set_value_var(const ID *arg_id, int arg_id_type); void set_value_var(const ID* arg_id, int arg_id_type);
bool anonymous_value_var() const { return anonymous_value_var_; } bool anonymous_value_var() const { return anonymous_value_var_; }
const ID *size_var() const; const ID* size_var() const;
// Adds a variable to env to represent the size of this type. // Adds a variable to env to represent the size of this type.
// Returns false if we do not need a size variable (because // Returns false if we do not need a size variable (because
// the type has a static size) or the size variable is already added. // the type has a static size) or the size variable is already added.
bool AddSizeVar(Output *out, Env *env); bool AddSizeVar(Output* out, Env* env);
const ID *parsing_state_var() const; const ID* parsing_state_var() const;
const ID *has_value_var() const; const ID* has_value_var() const;
void AddField(Field *f); void AddField(Field* f);
void AddCheck(Expr *expr) { /* TODO */ } void AddCheck(Expr* expr)
{ /* TODO */
}
virtual bool DefineValueVar() const = 0; virtual bool DefineValueVar() const = 0;
@ -120,14 +122,15 @@ public:
// Returns a default value for the type // Returns a default value for the type
virtual string DefaultValue() const virtual string DefaultValue() const
{ {
ASSERT(0); return "@@@"; ASSERT(0);
return "@@@";
} }
// Returns the data type of the member field/case // Returns the data type of the member field/case
virtual Type *MemberDataType(const ID *member_id) const; virtual Type* MemberDataType(const ID* member_id) const;
// Returns the data type of the element type of an array // Returns the data type of the element type of an array
virtual Type *ElementDataType() const; virtual Type* ElementDataType() const;
// Whether the type needs clean-up at deallocation. // Whether the type needs clean-up at deallocation.
bool NeedsCleanUp() const; bool NeedsCleanUp() const;
@ -139,37 +142,34 @@ public:
virtual bool RequiresAnalyzerContext(); virtual bool RequiresAnalyzerContext();
virtual bool IsPointerType() const = 0; virtual bool IsPointerType() const = 0;
virtual bool IsNumericType() const { return false; } virtual bool IsNumericType() const { return false; }
bool IsEmptyType() const; bool IsEmptyType() const;
//////////////////////////////////////// ////////////////////////////////////////
// Attributes // Attributes
virtual void ProcessAttr(Attr *a); virtual void ProcessAttr(Attr* a);
bool attr_chunked() const { return attr_chunked_; } bool attr_chunked() const { return attr_chunked_; }
Expr *attr_byteorder_expr() const { return attr_byteorder_expr_; } Expr* attr_byteorder_expr() const { return attr_byteorder_expr_; }
Expr *attr_if_expr() const { return attr_if_expr_; } Expr* attr_if_expr() const { return attr_if_expr_; }
// TODO: generate the length expression automatically. // TODO: generate the length expression automatically.
Expr *attr_length_expr() const { return attr_length_expr_; } Expr* attr_length_expr() const { return attr_length_expr_; }
bool attr_refcount() const { return attr_refcount_; } bool attr_refcount() const { return attr_refcount_; }
bool attr_transient() const { return attr_transient_; } bool attr_transient() const { return attr_transient_; }
// Whether the value remains valid outside the parse function // Whether the value remains valid outside the parse function
bool persistent() const bool persistent() const { return ! attr_transient() && ! attr_chunked(); }
{
return ! attr_transient() && ! attr_chunked();
}
void SetUntilCheck(ArrayType *t) { array_until_input_ = t; } void SetUntilCheck(ArrayType* t) { array_until_input_ = t; }
//////////////////////////////////////// ////////////////////////////////////////
// Size and boundary checking // Size and boundary checking
virtual int StaticSize(Env *env) const = 0; virtual int StaticSize(Env* env) const = 0;
string DataSize(Output *out, Env *env, const DataPtr& data); string DataSize(Output* out, Env* env, const DataPtr& data);
bool boundary_checked() const { return boundary_checked_; } bool boundary_checked() const { return boundary_checked_; }
virtual void SetBoundaryChecked() { boundary_checked_ = true; } virtual void SetBoundaryChecked() { boundary_checked_ = true; }
void GenBoundaryCheck(Output *out, Env *env, const DataPtr& data); void GenBoundaryCheck(Output* out, Env* env, const DataPtr& data);
//////////////////////////////////////// ////////////////////////////////////////
// Handling incremental input // Handling incremental input
@ -185,17 +185,17 @@ public:
virtual void DoMarkIncrementalInput(); virtual void DoMarkIncrementalInput();
// Whether the type may receive incremental input // Whether the type may receive incremental input
bool incremental_input() const { return incremental_input_; } bool incremental_input() const { return incremental_input_; }
// Whether parsing should also be incremental // Whether parsing should also be incremental
bool incremental_parsing() const { return incremental_parsing_; } bool incremental_parsing() const { return incremental_parsing_; }
// Whether we should buffer the input // Whether we should buffer the input
bool buffer_input() const { return buffer_input_; } bool buffer_input() const { return buffer_input_; }
// Whether parsing of the type is completed // Whether parsing of the type is completed
const ID *parsing_complete_var() const; const ID* parsing_complete_var() const;
string parsing_complete(Env *env) const; string parsing_complete(Env* env) const;
// Whether the input is bufferable // Whether the input is bufferable
bool Bufferable() const; bool Bufferable() const;
@ -204,20 +204,21 @@ public:
bool BufferableWithLineBreaker() const; bool BufferableWithLineBreaker() const;
Expr* LineBreaker() const; Expr* LineBreaker() const;
enum BufferMode { enum BufferMode
{
NOT_BUFFERABLE, NOT_BUFFERABLE,
BUFFER_NOTHING, // for type "empty" BUFFER_NOTHING, // for type "empty"
BUFFER_BY_LENGTH, BUFFER_BY_LENGTH,
BUFFER_BY_LINE, BUFFER_BY_LINE,
}; };
virtual BufferMode buffer_mode() const; virtual BufferMode buffer_mode() const;
void GenBufferConfiguration(Output *out, Env *env); void GenBufferConfiguration(Output* out, Env* env);
int InitialBufferLength() const; int InitialBufferLength() const;
protected: protected:
virtual void GenNewInstance(Output *out, Env *env) {} virtual void GenNewInstance(Output* out, Env* env) { }
virtual bool ByteOrderSensitive() const = 0; virtual bool ByteOrderSensitive() const = 0;
@ -228,86 +229,83 @@ protected:
void GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags); void GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags);
void GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags); void GenParseCode3(Output* out_cc, Env* env, const DataPtr& data, int flags);
virtual void DoGenParseCode(Output *out, Env *env, virtual void DoGenParseCode(Output* out, Env* env, const DataPtr& data, int flags) = 0;
const DataPtr& data,
int flags) = 0;
string EvalLengthExpr(Output* out_cc, Env* env); string EvalLengthExpr(Output* out_cc, Env* env);
// Generate code for computing the dynamic size of the type // Generate code for computing the dynamic size of the type
virtual void GenDynamicSize(Output *out, Env *env, virtual void GenDynamicSize(Output* out, Env* env, const DataPtr& data) = 0;
const DataPtr& data) = 0;
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
virtual Type *DoClone() const = 0; virtual Type* DoClone() const = 0;
protected: protected:
TypeType tot_; TypeType tot_;
const TypeDecl *type_decl_; const TypeDecl* type_decl_;
bool declared_as_type_; bool declared_as_type_;
const ID *type_decl_id_; const ID* type_decl_id_;
Env *env_; Env* env_;
const ID *value_var_; const ID* value_var_;
bool anonymous_value_var_; // whether the ID is anonymous bool anonymous_value_var_; // whether the ID is anonymous
string data_id_str_; string data_id_str_;
int value_var_type_; int value_var_type_;
Field *size_var_field_; Field* size_var_field_;
char *size_expr_; char* size_expr_;
bool boundary_checked_; bool boundary_checked_;
string lvalue_; string lvalue_;
FieldList *fields_; FieldList* fields_;
bool incremental_input_; bool incremental_input_;
bool incremental_parsing_; bool incremental_parsing_;
bool buffer_input_; bool buffer_input_;
// A boolean variable on whether parsing of the type is completed // A boolean variable on whether parsing of the type is completed
Field *parsing_complete_var_field_; Field* parsing_complete_var_field_;
// An integer variable holding the parsing state // An integer variable holding the parsing state
Field *parsing_state_var_field_; Field* parsing_state_var_field_;
Field *buffering_state_var_field_; Field* buffering_state_var_field_;
// The array type with &until($input...) condition, if // The array type with &until($input...) condition, if
// "this" is the element type // "this" is the element type
ArrayType *array_until_input_; ArrayType* array_until_input_;
// A "has_*" member var for fields with &if // A "has_*" member var for fields with &if
LetField *has_value_field_; LetField* has_value_field_;
// Attributes // Attributes
AttrList *attrs_; AttrList* attrs_;
Expr *attr_byteorder_expr_; Expr* attr_byteorder_expr_;
ExprList *attr_checks_; ExprList* attr_checks_;
ExprList *attr_enforces_; ExprList* attr_enforces_;
bool attr_chunked_; bool attr_chunked_;
bool attr_exportsourcedata_; bool attr_exportsourcedata_;
Expr *attr_if_expr_; Expr* attr_if_expr_;
Expr *attr_length_expr_; Expr* attr_length_expr_;
FieldList *attr_letfields_; FieldList* attr_letfields_;
Expr *attr_multiline_end_; Expr* attr_multiline_end_;
Expr *attr_linebreaker_; Expr* attr_linebreaker_;
bool attr_oneline_; bool attr_oneline_;
bool attr_refcount_; bool attr_refcount_;
ExprList *attr_requires_; ExprList* attr_requires_;
bool attr_restofdata_; bool attr_restofdata_;
bool attr_restofflow_; bool attr_restofflow_;
bool attr_transient_; bool attr_transient_;
public: public:
static void init(); static void init();
static bool CompatibleTypes(Type *type1, Type *type2); static bool CompatibleTypes(Type* type1, Type* type2);
static void AddPredefinedType(const string &type_name, Type *type); static void AddPredefinedType(const string& type_name, Type* type);
static Type *LookUpByID(ID *id); static Type* LookUpByID(ID* id);
protected: protected:
typedef map<string, Type *> type_map_t; typedef map<string, Type*> type_map_t;
static type_map_t type_map_; static type_map_t type_map_;
}; };
#endif // pac_type_h #endif // pac_type_h

View file

@ -1,3 +1,5 @@
#include "pac_typedecl.h"
#include "pac_attr.h" #include "pac_attr.h"
#include "pac_context.h" #include "pac_context.h"
#include "pac_dataptr.h" #include "pac_dataptr.h"
@ -12,7 +14,6 @@
#include "pac_paramtype.h" #include "pac_paramtype.h"
#include "pac_record.h" #include "pac_record.h"
#include "pac_type.h" #include "pac_type.h"
#include "pac_typedecl.h"
#include "pac_utils.h" #include "pac_utils.h"
TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type) TypeDecl::TypeDecl(ID* id, ParamList* params, Type* type)
@ -35,7 +36,7 @@ void TypeDecl::ProcessAttr(Attr* a)
type_->ProcessAttr(a); type_->ProcessAttr(a);
} }
void TypeDecl::AddParam(Param *param) void TypeDecl::AddParam(Param* param)
{ {
// Cannot work after Prepare() // Cannot work after Prepare()
ASSERT(! env_); ASSERT(! env_);
@ -65,11 +66,9 @@ void TypeDecl::Prepare()
if ( type_->attr_byteorder_expr() ) if ( type_->attr_byteorder_expr() )
{ {
DEBUG_MSG("Adding byteorder field to %s\n", DEBUG_MSG("Adding byteorder field to %s\n", id()->Name());
id()->Name()); type_->AddField(
type_->AddField(new LetField(byteorder_id->clone(), new LetField(byteorder_id->clone(), extern_type_int, type_->attr_byteorder_expr()));
extern_type_int,
type_->attr_byteorder_expr()));
} }
type_->Prepare(env_, Type::TO_BE_PARSED); type_->Prepare(env_, Type::TO_BE_PARSED);
@ -99,13 +98,11 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc)
if ( RequiresAnalyzerContext::compute(type_) ) if ( RequiresAnalyzerContext::compute(type_) )
{ {
DEBUG_MSG("%s requires analyzer context\n", DEBUG_MSG("%s requires analyzer context\n", id()->Name());
id()->Name()); Type* param_type = analyzer_context()->param_type();
Type *param_type = analyzer_context()->param_type();
env_->AddID(analyzer_context_id, TEMP_VAR, param_type); env_->AddID(analyzer_context_id, TEMP_VAR, param_type);
env_->SetEvaluated(analyzer_context_id); env_->SetEvaluated(analyzer_context_id);
env_->AddMacro(context_macro_id, env_->AddMacro(context_macro_id, new Expr(analyzer_context_id->clone()));
new Expr(analyzer_context_id->clone()));
} }
// Add parameter "byteorder" // Add parameter "byteorder"
@ -170,30 +167,25 @@ void TypeDecl::GenCode(Output* out_h, Output* out_cc)
out_h->println("};\n"); out_h->println("};\n");
} }
void TypeDecl::GenPubDecls(Output* out_h, Output *out_cc) void TypeDecl::GenPubDecls(Output* out_h, Output* out_cc)
{ {
// GenParamPubDecls(params_, out_h, env_); // GenParamPubDecls(params_, out_h, env_);
} }
void TypeDecl::GenPrivDecls(Output* out_h, Output *out_cc) void TypeDecl::GenPrivDecls(Output* out_h, Output* out_cc)
{ {
// GenParamPrivDecls(params_, out_h, env_); // GenParamPrivDecls(params_, out_h, env_);
} }
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 params_str = ParamDecls(params_);
string proto = string proto = strfmt("%s(%s)", class_name().c_str(), params_str.c_str());
strfmt("%s(%s)", class_name().c_str(), params_str.c_str());
out_h->println("%s;", proto.c_str()); out_h->println("%s;", proto.c_str());
@ -230,32 +222,29 @@ void TypeDecl::GenDestructorFunc(Output* out_h, Output* out_cc)
string TypeDecl::ParseFuncPrototype(Env* env) string TypeDecl::ParseFuncPrototype(Env* env)
{ {
const char *func_name = 0; const char* func_name = 0;
const char *return_type = 0; const char* return_type = 0;
string params; string params;
if ( type_->incremental_input() ) if ( type_->incremental_input() )
{ {
func_name = kParseFuncWithBuffer; func_name = kParseFuncWithBuffer;
return_type = "bool"; return_type = "bool";
params = strfmt("flow_buffer_t %s", params = strfmt("flow_buffer_t %s", env->LValue(flow_buffer_id));
env->LValue(flow_buffer_id));
} }
else else
{ {
func_name = kParseFuncWithoutBuffer; func_name = kParseFuncWithoutBuffer;
return_type = "int"; return_type = "int";
params = strfmt("const_byteptr const %s, const_byteptr const %s", params = strfmt("const_byteptr const %s, const_byteptr const %s",
env->LValue(begin_of_data), env->LValue(begin_of_data), env->LValue(end_of_data));
env->LValue(end_of_data));
} }
if ( RequiresAnalyzerContext::compute(type_) ) if ( RequiresAnalyzerContext::compute(type_) )
{ {
Type *param_type = analyzer_context()->param_type(); Type* param_type = analyzer_context()->param_type();
params += strfmt(", %s %s", params += strfmt(", %s %s", param_type->DataTypeConstRefStr().c_str(),
param_type->DataTypeConstRefStr().c_str(), env->LValue(analyzer_context_id));
env->LValue(analyzer_context_id));
} }
// Add parameter "byteorder" // Add parameter "byteorder"
@ -265,11 +254,10 @@ string TypeDecl::ParseFuncPrototype(Env* env)
} }
// Returns "<return type> %s<func name>(<params>)%s". // Returns "<return type> %s<func name>(<params>)%s".
return strfmt("%s %%s%s(%s)%%s", return strfmt("%s %%s%s(%s)%%s", return_type, func_name, params.c_str());
return_type, func_name, params.c_str());
} }
void TypeDecl::GenParsingEnd(Output *out_cc, Env *env, const DataPtr &data) void TypeDecl::GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data)
{ {
string ret_val_0, ret_val_1; string ret_val_0, ret_val_1;
@ -283,27 +271,23 @@ void TypeDecl::GenParsingEnd(Output *out_cc, Env *env, const DataPtr &data)
ret_val_0 = type_->DataSize(0, env, data).c_str(); ret_val_0 = type_->DataSize(0, env, data).c_str();
ret_val_1 = "@@@"; ret_val_1 = "@@@";
out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", out_cc->println("BINPAC_ASSERT(%s + (%s) <= %s);", env->RValue(begin_of_data),
env->RValue(begin_of_data), ret_val_0.c_str(), env->RValue(end_of_data));
ret_val_0.c_str(),
env->RValue(end_of_data));
} }
if ( type_->incremental_parsing() && if ( type_->incremental_parsing() &&
( type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY ) ) (type_->tot() == Type::RECORD || type_->tot() == Type::ARRAY) )
{ {
// In which case parsing may jump to label // In which case parsing may jump to label
// "need_more_data" ... // "need_more_data" ...
out_cc->println("BINPAC_ASSERT(%s);", out_cc->println("BINPAC_ASSERT(%s);", type_->parsing_complete(env).c_str());
type_->parsing_complete(env).c_str());
out_cc->println("return %s;", ret_val_0.c_str()); out_cc->println("return %s;", ret_val_0.c_str());
out_cc->println(""); out_cc->println("");
out_cc->dec_indent(); out_cc->dec_indent();
out_cc->println("%s:", kNeedMoreData); out_cc->println("%s:", kNeedMoreData);
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("BINPAC_ASSERT(!(%s));", out_cc->println("BINPAC_ASSERT(!(%s));", type_->parsing_complete(env).c_str());
type_->parsing_complete(env).c_str());
out_cc->println("return %s;", ret_val_1.c_str()); out_cc->println("return %s;", ret_val_1.c_str());
} }
else if ( type_->incremental_input() ) else if ( type_->incremental_input() )
@ -323,7 +307,7 @@ void TypeDecl::GenParseFunc(Output* out_h, Output* out_cc)
// Env within the parse function // Env within the parse function
Env p_func_env(env_, this); Env p_func_env(env_, this);
Env *env = &p_func_env; Env* env = &p_func_env;
if ( type_->incremental_input() ) if ( type_->incremental_input() )
{ {
@ -380,21 +364,19 @@ void TypeDecl::GenInitialBufferLengthFunc(Output* out_h, Output* out_cc)
int init_buffer_length = type_->InitialBufferLength(); int init_buffer_length = type_->InitialBufferLength();
if ( init_buffer_length < 0 ) // cannot be statically determined if ( init_buffer_length < 0 ) // cannot be statically determined
{ {
throw Exception(type()->attr_length_expr(), throw Exception(type()->attr_length_expr(), strfmt("cannot determine initial buffer length"
strfmt("cannot determine initial buffer length" " for type %s",
" for type %s", id_->Name())); id_->Name()));
} }
out_h->println("int %s() const { return %d; }", out_h->println("int %s() const { return %d; }", func.c_str(), init_buffer_length);
func.c_str(),
init_buffer_length);
} }
Type* TypeDecl::LookUpType(const ID *id) Type* TypeDecl::LookUpType(const ID* id)
{ {
Decl *decl = LookUpDecl(id); Decl* decl = LookUpDecl(id);
if ( ! decl ) if ( ! decl )
return 0; return 0;
switch ( decl->decl_type() ) switch ( decl->decl_type() )
@ -402,11 +384,10 @@ Type* TypeDecl::LookUpType(const ID *id)
case TYPE: case TYPE:
case CONN: case CONN:
case FLOW: case FLOW:
return static_cast<TypeDecl *>(decl)->type(); return static_cast<TypeDecl*>(decl)->type();
case ENUM: case ENUM:
return static_cast<EnumDecl *>(decl)->DataType(); return static_cast<EnumDecl*>(decl)->DataType();
default: default:
return 0; return 0;
} }
} }

View file

@ -4,44 +4,44 @@
#include "pac_decl.h" #include "pac_decl.h"
class TypeDecl : public Decl class TypeDecl : public Decl
{ {
public: public:
TypeDecl(ID *arg_id, ParamList *arg_params, Type *arg_type); TypeDecl(ID* arg_id, ParamList* arg_params, Type* arg_type);
~TypeDecl(); ~TypeDecl();
void Prepare(); void Prepare();
void GenForwardDeclaration(Output *out_h); void GenForwardDeclaration(Output* out_h);
void GenCode(Output *out_h, Output *out_cc); void GenCode(Output* out_h, Output* out_cc);
Env *env() const { return env_; } Env* env() const { return env_; }
Type *type() const { return type_; } Type* type() const { return type_; }
string class_name() const; string class_name() const;
static Type *LookUpType(const ID *id); static Type* LookUpType(const ID* id);
protected: protected:
void AddParam(Param *param); void AddParam(Param* param);
virtual void AddBaseClass(vector<string> *base_classes) const {} virtual void AddBaseClass(vector<string>* base_classes) const { }
void ProcessAttr(Attr *a); void ProcessAttr(Attr* a);
virtual void GenPubDecls(Output *out_h, Output *out_cc); virtual void GenPubDecls(Output* out_h, Output* out_cc);
virtual void GenPrivDecls(Output *out_h, Output *out_cc); virtual void GenPrivDecls(Output* out_h, Output* out_cc);
virtual void GenInitCode(Output *out_cc); virtual void GenInitCode(Output* out_cc);
virtual void GenCleanUpCode(Output *out_cc); virtual void GenCleanUpCode(Output* out_cc);
void GenConstructorFunc(Output *out_h, Output *out_cc); void GenConstructorFunc(Output* out_h, Output* out_cc);
void GenDestructorFunc(Output *out_h, Output *out_cc); void GenDestructorFunc(Output* out_h, Output* out_cc);
string ParseFuncPrototype(Env* env); string ParseFuncPrototype(Env* env);
void GenParseFunc(Output *out_h, Output *out_cc); void GenParseFunc(Output* out_h, Output* out_cc);
void GenParsingEnd(Output *out_cc, Env *env, const DataPtr &data); void GenParsingEnd(Output* out_cc, Env* env, const DataPtr& data);
void GenInitialBufferLengthFunc(Output *out_h, Output *out_cc); void GenInitialBufferLengthFunc(Output* out_h, Output* out_cc);
protected: protected:
Env *env_; Env* env_;
ParamList *params_; ParamList* params_;
Type *type_; Type* type_;
}; };
#endif // pac_typedecl_h #endif // pac_typedecl_h

View file

@ -1,17 +1,18 @@
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "pac_utils.h" #include "pac_utils.h"
char* copy_string(const char* s) #include <stdarg.h>
{ #include <stdio.h>
char* c = new char[strlen(s)+1]; #include <string.h>
strcpy(c, s);
return c;
}
namespace { char* copy_string(const char* s)
{
char* c = new char[strlen(s) + 1];
strcpy(c, s);
return c;
}
namespace
{
const char* do_fmt(const char* format, va_list ap) const char* do_fmt(const char* format, va_list ap)
{ {
@ -20,7 +21,7 @@ const char* do_fmt(const char* format, va_list ap)
return buf; return buf;
} }
} }
string strfmt(const char* format, ...) string strfmt(const char* format, ...)
{ {

View file

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

View file

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

View file

@ -1,14 +1,13 @@
#include "pac_withinput.h" #include "pac_withinput.h"
#include "pac_dataptr.h" #include "pac_dataptr.h"
#include "pac_expr.h" #include "pac_expr.h"
#include "pac_inputbuf.h" #include "pac_inputbuf.h"
#include "pac_output.h" #include "pac_output.h"
#include "pac_type.h" #include "pac_type.h"
WithInputField::WithInputField(ID* id, Type *type, InputBuffer* input) WithInputField::WithInputField(ID* id, Type* type, InputBuffer* input)
: Field(WITHINPUT_FIELD, : Field(WITHINPUT_FIELD, TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, id, type),
TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE,
id, type),
input_(input) input_(input)
{ {
ASSERT(type_); ASSERT(type_);
@ -20,16 +19,14 @@ WithInputField::~WithInputField()
delete input_; delete input_;
} }
bool WithInputField::DoTraverse(DataDepVisitor *visitor) bool WithInputField::DoTraverse(DataDepVisitor* visitor)
{ {
return Field::DoTraverse(visitor) && return Field::DoTraverse(visitor) && input()->Traverse(visitor);
input()->Traverse(visitor);
} }
bool WithInputField::RequiresAnalyzerContext() const bool WithInputField::RequiresAnalyzerContext() const
{ {
return Field::RequiresAnalyzerContext() || return Field::RequiresAnalyzerContext() || (input() && input()->RequiresAnalyzerContext());
(input() && input()->RequiresAnalyzerContext());
} }
void WithInputField::Prepare(Env* env) void WithInputField::Prepare(Env* env)
@ -43,8 +40,7 @@ void WithInputField::GenEval(Output* out_cc, Env* env)
GenParseCode(out_cc, env); GenParseCode(out_cc, env);
if ( type_->attr_if_expr() ) if ( type_->attr_if_expr() )
{ {
out_cc->println("BINPAC_ASSERT(%s);", out_cc->println("BINPAC_ASSERT(%s);", env->RValue(type_->has_value_var()));
env->RValue(type_->has_value_var()));
} }
} }
@ -55,8 +51,7 @@ void WithInputField::GenParseCode(Output* out_cc, Env* env)
{ {
// A conditional field // A conditional field
env->Evaluate(out_cc, type_->has_value_var()); env->Evaluate(out_cc, type_->has_value_var());
out_cc->println("if ( %s )", out_cc->println("if ( %s )", env->RValue(type_->has_value_var()));
env->RValue(type_->has_value_var()));
out_cc->inc_indent(); out_cc->inc_indent();
out_cc->println("{"); out_cc->println("{");
} }
@ -66,9 +61,7 @@ void WithInputField::GenParseCode(Output* out_cc, Env* env)
Env field_env(env, this); Env field_env(env, this);
ASSERT(! type_->incremental_input()); ASSERT(! type_->incremental_input());
type_->GenPreParsing(out_cc, &field_env); type_->GenPreParsing(out_cc, &field_env);
type_->GenParseCode(out_cc, &field_env, type_->GenParseCode(out_cc, &field_env, input()->GenDataBeginEnd(out_cc, &field_env), 0);
input()->GenDataBeginEnd(out_cc, &field_env),
0);
if ( type_->attr_if_expr() ) if ( type_->attr_if_expr() )
{ {

View file

@ -6,12 +6,12 @@
#include "pac_field.h" #include "pac_field.h"
class WithInputField : public Field, public Evaluatable class WithInputField : public Field, public Evaluatable
{ {
public: public:
WithInputField(ID* id, Type *type, InputBuffer* input); WithInputField(ID* id, Type* type, InputBuffer* input);
virtual ~WithInputField(); virtual ~WithInputField();
InputBuffer *input() const { return input_; } InputBuffer* input() const { return input_; }
void Prepare(Env* env); void Prepare(Env* env);
@ -29,10 +29,10 @@ public:
bool RequiresAnalyzerContext() const; bool RequiresAnalyzerContext() const;
protected: protected:
bool DoTraverse(DataDepVisitor *visitor); bool DoTraverse(DataDepVisitor* visitor);
protected: protected:
InputBuffer *input_; InputBuffer* input_;
}; };
#endif // pac_withinput_h #endif // pac_withinput_h