summaryrefslogtreecommitdiffstats
path: root/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/braces.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/braces.cpp')
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/braces.cpp1629
1 files changed, 1629 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/braces.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/braces.cpp
new file mode 100644
index 00000000..f13c0076
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/braces.cpp
@@ -0,0 +1,1629 @@
+/**
+ * @file braces.cpp
+ * Adds or removes braces.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "braces.h"
+
+#include "calculate_closing_brace_position.h"
+#include "combine_tools.h"
+#include "newlines.h"
+#include "prototypes.h"
+
+constexpr static auto LCURRENT = LBR;
+
+using namespace uncrustify;
+
+using std::vector;
+
+
+//! Converts a single brace into a virtual brace
+static void convert_brace(chunk_t *br);
+
+
+//! Converts a single virtual brace into a real brace
+static void convert_vbrace(chunk_t *br);
+
+
+static void convert_vbrace_to_brace(void);
+
+
+//! Go backwards to honor brace newline removal limits
+static void examine_braces(void);
+
+
+/**
+ * Step forward and count the number of semi colons at the current level.
+ * Abort if more than 1 or if we enter a preprocessor
+ */
+static void examine_brace(chunk_t *bopen);
+
+
+static void move_case_break(void);
+
+
+static void mod_case_brace(void);
+
+
+static void mod_full_brace_if_chain(void);
+
+
+/**
+ * Checks to see if the braces can be removed.
+ * - less than a certain length
+ * - doesn't mess up if/else stuff
+ */
+static bool can_remove_braces(chunk_t *bopen);
+
+
+/**
+ * Checks to see if the virtual braces should be converted to real braces.
+ * - over a certain length
+ *
+ * @param vbopen Virtual Brace Open chunk
+ *
+ * @return true (convert to real braces) or false (leave alone)
+ */
+static bool should_add_braces(chunk_t *vbopen);
+
+
+/**
+ * Collect the text into txt that contains the full tag name.
+ * Mainly for collecting namespace 'a.b.c' or function 'foo::bar()' names.
+ */
+static void append_tag_name(unc_text &txt, chunk_t *pc);
+
+
+//! Remove the case brace, if allowable.
+static chunk_t *mod_case_brace_remove(chunk_t *br_open);
+
+
+//! Add the case brace, if allowable.
+static chunk_t *mod_case_brace_add(chunk_t *cl_colon);
+
+
+/**
+ * Traverse the if chain and see if all can be removed
+ *
+ * @param br_start chunk pointing to opening brace of if clause
+ */
+static void process_if_chain(chunk_t *br_start);
+
+
+/**
+ * Check if parenthesis pair that comes before a brace spans multiple lines
+ *
+ *
+ * @param brace the brace chunk whose predecessing parenthesis will be checked
+ *
+ * @pre the brace chunk cannot be a nullptr,
+ * it needs to be of type CT_BRACE_OPEN or CT_BRACE_CLOSE,
+ * its parent type needs to be one of this types:
+ * CT_IF, CT_ELSEIF, CT_FOR, CT_USING_STMT, CT_WHILE,
+ * CT_FUNC_CLASS_DEF, CT_FUNC_DEF
+ *
+ * @return false: if preconditions are not met,
+ * if an error occurs while counting the newline between the
+ * parenthesis or
+ * when no newlines are found between the parenthesis
+ */
+static bool paren_multiline_before_brace(chunk_t *brace)
+{
+ if ( brace == nullptr
+ || ( chunk_is_not_token(brace, CT_BRACE_OPEN)
+ && chunk_is_not_token(brace, CT_BRACE_CLOSE))
+ || ( get_chunk_parent_type(brace) != CT_IF
+ && get_chunk_parent_type(brace) != CT_ELSEIF
+ && get_chunk_parent_type(brace) != CT_FOR
+ && get_chunk_parent_type(brace) != CT_USING_STMT
+ && get_chunk_parent_type(brace) != CT_WHILE
+ && get_chunk_parent_type(brace) != CT_FUNC_CLASS_DEF
+ && get_chunk_parent_type(brace) != CT_FUNC_DEF))
+ {
+ return(false);
+ }
+ const auto paren_t = CT_SPAREN_CLOSE;
+
+ // find parenthesis pair of the if/for/while/...
+ auto paren_close = chunk_get_prev_type(brace, paren_t, brace->level, scope_e::ALL);
+ auto paren_open = chunk_skip_to_match_rev(paren_close, scope_e::ALL);
+
+ if ( paren_close == nullptr
+ || paren_open == nullptr
+ || paren_close == brace
+ || paren_open == paren_close)
+ {
+ return(false);
+ }
+ // determine number of lines in the parenthesis pair spans
+ auto nl_count = size_t{};
+ const auto ret_flag = newlines_between(paren_open, paren_close, nl_count);
+
+ if (!ret_flag)
+ {
+ LOG_FMT(LERR, "%s(%d): newlines_between error\n", __func__, __LINE__);
+ return(false);
+ }
+ // nl_count = 0 -> 1 line
+ return(nl_count > 0);
+}
+
+
+void do_braces(void)
+{
+ LOG_FUNC_ENTRY();
+ // Mark one-liners
+ // Issue #2232 put this at the beginning
+ chunk_t *pc = chunk_get_head();
+
+ while ((pc = chunk_get_next_ncnnl(pc)) != nullptr)
+ {
+ if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
+ && chunk_is_not_token(pc, CT_VBRACE_OPEN))
+ {
+ continue;
+ }
+ chunk_t *br_open = pc;
+ const c_token_t brc_type = c_token_t(pc->type + 1); // corresponds to closing type
+ // Detect empty bodies
+ chunk_t *tmp = chunk_get_next_ncnnl(pc);
+
+ if (chunk_is_token(tmp, brc_type))
+ {
+ chunk_flags_set(br_open, PCF_EMPTY_BODY);
+ chunk_flags_set(tmp, PCF_EMPTY_BODY);
+ }
+ // Scan for the brace close or a newline
+ tmp = br_open;
+
+ while ((tmp = chunk_get_next_nc(tmp)) != nullptr)
+ {
+ if (chunk_is_newline(tmp))
+ {
+ break;
+ }
+
+ if ( chunk_is_token(tmp, brc_type)
+ && br_open->level == tmp->level)
+ {
+ flag_series(br_open, tmp, PCF_ONE_LINER);
+ break;
+ }
+ }
+ }
+ log_rule_B("mod_full_brace_if_chain");
+ log_rule_B("mod_full_brace_if_chain_only");
+
+ if ( options::mod_full_brace_if_chain()
+ || options::mod_full_brace_if_chain_only())
+ {
+ mod_full_brace_if_chain();
+ }
+ log_rule_B("mod_full_brace_if");
+ log_rule_B("mod_full_brace_do");
+ log_rule_B("mod_full_brace_for");
+ log_rule_B("mod_full_brace_using");
+ log_rule_B("mod_full_brace_while");
+
+ if ((options::mod_full_brace_if() |
+ options::mod_full_brace_do() |
+ options::mod_full_brace_for() |
+ options::mod_full_brace_using() |
+ options::mod_full_brace_while()) & IARF_REMOVE)
+ {
+ examine_braces();
+ }
+ // convert vbraces if needed
+ log_rule_B("mod_full_brace_if");
+ log_rule_B("mod_full_brace_do");
+ log_rule_B("mod_full_brace_for");
+ log_rule_B("mod_full_brace_function");
+ log_rule_B("mod_full_brace_using");
+ log_rule_B("mod_full_brace_while");
+
+ if ((options::mod_full_brace_if() |
+ options::mod_full_brace_do() |
+ options::mod_full_brace_for() |
+ options::mod_full_brace_function() |
+ options::mod_full_brace_using() |
+ options::mod_full_brace_while()) & IARF_ADD)
+ {
+ convert_vbrace_to_brace();
+ }
+ log_rule_B("mod_case_brace");
+
+ if (options::mod_case_brace() != IARF_IGNORE)
+ {
+ mod_case_brace();
+ }
+ log_rule_B("mod_move_case_break");
+
+ if (options::mod_move_case_break())
+ {
+ move_case_break();
+ }
+} // do_braces
+
+
+static void examine_braces(void)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("mod_full_brace_nl_block_rem_mlcond");
+ const auto multiline_block = options::mod_full_brace_nl_block_rem_mlcond();
+
+ log_rule_B("mod_full_brace_if");
+ log_rule_B("mod_full_brace_do");
+ log_rule_B("mod_full_brace_for");
+ log_rule_B("mod_full_brace_using");
+ log_rule_B("mod_full_brace_while");
+
+ for (auto pc = chunk_get_tail(); pc != nullptr;)
+ {
+ auto prev = chunk_get_prev_type(pc, CT_BRACE_OPEN, -1);
+
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && !pc->flags.test(PCF_IN_PREPROC)
+ && ( ( ( get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSE
+ || get_chunk_parent_type(pc) == CT_ELSEIF)
+ && options::mod_full_brace_if() == IARF_REMOVE)
+ || ( get_chunk_parent_type(pc) == CT_DO
+ && options::mod_full_brace_do() == IARF_REMOVE)
+ || ( get_chunk_parent_type(pc) == CT_FOR
+ && options::mod_full_brace_for() == IARF_REMOVE)
+ || ( get_chunk_parent_type(pc) == CT_USING_STMT
+ && options::mod_full_brace_using() == IARF_REMOVE)
+ || ( get_chunk_parent_type(pc) == CT_WHILE
+ && options::mod_full_brace_while() == IARF_REMOVE)))
+ {
+ if ( multiline_block
+ && paren_multiline_before_brace(pc))
+ {
+ pc = prev;
+ continue;
+ }
+ examine_brace(pc);
+ }
+ pc = prev;
+ }
+} // examine_braces
+
+
+static bool should_add_braces(chunk_t *vbopen)
+{
+ LOG_FUNC_ENTRY();
+ log_rule_B("mod_full_brace_nl");
+ const size_t nl_max = options::mod_full_brace_nl();
+
+ if (nl_max == 0)
+ {
+ return(false);
+ }
+ LOG_FMT(LBRDEL, "%s(%d): start on %zu:\n",
+ __func__, __LINE__, vbopen->orig_line);
+
+ size_t nl_count = 0;
+
+ chunk_t *pc = nullptr;
+
+ for (pc = chunk_get_next_nc(vbopen, scope_e::PREPROC);
+ (pc != nullptr && pc->level > vbopen->level);
+ pc = chunk_get_next_nc(pc, scope_e::PREPROC))
+ {
+ if (chunk_is_newline(pc))
+ {
+ nl_count += pc->nl_count;
+ }
+ }
+
+ if ( pc != nullptr
+ && nl_count > nl_max
+ && vbopen->pp_level == pc->pp_level)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): exceeded %zu newlines\n",
+ __func__, __LINE__, nl_max);
+ return(true);
+ }
+ return(false);
+}
+
+
+static bool can_remove_braces(chunk_t *bopen)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LBRDEL, "%s(%d): start on line %zu:\n",
+ __func__, __LINE__, bopen->orig_line);
+
+ // Cannot remove braces inside a preprocessor
+ if (bopen->flags.test(PCF_IN_PREPROC))
+ {
+ return(false);
+ }
+ chunk_t *pc = chunk_get_next_ncnnl(bopen, scope_e::PREPROC);
+
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ // Can't remove empty statement
+ return(false);
+ }
+ const size_t level = bopen->level + 1;
+
+ log_rule_B("mod_full_brace_nl");
+ const size_t nl_max = options::mod_full_brace_nl();
+ chunk_t *prev = nullptr;
+
+ size_t semi_count = 0;
+ bool hit_semi = false;
+ size_t nl_count = 0;
+ size_t if_count = 0;
+ int br_count = 0;
+
+ pc = chunk_get_next_nc(bopen, scope_e::ALL);
+ LOG_FMT(LBRDEL, "%s(%d): - begin with token '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
+
+ while ( pc != nullptr
+ && pc->level >= level)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): test token '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
+
+ if (pc->flags.test(PCF_IN_PREPROC))
+ {
+ // Cannot remove braces that contain a preprocessor
+ return(false);
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ nl_count += pc->nl_count;
+
+ if ( nl_max > 0
+ && nl_count > nl_max)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): exceeded %zu newlines\n",
+ __func__, __LINE__, nl_max);
+ return(false);
+ }
+ }
+ else
+ {
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ br_count++;
+ }
+ else if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ if (br_count == 0)
+ {
+ fprintf(stderr, "%s(%d): br_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ br_count--;
+
+ if (pc->level == level)
+ {
+ // mean a statement in a braces { stmt; }
+ // as a statement with a semicolon { stmt; };
+ ++semi_count;
+ hit_semi = true;
+ }
+ }
+ else if ( ( chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSEIF))
+ && br_count == 0)
+ {
+ if_count++;
+ }
+
+ if (pc->level == level)
+ {
+ if ( semi_count > 0
+ && hit_semi)
+ {
+ // should have bailed due to close brace level drop
+ LOG_FMT(LBRDEL, "%s(%d): no close brace\n", __func__, __LINE__);
+ return(false);
+ }
+ LOG_FMT(LBRDEL, "%s(%d): text() '%s', orig_line is %zu, semi_count is %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line, semi_count);
+
+ if (chunk_is_token(pc, CT_ELSE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on '%s' on line %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line);
+ return(false);
+ }
+
+ if ( chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSEIF)
+ || chunk_is_token(pc, CT_FOR)
+ || chunk_is_token(pc, CT_DO)
+ || chunk_is_token(pc, CT_WHILE)
+ || chunk_is_token(pc, CT_USING_STMT)
+ || ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && chunk_is_token(prev, CT_FPAREN_CLOSE)))
+ {
+ hit_semi |= chunk_is_semicolon(pc);
+
+ if (++semi_count > 1)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on %zu because of '%s' on line %zu\n",
+ __func__, __LINE__, bopen->orig_line, pc->text(), pc->orig_line);
+ return(false);
+ }
+ }
+ }
+ }
+ prev = pc;
+ pc = chunk_get_next_nc(pc);
+ }
+
+ if (pc == nullptr)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): pc is nullptr\n", __func__, __LINE__);
+ return(false);
+ }
+
+ if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(pc) == CT_IF)
+ {
+ chunk_t *next = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
+ chunk_t *tmp_prev = chunk_get_prev_ncnnl(pc, scope_e::PREPROC);
+
+ if ( chunk_is_token(next, CT_ELSE)
+ && ( chunk_is_token(tmp_prev, CT_BRACE_CLOSE)
+ || chunk_is_token(tmp_prev, CT_VBRACE_CLOSE))
+ && get_chunk_parent_type(tmp_prev) == CT_IF)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): - bailed on '%s'[%s] on line %zu due to 'if' and 'else' sequence\n",
+ __func__, __LINE__, get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)),
+ pc->orig_line);
+ return(false);
+ }
+ }
+ LOG_FMT(LBRDEL, "%s(%d): - end on '%s' on line %zu. if_count is %zu semi_count is %zu\n",
+ __func__, __LINE__, get_token_name(pc->type), pc->orig_line, if_count, semi_count);
+
+ return( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && pc->pp_level == bopen->pp_level);
+} // can_remove_braces
+
+
+static void examine_brace(chunk_t *bopen)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LBRDEL, "%s(%d): start on orig_line %zu, bopen->level is %zu\n",
+ __func__, __LINE__, bopen->orig_line, bopen->level);
+
+ const size_t level = bopen->level + 1;
+
+ log_rule_B("mod_full_brace_nl");
+ const size_t nl_max = options::mod_full_brace_nl();
+
+ chunk_t *prev = nullptr;
+ size_t semi_count = 0;
+ bool hit_semi = false;
+ size_t nl_count = 0;
+ size_t if_count = 0;
+ int br_count = 0;
+
+ chunk_t *pc = chunk_get_next_nc(bopen);
+
+ while ( pc != nullptr
+ && pc->level >= level)
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, <Newline>\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());
+ }
+
+ if (pc->flags.test(PCF_IN_PREPROC))
+ {
+ // Cannot remove braces that contain a preprocessor
+ LOG_FMT(LBRDEL, "%s(%d): PREPROC\n", __func__, __LINE__);
+ return;
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ nl_count += pc->nl_count;
+
+ if ( nl_max > 0
+ && nl_count > nl_max)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): exceeded %zu newlines\n",
+ __func__, __LINE__, nl_max);
+ return;
+ }
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): for pc->text() '%s', pc->level is %zu, bopen->level is %zu\n",
+ __func__, __LINE__, pc->text(), pc->level, bopen->level);
+
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && pc->level == bopen->level)
+ {
+ br_count++;
+ LOG_FMT(LBRDEL, "%s(%d): br_count is now %d, pc->level is %zu, bopen->level is %zu\n",
+ __func__, __LINE__, br_count, pc->level, bopen->level);
+ }
+ else if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && pc->level == bopen->level)
+ {
+ if (br_count == 0)
+ {
+ fprintf(stderr, "%s(%d): br_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ br_count--;
+ LOG_FMT(LBRDEL, "%s(%d): br_count is now %d, pc->level is %zu, bopen->level is %zu\n",
+ __func__, __LINE__, br_count, pc->level, bopen->level);
+
+ if (br_count == 0)
+ {
+ chunk_t *next = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
+
+ if ( next == nullptr
+ || chunk_is_not_token(next, CT_BRACE_CLOSE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): junk after close brace\n", __func__, __LINE__);
+ return;
+ }
+ }
+ }
+ else if ( ( chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSEIF))
+ && br_count == 0)
+ {
+ if_count++;
+ }
+ LOG_FMT(LBRDEL, "%s(%d): pc->level is %zu, level is %zu\n",
+ __func__, __LINE__, pc->level, level);
+
+ if (pc->level == level)
+ {
+ if ( semi_count > 0
+ && hit_semi)
+ {
+ // should have bailed due to close brace level drop
+ LOG_FMT(LBRDEL, "%s(%d): no close brace\n", __func__, __LINE__);
+ return;
+ }
+ LOG_FMT(LBRDEL, "%s(%d): text() '%s', orig_line is %zu, semi_count is %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line, semi_count);
+
+ if (chunk_is_token(pc, CT_ELSE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on '%s' on line %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line);
+ return;
+ }
+
+ if (prev != nullptr)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', prev->text '%s', prev->type %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), prev->text(), get_token_name(prev->type));
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', prev is nullptr\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());
+ }
+ LOG_FMT(LBRDEL, "%s(%d): for pc->text() '%s', pc->level is %zu, bopen->level is %zu\n",
+ __func__, __LINE__, pc->text(), pc->level, bopen->level);
+
+ if ( chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSEIF)
+ || chunk_is_token(pc, CT_FOR)
+ || chunk_is_token(pc, CT_DO)
+ || chunk_is_token(pc, CT_WHILE)
+ || chunk_is_token(pc, CT_SWITCH)
+ || chunk_is_token(pc, CT_USING_STMT)
+ || ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && pc->level == bopen->level)) // Issue #1758
+ {
+ LOG_FMT(LBRDEL, "%s(%d): pc->text() '%s', orig_line is %zu, orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col, pc->level);
+ hit_semi |= chunk_is_semicolon(pc);
+ semi_count++;
+ LOG_FMT(LBRDEL, "%s(%d): semi_count is %zu\n",
+ __func__, __LINE__, semi_count);
+
+ if (semi_count > 1)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on %zu because of '%s' on line %zu\n",
+ __func__, __LINE__, bopen->orig_line, pc->text(), pc->orig_line);
+ return;
+ }
+ }
+ }
+ }
+ prev = pc;
+ pc = chunk_get_next(pc); // Issue #1907
+ }
+
+ if (pc == nullptr)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): pc is nullptr\n", __func__, __LINE__);
+ return;
+ }
+ LOG_FMT(LBRDEL, "%s(%d): - end on '%s' on line %zu. if_count is %zu, semi_count is %zu\n",
+ __func__, __LINE__, get_token_name(pc->type), pc->orig_line, if_count, semi_count);
+
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ chunk_t *next = chunk_get_next_ncnnl(pc);
+
+ if (next != nullptr)
+ {
+ while (chunk_is_token(next, CT_VBRACE_CLOSE))
+ {
+ next = chunk_get_next_ncnnl(next);
+ }
+
+ if (next != nullptr)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, next is '%s'\n",
+ __func__, __LINE__, next->orig_line, next->orig_col, get_token_name(next->type));
+ }
+
+ if ( if_count > 0
+ && ( chunk_is_token(next, CT_ELSE)
+ || chunk_is_token(next, CT_ELSEIF)))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on because 'else' is next and %zu ifs\n",
+ __func__, __LINE__, if_count);
+ return;
+ }
+ }
+ LOG_FMT(LBRDEL, "%s(%d): semi_count is %zu\n",
+ __func__, __LINE__, semi_count);
+
+ if (semi_count > 0)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bopen->parent_type is %s\n",
+ __func__, __LINE__, get_token_name(get_chunk_parent_type(bopen)));
+
+ if (get_chunk_parent_type(bopen) == CT_ELSE)
+ {
+ chunk_t *tmp_next = chunk_get_next_ncnnl(bopen);
+
+ if (chunk_is_token(tmp_next, CT_IF))
+ {
+ chunk_t *tmp_prev = chunk_get_prev_ncnnl(bopen);
+ LOG_FMT(LBRDEL, "%s(%d): else-if removing braces on line %zu and %zu\n",
+ __func__, __LINE__, bopen->orig_line, pc->orig_line);
+
+ chunk_del(bopen);
+ chunk_del(pc);
+ newline_del_between(tmp_prev, tmp_next);
+
+ log_rule_B("nl_else_if");
+
+ if (options::nl_else_if() & IARF_ADD)
+ {
+ newline_add_between(tmp_prev, tmp_next);
+ }
+ return;
+ }
+ }
+ // we have a pair of braces with only 1 statement inside
+ LOG_FMT(LBRDEL, "%s(%d): we have a pair of braces with only 1 statement inside\n",
+ __func__, __LINE__);
+ LOG_FMT(LBRDEL, "%s(%d): removing braces on line %zu and %zu\n",
+ __func__, __LINE__, bopen->orig_line, pc->orig_line);
+ convert_brace(bopen);
+ convert_brace(pc);
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): empty statement\n", __func__, __LINE__);
+ }
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): not a close brace? - '%s'\n",
+ __func__, __LINE__, pc->text());
+ }
+} // examine_brace
+
+
+static void convert_brace(chunk_t *br)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( br == nullptr
+ || br->flags.test(PCF_KEEP_BRACE))
+ {
+ return;
+ }
+ chunk_t *tmp;
+
+ if (chunk_is_token(br, CT_BRACE_OPEN))
+ {
+ set_chunk_type(br, CT_VBRACE_OPEN);
+ br->str.clear();
+ tmp = chunk_get_prev(br);
+
+ if (tmp == nullptr)
+ {
+ return;
+ }
+ }
+ else if (chunk_is_token(br, CT_BRACE_CLOSE))
+ {
+ set_chunk_type(br, CT_VBRACE_CLOSE);
+ br->str.clear();
+ tmp = chunk_get_next(br);
+
+ if (tmp == nullptr)
+ {
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ if (chunk_is_newline(tmp))
+ {
+ if (tmp->nl_count > 1)
+ {
+ if (!br->flags.test(PCF_ONE_LINER)) // Issue #2232
+ {
+ if (tmp->nl_count == 0)
+ {
+ fprintf(stderr, "%s(%d): tmp->nl_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ tmp->nl_count--;
+ LOG_FMT(LBRDEL, "%s(%d): tmp->nl_count is %zu\n",
+ __func__, __LINE__, tmp->nl_count);
+ }
+ }
+ else
+ {
+ // Issue #2219
+ // look for opening brace
+ chunk_t *brace = nullptr;
+
+ if (chunk_is_token(br, CT_VBRACE_OPEN))
+ {
+ brace = tmp;
+ }
+ else if (chunk_is_token(br, CT_VBRACE_CLOSE))
+ {
+ brace = chunk_skip_to_match_rev(br);
+
+ if (brace == nullptr)
+ {
+ brace = chunk_get_prev_type(br, CT_BRACE_OPEN, br->level);
+ }
+ }
+
+ if ( chunk_is_token(br, CT_VBRACE_OPEN)
+ || ( chunk_is_token(br, CT_VBRACE_CLOSE)
+ && brace->orig_line < tmp->orig_line))
+ {
+ if (chunk_safe_to_del_nl(tmp))
+ {
+ chunk_del(tmp);
+ }
+ }
+ }
+ }
+} // convert_brace
+
+
+static void convert_vbrace(chunk_t *vbr)
+{
+ LOG_FUNC_ENTRY();
+
+ if (vbr == nullptr)
+ {
+ return;
+ }
+
+ if (chunk_is_token(vbr, CT_VBRACE_OPEN))
+ {
+ set_chunk_type(vbr, CT_BRACE_OPEN);
+ vbr->str = "{";
+
+ /*
+ * If the next chunk is a preprocessor, then move the open brace after the
+ * preprocessor.
+ */
+ chunk_t *tmp = chunk_get_next(vbr);
+
+ if (chunk_is_token(tmp, CT_PREPROC))
+ {
+ tmp = chunk_get_next(vbr, scope_e::PREPROC);
+ chunk_move_after(vbr, tmp);
+ newline_add_after(vbr);
+ }
+ }
+ else if (chunk_is_token(vbr, CT_VBRACE_CLOSE))
+ {
+ set_chunk_type(vbr, CT_BRACE_CLOSE);
+ vbr->str = "}";
+
+ /*
+ * If the next chunk is a comment, followed by a newline, then
+ * move the brace after the newline and add another newline after
+ * the close brace.
+ */
+ chunk_t *tmp = chunk_get_next(vbr);
+
+ if (chunk_is_comment(tmp))
+ {
+ tmp = chunk_get_next(tmp);
+
+ if (chunk_is_newline(tmp))
+ {
+ chunk_move_after(vbr, tmp);
+ newline_add_after(vbr);
+ }
+ }
+ }
+} // convert_vbrace
+
+
+static void convert_vbrace_to_brace(void)
+{
+ LOG_FUNC_ENTRY();
+
+ // Find every vbrace open
+ log_rule_B("mod_full_brace_if");
+ log_rule_B("mod_full_brace_if_chain");
+ log_rule_B("mod_full_brace_for");
+ log_rule_B("mod_full_brace_do");
+ log_rule_B("mod_full_brace_while");
+ log_rule_B("mod_full_brace_using");
+ log_rule_B("mod_full_brace_function");
+
+ for (chunk_t *pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnnl(pc))
+ {
+ if (chunk_is_not_token(pc, CT_VBRACE_OPEN))
+ {
+ continue;
+ }
+ auto const in_preproc = pc->flags.test(PCF_IN_PREPROC);
+
+ if ( ( ( get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSE
+ || get_chunk_parent_type(pc) == CT_ELSEIF)
+ && (options::mod_full_brace_if() & IARF_ADD)
+ && !options::mod_full_brace_if_chain())
+ || ( get_chunk_parent_type(pc) == CT_FOR
+ && (options::mod_full_brace_for() & IARF_ADD))
+ || ( get_chunk_parent_type(pc) == CT_DO
+ && (options::mod_full_brace_do() & IARF_ADD))
+ || ( get_chunk_parent_type(pc) == CT_WHILE
+ && (options::mod_full_brace_while() & IARF_ADD))
+ || ( get_chunk_parent_type(pc) == CT_USING_STMT
+ && (options::mod_full_brace_using() & IARF_ADD))
+ || ( get_chunk_parent_type(pc) == CT_FUNC_DEF
+ && (options::mod_full_brace_function() & IARF_ADD)))
+ {
+ // Find the matching vbrace close
+ chunk_t *vbc = nullptr;
+ chunk_t *tmp = pc;
+
+ while ((tmp = chunk_get_next(tmp)) != nullptr)
+ {
+ if ( in_preproc
+ && !tmp->flags.test(PCF_IN_PREPROC))
+ {
+ // Can't leave a preprocessor
+ break;
+ }
+
+ if ( pc->brace_level == tmp->brace_level
+ && chunk_is_token(tmp, CT_VBRACE_CLOSE)
+ && get_chunk_parent_type(pc) == get_chunk_parent_type(tmp)
+ && ((tmp->flags & PCF_IN_PREPROC) == (pc->flags & PCF_IN_PREPROC)))
+ {
+ vbc = tmp;
+ break;
+ }
+ }
+
+ if (vbc == nullptr)
+ {
+ continue;
+ }
+ // if we found a corresponding virtual closing brace
+ convert_vbrace(pc); // convert both the opening
+ convert_vbrace(vbc); // and closing brace
+ }
+ }
+} // convert_vbrace_to_brace
+
+
+chunk_t *insert_comment_after(chunk_t *ref, c_token_t cmt_type,
+ const unc_text &cmt_text)
+{
+ LOG_FUNC_ENTRY();
+
+ chunk_t new_cmt = *ref;
+
+ new_cmt.prev = nullptr;
+ new_cmt.next = nullptr;
+ new_cmt.flags = (ref->flags & PCF_COPY_FLAGS);
+ set_chunk_type(&new_cmt, cmt_type);
+ new_cmt.str.clear();
+
+ if (cmt_type == CT_COMMENT_CPP)
+ {
+ new_cmt.str.append("// ");
+ new_cmt.str.append(cmt_text);
+ }
+ else
+ {
+ if (chunk_is_token(ref, CT_PP_ELSE))
+ { // make test c/ 02501 stable
+ new_cmt.str.append(" ");
+ }
+ new_cmt.str.append("/* ");
+ new_cmt.str.append(cmt_text);
+ new_cmt.str.append(" */");
+ }
+ // TODO: expand comment type to cover other comment styles?
+
+ new_cmt.column = ref->column + ref->len() + 1;
+ new_cmt.orig_col = new_cmt.column;
+
+ return(chunk_add_after(&new_cmt, ref));
+}
+
+
+static void append_tag_name(unc_text &txt, chunk_t *pc)
+{
+ LOG_FUNC_ENTRY();
+ chunk_t *tmp = pc;
+
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+
+ // step backwards over all a::b stuff
+ while ((tmp = chunk_get_prev_ncnnl(tmp)) != nullptr)
+ {
+ if ( chunk_is_not_token(tmp, CT_DC_MEMBER)
+ && chunk_is_not_token(tmp, CT_MEMBER))
+ {
+ break;
+ }
+ tmp = chunk_get_prev_ncnnl(tmp);
+ pc = tmp;
+
+ if (!chunk_is_word(tmp))
+ {
+ break;
+ }
+ }
+ txt += pc->str;
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+
+ while ((pc = chunk_get_next_ncnnl(pc)) != nullptr)
+ {
+ if ( chunk_is_not_token(pc, CT_DC_MEMBER)
+ && chunk_is_not_token(pc, CT_MEMBER))
+ {
+ break;
+ }
+ txt += pc->str;
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+ pc = chunk_get_next_ncnnl(pc);
+
+ if (pc != nullptr)
+ {
+ txt += pc->str;
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+ }
+ }
+} // append_tag_name
+
+
+void add_long_closebrace_comment(void)
+{
+ LOG_FUNC_ENTRY();
+ chunk_t *fcn_pc = nullptr;
+ chunk_t *sw_pc = nullptr;
+ chunk_t *ns_pc = nullptr;
+ chunk_t *cl_pc = nullptr;
+
+ for (chunk_t *pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnnl(pc))
+ {
+ if ( chunk_is_token(pc, CT_FUNC_DEF)
+ || chunk_is_token(pc, CT_OC_MSG_DECL))
+ {
+ fcn_pc = pc;
+ }
+ else if (chunk_is_token(pc, CT_SWITCH))
+ {
+ // pointless, since it always has the text "switch"
+ sw_pc = pc;
+ }
+ else if (chunk_is_token(pc, CT_NAMESPACE))
+ {
+ ns_pc = pc;
+ }
+ else if (chunk_is_token(pc, CT_CLASS))
+ {
+ cl_pc = pc;
+ }
+
+ if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
+ || pc->flags.test(PCF_IN_PREPROC))
+ {
+ continue;
+ }
+ chunk_t *br_open = pc;
+ size_t nl_count = 0;
+
+ chunk_t *tmp = pc;
+
+ while ((tmp = chunk_get_next(tmp, scope_e::PREPROC)) != nullptr)
+ {
+ if (chunk_is_newline(tmp))
+ {
+ nl_count += tmp->nl_count;
+ continue;
+ }
+
+ // handle only matching closing braces, skip other chunks
+ if ( tmp->level != br_open->level
+ || chunk_is_not_token(tmp, CT_BRACE_CLOSE))
+ {
+ continue;
+ }
+ chunk_t *br_close = tmp;
+
+ tmp = chunk_get_next(tmp);
+
+ // check for a possible end semicolon
+ if (chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ // set br_close to the semi token,
+ // as br_close is used to add the coment after it
+ br_close = tmp;
+ tmp = chunk_get_next(tmp);
+ }
+
+ // make sure a newline follows in order to not overwrite an already
+ // existring comment
+ if ( tmp != nullptr
+ && !chunk_is_newline(tmp))
+ {
+ break;
+ }
+ size_t nl_min = 0;
+ chunk_t *tag_pc = nullptr;
+ unc_text xstr;
+
+ if ( get_chunk_parent_type(br_open) == CT_FUNC_DEF
+ || get_chunk_parent_type(br_open) == CT_OC_MSG_DECL)
+ {
+ log_rule_B("mod_add_long_function_closebrace_comment");
+ nl_min = options::mod_add_long_function_closebrace_comment();
+ tag_pc = fcn_pc;
+
+ if (tag_pc != nullptr)
+ {
+ append_tag_name(xstr, tag_pc);
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ }
+ }
+ else if ( get_chunk_parent_type(br_open) == CT_SWITCH
+ && sw_pc != nullptr)
+ {
+ log_rule_B("mod_add_long_switch_closebrace_comment");
+ nl_min = options::mod_add_long_switch_closebrace_comment();
+ tag_pc = sw_pc;
+ xstr = sw_pc->str;
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ }
+ else if ( get_chunk_parent_type(br_open) == CT_NAMESPACE
+ && ns_pc != nullptr)
+ {
+ log_rule_B("mod_add_long_namespace_closebrace_comment");
+ nl_min = options::mod_add_long_namespace_closebrace_comment();
+ tag_pc = ns_pc;
+ xstr = tag_pc->str; // add 'namespace' to the string
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+
+ // next chunk, normally is going to be the namespace name
+ // append it with a space to generate "namespace xyz"
+ chunk_t *tmp_next = chunk_get_next_ncnnl(tag_pc);
+
+ if (chunk_is_not_token(tmp_next, CT_BRACE_OPEN)) // anonymous namespace -> ignore
+ {
+ xstr.append(" ");
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ append_tag_name(xstr, tmp_next);
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ }
+ }
+ else if ( get_chunk_parent_type(br_open) == CT_CLASS
+ && cl_pc != nullptr
+ && ( !language_is_set(LANG_CPP) // proceed if not C++
+ || chunk_is_token(br_close, CT_SEMICOLON))) // else a C++ class needs to end with a semicolon
+ {
+ log_rule_B("mod_add_long_class_closebrace_comment");
+ nl_min = options::mod_add_long_class_closebrace_comment();
+ tag_pc = cl_pc;
+ xstr = tag_pc->str;
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+
+ chunk_t *tmp_next = chunk_get_next(cl_pc);
+
+ if (tag_pc != nullptr)
+ {
+ xstr.append(" ");
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ append_tag_name(xstr, tmp_next);
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ }
+ }
+
+ if ( nl_min > 0
+ && nl_count >= nl_min
+ && tag_pc != nullptr)
+ {
+ // use the comment style that fits to the selected language
+ const c_token_t style = language_is_set(LANG_CPP | LANG_CS)
+ ? CT_COMMENT_CPP : CT_COMMENT;
+
+ // Add a comment after the close brace
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ insert_comment_after(br_close, style, xstr);
+ }
+ break;
+ }
+ }
+} // add_long_closebrace_comment
+
+
+static void move_case_break(void)
+{
+ LOG_FUNC_ENTRY();
+ chunk_t *prev = nullptr;
+
+ for (chunk_t *pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnnl(pc))
+ {
+ if ( chunk_is_token(pc, CT_BREAK)
+ && chunk_is_token(prev, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(prev) == CT_CASE
+ && chunk_is_newline(chunk_get_prev(pc))
+ && chunk_is_newline(chunk_get_prev(prev)))
+ {
+ chunk_swap_lines(prev, pc);
+ }
+ prev = pc;
+ }
+}
+
+
+static chunk_t *mod_case_brace_remove(chunk_t *br_open)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LMCB, "%s(%d): line %zu",
+ __func__, __LINE__, br_open->orig_line);
+
+ // Find the matching brace close
+ chunk_t *next = chunk_get_next_ncnnl(br_open, scope_e::PREPROC);
+ chunk_t *br_close = chunk_get_next_type(br_open, CT_BRACE_CLOSE, br_open->level, scope_e::PREPROC);
+
+ if (br_close == nullptr)
+ {
+ LOG_FMT(LMCB, "%s(%d): - no close\n", __func__, __LINE__);
+ return(next);
+ }
+ // Make sure 'break', 'return', 'goto', 'case' or '}' is after the close brace
+ chunk_t *pc = chunk_get_next_ncnnl(br_close, scope_e::PREPROC);
+
+ if ( pc == nullptr
+ || ( chunk_is_not_token(pc, CT_BREAK)
+ && chunk_is_not_token(pc, CT_RETURN)
+ && chunk_is_not_token(pc, CT_CASE)
+ && chunk_is_not_token(pc, CT_GOTO)
+ && chunk_is_not_token(pc, CT_BRACE_CLOSE)))
+ {
+ LOG_FMT(LMCB, "%s(%d): - after '%s'\n",
+ __func__, __LINE__, (pc == nullptr) ? "<null>" : get_token_name(pc->type));
+ return(next);
+ }
+
+ // scan to make sure there are no definitions at brace level between braces
+ for (chunk_t *tmp_pc = br_open;
+ tmp_pc != br_close;
+ tmp_pc = chunk_get_next_ncnnl(tmp_pc, scope_e::PREPROC))
+ {
+ if ( tmp_pc->level == (br_open->level + 1)
+ && tmp_pc->flags.test(PCF_VAR_DEF))
+ {
+ LOG_FMT(LMCB, "%s(%d): - vardef on line %zu: '%s'\n",
+ __func__, __LINE__, tmp_pc->orig_line, pc->text());
+ return(next);
+ }
+ }
+
+ LOG_FMT(LMCB, "%s(%d): - removing braces on lines %zu and %zu\n",
+ __func__, __LINE__, br_open->orig_line, br_close->orig_line);
+
+ for (chunk_t *tmp_pc = br_open;
+ tmp_pc != br_close;
+ tmp_pc = chunk_get_next_ncnnl(tmp_pc, scope_e::PREPROC))
+ {
+ if (tmp_pc->brace_level == 0)
+ {
+ fprintf(stderr, "%s(%d): tmp_pc->brace_level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, tmp_pc->orig_line, tmp_pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ tmp_pc->brace_level--;
+
+ if (tmp_pc->level == 0)
+ {
+ fprintf(stderr, "%s(%d): tmp_pc->level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, tmp_pc->orig_line, tmp_pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ tmp_pc->level--;
+ }
+
+ next = chunk_get_prev(br_open, scope_e::PREPROC);
+
+ chunk_del(br_open);
+ chunk_del(br_close);
+
+ return(chunk_get_next(next, scope_e::PREPROC));
+} // mod_case_brace_remove
+
+
+static chunk_t *mod_case_brace_add(chunk_t *cl_colon)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LMCB, "%s(%d): orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, cl_colon->orig_line, cl_colon->orig_col);
+
+ chunk_t *pc = cl_colon;
+ chunk_t *last = nullptr;
+ // look for the case token to the colon
+ chunk_t *cas_ = chunk_get_prev_type(cl_colon, CT_CASE, cl_colon->level);
+ // look for the parent
+ chunk_t *swit = cas_->parent;
+ // look for the opening brace of the switch
+ chunk_t *open = chunk_get_next_type(swit, CT_BRACE_OPEN, swit->level);
+ // look for the closing brace of the switch
+ chunk_t *clos = chunk_skip_to_match(open);
+
+ // find the end of the case-block
+ while ((pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC)) != nullptr)
+ {
+ LOG_FMT(LMCB, "%s(%d): text() is '%s', orig_line %zu, orig_col is %zu, pp_level is %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col, pc->pp_level);
+
+ if (pc->level == cl_colon->level)
+ {
+ if (chunk_is_token(pc, CT_CASE))
+ {
+ LOG_FMT(LMCB, "%s(%d): text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
+ last = calculate_closing_brace_position(cl_colon, pc);
+ break;
+ }
+ }
+ else if (pc->level == cl_colon->level - 1)
+ {
+ if (pc == clos)
+ {
+ LOG_FMT(LMCB, "%s(%d): text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
+ // end of switch is reached
+ last = calculate_closing_brace_position(cl_colon, pc);
+ LOG_FMT(LMCB, "%s(%d): last->text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, last->text(), last->orig_line, last->orig_col);
+ break;
+ }
+ }
+ }
+
+ if (last == nullptr)
+ {
+ LOG_FMT(LMCB, "%s(%d): - last is nullptr\n", __func__, __LINE__);
+ chunk_t *next = chunk_get_next_ncnnl(cl_colon, scope_e::PREPROC);
+ return(next);
+ }
+ LOG_FMT(LMCB, "%s(%d): last->text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, last->text(), last->orig_line, last->orig_col);
+ LOG_FMT(LMCB, "%s(%d): adding braces after '%s' on line %zu\n",
+ __func__, __LINE__, cl_colon->text(), cl_colon->orig_line);
+
+ chunk_t chunk;
+
+ set_chunk_type(&chunk, CT_BRACE_OPEN);
+ set_chunk_parent(&chunk, CT_CASE);
+ chunk.orig_line = cl_colon->orig_line;
+ chunk.orig_col = cl_colon->orig_col;
+ chunk.level = cl_colon->level;
+ chunk.pp_level = cl_colon->pp_level;
+ chunk.brace_level = cl_colon->brace_level;
+ chunk.flags = pc->flags & PCF_COPY_FLAGS;
+ chunk.str = "{";
+ chunk_t *br_open = chunk_add_after(&chunk, cl_colon);
+
+ set_chunk_type(&chunk, CT_BRACE_CLOSE);
+ chunk.orig_line = last->orig_line;
+ chunk.orig_col = last->orig_col;
+ chunk.str = "}";
+ chunk_t *br_close = chunk_add_after(&chunk, last);
+
+ for (pc = chunk_get_next(br_open, scope_e::PREPROC);
+ pc != br_close;
+ pc = chunk_get_next(pc, scope_e::PREPROC))
+ {
+ pc->level++;
+ pc->brace_level++;
+ }
+
+ return(br_open);
+} // mod_case_brace_add
+
+
+static void mod_case_brace(void)
+{
+ LOG_FUNC_ENTRY();
+
+ chunk_t *pc = chunk_get_head();
+
+ // Make sure to start outside of a preprocessor line (see issue #3366)
+ if (chunk_is_preproc(pc))
+ {
+ pc = chunk_get_next_ncnnlnp(pc);
+ }
+
+ while (pc != nullptr)
+ {
+ chunk_t *next = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
+
+ if (next == nullptr)
+ {
+ return;
+ }
+ log_rule_B("mod_case_brace");
+
+ if ( options::mod_case_brace() == IARF_REMOVE
+ && chunk_is_token(pc, CT_BRACE_OPEN)
+ && get_chunk_parent_type(pc) == CT_CASE)
+ {
+ log_rule_B("mod_case_brace - add");
+ pc = mod_case_brace_remove(pc);
+ }
+ else if ( (options::mod_case_brace() & IARF_ADD)
+ && chunk_is_token(pc, CT_CASE_COLON)
+ && chunk_is_not_token(next, CT_BRACE_OPEN)
+ && chunk_is_not_token(next, CT_BRACE_CLOSE)
+ && chunk_is_not_token(next, CT_CASE))
+ {
+ log_rule_B("mod_case_brace - remove");
+ pc = mod_case_brace_add(pc);
+ }
+ else
+ {
+ pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
+ }
+ }
+} // mod_case_brace
+
+
+static void process_if_chain(chunk_t *br_start)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LBRCH, "%s(%d): if starts on line %zu, orig_col is %zu.\n",
+ __func__, __LINE__, br_start->orig_line, br_start->orig_col);
+
+ vector<chunk_t *> braces;
+
+ braces.reserve(16);
+
+ bool must_have_braces = false;
+
+ chunk_t *pc = br_start;
+
+ while (pc != nullptr)
+ {
+ LOG_FMT(LBRCH, "%s(%d): pc->text() is '%s', orig_line is %zu, orig_col is %zu.\n",
+ __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
+
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ const bool tmp = can_remove_braces(pc);
+ LOG_FMT(LBRCH, "%s(%d): braces.size() is %zu, line is %zu, - can%s remove %s\n",
+ __func__, __LINE__, braces.size(), pc->orig_line, tmp ? "" : "not",
+ get_token_name(pc->type));
+
+ if (!tmp)
+ {
+ must_have_braces = true;
+ }
+ }
+ else
+ {
+ const bool tmp = should_add_braces(pc);
+
+ if (tmp)
+ {
+ must_have_braces = true;
+ }
+ LOG_FMT(LBRCH, "%s(%d): braces.size() is %zu, line is %zu, - %s %s\n",
+ __func__, __LINE__, braces.size(), pc->orig_line, tmp ? "should add" : "ignore",
+ get_token_name(pc->type));
+ }
+ braces.push_back(pc);
+ chunk_t *br_close = chunk_skip_to_match(pc, scope_e::PREPROC);
+
+ if (br_close == nullptr)
+ {
+ break;
+ }
+ braces.push_back(br_close);
+
+ pc = chunk_get_next_ncnnl(br_close, scope_e::PREPROC);
+
+ if ( pc == nullptr
+ || chunk_is_not_token(pc, CT_ELSE))
+ {
+ break;
+ }
+ log_rule_B("mod_full_brace_if_chain_only");
+
+ if (options::mod_full_brace_if_chain_only())
+ {
+ // There is an 'else' - we want full braces.
+ must_have_braces = true;
+ }
+ pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
+
+ if (chunk_is_token(pc, CT_ELSEIF))
+ {
+ while ( chunk_is_not_token(pc, CT_VBRACE_OPEN)
+ && chunk_is_not_token(pc, CT_BRACE_OPEN))
+ {
+ pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
+ }
+ }
+
+ if (pc == nullptr)
+ {
+ break;
+ }
+
+ if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
+ && chunk_is_not_token(pc, CT_VBRACE_OPEN))
+ {
+ break;
+ }
+ }
+
+ if (must_have_braces)
+ {
+ LOG_FMT(LBRCH, "%s(%d): add braces on lines[%zu]:",
+ __func__, __LINE__, braces.size());
+
+ const auto ite = braces.rend();
+
+ for (auto itc = braces.rbegin(); itc != ite; ++itc)
+ {
+ const auto brace = *itc;
+
+ chunk_flags_set(brace, PCF_KEEP_BRACE);
+
+ if ( chunk_is_token(brace, CT_VBRACE_OPEN)
+ || chunk_is_token(brace, CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LBRCH, "%s(%d): %zu",
+ __func__, __LINE__, brace->orig_line);
+ convert_vbrace(brace);
+ }
+ else
+ {
+ LOG_FMT(LBRCH, "%s(%d): {%zu}",
+ __func__, __LINE__, brace->orig_line);
+ }
+ }
+
+ LOG_FMT(LBRCH, "\n");
+ }
+ else if (options::mod_full_brace_if_chain())
+ {
+ log_rule_B("mod_full_brace_if_chain");
+ LOG_FMT(LBRCH, "%s(%d): remove braces on lines[%zu]:\n",
+ __func__, __LINE__, braces.size());
+
+ /*
+ * This might run because either
+ * mod_full_brace_if_chain or mod_full_brace_if_chain_only
+ * is used.
+ * We only want to remove braces if the first one is active.
+ */
+ log_rule_B("mod_full_brace_nl_block_rem_mlcond");
+ const auto multiline_block = options::mod_full_brace_nl_block_rem_mlcond();
+
+ LOG_FMT(LBRCH, "%s(%d): remove braces on lines:\n", __func__, __LINE__);
+
+ // Issue #2229
+ const auto ite = braces.end();
+
+ for (auto itc = braces.begin(); itc != ite; ++itc)
+ {
+ const auto brace = *itc;
+
+ if ( ( chunk_is_token(brace, CT_BRACE_OPEN)
+ || chunk_is_token(brace, CT_BRACE_CLOSE))
+ && (get_chunk_parent_type(brace) != CT_BRACED_INIT_LIST)
+ && (multiline_block ? !paren_multiline_before_brace(brace) : true))
+ {
+ LOG_FMT(LBRCH, "%s(%d): brace->orig_line is %zu, brace->orig_col is %zu\n",
+ __func__, __LINE__, brace->orig_line, brace->orig_col);
+ convert_brace(brace);
+ }
+ else
+ {
+ LOG_FMT(LBRCH, "%s(%d): brace->orig_line is %zu, brace->orig_col is %zu\n",
+ __func__, __LINE__, brace->orig_line, brace->orig_col);
+ }
+ }
+ }
+} // process_if_chain
+
+
+static void mod_full_brace_if_chain(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (chunk_t *pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next(pc))
+ {
+ if ( ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_VBRACE_OPEN))
+ && get_chunk_parent_type(pc) == CT_IF)
+ {
+ process_if_chain(pc);
+ }
+ }
+}