decompiler  1.0.0
Public Member Functions | Private Member Functions | Private Attributes | List of all members
EmitPrettyPrint Class Reference

A generic source code pretty printer. More...

#include <prettyprint.hh>

Inheritance diagram for EmitPrettyPrint:
EmitXml

Public Member Functions

 EmitPrettyPrint (void)
 Construct with an initial maximum line size.
 
virtual int4 beginDocument (void)
 Begin a whole document of output. More...
 
virtual void endDocument (int4 id)
 End a whole document of output. More...
 
virtual int4 beginFunction (const Funcdata *fd)
 Begin a whole declaration and body of a function. More...
 
virtual void endFunction (int4 id)
 End a whole declaration and body of a function. More...
 
virtual int4 beginBlock (const FlowBlock *bl)
 Begin a control-flow element. More...
 
virtual void endBlock (int4 id)
 End a control-flow element. More...
 
virtual void tagLine (void)
 Force a line break. More...
 
virtual void tagLine (int4 indent)
 Force a line break and indent level. More...
 
virtual int4 beginReturnType (const Varnode *vn)
 Begin a return type declaration. More...
 
virtual void endReturnType (int4 id)
 End a return type declaration. More...
 
virtual int4 beginVarDecl (const Symbol *sym)
 Begin a variable declaration. More...
 
virtual void endVarDecl (int4 id)
 End a variable declaration. More...
 
virtual int4 beginStatement (const PcodeOp *op)
 Begin a source code statement. More...
 
virtual void endStatement (int4 id)
 End a source code statement. More...
 
virtual int4 beginFuncProto (void)
 Begin a function prototype declaration. More...
 
virtual void endFuncProto (int4 id)
 End a function prototype declaration. More...
 
virtual void tagVariable (const char *ptr, syntax_highlight hl, const Varnode *vn, const PcodeOp *op)
 Emit a variable token. More...
 
virtual void tagOp (const char *ptr, syntax_highlight hl, const PcodeOp *op)
 Emit an operation token. More...
 
virtual void tagFuncName (const char *ptr, syntax_highlight hl, const Funcdata *fd, const PcodeOp *op)
 Emit a function identifier. More...
 
virtual void tagType (const char *ptr, syntax_highlight hl, const Datatype *ct)
 Emit a data-type identifier. More...
 
virtual void tagField (const char *ptr, syntax_highlight hl, const Datatype *ct, int4 off)
 Emit an identifier for a field within a structured data-type. More...
 
virtual void tagComment (const char *ptr, syntax_highlight hl, const AddrSpace *spc, uintb off)
 Emit a comment string as part of the generated source code. More...
 
virtual void tagLabel (const char *ptr, syntax_highlight hl, const AddrSpace *spc, uintb off)
 Emit a code label identifier. More...
 
virtual void print (const char *str, syntax_highlight hl=no_color)
 Emit other (more unusual) syntax as part of source code generation. More...
 
virtual int4 openParen (char o, int4 id=0)
 Emit an open parenthesis. More...
 
virtual void closeParen (char c, int4 id)
 Emit a close parenthesis. More...
 
virtual int4 openGroup (void)
 Start a group of things that are printed together. More...
 
virtual void closeGroup (int4 id)
 End a group of things that are printed together. More...
 
virtual void clear (void)
 Reset the emitter to its initial state.
 
virtual void setOutputStream (ostream *t)
 Set the output stream for the emitter.
 
virtual ostream * getOutputStream (void) const
 Get the current output stream.
 
virtual void spaces (int4 num, int4 bump=0)
 Emit a sequence of space characters as part of source code. More...
 
virtual int4 startIndent (void)
 Start a new indent level. More...
 
virtual void stopIndent (int4 id)
 End an indent level. More...
 
virtual int4 startComment (void)
 Start a comment block within the emitted source code. More...
 
virtual void stopComment (int4 id)
 End a comment block. More...
 
