Merge remote-tracking branch 'origin/GP-3965_DecompilerBraces'

(Closes #81, Closes #1937, Closes #1938, Closes #4914, Closes #1240)
This commit is contained in:
Ryan Kurtz 2023-12-01 06:42:42 -05:00
commit bad90171c4
11 changed files with 374 additions and 74 deletions

View File

@ -1161,6 +1161,6 @@ ElementId ELEM_VAL = ElementId("val",8);
ElementId ELEM_VALUE = ElementId("value",9);
ElementId ELEM_VOID = ElementId("void",10);
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",284); // Number serves as next open index
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",285); // Number serves as next open index
} // End namespace ghidra

View File

@ -60,6 +60,7 @@ ElementId ELEM_TOGGLERULE = ElementId("togglerule",209);
ElementId ELEM_WARNING = ElementId("warning",210);
ElementId ELEM_JUMPTABLEMAX = ElementId("jumptablemax",271);
ElementId ELEM_NANIGNORE = ElementId("nanignore",272);
ElementId ELEM_BRACEFORMAT = ElementId("braceformat",284);
/// If the parameter is "on" return \b true, if "off" return \b false.
/// Any other value causes an exception.
@ -117,6 +118,7 @@ OptionDatabase::OptionDatabase(Architecture *g)
registerOption(new OptionCommentHeader());
registerOption(new OptionCommentInstruction());
registerOption(new OptionIntegerFormat());
registerOption(new OptionBraceFormat());
registerOption(new OptionCurrentAction());
registerOption(new OptionAllowContextSet());
registerOption(new OptionSetAction());
@ -578,6 +580,47 @@ string OptionIntegerFormat::apply(Architecture *glb,const string &p1,const strin
return "Integer format set to "+p1;
}
/// \class OptionBraceFormat
/// \brief Set the brace formatting strategy for various types of code block
///
/// The first parameter is the strategy name:
/// - \b same - For an opening brace on the same line
/// - \b next - For an opening brace on the next line
/// - \b skip - For an opening brace after a blank line
///
/// The second parameter is the type of code block:
/// - \b function - For the main function body
/// - \b ifelse - For if/else blocks
/// - \b loop - For do/while/for loop blocks
/// - \b switch - For a switch block
string OptionBraceFormat::apply(Architecture *glb,const string &p1,const string &p2,const string &p3) const
{
PrintC *lng = dynamic_cast<PrintC *>(glb->print);
if (lng == (PrintC *)0)
return "Can only set brace formatting for C language";
Emit::brace_style style;
if (p2 == "same")
style = Emit::same_line;
else if (p2 == "next")
style = Emit::next_line;
else if (p2 == "skip")
style = Emit::skip_line;
else
throw ParseError("Unknown brace style: "+p2);
if (p1 == "function")
lng->setBraceFormatFunction(style);
else if (p1 == "ifelse")
lng->setBraceFormatIfElse(style);
else if (p1 == "loop")
lng->setBraceFormatLoop(style);
else if (p1 == "switch")
lng->setBraceFormatSwitch(style);
else
throw ParseError("Unknown brace format category: "+p1);
return "Brace formatting for " + p1 + " set to " + p2;
}
/// \class OptionSetAction
/// \brief Establish a new root Action for the decompiler
///

View File

