Index: global/global.c
===================================================================
RCS file: /cvsroot/global/global/global/global.c,v
retrieving revision 1.96
diff -u -r1.96 global.c
--- global/global.c	27 Jun 2005 13:04:38 -0000	1.96
+++ global/global.c	1 Jul 2005 16:24:02 -0000
@@ -64,7 +64,7 @@
 void grep(const char *);
 void pathlist(const char *, const char *);
 void parsefile(int, char **, const char *, const char *, const char *, int);
-static int exec_parser(const char *, const char *, const char *, const char *, FILE *);
+static int exec_parser(const char *, STRBUF *, const char *, const char *, FILE *);
 void printtag(FILE *, const char *);
 int search(const char *, const char *, const char *, int);
 int includepath(const char *, const char *);
@@ -984,20 +984,15 @@
 		}
 
 		if (strbuf_getlen(path_list)
-		    && strbuf_getlen(path_list) + 1 + strlen(path) > path_list_max) {
-			count += exec_parser(parser, strbuf_value(path_list),
-					cwd, root, op);
+		    && strbuf_getlen(path_list) + strlen(path) > path_list_max) {
+			count += exec_parser(parser, path_list, cwd, root, op);
 			strbuf_reset(path_list);
 		}
 
-		if (strbuf_getlen(path_list))
-			strbuf_putc(path_list, ' ');
-		strbuf_puts(path_list, path);
-	}
-	if (strbuf_getlen(path_list)) {
-		count += exec_parser(parser, strbuf_value(path_list),
-				cwd, root, op);
+		strbuf_puts0(path_list, path);
 	}
+	if (strbuf_getlen(path_list))
+		count += exec_parser(parser, path_list, cwd, root, op);
 	gpath_close();
 	closefilter(op);
 	strbuf_close(sb);
@@ -1016,7 +1011,7 @@
  * exec_parser: execute parser
  *
  *	i)	parser		template of command line
- *	i)	path_list	space separated list of path
+ *	i)	path_list	\0 separated list of paths
  *	i)	cwd		current directory
  *	i)	root		root directory of source tree
  *	i)	op		filter to output
@@ -1025,7 +1020,7 @@
 static int
 exec_parser(parser, path_list, cwd, root, op)
 	const char *parser;
-	const char *path_list;
+	STRBUF *path_list;
 	const char *cwd;
 	const char *root;
 	FILE *op;
Index: gtags/gtags.c
===================================================================
RCS file: /cvsroot/global/global/gtags/gtags.c,v
retrieving revision 1.118
diff -u -r1.118 gtags.c
--- gtags/gtags.c	27 Jun 2005 15:28:32 -0000	1.118
+++ gtags/gtags.c	1 Jul 2005 16:24:02 -0000
@@ -59,6 +59,10 @@
 #include "global.h"
 #include "const.h"
 
+#if !defined(ARG_MAX) && defined(_SC_ARG_MAX)
+#define ARG_MAX		sysconf(_SC_ARG_MAX)
+#endif
+
 static void usage(void);
 static void help(void);
 void signal_setup(void);
@@ -68,6 +72,7 @@
 int incremental(const char *, const char *);
 void updatetags(const char *, const char *, const unsigned char *, int, STRBUF *, int);
 void createtags(const char *, const char *, int);
+static void print_extracting(int, STRBUF *);
 int printconf(const char *);
 void set_base_directory(const char *, const char *);
 void put_converting(const char *, int, int);