virtual void flush (void)
 Flush any remaining character data. More...
 
virtual void setMaxLineSize (int4 val)
 Provide a maximum line size to the pretty printer. More...
 
virtual int4 getMaxLineSize (void) const
 Get the current maximum line size. More...
 
virtual void setCommentFill (const string &fill)
 Set the comment fill characters for when line breaks are forced. More...
 
virtual bool emitsXml (void) const
 Determine if this is an XML markup emitter. More...
 
virtual void resetDefaults (void)
 (Re)set the default emitting options
 
void setXML (bool val)
 Toggle whether the low-level emitter emits XML markup or not. More...
 
- Public Member Functions inherited from EmitXml
 EmitXml (void)
 Constructor.
 
virtual ~EmitXml (void)
 Destructor.
 
int4 getParenLevel (void) const
 Get the current parentheses depth. More...
 
int4 getIndentIncrement (void) const
 Get the number of characters indented per level of nesting. More...
 
void setIndentIncrement (int4 val)
 Set the number of characters indented per level of nesting. More...
 

Private Member Functions

void expand (void)
 Expand the stream buffer. More...
 
void checkstart (void)
 Enforce whitespace for a start token. More...
 
void checkend (void)
 Enforce whitespace for an end token. More...
 
void checkstring (void)
 Enforce whitespace for a content token. More...
 
void checkbreak (void)
 Enforce whitespace for a line break. More...
 
void overflow (void)
 Reset indenting levels to accommodate a token that won't fit. More...
 
void print (const TokenSplit &tok)
 Output the given token to the low-level emitter. More...
 
void advanceleft (void)
 Emit tokens that have been fully committed. More...
 
void scan (void)
 Process a new token. More...
 
void resetDefaultsPrettyPrint (void)
 

Private Attributes

EmitXmllowlevel
 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.
 
int4 leftotal
 

of characters committed from the current line


 
int4 rightotal
 

of characters yet to be committed from the current line


 
bool needbreak
 true if break needed before next token
 
bool commentmode
 true if in the middle of a comment
 
string commentfill
 Used to fill comments if line breaks are forced.
 
circularqueue< int4 > scanqueue
 References to current open and whitespace tokens.
 
circularqueue< TokenSplittokqueue
 The full stream of tokens.
 

Additional Inherited Members

- Public Types inherited from EmitXml
enum  syntax_highlight {
  keyword_color = 0, comment_color = 1, type_color = 2, funcname_color = 3,
  var_color = 4, const_color = 5, param_color = 6, global_color = 7,
  no_color = 8
}
 Possible types of syntax highlighting. More...
 
- Protected Member Functions inherited from EmitXml
void resetDefaultsInternal (void)
 Set options to default values for EmitXml.
 
- Protected Attributes inherited from EmitXml
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.
 

Detailed Description

A generic source code pretty printer.

This pretty printer is based on the standard Derek C. Oppen pretty printing algorithm. It allows configurable indenting, spacing, and line breaks that enhances the readability of the high-level language output. It makes use of the extra information inherent in the AST to make decisions about how to best print language statements. It attempts to abstract the main formatting elements of imperative languages: statements, code blocks, declarations, etc., and so should be largely language independent. In this way, the main language emitter doesn't have to worry about formatting issues.

This emitter encapsulates a lower-level emitter that does the final emitting to stream and may add XML markup.

Member Function Documentation

void EmitPrettyPrint::advanceleft ( void  )
private

Emit tokens that have been fully committed.

Groups of tokens that have been fully committed are sent to the low-level emitter and purged from the queue. Delimiter tokens that open a new printing group initially have a negative size, indicating the group is uncommitted and may need additional line breaks inserted. As the ending delimiters are scanned and/or line breaks are forced. The negative sizes are converted to positive and the corresponding group becomes committed, and the constituent content is emitted by this method.

References EmitXml::print(), TokenSplit::tokenbreak, and TokenSplit::tokenstring.

int4 EmitPrettyPrint::beginBlock ( const FlowBlock bl)
virtual

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 '}'.

Parameters
blis the block structure object associated with the section
Returns
an id associated with the section

Reimplemented from EmitXml.

References TokenSplit::beginBlock().

int4 EmitPrettyPrint::beginDocument ( void  )
virtual

Begin a whole document of output.

Inform the emitter that generation of the source code document has begun

Returns
an id associated with the document

Reimplemented from EmitXml.

References TokenSplit::beginDocument().

int4 EmitPrettyPrint::beginFuncProto ( void  )
virtual

Begin a function prototype declaration.

Inform the emitter that a function prototype is starting.

Returns
an id associated with the prototype

Reimplemented from EmitXml.

References TokenSplit::beginFuncProto().

int4 EmitPrettyPrint::beginFunction ( const Funcdata fd)
virtual

Begin a whole declaration and body of a function.

Inform the emitter that generation of a function body has begun

Returns
an id associated with the function body

Reimplemented from EmitXml.

References TokenSplit::beginFunction().

int4 EmitPrettyPrint::beginReturnType ( const Varnode vn)
virtual

Begin a return type declaration.

Inform the emitter that generation of a function's return type is starting.

Parameters
vn(if non-null) is the storage location for the return value
Returns
an id associated with the return type

Reimplemented from EmitXml.

References TokenSplit::beginReturnType().

int4 EmitPrettyPrint::beginStatement ( const PcodeOp op)
virtual

Begin a source code statement.

Inform the emitter that a source code statement is beginning.

Parameters
opis the root p-code operation of the statement
Returns
an id associated with the statement

Reimplemented from EmitXml.

References TokenSplit::beginStatement().

int4 EmitPrettyPrint::beginVarDecl ( const Symbol sym)
virtual

Begin a variable declaration.

Inform the emitter that a variable declaration has started.

Parameters
symis the symbol being declared
Returns
an id associated with the declaration

Reimplemented from EmitXml.

References TokenSplit::beginVarDecl().

void EmitPrettyPrint::checkbreak ( void  )
private

Enforce whitespace for a line break.

Make sure there is some content either in the current print group or following the last line break, inserting an empty string token if necessary, before emitting a line break token.

References EmitXml::no_color, and TokenSplit::print().

void EmitPrettyPrint::checkend ( void  )
private

Enforce whitespace for an end token.

Make sure there is some content either in the current print group or following the last line break, inserting an empty string token if necessary, before emitting an end token.

References EmitXml::no_color, and TokenSplit::print().

void EmitPrettyPrint::checkstart ( void  )
private

Enforce whitespace for a start token.

Make sure there is whitespace after the last content token, inserting a zero-sized whitespace token if necessary, before emitting a start token.

References TokenSplit::spaces().

void EmitPrettyPrint::checkstring ( void  )
private

Enforce whitespace for a content token.

Make sure there is whitespace after the last content token, inserting a zero-sized whitespace token if necessary, before emitting a content token.

References TokenSplit::spaces().

void EmitPrettyPrint::closeGroup ( int4  id)
virtual

End a group of things that are printed together.

Inform the emitter that a printing group is ending.

Parameters
idis the id associated with the group (as returned by openGroup)

Reimplemented from EmitXml.

References TokenSplit::closeGroup().

void EmitPrettyPrint::closeParen ( char  c,
int4  id 
)
virtual

Emit a close parenthesis.

This method emits the parenthesis character itself and ends the printing unit that was started by the matching open parenthesis.

Parameters
cis the close parenthesis character to emit
idis the id associated with the matching open parenthesis (as returned by openParen)

Reimplemented from EmitXml.

References EmitXml::closeGroup(), and TokenSplit::closeParen().

virtual bool EmitPrettyPrint::emitsXml ( void  ) const
inlinevirtual

Determine if this is an XML markup emitter.

Returns
true if this produces an XML markup of its emitted source code

Reimplemented from EmitXml.

