/** * completion_tags: print completion list of specified @a prefix * * @param[in] dbpath dbpath directory * @param[in] root root directory * @param[in] prefix prefix of primary key * @param[in] db #GTAGS,#GRTAGS,#GSYMS * @return number of words */ int completion_tags(const char *dbpath, const char *root, const char *prefix, int db) { int flags = GTOP_KEY | GTOP_NOREGEX | GTOP_PREFIX; GTOP *gtop = gtags_open(dbpath, root, db, GTAGS_READ, 0); GTP *gtp; int count = 0; if (iflag) flags |= GTOP_IGNORECASE; for (gtp = gtags_first(gtop, prefix, flags); gtp; gtp = gtags_next(gtop)) { fputs(gtp->tag, stdout); fputc('\n', stdout); count++; } if (debug) gtags_show_statistics(gtop); gtags_close(gtop); return count; }
/** * @fn int search(const char *pattern, const char *root, const char *cwd, const char *dbpath, int db) * * search: search specified function * * @param[in] pattern search pattern * @param[in] root root of source tree * @param[in] cwd current directory * @param[in] dbpath database directory * @param[in] db #GTAGS,#GRTAGS,#GSYMS * @return count of output lines */ int search(const char *pattern, const char *root, const char *cwd, const char *dbpath, int db) { CONVERT *cv; int count = 0; GTOP *gtop; GTP *gtp; int flags = 0; start_output(); /* * open tag file. */ gtop = gtags_open(dbpath, root, db, GTAGS_READ, debug ? GTAGS_DEBUG : 0); cv = convert_open(type, format, root, cwd, dbpath, stdout, db); /* * search through tag file. */ if (nofilter & SORT_FILTER) flags |= GTOP_NOSORT; if (Gflag) flags |= GTOP_BASICREGEX; if (format == FORMAT_PATH) flags |= GTOP_PATH; if (iflag) flags |= GTOP_IGNORECASE; for (gtp = gtags_first(gtop, pattern, flags); gtp; gtp = gtags_next(gtop)) { if (Sflag && !locatestring(gtp->path, localprefix, MATCH_AT_FIRST)) continue; count += output_with_formatting(cv, gtp, gtop->format); } convert_close(cv); if (debug) gtags_show_statistics(gtop); gtags_close(gtop); end_output(); return count; }
/* * completion: print completion list of specified prefix * * i) dbpath dbpath directory * i) root root directory * i) prefix prefix of primary key */ void completion(const char *dbpath, const char *root, const char *prefix) { int flags = GTOP_KEY; GTOP *gtop = gtags_open(dbpath, root, (sflag) ? GSYMS : GTAGS, GTAGS_READ, 0); GTP *gtp; if (prefix && *prefix == 0) /* In the case global -c '' */ prefix = NULL; if (prefix && isalpha(*prefix) && iflag) { /* * If the -i option is specified, we use both of regular * expression and prefix read for performance. It is done * by connecting two prefix reading. */ STRBUF *sb = strbuf_open(0); regex_t preg; int i, firstchar[2]; flags |= GTOP_NOREGEX; flags |= GTOP_PREFIX; /* * make regular expression. */ strbuf_putc(sb, '^'); strbuf_puts(sb, prefix); if (regcomp(&preg, strbuf_value(sb), REG_ICASE) != 0) die("invalid regular expression."); /* * Two prefix reading: * * prefix = 'main' * v * firstchar[0] = 'M'; /^M/ the first time * firstchar[1] = 'm'; /^m/ the second time */ firstchar[0] = firstchar[1] = *prefix; if (isupper(firstchar[0])) firstchar[1] = tolower(firstchar[0]); else firstchar[0] = toupper(firstchar[0]); for (i = 0; i < 2; i++) { strbuf_reset(sb); strbuf_putc(sb, firstchar[i]); for (gtp = gtags_first(gtop, strbuf_value(sb), flags); gtp; gtp = gtags_next(gtop)) { if (regexec(&preg, gtp->tag, 0, 0, 0) == 0) { fputs(gtp->tag, stdout); fputc('\n', stdout); } } } strbuf_close(sb); } else { flags |= GTOP_NOREGEX; if (prefix) flags |= GTOP_PREFIX; for (gtp = gtags_first(gtop, prefix, flags); gtp; gtp = gtags_next(gtop)) { fputs(gtp->tag, stdout); fputc('\n', stdout); } } gtags_close(gtop); }
int search(const char *pattern, const char *root, const char *cwd, const char *dbpath, int db) { CONVERT *cv; int count = 0; GTOP *gtop; GTP *gtp; int flags = 0; STRBUF *sb = NULL, *ib = NULL; char curpath[MAXPATHLEN], curtag[IDENTLEN]; FILE *fp = NULL; const char *src = ""; int lineno, last_lineno; lineno = last_lineno = 0; curpath[0] = curtag[0] = '\0'; /* * open tag file. */ gtop = gtags_open(dbpath, root, db, GTAGS_READ, 0); cv = convert_open(type, format, root, cwd, dbpath, stdout); /* * search through tag file. */ if (nofilter & SORT_FILTER) flags |= GTOP_NOSORT; if (iflag) { if (!isregex(pattern)) { sb = strbuf_open(0); strbuf_putc(sb, '^'); strbuf_puts(sb, pattern); strbuf_putc(sb, '$'); pattern = strbuf_value(sb); } flags |= GTOP_IGNORECASE; } if (Gflag) flags |= GTOP_BASICREGEX; if (format == FORMAT_PATH) flags |= GTOP_PATH; if (gtop->format & GTAGS_COMPACT) ib = strbuf_open(0); for (gtp = gtags_first(gtop, pattern, flags); gtp; gtp = gtags_next(gtop)) { if (lflag && !locatestring(gtp->path, localprefix, MATCH_AT_FIRST)) continue; if (format == FORMAT_PATH) { convert_put_path(cv, gtp->path); count++; } else if (gtop->format & GTAGS_COMPACT) { /* * Compact format: * a b * tagline = <file id> <tag name> <line no>,... */ char *p = (char *)gtp->tagline; const char *fid, *tagname; int n = 0; fid = p; while (*p != ' ') p++; *p++ = '\0'; /* a */ tagname = p; while (*p != ' ') p++; *p++ = '\0'; /* b */ /* * Reopen or rewind source file. */ if (!nosource) { if (strcmp(gtp->path, curpath) != 0) { if (curpath[0] != '\0' && fp != NULL) fclose(fp); strlimcpy(curtag, tagname, sizeof(curtag)); strlimcpy(curpath, gtp->path, sizeof(curpath)); /* * Use absolute path name to support GTAGSROOT * environment variable. */ fp = fopen(makepath(root, curpath, NULL), "r"); if (fp == NULL) warning("source file '%s' is not available.", curpath); last_lineno = lineno = 0; } else if (strcmp(gtp->tag, curtag) != 0) { strlimcpy(curtag, gtp->tag, sizeof(curtag)); if (atoi(p) < last_lineno && fp != NULL) { rewind(fp); lineno = 0; } last_lineno = 0; } } /* * Unfold compact format. */ if (!isdigit(*p)) die("illegal compact format."); if (gtop->format & GTAGS_COMPLINE) { /* * * If GTAGS_COMPLINE flag is set, each line number is expressed as * the difference from the previous line number except for the head. * Please see flush_pool() in libutil/gtagsop.c for the details. */ int last = 0, cont = 0; while (*p || cont > 0) { if (cont > 0) { n = last + 1; if (n > cont) { cont = 0; continue; } } else if (isdigit(*p)) { GET_NEXT_NUMBER(p); } else if (*p == '-') { GET_NEXT_NUMBER(p); cont = n + last; n = last + 1; } else if (*p == ',') { GET_NEXT_NUMBER(p); n += last; } if (last_lineno != n && fp) { while (lineno < n) { if (!(src = strbuf_fgets(ib, fp, STRBUF_NOCRLF))) { src = ""; fclose(fp); fp = NULL; break; } lineno++; } } if (gtop->format & GTAGS_COMPNAME) tagname = (char *)uncompress(tagname, gtp->tag); convert_put_using(cv, tagname, gtp->path, n, src, fid); count++; last_lineno = last = n; } } else { /* * In fact, when GTAGS_COMPACT is set, GTAGS_COMPLINE is allways set. * Therefore, the following code are not actually used. * However, it is left for some test. */ while (*p) { for (n = 0; isdigit(*p); p++) n = n * 10 + *p - '0'; if (*p == ',') p++; if (last_lineno == n) continue; if (last_lineno != n && fp) { while (lineno < n) { if (!(src = strbuf_fgets(ib, fp, STRBUF_NOCRLF))) { src = ""; fclose(fp); fp = NULL; break; } lineno++; } } if (gtop->format & GTAGS_COMPNAME) tagname = (char *)uncompress(tagname, gtp->tag); convert_put_using(cv, tagname, gtp->path, n, src, fid); count++; last_lineno = n; } } } else { /* * Standard format: * a b c * tagline = <file id> <tag name> <line no> <line image> */ char *p = (char *)gtp->tagline; char namebuf[IDENTLEN]; const char *fid, *tagname, *image; fid = p; while (*p != ' ') p++; *p++ = '\0'; /* a */ tagname = p; while (*p != ' ') p++; *p++ = '\0'; /* b */ if (gtop->format & GTAGS_COMPNAME) { strlimcpy(namebuf, (char *)uncompress(tagname, gtp->tag), sizeof(namebuf)); tagname = namebuf; } if (nosource) { image = " "; } else { while (*p != ' ') p++; image = p + 1; /* c + 1 */ if (gtop->format & GTAGS_COMPRESS) image = (char *)uncompress(image, gtp->tag); } convert_put_using(cv, tagname, gtp->path, gtp->lineno, image, fid); count++; } } convert_close(cv); if (sb) strbuf_close(sb); if (ib) strbuf_close(ib); if (fp) fclose(fp); gtags_close(gtop); return count; }