/** * completion_path: print candidate path list. * * @param[in] dbpath dbpath directory * @param[in] prefix prefix of primary key */ void completion_path(const char *dbpath, const char *prefix) { GFIND *gp; const char *localprefix = "./"; DBOP *dbop = dbop_open(NULL, 1, 0600, DBOP_RAW); const char *path; int prefix_length; int target = GPATH_SOURCE; int flags = (match_part == MATCH_PART_LAST) ? MATCH_LAST : MATCH_FIRST; if (dbop == NULL) die("cannot open temporary file."); if (prefix && *prefix == 0) /* In the case global -c '' */ prefix = NULL; prefix_length = (prefix == NULL) ? 0 : strlen(prefix); if (oflag) target = GPATH_BOTH; if (Oflag) target = GPATH_OTHER; if (iflag || getconfb("icase_path")) flags |= IGNORE_CASE; #if _WIN32 || __DJGPP__ else if (!Mflag) flags |= IGNORE_CASE; #endif gp = gfind_open(dbpath, localprefix, target); while ((path = gfind_read(gp)) != NULL) { path++; /* skip '.'*/ if (prefix == NULL) { dbop_put(dbop, path + 1, ""); } else if (match_part == MATCH_PART_ALL) { const char *p = path; while ((p = locatestring(p, prefix, flags)) != NULL) { dbop_put(dbop, p, ""); p += prefix_length; } } else { const char *p = locatestring(path, prefix, flags); if (p != NULL) { dbop_put(dbop, p, ""); } } } gfind_close(gp); for (path = dbop_first(dbop, NULL, NULL, DBOP_KEY); path != NULL; path = dbop_next(dbop)) { fputs(path, stdout); fputc('\n', stdout); } dbop_close(dbop); }
/** * dbop_put_tag: put a tag * * @param[in] dbop descripter * @param[in] name key * @param[in] data data */ void dbop_put_tag(DBOP *dbop, const char *name, const char *data) { #ifdef USE_SQLITE3 if (dbop->openflags & DBOP_SQLITE3) { int len; char fid[MAXFIDLEN], *q = fid; const char *p = data; /* extract fid */ while (*p && isdigit(*p)) *q++ = *p++; *q = '\0'; /* trim line */ len = strlen(data); if (data[len-1] == '\n') len--; if (data[len-1] == '\r') len--; if (data[len] == '\r' || data[len] == '\n') { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_nputs(sb, data, len); data = strbuf_value(sb); } dbop3_put(dbop, name, data, fid); return; } #endif dbop_put(dbop, name, data); return; }
/** * dbop_update: update record. * * @param[in] dbop descripter * @param[in] key key * @param[in] dat data */ void dbop_update(DBOP *dbop, const char *key, const char *dat) { #ifdef USE_SQLITE3 if (dbop->openflags & DBOP_SQLITE3) return dbop3_update(dbop, key, dat); #endif dbop_put(dbop, key, dat); }
/** * dbop_close: close db * * @param[in] dbop dbop descripter */ void dbop_close(DBOP *dbop) { DB *db = dbop->db; /* * Load sorted tag records and write them to the tag file. */ if (dbop->sortout != NULL) { STRBUF *sb = strbuf_open(256); char *p; /* * End of the former stage of sorted writing. * fclose() and sortout = NULL is important. * * fclose(): enables reading from sortin descriptor. * sortout = NULL: makes the following dbop_put write to the tag file directly. */ fclose(dbop->sortout); dbop->sortout = NULL; /* * The last stage of sorted writing. */ while (strbuf_fgets(sb, dbop->sortin, STRBUF_NOCRLF)) { for (p = strbuf_value(sb); *p && *p != SORT_SEP; p++) ; if (!*p) die("unexpected end of record."); *p++ = '\0'; dbop_put(dbop, strbuf_value(sb), p); } fclose(dbop->sortin); strbuf_close(sb); terminate_sort_process(dbop); } #ifdef USE_SQLITE3 if (dbop->openflags & DBOP_SQLITE3) { dbop3_close(dbop); return; } #endif #ifdef USE_DB185_COMPAT (void)db->close(db); #else /* * If dbname = NULL, omit writing to the disk in __bt_close(). */ (void)db->close(db, dbop->dbname[0] == '\0' ? 1 : 0); #endif if (dbop->dbname[0] != '\0') { if (dbop->perm && chmod(dbop->dbname, dbop->perm) < 0) die("chmod(2) failed."); } (void)free(dbop); }
/** * dbop_putoption: put option */ void dbop_putoption(DBOP *dbop, const char *key, const char *string) { char buf[1024]; if (string) snprintf(buf, sizeof(buf), "%s %s", key, string); else snprintf(buf, sizeof(buf), "%s", key); dbop_put(dbop, key, buf); }
/** * gtags_put_using: put tag record with packing. * * @param[in] gtop descripter of #GTOP * @param[in] tag tag name * @param[in] lno line number * @param[in] fid file id * @param[in] img line image */ void gtags_put_using(GTOP *gtop, const char *tag, int lno, const char *fid, const char *img) { const char *key; if (gtop->format & GTAGS_COMPACT) { struct sh_entry *entry; /* * Register each record into the pool. * * Pool image: * * tagname lno * ------------------------------ * "funcA" | 1| 3| 7|23|11| 2|... * "funcB" |34| 2| 5|66| 3|... * ... */ entry = strhash_assign(gtop->path_hash, tag, 1); if (entry->value == NULL) entry->value = varray_open(sizeof(int), 100); *(int *)varray_append((VARRAY *)entry->value) = lno; return; } /* * extract method when class method definition. * * Ex: Class::method(...) * * key = 'method' * data = 'Class::method 103 ./class.cpp ...' */ if (gtop->flags & GTAGS_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; } strbuf_reset(gtop->sb); strbuf_puts(gtop->sb, fid); strbuf_putc(gtop->sb, ' '); strbuf_puts(gtop->sb, (gtop->format & GTAGS_COMPNAME) ? compress(tag, key) : tag); strbuf_putc(gtop->sb, ' '); strbuf_putn(gtop->sb, lno); strbuf_putc(gtop->sb, ' '); strbuf_puts(gtop->sb, (gtop->format & GTAGS_COMPRESS) ? compress(img, key) : img); dbop_put(gtop->dbop, key, strbuf_value(gtop->sb)); }
/** * flush_pool: flush the pool and write is as compact format. * * @param[in] gtop descripter of #GTOP * @param[in] s_fid */ static void flush_pool(GTOP *gtop, const char *s_fid) { struct sh_entry *entry; int header_offset; int i, last; if (s_fid == NULL && (s_fid = gpath_path2fid(gtop->cur_path, NULL)) == NULL) die("GPATH is corrupted.('%s' not found)", gtop->cur_path); /* * Write records as compact format and free line number table * for each entry in the pool. */ for (entry = strhash_first(gtop->path_hash); entry; entry = strhash_next(gtop->path_hash)) { VARRAY *vb = (VARRAY *)entry->value; int *lno_array = varray_assign(vb, 0, 0); const char *key = entry->name; /* * extract method when class method definition. * * Ex: Class::method(...) * * key = 'method' * data = 'Class::method 103 ./class.cpp ...' */ if (gtop->flags & GTAGS_EXTRACTMETHOD) { if ((key = locatestring(entry->name, ".", MATCH_LAST)) != NULL) key++; else if ((key = locatestring(entry->name, "::", MATCH_LAST)) != NULL) key += 2; else key = entry->name; } /* Sort line number table */ qsort(lno_array, vb->length, sizeof(int), compare_lineno); strbuf_reset(gtop->sb); strbuf_puts(gtop->sb, s_fid); strbuf_putc(gtop->sb, ' '); if (gtop->format & GTAGS_COMPNAME) { strbuf_puts(gtop->sb, compress(entry->name, key)); } else { strbuf_puts(gtop->sb, entry->name); } strbuf_putc(gtop->sb, ' '); header_offset = strbuf_getlen(gtop->sb); /* * If GTAGS_COMPLINE flag is set, each line number is expressed as the * difference from the previous line number except for the head. * GTAGS_COMPLINE is set by default in format version 5. */ if (gtop->format & GTAGS_COMPLINE) { int cont = 0; last = 0; /* line 0 doesn't exist */ for (i = 0; i < vb->length; i++) { int n = lno_array[i]; if (n == last) continue; if (last > 0 && n == last + 1) { if (!cont) { /* * Don't use range expression at the head. */ if (strbuf_getlen(gtop->sb) == header_offset) strbuf_putn(gtop->sb, n); else cont = last; } } else { /* * Range expression. ex: 10-2 means 10 11 12 */ if (cont) { strbuf_putc(gtop->sb, '-'); strbuf_putn(gtop->sb, last - cont); cont = 0; } if (strbuf_getlen(gtop->sb) > header_offset) { strbuf_putc(gtop->sb, ','); strbuf_putn(gtop->sb, n - last); } else { strbuf_putn(gtop->sb, n); } if (strbuf_getlen(gtop->sb) > DBOP_PAGESIZE / 4) { dbop_put(gtop->dbop, key, strbuf_value(gtop->sb)); strbuf_setlen(gtop->sb, header_offset); } } last = n; } if (cont) { strbuf_putc(gtop->sb, '-'); strbuf_putn(gtop->sb, last - cont); } } else { /* * This code is to support older format (version 4). */ last = 0; /* line 0 doesn't exist */ for (i = 0; i < vb->length; i++) { int n = lno_array[i]; if (n == last) continue; if (strbuf_getlen(gtop->sb) > header_offset) strbuf_putc(gtop->sb, ','); strbuf_putn(gtop->sb, n); if (strbuf_getlen(gtop->sb) > DBOP_PAGESIZE / 4) { dbop_put(gtop->dbop, key, strbuf_value(gtop->sb)); strbuf_setlen(gtop->sb, header_offset); } last = n; } } if (strbuf_getlen(gtop->sb) > header_offset) { dbop_put(gtop->dbop, key, strbuf_value(gtop->sb)); } /* Free line number table */ varray_close(vb); } }