References EmitXml::emitsXml(), and EmitXml::resetDefaults().

void EmitPrettyPrint::endBlock ( int4  id)
virtual

End a control-flow element.

Inform the emitter that a control-flow section is ending.

Parameters
idis the id associated with the section (as returned by beginBlock)

Reimplemented from EmitXml.

References TokenSplit::endBlock().

void EmitPrettyPrint::endDocument ( int4  id)
virtual

End a whole document of output.

Inform the emitter that generation of the source code document is finished

Parameters
idis the id associated with the document (as returned by beginDocument)

Reimplemented from EmitXml.

References TokenSplit::endDocument().

void EmitPrettyPrint::endFuncProto ( int4  id)
virtual

End a function prototype declaration.

Inform the emitter that a function prototype is ending.

Parameters
idis the id associated with the prototype (as returned by beginFuncProto)

Reimplemented from EmitXml.

References TokenSplit::endFuncProto().

void EmitPrettyPrint::endFunction ( int4  id)
virtual

End a whole declaration and body of a function.

Inform the emitter that generation of a function body has ended

Parameters
idis the id associated with the function body (as returned by beginFunction)

Reimplemented from EmitXml.

References TokenSplit::endFunction().

void EmitPrettyPrint::endReturnType ( int4  id)
virtual

End a return type declaration.

Inform the emitter that generation of a function's return type is ending.

Parameters
idis the id associated with the return type (as returned by beginReturnType)

Reimplemented from EmitXml.

References TokenSplit::endReturnType().

void EmitPrettyPrint::endStatement ( int4  id)
virtual

End a source code statement.

Inform the emitter that a source code statement is ending.

Parameters
idis the id associated with the statement (as returned by beginStatement)

Reimplemented from EmitXml.

References TokenSplit::endStatement().

void EmitPrettyPrint::endVarDecl ( int4  id)
virtual

End a variable declaration.

Inform the emitter that a variable declaration has ended.

Parameters
idis the id associated with the declaration (as returned by beginVarDecl)

Reimplemented from EmitXml.

References TokenSplit::endVarDecl().

void EmitPrettyPrint::expand ( void  )
private

Expand the stream buffer.

Increase the number of tokens that can be in the queue simultaneously. This is automatically called when the buffers are full. Given a fixed maximum line size for the pretty printer, the buffer should quickly reach a size that supports the biggest possible number of cached tokens. The current token queue is preserved and references into the queue are recalculated.

void EmitPrettyPrint::flush ( void  )
virtual

Flush any remaining character data.

Depending on the particular emitter, tokens and syntax that have been submitted to the emitter may be held internally for a time before getting output to the final stream. This routine makes sure submitted syntax is fully output.

Reimplemented from EmitXml.

References EmitXml::print().

virtual int4 EmitPrettyPrint::getMaxLineSize ( void  ) const
inlinevirtual

Get the current maximum line size.

If the emitter respects a maximum line size, return that size.

Returns
the maximum line size or -1 if the emitter does not have a maximum

Reimplemented from EmitXml.

int4 EmitPrettyPrint::openGroup ( void  )
virtual

Start a group of things that are printed together.

Inform the emitter that a new printing group is starting.

Returns
an id associated with the group

Reimplemented from EmitXml.

References TokenSplit::openGroup().

int4 EmitPrettyPrint::openParen ( char  o,
int4  id = 0 
)
virtual

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.

Parameters
ois the open parenthesis character to emit
idis an id to associate with the parenthesis
Returns
an id associated with the parenthesis

Reimplemented from EmitXml.

References EmitXml::openGroup(), and TokenSplit::openParen().

void EmitPrettyPrint::overflow ( void  )
private

Reset indenting levels to accommodate a token that won't fit.

(Permanently) adjust the current set of indent levels to guarantee a minimum amount of space and issue a line break. This disrupts currently established indenting but makes sure that at least half the line is available for the next token.

