# HG changeset patch # User Christian Brabandt # Date 1533935704 -7200 # Node ID 3f1a17863b7358417b2d7c5f2bbfca25abe43d11 # Parent 89b3aabf0a958846300c7d0fb8194062868b28e4 patch 8.1.0266: parsing Ex address range is not a separate function commit https://github.com/vim/vim/commit/ee8415bc5998792fab6f4dcf289d027856e05b89 Author: Bram Moolenaar Date: Fri Aug 10 23:13:12 2018 +0200 patch 8.1.0266: parsing Ex address range is not a separate function Problem: Parsing Ex address range is not a separate function. Solution: Refactor do_one_cmd() to separate address parsing. diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -1719,7 +1719,6 @@ do_one_cmd( cmdmod_T save_cmdmod; int ni; /* set when Not Implemented */ char_u *cmd; - int address_count = 1; vim_memset(&ea, 0, sizeof(ea)); ea.line1 = 1; @@ -2045,168 +2044,9 @@ do_one_cmd( get_wincmd_addr_type(skipwhite(p), &ea); } - /* repeat for all ',' or ';' separated addresses */ ea.cmd = cmd; - for (;;) - { - ea.line1 = ea.line2; - switch (ea.addr_type) - { - case ADDR_LINES: - /* default is current line number */ - ea.line2 = curwin->w_cursor.lnum; - break; - case ADDR_WINDOWS: - ea.line2 = CURRENT_WIN_NR; - break; - case ADDR_ARGUMENTS: - ea.line2 = curwin->w_arg_idx + 1; - if (ea.line2 > ARGCOUNT) - ea.line2 = ARGCOUNT; - break; - case ADDR_LOADED_BUFFERS: - case ADDR_BUFFERS: - ea.line2 = curbuf->b_fnum; - break; - case ADDR_TABS: - ea.line2 = CURRENT_TAB_NR; - break; - case ADDR_TABS_RELATIVE: - ea.line2 = 1; - break; -#ifdef FEAT_QUICKFIX - case ADDR_QUICKFIX: - ea.line2 = qf_get_cur_valid_idx(&ea); - break; -#endif - } - ea.cmd = skipwhite(ea.cmd); - lnum = get_address(&ea, &ea.cmd, ea.addr_type, ea.skip, - ea.addr_count == 0, address_count++); - if (ea.cmd == NULL) /* error detected */ - goto doend; - if (lnum == MAXLNUM) - { - if (*ea.cmd == '%') /* '%' - all lines */ - { - ++ea.cmd; - switch (ea.addr_type) - { - case ADDR_LINES: - ea.line1 = 1; - ea.line2 = curbuf->b_ml.ml_line_count; - break; - case ADDR_LOADED_BUFFERS: - { - buf_T *buf = firstbuf; - - while (buf->b_next != NULL - && buf->b_ml.ml_mfp == NULL) - buf = buf->b_next; - ea.line1 = buf->b_fnum; - buf = lastbuf; - while (buf->b_prev != NULL - && buf->b_ml.ml_mfp == NULL) - buf = buf->b_prev; - ea.line2 = buf->b_fnum; - break; - } - case ADDR_BUFFERS: - ea.line1 = firstbuf->b_fnum; - ea.line2 = lastbuf->b_fnum; - break; - case ADDR_WINDOWS: - case ADDR_TABS: - if (IS_USER_CMDIDX(ea.cmdidx)) - { - ea.line1 = 1; - ea.line2 = ea.addr_type == ADDR_WINDOWS - ? LAST_WIN_NR : LAST_TAB_NR; - } - else - { - /* there is no Vim command which uses '%' and - * ADDR_WINDOWS or ADDR_TABS */ - errormsg = (char_u *)_(e_invrange); - goto doend; - } - break; - case ADDR_TABS_RELATIVE: - errormsg = (char_u *)_(e_invrange); - goto doend; - break; - case ADDR_ARGUMENTS: - if (ARGCOUNT == 0) - ea.line1 = ea.line2 = 0; - else - { - ea.line1 = 1; - ea.line2 = ARGCOUNT; - } - break; -#ifdef FEAT_QUICKFIX - case ADDR_QUICKFIX: - ea.line1 = 1; - ea.line2 = qf_get_size(&ea); - if (ea.line2 == 0) - ea.line2 = 1; - break; -#endif - } - ++ea.addr_count; - } - /* '*' - visual area */ - else if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL) - { - pos_T *fp; - - if (ea.addr_type != ADDR_LINES) - { - errormsg = (char_u *)_(e_invrange); - goto doend; - } - - ++ea.cmd; - if (!ea.skip) - { - fp = getmark('<', FALSE); - if (check_mark(fp) == FAIL) - goto doend; - ea.line1 = fp->lnum; - fp = getmark('>', FALSE); - if (check_mark(fp) == FAIL) - goto doend; - ea.line2 = fp->lnum; - ++ea.addr_count; - } - } - } - else - ea.line2 = lnum; - ea.addr_count++; - - if (*ea.cmd == ';') - { - if (!ea.skip) - { - curwin->w_cursor.lnum = ea.line2; - /* don't leave the cursor on an illegal line or column */ - check_cursor(); - } - } - else if (*ea.cmd != ',') - break; - ++ea.cmd; - } - - /* One address given: set start and end lines */ - if (ea.addr_count == 1) - { - ea.line1 = ea.line2; - /* ... but only implicit: really no address given */ - if (lnum == MAXLNUM) - ea.addr_count = 0; - } + if (parse_cmd_address(&ea, &errormsg) == FAIL) + goto doend; /* * 5. Parse the command. @@ -2989,6 +2829,179 @@ doend: #endif /* + * Parse the address range, if any, in "eap". + * Return FAIL and set "errormsg" or return OK. + */ + int +parse_cmd_address(exarg_T *eap, char_u **errormsg) +{ + int address_count = 1; + linenr_T lnum; + + // Repeat for all ',' or ';' separated addresses. + for (;;) + { + eap->line1 = eap->line2; + switch (eap->addr_type) + { + case ADDR_LINES: + // default is current line number + eap->line2 = curwin->w_cursor.lnum; + break; + case ADDR_WINDOWS: + eap->line2 = CURRENT_WIN_NR; + break; + case ADDR_ARGUMENTS: + eap->line2 = curwin->w_arg_idx + 1; + if (eap->line2 > ARGCOUNT) + eap->line2 = ARGCOUNT; + break; + case ADDR_LOADED_BUFFERS: + case ADDR_BUFFERS: + eap->line2 = curbuf->b_fnum; + break; + case ADDR_TABS: + eap->line2 = CURRENT_TAB_NR; + break; + case ADDR_TABS_RELATIVE: + eap->line2 = 1; + break; +#ifdef FEAT_QUICKFIX + case ADDR_QUICKFIX: + eap->line2 = qf_get_cur_valid_idx(eap); + break; +#endif + } + eap->cmd = skipwhite(eap->cmd); + lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, + eap->addr_count == 0, address_count++); + if (eap->cmd == NULL) // error detected + return FAIL; + if (lnum == MAXLNUM) + { + if (*eap->cmd == '%') // '%' - all lines + { + ++eap->cmd; + switch (eap->addr_type) + { + case ADDR_LINES: + eap->line1 = 1; + eap->line2 = curbuf->b_ml.ml_line_count; + break; + case ADDR_LOADED_BUFFERS: + { + buf_T *buf = firstbuf; + + while (buf->b_next != NULL + && buf->b_ml.ml_mfp == NULL) + buf = buf->b_next; + eap->line1 = buf->b_fnum; + buf = lastbuf; + while (buf->b_prev != NULL + && buf->b_ml.ml_mfp == NULL) + buf = buf->b_prev; + eap->line2 = buf->b_fnum; + break; + } + case ADDR_BUFFERS: + eap->line1 = firstbuf->b_fnum; + eap->line2 = lastbuf->b_fnum; + break; + case ADDR_WINDOWS: + case ADDR_TABS: + if (IS_USER_CMDIDX(eap->cmdidx)) + { + eap->line1 = 1; + eap->line2 = eap->addr_type == ADDR_WINDOWS + ? LAST_WIN_NR : LAST_TAB_NR; + } + else + { + // there is no Vim command which uses '%' and + // ADDR_WINDOWS or ADDR_TABS + *errormsg = (char_u *)_(e_invrange); + return FAIL; + } + break; + case ADDR_TABS_RELATIVE: + *errormsg = (char_u *)_(e_invrange); + return FAIL; + case ADDR_ARGUMENTS: + if (ARGCOUNT == 0) + eap->line1 = eap->line2 = 0; + else + { + eap->line1 = 1; + eap->line2 = ARGCOUNT; + } + break; +#ifdef FEAT_QUICKFIX + case ADDR_QUICKFIX: + eap->line1 = 1; + eap->line2 = qf_get_size(eap); + if (eap->line2 == 0) + eap->line2 = 1; + break; +#endif + } + ++eap->addr_count; + } + else if (*eap->cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL) + { + pos_T *fp; + + // '*' - visual area + if (eap->addr_type != ADDR_LINES) + { + *errormsg = (char_u *)_(e_invrange); + return FAIL; + } + + ++eap->cmd; + if (!eap->skip) + { + fp = getmark('<', FALSE); + if (check_mark(fp) == FAIL) + return FAIL; + eap->line1 = fp->lnum; + fp = getmark('>', FALSE); + if (check_mark(fp) == FAIL) + return FAIL; + eap->line2 = fp->lnum; + ++eap->addr_count; + } + } + } + else + eap->line2 = lnum; + eap->addr_count++; + + if (*eap->cmd == ';') + { + if (!eap->skip) + { + curwin->w_cursor.lnum = eap->line2; + // don't leave the cursor on an illegal line or column + check_cursor(); + } + } + else if (*eap->cmd != ',') + break; + ++eap->cmd; + } + + // One address given: set start and end lines. + if (eap->addr_count == 1) + { + eap->line1 = eap->line2; + // ... but only implicit: really no address given + if (lnum == MAXLNUM) + eap->addr_count = 0; + } + return OK; +} + +/* * Check for an Ex command with optional tail. * If there is a match advance "pp" to the argument and return TRUE. */ @@ -4292,7 +4305,7 @@ set_one_cmd_context( } /* - * skip a range specifier of the form: addr [,addr] [;addr] .. + * Skip a range specifier of the form: addr [,addr] [;addr] .. * * Backslashed delimiters after / or ? will be skipped, and commands will * not be expanded between /'s and ?'s or after "'". diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -4,6 +4,7 @@ int do_cmdline_cmd(char_u *cmd); int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int), void *cookie, int flags); int getline_equal(char_u *(*fgetline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int)); void *getline_cookie(char_u *(*fgetline)(int, void *, int), void *cookie); +int parse_cmd_address(exarg_T *eap, char_u **errormsg); int checkforcmd(char_u **pp, char *cmd, int len); int modifier_len(char_u *cmd); int cmd_exists(char_u *name); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -795,6 +795,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 266, +/**/ 265, /**/ 264,