@ -235,6 +235,12 @@ public:
virtual string apply(Architecture *glb,const string &p1,const string &p2,const string &p3) const;
};
class OptionBraceFormat : public ArchOption {
public:
OptionBraceFormat(void) { name = "braceformat"; } ///< Constructor
virtual string apply(Architecture *glb,const string &p1,const string &p2,const string &p3) const;
};
class OptionSetAction : public ArchOption {
public:
OptionSetAction(void) { name = "setaction"; } ///< Constructor

View File

@ -58,6 +58,38 @@ void Emit::spaces(int4 num,int4 bump)
}
}
int4 Emit::openBraceIndent(const string &brace,brace_style style)
{
if (style == same_line)
spaces(1);
else if (style == skip_line) {
tagLine();
tagLine();
}
else {
tagLine();
}
int4 id = startIndent();
print(brace);
return id;
}
void Emit::openBrace(const string &brace,brace_style style)
{
if (style == same_line)
spaces(1);
else if (style == skip_line) {
tagLine();
tagLine();
}
else {
tagLine();
}
print(brace);
}
EmitMarkup::~EmitMarkup(void)
{

View File

@ -120,6 +120,13 @@ public:
error_color = 9, ///< Indicates a warning or error state
special_color = 10 ///< A token with special/highlighted meaning
};
/// \brief Different brace formatting styles
enum brace_style {
same_line = 0, ///< Opening brace on the same line as if/do/while/for/switch
next_line = 1, ///< Opening brace is on next line
skip_line = 2 ///< Opening brace is two lines down
};
virtual ~Emit(void) {} ///< Destructor
/// \brief Begin a whole document of output
@ -294,7 +301,7 @@ public:
/// \brief Emit a \e case label constant
///
/// A string describing the \e switch variable value is emitted and starting PcodeOp of the \e case block.
/// A string describing the \e switch variable value and starting PcodeOp of the \e case block.
/// \param name is the character data of the value
/// \param hl indicates how the value should be highlighted
/// \param op is the first PcodeOp in the \e case block
@ -436,6 +443,31 @@ public:
/// \return \b true if the specific print callback is pending
bool hasPendingPrint(PendPrint *pend) const { return (pendPrint == pend); }
/// \brief Emit an opening brace given a specific format and add an indent level
///
/// The brace is emitted on the same line, or on a following line,
/// depending on the selected style. One level of indent is added.
/// \param brace is the string to display as the opening brace
/// \param style indicates how the brace should be formatted
/// \return the nesting id associated with the index
int4 openBraceIndent(const string &brace,brace_style style);
/// \brief Emit an opening brace given a specific format
///
/// The indent level is \e not increased. The brace is emitted on the same
/// line, or on a following line, depending on the selected style.
/// \param brace is the string to display as the opening brace
/// \param style indicates how the brace should be formatted
void openBrace(const string &brace,brace_style style);
/// \brief Emit a closing brace and remove an indent level
///
/// The brace is emitted on the next line.
/// \param brace is the string to display as the closing brace
/// \param id is nesting id of the indent being removed
void closeBraceIndent(const string &brace,int4 id) {
stopIndent(id); tagLine(); print(brace);
}
};
/// \brief Emitter that associates markup with individual tokens
@ -1083,8 +1115,9 @@ inline void Emit::emitPending(void)
{
if (pendPrint != (PendPrint *)0) {
pendPrint->callback(this);
pendPrint = (PendPrint *)0;
PendPrint *tmp = pendPrint;
pendPrint = (PendPrint *)0; // Clear pending before callback
tmp->callback(this);
}
}

View File