void EmitPrettyPrint::print ( const TokenSplit tok)
private

Output the given token to the low-level emitter.

Content and markup is sent to the low-level emitter if appropriate. The indentlevel stack is adjusted as necessary depending on the token.

Parameters
tokis the given token to emit.

References TokenSplit::begin, TokenSplit::begin_comment, TokenSplit::begin_indent, EmitXml::comment_color, TokenSplit::end, TokenSplit::end_comment, TokenSplit::end_indent, TokenSplit::getClass(), TokenSplit::getIndentBump(), TokenSplit::getNumSpaces(), TokenSplit::getSize(), TokenSplit::getTag(), TokenSplit::ignore, TokenSplit::line_t, TokenSplit::print(), TokenSplit::tokenbreak, and TokenSplit::tokenstring.

void EmitPrettyPrint::print ( const char *  str,
syntax_highlight  hl = no_color 
)
virtual

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.

Parameters
stris the character data of the syntax being emitted
hlindicates how the syntax should be highlighted

Reimplemented from EmitXml.

References TokenSplit::print().

void EmitPrettyPrint::scan ( void  )
private

Process a new token.

The token is assumed to be just added and at the top of the queue. This is the heart of the pretty printing algorithm. The new token is assigned a size, the queue of open references and line breaks is updated. The amount of space currently available and the size of printing groups are updated. If the current line is going to overflow, a decision is mode where in the uncommented tokens a line break needs to be inserted and what its indent level will be. If the leftmost print group closes without needing a line break, all the content it contains is committed and is sent to the low-level emitter.

References TokenSplit::begin, TokenSplit::begin_comment, TokenSplit::begin_indent, TokenSplit::end, TokenSplit::end_comment, TokenSplit::end_indent, TokenSplit::getClass(), TokenSplit::getSize(), TokenSplit::ignore, TokenSplit::setSize(), TokenSplit::tokenbreak, and TokenSplit::tokenstring.

virtual void EmitPrettyPrint::setCommentFill ( const string &  fill)
inlinevirtual

Set the comment fill characters for when line breaks are forced.

If the pretty printer forces a line break in the middle of a comment, this string is emitted to provide proper syntax and indenting to continue the comment.

Parameters
fillis the set of fill characters

Reimplemented from EmitXml.

void EmitPrettyPrint::setMaxLineSize ( int4  mls)
virtual

Provide a maximum line size to the pretty printer.

The emitter may insert line breaks to enforce this maximum.

Parameters
mlsis the number of characters to set for the maximum line size

Reimplemented from EmitXml.

References EmitXml::clear().

void EmitPrettyPrint::setXML ( bool  val)

Toggle whether the low-level emitter emits XML markup or not.

This method toggles the low-level emitter between EmitXml and EmitNoXml depending on whether XML markup is desired.

Parameters
valis true if XML markup is desired

References EmitXml::EmitXml(), and EmitXml::setOutputStream().

void EmitPrettyPrint::spaces ( int4  num,
int4  bump = 0 
)
virtual

Emit a sequence of space characters as part of source code.

Parameters
numis the number of space characters to emit
bumpis the number of characters to indent if the spaces force a line break

Reimplemented from EmitXml.

References TokenSplit::spaces().

int4 EmitPrettyPrint::startComment ( void  )
virtual

Start a comment block within the emitted source code.

Inform the emitter that a set of comment tokens/lines is starting.

Returns
an id associated with the comment block

Reimplemented from EmitXml.

References TokenSplit::startComment().

int4 EmitPrettyPrint::startIndent ( void  )
virtual

Start a new indent level.

Inform the emitter that one level of nesting is being added.

Returns
an id associated with the nesting

Reimplemented from EmitXml.

References EmitXml::indentincrement, and TokenSplit::startIndent().

void EmitPrettyPrint::stopComment ( int4  id)
virtual

End a comment block.

Inform the emitter that a set of comment tokens/lines is ending.

Parameters
idis the id associated with the block (as returned by startComment)

