diff src/if_cscope.c @ 9:6a13985590e6

*** empty log message ***
author axmo
date Fri, 29 Aug 2008 15:41:29 +0900
parents 76efa0be13f1
children c16898406ff2
line wrap: on
line diff
--- a/src/if_cscope.c	Wed Aug 13 17:54:25 2008 +0900
+++ b/src/if_cscope.c	Fri Aug 29 15:41:29 2008 +0900
@@ -23,7 +23,6 @@
 #else
     /* not UNIX, must be WIN32 */
 # include "vimio.h"
-# include <fcntl.h>
 #endif
 #include "if_cscope.h"
 
@@ -75,7 +74,7 @@
     { "add",	cs_add,
 		N_("Add a new database"),     "add file|dir [pre-path] [flags]", 0 },
     { "find",	cs_find,
-		N_("Query for a pattern"),    FIND_USAGE, 1 },
+		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,
@@ -171,7 +170,7 @@
 
     cs_init();
 
-    if (eap->arg == NULL || strlen((const char *)(eap->arg)) == 0)
+    if (*eap->arg == NUL)
     {
 	(void)EMSG(_("E562: Usage: cstag <ident>"));
 	return;
@@ -1181,7 +1180,16 @@
 	(void)smsg((char_u *)_("%-5s: %-30s (Usage: %s)"),
 				      cmdp->name, _(cmdp->help), cmdp->usage);
 	if (strcmp(cmdp->name, "find") == 0)
-	    MSG_PUTS(FIND_HELP);
+	    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"
+		       "       g: Find this definition\n"
+		       "       i: Find files #including this file\n"
+		       "       s: Find this C symbol\n"
+		       "       t: Find assignments to\n"));
+
 	cmdp++;
     }
 
@@ -1225,7 +1233,7 @@
     csinfo[i].nIndexHigh = 0;
     csinfo[i].nIndexLow = 0;
 #endif
-    csinfo[i].pid    = -1;
+    csinfo[i].pid    = 0;
     csinfo[i].fr_fp  = NULL;
     csinfo[i].to_fp  = NULL;
 #if defined(WIN32)
@@ -1400,7 +1408,7 @@
 	return NULL;
 
     /* Store length of eap->arg before it gets modified by strtok(). */
-    eap_arg_len = STRLEN(eap->arg);
+    eap_arg_len = (int)STRLEN(eap->arg);
 
     if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL)
 	return NULL;
@@ -2096,6 +2104,18 @@
     return CSCOPE_SUCCESS;
 }
 
+#if defined(UNIX) && defined(SIGALRM)
+/*
+ * Used to catch and ignore SIGALRM below.
+ */
+/* ARGSUSED */
+    static RETSIGTYPE
+sig_handler SIGDEFARG(sigarg)
+{
+    /* do nothing */
+    SIGRETURN;
+}
+#endif
 
 /*
  * PRIVATE: cs_release_csp
@@ -2108,9 +2128,6 @@
     int i;
     int freefnpp;
 {
-#if defined(UNIX)
-    int pstat;
-#else
     /*
      * Trying to exit normally (not sure whether it is fit to UNIX cscope
      */
@@ -2119,6 +2136,88 @@
 	(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;
+	sa.sa_flags = SA_NODEFER;
+	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 */
+	    mch_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
+	    int 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;
+		    }
+		    mch_delay(50L, FALSE); /* sleep 50ms */
+		}
+	    }
+	    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 */
@@ -2133,18 +2232,6 @@
     if (csinfo[i].to_fp != NULL)
 	(void)fclose(csinfo[i].to_fp);
 
-    /*
-     * Safety check: If the PID would be zero here, the entire X session would
-     * be killed.  -1 and 1 are dangerous as well.
-     */
-#if defined(UNIX)
-    if (csinfo[i].pid > 1)
-    {
-	kill(csinfo[i].pid, SIGTERM);
-	(void)waitpid(csinfo[i].pid, &pstat, 0);
-    }
-#endif
-
     if (freefnpp)
     {
 	vim_free(csinfo[i].fname);