diff options
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.73.0/tests/expected/cpp/02102-indent-c.cpp')
-rw-r--r-- | debian/uncrustify-trinity/uncrustify-trinity-0.73.0/tests/expected/cpp/02102-indent-c.cpp | 1024 |
1 files changed, 1024 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.73.0/tests/expected/cpp/02102-indent-c.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.73.0/tests/expected/cpp/02102-indent-c.cpp new file mode 100644 index 00000000..70648397 --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.73.0/tests/expected/cpp/02102-indent-c.cpp @@ -0,0 +1,1024 @@ +/** + * @file indent.cpp + * Does all the indenting stuff. + * + * $Id: indent.cpp 548 2006-10-21 02:31:55Z bengardner $ + */ +#include "uncrustify_types.h" +#include "chunk_list.h" +#include "prototypes.h" +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cerrno> +#include <cctype> + + +/** + * General indenting approach: + * Indenting levels are put into a stack. + * + * The stack entries contain: + * - opening type + * - brace column + * - continuation column + * + * Items that start a new stack item: + * - preprocessor (new parse frame) + * - Brace Open (Virtual brace also) + * - Paren, Square, Angle open + * - Assignments + * - C++ '<<' operator (ie, cout << "blah") + * - case + * - class colon + * - return + * - types + * - any other continued statement + * + * Note that the column of items marked 'PCF_WAS_ALIGNED' is not changed. + * + * For an open brace: + * - indent increases by indent_columns + * - if part of if/else/do/while/switch/etc, an extra indent may be applied + * - if in a paren, then cont-col is set to column + 1, ie "({ some code })" + * + * Open paren/square/angle: + * cont-col is set to the column of the item after the open paren, unless + * followed by a newline, then it is set to (brace-col + indent_columns). + * Examples: + * a_really_long_funcion_name( + * param1, param2); + * a_really_long_funcion_name(param1, + * param2); + * + * Assignments: + * Assignments are continued aligned with the first item after the assignment, + * unless the assign is followed by a newline. + * Examples: + * some.variable = asdf + asdf + + * asdf; + * some.variable = + * asdf + asdf + asdf; + * + * C++ << operator: + * Handled the same as assignment. + * Examples: + * cout << "this is test number: " + * << test_number; + * + * case: + * Started with case or default. + * Terminated with close brace at level or another case or default. + * Special indenting according to various rules. + * - indent of case label + * - indent of case body + * - how to handle optional braces + * Examples: + * { + * case x: { + * a++; + * break; + * } + * case y: + * b--; + * break; + * default: + * c++; + * break; + * } + * + * Class colon: + * Indent continuation by indent_columns: + * class my_class : + * baseclass1, + * baseclass2 + * { + * + * Return: same as assignemts + * If the return statement is not fully paren'd, then the indent continues at + * the column of the item after the return. If it is paren'd, then the paren + * rules apply. + * return somevalue + + * othervalue; + * + * Type: pretty much the same as assignments + * Examples: + * int foo, + * bar, + * baz; + * + * Any other continued item: + * There shouldn't be anything not covered by the above cases, but any other + * continued item is indented by indent_columns: + * Example: + * somereallycrazylongname.with[lotsoflongstuff]. + * thatreallyannoysme.whenIhavetomaintain[thecode] = 3; + */ + +static void indent_comment(chunk_t *pc, int col); + + +void indent_to_column(chunk_t *pc, int column) + { + if (column < pc->column) + column = pc->column; + + reindent_line(pc, column); + } + +/** + * Changes the initial indent for a line to the given column + * + * @param pc The chunk at the start of the line + * @param column The desired column + */ +void reindent_line(chunk_t *pc, int column) + { + int col_delta; + int min_col; + + LOG_FMT(LINDLINE, "%s: %d] col %d on %.*s [%s] => %d\n", + __func__, pc->orig_line, pc->column, pc->len, pc->str, + get_token_name(pc->type), column); + + if (column == pc->column) + return; + + col_delta = column - pc->column; + pc->column = column; + min_col = pc->column; + + do + { + min_col += pc->len; + pc = chunk_get_next(pc); + + if (pc != NULL) + { + if (chunk_is_comment(pc)) + { + pc->column = pc->orig_col; + + if (pc->column < min_col) + pc->column = min_col + 1; + + LOG_FMT(LINDLINE, "%s: set comment on line %d to col %d (orig %d)\n", + __func__, pc->orig_line, pc->column, pc->orig_col); + } + else + { + pc->column += col_delta; + + if (pc->column < min_col) + pc->column = min_col; + } + } + } + while ((pc != NULL) && (pc->nl_count == 0)); + } + +/** + * Starts a new entry + * + * @param frm The parse frame + * @param pc The chunk causing the push + */ +static void indent_pse_push(struct parse_frame& frm, chunk_t *pc) + { + static int ref = 0; + + /* check the stack depth */ + if (frm.pse_tos < (int)ARRAY_SIZE(frm.pse)) + { + /* Bump up the index and initialize it */ + frm.pse_tos++; + memset(&frm.pse[frm.pse_tos], 0, sizeof(frm.pse[frm.pse_tos])); + + LOG_FMT(LINDPSE, "%4d] OPEN [%d,%s] level=%d\n", + pc->orig_line, frm.pse_tos, get_token_name(pc->type), pc->level); + + frm.pse[frm.pse_tos].type = pc->type; + frm.pse[frm.pse_tos].level = pc->level; + frm.pse[frm.pse_tos].open_line = pc->orig_line; + frm.pse[frm.pse_tos].ref = ++ref; + frm.pse[frm.pse_tos].in_preproc = (pc->flags & PCF_IN_PREPROC) != 0; + } + } + +/** + * Removes the top entry + * + * @param frm The parse frame + * @param pc The chunk causing the push + */ +static void indent_pse_pop(struct parse_frame& frm, chunk_t *pc) + { + /* Bump up the index and initialize it */ + if (frm.pse_tos > 0) + { + if (pc != NULL) + { + LOG_FMT(LINDPSE, "%4d] CLOSE [%d,%s] on %s, started on line %d, level=%d/%d\n", + pc->orig_line, frm.pse_tos, + get_token_name(frm.pse[frm.pse_tos].type), + get_token_name(pc->type), + frm.pse[frm.pse_tos].open_line, + frm.pse[frm.pse_tos].level, + pc->level); + } + else + { + LOG_FMT(LINDPSE, " EOF] CLOSE [%d,%s], started on line %d\n", + frm.pse_tos, get_token_name(frm.pse[frm.pse_tos].type), + frm.pse[frm.pse_tos].open_line); + } + + frm.pse_tos--; + } + } + +static int token_indent(c_token_t type) + { + switch (type) + { + case CT_IF: + case CT_DO: + return 3; + + case CT_FOR: + case CT_ELSE: // wacky, but that's what is wanted + return 4; + + case CT_WHILE: + return 6; + + case CT_SWITCH: + return 7; + + case CT_ELSEIF: + return 8; + + default: + return 0; //cpd.settings[UO_indent_braces].n; + } + } + +/** + * 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_ncnnl(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_ncnnl(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++; + } + } + +/** + * returns true if forward scan reveals only single newlines or comments + * stops when hits code + * false if next thing hit is a closing brace, also if 2 newlines in a row + */ + + +static bool single_line_comment_indent_rule_applies(chunk_t *start) + { + chunk_t *pc = start; + int nl_count = 0; + + if (!chunk_is_single_line_comment(pc)) + return false; + + /* scan forward, if only single newlines and comments before next line of code, we want to apply */ + while ((pc = chunk_get_next(pc)) != NULL) + { + if (chunk_is_newline(pc)) + { + if (nl_count > 0 || pc->nl_count > 1) + return false; + + nl_count++; + } + else + { + nl_count = 0; + + if (!chunk_is_single_line_comment(pc)) + { + /* here we check for things to run into that we wouldn't want to indent the comment for */ + /* for example, non-single line comment, closing brace */ + if (chunk_is_comment(pc) || chunk_is_closing_brace(pc)) + return false; + + return true; + } + } + } + + return false; + } + +/** + * REVISIT: This needs to be re-checked, maybe cleaned up + * + * Indents comments in a (hopefully) smart manner. + * + * There are two type of comments that get indented: + * - stand alone (ie, no tokens on the line before the comment) + * - trailing comments (last token on the line apart from a linefeed) + * + note that a stand-alone comment is a special case of a trailing + * + * The stand alone comments will get indented in one of three ways: + * - column 1: + * + There is an empty line before the comment AND the indent level is 0 + * + The comment was originally in column 1 + * + * - Same column as trailing comment on previous line (ie, aligned) + * + if originally within TBD (3) columns of the previous comment + * + * - syntax indent level + * + doesn't fit in the previous categories + * + * Options modify this behavior: + * - keep original column (don't move the comment, if possible) + * - keep relative column (move out the same amount as first item on line) + * - fix trailing comment in column TBD + * + * @param pc The comment, which is the first item on a line + * @param col The column if this is to be put at indent level + */ +static void indent_comment(chunk_t *pc, int col) + { + chunk_t *nl; + chunk_t *prev; + + LOG_FMT(LCMTIND, "%s: line %d, col %d, level %d: ", __func__, + pc->orig_line, pc->orig_col, pc->level); + + /* force column 1 comment to column 1 if not changing them */ + if ((pc->orig_col == 1) && !cpd.settings[UO_indent_col1_comment].b) + { + LOG_FMT(LCMTIND, "rule 1 - keep in col 1\n"); + pc->column = 1; + return; + } + + nl = chunk_get_prev(pc); + + /* outside of any expression or statement? */ + if (pc->level == 0) + { + if ((nl != NULL) && (nl->nl_count > 1)) + { + LOG_FMT(LCMTIND, "rule 2 - level 0, nl before\n"); + pc->column = 1; + return; + } + } + + prev = chunk_get_prev(nl); + + if (chunk_is_comment(prev) && (nl->nl_count == 1)) + { + int coldiff = prev->orig_col - pc->orig_col; + + if ((coldiff <= 3) && (coldiff >= -3)) + { + pc->column = prev->column; + LOG_FMT(LCMTIND, "rule 3 - prev comment, coldiff = %d, now in %d\n", + coldiff, pc->column); + return; + } + } + + /* check if special single line comment rule applies */ + if (cpd.settings[UO_indent_sing_line_comments].n > 0 && single_line_comment_indent_rule_applies(pc)) + { + pc->column = col + cpd.settings[UO_indent_sing_line_comments].n; + LOG_FMT(LCMTIND, "rule 4 - single line comment indent, now in %d\n", pc->column); + return; + } + + LOG_FMT(LCMTIND, "rule 5 - fall-through, stay in %d\n", col); + + pc->column = col; + } + +/** + * 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); + } + } |