diff options
| author | Eliseo Martínez <eliseomarmol@gmail.com> | 2014-05-12 02:25:17 +0200 |
|---|---|---|
| committer | Eliseo Martínez <eliseomarmol@gmail.com> | 2014-05-15 20:46:01 +0200 |
| commit | da51dc9cf202772f60bd2da975dbef257bd9237c (patch) | |
| tree | 5c16b93238a153f55634e9323077f30c8133970c /src/if_cscope.c | |
| parent | ffe61e5ba1721340ca51d56bae3ddaca415fb5bc (diff) | |
| download | rneovim-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.c | 2167 |
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" |