void indent_to_column(chunk_t *pc, int column) { if (column < pc->column) column = pc->column; reindent_line(pc, column); }
/** * Split right after the chunk */ static void split_before_chunk(chunk_t *pc) { LOG_FMT(LSPLIT, "%s: %s\n", __func__, pc->str.c_str()); if (!chunk_is_newline(pc) && !chunk_is_newline(chunk_get_prev(pc))) { newline_add_before(pc); reindent_line(pc, pc->brace_level * cpd.settings[UO_indent_columns].n); cpd.changes++; } }
/** * Split right after the chunk */ static void split_before_chunk(chunk_t *pc) { LOG_FMT(LSPLIT, "%s: %s\n", __func__, pc->str.c_str()); if (!chunk_is_newline(pc) && !chunk_is_newline(chunk_get_prev(pc))) { newline_add_before(pc); // reindent needs to include the indent_continue value and was off by one reindent_line(pc, pc->brace_level * cpd.settings[UO_indent_columns].n + abs(cpd.settings[UO_indent_continue].n) + 1); cpd.changes++; } }
static void split_template(chunk_t *start) { LOG_FUNC_ENTRY(); LOG_FMT(LSPLIT, " %s(%d): start %s\n", __func__, __LINE__, start->text()); LOG_FMT(LSPLIT, " %s(%d): back up until the prev is a comma\n", __func__, __LINE__); // back up until the prev is a comma chunk_t *prev = start; while ((prev = chunk_get_prev(prev)) != nullptr) { LOG_FMT(LSPLIT, " %s(%d): prev '%s'\n", __func__, __LINE__, prev->text()); if (chunk_is_newline(prev) || prev->type == CT_COMMA) { break; } } if (prev != nullptr && !chunk_is_newline(prev)) { LOG_FMT(LSPLIT, " %s(%d):", __func__, __LINE__); LOG_FMT(LSPLIT, " -- ended on [%s] --\n", get_token_name(prev->type)); chunk_t *pc = chunk_get_next(prev); newline_add_before(pc); size_t min_col = 1; if (cpd.settings[UO_indent_continue].n == 0) { min_col += cpd.settings[UO_indent_columns].u; } else { min_col += abs(cpd.settings[UO_indent_continue].n); } reindent_line(pc, min_col); cpd.changes++; } } // split_templatefcn_params
/** * Put spaces on either side of the preproc (#) symbol. * This is done by pointing pc->str into pp_str and adjusting the * length. */ void indent_preproc(void) { chunk_t *pc; chunk_t *next; int pp_level; int pp_level_sub = 0; int tmp; /* Define a string of 16 spaces + # + 16 spaces */ static const char *pp_str = " # "; static const char *alt_str = " %: "; /* Scan to see if the whole file is covered by one #ifdef */ int stage = 0; for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next(pc)) { if (chunk_is_comment(pc) || chunk_is_newline(pc)) continue; if (stage == 0) { /* Check the first PP, make sure it is an #if type */ if (pc->type != CT_PREPROC) break; next = chunk_get_next(pc); if ((next == NULL) || (next->type != CT_PP_IF)) break; stage = 1; } else if (stage == 1) { /* Scan until a PP at level 0 is found - the close to the #if */ if ((pc->type == CT_PREPROC) && (pc->pp_level == 0)) stage = 2; continue; } else if (stage == 2) { /* We should only see the rest of the preprocessor */ if ((pc->type == CT_PREPROC) || ((pc->flags & PCF_IN_PREPROC) == 0)) { stage = 0; break; } } } if (stage == 2) { LOG_FMT(LINFO, "The whole file is covered by a #IF\n"); pp_level_sub = 1; } for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next(pc)) { if (pc->type != CT_PREPROC) continue; if (pc->column != 1) { /* Don't handle preprocessors that aren't in column 1 */ LOG_FMT(LINFO, "%s: Line %d doesn't start in column 1 (%d)\n", __func__, pc->orig_line, pc->column); continue; } /* point into pp_str */ if (pc->len == 2) /* alternate token crap */ pc->str = &alt_str[16]; else pc->str = &pp_str[16]; pp_level = pc->pp_level - pp_level_sub; if (pp_level < 0) pp_level = 0; else if (pp_level > 16) pp_level = 16; /* Note that the indent is removed by default */ if ((cpd.settings[UO_pp_indent].a & AV_ADD) != 0) { /* Need to add some spaces */ pc->str -= pp_level; pc->len += pp_level; } else if (cpd.settings[UO_pp_indent].a == AV_IGNORE) { tmp = (pc->orig_col <= 16) ? pc->orig_col - 1 : 16; pc->str -= tmp; pc->len += tmp; } /* Add spacing by adjusting the length */ if ((cpd.settings[UO_pp_space].a & AV_ADD) != 0) pc->len += pp_level; next = chunk_get_next(pc); if (next != NULL) reindent_line(next, pc->len + 1); LOG_FMT(LPPIS, "%s: Indent line %d to %d (len %d, next->col %d)\n", __func__, pc->orig_line, pp_level, pc->len, next->column); } }
/** * Change the top-level indentation only by changing the column member in * the chunk structures. * The level indicator must already be set. */ void indent_text(void) { chunk_t *pc; chunk_t *next; chunk_t *prev = NULL; bool did_newline = true; int idx; int vardefcol = 0; int indent_size = cpd.settings[UO_indent_columns].n; int tmp; struct parse_frame frm; bool in_preproc = false, was_preproc = false; int indent_column; int cout_col = 0; // for aligning << stuff int cout_level = 0; // for aligning << stuff int parent_token_indent = 0; memset(&frm, 0, sizeof(frm)); /* dummy top-level entry */ frm.pse[0].indent = 1; frm.pse[0].indent_tmp = 1; frm.pse[0].type = CT_EOF; pc = chunk_get_head(); while (pc != NULL) { /* Handle proprocessor transitions */ was_preproc = in_preproc; in_preproc = (pc->flags & PCF_IN_PREPROC) != 0; if (cpd.settings[UO_indent_brace_parent].b) parent_token_indent = token_indent(pc->parent_type); /* Clean up after a #define */ if (!in_preproc) while ((frm.pse_tos > 0) && frm.pse[frm.pse_tos].in_preproc) indent_pse_pop(frm, pc); else { pf_check(&frm, pc); if (!was_preproc) { /* Transition into a preproc by creating a dummy indent */ frm.level++; indent_pse_push(frm, pc); frm.pse[frm.pse_tos].indent = 1 + indent_size; frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent; } } if ((cout_col > 0) && (chunk_is_semicolon(pc) || (pc->level < cout_level))) { cout_col = 0; cout_level = 0; } /** * Handle non-brace closures */ int old_pse_tos; do { old_pse_tos = frm.pse_tos; /* End anything that drops a level * REVISIT: not sure about the preproc check */ if (!chunk_is_newline(pc) && !chunk_is_comment(pc) && ((pc->flags & PCF_IN_PREPROC) == 0) && (frm.pse[frm.pse_tos].level > pc->level)) indent_pse_pop(frm, pc); if (frm.pse[frm.pse_tos].level == pc->level) { /* process virtual braces closes (no text output) */ if ((pc->type == CT_VBRACE_CLOSE) && (frm.pse[frm.pse_tos].type == CT_VBRACE_OPEN)) { indent_pse_pop(frm, pc); frm.level--; pc = chunk_get_next(pc); } /* End any assign operations with a semicolon on the same level */ if ((frm.pse[frm.pse_tos].type == CT_ASSIGN) && (chunk_is_semicolon(pc) || (pc->type == CT_COMMA) || (pc->type == CT_BRACE_OPEN))) indent_pse_pop(frm, pc); /* End any CPP class colon crap */ if ((frm.pse[frm.pse_tos].type == CT_CLASS_COLON) && ((pc->type == CT_BRACE_OPEN) || chunk_is_semicolon(pc))) indent_pse_pop(frm, pc); /* a case is ended with another case or a close brace */ if ((frm.pse[frm.pse_tos].type == CT_CASE) && ((pc->type == CT_BRACE_CLOSE) || (pc->type == CT_CASE))) indent_pse_pop(frm, pc); /* a return is ended with a semicolon */ if ((frm.pse[frm.pse_tos].type == CT_RETURN) && chunk_is_semicolon(pc)) indent_pse_pop(frm, pc); /* Close out parens and squares */ if ((frm.pse[frm.pse_tos].type == (pc->type - 1)) && ((pc->type == CT_PAREN_CLOSE) || (pc->type == CT_SPAREN_CLOSE) || (pc->type == CT_FPAREN_CLOSE) || (pc->type == CT_SQUARE_CLOSE) || (pc->type == CT_ANGLE_CLOSE))) { indent_pse_pop(frm, pc); frm.paren_count--; } } } while (old_pse_tos > frm.pse_tos); /* Grab a copy of the current indent */ indent_column = frm.pse[frm.pse_tos].indent_tmp; if (!chunk_is_newline(pc) && !chunk_is_comment(pc)) { LOG_FMT(LINDPC, " -=[ %.*s ]=- top=%d %s %d/%d\n", pc->len, pc->str, frm.pse_tos, get_token_name(frm.pse[frm.pse_tos].type), frm.pse[frm.pse_tos].indent_tmp, frm.pse[frm.pse_tos].indent); } /** * Handle stuff that can affect the current indent: * - brace close * - vbrace open * - brace open * - case (immediate) * - labels (immediate) * - class colons (immediate) * * And some stuff that can't * - open paren * - open square * - assignment * - return */ if (pc->type == CT_BRACE_CLOSE) { if (frm.pse[frm.pse_tos].type == CT_BRACE_OPEN) { indent_pse_pop(frm, pc); frm.level--; /* Update the indent_column if needed */ if (!cpd.settings[UO_indent_braces].b && (parent_token_indent == 0)) indent_column = frm.pse[frm.pse_tos].indent_tmp; if ((pc->parent_type == CT_IF) || (pc->parent_type == CT_ELSE) || (pc->parent_type == CT_ELSEIF) || (pc->parent_type == CT_DO) || (pc->parent_type == CT_WHILE) || (pc->parent_type == CT_SWITCH) || (pc->parent_type == CT_FOR)) indent_column += cpd.settings[UO_indent_brace].n; } } else if (pc->type == CT_VBRACE_OPEN) { frm.level++; indent_pse_push(frm, pc); frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + indent_size; frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent; /* Always indent on virtual braces */ indent_column = frm.pse[frm.pse_tos].indent_tmp; } else if (pc->type == CT_BRACE_OPEN) { frm.level++; indent_pse_push(frm, pc); if (frm.paren_count != 0) /* We are inside ({ ... }) -- indent one tab from the paren */ frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent_tmp + indent_size; else { /* Use the prev indent level + indent_size. */ frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + indent_size; /* If this brace is part of a statement, bump it out by indent_brace */ if ((pc->parent_type == CT_IF) || (pc->parent_type == CT_ELSE) || (pc->parent_type == CT_ELSEIF) || (pc->parent_type == CT_DO) || (pc->parent_type == CT_WHILE) || (pc->parent_type == CT_SWITCH) || (pc->parent_type == CT_FOR)) { if (parent_token_indent != 0) frm.pse[frm.pse_tos].indent += parent_token_indent - indent_size; else { frm.pse[frm.pse_tos].indent += cpd.settings[UO_indent_brace].n; indent_column += cpd.settings[UO_indent_brace].n; } } else if (pc->parent_type == CT_CASE) { /* The indent_case_brace setting affects the parent CT_CASE */ frm.pse[frm.pse_tos].indent_tmp += cpd.settings[UO_indent_case_brace].n; frm.pse[frm.pse_tos].indent += cpd.settings[UO_indent_case_brace].n; } else if ((pc->parent_type == CT_CLASS) && !cpd.settings[UO_indent_class].b) frm.pse[frm.pse_tos].indent -= indent_size; else if ((pc->parent_type == CT_NAMESPACE) && !cpd.settings[UO_indent_namespace].b) frm.pse[frm.pse_tos].indent -= indent_size; } if ((pc->flags & PCF_DONT_INDENT) != 0) { frm.pse[frm.pse_tos].indent = pc->column; indent_column = pc->column; } else { /** * If there isn't a newline between the open brace and the next * item, just indent to wherever the next token is. * This covers this sort of stuff: * { a++; * b--; }; */ next = chunk_get_next_ncnl(pc); if (!chunk_is_newline_between(pc, next)) frm.pse[frm.pse_tos].indent = next->column; frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent; frm.pse[frm.pse_tos].open_line = pc->orig_line; /* Update the indent_column if needed */ if (cpd.settings[UO_indent_braces].n || (parent_token_indent != 0)) indent_column = frm.pse[frm.pse_tos].indent_tmp; } } else if (pc->type == CT_CASE) { /* Start a case - indent UO_indent_switch_case from the switch level */ tmp = frm.pse[frm.pse_tos].indent + cpd.settings[UO_indent_switch_case].n; indent_pse_push(frm, pc); frm.pse[frm.pse_tos].indent = tmp; frm.pse[frm.pse_tos].indent_tmp = tmp - indent_size; /* Always set on case statements */ indent_column = frm.pse[frm.pse_tos].indent_tmp; } else if (pc->type == CT_LABEL) { /* Labels get sent to the left or backed up */ if (cpd.settings[UO_indent_label].n > 0) indent_column = cpd.settings[UO_indent_label].n; else indent_column = frm.pse[frm.pse_tos].indent + cpd.settings[UO_indent_label].n; } else if (pc->type == CT_CLASS_COLON) { /* just indent one level */ indent_pse_push(frm, pc); frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent_tmp + indent_size; frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent; indent_column = frm.pse[frm.pse_tos].indent_tmp; if (cpd.settings[UO_indent_class_colon].b) { prev = chunk_get_prev(pc); if (chunk_is_newline(prev)) frm.pse[frm.pse_tos].indent += 2; /* don't change indent of current line */ } } else if ((pc->type == CT_PAREN_OPEN) || (pc->type == CT_SPAREN_OPEN) || (pc->type == CT_FPAREN_OPEN) || (pc->type == CT_SQUARE_OPEN) || (pc->type == CT_ANGLE_OPEN)) { /* Open parens and squares - never update indent_column */ indent_pse_push(frm, pc); frm.pse[frm.pse_tos].indent = pc->column + pc->len; if (cpd.settings[UO_indent_func_call_param].b && (pc->type == CT_FPAREN_OPEN) && (pc->parent_type == CT_FUNC_CALL)) frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + indent_size; if ((chunk_is_str(pc, "(", 1) && !cpd.settings[UO_indent_paren_nl].b) || (chunk_is_str(pc, "[", 1) && !cpd.settings[UO_indent_square_nl].b)) { next = chunk_get_next_nc(pc); if (chunk_is_newline(next)) { int sub = 1; if (frm.pse[frm.pse_tos - 1].type == CT_ASSIGN) sub = 2; frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - sub].indent + indent_size; } } frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent; frm.paren_count++; } else if (pc->type == CT_ASSIGN) { /** * if there is a newline after the '=', just indent one level, * otherwise align on the '='. * Never update indent_column. */ next = chunk_get_next(pc); if (next != NULL) { indent_pse_push(frm, pc); if (chunk_is_newline(next)) frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent_tmp + indent_size; else frm.pse[frm.pse_tos].indent = pc->column + pc->len + 1; frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent; } } else if (pc->type == CT_RETURN) { /* don't count returns inside a () or [] */ if (pc->level == pc->brace_level) { indent_pse_push(frm, pc); frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + pc->len + 1; frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos - 1].indent; } } else if (chunk_is_str(pc, "<<", 2)) { if (cout_col == 0) { cout_col = pc->column; cout_level = pc->level; } } else { /* anything else? */ } /** * Indent the line if needed */ if (did_newline && !chunk_is_newline(pc) && (pc->len != 0)) { /** * Check for special continuations. * Note that some of these could be done as a stack item like * everything else */ prev = chunk_get_prev_ncnl(pc); if ((pc->type == CT_MEMBER) || (pc->type == CT_DC_MEMBER) || ((prev != NULL) && ((prev->type == CT_MEMBER) || (prev->type == CT_DC_MEMBER)))) { tmp = cpd.settings[UO_indent_member].n + indent_column; LOG_FMT(LINDENT, "%s: %d] member => %d\n", __func__, pc->orig_line, tmp); reindent_line(pc, tmp); } else if (chunk_is_str(pc, "<<", 2) && (cout_col > 0)) { LOG_FMT(LINDENT, "%s: %d] cout_col => %d\n", __func__, pc->orig_line, cout_col); reindent_line(pc, cout_col); } else if ((vardefcol > 0) && (pc->type == CT_WORD) && ((pc->flags & PCF_VAR_DEF) != 0) && (prev != NULL) && (prev->type == CT_COMMA)) { LOG_FMT(LINDENT, "%s: %d] Vardefcol => %d\n", __func__, pc->orig_line, vardefcol); reindent_line(pc, vardefcol); } else if ((pc->type == CT_STRING) && (prev->type == CT_STRING) && cpd.settings[UO_indent_align_string].b) { LOG_FMT(LINDENT, "%s: %d] String => %d\n", __func__, pc->orig_line, prev->column); reindent_line(pc, prev->column); } else if (chunk_is_comment(pc)) { LOG_FMT(LINDENT, "%s: %d] comment => %d\n", __func__, pc->orig_line, frm.pse[frm.pse_tos].indent_tmp); indent_comment(pc, frm.pse[frm.pse_tos].indent_tmp); } else if (pc->type == CT_PREPROC) { /* Preprocs are always in column 1. See indent_preproc() */ if (pc->column != 1) reindent_line(pc, 1); } else { if (pc->column != indent_column) { LOG_FMT(LINDENT, "%s: %d] indent => %d [%.*s]\n", __func__, pc->orig_line, indent_column, pc->len, pc->str); reindent_line(pc, indent_column); } } did_newline = false; } /** * Handle variable definition continuation indenting */ if ((pc->type == CT_WORD) && ((pc->flags & PCF_IN_FCN_DEF) == 0) && ((pc->flags & PCF_VAR_1ST_DEF) == PCF_VAR_1ST_DEF)) vardefcol = pc->column; if (chunk_is_semicolon(pc) || ((pc->type == CT_BRACE_OPEN) && (pc->parent_type == CT_FUNCTION))) vardefcol = 0; /* if we hit a newline, reset indent_tmp */ if (chunk_is_newline(pc) || (pc->type == CT_COMMENT_MULTI) || (pc->type == CT_COMMENT_CPP)) { frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent; /** * Handle the case of a multi-line #define w/o anything on the * first line (indent_tmp will be 1 or 0) */ if ((pc->type == CT_NL_CONT) && (frm.pse[frm.pse_tos].indent_tmp <= indent_size)) frm.pse[frm.pse_tos].indent_tmp = indent_size + 1; /* Get ready to indent the next item */ did_newline = true; } if (!chunk_is_comment(pc) && !chunk_is_newline(pc)) prev = pc; pc = chunk_get_next(pc); } /* Throw out any stuff inside a preprocessor - no need to warn */ while ((frm.pse_tos > 0) && frm.pse[frm.pse_tos].in_preproc) indent_pse_pop(frm, pc); for (idx = 1; idx <= frm.pse_tos; idx++) { LOG_FMT(LWARN, "%s:%d Unmatched %s\n", cpd.filename, frm.pse[idx].open_line, get_token_name(frm.pse[idx].type)); cpd.error_count++; } }
/** * Figures out where to split a function def/proto/call * * For fcn protos and defs. Also fcn calls where level == brace_level: * - find the open fparen * + if it doesn't have a newline right after it * * see if all parameters will fit individually after the paren * * if not, throw a newline after the open paren & return * - scan backwards to the open fparen or comma * + if there isn't a newline after that item, add one & return * + otherwise, add a newline before the start token * * @param start the offending token * @return the token that should have a newline * inserted before it */ static void split_fcn_params(chunk_t *start) { LOG_FUNC_ENTRY(); LOG_FMT(LSPLIT, " %s: ", __func__); chunk_t *prev; chunk_t *fpo; chunk_t *pc; int cur_width = 0; int last_col = -1; int min_col; /* Find the opening fparen */ fpo = start; while (((fpo = chunk_get_prev(fpo)) != NULL) && (fpo->type != CT_FPAREN_OPEN)) { /* do nothing */ } pc = chunk_get_next_ncnl(fpo); min_col = pc->column; LOG_FMT(LSPLIT, " mincol=%d, max_width=%d ", min_col, cpd.settings[UO_code_width].n - min_col); while (pc != NULL) { if (chunk_is_newline(pc)) { cur_width = 0; last_col = -1; } else { if (last_col < 0) { last_col = pc->column; } cur_width += (pc->column - last_col) + pc->len(); last_col = pc->column + pc->len(); if ((pc->type == CT_COMMA) || (pc->type == CT_FPAREN_CLOSE)) { cur_width--; LOG_FMT(LSPLIT, " width=%d ", cur_width); if (((last_col - 1) > cpd.settings[UO_code_width].n) || (pc->type == CT_FPAREN_CLOSE)) { break; } } } pc = chunk_get_next(pc); } /* back up until the prev is a comma */ prev = pc; while ((prev = chunk_get_prev(prev)) != NULL) { if (chunk_is_newline(prev) || (prev->type == CT_COMMA)) { break; } last_col -= pc->len(); if (prev->type == CT_FPAREN_OPEN) { pc = chunk_get_next(prev); if (!cpd.settings[UO_indent_paren_nl].b) { min_col = pc->brace_level * cpd.settings[UO_indent_columns].n + 1; if (cpd.settings[UO_indent_continue].n == 0) { min_col += cpd.settings[UO_indent_columns].n; } else { min_col += abs(cpd.settings[UO_indent_continue].n); } } /* Don't split "()" */ if (pc->type != c_token_t(prev->type + 1)) { break; } } } if ((prev != NULL) && !chunk_is_newline(prev)) { LOG_FMT(LSPLIT, " -- ended on [%s] --\n", get_token_name(prev->type)); pc = chunk_get_next(prev); newline_add_before(pc); reindent_line(pc, min_col); cpd.changes++; } } // split_fcn_params
static void split_fcn_params(chunk_t *start) { LOG_FUNC_ENTRY(); LOG_FMT(LSPLIT, "%s(%d): '%s'\n", __func__, __LINE__, start->text()); // Find the opening function parenthesis chunk_t *fpo = start; LOG_FMT(LSPLIT, "%s(%d): Find the opening function parenthesis\n", __func__, __LINE__); while ( ((fpo = chunk_get_prev(fpo)) != nullptr) && fpo->type != CT_FPAREN_OPEN) { // do nothing LOG_FMT(LSPLIT, "%s(%d): '%s', orig_col is %zu, level is %zu\n", __func__, __LINE__, fpo->text(), fpo->orig_col, fpo->level); } chunk_t *pc = chunk_get_next_ncnl(fpo); size_t min_col = pc->column; LOG_FMT(LSPLIT, " mincol is %zu, max_width is %zu\n", min_col, cpd.settings[UO_code_width].u - min_col); int cur_width = 0; int last_col = -1; LOG_FMT(LSPLIT, "%s(%d):look forward until CT_COMMA or CT_FPAREN_CLOSE\n", __func__, __LINE__); while (pc != nullptr) { LOG_FMT(LSPLIT, "%s(%d): pc->text() '%s', type is %s\n", __func__, __LINE__, pc->text(), get_token_name(pc->type)); if (chunk_is_newline(pc)) { cur_width = 0; last_col = -1; } else { if (last_col < 0) { last_col = pc->column; LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n", __func__, __LINE__, last_col); } cur_width += (pc->column - last_col) + pc->len(); last_col = pc->column + pc->len(); LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n", __func__, __LINE__, last_col); if (pc->type == CT_COMMA || pc->type == CT_FPAREN_CLOSE) { cur_width--; LOG_FMT(LSPLIT, "%s(%d): cur_width is %d\n", __func__, __LINE__, cur_width); if ( ((last_col - 1) > static_cast<int>(cpd.settings[UO_code_width].u)) || pc->type == CT_FPAREN_CLOSE) { break; } } } pc = chunk_get_next(pc); } // back up until the prev is a comma chunk_t *prev = pc; LOG_FMT(LSPLIT, " %s(%d): back up until the prev is a comma\n", __func__, __LINE__); while ((prev = chunk_get_prev(prev)) != nullptr) { LOG_FMT(LSPLIT, "%s(%d): pc '%s', pc->level is %zu, prev '%s', prev->type is %s\n", __func__, __LINE__, pc->text(), pc->level, prev->text(), get_token_name(prev->type)); if (chunk_is_newline(prev) || prev->type == CT_COMMA) { LOG_FMT(LSPLIT, "%s(%d): found at %zu\n", __func__, __LINE__, prev->orig_col); break; } LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n", __func__, __LINE__, last_col); last_col -= pc->len(); LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n", __func__, __LINE__, last_col); if (prev->type == CT_FPAREN_OPEN) { pc = chunk_get_next(prev); if (!cpd.settings[UO_indent_paren_nl].b) { min_col = pc->brace_level * cpd.settings[UO_indent_columns].u + 1; LOG_FMT(LSPLIT, "%s(%d): min_col is %zu\n", __func__, __LINE__, min_col); if (cpd.settings[UO_indent_continue].n == 0) { min_col += cpd.settings[UO_indent_columns].u; } else { min_col += abs(cpd.settings[UO_indent_continue].n); } LOG_FMT(LSPLIT, "%s(%d): min_col is %zu\n", __func__, __LINE__, min_col); } // Don't split "()" if (pc->type != c_token_t(prev->type + 1)) { break; } } } if (prev != nullptr && !chunk_is_newline(prev)) { LOG_FMT(LSPLIT, "%s(%d): -- ended on [%s] --\n", __func__, __LINE__, get_token_name(prev->type)); LOG_FMT(LSPLIT, "%s(%d): min_col is %zu\n", __func__, __LINE__, min_col); pc = chunk_get_next(prev); newline_add_before(pc); reindent_line(pc, min_col); cpd.changes++; } } // split_fcn_params
/** * Generically aligns on '=', '{', '(' and item after ',' * It scans the first line and picks up the location of those tags. * It then scans subsequent lines and adjusts the column. * Finally it does a second pass to align everything. * * Aligns all the '=' signs in stucture assignments. * a = { * .a = 1; * .type = fast; * }; * * And aligns on '{', numbers, strings, words. * colors[] = { * {"red", {255, 0, 0}}, {"blue", { 0, 255, 0}}, * {"green", { 0, 0, 255}}, {"purple", {255, 255, 0}}, * }; * * For the C99 indexed array assignment, the leading []= is skipped (no aligning) * struct foo_t bars[] = * { * [0] = { .name = "bar", * .age = 21 }, * [1] = { .name = "barley", * .age = 55 }, * }; * * NOTE: this assumes that spacing is at the minimum correct spacing (ie force) * if it isn't, some extra spaces will be inserted. * * @param start Points to the open brace chunk */ static void align_init_brace(chunk_t *start) { int idx; chunk_t *pc; chunk_t *next; chunk_t *prev; chunk_t *num_token = NULL; cpd.al_cnt = 0; cpd.al_c99_array = false; LOG_FMT(LALBR, "%s: line %d, col %d\n", __func__, start->orig_line, start->orig_col); pc = chunk_get_next_ncnl(start); pc = scan_ib_line(pc, true); if ((pc == NULL) || ((pc->type == CT_BRACE_CLOSE) && (pc->parent_type == CT_ASSIGN))) { /* single line - nothing to do */ return; } do { pc = scan_ib_line(pc, false); /* debug dump the current frame */ align_log_al(LALBR, pc->orig_line); while (chunk_is_newline(pc)) { pc = chunk_get_next(pc); } } while ((pc != NULL) && (pc->level > start->level)); /* debug dump the current frame */ align_log_al(LALBR, start->orig_line); if (cpd.settings[UO_align_on_tabstop].b && (cpd.al_cnt >= 1) && (cpd.al[0].type == CT_ASSIGN)) { int rem = (cpd.al[0].col - 1) % cpd.settings[UO_output_tab_size].n; if (rem != 0) { LOG_FMT(LALBR, "%s: col=%d rem=%d", __func__, cpd.al[0].col, rem); cpd.al[0].col += cpd.settings[UO_output_tab_size].n - rem; } } pc = chunk_get_next(start); idx = 0; do { if ((idx == 0) && (pc->type == CT_SQUARE_OPEN)) { pc = chunk_get_next_type(pc, CT_ASSIGN, pc->level); pc = chunk_get_next(pc); if (pc != NULL) { LOG_FMT(LALBR, " -%d- skipped '[] =' to %s\n", pc->orig_line, get_token_name(pc->type)); } continue; } next = pc; if (idx < cpd.al_cnt) { LOG_FMT(LALBR, " (%d) check %s vs %s -- ", idx, get_token_name(pc->type), get_token_name(cpd.al[idx].type)); if (pc->type == cpd.al[idx].type) { if ((idx == 0) && cpd.al_c99_array) { prev = chunk_get_prev(pc); if (chunk_is_newline(prev)) { pc->flags |= PCF_DONT_INDENT; } } LOG_FMT(LALBR, " [%.*s] to col %d\n", pc->len, pc->str, cpd.al[idx].col); if (num_token != NULL) { int col_diff = pc->column - num_token->column; reindent_line(num_token, cpd.al[idx].col - col_diff); //LOG_FMT(LSYS, "-= %d =- NUM indent [%.*s] col=%d diff=%d\n", // num_token->orig_line, // num_token->len, num_token->str, cpd.al[idx - 1].col, col_diff); num_token->flags |= PCF_WAS_ALIGNED; num_token = NULL; } /* Comma's need to 'fall back' to the previous token */ if (pc->type == CT_COMMA) { next = chunk_get_next(pc); if ((next != NULL) && !chunk_is_newline(next)) { //LOG_FMT(LSYS, "-= %d =- indent [%.*s] col=%d len=%d\n", // next->orig_line, // next->len, next->str, cpd.al[idx].col, cpd.al[idx].len); if ((idx < (cpd.al_cnt - 1)) && cpd.settings[UO_align_number_left].b && ((next->type == CT_NUMBER_FP) || (next->type == CT_NUMBER) || (next->type == CT_POS) || (next->type == CT_NEG))) { /* Need to wait until the next match to indent numbers */ num_token = next; } else { reindent_line(next, cpd.al[idx].col + cpd.al[idx].len); next->flags |= PCF_WAS_ALIGNED; } } } else { /* first item on the line */ reindent_line(pc, cpd.al[idx].col); pc->flags |= PCF_WAS_ALIGNED; /* see if we need to right-align a number */ if ((idx < (cpd.al_cnt - 1)) && cpd.settings[UO_align_number_left].b) { next = chunk_get_next(pc); if ((next != NULL) && !chunk_is_newline(next) && ((next->type == CT_NUMBER_FP) || (next->type == CT_NUMBER) || (next->type == CT_POS) || (next->type == CT_NEG))) { /* Need to wait until the next match to indent numbers */ num_token = next; } } } idx++; } else { LOG_FMT(LALBR, " no match\n"); } } if (chunk_is_newline(pc) || chunk_is_newline(next)) { idx = 0; } pc = chunk_get_next(pc); } while ((pc != NULL) && (pc->level > start->level)); }
/** * This renders the chunk list to a file. */ void output_text(FILE *pfile) { chunk_t *pc; chunk_t *prev; int cnt; int lvlcol; bool allow_tabs; cpd.fout = pfile; cpd.did_newline = 1; cpd.column = 1; if (cpd.bom) { write_bom(pfile, cpd.enc); } if (cpd.frag_cols > 0) { int indent = cpd.frag_cols - 1; for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next(pc)) { pc->column += indent; pc->column_indent += indent; } cpd.frag_cols = 0; } for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next(pc)) { if (pc->type == CT_NEWLINE) { for (cnt = 0; cnt < pc->nl_count; cnt++) { add_char('\n'); } cpd.did_newline = 1; cpd.column = 1; LOG_FMT(LOUTIND, " xx\n"); } else if (pc->type == CT_NL_CONT) { /* FIXME: this really shouldn't be done here! */ if ((pc->flags & PCF_WAS_ALIGNED) == 0) { if (cpd.settings[UO_sp_before_nl_cont].a & AV_REMOVE) { pc->column = cpd.column + (cpd.settings[UO_sp_before_nl_cont].a == AV_FORCE); } else { /* Try to keep the same relative spacing */ prev = chunk_get_prev(pc); while ((prev != NULL) && (prev->orig_col == 0) && (prev->nl_count == 0)) { prev = chunk_get_prev(prev); } if ((prev != NULL) && (prev->nl_count == 0)) { int orig_sp = (pc->orig_col - prev->orig_col_end); pc->column = cpd.column + orig_sp; if ((cpd.settings[UO_sp_before_nl_cont].a != AV_IGNORE) && (pc->column < (cpd.column + 1))) { pc->column = cpd.column + 1; } } } } output_to_column(pc->column, (cpd.settings[UO_indent_with_tabs].n == 2)); add_char('\\'); add_char('\n'); cpd.did_newline = 1; cpd.column = 1; LOG_FMT(LOUTIND, " \\xx\n"); } else if (pc->type == CT_COMMENT_MULTI) { if (cpd.settings[UO_cmt_indent_multi].b) { output_comment_multi(pc); } else { output_comment_multi_simple(pc); } } else if (pc->type == CT_COMMENT_CPP) { pc = output_comment_cpp(pc); } else if (pc->type == CT_COMMENT) { pc = output_comment_c(pc); } else if ((pc->type == CT_JUNK) || (pc->type == CT_IGNORED)) { /* do not adjust the column for junk */ add_text(pc->str); } else if (pc->len() == 0) { /* don't do anything for non-visible stuff */ LOG_FMT(LOUTIND, " <%d> -", pc->column); } else { /* indent to the 'level' first */ if (cpd.did_newline) { if (cpd.settings[UO_indent_with_tabs].n == 1) { /* FIXME: it would be better to properly set column_indent in * indent_text(), but this hack for '}' and ':' seems to work. */ if ((pc->type == CT_BRACE_CLOSE) || chunk_is_str(pc, ":", 1) || (pc->type == CT_PREPROC)) { lvlcol = pc->column; } else { lvlcol = pc->column_indent; if (lvlcol > pc->column) { lvlcol = pc->column; } } if (lvlcol > 1) { output_to_column(lvlcol, true); } } allow_tabs = (cpd.settings[UO_indent_with_tabs].n == 2) || (chunk_is_comment(pc) && (cpd.settings[UO_indent_with_tabs].n != 0)); LOG_FMT(LOUTIND, " %d> col %d/%d - ", pc->orig_line, pc->column, cpd.column); } else { /** * Reformatting multi-line comments can screw up the column. * Make sure we don't mess up the spacing on this line. * This has to be done here because comments are not formatted * until the output phase. */ if (pc->column < cpd.column) { reindent_line(pc, cpd.column); } /* not the first item on a line */ prev = chunk_get_prev(pc); allow_tabs = (cpd.settings[UO_align_with_tabs].b && ((pc->flags & PCF_WAS_ALIGNED) != 0) && ((prev->column + prev->len() + 1) != pc->column)); if (cpd.settings[UO_align_keep_tabs].b) { allow_tabs |= pc->after_tab; } LOG_FMT(LOUTIND, " %d(%d) -", pc->column, allow_tabs); } output_to_column(pc->column, allow_tabs); add_text(pc->str); cpd.did_newline = chunk_is_newline(pc); } } }