diff options
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.72.0/src/chunk_list.cpp')
| -rw-r--r-- | debian/uncrustify-trinity/uncrustify-trinity-0.72.0/src/chunk_list.cpp | 1072 |
1 files changed, 1072 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/src/chunk_list.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/src/chunk_list.cpp new file mode 100644 index 00000000..9e0f1d23 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.72.0/src/chunk_list.cpp @@ -0,0 +1,1072 @@ +/** + * @file chunk_list.cpp + * Manages and navigates the list of chunks. + * + * @author Ben Gardner + * @license GPL v2+ + */ + +#include "chunk_list.h" + +#include "ListManager.h" +#include "prototypes.h" +#include "space.h" +#include "uncrustify.h" +#include "uncrustify_types.h" + +#include <cstdlib> +#include <cstring> + + +typedef ListManager<chunk_t> ChunkList_t; + + +/** + * use this enum to define in what direction or location an + * operation shall be performed. + */ +enum class direction_e : unsigned int +{ + FORWARD, + BACKWARD +}; + + +/** + * @brief prototype for a function that checks a chunk to have a given type + * + * @note this typedef defines the function type "check_t" + * for a function pointer of type + * bool function(chunk_t *pc) + */ +typedef bool (*check_t)(chunk_t *pc); + + +/** + * @brief prototype for a function that searches through a chunk list + * + * @note this typedef defines the function type "search_t" + * for a function pointer of type + * chunk_t *function(chunk_t *cur, nav_t scope) + */ +typedef chunk_t * (*search_t)(chunk_t *cur, scope_e scope); + + +/** + * @brief search for a chunk that satisfies a condition in a chunk list + * + * A generic function that traverses a chunks list either + * in forward or reverse direction. The traversal continues until a + * chunk satisfies the condition defined by the compare function. + * Depending on the parameter cond the condition will either be + * checked to be true or false. + * + * Whenever a chunk list traversal is to be performed this function + * shall be used. This keeps the code clear and easy to understand. + * + * If there are performance issues this function might be worth to + * be optimized as it is heavily used. + * + * @param cur chunk to start search at + * @param check_fct compare function + * @param scope code parts to consider for search + * @param dir search direction + * @param cond success condition + * + * @retval nullptr no requested chunk was found or invalid parameters provided + * @retval chunk_t pointer to the found chunk + */ +static chunk_t *chunk_search(chunk_t *cur, const check_t check_fct, const scope_e scope = scope_e::ALL, const direction_e dir = direction_e::FORWARD, const bool cond = true); + + +/** + * @brief search for a chunk that satisfies a condition in a chunk list. + * + * This function is similar to chunk_search, except that it is tweaked to + * handle searches inside of preprocessor directives. Specifically, if the + * starting token is inside a preprocessor directive, it will ignore a line + * continuation, and will abort the search if it reaches the end of the + * directive. This function only searches forward. + * + * @param cur chunk to start search at + * @param check_fct compare function + * @param scope code parts to consider for search + * @param cond success condition + * + * @retval nullptr no requested chunk was found or invalid parameters provided + * @retval chunk_t pointer to the found chunk or pointer to the chunk at the + * end of the preprocessor directive + */ +static chunk_t *chunk_ppa_search(chunk_t *cur, const check_t check_fct, const bool cond = true); + + +static void chunk_log(chunk_t *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_t pointer to the found chunk + */ +static chunk_t *chunk_search_type(chunk_t *cur, const c_token_t type, const scope_e scope = scope_e::ALL, const direction_e dir = direction_e::FORWARD); + + +/** + * @brief search a chunk of a given type and level + * + * Traverses a chunk list in the specified direction until a chunk of a given type + * 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 + * @param level nesting level to match or -1 / ANY_LEVEL + * + * @retval nullptr no chunk found or invalid parameters provided + * @retval chunk_t pointer to the found chunk + */ +static chunk_t *chunk_search_typelevel(chunk_t *cur, c_token_t type, scope_e scope = scope_e::ALL, direction_e dir = direction_e::FORWARD, int level = -1); + + +/** + * @brief searches a chunk that is non-NEWLINE, non-comment and non-preprocessor + * + * Traverses a chunk list either in forward or backward direction. + * The traversal continues until a chunk of a given category is found. + * + * @param cur chunk to start search at + * @param scope code parts to consider for search + * @param dir search direction + * + * @retval nullptr no chunk found or invalid parameters provided + * @retval chunk_t pointer to the found chunk + */ +static chunk_t *chunk_get_ncnlnp(chunk_t *cur, const scope_e scope = scope_e::ALL, const direction_e dir = direction_e::FORWARD); + + +/** + * @brief searches a chunk that holds a specific string + * + * Traverses a chunk list either in forward or backward direction until a chunk + * with the provided string was found. Additionally a nesting level can be + * provided to narrow down the search. + * + * @param cur chunk to start search at + * @param str string that searched chunk needs to have + * @param len length of the string + * @param scope code parts to consider for search + * @param dir search direction + * @param level nesting level of the searched chunk, ignored when negative + * + * @retval NULL no chunk found or invalid parameters provided + * @retval chunk_t pointer to the found chunk + */ +static chunk_t *chunk_search_str(chunk_t *cur, const char *str, size_t len, scope_e scope, direction_e dir, int level); + + +/** + * @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_t pointer to the added chunk + */ +static chunk_t *chunk_add(const chunk_t *pc_in, chunk_t *ref, const direction_e pos = direction_e::FORWARD); + + +/** + * @brief Determines which chunk search function to use + * + * Depending on the required search direction return a pointer + * to the corresponding chunk search function. + * + * @param dir search direction + * + * @return pointer to chunk search function + */ +static search_t select_search_fct(const direction_e dir = direction_e::FORWARD); + + +ChunkList_t g_cl; //! global chunk list + + +chunk_t *chunk_get_head(void) +{ + return(g_cl.GetHead()); +} + + +chunk_t *chunk_get_tail(void) +{ + return(g_cl.GetTail()); +} + + +static search_t select_search_fct(const direction_e dir) +{ + return((dir == direction_e::FORWARD) ? chunk_get_next : chunk_get_prev); +} + + +chunk_t *chunk_search_prev_cat(chunk_t *pc, const c_token_t cat) +{ + return(chunk_search_type(pc, cat, scope_e::ALL, direction_e::BACKWARD)); +} + + +chunk_t *chunk_search_next_cat(chunk_t *pc, const c_token_t cat) +{ + return(chunk_search_type(pc, cat, scope_e::ALL, direction_e::FORWARD)); +} + + +bool are_chunks_in_same_line(chunk_t *start, chunk_t *end) +{ + chunk_t *tmp; + + if (start != nullptr) + { + tmp = chunk_get_next(start); + } + else + { + return(false); + } + + while (tmp != nullptr && tmp != end) + { + if (chunk_is_token(tmp, CT_NEWLINE)) + { + return(false); + } + tmp = chunk_get_next(tmp); + } + return(true); +} + + +static chunk_t *chunk_search_type(chunk_t *cur, const c_token_t type, + const scope_e scope, const direction_e dir) +{ + /* + * Depending on the parameter dir the search function searches + * in forward or backward direction + */ + search_t search_function = select_search_fct(dir); + chunk_t *pc = cur; + + do // loop over the chunk list + { + pc = search_function(pc, scope); // in either direction while + } while ( pc != nullptr // the end of the list was not reached yet + && pc->type != type); // and the demanded chunk was not found either + + return(pc); // the latest chunk is the searched one +} + + +static chunk_t *chunk_search_typelevel(chunk_t *cur, c_token_t type, scope_e scope, direction_e dir, int level) +{ + /* + * Depending on the parameter dir the search function searches + * in forward or backward direction + */ + search_t search_function = select_search_fct(dir); + chunk_t *pc = cur; + + do // loop over the chunk list + { + pc = search_function(pc, scope); // in either direction while + } while ( pc != nullptr // the end of the list was not reached yet + && (is_expected_type_and_level(pc, type, level) == false)); + + return(pc); // the latest chunk is the searched one +} + + +static chunk_t *chunk_search_str(chunk_t *cur, const char *str, size_t len, scope_e scope, direction_e dir, int level) +{ + /* + * Depending on the parameter dir the search function searches + * in forward or backward direction */ + search_t search_function = select_search_fct(dir); + chunk_t *pc = cur; + + do // loop over the chunk list + { + pc = search_function(pc, scope); // in either direction while + } while ( pc != nullptr // the end of the list was not reached yet + && (is_expected_string_and_level(pc, str, level, len) == false)); + + return(pc); // the latest chunk is the searched one +} + + +static chunk_t *chunk_search(chunk_t *cur, const check_t check_fct, const scope_e scope, + const direction_e dir, const bool cond) +{ + /* + * Depending on the parameter dir the search function searches + * in forward or backward direction */ + search_t search_function = select_search_fct(dir); + chunk_t *pc = cur; + + do // loop over the chunk list + { + pc = search_function(pc, scope); // in either direction while + } while ( pc != nullptr // the end of the list was not reached yet + && (check_fct(pc) != cond)); // and the demanded chunk was not found either + + return(pc); // the latest chunk is the searched one +} + + +static chunk_t *chunk_ppa_search(chunk_t *cur, const check_t check_fct, const bool cond) +{ + if (cur && !cur->flags.test(PCF_IN_PREPROC)) + { + // if not in preprocessor, do a regular search + return(chunk_search(cur, check_fct, scope_e::ALL, + direction_e::FORWARD, cond)); + } + chunk_t *pc = cur; + + while (pc != nullptr && (pc = pc->next) != nullptr) + { + if (!pc->flags.test(PCF_IN_PREPROC)) + { + // Bail if we run off the end of the preprocessor directive, but + // return the next token, NOT nullptr, 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 + continue; + } + + if (check_fct(pc) == cond) + { + // Requested token was found + return(pc); + } + } + // Ran out of tokens + return(nullptr); +} + + +/* @todo maybe it is better to combine chunk_get_next and chunk_get_prev + * into a common function However this should be done with the preprocessor + * to avoid addition check conditions that would be evaluated in the + * while loop of the calling function */ +chunk_t *chunk_get_next(chunk_t *cur, scope_e scope) +{ + if (cur == nullptr) + { + return(nullptr); + } + chunk_t *pc = g_cl.GetNext(cur); + + if (pc == nullptr || scope == scope_e::ALL) + { + return(pc); + } + + if (cur->flags.test(PCF_IN_PREPROC)) + { + // If in a preproc, return nullptr if trying to leave + if (!pc->flags.test(PCF_IN_PREPROC)) + { + return(nullptr); + } + return(pc); + } + + // Not in a preproc, skip any preproc + while (pc != nullptr && pc->flags.test(PCF_IN_PREPROC)) + { + pc = g_cl.GetNext(pc); + } + return(pc); +} + + +chunk_t *chunk_get_prev(chunk_t *cur, scope_e scope) +{ + if (cur == nullptr) + { + return(nullptr); + } + chunk_t *pc = g_cl.GetPrev(cur); + + if (pc == nullptr || scope == scope_e::ALL) + { + return(pc); + } + + if (cur->flags.test(PCF_IN_PREPROC)) + { + // If in a preproc, return NULL if trying to leave + if (!pc->flags.test(PCF_IN_PREPROC)) + { + return(nullptr); + } + return(pc); + } + + // Not in a preproc, skip any preproc + while (pc != nullptr && pc->flags.test(PCF_IN_PREPROC)) + { + pc = g_cl.GetPrev(pc); + } + return(pc); +} + + +chunk_t *chunk_dup(const chunk_t *pc_in) +{ + chunk_t *pc = new chunk_t; // Allocate a new chunk + + if (pc == nullptr) + { + // @todo clean up properly before crashing + LOG_FMT(LERR, "Failed to allocate memory\n"); + log_func_stack_inline(LSETFLG); + log_flush(true); + exit(EXIT_FAILURE); + } + // Copy all fields and then init the entry + *pc = *pc_in; // TODO: what happens if pc_in == nullptr? + g_cl.InitEntry(pc); + + return(pc); +} + + +static void chunk_log_msg(chunk_t *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>,"); + } + else if (chunk_is_token(chunk, CT_VBRACE_OPEN)) + { + LOG_FMT(log, "<VBRACE_OPEN>,"); + } + else if (chunk_is_token(chunk, CT_VBRACE_CLOSE)) + { + LOG_FMT(log, "<VBRACE_CLOSE>,"); + } + else + { + LOG_FMT(log, "text() is '%s', type is %s,\n", chunk->text(), get_token_name(chunk->type)); + } +} + + +static void chunk_log(chunk_t *pc, const char *text) +{ + if ( pc != nullptr + && (cpd.unc_stage != unc_stage_e::TOKENIZE) + && (cpd.unc_stage != unc_stage_e::CLEANUP)) + { + const log_sev_t log = LCHUNK; + chunk_t *prev = chunk_get_prev(pc); + chunk_t *next = chunk_get_next(pc); + + chunk_log_msg(pc, log, text); + + if (prev != nullptr && next != nullptr) + { + chunk_log_msg(prev, log, " @ between"); + chunk_log_msg(next, log, " and"); + } + else if (next != nullptr) + { + chunk_log_msg(next, log, " @ before"); + } + else if (prev != nullptr) + { + chunk_log_msg(prev, log, " @ after"); + } + LOG_FMT(log, " stage is %s", + get_unc_stage_name(cpd.unc_stage)); + log_func_stack_inline(log); + } +} + + +chunk_t *chunk_add_after(const chunk_t *pc_in, chunk_t *ref) +{ + return(chunk_add(pc_in, ref, direction_e::FORWARD)); +} + + +chunk_t *chunk_add_before(const chunk_t *pc_in, chunk_t *ref) +{ + return(chunk_add(pc_in, ref, direction_e::BACKWARD)); +} + + +void chunk_del_2(chunk_t *pc) +{ + g_cl.Pop(pc); + delete pc; +} + + +void chunk_move_after(chunk_t *pc_in, chunk_t *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_t *chunk_get_next_nl(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_newline, scope, direction_e::FORWARD, true)); +} + + +chunk_t *chunk_get_prev_nl(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_newline, scope, direction_e::BACKWARD, true)); +} + + +chunk_t *chunk_get_next_nnl(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_newline, scope, direction_e::FORWARD, false)); +} + + +chunk_t *chunk_get_prev_nnl(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_newline, scope, direction_e::BACKWARD, false)); +} + + +chunk_t *chunk_get_next_ncnl(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_comment_or_newline, scope, direction_e::FORWARD, false)); +} + + +chunk_t *chunk_get_next_ncnlnp(chunk_t *cur, scope_e scope) +{ + return(chunk_get_ncnlnp(cur, scope, direction_e::FORWARD)); +} + + +chunk_t *chunk_ppa_get_next_ncnl(chunk_t *cur) +{ + return(chunk_ppa_search(cur, chunk_is_comment_or_newline, false)); +} + + +chunk_t *chunk_get_prev_ncnlnp(chunk_t *cur, scope_e scope) +{ + return(chunk_get_ncnlnp(cur, scope, direction_e::BACKWARD)); +} + + +chunk_t *chunk_get_next_nblank(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_comment_newline_or_blank, scope, direction_e::FORWARD, false)); +} + + +chunk_t *chunk_get_prev_nblank(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_comment_newline_or_blank, scope, direction_e::BACKWARD, false)); +} + + +chunk_t *chunk_get_next_nc(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_comment, scope, direction_e::FORWARD, false)); +} + + +chunk_t *chunk_get_next_nisq(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_balanced_square, scope, direction_e::FORWARD, false)); +} + + +chunk_t *chunk_get_prev_ncnl(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_comment_or_newline, scope, direction_e::BACKWARD, false)); +} + + +chunk_t *chunk_get_prev_ncnlni(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_comment_or_newline_or_ignored, scope, direction_e::BACKWARD, false)); +} + + +chunk_t *chunk_get_prev_nc(chunk_t *cur, scope_e scope) +{ + return(chunk_search(cur, chunk_is_comment, scope, direction_e::BACKWARD, false)); +} + + +chunk_t *chunk_get_next_type(chunk_t *cur, c_token_t type, int level, scope_e scope) +{ + return(chunk_search_typelevel(cur, type, scope, direction_e::FORWARD, level)); +} + + +chunk_t *chunk_get_next_str(chunk_t *cur, const char *str, size_t len, int level, scope_e scope) +{ + return(chunk_search_str(cur, str, len, scope, direction_e::FORWARD, level)); +} + + +chunk_t *chunk_get_prev_type(chunk_t *cur, c_token_t type, int level, scope_e scope) +{ + return(chunk_search_typelevel(cur, type, scope, direction_e::BACKWARD, level)); +} + + +chunk_t *chunk_get_prev_str(chunk_t *cur, const char *str, size_t len, int level, scope_e scope) +{ + return(chunk_search_str(cur, str, len, scope, direction_e::BACKWARD, level)); +} + + +bool chunk_is_newline_between(chunk_t *start, chunk_t *end) +{ + for (chunk_t *pc = start; pc != end; pc = chunk_get_next(pc)) + { + if (chunk_is_newline(pc)) + { + return(true); + } + } + + return(false); +} + + +void chunk_swap(chunk_t *pc1, chunk_t *pc2) +{ + g_cl.Swap(pc1, pc2); +} + + +// TODO: the following function shall be made similar to the search functions +chunk_t *chunk_first_on_line(chunk_t *pc) +{ + chunk_t *first = pc; + + while ((pc = chunk_get_prev(pc)) != nullptr && !chunk_is_newline(pc)) + { + first = pc; + } + return(first); +} + + +bool chunk_is_last_on_line(chunk_t &pc) //TODO: pc should be const here +{ + // check if pc is the very last chunk of the file + const auto *end = chunk_get_tail(); + + if (&pc == end) + { + return(true); + } + // if the next chunk is a newline then pc is the last chunk on its line + const auto *next = chunk_get_next(&pc); + + if (chunk_is_token(next, CT_NEWLINE)) + { + return(true); + } + return(false); +} + + +// TODO: this function needs some cleanup +void chunk_swap_lines(chunk_t *pc1, chunk_t *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 == nullptr + || pc2 == nullptr + || pc1 == pc2) + { + return; + } + /* + * Example start: + * ? - start1 - a1 - b1 - nl1 - ? - ref2 - start2 - a2 - b2 - nl2 - ? + * ^- pc1 ^- pc2 + */ + chunk_t *ref2 = chunk_get_prev(pc2); + + // Move the line started at pc2 before pc1 + while (pc2 != nullptr && !chunk_is_newline(pc2)) + { + chunk_t *tmp = chunk_get_next(pc2); + 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 != nullptr && !chunk_is_newline(pc1)) + { + chunk_t *tmp = chunk_get_next(pc1); + g_cl.Pop(pc1); + + if (ref2 != nullptr) + { + 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 != nullptr && pc2 != nullptr) + { + 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_t *chunk_get_next_nvb(chunk_t *cur, const scope_e scope) +{ + return(chunk_search(cur, chunk_is_vbrace, scope, direction_e::FORWARD, false)); +} + + +chunk_t *chunk_get_prev_nvb(chunk_t *cur, const scope_e scope) +{ + return(chunk_search(cur, chunk_is_vbrace, scope, direction_e::BACKWARD, false)); +} + + +void chunk_flags_set_real(chunk_t *pc, pcf_flags_t clr_bits, pcf_flags_t set_bits) +{ + if (pc != nullptr) + { + LOG_FUNC_ENTRY(); + auto const nflags = (pc->flags & ~clr_bits) | set_bits; + + if (pc->flags != nflags) + { + LOG_FMT(LSETFLG, + "%s(%d): %016llx^%016llx=%016llx " + "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", + get_token_name(get_chunk_parent_type(pc))); + log_func_stack_inline(LSETFLG); + pc->flags = nflags; + } + } +} + + +void set_chunk_type_real(chunk_t *pc, c_token_t token, const char *func, int line) +{ + LOG_FUNC_ENTRY(); + + if ( pc == nullptr + || 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_t *pc, c_token_t token, const char *func, int line) +{ + LOG_FUNC_ENTRY(); + + if ( pc == nullptr + || 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 + { + LOG_FMT(LSETPAR, "'%s'\n", pc->text()); + } + 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 + + +c_token_t get_chunk_parent_type(chunk_t *pc) +{ + LOG_FUNC_ENTRY(); + + if (pc == nullptr) + { + return(CT_NONE); + } + return(pc->parent_type); +} // get_chunk_parent_type + + +static chunk_t *chunk_get_ncnlnp(chunk_t *cur, const scope_e scope, const direction_e dir) +{ + chunk_t *pc = cur; + + pc = (chunk_is_preproc(pc) == true) ? + chunk_search(pc, chunk_is_comment_or_newline_in_preproc, scope, dir, false) : + chunk_search(pc, chunk_is_comment_newline_or_preproc, scope, dir, false); + return(pc); +} + + +static chunk_t *chunk_add(const chunk_t *pc_in, chunk_t *ref, const direction_e pos) +{ +#ifdef DEBUG + 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_t *pc = chunk_dup(pc_in); + + if (pc != nullptr) + { + if (ref != nullptr) // ref is a valid chunk + { + (pos == direction_e::FORWARD) ? g_cl.AddAfter(pc, ref) : g_cl.AddBefore(pc, ref); + } + else // ref == NULL + { + (pos == direction_e::FORWARD) ? g_cl.AddHead(pc) : g_cl.AddTail(pc); + } + chunk_log(pc, "chunk_add(A):"); + } + return(pc); +} + + +chunk_t *chunk_get_next_ssq(chunk_t *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 = chunk_get_next_ncnl(cur); + } + return(cur); +} + + +chunk_t *chunk_get_prev_ssq(chunk_t *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 = chunk_get_prev_ncnl(cur); + } + return(cur); +} + + +chunk_t *chunk_get_pp_start(chunk_t *cur) +{ + if (!chunk_is_preproc(cur)) + { + return(nullptr); + } + + while (!chunk_is_token(cur, CT_PREPROC)) + { + cur = chunk_get_prev(cur, scope_e::PREPROC); + } + return(cur); +} + + +//! skip to the final word/type in a :: chain +static chunk_t *chunk_skip_dc_member(chunk_t *start, scope_e scope, direction_e dir) +{ + LOG_FUNC_ENTRY(); + + if (start == nullptr) + { + return(nullptr); + } + const auto step_fcn = (dir == direction_e::FORWARD) + ? chunk_get_next_ncnl : chunk_get_prev_ncnl; + + chunk_t *pc = start; + chunk_t *next = chunk_is_token(pc, CT_DC_MEMBER) ? pc : step_fcn(pc, scope); + + while (chunk_is_token(next, CT_DC_MEMBER)) + { + pc = step_fcn(next, scope); + + if (pc == nullptr) + { + return(nullptr); + } + next = step_fcn(pc, scope); + } + return(pc); +} + + +chunk_t *chunk_skip_dc_member(chunk_t *start, scope_e scope) +{ + return(chunk_skip_dc_member(start, scope, direction_e::FORWARD)); +} + + +chunk_t *chunk_skip_dc_member_rev(chunk_t *start, scope_e scope) +{ + return(chunk_skip_dc_member(start, scope, direction_e::BACKWARD)); +} + + +// set parent member +void chunk_set_parent(chunk_t *pc, chunk_t *parent) +{ + if (pc == nullptr) + { + return; + } + + if (parent == nullptr) + { + return; + } + + if (pc == parent) + { + return; + } + pc->parent = parent; +} + + +c_token_t get_type_of_the_parent(chunk_t *pc) +{ + if (pc == nullptr) + { + return(CT_UNKNOWN); + } + + if (pc->parent == nullptr) + { + return(CT_PARENT_NOT_SET); + } + return(pc->parent->type); +} |
