diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc
index b6e8aff94a..7e7ef1b194 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc
@@ -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
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc
index d5f2d5472e..877e1e2a12 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc
@@ -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(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
///
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/options.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/options.hh
index 2ff255c5c7..7a7f713b84 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/options.hh
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/options.hh
@@ -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
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc
index f4c25bfdf4..459ee5c341 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc
@@ -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)
{
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.hh
index e7f4a08da1..4b96b8cace 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.hh
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.hh
@@ -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);
}
}
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc
index dc81ae4233..d0623559f9 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc
@@ -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;igetNumCaseBlocks();++i) {
emitSwitchCase(i,bl);
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh
index 91f1197711..4373b58b4f 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh
@@ -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);
};
diff --git a/Ghidra/Features/Decompiler/src/main/doc/decompileplugin.xml b/Ghidra/Features/Decompiler/src/main/doc/decompileplugin.xml
index 11c1c94a03..31cc4bb79a 100644
--- a/Ghidra/Features/Decompiler/src/main/doc/decompileplugin.xml
+++ b/Ghidra/Features/Decompiler/src/main/doc/decompileplugin.xml
@@ -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
- File -> Configure...
+ File -> Configure
menu option, then clicking on the Configure link under the
Ghidra Core section and checking the box next to
@@ -3269,6 +3269,36 @@
+
+ Brace Format for <kind-of> blocks
+
+
+ Choose how braces are placed after function declarations, or other kinds of code blocks in Decompiler output.
+ Formatting can be controlled for:
+
+
+ function blocks - the main function bodies
+ if/else blocks - blocks delineated by the if
and else
keywords
+ loop blocks - blocks delineated by the for
, do
, and while
keywords
+ switch blocks - blocks delineated by the switch
keyword
+
+
+ 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:
+
+
+ Same line - opening brace placed on same line
+ Next line - opening brace placed on the next line
+ Skip one line - opening brace placed on line after a blank line
+
+
+
+
+ The "Same line" option is consistent with K & R code formatting style. The "Next line" option is consistent with
+ the Allman formatting style.
+
+
+
Color Default
diff --git a/Ghidra/Features/Decompiler/src/main/help/help/topics/DecompilePlugin/DecompilerOptions.html b/Ghidra/Features/Decompiler/src/main/help/help/topics/DecompilePlugin/DecompilerOptions.html
index a2996b1cd7..a59fceb8df 100644
--- a/Ghidra/Features/Decompiler/src/main/help/help/topics/DecompilePlugin/DecompilerOptions.html
+++ b/Ghidra/Features/Decompiler/src/main/help/help/topics/DecompilePlugin/DecompilerOptions.html
@@ -436,6 +436,47 @@
+Brace Format for <kind-of> blocks
+
+
+
+ Choose how braces are placed after function declarations, or other kinds of code blocks in Decompiler output.
+ Formatting can be controlled for:
+
+
+
+ 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:
+
+
+
+
+
+ The "Same line" option is consistent with K & R code formatting style. The "Next line" option is consistent with
+ the Allman formatting style.
+
+
+
Color Default
diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java
index 0800d12c9a..a7eb7c227d 100644
--- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java
+++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java
@@ -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
*/
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/ElementId.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/ElementId.java
index c47b4b17bb..51bfc12ef3 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/ElementId.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/ElementId.java
@@ -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);
}