/** * Scans between two parens and adds additional parens if needed. * This function is recursive. If it hits another open paren, it'll call itself * with the new bounds. * * Adds optional parens in an IF or SWITCH conditional statement. * * This basically just checks for a CT_COMPARE that isn't surrounded by parens. * The edges for the compare are the open, close and any CT_BOOL tokens. * * This only handleds VERY simple patterns: * (!a && b) => (!a && b) -- no change * (a && b == 1) => (a && (b == 1)) * (a == 1 || b > 2) => ((a == 1) || (b > 2)) * * FIXME: we really should bail if we transition between a preprocessor and * a non-preprocessor */ static void check_bool_parens(chunk_t *popen, chunk_t *pclose, int nest) { chunk_t *pc; chunk_t *ref = popen; chunk_t *next; bool hit_compare = false; LOG_FMT(LPARADD, "%s(%d): popen on %d, col %d, pclose on %d, col %d, level=%d\n", __func__, nest, popen->orig_line, popen->orig_col, pclose->orig_line, pclose->orig_col, popen->level); pc = popen; while (((pc = chunk_get_next_ncnl(pc)) != NULL) && (pc != pclose)) { if ((pc->type == CT_BOOL) || (pc->type == CT_QUESTION) || (pc->type == CT_COND_COLON)) { LOG_FMT(LPARADD2, " -- %s [%.*s] at line %d col %d, level %d\n", get_token_name(pc->type), pc->len, pc->str, pc->orig_line, pc->orig_col, pc->level); if (hit_compare) { hit_compare = false; add_parens_between(ref, pc); } ref = pc; } else if (pc->type == CT_COMPARE) { LOG_FMT(LPARADD2, " -- compare [%.*s] at line %d col %d, level %d\n", pc->len, pc->str, pc->orig_line, pc->orig_col, pc->level); hit_compare = true; } else if (chunk_is_paren_open(pc)) { next = chunk_get_next_type(pc, (c_token_t)(pc->type + 1), pc->level); if (next != NULL) { check_bool_parens(pc, next, nest + 1); pc = next; } } else if ((pc->type == CT_BRACE_OPEN) || (pc->type == CT_SQUARE_OPEN) || (pc->type == CT_ANGLE_OPEN)) { /* Skip [], {}, and <> */ pc = chunk_get_next_type(pc, (c_token_t)(pc->type + 1), pc->level); } } if (hit_compare && (ref != popen)) { add_parens_between(ref, pclose); } }
/** * Scans between two parens and adds additional parens if needed. * This function is recursive. If it hits another open paren, it'll call itself * with the new bounds. * * Adds optional parens in an IF or SWITCH conditional statement. * * This basically just checks for a CT_COMPARE that isn't surrounded by parens. * The edges for the compare are the open, close and any CT_BOOL tokens. * * This only handles VERY simple patterns: * (!a && b) => (!a && b) -- no change * (a && b == 1) => (a && (b == 1)) * (a == 1 || b > 2) => ((a == 1) || (b > 2)) * * FIXME: we really should bail if we transition between a preprocessor and * a non-preprocessor */ static void check_bool_parens(chunk_t *popen, chunk_t *pclose, int nest) { LOG_FUNC_ENTRY(); chunk_t *pc; chunk_t *ref = popen; chunk_t *next; bool hit_compare = false; LOG_FMT(LPARADD, "%s(%d): popen on %lu, col %lu, pclose on %lu, col %lu, level=%lu\n", __func__, nest, popen->orig_line, popen->orig_col, pclose->orig_line, pclose->orig_col, popen->level); pc = popen; while (((pc = chunk_get_next_ncnl(pc)) != NULL) && (pc != pclose)) { if (pc->flags & PCF_IN_PREPROC) { LOG_FMT(LPARADD2, " -- bail on PP %s [%s] at line %lu col %lu, level %lu\n", get_token_name(pc->type), pc->text(), pc->orig_line, pc->orig_col, pc->level); return; } if ((pc->type == CT_BOOL) || (pc->type == CT_QUESTION) || (pc->type == CT_COND_COLON) || (pc->type == CT_COMMA)) { LOG_FMT(LPARADD2, " -- %s [%s] at line %lu col %lu, level %lu\n", get_token_name(pc->type), pc->text(), pc->orig_line, pc->orig_col, pc->level); if (hit_compare) { hit_compare = false; add_parens_between(ref, pc); } ref = pc; } else if (pc->type == CT_COMPARE) { LOG_FMT(LPARADD2, " -- compare [%s] at line %lu col %lu, level %lu\n", pc->text(), pc->orig_line, pc->orig_col, pc->level); hit_compare = true; } else if (chunk_is_paren_open(pc)) { next = chunk_skip_to_match(pc); if (next != NULL) { check_bool_parens(pc, next, nest + 1); pc = next; } } else if ((pc->type == CT_BRACE_OPEN) || (pc->type == CT_SQUARE_OPEN) || (pc->type == CT_ANGLE_OPEN)) { /* Skip [], {}, and <> */ pc = chunk_skip_to_match(pc); } } if (hit_compare && (ref != popen)) { add_parens_between(ref, pclose); } } // check_bool_parens