/** * convert_put_using: convert @a path into relative or absolute and print. * * @param[in] cv #CONVERT structure * @param[in] tag tag name * @param[in] path path name * @param[in] lineno line number * @param[in] rest line image * @param[in] fid file id (only when @CODE{fid != NULL}) */ void convert_put_using(CONVERT *cv, const char *tag, const char *path, int lineno, const char *rest, const char *fid) { switch (cv->format) { case FORMAT_PATH: fputs(convert_pathname(cv, path), cv->op); break; case FORMAT_CTAGS: fputs(tag, cv->op); fputc('\t', cv->op); fputs(convert_pathname(cv, path), cv->op); fputc('\t', cv->op); fprintf(cv->op, "%d", lineno); break; case FORMAT_CTAGS_XID: if (fid == NULL) { fid = gpath_path2fid(path, NULL); if (fid == NULL) die("convert_put_using: unknown file. '%s'", path); } fputs(fid, cv->op); fputc(' ', cv->op); /* PASS THROUGH */ case FORMAT_CTAGS_X: fprintf(cv->op, "%-16s %4d %-16s %s", tag, lineno, convert_pathname(cv, path), rest); break; case FORMAT_CTAGS_MOD: fputs(convert_pathname(cv, path), cv->op); fputc('\t', cv->op); fprintf(cv->op, "%d", lineno); fputc('\t', cv->op); fputs(rest, cv->op); break; case FORMAT_GREP: fputs(convert_pathname(cv, path), cv->op); fputc(':', cv->op); fprintf(cv->op, "%d", lineno); fputc(':', cv->op); fputs(rest, cv->op); break; case FORMAT_CSCOPE: fputs(convert_pathname(cv, path), cv->op); fputc(' ', cv->op); fputs(tag, cv->op); fputc(' ', cv->op); fprintf(cv->op, "%d", lineno); fputc(' ', cv->op); for (; *rest && isspace(*rest); rest++) ; if (*rest) fputs(rest, cv->op); else fputs("<unknown>", cv->op); break; default: die("unknown format type."); } (void)fputc(newline, cv->op); }
/* * convertpath: convert source file into hypertext path. * * i) dbpath dbpath * i) htmldir HTML directory made by htags(1) * i) path source file path * o) sb string buffer * r) 0: normal, -1: error */ int convertpath(const char *dbpath, const char *htmldir, const char *path, STRBUF *sb) { static const char *suffix[] = {".html", ".htm"}; static const char *gz = ".gz"; int i, lim = sizeof(suffix)/sizeof(char *); const char *p; strbuf_reset(sb); strbuf_puts(sb, htmldir); strbuf_puts(sb, "/S/"); /* * new style. */ if (gpath_open(dbpath, 0) == 0) { int tag1 = strbuf_getlen(sb); p = gpath_path2fid(path, NULL); if (p == NULL) { gpath_close(); return -1; } gpath_close(); strbuf_puts(sb, p); for (i = 0; i < lim; i++) { int tag2 = strbuf_getlen(sb); strbuf_puts(sb, suffix[i]); if (test("f", strbuf_value(sb))) return 0; strbuf_puts(sb, gz); if (test("f", strbuf_value(sb))) return 0; strbuf_setlen(sb, tag2); } strbuf_setlen(sb, tag1); } /* * old style. */ for (p = path + 1; *p; p++) strbuf_putc(sb, (*p == '/') ? ' ' : *p); for (i = 0; i < lim; i++) { int tag = strbuf_getlen(sb); strbuf_puts(sb, suffix[i]); if (test("f", strbuf_value(sb))) return 0; strbuf_puts(sb, gz); if (test("f", strbuf_value(sb))) return 0; strbuf_setlen(sb, tag); } return -1; }
/** * 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); } }
/* * gpath_path2nfid: convert path into id * * i) path path name * o) type path type * GPATH_SOURCE: source file * GPATH_OTHER: other file * r) file id (integer) */ int gpath_path2nfid(const char *path, int *type) { const char *sfid = gpath_path2fid(path, type); return sfid == NULL ? 0 : atoi(sfid); }
int decide_tag_by_context(const char *tag, const char *file, int lineno) { STRBUF *sb = NULL; char path[MAXPATHLEN], s_fid[MAXFIDLEN]; const char *tagline, *p; DBOP *dbop; int db = GSYMS; int iscompline = 0; if (normalize(file, get_root_with_slash(), cwd, path, sizeof(path)) == NULL) die("'%s' is out of source tree.", file); /* * get file id */ if (gpath_open(dbpath, 0) < 0) die("GPATH not found."); if ((p = gpath_path2fid(path, NULL)) == NULL) die("path name in the context is not found."); strlimcpy(s_fid, p, sizeof(s_fid)); gpath_close(); /* * read btree records directly to avoid the overhead. */ dbop = dbop_open(makepath(dbpath, dbname(GTAGS), NULL), 0, 0, 0); if (dbop == NULL) die("cannot open GTAGS."); if (dbop_getoption(dbop, COMPLINEKEY)) iscompline = 1; tagline = dbop_first(dbop, tag, NULL, 0); if (tagline) { db = GTAGS; for (; tagline; tagline = dbop_next(dbop)) { /* * examine whether the definition record include the context. */ p = locatestring(tagline, s_fid, MATCH_AT_FIRST); if (p != NULL && *p == ' ') { for (p++; *p && *p != ' '; p++) ; if (*p++ != ' ' || !isdigit(*p)) die("Impossible! decide_tag_by_context(1)"); /* * Standard format n <blank> <image>$ * Compact format d,d,d,d$ */ if (!iscompline) { /* Standard format */ if (atoi(p) == lineno) { db = GRTAGS; goto finish; } } else { /* Compact format */ int n, cur, last = 0; do { if (!isdigit(*p)) die("Impossible! decide_tag_by_context(2)"); NEXT_NUMBER(p); cur = last + n; if (cur == lineno) { db = GRTAGS; goto finish; } last = cur; if (*p == '-') { if (!isdigit(*++p)) die("Impossible! decide_tag_by_context(3)"); NEXT_NUMBER(p); cur = last + n; if (lineno >= last && lineno <= cur) { db = GRTAGS; goto finish; } last = cur; } if (*p) { if (*p == ',') p++; else die("Impossible! decide_tag_by_context(4)"); } } while (*p); } } } } finish: dbop_close(dbop); if (db == GSYMS && getenv("GTAGSLIBPATH")) { char libdbpath[MAXPATHLEN]; char *libdir = NULL, *nextp = NULL; sb = strbuf_open(0); strbuf_puts(sb, getenv("GTAGSLIBPATH")); for (libdir = strbuf_value(sb); libdir; libdir = nextp) { if ((nextp = locatestring(libdir, PATHSEP, MATCH_FIRST)) != NULL) *nextp++ = 0; if (!gtagsexist(libdir, libdbpath, sizeof(libdbpath), 0)) continue; if (!strcmp(dbpath, libdbpath)) continue; dbop = dbop_open(makepath(libdbpath, dbname(GTAGS), NULL), 0, 0, 0); if (dbop == NULL) continue; tagline = dbop_first(dbop, tag, NULL, 0); dbop_close(dbop); if (tagline != NULL) { db = GTAGS; break; } } strbuf_close(sb); } return db; }
void parsefile(char *const *argv, const char *cwd, const char *root, const char *dbpath, int db) { int count = 0; int file_count = 0; STRBUF *sb = strbuf_open(0); char *langmap; const char *plugin_parser, *av; char path[MAXPATHLEN]; struct parsefile_data data; if (db == GRTAGS + GSYMS) data.target = TARGET_REF|TARGET_SYM; else data.target = 1 << db; data.extractmethod = getconfb("extractmethod"); if (getconfs("langmap", sb)) langmap = check_strdup(strbuf_value(sb)); else langmap = NULL; strbuf_reset(sb); if (getconfs("gtags_parser", sb)) plugin_parser = strbuf_value(sb); else plugin_parser = NULL; data.cv = convert_open(type, format, root, cwd, dbpath, stdout); if (gpath_open(dbpath, 0) < 0) die("GPATH not found."); if (data.target == TARGET_REF || data.target == TARGET_SYM) { data.dbop = dbop_open(makepath(dbpath, dbname(GTAGS), NULL), 0, 0, 0); if (data.dbop == NULL) die("%s not found.", dbname(GTAGS)); } else { data.dbop = NULL; } data.fid = NULL; parser_init(langmap, plugin_parser); if (langmap != NULL) free(langmap); 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_nop(); while ((av = args_read()) != NULL) { /* * convert the path into relative to the root directory of source tree. */ if (normalize(av, get_root_with_slash(), cwd, path, sizeof(path)) == NULL) if (!qflag) fprintf(stderr, "'%s' is out of source tree.\n", path + 2); /* * Memorize the file id of the path. This is used in put_syms(). */ { static char s_fid[MAXFIDLEN]; const char *p = gpath_path2fid(path, NULL); if (!p) { if (!qflag) fprintf(stderr, "'%s' not found in GPATH.\n", path + 2); continue; } strlimcpy(s_fid, p, sizeof(s_fid)); data.fid = s_fid; } if (!test("f", makepath(root, path, NULL))) { if (test("d", NULL)) { if (!qflag) fprintf(stderr, "'%s' is a directory.\n", av); } else { if (!qflag) fprintf(stderr, "'%s' not found.\n", av); } continue; } if (lflag && !locatestring(path, localprefix, MATCH_AT_FIRST)) continue; data.count = 0; parse_file(path, 0, put_syms, &data); count += data.count; file_count++; } args_close(); parser_exit(); /* * Settlement */ if (data.dbop != NULL) dbop_close(data.dbop); gpath_close(); convert_close(data.cv); strbuf_close(sb); if (vflag) { print_count(count); fprintf(stderr, " (no index used).\n"); } }
/* * createtags: create tags file * * i) dbpath dbpath directory * i) root root directory of source tree */ void createtags(const char *dbpath, const char *root) { STATISTICS_TIME *tim; STRBUF *sb = strbuf_open(0); struct put_func_data data; int openflags, flags, seqno; const char *path; tim = statistics_time_start("Time of creating %s and %s.", dbname(GTAGS), dbname(GRTAGS)); if (vflag) fprintf(stderr, "[%s] Creating '%s' and '%s'.\n", now(), dbname(GTAGS), dbname(GRTAGS)); openflags = cflag ? GTAGS_COMPACT : 0; data.gtop[GTAGS] = gtags_open(dbpath, root, GTAGS, GTAGS_CREATE, openflags); data.gtop[GTAGS]->flags = 0; if (extractmethod) data.gtop[GTAGS]->flags |= GTAGS_EXTRACTMETHOD; data.gtop[GRTAGS] = gtags_open(dbpath, root, GRTAGS, GTAGS_CREATE, openflags); data.gtop[GRTAGS]->flags = data.gtop[GTAGS]->flags; flags = 0; if (debug) flags |= PARSER_DEBUG; if (wflag) flags |= PARSER_WARNING; /* * Add tags to GTAGS and GRTAGS. */ if (file_list) find_open_filelist(file_list, root); else find_open(NULL); seqno = 0; while ((path = find_read()) != NULL) { if (*path == ' ') { path++; if (!test("b", path)) gpath_put(path, GPATH_OTHER); continue; } gpath_put(path, GPATH_SOURCE); data.fid = gpath_path2fid(path, NULL); if (data.fid == NULL) die("GPATH is corrupted.('%s' not found)", path); seqno++; if (vflag) fprintf(stderr, " [%d] extracting tags of %s\n", seqno, path + 2); if (debug) fprintf(stderr, "[%s]\n", path + 2); parse_file(path, flags, put_syms, &data); gtags_flush(data.gtop[GTAGS], data.fid); gtags_flush(data.gtop[GRTAGS], data.fid); } total = seqno; parser_exit(); find_close(); statistics_time_end(tim); tim = statistics_time_start("Time of flushing B-tree cache"); gtags_close(data.gtop[GTAGS]); gtags_close(data.gtop[GRTAGS]); statistics_time_end(tim); strbuf_reset(sb); if (getconfs("GTAGS_extra", sb)) { tim = statistics_time_start("Time of executing GTAGS_extra command"); if (system(strbuf_value(sb))) fprintf(stderr, "GTAGS_extra command failed: %s\n", strbuf_value(sb)); statistics_time_end(tim); } strbuf_reset(sb); if (getconfs("GRTAGS_extra", sb)) { tim = statistics_time_start("Time of executing GRTAGS_extra command"); if (system(strbuf_value(sb))) fprintf(stderr, "GRTAGS_extra command failed: %s\n", strbuf_value(sb)); statistics_time_end(tim); } strbuf_close(sb); }
/* * updatetags: update tag file. * * i) dbpath directory in which tag file exist * i) root root directory of source tree * i) deleteset bit array of fid of deleted or modified files * i) addlist \0 separated list of added or modified files */ void updatetags(const char *dbpath, const char *root, IDSET *deleteset, STRBUF *addlist) { struct put_func_data data; int seqno, flags; const char *path, *start, *end; if (vflag) fprintf(stderr, "[%s] Updating '%s' and '%s'.\n", now(), dbname(GTAGS), dbname(GRTAGS)); /* * Open tag files. */ data.gtop[GTAGS] = gtags_open(dbpath, root, GTAGS, GTAGS_MODIFY, 0); if (test("f", makepath(dbpath, dbname(GRTAGS), NULL))) { data.gtop[GRTAGS] = gtags_open(dbpath, root, GRTAGS, GTAGS_MODIFY, 0); } else { /* * If you set NULL to data.gtop[GRTAGS], parse_file() doesn't write to * GRTAGS. See put_syms(). */ data.gtop[GRTAGS] = NULL; } /* * Delete tags from GTAGS. */ if (!idset_empty(deleteset)) { if (vflag) { char fid[MAXFIDLEN]; int total = idset_count(deleteset); unsigned int id; seqno = 1; for (id = idset_first(deleteset); id != END_OF_ID; id = idset_next(deleteset)) { snprintf(fid, sizeof(fid), "%d", id); path = gpath_fid2path(fid, NULL); if (path == NULL) die("GPATH is corrupted."); fprintf(stderr, " [%d/%d] deleting tags of %s\n", seqno++, total, path + 2); } } gtags_delete(data.gtop[GTAGS], deleteset); if (data.gtop[GRTAGS] != NULL) gtags_delete(data.gtop[GRTAGS], deleteset); } /* * Set flags. */ data.gtop[GTAGS]->flags = 0; if (extractmethod) data.gtop[GTAGS]->flags |= GTAGS_EXTRACTMETHOD; data.gtop[GRTAGS]->flags = data.gtop[GTAGS]->flags; flags = 0; if (debug) flags |= PARSER_DEBUG; if (wflag) flags |= PARSER_WARNING; /* * Add tags to GTAGS and GRTAGS. */ start = strbuf_value(addlist); end = start + strbuf_getlen(addlist); seqno = 0; for (path = start; path < end; path += strlen(path) + 1) { gpath_put(path, GPATH_SOURCE); data.fid = gpath_path2fid(path, NULL); if (data.fid == NULL) die("GPATH is corrupted.('%s' not found)", path); if (vflag) fprintf(stderr, " [%d/%d] extracting tags of %s\n", ++seqno, total, path + 2); if (debug) fprintf(stderr, "[%s]\n", path + 2); parse_file(path, flags, put_syms, &data); gtags_flush(data.gtop[GTAGS], data.fid); if (data.gtop[GRTAGS] != NULL) gtags_flush(data.gtop[GRTAGS], data.fid); } parser_exit(); gtags_close(data.gtop[GTAGS]); if (data.gtop[GRTAGS] != NULL) gtags_close(data.gtop[GRTAGS]); }
/* * incremental: incremental update * * i) dbpath dbpath directory * i) root root directory of source tree * r) 0: not updated, 1: updated */ int incremental(const char *dbpath, const char *root) { STATISTICS_TIME *tim; struct stat statp; STRBUF *addlist = strbuf_open(0); STRBUF *deletelist = strbuf_open(0); STRBUF *addlist_other = strbuf_open(0); IDSET *deleteset, *findset; int updated = 0; const char *path; unsigned int id, limit; tim = statistics_time_start("Time of inspecting %s and %s.", dbname(GTAGS), dbname(GRTAGS)); if (vflag) { fprintf(stderr, " Tag found in '%s'.\n", dbpath); fprintf(stderr, " Incremental updating.\n"); } /* * get modified time of GTAGS. */ path = makepath(dbpath, dbname(GTAGS), NULL); if (gpath_open(dbpath, 0) < 0) die("GPATH not found."); /* * deleteset: * The list of the path name which should be deleted from GPATH. * findset: * The list of the path name which exists in the current project. * A project is limited by the --file option. */ deleteset = idset_open(gpath_nextkey()); findset = idset_open(gpath_nextkey()); total = 0; /* * Make add list and delete list for update. */ if (single_update) { int type; const char *fid = gpath_path2fid(single_update, &type); /* * The --single-update=file supports only updating. * If it is new file, this option is ignored, and the processing is * automatically switched to the normal procedure. */ if (fid == NULL) { if (vflag) fprintf(stderr, " --single-update option ignored, because '%s' is new file.\n", single_update); goto normal_update; } /* * If type != GPATH_SOURCE then we have nothing to do, and you will see * a message 'Global databases are up to date.'. */ if (type == GPATH_SOURCE) { strbuf_puts0(addlist, single_update); idset_add(deleteset, atoi(fid)); total++; } } else { normal_update: if (file_list) find_open_filelist(file_list, root); else find_open(NULL); while ((path = find_read()) != NULL) { const char *fid; int n_fid = 0; int other = 0; /* a blank at the head of path means 'NOT SOURCE'. */ if (*path == ' ') { if (test("b", ++path)) continue; other = 1; } if (stat(path, &statp) < 0) die("stat failed '%s'.", path); fid = gpath_path2fid(path, NULL); if (fid) { n_fid = atoi(fid); idset_add(findset, n_fid); } if (other) { if (fid == NULL) strbuf_puts0(addlist_other, path); } else { if (fid == NULL) { strbuf_puts0(addlist, path); total++; } else if (gpath_mtime(NULL, fid) < statp.st_mtime) { if (uflag) { printf("%s\n", path); } else { strbuf_puts0(addlist, path); total++; idset_add(deleteset, n_fid); } } } } find_close(); /* * make delete list. */ if (remove_lost) { limit = gpath_nextkey(); } else { limit = 0; } for (id = 1; id < limit; id++) { char fid[MAXFIDLEN]; int type; snprintf(fid, sizeof(fid), "%d", id); /* * This is a hole of GPATH. The hole increases if the deletion * and the addition are repeated. */ if ((path = gpath_fid2path(fid, &type)) == NULL) continue; /* * The file which does not exist in the findset is treated * assuming that it does not exist in the file system. */ if (type == GPATH_OTHER) { if (!idset_contains(findset, id) || !test("f", path) || test("b", path)) strbuf_puts0(deletelist, path); } else { if (!idset_contains(findset, id) || !test("f", path)) { strbuf_puts0(deletelist, path); idset_add(deleteset, id); } } } } gpath_close(); statistics_time_end(tim); /* * execute updating. */ if ((!idset_empty(deleteset) || strbuf_getlen(addlist) > 0) || (strbuf_getlen(deletelist) + strbuf_getlen(addlist_other) > 0)) { int db; updated = 1; tim = statistics_time_start("Time of updating %s and %s.", dbname(GTAGS), dbname(GRTAGS)); if (!idset_empty(deleteset) || strbuf_getlen(addlist) > 0) updatetags(dbpath, root, deleteset, addlist); if (strbuf_getlen(deletelist) + strbuf_getlen(addlist_other) > 0) { const char *start, *end, *p; if (vflag) fprintf(stderr, "[%s] Updating '%s'.\n", now(), dbname(GPATH)); gpath_open(dbpath, 2); if (strbuf_getlen(deletelist) > 0) { start = strbuf_value(deletelist); end = start + strbuf_getlen(deletelist); for (p = start; p < end; p += strlen(p) + 1) gpath_delete(p); } if (strbuf_getlen(addlist_other) > 0) { start = strbuf_value(addlist_other); end = start + strbuf_getlen(addlist_other); for (p = start; p < end; p += strlen(p) + 1) gpath_put(p, GPATH_OTHER); } gpath_close(); } /* * Update modification time of tag files * because they may have no definitions. */ for (db = GTAGS; db < GTAGLIM; db++) utime(makepath(dbpath, dbname(db), NULL), NULL); statistics_time_end(tim); } if (vflag) { if (updated) fprintf(stderr, " Global databases have been modified.\n"); else fprintf(stderr, " Global databases are up to date.\n"); fprintf(stderr, "[%s] Done.\n", now()); } strbuf_close(addlist); strbuf_close(deletelist); strbuf_close(addlist_other); idset_close(deleteset); idset_close(findset); return updated; }
/* * convert_put: convert path into relative or absolute and print. * * i) cv CONVERT structure * i) ctags_x tag record (ctags-x format) * * Note: This function is only called by gtags with the --path option. */ void convert_put(CONVERT *cv, const char *ctags_x) { char *tagnextp = NULL; int tagnextc = 0; char *tag = NULL, *lineno = NULL, *path, *rest = NULL; const char *fid = NULL; if (cv->format == FORMAT_PATH) die("convert_put: internal error."); /* Use convert_put_path() */ /* * parse tag line. * Don't use split() function not to destroy line image. */ { char *p = (char *)ctags_x; /* * tag name */ tag = p; for (; *p && !isspace(*p); p++) ; if (*p == '\0') die("illegal ctags-x format (line number not found)."); tagnextp = p; tagnextc = *p; *p++ = '\0'; /* skip blanks */ for (; *p && isspace(*p); p++) ; if (*p == '\0') die("illegal ctags-x format (line number not found)."); /* * line number */ lineno = p; for (; *p && !isspace(*p); p++) ; if (*p == '\0') die("illegal ctags-x format (path name not found)."); *p++ = '\0'; /* skip blanks */ for (; *p && isspace(*p); p++) ; if (*p == '\0') die("illegal ctags-x format (path name not found)."); /* * path name */ path = p; for (; *p && !isspace(*p); p++) ; if (*p == '\0') die("illegal ctags-x format (line image not found)."); *p++ = '\0'; rest = p; } /* * The path name has already been encoded. */ path = decode_path((unsigned char *)path); switch (cv->format) { case FORMAT_CTAGS: fputs(tag, cv->op); fputc('\t', cv->op); fputs(convert_pathname(cv, path), cv->op); fputc('\t', cv->op); fputs(lineno, cv->op); break; case FORMAT_CTAGS_XID: fid = gpath_path2fid(path, NULL); if (fid == NULL) die("convert_put: unknown file. '%s'", path); fputs(fid, cv->op); fputc(' ', cv->op); /* PASS THROUGH */ case FORMAT_CTAGS_X: /* * print until path name. */ *tagnextp = tagnextc; fputs(ctags_x, cv->op); fputc(' ', cv->op); /* * print path name and the rest. */ fputs(convert_pathname(cv, path), cv->op); fputc(' ', cv->op); fputs(rest, cv->op); break; case FORMAT_GREP: fputs(convert_pathname(cv, path), cv->op); fputc(':', cv->op); fputs(lineno, cv->op); fputc(':', cv->op); fputs(rest, cv->op); break; case FORMAT_CSCOPE: fputs(convert_pathname(cv, path), cv->op); fputc(' ', cv->op); fputs(tag, cv->op); fputc(' ', cv->op); fputs(lineno, cv->op); fputc(' ', cv->op); for (; *rest && isspace(*rest); rest++) ; fputs(rest, cv->op); break; default: die("unknown format type."); } (void)fputc(newline, cv->op); }