📄 gtagsop.c
字号:
static voidgtop_flush_htab(gtop) GTOP *gtop;{ const char *path, *key; struct gtop_compact_entry *entry, *next; int *lno_array; int i, j, savelen; path = gtop->prev_path; if (gtop->format & GTAGS_PATHINDEX) { path = gpath_path2fid(gtop->prev_path); if (path == NULL) die("GPATH is corrupted.('%s' not found)", gtop->prev_path); } for (i = 0; i < HASHBUCKETS; i++) { for (entry = gtop->htab[i]; entry != NULL; entry = next) { /* * extract method when class method definition. * * Ex: Class::method(...) * * key = 'method' * data = 'Class::method 103 ./class.cpp ...' */ key = entry->tag; if (gtop->flags & GTAGS_EXTRACTMETHOD) { if ((key = locatestring(entry->tag, ".", MATCH_LAST)) != NULL) key++; else if ((key = locatestring(entry->tag, "::", MATCH_LAST)) != NULL) key += 2; else key = entry->tag; } lno_array = varray_assign(entry->vb, 0, 0); qsort(lno_array, entry->vb->length, sizeof(int), compare_lno); strbuf_reset(gtop->sb); strbuf_puts(gtop->sb, entry->tag); strbuf_putc(gtop->sb, ' '); strbuf_puts(gtop->sb, path); strbuf_putc(gtop->sb, ' '); savelen = strbuf_getlen(gtop->sb); for (j = 0; j < entry->vb->length; j++) { if ((gtop->flags & GTAGS_UNIQUE) && j > 0 && lno_array[j - 1] == lno_array[j]) continue; if (strbuf_getlen(gtop->sb) > savelen) strbuf_putc(gtop->sb, ','); strbuf_putn(gtop->sb, lno_array[j]); if (strbuf_getlen(gtop->sb) > DBOP_PAGESIZE / 4) { dbop_put(gtop->dbop, key, strbuf_value(gtop->sb)); strbuf_setlen(gtop->sb, savelen); } } if (strbuf_getlen(gtop->sb) > savelen) dbop_put(gtop->dbop, key, strbuf_value(gtop->sb)); varray_close(entry->vb); next = entry->next; free(entry); } gtop->htab[i] = NULL; }}/* * gtags_add: add tags belonging to the path list into tag file. * * i) gtop descripter of GTOP * i) comline tag command line * i) path_list \0 separated list of source files * i) flags GTAGS_UNIQUE, GTAGS_EXTRACTMETHOD, GTAGS_DEBUG */voidgtags_add(gtop, comline, path_list, flags) GTOP *gtop; const char *comline; STRBUF *path_list; int flags;{ const char *ctags_x; FILE *ip; STRBUF *sb = strbuf_open(0); STRBUF *ib = strbuf_open(MAXBUFLEN); const char *path, *end; int path_num; gtop->flags = flags; /* * add path index if not yet. */ path = strbuf_value(path_list); end = path + strbuf_getlen(path_list); path_num = 0; while (path < end) { gpath_put(path); path_num++; path += strlen(path) + 1; } /* * make command line. */ makecommand(comline, path_list, sb); /* * Compact format requires the output of parser sorted by the path. * * We assume that the output of gtags-parser is sorted by the path. * About the other parsers, it is not guaranteed, so we sort it * using external sort command (gnusort). */ if ((gtop->format & GTAGS_COMPACT) != 0 && locatestring(comline, "gtags-parser", MATCH_FIRST) == NULL && path_num > 1) strbuf_puts(sb, "| gnusort -k 3,3");#ifdef DEBUG if (flags & GTAGS_DEBUG) fprintf(stderr, "gtags_add() executing '%s'\n", strbuf_value(sb));#endif if (!(ip = popen(strbuf_value(sb), "r"))) die("cannot execute '%s'.", strbuf_value(sb)); while ((ctags_x = strbuf_fgets(ib, ip, STRBUF_NOCRLF)) != NULL) { char tag[MAXTOKEN], *p; strbuf_trim(ib);#ifdef DEBUG if (flags & GTAGS_DEBUG) formatcheck(ctags_x);#endif /* tag = $1 */ strlimcpy(tag, strmake(ctags_x, " \t"), sizeof(tag)); /* * extract method when class method definition. * * Ex: Class::method(...) * * key = 'method' * data = 'Class::method 103 ./class.cpp ...' */ p = tag; if (flags & GTAGS_EXTRACTMETHOD) { if ((p = locatestring(tag, ".", MATCH_LAST)) != NULL) p++; else if ((p = locatestring(tag, "::", MATCH_LAST)) != NULL) p += 2; else p = tag; } gtags_put(gtop, p, ctags_x); } if (pclose(ip) != 0) die("terminated abnormally."); strbuf_close(sb); strbuf_close(ib);}/* * gtags_delete: delete records belong to set of fid. * * i) gtop GTOP structure * i) deleteset bit array of fid */voidgtags_delete(gtop, deleteset) GTOP *gtop; IDSET *deleteset;{ const char *line, *p; SPLIT ptable; int fid, n; for (line = dbop_first(gtop->dbop, NULL, NULL, 0); line; line = dbop_next(gtop->dbop)) { /* * Extract the path, and if needed, convert it into the file id. */ n = split((char *)line, 4, &ptable); if (gtop->format & GTAGS_COMPACT) { if (n != 3) die("illegal compact format.\n"); p = ptable.part[1].start; } else { if (n < 4) { recover(&ptable); die("too small number of parts.\n'%s'", line); } p = ptable.part[2].start; } if (!(gtop->format & GTAGS_PATHINDEX)) { p = gpath_path2fid(p); if (p == NULL) die("GPATH is corrupted."); } fid = atoi(p); recover(&ptable); /* * If the file id exists in the deleteset, delete the record. */ if (idset_contains(deleteset, fid)) dbop_delete(gtop->dbop, NULL); }}/* * gtags_first: return first record * * i) gtop GTOP structure * i) pattern tag name * o may be regular expression * o may be NULL * i) flags GTOP_PREFIX prefix read * GTOP_KEY read key only * GTOP_NOSOURCE don't read source file(compact format) * GTOP_NOREGEX don't use regular expression. * GTOP_IGNORECASE ignore case distinction. * GTOP_BASICREGEX use basic regular expression. * r) record */const char *gtags_first(gtop, pattern, flags) GTOP *gtop; const char *pattern; int flags;{ int dbflags = 0; char prefix[IDENTLEN+1]; regex_t *preg = ® const char *key, *p, *line; int regflags = 0; gtop->flags = flags; if (flags & GTOP_PREFIX && pattern != NULL) dbflags |= DBOP_PREFIX; if (flags & GTOP_KEY) dbflags |= DBOP_KEY; if (!(flags & GTOP_BASICREGEX)) regflags |= REG_EXTENDED; if (flags & GTOP_IGNORECASE) regflags |= REG_ICASE; if (flags & GTOP_NOREGEX) { key = pattern; preg = NULL; } else if (pattern == NULL || !strcmp(pattern, ".*")) { key = NULL; preg = NULL; } else if (isregex(pattern) && regcomp(preg, pattern, regflags) == 0) { if (!(flags & GTOP_IGNORECASE) && *pattern == '^' && *(p = pattern + 1) && !isregexchar(*p)) { int i = 0; while (*p && !isregexchar(*p) && i < IDENTLEN) prefix[i++] = *p++; prefix[i] = '\0'; key = prefix; dbflags |= DBOP_PREFIX; } else { key = NULL; } } else { key = pattern; preg = NULL; } if ((line = dbop_first(gtop->dbop, key, preg, dbflags)) == NULL) return NULL; if (gtop->format == GTAGS_STANDARD || gtop->flags & GTOP_KEY) return line; if (gtop->format == GTAGS_PATHINDEX) return unpack_pathindex(line); /* * Compact format. */ gtop->line = (char *)line; /* gtop->line = $0 */ gtop->opened = 0; return genrecord(gtop);}/* * gtags_next: return followed record * * i) gtop GTOP structure * r) record * NULL end of tag */const char *gtags_next(gtop) GTOP *gtop;{ const char *line; /* * If it is standard format or only key. * Just return it. */ if (gtop->format == GTAGS_STANDARD || gtop->flags & GTOP_KEY) return dbop_next(gtop->dbop); /* * Pathindex format. */ if (gtop->format == GTAGS_PATHINDEX) { line = dbop_next(gtop->dbop); if (line == NULL) return NULL; return unpack_pathindex(line); } /* * gtop->format & GTAGS_COMPACT */ if ((line = genrecord(gtop)) != NULL) return line; /* * read next record. */ if ((line = dbop_next(gtop->dbop)) == NULL) return line; gtop->line = (char *)line; /* gtop->line = $0 */ gtop->opened = 0; return genrecord(gtop);}/* * gtags_close: close tag file * * i) gtop GTOP structure */voidgtags_close(gtop) GTOP *gtop;{ if (gtop->htab) { if (gtop->prev_path[0]) gtop_flush_htab(gtop); free(gtop->htab); } if (gtop->sb) strbuf_close(gtop->sb); if (gtop->ib) strbuf_close(gtop->ib); if (gtop->format & GTAGS_PATHINDEX || gtop->mode != GTAGS_READ) gpath_close(); dbop_close(gtop->dbop); free(gtop);}/* * unpack_pathindex: convert pathindex format into standard format. * * i) line tag line */static const char *unpack_pathindex(line) const char *line; /* virtually const */{ STATIC_STRBUF(output); SPLIT ptable; int n; const char *path; n = split((char *)line, 4, &ptable); if (n < 4) { recover(&ptable); die("illegal tag format.'%s'\n", line); } /* * extract path and convert into file number. */ path = gpath_fid2path(ptable.part[2].start); if (path == NULL) die("GPATH is corrupted.(fid '%s' not found)", ptable.part[2].start); recover(&ptable); /* * copy line with converting. */ strbuf_clear(output); strbuf_nputs(output, line, ptable.part[2].start - line); strbuf_puts(output, path); strbuf_puts(output, ptable.part[2].end); return strbuf_value(output);}/* * genrecord: generate original tag line from compact format. * * io) gtop GTOP structure * r) tag line */static const char *genrecord(gtop) GTOP *gtop;{ SPLIT ptable; static char output[MAXBUFLEN+1]; char path[MAXPATHLEN+1]; static char buf[1]; const char *buffer = buf; const char *lnop; int tagline; if (!gtop->opened) { int n; const char *p; gtop->opened = 1; n = split(gtop->line, 3, &ptable); if (n != 3) { recover(&ptable); die("illegal compact format. '%s'\n", gtop->line); } /* * gtop->tag = part[0] */ strlimcpy(gtop->tag, ptable.part[0].start, sizeof(gtop->tag)); /* * gtop->path = part[1] */ p = ptable.part[1].start; if (gtop->format & GTAGS_PATHINDEX) { const char *q; if ((q = gpath_fid2path(p)) == NULL) die("GPATH is corrupted.('%s' not found)", p); p = q; } strlimcpy(gtop->path, p, sizeof(gtop->path)); /* * gtop->lnop = part[2] */ gtop->lnop = ptable.part[2].start; if (gtop->root) snprintf(path, sizeof(path), "%s/%s", gtop->root, >op->path[2]); else snprintf(path, sizeof(path), "%s", >op->path[2]); if (!(gtop->flags & GTOP_NOSOURCE)) { if ((gtop->fp = fopen(path, "r")) != NULL) gtop->lno = 0; } recover(&ptable); } lnop = gtop->lnop; if (*lnop >= '0' && *lnop <= '9') { /* get line number */ for (tagline = 0; *lnop >= '0' && *lnop <= '9'; lnop++) tagline = tagline * 10 + *lnop - '0'; if (*lnop == ',') lnop++; gtop->lnop = lnop; if (gtop->fp) { if (gtop->lno == tagline) return output; while (gtop->lno < tagline) { if (!(buffer = strbuf_fgets(gtop->ib, gtop->fp, STRBUF_NOCRLF))) die("unexpected end of file. '%s'", gtop->path); strbuf_trim(gtop->ib); gtop->lno++; } } snprintf(output, sizeof(output), "%-16s %4d %-16s %s", gtop->tag, tagline, gtop->path, buffer); return output; } if (gtop->opened && gtop->fp != NULL) { gtop->opened = 0; fclose(gtop->fp); gtop->fp = NULL; } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -