diff options
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/brace_cleanup.cpp')
-rw-r--r-- | debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/brace_cleanup.cpp | 1498 |
1 files changed, 0 insertions, 1498 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/brace_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/brace_cleanup.cpp deleted file mode 100644 index 0810c04c..00000000 --- a/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/brace_cleanup.cpp +++ /dev/null @@ -1,1498 +0,0 @@ -/** - * @file brace_cleanup.cpp - * Determines the brace level and paren level. - * Inserts virtual braces as needed. - * Handles all that preprocessor stuff. - * - * @author Ben Gardner - * @license GPL v2+ - */ - -#include "brace_cleanup.h" - -#include "flag_parens.h" -#include "frame_list.h" -#include "keywords.h" -#include "lang_pawn.h" -#include "prototypes.h" - -#include <stdexcept> // to get std::invalid_argument - -constexpr static auto LCURRENT = LBC; - -using namespace uncrustify; - -using std::invalid_argument; -using std::string; -using std::to_string; -using std::stringstream; - - -/* - * abbreviations used: - * - sparen = tbd - * - PS = Parenthesis Stack - * - pse = Parenthesis Stack - */ - - -struct BraceState -{ - std::vector<ParseFrame> frames = {}; - c_token_t in_preproc = CT_NONE; - int pp_level = 0; - bool consumed = false; -}; - -/** - * Called when a statement was just closed and the pse_tos was just - * decremented. - * - * - if the TOS is now VBRACE, insert a CT_VBRACE_CLOSE and recurse. - * - if the TOS is a complex statement, call handle_complex_close() - * - * @retval true done with this chunk - * @retval false keep processing - */ -static bool close_statement(ParseFrame &frm, chunk_t *pc, const BraceState &braceState); - - -static size_t preproc_start(BraceState &braceState, ParseFrame &frm, chunk_t *pc); - - -static void print_stack(log_sev_t logsev, const char *str, const ParseFrame &frm); - - -/** - * pc is a CT_WHILE. - * Scan backwards to see if we find a brace/vbrace with the parent set to CT_DO - */ -static bool maybe_while_of_do(chunk_t *pc); - - -/** - * @param after determines: true - insert_vbrace_close_after(pc, frm) - * false - insert_vbrace_open_before(pc, frm) - */ -static chunk_t *insert_vbrace(chunk_t *pc, bool after, const ParseFrame &frm); - -#define insert_vbrace_close_after(pc, frm) insert_vbrace(pc, true, frm) -#define insert_vbrace_open_before(pc, frm) insert_vbrace(pc, false, frm) - -static void parse_cleanup(BraceState &braceState, ParseFrame &frm, chunk_t *pc); - - -/** - * Checks the progression of complex statements. - * - checks for else after if - * - checks for if after else - * - checks for while after do - * - checks for open brace in BRACE2 and BRACE_DO stages, inserts open VBRACE - * - checks for open paren in PAREN1 and BRACE2 stages, complains - * - * @param frm The parse frame - * @param pc The current chunk - * - * @return true - done with this chunk, false - keep processing - */ -static bool check_complex_statements(ParseFrame &frm, chunk_t *pc, const BraceState &braceState); - - -/** - * Handles a close paren or brace - just progress the stage, if the end - * of the statement is hit, call close_statement() - * - * @param frm The parse frame - * @param pc The current chunk - * - * @return true - done with this chunk, false - keep processing - */ -static bool handle_complex_close(ParseFrame &frm, chunk_t *pc, const BraceState &braceState); - - -//! We're on a 'namespace' skip the word and then set the parent of the braces. -static void mark_namespace(chunk_t *pns); - - -static size_t preproc_start(BraceState &braceState, ParseFrame &frm, chunk_t *pc) -{ - LOG_FUNC_ENTRY(); - const size_t pp_level = braceState.pp_level; - - chunk_t *next = chunk_get_next_ncnnl(pc); - - if (next == nullptr) - { - return(pp_level); - } - // Get the type of preprocessor and handle it - braceState.in_preproc = next->type; - - // If we are not in a define, check for #if, #else, #endif, etc - if (braceState.in_preproc != CT_PP_DEFINE) - { - int pp_indent = fl_check(braceState.frames, frm, braceState.pp_level, pc); - return(pp_indent); - } - // else push the frame stack - fl_push(braceState.frames, frm); - - // a preproc body starts a new, blank frame - frm = {}; - frm.level = 1; - frm.brace_level = 1; - - // TODO: not sure about the next 3 lines - frm.push(nullptr); - frm.top().type = CT_PP_DEFINE; - - return(pp_level); -} - - -static void print_stack(log_sev_t logsev, const char *str, - const ParseFrame &frm) -{ - LOG_FUNC_ENTRY(); - - if (!log_sev_on(logsev)) - { - return; - } - log_fmt(logsev, "%s(%d): str is '%s'", __func__, __LINE__, str); - - for (size_t idx = 1; idx < frm.size(); idx++) - { - if (frm.at(idx).stage != brace_stage_e::NONE) - { - LOG_FMT(logsev, " [%s - %u]", get_token_name(frm.at(idx).type), - (unsigned int)frm.at(idx).stage); - } - else - { - LOG_FMT(logsev, " [%s]", get_token_name(frm.at(idx).type)); - } - } - - log_fmt(logsev, "\n"); -} - - -//TODO: This can be cleaned up and simplified - we can look both forward and backward! -void brace_cleanup(void) -{ - LOG_FUNC_ENTRY(); - - BraceState braceState; - ParseFrame frm{}; - chunk_t *pc = chunk_get_head(); - - while (pc != nullptr) - { - LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, text() is '%s'\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text()); - - // Check for leaving a #define body - if ( braceState.in_preproc != CT_NONE - && !pc->flags.test(PCF_IN_PREPROC)) - { - if (braceState.in_preproc == CT_PP_DEFINE) - { - // out of the #define body, restore the frame - fl_pop(braceState.frames, frm); - } - braceState.in_preproc = CT_NONE; - } - // Check for a preprocessor start - size_t pp_level; - - if (chunk_is_token(pc, CT_PREPROC)) - { - pp_level = preproc_start(braceState, frm, pc); - } - else - { - pp_level = braceState.pp_level; - } - LOG_FMT(LTOK, "%s(%d): pp_level is %zu\n", - __func__, __LINE__, pp_level); - - // Do before assigning stuff from the frame - if ( language_is_set(LANG_PAWN) - && frm.top().type == CT_VBRACE_OPEN - && chunk_is_token(pc, CT_NEWLINE)) - { - pc = pawn_check_vsemicolon(pc); - - if (pc == nullptr) - { - return; - } - } - - // Issue #1813 - if (chunk_is_token(pc, CT_NAMESPACE)) - { - mark_namespace(pc); - } - // Assume the level won't change - pc->level = frm.level; - pc->brace_level = frm.brace_level; - pc->pp_level = pp_level; - - /* - * #define bodies get the full formatting treatment - * Also need to pass in the initial '#' to close out any virtual braces. - */ - if ( !chunk_is_comment(pc) - && !chunk_is_newline(pc) - && !chunk_is_token(pc, CT_ATTRIBUTE) - && !chunk_is_token(pc, CT_IGNORED) // Issue #2279 - && ( braceState.in_preproc == CT_PP_DEFINE - || braceState.in_preproc == CT_NONE)) - { - braceState.consumed = false; - parse_cleanup(braceState, frm, pc); - print_stack(LBCSAFTER, (chunk_is_token(pc, CT_VBRACE_CLOSE)) ? "Virt-}\n" : pc->str.c_str(), frm); - } - pc = chunk_get_next(pc); - } -// pc = chunk_get_head(); -// -// while (pc != nullptr) -// { -// LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, text() is '%s'\n", -// __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text()); -// -// // look for template -// if (chunk_is_token(pc, CT_TEMPLATE)) // Issue #3309 -// { -// chunk_t *template_end = chunk_get_next_type(pc, CT_SEMICOLON, pc->level); -// -// // look for a parameter pack -// while (pc != nullptr) -// { -// LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, text() is '%s'\n", -// __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text()); -// -// if (chunk_is_token(pc, CT_PARAMETER_PACK)) -// { -// chunk_t *parameter_pack = pc; -// -// // look for a token with the same text -// while (pc != nullptr) -// { -// LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, text() is '%s'\n", -// __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text()); -// pc = chunk_get_next(pc); -// -// if (pc == template_end) -// { -// break; -// } -// -// if (strcmp(pc->text(), parameter_pack->text()) == 0) -// { -// set_chunk_type(pc, CT_PARAMETER_PACK); -// } -// } -// } -// pc = chunk_get_next(pc); -// -// if (pc == template_end) -// { -// break; -// } -// } -// } -// pc = chunk_get_next(pc); -// } -} // brace_cleanup - - -static bool maybe_while_of_do(chunk_t *pc) -{ - LOG_FUNC_ENTRY(); - - chunk_t *prev = chunk_get_prev_ncnnl(pc); - - if ( prev == nullptr - || !prev->flags.test(PCF_IN_PREPROC)) - { - return(false); - } - - // Find the chunk before the preprocessor - while ( prev != nullptr - && prev->flags.test(PCF_IN_PREPROC)) - { - prev = chunk_get_prev_ncnnl(prev); - } - - if ( ( chunk_is_token(prev, CT_VBRACE_CLOSE) - || chunk_is_token(prev, CT_BRACE_CLOSE)) - && get_chunk_parent_type(prev) == CT_DO) - { - return(true); - } - return(false); -} - - -/** - * At the heart of this algorithm are two stacks. - * There is the Paren Stack (PS) and the Frame stack. - * - * The PS (pse in the code) keeps track of braces, parens, - * if/else/switch/do/while/etc items -- anything that is nestable. - * Complex statements go through stages. - * Take this simple if statement as an example: - * if ( x ) { x--; } - * - * The stack would change like so: 'token' stack afterwards - * 'if' [IF - 1] - * '(' [IF - 1] [PAREN OPEN] - * 'x' [IF - 1] [PAREN OPEN] - * ')' [IF - 2] <- note that the state was incremented - * '{' [IF - 2] [BRACE OPEN] - * 'x' [IF - 2] [BRACE OPEN] - * '--' [IF - 2] [BRACE OPEN] - * ';' [IF - 2] [BRACE OPEN] - * '}' [IF - 3] - * <- lack of else kills the IF, closes statement - * - * Virtual braces example: - * if ( x ) x--; else x++; - * - * 'if' [IF - 1] - * '(' [IF - 1] [PAREN OPEN] - * 'x' [IF - 1] [PAREN OPEN] - * ')' [IF - 2] - * 'x' [IF - 2] [VBRACE OPEN] <- VBrace open inserted before because '{' was not next - * '--' [IF - 2] [VBRACE OPEN] - * ';' [IF - 3] <- VBrace close inserted after semicolon - * 'else' [ELSE - 0] <- IF changed into ELSE - * 'x' [ELSE - 0] [VBRACE OPEN] <- lack of '{' -> VBrace - * '++' [ELSE - 0] [VBRACE OPEN] - * ';' [ELSE - 0] <- VBrace close inserted after semicolon - * <- ELSE removed after statement close - * - * The pse stack is kept on a frame stack. - * The frame stack is need for languages that support preprocessors (C, C++, C#) - * that can arbitrarily change code flow. It also isolates #define macros so - * that they are indented independently and do not affect the rest of the program. - * - * When an #if is hit, a copy of the current frame is push on the frame stack. - * When an #else/#elif is hit, a copy of the current stack is pushed under the - * #if frame and the original (pre-#if) frame is copied to the current frame. - * When #endif is hit, the top frame is popped. - * This has the following effects: - * - a simple #if / #endif does not affect program flow - * - #if / #else /#endif - continues from the #if clause - * - * When a #define is entered, the current frame is pushed and cleared. - * When a #define is exited, the frame is popped. - */ -static void parse_cleanup(BraceState &braceState, ParseFrame &frm, chunk_t *pc) -{ - LOG_FUNC_ENTRY(); - - LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, type is %s, tos is %zu, TOS.type is %s, TOS.stage is %s, ", - __func__, __LINE__, pc->orig_line, pc->orig_col, get_token_name(pc->type), - frm.size() - 1, get_token_name(frm.top().type), - get_brace_stage_name(frm.top().stage)); - log_pcf_flags(LTOK, pc->flags); - - // Mark statement starts - LOG_FMT(LTOK, "%s(%d): orig_line is %zu, type is %s, text() is '%s'\n", - __func__, __LINE__, pc->orig_line, get_token_name(pc->type), pc->text()); - LOG_FMT(LTOK, "%s(%d): frm.stmt_count is %zu, frm.expr_count is %zu\n", - __func__, __LINE__, frm.stmt_count, frm.expr_count); - - if ( ( frm.stmt_count == 0 - || frm.expr_count == 0) - && !chunk_is_semicolon(pc) - && chunk_is_not_token(pc, CT_BRACE_CLOSE) - && chunk_is_not_token(pc, CT_VBRACE_CLOSE) - && !chunk_is_str(pc, ")", 1) - && !chunk_is_str(pc, "]", 1)) - { - chunk_flags_set(pc, PCF_EXPR_START | ((frm.stmt_count == 0) ? PCF_STMT_START : PCF_NONE)); - LOG_FMT(LSTMT, "%s(%d): orig_line is %zu, 1.marked '%s' as %s, start stmt_count is %zu, expr_count is %zu\n", - __func__, __LINE__, pc->orig_line, pc->text(), - pc->flags.test(PCF_STMT_START) ? "stmt" : "expr", frm.stmt_count, - frm.expr_count); - } - frm.stmt_count++; - frm.expr_count++; - LOG_FMT(LTOK, "%s(%d): frm.stmt_count is %zu, frm.expr_count is %zu\n", - __func__, __LINE__, frm.stmt_count, frm.expr_count); - - if (frm.sparen_count > 0) - { - chunk_flags_set(pc, PCF_IN_SPAREN); - - // Mark everything in the for statement - for (int tmp = static_cast<int>(frm.size()) - 2; tmp >= 0; tmp--) - { - if (frm.at(tmp).type == CT_FOR) - { - chunk_flags_set(pc, PCF_IN_FOR); - break; - } - } - - // Mark the parent on semicolons in for() statements - if ( chunk_is_token(pc, CT_SEMICOLON) - && frm.size() > 2 - && frm.prev().type == CT_FOR) - { - set_chunk_parent(pc, CT_FOR); - } - } - - // Check the progression of complex statements - if ( frm.top().stage != brace_stage_e::NONE - && !chunk_is_token(pc, CT_AUTORELEASEPOOL) - && check_complex_statements(frm, pc, braceState)) - { - return; - } - - /* - * Check for a virtual brace statement close due to a semicolon. - * The virtual brace will get handled the next time through. - * The semicolon isn't handled at all. - * TODO: may need to float VBRACE past comments until newline? - */ - if (frm.top().type == CT_VBRACE_OPEN) - { - if (chunk_is_semicolon(pc)) - { - braceState.consumed = true; - close_statement(frm, pc, braceState); - } - else if ( language_is_set(LANG_PAWN) - && chunk_is_token(pc, CT_BRACE_CLOSE)) - { - close_statement(frm, pc, braceState); - } - else if ( language_is_set(LANG_D) - && chunk_is_token(pc, CT_BRACE_CLOSE)) - { - close_statement(frm, pc, braceState); - } - } - - // Handle close parenthesis, vbrace, brace, and square - if ( chunk_is_token(pc, CT_PAREN_CLOSE) - || chunk_is_token(pc, CT_BRACE_CLOSE) - || chunk_is_token(pc, CT_VBRACE_CLOSE) - || chunk_is_token(pc, CT_ANGLE_CLOSE) - || chunk_is_token(pc, CT_MACRO_CLOSE) - || chunk_is_token(pc, CT_SQUARE_CLOSE)) - { - // Change CT_PAREN_CLOSE into CT_SPAREN_CLOSE or CT_FPAREN_CLOSE - if ( chunk_is_token(pc, CT_PAREN_CLOSE) - && ( (frm.top().type == CT_FPAREN_OPEN) - || (frm.top().type == CT_SPAREN_OPEN))) - { - // TODO: fix enum hack - set_chunk_type(pc, static_cast<c_token_t>(frm.top().type + 1)); - - if (chunk_is_token(pc, CT_SPAREN_CLOSE)) - { - frm.sparen_count--; - chunk_flags_clr(pc, PCF_IN_SPAREN); - } - } - - // Make sure the open / close match - if (chunk_is_not_token(pc, (c_token_t)(frm.top().type + 1))) - { - LOG_FMT(LWARN, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - paren_stack_entry_t AA = frm.top(); // Issue #3055 - - if (AA.type != CT_EOF) - { - LOG_FMT(LWARN, "%s(%d): (frm.top().type + 1) is %s\n", - __func__, __LINE__, get_token_name((c_token_t)(frm.top().type + 1))); - } - - if (pc->flags.test(PCF_IN_PREPROC)) // Issue #3113 - { - // do nothing - } - else - { - if ( frm.top().type != CT_EOF - && frm.top().type != CT_PP_DEFINE) - { - LOG_FMT(LWARN, "%s(%d): File: %s, orig_line is %zu, orig_col is %zu, Error: Unexpected '%s' for '%s', which was on line %zu\n", - __func__, __LINE__, cpd.filename.c_str(), pc->orig_line, pc->orig_col, - pc->text(), get_token_name(frm.top().pc->type), - frm.top().pc->orig_line); - print_stack(LBCSPOP, "=Error ", frm); - cpd.error_count++; - exit(EXIT_FAILURE); - } - } - } - else - { - braceState.consumed = true; - - // Copy the parent, update the parenthesis/brace levels - set_chunk_parent(pc, frm.top().parent); - frm.level--; - - if ( chunk_is_token(pc, CT_BRACE_CLOSE) - || chunk_is_token(pc, CT_VBRACE_CLOSE) - || chunk_is_token(pc, CT_MACRO_CLOSE)) - { - frm.brace_level--; - LOG_FMT(LBCSPOP, "%s(%d): frm.brace_level decreased to %zu", - __func__, __LINE__, frm.brace_level); - log_pcf_flags(LBCSPOP, pc->flags); - } - pc->level = frm.level; - pc->brace_level = frm.brace_level; - - // Pop the entry - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - print_stack(LBCSPOP, "-Close ", frm); - - if ( frm.top().stage == brace_stage_e::NONE - && ( chunk_is_token(pc, CT_VBRACE_CLOSE) - || chunk_is_token(pc, CT_BRACE_CLOSE) - || chunk_is_token(pc, CT_SEMICOLON)) - && chunk_is_token(frm.top().pc, CT_VBRACE_OPEN)) - { - // frames for functions are not created as they are for an if - // this here is a hackish solution to close a vbrace of a block that - // contains the function - frm.push(nullptr); // <- dummy frame for the function - frm.top().stage = brace_stage_e::BRACE2; - } - - // See if we are in a complex statement - if (frm.top().stage != brace_stage_e::NONE) - { - handle_complex_close(frm, pc, braceState); - } - } - } - - /* - * In this state, we expect a semicolon, but we'll also hit the closing - * sparen, so we need to check braceState.consumed to see if the close sparen - * was aleady handled. - */ - if (frm.top().stage == brace_stage_e::WOD_SEMI) - { - if (braceState.consumed) - { - /* - * If consumed, then we are on the close sparen. - * PAWN: Check the next chunk for a semicolon. If it isn't, then - * add a virtual semicolon, which will get handled on the next pass. - */ - if (language_is_set(LANG_PAWN)) - { - chunk_t *tmp = chunk_get_next_ncnnl(pc); - - if ( chunk_is_not_token(tmp, CT_SEMICOLON) - && chunk_is_not_token(tmp, CT_VSEMICOLON)) - { - pawn_add_vsemi_after(pc); - } - } - } - else - { - // Complain if this ISN'T a semicolon, but close out WHILE_OF_DO anyway - if ( chunk_is_token(pc, CT_SEMICOLON) - || chunk_is_token(pc, CT_VSEMICOLON)) - { - braceState.consumed = true; - set_chunk_parent(pc, CT_WHILE_OF_DO); - } - else - { - LOG_FMT(LWARN, "%s: %s(%d): %zu: Error: Expected a semicolon for WHILE_OF_DO, but got '%s'\n", - cpd.filename.c_str(), __func__, __LINE__, pc->orig_line, - get_token_name(pc->type)); - cpd.error_count++; - } - handle_complex_close(frm, pc, braceState); - } - } - // Get the parent type for brace and parenthesis open - c_token_t parent = get_chunk_parent_type(pc); - - if ( chunk_is_token(pc, CT_PAREN_OPEN) - || chunk_is_token(pc, CT_FPAREN_OPEN) - || chunk_is_token(pc, CT_SPAREN_OPEN) - || chunk_is_token(pc, CT_BRACE_OPEN)) - { - chunk_t *prev = chunk_get_prev_ncnnl(pc); - - if (prev != nullptr) - { - if ( chunk_is_token(pc, CT_PAREN_OPEN) - || chunk_is_token(pc, CT_FPAREN_OPEN) - || chunk_is_token(pc, CT_SPAREN_OPEN)) - { - // Set the parent for parenthesis and change parenthesis type - if ( chunk_is_token(prev, CT_IF) - || chunk_is_token(prev, CT_CONSTEXPR) - || chunk_is_token(prev, CT_ELSEIF) - || chunk_is_token(prev, CT_WHILE) - || chunk_is_token(prev, CT_WHILE_OF_DO) - || chunk_is_token(prev, CT_DO) - || chunk_is_token(prev, CT_FOR) - || chunk_is_token(prev, CT_SWITCH) - || chunk_is_token(prev, CT_CATCH) - || chunk_is_token(prev, CT_SYNCHRONIZED) - || chunk_is_token(prev, CT_D_VERSION) - || chunk_is_token(prev, CT_D_VERSION_IF) - || chunk_is_token(prev, CT_D_SCOPE) - || chunk_is_token(prev, CT_D_SCOPE_IF)) - { - set_chunk_type(pc, CT_SPAREN_OPEN); - parent = frm.top().type; - frm.sparen_count++; - } - else if (chunk_is_token(prev, CT_FUNCTION)) - { - set_chunk_type(pc, CT_FPAREN_OPEN); - parent = CT_FUNCTION; - } - // NS_ENUM and NS_OPTIONS are followed by a (type, name) pair - else if ( chunk_is_token(prev, CT_ENUM) - && language_is_set(LANG_OC)) - { - // Treat both as CT_ENUM since the syntax is identical - set_chunk_type(pc, CT_FPAREN_OPEN); - parent = CT_ENUM; - } - else if (chunk_is_token(prev, CT_DECLSPEC)) // Issue 1289 - { - parent = CT_DECLSPEC; - } - // else: no need to set parent - } - else // must be CT_BRACE_OPEN - { - // Set the parent for open braces - if (frm.top().stage != brace_stage_e::NONE) - { - parent = frm.top().type; - } - else if ( chunk_is_token(prev, CT_ASSIGN) - && (prev->str[0] == '=')) - { - parent = CT_ASSIGN; - } - else if ( chunk_is_token(prev, CT_RETURN) - && language_is_set(LANG_CPP)) - { - parent = CT_RETURN; - } - // Carry through CT_ENUM parent in NS_ENUM (type, name) { - // for the vim editor } - else if ( chunk_is_token(prev, CT_FPAREN_CLOSE) - && language_is_set(LANG_OC) - && get_chunk_parent_type(prev) == CT_ENUM) - { - parent = CT_ENUM; - } - else if (chunk_is_token(prev, CT_FPAREN_CLOSE)) - { - parent = CT_FUNCTION; - } - // else: no need to set parent - } - } - } - - /* - * Adjust the level for opens & create a stack entry - * Note that CT_VBRACE_OPEN has already been handled. - */ - if ( chunk_is_token(pc, CT_BRACE_OPEN) - || chunk_is_token(pc, CT_PAREN_OPEN) - || chunk_is_token(pc, CT_FPAREN_OPEN) - || chunk_is_token(pc, CT_SPAREN_OPEN) - || chunk_is_token(pc, CT_ANGLE_OPEN) - || chunk_is_token(pc, CT_MACRO_OPEN) - || chunk_is_token(pc, CT_SQUARE_OPEN)) - { - frm.level++; - - if ( chunk_is_token(pc, CT_BRACE_OPEN) - || chunk_is_token(pc, CT_MACRO_OPEN)) - { - // Issue #1813 - bool single = false; - - if (get_chunk_parent_type(pc) == CT_NAMESPACE) - { - LOG_FMT(LBCSPOP, "%s(%d): parent_type is NAMESPACE\n", - __func__, __LINE__); - chunk_t *tmp = frm.top().pc; - - if ( tmp != nullptr - && get_chunk_parent_type(tmp) == CT_NAMESPACE) - { - LOG_FMT(LBCSPOP, "%s(%d): tmp->parent_type is NAMESPACE\n", - __func__, __LINE__); - - log_rule_B("indent_namespace"); - log_rule_B("indent_namespace_single_indent"); - - if ( options::indent_namespace() - && options::indent_namespace_single_indent()) - { - LOG_FMT(LBCSPOP, "%s(%d): Options are SINGLE\n", - __func__, __LINE__); - single = true; - } - } - } - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s, parent_type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc))); - - if (!single) - { - frm.brace_level++; - LOG_FMT(LBCSPOP, "%s(%d): frm.brace_level increased to %zu\n", - __func__, __LINE__, frm.brace_level); - } - } - frm.push(pc, __func__, __LINE__); - frm.top().parent = parent; - // set parent type - set_chunk_parent(pc, parent); - } - // Issue #2281 - - if ( chunk_is_token(pc, CT_BRACE_OPEN) - && pc->parent_type == CT_SWITCH) - { - size_t idx = frm.size(); - LOG_FMT(LBCSPOP, "%s(%d): idx is %zu\n", - __func__, __LINE__, idx); - chunk_t *saved = frm.at(idx - 2).pc; - - if (saved != nullptr) - { - // set parent member - chunk_set_parent(pc, saved); - } - } - - if ( chunk_is_token(pc, CT_CASE) - || chunk_is_token(pc, CT_DEFAULT)) - { - chunk_t *prev = chunk_get_prev_ncnnl(pc); // Issue #3176 - - if ( chunk_is_token(pc, CT_CASE) - || ( chunk_is_token(pc, CT_DEFAULT) - && chunk_is_not_token(prev, CT_ASSIGN))) - { - // it is a CT_DEFAULT from a switch - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, pc->orig_col is %zu\n", - __func__, __LINE__, pc->orig_line, pc->orig_col); - set_chunk_parent(pc, CT_SWITCH); - size_t idx = frm.size(); - LOG_FMT(LBCSPOP, "%s(%d): idx is %zu\n", - __func__, __LINE__, idx); - chunk_t *saved = frm.at(idx - 2).pc; - - if (saved != nullptr) - { - // set parent member - chunk_set_parent(pc, saved); - } - } - } - - if (chunk_is_token(pc, CT_BREAK)) - { - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, pc->orig_col is %zu\n", - __func__, __LINE__, pc->orig_line, pc->orig_col); - size_t idx = frm.size(); - LOG_FMT(LBCSPOP, "%s(%d): idx is %zu\n", - __func__, __LINE__, idx); - chunk_t *saved = frm.at(idx - 2).pc; - - if (saved != nullptr) - { - // set parent member - chunk_set_parent(pc, saved); - } - } - const pattern_class_e patcls = get_token_pattern_class(pc->type); - - /* - * Create a stack entry for complex statements: - * if, elseif, switch, for, while, synchronized, using, lock, with, - * version, CT_D_SCOPE_IF - */ - if (patcls == pattern_class_e::BRACED) - { - frm.push(pc, __func__, __LINE__, (chunk_is_token(pc, CT_DO) ? brace_stage_e::BRACE_DO - : brace_stage_e::BRACE2)); - // "+ComplexBraced" - } - else if (patcls == pattern_class_e::PBRACED) - { - brace_stage_e bs = brace_stage_e::PAREN1; - - if ( chunk_is_token(pc, CT_WHILE) - && maybe_while_of_do(pc)) - { - set_chunk_type(pc, CT_WHILE_OF_DO); - bs = brace_stage_e::WOD_PAREN; - } - frm.push(pc, __func__, __LINE__, bs); - // "+ComplexParenBraced" - } - else if (patcls == pattern_class_e::OPBRACED) - { - frm.push(pc, __func__, __LINE__, brace_stage_e::OP_PAREN1); - // "+ComplexOpParenBraced"); - } - else if (patcls == pattern_class_e::ELSE) - { - frm.push(pc, __func__, __LINE__, brace_stage_e::ELSEIF); - // "+ComplexElse"); - } - - /* - * Mark simple statement/expression starts - * - after { or } - * - after ';', but not if the paren stack top is a paren - * - after '(' that has a parent type of CT_FOR - */ - if ( chunk_is_token(pc, CT_SQUARE_OPEN) - || ( chunk_is_token(pc, CT_BRACE_OPEN) - && get_chunk_parent_type(pc) != CT_ASSIGN) - || chunk_is_token(pc, CT_BRACE_CLOSE) - || chunk_is_token(pc, CT_VBRACE_CLOSE) - || ( chunk_is_token(pc, CT_SPAREN_OPEN) - && get_chunk_parent_type(pc) == CT_FOR) - || chunk_is_token(pc, CT_COLON) - || chunk_is_token(pc, CT_OC_END) - || ( chunk_is_semicolon(pc) - && frm.top().type != CT_PAREN_OPEN - && frm.top().type != CT_FPAREN_OPEN - && frm.top().type != CT_SPAREN_OPEN) - || chunk_is_token(pc, CT_MACRO)) // Issue #2742 - { - LOG_FMT(LSTMT, "%s(%d): orig_line is %zu, reset1 stmt on '%s'\n", - __func__, __LINE__, pc->orig_line, pc->text()); - frm.stmt_count = 0; - frm.expr_count = 0; - LOG_FMT(LTOK, "%s(%d): frm.stmt_count is %zu, frm.expr_count is %zu\n", - __func__, __LINE__, frm.stmt_count, frm.expr_count); - } - // Mark expression starts - LOG_FMT(LSTMT, "%s(%d): Mark expression starts: orig_line is %zu, orig_col is %zu, text() is '%s'\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text()); - chunk_t *tmp = chunk_get_next_ncnnl(pc); - - if ( chunk_is_token(pc, CT_ARITH) - || chunk_is_token(pc, CT_SHIFT) - || chunk_is_token(pc, CT_ASSIGN) - || chunk_is_token(pc, CT_CASE) - || chunk_is_token(pc, CT_COMPARE) - || ( chunk_is_token(pc, CT_STAR) - && chunk_is_not_token(tmp, CT_STAR)) - || chunk_is_token(pc, CT_BOOL) - || chunk_is_token(pc, CT_MINUS) - || chunk_is_token(pc, CT_PLUS) - || chunk_is_token(pc, CT_CARET) - || chunk_is_token(pc, CT_ANGLE_OPEN) - || chunk_is_token(pc, CT_ANGLE_CLOSE) - || chunk_is_token(pc, CT_RETURN) - || chunk_is_token(pc, CT_THROW) - || chunk_is_token(pc, CT_GOTO) - || chunk_is_token(pc, CT_CONTINUE) - || chunk_is_token(pc, CT_PAREN_OPEN) - || chunk_is_token(pc, CT_FPAREN_OPEN) - || chunk_is_token(pc, CT_SPAREN_OPEN) - || chunk_is_token(pc, CT_BRACE_OPEN) - || chunk_is_semicolon(pc) - || chunk_is_token(pc, CT_COMMA) - || chunk_is_token(pc, CT_NOT) - || chunk_is_token(pc, CT_INV) - || chunk_is_token(pc, CT_COLON) - || chunk_is_token(pc, CT_QUESTION)) - { - frm.expr_count = 0; - LOG_FMT(LSTMT, "%s(%d): orig_line is %zu, orig_col is %zu, reset expr on '%s'\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text()); - } -} // parse_cleanup - - -static bool check_complex_statements(ParseFrame &frm, chunk_t *pc, const BraceState &braceState) -{ - LOG_FUNC_ENTRY(); - - brace_stage_e atest = frm.top().stage; - - LOG_FMT(LBCSPOP, "%s(%d): atest is %s\n", - __func__, __LINE__, get_brace_stage_name(atest)); - - // Turn an optional parenthesis into either a real parenthesis or a brace - if (frm.top().stage == brace_stage_e::OP_PAREN1) - { - frm.top().stage = (chunk_is_not_token(pc, CT_PAREN_OPEN)) - ? brace_stage_e::BRACE2 - : brace_stage_e::PAREN1; - LOG_FMT(LBCSPOP, "%s(%d): frm.top().stage is now %s\n", - __func__, __LINE__, get_brace_stage_name(frm.top().stage)); - } - - // Check for CT_ELSE after CT_IF - while (frm.top().stage == brace_stage_e::ELSE) - { - if (chunk_is_token(pc, CT_ELSE)) - { - // Replace CT_IF with CT_ELSE on the stack & we are done - frm.top().type = CT_ELSE; - frm.top().stage = brace_stage_e::ELSEIF; - print_stack(LBCSSWAP, "=Swap ", frm); - - return(true); - } - // Remove the CT_IF and close the statement - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - print_stack(LBCSPOP, "-IF-CCS ", frm); - - if (close_statement(frm, pc, braceState)) - { - return(true); - } - } - - // Check for CT_IF after CT_ELSE - if (frm.top().stage == brace_stage_e::ELSEIF) - { - log_rule_B("indent_else_if"); - - if ( chunk_is_token(pc, CT_IF) - && ( !options::indent_else_if() - || !chunk_is_newline(chunk_get_prev_nc(pc)))) - { - // Replace CT_ELSE with CT_IF - set_chunk_type(pc, CT_ELSEIF); - frm.top().type = CT_ELSEIF; - frm.top().stage = brace_stage_e::PAREN1; - return(true); - } - // Jump to the 'expecting brace' stage - frm.top().stage = brace_stage_e::BRACE2; - } - - // Check for CT_CATCH or CT_FINALLY after CT_TRY or CT_CATCH - while (frm.top().stage == brace_stage_e::CATCH) - { - if ( chunk_is_token(pc, CT_CATCH) - || chunk_is_token(pc, CT_FINALLY)) - { - // Replace CT_TRY with CT_CATCH or CT_FINALLY on the stack & we are done - frm.top().type = pc->type; - - if (language_is_set(LANG_CS)) - { - frm.top().stage = (chunk_is_token(pc, CT_CATCH)) ? brace_stage_e::CATCH_WHEN : brace_stage_e::BRACE2; - } - else - { - // historically this used OP_PAREN1; however, to my knowledge the expression after a catch clause - // is only optional for C# which has been handled above; therefore, this should now always expect - // a parenthetical expression after the catch keyword and brace after the finally keyword - frm.top().stage = (chunk_is_token(pc, CT_CATCH)) ? brace_stage_e::PAREN1 : brace_stage_e::BRACE2; - } - print_stack(LBCSSWAP, "=Swap ", frm); - - return(true); - } - // Remove the CT_TRY and close the statement - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - print_stack(LBCSPOP, "-TRY-CCS ", frm); - - if (close_statement(frm, pc, braceState)) - { - return(true); - } - } - - // Check for optional parenthesis and optional CT_WHEN after CT_CATCH - if (frm.top().stage == brace_stage_e::CATCH_WHEN) - { - if (chunk_is_token(pc, CT_PAREN_OPEN)) // this is for the paren after "catch" - { - // Replace CT_PAREN_OPEN with CT_SPAREN_OPEN - set_chunk_type(pc, CT_SPAREN_OPEN); - frm.top().type = pc->type; - frm.top().stage = brace_stage_e::PAREN1; - - return(false); - } - - if (chunk_is_token(pc, CT_WHEN)) - { - frm.top().type = pc->type; - frm.top().stage = brace_stage_e::OP_PAREN1; - - return(true); - } - - if (chunk_is_token(pc, CT_BRACE_OPEN)) - { - frm.top().stage = brace_stage_e::BRACE2; - - return(false); - } - } - - // Check for CT_WHILE after the CT_DO - if (frm.top().stage == brace_stage_e::WHILE) - { - if (chunk_is_token(pc, CT_WHILE)) - { - set_chunk_type(pc, CT_WHILE_OF_DO); - frm.top().type = CT_WHILE_OF_DO; //CT_WHILE; - frm.top().stage = brace_stage_e::WOD_PAREN; - - return(true); - } - LOG_FMT(LWARN, "%s(%d): %s, orig_line is %zu, Error: Expected 'while', got '%s'\n", - __func__, __LINE__, cpd.filename.c_str(), pc->orig_line, - pc->text()); - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - print_stack(LBCSPOP, "-Error ", frm); - cpd.error_count++; - } - // Insert a CT_VBRACE_OPEN, if needed - // but not in a preprocessor - atest = frm.top().stage; - - if ( chunk_is_not_token(pc, CT_BRACE_OPEN) - && !pc->flags.test(PCF_IN_PREPROC) - && ( (frm.top().stage == brace_stage_e::BRACE2) - || (frm.top().stage == brace_stage_e::BRACE_DO))) - { - log_rule_B("indent_using_block"); - - if ( language_is_set(LANG_CS) - && chunk_is_token(pc, CT_USING_STMT) - && (!options::indent_using_block())) - { - // don't indent the using block - } - else - { - const c_token_t parent = frm.top().type; - - chunk_t *vbrace = insert_vbrace_open_before(pc, frm); - set_chunk_parent(vbrace, parent); - - frm.level++; - frm.brace_level++; - LOG_FMT(LBCSPOP, "%s(%d): frm.brace_level increased to %zu\n", - __func__, __LINE__, frm.brace_level); - log_pcf_flags(LBCSPOP, pc->flags); - - frm.push(vbrace, __func__, __LINE__, brace_stage_e::NONE); - // "+VBrace"); - - frm.top().parent = parent; - - // update the level of pc - pc->level = frm.level; - pc->brace_level = frm.brace_level; - - // Mark as a start of a statement - frm.stmt_count = 0; - frm.expr_count = 0; - LOG_FMT(LTOK, "%s(%d): frm.stmt_count is %zu, frm.expr_count is %zu\n", - __func__, __LINE__, frm.stmt_count, frm.expr_count); - chunk_flags_set(pc, PCF_STMT_START | PCF_EXPR_START); - frm.stmt_count = 1; - frm.expr_count = 1; - LOG_FMT(LSTMT, "%s(%d): orig_line is %zu, 2.marked '%s' as stmt start\n", - __func__, __LINE__, pc->orig_line, pc->text()); - } - } - - // Check for "constexpr" after CT_IF or CT_ELSEIF - if ( frm.top().stage == brace_stage_e::PAREN1 - && ( frm.top().type == CT_IF - || frm.top().type == CT_ELSEIF) - && chunk_is_token(pc, CT_CONSTEXPR)) - { - return(false); - } - - // Verify open parenthesis in complex statement - if ( chunk_is_not_token(pc, CT_PAREN_OPEN) - && ( (frm.top().stage == brace_stage_e::PAREN1) - || (frm.top().stage == brace_stage_e::WOD_PAREN))) - { - LOG_FMT(LWARN, "%s(%d): %s, orig_line is %zu, Error: Expected '(', got '%s' for '%s'\n", - __func__, __LINE__, cpd.filename.c_str(), pc->orig_line, pc->text(), - get_token_name(frm.top().type)); - - // Throw out the complex statement - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - print_stack(LBCSPOP, "-Error ", frm); - cpd.error_count++; - } - return(false); -} // check_complex_statements - - -static bool handle_complex_close(ParseFrame &frm, chunk_t *pc, const BraceState &braceState) -{ - LOG_FUNC_ENTRY(); - - if (frm.top().stage == brace_stage_e::PAREN1) - { - if ( pc->next != nullptr - && pc->next->type == CT_WHEN) - { - frm.top().type = pc->type; - frm.top().stage = brace_stage_e::CATCH_WHEN; - - return(true); - } - // PAREN1 always => BRACE2 - frm.top().stage = brace_stage_e::BRACE2; - } - else if (frm.top().stage == brace_stage_e::BRACE2) - { - // BRACE2: IF => ELSE, anything else => close - if ( (frm.top().type == CT_IF) - || (frm.top().type == CT_ELSEIF)) - { - frm.top().stage = brace_stage_e::ELSE; - - // If the next chunk isn't CT_ELSE, close the statement - chunk_t *next = chunk_get_next_ncnnl(pc); - - if ( next == nullptr - || chunk_is_not_token(next, CT_ELSE)) - { - LOG_FMT(LBCSPOP, "%s(%d): no CT_ELSE, pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - print_stack(LBCSPOP, "-IF-HCS ", frm); - - return(close_statement(frm, pc, braceState)); - } - } - else if ( (frm.top().type == CT_TRY) - || (frm.top().type == CT_CATCH)) - { - frm.top().stage = brace_stage_e::CATCH; - - // If the next chunk isn't CT_CATCH or CT_FINALLY, close the statement - chunk_t *next = chunk_get_next_ncnnl(pc); - - if ( chunk_is_not_token(next, CT_CATCH) - && chunk_is_not_token(next, CT_FINALLY)) - { - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - print_stack(LBCSPOP, "-TRY-HCS ", frm); - - return(close_statement(frm, pc, braceState)); - } - } - else - { - LOG_FMT(LNOTE, "%s(%d): close_statement on %s brace_stage_e::BRACE2\n", - __func__, __LINE__, get_token_name(frm.top().type)); - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - print_stack(LBCSPOP, "-HCC B2 ", frm); - - return(close_statement(frm, pc, braceState)); - } - } - else if (frm.top().stage == brace_stage_e::BRACE_DO) - { - frm.top().stage = brace_stage_e::WHILE; - } - else if (frm.top().stage == brace_stage_e::WOD_PAREN) - { - LOG_FMT(LNOTE, "%s(%d): close_statement on %s brace_stage_e::WOD_PAREN\n", - __func__, __LINE__, get_token_name(frm.top().type)); - frm.top().stage = brace_stage_e::WOD_SEMI; - print_stack(LBCSPOP, "-HCC WoDP ", frm); - } - else if (frm.top().stage == brace_stage_e::WOD_SEMI) - { - LOG_FMT(LNOTE, "%s(%d): close_statement on %s brace_stage_e::WOD_SEMI\n", - __func__, __LINE__, get_token_name(frm.top().type)); - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - print_stack(LBCSPOP, "-HCC WoDS ", frm); - - return(close_statement(frm, pc, braceState)); - } - else - { - // PROBLEM - LOG_FMT(LWARN, "%s(%d): %s:%zu Error: TOS.type='%s' TOS.stage=%u\n", - __func__, __LINE__, cpd.filename.c_str(), pc->orig_line, - get_token_name(frm.top().type), - (unsigned int)frm.top().stage); - cpd.error_count++; - } - return(false); -} // handle_complex_close - - -static void mark_namespace(chunk_t *pns) -{ - LOG_FUNC_ENTRY(); - // Issue #1813 - chunk_t *br_close; - bool is_using = false; - - chunk_t *pc = chunk_get_prev_ncnnl(pns); - - if (chunk_is_token(pc, CT_USING)) - { - is_using = true; - set_chunk_parent(pns, CT_USING); - } - pc = chunk_get_next_ncnnl(pns); - - while (pc != nullptr) - { - set_chunk_parent(pc, CT_NAMESPACE); - - if (chunk_is_not_token(pc, CT_BRACE_OPEN)) - { - if (chunk_is_token(pc, CT_SEMICOLON)) - { - if (is_using) - { - set_chunk_parent(pc, CT_USING); - } - return; - } - pc = chunk_get_next_ncnnl(pc); - continue; - } - log_rule_B("indent_namespace_limit"); - - if ( (options::indent_namespace_limit() > 0) - && ((br_close = chunk_skip_to_match(pc)) != nullptr)) - { - // br_close->orig_line is always >= pc->orig_line; - size_t numberOfLines = br_close->orig_line - pc->orig_line - 1; // Issue #2345 - LOG_FMT(LTOK, "%s(%d): br_close->orig_line is %zu, pc->orig_line is %zu\n", - __func__, __LINE__, br_close->orig_line, pc->orig_line); - LOG_FMT(LTOK, "%s(%d): numberOfLines is %zu, indent_namespace_limit() is %d\n", - __func__, __LINE__, numberOfLines, options::indent_namespace_limit()); - - log_rule_B("indent_namespace_limit"); - - if (numberOfLines > options::indent_namespace_limit()) - { - LOG_FMT(LTOK, "%s(%d): PCF_LONG_BLOCK is set\n", __func__, __LINE__); - chunk_flags_set(pc, PCF_LONG_BLOCK); - chunk_flags_set(br_close, PCF_LONG_BLOCK); - } - } - flag_parens(pc, PCF_IN_NAMESPACE, CT_NONE, CT_NAMESPACE, false); - return; - } -} // mark_namespace - - -static chunk_t *insert_vbrace(chunk_t *pc, bool after, const ParseFrame &frm) -{ - LOG_FUNC_ENTRY(); - - chunk_t chunk; - - set_chunk_parent(&chunk, frm.top().type); - chunk.orig_line = pc->orig_line; - chunk.level = frm.level; - chunk.pp_level = frm.pp_level; - chunk.brace_level = frm.brace_level; - chunk.flags = pc->flags & PCF_COPY_FLAGS; - chunk.str = ""; - - if (after) - { - chunk.orig_col = pc->orig_col; - set_chunk_type(&chunk, CT_VBRACE_CLOSE); - return(chunk_add_after(&chunk, pc)); - } - chunk_t *ref = chunk_get_prev(pc); - - if (ref == nullptr) - { - return(nullptr); - } - - if (!ref->flags.test(PCF_IN_PREPROC)) - { - chunk.flags &= ~PCF_IN_PREPROC; - } - bool ref_is_comment = chunk_is_comment(ref); // Issue #3351 - - while ( chunk_is_newline(ref) - || chunk_is_comment(ref)) - { - ref->level++; - ref->brace_level++; - ref = chunk_get_prev(ref); - } - - if (ref == nullptr) - { - return(nullptr); - } - - // Don't back into a preprocessor - if ( !pc->flags.test(PCF_IN_PREPROC) - && ref->flags.test(PCF_IN_PREPROC)) - { - if (chunk_is_token(ref, CT_PREPROC_BODY)) - { - while ( ref != nullptr - && ref->flags.test(PCF_IN_PREPROC)) - { - ref = chunk_get_prev(ref); - } - } - else - { - ref = chunk_get_next(ref); - - if (chunk_is_token(ref, CT_COMMENT)) // Issue #3034 - { - ref = chunk_get_next_nc(ref); - } - } - } - - if (ref_is_comment) // Issue #3351 - { - ref = chunk_get_next(ref); - } - - if (ref == nullptr) - { - return(nullptr); - } - chunk.orig_line = ref->orig_line; - chunk.orig_col = ref->orig_col; - chunk.column = ref->column + ref->len() + 1; - chunk.pp_level = ref->pp_level; // Issue #3055 - set_chunk_type(&chunk, CT_VBRACE_OPEN); - - return(chunk_add_after(&chunk, ref)); -} // insert_vbrace - - -bool close_statement(ParseFrame &frm, chunk_t *pc, const BraceState &braceState) -{ - LOG_FUNC_ENTRY(); - - if (pc == nullptr) - { - throw invalid_argument(string(__func__) + ":" + to_string(__LINE__) - + "args cannot be nullptr"); - } - LOG_FMT(LTOK, "%s(%d): orig_line is %zu, type is %s, '%s' type is %s, stage is %u\n", - __func__, __LINE__, pc->orig_line, - get_token_name(pc->type), pc->text(), - get_token_name(frm.top().type), - (unsigned int)frm.top().stage); - - if (braceState.consumed) - { - frm.stmt_count = 0; - frm.expr_count = 0; - LOG_FMT(LSTMT, "%s(%d): orig_line is %zu> reset2 stmt on '%s'\n", - __func__, __LINE__, pc->orig_line, pc->text()); - } - /* - * Insert a CT_VBRACE_CLOSE, if needed: - * If we are in a virtual brace and we are not ON a CT_VBRACE_CLOSE add one - */ - chunk_t *vbc = pc; - - if (frm.top().type == CT_VBRACE_OPEN) - { - // If the current token has already been consumed, then add after it - if (braceState.consumed) - { - insert_vbrace_close_after(pc, frm); - } - else - { - // otherwise, add before it and consume the vbrace - vbc = chunk_get_prev_ncnnl(pc); - - frm.level--; - frm.brace_level--; - vbc = insert_vbrace_close_after(vbc, frm); - set_chunk_parent(vbc, frm.top().parent); - - LOG_FMT(LBCSPOP, "%s(%d): frm.brace_level decreased to %zu\n", - __func__, __LINE__, frm.brace_level); - log_pcf_flags(LBCSPOP, pc->flags); - LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); - frm.pop(__func__, __LINE__); - - // Update the token level - pc->level = frm.level; - pc->brace_level = frm.brace_level; - - print_stack(LBCSPOP, "-CS VB ", frm); - - // And repeat the close - close_statement(frm, pc, braceState); - return(true); - } - } - - // See if we are done with a complex statement - if (frm.top().stage != brace_stage_e::NONE) - { - if (handle_complex_close(frm, vbc, braceState)) - { - return(true); - } - } - return(false); -} // close_statement |