diff options
Diffstat (limited to 'src/if_cscope.c')
-rw-r--r-- | src/if_cscope.c | 204 |
1 files changed, 107 insertions, 97 deletions
diff --git a/src/if_cscope.c b/src/if_cscope.c index 445494bcd..151dc91e0 100644 --- a/src/if_cscope.c +++ b/src/if_cscope.c @@ -24,11 +24,6 @@ /* not UNIX, must be WIN32 */ # include "vimio.h" # include <fcntl.h> -# include <process.h> -# define STDIN_FILENO 0 -# define STDOUT_FILENO 1 -# define STDERR_FILENO 2 -# define pipe(fds) _pipe(fds, 256, O_TEXT|O_NOINHERIT) #endif #include "if_cscope.h" @@ -65,7 +60,7 @@ static char * cs_manage_matches __ARGS((char **, char **, int, mcmd_e)); static char * cs_parse_results __ARGS((int cnumber, char *buf, int bufsize, char **context, char **linenumber, char **search)); static char * cs_pathcomponents __ARGS((char *path)); static void cs_print_tags_priv __ARGS((char **, char **, int)); -static int cs_read_prompt __ARGS((int )); +static int cs_read_prompt __ARGS((int)); static void cs_release_csp __ARGS((int, int freefnpp)); static int cs_reset __ARGS((exarg_T *eap)); static char * cs_resolve_file __ARGS((int, char *)); @@ -504,7 +499,7 @@ staterr: #if defined(UNIX) else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) #else - /* substitute define S_ISREG from os_unix.h */ + /* WIN32 - substitute define S_ISREG from os_unix.h */ else if (((statbuf.st_mode) & S_IFMT) == S_IFREG) #endif { @@ -717,17 +712,23 @@ cs_create_cmd(csoption, pattern) cs_create_connection(i) int i; { - int to_cs[2], from_cs[2], len; - char *prog, *cmd, *ppath = NULL; -#ifndef UNIX - int in_save, out_save, err_save; - long_i ph; -# ifdef FEAT_GUI - HWND activewnd = NULL; - HWND consolewnd = NULL; -# endif +#ifdef UNIX + int to_cs[2], from_cs[2]; +#endif + int len; + char *prog, *cmd, *ppath = NULL; +#ifdef WIN32 + int fd; + SECURITY_ATTRIBUTES sa; + PROCESS_INFORMATION pi; + STARTUPINFO si; + BOOL pipe_stdin = FALSE, pipe_stdout = FALSE; + HANDLE stdin_rd, stdout_rd; + HANDLE stdout_wr, stdin_wr; + BOOL created; #endif +#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]. @@ -748,18 +749,12 @@ err_closing: return CSCOPE_FAILURE; } -#if defined(UNIX) switch (csinfo[i].pid = fork()) { case -1: (void)EMSG(_("E622: Could not fork for cscope")); goto err_closing; case 0: /* child: run cscope. */ -#else - in_save = dup(STDIN_FILENO); - out_save = dup(STDOUT_FILENO); - err_save = dup(STDERR_FILENO); -#endif if (dup2(to_cs[0], STDIN_FILENO) == -1) PERROR("cs_create_connection 1"); if (dup2(from_cs[1], STDOUT_FILENO) == -1) @@ -768,15 +763,32 @@ err_closing: PERROR("cs_create_connection 3"); /* close unused */ -#if defined(UNIX) (void)close(to_cs[1]); (void)close(from_cs[0]); #else - /* On win32 we must close opposite ends because we are the parent */ - (void)close(to_cs[0]); - to_cs[0] = -1; - (void)close(from_cs[1]); - from_cs[1] = -1; + /* 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 */ if ((prog = (char *)alloc(MAXPATHL + 1)) == NULL) @@ -784,6 +796,7 @@ err_closing: #ifdef UNIX return CSCOPE_FAILURE; #else + /* WIN32 */ goto err_closing; #endif } @@ -800,6 +813,7 @@ err_closing: #ifdef UNIX return CSCOPE_FAILURE; #else + /* WIN32 */ goto err_closing; #endif } @@ -818,6 +832,7 @@ err_closing: #ifdef UNIX return CSCOPE_FAILURE; #else + /* WIN32 */ goto err_closing; #endif } @@ -826,6 +841,7 @@ err_closing: #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) @@ -851,60 +867,6 @@ err_closing: exit(127); /* NOTREACHED */ default: /* parent. */ -#else -# ifdef FEAT_GUI - activewnd = GetForegroundWindow(); /* on win9x cscope steals focus */ - /* Dirty hack to hide annoying console window */ - if (AllocConsole()) - { - char *title; - title = (char *)alloc(1024); - if (title == NULL) - FreeConsole(); - else - { - GetConsoleTitle(title, 1024); /* save for future restore */ - SetConsoleTitle( - "GVIMCS{5499421B-CBEF-45b0-85EF-38167FDEA5C5}GVIMCS"); - Sleep(40); /* as stated in MS KB we must wait 40 ms */ - consolewnd = FindWindow(NULL, - "GVIMCS{5499421B-CBEF-45b0-85EF-38167FDEA5C5}GVIMCS"); - if (consolewnd != NULL) - ShowWindow(consolewnd, SW_HIDE); - SetConsoleTitle(title); - vim_free(title); - } - } -# endif - /* May be use &shell, &shellquote etc */ -# ifdef __BORLANDC__ - /* BCC 5.5 uses a different function name for spawnlp */ - ph = (long_i)spawnlp(P_NOWAIT, prog, cmd, NULL); -# else - ph = (long_i)_spawnlp(_P_NOWAIT, prog, cmd, NULL); -# endif - vim_free(prog); - vim_free(cmd); -# ifdef FEAT_GUI - /* Dirty hack part two */ - if (activewnd != NULL) - /* restoring focus */ - SetForegroundWindow(activewnd); - if (consolewnd != NULL) - FreeConsole(); - -# endif - if (ph == -1) - { - PERROR(_("cs_create_connection exec failed")); - (void)EMSG(_("E623: Could not spawn cscope process")); - goto err_closing; - } - /* else */ - csinfo[i].pid = 0; - csinfo[i].hProc = (HANDLE)ph; - -#endif /* !UNIX */ /* * Save the file descriptors for later duplication, and * reopen as streams. @@ -914,22 +876,52 @@ err_closing: if ((csinfo[i].fr_fp = fdopen(from_cs[0], "r")) == NULL) PERROR(_("cs_create_connection: fdopen for fr_fp failed")); -#if defined(UNIX) /* close unused */ (void)close(to_cs[0]); (void)close(from_cs[1]); break; } + #else - /* restore stdhandles */ - dup2(in_save, STDIN_FILENO); - dup2(out_save, STDOUT_FILENO); - dup2(err_save, STDERR_FILENO); - close(in_save); - close(out_save); - close(err_save); -#endif + /* 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); + vim_free(prog); + vim_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((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; } /* cs_create_connection */ @@ -2097,8 +2089,8 @@ cs_read_prompt(i) /* * PRIVATE: cs_release_csp * - * 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. + * 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(i, freefnpp) @@ -2116,10 +2108,13 @@ cs_release_csp(i, freefnpp) (void)fputs("q\n", csinfo[i].to_fp); (void)fflush(csinfo[i].to_fp); } - /* give cscope chance to exit normally */ - if (csinfo[i].hProc != NULL - && WaitForSingleObject(csinfo[i].hProc, 1000) == WAIT_TIMEOUT) - TerminateProcess(csinfo[i].hProc, 0); + 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) @@ -2302,6 +2297,21 @@ cs_show(eap) return CSCOPE_SUCCESS; } /* cs_show */ + +/* + * PUBLIC: cs_end + * + * Only called when VIM exits to quit any cscope sessions. + */ + void +cs_end() +{ + int i; + + for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + cs_release_csp(i, TRUE); +} + #endif /* FEAT_CSCOPE */ /* the end */ |