/* * the value of after determines: * true: insert_vbrace_close_after(pc, frm) * false: insert_vbrace_open_before(pc, frm) */ static chunk_t *insert_vbrace(chunk_t *pc, bool after, struct parse_frame *frm) { LOG_FUNC_ENTRY(); chunk_t chunk; chunk_t *rv; chunk_t *ref; chunk.orig_line = pc->orig_line; chunk.parent_type = frm->pse[frm->pse_tos].type; chunk.level = frm->level; chunk.brace_level = frm->brace_level; chunk.flags = pc->flags & PCF_COPY_FLAGS; chunk.str = ""; if (after) { chunk.type = CT_VBRACE_CLOSE; rv = chunk_add_after(&chunk, pc); } else { ref = chunk_get_prev(pc); if ((ref->flags & PCF_IN_PREPROC) == 0) { chunk.flags &= ~PCF_IN_PREPROC; } while (chunk_is_newline(ref) || chunk_is_comment(ref)) { ref->level++; ref->brace_level++; ref = chunk_get_prev(ref); } /* Don't back into a preprocessor */ if (((pc->flags & PCF_IN_PREPROC) == 0) && (ref->flags & PCF_IN_PREPROC)) { if (ref->type == CT_PREPROC_BODY) { do { ref = chunk_get_prev(ref); } while ((ref != NULL) && (ref->flags & PCF_IN_PREPROC)); } else { ref = chunk_get_next(ref); } } chunk.orig_line = ref->orig_line; chunk.column = ref->column + ref->len() + 1; chunk.type = CT_VBRACE_OPEN; rv = chunk_add_after(&chunk, ref); } return(rv); } // insert_vbrace
static void split_off_angle_close(chunk_t *pc) { chunk_t nc; nc = *pc; const chunk_tag_t *ct; ct = find_punctuator(pc->str + 1, cpd.lang_flags); if (ct == NULL) { return; } pc->len = 1; pc->orig_col_end = pc->orig_col + 1; pc->type = CT_ANGLE_CLOSE; nc.type = ct->type; nc.str++; nc.len--; nc.orig_col++; nc.column++; chunk_add_after(&nc, pc); }
chunk_t *pawn_add_vsemi_after(chunk_t *pc) { if ((pc->type == CT_VSEMICOLON) || (pc->type == CT_SEMICOLON)) { return(pc); } chunk_t *next = chunk_get_next_nc(pc); if ((next != NULL) && ((next->type == CT_VSEMICOLON) || (next->type == CT_SEMICOLON))) { return(pc); } chunk_t chunk; chunk = *pc; chunk.type = CT_VSEMICOLON; chunk.str = cpd.settings[UO_mod_pawn_semicolon].b ? ";" : ""; chunk.column += pc->len(); chunk.parent_type = CT_NONE; LOG_FMT(LPVSEMI, "%s: Added VSEMI on line %d, prev='%s' [%s]\n", __func__, pc->orig_line, pc->str.c_str(), get_token_name(pc->type)); return(chunk_add_after(&chunk, pc)); }
/** * Adds a comment after the ref chunk * Returns the added chunk or NULL */ chunk_t *insert_comment_after(chunk_t *ref, c_token_t cmt_type, const unc_text &cmt_text) { LOG_FUNC_ENTRY(); chunk_t new_cmt = *ref; new_cmt.prev = NULL; new_cmt.next = NULL; new_cmt.flags = (ref->flags & PCF_COPY_FLAGS); new_cmt.type = cmt_type; new_cmt.str.clear(); if (cmt_type == CT_COMMENT_CPP) { new_cmt.str.append("// "); new_cmt.str.append(cmt_text); } else { if (ref->type == CT_PP_ELSE) { // make test c/ 02501 stable new_cmt.str.append(" "); } new_cmt.str.append("/* "); new_cmt.str.append(cmt_text); new_cmt.str.append(" */"); } /* TODO: expand comment type to cover other comment styles? */ new_cmt.column = ref->column + ref->len() + 1; new_cmt.orig_col = new_cmt.column; return(chunk_add_after(&new_cmt, ref)); }
/** * Add an open paren after first and add a close paren before the last */ static void add_parens_between(chunk_t *first, chunk_t *last) { chunk_t pc; chunk_t *first_n; chunk_t *last_p; chunk_t *tmp; LOG_FMT(LPARADD, "%s: line %d between %.*s [lvl=%d] and %.*s [lvl=%d]\n", __func__, first->orig_line, first->len, first->str, first->level, last->len, last->str, last->level); /* Don't do anything if we have a bad sequence, ie "&& )" */ first_n = chunk_get_next_ncnl(first); if (first_n == last) { return; } memset(&pc, 0, sizeof(pc)); pc.type = CT_PAREN_OPEN; pc.str = "("; pc.len = 1; pc.flags = first_n->flags & PCF_COPY_FLAGS; pc.level = first_n->level; pc.pp_level = first_n->pp_level; pc.brace_level = first_n->brace_level; chunk_add_before(&pc, first_n); last_p = chunk_get_prev_ncnl(last, CNAV_PREPROC); pc.type = CT_PAREN_CLOSE; pc.str = ")"; pc.flags = last_p->flags & PCF_COPY_FLAGS; pc.level = last_p->level; pc.pp_level = last_p->pp_level; pc.brace_level = last_p->brace_level; chunk_add_after(&pc, last_p); for (tmp = first_n; tmp != last_p; tmp = chunk_get_next_ncnl(tmp)) { tmp->level++; } last_p->level++; }
void space_add_after(chunk_t *pc, int count) { if (count <= 0) { return; } chunk_t *next = chunk_get_next(pc); /* don't add at the end of the file or before a newline */ if ((next == NULL) || chunk_is_newline(next)) { return; } /* Limit to 16 spaces */ if (count > 16) { count = 16; } /* Two CT_SPACE in a row -- use the max of the two */ if (next->type == CT_SPACE) { if (next->len() < count) { while (next->len() < count) { next->str.append(' '); } } return; } chunk_t sp; sp.flags = pc->flags & PCF_COPY_FLAGS; sp.type = CT_SPACE; sp.str = " "; // 16 spaces sp.str.resize(count); sp.level = pc->level; sp.brace_level = pc->brace_level; sp.pp_level = pc->pp_level; sp.column = pc->column + pc->len(); sp.orig_line = pc->orig_line; chunk_add_after(&sp, pc); }
static void add_parens_between(chunk_t *first, chunk_t *last) { LOG_FUNC_ENTRY(); LOG_FMT(LPARADD, "%s: line %zu between %s [lvl=%zu] and %s [lvl=%zu]\n", __func__, first->orig_line, first->text(), first->level, last->text(), last->level); // Don't do anything if we have a bad sequence, ie "&& )" chunk_t *first_n = chunk_get_next_ncnl(first); if (first_n == last) { return; } chunk_t pc; pc.type = CT_PAREN_OPEN; pc.str = "("; pc.flags = first_n->flags & PCF_COPY_FLAGS; pc.level = first_n->level; pc.pp_level = first_n->pp_level; pc.brace_level = first_n->brace_level; chunk_add_before(&pc, first_n); chunk_t *last_p = chunk_get_prev_ncnl(last, scope_e::PREPROC); pc.type = CT_PAREN_CLOSE; pc.str = ")"; pc.flags = last_p->flags & PCF_COPY_FLAGS; pc.level = last_p->level; pc.pp_level = last_p->pp_level; pc.brace_level = last_p->brace_level; chunk_add_after(&pc, last_p); for (chunk_t *tmp = first_n; tmp != last_p; tmp = chunk_get_next_ncnl(tmp)) { tmp->level++; } last_p->level++; } // add_parens_between
/** * Adds a comment after the ref chunk * Returns the added chunk or NULL */ chunk_t *insert_comment_after(chunk_t *ref, c_token_t cmt_type, int cmt_len, const char *cmt_text) { chunk_t new_cmt; char *txt; int txt_len; if (cmt_len <= 0) { cmt_len = strlen(cmt_text); } txt_len = cmt_len + 8; /* 8 is big enough for all types */ memcpy(&new_cmt, ref, sizeof(new_cmt)); /* [i_a] clone levels, etc. */ new_cmt.prev = NULL; new_cmt.next = NULL; new_cmt.flags = (ref->flags & PCF_COPY_FLAGS) | PCF_OWN_STR; new_cmt.type = cmt_type; /* allocate memory for the string */ txt = new char[txt_len + 1]; /* + 1 for '\0' */ if (txt == NULL) { return(NULL); } new_cmt.str = txt; if (cmt_type == CT_COMMENT_CPP) { new_cmt.len = snprintf(txt, txt_len, "// %.*s", cmt_len, cmt_text); } else { new_cmt.len = snprintf(txt, txt_len, "/* %.*s */", cmt_len, cmt_text); } /* TODO: expand comment type to cover other comment styles? */ new_cmt.column = ref->column + ref->len + 1; new_cmt.orig_col = new_cmt.column; return(chunk_add_after(&new_cmt, ref)); }
static void split_off_angle_close(chunk_t *pc) { chunk_t nc; nc = *pc; const chunk_tag_t *ct; ct = find_punctuator(pc->text() + 1, cpd.lang_flags); if (ct == NULL) { return; } pc->str.resize(1); pc->orig_col_end = pc->orig_col + 1; set_chunk_type(pc, CT_ANGLE_CLOSE); nc.type = ct->type; nc.str.pop_front(); nc.orig_col++; nc.column++; chunk_add_after(&nc, pc); }
void tokenize_cleanup(void) { LOG_FUNC_ENTRY(); chunk_t *pc = chunk_get_head(); chunk_t *prev = NULL; chunk_t *next; chunk_t *tmp; chunk_t *tmp2; bool in_type_cast = false; cpd.unc_stage = US_TOKENIZE_CLEANUP; /* Since [] is expected to be TSQUARE for the 'operator', we need to make * this change in the first pass. */ for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next_ncnl(pc)) { if (pc->type == CT_SQUARE_OPEN) { next = chunk_get_next_ncnl(pc); if (chunk_is_token(next, CT_SQUARE_CLOSE)) { /* Change '[' + ']' into '[]' */ set_chunk_type(pc, CT_TSQUARE); pc->str = "[]"; // bug # 664 // The original orig_col_end of CT_SQUARE_CLOSE is stored at orig_col_end of CT_TSQUARE. // pc->orig_col_end += 1; pc->orig_col_end = next->orig_col_end; chunk_del(next); } } if ((pc->type == CT_SEMICOLON) && (pc->flags & PCF_IN_PREPROC) && !chunk_get_next_ncnl(pc, CNAV_PREPROC)) { LOG_FMT(LNOTE, "%s:%d Detected a macro that ends with a semicolon. Possible failures if used.\n", cpd.filename, pc->orig_line); } } /* We can handle everything else in the second pass */ pc = chunk_get_head(); next = chunk_get_next_ncnl(pc); while ((pc != NULL) && (next != NULL)) { if ((pc->type == CT_DOT) && (cpd.lang_flags & LANG_ALLC)) { set_chunk_type(pc, CT_MEMBER); } if ((pc->type == CT_NULLCOND) && (cpd.lang_flags & LANG_CS)) { set_chunk_type(pc, CT_MEMBER); } /* Determine the version stuff (D only) */ if (pc->type == CT_D_VERSION) { if (next->type == CT_PAREN_OPEN) { set_chunk_type(pc, CT_D_VERSION_IF); } else { if (next->type != CT_ASSIGN) { LOG_FMT(LERR, "%s:%d %s: version: Unexpected token %s\n", cpd.filename, pc->orig_line, __func__, get_token_name(next->type)); cpd.error_count++; } set_chunk_type(pc, CT_WORD); } } /* Determine the scope stuff (D only) */ if (pc->type == CT_D_SCOPE) { if (next->type == CT_PAREN_OPEN) { set_chunk_type(pc, CT_D_SCOPE_IF); } else { set_chunk_type(pc, CT_TYPE); } } /** * Change CT_BASE before CT_PAREN_OPEN to CT_WORD. * public myclass() : base() { * } */ if ((pc->type == CT_BASE) && (next->type == CT_PAREN_OPEN)) { set_chunk_type(pc, CT_WORD); } if ((pc->type == CT_ENUM) && (next->type == CT_CLASS)) { set_chunk_type(next, CT_ENUM_CLASS); } /** * Change CT_WORD after CT_ENUM, CT_UNION, or CT_STRUCT to CT_TYPE * Change CT_WORD before CT_WORD to CT_TYPE */ if (next->type == CT_WORD) { if ((pc->type == CT_ENUM) || (pc->type == CT_ENUM_CLASS) || (pc->type == CT_UNION) || (pc->type == CT_STRUCT)) { set_chunk_type(next, CT_TYPE); } if (pc->type == CT_WORD) { set_chunk_type(pc, CT_TYPE); } } /* change extern to qualifier if extern isn't followed by a string or * an open paren */ if (pc->type == CT_EXTERN) { if (next->type == CT_STRING) { /* Probably 'extern "C"' */ } else if (next->type == CT_PAREN_OPEN) { /* Probably 'extern (C)' */ } else { /* Something else followed by a open brace */ tmp = chunk_get_next_ncnl(next); if ((tmp == NULL) || (tmp->type != CT_BRACE_OPEN)) { set_chunk_type(pc, CT_QUALIFIER); } } } /** * Change CT_STAR to CT_PTR_TYPE if preceded by CT_TYPE, * CT_QUALIFIER, or CT_PTR_TYPE. */ if ((next->type == CT_STAR) && ((pc->type == CT_TYPE) || (pc->type == CT_QUALIFIER) || (pc->type == CT_PTR_TYPE))) { set_chunk_type(next, CT_PTR_TYPE); } if ((pc->type == CT_TYPE_CAST) && (next->type == CT_ANGLE_OPEN)) { set_chunk_parent(next, CT_TYPE_CAST); in_type_cast = true; } /** * Change angle open/close to CT_COMPARE, if not a template thingy */ if ((pc->type == CT_ANGLE_OPEN) && (pc->parent_type != CT_TYPE_CAST)) { /* pretty much all languages except C use <> for something other than * comparisons. "#include<xxx>" is handled elsewhere. */ if (cpd.lang_flags & (LANG_CPP | LANG_CS | LANG_JAVA | LANG_VALA | LANG_OC)) { // bug #663 check_template(pc); } else { /* convert CT_ANGLE_OPEN to CT_COMPARE */ set_chunk_type(pc, CT_COMPARE); } } if ((pc->type == CT_ANGLE_CLOSE) && (pc->parent_type != CT_TEMPLATE)) { if (in_type_cast) { in_type_cast = false; set_chunk_parent(pc, CT_TYPE_CAST); } else { next = handle_double_angle_close(pc); } } if (cpd.lang_flags & LANG_D) { /* Check for the D string concat symbol '~' */ if ((pc->type == CT_INV) && ((prev->type == CT_STRING) || (prev->type == CT_WORD) || (next->type == CT_STRING))) { set_chunk_type(pc, CT_CONCAT); } /* Check for the D template symbol '!' (word + '!' + word or '(') */ if ((pc->type == CT_NOT) && (prev->type == CT_WORD) && ((next->type == CT_PAREN_OPEN) || (next->type == CT_WORD) || (next->type == CT_TYPE))) { set_chunk_type(pc, CT_D_TEMPLATE); } /* handle "version(unittest) { }" vs "unittest { }" */ if (prev && (pc->type == CT_UNITTEST) && (prev->type == CT_PAREN_OPEN)) { set_chunk_type(pc, CT_WORD); } /* handle 'static if' and merge the tokens */ if (prev && (pc->type == CT_IF) && chunk_is_str(prev, "static", 6)) { /* delete PREV and merge with IF */ pc->str.insert(0, ' '); pc->str.insert(0, prev->str); pc->orig_col = prev->orig_col; pc->orig_line = prev->orig_line; chunk_t *to_be_deleted = prev; prev = chunk_get_prev_ncnl(prev); chunk_del(to_be_deleted); } } if (cpd.lang_flags & LANG_CPP) { /* Change Word before '::' into a type */ if ((pc->type == CT_WORD) && (next->type == CT_DC_MEMBER)) { set_chunk_type(pc, CT_TYPE); } } /* Change get/set to CT_WORD if not followed by a brace open */ if ((pc->type == CT_GETSET) && (next->type != CT_BRACE_OPEN)) { if ((next->type == CT_SEMICOLON) && ((prev->type == CT_BRACE_CLOSE) || (prev->type == CT_BRACE_OPEN) || (prev->type == CT_SEMICOLON))) { set_chunk_type(pc, CT_GETSET_EMPTY); set_chunk_parent(next, CT_GETSET); } else { set_chunk_type(pc, CT_WORD); } } /* Interface is only a keyword in MS land if followed by 'class' or 'struct' * likewise, 'class' may be a member name in Java. */ if ((pc->type == CT_CLASS) && !CharTable::IsKw1(next->str[0])) { set_chunk_type(pc, CT_WORD); } /* Change item after operator (>=, ==, etc) to a CT_OPERATOR_VAL * Usually the next item is part of the operator. * In a few cases the next few tokens are part of it: * operator + - common case * operator >> - need to combine '>' and '>' * operator () * operator [] - already converted to TSQUARE * operator new [] * operator delete [] * operator const char * * operator const B& * operator std::allocator<U> * * In all cases except the last, this will put the entire operator value * in one chunk. */ if (pc->type == CT_OPERATOR) { tmp2 = chunk_get_next(next); /* Handle special case of () operator -- [] already handled */ if (next->type == CT_PAREN_OPEN) { tmp = chunk_get_next(next); if ((tmp != NULL) && (tmp->type == CT_PAREN_CLOSE)) { next->str = "()"; set_chunk_type(next, CT_OPERATOR_VAL); chunk_del(tmp); next->orig_col_end += 1; } } else if ((next->type == CT_ANGLE_CLOSE) && tmp2 && (tmp2->type == CT_ANGLE_CLOSE) && (tmp2->orig_col == next->orig_col_end)) { next->str.append('>'); next->orig_col_end++; set_chunk_type(next, CT_OPERATOR_VAL); chunk_del(tmp2); } else if (next->flags & PCF_PUNCTUATOR) { set_chunk_type(next, CT_OPERATOR_VAL); } else { set_chunk_type(next, CT_TYPE); /* Replace next with a collection of all tokens that are part of * the type. */ tmp2 = next; while ((tmp = chunk_get_next(tmp2)) != NULL) { if ((tmp->type != CT_WORD) && (tmp->type != CT_TYPE) && (tmp->type != CT_QUALIFIER) && (tmp->type != CT_STAR) && (tmp->type != CT_CARET) && (tmp->type != CT_AMP) && (tmp->type != CT_TSQUARE)) { break; } /* Change tmp into a type so that space_needed() works right */ make_type(tmp); int num_sp = space_needed(tmp2, tmp); while (num_sp-- > 0) { next->str.append(" "); } next->str.append(tmp->str); tmp2 = tmp; } while ((tmp2 = chunk_get_next(next)) != tmp) { chunk_del(tmp2); } set_chunk_type(next, CT_OPERATOR_VAL); next->orig_col_end = next->orig_col + next->len(); } set_chunk_parent(next, CT_OPERATOR); LOG_FMT(LOPERATOR, "%s: %d:%d operator '%s'\n", __func__, pc->orig_line, pc->orig_col, next->text()); } /* Change private, public, protected into either a qualifier or label */ if (pc->type == CT_PRIVATE) { /* Handle Qt slots - maybe should just check for a CT_WORD? */ if (chunk_is_str(next, "slots", 5) || chunk_is_str(next, "Q_SLOTS", 7)) { tmp = chunk_get_next(next); if ((tmp != NULL) && (tmp->type == CT_COLON)) { next = tmp; } } if (next->type == CT_COLON) { set_chunk_type(next, CT_PRIVATE_COLON); if ((tmp = chunk_get_next_ncnl(next)) != NULL) { chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START); } } else { set_chunk_type(pc, (chunk_is_str(pc, "signals", 7) || chunk_is_str(pc, "Q_SIGNALS", 9)) ? CT_WORD : CT_QUALIFIER); } } /* Look for <newline> 'EXEC' 'SQL' */ if ((chunk_is_str(pc, "EXEC", 4) && chunk_is_str(next, "SQL", 3)) || ((*pc->str == '$') && (pc->type != CT_SQL_WORD))) { tmp = chunk_get_prev(pc); if (chunk_is_newline(tmp)) { if (*pc->str == '$') { set_chunk_type(pc, CT_SQL_EXEC); if (pc->len() > 1) { /* SPLIT OFF '$' */ chunk_t nc; nc = *pc; pc->str.resize(1); pc->orig_col_end = pc->orig_col + 1; nc.type = CT_SQL_WORD; nc.str.pop_front(); nc.orig_col++; nc.column++; chunk_add_after(&nc, pc); next = chunk_get_next(pc); } } tmp = chunk_get_next(next); if (chunk_is_str_case(tmp, "BEGIN", 5)) { set_chunk_type(pc, CT_SQL_BEGIN); } else if (chunk_is_str_case(tmp, "END", 3)) { set_chunk_type(pc, CT_SQL_END); } else { set_chunk_type(pc, CT_SQL_EXEC); } /* Change words into CT_SQL_WORD until CT_SEMICOLON */ while (tmp != NULL) { if (tmp->type == CT_SEMICOLON) { break; } if ((tmp->len() > 0) && (unc_isalpha(*tmp->str) || (*tmp->str == '$'))) { set_chunk_type(tmp, CT_SQL_WORD); } tmp = chunk_get_next_ncnl(tmp); } } } /* handle MS abomination 'for each' */ if ((pc->type == CT_FOR) && chunk_is_str(next, "each", 4) && (next == chunk_get_next(pc))) { /* merge the two with a space between */ pc->str.append(' '); pc->str += next->str; pc->orig_col_end = next->orig_col_end; chunk_del(next); next = chunk_get_next_ncnl(pc); /* label the 'in' */ if (next && (next->type == CT_PAREN_OPEN)) { tmp = chunk_get_next_ncnl(next); while (tmp && (tmp->type != CT_PAREN_CLOSE)) { if (chunk_is_str(tmp, "in", 2)) { set_chunk_type(tmp, CT_IN); break; } tmp = chunk_get_next_ncnl(tmp); } } } /* ObjectiveC allows keywords to be used as identifiers in some situations * This is a dirty hack to allow some of the more common situations. */ if (cpd.lang_flags & LANG_OC) { if (((pc->type == CT_IF) || (pc->type == CT_FOR) || (pc->type == CT_WHILE)) && !chunk_is_token(next, CT_PAREN_OPEN)) { set_chunk_type(pc, CT_WORD); } if ((pc->type == CT_DO) && (chunk_is_token(prev, CT_MINUS) || chunk_is_token(next, CT_SQUARE_CLOSE))) { set_chunk_type(pc, CT_WORD); } } /* Another hack to clean up more keyword abuse */ if ((pc->type == CT_CLASS) && (chunk_is_token(prev, CT_DOT) || chunk_is_token(next, CT_DOT))) { set_chunk_type(pc, CT_WORD); } /* Detect Objective C class name */ if ((pc->type == CT_OC_IMPL) || (pc->type == CT_OC_INTF) || (pc->type == CT_OC_PROTOCOL)) { if (next->type != CT_PAREN_OPEN) { set_chunk_type(next, CT_OC_CLASS); } set_chunk_parent(next, pc->type); tmp = chunk_get_next_ncnl(next); if (tmp != NULL) { chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START); } tmp = chunk_get_next_type(pc, CT_OC_END, pc->level); if (tmp != NULL) { set_chunk_parent(tmp, pc->type); } } if (pc->type == CT_OC_INTF) { tmp = chunk_get_next_ncnl(pc, CNAV_PREPROC); while ((tmp != NULL) && (tmp->type != CT_OC_END)) { if (get_token_pattern_class(tmp->type) != PATCLS_NONE) { LOG_FMT(LOBJCWORD, "@interface %d:%d change '%s' (%s) to CT_WORD\n", pc->orig_line, pc->orig_col, tmp->text(), get_token_name(tmp->type)); set_chunk_type(tmp, CT_WORD); } tmp = chunk_get_next_ncnl(tmp, CNAV_PREPROC); } } /* Detect Objective-C categories and class extensions */ /* @interface ClassName (CategoryName) */ /* @implementation ClassName (CategoryName) */ /* @interface ClassName () */ /* @implementation ClassName () */ if (((pc->parent_type == CT_OC_IMPL) || (pc->parent_type == CT_OC_INTF) || (pc->type == CT_OC_CLASS)) && (next->type == CT_PAREN_OPEN)) { set_chunk_parent(next, pc->parent_type); tmp = chunk_get_next(next); if ((tmp != NULL) && (tmp->next != NULL)) { if (tmp->type == CT_PAREN_CLOSE) { //set_chunk_type(tmp, CT_OC_CLASS_EXT); set_chunk_parent(tmp, pc->parent_type); } else { set_chunk_type(tmp, CT_OC_CATEGORY); set_chunk_parent(tmp, pc->parent_type); } } tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level); if (tmp != NULL) { set_chunk_parent(tmp, pc->parent_type); } } /* Detect Objective C @property * @property NSString *stringProperty; * @property(nonatomic, retain) NSMutableDictionary *shareWith; */ if (pc->type == CT_OC_PROPERTY) { if (next->type != CT_PAREN_OPEN) { chunk_flags_set(next, PCF_STMT_START | PCF_EXPR_START); } else { set_chunk_parent(next, pc->type); tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level); if (tmp != NULL) { set_chunk_parent(tmp, pc->type); tmp = chunk_get_next_ncnl(tmp); if (tmp != NULL) { chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START); tmp = chunk_get_next_type(tmp, CT_SEMICOLON, pc->level); if (tmp != NULL) { set_chunk_parent(tmp, pc->type); } } } } } /* Detect Objective C @selector * @selector(msgNameWithNoArg) * @selector(msgNameWith1Arg:) * @selector(msgNameWith2Args:arg2Name:) */ if ((pc->type == CT_OC_SEL) && (next->type == CT_PAREN_OPEN)) { set_chunk_parent(next, pc->type); tmp = chunk_get_next(next); if (tmp != NULL) { set_chunk_type(tmp, CT_OC_SEL_NAME); set_chunk_parent(tmp, pc->type); while ((tmp = chunk_get_next_ncnl(tmp)) != NULL) { if (tmp->type == CT_PAREN_CLOSE) { set_chunk_parent(tmp, CT_OC_SEL); break; } set_chunk_type(tmp, CT_OC_SEL_NAME); set_chunk_parent(tmp, pc->type); } } } /* Handle special preprocessor junk */ if (pc->type == CT_PREPROC) { set_chunk_parent(pc, next->type); } /* Detect "pragma region" and "pragma endregion" */ if ((pc->type == CT_PP_PRAGMA) && (next->type == CT_PREPROC_BODY)) { if ((memcmp(next->str, "region", 6) == 0) || (memcmp(next->str, "endregion", 9) == 0)) { set_chunk_type(pc, (*next->str == 'r') ? CT_PP_REGION : CT_PP_ENDREGION); set_chunk_parent(prev, pc->type); } } /* Check for C# nullable types '?' is in next */ if ((cpd.lang_flags & LANG_CS) && (next->type == CT_QUESTION) && (next->orig_col == (pc->orig_col + pc->len()))) { tmp = chunk_get_next_ncnl(next); if (tmp != NULL) { bool doit = ((tmp->type == CT_PAREN_CLOSE) || (tmp->type == CT_ANGLE_CLOSE)); if (tmp->type == CT_WORD) { tmp2 = chunk_get_next_ncnl(tmp); if ((tmp2 != NULL) && ((tmp2->type == CT_SEMICOLON) || (tmp2->type == CT_ASSIGN) || (tmp2->type == CT_COMMA) || (tmp2->type == CT_BRACE_OPEN))) { doit = true; } } if (doit) { pc->str += next->str; pc->orig_col_end = next->orig_col_end; chunk_del(next); next = tmp; } } } /* Change 'default(' into a sizeof-like statement */ if ((cpd.lang_flags & LANG_CS) && (pc->type == CT_DEFAULT) && (next->type == CT_PAREN_OPEN)) { set_chunk_type(pc, CT_SIZEOF); } if ((pc->type == CT_UNSAFE) && (next->type != CT_BRACE_OPEN)) { set_chunk_type(pc, CT_QUALIFIER); } if (((pc->type == CT_USING) || ((pc->type == CT_TRY) && (cpd.lang_flags & LANG_JAVA))) && (next->type == CT_PAREN_OPEN)) { set_chunk_type(pc, CT_USING_STMT); } /* Add minimal support for C++0x rvalue references */ if ((pc->type == CT_BOOL) && chunk_is_str(pc, "&&", 2)) { if (prev->type == CT_TYPE) { set_chunk_type(pc, CT_BYREF); } } /* HACK: treat try followed by a colon as a qualifier to handle this: * A::A(int) try : B() { } catch (...) { } */ if ((pc->type == CT_TRY) && chunk_is_str(pc, "try", 3) && (next != NULL) && (next->type == CT_COLON)) { set_chunk_type(pc, CT_QUALIFIER); } /* If Java's 'synchronized' is in a method declaration, it should be * a qualifier. */ if ((cpd.lang_flags & LANG_JAVA) && (pc->type == CT_SYNCHRONIZED) && (next->type != CT_PAREN_OPEN)) { set_chunk_type(pc, CT_QUALIFIER); } // guy 2015-11-05 // change CT_DC_MEMBER + CT_FOR into CT_DC_MEMBER + CT_FUNC_CALL if ((pc->type == CT_FOR) && (pc->prev->type == CT_DC_MEMBER)) { set_chunk_type(pc, CT_FUNC_CALL); } /* TODO: determine other stuff here */ prev = pc; pc = next; next = chunk_get_next_ncnl(pc); } } // tokenize_cleanup
static chunk_t *pawn_process_func_def(chunk_t *pc) { /* We are on a function definition */ chunk_t *clp; chunk_t *last; chunk_t *next; pc->type = CT_FUNC_DEF; /* If we don't have a brace open right after the close fparen, then * we need to add virtual braces around the function body. */ clp = chunk_get_next_str(pc, ")", 1, 0); last = chunk_get_next_ncnl(clp); if (last != NULL) { LOG_FMT(LPFUNC, "%s: %d] last is '%s' [%s]\n", __func__, last->orig_line, last->str.c_str(), get_token_name(last->type)); } /* See if there is a state clause after the function */ if ((last != NULL) && chunk_is_str(last, "<", 1)) { LOG_FMT(LPFUNC, "%s: %d] '%s' has state angle open %s\n", __func__, pc->orig_line, pc->str.c_str(), get_token_name(last->type)); last->type = CT_ANGLE_OPEN; last->parent_type = CT_FUNC_DEF; while (((last = chunk_get_next(last)) != NULL) && !chunk_is_str(last, ">", 1)) { } if (last != NULL) { LOG_FMT(LPFUNC, "%s: %d] '%s' has state angle close %s\n", __func__, pc->orig_line, pc->str.c_str(), get_token_name(last->type)); last->type = CT_ANGLE_CLOSE; last->parent_type = CT_FUNC_DEF; } last = chunk_get_next_ncnl(last); } if (last == NULL) { return(last); } if (last->type == CT_BRACE_OPEN) { last->parent_type = CT_FUNC_DEF; last = chunk_get_next_type(last, CT_BRACE_CLOSE, last->level); if (last != NULL) { last->parent_type = CT_FUNC_DEF; } } else { LOG_FMT(LPFUNC, "%s: %d] '%s' fdef: expected brace open: %s\n", __func__, pc->orig_line, pc->str.c_str(), get_token_name(last->type)); chunk_t chunk; chunk = *last; chunk.str.clear(); chunk.type = CT_VBRACE_OPEN; chunk.parent_type = CT_FUNC_DEF; chunk_t *prev = chunk_add_before(&chunk, last); last = prev; /* find the next newline at level 0 */ prev = chunk_get_next_ncnl(prev); do { LOG_FMT(LPFUNC, "%s:%d] check %s, level %d\n", __func__, prev->orig_line, get_token_name(prev->type), prev->level); if ((prev->type == CT_NEWLINE) && (prev->level == 0)) { next = chunk_get_next_ncnl(prev); if ((next != NULL) && (next->type != CT_ELSE) && (next->type != CT_WHILE_OF_DO)) { break; } } prev->level++; prev->brace_level++; last = prev; } while ((prev = chunk_get_next(prev)) != NULL); if (last != NULL) { LOG_FMT(LPFUNC, "%s:%d] ended on %s, level %d\n", __func__, last->orig_line, get_token_name(last->type), last->level); } chunk = *last; chunk.str.clear(); chunk.column += last->len(); chunk.type = CT_VBRACE_CLOSE; chunk.level = 0; chunk.brace_level = 0; chunk.parent_type = CT_FUNC_DEF; last = chunk_add_after(&chunk, last); } return(last); }
static chunk_t *mod_case_brace_add(chunk_t *cl_colon) { LOG_FUNC_ENTRY(); chunk_t *pc = cl_colon; chunk_t *last = NULL; chunk_t *next = chunk_get_next_ncnl(cl_colon, CNAV_PREPROC); LOG_FMT(LMCB, "%s: line %zu", __func__, pc->orig_line); while ((pc = chunk_get_next_ncnl(pc, CNAV_PREPROC)) != NULL) { if (pc->level < cl_colon->level) { LOG_FMT(LMCB, " - level drop\n"); return(next); } if ((pc->level == cl_colon->level) && ((pc->type == CT_CASE) || (pc->type == CT_BREAK))) { last = pc; //if (pc->type == CT_BREAK) //{ // /* Step past the semicolon */ // last = chunk_get_next_ncnl(chunk_get_next_ncnl(last)); //} break; } } if (last == NULL) { LOG_FMT(LMCB, " - NULL last\n"); return(next); } LOG_FMT(LMCB, " - adding before '%s' on line %zu\n", last->text(), last->orig_line); chunk_t chunk; chunk.type = CT_BRACE_OPEN; chunk.orig_line = cl_colon->orig_line; chunk.parent_type = CT_CASE; chunk.level = cl_colon->level; chunk.brace_level = cl_colon->brace_level; chunk.flags = pc->flags & PCF_COPY_FLAGS; chunk.str = "{"; chunk_t *br_open = chunk_add_after(&chunk, cl_colon); chunk.type = CT_BRACE_CLOSE; chunk.orig_line = last->orig_line; chunk.str = "}"; chunk_t *br_close = chunk_add_before(&chunk, last); newline_add_before(last); for (pc = chunk_get_next(br_open, CNAV_PREPROC); pc != br_close; pc = chunk_get_next(pc, CNAV_PREPROC)) { pc->level++; pc->brace_level++; } return(br_open); } // mod_case_brace_add