aboutsummaryrefslogtreecommitdiff
path: root/src/if_cscope.c
diff options
context:
space:
mode:
authorEliseo Martínez <eliseomarmol@gmail.com>2014-05-12 02:25:17 +0200
committerEliseo Martínez <eliseomarmol@gmail.com>2014-05-15 20:46:01 +0200
commitda51dc9cf202772f60bd2da975dbef257bd9237c (patch)
tree5c16b93238a153f55634e9323077f30c8133970c /src/if_cscope.c
parentffe61e5ba1721340ca51d56bae3ddaca415fb5bc (diff)
downloadrneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.gz
rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.bz2
rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.zip
Introduce nvim namespace: Move files.
Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library.
Diffstat (limited to 'src/if_cscope.c')
-rw-r--r--src/if_cscope.c2167
1 files changed, 0 insertions, 2167 deletions
diff --git a/src/if_cscope.c b/src/if_cscope.c
deleted file mode 100644
index b000b03444..0000000000
--- a/src/if_cscope.c
+++ /dev/null
@@ -1,2167 +0,0 @@
-/*
- * 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.
- *
- * See README.txt for an overview of the Vim source code.
- */
-
-#include "vim.h"
-#include "if_cscope.h"
-#include "charset.h"
-#include "eval.h"
-#include "fileio.h"
-#include "message.h"
-#include "misc1.h"
-#include "misc2.h"
-#include "memory.h"
-#include "os/time.h"
-#include "path.h"
-#include "quickfix.h"
-#include "tag.h"
-#include "ui.h"
-#include "window.h"
-#include "os/os.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#if defined(UNIX)
-# include <sys/wait.h>
-#endif
-#include "if_cscope_defs.h"
-
-static void cs_usage_msg(csid_e x);
-static int cs_add(exarg_T *eap);
-static void cs_stat_emsg(char *fname);
-static int cs_add_common(char *, char *, char *);
-static int cs_check_for_connections(void);
-static int cs_check_for_tags(void);
-static int cs_cnt_connections(void);
-static void cs_reading_emsg(int idx);
-static int cs_cnt_matches(int idx);
-static char * cs_create_cmd(char *csoption, char *pattern);
-static int cs_create_connection(int i);
-static void do_cscope_general(exarg_T *eap, int make_split);
-static void cs_file_results(FILE *, int *);
-static void cs_fill_results(char *, int, int *, char ***,
- char ***, int *);
-static int cs_find(exarg_T *eap);
-static int cs_find_common(char *opt, char *pat, int, int, int,
- char_u *cmdline);
-static int cs_help(exarg_T *eap);
-static void clear_csinfo(int i);
-static int cs_insert_filelist(char *, char *, char *, FileInfo *file_info);
-static int cs_kill(exarg_T *eap);
-static void cs_kill_execute(int, char *);
-static cscmd_T * cs_lookup_cmd(exarg_T *eap);
-static char * cs_make_vim_style_matches(char *, char *,
- char *, char *);
-static char * cs_manage_matches(char **, char **, int, mcmd_e);
-static char * cs_parse_results(int cnumber, char *buf,
- int bufsize, char **context,
- char **linenumber,
- char **search);
-static char * cs_pathcomponents(char *path);
-static void cs_print_tags_priv(char **, char **, int);
-static int cs_read_prompt(int);
-static void cs_release_csp(int, int freefnpp);
-static int cs_reset(exarg_T *eap);
-static char * cs_resolve_file(int, char *);
-static int cs_show(exarg_T *eap);
-
-
-static csinfo_T * csinfo = NULL;
-static int 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 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)EMSG2(_("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_u *get_cscope_name(expand_T *xp, int idx)
-{
- int current_idx;
- int i;
-
- switch (expand_what) {
- case EXP_CSCOPE_SUBCMD:
- /* Complete with sub-commands of ":cscope":
- * add, find, help, kill, reset, show */
- return (char_u *)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 */
- for (i = 0, current_idx = 0; cs_cmds[i].name != NULL; i++)
- if (cs_cmds[i].cansplit)
- if (current_idx++ == idx)
- break;
- return (char_u *)cs_cmds[i].name;
- case EXP_CSCOPE_FIND:
- {
- const char *query_type[] =
- {
- "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, ... t) or numbers (0, 1,
- * ..., 8) but only complete with letters, since numbers are
- * redundant. */
- return (char_u *)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. */
- 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), "%d", i);
- return (char_u *)connection;
- }
- }
- return (current_idx == idx && idx > 0) ? (char_u *)"-1" : NULL;
- }
- default:
- return NULL;
- }
-}
-
-/*
- * Handle command line completion for :cscope command.
- */
-void set_context_in_cscope_cmd(expand_T *xp, char_u *arg, cmdidx_T cmdidx)
-{
- char_u *p;
-
- /* Default: expand subcommands */
- xp->xp_context = EXPAND_CSCOPE;
- xp->xp_pattern = arg;
- expand_what = (cmdidx == CMD_scscope)
- ? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD;
-
- /* (part of) subcommand already typed */
- if (*arg != NUL) {
- p = 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;
- }
- }
-}
-
-
-/*
- * PRIVATE: do_cscope_general
- *
- * Find the command, print help if invalid, and then call the corresponding
- * command function.
- */
-static void
-do_cscope_general (
- exarg_T *eap,
- int make_split /* whether to split window */
-)
-{
- 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.split;
- postponed_split_tab = cmdmod.tab;
- }
-
- cmdp->func(eap);
-
- postponed_split_flags = 0;
- postponed_split_tab = 0;
-}
-
-/*
- * PUBLIC: do_cscope
- */
-void do_cscope(exarg_T *eap)
-{
- do_cscope_general(eap, FALSE);
-}
-
-/*
- * PUBLIC: do_scscope
- *
- * same as do_cscope, but splits window, too.
- */
-void do_scscope(exarg_T *eap)
-{
- do_cscope_general(eap, TRUE);
-}
-
-/*
- * PUBLIC: do_cstag
- *
- */
-void do_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", (char *)(eap->arg), eap->forceit, FALSE,
- FALSE, *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", (char *)(eap->arg), eap->forceit,
- FALSE, FALSE, *eap->cmdlinep);
- if (ret == FALSE)
- cs_free_tags();
- }
- }
- } else if (cs_check_for_connections()) {
- ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, FALSE,
- FALSE, *eap->cmdlinep);
- if (ret == FALSE)
- cs_free_tags();
- }
- break;
- default:
- break;
- }
-
- if (!ret) {
- (void)EMSG(_("E257: cstag: tag not found"));
- g_do_tagpreview = 0;
- }
-
-} /* do_cscope */
-
-
-/*
- * PUBLIC: cs_find
- *
- * this simulates a vim_fgets(), but for cscope, returns the next line
- * from the cscope output. should only be called from find_tags()
- *
- * returns TRUE if eof, FALSE otherwise
- */
-int cs_fgets(char_u *buf, int size)
-{
- char *p;
-
- if ((p = cs_manage_matches(NULL, NULL, -1, Get)) == NULL)
- return TRUE;
- vim_strncpy(buf, (char_u *)p, size - 1);
-
- return FALSE;
-} /* cs_fgets */
-
-
-/*
- * PUBLIC: cs_free_tags
- *
- * called only from do_tag(), when popping the tag stack
- */
-void cs_free_tags(void)
-{
- cs_manage_matches(NULL, NULL, -1, Free);
-}
-
-/*
- * PUBLIC: cs_print_tags
- *
- * called from do_tag()
- */
-void cs_print_tags(void)
-{
- cs_manage_matches(NULL, NULL, -1, 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!
- */
-int cs_connection(int num, char_u *dbpath, char_u *ppath)
-{
- int i;
-
- if (num < 0 || num > 4 || (num > 0 && !dbpath))
- return FALSE;
-
- for (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
- ****************************************************************************/
-
-/*
- * PRIVATE: cs_add
- *
- * add cscope database or a directory name (to look for cscope.out)
- * to the cscope connection list
- *
- * MAXPATHL 256
- */
-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)
-{
- char *stat_emsg = _("E563: stat(%s) error: %d");
- char *buf = (char *)alloc((unsigned)strlen(stat_emsg) + MAXPATHL + 10);
-
- (void)sprintf(buf, stat_emsg, fname, errno);
- (void)EMSG(buf);
- free(buf);
-}
-
-
-/*
- * PRIVATE: cs_add_common
- *
- * 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.
- */
-static int
-cs_add_common (
- char *arg1, /* filename - may contain environment variables */
- char *arg2, /* prepend path - may contain environment variables */
- char *flags
-)
-{
- char *fname = NULL;
- char *fname2 = NULL;
- char *ppath = NULL;
- int i;
- int len;
- int usedlen = 0;
- char_u *fbuf = NULL;
-
- /* get the filename (arg1), expand it, and try to stat it */
- fname = (char *)alloc(MAXPATHL + 1);
-
- expand_env((char_u *)arg1, (char_u *)fname, MAXPATHL);
- len = (int)STRLEN(fname);
- fbuf = (char_u *)fname;
- (void)modify_fname((char_u *)":p", &usedlen,
- (char_u **)&fname, &fbuf, &len);
- if (fname == NULL)
- goto add_err;
- fname = (char *)vim_strnsave((char_u *)fname, len);
- free(fbuf);
- FileInfo file_info;
- bool file_info_ok = os_get_file_info(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 = (char *)alloc(MAXPATHL + 1);
- expand_env((char_u *)arg2, (char_u *)ppath, MAXPATHL);
- if (!os_file_exists((char_u *)ppath))
- goto staterr;
- }
-
- /* if filename is a directory, append the cscope database name to it */
- if ((file_info.stat.st_mode & S_IFMT) == S_IFDIR) {
- fname2 = (char *)alloc((unsigned)(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_get_file_info(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)EMSG2(
- _("E564: %s is not a directory or a valid cscope database"),
- fname);
- goto add_err;
- }
-
- if (i != -1) {
- if (cs_create_connection(i) == CSCOPE_FAILURE
- || cs_read_prompt(i) == CSCOPE_FAILURE) {
- cs_release_csp(i, TRUE);
- goto add_err;
- }
-
- if (p_csverbose) {
- msg_clr_eos();
- (void)smsg_attr(hl_attr(HLF_R),
- (char_u *)_("Added cscope database %s"),
- csinfo[i].fname);
- }
- }
-
- free(fname);
- free(fname2);
- free(ppath);
- return CSCOPE_SUCCESS;
-
-add_err:
- free(fname2);
- free(fname);
- free(ppath);
- return CSCOPE_FAILURE;
-} /* cs_add_common */
-
-
-static int cs_check_for_connections(void)
-{
- return cs_cnt_connections() > 0;
-} /* cs_check_for_connections */
-
-static int cs_check_for_tags(void)
-{
- return p_tags[0] != NUL && curbuf->b_p_tags != NULL;
-} /* cs_check_for_tags */
-
-/*
- * PRIVATE: cs_cnt_connections
- *
- * count the number of cscope connections
- */
-static int cs_cnt_connections(void)
-{
- short i;
- short cnt = 0;
-
- for (i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname != NULL)
- cnt++;
- }
- return cnt;
-} /* cs_cnt_connections */
-
-static void
-cs_reading_emsg (
- int idx /* connection index */
-)
-{
- EMSGN(_("E262: error reading cscope connection %" PRId64), idx);
-}
-
-#define CSREAD_BUFSIZE 2048
-/*
- * PRIVATE: cs_cnt_matches
- *
- * count the number of matches for a given cscope connection.
- */
-static int cs_cnt_matches(int idx)
-{
- char *stok;
- char *buf;
- int nlines;
-
- buf = (char *)alloc(CSREAD_BUFSIZE);
- for (;; ) {
- if (!fgets(buf, CSREAD_BUFSIZE, csinfo[idx].fr_fp)) {
- if (feof(csinfo[idx].fr_fp))
- errno = EIO;
-
- cs_reading_emsg(idx);
-
- free(buf);
- return -1;
- }
-
- /*
- * 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".
- */
- 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((const char *)stok, "lines", 5))
- continue;
-
- break;
- }
-
- free(buf);
- return nlines;
-} /* cs_cnt_matches */
-
-
-/*
- * PRIVATE: cs_create_cmd
- *
- * 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;
- default:
- (void)EMSG(_("E561: unknown cscope search type"));
- cs_usage_msg(Find);
- return NULL;
- }
-
- /* Skip white space before the patter, except for text and pattern search,
- * they may want to use the leading white space. */
- pat = pattern;
- if (search != 4 && search != 6)
- while (vim_iswhite(*pat))
- ++pat;
-
- cmd = (char *)alloc((unsigned)(strlen(pat) + 2));
-
- (void)sprintf(cmd, "%d%s", search, pat);
-
- return cmd;
-} /* cs_create_cmd */
-
-
-/*
- * PRIVATE: cs_create_connection
- *
- * This piece of code was taken/adapted from nvi. do we need to add
- * the BSD license notice?
- */
-static int cs_create_connection(int i)
-{
-#ifdef UNIX
- int to_cs[2], from_cs[2];
-#endif
- int len;
- 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
- /* WIN32 */
- /* Create pipes to communicate with cscope */
- 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 = (char *)alloc(MAXPATHL + 1);
- expand_env((char_u *)p_csprg, (char_u *)prog, MAXPATHL);
-
- /* alloc space to hold the cscope command */
- len = (int)(strlen(prog) + strlen(csinfo[i].fname) + 32);
- if (csinfo[i].ppath) {
- /* expand the prepend path for env var's */
- ppath = (char *)alloc(MAXPATHL + 1);
- expand_env((char_u *)csinfo[i].ppath, (char_u *)ppath, MAXPATHL);
-
- len += (int)strlen(ppath);
- }
-
- if (csinfo[i].flags)
- len += (int)strlen(csinfo[i].flags);
-
- cmd = (char *)alloc(len);
-
- /* run the cscope command; is there execl for non-unix systems? */
-#if defined(UNIX)
- (void)sprintf(cmd, "exec %s -dl -f %s", prog, csinfo[i].fname);
-#else
- /* WIN32 */
- (void)sprintf(cmd, "%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 */
- free(prog);
-# endif
- free(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
- /* WIN32 */
- /* 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);
- free(prog);
- free(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 - tidy up after failure to create files on pipe handles. */
- if (((fd = _open_osfhandle((OPEN_OH_ARGTYPE)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((OPEN_OH_ARGTYPE)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;
-} /* cs_create_connection */
-
-
-/*
- * PRIVATE: cs_find
- *
- * 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.
- *
- * returns TRUE if we jump to a tag or abort, FALSE if not.
- */
-static int cs_find(exarg_T *eap)
-{
- char *opt, *pat;
- int i;
-
- 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 >= (char *)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 (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, *eap->cmdlinep);
-} /* cs_find */
-
-
-/*
- * PRIVATE: cs_find_common
- *
- * common code for cscope find, shared by cs_find() and do_cstag()
- */
-static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int use_ll, char_u *cmdline)
-{
- int i;
- char *cmd;
- int *nummatches;
- int 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;
- default:
- cmdletter = opt[0];
- }
-
- qfpos = (char *)vim_strchr(p_csqf, cmdletter);
- if (qfpos != NULL) {
- qfpos++;
- /* next symbol must be + or - */
- if (strchr(CSQF_FLAGS, *qfpos) == NULL) {
- char *nf = _("E469: invalid cscopequickfix flag %c for %c");
- /* strlen will be enough because we use chars */
- char *buf = (char *)alloc((unsigned)strlen(nf));
-
- sprintf(buf, nf, *qfpos, *(qfpos-1));
- (void)EMSG(buf);
- free(buf);
- return FALSE;
- }
-
- if (*qfpos != '0') {
- apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)"cscope",
- curbuf->b_fname, TRUE, curbuf);
- if (did_throw || force_abort)
- return FALSE;
- }
- }
-
- /* create the actual command to send to cscope */
- cmd = cs_create_cmd(opt, pat);
- if (cmd == NULL)
- return FALSE;
-
- nummatches = (int *)alloc(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 (i = 0; i < csinfo_size; i++)
- nummatches[i] = 0;
- totmatches = 0;
- for (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 += nummatches[i];
-
- if (nummatches[i] == 0)
- (void)cs_read_prompt(i);
- }
- free(cmd);
-
- if (totmatches == 0) {
- char *nf = _("E259: no matches found for cscope query %s of %s");
- char *buf;
-
- if (!verbose) {
- free(nummatches);
- return FALSE;
- }
-
- buf = (char *)alloc((unsigned)(strlen(opt) + strlen(pat) + strlen(nf)));
- sprintf(buf, nf, opt, pat);
- (void)EMSG(buf);
- free(buf);
- free(nummatches);
- return FALSE;
- }
-
- if (qfpos != NULL && *qfpos != '0' && totmatches > 0) {
- /* fill error list */
- FILE *f;
- char_u *tmp = vim_tempname('c');
- qf_info_T *qi = NULL;
- win_T *wp = NULL;
-
- f = mch_fopen((char *)tmp, "w");
- if (f == NULL)
- EMSG2(_(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, tmp, (char_u *)"%f%*\\t%l%*\\t%m",
- *qfpos == '-', cmdline) > 0) {
- if (postponed_split != 0) {
- win_split(postponed_split > 0 ? postponed_split : 0,
- postponed_split_flags);
- RESET_BINDING(curwin);
- postponed_split = 0;
- }
-
- apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)"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);
- free(tmp);
- free(nummatches);
- return TRUE;
- } else {
- char **matches = NULL, **contexts = NULL;
- int matched = 0;
-
- /* read output */
- cs_fill_results((char *)pat, totmatches, nummatches, &matches,
- &contexts, &matched);
- free(nummatches);
- if (matches == NULL)
- return FALSE;
-
- (void)cs_manage_matches(matches, contexts, matched, Store);
-
- return do_tag((char_u *)pat, DT_CSCOPE, 0, forceit, verbose);
- }
-
-} /* cs_find_common */
-
-/*
- * PRIVATE: cs_help
- *
- * 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((char_u *)help);
-
- /* Use %*s rather than %30s to ensure proper alignment in utf-8 */
- if (space_cnt < 0)
- space_cnt = 0;
- (void)smsg((char_u *)_("%-5s: %s%*s (Usage: %s)"),
- cmdp->name,
- help, space_cnt, " ",
- cmdp->usage);
- if (strcmp(cmdp->name, "find") == 0)
- MSG_PUTS(_("\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"