static void put_syms(int type, const char *tag, int lno, const char *path, const char *line_image, void *arg) { struct parsefile_data *data = arg; const char *key; if (format == FORMAT_PATH && data->count > 0) return; switch (type) { case PARSER_DEF: if (!(data->target & TARGET_DEF)) return; break; case PARSER_REF_SYM: if (!(data->target & (TARGET_REF | TARGET_SYM))) return; /* * extract method when class method definition. * * Ex: Class::method(...) * * key = 'method' * data = 'Class::method 103 ./class.cpp ...' */ if (data->extractmethod) { if ((key = locatestring(tag, ".", MATCH_LAST)) != NULL) key++; else if ((key = locatestring(tag, "::", MATCH_LAST)) != NULL) key += 2; else key = tag; } else { key = tag; } if (data->target == TARGET_REF || data->target == TARGET_SYM) { if (dbop_get(data->dbop, key) != NULL) { if (!(data->target & TARGET_REF)) return; } else { if (!(data->target & TARGET_SYM)) return; } } break; default: return; } convert_put_using(data->cv, tag, path, lno, line_image, data->fid); data->count++; }
/* * grep: grep pattern * * i) pattern POSIX regular expression */ void grep(const char *pattern, char *const *argv, const char *dbpath) { FILE *fp; CONVERT *cv; GFIND *gp = NULL; STRBUF *ib = strbuf_open(MAXBUFLEN); const char *path; char encoded_pattern[IDENTLEN]; const char *buffer; int linenum, count; int flags = 0; int target = GPATH_SOURCE; regex_t preg; int user_specified = 1; /* * convert spaces into %FF format. */ encode(encoded_pattern, sizeof(encoded_pattern), pattern); if (oflag) target = GPATH_BOTH; if (Oflag) target = GPATH_OTHER; if (!Gflag) flags |= REG_EXTENDED; if (iflag) flags |= REG_ICASE; if (regcomp(&preg, pattern, flags) != 0) die("invalid regular expression."); cv = convert_open(type, format, root, cwd, dbpath, stdout); count = 0; if (*argv && file_list) args_open_both(argv, file_list); else if (*argv) args_open(argv); else if (file_list) args_open_filelist(file_list); else { args_open_gfind(gp = gfind_open(dbpath, localprefix, target)); user_specified = 0; } while ((path = args_read()) != NULL) { if (user_specified) { static char buf[MAXPATHLEN]; if (normalize(path, get_root_with_slash(), cwd, buf, sizeof(buf)) == NULL) if (!qflag) fprintf(stderr, "'%s' is out of source tree.\n", path); if (!test("f", buf)) die("'%s' not found. Please remake tag files by invoking gtags(1).", path); path = buf; } if (!(fp = fopen(path, "r"))) die("cannot open file '%s'.", path); linenum = 0; while ((buffer = strbuf_fgets(ib, fp, STRBUF_NOCRLF)) != NULL) { int result = regexec(&preg, buffer, 0, 0, 0); linenum++; if ((!Vflag && result == 0) || (Vflag && result != 0)) { count++; if (format == FORMAT_PATH) { convert_put_path(cv, path); break; } else { convert_put_using(cv, encoded_pattern, path, linenum, buffer, (user_specified) ? NULL : gp->dbop->lastdat); } } } fclose(fp); } args_close(); convert_close(cv); strbuf_close(ib); regfree(&preg); if (vflag) { print_count(count); fprintf(stderr, " (no index used).\n"); } }
/* * idutils: lid(idutils) pattern * * i) pattern POSIX regular expression * i) dbpath GTAGS directory */ void idutils(const char *pattern, const char *dbpath) { FILE *ip; CONVERT *cv; STRBUF *ib = strbuf_open(0); char encoded_pattern[IDENTLEN]; char path[MAXPATHLEN]; const char *lid; int linenum, count; char *p, *q, *grep; lid = usable("lid"); if (!lid) die("lid(idutils) not found."); /* * convert spaces into %FF format. */ encode(encoded_pattern, sizeof(encoded_pattern), pattern); /* * make lid command line. * Invoke lid with the --result=grep option to generate grep format. */ strbuf_puts(ib, lid); strbuf_sprintf(ib, " --file='%s/ID'", dbpath); strbuf_puts(ib, " --separator=newline"); if (format == FORMAT_PATH) strbuf_puts(ib, " --result=filenames --key=none"); else strbuf_puts(ib, " --result=grep"); if (iflag) strbuf_puts(ib, " --ignore-case"); strbuf_putc(ib, ' '); strbuf_puts(ib, quote_string(pattern)); if (debug) fprintf(stderr, "idutils: %s\n", strbuf_value(ib)); if (!(ip = popen(strbuf_value(ib), "r"))) die("cannot execute '%s'.", strbuf_value(ib)); cv = convert_open(type, format, root, cwd, dbpath, stdout); count = 0; strcpy(path, "./"); while ((grep = strbuf_fgets(ib, ip, STRBUF_NOCRLF)) != NULL) { q = path + 2; /* extract path name */ if (*grep == '/') die("The path in the output of lid is assumed absolute. '%s'", grep); p = grep; while (*p && *p != ':') *q++ = *p++; *q = '\0'; if ((xflag || tflag) && !*p) die("invalid lid(idutils) output format(1). '%s'", grep); p++; if (lflag) { if (!locatestring(path, localprefix, MATCH_AT_FIRST)) continue; } count++; switch (format) { case FORMAT_PATH: convert_put_path(cv, path); break; default: /* extract line number */ while (*p && isspace(*p)) p++; linenum = 0; for (linenum = 0; *p && isdigit(*p); linenum = linenum * 10 + (*p++ - '0')) ; if (*p != ':') die("invalid lid(idutils) output format(2). '%s'", grep); if (linenum <= 0) die("invalid lid(idutils) output format(3). '%s'", grep); p++; /* * print out. */ convert_put_using(cv, encoded_pattern, path, linenum, p, NULL); break; } } if (pclose(ip) < 0) die("terminated abnormally."); convert_close(cv); strbuf_close(ib); if (vflag) { print_count(count); fprintf(stderr, " (using idutils index in '%s').\n", dbpath); } }
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; }
/* * pathlist: print candidate path list. * * i) dbpath */ void pathlist(const char *pattern, const char *dbpath) { GFIND *gp; CONVERT *cv; const char *path, *p; regex_t preg; int count; int target = GPATH_SOURCE; if (oflag) target = GPATH_BOTH; if (Oflag) target = GPATH_OTHER; if (pattern) { int flags = 0; char edit[IDENTLEN]; if (!Gflag) flags |= REG_EXTENDED; if (iflag || getconfb("icase_path")) flags |= REG_ICASE; #ifdef _WIN32 flags |= REG_ICASE; #endif /* _WIN32 */ /* * We assume '^aaa' as '^/aaa'. */ if (*pattern == '^' && *(pattern + 1) != '/') { snprintf(edit, sizeof(edit), "^/%s", pattern + 1); pattern = edit; } if (regcomp(&preg, pattern, flags) != 0) die("invalid regular expression."); } if (!localprefix) localprefix = "./"; cv = convert_open(type, format, root, cwd, dbpath, stdout); count = 0; gp = gfind_open(dbpath, localprefix, target); while ((path = gfind_read(gp)) != NULL) { /* * skip localprefix because end-user doesn't see it. */ p = path + strlen(localprefix) - 1; if (pattern) { int result = regexec(&preg, p, 0, 0, 0); if ((!Vflag && result != 0) || (Vflag && result == 0)) continue; } else if (Vflag) continue; if (format == FORMAT_PATH) convert_put_path(cv, path); else convert_put_using(cv, "path", path, 1, " ", gp->dbop->lastdat); count++; } gfind_close(gp); convert_close(cv); if (pattern) regfree(&preg); if (vflag) { switch (count) { case 0: fprintf(stderr, "file not found"); break; case 1: fprintf(stderr, "1 file located"); break; default: fprintf(stderr, "%d files located", count); break; } fprintf(stderr, " (using '%s').\n", makepath(dbpath, dbname(GPATH), NULL)); } }
void literal_search(CONVERT *cv, const char *file) { struct words *c; int ccount; char *p; char *buf; struct stat stb; char *linep; long lineno; int f; if ((f = open(file, 0)) < 0) die("cannot open '%s'.", file); if (fstat(f, &stb) < 0) die("cannot fstat '%s'.", file); if (stb.st_size == 0) goto skip_empty_file; #ifdef HAVE_MMAP buf = mmap(0, stb.st_size, PROT_READ, MAP_SHARED, f, 0); if (buf == MAP_FAILED) die("mmap failed (%s).", file); #else #ifdef HAVE_ALLOCA buf = (char *)alloca(stb.st_size); #else buf = (char *)malloc(stb.st_size); #endif if (buf == NULL) die("short of memory."); if (read(f, buf, stb.st_size) < stb.st_size) die("read failed (%s).", file); #endif linep = p = buf; ccount = stb.st_size; lineno = 1; c = w; for (;;) { if (--ccount <= 0) break; nstate: if (ccomp(c->inp, *p)) { c = c->nst; } else if (c->link != 0) { c = c->link; goto nstate; } else { c = c->fail; if (c==0) { c = w; istate: if (ccomp(c->inp , *p)) { c = c->nst; } else if (c->link != 0) { c = c->link; goto istate; } } else goto nstate; } if (c->out) { while (*p++ != '\n') { if (--ccount <= 0) break; } if (Vflag) goto nomatch; succeed: if (cv->format == FORMAT_PATH) { convert_put_path(cv, file); goto finish; } else { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_nputs(sb, linep, p - linep); strbuf_unputc(sb, '\n'); strbuf_unputc(sb, '\r'); convert_put_using(cv, encoded_pattern, file, lineno, strbuf_value(sb), NULL); } nomatch: lineno++; linep = p; c = w; continue; } if (*p++ == '\n') { if (Vflag) goto succeed; else { lineno++; linep = p; c = w; } } } finish: #ifdef HAVE_MMAP munmap(buf, stb.st_size); #elif HAVE_ALLOCA #else free(buf); #endif skip_empty_file: close(f); }
/** * literal_search: execute literal search * * @param[in] cv CONVERT structure * @param[in] file file to search * @return 0: normal, -1: error */ int literal_search(CONVERT *cv, const char *file) { # define ccomp(a,b) (iflag ? lca(a)==lca(b) : a==b) # define lca(x) (isupper(x) ? tolower(x) : x) struct words *c; int ccount; char *p; char *buf; struct stat stb; char *linep; long lineno; int f; int count = 0; if ((f = open(file, O_BINARY)) < 0) { warning("cannot open '%s'.", file); return -1; } if (fstat(f, &stb) < 0) { warning("cannot fstat '%s'.", file); goto skip_empty_file; } if (stb.st_size == 0) goto skip_empty_file; #ifdef HAVE_MMAP buf = mmap(0, stb.st_size, PROT_READ, MAP_SHARED, f, 0); if (buf == MAP_FAILED) die("mmap failed (%s).", file); #elif _WIN32 { HANDLE hMap = CreateFileMapping((HANDLE)_get_osfhandle(f), NULL, PAGE_READONLY, 0, stb.st_size, NULL); if (hMap == NULL) die("CreateFileMapping failed (%s).", file); buf = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); if (buf == NULL) die("MapViewOfFile failed (%s).", file); #else #ifdef HAVE_ALLOCA buf = (char *)alloca(stb.st_size); #else buf = (char *)malloc(stb.st_size); #endif if (buf == NULL) die("short of memory."); if (read(f, buf, stb.st_size) < stb.st_size) die("read failed (%s).", file); #endif linep = p = buf; ccount = stb.st_size; lineno = 1; c = w; for (;;) { if (--ccount < 0) break; nstate: if (ccomp(c->inp, *p)) { c = c->nst; } else if (c->link != 0) { c = c->link; goto nstate; } else { c = c->fail; if (c==0) { c = w; istate: if (ccomp(c->inp , *p)) { c = c->nst; } else if (c->link != 0) { c = c->link; goto istate; } } else goto nstate; } if (c->out) { while (*p++ != '\n') { if (--ccount < 0) break; } if (Vflag) goto nomatch; succeed: if (cv->format == FORMAT_PATH) { convert_put_path(cv, NULL, file); count++; goto finish; } else { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_nputs(sb, linep, p - linep); strbuf_unputc(sb, '\n'); strbuf_unputc(sb, '\r'); convert_put_using(cv, pattern, file, lineno, strbuf_value(sb), NULL); count++; } nomatch: lineno++; linep = p; c = w; continue; } if (*p++ == '\n' || ccount == 0) { if (Vflag) goto succeed; else { lineno++; linep = p; c = w; } } } finish: #ifdef HAVE_MMAP munmap(buf, stb.st_size); #elif _WIN32 UnmapViewOfFile(buf); CloseHandle(hMap); } #elif HAVE_ALLOCA #else free(buf); #endif skip_empty_file: close(f); return count; }
/** * grep: @NAME{grep} pattern * * @param[in] pattern @NAME{POSIX} regular expression * @param argv * @param dbpath */ void grep(const char *pattern, char *const *argv, const char *dbpath) { FILE *fp; CONVERT *cv; GFIND *gp = NULL; STRBUF *ib = strbuf_open(MAXBUFLEN); const char *path; char encoded_pattern[IDENTLEN]; const char *buffer; int linenum, count; int flags = 0; int target = GPATH_SOURCE; regex_t preg; int user_specified = 1; /* * convert spaces into %FF format. */ encode(encoded_pattern, sizeof(encoded_pattern), pattern); /* * literal search available? */ if (!literal) { const char *p = pattern; int normal = 1; for (; *p; p++) { if (!(isalpha(*p) || isdigit(*p) || isblank(*p) || *p == '_')) { normal = 0; break; } } if (normal) literal = 1; } if (oflag) target = GPATH_BOTH; if (Oflag) target = GPATH_OTHER; if (literal) { literal_comple(pattern); } else { if (!Gflag) flags |= REG_EXTENDED; if (iflag) flags |= REG_ICASE; if (regcomp(&preg, pattern, flags) != 0) die("invalid regular expression."); } cv = convert_open(type, format, root, cwd, dbpath, stdout, NOTAGS); cv->tag_for_display = encoded_pattern; count = 0; if (*argv && file_list) args_open_both(argv, file_list); else if (*argv) args_open(argv); else if (file_list) args_open_filelist(file_list); else { args_open_gfind(gp = gfind_open(dbpath, localprefix, target)); user_specified = 0; } while ((path = args_read()) != NULL) { if (user_specified) { static char buf[MAXPATHLEN]; if (normalize(path, get_root_with_slash(), cwd, buf, sizeof(buf)) == NULL) { warning("'%s' is out of the source project.", path); continue; } if (test("d", buf)) { warning("'%s' is a directory. Ignored.", path); continue; } if (!test("f", buf)) { warning("'%s' not found. Ignored.", path); continue; } path = buf; } if (Sflag && !locatestring(path, localprefix, MATCH_AT_FIRST)) continue; if (literal) { int n = literal_search(cv, path); if (n > 0) count += n; } else { if (!(fp = fopen(path, "r"))) die("cannot open file '%s'.", path); linenum = 0; while ((buffer = strbuf_fgets(ib, fp, STRBUF_NOCRLF)) != NULL) { int result = regexec(&preg, buffer, 0, 0, 0); linenum++; if ((!Vflag && result == 0) || (Vflag && result != 0)) { count++; if (format == FORMAT_PATH) { convert_put_path(cv, NULL, path); break; } else { convert_put_using(cv, pattern, path, linenum, buffer, (user_specified) ? NULL : gp->dbop->lastdat); } } } fclose(fp); } } args_close(); convert_close(cv); strbuf_close(ib); if (literal == 0) regfree(&preg); if (vflag) { print_count(count); fprintf(stderr, " (no index used).\n"); } }