Reimplemented from EmitXml.

References TokenSplit::stopComment().

void EmitPrettyPrint::stopIndent ( int4  id)
virtual

End an indent level.

Inform the emitter that the current nesting has ended, and we are returning to the previous level.

Parameters
idis the id associated with the nesting (as returned by startIndent)

Reimplemented from EmitXml.

References TokenSplit::stopIndent().

void EmitPrettyPrint::tagComment ( const char *  ptr,
syntax_highlight  hl,
const AddrSpace spc,
uintb  off 
)
virtual

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.

Parameters
ptris the character data for the comment
hlindicates how the comment should be highlighted
spcis the address space of the address where the comment is attached
offis the offset of the address where the comment is attached

Reimplemented from EmitXml.

References TokenSplit::tagComment().

void EmitPrettyPrint::tagField ( const char *  ptr,
syntax_highlight  hl,
const Datatype ct,
int4  o 
)
virtual

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.

Parameters
ptris the character data for the identifier
hlindicates how the identifier should be highlighted
ctis the data-type associated with the field
ois the (byte) offset of the field within its structured data-type

Reimplemented from EmitXml.

References TokenSplit::tagField().

void EmitPrettyPrint::tagFuncName ( const char *  ptr,
syntax_highlight  hl,
const Funcdata fd,
const PcodeOp op 
)
virtual

Emit a function identifier.

An identifier string representing the symbol name of the function is emitted, possible with additional markup.

Parameters
ptris the character data for the identifier
hlindicates how the identifier should be highlighted
fdis the function
opis the CALL operation associated within the syntax tree or null for a declaration

Reimplemented from EmitXml.

References TokenSplit::tagFuncName().

void EmitPrettyPrint::tagLabel ( const char *  ptr,
syntax_highlight  hl,
const AddrSpace spc,
uintb  off 
)
virtual

Emit a code label identifier.

A string describing a control-flow destination, as appropriate for the source language is output, possibly with additional markup.

Parameters
ptris the character data of the label
hlindicates how the label should be highlighted
spcis the address space of the code address being labeled
offis the offset of the code address being labeled

Reimplemented from EmitXml.

References TokenSplit::tagLabel().

void EmitPrettyPrint::tagLine ( void  )
virtual

Force a line break.

Tell the emitter that a new line is desired at the current indent level.

Reimplemented from EmitXml.

References TokenSplit::tagLine().

void EmitPrettyPrint::tagLine ( int4  indent)
virtual

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.

Parameters
indentis the desired indent level for the new line

Reimplemented from EmitXml.

References TokenSplit::tagLine().

void EmitPrettyPrint::tagOp ( const char *  ptr,
syntax_highlight  hl,
const PcodeOp op 
)
virtual

Emit an operation token.

The string representing the operation as appropriate for the source language is emitted, possibly with additional markup.

Parameters
ptris the character data for the emitted representation
hlindicates how the token should be highlighted
opis the PcodeOp object associated with the operation with the syntax tree

Reimplemented from EmitXml.

References TokenSplit::tagOp().

void EmitPrettyPrint::tagType ( const char *  ptr,
syntax_highlight  hl,
const Datatype ct 
)
virtual

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.

Parameters
ptris the character data for the identifier
hlindicates how the identifier should be highlighted
ctis the data-type description object

Reimplemented from EmitXml.

References TokenSplit::tagType().

void EmitPrettyPrint::tagVariable ( const char *  ptr,
syntax_highlight  hl,
const Varnode vn,
const PcodeOp op 
)
virtual

Emit a variable token.

An identifier string representing the variable is output, possibly with additional markup.

Parameters
ptris the character data for the identifier
hlindicates how the identifier should be highlighted
vnis the Varnode representing the variable within the syntax tree
opis a p-code operation related to the use of the variable (may be null)

Reimplemented from EmitXml.

References TokenSplit::tagVariable().


The documentation for this class was generated from the following files: