From c3528e668e7a17ff56b82624f93f2227778c4b00 Mon Sep 17 00:00:00 2001 From: edyfox Date: Thu, 6 Sep 2007 15:54:41 +0000 Subject: [PATCH] Merged from the latest developing branch. git-svn-id: https://vim.svn.sourceforge.net/svnroot/vim/trunk@511 2a77ed30-b011-0410-a7ad-c7884a0aa172 --- src/if_cscope.c | 204 +++++++++++++++++++++++++----------------------- src/if_cscope.h | 2 +- src/main.c | 11 ++- src/option.c | 20 ++++- src/proto/if_cscope.pro | 1 + src/version.c | 4 + 6 files changed, 139 insertions(+), 103 deletions(-) diff --git a/src/if_cscope.c b/src/if_cscope.c index 445494bc..151dc91e 100644 --- a/src/if_cscope.c +++ b/src/if_cscope.c @@ -24,11 +24,6 @@ /* not UNIX, must be WIN32 */ # include "vimio.h" # include -# include -# 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 */ diff --git a/src/if_cscope.h b/src/if_cscope.h index 5dc69e8f..99d472b9 100644 --- a/src/if_cscope.h +++ b/src/if_cscope.h @@ -72,7 +72,7 @@ typedef struct csi { ino_t st_ino; /* inode number of cscope db */ #else # if defined(WIN32) - int pid; /* Can't get pid so set it to 0 ;) */ + 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 in the Windows */ diff --git a/src/main.c b/src/main.c index ab5d31bf..906d8bd5 100644 --- a/src/main.c +++ b/src/main.c @@ -1331,6 +1331,9 @@ getout(exitval) #ifdef FEAT_NETBEANS_INTG netbeans_end(); #endif +#ifdef FEAT_CSCOPE + cs_end(); +#endif mch_exit(exitval); } @@ -3671,7 +3674,13 @@ build_drop_cmd(filec, filev, tabs, sendReply) mainerr_arg_missing((char_u *)filev[-1]); if (mch_dirname(cwd, MAXPATHL) != OK) return NULL; - if ((p = vim_strsave_escaped_ext(cwd, PATH_ESC_CHARS, '\\', TRUE)) == NULL) + if ((p = vim_strsave_escaped_ext(cwd, +#ifdef BACKSLASH_IN_FILENAME + "", /* rem_backslash() will tell what chars to escape */ +#else + PATH_ESC_CHARS, +#endif + '\\', TRUE)) == NULL) return NULL; ga_init2(&ga, 1, 100); ga_concat(&ga, (char_u *)":cd "); diff --git a/src/option.c b/src/option.c index 893f1457..59a2fa34 100644 --- a/src/option.c +++ b/src/option.c @@ -427,6 +427,8 @@ struct vimoption #define P_NOGLOB 0x100000L/* do not use local value for global vimrc */ #define P_NFNAME 0x200000L/* only normal file name chars allowed */ #define P_INSECURE 0x400000L/* option was set from a modeline */ +#define P_PRI_MKRC 0x800000L/* priority for :mkvimrc (setting option has + side effects) */ #define ISK_LATIN1 (char_u *)"@,48-57,_,192-255" @@ -773,6 +775,8 @@ static struct vimoption {(char_u *)0L, (char_u *)0L} #endif }, + /* P_PRI_MKRC isn't needed here, optval_default() + * always returns TRUE for 'compatible' */ {"compatible", "cp", P_BOOL|P_RALL, (char_u *)&p_cp, PV_NONE, {(char_u *)TRUE, (char_u *)FALSE}}, @@ -1515,7 +1519,7 @@ static struct vimoption {(char_u *)0L, (char_u *)0L} #endif }, - {"keymap", "kmp", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME, + {"keymap", "kmp", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME|P_PRI_MKRC, #ifdef FEAT_KEYMAP (char_u *)&p_keymap, PV_KMAP, {(char_u *)"", (char_u *)0L} @@ -1836,7 +1840,7 @@ static struct vimoption {"paragraphs", "para", P_STRING|P_VI_DEF, (char_u *)&p_para, PV_NONE, {(char_u *)"IPLPPPQPP LIpplpipbp", (char_u *)0L}}, - {"paste", NULL, P_BOOL|P_VI_DEF, + {"paste", NULL, P_BOOL|P_VI_DEF|P_PRI_MKRC, (char_u *)&p_paste, PV_NONE, {(char_u *)FALSE, (char_u *)0L}}, {"pastetoggle", "pt", P_STRING|P_VI_DEF, @@ -8535,13 +8539,20 @@ makeset(fd, opt_flags, local_only) char_u *varp_local = NULL; /* fresh value */ char *cmd; int round; + int pri; /* * The options that don't have a default (terminal name, columns, lines) * are never written. Terminal options are also not written. + * Do the loop over "options[]" twice: once for options with the + * P_PRI_MKRC flag and once without. */ - for (p = &options[0]; !istermoption(p); p++) - if (!(p->flags & P_NO_MKRC) && !istermoption(p)) + for (pri = 1; pri >= 0; --pri) + { + for (p = &options[0]; !istermoption(p); p++) + if (!(p->flags & P_NO_MKRC) + && !istermoption(p) + && ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0))) { /* skip global option when only doing locals */ if (p->indir == PV_NONE && !(opt_flags & OPT_GLOBAL)) @@ -8637,6 +8648,7 @@ makeset(fd, opt_flags, local_only) } } } + } return OK; } diff --git a/src/proto/if_cscope.pro b/src/proto/if_cscope.pro index 0617d13a..555a0a4b 100644 --- a/src/proto/if_cscope.pro +++ b/src/proto/if_cscope.pro @@ -6,4 +6,5 @@ int cs_fgets __ARGS((char_u *buf, int size)); void cs_free_tags __ARGS((void)); void cs_print_tags __ARGS((void)); int cs_connection __ARGS((int num, char_u *dbpath, char_u *ppath)); +void cs_end __ARGS((void)); /* vim: set ft=c : */ diff --git a/src/version.c b/src/version.c index 20c5be33..761bff65 100644 --- a/src/version.c +++ b/src/version.c @@ -667,6 +667,10 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 100, +/**/ + 99, +/**/ 98, /**/ 97, -- 2.11.4.GIT