예제 #1
0
char *getconfigfile(const char *path, const char *fname)
{
	char *cfgpath = getconfigpath(path);
	char result[PATH_MAX];
	sprintf(result, "%s%s", cfgpath, fname);
	free(cfgpath);
	return dostrdup(result);
} // getconfigfile()
예제 #2
0
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;

	/*
	 * Setup GTAGSCONF and GTAGSLABEL environment variable
	 * according to the --gtagsconf and --gtagslabel option.
	 */
	preparse_options(argc, argv);
	/*
	 * Get the project root directory.
	 */
	if (!vgetcwd(cwd, MAXPATHLEN))
		die("cannot get current directory.");
	canonpath(cwd);
	/*
	 * Load configuration file.
	 */
	openconf(cwd);
	configuration();
	setenv_from_config();
	{
		char *env = getenv("GTAGS_OPTIONS");
		if (env && *env)
			argv = prepend_options(&argc, argv, env);
	}
	/*
	 * Execute gtags_hook before the jobs.
	 */
	if (getconfs("gtags_hook", sb)) {
		char *p = serialize_options(argc, argv);
		set_env("GTAGS_COMMANDLINE", p);
		free(p);
		if (system(strbuf_value(sb)))
			fprintf(stderr, "gtags-hook failed: %s\n", strbuf_value(sb));
	}
	logging_arguments(argc, argv);
	while ((optchar = getopt_long(argc, argv, "cd:f:iIn: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:
		case OPT_GTAGSLABEL:
			/* These options are already parsed in preparse_options() */
			break;
		case OPT_SINGLE_UPDATE:
			iflag++;
			single_update = optarg;
			break;
		case OPT_ACCEPT_DOTFILES:
			accept_dotfiles = 1;
			break;
		case OPT_SKIP_UNREADABLE:
			skip_unreadable = 1;
			break;
		case 'c':
			cflag++;
			break;
		case 'd':
			dump_target = optarg;
			break;
		case 'f':
			file_list = optarg;
			break;
		case 'i':
			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++;
			break;
		case 'w':
			wflag++;
			break;
		case 'v':
			vflag++;
			break;
		default:
			usage();
			break;
		}
	}
	if (qflag) {
		vflag = 0;
		setquiet();
	}
	if (vflag)
		setverbose();
	if (wflag)
		set_langmap_wflag();
	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) {
		openconf(setupdbpath(0) == 0 ? get_root() : NULL);
		if (config_name)
			printconf(config_name);
		else
			fprintf(stdout, "%s\n", getconfline());
		exit(0);
	} else if (dump_target) {
		/*
		 * Dump a tag file.
		 */
		DBOP *dbop = NULL;
		const char *dat = 0;
		int is_gpath = 0;

		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;
		for (dat = dbop_first(dbop, NULL, NULL, 0); dat != NULL; dat = dbop_next(dbop)) {
			const char *flag = is_gpath ? dbop_getflag(dbop) : "";

			if (*flag)
				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) {
#define REQUIRED_MKID_VERSION "4.5"
		char *p;

		if (!usable("mkid"))
			die("mkid not found.");
		if (read_first_line("mkid --version", sb))
			die("mkid cannot executed.");
		p = strrchr(strbuf_value(sb), ' ');
		if (p == NULL)
			die("invalid version string of mkid: %s", strbuf_value(sb));
		switch (check_version(p + 1, REQUIRED_MKID_VERSION)
#ifdef _WIN32
			| strcmp(p + 1, "3.2.99") == 0
#endif
			)  {
		case 1:		break;	/* OK */
		case 0:		die("mkid version %s or later is required.", REQUIRED_MKID_VERSION);
		default:	die("invalid version string of mkid: %s", strbuf_value(sb));
		}
	}

	/*
	 * 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 _WIN32 || __DJGPP__
		for (; *p; p++)
			if (*p == '\\')
				*p = '/';
		p = single_update;
#define LOCATEFLAG MATCH_AT_FIRST|IGNORE_CASE
#else
#define LOCATEFLAG MATCH_AT_FIRST
#endif
		if (isabspath(p)) {
			char *q = locatestring(p, cwd, LOCATEFLAG);

			if (q && *q == '/')
				snprintf(regular_path_name, MAXPATHLEN, "./%s", q + 1);
			else
				die("path '%s' is out of the project.", p);

		} else {
			if (p[0] == '.' && p[1] == '/')
				snprintf(regular_path_name, MAXPATHLEN, "%s", p);
			else
				snprintf(regular_path_name, MAXPATHLEN, "./%s", p);
		}
		single_update = regular_path_name;
	}
	/*
	 * 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);
	/*
	 * Start processing.
	 */
	if (accept_dotfiles)
		set_accept_dotfiles();
	if (skip_unreadable)
		set_skip_unreadable();
	if (vflag) {
		const char *config_path = getconfigpath();
		const char *config_label = getconfiglabel();

		fprintf(stderr, "[%s] Gtags started.\n", now());
		if (config_path)
			fprintf(stderr, " Using configuration file '%s'.\n", config_path);
		else {
			fprintf(stderr, " Using default configuration.\n");
			if (getenv("GTAGSLABEL"))
				fprintf(stderr, " GTAGSLABEL(--gtagslabel) ignored since configuration file not found.\n");
		}
		if (config_label)
			fprintf(stderr, " Using configuration label '%s'.\n", config_label);
		if (file_list)
			fprintf(stderr, " Using '%s' as a file list.\n", file_list);
	}
	/*
	 * initialize parser.
	 */
	if (vflag && gtags_parser)
		fprintf(stderr, " Using plug-in parser.\n");
	parser_init(langmap, gtags_parser);
	/*
	 * 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) {
		FILE *op;
		GFIND *gp;
		const char *path;

		tim = statistics_time_start("Time of creating ID");
		if (vflag)
			fprintf(stderr, "[%s] Creating indexes for idutils.\n", now());
		strbuf_reset(sb);
		/*
		 * Since idutils stores the value of PWD in ID file, we need to
		 * force idutils to follow our style.
		 */
#if _WIN32 || __DJGPP__
		strbuf_puts(sb, "mkid --files0-from=-");
#else
		strbuf_sprintf(sb, "PWD=%s mkid --files0-from=-", quote_shell(cwd));
#endif
		if (vflag)
			strbuf_puts(sb, " -v");
		strbuf_sprintf(sb, " --file=%s/ID", quote_shell(dbpath));
		if (vflag) {
#ifdef __DJGPP__
			if (is_unixy())	/* test for 4DOS as well? */
#endif
			strbuf_puts(sb, " 1>&2");
		} else {
			strbuf_puts(sb, " >" NULL_DEVICE);
#ifdef __DJGPP__
			if (is_unixy())	/* test for 4DOS as well? */
#endif
			strbuf_puts(sb, " 2>&1");
		}
		if (debug)
			fprintf(stderr, "executing mkid like: %s\n", strbuf_value(sb));
		op = popen(strbuf_value(sb), "w");
		if (op == NULL)
			die("cannot execute '%s'.", strbuf_value(sb));
		gp = gfind_open(dbpath, NULL, GPATH_BOTH, 0);
		while ((path = gfind_read(gp)) != NULL) {
			fputs(path, op);
			fputc('\0', op);
		}
		gfind_close(gp);
		if (pclose(op) != 0)
			die("terminated abnormally '%s' (errno = %d).", strbuf_value(sb), errno);
		if (test("f", makepath(dbpath, "ID", NULL)))
			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;
}