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 csc->mtim = sb.st_mtimespec; 265 266 /* Get the search paths for the cscope. */ 267 if (get_paths(sp, csc)) 268 goto err; 269 270 /* Start the cscope process. */ 271 if (run_cscope(sp, csc, dbname)) 272 goto err; 273 274 /* 275 * Add the cscope connection to the screen's list. From now on, 276 * on error, we have to call terminate, which expects the csc to 277 * be on the chain. 278 */ 279 SLIST_INSERT_HEAD(exp->cscq, csc, q); 280 281 /* Read the initial prompt from the cscope to make sure it's okay. */ 282 return read_prompt(sp, csc); 283 284 err: free(csc); 285 return (1); 286 } 287 288 /* 289 * get_paths -- 290 * Get the directories to search for the files associated with this 291 * cscope database. 292 */ 293 static int 294 get_paths(SCR *sp, CSC *csc) 295 { 296 struct stat sb; 297 int fd, nentries; 298 size_t len; 299 char *p, **pathp, *buf; 300 301 /* 302 * EXTENSION #2: 303 * 304 * If there's a cscope directory with a file named CSCOPE_PATHS, it 305 * contains a colon-separated list of paths in which to search for 306 * files returned by cscope. 307 * 308 * XXX 309 * These paths are absolute paths, and not relative to the cscope 310 * directory. To fix this, rewrite the each path using the cscope 311 * directory as a prefix. 312 */ 313 if ((buf = join(csc->dname, CSCOPE_PATHS)) == NULL) { 314 msgq(sp, M_SYSERR, NULL); 315 return (1); 316 } 317 if (stat(buf, &sb) == 0) { 318 /* Read in the CSCOPE_PATHS file. */ 319 len = sb.st_size; 320 MALLOC_RET(sp, csc->pbuf, len + 1); 321 if ((fd = open(buf, O_RDONLY, 0)) < 0 || 322 read(fd, csc->pbuf, len) != len) { 323 msgq_str(sp, M_SYSERR, buf, "%s"); 324 if (fd >= 0) 325 (void)close(fd); 326 free(buf); 327 return (1); 328 } 329 (void)close(fd); 330 free(buf); 331 csc->pbuf[len] = '\0'; 332 333 /* Count up the entries. */ 334 for (nentries = 0, p = csc->pbuf; *p != '\0'; ++p) 335 if (p[0] == ':' && p[1] != '\0') 336 ++nentries; 337 338 /* Build an array of pointers to the paths. */ 339 CALLOC_GOTO(sp, csc->paths, nentries + 1, sizeof(char **)); 340 for (pathp = csc->paths, p = strtok(csc->pbuf, ":"); 341 p != NULL; p = strtok(NULL, ":")) 342 *pathp++ = p; 343 return (0); 344 } 345 free(buf); 346 347 /* 348 * If the CSCOPE_PATHS file doesn't exist, we look for files 349 * relative to the cscope directory. 350 */ 351 if ((csc->pbuf = strdup(csc->dname)) == NULL) { 352 msgq(sp, M_SYSERR, NULL); 353 return (1); 354 } 355 CALLOC_GOTO(sp, csc->paths, 2, sizeof(char *)); 356 csc->paths[0] = csc->pbuf; 357 return (0); 358 359 alloc_err: 360 free(csc->pbuf); 361 csc->pbuf = NULL; 362 return (1); 363 } 364 365 /* 366 * run_cscope -- 367 * Fork off the cscope process. 368 */ 369 static int 370 run_cscope(SCR *sp, CSC *csc, char *dbname) 371 { 372 int to_cs[2], from_cs[2]; 373 char *cmd; 374 375 /* 376 * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from 377 * from_cs[0] and writes to to_cs[1]. 378 */ 379 to_cs[0] = to_cs[1] = from_cs[0] = from_cs[1] = -1; 380 if (pipe(to_cs) < 0 || pipe(from_cs) < 0) { 381 msgq(sp, M_SYSERR, "pipe"); 382 goto err; 383 } 384 switch (csc->pid = vfork()) { 385 char *dn, *dbn; 386 case -1: 387 msgq(sp, M_SYSERR, "vfork"); 388 err: if (to_cs[0] != -1) 389 (void)close(to_cs[0]); 390 if (to_cs[1] != -1) 391 (void)close(to_cs[1]); 392 if (from_cs[0] != -1) 393 (void)close(from_cs[0]); 394 if (from_cs[1] != -1) 395 (void)close(from_cs[1]); 396 return (1); 397 case 0: /* child: run cscope. */ 398 (void)dup2(to_cs[0], STDIN_FILENO); 399 (void)dup2(from_cs[1], STDOUT_FILENO); 400 (void)dup2(from_cs[1], STDERR_FILENO); 401 402 /* Close unused file descriptors. */ 403 (void)close(to_cs[1]); 404 (void)close(from_cs[0]); 405 406 /* Run the cscope command. */ 407 #define CSCOPE_CMD_FMT "cd %s && exec cscope -dl -f %s" 408 if ((dn = quote(csc->dname)) == NULL) 409 goto nomem; 410 if ((dbn = quote(dbname)) == NULL) { 411 free(dn); 412 goto nomem; 413 } 414 (void)asprintf(&cmd, CSCOPE_CMD_FMT, dn, dbn); 415 free(dbn); 416 free(dn); 417 if (cmd == NULL) { 418 nomem: msgq(sp, M_SYSERR, NULL); 419 _exit (1); 420 } 421 (void)execl(_PATH_BSHELL, "sh", "-c", cmd, (char *)NULL); 422 msgq_str(sp, M_SYSERR, cmd, "execl: %s"); 423 free(cmd); 424 _exit (127); 425 /* NOTREACHED */ 426 default: /* parent. */ 427 /* Close unused file descriptors. */ 428 (void)close(to_cs[0]); 429 (void)close(from_cs[1]); 430 431 /* 432 * Save the file descriptors for later duplication, and 433 * reopen as streams. 434 */ 435 csc->to_fd = to_cs[1]; 436 csc->to_fp = fdopen(to_cs[1], "w"); 437 csc->from_fd = from_cs[0]; 438 csc->from_fp = fdopen(from_cs[0], "r"); 439 break; 440 } 441 return (0); 442 } 443 444 /* 445 * cscope_find -- 446 * The cscope find command. 447 */ 448 static int 449 cscope_find(SCR *sp, EXCMD *cmdp, CHAR_T *pattern) 450 { 451 CSC *csc, *csc_next; 452 EX_PRIVATE *exp; 453 FREF *frp; 454 TAGQ *rtqp, *tqp; 455 TAG *rtp; 456 recno_t lno; 457 size_t cno, search; 458 int force, istmp, matches; 459 char *np = NULL; 460 size_t nlen; 461 462 exp = EXP(sp); 463 464 /* Check for connections. */ 465 if (SLIST_EMPTY(exp->cscq)) { 466 msgq(sp, M_ERR, "310|No cscope connections running"); 467 return (1); 468 } 469 470 /* 471 * Allocate all necessary memory before doing anything hard. If the 472 * tags stack is empty, we'll need the `local context' TAGQ structure 473 * later. 474 */ 475 rtp = NULL; 476 rtqp = NULL; 477 if (TAILQ_EMPTY(exp->tq)) { 478 /* Initialize the `local context' tag queue structure. */ 479 CALLOC_GOTO(sp, rtqp, 1, sizeof(TAGQ)); 480 TAILQ_INIT(rtqp->tagq); 481 482 /* Initialize and link in its tag structure. */ 483 CALLOC_GOTO(sp, rtp, 1, sizeof(TAG)); 484 TAILQ_INSERT_HEAD(rtqp->tagq, rtp, q); 485 rtqp->current = rtp; 486 } 487 488 /* Create the cscope command. */ 489 INT2CHAR(sp, pattern, STRLEN(pattern) + 1, np, nlen); 490 np = strdup(np); 491 if ((tqp = create_cs_cmd(sp, np, &search)) == NULL) 492 goto err; 493 free(np); 494 np = NULL; 495 496 /* 497 * Stick the current context in a convenient place, we'll lose it 498 * when we switch files. 499 */ 500 frp = sp->frp; 501 lno = sp->lno; 502 cno = sp->cno; 503 istmp = F_ISSET(sp->frp, FR_TMPFILE) && !F_ISSET(cmdp, E_NEWSCREEN); 504 505 /* Search all open connections for a match. */ 506 matches = 0; 507 /* Copy next connect here in case csc is killed. */ 508 SLIST_FOREACH_SAFE(csc, exp->cscq, q, csc_next) { 509 /* 510 * Send the command to the cscope program. (We skip the 511 * first two bytes of the command, because we stored the 512 * search cscope command character and a leading space 513 * there.) 514 */ 515 (void)fprintf(csc->to_fp, "%lu%s\n", search, tqp->tag + 2); 516 (void)fflush(csc->to_fp); 517 518 /* Read the output. */ 519 if (parse(sp, csc, tqp, &matches)) 520 goto nomatch; 521 } 522 523 if (matches == 0) { 524 msgq(sp, M_INFO, "278|No matches for query"); 525 nomatch: free(rtp); 526 free(rtqp); 527 tagq_free(sp, tqp); 528 return (1); 529 } 530 531 /* Try to switch to the first tag. */ 532 force = FL_ISSET(cmdp->iflags, E_C_FORCE); 533 if (F_ISSET(cmdp, E_NEWSCREEN)) { 534 if (ex_tag_Nswitch(sp, tqp->current, force)) 535 goto err; 536 537 /* Everything else gets done in the new screen. */ 538 sp = sp->nextdisp; 539 exp = EXP(sp); 540 } else 541 if (ex_tag_nswitch(sp, tqp->current, force)) 542 goto err; 543 544 /* 545 * If this is the first tag, put a `current location' queue entry 546 * in place, so we can pop all the way back to the current mark. 547 * Note, it doesn't point to much of anything, it's a placeholder. 548 */ 549 if (TAILQ_EMPTY(exp->tq)) { 550 TAILQ_INSERT_HEAD(exp->tq, rtqp, q); 551 } else 552 rtqp = TAILQ_FIRST(exp->tq); 553 554 /* Link the current TAGQ structure into place. */ 555 TAILQ_INSERT_HEAD(exp->tq, tqp, q); 556 557 (void)cscope_search(sp, tqp, tqp->current); 558 559 /* 560 * Move the current context from the temporary save area into the 561 * right structure. 562 * 563 * If we were in a temporary file, we don't have a context to which 564 * we can return, so just make it be the same as what we're moving 565 * to. It will be a little odd that ^T doesn't change anything, but 566 * I don't think it's a big deal. 567 */ 568 if (istmp) { 569 rtqp->current->frp = sp->frp; 570 rtqp->current->lno = sp->lno; 571 rtqp->current->cno = sp->cno; 572 } else { 573 rtqp->current->frp = frp; 574 rtqp->current->lno = lno; 575 rtqp->current->cno = cno; 576 } 577 578 return (0); 579 580 err: 581 alloc_err: 582 free(rtqp); 583 free(rtp); 584 free(np); 585 return (1); 586 } 587 588 /* 589 * create_cs_cmd -- 590 * Build a cscope command, creating and initializing the base TAGQ. 591 */ 592 static TAGQ * 593 create_cs_cmd(SCR *sp, char *pattern, size_t *searchp) 594 { 595 CB *cbp; 596 TAGQ *tqp; 597 size_t tlen; 598 char *p; 599 600 /* 601 * Cscope supports a "change pattern" command which we never use, 602 * cscope command 5. Set CSCOPE_QUERIES[5] to " " since the user 603 * can't pass " " as the first character of pattern. That way the 604 * user can't ask for pattern 5 so we don't need any special-case 605 * code. 606 */ 607 #define CSCOPE_QUERIES "sgdct efi" 608 609 if (pattern == NULL) 610 goto usage; 611 612 /* Skip leading blanks, check for command character. */ 613 for (; cmdskip(pattern[0]); ++pattern); 614 if (pattern[0] == '\0' || !cmdskip(pattern[1])) 615 goto usage; 616 for (*searchp = 0, p = CSCOPE_QUERIES; 617 *p != '\0' && *p != pattern[0]; ++*searchp, ++p); 618 if (*p == '\0') { 619 msgq(sp, M_ERR, 620 "311|%s: unknown search type: use one of %s", 621 KEY_NAME(sp, pattern[0]), CSCOPE_QUERIES); 622 return (NULL); 623 } 624 625 /* Skip <blank> characters to the pattern. */ 626 for (p = pattern + 1; *p != '\0' && cmdskip(*p); ++p); 627 if (*p == '\0') { 628 usage: (void)csc_help(sp, "find"); 629 return (NULL); 630 } 631 632 /* The user can specify the contents of a buffer as the pattern. */ 633 cbp = NULL; 634 if (p[0] == '"' && p[1] != '\0' && p[2] == '\0') 635 CBNAME(sp, cbp, p[1]); 636 if (cbp != NULL) { 637 INT2CHAR(sp, TAILQ_FIRST(cbp->textq)->lb, 638 TAILQ_FIRST(cbp->textq)->len, p, tlen); 639 } else 640 tlen = strlen(p); 641 642 /* Allocate and initialize the TAGQ structure. */ 643 CALLOC(sp, tqp, 1, sizeof(TAGQ) + tlen + 3); 644 if (tqp == NULL) 645 return (NULL); 646 TAILQ_INIT(tqp->tagq); 647 tqp->tag = tqp->buf; 648 tqp->tag[0] = pattern[0]; 649 tqp->tag[1] = ' '; 650 tqp->tlen = tlen + 2; 651 memcpy(tqp->tag + 2, p, tlen); 652 tqp->tag[tlen + 2] = '\0'; 653 F_SET(tqp, TAG_CSCOPE); 654 655 return (tqp); 656 } 657 658 /* 659 * parse -- 660 * Parse the cscope output. 661 */ 662 static int 663 parse(SCR *sp, CSC *csc, TAGQ *tqp, int *matchesp) 664 { 665 TAG *tp; 666 recno_t slno = 0; 667 size_t dlen, nlen = 0, slen = 0; 668 int ch, i, isolder = 0, nlines; 669 char *dname = NULL, *name = NULL, *search, *p, *t, dummy[2], buf[2048]; 670 CHAR_T *wp; 671 size_t wlen; 672 673 for (;;) { 674 if (!fgets(buf, sizeof(buf), csc->from_fp)) 675 goto io_err; 676 677 /* 678 * If the database is out of date, or there's some other 679 * problem, cscope will output error messages before the 680 * number-of-lines output. Display/discard any output 681 * that doesn't match what we want. 682 */ 683 #define CSCOPE_NLINES_FMT "cscope: %d lines%1[\n]" 684 if (sscanf(buf, CSCOPE_NLINES_FMT, &nlines, dummy) == 2) 685 break; 686 if ((p = strchr(buf, '\n')) != NULL) 687 *p = '\0'; 688 msgq(sp, M_ERR, "%s: \"%s\"", csc->dname, buf); 689 } 690 691 while (nlines--) { 692 if (fgets(buf, sizeof(buf), csc->from_fp) == NULL) 693 goto io_err; 694 695 /* If the line's too long for the buffer, discard it. */ 696 if ((p = strchr(buf, '\n')) == NULL) { 697 while ((ch = getc(csc->from_fp)) != EOF && ch != '\n'); 698 continue; 699 } 700 *p = '\0'; 701 702 /* 703 * The cscope output is in the following format: 704 * 705 * <filename> <context> <line number> <pattern> 706 * 707 * Figure out how long everything is so we can allocate in one 708 * swell foop, but discard anything that looks wrong. 709 */ 710 for (p = buf, i = 0; 711 i < 3 && (t = strsep(&p, "\t ")) != NULL; ++i) 712 switch (i) { 713 case 0: /* Filename. */ 714 name = t; 715 nlen = strlen(name); 716 break; 717 case 1: /* Context. */ 718 break; 719 case 2: /* Line number. */ 720 slno = (recno_t)atol(t); 721 break; 722 } 723 if (i != 3 || p == NULL || t == NULL) 724 continue; 725 726 /* The rest of the string is the search pattern. */ 727 search = p; 728 slen = strlen(p); 729 730 /* Resolve the file name. */ 731 csc_file(sp, csc, name, &dname, &dlen, &isolder); 732 733 /* 734 * If the file is older than the cscope database, that is, 735 * the database was built since the file was last modified, 736 * or there wasn't a search string, use the line number. 737 */ 738 if (isolder || strcmp(search, "<unknown>") == 0) { 739 search = NULL; 740 slen = 0; 741 } 742 743 /* 744 * Allocate and initialize a tag structure plus the variable 745 * length cscope information that follows it. 746 */ 747 CALLOC_RET(sp, tp, 1, 748 sizeof(TAG) + dlen + 2 + nlen + 1 + (slen + 1) * sizeof(CHAR_T)); 749 tp->fname = (char *)tp->buf; 750 if (dlen == 1 && *dname == '.') 751 --dlen; 752 else if (dlen != 0) { 753 memcpy(tp->fname, dname, dlen); 754 tp->fname[dlen] = '/'; 755 ++dlen; 756 } 757 memcpy(tp->fname + dlen, name, nlen + 1); 758 tp->fnlen = dlen + nlen; 759 tp->slno = slno; 760 if (slen != 0) { 761 tp->search = (CHAR_T*)(tp->fname + tp->fnlen + 1); 762 CHAR2INT(sp, search, slen + 1, wp, wlen); 763 MEMCPY(tp->search, wp, (tp->slen = slen) + 1); 764 } 765 TAILQ_INSERT_TAIL(tqp->tagq, tp, q); 766 767 /* Try to preset the tag within the current file. */ 768 if (sp->frp != NULL && sp->frp->name != NULL && 769 tqp->current == NULL && !strcmp(tp->fname, sp->frp->name)) 770 tqp->current = tp; 771 772 ++*matchesp; 773 } 774 775 if (tqp->current == NULL) 776 tqp->current = TAILQ_FIRST(tqp->tagq); 777 778 return read_prompt(sp, csc); 779 780 io_err: if (feof(csc->from_fp)) 781 errno = EIO; 782 msgq_str(sp, M_SYSERR, "%s", csc->dname); 783 terminate(sp, csc, 0); 784 return (1); 785 } 786 787 /* 788 * csc_file -- 789 * Search for the right path to this file. 790 */ 791 static void 792 csc_file(SCR *sp, CSC *csc, char *name, char **dirp, size_t *dlenp, int *isolderp) 793 { 794 struct stat sb; 795 char **pp, *buf; 796 797 /* 798 * Check for the file in all of the listed paths. If we don't 799 * find it, we simply return it unchanged. We have to do this 800 * now, even though it's expensive, because if the user changes 801 * directories, we can't change our minds as to where the file 802 * lives. 803 */ 804 for (pp = csc->paths; *pp != NULL; ++pp) { 805 if ((buf = join(*pp, name)) == NULL) { 806 msgq(sp, M_SYSERR, NULL); 807 *dlenp = 0; 808 return; 809 } 810 if (stat(buf, &sb) == 0) { 811 free(buf); 812 *dirp = *pp; 813 *dlenp = strlen(*pp); 814 *isolderp = timespeccmp( 815 &sb.st_mtimespec, &csc->mtim, <); 816 return; 817 } 818 free(buf); 819 } 820 *dlenp = 0; 821 } 822 823 /* 824 * cscope_help -- 825 * The cscope help command. 826 */ 827 static int 828 cscope_help(SCR *sp, EXCMD *cmdp, CHAR_T *subcmd) 829 { 830 char *np; 831 size_t nlen; 832 833 INT2CHAR(sp, subcmd, STRLEN(subcmd) + 1, np, nlen); 834 return (csc_help(sp, np)); 835 } 836 837 /* 838 * csc_help -- 839 * Display help/usage messages. 840 */ 841 static int 842 csc_help(SCR *sp, char *cmd) 843 { 844 CC const *ccp; 845 846 if (cmd != NULL && *cmd != '\0') 847 if ((ccp = lookup_ccmd(cmd)) == NULL) { 848 ex_printf(sp, 849 "%s doesn't match any cscope command\n", cmd); 850 return (1); 851 } else { 852 ex_printf(sp, 853 "Command: %s (%s)\n", ccp->name, ccp->help_msg); 854 ex_printf(sp, " Usage: %s\n", ccp->usage_msg); 855 return (0); 856 } 857 858 ex_printf(sp, "cscope commands:\n"); 859 for (ccp = cscope_cmds; ccp->name != NULL; ++ccp) 860 ex_printf(sp, " %*s: %s\n", 5, ccp->name, ccp->help_msg); 861 return (0); 862 } 863 864 /* 865 * cscope_kill -- 866 * The cscope kill command. 867 */ 868 static int 869 cscope_kill(SCR *sp, EXCMD *cmdp, CHAR_T *cn) 870 { 871 char *np; 872 size_t nlen; 873 int n = 1; 874 875 if (*cn) { 876 INT2CHAR(sp, cn, STRLEN(cn) + 1, np, nlen); 877 n = atoi(np); 878 } 879 return (terminate(sp, NULL, n)); 880 } 881 882 /* 883 * terminate -- 884 * Detach from a cscope process. 885 */ 886 static int 887 terminate(SCR *sp, CSC *csc, int n) 888 { 889 EX_PRIVATE *exp; 890 int i = 0, pstat; 891 CSC *cp, *pre_cp = NULL; 892 893 exp = EXP(sp); 894 895 /* 896 * We either get a csc structure or a number. Locate and remove 897 * the candidate which matches the structure or the number. 898 */ 899 if (csc == NULL && n < 1) 900 goto badno; 901 SLIST_FOREACH(cp, exp->cscq, q) { 902 ++i; 903 if (csc == NULL ? i != n : cp != csc) { 904 pre_cp = cp; 905 continue; 906 } 907 if (cp == SLIST_FIRST(exp->cscq)) 908 SLIST_REMOVE_HEAD(exp->cscq, q); 909 else 910 SLIST_REMOVE_AFTER(pre_cp, q); 911 csc = cp; 912 break; 913 } 914 if (csc == NULL) { 915 badno: msgq(sp, M_ERR, "312|%d: no such cscope session", n); 916 return (1); 917 } 918 919 /* 920 * XXX 921 * Theoretically, we have the only file descriptors to the process, 922 * so closing them should let it exit gracefully, deleting temporary 923 * files, etc. However, the earlier created cscope processes seems 924 * to refuse to quit unless we send a SIGTERM signal. 925 */ 926 if (csc->from_fp != NULL) 927 (void)fclose(csc->from_fp); 928 if (csc->to_fp != NULL) 929 (void)fclose(csc->to_fp); 930 if (i > 1) 931 (void)kill(csc->pid, SIGTERM); 932 (void)waitpid(csc->pid, &pstat, 0); 933 934 /* Discard cscope connection information. */ 935 free(csc->pbuf); 936 free(csc->paths); 937 free(csc); 938 return (0); 939 } 940 941 /* 942 * cscope_reset -- 943 * The cscope reset command. 944 */ 945 static int 946 cscope_reset(SCR *sp, EXCMD *cmdp, CHAR_T *notusedp) 947 { 948 return cscope_end(sp); 949 } 950 951 /* 952 * cscope_end -- 953 * End all cscope connections. 954 * 955 * PUBLIC: int cscope_end(SCR *); 956 */ 957 int 958 cscope_end(SCR *sp) 959 { 960 EX_PRIVATE *exp; 961 962 for (exp = EXP(sp); !SLIST_EMPTY(exp->cscq);) 963 if (terminate(sp, NULL, 1)) 964 return (1); 965 return (0); 966 } 967 968 /* 969 * cscope_display -- 970 * Display current connections. 971 * 972 * PUBLIC: int cscope_display(SCR *); 973 */ 974 int 975 cscope_display(SCR *sp) 976 { 977 EX_PRIVATE *exp; 978 CSC *csc; 979 int i = 0; 980 981 exp = EXP(sp); 982 if (SLIST_EMPTY(exp->cscq)) { 983 ex_printf(sp, "No cscope connections.\n"); 984 return (0); 985 } 986 SLIST_FOREACH(csc, exp->cscq, q) 987 ex_printf(sp, "%2d %s (process %lu)\n", 988 ++i, csc->dname, (u_long)csc->pid); 989 return (0); 990 } 991 992 /* 993 * cscope_search -- 994 * Search a file for a cscope entry. 995 * 996 * PUBLIC: int cscope_search(SCR *, TAGQ *, TAG *); 997 */ 998 int 999 cscope_search(SCR *sp, TAGQ *tqp, TAG *tp) 1000 { 1001 MARK m; 1002 1003 /* If we don't have a search pattern, use the line number. */ 1004 if (tp->search == NULL) { 1005 if (!db_exist(sp, tp->slno)) { 1006 tag_msg(sp, TAG_BADLNO, tqp->tag); 1007 return (1); 1008 } 1009 m.lno = tp->slno; 1010 } else { 1011 /* 1012 * Search for the tag; cheap fallback for C functions 1013 * if the name is the same but the arguments have changed. 1014 */ 1015 m.lno = 1; 1016 m.cno = 0; 1017 if (f_search(sp, &m, &m, 1018 tp->search, tp->slen, NULL, SEARCH_CSCOPE | SEARCH_FILE)) { 1019 tag_msg(sp, TAG_SEARCH, tqp->tag); 1020 return (1); 1021 } 1022 1023 /* 1024 * !!! 1025 * Historically, tags set the search direction if it wasn't 1026 * already set. 1027 */ 1028 if (sp->searchdir == NOTSET) 1029 sp->searchdir = FORWARD; 1030 } 1031 1032 /* 1033 * !!! 1034 * Tags move to the first non-blank, NOT the search pattern start. 1035 */ 1036 sp->lno = m.lno; 1037 sp->cno = 0; 1038 (void)nonblank(sp, sp->lno, &sp->cno); 1039 return (0); 1040 } 1041 1042 1043 /* 1044 * lookup_ccmd -- 1045 * Return a pointer to the command structure. 1046 */ 1047 static CC const * 1048 lookup_ccmd(char *name) 1049 { 1050 CC const *ccp; 1051 size_t len; 1052 1053 len = strlen(name); 1054 for (ccp = cscope_cmds; ccp->name != NULL; ++ccp) 1055 if (strncmp(name, ccp->name, len) == 0) 1056 return (ccp); 1057 return (NULL); 1058 } 1059 1060 /* 1061 * read_prompt -- 1062 * Read a prompt from cscope. 1063 */ 1064 static int 1065 read_prompt(SCR *sp, CSC *csc) 1066 { 1067 int ch; 1068 1069 #define CSCOPE_PROMPT ">> " 1070 for (;;) { 1071 while ((ch = 1072 getc(csc->from_fp)) != EOF && ch != CSCOPE_PROMPT[0]); 1073 if (ch == EOF) { 1074 terminate(sp, csc, 0); 1075 return (1); 1076 } 1077 if (getc(csc->from_fp) != CSCOPE_PROMPT[1]) 1078 continue; 1079 if (getc(csc->from_fp) != CSCOPE_PROMPT[2]) 1080 continue; 1081 break; 1082 } 1083 return (0); 1084 } 1085