GP-2237 AddrSpace as marshaling primitive and prettyprint update

This commit is contained in:
caheckman 2022-06-23 20:16:51 -04:00
parent 4807ec354a
commit 6be9943b8a
58 changed files with 1333 additions and 1098 deletions

View file

@ -28,11 +28,30 @@ class Funcdata;
class Symbol;
class PendPrint;
/// \brief Base class (and interface) for pretty printing and XML markup of tokens
extern AttributeId ATTRIB_BLOCKREF; ///< Marshaling attribute "blockref"
extern AttributeId ATTRIB_CLOSE; ///< Marshaling attribute "close"
extern AttributeId ATTRIB_COLOR; ///< Marshaling attribute "color"
extern AttributeId ATTRIB_INDENT; ///< Marshaling attribute "indent"
extern AttributeId ATTRIB_OFF; ///< Marshaling attribute "off"
extern AttributeId ATTRIB_OPEN; ///< Marshaling attribute "open"
extern AttributeId ATTRIB_OPREF; ///< Marshaling attribute "opref"
extern AttributeId ATTRIB_VARREF; ///< Marshaling attribute "varref"
extern ElementId ELEM_BREAK; ///< Marshaling element \<break>
extern ElementId ELEM_CLANG_DOCUMENT; ///< Marshaling element \<clang_document>
extern ElementId ELEM_FUNCNAME; ///< Marshaling element \<funcname>
extern ElementId ELEM_FUNCPROTO; ///< Marshaling element \<funcproto>
extern ElementId ELEM_LABEL; ///< Marshaling element \<label>
extern ElementId ELEM_RETURN_TYPE; ///< Marshaling element \<return_type>
extern ElementId ELEM_STATEMENT; ///< Marshaling element \<statement>
extern ElementId ELEM_SYNTAX; ///< Marshaling element \<syntax>
extern ElementId ELEM_VARDECL; ///< Marshaling element \<vardecl>
extern ElementId ELEM_VARIABLE; ///< Marshaling element \<variable>
/// \brief Interface for emitting the Decompiler's formal output: source code
///
/// There are two basic functions being implemented through this interface:
///
/// \b XML \b markup: allows recording of the natural grouping of the high-level tokens
/// \b Markup: allows recording of the natural grouping of the high-level tokens
/// and directly links the nodes of the abstract syntax tree to the emitted tokens.
///
/// \b Pretty \b printing: Line breaks and additional white space characters are
@ -70,23 +89,19 @@ class PendPrint;
/// - tagLine forces a line break
/// - tagLine(indent) forces a line break with an indent override
///
/// This base class does not actually do any pretty printing it only does the XML
/// markup. For an implementation that actually does pretty printing, see EmitPrettyPrint.
/// This class can be used as the low-level back-end to EmitPrettyPrint to provide a solution
/// that does both pretty printing and XML markup.
class EmitXml {
static const char *highlight[]; ///< Map from syntax_highlight enumeration to color attribute string
/// For an implementation that actually does pretty printing, see EmitPrettyPrint.
class Emit {
public:
static const string EMPTY_STRING; ///< An empty string
protected:
ostream *s; ///< Stream being emitted to
int4 indentlevel; ///< Current indent level (in fixed width characters)
int4 parenlevel; ///< Current depth of parentheses
int4 indentincrement; ///< Change in indentlevel per level of nesting
PendPrint *pendPrint; ///< Pending print callback
void resetDefaultsInternal(void) { indentincrement = 2; } ///< Set options to default values for EmitXml
void resetDefaultsInternal(void) { indentincrement = 2; } ///< Set options to default values for EmitMarkup
void emitPending(void); ///< Emit any pending print commands
public:
EmitXml(void) { s = (ostream *)0; indentlevel=0; parenlevel=0; pendPrint=(PendPrint *)0; resetDefaultsInternal(); } ///< Constructor
Emit(void) { indentlevel=0; parenlevel=0; pendPrint=(PendPrint *)0; resetDefaultsInternal(); } ///< Constructor
/// \brief Possible types of syntax highlighting
enum syntax_highlight {
keyword_color = 0, ///< Keyword in the high-level language
@ -99,34 +114,202 @@ public:
global_color = 7, ///< Global variable identifiers
no_color = 8 ///< Un-highlighted
};
virtual ~EmitXml(void) {} ///< Destructor
virtual int4 beginDocument(void); ///< Begin a whole document of output
virtual void endDocument(int4 id); ///< End a whole document of output
virtual int4 beginFunction(const Funcdata *fd); ///< Begin a whole declaration and body of a function
virtual void endFunction(int4 id); ///< End a whole declaration and body of a function
virtual int4 beginBlock(const FlowBlock *bl); ///< Begin a control-flow element
virtual void endBlock(int4 id); ///< End a control-flow element
virtual void tagLine(void); ///< Force a line break
virtual void tagLine(int4 indent); ///< Force a line break and indent level
virtual int4 beginReturnType(const Varnode *vn); ///< Begin a return type declaration
virtual void endReturnType(int4 id); ///< End a return type declaration
virtual int4 beginVarDecl(const Symbol *sym); ///< Begin a variable declaration
virtual void endVarDecl(int4 id); ///< End a variable declaration
virtual int4 beginStatement(const PcodeOp *op); ///< Begin a source code statement
virtual void endStatement(int4 id); ///< End a source code statement
virtual int4 beginFuncProto(void); ///< Begin a function prototype declaration
virtual void endFuncProto(int4 id); ///< End a function prototype declaration
virtual void tagVariable(const char *ptr,syntax_highlight hl,
const Varnode *vn,const PcodeOp *op);
virtual void tagOp(const char *ptr,syntax_highlight hl,const PcodeOp *op);
virtual void tagFuncName(const char *ptr,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
virtual void tagType(const char *ptr,syntax_highlight hl,const Datatype *ct);
virtual void tagField(const char *ptr,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const char *ptr,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagLabel(const char *ptr,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void print(const char *str,syntax_highlight hl=no_color);
virtual int4 openParen(char o,int4 id=0); ///< Emit an open parenthesis
virtual void closeParen(char c,int4 id); ///< Emit a close parenthesis
virtual ~Emit(void) {} ///< Destructor
/// \brief Begin a whole document of output
///
/// Inform the emitter that generation of the source code document has begun
/// \return an id associated with the document
virtual int4 beginDocument(void)=0;
/// \brief End a whole document of output
///
/// Inform the emitter that generation of the source code document is finished
/// \param id is the id associated with the document (as returned by beginDocument)
virtual void endDocument(int4 id)=0;
/// \brief Begin a whole declaration and body of a function
///
/// Inform the emitter that generation of a function body has begun
/// \return an id associated with the function body
virtual int4 beginFunction(const Funcdata *fd)=0;
/// \brief End a whole declaration and body of a function
///
/// Inform the emitter that generation of a function body has ended
/// \param id is the id associated with the function body (as returned by beginFunction)
virtual void endFunction(int4 id)=0;
/// \brief Begin a control-flow element
///
/// Inform the emitter that a new control-flow section is starting. This is a source code unit
/// usually surrounded with curly braces '{' and '}'.
/// \param bl is the block structure object associated with the section
/// \return an id associated with the section
virtual int4 beginBlock(const FlowBlock *bl)=0;
/// \brief End a control-flow element
///
/// Inform the emitter that a control-flow section is ending.
/// \param id is the id associated with the section (as returned by beginBlock)
virtual void endBlock(int4 id)=0;
/// \brief Force a line break
///
/// Tell the emitter that a new line is desired at the current indent level
virtual void tagLine(void)=0;
/// \brief Force a line break and indent level
///
/// Tell the emitter that a new line is desired at a specific indent level. The indent level
/// is overridden only for the line, then it returns to its previous value.
/// \param indent is the desired indent level for the new line
virtual void tagLine(int4 indent)=0;
/// \brief Begin a return type declaration
///
/// Inform the emitter that generation of a function's return type is starting.
/// \param vn (if non-null) is the storage location for the return value
/// \return an id associated with the return type
virtual int4 beginReturnType(const Varnode *vn)=0;
/// \brief End a return type declaration
///
/// Inform the emitter that generation of a function's return type is ending.
/// \param id is the id associated with the return type (as returned by beginReturnType)
virtual void endReturnType(int4 id)=0;
/// \brief Begin a variable declaration
///
/// Inform the emitter that a variable declaration has started.
/// \param sym is the symbol being declared
/// \return an id associated with the declaration
virtual int4 beginVarDecl(const Symbol *sym)=0;
/// \brief End a variable declaration
///
/// Inform the emitter that a variable declaration has ended.
/// \param id is the id associated with the declaration (as returned by beginVarDecl)
virtual void endVarDecl(int4 id)=0;
/// \brief Begin a source code statement
///
/// Inform the emitter that a source code statement is beginning.
/// \param op is the root p-code operation of the statement
/// \return an id associated with the statement
virtual int4 beginStatement(const PcodeOp *op)=0;
/// \brief End a source code statement
///
/// Inform the emitter that a source code statement is ending.
/// \param id is the id associated with the statement (as returned by beginStatement)
virtual void endStatement(int4 id)=0;
/// \brief Begin a function prototype declaration
///
/// Inform the emitter that a function prototype is starting.
/// \return an id associated with the prototype
virtual int4 beginFuncProto(void)=0;
/// \brief End a function prototype declaration
///
/// Inform the emitter that a function prototype is ending.
/// \param id is the id associated with the prototype (as returned by beginFuncProto)
virtual void endFuncProto(int4 id)=0;
/// \brief Emit a variable token
///
/// An identifier string representing the variable is output, possibly with additional markup.
/// \param name is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param vn is the Varnode representing the variable within the syntax tree
/// \param op is a p-code operation related to the use of the variable (may be null)
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op)=0;
/// \brief Emit an operation token
///
/// The string representing the operation as appropriate for the source language is emitted,
/// possibly with additional markup.
/// \param name is the character data for the emitted representation
/// \param hl indicates how the token should be highlighted
/// \param op is the PcodeOp object associated with the operation with the syntax tree
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op)=0;
/// \brief Emit a function identifier
///
/// An identifier string representing the symbol name of the function is emitted, possible
/// with additional markup.
/// \param name is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param fd is the function
/// \param op is the CALL operation associated within the syntax tree or null for a declaration
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op)=0;
/// \brief Emit a data-type identifier
///
/// A string representing the name of a data-type, as appropriate for the source language
/// is emitted, possibly with additional markup.
/// \param name is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param ct is the data-type description object
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct)=0;
/// \brief Emit an identifier for a field within a structured data-type
///
/// A string representing an individual component of a structured data-type is emitted,
/// possibly with additional markup.
/// \param name is the character data for the identifier
/// \param hl indicates how the identifier should be highlighted
/// \param ct is the data-type associated with the field
/// \param off is the (byte) offset of the field within its structured data-type
/// \param op is the PcodeOp associated with the field (usually PTRSUB or SUBPIECE)
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op)=0;
/// \brief Emit a comment string as part of the generated source code
///
/// Individual comments can be broken up and emitted using multiple calls to this method,
/// but ultimately the comment delimiters and the body of the comment are both emitted with
/// this method, which may provide addition markup.
/// \param name is the character data for the comment
/// \param hl indicates how the comment should be highlighted
/// \param spc is the address space of the address where the comment is attached
/// \param off is the offset of the address where the comment is attached
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)=0;
/// \brief Emit a code label identifier
///
/// A string describing a control-flow destination, as appropriate for the source language
/// is output, possibly with additional markup.
/// \param name is the character data of the label
/// \param hl indicates how the label should be highlighted
/// \param spc is the address space of the code address being labeled
/// \param off is the offset of the code address being labeled
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)=0;
/// \brief Emit other (more unusual) syntax as part of source code generation
///
/// This method is used to emit syntax not covered by the other methods, such as
/// spaces, semi-colons, braces, and other punctuation.
/// \param data is the character data of the syntax being emitted
/// \param hl indicates how the syntax should be highlighted
virtual void print(const string &data,syntax_highlight hl=no_color)=0;
/// \brief Emit an open parenthesis
///
/// This method emits the parenthesis character itself and also starts a printing unit
/// of the source code being surrounded by the parentheses.
/// \param paren is the open parenthesis character to emit
/// \param id is an id to associate with the parenthesis
/// \return an id associated with the parenthesis
virtual int4 openParen(const string &paren,int4 id=0)=0;
/// \brief Emit a close parenthesis
///
/// This method emits the parenthesis character itself and ends the printing unit that
/// was started by the matching open parenthesis.
/// \param paren is the close parenthesis character to emit
/// \param id is the id associated with the matching open parenthesis (as returned by openParen)
virtual void closeParen(const string &paren,int4 id)=0;
/// \brief Start a group of things that are printed together
///
@ -140,8 +323,8 @@ public:
/// \param id is the id associated with the group (as returned by openGroup)
virtual void closeGroup(int4 id) {}
virtual void clear(void) { parenlevel = 0; indentlevel=0; pendPrint=(PendPrint *)0; } ///< Reset the emitter to its initial state
virtual void setOutputStream(ostream *t) { s = t; } ///< Set the output stream for the emitter
virtual ostream *getOutputStream(void) const { return s; } ///< Get the current output stream
virtual void setOutputStream(ostream *t)=0; ///< Set the output stream for the emitter
virtual ostream *getOutputStream(void) const=0; ///< Get the current output stream
virtual void spaces(int4 num,int4 bump=0);
/// \brief Start a new indent level
@ -198,10 +381,10 @@ public:
/// \brief Determine if \b this is an XML markup emitter
///
/// \return \b true if \b this produces an XML markup of its emitted source code
virtual bool emitsXml(void) const { return true; }
virtual bool emitsMarkup(void) const=0;
/// \brief (Re)set the default emitting options
virtual void resetDefaults(void);
virtual void resetDefaults(void) { resetDefaultsInternal(); }
/// \brief Get the current parentheses depth
///
@ -235,22 +418,81 @@ public:
/// \param pend is the given print callback to check
/// \return \b true if the specific print callback is pending
bool hasPendingPrint(PendPrint *pend) const { return (pendPrint == pend); }
};
/// \brief Emitter that associates markup with individual tokens
///
/// Variable and operation tokens are associated with their corresponding Varnode or PcodeOp object in
/// the data-flow graph of the decompiled function.
///
/// Explicit descriptions of various token groups is emitted, including:
/// - Function prototypes
/// - Variable declarations
/// - Control-flow blocks
/// - Statements
///
/// Tokens are emitted with syntax highlighting information.
///
/// This class can be used as the low-level back-end to EmitPrettyPrint to provide a solution
/// that does both pretty printing and markup.
class EmitMarkup : public Emit {
static const string highlight[]; ///< Map from syntax_highlight enumeration to color attribute string
protected:
ostream *s; ///< Stream being emitted to
Encoder *encoder; ///< How markup is encoded to the output stream
public:
EmitMarkup(void) : Emit() { s = (ostream *)0; encoder = (Encoder *)0; } ///< Constructor
virtual ~EmitMarkup(void);
virtual int4 beginDocument(void);
virtual void endDocument(int4 id);
virtual int4 beginFunction(const Funcdata *fd);
virtual void endFunction(int4 id);
virtual int4 beginBlock(const FlowBlock *bl);
virtual void endBlock(int4 id);
virtual void tagLine(void);
virtual void tagLine(int4 indent);
virtual int4 beginReturnType(const Varnode *vn);
virtual void endReturnType(int4 id);
virtual int4 beginVarDecl(const Symbol *sym);
virtual void endVarDecl(int4 id);
virtual int4 beginStatement(const PcodeOp *op);
virtual void endStatement(int4 id);
virtual int4 beginFuncProto(void);
virtual void endFuncProto(int4 id);
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op);
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op);
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct);
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void print(const string &data,syntax_highlight hl=no_color);
virtual int4 openParen(const string &paren,int4 id=0);
virtual void closeParen(const string &paren,int4 id);
virtual void setOutputStream(ostream *t);
virtual ostream *getOutputStream(void) const { return s; }
virtual bool emitsMarkup(void) const { return true; }
};
/// \brief A trivial emitter that outputs syntax straight to the stream
///
/// This emitter does neither pretty printing nor XML markup. It dumps any tokens
/// This emitter does neither pretty printing nor markup. It dumps any tokens
/// straight to the final output stream. It can be used as the low-level back-end
/// for EmitPrettyPrint.
class EmitNoXml : public EmitXml {
class EmitNoMarkup : public Emit {
ostream *s; ///< The stream to output tokens to
public:
EmitNoXml(void) : EmitXml() {} ///< Constructor
EmitNoMarkup(void) : Emit() { s = (ostream *)0; } ///< Constructor
virtual int4 beginDocument(void) { return 0; }
virtual void endDocument(int4 id) {}
virtual int4 beginFunction(const Funcdata *fd) { return 0; }
virtual void endFunction(int4 id) {}
virtual int4 beginBlock(const FlowBlock *bl) { return 0; }
virtual void endBlock(int4 id) {}
virtual void tagLine(void) {
*s << endl; for(int4 i=indentlevel;i>0;--i) *s << ' '; }
virtual void tagLine(int4 indent) {
*s << endl; for(int4 i=indent;i>0;--i) *s << ' '; }
virtual int4 beginReturnType(const Varnode *vn) { return 0; }
@ -261,30 +503,29 @@ public:
virtual void endStatement(int4 id) {}
virtual int4 beginFuncProto(void) { return 0; }
virtual void endFuncProto(int4 id) {}
virtual void tagVariable(const char *ptr,syntax_highlight hl,
const Varnode *vn,const PcodeOp *op) {
*s << ptr; }
virtual void tagOp(const char *ptr,syntax_highlight hl,const PcodeOp *op) {
*s << ptr; }
virtual void tagFuncName(const char *ptr,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op) {
*s << ptr; }
virtual void tagType(const char *ptr,syntax_highlight hl,const Datatype *ct) {
*s << ptr; }
virtual void tagField(const char *ptr,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op) {
*s << ptr; }
virtual void tagComment(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off) {
*s << ptr; }
virtual void tagLabel(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off) {
*s << ptr; }
virtual void print(const char *str,syntax_highlight hl=no_color) {
*s << str; }
virtual int4 openParen(char o,int4 id=0) {
*s << o; parenlevel += 1; return id; }
virtual void closeParen(char c,int4 id) {
*s << c; parenlevel -= 1; }
virtual bool emitsXml(void) const { return false; }
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op) {
*s << name; }
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op) {
*s << name; }
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op) {
*s << name; }
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct) {
*s << name; }
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op) {
*s << name; }
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off) {
*s << name; }
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off) {
*s << name; }
virtual void print(const string &data,syntax_highlight hl=no_color) {
*s << data; }
virtual int4 openParen(const string &paren,int4 id=0) {
*s << paren; parenlevel += 1; return id; }
virtual void closeParen(const string &paren,int4 id) {
*s << paren; parenlevel -= 1; }
virtual void setOutputStream(ostream *t) { s = t; }
virtual ostream *getOutputStream(void) const { return s; }
virtual bool emitsMarkup(void) const { return false; }
};
/// \brief A token/command object in the pretty printing stream
@ -299,7 +540,7 @@ public:
/// the token is one of the begin/end delimiters or is actual content.
/// Instances also have a \e tag_type that indicate the specific function of the
/// token within the stream, which mirror the begin/end/open/close/tag methods
/// on the emitter classes (EmitXml).
/// on the emitter classes (EmitMarkup).
class TokenSplit {
public:
/// \brief An enumeration denoting the general class of a token
@ -351,7 +592,7 @@ private:
tag_type tagtype; ///< Type of token
printclass delimtype; ///< The general class of the token
string tok; ///< Characters of token (if any)
EmitXml::syntax_highlight hl; ///< Highlighting for token
EmitMarkup::syntax_highlight hl; ///< Highlighting for token
// Additional markup elements for token
const PcodeOp *op; ///< Pcode-op associated with \b this token
union {
@ -461,98 +702,95 @@ public:
/// \brief Create a variable identifier token
///
/// \param ptr is the character data for the identifier
/// \param name is the character data for the identifier
/// \param h indicates how the identifier should be highlighted
/// \param v is the Varnode representing the variable within the syntax tree
/// \param o is a p-code operation related to the use of the variable (may be null)
void tagVariable(const char *ptr,EmitXml::syntax_highlight h,
const Varnode *v,const PcodeOp *o) {
tok = ptr; size = tok.size();
void tagVariable(const string &name,EmitMarkup::syntax_highlight h,const Varnode *v,const PcodeOp *o) {
tok = name; size = tok.size();
tagtype=vari_t; delimtype=tokenstring; hl=h; ptr_second.vn=v; op=o; }
/// \brief Create an operator token
///
/// \param ptr is the character data for the emitted representation
/// \param name is the character data for the emitted representation
/// \param h indicates how the token should be highlighted
/// \param o is the PcodeOp object associated with the operation with the syntax tree
void tagOp(const char *ptr,EmitXml::syntax_highlight h,const PcodeOp *o) {
tok = ptr; size = tok.size();
void tagOp(const string &name,EmitMarkup::syntax_highlight h,const PcodeOp *o) {
tok = name; size = tok.size();
tagtype=op_t; delimtype=tokenstring; hl=h; op=o; }
/// \brief Create a function identifier token
///
/// \param ptr is the character data for the identifier
/// \param name is the character data for the identifier
/// \param h indicates how the identifier should be highlighted
/// \param f is the function
/// \param o is the CALL operation associated within the syntax tree or null for a declaration
void tagFuncName(const char *ptr,EmitXml::syntax_highlight h,const Funcdata *f,const PcodeOp *o) {
tok = ptr; size = tok.size();
void tagFuncName(const string &name,EmitMarkup::syntax_highlight h,const Funcdata *f,const PcodeOp *o) {
tok = name; size = tok.size();
tagtype=fnam_t; delimtype=tokenstring; hl=h; ptr_second.fd=f; op=o; }
/// \brief Create a data-type identifier token
///
/// \param ptr is the character data for the identifier
/// \param name is the character data for the identifier
/// \param h indicates how the identifier should be highlighted
/// \param ct is the data-type description object
void tagType(const char *ptr,EmitXml::syntax_highlight h,const Datatype *ct) {
tok = ptr; size = tok.size();
void tagType(const string &name,EmitMarkup::syntax_highlight h,const Datatype *ct) {
tok = name; size = tok.size();
tagtype=type_t; delimtype=tokenstring; hl=h; ptr_second.ct=ct; }
/// \brief Create an identifier for a field within a structured data-type
///
/// \param ptr is the character data for the identifier
/// \param name is the character data for the identifier
/// \param h indicates how the identifier should be highlighted
/// \param ct is the data-type associated with the field
/// \param o is the (byte) offset of the field within its structured data-type
/// \param inOp is the PcodeOp associated with the field (usually PTRSUB or SUBPIECE)
void tagField(const char *ptr,EmitXml::syntax_highlight h,const Datatype *ct,int4 o,const PcodeOp *inOp) {
tok = ptr; size = tok.size();
void tagField(const string &name,EmitMarkup::syntax_highlight h,const Datatype *ct,int4 o,const PcodeOp *inOp) {
tok = name; size = tok.size();
tagtype=field_t; delimtype=tokenstring; hl=h; ptr_second.ct=ct; off=(uintb)o; op=inOp; }
/// \brief Create a comment string in the generated source code
///
/// \param ptr is the character data for the comment
/// \param name is the character data for the comment
/// \param h indicates how the comment should be highlighted
/// \param s is the address space of the address where the comment is attached
/// \param o is the offset of the address where the comment is attached
void tagComment(const char *ptr,EmitXml::syntax_highlight h,
const AddrSpace *s,uintb o) {
tok = ptr; size = tok.size(); ptr_second.spc=s; off=o;
void tagComment(const string &name,EmitMarkup::syntax_highlight h,const AddrSpace *s,uintb o) {
tok = name; size = tok.size(); ptr_second.spc=s; off=o;
tagtype=comm_t; delimtype=tokenstring; hl=h; }
/// \brief Create a code label identifier token
///
/// \param ptr is the character data of the label
/// \param name is the character data of the label
/// \param h indicates how the label should be highlighted
/// \param s is the address space of the code address being labeled
/// \param o is the offset of the code address being labeled
void tagLabel(const char *ptr,EmitXml::syntax_highlight h,
const AddrSpace *s,uintb o) {
tok = ptr; size = tok.size(); ptr_second.spc=s; off=o;
void tagLabel(const string &name,EmitMarkup::syntax_highlight h,const AddrSpace *s,uintb o) {
tok = name; size = tok.size(); ptr_second.spc=s; off=o;
tagtype=label_t; delimtype=tokenstring; hl=h; }
/// \brief Create a token for other (more unusual) syntax in source code
///
/// \param str is the character data of the syntax being emitted
/// \param data is the character data of the syntax being emitted
/// \param h indicates how the syntax should be highlighted
void print(const char *str,EmitXml::syntax_highlight h) {
tok = str; size=tok.size();
void print(const string &data,EmitMarkup::syntax_highlight h) {
tok = data; size=tok.size();
tagtype=synt_t; delimtype=tokenstring; hl=h; }
/// \brief Create an open parenthesis
///
/// \param o is the open parenthesis character to emit
/// \param paren is the open parenthesis character to emit
/// \param id is an id to associate with the parenthesis
void openParen(char o,int4 id) {
tok = o; size = 1;
void openParen(const string &paren,int4 id) {
tok = paren; size = 1;
tagtype=opar_t; delimtype=tokenstring; count=id; }
/// \brief Create a close parenthesis
///
/// \param c is the close parenthesis character to emit
/// \param paren is the close parenthesis character to emit
/// \param id is the id associated with the matching open parenthesis (as returned by openParen)
void closeParen(char c,int4 id) {
tok = c; size = 1;
void closeParen(const string &paren,int4 id) {
tok = paren; size = 1;
tagtype=cpar_t; delimtype=tokenstring; count=id; }
/// \brief Create a "start a printing group" command
@ -608,7 +846,7 @@ public:
void tagLine(int4 indent) {
tagtype=line_t; delimtype=tokenbreak; numspaces=999999; indentbump=indent; }
void print(EmitXml *emit) const; ///< Send \b this token to emitter
void print(Emit *emit) const; ///< Send \b this token to emitter
int4 getIndentBump(void) const { return indentbump; } ///< Get the extra indent after a line break
int4 getNumSpaces(void) const { return numspaces; } ///< Get the number of characters of whitespace
int4 getSize(void) const { return size; } ///< Get the number of content characters
@ -724,12 +962,12 @@ void circularqueue<_type>::expand(int4 amount)
/// about formatting issues.
///
/// This emitter encapsulates a lower-level emitter that does the final emitting to
/// stream and may add XML markup.
class EmitPrettyPrint : public EmitXml {
/// stream and may add markup.
class EmitPrettyPrint : public Emit {
#ifdef PRETTY_DEBUG
vector<int4> checkid;
#endif
EmitXml *lowlevel; ///< The low-level emitter
Emit *lowlevel; ///< The low-level emitter
vector<int4> indentstack; ///< Space available for currently active nesting levels
int4 spaceremain; ///< Space remaining in current line
int4 maxlinesize; ///< Maximum number of characters allowed in a line
@ -769,19 +1007,16 @@ public:
virtual void endStatement(int4 id);
virtual int4 beginFuncProto(void);
virtual void endFuncProto(int4 id);
virtual void tagVariable(const char *ptr,syntax_highlight hl,
const Varnode *vn,const PcodeOp *op);
virtual void tagOp(const char *ptr,syntax_highlight hl,const PcodeOp *op);
virtual void tagFuncName(const char *ptr,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
virtual void tagType(const char *ptr,syntax_highlight hl,const Datatype *ct);
virtual void tagField(const char *ptr,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off);
virtual void tagLabel(const char *ptr,syntax_highlight hl,
const AddrSpace *spc,uintb off);
virtual void print(const char *str,syntax_highlight hl=no_color);
virtual int4 openParen(char o,int4 id=0);
virtual void closeParen(char c,int4 id);
virtual void tagVariable(const string &name,syntax_highlight hl,const Varnode *vn,const PcodeOp *op);
virtual void tagOp(const string &name,syntax_highlight hl,const PcodeOp *op);
virtual void tagFuncName(const string &name,syntax_highlight hl,const Funcdata *fd,const PcodeOp *op);
virtual void tagType(const string &name,syntax_highlight hl,const Datatype *ct);
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void print(const string &data,syntax_highlight hl=no_color);
virtual int4 openParen(const string &paren,int4 id=0);
virtual void closeParen(const string &paren,int4 id);
virtual int4 openGroup(void);
virtual void closeGroup(int4 id);
virtual void clear(void);
@ -796,9 +1031,9 @@ public:
virtual void setMaxLineSize(int4 val);
virtual int4 getMaxLineSize(void) const { return maxlinesize; }
virtual void setCommentFill(const string &fill) { commentfill = fill; }
virtual bool emitsXml(void) const { return lowlevel->emitsXml(); }
virtual bool emitsMarkup(void) const { return lowlevel->emitsMarkup(); }
virtual void resetDefaults(void);
void setXML(bool val); ///< Toggle whether the low-level emitter emits XML markup or not
void setMarkup(bool val); ///< Toggle whether the low-level emitter emits markup or not
};
/// \brief Helper class for sending cancelable print commands to an ExitXml
@ -810,10 +1045,10 @@ public:
class PendPrint {
public:
virtual ~PendPrint(void) {} ///< Destructor
virtual void callback(EmitXml *emit)=0; ///< Callback that executes the actual print commands
virtual void callback(Emit *emit)=0; ///< Callback that executes the actual print commands
};
inline void EmitXml::emitPending(void)
inline void Emit::emitPending(void)
{
if (pendPrint != (PendPrint *)0) {