/** * load configuration variables. */ static void configuration(void) { STRBUF *sb = strbuf_open(0); /* * Config variables. */ strbuf_reset(sb); if (!getconfs("datadir", sb)) die("cannot get datadir directory name."); strlimcpy(datadir, strbuf_value(sb), sizeof(datadir)); strbuf_reset(sb); if (!getconfs("localstatedir", sb)) die("cannot get localstatedir directory name."); strlimcpy(localstatedir, strbuf_value(sb), sizeof(localstatedir)); strbuf_reset(sb); if (getconfs("prolog_script", sb)) prolog_script = check_strdup(strbuf_value(sb)); strbuf_reset(sb); if (getconfs("epilog_script", sb)) epilog_script = check_strdup(strbuf_value(sb)); if (getconfb("colorize_warned_line")) colorize_warned_line = 1; strbuf_reset(sb); if (getconfs("include_file_suffixes", sb)) include_file_suffixes = check_strdup(strbuf_value(sb)); strbuf_reset(sb); if (getconfs("langmap", sb)) langmap = check_strdup(strbuf_value(sb)); strbuf_close(sb); }
void setenv_from_config(void) { int i, lim = sizeof(envname) / sizeof(char *); STRBUF *sb = strbuf_open(0); for (i = 0; i < lim; i++) { if (getenv(envname[i]) == NULL) { strbuf_reset(sb); if (getconfs(envname[i], sb)) set_env(envname[i], strbuf_value(sb)); else if (getconfb(envname[i])) set_env(envname[i], ""); } } /* * For upper compatibility. * htags_options is deprecated. */ if (getenv("HTAGS_OPTIONS") == NULL) { strbuf_reset(sb); if (getconfs("htags_options", sb)) set_env("HTAGS_OPTIONS", strbuf_value(sb)); } strbuf_close(sb); }
/* * prepare_source: preparing regular expression. * * i) flags flags for regcomp. * go) suff regular expression for source files. */ static void prepare_source(void) { STRBUF *sb = strbuf_open(0); char *sufflist = NULL; int flags = REG_EXTENDED; /* * load icase_path option. */ if (getconfb("icase_path")) flags |= REG_ICASE; #if defined(_WIN32) || defined(__DJGPP__) flags |= REG_ICASE; #endif strbuf_reset(sb); if (!getconfs("suffixes", sb)) die("cannot get suffixes data."); sufflist = check_strdup(strbuf_value(sb)); trim(sufflist); { const char *suffp; int retval; strbuf_reset(sb); strbuf_puts(sb, "\\.("); /* ) */ for (suffp = sufflist; suffp; ) { const char *p; for (p = suffp; *p && *p != ','; p++) { if (!isalnum((unsigned char)*p)) strbuf_putc(sb, '\\'); strbuf_putc(sb, *p); } if (!*p) break; assert(*p == ','); strbuf_putc(sb, '|'); suffp = ++p; } strbuf_puts(sb, ")$"); /* * compile regular expression. */ retval = regcomp(suff, strbuf_value(sb), flags); #ifdef DEBUG if (debug) fprintf(stderr, "find regex: %s\n", strbuf_value(sb)); #endif if (retval != 0) die("cannot compile regular expression."); } strbuf_close(sb); if (sufflist) free(sufflist); }
/** * 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); }
/** * load configuration variables. */ static void configuration() { STRBUF *sb = strbuf_open(0); if (getconfb("extractmethod")) extractmethod = 1; strbuf_reset(sb); if (getconfs("langmap", sb)) langmap = check_strdup(strbuf_value(sb)); strbuf_reset(sb); if (getconfs("gtags_parser", sb)) gtags_parser = check_strdup(strbuf_value(sb)); strbuf_close(sb); }
/* * printconf: print configuration data. * * i) name label of config data * r) exit code */ int printconf(const char *name) { int num; int exist = 1; if (getconfn(name, &num)) fprintf(stdout, "%d\n", num); else if (getconfb(name)) fprintf(stdout, "1\n"); else { STRBUF *sb = strbuf_open(0); if (getconfs(name, sb)) fprintf(stdout, "%s\n", strbuf_value(sb)); else exist = 0; strbuf_close(sb); } return exist; }
/* * prepare_skip: prepare skipping files. * * go) skip regular expression for skip files. * go) listarry[] skip list. * go) list_count count of skip list. */ static void prepare_skip(void) { char *skiplist; STRBUF *reg = strbuf_open(0); int reg_count = 0; char *p, *q; int flags = REG_EXTENDED|REG_NEWLINE; /* * load icase_path option. */ if (getconfb("icase_path")) flags |= REG_ICASE; #if defined(_WIN32) || defined(__DJGPP__) flags |= REG_ICASE; #endif /* * initialize common data. */ if (!list) list = strbuf_open(0); else strbuf_reset(list); list_count = 0; if (listarray) (void)free(listarray); listarray = (char **)0; /* * load skip data. */ if (!getconfs("skip", reg)) { strbuf_close(reg); return; } skiplist = check_strdup(strbuf_value(reg)); trim(skiplist); strbuf_reset(reg); /* * construct regular expression. */ strbuf_putc(reg, '('); /* ) */ /* skip files which start with '.' e.g. .cvsignore */ strbuf_puts(reg, "/\\.[^/]+$|"); strbuf_puts(reg, "/\\.[^/]+/|"); for (p = skiplist; p; ) { char *skipf = p; if ((p = locatestring(p, ",", MATCH_FIRST)) != NULL) *p++ = 0; if (*skipf == '/') { list_count++; strbuf_puts0(list, skipf); } else { reg_count++; strbuf_putc(reg, '/'); for (q = skipf; *q; q++) { if (isregexchar(*q)) strbuf_putc(reg, '\\'); strbuf_putc(reg, *q); } if (*(q - 1) != '/') strbuf_putc(reg, '$'); if (p) strbuf_putc(reg, '|'); } } strbuf_unputc(reg, '|'); strbuf_putc(reg, ')'); if (reg_count > 0) { int retval; /* * compile regular expression. */ skip = &skip_area; retval = regcomp(skip, strbuf_value(reg), flags); #ifdef DEBUG if (debug) fprintf(stderr, "skip regex: %s\n", strbuf_value(reg)); #endif if (retval != 0) die("cannot compile regular expression."); } else { skip = (regex_t *)0; } if (list_count > 0) { int i; listarray = (char **)check_malloc(sizeof(char *) * list_count); p = strbuf_value(list); #ifdef DEBUG if (debug) fprintf(stderr, "skip list: "); #endif for (i = 0; i < list_count; i++) { #ifdef DEBUG if (debug) { fprintf(stderr, "%s", p); if (i + 1 < list_count) fputc(',', stderr); } #endif listarray[i] = p; p += strlen(p) + 1; } #ifdef DEBUG if (debug) fputc('\n', stderr); #endif } strbuf_close(reg); free(skiplist); }
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"); } }
/* * 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)); } }
int main(int argc, char **argv) { char dbpath[MAXPATHLEN]; char cwd[MAXPATHLEN]; STRBUF *sb = strbuf_open(0); int optchar; int option_index = 0; STATISTICS_TIME *tim; while ((optchar = getopt_long(argc, argv, "cd:f:iuIn:oOqvwse", long_options, &option_index)) != EOF) { switch (optchar) { case 0: /* already flags set */ break; case OPT_CONFIG: show_config = 1; if (optarg) config_name = optarg; break; case OPT_GTAGSCONF: gtagsconf = optarg; break; case OPT_GTAGSLABEL: gtagslabel = optarg; break; case OPT_PATH: do_path = 1; if (!strcmp("absolute", optarg)) convert_type = PATH_ABSOLUTE; else if (!strcmp("relative", optarg)) convert_type = PATH_RELATIVE; else if (!strcmp("through", optarg)) convert_type = PATH_THROUGH; else die("Unknown path type."); break; case OPT_SINGLE_UPDATE: iflag++; single_update = optarg; break; case OPT_ENCODE_PATH: if (strlen(optarg) > 255) die("too many encode chars."); if (strchr(optarg, '/') || strchr(optarg, '.')) die("cannot encode '/' and '.' in the path."); set_encode_chars((unsigned char *)optarg); break; case 'c': cflag++; break; case 'd': dump_target = optarg; break; case 'f': file_list = optarg; break; case 'i': iflag++; break; case 'u': uflag++; iflag++; break; case 'I': Iflag++; break; case 'o': /* * Though the -o(--omit-gsyms) was removed, this code * is left for compatibility. */ break; case 'O': Oflag++; break; case 'q': qflag++; setquiet(); break; case 'w': wflag++; break; case 'v': vflag++; setverbose(); break; default: usage(); break; } } if (gtagsconf) { char path[MAXPATHLEN]; if (realpath(gtagsconf, path) == NULL) die("%s not found.", gtagsconf); set_env("GTAGSCONF", path); } if (gtagslabel) { set_env("GTAGSLABEL", gtagslabel); } if (qflag) vflag = 0; if (show_version) version(NULL, vflag); if (show_help) help(); argc -= optind; argv += optind; /* If dbpath is specified, -O(--objdir) option is ignored. */ if (argc > 0) Oflag = 0; if (show_config) { if (config_name) printconf(config_name); else fprintf(stdout, "%s\n", getconfline()); exit(0); } else if (do_path) { /* * This is the main body of path filter. * This code extract path name from tag line and * replace it with the relative or the absolute path name. * * By default, if we are in src/ directory, the output * should be converted like follws: * * main 10 ./src/main.c main(argc, argv)\n * main 22 ./libc/func.c main(argc, argv)\n * v * main 10 main.c main(argc, argv)\n * main 22 ../libc/func.c main(argc, argv)\n * * Similarly, the --path=absolute option specified, then * v * main 10 /prj/xxx/src/main.c main(argc, argv)\n * main 22 /prj/xxx/libc/func.c main(argc, argv)\n */ STRBUF *ib = strbuf_open(MAXBUFLEN); CONVERT *cv; char *ctags_x; if (argc < 3) die("gtags --path: 3 arguments needed."); cv = convert_open(convert_type, FORMAT_CTAGS_X, argv[0], argv[1], argv[2], stdout); while ((ctags_x = strbuf_fgets(ib, stdin, STRBUF_NOCRLF)) != NULL) convert_put(cv, ctags_x); convert_close(cv); strbuf_close(ib); exit(0); } else if (dump_target) { /* * Dump a tag file. */ DBOP *dbop = NULL; const char *dat = 0; int is_gpath = 0; char* target_file = NULL; if (!test("f", dump_target)) { target_file = strchr(dump_target, ':'); if (target_file == NULL) die("file '%s' not found", dump_target); *target_file++ = 0; //move to the next char, which starts the target file. if (!test("f", dump_target)) { die("file '%s' not found.", dump_target); } } if ((dbop = dbop_open(dump_target, 0, 0, DBOP_RAW)) == NULL) die("file '%s' is not a tag file.", dump_target); /* * The file which has a NEXTKEY record is GPATH. */ if (dbop_get(dbop, NEXTKEY)) is_gpath = 1; if (target_file && !is_gpath) { die("dump target_file can only be used with GPATH"); } if (target_file) { dat = dbop_get(dbop, target_file); if (dat == NULL) { die("target_file %s not found in GPATH", target_file); } time_t t = gpath_mtime(dbop, target_file); printf("%d\n", t); } else { for (dat = dbop_first(dbop, NULL, NULL, 0); dat != NULL; dat = dbop_next(dbop)) { const char *flag = is_gpath ? dbop_getflag(dbop) : ""; if (*flag) if (is_gpath) { time_t t = gpath_mtime(dbop, dbop->lastkey); printf("%s\t%s\t%s\t%s\n", dbop->lastkey, dat, flag, ctime(&t)); } else printf("%s\t%s\t%s\n", dbop->lastkey, dat, flag); else printf("%s\t%s\n", dbop->lastkey, dat); } } dbop_close(dbop); exit(0); } else if (Iflag) { if (!usable("mkid")) die("mkid not found."); } /* * If 'gtags.files' exists, use it as a file list. * If the file_list other than "-" is given, it must be readable file. */ if (file_list == NULL && test("f", GTAGSFILES)) file_list = GTAGSFILES; if (file_list && strcmp(file_list, "-")) { if (test("d", file_list)) die("'%s' is a directory.", file_list); else if (!test("f", file_list)) die("'%s' not found.", file_list); else if (!test("r", file_list)) die("'%s' is not readable.", file_list); } /* * Regularize the path name for single updating (--single-update). */ if (single_update) { static char regular_path_name[MAXPATHLEN]; char *p = single_update; if (!test("f", p)) die("'%s' not found.", p); if (isabspath(p)) die("--single-update requires relative path name."); if (!(p[0] == '.' && p[1] == '/')) { snprintf(regular_path_name, MAXPATHLEN, "./%s", p); p = regular_path_name; } single_update = p; } if (!getcwd(cwd, MAXPATHLEN)) die("cannot get current directory."); canonpath(cwd); /* * Decide directory (dbpath) in which gtags make tag files. * * Gtags create tag files at current directory by default. * If dbpath is specified as an argument then use it. * If the -i option specified and both GTAGS and GRTAGS exists * at one of the candidate directories then gtags use existing * tag files. */ if (iflag) { if (argc > 0) realpath(*argv, dbpath); else if (!gtagsexist(cwd, dbpath, MAXPATHLEN, vflag)) strlimcpy(dbpath, cwd, sizeof(dbpath)); } else { if (argc > 0) realpath(*argv, dbpath); else if (Oflag) { char *objdir = getobjdir(cwd, vflag); if (objdir == NULL) die("Objdir not found."); strlimcpy(dbpath, objdir, sizeof(dbpath)); } else strlimcpy(dbpath, cwd, sizeof(dbpath)); } if (iflag && (!test("f", makepath(dbpath, dbname(GTAGS), NULL)) || !test("f", makepath(dbpath, dbname(GRTAGS), NULL)) || !test("f", makepath(dbpath, dbname(GPATH), NULL)))) { if (wflag) warning("GTAGS, GRTAGS or GPATH not found. -i option ignored."); iflag = 0; } if (!test("d", dbpath)) die("directory '%s' not found.", dbpath); if (vflag) fprintf(stderr, "[%s] Gtags started.\n", now()); /* * load configuration file. */ openconf(); if (getconfb("extractmethod")) extractmethod = 1; strbuf_reset(sb); if (getconfs("langmap", sb)) langmap = check_strdup(strbuf_value(sb)); strbuf_reset(sb); if (getconfs("gtags_parser", sb)) gtags_parser = check_strdup(strbuf_value(sb)); /* * initialize parser. */ if (vflag && gtags_parser) fprintf(stderr, " Using plug-in parser.\n"); parser_init(langmap, gtags_parser); if (vflag && file_list) fprintf(stderr, " Using '%s' as a file list.\n", file_list); /* * Start statistics. */ init_statistics(); /* * incremental update. */ if (iflag) { /* * Version check. If existing tag files are old enough * gtagsopen() abort with error message. */ GTOP *gtop = gtags_open(dbpath, cwd, GTAGS, GTAGS_MODIFY, 0); gtags_close(gtop); /* * GPATH is needed for incremental updating. * Gtags check whether or not GPATH exist, since it may be * removed by mistake. */ if (!test("f", makepath(dbpath, dbname(GPATH), NULL))) die("Old version tag file found. Please remake it."); (void)incremental(dbpath, cwd); print_statistics(statistics); exit(0); } /* * create GTAGS and GRTAGS */ createtags(dbpath, cwd); /* * create idutils index. */ if (Iflag) { tim = statistics_time_start("Time of creating ID"); if (vflag) fprintf(stderr, "[%s] Creating indexes for idutils.\n", now()); strbuf_reset(sb); strbuf_puts(sb, "mkid"); if (vflag) strbuf_puts(sb, " -v"); strbuf_sprintf(sb, " --file='%s/ID'", dbpath); if (vflag) { #ifdef __DJGPP__ if (is_unixy()) /* test for 4DOS as well? */ #endif strbuf_puts(sb, " 1>&2"); } else { strbuf_puts(sb, " >/dev/null"); } if (debug) fprintf(stderr, "executing mkid like: %s\n", strbuf_value(sb)); if (system(strbuf_value(sb))) die("mkid failed: %s", strbuf_value(sb)); if (chmod(makepath(dbpath, "ID", NULL), 0644) < 0) die("cannot chmod ID file."); statistics_time_end(tim); } if (vflag) fprintf(stderr, "[%s] Done.\n", now()); closeconf(); strbuf_close(sb); print_statistics(statistics); return 0; }