Index: htags/anchor.c
===================================================================
RCS file: /cvsroot/global/global/htags/anchor.c,v
retrieving revision 1.16
diff -u -r1.16 anchor.c
--- htags/anchor.c	10 May 2005 05:17:52 -0000	1.16
+++ htags/anchor.c	5 Aug 2005 13:44:19 -0000
@@ -34,6 +34,15 @@
 #include "anchor.h"
 #include "htags.h"
 
+struct anchor_input {
+	STRBUF *command;
+	FILE *ip;
+	STRBUF *ib;
+	char *ctags_x;
+	SPLIT ptable;
+};
+
+static struct anchor_input anchor_input[GTAGLIM - GTAGS];
 static struct anchor *table;
 static VARRAY *vb;
 
@@ -57,6 +66,88 @@
 static struct anchor *CURRENTDEF;
 
 /*
+ * anchor_pathlist_limit: determine the maximum length of the list of paths.
+ */
+int
+anchor_pathlist_limit()
+{
+	int limit, db, max = 0;
+	STRBUF *comline = strbuf_open(0);
+
+	limit = exec_line_limit();
+	for (db = GTAGS; db < GTAGLIM; db++) {
+		if (!symbol && db == GSYMS)
+			continue;
+		strbuf_reset(comline);
+		if (!getconfs(dbname(db), comline))
+			die("cannot get parser for %s.", dbname(db));
+		if (strbuf_getlen(comline) > max)
+			max = strbuf_getlen(comline);
+	}
+	strbuf_close(comline);
+	limit -= max + 40;
+	if (limit < 0)
+		limit = 0;
+	return limit;
+}
+/*
+ * anchor_prepare: setup input stream.
+ *
+ *	i)	path_list	\0 separated list of paths
+ */
+void
+anchor_prepare(path_list)
+	STRBUF *path_list;
+{
+	int db;
+	struct anchor_input *input;
+	STRBUF *comline = strbuf_open(0);
+
+	for (db = GTAGS; db < GTAGLIM; db++) {
+		if (!symbol && db == GSYMS)
+			continue;
+		input = &anchor_input[db - GTAGS];
+		input->command = strbuf_open(0);
+		input->ib = strbuf_open(MAXBUFLEN);
+		strbuf_reset(comline);
+		if (!getconfs(dbname(db), comline))
+			die("cannot get parser for %s.", dbname(db));
+		makecommand(strbuf_value(comline), path_list, input->command);
+		/*
+		 * We assume that the output of gtags-parser is sorted by the path.
+		 * About the other parsers, it is not guaranteed, so we sort it
+		 * using external sort command (gnusort).
+		 */
+		if (locatestring(strbuf_value(comline), "gtags-parser", MATCH_FIRST) == NULL)
+			strbuf_puts(input->command, "| gnusort -k3,3");
+		input->ip = popen(strbuf_value(input->command), "r");
+		if (input->ip == NULL)
+			die("cannot execute command '%s'.", strbuf_value(input->command));
+		if (input->ctags_x != NULL) {
+			recover(&input->ptable);
+			die("The output of parser is illegal.\n%s", input->ctags_x);
+		}
+		input->ctags_x = strbuf_fgets(input->ib, input->ip, STRBUF_NOCRLF);
+		if (input->ctags_x == NULL) {
+			if (pclose(input->ip) != 0)
+				die("command '%s' failed.", strbuf_value(input->command));
+			strbuf_close(input->ib);
+			strbuf_close(input->command);
+			continue;
+		}
+		if (split(input->ctags_x, 4, &input->ptable) < 4) {
+			recover(&input->ptable);
+			die("too small number of parts in anchor_prepare().\n'%s'", input->ctags_x);
+		}
+		if (input->ptable.part[PART_PATH].start[0] != '.'
+		 || input->ptable.part[PART_PATH].start[1] != '/') {
+			recover(&input->ptable);
+			die("The output of parser is illegal.\n%s", input->ctags_x);
+		}
+	}
+	strbuf_close(comline);
+}
+/*
  * anchor_load: load anchor table
  *
  *	i)	file	file name
@@ -65,10 +156,7 @@
 anchor_load(file)
 	const char *file;
 {
-	char command[MAXFILLEN];
-	const char *options[] = {NULL, "", "r", "s"};
-	STRBUF *sb = strbuf_open(0);
-	FILE *ip;
+	struct anchor_input *input;
 	int i, db;
 
 	FIRST = LAST = 0;
@@ -80,34 +168,26 @@
 		varray_reset(vb);
 
 	for (db = GTAGS; db < GTAGLIM; db++) {
-		char *ctags_x;
-
 		if (!symbol && db == GSYMS)
 			continue;
+		input = &anchor_input[db - GTAGS];
 		/*
-		 * Setup input stream.
+		 * Read from input stream until it reaches end of file
+		 * or the line of another file appears.
 		 */