@@ -827,11 +832,14 @@
 	int db;
 {
 	GTOP *gtop;
-	const char *path;
 	const char *comline;
 	const char *end;
 	STRBUF *sb = strbuf_open(0);
 	int gflags;
+	STATIC_STRBUF(path_list);
+	int path_list_max;
+	int savec;
+	int pathlen;
 
 	if (vflag)
 		fprintf(stderr, " Updating '%s'...", dbname(db));
@@ -849,7 +857,28 @@
 		die("cannot get tag command. (%s)", dbname(db));
 	comline = strbuf_value(sb);
 
+	/*
+	 * determine the maximum length of the list of paths.
+	 */
+#ifdef ARG_MAX
+	path_list_max = ARG_MAX;
+	path_list_max -= 2048;
+	if (path_list_max > 20 * 1024)
+		path_list_max = 20 * 1024;
+	path_list_max -= env_size();
+	path_list_max -= strbuf_getlen(sb);
+	path_list_max -= 40;
+	if (path_list_max < 0)
+		path_list_max = 0;
+#else
+	path_list_max = 0;
+#endif
+
 	gtop = gtags_open(dbpath, root, db, GTAGS_MODIFY, 0);
+	if (gtop->format & (GTAGS_PATHINDEX | GTAGS_COMPACT)) {
+		/* force processing files individually. */
+		path_list_max = 0;
+	}
 
 	if (max_fid > 0) {
 		if (vflag)
@@ -864,14 +893,23 @@
 		gflags |= GTAGS_EXTRACTMETHOD;
 	if (debug)
 		gflags |= GTAGS_DEBUG;
-	path = strbuf_value(extractlist);
-	end = path + strbuf_getlen(extractlist);
-	while (path < end) {
-		gtags_add(gtop, comline, path, gflags);
+	path_list->sbuf = path_list->curp = strbuf_value(extractlist);
+	end = path_list->curp + strbuf_getlen(extractlist);
+	while (path_list->curp < end) {
+		pathlen = strlen(path_list->curp);
+		if (strbuf_getlen(path_list)
+		    && strbuf_getlen(path_list) + pathlen > path_list_max) {
+			savec = *path_list->curp;
+			gtags_add(gtop, comline, path_list, gflags);
+			*path_list->curp = savec;
+			path_list->sbuf = path_list->curp;
+		}
 		if (exitflag)
 			break;
-		path += strlen(path) + 1;
+		path_list->curp += pathlen + 1;
 	}
+	if (strbuf_getlen(path_list))
+		gtags_add(gtop, comline, path_list, gflags);
 
 	gtags_close(gtop);
 	strbuf_close(sb);
@@ -895,10 +933,12 @@
 {
 	const char *path;
 	GTOP *gtop;
-	int flags;
+	int flags, gflags;
 	const char *comline;
 	STRBUF *sb = strbuf_open(0);
 	int count = 0;
+	STRBUF *path_list = strbuf_open(MAXPATHLEN);
+	int path_list_max;
 
 	/*
 	 * get tag command.
@@ -911,6 +951,24 @@
 	 */
 	if (db == GRTAGS && !test("f", makepath(dbpath, dbname(GTAGS), NULL)))
 		die("GTAGS needed to create GRTAGS.");
+
+	/*
+	 * determine the maximum length of the list of paths.
+	 */
+#ifdef ARG_MAX
+	path_list_max = ARG_MAX;
+	path_list_max -= 2048;
+	if (path_list_max > 20 * 1024)
+		path_list_max = 20 * 1024;
+	path_list_max -= env_size();
+	path_list_max -= strbuf_getlen(sb);
+	path_list_max -= 40;
+	if (path_list_max < 0)
+		path_list_max = 0;
+#else
+	path_list_max = 0;
+#endif
+
 	flags = 0;
 	/*
 	 * Compact format:
@@ -928,46 +986,71 @@
 	if (vflag > 1)
 		fprintf(stderr, " using tag command '%s <path>'.\n", comline);
 	gtop = gtags_open(dbpath, root, db, GTAGS_CREATE, flags);
+	if (gtop->format & (GTAGS_PATHINDEX | GTAGS_COMPACT)) {
+		/* force processing files individually. */
+		path_list_max = 0;
+	}
+	gflags = 0;
+	if (extractmethod)
+		gflags |= GTAGS_EXTRACTMETHOD;
+	if (debug)
+		gflags |= GTAGS_DEBUG;
 	for (find_open(NULL); (path = find_read()) != NULL; ) {
-		int	gflags = 0;
-		int	skip = 0;
-
 		/* a blank at the head of path means 'NOT SOURCE'. */
 		if (*path == ' ')
 			continue;
 		if (exitflag)
 			break;
-		count++;
-		/*
-		 * GSYMS doesn't treat asembler.
-		 */
-		if (db == GSYMS) {
-			if (locatestring(path, ".s", MATCH_AT_LAST) != NULL ||
-			    locatestring(path, ".S", MATCH_AT_LAST) != NULL)
-				skip = 1;
-		}
-		if (vflag) {
-			if (total)
-				fprintf(stderr, " [%d/%d]", count, total);
-			else
-				fprintf(stderr, " [%d]", count);
-			fprintf(stderr, " extracting tags of %s", path + 2);
-			if (skip)
-				fprintf(stderr, " (skipped)");
-			fputc('\n', stderr);
+		if (strbuf_getlen(path_list)
+		    && strbuf_getlen(path_list) + strlen(path) > path_list_max) {
+			if (vflag)
+				print_extracting(count, path_list);
+			gtags_add(gtop, comline, path_list, gflags);
+			strbuf_reset(path_list);
 		}
-		if (skip)
-			continue;
-		if (extractmethod)
-			gflags |= GTAGS_EXTRACTMETHOD;
-		if (debug)
-			gflags |= GTAGS_DEBUG;
-		gtags_add(gtop, comline, path, gflags);
+		strbuf_puts0(path_list, path);
+		count++;
+	}
+	if (strbuf_getlen(path_list)) {
+		if (vflag)
+			print_extracting(count, path_list);
+		gtags_add(gtop, comline, path_list, gflags);
 	}
 	total = count;				/* save total count */
 	find_close();
 	gtags_close(gtop);
 	strbuf_close(sb);
+	strbuf_close(path_list);
+}
+/*
+ * print_extracting: print verbose message " [count/total] extracting tags of ..."
+ *
+ *	i)	count	how many files are already parsed
+ *	i)	path_list	\0 separated list of paths
+ *	gi)	total	total numbers of file to parse
+ */
+static void
+print_extracting(count, path_list)
+	int count;
+	STRBUF *path_list;
+{
+	const char *path, *end;
+
+	if (total)
+		fprintf(stderr, " [%d/%d]", count, total);
+	else
+		fprintf(stderr, " [%d]", count);
+	fputs(" extracting tags of ", stderr);
+	path = strbuf_value(path_list);
+	end = path + strbuf_getlen(path_list);
+	while (path < end) {
+		fputs(path + 2, stderr);
+		path += strlen(path) + 1;
+		if (path == end)
+			fputc('\n', stderr);
+		else
+			fputs(", ", stderr);
+	}
 }
 /*
  * printconf: print configuration data.
Index: libutil/gtagsop.c
===================================================================
RCS file: /cvsroot/global/global/libutil/gtagsop.c,v
retrieving revision 1.66
diff -u -r1.66 gtagsop.c
--- libutil/gtagsop.c	27 Jun 2005 12:39:51 -0000	1.66
+++ libutil/gtagsop.c	1 Jul 2005 16:24:02 -0000
@@ -121,7 +121,7 @@
  * makecommand: make command line to make global tag file
  *
  *	i)	comline	skeleton command line
- *	i)	path	path name
+ *	i)	path_list	\0 separated list of path names
  *	o)	sb	command line
  *
  * command skeleton is like this:
@@ -130,22 +130,32 @@
  *	'gtags-parser -r'
  */
 void
-makecommand(comline, path, sb)
+makecommand(comline, path_list, sb)
 	const char *comline;
-	const char *path;
+	STRBUF *path_list;
 	STRBUF *sb;
 {
 	const char *p = locatestring(comline, "%s", MATCH_FIRST);
+	const char *path, *end;
 
 	if (p) {
 		strbuf_nputs(sb, comline, p - comline);
-		strbuf_puts(sb, path);
-		strbuf_puts(sb, p + 2);
 	} else {
 		strbuf_puts(sb, comline);
 		strbuf_putc(sb, ' ');
+	}
+
+	path = strbuf_value(path_list);
+	end = path + strbuf_getlen(path_list);
+	while (path < end) {
 		strbuf_puts(sb, path);
+		path += strlen(path) + 1;
+		if (path < end)
+			strbuf_putc(sb, ' ');
 	}
+
+	if (p)
+		strbuf_puts(sb, p + 2);
 }
 /*
  * formatcheck: check format of tag command's output
@@ -403,18 +413,18 @@
 	recover(&ptable);
 }
 /*
- * gtags_add: add tags belonging to the path into tag file.
+ * gtags_add: add tags belonging to the path list into tag file.
  *
  *	i)	gtop	descripter of GTOP
  *	i)	comline	tag command line
- *	i)	path	source file
+ *	i)	path_list	\0 separated list of source files
  *	i)	flags	GTAGS_UNIQUE, GTAGS_EXTRACTMETHOD, GTAGS_DEBUG
  */
 void
-gtags_add(gtop, comline, path, flags)
+gtags_add(gtop, comline, path_list, flags)
 	GTOP *gtop;
 	const char *comline;
-	const char *path;
+	STRBUF *path_list;
 	int flags;
 {
 	const char *ctags_x;
@@ -422,19 +432,26 @@
 	STRBUF *sb = strbuf_open(0);
 	STRBUF *ib = strbuf_open(MAXBUFLEN);
 	const char *fid;
+	const char *path, *end;
 
 	/*
 	 * add path index if not yet.
 	 */
-	gpath_put(path);
+	path = strbuf_value(path_list);
+	end = path + strbuf_getlen(path_list);
+	while (path < end) {
+		gpath_put(path);
+		path += strlen(path) + 1;
+	}
 	/*
 	 * make command line.
 	 */
-	makecommand(comline, path, sb);
+	makecommand(comline, path_list, sb);
 	/*
 	 * get file id.
 	 */
 	if (gtop->format & GTAGS_PATHINDEX) {
+		path = strbuf_value(path_list);
 		if (!(fid = gpath_path2fid(path)))
 			die("GPATH is corrupted.('%s' not found)", path);
 	} else
Index: libutil/gtagsop.h
===================================================================
RCS file: /cvsroot/global/global/libutil/gtagsop.h,v
retrieving revision 1.21
diff -u -r1.21 gtagsop.h
--- libutil/gtagsop.h	27 Jun 2005 12:39:51 -0000	1.21
+++ libutil/gtagsop.h	1 Jul 2005 16:24:02 -0000
@@ -84,11 +84,11 @@
 } GTOP;
 
 const char *dbname(int);
-void makecommand(const char *, const char *, STRBUF *);
+void makecommand(const char *, STRBUF *, STRBUF *);
 void formatcheck(const char *, int);
 GTOP *gtags_open(const char *, const char *, int, int, int);
 void gtags_put(GTOP *, const char *, const char *);
-void gtags_add(GTOP *, const char *, const char *, int);
+void gtags_add(GTOP *, const char *, STRBUF *, int);
 void gtags_delete(GTOP *, const char *);
 void gtags_delete_by_fidset(GTOP *, const unsigned char *, int);
 const char *gtags_first(GTOP *, const char *, int);
