Index: gtags/gtags.c
===================================================================
RCS file: /cvsroot/global/global/gtags/gtags.c,v
retrieving revision 1.130
diff -u -r1.130 gtags.c
--- gtags/gtags.c	9 Aug 2005 16:39:53 -0000	1.130
+++ gtags/gtags.c	16 Aug 2005 11:09:03 -0000
@@ -94,6 +94,7 @@
 int secure_mode;
 const char *extra_options;
 const char *info_string;
+const char *file_list;
 
 int extractmethod;
 int total;
@@ -130,6 +131,7 @@
 	{"cxref", no_argument, &cxref, 1},
 	{"debug", no_argument, &debug, 1},
 	{"expand", required_argument, &do_expand, 1},
+	{"file", required_argument, NULL, 0},
 	{"find", no_argument, &do_find, 1},
 	{"gtagsconf", required_argument, &gtagsconf, 1},
 	{"gtagslabel", required_argument, &gtagslabel, 1},
@@ -220,6 +222,8 @@
 				}
 				set_env(name, value);
 				gtagsconf = gtagslabel = 0;
+			} else if (!strcmp(p, "file")) {
+				file_list = optarg;
 			}
 			break;
 		case 'c':
@@ -684,7 +688,11 @@
 	/*
 	 * make add list and update list.
 	 */
