Mercurial > hg > RemoteEditor > vim7
diff src/if_cscope.c @ 39:c16898406ff2
synchorinize version 7.3.081
author | one@zeus.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Fri, 17 Dec 2010 17:43:06 +0900 |
parents | 6a13985590e6 |
children | 67300faee616 |
line wrap: on
line diff
--- a/src/if_cscope.c Wed Nov 26 18:20:31 2008 +0900 +++ b/src/if_cscope.c Fri Dec 17 17:43:06 2010 +0900 @@ -44,9 +44,8 @@ static void cs_fill_results __ARGS((char *, int , int *, char ***, char ***, int *)); static int cs_find __ARGS((exarg_T *eap)); -static int cs_find_common __ARGS((char *opt, char *pat, int, int, int)); +static int cs_find_common __ARGS((char *opt, char *pat, int, int, int, char_u *cmdline)); static int cs_help __ARGS((exarg_T *eap)); -static void cs_init __ARGS((void)); static void clear_csinfo __ARGS((int i)); static int cs_insert_filelist __ARGS((char *, char *, char *, struct stat *)); @@ -66,7 +65,10 @@ static int cs_show __ARGS((exarg_T *eap)); -static csinfo_T csinfo[CSCOPE_MAX_CONNECTIONS]; +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[] = @@ -83,7 +85,7 @@ N_("Reinit all connections"), "reset", 0 }, { "show", cs_show, N_("Show connections"), "show", 0 }, - { NULL } + { NULL, NULL, NULL, NULL, 0 } }; static void @@ -93,12 +95,125 @@ (void)EMSG2(_("E560: Usage: cs[cope] %s"), cs_cmds[(int)x].usage); } +#if defined(FEAT_CMDL_COMPL) || defined(PROTO) + +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(xp, idx) + expand_T *xp UNUSED; + 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(xp, arg, cmdidx) + 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; + } + } +} + +#endif /* FEAT_CMDL_COMPL */ + /* * PRIVATE: do_cscope_general * - * find the command, print help if invalid, and the then call the - * corresponding command function, - * called from do_cscope and do_scscope + * Find the command, print help if invalid, and then call the corresponding + * command function. */ static void do_cscope_general(eap, make_split) @@ -107,7 +222,6 @@ { cscmd_T *cmdp; - cs_init(); if ((cmdp = cs_lookup_cmd(eap)) == NULL) { cs_help(eap); @@ -168,8 +282,6 @@ { int ret = FALSE; - cs_init(); - if (*eap->arg == NUL) { (void)EMSG(_("E562: Usage: cstag <ident>")); @@ -182,7 +294,7 @@ if (cs_check_for_connections()) { ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, FALSE, - FALSE); + FALSE, *eap->cmdlinep); if (ret == FALSE) { cs_free_tags(); @@ -210,7 +322,7 @@ if (cs_check_for_connections()) { ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, - FALSE, FALSE); + FALSE, FALSE, *eap->cmdlinep); if (ret == FALSE) cs_free_tags(); } @@ -219,7 +331,7 @@ else if (cs_check_for_connections()) { ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, FALSE, - FALSE); + FALSE, *eap->cmdlinep); if (ret == FALSE) cs_free_tags(); } @@ -325,7 +437,7 @@ if (num < 0 || num > 4 || (num > 0 && !dbpath)) return FALSE; - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) { if (!csinfo[i].fname) continue; @@ -379,10 +491,9 @@ * * MAXPATHL 256 */ -/* ARGSUSED */ static int cs_add(eap) - exarg_T *eap; + exarg_T *eap UNUSED; { char *fname, *ppath, *flags = NULL; @@ -477,7 +588,7 @@ ) { fname[strlen(fname)-1] = '\0'; - if (strlen(fname) == 0) + if (fname[0] == '\0') break; } if (fname[0] == '\0') @@ -569,7 +680,7 @@ short i; short cnt = 0; - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) { if (csinfo[i].fname != NULL) cnt++; @@ -659,6 +770,7 @@ { char *cmd; short search; + char *pat; switch (csoption[0]) { @@ -692,10 +804,17 @@ return NULL; } - if ((cmd = (char *)alloc((unsigned)(strlen(pattern) + 2))) == 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; + + if ((cmd = (char *)alloc((unsigned)(strlen(pat) + 2))) == NULL) return NULL; - (void)sprintf(cmd, "%d%s", search, pattern); + (void)sprintf(cmd, "%d%s", search, pat); return cmd; } /* cs_create_cmd */ @@ -869,7 +988,7 @@ vim_free(ppath); #if defined(UNIX) - if (execl("/bin/sh", "sh", "-c", cmd, NULL) == -1) + if (execl("/bin/sh", "sh", "-c", cmd, (char *)NULL) == -1) PERROR(_("cs_create_connection exec failed")); exit(127); @@ -949,6 +1068,7 @@ exarg_T *eap; { char *opt, *pat; + int i; if (cs_check_for_connections() == FALSE) { @@ -969,8 +1089,16 @@ 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->cmdidx == CMD_lcscope, *eap->cmdlinep); } /* cs_find */ @@ -980,72 +1108,22 @@ * common code for cscope find, shared by cs_find() and do_cstag() */ static int -cs_find_common(opt, pat, forceit, verbose, use_ll) +cs_find_common(opt, pat, forceit, verbose, use_ll, cmdline) char *opt; char *pat; int forceit; int verbose; int use_ll; + char_u *cmdline; { int i; char *cmd; - int nummatches[CSCOPE_MAX_CONNECTIONS], totmatches; + int *nummatches; + int totmatches; #ifdef FEAT_QUICKFIX char cmdletter; char *qfpos; -#endif - /* create the actual command to send to cscope */ - cmd = cs_create_cmd(opt, pat); - if (cmd == NULL) - return FALSE; - - /* send query to all open connections, then count the total number - * of matches so we can alloc matchesp all in one swell foop - */ - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) - nummatches[i] = 0; - totmatches = 0; - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; 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); - } - vim_free(cmd); - - if (totmatches == 0) - { - char *nf = _("E259: no matches found for cscope query %s of %s"); - char *buf; - - if (!verbose) - return FALSE; - - buf = (char *)alloc((unsigned)(strlen(opt) + strlen(pat) + strlen(nf))); - if (buf == NULL) - (void)EMSG(nf); - else - { - sprintf(buf, nf, opt, pat); - (void)EMSG(buf); - vim_free(buf); - } - return FALSE; - } - -#ifdef FEAT_QUICKFIX /* get cmd letter */ switch (opt[0]) { @@ -1096,7 +1174,80 @@ } return FALSE; } + +# ifdef FEAT_AUTOCMD + if (*qfpos != '0') + { + apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)"cscope", + curbuf->b_fname, TRUE, curbuf); +# ifdef FEAT_EVAL + if (did_throw || force_abort) + return FALSE; +# endif + } +# endif } +#endif + + /* 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); + if (nummatches == NULL) + return FALSE; + + /* send query to all open connections, then count the total number + * of matches so we can alloc matchesp 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); + } + vim_free(cmd); + + if (totmatches == 0) + { + char *nf = _("E259: no matches found for cscope query %s of %s"); + char *buf; + + if (!verbose) + { + vim_free(nummatches); + return FALSE; + } + + buf = (char *)alloc((unsigned)(strlen(opt) + strlen(pat) + strlen(nf))); + if (buf == NULL) + (void)EMSG(nf); + else + { + sprintf(buf, nf, opt, pat); + (void)EMSG(buf); + vim_free(buf); + } + vim_free(nummatches); + return FALSE; + } + +#ifdef FEAT_QUICKFIX if (qfpos != NULL && *qfpos != '0' && totmatches > 0) { /* fill error list */ @@ -1116,19 +1267,22 @@ wp = curwin; /* '-' starts a new error list */ if (qf_init(wp, tmp, (char_u *)"%f%*\\t%l%*\\t%m", - *qfpos == '-') > 0) + *qfpos == '-', cmdline) > 0) { # ifdef FEAT_WINDOWS if (postponed_split != 0) { win_split(postponed_split > 0 ? postponed_split : 0, postponed_split_flags); -# ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -# endif + RESET_BINDING(curwin); postponed_split = 0; } # endif + +# ifdef FEAT_AUTOCMD + apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)"cscope", + curbuf->b_fname, TRUE, curbuf); +# endif if (use_ll) /* * In the location list window, use the displayed location @@ -1141,6 +1295,7 @@ } mch_remove(tmp); vim_free(tmp); + vim_free(nummatches); return TRUE; } else @@ -1152,6 +1307,7 @@ /* read output */ cs_fill_results((char *)pat, totmatches, nummatches, &matches, &contexts, &matched); + vim_free(nummatches); if (matches == NULL) return FALSE; @@ -1167,18 +1323,25 @@ * * print help */ -/* ARGSUSED */ static int cs_help(eap) - exarg_T *eap; + exarg_T *eap UNUSED; { cscmd_T *cmdp = cs_cmds; (void)MSG_PUTS(_("cscope commands:\n")); while (cmdp->name != NULL) { - (void)smsg((char_u *)_("%-5s: %-30s (Usage: %s)"), - cmdp->name, _(cmdp->help), cmdp->usage); + 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" @@ -1198,26 +1361,6 @@ } /* cs_help */ -/* - * PRIVATE: cs_init - * - * initialize cscope structure if not already - */ - static void -cs_init() -{ - short i; - static int init_already = FALSE; - - if (init_already) - return; - - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) - clear_csinfo(i); - - init_already = TRUE; -} /* cs_init */ - static void clear_csinfo(i) int i; @@ -1266,13 +1409,12 @@ * * insert a new cscope database filename into the filelist */ -/*ARGSUSED*/ static int cs_insert_filelist(fname, ppath, flags, sb) char *fname; char *ppath; char *flags; - struct stat *sb; + struct stat *sb UNUSED; { short i, j; #ifndef UNIX @@ -1315,7 +1457,7 @@ #endif i = -1; /* can be set to the index of an empty item in csinfo */ - for (j = 0; j < CSCOPE_MAX_CONNECTIONS; j++) + for (j = 0; j < csinfo_size; j++) { if (csinfo[j].fname != NULL #if defined(UNIX) @@ -1342,9 +1484,25 @@ if (i == -1) { - if (p_csverbose) - (void)EMSG(_("E569: maximum number of cscope connections reached")); - return -1; + i = csinfo_size; + if (csinfo_size == 0) + { + /* First time allocation: allocate only 1 connection. It should + * be enough for most users. If more is needed, csinfo will be + * reallocated. */ + csinfo_size = 1; + csinfo = (csinfo_T *)alloc_clear(sizeof(csinfo_T)); + } + else + { + /* Reallocate space for more connections. */ + csinfo_size *= 2; + csinfo = vim_realloc(csinfo, sizeof(csinfo_T)*csinfo_size); + } + if (csinfo == NULL) + return -1; + for (j = csinfo_size/2; j < csinfo_size; j++) + clear_csinfo(j); } if ((csinfo[i].fname = (char *)alloc((unsigned)strlen(fname)+1)) == NULL) @@ -1428,10 +1586,9 @@ * * nuke em */ -/* ARGSUSED */ static int cs_kill(eap) - exarg_T *eap; + exarg_T *eap UNUSED; { char *stok; short i; @@ -1452,15 +1609,14 @@ /* It must be part of a name. We will try to find a match * within all the names in the csinfo data structure */ - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) { if (csinfo[i].fname != NULL && strstr(csinfo[i].fname, stok)) break; } } - if ((i >= CSCOPE_MAX_CONNECTIONS || i < -1 || csinfo[i].fname == NULL) - && i != -1) + if ((i != -1) && (i >= csinfo_size || i < -1 || csinfo[i].fname == NULL)) { if (p_csverbose) (void)EMSG2(_("E261: cscope connection %s not found"), stok); @@ -1469,7 +1625,7 @@ { if (i == -1) { - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) { if (csinfo[i].fname) cs_kill_execute(i, csinfo[i].fname); @@ -1729,7 +1885,7 @@ if (buf == NULL) return; - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) { if (nummatches_a[i] < 1) continue; @@ -1801,7 +1957,7 @@ if ((cntxts = (char **)alloc(sizeof(char *) * totmatches)) == NULL) goto parse_out; - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) { if (nummatches_a[i] < 1) continue; @@ -1938,7 +2094,7 @@ continue; (void)strcpy(tbuf, matches[idx]); - if ((fname = strtok(tbuf, (const char *)"\t")) == NULL) + if (strtok(tbuf, (const char *)"\t") == NULL) continue; if ((fname = strtok(NULL, (const char *)"\t")) == NULL) continue; @@ -2108,7 +2264,6 @@ /* * Used to catch and ignore SIGALRM below. */ -/* ARGSUSED */ static RETSIGTYPE sig_handler SIGDEFARG(sigarg) { @@ -2148,7 +2303,11 @@ /* Use sigaction() to limit the waiting time to two seconds. */ sigemptyset(&sa.sa_mask); sa.sa_handler = sig_handler; +# ifdef SA_NODEFER sa.sa_flags = SA_NODEFER; +# else + sa.sa_flags = 0; +# endif sigaction(SIGALRM, &sa, &old); alarm(2); /* 2 sec timeout */ @@ -2248,19 +2407,21 @@ * * calls cs_kill on all cscope connections then reinits */ -/* ARGSUSED */ static int cs_reset(eap) - exarg_T *eap; + exarg_T *eap UNUSED; { char **dblist = NULL, **pplist = NULL, **fllist = NULL; int i; char buf[20]; /* for sprintf " (#%d)" */ + if (csinfo_size == 0) + return CSCOPE_SUCCESS; + /* malloc our db and ppath list */ - dblist = (char **)alloc(CSCOPE_MAX_CONNECTIONS * sizeof(char *)); - pplist = (char **)alloc(CSCOPE_MAX_CONNECTIONS * sizeof(char *)); - fllist = (char **)alloc(CSCOPE_MAX_CONNECTIONS * sizeof(char *)); + dblist = (char **)alloc(csinfo_size * sizeof(char *)); + pplist = (char **)alloc(csinfo_size * sizeof(char *)); + fllist = (char **)alloc(csinfo_size * sizeof(char *)); if (dblist == NULL || pplist == NULL || fllist == NULL) { vim_free(dblist); @@ -2269,7 +2430,7 @@ return CSCOPE_FAILURE; } - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) { dblist[i] = csinfo[i].fname; pplist[i] = csinfo[i].ppath; @@ -2279,7 +2440,7 @@ } /* rebuild the cscope connection list */ - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) { if (dblist[i] != NULL) { @@ -2364,10 +2525,9 @@ * * show all cscope connections */ -/* ARGSUSED */ static int cs_show(eap) - exarg_T *eap; + exarg_T *eap UNUSED; { short i; if (cs_cnt_connections() == 0) @@ -2377,7 +2537,7 @@ MSG_PUTS_ATTR( _(" # pid database name prepend path\n"), hl_attr(HLF_T)); - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) { if (csinfo[i].fname == NULL) continue; @@ -2406,8 +2566,10 @@ { int i; - for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + for (i = 0; i < csinfo_size; i++) cs_release_csp(i, TRUE); + vim_free(csinfo); + csinfo_size = 0; } #endif /* FEAT_CSCOPE */