59 |
#include "global.h" |
#include "global.h" |
60 |
#include "const.h" |
#include "const.h" |
61 |
|
|
62 |
|
#if !defined(ARG_MAX) && defined(_SC_ARG_MAX) |
63 |
|
#define ARG_MAX sysconf(_SC_ARG_MAX) |
64 |
|
#endif |
65 |
|
|
66 |
static void usage(void); |
static void usage(void); |
67 |
static void help(void); |
static void help(void); |
68 |
void signal_setup(void); |
void signal_setup(void); |
70 |
int match(const char *, const char *); |
int match(const char *, const char *); |
71 |
int main(int, char **); |
int main(int, char **); |
72 |
int incremental(const char *, const char *); |
int incremental(const char *, const char *); |
73 |
void updatetags(const char *, const char *, const char *, int); |
void updatetags(const char *, const char *, const unsigned char *, int, STRBUF *, int); |
|
int incremental_optimized_for_speed(const char *, const char *); |
|
|
void updatetags_optimized_for_speed(const char *, const char *, const unsigned char *, int, STRBUF *, int); |
|
74 |
void createtags(const char *, const char *, int); |
void createtags(const char *, const char *, int); |
75 |
int printconf(const char *); |
int printconf(const char *); |
76 |
void set_base_directory(const char *, const char *); |
void set_base_directory(const char *, const char *); |
99 |
int other_files; |
int other_files; |
100 |
int debug; |
int debug; |
101 |
int secure_mode; |
int secure_mode; |
102 |
|
int noxargs; |
103 |
const char *extra_options; |
const char *extra_options; |
104 |
const char *info_string; |
const char *info_string; |
105 |
const char *sed_string; |
const char *sed_string; |
141 |
{"gtagsconf", required_argument, >agsconf, 1}, |
{"gtagsconf", required_argument, >agsconf, 1}, |
142 |
{"gtagslabel", required_argument, >agslabel, 1}, |
{"gtagslabel", required_argument, >agslabel, 1}, |
143 |
{"idutils", no_argument, NULL, 'I'}, |
{"idutils", no_argument, NULL, 'I'}, |
144 |
|
{"noxargs", no_argument, &noxargs, 1}, |
145 |
{"other", no_argument, &other_files, 1}, |
{"other", no_argument, &other_files, 1}, |
146 |
{"relative", no_argument, &do_relative, 1}, |
{"relative", no_argument, &do_relative, 1}, |
147 |
{"secure", no_argument, &secure_mode, 1}, |
{"secure", no_argument, &secure_mode, 1}, |
596 |
*/ |
*/ |
597 |
if (!test("f", makepath(dbpath, dbname(GPATH), NULL))) |
if (!test("f", makepath(dbpath, dbname(GPATH), NULL))) |
598 |
die("Old version tag file found. Please remake it."); |
die("Old version tag file found. Please remake it."); |
599 |
if (vflag) |
(void)incremental(dbpath, cwd); |
|
(void)incremental(dbpath, cwd); |
|
|
else |
|
|
(void)incremental_optimized_for_speed(dbpath, cwd); |
|
600 |
exit(0); |
exit(0); |
601 |
} |
} |
602 |
/* |
/* |
685 |
{ |
{ |
686 |
struct stat statp; |
struct stat statp; |
687 |
time_t gtags_mtime; |
time_t gtags_mtime; |
688 |
STRBUF *addlist = strbuf_open(0); |
STRBUF *extractlist = strbuf_open(0); |
|
STRBUF *updatelist = strbuf_open(0); |
|
689 |
STRBUF *deletelist = strbuf_open(0); |
STRBUF *deletelist = strbuf_open(0); |
690 |
|
unsigned char *fidset; |
691 |
|
int max_fid = 0; |
692 |
int updated = 0; |
int updated = 0; |
693 |
const char *path; |
const char *path; |
694 |
|
|
706 |
|
|
707 |
if (gpath_open(dbpath, 0) < 0) |
if (gpath_open(dbpath, 0) < 0) |
708 |
die("GPATH not found."); |
die("GPATH not found."); |
|
/* |
|
|
* make add list and update list. |
|
|
*/ |
|
|
for (find_open(NULL); (path = find_read()) != NULL; ) { |
|
|
/* a blank at the head of path means 'NOT SOURCE'. */ |
|
|
if (*path == ' ') |
|
|
continue; |
|
|
if (stat(path, &statp) < 0) |
|
|
die("stat failed '%s'.", path); |
|
|
if (!gpath_path2fid(path)) |
|
|
strbuf_puts0(addlist, path); |
|
|
else if (gtags_mtime < statp.st_mtime) |
|
|
strbuf_puts0(updatelist, path); |
|
|
} |
|
|
find_close(); |
|
|
/* |
|
|
* make delete list. |
|
|
*/ |
|
|
{ |
|
|
char fid[32]; |
|
|
int i, limit = gpath_nextkey(); |
|
|
|
|
|
for (i = 1; i < limit; i++) { |
|
|
snprintf(fid, sizeof(fid), "%d", i); |
|
|
if ((path = gpath_fid2path(fid)) == NULL) |
|
|
continue; |
|
|
if (!test("f", path)) |
|
|
strbuf_puts0(deletelist, path); |
|
|
} |
|
|
} |
|
|
gpath_close(); |
|
|
if (strbuf_getlen(addlist) + strbuf_getlen(deletelist) + strbuf_getlen(updatelist)) |
|
|
updated = 1; |
|
|
/* |
|
|
* execute updating. |
|
|
*/ |
|
|
signal_setup(); |
|
|
if (strbuf_getlen(updatelist) > 0) { |
|
|
const char *start = strbuf_value(updatelist); |
|
|
const char *end = start + strbuf_getlen(updatelist); |
|
|
const char *p; |
|
|
|
|
|
for (p = start; p < end; p += strlen(p) + 1) { |
|
|
updatetags(dbpath, root, p, 0); |
|
|
if (exitflag) |
|
|
exit(1); |
|
|
} |
|
|
updated = 1; |
|
|
} |
|
|
if (strbuf_getlen(addlist) > 0) { |
|
|
const char *start = strbuf_value(addlist); |
|
|
const char *end = start + strbuf_getlen(addlist); |
|
|
const char *p; |
|
|
|
|
|
for (p = start; p < end; p += strlen(p) + 1) { |
|
|
updatetags(dbpath, root, p, 1); |
|
|
if (exitflag) |
|
|
exit(1); |
|
|
} |
|
|
updated = 1; |
|
|
} |
|
|
if (strbuf_getlen(deletelist) > 0) { |
|
|
const char *start = strbuf_value(deletelist); |
|
|
const char *end = start + strbuf_getlen(deletelist); |
|
|
const char *p; |
|
|
|
|
|
for (p = start; p < end; p += strlen(p) + 1) { |
|
|
updatetags(dbpath, root, p, 2); |
|
|
if (exitflag) |
|
|
exit(1); |
|
|
} |
|
|
|
|
|
gpath_open(dbpath, 2); |
|
|
for (p = start; p < end; p += strlen(p) + 1) { |
|
|
if (exitflag) |
|
|
break; |
|
|
gpath_delete(p); |
|
|
} |
|
|
gpath_close(); |
|
|
updated = 1; |
|
|
} |
|
|
if (exitflag) |
|
|
exit(1); |
|
|
if (updated) { |
|
|
int db; |
|
|
/* |
|
|
* Update modification time of tag files |
|
|
* because they may have no definitions. |
|
|
*/ |
|
|
for (db = GTAGS; db < GTAGLIM; db++) |
|
|
#ifdef HAVE_UTIMES |
|
|
utimes(makepath(dbpath, dbname(db), NULL), NULL); |
|
|
#else |
|
|
utime(makepath(dbpath, dbname(db), NULL), NULL); |
|
|
#endif /* HAVE_UTIMES */ |
|
|
} |
|
|
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(updatelist); |
|
|
return updated; |
|
|
} |
|
|
/* |
|
|
* updatetags: update tag file. |
|
|
* |
|
|
* i) dbpath directory in which tag file exist |
|
|
* i) root root directory of source tree |
|
|
* i) path path which should be updated |
|
|
* i) type 0:update, 1:add, 2:delete |
|
|
*/ |
|
|
void |
|
|
updatetags(dbpath, root, path, type) |
|
|
const char *dbpath; |
|
|
const char *root; |
|
|
const char *path; |
|
|
int type; |
|
|
{ |
|
|
GTOP *gtop; |
|
|
STRBUF *sb = strbuf_open(0); |
|
|
int db; |
|
|
const char *msg = NULL; |
|
|
|
|
|
switch (type) { |
|
|
case 0: msg = "Updating"; break; |
|
|
case 1: msg = "Adding"; break; |
|
|
case 2: msg = "Deleting"; break; |
|
|
} |
|
|
if (vflag) |
|
|
fprintf(stderr, " %s tags of %s ...", msg, path + 2); |
|
|
for (db = GTAGS; db < GTAGLIM; db++) { |
|
|
int gflags = 0; |
|
|
|
|
|
if (exitflag) |
|
|
break; |
|
|
/* |
|
|
* GTAGS needed at least. |
|
|
*/ |
|
|
if ((db == GRTAGS || db == GSYMS) && !test("f", makepath(dbpath, dbname(db), NULL))) |
|
|
continue; |
|
|
/* |
|
|
* GTAGS needed to make GRTAGS. |
|
|
*/ |
|
|
if (db == GRTAGS && !test("f", makepath(dbpath, dbname(GTAGS), NULL))) |
|
|
die("GTAGS needed to create GRTAGS."); |
|
|
if (vflag) |
|
|
fprintf(stderr, "%s", dbname(db)); |
|
|
/* |
|
|
* get tag command. |
|
|
*/ |
|
|
strbuf_reset(sb); |
|
|
if (!getconfs(dbname(db), sb)) |
|
|
die("cannot get tag command. (%s)", dbname(db)); |
|
|
gtop = gtags_open(dbpath, root, db, GTAGS_MODIFY, 0); |
|
|
if (type != 1) |
|
|
gtags_delete(gtop, path); |
|
|
if (vflag) |
|
|
fprintf(stderr, ".."); |
|
|
if (type != 2) { |
|
|
if (extractmethod) |
|
|
gflags |= GTAGS_EXTRACTMETHOD; |
|
|
if (debug) |
|
|
gflags |= GTAGS_DEBUG; |
|
|
gtags_add(gtop, strbuf_value(sb), path, gflags); |
|
|
} |
|
|
gtags_close(gtop); |
|
|
} |
|
|
strbuf_close(sb); |
|
|
if (exitflag) |
|
|
return; |
|
|
if (vflag) |
|
|
fprintf(stderr, " Done.\n"); |
|
|
} |
|
|
/* |
|
|
* incremental_optimized_for_speed: incremental update |
|
|
* |
|
|
* i) dbpath dbpath directory |
|
|
* i) root root directory of source tree |
|
|
* r) 0: not updated, 1: updated |
|
|
*/ |
|
|
int |
|
|
incremental_optimized_for_speed(dbpath, root) |
|
|
const char *dbpath; |
|
|
const char *root; |
|
|
{ |
|
|
struct stat statp; |
|
|
time_t gtags_mtime; |
|
|
STRBUF *extractlist = strbuf_open(0); |
|
|
STRBUF *deletelist = strbuf_open(0); |
|
|
unsigned char *fidset; |
|
|
int max_fid = 0; |
|
|
int updated = 0; |
|
|
const char *path; |
|
|
|
|
|
/* |
|
|
* get modified time of GTAGS. |
|
|
*/ |
|
|
path = makepath(dbpath, dbname(GTAGS), NULL); |
|
|
if (stat(path, &statp) < 0) |
|
|
die("stat failed '%s'.", path); |
|
|
gtags_mtime = statp.st_mtime; |
|
|
|
|
|
if (gpath_open(dbpath, 0) < 0) |
|
|
die("GPATH not found."); |
|
709 |
fidset = (unsigned char *)calloc((gpath_nextkey() + CHAR_BIT - 1) / CHAR_BIT, 1); |
fidset = (unsigned char *)calloc((gpath_nextkey() + CHAR_BIT - 1) / CHAR_BIT, 1); |
710 |
if (fidset == NULL) |
if (fidset == NULL) |
711 |
die("short of memory."); |
die("short of memory."); |
768 |
if ((db == GRTAGS || db == GSYMS) |
if ((db == GRTAGS || db == GSYMS) |
769 |
&& !test("f", makepath(dbpath, dbname(db), NULL))) |
&& !test("f", makepath(dbpath, dbname(db), NULL))) |
770 |
continue; |
continue; |
771 |
updatetags_optimized_for_speed(dbpath, root, fidset, max_fid, extractlist, db); |
if (vflag) |
772 |
|
fprintf(stderr, "[%s] Updating '%s'.\n", now(), dbname(db)); |
773 |
|
updatetags(dbpath, root, fidset, max_fid, extractlist, db); |
774 |
if (exitflag) |
if (exitflag) |
775 |
exit(1); |
exit(1); |
776 |
} |
} |
803 |
utime(makepath(dbpath, dbname(db), NULL), NULL); |
utime(makepath(dbpath, dbname(db), NULL), NULL); |
804 |
#endif /* HAVE_UTIMES */ |
#endif /* HAVE_UTIMES */ |
805 |
} |
} |
806 |
|
if (vflag) { |
807 |
|
if (updated) |
808 |
|
fprintf(stderr, " Global databases have been modified.\n"); |
809 |
|
else |
810 |
|
fprintf(stderr, " Global databases are up to date.\n"); |
811 |
|
fprintf(stderr, "[%s] Done.\n", now()); |
812 |
|
} |
813 |
strbuf_close(extractlist); |
strbuf_close(extractlist); |
814 |
strbuf_close(deletelist); |
strbuf_close(deletelist); |
815 |
free(fidset); |
free(fidset); |
816 |
return updated; |
return updated; |
817 |
} |
} |
818 |
/* |
/* |
819 |
* updatetags_optimized_for_speed: update tag file. |
* updatetags: update tag file. |
820 |
* |
* |
821 |
* i) dbpath directory in which tag file exist |
* i) dbpath directory in which tag file exist |
822 |
* i) root root directory of source tree |
* i) root root directory of source tree |
826 |
* i) db GTAGS, GRTAGS, GSYMS |
* i) db GTAGS, GRTAGS, GSYMS |
827 |
*/ |
*/ |
828 |
void |
void |
829 |
updatetags_optimized_for_speed(dbpath, root, fidset, max_fid, extractlist, db) |
updatetags(dbpath, root, fidset, max_fid, extractlist, db) |
830 |
const char *dbpath; |
const char *dbpath; |
831 |
const char *root; |
const char *root; |
832 |
const unsigned char *fidset; |
const unsigned char *fidset; |
835 |
int db; |
int db; |
836 |
{ |
{ |
837 |
GTOP *gtop; |
GTOP *gtop; |
|
const char *path; |
|
838 |
const char *comline; |
const char *comline; |
839 |
const char *end; |
const char *end; |
840 |
STRBUF *sb = strbuf_open(0); |
STRBUF *sb = strbuf_open(0); |
841 |
int gflags; |
int gflags; |
842 |
|
STATIC_STRBUF(path_list); |
843 |
|
int path_list_max; |
844 |
|
int savec; |
845 |
|
int pathlen; |
846 |
|
|
847 |
/* |
/* |
848 |
* GTAGS needed to make GRTAGS. |
* GTAGS needed to make GRTAGS. |
857 |
die("cannot get tag command. (%s)", dbname(db)); |
die("cannot get tag command. (%s)", dbname(db)); |
858 |
comline = strbuf_value(sb); |
comline = strbuf_value(sb); |
859 |
|
|
860 |
|
/* |
861 |
|
* determine the maximum length of the list of paths. |
862 |
|
*/ |
863 |
|
#ifdef ARG_MAX |
864 |
|
if (noxargs) { |
865 |
|
/* force processing files individually. */ |
866 |
|
path_list_max = 0; |
867 |
|
} else { |
868 |
|
path_list_max = ARG_MAX; |
869 |
|
path_list_max -= 2048; |
870 |
|
if (path_list_max > 20 * 1024) |
871 |
|
path_list_max = 20 * 1024; |
872 |
|
path_list_max -= env_size(); |
873 |
|
path_list_max -= strbuf_getlen(sb); |
874 |
|
path_list_max -= 40; |
875 |
|
if (path_list_max < 0) |
876 |
|
path_list_max = 0; |
877 |
|
} |
878 |
|
#else |
879 |
|
path_list_max = 0; |
880 |
|
#endif |
881 |
|
|
882 |
gtop = gtags_open(dbpath, root, db, GTAGS_MODIFY, 0); |
gtop = gtags_open(dbpath, root, db, GTAGS_MODIFY, 0); |
883 |
|
if (gtop->format & GTAGS_COMPACT) { |
884 |
|
/* force processing files individually. */ |
885 |
|
path_list_max = 0; |
886 |
|
} |
887 |
|
|
888 |
|
if (vflag) { |
889 |
|
char fid[32]; |
890 |
|
const char *path; |
891 |
|
int i; |
892 |
|
|
893 |
|
for (i = 0; i < max_fid; i++) { |
894 |
|
if (fidset[i / CHAR_BIT] & (1 << (i % CHAR_BIT))) { |
895 |
|
snprintf(fid, sizeof(fid), "%d", i); |
896 |
|
path = gpath_fid2path(fid); |
897 |
|
if (path == NULL) |
898 |
|
die("GPATH is corrupted."); |
899 |
|
fprintf(stderr, " deleting tags of %s\n", path + 2); |
900 |
|
} |
901 |
|
} |
902 |
|
} |
903 |
if (max_fid > 0) |
if (max_fid > 0) |
904 |
gtags_delete_by_fidset(gtop, fidset, max_fid); |
gtags_delete_by_fidset(gtop, fidset, max_fid); |
905 |
|
|
908 |
gflags |= GTAGS_EXTRACTMETHOD; |
gflags |= GTAGS_EXTRACTMETHOD; |
909 |
if (debug) |
if (debug) |
910 |
gflags |= GTAGS_DEBUG; |
gflags |= GTAGS_DEBUG; |
911 |
path = strbuf_value(extractlist); |
path_list->sbuf = path_list->curp = strbuf_value(extractlist); |
912 |
end = path + strbuf_getlen(extractlist); |
end = path_list->curp + strbuf_getlen(extractlist); |
913 |
while (path < end) { |
while (path_list->curp < end) { |
914 |
gtags_add(gtop, comline, path, gflags); |
if (vflag) |
915 |
|
fprintf(stderr, " adding tags of %s\n", path_list->curp + 2); |
916 |
|
pathlen = strlen(path_list->curp); |
917 |
|
if (strbuf_getlen(path_list) |
918 |
|
&& strbuf_getlen(path_list) + pathlen > path_list_max) { |
919 |
|
savec = *path_list->curp; |
920 |
|
gtags_add(gtop, comline, path_list, gflags); |
921 |
|
*path_list->curp = savec; |
922 |
|
path_list->sbuf = path_list->curp; |
923 |
|
} |
924 |
if (exitflag) |
if (exitflag) |
925 |
break; |
break; |
926 |
path += strlen(path) + 1; |
path_list->curp += pathlen + 1; |
927 |
} |
} |
928 |
|
if (strbuf_getlen(path_list)) |
929 |
|
gtags_add(gtop, comline, path_list, gflags); |
930 |
|
|
931 |
gtags_close(gtop); |
gtags_close(gtop); |
932 |
strbuf_close(sb); |
strbuf_close(sb); |
946 |
{ |
{ |
947 |
const char *path; |
const char *path; |
948 |
GTOP *gtop; |
GTOP *gtop; |
949 |
int flags; |
int flags, gflags; |
950 |
const char *comline; |
const char *comline; |
951 |
STRBUF *sb = strbuf_open(0); |
STRBUF *sb = strbuf_open(0); |
952 |
int count = 0; |
int count = 0; |
953 |
|
STRBUF *path_list = strbuf_open(MAXPATHLEN); |
954 |
|
int path_list_max; |
955 |
|
|
956 |
/* |
/* |
957 |
* get tag command. |
* get tag command. |
964 |
*/ |
*/ |
965 |
if (db == GRTAGS && !test("f", makepath(dbpath, dbname(GTAGS), NULL))) |
if (db == GRTAGS && !test("f", makepath(dbpath, dbname(GTAGS), NULL))) |
966 |
die("GTAGS needed to create GRTAGS."); |
die("GTAGS needed to create GRTAGS."); |
967 |
|
|
968 |
|
/* |
969 |
|
* determine the maximum length of the list of paths. |
970 |
|
*/ |
971 |
|
#ifdef ARG_MAX |
972 |
|
if (noxargs) { |
973 |
|
/* force processing files individually. */ |
974 |
|
path_list_max = 0; |
975 |
|
} else { |
976 |
|
path_list_max = ARG_MAX; |
977 |
|
path_list_max -= 2048; |
978 |
|
if (path_list_max > 20 * 1024) |
979 |
|
path_list_max = 20 * 1024; |
980 |
|
path_list_max -= env_size(); |
981 |
|
path_list_max -= strbuf_getlen(sb); |
982 |
|
path_list_max -= 40; |
983 |
|
if (path_list_max < 0) |
984 |
|
path_list_max = 0; |
985 |
|
} |
986 |
|
#else |
987 |
|
path_list_max = 0; |
988 |
|
#endif |
989 |
|
|
990 |
flags = 0; |
flags = 0; |
991 |
/* |
/* |
992 |
* Compact format: |
* Compact format: |
1004 |
if (vflag > 1) |
if (vflag > 1) |
1005 |
fprintf(stderr, " using tag command '%s <path>'.\n", comline); |
fprintf(stderr, " using tag command '%s <path>'.\n", comline); |
1006 |
gtop = gtags_open(dbpath, root, db, GTAGS_CREATE, flags); |
gtop = gtags_open(dbpath, root, db, GTAGS_CREATE, flags); |
1007 |
|
if (gtop->format & GTAGS_COMPACT) { |
1008 |
|
/* force processing files individually. */ |
1009 |
|
path_list_max = 0; |
1010 |
|
} |
1011 |
|
gflags = 0; |
1012 |
|
if (extractmethod) |
1013 |
|
gflags |= GTAGS_EXTRACTMETHOD; |
1014 |
|
if (debug) |
1015 |
|
gflags |= GTAGS_DEBUG; |
1016 |
for (find_open(NULL); (path = find_read()) != NULL; ) { |
for (find_open(NULL); (path = find_read()) != NULL; ) { |
1017 |
int gflags = 0; |
int skip = 0; |
|
int skip = 0; |
|
1018 |
|
|
1019 |
/* a blank at the head of path means 'NOT SOURCE'. */ |
/* a blank at the head of path means 'NOT SOURCE'. */ |
1020 |
if (*path == ' ') |
if (*path == ' ') |
1042 |
} |
} |
1043 |
if (skip) |
if (skip) |
1044 |
continue; |
continue; |
1045 |
if (extractmethod) |
if (strbuf_getlen(path_list) |
1046 |
gflags |= GTAGS_EXTRACTMETHOD; |
&& strbuf_getlen(path_list) + strlen(path) > path_list_max) { |
1047 |
if (debug) |
gtags_add(gtop, comline, path_list, gflags); |
1048 |
gflags |= GTAGS_DEBUG; |
strbuf_reset(path_list); |
1049 |
gtags_add(gtop, comline, path, gflags); |
} |
1050 |
|
strbuf_puts0(path_list, path); |
1051 |
} |
} |
1052 |
|
if (strbuf_getlen(path_list)) |
1053 |
|
gtags_add(gtop, comline, path_list, gflags); |
1054 |
total = count; /* save total count */ |
total = count; /* save total count */ |
1055 |
find_close(); |
find_close(); |
1056 |
gtags_close(gtop); |
gtags_close(gtop); |
1057 |
strbuf_close(sb); |
strbuf_close(sb); |
1058 |
|
strbuf_close(path_list); |
1059 |
} |
} |
1060 |
/* |
/* |
1061 |
* printconf: print configuration data. |
* printconf: print configuration data. |