@ -1568,6 +1568,10 @@ void PrintC::resetDefaultsPrintC(void)
option_nocasts = false;
option_NULL = false;
option_unplaced = false;
option_brace_func = Emit::skip_line;
option_brace_ifelse = Emit::same_line;
option_brace_loop = Emit::same_line;
option_brace_switch = Emit::same_line;
setCStyleComments();
}
@ -2096,9 +2100,7 @@ void PrintC::emitStructDefinition(const TypeStruct *ct)
emit->tagLine();
emit->print("typedef struct",EmitMarkup::keyword_color);
emit->spaces(1);
int4 id = emit->startIndent();
emit->print(OPEN_CURLY);
int4 id = emit->openBraceIndent(OPEN_CURLY, Emit::same_line);
emit->tagLine();
iter = ct->beginField();
while(iter!=ct->endField()) {
@ -2111,9 +2113,7 @@ void PrintC::emitStructDefinition(const TypeStruct *ct)
emit->tagLine();
}
}
emit->stopIndent(id);
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, id);
emit->spaces(1);
emit->print(ct->getDisplayName());
emit->print(SEMICOLON);
@ -2135,9 +2135,7 @@ void PrintC::emitEnumDefinition(const TypeEnum *ct)
bool sign = (ct->getMetatype() == TYPE_INT);
emit->tagLine();
emit->print("typedef enum",EmitMarkup::keyword_color);
emit->spaces(1);
int4 id = emit->startIndent();
emit->print(OPEN_CURLY);
int4 id = emit->openBraceIndent(OPEN_CURLY, Emit::same_line);
emit->tagLine();
iter = ct->beginEnum();
while(iter!=ct->endEnum()) {
@ -2153,9 +2151,7 @@ void PrintC::emitEnumDefinition(const TypeEnum *ct)
emit->tagLine();
}
popMod();
emit->stopIndent(id);
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, id);
emit->spaces(1);
emit->print(ct->getDisplayName());
emit->print(SEMICOLON);
@ -2627,19 +2623,14 @@ void PrintC::docFunction(const Funcdata *fd)
emitCommentFuncHeader(fd);
emit->tagLine();
emitFunctionDeclaration(fd); // Causes us to enter function's scope
emit->tagLine();
emit->tagLine();
int4 id = emit->startIndent();
emit->print(OPEN_CURLY);
int4 id = emit->openBraceIndent(OPEN_CURLY, option_brace_func);
emitLocalVarDecls(fd);
if (isSet(flat))
emitBlockGraph(&fd->getBasicBlocks());
else
emitBlockGraph(&fd->getStructure());
popScope(); // Exit function's scope
emit->stopIndent(id);
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, id);
emit->tagLine();
emit->endFunction(id1);
emit->flush();
@ -2852,15 +2843,14 @@ void PrintC::emitBlockCondition(const BlockCondition *bl)
void PendingBrace::callback(Emit *emit)
{
emit->print(PrintC::OPEN_CURLY);
indentId = emit->startIndent();
indentId = emit->openBraceIndent(PrintC::OPEN_CURLY, style);
}
void PrintC::emitBlockIf(const BlockIf *bl)
{
const PcodeOp *op;
PendingBrace pendingBrace;
PendingBrace pendingBrace(option_brace_ifelse);
if (isSet(pending_brace))
emit->setPendingPrint(&pendingBrace);
@ -2878,8 +2868,10 @@ void PrintC::emitBlockIf(const BlockIf *bl)
condBlock->emit(this);
popMod();
emitCommentBlockTree(condBlock);
if (emit->hasPendingPrint(&pendingBrace)) // If we issued a brace but it did not emit
if (emit->hasPendingPrint(&pendingBrace)) { // If we issued a brace but it did not emit
emit->cancelPendingPrint(); // Cancel the brace in order to have "else if" syntax
emit->spaces(1);
}
else
emit->tagLine(); // Otherwise start the "if" on a new line
@ -2896,19 +2888,14 @@ void PrintC::emitBlockIf(const BlockIf *bl)
}
else {
setMod(no_branch);
emit->spaces(1);
int4 id = emit->startIndent();
emit->print(OPEN_CURLY);
int4 id = emit->openBraceIndent(OPEN_CURLY, option_brace_ifelse);
int4 id1 = emit->beginBlock(bl->getBlock(1));
bl->getBlock(1)->emit(this);
emit->endBlock(id1);
emit->stopIndent(id);
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, id);
if (bl->getSize() == 3) {
emit->tagLine();
emit->print(KEYWORD_ELSE,EmitMarkup::keyword_color);
emit->spaces(1);
FlowBlock *elseBlock = bl->getBlock(2);
if (elseBlock->getType() == FlowBlock::t_if) {
// Attempt to merge the "else" and "if" syntax
@ -2918,22 +2905,17 @@ void PrintC::emitBlockIf(const BlockIf *bl)
emit->endBlock(id2);
}
else {
int4 id2 = emit->startIndent();
emit->print(OPEN_CURLY);
int4 id2 = emit->openBraceIndent(OPEN_CURLY, option_brace_ifelse);
int4 id3 = emit->beginBlock(elseBlock);
elseBlock->emit(this);
emit->endBlock(id3);
emit->stopIndent(id2);
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, id2);
}
}
}
popMod();
if (pendingBrace.getIndentId() >= 0) {
emit->stopIndent(pendingBrace.getIndentId());
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, pendingBrace.getIndentId());
}
}
@ -2978,16 +2960,12 @@ void PrintC::emitForLoop(const BlockWhileDo *bl)
emit->endStatement(id4);
popMod();
emit->closeParen(CLOSE_PAREN,id1);
emit->spaces(1);
indent = emit->startIndent();
emit->print(OPEN_CURLY);
indent = emit->openBraceIndent(OPEN_CURLY, option_brace_loop);
setMod(no_branch); // Dont print goto at bottom of clause
int4 id2 = emit->beginBlock(bl->getBlock(1));
bl->getBlock(1)->emit(this);
emit->endBlock(id2);
emit->stopIndent(indent);
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, indent);
popMod();
}
@ -3019,9 +2997,7 @@ void PrintC::emitBlockWhileDo(const BlockWhileDo *bl)
emit->print(KEYWORD_TRUE,EmitMarkup::const_color);
emit->spaces(1);
emit->closeParen(CLOSE_PAREN,id1);
emit->spaces(1);
indent = emit->startIndent();
emit->print(OPEN_CURLY);
indent = emit->openBraceIndent(OPEN_CURLY, option_brace_loop);
pushMod();
setMod(no_branch);
condBlock->emit(this);
@ -3050,17 +3026,13 @@ void PrintC::emitBlockWhileDo(const BlockWhileDo *bl)
condBlock->emit(this);
popMod();
emit->closeParen(CLOSE_PAREN,id1);
emit->spaces(1);
indent = emit->startIndent();
emit->print(OPEN_CURLY);
indent = emit->openBraceIndent(OPEN_CURLY, option_brace_loop);
}
setMod(no_branch); // Dont print goto at bottom of clause
int4 id2 = emit->beginBlock(bl->getBlock(1));
bl->getBlock(1)->emit(this);
emit->endBlock(id2);
emit->stopIndent(indent);
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, indent);
popMod();
}
@ -3075,18 +3047,14 @@ void PrintC::emitBlockDoWhile(const BlockDoWhile *bl)
emitAnyLabelStatement(bl);
emit->tagLine();
emit->print(KEYWORD_DO,EmitMarkup::keyword_color);
emit->spaces(1);
int4 id = emit->startIndent();
emit->print(OPEN_CURLY);
int4 id = emit->openBraceIndent(OPEN_CURLY, option_brace_loop);
pushMod();
int4 id2 = emit->beginBlock(bl->getBlock(0));
setMod(no_branch);
bl->getBlock(0)->emit(this);
emit->endBlock(id2);
popMod();
emit->stopIndent(id);
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, id);
emit->spaces(1);
op = bl->getBlock(0)->lastOp();
emit->tagOp(KEYWORD_WHILE,EmitMarkup::keyword_color,op);
@ -3107,15 +3075,11 @@ void PrintC::emitBlockInfLoop(const BlockInfLoop *bl)
emitAnyLabelStatement(bl);
emit->tagLine();
emit->print(KEYWORD_DO,EmitMarkup::keyword_color);
emit->spaces(1);
int4 id = emit->startIndent();
emit->print(OPEN_CURLY);
int4 id = emit->openBraceIndent(OPEN_CURLY, option_brace_loop);
int4 id1 = emit->beginBlock(bl->getBlock(0));
bl->getBlock(0)->emit(this);
emit->endBlock(id1);
emit->stopIndent(id);
emit->tagLine();
emit->print(CLOSE_CURLY);
emit->closeBraceIndent(CLOSE_CURLY, id);
emit->spaces(1);
op = bl->getBlock(0)->lastOp();
emit->tagOp(KEYWORD_WHILE,EmitMarkup::keyword_color,op);
@ -3333,8 +3297,7 @@ void PrintC::emitBlockSwitch(const BlockSwitch *bl)
setMod(only_branch|comma_separate);
bl->getSwitchBlock()->emit(this);
popMod();
emit->spaces(1);
emit->print(OPEN_CURLY);
emit->openBrace(OPEN_CURLY,option_brace_switch);
for(int4 i=0;i<bl->getNumCaseBlocks();++i) {
emitSwitchCase(i,bl);

View File

@ -148,6 +148,10 @@ protected:
bool option_nocasts; ///< Don't print a cast if \b true
bool option_unplaced; ///< Set to \b true if we should display unplaced comments
bool option_hide_exts; ///< Set to \b true if we should hide implied extension operations
Emit::brace_style option_brace_func; ///< How function declaration braces should be formatted
Emit::brace_style option_brace_ifelse; ///< How braces for if/else blocks are formatted
Emit::brace_style option_brace_loop; ///< How braces for loop blocks are formatted
Emit::brace_style option_brace_switch; ///< How braces for switch blocks are formatted
string nullToken; ///< Token to use for 'null'
string sizeSuffix; ///< Characters to print to indicate a \e long integer token
CommentSorter commsorter; ///< Container/organizer for comments in the current function
@ -238,6 +242,10 @@ public:
void setCPlusPlusStyleComments(void) { setCommentDelimeter("// ","",true); } ///< Set c++-style "//" comment delimiters
void setDisplayUnplaced(bool val) { option_unplaced = val; } ///< Toggle whether \e unplaced comments are displayed in the header
void setHideImpliedExts(bool val) { option_hide_exts = val; } ///< Toggle whether implied extensions are hidden
void setBraceFormatFunction(Emit::brace_style style) { option_brace_func = style; } ///< Set how function declarations are formatted
void setBraceFormatIfElse(Emit::brace_style style) { option_brace_ifelse = style; } ///< Set how if/else blocks are formatted
void setBraceFormatLoop(Emit::brace_style style) { option_brace_loop = style; } ///< Set how loop blocks are formatted
void setBraceFormatSwitch(Emit::brace_style style) { option_brace_switch = style; } ///< Set how switch blocks are formatted
virtual ~PrintC(void) {}
virtual void resetDefaults(void);
virtual void initializeFromArchitecture(void);
@ -341,8 +349,9 @@ public:
/// The open brace can be canceled if the block decides it wants to use "else if" syntax.
class PendingBrace : public PendPrint {
int4 indentId; ///< Id associated with the new indent level
Emit::brace_style style; ///< Style to use for pending brace
public:
PendingBrace(void) { indentId = -1; } ///< Constructor
PendingBrace(Emit::brace_style s) { indentId = -1; style = s; } ///< Constructor
int4 getIndentId(void) const { return indentId; } ///< If commands have been issued, returns the new indent level id.
virtual void callback(Emit *emit);
};

View File

@ -39,7 +39,7 @@
plug-in enabled, but if it is disabled for some reason, it can be enabled from within
a Code Browser by selecting the
<informalexample>
<emphasis role="bold">File -> Configure...</emphasis>
<emphasis role="bold">File -> Configure</emphasis>
</informalexample>
menu option, then clicking on the <emphasis>Configure</emphasis> link under the
<emphasis role="bold">Ghidra Core</emphasis> section and checking the box next to
@ -3269,6 +3269,36 @@
</para>
</listitem>
</varlistentry>
<varlistentry id="DisplayBraceFormatting">
<term><emphasis role="bold">Brace Format for &lt;kind-of&gt; blocks</emphasis></term>
<listitem>
<para>
Choose how braces are placed after function declarations, or other kinds of code blocks in Decompiler output.
Formatting can be controlled for:
<informalexample>
<itemizedlist mark='bullet'>
<listitem><emphasis role="bold">function blocks</emphasis> - the main function bodies</listitem>
<listitem><emphasis role="bold">if/else blocks</emphasis> - blocks delineated by the <code>if</code> and <code>else</code> keywords</listitem>
<listitem><emphasis role="bold">loop blocks</emphasis> - blocks delineated by the <code>for</code>, <code>do</code>, and <code>while</code> keywords</listitem>
<listitem><emphasis role="bold">switch blocks</emphasis> - blocks delineated by the <code>switch</code> keyword</listitem>
</itemizedlist>
</informalexample>
The different formatting options primarily control how the opening brace is displayed relative to the line containing
the declaration or keyword starting the block. The formatting options are:
<informalexample>
<itemizedlist mark='bullet'>
<listitem><emphasis role="bold">Same line</emphasis> - opening brace placed on same line</listitem>
<listitem><emphasis role="bold">Next line</emphasis> - opening brace placed on the next line</listitem>
<listitem><emphasis role="bold">Skip one line</emphasis> - opening brace placed on line after a blank line</listitem>
</itemizedlist>
</informalexample>
</para>
<para>
The "Same line" option is consistent with K &amp; R code formatting style. The "Next line" option is consistent with
the Allman formatting style.
</para>
</listitem>
</varlistentry>
<varlistentry id="DisplayColorDefault">
<term><emphasis role="bold">Color Default</emphasis></term>
<listitem>

View File

@ -436,6 +436,47 @@
</p>
</dd>
<dt>
<a name="DisplayBraceFormatting"></a><span class="term"><span class="bold"><strong>Brace Format for &lt;kind-of&gt; blocks</strong></span></span>
</dt>
<dd>
<p>
Choose how braces are placed after function declarations, or other kinds of code blocks in Decompiler output.
Formatting can be controlled for:
</p>
<div class="informalexample">
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: bullet; ">
<li class="listitem" style="list-style-type: disc">
<span class="bold"><strong>function blocks</strong></span> - the main function bodies</li>
<li class="listitem" style="list-style-type: disc">
<span class="bold"><strong>if/else blocks</strong></span> - blocks delineated by the <code class="code">if</code> and <code class="code">else</code> keywords</li>
<li class="listitem" style="list-style-type: disc">
<span class="bold"><strong>loop blocks</strong></span> - blocks delineated by the <code class="code">for</code>, <code class="code">do</code>, and <code class="code">while</code> keywords</li>
<li class="listitem" style="list-style-type: disc">
<span class="bold"><strong>switch blocks</strong></span> - blocks delineated by the <code class="code">switch</code> keyword</li>
</ul></div>
</div>
<p>
The different formatting options primarily control how the opening brace is displayed relative to the line containing
the declaration or keyword starting the block. The formatting options are:
</p>
<div class="informalexample">
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: bullet; ">
<li class="listitem" style="list-style-type: disc">
<span class="bold"><strong>Same line</strong></span> - opening brace placed on same line</li>
<li class="listitem" style="list-style-type: disc">
<span class="bold"><strong>Next line</strong></span> - opening brace placed on the next line</li>
<li class="listitem" style="list-style-type: disc">
<span class="bold"><strong>Skip one line</strong></span> - opening brace placed on line after a blank line</li>
</ul></div>
</div>
<p>
</p>
<p>
The "Same line" option is consistent with K &amp; R code formatting style. The "Next line" option is consistent with
the Allman formatting style.
</p>
</dd>
<dt>
<a name="DisplayColorDefault"></a><span class="term"><span class="bold"><strong>Color Default</strong></span></span>
</dt>
<dd>

View File

@ -217,6 +217,54 @@ public class DecompileOptions {
private final static boolean NOCAST_OPTIONDEFAULT = false; // Must match PrintC::resetDefaultsPrintC
private boolean noCastPrint;
public enum BraceStyle {
Same("same", "Same line"), Next("next", "Next line"), Skip("skip", "Skip one line");
private String label;
private String optionString;
private BraceStyle(String optString, String label) {
this.label = label;
this.optionString = optString;
}
public String getOptionString() {
return optionString;
}
@Override
public String toString() {
return label;
}
}
private final static String BRACEFUNCTION_OPTIONSTRING =
"Display.Brace format for function blocks";
private final static String BRACEFUNCTION_OPTIONDESCRIPTION =
"Where the opening brace is displayed, after a function declaration";
private final static BraceStyle BRACEFUNCTION_OPTIONDEFAULT = BraceStyle.Skip;
private BraceStyle braceFunction;
private final static String BRACEIFELSE_OPTIONSTRING =
"Display.Brace format for if/else blocks";
private final static String BRACEIFELSE_OPTIONDESCRIPTION =
"Where the opening brace is displayed, for an if/else code block";
private final static BraceStyle BRACEIFELSE_OPTIONDEFAULT = BraceStyle.Same;
private BraceStyle braceIfElse;
private final static String BRACELOOP_OPTIONSTRING = "Display.Brace format for loop blocks";
private final static String BRACELOOP_OPTIONDESCRIPTION =
"Where the opening brace is displayed, for the body of a loop";
private final static BraceStyle BRACELOOP_OPTIONDEFAULT = BraceStyle.Same;
private BraceStyle braceLoop;
private final static String BRACESWITCH_OPTIONSTRING = "Display.Brace format for switch blocks";
private final static String BRACESWITCH_OPTIONDESCRIPTION =
"Where the opening brace is displayed, for the body of a switch statement";
private final static BraceStyle BRACESWITCH_OPTIONDEFAULT = BraceStyle.Same;
private BraceStyle braceSwitch;
private final static String MAXWIDTH_OPTIONSTRING = "Display.Maximum characters in a code line";
private final static String MAXWIDTH_OPTIONDESCRIPTION =
"Maximum number of characters allowed per line before before line breaks are forced.";
@ -452,6 +500,10 @@ public class DecompileOptions {
aliasBlock = ALIASBLOCK_OPTIONDEFAULT;
conventionPrint = CONVENTION_OPTIONDEFAULT;
noCastPrint = NOCAST_OPTIONDEFAULT;
braceFunction = BRACEFUNCTION_OPTIONDEFAULT;
braceIfElse = BRACEIFELSE_OPTIONDEFAULT;
braceLoop = BRACELOOP_OPTIONDEFAULT;
braceSwitch = BRACESWITCH_OPTIONDEFAULT;
maxwidth = MAXWIDTH_OPTIONDEFAULT;
indentwidth = INDENTWIDTH_OPTIONDEFAULT;
commentindent = COMMENTINDENT_OPTIONDEFAULT;
@ -512,6 +564,10 @@ public class DecompileOptions {
aliasBlock = opt.getEnum(ALIASBLOCK_OPTIONSTRING, ALIASBLOCK_OPTIONDEFAULT);
conventionPrint = opt.getBoolean(CONVENTION_OPTIONSTRING, CONVENTION_OPTIONDEFAULT);
noCastPrint = opt.getBoolean(NOCAST_OPTIONSTRING, NOCAST_OPTIONDEFAULT);
braceFunction = opt.getEnum(BRACEFUNCTION_OPTIONSTRING, BRACEFUNCTION_OPTIONDEFAULT);
braceIfElse = opt.getEnum(BRACEIFELSE_OPTIONSTRING, BRACEIFELSE_OPTIONDEFAULT);
braceLoop = opt.getEnum(BRACELOOP_OPTIONSTRING, BRACELOOP_OPTIONDEFAULT);
braceSwitch = opt.getEnum(BRACESWITCH_OPTIONSTRING, BRACESWITCH_OPTIONDEFAULT);
maxwidth = opt.getInt(MAXWIDTH_OPTIONSTRING, MAXWIDTH_OPTIONDEFAULT);
indentwidth = opt.getInt(INDENTWIDTH_OPTIONSTRING, INDENTWIDTH_OPTIONDEFAULT);
commentindent = opt.getInt(COMMENTINDENT_OPTIONSTRING, COMMENTINDENT_OPTIONDEFAULT);
@ -642,6 +698,18 @@ public class DecompileOptions {
opt.registerOption(NOCAST_OPTIONSTRING, NOCAST_OPTIONDEFAULT,
new HelpLocation(HelpTopics.DECOMPILER, "DisplayDisableCasts"),
NOCAST_OPTIONDESCRIPTION);
opt.registerOption(BRACEFUNCTION_OPTIONSTRING, BRACEFUNCTION_OPTIONDEFAULT,
new HelpLocation(HelpTopics.DECOMPILER, "DisplayBraceFormatting"),
BRACEFUNCTION_OPTIONDESCRIPTION);
opt.registerOption(BRACEIFELSE_OPTIONSTRING, BRACEIFELSE_OPTIONDEFAULT,
new HelpLocation(HelpTopics.DECOMPILER, "DisplayBraceFormatting"),
BRACEIFELSE_OPTIONDESCRIPTION);
opt.registerOption(BRACELOOP_OPTIONSTRING, BRACELOOP_OPTIONDEFAULT,
new HelpLocation(HelpTopics.DECOMPILER, "DisplayBraceFormatting"),
BRACELOOP_OPTIONDESCRIPTION);
opt.registerOption(BRACESWITCH_OPTIONSTRING, BRACESWITCH_OPTIONDEFAULT,
new HelpLocation(HelpTopics.DECOMPILER, "DisplayBraceFormatting"),
BRACESWITCH_OPTIONDESCRIPTION);
opt.registerOption(MAXWIDTH_OPTIONSTRING, MAXWIDTH_OPTIONDEFAULT,
new HelpLocation(HelpTopics.DECOMPILER, "DisplayMaxChar"), MAXWIDTH_OPTIONDESCRIPTION);
opt.registerOption(INDENTWIDTH_OPTIONSTRING, INDENTWIDTH_OPTIONDEFAULT,
@ -826,6 +894,19 @@ public class DecompileOptions {
if (noCastPrint != NOCAST_OPTIONDEFAULT) {
appendOption(encoder, ELEM_NOCASTPRINTING, noCastPrint ? "on" : "off", "", "");
}
if (braceFunction != BRACEFUNCTION_OPTIONDEFAULT) {
appendOption(encoder, ELEM_BRACEFORMAT, "function", braceFunction.getOptionString(),
"");
}
if (braceIfElse != BRACEIFELSE_OPTIONDEFAULT) {
appendOption(encoder, ELEM_BRACEFORMAT, "ifelse", braceIfElse.getOptionString(), "");
}
if (braceLoop != BRACELOOP_OPTIONDEFAULT) {
appendOption(encoder, ELEM_BRACEFORMAT, "loop", braceLoop.getOptionString(), "");
}
if (braceSwitch != BRACESWITCH_OPTIONDEFAULT) {
appendOption(encoder, ELEM_BRACEFORMAT, "switch", braceSwitch.getOptionString(), "");
}
if (maxwidth != MAXWIDTH_OPTIONDEFAULT) {
appendOption(encoder, ELEM_MAXLINEWIDTH, Integer.toString(maxwidth), "", "");
}
@ -884,6 +965,66 @@ public class DecompileOptions {
encoder.closeElement(ELEM_OPTIONSLIST);
}
/**
* @return the brace formatting style for function bodies
*/
public BraceStyle getFunctionBraceFormat() {
return braceFunction;
}
/**
* Set how braces are formatted around a function body
* @param style is the formatting style
*/
public void setFunctionBraceFormat(BraceStyle style) {
this.braceFunction = style;
}
/**
* @return the brace formatting style for if/else code blocks
*/
public BraceStyle getIfElseBraceFormat() {
return braceIfElse;
}
/**
* Set how braces are formatted around an if/else code block
* @param style is the formatting style
*/
public void setIfElseBraceFormat(BraceStyle style) {
this.braceIfElse = style;
}
/**
* @return the brace formatting style for loop bodies
*/
public BraceStyle getLoopBraceFormat() {
return braceLoop;
}
/**
* Set how braces are formatted a loop body
* @param style is the formatting style
*/
public void setLoopBraceFormat(BraceStyle style) {
this.braceLoop = style;
}
/**
* @return the brace formatting style for switch blocks
*/
public BraceStyle getSwitchBraceFormat() {
return braceSwitch;
}
/**
* Set how braces are formatted around a switch block
* @param style is the formatting style
*/
public void setSwitchBraceFormat(BraceStyle style) {
this.braceSwitch = style;
}
/**
* @return the maximum number of characters the decompiler displays in a single line of output
*/

View File

@ -314,6 +314,8 @@ public record ElementId(String name, int id) {
public static final ElementId ELEM_TOGGLERULE = new ElementId("togglerule", 209);
public static final ElementId ELEM_WARNING = new ElementId("warning", 210);
public static final ElementId ELEM_BRACEFORMAT = new ElementId("braceformat", 284);
// jumptable
public static final ElementId ELEM_BASICOVERRIDE = new ElementId("basicoverride", 211);
public static final ElementId ELEM_DEST = new ElementId("dest", 212);
@ -439,5 +441,5 @@ public record ElementId(String name, int id) {
public static final ElementId ELEM_JOIN_PER_PRIMITIVE =
new ElementId("join_per_primitive", 283);
public static final ElementId ELEM_UNKNOWN = new ElementId("XMLunknown", 284);
public static final ElementId ELEM_UNKNOWN = new ElementId("XMLunknown", 285);
}