aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2022-10-14 09:53:15 +0100
committerGitHub <noreply@github.com>2022-10-14 09:53:15 +0100
commit9931db2e3fa43ed02e1b0bc6f167ed5398fa6369 (patch)
treeb29a3b9d45b0700da10be86c0237510a2a2f2cde /src
parentd339b4aad7461937e1e03ac0836b2eb1354ff442 (diff)
parent7f11dfdef880ee98e4f18f046f21e285157d10ac (diff)
downloadrneovim-9931db2e3fa43ed02e1b0bc6f167ed5398fa6369.tar.gz
rneovim-9931db2e3fa43ed02e1b0bc6f167ed5398fa6369.tar.bz2
rneovim-9931db2e3fa43ed02e1b0bc6f167ed5398fa6369.zip
Merge pull request #20545 from lewis6991/remove_cscope
Diffstat (limited to 'src')
-rw-r--r--src/nvim/cmdexpand.c12
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c25
-rw-r--r--src/nvim/ex_cmds.lua24
-rw-r--r--src/nvim/ex_docmd.c5
-rwxr-xr-xsrc/nvim/generators/gen_declarations.lua3
-rw-r--r--src/nvim/if_cscope.c2027
-rw-r--r--src/nvim/if_cscope.h10
-rw-r--r--src/nvim/if_cscope_defs.h64
-rw-r--r--src/nvim/main.c2
-rw-r--r--src/nvim/normal.c6
-rw-r--r--src/nvim/option_defs.h9
-rw-r--r--src/nvim/options.lua52
-rw-r--r--src/nvim/optionstr.c17
-rw-r--r--src/nvim/tag.c237
-rw-r--r--src/nvim/tag.h2
-rw-r--r--src/nvim/testdir/test_cscope.vim344
-rw-r--r--src/nvim/usercmd.c1
-rw-r--r--src/nvim/vim.h1
19 files changed, 93 insertions, 2749 deletions
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index a29d022606..e728bd6967 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -22,7 +22,6 @@
#include "nvim/getchar.h"
#include "nvim/help.h"
#include "nvim/highlight_group.h"
-#include "nvim/if_cscope.h"
#include "nvim/locale.h"
#include "nvim/lua/executor.h"
#include "nvim/mapping.h"
@@ -1419,11 +1418,6 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, cons
case CMD_highlight:
set_context_in_highlight_cmd(xp, arg);
break;
- case CMD_cscope:
- case CMD_lcscope:
- case CMD_scscope:
- set_context_in_cscope_cmd(xp, arg, cmdidx);
- break;
case CMD_sign:
set_context_in_sign_cmd(xp, (char *)arg);
break;
@@ -2063,7 +2057,6 @@ static int ExpandOther(expand_T *xp, regmatch_T *rmp, int *num_file, char ***fil
{ EXPAND_HIGHLIGHT, (ExpandFunc)get_highlight_name, true, false },
{ EXPAND_EVENTS, expand_get_event_name, true, false },
{ EXPAND_AUGROUP, expand_get_augroup_name, true, false },
- { EXPAND_CSCOPE, get_cscope_name, true, true },
{ EXPAND_SIGN, get_sign_name, true, true },
{ EXPAND_PROFILE, get_profile_name, true, true },
#ifdef HAVE_WORKING_LIBINTL
@@ -2883,11 +2876,6 @@ void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
xpc.xp_pattern_len = strlen(xpc.xp_pattern);
}
- if (xpc.xp_context == EXPAND_CSCOPE) {
- set_context_in_cscope_cmd(&xpc, (const char *)xpc.xp_pattern, CMD_cscope);
- xpc.xp_pattern_len = strlen(xpc.xp_pattern);
- }
-
if (xpc.xp_context == EXPAND_SIGN) {
set_context_in_sign_cmd(&xpc, xpc.xp_pattern);
xpc.xp_pattern_len = strlen(xpc.xp_pattern);
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 837fef23f4..cc26bbf1a8 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -88,7 +88,6 @@ return {
cos={args=1, base=1, float_func="cos"},
cosh={args=1, base=1, float_func="cosh"},
count={args={2, 4}, base=1},
- cscope_connection={args={0, 3}},
ctxget={args={0, 1}},
ctxpop={},
ctxpush={args={0, 1}},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index a326c44371..861f68993a 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -39,7 +39,6 @@
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/highlight_group.h"
-#include "nvim/if_cscope.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/input.h"
@@ -1132,29 +1131,6 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = n;
}
-/// "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
-///
-/// Checks the existence of a cscope connection.
-static void f_cscope_connection(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
-{
- int num = 0;
- const char *dbpath = NULL;
- const char *prepend = NULL;
- char buf[NUMBUFLEN];
-
- if (argvars[0].v_type != VAR_UNKNOWN
- && argvars[1].v_type != VAR_UNKNOWN) {
- num = (int)tv_get_number(&argvars[0]);
- dbpath = tv_get_string(&argvars[1]);
- if (argvars[2].v_type != VAR_UNKNOWN) {
- prepend = tv_get_string_buf(&argvars[2], buf);
- }
- }
-
- rettv->vval.v_number = cs_connection(num, (char_u *)dbpath,
- (char_u *)prepend);
-}
-
/// "ctxget([{index}])" function
static void f_ctxget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@@ -3565,7 +3541,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
"cmdwin",
"comments",
"conceal",
- "cscope",
"cursorbind",
"cursorshape",
#ifdef DEBUG
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 04b8832428..e3eea884c4 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -673,18 +673,6 @@ module.cmds = {
func='ex_cc',
},
{
- command='cscope',
- flags=bit.bor(EXTRA, NOTRLCOM, XFILE),
- addr_type='ADDR_NONE',
- func='ex_cscope',
- },
- {
- command='cstag',
- flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_NONE',
- func='ex_cstag',
- },
- {
command='cunmap',
flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
addr_type='ADDR_NONE',
@@ -1405,12 +1393,6 @@ module.cmds = {
func='ex_cclose',
},
{
- command='lcscope',
- flags=bit.bor(EXTRA, NOTRLCOM, XFILE),
- addr_type='ADDR_NONE',
- func='ex_cscope',
- },
- {
command='ldo',
flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
addr_type='ADDR_QUICKFIX_VALID',
@@ -2422,12 +2404,6 @@ module.cmds = {
func='ex_scriptencoding',
},
{
- command='scscope',
- flags=bit.bor(EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_scscope',
- },
- {
command='set',
flags=bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK),
addr_type='ADDR_NONE',
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 5591b5f55d..77d310e338 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -44,7 +44,6 @@
#include "nvim/hardcopy.h"
#include "nvim/help.h"
#include "nvim/highlight_group.h"
-#include "nvim/if_cscope.h"
#include "nvim/input.h"
#include "nvim/keycodes.h"
#include "nvim/locale.h"
@@ -6589,10 +6588,6 @@ static void ex_tag_cmd(exarg_T *eap, char *name)
cmd = DT_LAST; // ":tlast"
break;
default: // ":tag"
- if (p_cst && *eap->arg != NUL) {
- ex_cstag(eap);
- return;
- }
cmd = DT_TAG;
break;
}
diff --git a/src/nvim/generators/gen_declarations.lua b/src/nvim/generators/gen_declarations.lua
index bf1adaeee3..4097ff7dc5 100755
--- a/src/nvim/generators/gen_declarations.lua
+++ b/src/nvim/generators/gen_declarations.lua
@@ -182,8 +182,7 @@ Additionally uses the following environment variables:
If set to 1 then all generated declarations receive a comment with file
name and line number after the declaration. This may be useful for
debugging gen_declarations script, but not much beyond that with
- configured development environment (i.e. with ctags/cscope/finding
- definitions with clang/etc).
+ configured development environment (i.e. with with clang/etc).
WARNING: setting this to 1 will cause extensive rebuilds: declarations
generator script will not regenerate non-static.h file if its
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
deleted file mode 100644
index bc31d702f4..0000000000
--- a/src/nvim/if_cscope.c
+++ /dev/null
@@ -1,2027 +0,0 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
-// CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com>
-// Ported to Win32 by Sergey Khorev <sergey.khorev@gmail.com>
-//
-// The basic idea/structure of cscope for Vim was borrowed from Nvi. There
-// might be a few lines of code that look similar to what Nvi has.
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "nvim/ascii.h"
-#include "nvim/autocmd.h"
-#include "nvim/buffer.h"
-#include "nvim/charset.h"
-#include "nvim/eval.h"
-#include "nvim/event/stream.h"
-#include "nvim/ex_eval.h"
-#include "nvim/fileio.h"
-#include "nvim/if_cscope.h"
-#include "nvim/memory.h"
-#include "nvim/message.h"
-#include "nvim/os/input.h"
-#include "nvim/os/os.h"
-#include "nvim/os/time.h"
-#include "nvim/path.h"
-#include "nvim/quickfix.h"
-#include "nvim/strings.h"
-#include "nvim/tag.h"
-#include "nvim/window.h"
-#if defined(UNIX)
-# include <sys/wait.h>
-#endif
-#include "nvim/if_cscope_defs.h"
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "if_cscope.c.generated.h"
-#endif
-
-static csinfo_T *csinfo = NULL;
-static size_t csinfo_size = 0; // number of items allocated in csinfo[]
-
-static int eap_arg_len; // length of eap->arg, set in cs_lookup_cmd()
-static cscmd_T cs_cmds[] =
-{
- { "add", cs_add,
- N_("Add a new database"), "add file|dir [pre-path] [flags]", 0 },
- { "find", cs_find,
- N_("Query for a pattern"), "find a|c|d|e|f|g|i|s|t name", 1 },
- { "help", cs_help,
- N_("Show this message"), "help", 0 },
- { "kill", cs_kill,
- N_("Kill a connection"), "kill #", 0 },
- { "reset", cs_reset,
- N_("Reinit all connections"), "reset", 0 },
- { "show", cs_show,
- N_("Show connections"), "show", 0 },
- { NULL, NULL, NULL, NULL, 0 }
-};
-
-static void cs_usage_msg(csid_e x)
-{
- (void)semsg(_("E560: Usage: cs[cope] %s"), cs_cmds[(int)x].usage);
-}
-
-static enum {
- EXP_CSCOPE_SUBCMD, // expand ":cscope" sub-commands
- EXP_SCSCOPE_SUBCMD, // expand ":scscope" sub-commands
- EXP_CSCOPE_FIND, // expand ":cscope find" arguments
- EXP_CSCOPE_KILL, // expand ":cscope kill" arguments
-} expand_what;
-
-// Function given to ExpandGeneric() to obtain the cscope command
-// expansion.
-char *get_cscope_name(expand_T *xp, int idx)
-{
- int current_idx;
-
- switch (expand_what) {
- case EXP_CSCOPE_SUBCMD:
- // Complete with sub-commands of ":cscope":
- // add, find, help, kill, reset, show
- return cs_cmds[idx].name;
- case EXP_SCSCOPE_SUBCMD: {
- // Complete with sub-commands of ":scscope": same sub-commands as
- // ":cscope" but skip commands which don't support split windows
- int i;
- for (i = 0, current_idx = 0; cs_cmds[i].name != NULL; i++) {
- if (cs_cmds[i].cansplit) {
- if (current_idx++ == idx) {
- break;
- }
- }
- }
- return cs_cmds[i].name;
- }
- case EXP_CSCOPE_FIND: {
- const char *query_type[] =
- {
- "a", "c", "d", "e", "f", "g", "i", "s", "t", NULL
- };
-
- // Complete with query type of ":cscope find {query_type}".
- // {query_type} can be letters (c, d, ... a) or numbers (0, 1,
- // ..., 9) but only complete with letters, since numbers are
- // redundant.
- return (char *)query_type[idx];
- }
- case EXP_CSCOPE_KILL: {
- static char connection[5];
-
- // ":cscope kill" accepts connection numbers or partial names of
- // the pathname of the cscope database as argument. Only complete
- // with connection numbers. -1 can also be used to kill all
- // connections.
- size_t i;
- for (i = 0, current_idx = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname == NULL) {
- continue;
- }
- if (current_idx++ == idx) {
- vim_snprintf(connection, sizeof(connection), "%zu", i);
- return connection;
- }
- }
- return (current_idx == idx && idx > 0) ? "-1" : NULL;
- }
- default:
- return NULL;
- }
-}
-
-// Handle command line completion for :cscope command.
-void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
-{
- // Default: expand subcommands.
- xp->xp_context = EXPAND_CSCOPE;
- xp->xp_pattern = (char *)arg;
- expand_what = ((cmdidx == CMD_scscope)
- ? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD);
-
- // (part of) subcommand already typed
- if (*arg != NUL) {
- const char *p = (const char *)skiptowhite(arg);
- if (*p != NUL) { // Past first word.
- xp->xp_pattern = skipwhite(p);
- if (*skiptowhite(xp->xp_pattern) != NUL) {
- xp->xp_context = EXPAND_NOTHING;
- } else if (STRNICMP(arg, "add", p - arg) == 0) {
- xp->xp_context = EXPAND_FILES;
- } else if (STRNICMP(arg, "kill", p - arg) == 0) {
- expand_what = EXP_CSCOPE_KILL;
- } else if (STRNICMP(arg, "find", p - arg) == 0) {
- expand_what = EXP_CSCOPE_FIND;
- } else {
- xp->xp_context = EXPAND_NOTHING;
- }
- }
- }
-}
-
-/// Find the command, print help if invalid, and then call the corresponding
-/// command function.
-///
-/// @param make_split whether to split window
-static void do_cscope_general(exarg_T *eap, int make_split)
-{
- cscmd_T *cmdp;
-
- if ((cmdp = cs_lookup_cmd(eap)) == NULL) {
- cs_help(eap);
- return;
- }
-
- if (make_split) {
- if (!cmdp->cansplit) {
- (void)msg_puts(_("This cscope command does not support splitting the window.\n"));
- return;
- }
- postponed_split = -1;
- postponed_split_flags = cmdmod.cmod_split;
- postponed_split_tab = cmdmod.cmod_tab;
- }
-
- cmdp->func(eap);
-
- postponed_split_flags = 0;
- postponed_split_tab = 0;
-}
-
-/// Implementation of ":cscope" and ":lcscope"
-void ex_cscope(exarg_T *eap)
-{
- do_cscope_general(eap, false);
-}
-
-/// Implementation of ":scscope". Same as ex_cscope(), but splits window, too.
-void ex_scscope(exarg_T *eap)
-{
- do_cscope_general(eap, true);
-}
-
-/// Implementation of ":cstag"
-void ex_cstag(exarg_T *eap)
-{
- int ret = false;
-
- if (*eap->arg == NUL) {
- (void)emsg(_("E562: Usage: cstag <ident>"));
- return;
- }
-
- switch (p_csto) {
- case 0:
- if (cs_check_for_connections()) {
- ret = cs_find_common("g", eap->arg, eap->forceit, false,
- false, (char_u *)(*eap->cmdlinep));
- if (ret == false) {
- cs_free_tags();
- if (msg_col) {
- msg_putchar('\n');
- }
-
- if (cs_check_for_tags()) {
- ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, false);
- }
- }
- } else if (cs_check_for_tags()) {
- ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, false);
- }
- break;
- case 1:
- if (cs_check_for_tags()) {
- ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, false);
- if (ret == false) {
- if (msg_col) {
- msg_putchar('\n');
- }
-
- if (cs_check_for_connections()) {
- ret = cs_find_common("g", eap->arg, eap->forceit,
- false, false, (char_u *)(*eap->cmdlinep));
- if (ret == false) {
- cs_free_tags();
- }
- }
- }
- } else if (cs_check_for_connections()) {
- ret = cs_find_common("g", eap->arg, eap->forceit, false,
- false, (char_u *)(*eap->cmdlinep));
- if (ret == false) {
- cs_free_tags();
- }
- }
- break;
- default:
- break;
- }
-
- if (!ret) {
- (void)emsg(_("E257: cstag: tag not found"));
- g_do_tagpreview = 0;
- }
-}
-
-/// This simulates a vim_fgets(), but for cscope, returns the next line
-/// from the cscope output. should only be called from find_tags()
-///
-/// @return true if eof, false otherwise
-bool cs_fgets(char_u *buf, int size)
- FUNC_ATTR_NONNULL_ALL
-{
- char *p;
-
- if ((p = cs_manage_matches(NULL, NULL, 0, Get)) == NULL) {
- return true;
- }
- STRLCPY(buf, p, size);
-
- return false;
-}
-
-/// Called only from do_tag(), when popping the tag stack.
-void cs_free_tags(void)
-{
- cs_manage_matches(NULL, NULL, 0, Free);
-}
-
-/// Called from do_tag().
-void cs_print_tags(void)
-{
- cs_manage_matches(NULL, NULL, 0, Print);
-}
-
-// "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
-//
-// Checks for the existence of a |cscope| connection. If no
-// parameters are specified, then the function returns:
-//
-// 0, if cscope was not available (not compiled in), or if there
-// are no cscope connections; or
-// 1, if there is at least one cscope connection.
-//
-// If parameters are specified, then the value of {num}
-// determines how existence of a cscope connection is checked:
-//
-// {num} Description of existence check
-// ----- ------------------------------
-// 0 Same as no parameters (e.g., "cscope_connection()").
-// 1 Ignore {prepend}, and use partial string matches for
-// {dbpath}.
-// 2 Ignore {prepend}, and use exact string matches for
-// {dbpath}.
-// 3 Use {prepend}, use partial string matches for both
-// {dbpath} and {prepend}.
-// 4 Use {prepend}, use exact string matches for both
-// {dbpath} and {prepend}.
-//
-// Note: All string comparisons are case sensitive!
-bool cs_connection(int num, char_u *dbpath, char_u *ppath)
-{
- if (num < 0 || num > 4 || (num > 0 && !dbpath)) {
- return false;
- }
-
- for (size_t i = 0; i < csinfo_size; i++) {
- if (!csinfo[i].fname) {
- continue;
- }
- if (num == 0) {
- return true;
- }
- switch (num) {
- case 1:
- if (strstr(csinfo[i].fname, (char *)dbpath)) {
- return true;
- }
- break;
- case 2:
- if (strcmp(csinfo[i].fname, (char *)dbpath) == 0) {
- return true;
- }
- break;
- case 3:
- if (strstr(csinfo[i].fname, (char *)dbpath)
- && ((!ppath && !csinfo[i].ppath)
- || (ppath
- && csinfo[i].ppath
- && strstr(csinfo[i].ppath, (char *)ppath)))) {
- return true;
- }
- break;
- case 4:
- if ((strcmp(csinfo[i].fname, (char *)dbpath) == 0)
- && ((!ppath && !csinfo[i].ppath)
- || (ppath
- && csinfo[i].ppath
- && (strcmp(csinfo[i].ppath, (char *)ppath) == 0)))) {
- return true;
- }
- break;
- }
- }
-
- return false;
-} // cs_connection
-
-// PRIVATE functions
-// **************************************************************************
-
-/// Add cscope database or a directory name (to look for cscope.out)
-/// to the cscope connection list.
-static int cs_add(exarg_T *eap)
-{
- char *fname, *ppath, *flags = NULL;
-
- if ((fname = strtok((char *)NULL, (const char *)" ")) == NULL) {
- cs_usage_msg(Add);
- return CSCOPE_FAILURE;
- }
- if ((ppath = strtok((char *)NULL, (const char *)" ")) != NULL) {
- flags = strtok((char *)NULL, (const char *)" ");
- }
-
- return cs_add_common(fname, ppath, flags);
-}
-
-static void cs_stat_emsg(char *fname)
-{
- int err = errno;
- (void)semsg(_("E563: stat(%s) error: %d"), fname, err);
-}
-
-/// The common routine to add a new cscope connection. Called by
-/// cs_add() and cs_reset(). I really don't like to do this, but this
-/// routine uses a number of goto statements.
-///
-/// @param arg1 filename - may contain environment variables
-/// @param arg2 prepend path - may contain environment variables
-static int cs_add_common(char *arg1, char *arg2, char *flags)
-{
- char *fname = NULL;
- char *fname2 = NULL;
- char *ppath = NULL;
- size_t usedlen = 0;
- char *fbuf = NULL;
-
- // get the filename (arg1), expand it, and try to stat it
- fname = xmalloc(MAXPATHL + 1);
-
- expand_env(arg1, fname, MAXPATHL);
- size_t len = strlen(fname);
- fbuf = fname;
- (void)modify_fname(":p", false, &usedlen, &fname, &fbuf, &len);
- if (fname == NULL) {
- goto add_err;
- }
- fname = xstrnsave(fname, len);
- xfree(fbuf);
- FileInfo file_info;
- bool file_info_ok = os_fileinfo(fname, &file_info);
- if (!file_info_ok) {
-staterr:
- if (p_csverbose) {
- cs_stat_emsg(fname);
- }
- goto add_err;
- }
-
- // get the prepend path (arg2), expand it, and see if it exists
- if (arg2 != NULL) {
- ppath = xmalloc(MAXPATHL + 1);
- expand_env(arg2, ppath, MAXPATHL);
- if (!os_path_exists(ppath)) {
- goto staterr;
- }
- }
-
- int i;
- // if filename is a directory, append the cscope database name to it
- if (S_ISDIR(file_info.stat.st_mode)) {
- fname2 = (char *)xmalloc(strlen(CSCOPE_DBFILE) + strlen(fname) + 2);
-
- while (fname[strlen(fname) - 1] == '/'
- ) {
- fname[strlen(fname) - 1] = '\0';
- if (fname[0] == '\0') {
- break;
- }
- }
- if (fname[0] == '\0') {
- (void)sprintf(fname2, "/%s", CSCOPE_DBFILE);
- } else {
- (void)sprintf(fname2, "%s/%s", fname, CSCOPE_DBFILE);
- }
-
- file_info_ok = os_fileinfo(fname2, &file_info);
- if (!file_info_ok) {
- if (p_csverbose) {
- cs_stat_emsg(fname2);
- }
- goto add_err;
- }
-
- i = cs_insert_filelist(fname2, ppath, flags, &file_info);
- } else if (S_ISREG(file_info.stat.st_mode) || S_ISLNK(file_info.stat.st_mode)) {
- i = cs_insert_filelist(fname, ppath, flags, &file_info);
- } else {
- if (p_csverbose) {
- (void)semsg(_("E564: %s is not a directory or a valid cscope database"),
- fname);
- }
- goto add_err;
- }
-
- if (i != -1) {
- assert(i >= 0);
- if (cs_create_connection((size_t)i) == CSCOPE_FAILURE
- || cs_read_prompt((size_t)i) == CSCOPE_FAILURE) {
- cs_release_csp((size_t)i, true);
- goto add_err;
- }
-
- if (p_csverbose) {
- msg_clr_eos();
- (void)smsg_attr(HL_ATTR(HLF_R),
- _("Added cscope database %s"),
- csinfo[i].fname);
- }
- }
-
- xfree(fname);
- xfree(fname2);
- xfree(ppath);
- return CSCOPE_SUCCESS;
-
-add_err:
- xfree(fname2);
- xfree(fname);
- xfree(ppath);
- return CSCOPE_FAILURE;
-}
-
-static bool cs_check_for_connections(void)
-{
- return cs_cnt_connections() > 0;
-}
-
-static int cs_check_for_tags(void)
-{
- return p_tags[0] != NUL && curbuf->b_p_tags != NULL;
-}
-
-/// Count the number of cscope connections.
-static size_t cs_cnt_connections(void)
-{
- size_t cnt = 0;
-
- for (size_t i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname != NULL) {
- cnt++;
- }
- }
- return cnt;
-}
-
-/// @param idx connection index
-static void cs_reading_emsg(size_t idx)
-{
- semsg(_("E262: error reading cscope connection %" PRIu64), (uint64_t)idx);
-}
-
-#define CSREAD_BUFSIZE 2048
-/// Count the number of matches for a given cscope connection.
-static int cs_cnt_matches(size_t idx)
-{
- char *stok;
- int nlines = 0;
-
- char *buf = xmalloc(CSREAD_BUFSIZE);
- for (;;) {
- errno = 0;
- if (!fgets(buf, CSREAD_BUFSIZE, csinfo[idx].fr_fp)) {
- if (errno == EINTR) {
- continue;
- }
-
- if (feof(csinfo[idx].fr_fp)) {
- errno = EIO;
- }
-
- cs_reading_emsg(idx);
-
- xfree(buf);
- return CSCOPE_FAILURE;
- }
-
- // If the database is out of date, or there's some other problem,
- // cscope will output error messages before the number-of-lines output.
- // Display/discard any output that doesn't match what we want.
- // Accept "\S*cscope: X lines", also matches "mlcscope".
- // Bail out for the "Unable to search" error.
- if (strstr((const char *)buf, "Unable to search database") != NULL) {
- break;
- }
- if ((stok = strtok(buf, (const char *)" ")) == NULL) {
- continue;
- }
- if (strstr((const char *)stok, "cscope:") == NULL) {
- continue;
- }
-
- if ((stok = strtok(NULL, (const char *)" ")) == NULL) {
- continue;
- }
- nlines = atoi(stok);
- if (nlines < 0) {
- nlines = 0;
- break;
- }
-
- if ((stok = strtok(NULL, (const char *)" ")) == NULL) {
- continue;
- }
- if (strncmp(stok, "lines", 5)) {
- continue;
- }
-
- break;
- }
-
- xfree(buf);
- return nlines;
-}
-
-/// Creates the actual cscope command query from what the user entered.
-static char *cs_create_cmd(char *csoption, char *pattern)
-{
- char *cmd;
- short search;
- char *pat;
-
- switch (csoption[0]) {
- case '0':
- case 's':
- search = 0;
- break;
- case '1':
- case 'g':
- search = 1;
- break;
- case '2':
- case 'd':
- search = 2;
- break;
- case '3':
- case 'c':
- search = 3;
- break;
- case '4':
- case 't':
- search = 4;
- break;
- case '6':
- case 'e':
- search = 6;
- break;
- case '7':
- case 'f':
- search = 7;
- break;
- case '8':
- case 'i':
- search = 8;
- break;
- case '9':
- case 'a':
- search = 9;
- break;
- default:
- (void)emsg(_("E561: unknown cscope search type"));
- cs_usage_msg(Find);
- return NULL;
- }
-
- // Skip white space before the pattern, except for text and pattern search,
- // they may want to use the leading white space.
- pat = pattern;
- if (search != 4 && search != 6) {
- while (ascii_iswhite(*pat)) {
- pat++;
- }
- }
-
- cmd = xmalloc(strlen(pat) + 2);
-
- (void)sprintf(cmd, "%d%s", search, pat);
-
- return cmd;
-}
-
-/// This piece of code was taken/adapted from nvi. do we need to add
-/// the BSD license notice?
-static int cs_create_connection(size_t i)
-{
-#ifdef UNIX
- int to_cs[2], from_cs[2];
-#endif
- char *prog, *cmd, *ppath = NULL;
-
-#if defined(UNIX)
- // Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
- // from_cs[0] and writes to to_cs[1].
- to_cs[0] = to_cs[1] = from_cs[0] = from_cs[1] = -1;
- if (pipe(to_cs) < 0 || pipe(from_cs) < 0) {
- (void)emsg(_("E566: Could not create cscope pipes"));
-err_closing:
- if (to_cs[0] != -1) {
- (void)close(to_cs[0]);
- }
- if (to_cs[1] != -1) {
- (void)close(to_cs[1]);
- }
- if (from_cs[0] != -1) {
- (void)close(from_cs[0]);
- }
- if (from_cs[1] != -1) {
- (void)close(from_cs[1]);
- }
- return CSCOPE_FAILURE;
- }
-
- switch (csinfo[i].pid = fork()) {
- case -1:
- (void)emsg(_("E622: Could not fork for cscope"));
- goto err_closing;
- case 0: // child: run cscope.
- if (dup2(to_cs[0], STDIN_FILENO) == -1) {
- PERROR("cs_create_connection 1");
- }
- if (dup2(from_cs[1], STDOUT_FILENO) == -1) {
- PERROR("cs_create_connection 2");
- }
- if (dup2(from_cs[1], STDERR_FILENO) == -1) {
- PERROR("cs_create_connection 3");
- }
-
- // close unused
- (void)close(to_cs[1]);
- (void)close(from_cs[0]);
-#else
- // Create pipes to communicate with cscope
- int fd;
- SECURITY_ATTRIBUTES sa;
- PROCESS_INFORMATION pi;
- BOOL pipe_stdin = FALSE, pipe_stdout = FALSE; // NOLINT(readability/bool)
- STARTUPINFO si;
- HANDLE stdin_rd, stdout_rd;
- HANDLE stdout_wr, stdin_wr;
- BOOL created;
-
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
-
- if (!(pipe_stdin = CreatePipe(&stdin_rd, &stdin_wr, &sa, 0))
- || !(pipe_stdout = CreatePipe(&stdout_rd, &stdout_wr, &sa, 0))) {
- (void)emsg(_("E566: Could not create cscope pipes"));
-err_closing:
- if (pipe_stdin) {
- CloseHandle(stdin_rd);
- CloseHandle(stdin_wr);
- }
- if (pipe_stdout) {
- CloseHandle(stdout_rd);
- CloseHandle(stdout_wr);
- }
- return CSCOPE_FAILURE;
- }
-#endif
- // expand the cscope exec for env var's
- prog = xmalloc(MAXPATHL + 1);
- expand_env(p_csprg, prog, MAXPATHL);
-
- // alloc space to hold the cscope command
- size_t len = strlen(prog) + strlen(csinfo[i].fname) + 32;
- if (csinfo[i].ppath) {
- // expand the prepend path for env var's
- ppath = xmalloc(MAXPATHL + 1);
- expand_env(csinfo[i].ppath, ppath, MAXPATHL);
-
- len += strlen(ppath);
- }
-
- if (csinfo[i].flags) {
- len += strlen(csinfo[i].flags);
- }
-
- cmd = xmalloc(len);
-
- // run the cscope command; is there execl for non-unix systems?
-#if defined(UNIX)
- (void)snprintf(cmd, len, "exec %s -dl -f %s", prog, csinfo[i].fname);
-#else
- // MS-Windows
- (void)snprintf(cmd, len, "%s -dl -f %s", prog, csinfo[i].fname);
-#endif
- if (csinfo[i].ppath != NULL) {
- (void)strcat(cmd, " -P");
- (void)strcat(cmd, csinfo[i].ppath);
- }
- if (csinfo[i].flags != NULL) {
- (void)strcat(cmd, " ");
- (void)strcat(cmd, csinfo[i].flags);
- }
-#ifdef UNIX
- // on Win32 we still need prog
- xfree(prog);
-#endif
- xfree(ppath);
-
-#if defined(UNIX)
-# if defined(HAVE_SETSID) || defined(HAVE_SETPGID)
- // Change our process group to avoid cscope receiving SIGWINCH.
-# if defined(HAVE_SETSID)
- (void)setsid();
-# else
- if (setpgid(0, 0) == -1) {
- PERROR(_("cs_create_connection setpgid failed"));
- }
-# endif
-# endif
- if (execl("/bin/sh", "sh", "-c", cmd, (char *)NULL) == -1) {
- PERROR(_("cs_create_connection exec failed"));
- }
-
- exit(127);
- // NOTREACHED
- default: // parent.
- // Save the file descriptors for later duplication, and
- // reopen as streams.
- if ((csinfo[i].to_fp = fdopen(to_cs[1], "w")) == NULL) {
- PERROR(_("cs_create_connection: fdopen for to_fp failed"));
- }
- if ((csinfo[i].fr_fp = fdopen(from_cs[0], "r")) == NULL) {
- PERROR(_("cs_create_connection: fdopen for fr_fp failed"));
- }
-
- // close unused
- (void)close(to_cs[0]);
- (void)close(from_cs[1]);
-
- break;
- }
-
-#else
- // MS-Windows
- // Create a new process to run cscope and use pipes to talk with it
- GetStartupInfo(&si);
- si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE; // Hide child application window
- si.hStdOutput = stdout_wr;
- si.hStdError = stdout_wr;
- si.hStdInput = stdin_rd;
- created = CreateProcess(NULL, cmd, NULL, NULL, true, CREATE_NEW_CONSOLE,
- NULL, NULL, &si, &pi);
- xfree(prog);
- xfree(cmd);
-
- if (!created) {
- PERROR(_("cs_create_connection exec failed"));
- (void)emsg(_("E623: Could not spawn cscope process"));
- goto err_closing;
- }
- // else
- csinfo[i].pid = pi.dwProcessId;
- csinfo[i].hProc = pi.hProcess;
- CloseHandle(pi.hThread);
-
- // TODO(neovim): tidy up after failure to create files on pipe handles.
- if (((fd = _open_osfhandle((intptr_t)stdin_wr, _O_TEXT|_O_APPEND)) < 0)
- || ((csinfo[i].to_fp = _fdopen(fd, "w")) == NULL)) {
- PERROR(_("cs_create_connection: fdopen for to_fp failed"));
- }
- if (((fd = _open_osfhandle((intptr_t)stdout_rd, _O_TEXT|_O_RDONLY)) < 0)
- || ((csinfo[i].fr_fp = _fdopen(fd, "r")) == NULL)) {
- PERROR(_("cs_create_connection: fdopen for fr_fp failed"));
- }
- // Close handles for file descriptors inherited by the cscope process.
- CloseHandle(stdin_rd);
- CloseHandle(stdout_wr);
-
-#endif // !UNIX
-
- return CSCOPE_SUCCESS;
-}
-
-/// Query cscope using command line interface. Parse the output and use tselect
-/// to allow choices. Like Nvi, creates a pipe to send to/from query/cscope.
-///
-/// @return true if we jump to a tag or abort, false if not.
-static int cs_find(exarg_T *eap)
-{
- char *opt, *pat;
-
- if (cs_check_for_connections() == false) {
- (void)emsg(_("E567: no cscope connections"));
- return false;
- }
-
- if ((opt = strtok((char *)NULL, (const char *)" ")) == NULL) {
- cs_usage_msg(Find);
- return false;
- }
-
- pat = opt + strlen(opt) + 1;
- if (pat >= eap->arg + eap_arg_len) {
- cs_usage_msg(Find);
- return false;
- }
-
- // Let's replace the NULs written by strtok() with spaces - we need the
- // spaces to correctly display the quickfix/location list window's title.
- for (int i = 0; i < eap_arg_len; i++) {
- if (NUL == eap->arg[i]) {
- eap->arg[i] = ' ';
- }
- }
-
- return cs_find_common(opt, pat, eap->forceit, true,
- eap->cmdidx == CMD_lcscope, (char_u *)(*eap->cmdlinep));
-}
-
-/// Common code for cscope find, shared by cs_find() and ex_cstag().
-static bool cs_find_common(char *opt, char *pat, int forceit, int verbose, bool use_ll,
- char_u *cmdline)
-{
- char *cmd;
- int *nummatches;
- size_t totmatches;
- char cmdletter;
- char *qfpos;
-
- // get cmd letter
- switch (opt[0]) {
- case '0':
- cmdletter = 's';
- break;
- case '1':
- cmdletter = 'g';
- break;
- case '2':
- cmdletter = 'd';
- break;
- case '3':
- cmdletter = 'c';
- break;
- case '4':
- cmdletter = 't';
- break;
- case '6':
- cmdletter = 'e';
- break;
- case '7':
- cmdletter = 'f';
- break;
- case '8':
- cmdletter = 'i';
- break;
- case '9':
- cmdletter = 'a';
- break;
- default:
- cmdletter = opt[0];
- }
-
- qfpos = vim_strchr(p_csqf, cmdletter);
- if (qfpos != NULL) {
- qfpos++;
- // next symbol must be + or -
- if (strchr(CSQF_FLAGS, *qfpos) == NULL) {
- (void)semsg(_("E469: invalid cscopequickfix flag %c for %c"), *qfpos, *(qfpos - 1));
- return false;
- }
-
- if (*qfpos != '0'
- && apply_autocmds(EVENT_QUICKFIXCMDPRE, "cscope", curbuf->b_fname, true, curbuf)) {
- if (aborting()) {
- return false;
- }
- }
- }
-
- // create the actual command to send to cscope
- cmd = cs_create_cmd(opt, pat);
- if (cmd == NULL) {
- return false;
- }
-
- nummatches = xmalloc(sizeof(int) * csinfo_size);
-
- // Send query to all open connections, then count the total number
- // of matches so we can alloc all in one swell foop.
- for (size_t i = 0; i < csinfo_size; i++) {
- nummatches[i] = 0;
- }
- totmatches = 0;
- for (size_t i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname == NULL || csinfo[i].to_fp == NULL) {
- continue;
- }
-
- // send cmd to cscope
- (void)fprintf(csinfo[i].to_fp, "%s\n", cmd);
- (void)fflush(csinfo[i].to_fp);
-
- nummatches[i] = cs_cnt_matches(i);
-
- if (nummatches[i] > -1) {
- totmatches += (size_t)nummatches[i];
- }
-
- if (nummatches[i] == 0) {
- (void)cs_read_prompt(i);
- }
- }
- xfree(cmd);
-
- if (totmatches == 0) {
- if (verbose) {
- (void)semsg(_("E259: no matches found for cscope query %s of %s"), opt, pat);
- }
- xfree(nummatches);
- return false;
- }
-
- if (qfpos != NULL && *qfpos != '0') {
- // Fill error list.
- FILE *f;
- char_u *tmp = (char_u *)vim_tempname();
- qf_info_T *qi = NULL;
- win_T *wp = NULL;
-
- f = os_fopen((char *)tmp, "w");
- if (f == NULL) {
- semsg(_(e_notopen), tmp);
- } else {
- cs_file_results(f, nummatches);
- fclose(f);
- if (use_ll) { // Use location list
- wp = curwin;
- }
- // '-' starts a new error list
- if (qf_init(wp, (char *)tmp, "%f%*\\t%l%*\\t%m",
- *qfpos == '-', (char *)cmdline, NULL) > 0) {
- if (postponed_split != 0) {
- (void)win_split(postponed_split > 0 ? postponed_split : 0,
- postponed_split_flags);
- RESET_BINDING(curwin);
- postponed_split = 0;
- }
-
- apply_autocmds(EVENT_QUICKFIXCMDPOST, "cscope", curbuf->b_fname, true, curbuf);
- if (use_ll) {
- // In the location list window, use the displayed location
- // list. Otherwise, use the location list for the window.
- qi = (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)
- ? wp->w_llist_ref : wp->w_llist;
- }
- qf_jump(qi, 0, 0, forceit);
- }
- }
- os_remove((char *)tmp);
- xfree(tmp);
- xfree(nummatches);
- return true;
- } else {
- char **matches = NULL, **contexts = NULL;
- size_t matched = 0;
-
- // read output
- cs_fill_results(pat, totmatches, nummatches, &matches, &contexts, &matched);
- xfree(nummatches);
- if (matches == NULL) {
- return false;
- }
-
- (void)cs_manage_matches(matches, contexts, matched, Store);
-
- return do_tag(pat, DT_CSCOPE, 0, forceit, verbose);
- }
-}
-
-/// Print help.
-static int cs_help(exarg_T *eap)
-{
- cscmd_T *cmdp = cs_cmds;
-
- (void)msg_puts(_("cscope commands:\n"));
- while (cmdp->name != NULL) {
- char *help = _(cmdp->help);
- int space_cnt = 30 - vim_strsize(help);
-
- // Use %*s rather than %30s to ensure proper alignment in utf-8
- if (space_cnt < 0) {
- space_cnt = 0;
- }
- (void)smsg(_("%-5s: %s%*s (Usage: %s)"),
- cmdp->name,
- help, space_cnt, " ",
- cmdp->usage);
- if (strcmp(cmdp->name, "find") == 0) {
- msg_puts(_("\n"
- " a: Find assignments to this symbol\n"
- " c: Find functions calling this function\n"
- " d: Find functions called by this function\n"
- " e: Find this egrep pattern\n"
- " f: Find this file\n"
- " g: Find this definition\n"
- " i: Find files #including this file\n"
- " s: Find this C symbol\n"
- " t: Find this text string\n"));
- }
-
- cmdp++;
- }
-
- wait_return(true);
- return CSCOPE_SUCCESS;
-}
-
-static void clear_csinfo(size_t i)
-{
- csinfo[i].fname = NULL;
- csinfo[i].ppath = NULL;
- csinfo[i].flags = NULL;
- csinfo[i].file_id = FILE_ID_EMPTY;
- csinfo[i].pid = 0;
- csinfo[i].fr_fp = NULL;
- csinfo[i].to_fp = NULL;
-}
-
-/// Insert a new cscope database filename into the filelist.
-static int cs_insert_filelist(char *fname, char *ppath, char *flags, FileInfo *file_info)
-{
- size_t i = 0;
- bool empty_found = false;
-
- for (size_t j = 0; j < csinfo_size; j++) {
- if (csinfo[j].fname != NULL
- && os_fileid_equal_fileinfo(&(csinfo[j].file_id), file_info)) {
- if (p_csverbose) {
- (void)emsg(_("E568: duplicate cscope database not added"));
- }
- return CSCOPE_FAILURE;
- }
-
- if (csinfo[j].fname == NULL && !empty_found) {
- i = j; // remember first empty entry
- empty_found = true;
- }
- }
-
- if (!empty_found) {
- i = csinfo_size;
- if (csinfo_size == 0) {
- // First time allocation: allocate only 1 connection. It should
- // be enough for most users. If more is needed, csinfo will be
- // reallocated.
- csinfo_size = 1;
- csinfo = xcalloc(1, sizeof(csinfo_T));
- } else {
- // Reallocate space for more connections.
- csinfo_size *= 2;
- csinfo = xrealloc(csinfo, sizeof(csinfo_T)*csinfo_size);
- }
- for (size_t j = csinfo_size/2; j < csinfo_size; j++) {
- clear_csinfo(j);
- }
- }
-
- csinfo[i].fname = xmalloc(strlen(fname) + 1);
-
- (void)strcpy(csinfo[i].fname, (const char *)fname);
-
- if (ppath != NULL) {
- csinfo[i].ppath = xmalloc(strlen(ppath) + 1);
- (void)strcpy(csinfo[i].ppath, (const char *)ppath);
- } else {
- csinfo[i].ppath = NULL;
- }
-
- if (flags != NULL) {
- csinfo[i].flags = xmalloc(strlen(flags) + 1);
- (void)strcpy(csinfo[i].flags, (const char *)flags);
- } else {
- csinfo[i].flags = NULL;
- }
-
- os_fileinfo_id(file_info, &(csinfo[i].file_id));
- assert(i <= INT_MAX);
- return (int)i;
-}
-
-/// Find cscope command in command table.
-static cscmd_T *cs_lookup_cmd(exarg_T *eap)
-{
- cscmd_T *cmdp;
- char *stok;
- size_t len;
-
- if (eap->arg == NULL) {
- return NULL;
- }
-
- // Store length of eap->arg before it gets modified by strtok().
- eap_arg_len = (int)strlen(eap->arg);
-
- if ((stok = strtok(eap->arg, (const char *)" ")) == NULL) { // NOLINT(runtime/threadsafe_fn)
- return NULL;
- }
-
- len = strlen(stok);
- for (cmdp = cs_cmds; cmdp->name != NULL; cmdp++) {
- if (strncmp(stok, cmdp->name, len) == 0) {
- return cmdp;
- }
- }
- return NULL;
-}
-
-/// Nuke em.
-static int cs_kill(exarg_T *eap)
-{
- char *stok;
- int num;
- size_t i = 0;
- bool killall = false;
-
- if ((stok = strtok((char *)NULL, (const char *)" ")) == NULL) {
- cs_usage_msg(Kill);
- return CSCOPE_FAILURE;
- }
-
- // Check if string is a number, only single digit
- // positive and negative integers are allowed
- if ((strlen(stok) < 2 && ascii_isdigit((int)(stok[0])))
- || (strlen(stok) < 3 && stok[0] == '-'
- && ascii_isdigit((int)(stok[1])))) {
- num = atoi(stok);
- if (num == -1) {
- killall = true;
- } else if (num >= 0) {
- i = (size_t)num;
- } else { // All negative values besides -1 are invalid.
- if (p_csverbose) {
- (void)semsg(_("E261: cscope connection %s not found"), stok);
- }
- return CSCOPE_FAILURE;
- }
- } else {
- // Else it must be part of a name. We will try to find a match
- // within all the names in the csinfo data structure
- for (i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname != NULL && strstr(csinfo[i].fname, stok)) {
- break;
- }
- }
- }
-
- if (!killall && (i >= csinfo_size || csinfo[i].fname == NULL)) {
- if (p_csverbose) {
- (void)semsg(_("E261: cscope connection %s not found"), stok);
- }
- return CSCOPE_FAILURE;
- } else {
- if (killall) {
- for (i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname) {
- cs_kill_execute(i, csinfo[i].fname);
- }
- }
- } else {
- cs_kill_execute(i, stok);
- }
- }
-
- return CSCOPE_SUCCESS;
-}
-
-/// Actually kills a specific cscope connection.
-///
-/// @param i cscope table index
-/// @param cname cscope database name
-static void cs_kill_execute(size_t i, char *cname)
-{
- if (p_csverbose) {
- msg_clr_eos();
- (void)smsg_attr(HL_ATTR(HLF_R) | MSG_HIST,
- _("cscope connection %s closed"), cname);
- }
- cs_release_csp(i, true);
-}
-
-/// Convert the cscope output into a ctags style entry (as might be found
-/// in a ctags tags file). there's one catch though: cscope doesn't tell you
-/// the type of the tag you are looking for. for example, in Darren Hiebert's
-/// ctags (the one that comes with vim), #define's use a line number to find the
-/// tag in a file while function definitions use a regexp search pattern.
-///
-/// I'm going to always use the line number because cscope does something
-/// quirky (and probably other things i don't know about):
-///
-/// if you have "# define" in your source file, which is
-/// perfectly legal, cscope thinks you have "#define". this
-/// will result in a failed regexp search. :(
-///
-/// Besides, even if this particular case didn't happen, the search pattern
-/// would still have to be modified to escape all the special regular expression
-/// characters to comply with ctags formatting.
-static char *cs_make_vim_style_matches(char *fname, char *slno, char *search, char *tagstr)
-{
- // vim style is ctags:
- //
- // <tagstr>\t<filename>\t<linenum_or_search>"\t<extra>
- //
- // but as mentioned above, we'll always use the line number and
- // put the search pattern (if one exists) as "extra"
- //
- // buf is used as part of vim's method of handling tags, and
- // (i think) vim frees it when you pop your tags and get replaced
- // by new ones on the tag stack.
- char *buf;
- size_t amt;
-
- if (search != NULL) {
- amt = strlen(fname) + strlen(slno) + strlen(tagstr) + strlen(search) + 6;
- buf = xmalloc(amt);
-
- (void)sprintf(buf, "%s\t%s\t%s;\"\t%s", tagstr, fname, slno, search);
- } else {
- amt = strlen(fname) + strlen(slno) + strlen(tagstr) + 5;
- buf = xmalloc(amt);
-
- (void)sprintf(buf, "%s\t%s\t%s;\"", tagstr, fname, slno);
- }
-
- return buf;
-}
-
-/// This is kind of hokey, but i don't see an easy way round this.
-///
-/// Store: keep a ptr to the (malloc'd) memory of matches originally
-/// generated from cs_find(). the matches are originally lines directly
-/// from cscope output, but transformed to look like something out of a
-/// ctags. see cs_make_vim_style_matches for more details.
-///
-/// Get: used only from cs_fgets(), this simulates a vim_fgets() to return
-/// the next line from the cscope output. it basically keeps track of which
-/// lines have been "used" and returns the next one.
-///
-/// Free: frees up everything and resets
-///
-/// Print: prints the tags
-static char *cs_manage_matches(char **matches, char **contexts, size_t totmatches, mcmd_e cmd)
-{
- static char **mp = NULL;
- static char **cp = NULL;
- static size_t cnt = 0;
- static size_t next = 0;
- char *p = NULL;
-
- switch (cmd) {
- case Store:
- assert(matches != NULL);
- assert(totmatches > 0);
- if (mp != NULL || cp != NULL) {
- (void)cs_manage_matches(NULL, NULL, 0, Free);
- }
- mp = matches;
- cp = contexts;
- cnt = totmatches;
- next = 0;
- break;
- case Get:
- if (next >= cnt) {
- return NULL;
- }
-
- p = mp[next];
- next++;
- break;
- case Free:
- if (mp != NULL) {
- while (cnt--) {
- xfree(mp[cnt]);
- if (cp != NULL) {
- xfree(cp[cnt]);
- }
- }
- xfree(mp);
- xfree(cp);
- }
- mp = NULL;
- cp = NULL;
- cnt = 0;
- next = 0;
- break;
- case Print:
- assert(mp != NULL);
- assert(cp != NULL);
- cs_print_tags_priv(mp, cp, cnt);
- break;
- default: // should not reach here
- iemsg(_("E570: fatal error in cs_manage_matches"));
- return NULL;
- }
-
- return p;
-}
-
-/// Parse cscope output.
-static char *cs_parse_results(size_t cnumber, char *buf, int bufsize, char **context,
- char **linenumber, char **search)
-{
- int ch;
- char *p;
- char *name;
-
-retry:
- errno = 0;
- if (fgets(buf, bufsize, csinfo[cnumber].fr_fp) == NULL) {
- if (errno == EINTR) {
- goto retry;
- }
-
- if (feof(csinfo[cnumber].fr_fp)) {
- errno = EIO;
- }
-
- cs_reading_emsg(cnumber);
-
- return NULL;
- }
-
- // If the line's too long for the buffer, discard it.
- if ((p = strchr(buf, '\n')) == NULL) {
- while ((ch = getc(csinfo[cnumber].fr_fp)) != EOF && ch != '\n') {}
- return NULL;
- }
- *p = '\0';
-
- // cscope output is in the following format:
- //
- // <filename> <context> <line number> <pattern>
- char *saveptr = NULL;
- if ((name = os_strtok(buf, (const char *)" ", &saveptr)) == NULL) {
- return NULL;
- }
- if ((*context = os_strtok(NULL, (const char *)" ", &saveptr)) == NULL) {
- return NULL;
- }
- if ((*linenumber = os_strtok(NULL, (const char *)" ", &saveptr)) == NULL) {
- return NULL;
- }
- *search = *linenumber + strlen(*linenumber) + 1; // +1 to skip \0
-
- // --- nvi ---
- // If the file is older than the cscope database, that is,
- // the database was built since the file was last modified,
- // or there wasn't a search string, use the line number.
- if (strcmp(*search, "<unknown>") == 0) {
- *search = NULL;
- }
-
- name = cs_resolve_file(cnumber, name);
- return name;
-}
-
-/// Write cscope find results to file.
-static void cs_file_results(FILE *f, int *nummatches_a)
-{
- char *search, *slno;
- char *fullname;
- char *cntx;
- char *context;
-
- char *buf = xmalloc(CSREAD_BUFSIZE);
-
- for (size_t i = 0; i < csinfo_size; i++) {
- if (nummatches_a[i] < 1) {
- continue;
- }
-
- for (int j = 0; j < nummatches_a[i]; j++) {
- if ((fullname = cs_parse_results(i, buf, CSREAD_BUFSIZE, &cntx,
- &slno, &search)) == NULL) {
- continue;
- }
-
- size_t context_len = strlen(cntx) + 5;
- context = xmalloc(context_len);
-
- if (strcmp(cntx, "<global>") == 0) {
- xstrlcpy(context, "<<global>>", context_len);
- } else {
- snprintf(context, context_len, "<<%s>>", cntx);
- }
-
- if (search == NULL) {
- fprintf(f, "%s\t%s\t%s\n", fullname, slno, context);
- } else {
- fprintf(f, "%s\t%s\t%s %s\n", fullname, slno, context, search);
- }
-
- xfree(context);
- xfree(fullname);
- } // for all matches
-
- (void)cs_read_prompt(i);
- } // for all cscope connections
- xfree(buf);
-}
-
-/// Get parsed cscope output and calls cs_make_vim_style_matches to convert
-/// into ctags format.
-/// When there are no matches sets "*matches_p" to NULL.
-static void cs_fill_results(char *tagstr, size_t totmatches, int *nummatches_a, char ***matches_p,
- char ***cntxts_p, size_t *matched)
-{
- char *buf;
- char *search, *slno;
- size_t totsofar = 0;
- char **matches = NULL;
- char **cntxts = NULL;
- char *fullname;
- char *cntx;
-
- assert(totmatches > 0);
-
- buf = xmalloc(CSREAD_BUFSIZE);
- matches = xmalloc(sizeof(char *) * totmatches);
- cntxts = xmalloc(sizeof(char *) * totmatches);
-
- for (size_t i = 0; i < csinfo_size; i++) {
- if (nummatches_a[i] < 1) {
- continue;
- }
-
- for (int j = 0; j < nummatches_a[i]; j++) {
- if ((fullname = cs_parse_results(i, buf, CSREAD_BUFSIZE, &cntx,
- &slno, &search)) == NULL) {
- continue;
- }
-
- matches[totsofar] = cs_make_vim_style_matches(fullname, slno, search,
- tagstr);
-
- xfree(fullname);
-
- if (strcmp(cntx, "<global>") == 0) {
- cntxts[totsofar] = NULL;
- } else {
- cntxts[totsofar] = xstrdup(cntx);
- }
-
- totsofar++;
- } // for all matches
-
- (void)cs_read_prompt(i);
- } // for all cscope connections
-
- if (totsofar == 0) {
- // No matches, free the arrays and return NULL in "*matches_p".
- XFREE_CLEAR(matches);
- XFREE_CLEAR(cntxts);
- }
- *matched = totsofar;
- *matches_p = matches;
- *cntxts_p = cntxts;
-
- xfree(buf);
-}
-
-// get the requested path components
-static char *cs_pathcomponents(char *path)
-{
- if (p_cspc == 0) {
- return path;
- }
-
- char *s = path + strlen(path) - 1;
- for (int i = 0; i < p_cspc; i++) {
- while (s > path && *--s != '/') {}
- }
- if ((s > path && *s == '/')) {
- s++;
- }
- return s;
-}
-
-/// Print cscope output that was converted into ctags style entries.
-///
-/// Only called from cs_manage_matches().
-///
-/// @param matches Array of cscope lines in ctags style. Every entry was
-// produced with a format string of the form
-// "%s\t%s\t%s;\"\t%s" or
-// "%s\t%s\t%s;\""
-// by cs_make_vim_style_matches().
-/// @param cntxts Context for matches.
-/// @param num_matches Number of entries in matches/cntxts, always greater 0.
-static void cs_print_tags_priv(char **matches, char **cntxts,
- size_t num_matches) FUNC_ATTR_NONNULL_ALL
-{
- char *globalcntx = "GLOBAL";
- char *cstag_msg = _("Cscope tag: %s");
-
- assert(num_matches > 0);
- assert(strcnt(matches[0], '\t') >= 2);
-
- char *ptag = matches[0];
- char *ptag_end = strchr(ptag, '\t');
- assert(ptag_end >= ptag);
- // NUL terminate tag string in matches[0].
- *ptag_end = NUL;
-
- // The "%s" in cstag_msg won't appear in the result string, so we don't need
- // extra memory for terminating NUL.
- size_t newsize = strlen(cstag_msg) + (size_t)(ptag_end - ptag);
- char *buf = xmalloc(newsize);
- size_t bufsize = newsize; // Track available bufsize
- (void)snprintf(buf, bufsize, cstag_msg, ptag);
- msg_puts_attr(buf, HL_ATTR(HLF_T));
- msg_clr_eos();
-
- // restore matches[0]
- *ptag_end = '\t';
-
- // Column headers for match number, line number and filename.
- msg_puts_attr(_("\n # line"), HL_ATTR(HLF_T));
- msg_advance(msg_col + 2);
- msg_puts_attr(_("filename / context / line\n"), HL_ATTR(HLF_T));
-
- for (size_t i = 0; i < num_matches; i++) {
- assert(strcnt(matches[i], '\t') >= 2);
-
- // Parse filename, line number and optional part.
- char *fname = strchr(matches[i], '\t') + 1;
- char *fname_end = strchr(fname, '\t');
- // Replace second '\t' in matches[i] with NUL to terminate fname.
- *fname_end = NUL;
-
- char *lno = fname_end + 1;
- char *extra = xstrchrnul(lno, '\t');
- // Ignore ;" at the end of lno.
- char *lno_end = extra - 2;
- *lno_end = NUL;
- // Do we have an optional part?
- extra = *extra ? extra + 1 : NULL;
-
- const char *csfmt_str = "%4zu %6s ";
- // hopefully num_matches will be less than 10^16
- newsize = strlen(csfmt_str) + 16 + (size_t)(lno_end - lno);
- if (bufsize < newsize) {
- buf = xrealloc(buf, newsize);
- bufsize = newsize;
- }
- (void)snprintf(buf, bufsize, csfmt_str, i + 1, lno);
- msg_puts_attr(buf, HL_ATTR(HLF_CM));
- msg_outtrans_long_attr(cs_pathcomponents(fname), HL_ATTR(HLF_CM));
-
- // compute the required space for the context
- char *context = cntxts[i] ? cntxts[i] : globalcntx;
-
- const char *cntxformat = " <<%s>>";
- // '%s' won't appear in result string, so:
- // newsize = len(cntxformat) - 2 + len(context) + 1 (for NUL).
- newsize = strlen(context) + strlen(cntxformat) - 1;
-
- if (bufsize < newsize) {
- buf = xrealloc(buf, newsize);
- bufsize = newsize;
- }
- int buf_len = snprintf(buf, bufsize, cntxformat, context);
- assert(buf_len >= 0);
-
- // Print the context only if it fits on the same line.
- if (msg_col + buf_len >= Columns) {
- msg_putchar('\n');
- }
- msg_advance(12);
- msg_outtrans_long_attr(buf, 0);
- msg_putchar('\n');
- if (extra != NULL) {
- msg_advance(13);
- msg_outtrans_long_attr(extra, 0);
- }
-
- // restore matches[i]
- *fname_end = '\t';
- *lno_end = ';';
-
- if (msg_col) {
- msg_putchar('\n');
- }
-
- os_breakcheck();
- if (got_int) {
- got_int = false; // don't print any more matches
- break;
- }
- }
-
- xfree(buf);
-}
-
-/// Read a cscope prompt (basically, skip over the ">> ").
-static int cs_read_prompt(size_t i)
-{
- int ch;
- char *buf = NULL; // buffer for possible error message from cscope
- size_t bufpos = 0;
- char *cs_emsg = _("E609: Cscope error: %s");
- size_t cs_emsg_len = strlen(cs_emsg);
- static char *eprompt = "Press the RETURN key to continue:";
- size_t epromptlen = strlen(eprompt);
-
- // compute maximum allowed len for Cscope error message
- assert(IOSIZE >= cs_emsg_len);
- size_t maxlen = IOSIZE - cs_emsg_len;
-
- while (1) {
- while (1) {
- do {
- errno = 0;
- ch = fgetc(csinfo[i].fr_fp);
- } while (ch == EOF && errno == EINTR && ferror(csinfo[i].fr_fp));
- if (ch == EOF || ch == CSCOPE_PROMPT[0]) {
- break;
- }
- // if there is room and char is printable
- if (bufpos < maxlen - 1 && vim_isprintc(ch)) {
- // lazy buffer allocation
- if (buf == NULL) {
- buf = xmalloc(maxlen);
- }
- // append character to the message
- buf[bufpos++] = (char)ch;
- buf[bufpos] = NUL;
- if (bufpos >= epromptlen
- && strcmp(&buf[bufpos - epromptlen], eprompt) == 0) {
- // remove eprompt from buf
- buf[bufpos - epromptlen] = NUL;
-
- // print message to user
- (void)semsg(cs_emsg, buf);
-
- // send RETURN to cscope
- (void)putc('\n', csinfo[i].to_fp);
- (void)fflush(csinfo[i].to_fp);
-
- // clear buf
- bufpos = 0;
- buf[bufpos] = NUL;
- }
- }
- }
-
- for (size_t n = 0; n < strlen(CSCOPE_PROMPT); n++) {
- if (n > 0) {
- do {
- errno = 0;
- ch = fgetc(csinfo[i].fr_fp);
- } while (ch == EOF && errno == EINTR && ferror(csinfo[i].fr_fp));
- }
- if (ch == EOF) {
- PERROR("cs_read_prompt EOF");
- if (buf != NULL && buf[0] != NUL) {
- (void)semsg(cs_emsg, buf);
- } else if (p_csverbose) {
- cs_reading_emsg(i); // don't have additional information
- }
- cs_release_csp(i, true);
- xfree(buf);
- return CSCOPE_FAILURE;
- }
-
- if (ch != CSCOPE_PROMPT[n]) {
- ch = EOF;
- break;
- }
- }
-
- if (ch == EOF) {
- continue; // didn't find the prompt
- }
- break; // did find the prompt
- }
-
- xfree(buf);
- return CSCOPE_SUCCESS;
-}
-
-#if defined(UNIX) && defined(SIGALRM)
-// Used to catch and ignore SIGALRM below.
-static void sig_handler(int s)
-{
- // do nothing
-}
-
-#endif
-
-/// Does the actual free'ing for the cs ptr with an optional flag of whether
-/// or not to free the filename. Called by cs_kill and cs_reset.
-static void cs_release_csp(size_t i, bool freefnpp)
-{
- // Trying to exit normally (not sure whether it is fit to Unix cscope)
- if (csinfo[i].to_fp != NULL) {
- (void)fputs("q\n", csinfo[i].to_fp);
- (void)fflush(csinfo[i].to_fp);
- }
-#if defined(UNIX)
- {
- int waitpid_errno;
- int pstat;
- pid_t pid;
-
-# if defined(HAVE_SIGACTION)
- struct sigaction sa, old;
-
- // Use sigaction() to limit the waiting time to two seconds.
- sigemptyset(&sa.sa_mask);
- sa.sa_handler = sig_handler;
-# ifdef SA_NODEFER
- sa.sa_flags = SA_NODEFER;
-# else
- sa.sa_flags = 0;
-# endif
- sigaction(SIGALRM, &sa, &old);
- alarm(2); // 2 sec timeout
-
- // Block until cscope exits or until timer expires
- pid = waitpid(csinfo[i].pid, &pstat, 0);
- waitpid_errno = errno;
-
- // cancel pending alarm if still there and restore signal
- alarm(0);
- sigaction(SIGALRM, &old, NULL);
-# else
- int waited;
-
- // Can't use sigaction(), loop for two seconds. First yield the CPU
- // to give cscope a chance to exit quickly.
- sleep(0);
- for (waited = 0; waited < 40; waited++) {
- pid = waitpid(csinfo[i].pid, &pstat, WNOHANG);
- waitpid_errno = errno;
- if (pid != 0) {
- break; // break unless the process is still running
- }
- os_delay(50L, false); // sleep 50 ms
- }
-# endif
- // If the cscope process is still running: kill it.
- // Safety check: If the PID would be zero here, the entire X session
- // would be killed. -1 and 1 are dangerous as well.
- if (pid < 0 && csinfo[i].pid > 1) {
-# ifdef ECHILD
- bool alive = true;
-
- if (waitpid_errno == ECHILD) {
- // When using 'vim -g', vim is forked and cscope process is
- // no longer a child process but a sibling. So waitpid()
- // fails with errno being ECHILD (No child processes).
- // Don't send SIGKILL to cscope immediately but wait
- // (polling) for it to exit normally as result of sending
- // the "q" command, hence giving it a chance to clean up
- // its temporary files.
- int waited;
-
- sleep(0);
- for (waited = 0; waited < 40; waited++) {
- // Check whether cscope process is still alive
- if (kill(csinfo[i].pid, 0) != 0) {
- alive = false; // cscope process no longer exists
- break;
- }
- os_delay(50L, false); // sleep 50 ms
- }
- }
- if (alive)
-# endif
- {
- kill(csinfo[i].pid, SIGKILL);
- (void)waitpid(csinfo[i].pid, &pstat, 0);
- }
- }
- }
-#else // !UNIX
- if (csinfo[i].hProc != NULL) {
- // Give cscope a chance to exit normally
- if (WaitForSingleObject(csinfo[i].hProc, 1000) == WAIT_TIMEOUT) {
- TerminateProcess(csinfo[i].hProc, 0);
- }
- CloseHandle(csinfo[i].hProc);
- }
-#endif
-
- if (csinfo[i].fr_fp != NULL) {
- (void)fclose(csinfo[i].fr_fp);
- }
- if (csinfo[i].to_fp != NULL) {
- (void)fclose(csinfo[i].to_fp);
- }
-
- if (freefnpp) {
- xfree(csinfo[i].fname);
- xfree(csinfo[i].ppath);
- xfree(csinfo[i].flags);
- }
-
- clear_csinfo(i);
-}
-
-/// Calls cs_kill on all cscope connections then reinits.
-static int cs_reset(exarg_T *eap)
-{
- char **dblist = NULL, **pplist = NULL, **fllist = NULL;
- char buf[25]; // for snprintf " (#%zu)"
-
- if (csinfo_size == 0) {
- return CSCOPE_SUCCESS;
- }
-
- // malloc our db and ppath list
- dblist = xmalloc(csinfo_size * sizeof(char *));
- pplist = xmalloc(csinfo_size * sizeof(char *));
- fllist = xmalloc(csinfo_size * sizeof(char *));
-
- for (size_t i = 0; i < csinfo_size; i++) {
- dblist[i] = csinfo[i].fname;
- pplist[i] = csinfo[i].ppath;
- fllist[i] = csinfo[i].flags;
- if (csinfo[i].fname != NULL) {
- cs_release_csp(i, false);
- }
- }
-
- // rebuild the cscope connection list
- for (size_t i = 0; i < csinfo_size; i++) {
- if (dblist[i] != NULL) {
- cs_add_common(dblist[i], pplist[i], fllist[i]);
- if (p_csverbose) {
- // don't use smsg_attr() because we want to display the
- // connection number in the same line as
- // "Added cscope database..."
- snprintf(buf, ARRAY_SIZE(buf), " (#%zu)", i);
- msg_puts_attr(buf, HL_ATTR(HLF_R));
- }
- }
- xfree(dblist[i]);
- xfree(pplist[i]);
- xfree(fllist[i]);
- }
- xfree(dblist);
- xfree(pplist);
- xfree(fllist);
-
- if (p_csverbose) {
- msg_attr(_("All cscope databases reset"), HL_ATTR(HLF_R) | MSG_HIST);
- }
- return CSCOPE_SUCCESS;
-}
-
-/// Construct the full pathname to a file found in the cscope database.
-/// (Prepends ppath, if there is one and if it's not already prepended,
-/// otherwise just uses the name found.)
-///
-/// We need to prepend the prefix because on some cscope's (e.g., the one that
-/// ships with Solaris 2.6), the output never has the prefix prepended.
-/// Contrast this with my development system (Digital Unix), which does.
-static char *cs_resolve_file(size_t i, char *name)
-{
- char *fullname;
- char_u *csdir = NULL;
-
- // Ppath is freed when we destroy the cscope connection.
- // Fullname is freed after cs_make_vim_style_matches, after it's been
- // copied into the tag buffer used by Vim.
- size_t len = strlen(name) + 2;
- if (csinfo[i].ppath != NULL) {
- len += strlen(csinfo[i].ppath);
- } else if (p_csre && csinfo[i].fname != NULL) {
- // If 'cscoperelative' is set and ppath is not set, use cscope.out
- // path in path resolution.
- csdir = xmalloc(MAXPATHL);
- STRLCPY(csdir, csinfo[i].fname,
- path_tail(csinfo[i].fname)
- - csinfo[i].fname + 1);
- len += STRLEN(csdir);
- }
-
- // Note/example: this won't work if the cscope output already starts
- // "../.." and the prefix path is also "../..". if something like this
- // happens, you are screwed up and need to fix how you're using cscope.
- if (csinfo[i].ppath != NULL
- && (strncmp(name, csinfo[i].ppath, strlen(csinfo[i].ppath)) != 0)
- && (name[0] != '/')) {
- fullname = xmalloc(len);
- (void)sprintf(fullname, "%s/%s", csinfo[i].ppath, name);
- } else if (csdir != NULL && csinfo[i].fname != NULL && *csdir != NUL) {
- // Check for csdir to be non empty to avoid empty path concatenated to
- // cscope output.
- fullname = concat_fnames((char *)csdir, name, true);
- } else {
- fullname = xstrdup(name);
- }
-
- xfree(csdir);
- return fullname;
-}
-
-/// Show all cscope connections.
-static int cs_show(exarg_T *eap)
-{
- if (cs_cnt_connections() == 0) {
- msg_puts(_("no cscope connections\n"));
- } else {
- msg_puts_attr(_(" # pid database name prepend path\n"),
- HL_ATTR(HLF_T));
- for (size_t i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname == NULL) {
- continue;
- }
-
- if (csinfo[i].ppath != NULL) {
- (void)smsg("%2zu %-5" PRId64 " %-34s %-32s", i,
- (int64_t)csinfo[i].pid, csinfo[i].fname, csinfo[i].ppath);
- } else {
- (void)smsg("%2zu %-5" PRId64 " %-34s <none>", i,
- (int64_t)csinfo[i].pid, csinfo[i].fname);
- }
- }
- }
-
- wait_return(false);
- return CSCOPE_SUCCESS;
-}
-
-/// Only called when VIM exits to quit any cscope sessions.
-void cs_end(void)
-{
- for (size_t i = 0; i < csinfo_size; i++) {
- cs_release_csp(i, true);
- }
- xfree(csinfo);
- csinfo_size = 0;
-}
-
-// the end
diff --git a/src/nvim/if_cscope.h b/src/nvim/if_cscope.h
deleted file mode 100644
index 8dbc78943f..0000000000
--- a/src/nvim/if_cscope.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef NVIM_IF_CSCOPE_H
-#define NVIM_IF_CSCOPE_H
-
-#include "nvim/ex_cmds_defs.h" // for exarg_T
-#include "nvim/types.h" // for char_u and expand_T
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "if_cscope.h.generated.h"
-#endif
-#endif // NVIM_IF_CSCOPE_H
diff --git a/src/nvim/if_cscope_defs.h b/src/nvim/if_cscope_defs.h
deleted file mode 100644
index 6ded89fa0b..0000000000
--- a/src/nvim/if_cscope_defs.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef NVIM_IF_CSCOPE_DEFS_H
-#define NVIM_IF_CSCOPE_DEFS_H
-
-// CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com>
-// Ported to Win32 by Sergey Khorev <sergey.khorev@gmail.com>
-//
-// The basic idea/structure of cscope for Vim was borrowed from Nvi.
-// There might be a few lines of code that look similar to what Nvi
-// has. If this is a problem and requires inclusion of the annoying
-// BSD license, then sue me; I'm not worth much anyway.
-
-#if defined(UNIX)
-# include <sys/types.h> // pid_t
-#endif
-
-#include "nvim/ex_cmds_defs.h"
-#include "nvim/os/fs_defs.h"
-#include "nvim/os/os_defs.h"
-
-#define CSCOPE_SUCCESS 0
-#define CSCOPE_FAILURE -1
-
-#define CSCOPE_DBFILE "cscope.out"
-#define CSCOPE_PROMPT ">> "
-
-// See ":help cscope-find" for the possible queries.
-
-typedef struct {
- char *name;
- int (*func)(exarg_T *eap);
- char *help;
- char *usage;
- int cansplit; // if supports splitting window
-} cscmd_T;
-
-typedef struct csi {
- char *fname; // cscope db name
- char *ppath; // path to prepend (the -P option)
- char *flags; // additional cscope flags/options (e.g, -p2)
-#if defined(UNIX)
- pid_t pid; // PID of the connected cscope process
-#else
- DWORD pid; // PID of the connected cscope process
- HANDLE hProc; // cscope process handle
- DWORD nVolume; // Volume serial number, instead of st_dev
- DWORD nIndexHigh; // st_ino has no meaning on Windows
- DWORD nIndexLow;
-#endif
- FileID file_id;
-
- FILE *fr_fp; // from cscope: FILE.
- FILE *to_fp; // to cscope: FILE.
-} csinfo_T;
-
-typedef enum { Add, Find, Help, Kill, Reset, Show, } csid_e;
-
-typedef enum {
- Store,
- Get,
- Free,
- Print,
-} mcmd_e;
-
-#endif // NVIM_IF_CSCOPE_DEFS_H
diff --git a/src/nvim/main.c b/src/nvim/main.c
index f6ec08c8e0..82c32f8e25 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -31,7 +31,6 @@
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/iconv.h"
-#include "nvim/if_cscope.h"
#include "nvim/insexpand.h"
#include "nvim/locale.h"
#include "nvim/log.h"
@@ -772,7 +771,6 @@ void getout(int exitval)
ui_call_set_title(cstr_as_string((char *)p_titleold));
}
- cs_end();
if (garbage_collect_at_exit) {
garbage_collect(false);
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 8aafe6671d..0ef7b76de3 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -4313,11 +4313,7 @@ static void nv_ident(cmdarg_T *cap)
case ']':
tag_cmd = true;
- if (p_cst) {
- STRCPY(buf, "cstag ");
- } else {
- STRCPY(buf, "ts ");
- }
+ STRCPY(buf, "ts ");
break;
default:
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 5470b66d6d..e5bd065aef 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -471,15 +471,6 @@ EXTERN long p_ph; // 'pumheight'
EXTERN long p_pw; // 'pumwidth'
EXTERN char *p_com; ///< 'comments'
EXTERN char *p_cpo; // 'cpoptions'
-EXTERN char *p_csprg; // 'cscopeprg'
-EXTERN int p_csre; // 'cscoperelative'
-EXTERN char *p_csqf; // 'cscopequickfix'
-#define CSQF_CMDS "sgdctefia"
-#define CSQF_FLAGS "+-0"
-EXTERN int p_cst; // 'cscopetag'
-EXTERN long p_csto; // 'cscopetagorder'
-EXTERN long p_cspc; // 'cscopepathcomp'
-EXTERN int p_csverbose; // 'cscopeverbose'
EXTERN char *p_debug; // 'debug'
EXTERN char *p_def; // 'define'
EXTERN char *p_inc;
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 149d0bace4..f4d6c808fa 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -496,58 +496,6 @@ return {
defaults={if_true=macros('CPO_VIM')}
},
{
- full_name='cscopepathcomp', abbreviation='cspc',
- short_desc=N_("how many components of the path to show"),
- type='number', scope={'global'},
- varname='p_cspc',
- defaults={if_true=0}
- },
- {
- full_name='cscopeprg', abbreviation='csprg',
- short_desc=N_("command to execute cscope"),
- type='string', scope={'global'},
- secure=true,
- expand=true,
- varname='p_csprg',
- defaults={if_true="cscope"}
- },
- {
- full_name='cscopequickfix', abbreviation='csqf',
- short_desc=N_("use quickfix window for cscope results"),
- type='string', list='onecomma', scope={'global'},
- deny_duplicates=true,
- varname='p_csqf',
- defaults={if_true=""}
- },
- {
- full_name='cscoperelative', abbreviation='csre',
- short_desc=N_("Use cscope.out path basename as prefix"),
- type='bool', scope={'global'},
- varname='p_csre',
- defaults={if_true=0}
- },
- {
- full_name='cscopetag', abbreviation='cst',
- short_desc=N_("use cscope for tag commands"),
- type='bool', scope={'global'},
- varname='p_cst',
- defaults={if_true=0}
- },
- {
- full_name='cscopetagorder', abbreviation='csto',
- short_desc=N_("determines \":cstag\" search order"),
- type='number', scope={'global'},
- varname='p_csto',
- defaults={if_true=0}
- },
- {
- full_name='cscopeverbose', abbreviation='csverb',
- short_desc=N_("give messages when adding a cscope database"),
- type='bool', scope={'global'},
- varname='p_csverbose',
- defaults={if_true=1}
- },
- {
full_name='cursorbind', abbreviation='crb',
short_desc=N_("move cursor in window as it moves in other windows"),
type='bool', scope={'window'},
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 24ee0a1f69..be3e137b69 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -1375,23 +1375,6 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
coladvance(curwin->w_virtcol);
}
}
- } else if (varp == &p_csqf) {
- if (p_csqf != NULL) {
- p = p_csqf;
- while (*p != NUL) {
- if (vim_strchr(CSQF_CMDS, *p) == NULL
- || p[1] == NUL
- || vim_strchr(CSQF_FLAGS, p[1]) == NULL
- || (p[2] != NUL && p[2] != ',')) {
- errmsg = e_invarg;
- break;
- } else if (p[2] == NUL) {
- break;
- } else {
- p += 3;
- }
- }
- }
} else if (gvarp == &p_cino) { // 'cinoptions'
// TODO(vim): recognize errors
parse_cino(curbuf);
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 4658aed235..2ac3fed8b7 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -24,7 +24,6 @@
#include "nvim/fold.h"
#include "nvim/garray.h"
#include "nvim/help.h"
-#include "nvim/if_cscope.h"
#include "nvim/input.h"
#include "nvim/insexpand.h"
#include "nvim/mark.h"
@@ -132,16 +131,13 @@ static int tfu_in_use = false; // disallow recursive call of tagfunc
/// type == DT_LAST: jump to last match of same tag
/// type == DT_SELECT: ":tselect [tag]", select tag from a list of all matches
/// type == DT_JUMP: ":tjump [tag]", jump to tag or select tag from a list
-/// type == DT_CSCOPE: use cscope to find the tag
/// type == DT_LTAG: use location list for displaying tag matches
/// type == DT_FREE: free cached matches
///
-/// for cscope, returns true if we jumped to tag or aborted, false otherwise
-///
/// @param tag tag (pattern) to jump to
/// @param forceit :ta with !
/// @param verbose print "tag not found" message
-bool do_tag(char *tag, int type, int count, int forceit, int verbose)
+void do_tag(char *tag, int type, int count, int forceit, int verbose)
{
taggy_T *tagstack = curwin->w_tagstack;
int tagstackidx = curwin->w_tagstackidx;
@@ -158,7 +154,6 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
int error_cur_match = 0;
int save_pos = false;
fmark_T saved_fmark;
- bool jumped_to_tag = false;
int new_num_matches;
char **new_matches;
int use_tagstack;
@@ -174,16 +169,15 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
if (tfu_in_use) {
emsg(_(recurmsg));
- return false;
+ return;
}
#ifdef EXITFREE
if (type == DT_FREE) {
// remove the list of matches
FreeWild(num_matches, matches);
- cs_free_tags();
num_matches = 0;
- return false;
+ return;
}
#endif
@@ -219,8 +213,7 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
// new pattern, add to the tag stack
if (*tag != NUL
&& (type == DT_TAG || type == DT_SELECT || type == DT_JUMP
- || type == DT_LTAG
- || type == DT_CSCOPE)) {
+ || type == DT_LTAG)) {
if (g_do_tagpreview != 0) {
if (ptag_entry.tagname != NULL
&& strcmp(ptag_entry.tagname, tag) == 0) {
@@ -311,7 +304,6 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
// remove the old list of matches
FreeWild(num_matches, matches);
- cs_free_tags();
num_matches = 0;
tag_freematch();
goto end_do_tag;
@@ -360,7 +352,6 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
cur_match = count - 1; break;
case DT_SELECT:
case DT_JUMP:
- case DT_CSCOPE:
case DT_LAST:
cur_match = MAXCOL - 1; break;
case DT_NEXT:
@@ -454,9 +445,6 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
flags = TAG_NOIC;
}
- if (type == DT_CSCOPE) {
- flags = TAG_CSCOPE;
- }
if (verbose) {
flags |= TAG_VERBOSE;
}
@@ -509,10 +497,7 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
} else {
bool ask_for_selection = false;
- if (type == DT_CSCOPE && num_matches > 1) {
- cs_print_tags();
- ask_for_selection = true;
- } else if (type == DT_TAG && *tag != NUL) {
+ if (type == DT_TAG && *tag != NUL) {
// If a count is supplied to the ":tag <name>" command, then
// jump to count'th matching tag.
cur_match = count > 0 ? count - 1 : 0;
@@ -536,8 +521,6 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
tagstack[tagstackidx].fmark = saved_fmark;
tagstackidx = prevtagstackidx;
}
- cs_free_tags();
- jumped_to_tag = true;
break;
}
cur_match = i - 1;
@@ -586,7 +569,6 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
ic = (matches[cur_match][0] & MT_IC_OFF);
if (type != DT_TAG && type != DT_SELECT && type != DT_JUMP
- && type != DT_CSCOPE
&& (num_matches > 1 || ic)
&& !skip_msg) {
// Give an indication of the number of matching tags
@@ -619,7 +601,7 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
set_vim_var_string(VV_SWAPCOMMAND, (char *)IObuff, -1);
// Jump to the desired match.
- i = jumpto_tag((char_u *)matches[cur_match], forceit, type != DT_CSCOPE);
+ i = jumpto_tag((char_u *)matches[cur_match], forceit, true);
set_vim_var_string(VV_SWAPCOMMAND, NULL, -1);
@@ -649,7 +631,6 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose)
if (use_tagstack && tagstackidx > curwin->w_tagstacklen) {
tagstackidx = curwin->w_tagstackidx;
}
- jumped_to_tag = true;
}
}
break;
@@ -663,7 +644,7 @@ end_do_tag:
postponed_split = 0; // don't split next time
g_do_tagpreview = 0; // don't do tag preview next time
- return jumped_to_tag;
+ return;
}
// List all the matching tags.
@@ -1324,7 +1305,6 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl
/// TAG_REGEXP use "pat" as a regexp
/// TAG_NOIC don't always ignore case
/// TAG_KEEP_LANG keep language
-/// TAG_CSCOPE use cscope results for tags
/// TAG_NO_TAGFUNC do not call the 'tagfunc' function
///
/// @param pat pattern to search for
@@ -1409,7 +1389,6 @@ int find_tags(char *pat, int *num_matches, char ***matchesp, int flags, int minc
int name_only = (flags & TAG_NAMES);
int noic = (flags & TAG_NOIC);
int get_it_again = false;
- int use_cscope = (flags & TAG_CSCOPE);
int verbose = (flags & TAG_VERBOSE);
int use_tfu = ((flags & TAG_NO_TAGFUNC) == 0);
int save_p_ic = p_ic;
@@ -1448,15 +1427,9 @@ int find_tags(char *pat, int *num_matches, char ***matchesp, int flags, int minc
hash_init(&ht_match[mtt]);
}
- STRCPY(tag_fname, "from cscope"); // for error messages
-
// Initialize a few variables
if (help_only) { // want tags from help file
curbuf->b_help = true; // will be restored later
- } else if (use_cscope) {
- // Make sure we don't mix help and cscope, confuses Coverity.
- help_only = false;
- curbuf->b_help = false;
}
orgpat.len = (int)strlen(pat);
@@ -1522,77 +1495,74 @@ int find_tags(char *pat, int *num_matches, char ***matchesp, int flags, int minc
// Try tag file names from tags option one by one.
for (first_file = true;
- use_cscope || get_tagfname(&tn, first_file, (char *)tag_fname) == OK;
+ get_tagfname(&tn, first_file, (char *)tag_fname) == OK;
first_file = false) {
// A file that doesn't exist is silently ignored. Only when not a
// single file is found, an error message is given (further on).
- if (use_cscope) {
- fp = NULL; // avoid GCC warning
- } else {
- if (curbuf->b_help) {
- // Keep en if the file extension is .txt
- if (is_txt) {
- STRCPY(help_lang, "en");
+ if (curbuf->b_help) {
+ // Keep en if the file extension is .txt
+ if (is_txt) {
+ STRCPY(help_lang, "en");
+ } else {
+ // Prefer help tags according to 'helplang'. Put the
+ // two-letter language name in help_lang[].
+ i = (int)STRLEN(tag_fname);
+ if (i > 3 && tag_fname[i - 3] == '-') {
+ STRCPY(help_lang, tag_fname + i - 2);
} else {
- // Prefer help tags according to 'helplang'. Put the
- // two-letter language name in help_lang[].
- i = (int)STRLEN(tag_fname);
- if (i > 3 && tag_fname[i - 3] == '-') {
- STRCPY(help_lang, tag_fname + i - 2);
- } else {
- STRCPY(help_lang, "en");
- }
+ STRCPY(help_lang, "en");
}
+ }
- // When searching for a specific language skip tags files
- // for other languages.
- if (help_lang_find != NULL
- && STRICMP(help_lang, help_lang_find) != 0) {
- continue;
- }
+ // When searching for a specific language skip tags files
+ // for other languages.
+ if (help_lang_find != NULL
+ && STRICMP(help_lang, help_lang_find) != 0) {
+ continue;
+ }
- // For CTRL-] in a help file prefer a match with the same
- // language.
- if ((flags & TAG_KEEP_LANG)
- && help_lang_find == NULL
- && curbuf->b_fname != NULL
- && (i = (int)strlen(curbuf->b_fname)) > 4
- && curbuf->b_fname[i - 1] == 'x'
- && curbuf->b_fname[i - 4] == '.'
- && STRNICMP(curbuf->b_fname + i - 3, help_lang, 2) == 0) {
- help_pri = 0;
- } else {
- help_pri = 1;
- for (s = p_hlg; *s != NUL; s++) {
- if (STRNICMP(s, help_lang, 2) == 0) {
- break;
- }
- help_pri++;
- if ((s = (char_u *)vim_strchr((char *)s, ',')) == NULL) {
- break;
- }
+ // For CTRL-] in a help file prefer a match with the same
+ // language.
+ if ((flags & TAG_KEEP_LANG)
+ && help_lang_find == NULL
+ && curbuf->b_fname != NULL
+ && (i = (int)strlen(curbuf->b_fname)) > 4
+ && curbuf->b_fname[i - 1] == 'x'
+ && curbuf->b_fname[i - 4] == '.'
+ && STRNICMP(curbuf->b_fname + i - 3, help_lang, 2) == 0) {
+ help_pri = 0;
+ } else {
+ help_pri = 1;
+ for (s = p_hlg; *s != NUL; s++) {
+ if (STRNICMP(s, help_lang, 2) == 0) {
+ break;
+ }
+ help_pri++;
+ if ((s = (char_u *)vim_strchr((char *)s, ',')) == NULL) {
+ break;
}
- if (s == NULL || *s == NUL) {
- // Language not in 'helplang': use last, prefer English,
- // unless found already.
+ }
+ if (s == NULL || *s == NUL) {
+ // Language not in 'helplang': use last, prefer English,
+ // unless found already.
+ help_pri++;
+ if (STRICMP(help_lang, "en") != 0) {
help_pri++;
- if (STRICMP(help_lang, "en") != 0) {
- help_pri++;
- }
}
}
}
+ }
- if ((fp = os_fopen((char *)tag_fname, "r")) == NULL) {
- continue;
- }
+ if ((fp = os_fopen((char *)tag_fname, "r")) == NULL) {
+ continue;
+ }
- if (p_verbose >= 5) {
- verbose_enter();
- smsg(_("Searching tags file %s"), tag_fname);
- verbose_leave();
- }
+ if (p_verbose >= 5) {
+ verbose_enter();
+ smsg(_("Searching tags file %s"), tag_fname);
+ verbose_leave();
}
+
did_open = true; // remember that we found at least one file
state = TS_START; // we're at the start of the file
@@ -1676,9 +1646,7 @@ int find_tags(char *pat, int *num_matches, char ***matchesp, int flags, int minc
// skip empty and blank lines
do {
- eof = use_cscope
- ? cs_fgets(lbuf, lbuf_size)
- : vim_fgets(lbuf, lbuf_size, fp);
+ eof = vim_fgets(lbuf, lbuf_size, fp);
} while (!eof && vim_isblankline((char *)lbuf));
if (eof) {
@@ -1745,8 +1713,7 @@ line_read_in:
// the tag file isn't sorted, the second loop will find it.
// When "!_TAG_FILE_SORTED" found: start binary search if
// flag set.
- // For cscope, it's always linear.
- if (linear || use_cscope) {
+ if (linear) {
state = TS_LINEAR;
} else if (tag_file_sorted == NUL) {
state = TS_BINARY;
@@ -1797,7 +1764,7 @@ parse_line:
// last-but-one byte (see vim_fgets()).
// Has been reported for Mozilla JS with extremely long names.
// In that case we need to increase lbuf_size.
- if (lbuf[lbuf_size - 2] != NUL && !use_cscope) {
+ if (lbuf[lbuf_size - 2] != NUL) {
lbuf_size *= 2;
xfree(lbuf);
lbuf = xmalloc((size_t)lbuf_size);
@@ -1985,37 +1952,32 @@ parse_line:
if (match) {
size_t len = 0;
- if (use_cscope) {
- // Don't change the ordering, always use the same table.
- mtt = MT_GL_OTH;
- } else {
- // Decide in which array to store this match.
- is_current = test_for_current((char *)tagp.fname, (char *)tagp.fname_end,
- (char *)tag_fname,
- buf_ffname);
- is_static = test_for_static(&tagp);
-
- // Decide in which of the sixteen tables to store this match.
- if (is_static) {
- if (is_current) {
- mtt = MT_ST_CUR;
- } else {
- mtt = MT_ST_OTH;
- }
+ // Decide in which array to store this match.
+ is_current = test_for_current((char *)tagp.fname, (char *)tagp.fname_end,
+ (char *)tag_fname,
+ buf_ffname);
+ is_static = test_for_static(&tagp);
+
+ // Decide in which of the sixteen tables to store this match.
+ if (is_static) {
+ if (is_current) {
+ mtt = MT_ST_CUR;
} else {
- if (is_current) {
- mtt = MT_GL_CUR;
- } else {
- mtt = MT_GL_OTH;
- }
- }
- if (orgpat.regmatch.rm_ic && !match_no_ic) {
- mtt += MT_IC_OFF;
+ mtt = MT_ST_OTH;
}
- if (match_re) {
- mtt += MT_RE_OFF;
+ } else {
+ if (is_current) {
+ mtt = MT_GL_CUR;
+ } else {
+ mtt = MT_GL_OTH;
}
}
+ if (orgpat.regmatch.rm_ic && !match_no_ic) {
+ mtt += MT_IC_OFF;
+ }
+ if (match_re) {
+ mtt += MT_RE_OFF;
+ }
// Add the found match in ht_match[mtt] and ga_match[mtt].
// Store the info we need later, which depends on the kind of
@@ -2098,16 +2060,11 @@ parse_line:
hashitem_T *hi;
// Don't add identical matches.
- // Add all cscope tags, because they are all listed.
// "mfp" is used as a hash key, there is a NUL byte to end
// the part that matters for comparing, more bytes may
// follow after it. E.g. help tags store the priority
// after the NUL.
- if (use_cscope) {
- hash++;
- } else {
- hash = hash_hash((char_u *)mfp);
- }
+ hash = hash_hash((char_u *)mfp);
hi = hash_lookup(&ht_match[mtt], (const char *)mfp,
strlen(mfp), hash);
if (HASHITEM_EMPTY(hi)) {
@@ -2121,23 +2078,16 @@ parse_line:
}
}
}
- if (use_cscope && eof) {
- break;
- }
} // forever
if (line_error) {
semsg(_("E431: Format error in tags file \"%s\""), tag_fname);
- if (!use_cscope) {
- semsg(_("Before byte %" PRId64), (int64_t)vim_ftell(fp));
- }
+ semsg(_("Before byte %" PRId64), (int64_t)vim_ftell(fp));
stop_searching = true;
line_error = false;
}
- if (!use_cscope) {
- fclose(fp);
- }
+ fclose(fp);
if (vimconv.vc_type != CONV_NONE) {
convert_setup(&vimconv, NULL, NULL);
}
@@ -2154,23 +2104,18 @@ parse_line:
stop_searching = true;
}
- if (stop_searching || use_cscope) {
+ if (stop_searching) {
break;
}
} // end of for-each-file loop
- if (!use_cscope) {
- tagname_free(&tn);
- }
+ tagname_free(&tn);
// stop searching when already did a linear search, or when TAG_NOIC
// used, and 'ignorecase' not set or already did case-ignore search
if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic) {
break;
}
- if (use_cscope) {
- break;
- }
orgpat.regmatch.rm_ic = true; // try another time while ignoring case
}
@@ -2559,7 +2504,7 @@ static char_u *tag_full_fname(tagptrs_T *tagp)
///
/// @param lbuf_arg line from the tags file for this tag
/// @param forceit :ta with !
-/// @param keep_help keep help flag (false for cscope)
+/// @param keep_help keep help flag
///
/// @return OK for success, NOTAGFILE when file not found, FAIL otherwise.
static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
diff --git a/src/nvim/tag.h b/src/nvim/tag.h
index 7f2ef8d6d7..e08145f727 100644
--- a/src/nvim/tag.h
+++ b/src/nvim/tag.h
@@ -14,7 +14,6 @@
#define DT_SELECT 7 // jump to selection from list
#define DT_HELP 8 // like DT_TAG, but no wildcards
#define DT_JUMP 9 // jump to new tag or selection from list
-#define DT_CSCOPE 10 // cscope find command (like tjump)
#define DT_LTAG 11 // tag using location list
#define DT_FREE 99 // free cached matches
@@ -23,7 +22,6 @@
#define TAG_NAMES 2 // only return name of tag
#define TAG_REGEXP 4 // use tag pattern as regexp
#define TAG_NOIC 8 // don't always ignore case
-#define TAG_CSCOPE 16 // cscope tag
#define TAG_VERBOSE 32 // message verbosity
#define TAG_INS_COMP 64 // Currently doing insert completion
#define TAG_KEEP_LANG 128 // keep current language
diff --git a/src/nvim/testdir/test_cscope.vim b/src/nvim/testdir/test_cscope.vim
deleted file mode 100644
index 76ea35fa10..0000000000
--- a/src/nvim/testdir/test_cscope.vim
+++ /dev/null
@@ -1,344 +0,0 @@
-" Test for cscope commands.
-
-source check.vim
-CheckFeature cscope
-CheckFeature quickfix
-
-if !executable('cscope')
- throw 'Skipped: cscope program missing'
-endif
-
-func CscopeSetupOrClean(setup)
- if a:setup
- noa sp samples/memfile_test.c
- saveas! Xmemfile_test.c
- call system('cscope -bk -fXcscope.out Xmemfile_test.c')
- call system('cscope -bk -fXcscope2.out Xmemfile_test.c')
- cscope add Xcscope.out
- set cscopequickfix=s-,g-,d-,c-,t-,e-,f-,i-,a-
- else
- cscope kill -1
- for file in ['Xcscope.out', 'Xcscope2.out', 'Xmemfile_test.c']
- call delete(file)
- endfo
- endif
-endfunc
-
-func Test_cscopeWithCscopeConnections()
- call CscopeSetupOrClean(1)
- " Test: E568: duplicate cscope database not added
- try
- set nocscopeverbose
- cscope add Xcscope.out
- set cscopeverbose
- catch
- call assert_report('exception thrown')
- endtry
- call assert_fails('cscope add', 'E560')
- call assert_fails('cscope add Xcscope.out', 'E568')
- call assert_fails('cscope add doesnotexist.out', 'E563')
- if has('unix')
- call assert_fails('cscope add /dev/null', 'E564:')
- endif
-
- " Test: Find this C-Symbol
- for cmd in ['cs find s main', 'cs find 0 main']
- let a = execute(cmd)
- " Test where it moves the cursor
- call assert_equal('main(void)', getline('.'))
- " Test the output of the :cs command
- call assert_match('\n(1 of 1): <<main>> main(void )', a)
- endfor
-
- " Test: Find this definition
- for cmd in ['cs find g test_mf_hash',
- \ 'cs find 1 test_mf_hash',
- \ 'cs find 1 test_mf_hash'] " leading space ignored.
- exe cmd
- call assert_equal(['', '/*', ' * Test mf_hash_*() functions.', ' */', ' static void', 'test_mf_hash(void)', '{'], getline(line('.')-5, line('.')+1))
- endfor
-
- " Test: Find functions called by this function
- for cmd in ['cs find d test_mf_hash', 'cs find 2 test_mf_hash']
- let a = execute(cmd)
- call assert_match('\n(1 of 42): <<mf_hash_init>> mf_hash_init(&ht);', a)
- call assert_equal(' mf_hash_init(&ht);', getline('.'))
- endfor
-
- " Test: Find functions calling this function
- for cmd in ['cs find c test_mf_hash', 'cs find 3 test_mf_hash']
- let a = execute(cmd)
- call assert_match('\n(1 of 1): <<main>> test_mf_hash();', a)
- call assert_equal(' test_mf_hash();', getline('.'))
- endfor
-
- " Test: Find this text string
- for cmd in ['cs find t Bram', 'cs find 4 Bram']
- let a = execute(cmd)
- call assert_match('(1 of 1): <<<unknown>>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a)
- call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.'))
- endfor
-
- " Test: Find this egrep pattern
- " test all matches returned by cscope
- for cmd in ['cs find e ^\#includ.', 'cs find 6 ^\#includ.']
- let a = execute(cmd)
- call assert_match('\n(1 of 3): <<<unknown>>> #include <assert.h>', a)
- call assert_equal('#include <assert.h>', getline('.'))
- cnext
- call assert_equal('#include "main.c"', getline('.'))
- cnext
- call assert_equal('#include "memfile.c"', getline('.'))
- call assert_fails('cnext', 'E553:')
- endfor
-
- " Test: Find the same egrep pattern using lcscope this time.
- let a = execute('lcs find e ^\#includ.')
- call assert_match('\n(1 of 3): <<<unknown>>> #include <assert.h>', a)
- call assert_equal('#include <assert.h>', getline('.'))
- lnext
- call assert_equal('#include "main.c"', getline('.'))
- lnext
- call assert_equal('#include "memfile.c"', getline('.'))
- call assert_fails('lnext', 'E553:')
-
- " Test: Find this file
- for cmd in ['cs find f Xmemfile_test.c', 'cs find 7 Xmemfile_test.c']
- enew
- let a = execute(cmd)
- call assert_true(a =~ '"Xmemfile_test.c" \d\+L, \d\+B')
- call assert_equal('Xmemfile_test.c', @%)
- endfor
-
- " Test: Find files #including this file
- for cmd in ['cs find i assert.h', 'cs find 8 assert.h']
- enew
- let a = execute(cmd)
- let alines = split(a, '\n', 1)
- call assert_equal('', alines[0])
- call assert_true(alines[1] =~ '"Xmemfile_test.c" \d\+L, \d\+B')
- call assert_equal('(1 of 1): <<global>> #include <assert.h>', alines[2])
- call assert_equal('#include <assert.h>', getline('.'))
- endfor
-
- " Test: Invalid find command
- call assert_fails('cs find', 'E560:')
- call assert_fails('cs find x', 'E560:')
-
- if has('float')
- " Test: Find places where this symbol is assigned a value
- " this needs a cscope >= 15.8
- " unfortunately, Travis has cscope version 15.7
- let cscope_version = systemlist('cscope --version')[0]
- let cs_version = str2float(matchstr(cscope_version, '\d\+\(\.\d\+\)\?'))
- if cs_version >= 15.8
- for cmd in ['cs find a item', 'cs find 9 item']
- let a = execute(cmd)
- call assert_equal(['', '(1 of 4): <<test_mf_hash>> item = (mf_hashitem_T *)lalloc_clear(sizeof(*item), FALSE);'], split(a, '\n', 1))
- call assert_equal(' item = (mf_hashitem_T *)lalloc_clear(sizeof(*item), FALSE);', getline('.'))
- cnext
- call assert_equal(' item = mf_hash_find(&ht, key);', getline('.'))
- cnext
- call assert_equal(' item = mf_hash_find(&ht, key);', getline('.'))
- cnext
- call assert_equal(' item = mf_hash_find(&ht, key);', getline('.'))
- endfor
- endif
- endif
-
- " Test: leading whitespace is not removed for cscope find text
- let a = execute('cscope find t test_mf_hash')
- call assert_equal(['', '(1 of 1): <<<unknown>>> test_mf_hash();'], split(a, '\n', 1))
- call assert_equal(' test_mf_hash();', getline('.'))
-
- " Test: test with scscope
- let a = execute('scs find t Bram')
- call assert_match('(1 of 1): <<<unknown>>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a)
- call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.'))
-
- " Test: cscope help
- for cmd in ['cs', 'cs help', 'cs xxx']
- let a = execute(cmd)
- call assert_match('^cscope commands:\n', a)
- call assert_match('\nadd :', a)
- call assert_match('\nfind :', a)
- call assert_match('\nhelp : Show this message', a)
- call assert_match('\nkill : Kill a connection', a)
- call assert_match('\nreset: Reinit all connections', a)
- call assert_match('\nshow : Show connections', a)
- endfor
- let a = execute('scscope help')
- call assert_match('This cscope command does not support splitting the window\.', a)
-
- " Test: reset connections
- let a = execute('cscope reset')
- call assert_match('\nAdded cscope database.*Xcscope.out (#0)', a)
- call assert_match('\nAll cscope databases reset', a)
-
- " Test: cscope show
- let a = execute('cscope show')
- call assert_match('\n 0 \d\+.*Xcscope.out\s*<none>', a)
-
- " Test: cstag and 'csto' option
- set csto=0
- let a = execute('cstag TEST_COUNT')
- call assert_match('(1 of 1): <<TEST_COUNT>> #define TEST_COUNT 50000', a)
- call assert_equal('#define TEST_COUNT 50000', getline('.'))
- call assert_fails('cstag DOES_NOT_EXIST', 'E257:')
- set csto=1
- let a = execute('cstag index_to_key')
- call assert_match('(1 of 1): <<index_to_key>> #define index_to_key(i) ((i) ^ 15167)', a)
- call assert_equal('#define index_to_key(i) ((i) ^ 15167)', getline('.'))
- call assert_fails('cstag DOES_NOT_EXIST', 'E257:')
- call assert_fails('cstag', 'E562:')
- let save_tags = &tags
- set tags=
- call assert_fails('cstag DOES_NOT_EXIST', 'E257:')
- let a = execute('cstag index_to_key')
- call assert_match('(1 of 1): <<index_to_key>> #define index_to_key(i) ((i) ^ 15167)', a)
- let &tags = save_tags
-
- " Test: 'cst' option
- set nocst
- call assert_fails('tag TEST_COUNT', 'E426:')
- set cst
- let a = execute('tag TEST_COUNT')
- call assert_match('(1 of 1): <<TEST_COUNT>> #define TEST_COUNT 50000', a)
- call assert_equal('#define TEST_COUNT 50000', getline('.'))
- let a = execute('tags')
- call assert_match('1 1 TEST_COUNT\s\+\d\+\s\+#define index_to_key', a)
-
- " Test: 'cscoperelative'
- call mkdir('Xcscoperelative')
- cd Xcscoperelative
- let a = execute('cs find g test_mf_hash')
- call assert_notequal('test_mf_hash(void)', getline('.'))
- set cscoperelative
- let a = execute('cs find g test_mf_hash')
- call assert_equal('test_mf_hash(void)', getline('.'))
- set nocscoperelative
- cd ..
- call delete('Xcscoperelative', 'd')
-
- " Test: E259: no match found
- call assert_fails('cscope find g DOES_NOT_EXIST', 'E259:')
-
- " Test: this should trigger call to cs_print_tags()
- " Unclear how to check result though, we just exercise the code.
- set cst cscopequickfix=s0
- call feedkeys(":cs find s main\<CR>", 't')
-
- " Test: cscope kill
- call assert_fails('cscope kill', 'E560:')
- call assert_fails('cscope kill 2', 'E261:')
- call assert_fails('cscope kill xxx', 'E261:')
-
- let a = execute('cscope kill 0')
- call assert_match('cscope connection 0 closed', a)
-
- cscope add Xcscope.out
- let a = execute('cscope kill Xcscope.out')
- call assert_match('cscope connection Xcscope.out closed', a)
-
- cscope add Xcscope.out .
- let a = execute('cscope kill -1')
- call assert_match('cscope connection .*Xcscope.out closed', a)
- let a = execute('cscope kill -1')
- call assert_equal('', a)
-
- " Test: 'csprg' option
- call assert_equal('cscope', &csprg)
- set csprg=doesnotexist
- call assert_fails('cscope add Xcscope2.out', 'E609:')
- set csprg=cscope
-
- " Test: multiple cscope connections
- cscope add Xcscope.out
- cscope add Xcscope2.out . -C
- let a = execute('cscope show')
- call assert_match('\n 0 \d\+.*Xcscope.out\s*<none>', a)
- call assert_match('\n 1 \d\+.*Xcscope2.out\s*\.', a)
-
- " Test: test Ex command line completion
- call feedkeys(":cs \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"cs add find help kill reset show', @:)
-
- call feedkeys(":scs \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"scs find', @:)
-
- call feedkeys(":cs find \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"cs find a c d e f g i s t', @:)
-
- call feedkeys(":cs kill \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"cs kill -1 0 1', @:)
-
- call feedkeys(":cs add Xcscope\<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"cs add Xcscope.out Xcscope2.out', @:)
-
- " Test: cscope_connection()
- call assert_equal(cscope_connection(), 1)
- call assert_equal(cscope_connection(0, 'out'), 1)
- call assert_equal(cscope_connection(0, 'xxx'), 1)
-
- call assert_equal(cscope_connection(1, 'out'), 1)
- call assert_equal(cscope_connection(1, 'xxx'), 0)
-
- call assert_equal(cscope_connection(2, 'out'), 0)
- call assert_equal(cscope_connection(2, getcwd() .. '/Xcscope.out', 1), 1)
-
- call assert_equal(cscope_connection(3, 'xxx', '..'), 0)
- call assert_equal(cscope_connection(3, 'out', 'xxx'), 0)
- call assert_equal(cscope_connection(3, 'out', '.'), 1)
-
- call assert_equal(cscope_connection(4, 'out', '.'), 0)
-
- call assert_equal(cscope_connection(5, 'out'), 0)
- call assert_equal(cscope_connection(-1, 'out'), 0)
-
- call CscopeSetupOrClean(0)
-endfunc
-
-" Test ":cs add {dir}" (add the {dir}/cscope.out database)
-func Test_cscope_add_dir()
- call mkdir('Xcscopedir', 'p')
-
- " Cscope doesn't handle symlinks, so this needs to be resolved in case a
- " shadow directory is being used.
- let memfile = resolve('./samples/memfile_test.c')
- call system('cscope -bk -fXcscopedir/cscope.out ' . memfile)
-
- cs add Xcscopedir
- let a = execute('cscope show')
- let lines = split(a, "\n", 1)
- call assert_equal(3, len(lines))
- call assert_equal(' # pid database name prepend path', lines[0])
- call assert_equal('', lines[1])
- call assert_match('^ 0 \d\+.*Xcscopedir/cscope.out\s\+<none>$', lines[2])
-
- cs kill -1
- call delete('Xcscopedir/cscope.out')
- call assert_fails('cs add Xcscopedir', 'E563:')
-
- call delete('Xcscopedir', 'd')
-endfunc
-
-func Test_cscopequickfix()
- set cscopequickfix=s-,g-,d+,c-,t+,e-,f0,i-,a-
- call assert_equal('s-,g-,d+,c-,t+,e-,f0,i-,a-', &cscopequickfix)
-
- call assert_fails('set cscopequickfix=x-', 'E474:')
- call assert_fails('set cscopequickfix=s', 'E474:')
- call assert_fails('set cscopequickfix=s7', 'E474:')
- call assert_fails('set cscopequickfix=s-a', 'E474:')
-endfunc
-
-func Test_withoutCscopeConnection()
- call assert_equal(cscope_connection(), 0)
-
- call assert_fails('cscope find s main', 'E567:')
- let a = execute('cscope show')
- call assert_match('no cscope connections', a)
-endfunc
-
-
-" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index c3cf0b6df8..0e045c773f 100644
--- a/src/nvim/usercmd.c
+++ b/src/nvim/usercmd.c
@@ -46,7 +46,6 @@ static const char *command_complete[] =
[EXPAND_COLORS] = "color",
[EXPAND_COMMANDS] = "command",
[EXPAND_COMPILER] = "compiler",
- [EXPAND_CSCOPE] = "cscope",
[EXPAND_USER_DEFINED] = "custom",
[EXPAND_USER_LIST] = "customlist",
[EXPAND_USER_LUA] = "<Lua function>",
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 5b7ff7ba52..4bcda9fc4f 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -138,7 +138,6 @@ enum {
EXPAND_USER_LIST,
EXPAND_USER_LUA,
EXPAND_SHELLCMD,
- EXPAND_CSCOPE,
EXPAND_SIGN,
EXPAND_PROFILE,
EXPAND_BEHAVE,