-	for (find_open(NULL); (path = find_read()) != NULL; ) {
+	if (file_list)
+		find_open_filelist(file_list, root);
+	else
+		find_open(NULL);
+	while ((path = find_read()) != NULL) {
 		const char *fid;
 
 		/* a blank at the head of path means 'NOT SOURCE'. */
@@ -925,6 +933,7 @@
 	int arg_count = 0;
 	STRBUF *path_list = strbuf_open(MAXPATHLEN);
 	int path_list_max;
+	static int gpath_created;
 
 	/*
 	 * get tag command.
@@ -973,7 +982,13 @@
 	 * the source file as a lot as possible to decrease the invoking
 	 * frequency of the parser.
 	 */
-	for (find_open(NULL); (path = find_read()) != NULL; ) {
+	if (gpath_created)
+		gfind_open(dbpath, NULL);
+	else if (file_list)
+		find_open_filelist(file_list, root);
+	else
+		find_open(NULL);
+	while ((path = gpath_created ? gfind_read() : find_read()) != NULL) {
 		int skip = 0;
 
 		/* a blank at the head of path means 'NOT SOURCE'. */
@@ -1028,7 +1043,11 @@
 	if (strbuf_getlen(path_list))
 		gtags_add(gtop, strbuf_value(comline), path_list, gflags);
 	total = count;				/* save total count */
-	find_close();
+	if (gpath_created)
+		gfind_close();
+	else
+		find_close();
+	gpath_created = 1;
 	gtags_close(gtop);
 	strbuf_close(comline);
 	strbuf_close(path_list);
Index: gtags/manual.in
===================================================================
RCS file: /cvsroot/global/global/gtags/manual.in,v
retrieving revision 1.49
diff -u -r1.49 manual.in
--- gtags/manual.in	9 Aug 2005 16:39:53 -0000	1.49
+++ gtags/manual.in	16 Aug 2005 11:09:03 -0000
@@ -55,6 +55,10 @@
 	@item{@option{--config} @arg{name}}
 		Show the value of config variable @arg{name}.
 		If @arg{name} is not specified then show whole of config entry.
+	@item{@option{--file} @arg{file}}
+		Read from @arg{file} a list of file names which should be parsed.
+		If @arg{file} is @file{-}, read from standard input.
+		File names must be separated by newline.
 	@item{@option{--gtagsconf} @arg{file}}
 		Load user's configuration from @arg{file}.
 	@item{@option{--gtagslabel} @arg{label}}
Index: libutil/find.c
===================================================================
RCS file: /cvsroot/global/global/libutil/find.c,v
retrieving revision 1.45
diff -u -r1.45 find.c
--- libutil/find.c	31 Jul 2005 15:00:26 -0000	1.45
+++ libutil/find.c	16 Aug 2005 11:09:04 -0000
@@ -29,6 +29,9 @@
 #include <dirent.h>
 #include <sys/stat.h>
 #endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
 #include <stdio.h>
 #ifdef STDC_HEADERS
 #include <stdlib.h>
@@ -52,8 +55,10 @@
 #include "is_unixy.h"
 #include "locatestring.h"
 #include "makepath.h"
+#include "path.h"
 #include "strbuf.h"
 #include "strlimcpy.h"
+#include "test.h"
 
 /*
  * usage of find_xxx()
@@ -72,10 +77,20 @@
 static STRBUF *list;
 static int list_count;
 static char **listarray;		/* list for skipping full path */
+static FILE *ip;
+static STRBUF *ib;
+static char root[MAXPATHLEN + 1];
+static size_t rootlen;
+static char buf[MAXPATHLEN + 1];
 static int opened;
+#define FIND_OPEN	1
+#define FILELIST_OPEN	2
 static int retval;
 
 static void trim(char *);
+static char *find_read_filelist(void);
+
+extern int qflag;
 #ifdef DEBUG
 extern int debug;
 #endif
@@ -390,7 +405,7 @@
 	const char *start;
 {
 	assert(opened == 0);
-	opened = 1;
+	opened = FIND_OPEN;
 
 	if (!start)
 		start = ".";
@@ -414,6 +429,39 @@
 	prepare_skip();
 }
 /*
+ * find_open_filelist: find_open like interface for handling output of find(1).
+ *
+ *	i)	filename	file including list of file names.
+ *				When "-" is specified, read from standard input.
+ *	i)	rootdir		root directory of source tree
+ */
+void
+find_open_filelist(filename, rootdir)
+	const char *filename;
+	const char *rootdir;
+{
+	assert(opened == 0);
+	opened = FILELIST_OPEN;
+	ib = strbuf_open(MAXBUFLEN);
+	if (filename[0] == '-' && filename[1] == '\0') {
+		ip = stdin;
+	} else {
+		if (test("d", filename))
+			die("'%s' is a directory.", filename);
+		if (!test("f", filename))
+			die("'%s' not found.", filename);
+		if (!test("r", filename))
+			die("'%s' is not readable.", filename);
+		ip = fopen(filename, "r");
+		if (ip == NULL)
+			die("cannot open '%s'.", filename);
+	}
+	strlimcpy(root, rootdir, sizeof(root));
+	rootlen = strlen(root);
+	prepare_skip();
+	prepare_source();
+}
+/*
  * find_read: read path without GPATH.
  *
  *	r)		path
@@ -422,8 +470,10 @@
 find_read(void)
 {
 	static char val[MAXPATHLEN+1];
-	extern int qflag;
 
+	assert(opened != 0);
+	if (opened == FILELIST_OPEN)
+		return find_read_filelist();
 	for (;;) {
 		while (curp->p < curp->end) {
 			char type = *(curp->p);
@@ -497,15 +547,84 @@
 	return NULL;
 }
 /*
+ * find_read_filelist: read path from file
+ *
+ *	r)		path
+ */
+static char *
+find_read_filelist()
+{
+	char *path;
+
+	for (;;) {
+		path = strbuf_fgets(ib, ip, STRBUF_NOCRLF);
+		if (path == NULL) {
+			/* EOF */
+			return NULL;
+		}
+		if (*path == '\0') {
+			/* skip empty line.  */
+			continue;
+		}
+		if (!test("f", path)) {
+			if (!qflag) {
+				if (test("d", path))
+					fprintf(stderr, "'%s' is a directory.\n", path);
+				else
+					fprintf(stderr, "'%s' not found.\n", path);
+			}
+			continue;
+		}
+		if (realpath(path, buf) == NULL) {
+			if (!qflag)
+				fprintf(stderr, "realpath(\"%s\", buf) failed.\n", path);
+			continue;
+		}
+		if (!isabspath(buf))
+			die("realpath(3) is not compatible with BSD version.");
+		if (strncmp(buf, root, rootlen) || buf[rootlen] != '/') {
+			if (!qflag)
+				fprintf(stderr, "'%s' is out of source tree.\n", buf);
+			continue;
+		}
+		path = buf + rootlen - 1;
+		*path = '.';
+		/*
+		 * GLOBAL cannot treat path which includes blanks.
+		 * It will be improved in the future.
+		 */
+		if (locatestring(path, " ", MATCH_LAST)) {
+			if (!qflag)
+				fprintf(stderr, "'%s' ignored, because it includes blank.\n", path + 2);
+			continue;
+		}
+		if (skipthisfile(path))
+			continue;
+		/*
+		 * A blank at the head of path means
+		 * other than source file.
+		 */
+		if (regexec(suff, path, 0, 0, 0) != 0)
+			*--path = ' ';
+		return path;
+	}
+}
+/*
  * find_close: close iterator.
  */
 void
 find_close(void)
 {
-	assert(opened == 1);
-	for (curp = &stack[0]; curp < topp; curp++)
-		if (curp->sb != NULL)
-			strbuf_close(curp->sb);
+	assert(opened != 0);
+	if (opened == FIND_OPEN) {
+		for (curp = &stack[0]; curp < topp; curp++)
+			if (curp->sb != NULL)
+				strbuf_close(curp->sb);
+	} else {
+		if (ip != stdin)
+			fclose(ip);
+		strbuf_close(ib);
+	}
 	regfree(suff);
 	if (skip)
 		regfree(skip);
Index: libutil/find.h
===================================================================
RCS file: /cvsroot/global/global/libutil/find.h,v
retrieving revision 1.12
diff -u -r1.12 find.h
--- libutil/find.h	10 May 2005 05:17:52 -0000	1.12
+++ libutil/find.h	16 Aug 2005 11:09:04 -0000
@@ -23,6 +23,7 @@
 #define _FIND_H_
 
 void find_open(const char *);
+void find_open_filelist(const char *, const char *);
 char *find_read(void);
 void find_close(void);
 
