void quick_align_again(void) { chunk_t *pc; chunk_t *tmp; AlignStack as; LOG_FMT(LALAGAIN, "%s:\n", __func__); for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next(pc)) { if ((pc->align.next != NULL) && (pc->flags & PCF_ALIGN_START)) { as.Start(100, 0); as.m_right_align = pc->align.right_align; as.m_star_style = (AlignStack::StarStyle)pc->align.star_style; as.m_amp_style = (AlignStack::StarStyle)pc->align.amp_style; as.m_gap = pc->align.gap; LOG_FMT(LALAGAIN, " [%.*s:%d]", pc->len, pc->str, pc->orig_line); as.Add(pc->align.start); pc->flags |= PCF_WAS_ALIGNED; for (tmp = pc->align.next; tmp != NULL; tmp = tmp->align.next) { tmp->flags |= PCF_WAS_ALIGNED; as.Add(tmp->align.start); LOG_FMT(LALAGAIN, " => [%.*s:%d]", tmp->len, tmp->str, tmp->orig_line); } LOG_FMT(LALAGAIN, "\n"); as.End(); } } }
/** * Aligns an OC message * * @param so the square open of the message * @param span the span value */ static void align_oc_msg_colon(chunk_t *so) { int span = cpd.settings[UO_align_oc_msg_colon_span].n; chunk_t *pc; chunk_t *tmp; AlignStack cas; /* for the colons */ AlignStack nas; /* for the parameter tag */ int level; bool did_line; int lcnt; /* line count with no colon for span */ bool has_colon; nas.Reset(); nas.m_right_align = true; cas.Start(span); level = so->level; pc = chunk_get_next_ncnl(so, CNAV_PREPROC); did_line = false; has_colon = false; lcnt = 0; while ((pc != NULL) && (pc->level > level)) { if (pc->level > (level + 1)) { /* do nothing */ } else if (chunk_is_newline(pc)) { if (!has_colon) { ++lcnt; } did_line = false; has_colon = !has_colon; } else if (!did_line && (lcnt - 1 < span) && (pc->type == CT_OC_COLON)) { has_colon = true; cas.Add(pc); tmp = chunk_get_prev(pc); if ((tmp != NULL) && ((tmp->type == CT_OC_MSG_FUNC) || (tmp->type == CT_OC_MSG_NAME))) { nas.Add(tmp); } did_line = true; } pc = chunk_get_next(pc, CNAV_PREPROC); } nas.End(); cas.End(); }
static chunk_t *align_func_param(chunk_t *start) { AlignStack as; chunk_t *pc = start; as.Start(2, 0); as.m_star_style = (AlignStack::StarStyle)cpd.settings[UO_align_var_def_star_style].n; as.m_amp_style = (AlignStack::StarStyle)cpd.settings[UO_align_var_def_amp_style].n; bool did_this_line = false; int comma_count = 0; int chunk_count = 0; while ((pc = chunk_get_next(pc)) != NULL) { chunk_count++; if (chunk_is_newline(pc)) { did_this_line = false; comma_count = 0; chunk_count = 0; } else if (pc->level <= start->level) { break; } else if (!did_this_line && (pc->flags & PCF_VAR_DEF)) { if (chunk_count > 1) { as.Add(pc); } did_this_line = true; } else if (comma_count > 0) { if (!chunk_is_comment(pc)) { comma_count = 2; break; } } else if (pc->type == CT_COMMA) { comma_count++; } } if (comma_count <= 1) { as.End(); } return(pc); }
/** * Align '<<' (CT_ARITH?) */ static void align_left_shift(void) { chunk_t *pc; chunk_t *start = NULL; AlignStack as; as.Start(2); pc = chunk_get_head(); while (pc != NULL) { if (chunk_is_newline(pc)) { as.NewLines(pc->nl_count); } else if ((start != NULL) && (pc->level < start->level)) { /* A drop in level restarts the aligning */ as.Flush(); start = NULL; } else if ((start != NULL) && (pc->level > start->level)) { /* Ignore any deeper levels when aligning */ } else if (pc->type == CT_SEMICOLON) { /* A semicolon at the same level flushes */ as.Flush(); start = NULL; } else if (chunk_is_str(pc, "<<", 2)) { if (as.m_aligned.Empty()) { /* first one can be anywhere */ as.Add(pc); start = pc; } else if (chunk_is_newline(chunk_get_prev(pc))) { /* subsequent ones must be after a newline */ as.Add(pc); } } pc = chunk_get_next(pc); } as.End(); }
/** * Aligns all function prototypes in the file. */ static void align_func_proto(int span) { chunk_t *pc; bool look_bro = false; AlignStack as; AlignStack as_br; LOG_FMT(LALIGN, "%s\n", __func__); as.Start(span, 0); as.m_gap = cpd.settings[UO_align_func_proto_gap].n; as_br.Start(span, 0); as_br.m_gap = cpd.settings[UO_align_single_line_brace_gap].n; for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next(pc)) { if (chunk_is_newline(pc)) { look_bro = false; as.NewLines(pc->nl_count); as_br.NewLines(pc->nl_count); } else if ((pc->type == CT_FUNC_PROTO) || ((pc->type == CT_FUNC_DEF) && cpd.settings[UO_align_single_line_func].b)) { if ((pc->parent_type == CT_OPERATOR) && cpd.settings[UO_align_on_operator].b) { as.Add(chunk_get_prev_ncnl(pc)); } else { as.Add(pc); } look_bro = (pc->type == CT_FUNC_DEF) && cpd.settings[UO_align_single_line_brace].b; } else if (look_bro && (pc->type == CT_BRACE_OPEN) && (pc->flags & PCF_ONE_LINER)) { as_br.Add(pc); look_bro = false; } } as.End(); as_br.End(); }
/** * Aligns simple typedefs that are contained on a single line each. * This should be called after the typedef target is marked as a type. * * Won't align function typedefs. * * typedef int foo_t; * typedef char bar_t; * typedef const char cc_t; */ static void align_typedefs(int span) { chunk_t *pc; chunk_t *c_type = NULL; chunk_t *c_typedef = NULL; AlignStack as; as.Start(span); as.m_gap = cpd.settings[UO_align_typedef_gap].n; as.m_star_style = (AlignStack::StarStyle)cpd.settings[UO_align_typedef_star_style].n; as.m_amp_style = (AlignStack::StarStyle)cpd.settings[UO_align_typedef_amp_style].n; pc = chunk_get_head(); while (pc != NULL) { if (chunk_is_newline(pc)) { as.NewLines(pc->nl_count); c_typedef = NULL; } else if (c_typedef != NULL) { if (pc->flags & PCF_ANCHOR) { as.Add(pc); c_typedef = NULL; } } else { if (pc->type == CT_TYPEDEF) { LOG_FMT(LALTD, "%s: line %d, col %d\n", __func__, pc->orig_line, pc->orig_col); c_typedef = pc; c_type = NULL; } } pc = chunk_get_next(pc); } as.End(); }
/** * Aligns all function prototypes in the file. */ static void align_oc_msg_spec(int span) { chunk_t *pc; AlignStack as; LOG_FMT(LALIGN, "%s\n", __func__); as.Start(span, 0); for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next(pc)) { if (chunk_is_newline(pc)) { as.NewLines(pc->nl_count); } else if (pc->type == CT_OC_MSG_SPEC) { as.Add(pc); } } as.End(); }
/** * Scan everything at the current level until the close brace and find the * variable def align column. Also aligns bit-colons, but that assumes that * bit-types are the same! But that should always be the case... */ static chunk_t *align_var_def_brace(chunk_t *start, int span, int *p_nl_count) { chunk_t *pc; chunk_t *next; chunk_t *prev; UINT64 align_mask = PCF_IN_FCN_DEF | PCF_VAR_1ST; int myspan = span; int mythresh = 0; int mygap = 0; AlignStack as; /* var/proto/def */ AlignStack as_bc; /* bit-colon */ AlignStack as_at; /* attribute */ AlignStack as_br; /* one-liner brace open */ bool fp_active = cpd.settings[UO_align_mix_var_proto].b; bool fp_look_bro = false; if (start == NULL) { return(NULL); } /* Override the span, if this is a struct/union */ if ((start->parent_type == CT_STRUCT) || (start->parent_type == CT_UNION)) { myspan = cpd.settings[UO_align_var_struct_span].n; mythresh = cpd.settings[UO_align_var_struct_thresh].n; mygap = cpd.settings[UO_align_var_struct_gap].n; } else { mythresh = cpd.settings[UO_align_var_def_thresh].n; mygap = cpd.settings[UO_align_var_def_gap].n; } /* can't be any variable definitions in a "= {" block */ prev = chunk_get_prev_ncnl(start); if ((prev != NULL) && (prev->type == CT_ASSIGN)) { LOG_FMT(LAVDB, "%s: start=%.*s [%s] on line %d (abort due to assign)\n", __func__, start->len, start->str, get_token_name(start->type), start->orig_line); pc = chunk_get_next_type(start, CT_BRACE_CLOSE, start->level); return(chunk_get_next_ncnl(pc)); } LOG_FMT(LAVDB, "%s: start=%.*s [%s] on line %d\n", __func__, start->len, start->str, get_token_name(start->type), start->orig_line); if (!cpd.settings[UO_align_var_def_inline].b) { align_mask |= PCF_VAR_INLINE; } /* Set up the var/proto/def aligner */ as.Start(myspan, mythresh); as.m_gap = mygap; as.m_star_style = (AlignStack::StarStyle)cpd.settings[UO_align_var_def_star_style].n; as.m_amp_style = (AlignStack::StarStyle)cpd.settings[UO_align_var_def_amp_style].n; /* Set up the bit colon aligner */ as_bc.Start(myspan, 0); as_bc.m_gap = cpd.settings[UO_align_var_def_colon_gap].n; as_at.Start(myspan, 0); /* Set up the brace open aligner */ as_br.Start(myspan, mythresh); as_br.m_gap = cpd.settings[UO_align_single_line_brace_gap].n; bool did_this_line = false; pc = chunk_get_next(start); while ((pc != NULL) && ((pc->level >= start->level) || (pc->level == 0))) { if (chunk_is_comment(pc)) { if (pc->nl_count > 0) { as.NewLines(pc->nl_count); as_bc.NewLines(pc->nl_count); as_at.NewLines(pc->nl_count); as_br.NewLines(pc->nl_count); } pc = chunk_get_next(pc); continue; } if (fp_active) { if ((pc->type == CT_FUNC_PROTO) || ((pc->type == CT_FUNC_DEF) && cpd.settings[UO_align_single_line_func].b)) { LOG_FMT(LAVDB, " add=[%.*s] line=%d col=%d level=%d\n", pc->len, pc->str, pc->orig_line, pc->orig_col, pc->level); as.Add(pc); fp_look_bro = (pc->type == CT_FUNC_DEF) && cpd.settings[UO_align_single_line_brace].b; } else if (fp_look_bro && (pc->type == CT_BRACE_OPEN) && (pc->flags & PCF_ONE_LINER)) { as_br.Add(pc); fp_look_bro = false; } } /* process nested braces */ if (pc->type == CT_BRACE_OPEN) { int sub_nl_count = 0; pc = align_var_def_brace(pc, span, &sub_nl_count); if (sub_nl_count > 0) { fp_look_bro = false; did_this_line = false; as.NewLines(sub_nl_count); as_bc.NewLines(sub_nl_count); as_at.NewLines(sub_nl_count); as_br.NewLines(sub_nl_count); if (p_nl_count != NULL) { *p_nl_count += sub_nl_count; } } continue; } /* Done with this brace set? */ if (pc->type == CT_BRACE_CLOSE) { pc = chunk_get_next(pc); break; } if (chunk_is_newline(pc)) { fp_look_bro = false; did_this_line = false; as.NewLines(pc->nl_count); as_bc.NewLines(pc->nl_count); as_at.NewLines(pc->nl_count); as_br.NewLines(pc->nl_count); if (p_nl_count != NULL) { *p_nl_count += pc->nl_count; } } /* don't align stuff inside parens/squares/angles */ if (pc->level > pc->brace_level) { pc = chunk_get_next(pc); continue; } /* If this is a variable def, update the max_col */ if ((pc->type != CT_FUNC_CLASS) && ((pc->flags & align_mask) == PCF_VAR_1ST) && ((pc->level == (start->level + 1)) || (pc->level == 0))) { if (!did_this_line) { LOG_FMT(LAVDB, " add=[%.*s] line=%d col=%d level=%d\n", pc->len, pc->str, pc->orig_line, pc->orig_col, pc->level); as.Add(pc); if (cpd.settings[UO_align_var_def_colon].b) { next = chunk_get_next_nc(pc); if (next->type == CT_BIT_COLON) { as_bc.Add(next); } } if (cpd.settings[UO_align_var_def_attribute].b) { next = pc; while ((next = chunk_get_next_nc(next)) != NULL) { if (next->type == CT_ATTRIBUTE) { as_at.Add(next); break; } if ((next->type == CT_SEMICOLON) || chunk_is_newline(next)) { break; } } } } did_this_line = true; } else if (pc->type == CT_BIT_COLON) { if (!did_this_line) { as_bc.Add(pc); did_this_line = true; } } pc = chunk_get_next(pc); } as.End(); as_bc.End(); as_at.End(); as_br.End(); return(pc); }
/** * Aligns all assignment operators on the same level as first, starting with * first. * * For variable definitions, only consider the '=' for the first variable. * Otherwise, only look at the first '=' on the line. */ chunk_t *align_assign(chunk_t *first, int span, int thresh) { int my_level; chunk_t *pc; int tmp; int var_def_cnt = 0; int equ_count = 0; if (first == NULL) { return(NULL); } my_level = first->level; if (span <= 0) { return(chunk_get_next(first)); } LOG_FMT(LALASS, "%s[%d]: checking %.*s on line %d - span=%d thresh=%d\n", __func__, my_level, first->len, first->str, first->orig_line, span, thresh); AlignStack as; // regular assigns AlignStack vdas; // variable def assigns as.Start(span, thresh); as.m_right_align = true; vdas.Start(span, thresh); vdas.m_right_align = true; pc = first; while ((pc != NULL) && ((pc->level >= my_level) || (pc->level == 0))) { /* Don't check inside PAREN or SQUARE groups */ if ((pc->type == CT_SPAREN_OPEN) || (pc->type == CT_FPAREN_OPEN) || (pc->type == CT_SQUARE_OPEN) || (pc->type == CT_PAREN_OPEN)) { tmp = pc->orig_line; pc = chunk_skip_to_match(pc); if (pc != NULL) { as.NewLines(pc->orig_line - tmp); vdas.NewLines(pc->orig_line - tmp); } continue; } /* Recurse if a brace set is found */ if ((pc->type == CT_BRACE_OPEN) || (pc->type == CT_VBRACE_OPEN)) { int myspan; int mythresh; tmp = pc->orig_line; if (pc->parent_type == CT_ENUM) { myspan = cpd.settings[UO_align_enum_equ_span].n; mythresh = cpd.settings[UO_align_enum_equ_thresh].n; } else { myspan = cpd.settings[UO_align_assign_span].n; mythresh = cpd.settings[UO_align_assign_thresh].n; } pc = align_assign(chunk_get_next_ncnl(pc), myspan, mythresh); if (pc != NULL) { /* do a rough count of the number of lines just spanned */ as.NewLines(pc->orig_line - tmp); vdas.NewLines(pc->orig_line - tmp); } continue; } if (chunk_is_newline(pc)) { as.NewLines(pc->nl_count); vdas.NewLines(pc->nl_count); var_def_cnt = 0; equ_count = 0; } else if ((pc->flags & PCF_VAR_DEF) != 0) { var_def_cnt++; } else if (var_def_cnt > 1) { /* we hit the second variable def - don't look for assigns */ } else if ((equ_count == 0) && (pc->type == CT_ASSIGN)) { //fprintf(stderr, "%s: ** %s level=%d line=%d col=%d prev=%d count=%d\n", // __func__, pc->str, pc->level, pc->orig_line, pc->orig_col, prev_equ_type, // equ_count); equ_count++; if (var_def_cnt != 0) { vdas.Add(pc); } else { as.Add(pc); } } pc = chunk_get_next(pc); } as.End(); vdas.End(); if (pc != NULL) { LOG_FMT(LALASS, "%s: done on %.*s on line %d\n", __func__, pc->len, pc->str, pc->orig_line); } else { LOG_FMT(LALASS, "%s: done on NULL\n", __func__); } return(pc); }
/** * Scans the whole file for #defines. Aligns all within X lines of each other */ void align_preprocessor(void) { chunk_t *pc; AlignStack as; // value macros AlignStack asf; // function macros AlignStack *cur_as = &as; as.Start(cpd.settings[UO_align_pp_define_span].n); as.m_gap = cpd.settings[UO_align_pp_define_gap].n; asf.Start(cpd.settings[UO_align_pp_define_span].n); asf.m_gap = cpd.settings[UO_align_pp_define_gap].n; pc = chunk_get_head(); while (pc != NULL) { /* Note: not counting back-slash newline combos */ if (pc->type == CT_NEWLINE) { as.NewLines(pc->nl_count); asf.NewLines(pc->nl_count); } /* If we aren't on a 'define', then skip to the next non-comment */ if (pc->type != CT_PP_DEFINE) { pc = chunk_get_next_nc(pc); continue; } /* step past the 'define' */ pc = chunk_get_next_nc(pc); if (pc == NULL) { break; } LOG_FMT(LALPP, "%s: define (%.*s) on line %d col %d\n", __func__, pc->len, pc->str, pc->orig_line, pc->orig_col); cur_as = &as; if (pc->type == CT_MACRO_FUNC) { cur_as = &asf; /* Skip to the close paren */ pc = chunk_get_next_nc(pc); // point to open ( pc = chunk_get_next_type(pc, CT_FPAREN_CLOSE, pc->level); LOG_FMT(LALPP, "%s: jumped to (%.*s) on line %d col %d\n", __func__, pc->len, pc->str, pc->orig_line, pc->orig_col); } /* step to the value past the close paren or the macro name */ pc = chunk_get_next(pc); if (pc == NULL) { break; } /* don't align anything if the first line ends with a newline before * a value is given */ if (!chunk_is_newline(pc)) { LOG_FMT(LALPP, "%s: align on '%.*s', line %d col %d\n", __func__, pc->len, pc->str, pc->orig_line, pc->orig_col); cur_as->Add(pc); } } as.End(); asf.End(); }
/** * Aligns OC declarations on the colon * -(void) doSomething: (NSString*) param1 * with: (NSString*) param2 */ static void align_oc_decl_colon(void) { chunk_t *pc = chunk_get_head(); chunk_t *tmp; chunk_t *tmp2; AlignStack cas; /* for the colons */ AlignStack nas; /* for the parameter label */ int level; bool did_line; cas.Start(4); nas.Start(4); nas.m_right_align = true; while (pc != NULL) { if (pc->type != CT_OC_SCOPE) { pc = chunk_get_next(pc); continue; } nas.Reset(); cas.Reset(); level = pc->level; pc = chunk_get_next_ncnl(pc, CNAV_PREPROC); did_line = false; while ((pc != NULL) && (pc->level >= level)) { /* The decl ends with an open brace or semicolon */ if ((pc->type == CT_BRACE_OPEN) || chunk_is_semicolon(pc)) { break; } if (chunk_is_newline(pc)) { nas.NewLines(pc->nl_count); cas.NewLines(pc->nl_count); did_line = false; } else if (!did_line && (pc->type == CT_OC_COLON)) { cas.Add(pc); tmp = chunk_get_prev(pc, CNAV_PREPROC); tmp2 = chunk_get_prev_ncnl(tmp, CNAV_PREPROC); /* Check for an un-labeled parameter */ if ((tmp != NULL) && (tmp2 != NULL) && ((tmp->type == CT_WORD) || (tmp->type == CT_TYPE) || (tmp->type == CT_OC_MSG_DECL)) && ((tmp2->type == CT_WORD) || (tmp2->type == CT_TYPE) || (tmp2->type == CT_PAREN_CLOSE))) { nas.Add(tmp); } did_line = true; } pc = chunk_get_next(pc, CNAV_PREPROC); } nas.End(); cas.End(); } }
chunk_t *align_func_param(chunk_t *start) { LOG_FUNC_ENTRY(); // Defaults, if the align_func_params = true size_t myspan = 2; size_t mythresh = 0; size_t mygap = 0; // Override, if the align_func_params_span > 0 if (options::align_func_params_span() > 0) { myspan = options::align_func_params_span(); mythresh = options::align_func_params_thresh(); mygap = options::align_func_params_gap(); } AlignStack as; as.Start(myspan, mythresh); as.m_gap = mygap; as.m_star_style = static_cast<AlignStack::StarStyle>(options::align_var_def_star_style()); as.m_amp_style = static_cast<AlignStack::StarStyle>(options::align_var_def_amp_style()); bool did_this_line = false; size_t comma_count = 0; size_t chunk_count = 0; chunk_t *pc = start; while ((pc = chunk_get_next(pc)) != nullptr) { chunk_count++; if (chunk_is_newline(pc)) { did_this_line = false; comma_count = 0; chunk_count = 0; as.NewLines(pc->nl_count); } else if (pc->level <= start->level) { break; } else if (!did_this_line && (pc->flags & PCF_VAR_DEF)) { if (chunk_count > 1) { as.Add(pc); } did_this_line = true; } else if (comma_count > 0) { if (!chunk_is_comment(pc)) { comma_count = 2; break; } } else if (chunk_is_token(pc, CT_COMMA)) { chunk_t *tmp_prev = chunk_get_prev_nc(pc); if (!chunk_is_newline(tmp_prev)) // don't count leading commas { comma_count++; } } } if (comma_count <= 1) { as.End(); } return(pc); } // align_func_param