ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/trunk/contrib/nvi/ex/ex_cscope.c
(Generate patch)

Comparing trunk/contrib/nvi/ex/ex_cscope.c (file contents):
Revision 10822 by laffer1, Sat Dec 7 23:54:44 2013 UTC vs.
Revision 10823 by laffer1, Sun Jun 10 20:23:48 2018 UTC

# Line 10 | Line 10
10   #include "config.h"
11  
12   #ifndef lint
13 < static const char sccsid[] = "@(#)ex_cscope.c   10.13 (Berkeley) 9/15/96";
13 > static const char sccsid[] = "$Id: ex_cscope.c,v 10.25 2012/10/04 09:23:03 zy Exp $";
14   #endif /* not lint */
15  
16 < #include <sys/param.h>
17 < #include <sys/types.h>          /* XXX: param.h may not have included types.h */
16 > #include <sys/types.h>
17   #include <sys/queue.h>
18   #include <sys/stat.h>
20 #include <sys/time.h>
19   #include <sys/wait.h>
20  
21   #include <bitstring.h>
# Line 25 | Line 23 | static const char sccsid[] = "@(#)ex_cscope.c  10.13 (B
23   #include <errno.h>
24   #include <fcntl.h>
25   #include <limits.h>
26 + #include <signal.h>
27   #include <stddef.h>
28   #include <stdio.h>
29   #include <stdlib.h>
# Line 62 | Line 61 | find c|d|e|f|g|i|s|t buffer|pattern\n\
61        s: find all uses of name\n\
62        t: find assignments to name"
63  
64 < static int cscope_add __P((SCR *, EXCMD *, char *));
65 < static int cscope_find __P((SCR *, EXCMD*, char *));
66 < static int cscope_help __P((SCR *, EXCMD *, char *));
67 < static int cscope_kill __P((SCR *, EXCMD *, char *));
68 < static int cscope_reset __P((SCR *, EXCMD *, char *));
64 > static int cscope_add __P((SCR *, EXCMD *, CHAR_T *));
65 > static int cscope_find __P((SCR *, EXCMD*, CHAR_T *));
66 > static int cscope_help __P((SCR *, EXCMD *, CHAR_T *));
67 > static int cscope_kill __P((SCR *, EXCMD *, CHAR_T *));
68 > static int cscope_reset __P((SCR *, EXCMD *, CHAR_T *));
69  
70   typedef struct _cc {
71          char     *name;
72 <        int     (*function) __P((SCR *, EXCMD *, char *));
72 >        int     (*function) __P((SCR *, EXCMD *, CHAR_T *));
73          char     *help_msg;
74          char     *usage_msg;
75   } CC;
# Line 108 | Line 107 | static int      terminate __P((SCR *, CSC *, int));
107   * PUBLIC: int ex_cscope __P((SCR *, EXCMD *));
108   */
109   int
110 < ex_cscope(sp, cmdp)
112 <        SCR *sp;
113 <        EXCMD *cmdp;
110 > ex_cscope(SCR *sp, EXCMD *cmdp)
111   {
112          CC const *ccp;
113          EX_PRIVATE *exp;
114          int i;
115 <        char *cmd, *p;
115 >        CHAR_T *cmd;
116 >        CHAR_T *p;
117 >        char *np;
118 >        size_t nlen;
119  
120          /* Initialize the default cscope directories. */
121          exp = EXP(sp);
# Line 139 | Line 139 | ex_cscope(sp, cmdp)
139                  for (; *p && isspace(*p); ++p);
140          }
141  
142 <        if ((ccp = lookup_ccmd(cmd)) == NULL) {
142 >        INT2CHAR(sp, cmd, STRLEN(cmd) + 1, np, nlen);
143 >        if ((ccp = lookup_ccmd(np)) == NULL) {
144   usage:          msgq(sp, M_ERR, "309|Use \"cscope help\" for help");
145                  return (1);
146          }
# Line 153 | Line 154 | usage:         msgq(sp, M_ERR, "309|Use \"cscope help\" for h
154   *      Initialize the cscope package.
155   */
156   static int
157 < start_cscopes(sp, cmdp)
157 <        SCR *sp;
158 <        EXCMD *cmdp;
157 > start_cscopes(SCR *sp, EXCMD *cmdp)
158   {
159          size_t blen, len;
160          char *bp, *cscopes, *p, *t;
161 +        CHAR_T *wp;
162 +        size_t wlen;
163  
164          /*
165           * EXTENSION #1:
# Line 175 | Line 176 | start_cscopes(sp, cmdp)
176          if ((cscopes = getenv("CSCOPE_DIRS")) == NULL)
177                  return (0);
178          len = strlen(cscopes);
179 <        GET_SPACE_RET(sp, bp, blen, len);
179 >        GET_SPACE_RETC(sp, bp, blen, len);
180          memcpy(bp, cscopes, len + 1);
181  
182          for (cscopes = t = bp; (p = strsep(&t, "\t :")) != NULL;)
183 <                if (*p != '\0')
184 <                        (void)cscope_add(sp, cmdp, p);
183 >                if (*p != '\0') {
184 >                        CHAR2INT(sp, p, strlen(p) + 1, wp, wlen);
185 >                        (void)cscope_add(sp, cmdp, wp);
186 >                }
187  
188          FREE_SPACE(sp, bp, blen);
189          return (0);
# Line 191 | Line 194 | start_cscopes(sp, cmdp)
194   *      The cscope add command.
195   */
196   static int
197 < cscope_add(sp, cmdp, dname)
195 <        SCR *sp;
196 <        EXCMD *cmdp;
197 <        char *dname;
197 > cscope_add(SCR *sp, EXCMD *cmdp, CHAR_T *dname)
198   {
199          struct stat sb;
200          EX_PRIVATE *exp;
201          CSC *csc;
202          size_t len;
203          int cur_argc;
204 <        char *dbname, path[MAXPATHLEN];
204 >        char *dbname, *path;
205 >        char *np = NULL;
206 >        size_t nlen;
207  
208          exp = EXP(sp);
209  
# Line 211 | Line 213 | cscope_add(sp, cmdp, dname)
213           * >1 additional args: object, too many args.
214           */
215          cur_argc = cmdp->argc;
216 <        if (argv_exp2(sp, cmdp, dname, strlen(dname)))
216 >        if (argv_exp2(sp, cmdp, dname, STRLEN(dname))) {
217                  return (1);
218 +        }
219          if (cmdp->argc == cur_argc) {
220                  (void)csc_help(sp, "add");
221                  return (1);
# Line 220 | Line 223 | cscope_add(sp, cmdp, dname)
223          if (cmdp->argc == cur_argc + 1)
224                  dname = cmdp->argv[cur_argc]->bp;
225          else {
226 <                ex_emsg(sp, dname, EXM_FILECOUNT);
226 >                ex_emsg(sp, np, EXM_FILECOUNT);
227                  return (1);
228          }
229  
230 +        INT2CHAR(sp, dname, STRLEN(dname)+1, np, nlen);
231 +
232          /*
233           * The user can specify a specific file (so they can have multiple
234           * Cscope databases in a single directory) or a directory.  If the
# Line 231 | Line 236 | cscope_add(sp, cmdp, dname)
236           * standard database file name and try again.  Store the directory
237           * name regardless so that we can use it as a base for searches.
238           */
239 <        if (stat(dname, &sb)) {
240 <                msgq(sp, M_SYSERR, dname);
239 >        if (stat(np, &sb)) {
240 >                msgq(sp, M_SYSERR, "%s", np);
241                  return (1);
242          }
243          if (S_ISDIR(sb.st_mode)) {
244 <                (void)snprintf(path, sizeof(path),
245 <                    "%s/%s", dname, CSCOPE_DBFILE);
244 >                if ((path = join(np, CSCOPE_DBFILE)) == NULL) {
245 >                        msgq(sp, M_SYSERR, NULL);
246 >                        return (1);
247 >                }
248                  if (stat(path, &sb)) {
249 <                        msgq(sp, M_SYSERR, path);
249 >                        msgq(sp, M_SYSERR, "%s", path);
250 >                        free(path);
251                          return (1);
252                  }
253 +                free(path);
254                  dbname = CSCOPE_DBFILE;
255 <        } else if ((dbname = strrchr(dname, '/')) != NULL)
255 >        } else if ((dbname = strrchr(np, '/')) != NULL)
256                  *dbname++ = '\0';
257 +        else {
258 +                dbname = np;
259 +                np = ".";
260 +        }
261  
262          /* Allocate a cscope connection structure and initialize its fields. */
263 <        len = strlen(dname);
263 >        len = strlen(np);
264          CALLOC_RET(sp, csc, CSC *, 1, sizeof(CSC) + len);
265          csc->dname = csc->buf;
266          csc->dlen = len;
267 <        memcpy(csc->dname, dname, len);
268 <        csc->mtime = sb.st_mtime;
267 >        memcpy(csc->dname, np, len);
268 >        csc->mtim = sb.st_mtimespec;
269  
270          /* Get the search paths for the cscope. */
271          if (get_paths(sp, csc))
# Line 267 | Line 280 | cscope_add(sp, cmdp, dname)
280           * on error, we have to call terminate, which expects the csc to
281           * be on the chain.
282           */
283 <        LIST_INSERT_HEAD(&exp->cscq, csc, q);
283 >        SLIST_INSERT_HEAD(exp->cscq, csc, q);
284  
285          /* Read the initial prompt from the cscope to make sure it's okay. */
286 <        if (read_prompt(sp, csc)) {
274 <                terminate(sp, csc, 0);
275 <                return (1);
276 <        }
286 >        return read_prompt(sp, csc);
287  
278        return (0);
279
288   err:    free(csc);
289          return (1);
290   }
# Line 287 | Line 295 | err:   free(csc);
295   *      cscope database.
296   */
297   static int
298 < get_paths(sp, csc)
291 <        SCR *sp;
292 <        CSC *csc;
298 > get_paths(SCR *sp, CSC *csc)
299   {
300          struct stat sb;
301          int fd, nentries;
302          size_t len;
303 <        char *p, **pathp, buf[MAXPATHLEN * 2];
303 >        char *p, **pathp, *buf;
304  
305          /*
306           * EXTENSION #2:
# Line 308 | Line 314 | get_paths(sp, csc)
314           * directory.  To fix this, rewrite the each path using the cscope
315           * directory as a prefix.
316           */
317 <        (void)snprintf(buf, sizeof(buf), "%s/%s", csc->dname, CSCOPE_PATHS);
317 >        if ((buf = join(csc->dname, CSCOPE_PATHS)) == NULL) {
318 >                msgq(sp, M_SYSERR, NULL);
319 >                return (1);
320 >        }
321          if (stat(buf, &sb) == 0) {
322                  /* Read in the CSCOPE_PATHS file. */
323                  len = sb.st_size;
# Line 318 | Line 327 | get_paths(sp, csc)
327                           msgq_str(sp, M_SYSERR, buf, "%s");
328                           if (fd >= 0)
329                                  (void)close(fd);
330 +                         free(buf);
331                           return (1);
332                  }
333                  (void)close(fd);
334 +                free(buf);
335                  csc->pbuf[len] = '\0';
336  
337                  /* Count up the entries. */
# Line 336 | Line 347 | get_paths(sp, csc)
347                          *pathp++ = p;
348                  return (0);
349          }
350 +        free(buf);
351  
352          /*
353           * If the CSCOPE_PATHS file doesn't exist, we look for files
# Line 362 | Line 374 | alloc_err:
374   *      Fork off the cscope process.
375   */
376   static int
377 < run_cscope(sp, csc, dbname)
366 <        SCR *sp;
367 <        CSC *csc;
368 <        char *dbname;
377 > run_cscope(SCR *sp, CSC *csc, char *dbname)
378   {
379          int to_cs[2], from_cs[2];
380 <        char cmd[MAXPATHLEN * 2];
380 >        char *cmd;
381  
382          /*
383           * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
384           * from_cs[0] and writes to to_cs[1].
385           */
386 <        to_cs[0] = to_cs[1] = from_cs[0] = from_cs[0] = -1;
386 >        to_cs[0] = to_cs[1] = from_cs[0] = from_cs[1] = -1;
387          if (pipe(to_cs) < 0 || pipe(from_cs) < 0) {
388                  msgq(sp, M_SYSERR, "pipe");
389                  goto err;
390          }
391          switch (csc->pid = vfork()) {
392 +                char *dn, *dbn;
393          case -1:
394                  msgq(sp, M_SYSERR, "vfork");
395   err:            if (to_cs[0] != -1)
# Line 401 | Line 411 | err:           if (to_cs[0] != -1)
411                  (void)close(from_cs[0]);
412  
413                  /* Run the cscope command. */
414 < #define CSCOPE_CMD_FMT          "cd '%s' && exec cscope -dl -f %s"
415 <                (void)snprintf(cmd, sizeof(cmd),
416 <                    CSCOPE_CMD_FMT, csc->dname, dbname);
417 <                (void)execl(_PATH_BSHELL, "sh", "-c", cmd, NULL);
414 > #define CSCOPE_CMD_FMT          "cd %s && exec cscope -dl -f %s"
415 >                if ((dn = quote(csc->dname)) == NULL)
416 >                        goto nomem;
417 >                if ((dbn = quote(dbname)) == NULL) {
418 >                        free(dn);
419 >                        goto nomem;
420 >                }
421 >                (void)asprintf(&cmd, CSCOPE_CMD_FMT, dn, dbn);
422 >                free(dbn);
423 >                free(dn);
424 >                if (cmd == NULL) {
425 > nomem:                  msgq(sp, M_SYSERR, NULL);
426 >                        _exit (1);
427 >                }
428 >                (void)execl(_PATH_BSHELL, "sh", "-c", cmd, (char *)NULL);
429                  msgq_str(sp, M_SYSERR, cmd, "execl: %s");
430 +                free(cmd);
431                  _exit (127);
432                  /* NOTREACHED */
433          default:                        /* parent. */
# Line 431 | Line 453 | err:           if (to_cs[0] != -1)
453   *      The cscope find command.
454   */
455   static int
456 < cscope_find(sp, cmdp, pattern)
435 <        SCR *sp;
436 <        EXCMD *cmdp;
437 <        char *pattern;
456 > cscope_find(SCR *sp, EXCMD *cmdp, CHAR_T *pattern)
457   {
458          CSC *csc, *csc_next;
459          EX_PRIVATE *exp;
# Line 444 | Line 463 | cscope_find(sp, cmdp, pattern)
463          recno_t lno;
464          size_t cno, search;
465          int force, istmp, matches;
466 +        char *np = NULL;
467 +        size_t nlen;
468  
469          exp = EXP(sp);
470  
471          /* Check for connections. */
472 <        if (exp->cscq.lh_first == NULL) {
472 >        if (SLIST_EMPTY(exp->cscq)) {
473                  msgq(sp, M_ERR, "310|No cscope connections running");
474                  return (1);
475          }
# Line 460 | Line 481 | cscope_find(sp, cmdp, pattern)
481           */
482          rtp = NULL;
483          rtqp = NULL;
484 <        if (exp->tq.cqh_first == (void *)&exp->tq) {
484 >        if (TAILQ_EMPTY(exp->tq)) {
485                  /* Initialize the `local context' tag queue structure. */
486                  CALLOC_GOTO(sp, rtqp, TAGQ *, 1, sizeof(TAGQ));
487 <                CIRCLEQ_INIT(&rtqp->tagq);
487 >                TAILQ_INIT(rtqp->tagq);
488  
489                  /* Initialize and link in its tag structure. */
490                  CALLOC_GOTO(sp, rtp, TAG *, 1, sizeof(TAG));
491 <                CIRCLEQ_INSERT_HEAD(&rtqp->tagq, rtp, q);
492 <                rtqp->current = rtp;
491 >                TAILQ_INSERT_HEAD(rtqp->tagq, rtp, q);
492 >                rtqp->current = rtp;
493          }
494  
495          /* Create the cscope command. */
496 <        if ((tqp = create_cs_cmd(sp, pattern, &search)) == NULL)
496 >        INT2CHAR(sp, pattern, STRLEN(pattern) + 1, np, nlen);
497 >        np = strdup(np);
498 >        if ((tqp = create_cs_cmd(sp, np, &search)) == NULL)
499                  goto err;
500 +        if (np != NULL)
501 +                free(np);
502  
503          /*
504           * Stick the current context in a convenient place, we'll lose it
# Line 486 | Line 511 | cscope_find(sp, cmdp, pattern)
511  
512          /* Search all open connections for a match. */
513          matches = 0;
514 <        for (csc = exp->cscq.lh_first; csc != NULL; csc = csc_next) {
515 <                /* Copy csc->q.lh_next here in case csc is killed. */
491 <                csc_next = csc->q.le_next;
492 <
514 >        /* Copy next connect here in case csc is killed. */
515 >        SLIST_FOREACH_SAFE(csc, exp->cscq, q, csc_next) {
516                  /*
517                   * Send the command to the cscope program.  (We skip the
518                   * first two bytes of the command, because we stored the
519                   * search cscope command character and a leading space
520                   * there.)
521                   */
522 <                (void)fprintf(csc->to_fp, "%d%s\n", search, tqp->tag + 2);
522 >                (void)fprintf(csc->to_fp, "%lu%s\n", search, tqp->tag + 2);
523                  (void)fflush(csc->to_fp);
524  
525                  /* Read the output. */
526 <                if (parse(sp, csc, tqp, &matches)) {
527 <                        if (rtqp != NULL)
505 <                                free(rtqp);
506 <                        tagq_free(sp, tqp);
507 <                        return (1);
508 <                }
526 >                if (parse(sp, csc, tqp, &matches))
527 >                        goto nomatch;
528          }
529  
530          if (matches == 0) {
531                  msgq(sp, M_INFO, "278|No matches for query");
532 <                return (0);
532 > nomatch:        if (rtp != NULL)
533 >                        free(rtp);
534 >                if (rtqp != NULL)
535 >                        free(rtqp);
536 >                tagq_free(sp, tqp);
537 >                return (1);
538          }
539  
516        tqp->current = tqp->tagq.cqh_first;
517
540          /* Try to switch to the first tag. */
541          force = FL_ISSET(cmdp->iflags, E_C_FORCE);
542          if (F_ISSET(cmdp, E_NEWSCREEN)) {
# Line 533 | Line 555 | cscope_find(sp, cmdp, pattern)
555           * in place, so we can pop all the way back to the current mark.
556           * Note, it doesn't point to much of anything, it's a placeholder.
557           */
558 <        if (exp->tq.cqh_first == (void *)&exp->tq) {
559 <                CIRCLEQ_INSERT_HEAD(&exp->tq, rtqp, q);
558 >        if (TAILQ_EMPTY(exp->tq)) {
559 >                TAILQ_INSERT_HEAD(exp->tq, rtqp, q);
560          } else
561 <                rtqp = exp->tq.cqh_first;
561 >                rtqp = TAILQ_FIRST(exp->tq);
562  
563          /* Link the current TAGQ structure into place. */
564 <        CIRCLEQ_INSERT_HEAD(&exp->tq, tqp, q);
564 >        TAILQ_INSERT_HEAD(exp->tq, tqp, q);
565  
566          (void)cscope_search(sp, tqp, tqp->current);
567  
# Line 570 | Line 592 | alloc_err:
592                  free(rtqp);
593          if (rtp != NULL)
594                  free(rtp);
595 +        if (np != NULL)
596 +                free(np);
597          return (1);
598   }
599  
# Line 578 | Line 602 | alloc_err:
602   *      Build a cscope command, creating and initializing the base TAGQ.
603   */
604   static TAGQ *
605 < create_cs_cmd(sp, pattern, searchp)
582 <        SCR *sp;
583 <        char *pattern;
584 <        size_t *searchp;
605 > create_cs_cmd(SCR *sp, char *pattern, size_t *searchp)
606   {
607          CB *cbp;
608          TAGQ *tqp;
# Line 601 | Line 622 | create_cs_cmd(sp, pattern, searchp)
622                  goto usage;
623  
624          /* Skip leading blanks, check for command character. */
625 <        for (; isblank(pattern[0]); ++pattern);
626 <        if (pattern[0] == '\0' || !isblank(pattern[1]))
625 >        for (; cmdskip(pattern[0]); ++pattern);
626 >        if (pattern[0] == '\0' || !cmdskip(pattern[1]))
627                  goto usage;
628          for (*searchp = 0, p = CSCOPE_QUERIES;
629              *p != '\0' && *p != pattern[0]; ++*searchp, ++p);
# Line 614 | Line 635 | create_cs_cmd(sp, pattern, searchp)
635          }
636  
637          /* Skip <blank> characters to the pattern. */
638 <        for (p = pattern + 1; *p != '\0' && isblank(*p); ++p);
638 >        for (p = pattern + 1; *p != '\0' && cmdskip(*p); ++p);
639          if (*p == '\0') {
640   usage:          (void)csc_help(sp, "find");
641                  return (NULL);
# Line 625 | Line 646 | usage:         (void)csc_help(sp, "find");
646          if (p[0] == '"' && p[1] != '\0' && p[2] == '\0')
647                  CBNAME(sp, cbp, p[1]);
648          if (cbp != NULL) {
649 <                p = cbp->textq.cqh_first->lb;
650 <                tlen = cbp->textq.cqh_first->len;
649 >                INT2CHAR(sp, TAILQ_FIRST(cbp->textq)->lb,
650 >                        TAILQ_FIRST(cbp->textq)->len, p, tlen);
651          } else
652                  tlen = strlen(p);
653  
# Line 634 | Line 655 | usage:         (void)csc_help(sp, "find");
655          CALLOC(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + tlen + 3);
656          if (tqp == NULL)
657                  return (NULL);
658 <        CIRCLEQ_INIT(&tqp->tagq);
658 >        TAILQ_INIT(tqp->tagq);
659          tqp->tag = tqp->buf;
660          tqp->tag[0] = pattern[0];
661          tqp->tag[1] = ' ';
# Line 651 | Line 672 | usage:         (void)csc_help(sp, "find");
672   *      Parse the cscope output.
673   */
674   static int
675 < parse(sp, csc, tqp, matchesp)
655 <        SCR *sp;
656 <        CSC *csc;
657 <        TAGQ *tqp;
658 <        int *matchesp;
675 > parse(SCR *sp, CSC *csc, TAGQ *tqp, int *matchesp)
676   {
677          TAG *tp;
678 <        recno_t slno;
679 <        size_t dlen, nlen, slen;
680 <        int ch, i, isolder, nlines;
681 <        char *dname, *name, *search, *p, *t, dummy[2], buf[2048];
678 >        recno_t slno = 0;
679 >        size_t dlen, nlen = 0, slen = 0;
680 >        int ch, i, isolder = 0, nlines;
681 >        char *dname = NULL, *name = NULL, *search, *p, *t, dummy[2], buf[2048];
682 >        CHAR_T *wp;
683 >        size_t wlen;
684  
685          for (;;) {
686                  if (!fgets(buf, sizeof(buf), csc->from_fp))
# Line 738 | Line 757 | parse(sp, csc, tqp, matchesp)
757                   * length cscope information that follows it.
758                   */
759                  CALLOC_RET(sp, tp,
760 <                    TAG *, 1, sizeof(TAG) + dlen + 2 + nlen + 1 + slen + 1);
761 <                tp->fname = tp->buf;
762 <                if (dlen != 0) {
760 >                    TAG *, 1, sizeof(TAG) + dlen + 2 + nlen + 1 +
761 >                    (slen + 1) * sizeof(CHAR_T));
762 >                tp->fname = (char *)tp->buf;
763 >                if (dlen == 1 && *dname == '.')
764 >                        --dlen;
765 >                else if (dlen != 0) {
766                          memcpy(tp->fname, dname, dlen);
767                          tp->fname[dlen] = '/';
768                          ++dlen;
# Line 748 | Line 770 | parse(sp, csc, tqp, matchesp)
770                  memcpy(tp->fname + dlen, name, nlen + 1);
771                  tp->fnlen = dlen + nlen;
772                  tp->slno = slno;
773 <                if (slen != 0) {
774 <                        tp->search = tp->fname + tp->fnlen + 1;
775 <                        memcpy(tp->search, search, (tp->slen = slen) + 1);
776 <                }
755 <                CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
773 >                tp->search = (CHAR_T*)(tp->fname + tp->fnlen + 1);
774 >                CHAR2INT(sp, search, slen + 1, wp, wlen);
775 >                MEMCPY(tp->search, wp, (tp->slen = slen) + 1);
776 >                TAILQ_INSERT_TAIL(tqp->tagq, tp, q);
777  
778 +                /* Try to preset the tag within the current file. */
779 +                if (sp->frp != NULL && sp->frp->name != NULL &&
780 +                    tqp->current == NULL && !strcmp(tp->fname, sp->frp->name))
781 +                        tqp->current = tp;
782 +
783                  ++*matchesp;
784          }
785  
786 <        (void)read_prompt(sp, csc);
787 <        return (0);
786 >        if (tqp->current == NULL)
787 >                tqp->current = TAILQ_FIRST(tqp->tagq);
788  
789 +        return read_prompt(sp, csc);
790 +
791   io_err: if (feof(csc->from_fp))
792                  errno = EIO;
793          msgq_str(sp, M_SYSERR, "%s", csc->dname);
# Line 772 | Line 800 | io_err:        if (feof(csc->from_fp))
800   *      Search for the right path to this file.
801   */
802   static void
803 < csc_file(sp, csc, name, dirp, dlenp, isolderp)
776 <        SCR *sp;
777 <        CSC *csc;
778 <        char *name, **dirp;
779 <        size_t *dlenp;
780 <        int *isolderp;
803 > csc_file(SCR *sp, CSC *csc, char *name, char **dirp, size_t *dlenp, int *isolderp)
804   {
805          struct stat sb;
806 <        char **pp, buf[MAXPATHLEN];
806 >        char **pp, *buf;
807  
808          /*
809           * Check for the file in all of the listed paths.  If we don't
# Line 790 | Line 813 | csc_file(sp, csc, name, dirp, dlenp, isolderp)
813           * lives.
814           */
815          for (pp = csc->paths; *pp != NULL; ++pp) {
816 <                (void)snprintf(buf, sizeof(buf), "%s/%s", *pp, name);
816 >                if ((buf = join(*pp, name)) == NULL) {
817 >                        msgq(sp, M_SYSERR, NULL);
818 >                        *dlenp = 0;
819 >                        return;
820 >                }
821                  if (stat(buf, &sb) == 0) {
822 +                        free(buf);
823                          *dirp = *pp;
824                          *dlenp = strlen(*pp);
825 <                        *isolderp = sb.st_mtime < csc->mtime;
825 >                        *isolderp = timespeccmp(
826 >                            &sb.st_mtimespec, &csc->mtim, <);
827                          return;
828                  }
829 +                free(buf);
830          }
831          *dlenp = 0;
832   }
# Line 806 | Line 836 | csc_file(sp, csc, name, dirp, dlenp, isolderp)
836   *      The cscope help command.
837   */
838   static int
839 < cscope_help(sp, cmdp, subcmd)
810 <        SCR *sp;
811 <        EXCMD *cmdp;
812 <        char *subcmd;
839 > cscope_help(SCR *sp, EXCMD *cmdp, CHAR_T *subcmd)
840   {
841 <        return (csc_help(sp, subcmd));
841 >        char *np;
842 >        size_t nlen;
843 >
844 >        INT2CHAR(sp, subcmd, STRLEN(subcmd) + 1, np, nlen);
845 >        return (csc_help(sp, np));
846   }
847  
848   /*
# Line 819 | Line 850 | cscope_help(sp, cmdp, subcmd)
850   *      Display help/usage messages.
851   */
852   static int
853 < csc_help(sp, cmd)
823 <        SCR *sp;
824 <        char *cmd;
853 > csc_help(SCR *sp, char *cmd)
854   {
855          CC const *ccp;
856  
# Line 848 | Line 877 | csc_help(sp, cmd)
877   *      The cscope kill command.
878   */
879   static int
880 < cscope_kill(sp, cmdp, cn)
852 <        SCR *sp;
853 <        EXCMD *cmdp;
854 <        char *cn;
880 > cscope_kill(SCR *sp, EXCMD *cmdp, CHAR_T *cn)
881   {
882 <        return (terminate(sp, NULL, atoi(cn)));
882 >        char *np;
883 >        size_t nlen;
884 >        int n = 1;
885 >
886 >        if (*cn) {
887 >                INT2CHAR(sp, cn, STRLEN(cn) + 1, np, nlen);
888 >                n = atoi(np);
889 >        }
890 >        return (terminate(sp, NULL, n));
891   }
892  
893   /*
# Line 861 | Line 895 | cscope_kill(sp, cmdp, cn)
895   *      Detach from a cscope process.
896   */
897   static int
898 < terminate(sp, csc, n)
865 <        SCR *sp;
866 <        CSC *csc;
867 <        int n;
898 > terminate(SCR *sp, CSC *csc, int n)
899   {
900          EX_PRIVATE *exp;
901 <        int i, pstat;
901 >        int i = 0, pstat;
902 >        CSC *cp, *pre_cp = NULL;
903  
904          exp = EXP(sp);
905  
906          /*
907 <         * We either get a csc structure or a number.  If not provided a
908 <         * csc structure, find the right one.
907 >         * We either get a csc structure or a number.  Locate and remove
908 >         * the candidate which matches the structure or the number.
909           */
910 <        if (csc == NULL) {
911 <                if (n < 1)
912 <                        goto badno;
913 <                for (i = 1, csc = exp->cscq.lh_first;
914 <                    csc != NULL; csc = csc->q.le_next, i++)
915 <                        if (i == n)
916 <                                break;
885 <                if (csc == NULL) {
886 < badno:                  msgq(sp, M_ERR, "312|%d: no such cscope session", n);
887 <                        return (1);
910 >        if (csc == NULL && n < 1)
911 >                goto badno;
912 >        SLIST_FOREACH(cp, exp->cscq, q) {
913 >                ++i;
914 >                if (csc == NULL ? i != n : cp != csc) {
915 >                        pre_cp = cp;
916 >                        continue;
917                  }
918 +                if (cp == SLIST_FIRST(exp->cscq))
919 +                        SLIST_REMOVE_HEAD(exp->cscq, q);
920 +                else
921 +                        SLIST_REMOVE_AFTER(pre_cp, q);
922 +                csc = cp;
923 +                break;
924          }
925 +        if (csc == NULL) {
926 + badno:          msgq(sp, M_ERR, "312|%d: no such cscope session", n);
927 +                return (1);
928 +        }
929  
930          /*
931           * XXX
932           * Theoretically, we have the only file descriptors to the process,
933           * so closing them should let it exit gracefully, deleting temporary
934 <         * files, etc.  The original vi cscope integration sent the cscope
935 <         * connection a SIGTERM signal, so I'm not sure if closing the file
897 <         * descriptors is sufficient.
934 >         * files, etc.  However, the earlier created cscope processes seems
935 >         * to refuse to quit unless we send a SIGTERM signal.
936           */
937          if (csc->from_fp != NULL)
938                  (void)fclose(csc->from_fp);
939          if (csc->to_fp != NULL)
940                  (void)fclose(csc->to_fp);
941 +        if (i > 1)
942 +                (void)kill(csc->pid, SIGTERM);
943          (void)waitpid(csc->pid, &pstat, 0);
944  
945          /* Discard cscope connection information. */
906        LIST_REMOVE(csc, q);
946          if (csc->pbuf != NULL)
947                  free(csc->pbuf);
948          if (csc->paths != NULL)
# Line 917 | Line 956 | badno:                 msgq(sp, M_ERR, "312|%d: no such cscope sessi
956   *      The cscope reset command.
957   */
958   static int
959 < cscope_reset(sp, cmdp, notusedp)
921 <        SCR *sp;
922 <        EXCMD *cmdp;
923 <        char *notusedp;
959 > cscope_reset(SCR *sp, EXCMD *cmdp, CHAR_T *notusedp)
960   {
961 +        return cscope_end(sp);
962 + }
963 +
964 + /*
965 + * cscope_end --
966 + *      End all cscope connections.
967 + *
968 + * PUBLIC: int cscope_end __P((SCR *));
969 + */
970 + int
971 + cscope_end(SCR *sp)
972 + {
973          EX_PRIVATE *exp;
974  
975 <        for (exp = EXP(sp); exp->cscq.lh_first != NULL;)
976 <                if (cscope_kill(sp, cmdp, "1"))
975 >        for (exp = EXP(sp); !SLIST_EMPTY(exp->cscq);)
976 >                if (terminate(sp, NULL, 1))
977                          return (1);
978          return (0);
979   }
# Line 937 | Line 985 | cscope_reset(sp, cmdp, notusedp)
985   * PUBLIC: int cscope_display __P((SCR *));
986   */
987   int
988 < cscope_display(sp)
941 <        SCR *sp;
988 > cscope_display(SCR *sp)
989   {
990          EX_PRIVATE *exp;
991          CSC *csc;
992 <        int i;
992 >        int i = 0;
993  
994          exp = EXP(sp);
995 <        if (exp->cscq.lh_first == NULL) {
995 >        if (SLIST_EMPTY(exp->cscq)) {
996                  ex_printf(sp, "No cscope connections.\n");
997                  return (0);
998          }
999 <        for (i = 1,
1000 <            csc = exp->cscq.lh_first; csc != NULL; ++i, csc = csc->q.le_next)
1001 <                ex_printf(sp,
955 <                    "%2d %s (process %lu)\n", i, csc->dname, (u_long)csc->pid);
999 >        SLIST_FOREACH(csc, exp->cscq, q)
1000 >                ex_printf(sp, "%2d %s (process %lu)\n",
1001 >                    ++i, csc->dname, (u_long)csc->pid);
1002          return (0);
1003   }
1004  
# Line 963 | Line 1009 | cscope_display(sp)
1009   * PUBLIC: int cscope_search __P((SCR *, TAGQ *, TAG *));
1010   */
1011   int
1012 < cscope_search(sp, tqp, tp)
967 <        SCR *sp;
968 <        TAGQ *tqp;
969 <        TAG *tp;
1012 > cscope_search(SCR *sp, TAGQ *tqp, TAG *tp)
1013   {
1014          MARK m;
1015  
# Line 1015 | Line 1058 | cscope_search(sp, tqp, tp)
1058   *      Return a pointer to the command structure.
1059   */
1060   static CC const *
1061 < lookup_ccmd(name)
1019 <        char *name;
1061 > lookup_ccmd(char *name)
1062   {
1063          CC const *ccp;
1064          size_t len;
# Line 1033 | Line 1075 | lookup_ccmd(name)
1075   *      Read a prompt from cscope.
1076   */
1077   static int
1078 < read_prompt(sp, csc)
1037 <        SCR *sp;
1038 <        CSC *csc;
1078 > read_prompt(SCR *sp, CSC *csc)
1079   {
1080          int ch;
1081  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines