diff options
author | Michele Calgaro <[email protected]> | 2022-05-06 13:43:02 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2022-05-06 13:49:57 +0900 |
commit | 80a31d6c8a114799dc5284086ffce2e9be34c50e (patch) | |
tree | 1719891657e76c04f063f5ff7b5fdf63d9e562c3 /debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp | |
parent | e6ba08c3b21cdb14ee3a97b5d584759a4597b54b (diff) | |
download | extra-dependencies-80a31d6c8a114799dc5284086ffce2e9be34c50e.tar.gz extra-dependencies-80a31d6c8a114799dc5284086ffce2e9be34c50e.zip |
uncrustify-trinity: updated based on upstream version 0.75.0
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp')
-rw-r--r-- | debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp | 1167 |
1 files changed, 1167 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp new file mode 100644 index 00000000..0ad879b4 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp @@ -0,0 +1,1167 @@ +/** + * @file chunk.cpp + * Manages and navigates the list of chunks. + * + * @author Ben Gardner + * @license GPL v2+ + */ + +#include "chunk.h" + +#include "ListManager.h" +#include "prototypes.h" +#include "space.h" + +typedef ListManager<Chunk> ChunkList_t; + + +ChunkList_t g_cl; //! global chunk list + + +/* + * Chunk class methods + */ + +// Null Chunk +Chunk Chunk::NullChunk(true); +Chunk *const Chunk::NullChunkPtr(&Chunk::NullChunk); + + +Chunk::Chunk(bool null_c) + : null_chunk(null_c) +{ + Reset(); +} + + +Chunk::Chunk(const Chunk &o) + : null_chunk(o.null_chunk) +{ + copyFrom(o); +} + + +Chunk &Chunk::operator=(const Chunk &o) +{ + if (this != &o) + { + copyFrom(o); + } + return(*this); +} + + +void Chunk::copyFrom(const Chunk &o) +{ + next = nullptr; + prev = nullptr; + parent = nullptr; + align = o.align; + indent = o.indent; + type = o.type; + parent_type = o.parent_type; + + orig_line = o.orig_line; + orig_col = o.orig_col; + orig_col_end = o.orig_col_end; + orig_prev_sp = o.orig_prev_sp; + flags = o.flags; + column = o.column; + column_indent = o.column_indent; + + nl_count = o.nl_count; + nl_column = o.nl_column; + level = o.level; + + brace_level = o.brace_level; + pp_level = o.pp_level; + after_tab = o.after_tab; + str = o.str; + + tracking = o.tracking; +} + + +void Chunk::Reset() +{ + memset(&align, 0, sizeof(align)); + memset(&indent, 0, sizeof(indent)); + next = nullptr; + prev = nullptr; + parent = nullptr; + type = CT_NONE; + parent_type = CT_NONE; + orig_line = 0; + orig_col = 0; + orig_col_end = 0; + orig_prev_sp = 0; + flags = PCF_NONE; + column = 0; + column_indent = 0; + nl_count = 0; + nl_column = 0; + level = 0; + brace_level = 0; + pp_level = 999; // use a big value to find some errors + after_tab = false; + // for debugging purpose only + tracking = nullptr; + str.clear(); +} + + +size_t Chunk::Len() const +{ + return(str.size()); +} + + +const char *Chunk::Text() const +{ + return(str.c_str()); +} + + +const char *Chunk::ElidedText(char *for_the_copy) const +{ + const char *test_it = Text(); + size_t test_it_length = strlen(test_it); + + size_t truncate_value = uncrustify::options::debug_truncate(); + + if (truncate_value != 0) + { + if (test_it_length > truncate_value) + { + memset(for_the_copy, 0, 1000); + + if (test_it_length < truncate_value + 30) + { + strncpy(for_the_copy, test_it, truncate_value - 30); + for_the_copy[truncate_value - 30] = 0; + } + else + { + strncpy(for_the_copy, test_it, truncate_value); + for_the_copy[truncate_value] = 0; + } + char *message = strcat(for_the_copy, " ... <The string is truncated>"); + + return(message); + } + else + { + return(test_it); + } + } + return(test_it); +} + + +Chunk *Chunk::GetNext(const E_Scope scope) const +{ + if (IsNullChunk()) + { + return(NullChunkPtr); + } + Chunk *pc = g_cl.GetNext(this); + + if ( pc == nullptr + || pc->IsNullChunk()) + { + return(NullChunkPtr); + } + + if (scope == E_Scope::ALL) + { + return(pc); + } + + if (flags.test(PCF_IN_PREPROC)) + { + // If in a preproc, return a null chunk if trying to leave + if (!pc->flags.test(PCF_IN_PREPROC)) + { + return(NullChunkPtr); + } + return(pc); + } + + // Not in a preproc, skip any preproc + while ( pc != nullptr + && pc->IsNotNullChunk() + && pc->flags.test(PCF_IN_PREPROC)) + { + pc = g_cl.GetNext(pc); + } + + if ( pc == nullptr + || pc->IsNullChunk()) + { + return(NullChunkPtr); + } + return(pc); +} // Chunk::GetNext + + +Chunk *Chunk::GetPrev(const E_Scope scope) const +{ + if (IsNullChunk()) + { + return(NullChunkPtr); + } + Chunk *pc = g_cl.GetPrev(this); + + if ( pc == nullptr + || pc->IsNullChunk()) + { + return(NullChunkPtr); + } + + if (scope == E_Scope::ALL) + { + return(pc); + } + + if (flags.test(PCF_IN_PREPROC)) + { + // If in a preproc, return a null chunk if trying to leave + if (!pc->flags.test(PCF_IN_PREPROC)) + { + return(NullChunkPtr); + } + return(pc); + } + + // Not in a preproc, skip any preproc + while ( pc != nullptr + && pc->IsNotNullChunk() + && pc->flags.test(PCF_IN_PREPROC)) + { + pc = g_cl.GetPrev(pc); + } + + if ( pc == nullptr + || pc->IsNullChunk()) + { + return(NullChunkPtr); + } + return(pc); +} // Chunk::GetPrev + + +static void chunk_log(Chunk *pc, const char *text); + + +/* + * TODO: if we use C++ we can overload the following two functions + * and thus name them equally + */ + +/** + * @brief search a chunk of a given category in a chunk list + * + * traverses a chunk list either in forward or backward direction. + * The traversal continues until a chunk of a given category is found. + * + * This function is a specialization of Chunk::Search. + * + * @param cur chunk to start search at + * @param type category to search for + * @param scope code parts to consider for search + * @param dir search direction + * + * @retval nullptr no chunk found or invalid parameters provided + * @retval Chunk pointer to the found chunk + */ +static Chunk *chunk_search_type(Chunk *cur, const E_Token type, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD); + + +/** + * @brief Add a new chunk before/after the given position in a chunk list + * + * If ref is nullptr, add either at the head or tail based on the specified pos + * + * @param pc_in chunk to add to list + * @param ref insert position in list + * @param pos insert before or after + * + * @return Chunk pointer to the added chunk + */ +static Chunk *chunk_add(const Chunk *pc_in, Chunk *ref, const E_Direction pos = E_Direction::FORWARD); + + +Chunk *Chunk::GetHead(void) +{ + Chunk *ret = g_cl.GetHead(); + + if (ret == nullptr) + { + return(Chunk::NullChunkPtr); + } + return(ret); +} + + +Chunk *Chunk::GetTail(void) +{ + Chunk *ret = g_cl.GetTail(); + + if (ret == nullptr) + { + return(Chunk::NullChunkPtr); + } + return(ret); +} + + +Chunk::T_SearchFnPtr Chunk::GetSearchFn(const E_Direction dir) +{ + return((dir == E_Direction::FORWARD) ? &Chunk::GetNext : &Chunk::GetPrev); +} + + +Chunk *Chunk::Search(const T_CheckFnPtr checkFn, const E_Scope scope, + const E_Direction dir, const bool cond) const +{ + T_SearchFnPtr searchFnPtr = GetSearchFn(dir); + Chunk *pc = const_cast<Chunk *>(this); + + do // loop over the chunk list + { + pc = (pc->*searchFnPtr)(scope); // in either direction while + } while ( pc->IsNotNullChunk() // the end of the list was not reached yet + && ((pc->*checkFn)() != cond)); // and the demanded chunk was not found either + + return(pc); // the latest chunk is the searched one +} + + +Chunk *chunk_search_prev_cat(Chunk *pc, const E_Token cat) +{ + return(chunk_search_type(pc, cat, E_Scope::ALL, E_Direction::BACKWARD)); +} + + +Chunk *chunk_search_next_cat(Chunk *pc, const E_Token cat) +{ + return(chunk_search_type(pc, cat, E_Scope::ALL, E_Direction::FORWARD)); +} + + +bool are_chunks_in_same_line(Chunk *start, Chunk *end) +{ + if (start == nullptr) + { + return(false); + } + Chunk *tmp = start->GetNext(); + + while ( tmp->IsNotNullChunk() + && tmp != end) + { + if (chunk_is_token(tmp, CT_NEWLINE)) + { + return(false); + } + tmp = tmp->GetNext(); + } + return(true); +} + + +static Chunk *chunk_search_type(Chunk *cur, const E_Token type, + const E_Scope scope, const E_Direction dir) +{ + /* + * Depending on the parameter dir the search function searches + * in forward or backward direction + */ + Chunk::T_SearchFnPtr search_function = Chunk::GetSearchFn(dir); + Chunk *pc = cur; + + if (pc == nullptr) + { + pc = Chunk::NullChunkPtr; + } + + do // loop over the chunk list + { + pc = (pc->*search_function)(scope); // in either direction while + } while ( pc->IsNotNullChunk() // the end of the list was not reached yet + && pc->type != type); // and the demanded chunk was not found either + + if (pc->IsNullChunk()) + { + pc = nullptr; + } + return(pc); // the latest chunk is the searched one +} + + +Chunk *Chunk::SearchTypeLevel(const E_Token cType, const E_Scope scope, + const E_Direction dir, const int cLevel) const +{ + T_SearchFnPtr searchFnPtr = GetSearchFn(dir); + Chunk *pc = const_cast<Chunk *>(this); + + do // loop over the chunk list + { + pc = (pc->*searchFnPtr)(scope); // in either direction while + } while ( pc->IsNotNullChunk() // the end of the list was not reached yet + && (!pc->IsTypeAndLevel(cType, cLevel))); // and the chunk was not found either + + return(pc); // the latest chunk is the searched one +} + + +Chunk *Chunk::SearchStringLevel(const char *cStr, const size_t len, int cLevel, + const E_Scope scope, const E_Direction dir) const +{ + T_SearchFnPtr searchFnPtr = GetSearchFn(dir); + Chunk *pc = const_cast<Chunk *>(this); + + do // loop over the chunk list + { + pc = (pc->*searchFnPtr)(scope); // in either direction while + } while ( pc->IsNotNullChunk() // the end of the list was not reached yet + && !pc->IsStringAndLevel(cStr, len, cLevel)); // and the demanded chunk was not found either + + return(pc); // the latest chunk is the searched one +} + + +Chunk *Chunk::SearchPpa(const T_CheckFnPtr checkFn, const bool cond) const +{ + if (!flags.test(PCF_IN_PREPROC)) + { + // if not in preprocessor, do a regular search + return(Search(checkFn, E_Scope::ALL, E_Direction::FORWARD, cond)); + } + Chunk *pc = GetNext(); + + while (pc->IsNotNullChunk()) + { + if (!pc->flags.test(PCF_IN_PREPROC)) + { + // Bail if we run off the end of the preprocessor directive, but return + // the token because the caller may need to know where the search ended + assert(chunk_is_token(pc, CT_NEWLINE)); + return(pc); + } + + if (chunk_is_token(pc, CT_NL_CONT)) + { + // Skip line continuation + pc = pc->GetNext(); + continue; + } + + if ((pc->*checkFn)() == cond) + { + // Requested token was found + return(pc); + } + pc = pc->GetNext(); + } + // Ran out of tokens + return(Chunk::NullChunkPtr); +} + + +static void chunk_log_msg(Chunk *chunk, const log_sev_t log, const char *str) +{ + LOG_FMT(log, "%s orig_line is %zu, orig_col is %zu, ", + str, chunk->orig_line, chunk->orig_col); + + if (chunk_is_token(chunk, CT_NEWLINE)) + { + LOG_FMT(log, "<Newline>,\n"); + } + else if (chunk_is_token(chunk, CT_VBRACE_OPEN)) + { + LOG_FMT(log, "<VBRACE_OPEN>,\n"); + } + else if (chunk_is_token(chunk, CT_VBRACE_CLOSE)) + { + LOG_FMT(log, "<VBRACE_CLOSE>,\n"); + } + else + { + LOG_FMT(log, "Text() is '%s', type is %s,\n", chunk->Text(), get_token_name(chunk->type)); + } +} + + +static void chunk_log(Chunk *pc, const char *text) +{ + if ( pc != nullptr + && pc->IsNotNullChunk() + && (cpd.unc_stage != unc_stage_e::TOKENIZE) + && (cpd.unc_stage != unc_stage_e::CLEANUP)) + { + const log_sev_t log = LCHUNK; + Chunk *prev = pc->GetPrev(); + Chunk *next = pc->GetNext(); + + chunk_log_msg(pc, log, text); + + if ( prev->IsNotNullChunk() + && next->IsNotNullChunk()) + { + chunk_log_msg(prev, log, " @ between"); + chunk_log_msg(next, log, " and"); + } + else if (next->IsNotNullChunk()) + { + chunk_log_msg(next, log, " @ before"); + } + else if (prev->IsNotNullChunk()) + { + chunk_log_msg(prev, log, " @ after"); + } + LOG_FMT(log, " stage is %s", // Issue #3034 + get_unc_stage_name(cpd.unc_stage)); + log_func_stack_inline(log); + } +} + + +Chunk *chunk_add_after(const Chunk *pc_in, Chunk *ref) +{ + return(chunk_add(pc_in, ref, E_Direction::FORWARD)); +} + + +Chunk *chunk_add_before(const Chunk *pc_in, Chunk *ref) +{ + return(chunk_add(pc_in, ref, E_Direction::BACKWARD)); +} + + +void chunk_del(Chunk * &pc) +{ + g_cl.Pop(pc); + delete pc; + pc = nullptr; +} + + +void chunk_move_after(Chunk *pc_in, Chunk *ref) +{ + LOG_FUNC_ENTRY(); + g_cl.Pop(pc_in); + g_cl.AddAfter(pc_in, ref); + + // HACK: Adjust the original column + pc_in->column = ref->column + space_col_align(ref, pc_in); + pc_in->orig_col = pc_in->column; + pc_in->orig_col_end = pc_in->orig_col + pc_in->Len(); +} + + +Chunk *Chunk::GetNextNl(const E_Scope scope) const +{ + return(Search(&Chunk::IsNewline, scope, E_Direction::FORWARD, true)); +} + + +Chunk *Chunk::GetPrevNl(const E_Scope scope) const +{ + return(Search(&Chunk::IsNewline, scope, E_Direction::BACKWARD, true)); +} + + +Chunk *Chunk::GetNextNnl(const E_Scope scope) const +{ + return(Search(&Chunk::IsNewline, scope, E_Direction::FORWARD, false)); +} + + +Chunk *Chunk::GetPrevNnl(const E_Scope scope) const +{ + return(Search(&Chunk::IsNewline, scope, E_Direction::BACKWARD, false)); +} + + +Chunk *Chunk::GetNextNc(const E_Scope scope) const +{ + return(Search(&Chunk::IsComment, scope, E_Direction::FORWARD, false)); +} + + +Chunk *Chunk::GetPrevNc(const E_Scope scope) const +{ + return(Search(&Chunk::IsComment, scope, E_Direction::BACKWARD, false)); +} + + +Chunk *Chunk::GetNextNcNnl(const E_Scope scope) const +{ + return(Search(&Chunk::IsCommentOrNewline, scope, E_Direction::FORWARD, false)); +} + + +Chunk *Chunk::GetPrevNcNnl(const E_Scope scope) const +{ + return(Search(&Chunk::IsCommentOrNewline, scope, E_Direction::BACKWARD, false)); +} + + +Chunk *Chunk::GetNextNcNnlNpp(const E_Scope scope) const +{ + return(Search(&Chunk::IsCommentNewlineOrPreproc, scope, E_Direction::FORWARD, false)); +} + + +Chunk *Chunk::GetPrevNcNnlNpp(const E_Scope scope) const +{ + return(Search(&Chunk::IsCommentNewlineOrPreproc, scope, E_Direction::BACKWARD, false)); +} + + +Chunk *Chunk::GetNextNppOrNcNnl(const E_Scope scope) const +{ + return(Search(&Chunk::IsCommentOrNewlineInPreproc, scope, E_Direction::FORWARD, false)); +} + + +Chunk *Chunk::GetPrevNppOrNcNnl(const E_Scope scope) const +{ + return(Search(&Chunk::IsCommentOrNewlineInPreproc, scope, E_Direction::BACKWARD, false)); +} + + +Chunk *Chunk::PpaGetNextNcNnl() const +{ + return(SearchPpa(&Chunk::IsCommentOrNewline, false)); +} + + +Chunk *Chunk::GetNextNcNnlNet(const E_Scope scope) const +{ + return(Search(&Chunk::IsCommentNewlineOrEmptyText, scope, E_Direction::FORWARD, false)); +} + + +Chunk *Chunk::GetPrevNcNnlNet(const E_Scope scope) const +{ + return(Search(&Chunk::IsCommentNewlineOrEmptyText, scope, E_Direction::BACKWARD, false)); +} + + +Chunk *Chunk::GetPrevNcNnlNi(const E_Scope scope) const +{ + return(Search(&Chunk::IsCommentNewlineOrIgnored, scope, E_Direction::BACKWARD, false)); +} + + +Chunk *Chunk::GetNextNisq(const E_Scope scope) const +{ + return(Search(&Chunk::IsSquareBracket, scope, E_Direction::FORWARD, false)); +} + + +Chunk *Chunk::GetNextType(const E_Token cType, const int cLevel, const E_Scope scope) const +{ + return(SearchTypeLevel(cType, scope, E_Direction::FORWARD, cLevel)); +} + + +Chunk *Chunk::GetPrevType(const E_Token cType, const int cLevel, const E_Scope scope) const +{ + return(SearchTypeLevel(cType, scope, E_Direction::BACKWARD, cLevel)); +} + + +Chunk *Chunk::GetNextString(const char *cStr, const size_t len, const int cLevel, const E_Scope scope) const +{ + return(SearchStringLevel(cStr, len, cLevel, scope, E_Direction::FORWARD)); +} + + +Chunk *Chunk::GetPrevString(const char *cStr, const size_t len, const int cLevel, const E_Scope scope) const +{ + return(SearchStringLevel(cStr, len, cLevel, scope, E_Direction::BACKWARD)); +} + + +bool chunk_is_newline_between(Chunk *start, Chunk *end) +{ + for (Chunk *pc = start; pc != nullptr && pc != end; pc = pc->GetNext()) + { + if (chunk_is_newline(pc)) + { + return(true); + } + } + + return(false); +} + + +void chunk_swap(Chunk *pc1, Chunk *pc2) +{ + g_cl.Swap(pc1, pc2); +} + + +// TODO: the following function shall be made similar to the search functions +Chunk *chunk_first_on_line(Chunk *pc) +{ + if ( pc == nullptr + || pc->IsNullChunk()) + { + return(Chunk::NullChunkPtr); + } + Chunk *first = pc; + + while ( (pc = pc->GetPrev())->IsNotNullChunk() + && !chunk_is_newline(pc)) + { + first = pc; + } + return(first); +} + + +bool chunk_is_last_on_line(Chunk *pc) //TODO: pc should be const here +{ + // check if pc is the very last chunk of the file + const Chunk *end = Chunk::GetTail(); + + if (pc == end) + { + return(true); + } + // if the next chunk is a newline then pc is the last chunk on its line + const Chunk *next = pc->GetNext(); + + if (chunk_is_token(next, CT_NEWLINE)) + { + return(true); + } + return(false); +} + + +// TODO: this function needs some cleanup +void chunk_swap_lines(Chunk *pc1, Chunk *pc2) +{ + // to swap lines we need to find the first chunk of the lines + pc1 = chunk_first_on_line(pc1); + pc2 = chunk_first_on_line(pc2); + + if ( pc1->IsNullChunk() + || pc2->IsNullChunk() + || pc1 == pc2) + { + return; + } + /* + * Example start: + * ? - start1 - a1 - b1 - nl1 - ? - ref2 - start2 - a2 - b2 - nl2 - ? + * ^- pc1 ^- pc2 + */ + Chunk *ref2 = pc2->GetPrev(); + + // Move the line started at pc2 before pc1 + while ( pc2->IsNotNullChunk() + && !chunk_is_newline(pc2)) + { + Chunk *tmp = pc2->GetNext(); + g_cl.Pop(pc2); + g_cl.AddBefore(pc2, pc1); + pc2 = tmp; + } + /* + * Should now be: + * ? - start2 - a2 - b2 - start1 - a1 - b1 - nl1 - ? - ref2 - nl2 - ? + * ^- pc1 ^- pc2 + */ + + // Now move the line started at pc1 after ref2 + while ( pc1->IsNotNullChunk() + && !chunk_is_newline(pc1)) + { + Chunk *tmp = pc1->GetNext(); + g_cl.Pop(pc1); + + if (ref2->IsNotNullChunk()) + { + g_cl.AddAfter(pc1, ref2); + } + else + { + g_cl.AddHead(pc1); + } + ref2 = pc1; + pc1 = tmp; + } + /* + * Should now be: + * ? - start2 - a2 - b2 - nl1 - ? - ref2 - start1 - a1 - b1 - nl2 - ? + * ^- pc1 ^- pc2 + */ + + /* + * pc1 and pc2 should be the newlines for their lines. + * swap the chunks and the nl_count so that the spacing remains the same. + */ + if ( pc1->IsNotNullChunk() + && pc2->IsNotNullChunk()) + { + size_t nl_count = pc1->nl_count; + + pc1->nl_count = pc2->nl_count; + pc2->nl_count = nl_count; + + chunk_swap(pc1, pc2); + } +} // chunk_swap_lines + + +Chunk *Chunk::GetNextNvb(const E_Scope scope) const +{ + return(Search(&Chunk::IsVBrace, scope, E_Direction::FORWARD, false)); +} + + +Chunk *Chunk::GetPrevNvb(const E_Scope scope) const +{ + return(Search(&Chunk::IsVBrace, scope, E_Direction::BACKWARD, false)); +} + + +void chunk_flags_set_real(Chunk *pc, pcf_flags_t clr_bits, pcf_flags_t set_bits) +{ + if ( pc != nullptr + && pc->IsNotNullChunk()) + { + LOG_FUNC_ENTRY(); + auto const nflags = (pc->flags & ~clr_bits) | set_bits; + + if (pc->flags != nflags) + { + LOG_FMT(LSETFLG, + "%s(%d): %016llx^%016llx=%016llx\n" + " orig_line is %zu, orig_col is %zu, Text() '%s', type is %s,", + __func__, __LINE__, + static_cast<pcf_flags_t::int_t>(pc->flags), + static_cast<pcf_flags_t::int_t>(pc->flags ^ nflags), + static_cast<pcf_flags_t::int_t>(nflags), + pc->orig_line, pc->orig_col, pc->Text(), + get_token_name(pc->type)); + LOG_FMT(LSETFLG, " parent_type is %s,\n ", + get_token_name(get_chunk_parent_type(pc))); + log_func_stack_inline(LSETFLG); + pc->flags = nflags; + } + } +} + + +void set_chunk_type_real(Chunk *pc, E_Token token, const char *func, int line) +{ + LOG_FUNC_ENTRY(); + + if ( pc == nullptr + || pc->IsNullChunk() + || pc->type == token) + { + return; + } + LOG_FMT(LSETTYP, "%s(%d): orig_line is %zu, orig_col is %zu, pc->Text() ", + func, line, pc->orig_line, pc->orig_col); + + if (token == CT_NEWLINE) + { + LOG_FMT(LSETTYP, "<Newline>\n"); + } + else + { + LOG_FMT(LSETTYP, "'%s'\n", pc->Text()); + } + LOG_FMT(LSETTYP, " pc->type is %s, pc->parent_type is %s => *type is %s, *parent_type is %s\n", + get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)), + get_token_name(token), get_token_name(get_chunk_parent_type(pc))); + pc->type = token; +} // set_chunk_type_real + + +void set_chunk_parent_real(Chunk *pc, E_Token token, const char *func, int line) +{ + LOG_FUNC_ENTRY(); + + if ( pc == nullptr + || pc->IsNullChunk() + || get_chunk_parent_type(pc) == token) + { + return; + } + LOG_FMT(LSETPAR, "%s(%d): orig_line is %zu, orig_col is %zu, pc->Text() ", + func, line, pc->orig_line, pc->orig_col); + + if (token == CT_NEWLINE) + { + LOG_FMT(LSETPAR, "<Newline>\n"); + } + else + { + char copy[1000]; + LOG_FMT(LSETPAR, "'%s'\n", pc->ElidedText(copy)); + } + LOG_FMT(LSETPAR, " pc->type is %s, pc->parent_type is %s => *type is %s, *parent_type is %s\n", + get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)), + get_token_name(token), get_token_name(get_chunk_parent_type(pc))); + pc->parent_type = token; +} // set_chunk_parent_real + + +E_Token get_chunk_parent_type(Chunk *pc) +{ + LOG_FUNC_ENTRY(); + + if (pc == nullptr) + { + return(CT_NONE); + } + return(pc->parent_type); +} // get_chunk_parent_type + + +static Chunk *chunk_add(const Chunk *pc_in, Chunk *ref, const E_Direction pos) +{ +#ifdef DEBUG + // test if the pc_in chunk is properly set + if (pc_in->pp_level == 999) + { + fprintf(stderr, "%s(%d): pp_level is not set\n", __func__, __LINE__); + log_func_stack_inline(LSETFLG); + log_flush(true); + exit(EX_SOFTWARE); + } + + if (pc_in->orig_line == 0) + { + fprintf(stderr, "%s(%d): no line number\n", __func__, __LINE__); + log_func_stack_inline(LSETFLG); + log_flush(true); + exit(EX_SOFTWARE); + } + + if (pc_in->orig_col == 0) + { + fprintf(stderr, "%s(%d): no column number\n", __func__, __LINE__); + log_func_stack_inline(LSETFLG); + log_flush(true); + exit(EX_SOFTWARE); + } +#endif /* DEBUG */ + + Chunk *pc = new Chunk(*pc_in); + + if (pc != nullptr) + { + if (ref != nullptr) // ref is a valid chunk + { + (pos == E_Direction::FORWARD) ? g_cl.AddAfter(pc, ref) : g_cl.AddBefore(pc, ref); + } + else // ref == NULL + { + (pos == E_Direction::FORWARD) ? g_cl.AddHead(pc) : g_cl.AddTail(pc); + } + chunk_log(pc, "chunk_add(A):"); + } + return(pc); +} // chunk_add + + +Chunk *chunk_get_next_ssq(Chunk *cur) +{ + while ( chunk_is_token(cur, CT_TSQUARE) + || chunk_is_token(cur, CT_SQUARE_OPEN)) + { + if (chunk_is_token(cur, CT_SQUARE_OPEN)) + { + cur = chunk_skip_to_match(cur); + } + cur = cur->GetNextNcNnl(); + } + return(cur); +} + + +Chunk *chunk_get_prev_ssq(Chunk *cur) +{ + while ( chunk_is_token(cur, CT_TSQUARE) + || chunk_is_token(cur, CT_SQUARE_CLOSE)) + { + if (chunk_is_token(cur, CT_SQUARE_CLOSE)) + { + cur = chunk_skip_to_match_rev(cur); + } + cur = cur->GetPrevNcNnl(); + } + return(cur); +} + + +Chunk *chunk_get_pp_start(Chunk *cur) +{ + if (!cur->IsPreproc()) + { + return(nullptr); + } + + while (!chunk_is_token(cur, CT_PREPROC)) + { + cur = cur->GetPrev(E_Scope::PREPROC); + } + return(cur); +} + + +//! skip to the final word/type in a :: chain +static Chunk *chunk_skip_dc_member(Chunk *start, E_Scope scope, E_Direction dir) +{ + LOG_FUNC_ENTRY(); + + if (start == nullptr) + { + return(nullptr); + } + const auto step_fcn = (dir == E_Direction::FORWARD) + ? &Chunk::GetNextNcNnl : &Chunk::GetPrevNcNnl; + + Chunk *pc = start; + Chunk *next = chunk_is_token(pc, CT_DC_MEMBER) ? pc : (pc->*step_fcn)(scope); + + while (chunk_is_token(next, CT_DC_MEMBER)) + { + pc = (next->*step_fcn)(scope); + + if (pc->IsNullChunk()) + { + return(Chunk::NullChunkPtr); + } + next = (pc->*step_fcn)(scope); + } + return(pc); +} + + +Chunk *chunk_skip_dc_member(Chunk *start, E_Scope scope) +{ + return(chunk_skip_dc_member(start, scope, E_Direction::FORWARD)); +} + + +Chunk *chunk_skip_dc_member_rev(Chunk *start, E_Scope scope) +{ + return(chunk_skip_dc_member(start, scope, E_Direction::BACKWARD)); +} + + +// set parent member +void chunk_set_parent(Chunk *pc, Chunk *parent) +{ + if (pc == nullptr) + { + return; + } + + if (parent == nullptr) + { + return; + } + + if (pc == parent) + { + return; + } + pc->parent = parent; +} + + +E_Token get_type_of_the_parent(Chunk *pc) +{ + if (pc == nullptr) + { + return(CT_UNKNOWN); + } + + if (pc->parent == nullptr) + { + return(CT_PARENT_NOT_SET); + } + return(pc->parent->type); +} + + +bool chunk_is_attribute_or_declspec(Chunk *pc) +{ + return( language_is_set(LANG_CPP) + && ( chunk_is_token(pc, CT_ATTRIBUTE) + || chunk_is_token(pc, CT_DECLSPEC))); +} + + +bool chunk_is_class_enum_struct_union(Chunk *pc) +{ + return( chunk_is_class_or_struct(pc) + || chunk_is_enum(pc) + || chunk_is_token(pc, CT_UNION)); +} + + +bool chunk_is_class_or_struct(Chunk *pc) +{ + return( chunk_is_token(pc, CT_CLASS) + || chunk_is_token(pc, CT_STRUCT)); +} + + +bool chunk_is_class_struct_union(Chunk *pc) +{ + return( chunk_is_class_or_struct(pc) + || chunk_is_token(pc, CT_UNION)); +} + + +bool chunk_is_enum(Chunk *pc) +{ + return( chunk_is_token(pc, CT_ENUM) + || chunk_is_token(pc, CT_ENUM_CLASS)); +} + + +int chunk_compare_position(const Chunk *A_token, const Chunk *B_token) +{ + if (A_token == nullptr) + { + assert(A_token); + } + + if (B_token == nullptr) + { + assert(B_token); + } + + if (A_token->orig_line < B_token->orig_line) + { + return(-1); + } + else if (A_token->orig_line == B_token->orig_line) + { + if (A_token->orig_col < B_token->orig_col) + { + return(-1); + } + else if (A_token->orig_col == B_token->orig_col) + { + return(0); + } + } + return(1); +} |