-		snprintf(command, sizeof(command), "global -fn%s \"%s\"", options[db], file);
-		ip = popen(command, "r");
-		if (ip == NULL)
-			die("cannot execute command '%s'.", command);
-		while ((ctags_x = strbuf_fgets(sb, ip, STRBUF_NOCRLF)) != NULL) {
-			SPLIT ptable;
+		while (input->ctags_x != NULL
+		       && strcmp(input->ptable.part[PART_PATH].start + 2, file) == 0) {
 			struct anchor *a;
 			int type;
 
-			if (split(ctags_x, 4, &ptable) < 4) {
-				recover(&ptable);
-				die("too small number of parts in anchor_load().\n'%s'", ctags_x);
-			}
 			if (db == GTAGS) {
 				const char *p;
 
-				for (p = ptable.part[PART_LINE].start; *p && isspace((unsigned char)*p); p++)
+				for (p = input->ptable.part[PART_LINE].start; *p && isspace((unsigned char)*p); p++)
 					;
 				if (!*p) {
-					recover(&ptable);
-					die("The output of global is illegal.\n%s", p);
+					recover(&input->ptable);
+					die("The output of parser is illegal.\n%s", input->ctags_x);
 				}
 				type = 'D';
 				if (*p == '#') {
@@ -127,16 +207,30 @@
 				type = 'Y';
 			/* allocate an entry */
 			a = varray_append(vb);
-			a->lineno = atoi(ptable.part[PART_LNO].start);
+			a->lineno = atoi(input->ptable.part[PART_LNO].start);
 			a->type = type;
 			a->done = 0;
-			settag(a, ptable.part[PART_TAG].start);
-			recover(&ptable);
+			settag(a, input->ptable.part[PART_TAG].start);
+			recover(&input->ptable);
+			input->ctags_x = strbuf_fgets(input->ib, input->ip, STRBUF_NOCRLF);
+			if (input->ctags_x == NULL) {
+				if (pclose(input->ip) != 0)
+					die("command '%s' failed.", strbuf_value(input->command));
+				strbuf_close(input->ib);
+				strbuf_close(input->command);
+				break;
+			}
+			if (split(input->ctags_x, 4, &input->ptable) < 4) {
+				recover(&input->ptable);
+				die("too small number of parts in anchor_load().\n'%s'", input->ctags_x);
+			}
+			if (input->ptable.part[PART_PATH].start[0] != '.'
+			 || input->ptable.part[PART_PATH].start[1] != '/') {
+				recover(&input->ptable);
+				die("The output of parser is illegal.\n%s", input->ctags_x);
+			}
 		}
-		if (pclose(ip) != 0)
-			die("command '%s' failed.", command);
 	}
-	strbuf_close(sb);
 	if (vb->length == 0) {
 		table = NULL;
 	} else {
Index: htags/anchor.h
===================================================================
RCS file: /cvsroot/global/global/htags/anchor.h,v
retrieving revision 1.9
diff -u -r1.9 anchor.h
--- htags/anchor.h	10 May 2005 05:17:52 -0000	1.9
+++ htags/anchor.h	5 Aug 2005 13:44:19 -0000
@@ -20,6 +20,8 @@
 #ifndef _ANCHOR_H_
 #define _ANCHOR_H_
 
+#include "strbuf.h"
+
 /*
  * Anchor table.
  *
@@ -65,6 +67,8 @@
 #define A_HELP		7
 #define A_LIMIT		8
 
+int anchor_pathlist_limit(void);
+void anchor_prepare(STRBUF *);
 void anchor_load(const char *);
 void anchor_unload(void);
 struct anchor *anchor_first();
Index: htags/htags.c
===================================================================
RCS file: /cvsroot/global/global/htags/htags.c,v
retrieving revision 1.66
diff -u -r1.66 htags.c
--- htags/htags.c	16 May 2005 13:48:31 -0000	1.66
+++ htags/htags.c	5 Aug 2005 13:44:19 -0000
@@ -43,6 +43,7 @@
 #include "getopt.h"
 #include "regex.h"
 #include "global.h"
+#include "anchor.h"
 #include "cache.h"
 #include "common.h"
 #include "htags.h"
@@ -754,6 +755,32 @@
 	fclose(op);
 }
 /*
+ * Wrapper of src2html()
+ */
+static int
+do_src2html(path_list, count, total)
+	STRBUF *path_list;
+	int count;
+	int total;
+{
+	int notsource;
+	char path[MAXPATHLEN];
+	const char *_ = strbuf_value(path_list);
+	const char *end = _ + strbuf_getlen(path_list);
+	const char *p;
+
+	while (_ < end) {
+		notsource = *_++;
+		count++;
+		message(" [%d/%d] converting %s", count, total, _);
+		p = path2fid(_);
+		snprintf(path, sizeof(path), "%s/%s/%s.%s", distpath, SRCS, p, HTML);
+		src2html(_, path, notsource);
+		_ += strlen(_) + 1;
+	}
+	return count;
+}
+/*
  * makehtml: make html files
  *
  *	i)	total	number of files.
@@ -765,8 +792,11 @@
 	FILE *ip;
 	const char *_;
 	int count = 0;
-	char command[MAXFILLEN], path[MAXPATHLEN];
+	char command[MAXFILLEN];
 	STRBUF *sb = strbuf_open(0);
+	STRBUF *alllist = strbuf_open(0);
+	STRBUF *srclist = strbuf_open(0);
+	int path_list_max = anchor_pathlist_limit();
 
 	if (other_files && !dynamic)
 		snprintf(command, sizeof(command), "%s --other | gnusort -t / -k 2", findcom);
@@ -777,7 +807,6 @@
 		die("cannot execute command '%s'.", command);
 	while ((_ = strbuf_fgets(sb, ip, STRBUF_NOCRLF)) != NULL) {
 		int notsource = 0;
-		const char *p;
 
 		if (*_ == ' ') {
 			if (!other_files)
@@ -789,18 +818,40 @@
 				continue;
 			}
 			notsource = 1;
+		} else {
+			/*
+			 * Execute parser when path name collects enough.
+			 * Though the path_list is \0 separated list of string,
+			 * we can think its length equals to the length of
+			 * argument string because each \0 can be replaced
+			 * with a blank.
+			 */
+			if (strbuf_getlen(srclist)) {
+				if (strbuf_getlen(srclist) + strlen(_) > path_list_max) {
+					anchor_prepare(srclist);
+					count = do_src2html(alllist, count, total);
+					strbuf_reset(srclist);
+					strbuf_reset(alllist);
+				}
+			}
+			/*
+			 * Add a path to the path list.
+			 */
+			strbuf_puts0(srclist, _);
 		}
-		count++;
-		_ += 2;
-		p = _;
-		message(" [%d/%d] converting %s", count, total, p);
-		p = path2fid(p);
-		snprintf(path, sizeof(path), "%s/%s/%s.%s", distpath, SRCS, p, HTML);
-		src2html(_, path, notsource);
+		strbuf_putc(alllist, notsource);
+		strbuf_puts0(alllist, _ + 2);
+	}
+	if (strbuf_getlen(alllist)) {
+		if (strbuf_getlen(srclist))
+			anchor_prepare(srclist);
+		do_src2html(alllist, count, total);
 	}
 	if (pclose(ip) != 0)
 		die("cannot traverse directory.(%s)", command);
 	strbuf_close(sb);
+	strbuf_close(alllist);
+	strbuf_close(srclist);
 }
 /*
  * copy file.
