예제 #1
0
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);
}
예제 #2
0
파일: gtags.c 프로젝트: lianhongHou/Emacs
/**
 * 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);
}
예제 #3
0
파일: find.c 프로젝트: kosaki/gtags
/*
 * 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);
}
예제 #4
0
/**
 * 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);
}
예제 #5
0
static void
replace_variables(STRBUF *sb)
{
	STRBUF *result = strbuf_open(0);
	STRBUF *word = strbuf_open(0);
	const char *p = strbuf_value(sb);

	/*
	 * Simple of detecting infinite loop.
	 */
	if (++recursive_call > 32)
		die("Seems to be a never-ending referring.");
	for (;;) {
		for (; *p; p++) {
			if (*p == '$')
				break;
			if (*p == '\\' && *(p + 1) != 0)
				p++;
			strbuf_putc(result, *p);
		}
		if (*p == 0)
			break;
		/*
		 * $<word> or ${<word>}
		 */
		if (*p == '$') {
			strbuf_reset(word);
			if (*++p == '{') {
				for (p++; *p && *p != '}'; p++)
					strbuf_putc(word, *p);;
				if (*p++ != '}')
					die("invalid variable.");
			} else {
				for (; *p && (isalnum(*p) || *p == '_'); p++)
					strbuf_putc(word, *p);
			}
			getconfs(strbuf_value(word), result);
		}
	}
	strbuf_reset(sb);
	strbuf_puts(sb, strbuf_value(result));
	strbuf_close(result);
	strbuf_close(word);
	recursive_call--;
}
예제 #6
0
/*
 * 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;
}
예제 #7
0
파일: gozilla.c 프로젝트: GimXu/global
static char *
make_url_file(const char *url)
{
	STATIC_STRBUF(sb);
	FILE *op;
	struct passwd *pw = getpwuid(getuid());

	strbuf_clear(sb);
	getconfs("localstatedir", sb);
	snprintf(urlfile, sizeof(urlfile), "%s/gtags/lasturl-%s.html", strbuf_value(sb),
			pw ? pw->pw_name : "nobody");
	op = fopen(urlfile, "w");
	if (op == NULL)
		die("cannot make url file.");
	fprintf(op, "<!-- You may remove this file. It was needed by gozilla(1) temporarily. -->\n");
	fprintf(op, "<html><head>\n");
	fprintf(op, "<meta http-equiv='refresh' content='0;url=\"%s\"' />\n", url);
	fprintf(op, "</head></html>\n");
	fclose(op);

	return urlfile;
}
예제 #8
0
/**
 * openconf: load configuration file.
 *
 *	@param[in]	rootdir	Project root directory
 *
 * Globals used (output):
 *	confline:	 specified entry
 */
void
openconf(const char *rootdir)
{
	STRBUF *sb;

	if (opened)
		return;
	opened = 1;
	/*
	 * if config file not found then return default value.
	 */
	if (!(config_path = configpath(rootdir)))
		confline = check_strdup("");
	/*
	 * if it is not an absolute path then assumed config value itself.
	 */
	else if (!isabspath(config_path)) {
		confline = check_strdup(config_path);
		if (!locatestring(confline, ":", MATCH_FIRST))
			die("GTAGSCONF must be absolute path name.");
	}
	/*
	 * else load value from config file.
	 */
	else {
		if (test("d", config_path))
			die("config file '%s' is a directory.", config_path);
		if (!test("f", config_path))
			die("config file '%s' not found.", config_path);
		if (!test("r", config_path))
			die("config file '%s' is not readable.", config_path);
		if ((config_label = getenv("GTAGSLABEL")) == NULL)
			config_label = "default";
	
		if (!(fp = fopen(config_path, "r")))
			die("cannot open '%s'.", config_path);
		ib = strbuf_open(MAXBUFLEN);
		sb = strbuf_open(0);
		includelabel(fp, sb, config_label, 0);
		confline = check_strdup(strbuf_value(sb));
		strbuf_close(ib);
		strbuf_close(sb);
		fclose(fp);
	}
	/*
	 * make up required variables.
	 */
	sb = strbuf_open(0);
	strbuf_puts(sb, confline);
	strbuf_unputc(sb, ':');

	if (!getconfs("langmap", NULL)) {
		strbuf_puts(sb, ":langmap=");
		strbuf_puts(sb, quote_chars(DEFAULTLANGMAP, ':'));
	}
	if (!getconfs("skip", NULL)) {
		strbuf_puts(sb, ":skip=");
		strbuf_puts(sb, DEFAULTSKIP);
	}
	strbuf_unputc(sb, ':');
	strbuf_putc(sb, ':');
	confline = check_strdup(strbuf_value(sb));
	strbuf_close(sb);
	trim(confline);
	return;
}
예제 #9
0
파일: find.c 프로젝트: kosaki/gtags
/*
 * 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);
}
예제 #10
0
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");
	}
}
예제 #11
0
/*
 * 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);
}
예제 #12
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;

	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;
}
예제 #13
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;
}