1 /*- 2 * Copyright (c) 1994, 1996 3 * Rob Mayoff. All rights reserved. 4 * Copyright (c) 1996 5 * Keith Bostic. All rights reserved. 6 * 7 * See the LICENSE file for redistribution information. 8 */ 9 10 #include "config.h" 11 12 #include <sys/types.h> 13 #include <sys/queue.h> 14 #include <sys/stat.h> 15 #include <sys/wait.h> 16 17 #include <bitstring.h> 18 #include <ctype.h> 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <limits.h> 22 #include <signal.h> 23 #include <stddef.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <termios.h> 28 #include <unistd.h> 29 30 #include "../common/common.h" 31 #include "pathnames.h" 32 #include "tag.h" 33 34 #define CSCOPE_DBFILE "cscope.out" 35 #define CSCOPE_PATHS "cscope.tpath" 36 37 /* 38 * 0name find all uses of name 39 * 1name find definition of name 40 * 2name find all function calls made from name 41 * 3name find callers of name 42 * 4string find text string (cscope 12.9) 43 * 4name find assignments to name (cscope 13.3) 44 * 5pattern change pattern -- NOT USED 45 * 6pattern find pattern 46 * 7name find files with name as substring 47 * 8name find files #including name 48 */ 49 #define FINDHELP "\ 50 find c|d|e|f|g|i|s|t buffer|pattern\n\ 51 c: find callers of name\n\ 52 d: find all function calls made from name\n\ 53 e: find pattern\n\ 54 f: find files with name as substring\n\ 55 g: find definition of name\n\ 56 i: find files #including name\n\ 57 s: find all uses of name\n\ 58 t: find assignments to name" 59 60 static int cscope_add(SCR *, EXCMD *, CHAR_T *); 61 static int cscope_find(SCR *, EXCMD*, CHAR_T *); 62 static int cscope_help(SCR *, EXCMD *, CHAR_T *); 63 static int cscope_kill(SCR *, EXCMD *, CHAR_T *); 64 static int cscope_reset(SCR *, EXCMD *, CHAR_T *); 65 66 typedef struct _cc { 67 char *name; 68 int (*function)(SCR *, EXCMD *, CHAR_T *); 69 char *help_msg; 70 char *usage_msg; 71 } CC; 72 73 static CC const cscope_cmds[] = { 74 { "add", cscope_add, 75 "Add a new cscope database", "add file | directory" }, 76 { "find", cscope_find, 77 "Query the databases for a pattern", FINDHELP }, 78 { "help", cscope_help, 79 "Show help for cscope commands", "help [command]" }, 80 { "kill", cscope_kill, 81 "Kill a cscope connection", "kill number" }, 82 { "reset", cscope_reset, 83 "Discard all current cscope connections", "reset" }, 84 { NULL } 85 }; 86 87 static TAGQ *create_cs_cmd(SCR *, char *, size_t *); 88 static int csc_help(SCR *, char *); 89 static void csc_file(SCR *, 90 CSC *, char *, char **, size_t *, int *); 91 static int get_paths(SCR *, CSC *); 92 static CC const *lookup_ccmd(char *); 93 static int parse(SCR *, CSC *, TAGQ *, int *); 94 static int read_prompt(SCR *, CSC *); 95 static int run_cscope(SCR *, CSC *, char *); 96 static int start_cscopes(SCR *, EXCMD *); 97 static int terminate(SCR *, CSC *, int); 98 99 /* 100 * ex_cscope -- 101 * Perform an ex cscope. 102 * 103 * PUBLIC: int ex_cscope(SCR *, EXCMD *); 104 */ 105 int 106 ex_cscope(SCR *sp, EXCMD *cmdp) 107 { 108 CC const *ccp; 109 EX_PRIVATE *exp; 110 int i; 111 CHAR_T *cmd; 112 CHAR_T *p; 113 char *np; 114 size_t nlen; 115 116 /* Initialize the default cscope directories. */ 117 exp = EXP(sp); 118 if (!F_ISSET(exp, EXP_CSCINIT) && start_cscopes(sp, cmdp)) 119 return (1); 120 F_SET(exp, EXP_CSCINIT); 121 122 /* Skip leading whitespace. */ 123 for (p = cmdp->argv[0]->bp, i = cmdp->argv[0]->len; i > 0; --i, ++p) 124 if (!isspace(*p)) 125 break; 126 if (i == 0) 127 goto usage; 128 129 /* Skip the command to any arguments. */ 130 for (cmd = p; i > 0; --i, ++p) 131 if (isspace(*p)) 132 break; 133 if (*p != '\0') { 134 *p++ = '\0'; 135 for (; *p && isspace(*p); ++p); 136 } 137 138 INT2CHAR(sp, cmd, STRLEN(cmd) + 1, np, nlen); 139 if ((ccp = lookup_ccmd(np)) == NULL) { 140 usage: msgq(sp, M_ERR, "309|Use \"cscope help\" for help"); 141 return (1); 142 } 143 144 /* Call the underlying function. */ 145 return (ccp->function(sp, cmdp, p)); 146 } 147 148 /* 149 * start_cscopes -- 150 * Initialize the cscope package. 151 */ 152 static int 153 start_cscopes(SCR *sp, EXCMD *cmdp) 154 { 155 size_t blen, len; 156 char *bp, *cscopes, *p, *t; 157 CHAR_T *wp; 158 size_t wlen; 159 160 /* 161 * EXTENSION #1: 162 * 163 * If the CSCOPE_DIRS environment variable is set, we treat it as a 164 * list of cscope directories that we're using, similar to the tags 165 * edit option. 166 * 167 * XXX 168 * This should probably be an edit option, although that implies that 169 * we start/stop cscope processes periodically, instead of once when 170 * the editor starts. 171 */ 172 if ((cscopes = getenv("CSCOPE_DIRS")) == NULL) 173 return (0); 174 len = strlen(cscopes); 175 GET_SPACE_RETC(sp, bp, blen, len); 176 memcpy(bp, cscopes, len + 1); 177 178 for (cscopes = t = bp; (p = strsep(&t, "\t :")) != NULL;) 179 if (*p != '\0') { 180 CHAR2INT(sp, p, strlen(p) + 1, wp, wlen); 181 (void)cscope_add(sp, cmdp, wp); 182 } 183 184 FREE_SPACE(sp, bp, blen); 185 return (0); 186 } 187 188 /* 189 * cscope_add -- 190 * The cscope add command. 191 */ 192 static int 193 cscope_add(SCR *sp, EXCMD *cmdp, CHAR_T *dname) 194 { 195 struct stat sb; 196 EX_PRIVATE *exp; 197 CSC *csc; 198 size_t len; 199 int cur_argc; 200 char *dbname, *path; 201 char *np = NULL; 202 size_t nlen; 203 204 exp = EXP(sp); 205 206 /* 207 * 0 additional args: usage. 208 * 1 additional args: matched a file. 209 * >1 additional args: object, too many args. 210 */ 211 cur_argc = cmdp->argc; 212 if (argv_exp2(sp, cmdp, dname, STRLEN(dname))) { 213 return (1); 214 } 215 if (cmdp->argc == cur_argc) { 216 (void)csc_help(sp, "add"); 217 return (1); 218 } 219 if (cmdp->argc == cur_argc + 1) 220 dname = cmdp->argv[cur_argc]->bp; 221 else { 222 ex_emsg(sp, np, EXM_FILECOUNT); 223 return (1); 224 } 225 226 INT2CHAR(sp, dname, STRLEN(dname)+1, np, nlen); 227 228 /* 229 * The user can specify a specific file (so they can have multiple 230 * Cscope databases in a single directory) or a directory. If the 231 * file doesn't exist, we're done. If it's a directory, append the 232 * standard database file name and try again. Store the directory 233 * name regardless so that we can use it as a base for searches. 234 */ 235 if (stat(np, &sb)) { 236 msgq(sp, M_SYSERR, "%s", np); 237 return (1); 238 } 239 if (S_ISDIR(sb.st_mode)) { 240 if ((path = join(np, CSCOPE_DBFILE)) == NULL) { 241 msgq(sp, M_SYSERR, NULL); 242 return (1); 243 } 244 if (stat(path, &sb)) { 245 msgq(sp, M_SYSERR, "%s", path); 246 free(path); 247 return (1); 248 } 249 free(path); 250 dbname = CSCOPE_DBFILE; 251 } else if ((dbname = strrchr(np, '/')) != NULL) 252 *dbname++ = '\0'; 253 else { 254 dbname = np; 255 np = "."; 256 } 257 258 /* Allocate a cscope connection structure and initialize its fields. */ 259 len = strlen(np); 260 CALLOC_RET(sp, csc, 1, sizeof(CSC) + len); 261 csc->dname = csc->buf; 262 csc->dlen = len; 263 memcpy(csc->dname, np, len); 264 #if defined HAVE_STRUCT_STAT_ST_MTIMESPEC 265 csc->mtim = sb.st_mtimespec; 266 #elif defined HAVE_STRUCT_STAT_ST_MTIM 267 csc->mtim = sb.st_mtim; 268 #else 269 csc->mtim.tv_sec = sb.st_mtime; 270 csc->mtim.tv_nsec = 0; 271 #endif 272 273 /* Get the search paths for the cscope. */ 274 if (get_paths(sp, csc)) 275 goto err; 276 277 /* Start the cscope process. */ 278 if (run_cscope(sp, csc, dbname)) 279 goto err; 280 281 /* 282 * Add the cscope connection to the screen's list. From now on, 283 * on error, we have to call terminate, which expects the csc to 284 * be on the chain. 285 */ 286 SLIST_INSERT_HEAD(exp->cscq, csc, q); 287 288 /* Read the initial prompt from the cscope to make sure it's okay. */ 289 return read_prompt(sp, csc); 290 291 err: free(csc); 292 return (1); 293 } 294 295 /* 296 * get_paths -- 297 * Get the directories to search for the files associated with this 298 * cscope database. 299 */ 300 static int 301 get_paths(SCR *sp, CSC *csc) 302 { 303 struct stat sb; 304 int fd, nentries; 305 size_t len; 306 char *p, **pathp, *buf; 307 308 /* 309 * EXTENSION #2: 310 * 311 * If there's a cscope directory with a file named CSCOPE_PATHS, it 312 * contains a colon-separated list of paths in which to search for 313 * files returned by cscope. 314 * 315 * XXX 316 * These paths are absolute paths, and not relative to the cscope 317 * directory. To fix this, rewrite the each path using the cscope 318 * directory as a prefix. 319 */ 320 if ((buf = join(csc->dname, CSCOPE_PATHS)) == NULL) { 321 msgq(sp, M_SYSERR, NULL); 322 return (1); 323 } 324 if (stat(buf, &sb) == 0) { 325 /* Read in the CSCOPE_PATHS file. */ 326 len = sb.st_size; 327 MALLOC_RET(sp, csc->pbuf, len + 1); 328 if ((fd = open(buf, O_RDONLY, 0)) < 0 || 329 read(fd, csc->pbuf, len) != len) { 330 msgq_str(sp, M_SYSERR, buf, "%s"); 331 if (fd >= 0) 332 (void)close(fd); 333 free(buf); 334 return (1); 335 } 336 (void)close(fd); 337 free(buf); 338 csc->pbuf[len] = '\0'; 339 340 /* Count up the entries. */ 341 for (nentries = 0, p = csc->pbuf; *p != '\0'; ++p) 342 if (p[0] == ':' && p[1] != '\0') 343 ++nentries; 344 345 /* Build an array of pointers to the paths. */ 346 CALLOC_GOTO(sp, csc->paths, nentries + 1, sizeof(char **)); 347 for (pathp = csc->paths, p = strtok(csc->pbuf, ":"); 348 p != NULL; p = strtok(NULL, ":")) 349 *pathp++ = p; 350 return (0); 351 } 352 free(buf); 353 354 /* 355 * If the CSCOPE_PATHS file doesn't exist, we look for files 356 * relative to the cscope directory. 357 */ 358 if ((csc->pbuf = strdup(csc->dname)) == NULL) { 359 msgq(sp, M_SYSERR, NULL); 360 return (1); 361 } 362 CALLOC_GOTO(sp, csc->paths, 2, sizeof(char *)); 363 csc->paths[0] = csc->pbuf; 364 return (0); 365 366 alloc_err: 367 free(csc->pbuf); 368 csc->pbuf = NULL; 369 return (1); 370 } 371 372 /* 373 * run_cscope -- 374 * Fork off the cscope process. 375 */ 376 static int 377 run_cscope(SCR *sp, CSC *csc, char *dbname) 378 { 379 int to_cs[2], from_cs[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[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) 396 (void)close(to_cs[0]); 397 if (to_cs[1] != -1) 398 (void)close(to_cs[1]); 399 if (from_cs[0] != -1) 400 (void)close(from_cs[0]); 401 if (from_cs[1] != -1) 402 (void)close(from_cs[1]); 403 return (1); 404 case 0: /* child: run cscope. */ 405 (void)dup2(to_cs[0], STDIN_FILENO); 406 (void)dup2(from_cs[1], STDOUT_FILENO); 407 (void)dup2(from_cs[1], STDERR_FILENO); 408 409 /* Close unused file descriptors. */ 410 (void)close(to_cs[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 if ((dn = quote(csc->dname)) == NULL) 416 goto nomem; 417 if ((dbn = quote(dbname)) == NULL) { 418 free(dn); 419 goto nomem; 420 } 421 if (asprintf(&cmd, CSCOPE_CMD_FMT, dn, dbn) == -1) 422 cmd = NULL; 423 free(dbn); 424 free(dn); 425 if (cmd == NULL) { 426 nomem: msgq(sp, M_SYSERR, NULL); 427 _exit (1); 428 } 429 (void)execl(_PATH_BSHELL, "sh", "-c", cmd, (char *)NULL); 430 msgq_str(sp, M_SYSERR, cmd, "execl: %s"); 431 free(cmd); 432 _exit (127); 433 /* NOTREACHED */ 434 default: /* parent. */ 435 /* Close unused file descriptors. */ 436 (void)close(to_cs[0]); 437 (void)close(from_cs[1]); 438 439 /* 440 * Save the file descriptors for later duplication, and 441 * reopen as streams. 442 */ 443 csc->to_fd = to_cs[1]; 444 csc->to_fp = fdopen(to_cs[1], "w"); 445 csc->from_fd = from_cs[0]; 446 csc->from_fp = fdopen(from_cs[0], "r"); 447 break; 448 } 449 return (0); 450 } 451 452 /* 453 * cscope_find -- 454 * The cscope find command. 455 */ 456 static int 457 cscope_find(SCR *sp, EXCMD *cmdp, CHAR_T *pattern) 458 { 459 CSC *csc, *csc_next; 460 EX_PRIVATE *exp; 461 FREF *frp; 462 TAGQ *rtqp, *tqp; 463 TAG *rtp; 464 recno_t lno; 465 size_t cno, search; 466 int force, istmp, matches; 467 char *np = NULL; 468 size_t nlen; 469 470 exp = EXP(sp); 471 472 /* Check for connections. */ 473 if (SLIST_EMPTY(exp->cscq)) { 474 msgq(sp, M_ERR, "310|No cscope connections running"); 475 return (1); 476 } 477 478 /* 479 * Allocate all necessary memory before doing anything hard. If the 480 * tags stack is empty, we'll need the `local context' TAGQ structure 481 * later. 482 */ 483 rtp = NULL; 484 rtqp = NULL; 485 if (TAILQ_EMPTY(exp->tq)) { 486 /* Initialize the `local context' tag queue structure. */ 487 CALLOC_GOTO(sp, rtqp, 1, sizeof(TAGQ)); 488 TAILQ_INIT(rtqp->tagq); 489 490 /* Initialize and link in its tag structure. */ 491 CALLOC_GOTO(sp, rtp, 1, sizeof(TAG)); 492 TAILQ_INSERT_HEAD(rtqp->tagq, rtp, q); 493 rtqp->current = rtp; 494 } 495 496 /* Create the cscope command. */ 497 INT2CHAR(sp, pattern, STRLEN(pattern) + 1, np, nlen); 498 np = strdup(np); 499 if ((tqp = create_cs_cmd(sp, np, &search)) == NULL) 500 goto err; 501 free(np); 502 np = NULL; 503 504 /* 505 * Stick the current context in a convenient place, we'll lose it 506 * when we switch files. 507 */ 508 frp = sp->frp; 509 lno = sp->lno; 510 cno = sp->cno; 511 istmp = F_ISSET(sp->frp, FR_TMPFILE) && !F_ISSET(cmdp, E_NEWSCREEN); 512 513 /* Search all open connections for a match. */ 514 matches = 0; 515 /* Copy next connect here in case csc is killed. */ 516 SLIST_FOREACH_SAFE(csc, exp->cscq, q, csc_next) { 517 /* 518 * Send the command to the cscope program. (We skip the 519 * first two bytes of the command, because we stored the 520 * search cscope command character and a leading space 521 * there.) 522 */ 523 (void)fprintf(csc->to_fp, "%lu%s\n", search, tqp->tag + 2); 524 (void)fflush(csc->to_fp); 525 526 /* Read the output. */ 527 if (parse(sp, csc, tqp, &matches)) 528 goto nomatch; 529 } 530 531 if (matches == 0) { 532 msgq(sp, M_INFO, "278|No matches for query"); 533 nomatch: free(rtp); 534 free(rtqp); 535 tagq_free(sp, tqp); 536 return (1); 537 } 538 539 /* Try to switch to the first tag. */ 540 force = FL_ISSET(cmdp->iflags, E_C_FORCE); 541 if (F_ISSET(cmdp, E_NEWSCREEN)) { 542 if (ex_tag_Nswitch(sp, tqp->current, force)) 543 goto err; 544 545 /* Everything else gets done in the new screen. */ 546 sp = sp->nextdisp; 547 exp = EXP(sp); 548 } else 549 if (ex_tag_nswitch(sp, tqp->current, force)) 550 goto err; 551 552 /* 553 * If this is the first tag, put a `current location' queue entry 554 * in place, so we can pop all the way back to the current mark. 555 * Note, it doesn't point to much of anything, it's a placeholder. 556 */ 557 if (TAILQ_EMPTY(exp->tq)) { 558 TAILQ_INSERT_HEAD(exp->tq, rtqp, q); 559 } else 560 rtqp = TAILQ_FIRST(exp->tq); 561 562 /* Link the current TAGQ structure into place. */ 563 TAILQ_INSERT_HEAD(exp->tq, tqp, q); 564 565 (void)cscope_search(sp, tqp, tqp->current); 566 567 /* 568 * Move the current context from the temporary save area into the 569 * right structure. 570 * 571 * If we were in a temporary file, we don't have a context to which 572 * we can return, so just make it be the same as what we're moving 573 * to. It will be a little odd that ^T doesn't change anything, but 574 * I don't think it's a big deal. 575 */ 576 if (istmp) { 577 rtqp->current->frp = sp->frp; 578 rtqp->current->lno = sp->lno; 579 rtqp->current->cno = sp->cno; 580 } else { 581 rtqp->current->frp = frp; 582 rtqp->current->lno = lno; 583 rtqp->current->cno = cno; 584 } 585 586 return (0); 587 588 err: 589 alloc_err: 590 free(rtqp); 591 free(rtp); 592 free(np); 593 return (1); 594 } 595 596 /* 597 * create_cs_cmd -- 598 * Build a cscope command, creating and initializing the base TAGQ. 599 */ 600 static TAGQ * 601 create_cs_cmd(SCR *sp, char *pattern, size_t *searchp) 602 { 603 CB *cbp; 604 TAGQ *tqp; 605 size_t tlen; 606 char *p; 607 608 /* 609 * Cscope supports a "change pattern" command which we never use, 610 * cscope command 5. Set CSCOPE_QUERIES[5] to " " since the user 611 * can't pass " " as the first character of pattern. That way the 612 * user can't ask for pattern 5 so we don't need any special-case 613 * code. 614 */ 615 #define CSCOPE_QUERIES "sgdct efi" 616 617 if (pattern == NULL) 618 goto usage; 619 620 /* Skip leading blanks, check for command character. */ 621 for (; cmdskip(pattern[0]); ++pattern); 622 if (pattern[0] == '\0' || !cmdskip(pattern[1])) 623 goto usage; 624 for (*searchp = 0, p = CSCOPE_QUERIES; 625 *p != '\0' && *p != pattern[0]; ++*searchp, ++p); 626 if (*p == '\0') { 627 msgq(sp, M_ERR, 628 "311|%s: unknown search type: use one of %s", 629 KEY_NAME(sp, pattern[0]), CSCOPE_QUERIES); 630 return (NULL); 631 } 632 633 /* Skip <blank> characters to the pattern. */ 634 for (p = pattern + 1; *p != '\0' && cmdskip(*p); ++p); 635 if (*p == '\0') { 636 usage: (void)csc_help(sp, "find"); 637 return (NULL); 638 } 639 640 /* The user can specify the contents of a buffer as the pattern. */ 641 cbp = NULL; 642 if (p[0] == '"' && p[1] != '\0' && p[2] == '\0') 643 CBNAME(sp, cbp, p[1]); 644 if (cbp != NULL) { 645 INT2CHAR(sp, TAILQ_FIRST(cbp->textq)->lb, 646 TAILQ_FIRST(cbp->textq)->len, p, tlen); 647 } else 648 tlen = strlen(p); 649 650 /* Allocate and initialize the TAGQ structure. */ 651 CALLOC(sp, tqp, 1, sizeof(TAGQ) + tlen + 3); 652 if (tqp == NULL) 653 return (NULL); 654 TAILQ_INIT(tqp->tagq); 655 tqp->tag = tqp->buf; 656 tqp->tag[0] = pattern[0]; 657 tqp->tag[1] = ' '; 658 tqp->tlen = tlen + 2; 659 memcpy(tqp->tag + 2, p, tlen); 660 tqp->tag[tlen + 2] = '\0'; 661 F_SET(tqp, TAG_CSCOPE); 662 663 return (tqp); 664 } 665 666 /* 667 * parse -- 668 * Parse the cscope output. 669 */ 670 static int 671 parse(SCR *sp, CSC *csc, TAGQ *tqp, int *matchesp) 672 { 673 TAG *tp; 674 recno_t slno = 0; 675 size_t dlen, nlen = 0, slen = 0; 676 int ch, i, isolder = 0, nlines; 677 char *dname = NULL, *name = NULL, *search, *p, *t, dummy[2], buf[2048]; 678 CHAR_T *wp; 679 size_t wlen; 680 681 for (;;) { 682 if (!fgets(buf, sizeof(buf), csc->from_fp)) 683 goto io_err; 684 685 /* 686 * If the database is out of date, or there's some other 687 * problem, cscope will output error messages before the 688 * number-of-lines output. Display/discard any output 689 * that doesn't match what we want. 690 */ 691 #define CSCOPE_NLINES_FMT "cscope: %d lines%1[\n]" 692 if (sscanf(buf, CSCOPE_NLINES_FMT, &nlines, dummy) == 2) 693 break; 694 if ((p = strchr(buf, '\n')) != NULL) 695 *p = '\0'; 696 msgq(sp, M_ERR, "%s: \"%s\"", csc->dname, buf); 697 } 698 699 while (nlines--) { 700 if (fgets(buf, sizeof(buf), csc->from_fp) == NULL) 701 goto io_err; 702 703 /* If the line's too long for the buffer, discard it. */ 704 if ((p = strchr(buf, '\n')) == NULL) { 705 while ((ch = getc(csc->from_fp)) != EOF && ch != '\n'); 706 continue; 707 } 708 *p = '\0'; 709 710 /* 711 * The cscope output is in the following format: 712 * 713 * <filename> <context> <line number> <pattern> 714 * 715 * Figure out how long everything is so we can allocate in one 716 * swell foop, but discard anything that looks wrong. 717 */ 718 for (p = buf, i = 0; 719 i < 3 && (t = strsep(&p, "\t ")) != NULL; ++i) 720 switch (i) { 721 case 0: /* Filename. */ 722 name = t; 723 nlen = strlen(name); 724 break; 725 case 1: /* Context. */ 726 break; 727 case 2: /* Line number. */ 728 slno = (recno_t)atol(t); 729 break; 730 } 731 if (i != 3 || p == NULL || t == NULL) 732 continue; 733 734 /* The rest of the string is the search pattern. */ 735 search = p; 736 slen = strlen(p); 737 738 /* Resolve the file name. */ 739 csc_file(sp, csc, name, &dname, &dlen, &isolder); 740 741 /* 742 * If the file is older than the cscope database, that is, 743 * the database was built since the file was last modified, 744 * or there wasn't a search string, use the line number. 745 */ 746 if (isolder || strcmp(search, "<unknown>") == 0) { 747 search = NULL; 748 slen = 0; 749 } 750 751 /* 752 * Allocate and initialize a tag structure plus the variable 753 * length cscope information that follows it. 754 */ 755 CALLOC_RET(sp, tp, 1, 756 sizeof(TAG) + dlen + 2 + nlen + 1 + (slen + 1) * sizeof(CHAR_T)); 757 tp->fname = (char *)tp->buf; 758 if (dlen == 1 && *dname == '.') 759 --dlen; 760 else if (dlen != 0) { 761 memcpy(tp->fname, dname, dlen); 762 tp->fname[dlen] = '/'; 763 ++dlen; 764 } 765 memcpy(tp->fname + dlen, name, nlen + 1); 766 tp->fnlen = dlen + nlen; 767 tp->slno = slno; 768 if (slen != 0) { 769 tp->search = (CHAR_T*)(tp->fname + tp->fnlen + 1); 770 CHAR2INT(sp, search, slen + 1, wp, wlen); 771 MEMCPY(tp->search, wp, (tp->slen = slen) + 1); 772 } 773 TAILQ_INSERT_TAIL(tqp->tagq, tp, q); 774 775 /* Try to preset the tag within the current file. */ 776 if (sp->frp != NULL && sp->frp->name != NULL && 777 tqp->current == NULL && !strcmp(tp->fname, sp->frp->name)) 778 tqp->current = tp; 779 780 ++*matchesp; 781 } 782 783 if (tqp->current == NULL) 784 tqp->current = TAILQ_FIRST(tqp->tagq); 785 786 return read_prompt(sp, csc); 787 788 io_err: if (feof(csc->from_fp)) 789 errno = EIO; 790 msgq_str(sp, M_SYSERR, "%s", csc->dname); 791 terminate(sp, csc, 0); 792 return (1); 793 } 794 795 /* 796 * csc_file -- 797 * Search for the right path to this file. 798 */ 799 static void 800 csc_file(SCR *sp, CSC *csc, char *name, char **dirp, size_t *dlenp, int *isolderp) 801 { 802 struct stat sb; 803 char **pp, *buf; 804 805 /* 806 * Check for the file in all of the listed paths. If we don't 807 * find it, we simply return it unchanged. We have to do this 808 * now, even though it's expensive, because if the user changes 809 * directories, we can't change our minds as to where the file 810 * lives. 811 */ 812 for (pp = csc->paths; *pp != NULL; ++pp) { 813 if ((buf = join(*pp, name)) == NULL) { 814 msgq(sp, M_SYSERR, NULL); 815 *dlenp = 0; 816 return; 817 } 818 if (stat(buf, &sb) == 0) { 819 free(buf); 820 *dirp = *pp; 821 *dlenp = strlen(*pp); 822 #if defined HAVE_STRUCT_STAT_ST_MTIMESPEC 823 *isolderp = timespeccmp( 824 &sb.st_mtimespec, &csc->mtim, <); 825 #elif defined HAVE_STRUCT_STAT_ST_MTIM 826 *isolderp = timespeccmp( 827 &sb.st_mtim, &csc->mtim, <); 828 #else 829 *isolderp = sb.st_mtime < csc->mtim.tv_sec; 830 #endif 831 return; 832 } 833 free(buf); 834 } 835 *dlenp = 0; 836 } 837 838 /* 839 * cscope_help -- 840 * The cscope help command. 841 */ 842 static int 843 cscope_help(SCR *sp, EXCMD *cmdp, CHAR_T *subcmd) 844 { 845 char *np; 846 size_t nlen; 847 848 INT2CHAR(sp, subcmd, STRLEN(subcmd) + 1, np, nlen); 849 return (csc_help(sp, np)); 850 } 851 852 /* 853 * csc_help -- 854 * Display help/usage messages. 855 */ 856 static int 857 csc_help(SCR *sp, char *cmd) 858 { 859 CC const *ccp; 860 861 if (cmd != NULL && *cmd != '\0') { 862 if ((ccp = lookup_ccmd(cmd)) == NULL) { 863 ex_printf(sp, 864 "%s doesn't match any cscope command\n", cmd); 865 return (1); 866 } else { 867 ex_printf(sp, 868 "Command: %s (%s)\n", ccp->name, ccp->help_msg); 869 ex_printf(sp, " Usage: %s\n", ccp->usage_msg); 870 return (0); 871 } 872 } 873 874 ex_printf(sp, "cscope commands:\n"); 875 for (ccp = cscope_cmds; ccp->name != NULL; ++ccp) 876 ex_printf(sp, " %*s: %s\n", 5, ccp->name, ccp->help_msg); 877 return (0); 878 } 879 880 /* 881 * cscope_kill -- 882 * The cscope kill command. 883 */ 884 static int 885 cscope_kill(SCR *sp, EXCMD *cmdp, CHAR_T *cn) 886 { 887 char *np; 888 size_t nlen; 889 int n = 1; 890 891 if (*cn) { 892 INT2CHAR(sp, cn, STRLEN(cn) + 1, np, nlen); 893 n = atoi(np); 894 } 895 return (terminate(sp, NULL, n)); 896 } 897 898 /* 899 * terminate -- 900 * Detach from a cscope process. 901 */ 902 static int 903 terminate(SCR *sp, CSC *csc, int n) 904 { 905 EX_PRIVATE *exp; 906 int i = 0, pstat; 907 CSC *cp, *pre_cp = NULL; 908 909 exp = EXP(sp); 910 911 /* 912 * We either get a csc structure or a number. Locate and remove 913 * the candidate which matches the structure or the number. 914 */ 915 if (csc == NULL && n < 1) 916 goto badno; 917 SLIST_FOREACH(cp, exp->cscq, q) { 918 ++i; 919 if (csc == NULL ? i != n : cp != csc) { 920 pre_cp = cp; 921 continue; 922 } 923 if (cp == SLIST_FIRST(exp->cscq)) 924 SLIST_REMOVE_HEAD(exp->cscq, q); 925 else 926 SLIST_REMOVE_AFTER(pre_cp, q); 927 csc = cp; 928 break; 929 } 930 if (csc == NULL) { 931 badno: msgq(sp, M_ERR, "312|%d: no such cscope session", n); 932 return (1); 933 } 934 935 /* 936 * XXX 937 * Theoretically, we have the only file descriptors to the process, 938 * so closing them should let it exit gracefully, deleting temporary 939 * files, etc. However, the earlier created cscope processes seems 940 * to refuse to quit unless we send a SIGTERM signal. 941 */ 942 if (csc->from_fp != NULL) 943 (void)fclose(csc->from_fp); 944 if (csc->to_fp != NULL) 945 (void)fclose(csc->to_fp); 946 if (i > 1) 947 (void)kill(csc->pid, SIGTERM); 948 (void)waitpid(csc->pid, &pstat, 0); 949 950 /* Discard cscope connection information. */ 951 free(csc->pbuf); 952 free(csc->paths); 953 free(csc); 954 return (0); 955 } 956 957 /* 958 * cscope_reset -- 959 * The cscope reset command. 960 */ 961 static int 962 cscope_reset(SCR *sp, EXCMD *cmdp, CHAR_T *notusedp) 963 { 964 return cscope_end(sp); 965 } 966 967 /* 968 * cscope_end -- 969 * End all cscope connections. 970 * 971 * PUBLIC: int cscope_end(SCR *); 972 */ 973 int 974 cscope_end(SCR *sp) 975 { 976 EX_PRIVATE *exp; 977 978 for (exp = EXP(sp); !SLIST_EMPTY(exp->cscq);) 979 if (terminate(sp, NULL, 1)) 980 return (1); 981 return (0); 982 } 983 984 /* 985 * cscope_display -- 986 * Display current connections. 987 * 988 * PUBLIC: int cscope_display(SCR *); 989 */ 990 int 991 cscope_display(SCR *sp) 992 { 993 EX_PRIVATE *exp; 994 CSC *csc; 995 int i = 0; 996 997 exp = EXP(sp); 998 if (SLIST_EMPTY(exp->cscq)) { 999 ex_printf(sp, "No cscope connections.\n"); 1000 return (0); 1001 } 1002 SLIST_FOREACH(csc, exp->cscq, q) 1003 ex_printf(sp, "%2d %s (process %lu)\n", 1004 ++i, csc->dname, (u_long)csc->pid); 1005 return (0); 1006 } 1007 1008 /* 1009 * cscope_search -- 1010 * Search a file for a cscope entry. 1011 * 1012 * PUBLIC: int cscope_search(SCR *, TAGQ *, TAG *); 1013 */ 1014 int 1015 cscope_search(SCR *sp, TAGQ *tqp, TAG *tp) 1016 { 1017 MARK m; 1018 1019 /* If we don't have a search pattern, use the line number. */ 1020 if (tp->search == NULL) { 1021 if (!db_exist(sp, tp->slno)) { 1022 tag_msg(sp, TAG_BADLNO, tqp->tag); 1023 return (1); 1024 } 1025 m.lno = tp->slno; 1026 } else { 1027 /* 1028 * Search for the tag; cheap fallback for C functions 1029 * if the name is the same but the arguments have changed. 1030 */ 1031 m.lno = 1; 1032 m.cno = 0; 1033 if (f_search(sp, &m, &m, 1034 tp->search, tp->slen, NULL, SEARCH_CSCOPE | SEARCH_FILE)) { 1035 tag_msg(sp, TAG_SEARCH, tqp->tag); 1036 return (1); 1037 } 1038 1039 /* 1040 * !!! 1041 * Historically, tags set the search direction if it wasn't 1042 * already set. 1043 */ 1044 if (sp->searchdir == NOTSET) 1045 sp->searchdir = FORWARD; 1046 } 1047 1048 /* 1049 * !!! 1050 * Tags move to the first non-blank, NOT the search pattern start. 1051 */ 1052 sp->lno = m.lno; 1053 sp->cno = 0; 1054 (void)nonblank(sp, sp->lno, &sp->cno); 1055 return (0); 1056 } 1057 1058 1059 /* 1060 * lookup_ccmd -- 1061 * Return a pointer to the command structure. 1062 */ 1063 static CC const * 1064 lookup_ccmd(char *name) 1065 { 1066 CC const *ccp; 1067 size_t len; 1068 1069 len = strlen(name); 1070 for (ccp = cscope_cmds; ccp->name != NULL; ++ccp) 1071 if (strncmp(name, ccp->name, len) == 0) 1072 return (ccp); 1073 return (NULL); 1074 } 1075 1076 /* 1077 * read_prompt -- 1078 * Read a prompt from cscope. 1079 */ 1080 static int 1081 read_prompt(SCR *sp, CSC *csc) 1082 { 1083 int ch; 1084 1085 #define CSCOPE_PROMPT ">> " 1086 for (;;) { 1087 while ((ch = 1088 getc(csc->from_fp)) != EOF && ch != CSCOPE_PROMPT[0]); 1089 if (ch == EOF) { 1090 terminate(sp, csc, 0); 1091 return (1); 1092 } 1093 if (getc(csc->from_fp) != CSCOPE_PROMPT[1]) 1094 continue; 1095 if (getc(csc->from_fp) != CSCOPE_PROMPT[2]) 1096 continue; 1097 break; 1098 } 1099 return (0); 1100 } 1101