1 /* vi:set ts=8 sts=4 sw=4:
3 * CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com>
4 * Ported to Win32 by Sergey Khorev <sergey.khorev@gmail.com>
6 * The basic idea/structure of cscope for Vim was borrowed from Nvi. There
7 * might be a few lines of code that look similar to what Nvi has.
9 * See README.txt for an overview of the Vim source code.
14 #if defined(FEAT_CSCOPE) || defined(PROTO)
19 #include <sys/types.h>
22 # include <sys/wait.h>
24 /* not UNIX, must be WIN32 */
27 #include "if_cscope.h"
29 static void cs_usage_msg
__ARGS((csid_e x
));
30 static int cs_add
__ARGS((exarg_T
*eap
));
31 static void cs_stat_emsg
__ARGS((char *fname
));
32 static int cs_add_common
__ARGS((char *, char *, char *));
33 static int cs_check_for_connections
__ARGS((void));
34 static int cs_check_for_tags
__ARGS((void));
35 static int cs_cnt_connections
__ARGS((void));
36 static void cs_reading_emsg
__ARGS((int idx
));
37 static int cs_cnt_matches
__ARGS((int idx
));
38 static char * cs_create_cmd
__ARGS((char *csoption
, char *pattern
));
39 static int cs_create_connection
__ARGS((int i
));
40 static void do_cscope_general
__ARGS((exarg_T
*eap
, int make_split
));
42 static void cs_file_results
__ARGS((FILE *, int *));
44 static void cs_fill_results
__ARGS((char *, int , int *, char ***,
46 static int cs_find
__ARGS((exarg_T
*eap
));
47 static int cs_find_common
__ARGS((char *opt
, char *pat
, int, int, int, char *cmdline
));
48 static int cs_help
__ARGS((exarg_T
*eap
));
49 static void clear_csinfo
__ARGS((int i
));
50 static int cs_insert_filelist
__ARGS((char *, char *, char *,
52 static int cs_kill
__ARGS((exarg_T
*eap
));
53 static void cs_kill_execute
__ARGS((int, char *));
54 static cscmd_T
* cs_lookup_cmd
__ARGS((exarg_T
*eap
));
55 static char * cs_make_vim_style_matches
__ARGS((char *, char *,
57 static char * cs_manage_matches
__ARGS((char **, char **, int, mcmd_e
));
58 static char * cs_parse_results
__ARGS((int cnumber
, char *buf
, int bufsize
, char **context
, char **linenumber
, char **search
));
59 static char * cs_pathcomponents
__ARGS((char *path
));
60 static void cs_print_tags_priv
__ARGS((char **, char **, int));
61 static int cs_read_prompt
__ARGS((int));
62 static void cs_release_csp
__ARGS((int, int freefnpp
));
63 static int cs_reset
__ARGS((exarg_T
*eap
));
64 static char * cs_resolve_file
__ARGS((int, char *));
65 static int cs_show
__ARGS((exarg_T
*eap
));
68 static csinfo_T
* csinfo
= NULL
;
69 static int csinfo_size
= 0; /* number of items allocated in
72 static int eap_arg_len
; /* length of eap->arg, set in
74 static cscmd_T cs_cmds
[] =
77 N_("Add a new database"), "add file|dir [pre-path] [flags]", 0 },
79 N_("Query for a pattern"), "find c|d|e|f|g|i|s|t name", 1 },
81 N_("Show this message"), "help", 0 },
83 N_("Kill a connection"), "kill #", 0 },
85 N_("Reinit all connections"), "reset", 0 },
87 N_("Show connections"), "show", 0 },
88 { NULL
, NULL
, NULL
, NULL
, 0 }
95 (void)EMSG2(_("E560: Usage: cs[cope] %s"), cs_cmds
[(int)x
].usage
);
98 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
102 EXP_CSCOPE_SUBCMD
, /* expand ":cscope" sub-commands */
103 EXP_SCSCOPE_SUBCMD
, /* expand ":scscope" sub-commands */
104 EXP_CSCOPE_FIND
, /* expand ":cscope find" arguments */
105 EXP_CSCOPE_KILL
/* expand ":cscope kill" arguments */
109 * Function given to ExpandGeneric() to obtain the cscope command
113 get_cscope_name(xp
, idx
)
122 case EXP_CSCOPE_SUBCMD
:
123 /* Complete with sub-commands of ":cscope":
124 * add, find, help, kill, reset, show */
125 return (char_u
*)cs_cmds
[idx
].name
;
126 case EXP_SCSCOPE_SUBCMD
:
127 /* Complete with sub-commands of ":scscope": same sub-commands as
128 * ":cscope" but skip commands which don't support split windows */
129 for (i
= 0, current_idx
= 0; cs_cmds
[i
].name
!= NULL
; i
++)
130 if (cs_cmds
[i
].cansplit
)
131 if (current_idx
++ == idx
)
133 return (char_u
*)cs_cmds
[i
].name
;
134 case EXP_CSCOPE_FIND
:
136 const char *query_type
[] =
138 "c", "d", "e", "f", "g", "i", "s", "t", NULL
141 /* Complete with query type of ":cscope find {query_type}".
142 * {query_type} can be letters (c, d, ... t) or numbers (0, 1,
143 * ..., 8) but only complete with letters, since numbers are
145 return (char_u
*)query_type
[idx
];
147 case EXP_CSCOPE_KILL
:
149 static char connection
[5];
151 /* ":cscope kill" accepts connection numbers or partial names of
152 * the pathname of the cscope database as argument. Only complete
153 * with connection numbers. -1 can also be used to kill all
155 for (i
= 0, current_idx
= 0; i
< csinfo_size
; i
++)
157 if (csinfo
[i
].fname
== NULL
)
159 if (current_idx
++ == idx
)
161 vim_snprintf(connection
, sizeof(connection
), "%d", i
);
162 return (char_u
*)connection
;
165 return (current_idx
== idx
&& idx
> 0) ? (char_u
*)"-1" : NULL
;
173 * Handle command line completion for :cscope command.
176 set_context_in_cscope_cmd(xp
, arg
, cmdidx
)
183 /* Default: expand subcommands */
184 xp
->xp_context
= EXPAND_CSCOPE
;
185 xp
->xp_pattern
= arg
;
186 expand_what
= (cmdidx
== CMD_scscope
)
187 ? EXP_SCSCOPE_SUBCMD
: EXP_CSCOPE_SUBCMD
;
189 /* (part of) subcommand already typed */
192 p
= skiptowhite(arg
);
193 if (*p
!= NUL
) /* past first word */
195 xp
->xp_pattern
= skipwhite(p
);
196 if (*skiptowhite(xp
->xp_pattern
) != NUL
)
197 xp
->xp_context
= EXPAND_NOTHING
;
198 else if (STRNICMP(arg
, "add", p
- arg
) == 0)
199 xp
->xp_context
= EXPAND_FILES
;
200 else if (STRNICMP(arg
, "kill", p
- arg
) == 0)
201 expand_what
= EXP_CSCOPE_KILL
;
202 else if (STRNICMP(arg
, "find", p
- arg
) == 0)
203 expand_what
= EXP_CSCOPE_FIND
;
205 xp
->xp_context
= EXPAND_NOTHING
;
210 #endif /* FEAT_CMDL_COMPL */
213 * PRIVATE: do_cscope_general
215 * Find the command, print help if invalid, and then call the corresponding
219 do_cscope_general(eap
, make_split
)
221 int make_split
; /* whether to split window */
225 if ((cmdp
= cs_lookup_cmd(eap
)) == NULL
)
236 (void)MSG_PUTS(_("This cscope command does not support splitting the window.\n"));
239 postponed_split
= -1;
240 postponed_split_flags
= cmdmod
.split
;
241 postponed_split_tab
= cmdmod
.tab
;
248 postponed_split_flags
= 0;
249 postponed_split_tab
= 0;
260 do_cscope_general(eap
, FALSE
);
266 * same as do_cscope, but splits window, too.
272 do_cscope_general(eap
, TRUE
);
285 if (*eap
->arg
== NUL
)
287 (void)EMSG(_("E562: Usage: cstag <ident>"));
294 if (cs_check_for_connections())
296 ret
= cs_find_common("g", (char *)(eap
->arg
), eap
->forceit
, FALSE
,
298 (char *)*eap
->cmdlinep
);
305 if (cs_check_for_tags())
306 ret
= do_tag(eap
->arg
, DT_JUMP
, 0, eap
->forceit
, FALSE
);
309 else if (cs_check_for_tags())
311 ret
= do_tag(eap
->arg
, DT_JUMP
, 0, eap
->forceit
, FALSE
);
315 if (cs_check_for_tags())
317 ret
= do_tag(eap
->arg
, DT_JUMP
, 0, eap
->forceit
, FALSE
);
323 if (cs_check_for_connections())
325 ret
= cs_find_common("g", (char *)(eap
->arg
), eap
->forceit
,
327 (char *)*eap
->cmdlinep
);
333 else if (cs_check_for_connections())
335 ret
= cs_find_common("g", (char *)(eap
->arg
), eap
->forceit
, FALSE
,
337 (char *)*eap
->cmdlinep
);
348 (void)EMSG(_("E257: cstag: tag not found"));
349 #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
360 * this simulates a vim_fgets(), but for cscope, returns the next line
361 * from the cscope output. should only be called from find_tags()
363 * returns TRUE if eof, FALSE otherwise
372 if ((p
= cs_manage_matches(NULL
, NULL
, -1, Get
)) == NULL
)
374 vim_strncpy(buf
, (char_u
*)p
, size
- 1);
381 * PUBLIC: cs_free_tags
383 * called only from do_tag(), when popping the tag stack
388 cs_manage_matches(NULL
, NULL
, -1, Free
);
393 * PUBLIC: cs_print_tags
395 * called from do_tag()
400 cs_manage_matches(NULL
, NULL
, -1, Print
);
405 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
407 * Checks for the existence of a |cscope| connection. If no
408 * parameters are specified, then the function returns:
410 * 0, if cscope was not available (not compiled in), or if there
411 * are no cscope connections; or
412 * 1, if there is at least one cscope connection.
414 * If parameters are specified, then the value of {num}
415 * determines how existence of a cscope connection is checked:
417 * {num} Description of existence check
418 * ----- ------------------------------
419 * 0 Same as no parameters (e.g., "cscope_connection()").
420 * 1 Ignore {prepend}, and use partial string matches for
422 * 2 Ignore {prepend}, and use exact string matches for
424 * 3 Use {prepend}, use partial string matches for both
425 * {dbpath} and {prepend}.
426 * 4 Use {prepend}, use exact string matches for both
427 * {dbpath} and {prepend}.
429 * Note: All string comparisons are case sensitive!
431 #if defined(FEAT_EVAL) || defined(PROTO)
433 cs_connection(num
, dbpath
, ppath
)
440 if (num
< 0 || num
> 4 || (num
> 0 && !dbpath
))
443 for (i
= 0; i
< csinfo_size
; i
++)
445 if (!csinfo
[i
].fname
)
454 if (strstr(csinfo
[i
].fname
, (char *)dbpath
))
458 if (strcmp(csinfo
[i
].fname
, (char *)dbpath
) == 0)
462 if (strstr(csinfo
[i
].fname
, (char *)dbpath
)
463 && ((!ppath
&& !csinfo
[i
].ppath
)
466 && strstr(csinfo
[i
].ppath
, (char *)ppath
))))
470 if ((strcmp(csinfo
[i
].fname
, (char *)dbpath
) == 0)
471 && ((!ppath
&& !csinfo
[i
].ppath
)
474 && (strcmp(csinfo
[i
].ppath
, (char *)ppath
) == 0))))
481 } /* cs_connection */
487 ****************************************************************************/
492 * add cscope database or a directory name (to look for cscope.out)
493 * to the cscope connection list
501 char *fname
, *ppath
, *flags
= NULL
;
503 if ((fname
= strtok((char *)NULL
, (const char *)" ")) == NULL
)
506 return CSCOPE_FAILURE
;
508 if ((ppath
= strtok((char *)NULL
, (const char *)" ")) != NULL
)
509 flags
= strtok((char *)NULL
, (const char *)" ");
511 return cs_add_common(fname
, ppath
, flags
);
518 char *stat_emsg
= _("E563: stat(%s) error: %d");
519 char *buf
= (char *)alloc((unsigned)strlen(stat_emsg
) + MAXPATHL
+ 10);
523 (void)sprintf(buf
, stat_emsg
, fname
, errno
);
528 (void)EMSG(_("E563: stat error"));
533 * PRIVATE: cs_add_common
535 * the common routine to add a new cscope connection. called by
536 * cs_add() and cs_reset(). i really don't like to do this, but this
537 * routine uses a number of goto statements.
540 cs_add_common(arg1
, arg2
, flags
)
541 char *arg1
; /* filename - may contain environment variables */
542 char *arg2
; /* prepend path - may contain environment variables */
552 /* get the filename (arg1), expand it, and try to stat it */
553 if ((fname
= (char *)alloc(MAXPATHL
+ 1)) == NULL
)
556 expand_env((char_u
*)arg1
, (char_u
*)fname
, MAXPATHL
);
557 ret
= stat(fname
, &statbuf
);
566 /* get the prepend path (arg2), expand it, and try to stat it */
569 struct stat statbuf2
;
571 if ((ppath
= (char *)alloc(MAXPATHL
+ 1)) == NULL
)
574 expand_env((char_u
*)arg2
, (char_u
*)ppath
, MAXPATHL
);
575 ret
= stat(ppath
, &statbuf2
);
580 /* if filename is a directory, append the cscope database name to it */
581 if ((statbuf
.st_mode
& S_IFMT
) == S_IFDIR
)
583 fname2
= (char *)alloc((unsigned)(strlen(CSCOPE_DBFILE
) + strlen(fname
) + 2));
587 while (fname
[strlen(fname
)-1] == '/'
589 || fname
[strlen(fname
)-1] == '\\'
593 fname
[strlen(fname
)-1] = '\0';
594 if (strlen(fname
) == 0)
597 if (fname
[0] == '\0')
598 (void)sprintf(fname2
, "/%s", CSCOPE_DBFILE
);
600 (void)sprintf(fname2
, "%s/%s", fname
, CSCOPE_DBFILE
);
602 ret
= stat(fname2
, &statbuf
);
606 cs_stat_emsg(fname2
);
610 i
= cs_insert_filelist(fname2
, ppath
, flags
, &statbuf
);
613 else if (S_ISREG(statbuf
.st_mode
) || S_ISLNK(statbuf
.st_mode
))
615 /* WIN32 - substitute define S_ISREG from os_unix.h */
616 else if (((statbuf
.st_mode
) & S_IFMT
) == S_IFREG
)
619 i
= cs_insert_filelist(fname
, ppath
, flags
, &statbuf
);
625 _("E564: %s is not a directory or a valid cscope database"),
632 if (cs_create_connection(i
) == CSCOPE_FAILURE
633 || cs_read_prompt(i
) == CSCOPE_FAILURE
)
635 cs_release_csp(i
, TRUE
);
642 (void)smsg_attr(hl_attr(HLF_R
),
643 (char_u
*)_("Added cscope database %s"),
651 return CSCOPE_SUCCESS
;
657 return CSCOPE_FAILURE
;
658 } /* cs_add_common */
662 cs_check_for_connections()
664 return (cs_cnt_connections() > 0);
665 } /* cs_check_for_connections */
671 return (p_tags
[0] != NUL
&& curbuf
->b_p_tags
!= NULL
);
672 } /* cs_check_for_tags */
676 * PRIVATE: cs_cnt_connections
678 * count the number of cscope connections
686 for (i
= 0; i
< csinfo_size
; i
++)
688 if (csinfo
[i
].fname
!= NULL
)
692 } /* cs_cnt_connections */
696 int idx
; /* connection index */
698 EMSGN(_("E262: error reading cscope connection %ld"), idx
);
701 #define CSREAD_BUFSIZE 2048
703 * PRIVATE: cs_cnt_matches
705 * count the number of matches for a given cscope connection.
715 buf
= (char *)alloc(CSREAD_BUFSIZE
);
720 if (!fgets(buf
, CSREAD_BUFSIZE
, csinfo
[idx
].fr_fp
))
722 if (feof(csinfo
[idx
].fr_fp
))
725 cs_reading_emsg(idx
);
732 * If the database is out of date, or there's some other problem,
733 * cscope will output error messages before the number-of-lines output.
734 * Display/discard any output that doesn't match what we want.
735 * Accept "\S*cscope: X lines", also matches "mlcscope".
737 if ((stok
= strtok(buf
, (const char *)" ")) == NULL
)
739 if (strstr((const char *)stok
, "cscope:") == NULL
)
742 if ((stok
= strtok(NULL
, (const char *)" ")) == NULL
)
751 if ((stok
= strtok(NULL
, (const char *)" ")) == NULL
)
753 if (strncmp((const char *)stok
, "lines", 5))
761 } /* cs_cnt_matches */
765 * PRIVATE: cs_create_cmd
767 * Creates the actual cscope command query from what the user entered.
770 cs_create_cmd(csoption
, pattern
)
780 case '0' : case 's' :
783 case '1' : case 'g' :
786 case '2' : case 'd' :
789 case '3' : case 'c' :
792 case '4' : case 't' :
795 case '6' : case 'e' :
798 case '7' : case 'f' :
801 case '8' : case 'i' :
805 (void)EMSG(_("E561: unknown cscope search type"));
810 /* Skip white space before the patter, except for text and pattern search,
811 * they may want to use the leading white space. */
813 if (search
!= 4 && search
!= 6)
814 while vim_iswhite(*pat
)
817 if ((cmd
= (char *)alloc((unsigned)(strlen(pat
) + 2))) == NULL
)
820 (void)sprintf(cmd
, "%d%s", search
, pat
);
823 } /* cs_create_cmd */
827 * PRIVATE: cs_create_connection
829 * This piece of code was taken/adapted from nvi. do we need to add
830 * the BSD license notice?
833 cs_create_connection(i
)
837 int to_cs
[2], from_cs
[2];
840 char *prog
, *cmd
, *ppath
= NULL
;
843 SECURITY_ATTRIBUTES sa
;
844 PROCESS_INFORMATION pi
;
846 BOOL pipe_stdin
= FALSE
, pipe_stdout
= FALSE
;
847 HANDLE stdin_rd
, stdout_rd
;
848 HANDLE stdout_wr
, stdin_wr
;
851 # define OPEN_OH_ARGTYPE long
853 # if (_MSC_VER >= 1300)
854 # define OPEN_OH_ARGTYPE intptr_t
856 # define OPEN_OH_ARGTYPE long
863 * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
864 * from_cs[0] and writes to to_cs[1].
866 to_cs
[0] = to_cs
[1] = from_cs
[0] = from_cs
[1] = -1;
867 if (pipe(to_cs
) < 0 || pipe(from_cs
) < 0)
869 (void)EMSG(_("E566: Could not create cscope pipes"));
872 (void)close(to_cs
[0]);
874 (void)close(to_cs
[1]);
875 if (from_cs
[0] != -1)
876 (void)close(from_cs
[0]);
877 if (from_cs
[1] != -1)
878 (void)close(from_cs
[1]);
879 return CSCOPE_FAILURE
;
882 switch (csinfo
[i
].pid
= fork())
885 (void)EMSG(_("E622: Could not fork for cscope"));
887 case 0: /* child: run cscope. */
888 if (dup2(to_cs
[0], STDIN_FILENO
) == -1)
889 PERROR("cs_create_connection 1");
890 if (dup2(from_cs
[1], STDOUT_FILENO
) == -1)
891 PERROR("cs_create_connection 2");
892 if (dup2(from_cs
[1], STDERR_FILENO
) == -1)
893 PERROR("cs_create_connection 3");
896 (void)close(to_cs
[1]);
897 (void)close(from_cs
[0]);
900 /* Create pipes to communicate with cscope */
901 sa
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
902 sa
.bInheritHandle
= TRUE
;
903 sa
.lpSecurityDescriptor
= NULL
;
905 if (!(pipe_stdin
= CreatePipe(&stdin_rd
, &stdin_wr
, &sa
, 0))
906 || !(pipe_stdout
= CreatePipe(&stdout_rd
, &stdout_wr
, &sa
, 0)))
908 (void)EMSG(_("E566: Could not create cscope pipes"));
912 CloseHandle(stdin_rd
);
913 CloseHandle(stdin_wr
);
917 CloseHandle(stdout_rd
);
918 CloseHandle(stdout_wr
);
920 return CSCOPE_FAILURE
;
923 /* expand the cscope exec for env var's */
924 if ((prog
= (char *)alloc(MAXPATHL
+ 1)) == NULL
)
927 return CSCOPE_FAILURE
;
933 expand_env((char_u
*)p_csprg
, (char_u
*)prog
, MAXPATHL
);
935 /* alloc space to hold the cscope command */
936 len
= (int)(strlen(prog
) + strlen(csinfo
[i
].fname
) + 32);
939 /* expand the prepend path for env var's */
940 if ((ppath
= (char *)alloc(MAXPATHL
+ 1)) == NULL
)
944 return CSCOPE_FAILURE
;
950 expand_env((char_u
*)csinfo
[i
].ppath
, (char_u
*)ppath
, MAXPATHL
);
952 len
+= (int)strlen(ppath
);
956 len
+= (int)strlen(csinfo
[i
].flags
);
958 if ((cmd
= (char *)alloc(len
)) == NULL
)
963 return CSCOPE_FAILURE
;
970 /* run the cscope command; is there execl for non-unix systems? */
972 (void)sprintf(cmd
, "exec %s -dl -f %s", prog
, csinfo
[i
].fname
);
975 (void)sprintf(cmd
, "%s -dl -f %s", prog
, csinfo
[i
].fname
);
977 if (csinfo
[i
].ppath
!= NULL
)
979 (void)strcat(cmd
, " -P");
980 (void)strcat(cmd
, csinfo
[i
].ppath
);
982 if (csinfo
[i
].flags
!= NULL
)
984 (void)strcat(cmd
, " ");
985 (void)strcat(cmd
, csinfo
[i
].flags
);
988 /* on Win32 we still need prog */
994 if (execl("/bin/sh", "sh", "-c", cmd
, (char *)NULL
) == -1)
995 PERROR(_("cs_create_connection exec failed"));
999 default: /* parent. */
1001 * Save the file descriptors for later duplication, and
1002 * reopen as streams.
1004 if ((csinfo
[i
].to_fp
= fdopen(to_cs
[1], "w")) == NULL
)
1005 PERROR(_("cs_create_connection: fdopen for to_fp failed"));
1006 if ((csinfo
[i
].fr_fp
= fdopen(from_cs
[0], "r")) == NULL
)
1007 PERROR(_("cs_create_connection: fdopen for fr_fp failed"));
1010 (void)close(to_cs
[0]);
1011 (void)close(from_cs
[1]);
1018 /* Create a new process to run cscope and use pipes to talk with it */
1019 GetStartupInfo(&si
);
1020 si
.dwFlags
= STARTF_USESTDHANDLES
| STARTF_USESHOWWINDOW
;
1021 si
.wShowWindow
= SW_HIDE
; /* Hide child application window */
1022 si
.hStdOutput
= stdout_wr
;
1023 si
.hStdError
= stdout_wr
;
1024 si
.hStdInput
= stdin_rd
;
1025 created
= CreateProcess(NULL
, cmd
, NULL
, NULL
, TRUE
, CREATE_NEW_CONSOLE
,
1026 NULL
, NULL
, &si
, &pi
);
1032 PERROR(_("cs_create_connection exec failed"));
1033 (void)EMSG(_("E623: Could not spawn cscope process"));
1037 csinfo
[i
].pid
= pi
.dwProcessId
;
1038 csinfo
[i
].hProc
= pi
.hProcess
;
1039 CloseHandle(pi
.hThread
);
1041 /* TODO - tidy up after failure to create files on pipe handles. */
1042 if (((fd
= _open_osfhandle((OPEN_OH_ARGTYPE
)stdin_wr
,
1043 _O_TEXT
|_O_APPEND
)) < 0)
1044 || ((csinfo
[i
].to_fp
= _fdopen(fd
, "w")) == NULL
))
1045 PERROR(_("cs_create_connection: fdopen for to_fp failed"));
1046 if (((fd
= _open_osfhandle((OPEN_OH_ARGTYPE
)stdout_rd
,
1047 _O_TEXT
|_O_RDONLY
)) < 0)
1048 || ((csinfo
[i
].fr_fp
= _fdopen(fd
, "r")) == NULL
))
1049 PERROR(_("cs_create_connection: fdopen for fr_fp failed"));
1051 /* Close handles for file descriptors inherited by the cscope process */
1052 CloseHandle(stdin_rd
);
1053 CloseHandle(stdout_wr
);
1057 return CSCOPE_SUCCESS
;
1058 } /* cs_create_connection */
1064 * query cscope using command line interface. parse the output and use tselect
1065 * to allow choices. like Nvi, creates a pipe to send to/from query/cscope.
1067 * returns TRUE if we jump to a tag or abort, FALSE if not.
1076 if (cs_check_for_connections() == FALSE
)
1078 (void)EMSG(_("E567: no cscope connections"));
1082 if ((opt
= strtok((char *)NULL
, (const char *)" ")) == NULL
)
1088 pat
= opt
+ strlen(opt
) + 1;
1089 if (pat
>= (char *)eap
->arg
+ eap_arg_len
)
1096 * Let's replace the NULs written by strtok() with spaces - we need the
1097 * spaces to correctly display the quickfix/location list window's title.
1099 for (i
= 0; i
< eap_arg_len
; ++i
)
1100 if ('\0' == eap
->arg
[i
])
1103 return cs_find_common(opt
, pat
, eap
->forceit
, TRUE
,
1104 eap
->cmdidx
== CMD_lcscope
,
1105 (char *)*eap
->cmdlinep
);
1110 * PRIVATE: cs_find_common
1112 * common code for cscope find, shared by cs_find() and do_cstag()
1115 cs_find_common(opt
, pat
, forceit
, verbose
, use_ll
, cmdline
)
1127 #ifdef FEAT_QUICKFIX
1132 /* create the actual command to send to cscope */
1133 cmd
= cs_create_cmd(opt
, pat
);
1137 nummatches
= (int *)alloc(sizeof(int)*csinfo_size
);
1138 if (nummatches
== NULL
)
1141 /* send query to all open connections, then count the total number
1142 * of matches so we can alloc matchesp all in one swell foop
1144 for (i
= 0; i
< csinfo_size
; i
++)
1147 for (i
= 0; i
< csinfo_size
; i
++)
1149 if (csinfo
[i
].fname
== NULL
|| csinfo
[i
].to_fp
== NULL
)
1152 /* send cmd to cscope */
1153 (void)fprintf(csinfo
[i
].to_fp
, "%s\n", cmd
);
1154 (void)fflush(csinfo
[i
].to_fp
);
1156 nummatches
[i
] = cs_cnt_matches(i
);
1158 if (nummatches
[i
] > -1)
1159 totmatches
+= nummatches
[i
];
1161 if (nummatches
[i
] == 0)
1162 (void)cs_read_prompt(i
);
1166 if (totmatches
== 0)
1168 char *nf
= _("E259: no matches found for cscope query %s of %s");
1173 vim_free(nummatches
);
1177 buf
= (char *)alloc((unsigned)(strlen(opt
) + strlen(pat
) + strlen(nf
)));
1182 sprintf(buf
, nf
, opt
, pat
);
1186 vim_free(nummatches
);
1190 #ifdef FEAT_QUICKFIX
1191 /* get cmd letter */
1222 qfpos
= (char *)vim_strchr(p_csqf
, cmdletter
);
1226 /* next symbol must be +, - or 0 */
1227 if (strchr(CSQF_FLAGS
, *qfpos
) == NULL
)
1229 char *nf
= _("E469: invalid cscopequickfix flag %c for %c");
1230 char *buf
= (char *)alloc((unsigned)strlen(nf
));
1232 /* strlen will be enough because we use chars */
1235 sprintf(buf
, nf
, *qfpos
, *(qfpos
-1));
1239 vim_free(nummatches
);
1243 if (qfpos
!= NULL
&& *qfpos
!= '0' && totmatches
> 0)
1245 /* fill error list */
1247 char_u
*tmp
= vim_tempname('c');
1248 qf_info_T
*qi
= NULL
;
1251 f
= mch_fopen((char *)tmp
, "w");
1253 EMSG2(_(e_notopen
), tmp
);
1256 cs_file_results(f
, nummatches
);
1258 if (use_ll
) /* Use location list */
1260 /* '-' starts a new error list */
1261 if (qf_init(wp
, tmp
, (char_u
*)"%f%*\\t%l%*\\t%m",
1262 *qfpos
== '-', cmdline
) > 0)
1264 # ifdef FEAT_WINDOWS
1265 if (postponed_split
!= 0)
1267 win_split(postponed_split
> 0 ? postponed_split
: 0,
1268 postponed_split_flags
);
1269 # ifdef FEAT_SCROLLBIND
1270 curwin
->w_p_scb
= FALSE
;
1272 postponed_split
= 0;
1277 * In the location list window, use the displayed location
1278 * list. Otherwise, use the location list for the window.
1280 qi
= (bt_quickfix(wp
->w_buffer
) && wp
->w_llist_ref
!= NULL
)
1281 ? wp
->w_llist_ref
: wp
->w_llist
;
1282 qf_jump(qi
, 0, 0, forceit
);
1287 vim_free(nummatches
);
1291 #endif /* FEAT_QUICKFIX */
1293 char **matches
= NULL
, **contexts
= NULL
;
1297 cs_fill_results((char *)pat
, totmatches
, nummatches
, &matches
,
1298 &contexts
, &matched
);
1299 vim_free(nummatches
);
1300 if (matches
== NULL
)
1303 (void)cs_manage_matches(matches
, contexts
, matched
, Store
);
1305 return do_tag((char_u
*)pat
, DT_CSCOPE
, 0, forceit
, verbose
);
1308 } /* cs_find_common */
1317 exarg_T
*eap UNUSED
;
1319 cscmd_T
*cmdp
= cs_cmds
;
1321 (void)MSG_PUTS(_("cscope commands:\n"));
1322 while (cmdp
->name
!= NULL
)
1324 char *help
= _(cmdp
->help
);
1325 int space_cnt
= 30 - vim_strsize((char_u
*)help
);
1327 /* Use %*s rather than %30s to ensure proper alignment in utf-8 */
1330 (void)smsg((char_u
*)_("%-5s: %s%*s (Usage: %s)"),
1332 help
, space_cnt
, " ",
1334 if (strcmp(cmdp
->name
, "find") == 0)
1336 " c: Find functions calling this function\n"
1337 " d: Find functions called by this function\n"
1338 " e: Find this egrep pattern\n"
1339 " f: Find this file\n"
1340 " g: Find this definition\n"
1341 " i: Find files #including this file\n"
1342 " s: Find this C symbol\n"
1343 " t: Find assignments to\n"));
1357 csinfo
[i
].fname
= NULL
;
1358 csinfo
[i
].ppath
= NULL
;
1359 csinfo
[i
].flags
= NULL
;
1361 csinfo
[i
].st_dev
= (dev_t
)0;
1362 csinfo
[i
].st_ino
= (ino_t
)0;
1364 csinfo
[i
].nVolume
= 0;
1365 csinfo
[i
].nIndexHigh
= 0;
1366 csinfo
[i
].nIndexLow
= 0;
1369 csinfo
[i
].fr_fp
= NULL
;
1370 csinfo
[i
].to_fp
= NULL
;
1372 csinfo
[i
].hProc
= NULL
;
1377 static char *GetWin32Error
__ARGS((void));
1383 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
,
1384 NULL
, GetLastError(), 0, (LPSTR
)&msg
, 0, NULL
);
1387 /* remove trailing \r\n */
1388 char *pcrlf
= strstr(msg
, "\r\n");
1397 * PRIVATE: cs_insert_filelist
1399 * insert a new cscope database filename into the filelist
1402 cs_insert_filelist(fname
, ppath
, flags
, sb
)
1406 struct stat
*sb UNUSED
;
1411 BY_HANDLE_FILE_INFORMATION bhfi
;
1413 vim_memset(&bhfi
, 0, sizeof(bhfi
));
1414 /* On windows 9x GetFileInformationByHandle doesn't work, so skip it */
1415 if (!mch_windows95())
1417 hFile
= CreateFile(fname
, FILE_READ_ATTRIBUTES
, 0, NULL
, OPEN_EXISTING
,
1418 FILE_ATTRIBUTE_NORMAL
, NULL
);
1419 if (hFile
== INVALID_HANDLE_VALUE
)
1423 char *cant_msg
= _("E625: cannot open cscope database: %s");
1424 char *winmsg
= GetWin32Error();
1428 (void)EMSG2(cant_msg
, winmsg
);
1432 /* subst filename if can't get error text */
1433 (void)EMSG2(cant_msg
, fname
);
1437 if (!GetFileInformationByHandle(hFile
, &bhfi
))
1441 (void)EMSG(_("E626: cannot get cscope database information"));
1448 i
= -1; /* can be set to the index of an empty item in csinfo */
1449 for (j
= 0; j
< csinfo_size
; j
++)
1451 if (csinfo
[j
].fname
!= NULL
1453 && csinfo
[j
].st_dev
== sb
->st_dev
&& csinfo
[j
].st_ino
== sb
->st_ino
1455 /* compare pathnames first */
1456 && ((fullpathcmp(csinfo
[j
].fname
, fname
, FALSE
) & FPC_SAME
)
1457 /* if not Windows 9x, test index file attributes too */
1458 || (!mch_windows95()
1459 && csinfo
[j
].nVolume
== bhfi
.dwVolumeSerialNumber
1460 && csinfo
[j
].nIndexHigh
== bhfi
.nFileIndexHigh
1461 && csinfo
[j
].nIndexLow
== bhfi
.nFileIndexLow
))
1466 (void)EMSG(_("E568: duplicate cscope database not added"));
1470 if (csinfo
[j
].fname
== NULL
&& i
== -1)
1471 i
= j
; /* remember first empty entry */
1477 if (csinfo_size
== 0)
1479 /* First time allocation: allocate only 1 connection. It should
1480 * be enough for most users. If more is needed, csinfo will be
1483 csinfo
= (csinfo_T
*)alloc_clear(sizeof(csinfo_T
));
1487 /* Reallocate space for more connections. */
1489 csinfo
= vim_realloc(csinfo
, sizeof(csinfo_T
)*csinfo_size
);
1493 for (j
= csinfo_size
/2; j
< csinfo_size
; j
++)
1497 if ((csinfo
[i
].fname
= (char *)alloc((unsigned)strlen(fname
)+1)) == NULL
)
1500 (void)strcpy(csinfo
[i
].fname
, (const char *)fname
);
1504 if ((csinfo
[i
].ppath
= (char *)alloc((unsigned)strlen(ppath
) + 1)) == NULL
)
1506 vim_free(csinfo
[i
].fname
);
1507 csinfo
[i
].fname
= NULL
;
1510 (void)strcpy(csinfo
[i
].ppath
, (const char *)ppath
);
1512 csinfo
[i
].ppath
= NULL
;
1516 if ((csinfo
[i
].flags
= (char *)alloc((unsigned)strlen(flags
) + 1)) == NULL
)
1518 vim_free(csinfo
[i
].fname
);
1519 vim_free(csinfo
[i
].ppath
);
1520 csinfo
[i
].fname
= NULL
;
1521 csinfo
[i
].ppath
= NULL
;
1524 (void)strcpy(csinfo
[i
].flags
, (const char *)flags
);
1526 csinfo
[i
].flags
= NULL
;
1529 csinfo
[i
].st_dev
= sb
->st_dev
;
1530 csinfo
[i
].st_ino
= sb
->st_ino
;
1533 csinfo
[i
].nVolume
= bhfi
.dwVolumeSerialNumber
;
1534 csinfo
[i
].nIndexLow
= bhfi
.nFileIndexLow
;
1535 csinfo
[i
].nIndexHigh
= bhfi
.nFileIndexHigh
;
1538 } /* cs_insert_filelist */
1542 * PRIVATE: cs_lookup_cmd
1544 * find cscope command in command table
1554 if (eap
->arg
== NULL
)
1557 /* Store length of eap->arg before it gets modified by strtok(). */
1558 eap_arg_len
= (int)STRLEN(eap
->arg
);
1560 if ((stok
= strtok((char *)(eap
->arg
), (const char *)" ")) == NULL
)
1564 for (cmdp
= cs_cmds
; cmdp
->name
!= NULL
; ++cmdp
)
1566 if (strncmp((const char *)(stok
), cmdp
->name
, len
) == 0)
1570 } /* cs_lookup_cmd */
1580 exarg_T
*eap UNUSED
;
1585 if ((stok
= strtok((char *)NULL
, (const char *)" ")) == NULL
)
1588 return CSCOPE_FAILURE
;
1591 /* only single digit positive and negative integers are allowed */
1592 if ((strlen(stok
) < 2 && VIM_ISDIGIT((int)(stok
[0])))
1593 || (strlen(stok
) < 3 && stok
[0] == '-'
1594 && VIM_ISDIGIT((int)(stok
[1]))))
1598 /* It must be part of a name. We will try to find a match
1599 * within all the names in the csinfo data structure
1601 for (i
= 0; i
< csinfo_size
; i
++)
1603 if (csinfo
[i
].fname
!= NULL
&& strstr(csinfo
[i
].fname
, stok
))
1608 if ((i
!= -1) && (i
>= csinfo_size
|| i
< -1 || csinfo
[i
].fname
== NULL
))
1611 (void)EMSG2(_("E261: cscope connection %s not found"), stok
);
1617 for (i
= 0; i
< csinfo_size
; i
++)
1619 if (csinfo
[i
].fname
)
1620 cs_kill_execute(i
, csinfo
[i
].fname
);
1624 cs_kill_execute(i
, stok
);
1632 * PRIVATE: cs_kill_execute
1634 * Actually kills a specific cscope connection.
1637 cs_kill_execute(i
, cname
)
1638 int i
; /* cscope table index */
1639 char *cname
; /* cscope database name */
1644 (void)smsg_attr(hl_attr(HLF_R
) | MSG_HIST
,
1645 (char_u
*)_("cscope connection %s closed"), cname
);
1647 cs_release_csp(i
, TRUE
);
1652 * PRIVATE: cs_make_vim_style_matches
1654 * convert the cscope output into into a ctags style entry (as might be found
1655 * in a ctags tags file). there's one catch though: cscope doesn't tell you
1656 * the type of the tag you are looking for. for example, in Darren Hiebert's
1657 * ctags (the one that comes with vim), #define's use a line number to find the
1658 * tag in a file while function definitions use a regexp search pattern.
1660 * i'm going to always use the line number because cscope does something
1661 * quirky (and probably other things i don't know about):
1663 * if you have "# define" in your source file, which is
1664 * perfectly legal, cscope thinks you have "#define". this
1665 * will result in a failed regexp search. :(
1667 * besides, even if this particular case didn't happen, the search pattern
1668 * would still have to be modified to escape all the special regular expression
1669 * characters to comply with ctags formatting.
1672 cs_make_vim_style_matches(fname
, slno
, search
, tagstr
)
1678 /* vim style is ctags:
1680 * <tagstr>\t<filename>\t<linenum_or_search>"\t<extra>
1682 * but as mentioned above, we'll always use the line number and
1683 * put the search pattern (if one exists) as "extra"
1685 * buf is used as part of vim's method of handling tags, and
1686 * (i think) vim frees it when you pop your tags and get replaced
1687 * by new ones on the tag stack.
1694 amt
= (int)(strlen(fname
) + strlen(slno
) + strlen(tagstr
) + strlen(search
)+6);
1695 if ((buf
= (char *)alloc(amt
)) == NULL
)
1698 (void)sprintf(buf
, "%s\t%s\t%s;\"\t%s", tagstr
, fname
, slno
, search
);
1702 amt
= (int)(strlen(fname
) + strlen(slno
) + strlen(tagstr
) + 5);
1703 if ((buf
= (char *)alloc(amt
)) == NULL
)
1706 (void)sprintf(buf
, "%s\t%s\t%s;\"", tagstr
, fname
, slno
);
1710 } /* cs_make_vim_style_matches */
1714 * PRIVATE: cs_manage_matches
1716 * this is kind of hokey, but i don't see an easy way round this..
1718 * Store: keep a ptr to the (malloc'd) memory of matches originally
1719 * generated from cs_find(). the matches are originally lines directly
1720 * from cscope output, but transformed to look like something out of a
1721 * ctags. see cs_make_vim_style_matches for more details.
1723 * Get: used only from cs_fgets(), this simulates a vim_fgets() to return
1724 * the next line from the cscope output. it basically keeps track of which
1725 * lines have been "used" and returns the next one.
1727 * Free: frees up everything and resets
1729 * Print: prints the tags
1732 cs_manage_matches(matches
, contexts
, totmatches
, cmd
)
1738 static char **mp
= NULL
;
1739 static char **cp
= NULL
;
1740 static int cnt
= -1;
1741 static int next
= -1;
1747 assert(matches
!= NULL
);
1748 assert(totmatches
> 0);
1749 if (mp
!= NULL
|| cp
!= NULL
)
1750 (void)cs_manage_matches(NULL
, NULL
, -1, Free
);
1782 cs_print_tags_priv(mp
, cp
, cnt
);
1784 default: /* should not reach here */
1785 (void)EMSG(_("E570: fatal error in cs_manage_matches"));
1790 } /* cs_manage_matches */
1794 * PRIVATE: cs_parse_results
1796 * parse cscope output
1799 cs_parse_results(cnumber
, buf
, bufsize
, context
, linenumber
, search
)
1811 if (fgets(buf
, bufsize
, csinfo
[cnumber
].fr_fp
) == NULL
)
1813 if (feof(csinfo
[cnumber
].fr_fp
))
1816 cs_reading_emsg(cnumber
);
1821 /* If the line's too long for the buffer, discard it. */
1822 if ((p
= strchr(buf
, '\n')) == NULL
)
1824 while ((ch
= getc(csinfo
[cnumber
].fr_fp
)) != EOF
&& ch
!= '\n')
1831 * cscope output is in the following format:
1833 * <filename> <context> <line number> <pattern>
1835 if ((name
= strtok((char *)buf
, (const char *)" ")) == NULL
)
1837 if ((*context
= strtok(NULL
, (const char *)" ")) == NULL
)
1839 if ((*linenumber
= strtok(NULL
, (const char *)" ")) == NULL
)
1841 *search
= *linenumber
+ strlen(*linenumber
) + 1; /* +1 to skip \0 */
1844 * If the file is older than the cscope database, that is,
1845 * the database was built since the file was last modified,
1846 * or there wasn't a search string, use the line number.
1848 if (strcmp(*search
, "<unknown>") == 0)
1851 name
= cs_resolve_file(cnumber
, name
);
1855 #ifdef FEAT_QUICKFIX
1857 * PRIVATE: cs_file_results
1859 * write cscope find results to file
1862 cs_file_results(f
, nummatches_a
)
1868 char *search
, *slno
;
1873 buf
= (char *)alloc(CSREAD_BUFSIZE
);
1877 for (i
= 0; i
< csinfo_size
; i
++)
1879 if (nummatches_a
[i
] < 1)
1882 for (j
= 0; j
< nummatches_a
[i
]; j
++)
1884 if ((fullname
= cs_parse_results(i
, buf
, CSREAD_BUFSIZE
, &cntx
,
1885 &slno
, &search
)) == NULL
)
1888 context
= (char *)alloc((unsigned)strlen(cntx
)+5);
1889 if (context
== NULL
)
1892 if (strcmp(cntx
, "<global>")==0)
1893 strcpy(context
, "<<global>>");
1895 sprintf(context
, "<<%s>>", cntx
);
1898 fprintf(f
, "%s\t%s\t%s\n", fullname
, slno
, context
);
1900 fprintf(f
, "%s\t%s\t%s %s\n", fullname
, slno
, context
, search
);
1904 } /* for all matches */
1906 (void)cs_read_prompt(i
);
1908 } /* for all cscope connections */
1914 * PRIVATE: cs_fill_results
1916 * get parsed cscope output and calls cs_make_vim_style_matches to convert
1918 * When there are no matches sets "*matches_p" to NULL.
1921 cs_fill_results(tagstr
, totmatches
, nummatches_a
, matches_p
, cntxts_p
, matched
)
1931 char *search
, *slno
;
1933 char **matches
= NULL
;
1934 char **cntxts
= NULL
;
1938 assert(totmatches
> 0);
1940 buf
= (char *)alloc(CSREAD_BUFSIZE
);
1944 if ((matches
= (char **)alloc(sizeof(char *) * totmatches
)) == NULL
)
1946 if ((cntxts
= (char **)alloc(sizeof(char *) * totmatches
)) == NULL
)
1949 for (i
= 0; i
< csinfo_size
; i
++)
1951 if (nummatches_a
[i
] < 1)
1954 for (j
= 0; j
< nummatches_a
[i
]; j
++)
1956 if ((fullname
= cs_parse_results(i
, buf
, CSREAD_BUFSIZE
, &cntx
,
1957 &slno
, &search
)) == NULL
)
1960 matches
[totsofar
] = cs_make_vim_style_matches(fullname
, slno
,
1965 if (strcmp(cntx
, "<global>") == 0)
1966 cntxts
[totsofar
] = NULL
;
1968 /* note: if vim_strsave returns NULL, then the context
1969 * will be "<global>", which is misleading.
1971 cntxts
[totsofar
] = (char *)vim_strsave((char_u
*)cntx
);
1973 if (matches
[totsofar
] != NULL
)
1976 } /* for all matches */
1978 (void)cs_read_prompt(i
);
1980 } /* for all cscope connections */
1985 /* No matches, free the arrays and return NULL in "*matches_p". */
1991 *matched
= totsofar
;
1992 *matches_p
= matches
;
1996 } /* cs_fill_results */
1999 /* get the requested path components */
2001 cs_pathcomponents(path
)
2010 s
= path
+ strlen(path
) - 1;
2011 for (i
= 0; i
< p_cspc
; ++i
)
2012 while (s
> path
&& *--s
!= '/'
2018 if ((s
> path
&& *s
== '/')
2020 || (s
> path
&& *s
== '\\')
2028 * PRIVATE: cs_print_tags_priv
2030 * called from cs_manage_matches()
2033 cs_print_tags_priv(matches
, cntxts
, num_matches
)
2039 int bufsize
= 0; /* Track available bufsize */
2042 char *fname
, *lno
, *extra
, *tbuf
;
2044 char *globalcntx
= "GLOBAL";
2045 char *cntxformat
= " <<%s>>";
2047 char *cstag_msg
= _("Cscope tag: %s");
2048 char *csfmt_str
= "%4d %6s ";
2050 assert (num_matches
> 0);
2052 if ((tbuf
= (char *)alloc((unsigned)strlen(matches
[0]) + 1)) == NULL
)
2055 strcpy(tbuf
, matches
[0]);
2056 ptag
= strtok(tbuf
, "\t");
2058 newsize
= (int)(strlen(cstag_msg
) + strlen(ptag
));
2059 buf
= (char *)alloc(newsize
);
2063 (void)sprintf(buf
, cstag_msg
, ptag
);
2064 MSG_PUTS_ATTR(buf
, hl_attr(HLF_T
));
2069 MSG_PUTS_ATTR(_("\n # line"), hl_attr(HLF_T
)); /* strlen is 7 */
2070 msg_advance(msg_col
+ 2);
2071 MSG_PUTS_ATTR(_("filename / context / line\n"), hl_attr(HLF_T
));
2074 for (i
= 0; i
< num_matches
; i
++)
2078 /* if we really wanted to, we could avoid this malloc and strcpy
2079 * by parsing matches[i] on the fly and placing stuff into buf
2080 * directly, but that's too much of a hassle
2082 if ((tbuf
= (char *)alloc((unsigned)strlen(matches
[idx
]) + 1)) == NULL
)
2084 (void)strcpy(tbuf
, matches
[idx
]);
2086 if ((fname
= strtok(tbuf
, (const char *)"\t")) == NULL
)
2088 if ((fname
= strtok(NULL
, (const char *)"\t")) == NULL
)
2090 if ((lno
= strtok(NULL
, (const char *)"\t")) == NULL
)
2092 extra
= strtok(NULL
, (const char *)"\t");
2094 lno
[strlen(lno
)-2] = '\0'; /* ignore ;" at the end */
2096 /* hopefully 'num' (num of matches) will be less than 10^16 */
2097 newsize
= (int)(strlen(csfmt_str
) + 16 + strlen(lno
));
2098 if (bufsize
< newsize
)
2100 buf
= (char *)vim_realloc(buf
, newsize
);
2108 /* csfmt_str = "%4d %6s "; */
2109 (void)sprintf(buf
, csfmt_str
, num
, lno
);
2110 MSG_PUTS_ATTR(buf
, hl_attr(HLF_CM
));
2112 MSG_PUTS_LONG_ATTR(cs_pathcomponents(fname
), hl_attr(HLF_CM
));
2114 /* compute the required space for the context */
2115 if (cntxts
[idx
] != NULL
)
2116 context
= cntxts
[idx
];
2118 context
= globalcntx
;
2119 newsize
= (int)(strlen(context
) + strlen(cntxformat
));
2121 if (bufsize
< newsize
)
2123 buf
= (char *)vim_realloc(buf
, newsize
);
2131 (void)sprintf(buf
, cntxformat
, context
);
2133 /* print the context only if it fits on the same line */
2134 if (msg_col
+ (int)strlen(buf
) >= (int)Columns
)
2143 MSG_PUTS_LONG(extra
);
2146 vim_free(tbuf
); /* only after printing extra due to strtok use */
2154 got_int
= FALSE
; /* don't print any more matches */
2159 } /* for all matches */
2162 } /* cs_print_tags_priv */
2166 * PRIVATE: cs_read_prompt
2168 * read a cscope prompt (basically, skip over the ">> ")
2175 char *buf
= NULL
; /* buffer for possible error message from cscope */
2179 static char *eprompt
= "Press the RETURN key to continue:";
2180 int epromptlen
= (int)strlen(eprompt
);
2183 cs_emsg
= _("E609: Cscope error: %s");
2184 /* compute maximum allowed len for Cscope error message */
2185 maxlen
= (int)(IOSIZE
- strlen(cs_emsg
));
2189 while ((ch
= getc(csinfo
[i
].fr_fp
)) != EOF
&& ch
!= CSCOPE_PROMPT
[0])
2190 /* if there is room and char is printable */
2191 if (bufpos
< maxlen
- 1 && vim_isprintc(ch
))
2193 if (buf
== NULL
) /* lazy buffer allocation */
2194 buf
= (char *)alloc(maxlen
);
2197 /* append character to the message */
2200 if (bufpos
>= epromptlen
2201 && strcmp(&buf
[bufpos
- epromptlen
], eprompt
) == 0)
2203 /* remove eprompt from buf */
2204 buf
[bufpos
- epromptlen
] = NUL
;
2206 /* print message to user */
2207 (void)EMSG2(cs_emsg
, buf
);
2209 /* send RETURN to cscope */
2210 (void)putc('\n', csinfo
[i
].to_fp
);
2211 (void)fflush(csinfo
[i
].to_fp
);
2220 for (n
= 0; n
< (int)strlen(CSCOPE_PROMPT
); ++n
)
2223 ch
= getc(csinfo
[i
].fr_fp
);
2226 PERROR("cs_read_prompt EOF");
2227 if (buf
!= NULL
&& buf
[0] != NUL
)
2228 (void)EMSG2(cs_emsg
, buf
);
2229 else if (p_csverbose
)
2230 cs_reading_emsg(i
); /* don't have additional information */
2231 cs_release_csp(i
, TRUE
);
2233 return CSCOPE_FAILURE
;
2236 if (ch
!= CSCOPE_PROMPT
[n
])
2244 continue; /* didn't find the prompt */
2245 break; /* did find the prompt */
2249 return CSCOPE_SUCCESS
;
2252 #if defined(UNIX) && defined(SIGALRM)
2254 * Used to catch and ignore SIGALRM below.
2257 sig_handler
SIGDEFARG(sigarg
)
2265 * PRIVATE: cs_release_csp
2267 * Does the actual free'ing for the cs ptr with an optional flag of whether
2268 * or not to free the filename. Called by cs_kill and cs_reset.
2271 cs_release_csp(i
, freefnpp
)
2276 * Trying to exit normally (not sure whether it is fit to UNIX cscope
2278 if (csinfo
[i
].to_fp
!= NULL
)
2280 (void)fputs("q\n", csinfo
[i
].to_fp
);
2281 (void)fflush(csinfo
[i
].to_fp
);
2289 # if defined(HAVE_SIGACTION)
2290 struct sigaction sa
, old
;
2292 /* Use sigaction() to limit the waiting time to two seconds. */
2293 sigemptyset(&sa
.sa_mask
);
2294 sa
.sa_handler
= sig_handler
;
2295 sa
.sa_flags
= SA_NODEFER
;
2296 sigaction(SIGALRM
, &sa
, &old
);
2297 alarm(2); /* 2 sec timeout */
2299 /* Block until cscope exits or until timer expires */
2300 pid
= waitpid(csinfo
[i
].pid
, &pstat
, 0);
2301 waitpid_errno
= errno
;
2303 /* cancel pending alarm if still there and restore signal */
2305 sigaction(SIGALRM
, &old
, NULL
);
2309 /* Can't use sigaction(), loop for two seconds. First yield the CPU
2310 * to give cscope a chance to exit quickly. */
2312 for (waited
= 0; waited
< 40; ++waited
)
2314 pid
= waitpid(csinfo
[i
].pid
, &pstat
, WNOHANG
);
2315 waitpid_errno
= errno
;
2317 break; /* break unless the process is still running */
2318 mch_delay(50L, FALSE
); /* sleep 50 ms */
2322 * If the cscope process is still running: kill it.
2323 * Safety check: If the PID would be zero here, the entire X session
2324 * would be killed. -1 and 1 are dangerous as well.
2326 if (pid
< 0 && csinfo
[i
].pid
> 1)
2331 if (waitpid_errno
== ECHILD
)
2334 * When using 'vim -g', vim is forked and cscope process is
2335 * no longer a child process but a sibling. So waitpid()
2336 * fails with errno being ECHILD (No child processes).
2337 * Don't send SIGKILL to cscope immediately but wait
2338 * (polling) for it to exit normally as result of sending
2339 * the "q" command, hence giving it a chance to clean up
2340 * its temporary files.
2345 for (waited
= 0; waited
< 40; ++waited
)
2347 /* Check whether cscope process is still alive */
2348 if (kill(csinfo
[i
].pid
, 0) != 0)
2350 alive
= FALSE
; /* cscope process no longer exists */
2353 mch_delay(50L, FALSE
); /* sleep 50ms */
2359 kill(csinfo
[i
].pid
, SIGKILL
);
2360 (void)waitpid(csinfo
[i
].pid
, &pstat
, 0);
2365 if (csinfo
[i
].hProc
!= NULL
)
2367 /* Give cscope a chance to exit normally */
2368 if (WaitForSingleObject(csinfo
[i
].hProc
, 1000) == WAIT_TIMEOUT
)
2369 TerminateProcess(csinfo
[i
].hProc
, 0);
2370 CloseHandle(csinfo
[i
].hProc
);
2374 if (csinfo
[i
].fr_fp
!= NULL
)
2375 (void)fclose(csinfo
[i
].fr_fp
);
2376 if (csinfo
[i
].to_fp
!= NULL
)
2377 (void)fclose(csinfo
[i
].to_fp
);
2381 vim_free(csinfo
[i
].fname
);
2382 vim_free(csinfo
[i
].ppath
);
2383 vim_free(csinfo
[i
].flags
);
2387 } /* cs_release_csp */
2393 * calls cs_kill on all cscope connections then reinits
2397 exarg_T
*eap UNUSED
;
2399 char **dblist
= NULL
, **pplist
= NULL
, **fllist
= NULL
;
2401 char buf
[20]; /* for sprintf " (#%d)" */
2403 if (csinfo_size
== 0)
2404 return CSCOPE_SUCCESS
;
2406 /* malloc our db and ppath list */
2407 dblist
= (char **)alloc(csinfo_size
* sizeof(char *));
2408 pplist
= (char **)alloc(csinfo_size
* sizeof(char *));
2409 fllist
= (char **)alloc(csinfo_size
* sizeof(char *));
2410 if (dblist
== NULL
|| pplist
== NULL
|| fllist
== NULL
)
2415 return CSCOPE_FAILURE
;
2418 for (i
= 0; i
< csinfo_size
; i
++)
2420 dblist
[i
] = csinfo
[i
].fname
;
2421 pplist
[i
] = csinfo
[i
].ppath
;
2422 fllist
[i
] = csinfo
[i
].flags
;
2423 if (csinfo
[i
].fname
!= NULL
)
2424 cs_release_csp(i
, FALSE
);
2427 /* rebuild the cscope connection list */
2428 for (i
= 0; i
< csinfo_size
; i
++)
2430 if (dblist
[i
] != NULL
)
2432 cs_add_common(dblist
[i
], pplist
[i
], fllist
[i
]);
2435 /* don't use smsg_attr() because we want to display the
2436 * connection number in the same line as
2437 * "Added cscope database..."
2439 sprintf(buf
, " (#%d)", i
);
2440 MSG_PUTS_ATTR(buf
, hl_attr(HLF_R
));
2443 vim_free(dblist
[i
]);
2444 vim_free(pplist
[i
]);
2445 vim_free(fllist
[i
]);
2452 MSG_ATTR(_("All cscope databases reset"), hl_attr(HLF_R
) | MSG_HIST
);
2453 return CSCOPE_SUCCESS
;
2458 * PRIVATE: cs_resolve_file
2460 * construct the full pathname to a file found in the cscope database.
2461 * (Prepends ppath, if there is one and if it's not already prepended,
2462 * otherwise just uses the name found.)
2464 * we need to prepend the prefix because on some cscope's (e.g., the one that
2465 * ships with Solaris 2.6), the output never has the prefix prepended.
2466 * contrast this with my development system (Digital Unix), which does.
2469 cs_resolve_file(i
, name
)
2477 * ppath is freed when we destroy the cscope connection.
2478 * fullname is freed after cs_make_vim_style_matches, after it's been
2479 * copied into the tag buffer used by vim
2481 len
= (int)(strlen(name
) + 2);
2482 if (csinfo
[i
].ppath
!= NULL
)
2483 len
+= (int)strlen(csinfo
[i
].ppath
);
2485 if ((fullname
= (char *)alloc(len
)) == NULL
)
2489 * note/example: this won't work if the cscope output already starts
2490 * "../.." and the prefix path is also "../..". if something like this
2491 * happens, you are screwed up and need to fix how you're using cscope.
2493 if (csinfo
[i
].ppath
!= NULL
&&
2494 (strncmp(name
, csinfo
[i
].ppath
, strlen(csinfo
[i
].ppath
)) != 0) &&
2497 && name
[0] != '\\' && name
[1] != ':'
2500 (void)sprintf(fullname
, "%s/%s", csinfo
[i
].ppath
, name
);
2502 (void)sprintf(fullname
, "%s", name
);
2505 } /* cs_resolve_file */
2511 * show all cscope connections
2515 exarg_T
*eap UNUSED
;
2518 if (cs_cnt_connections() == 0)
2519 MSG_PUTS(_("no cscope connections\n"));
2523 _(" # pid database name prepend path\n"),
2525 for (i
= 0; i
< csinfo_size
; i
++)
2527 if (csinfo
[i
].fname
== NULL
)
2530 if (csinfo
[i
].ppath
!= NULL
)
2531 (void)smsg((char_u
*)"%2d %-5ld %-34s %-32s",
2532 i
, (long)csinfo
[i
].pid
, csinfo
[i
].fname
, csinfo
[i
].ppath
);
2534 (void)smsg((char_u
*)"%2d %-5ld %-34s <none>",
2535 i
, (long)csinfo
[i
].pid
, csinfo
[i
].fname
);
2540 return CSCOPE_SUCCESS
;
2547 * Only called when VIM exits to quit any cscope sessions.
2554 for (i
= 0; i
< csinfo_size
; i
++)
2555 cs_release_csp(i
, TRUE
);
2560 #endif /* FEAT_CSCOPE */