Index: gtags.conf.in
===================================================================
RCS file: /sources/global/global/gtags.conf.in,v
retrieving revision 1.19
diff -u -p -r1.19 gtags.conf.in
--- gtags.conf.in	10 Mar 2008 09:50:11 -0000	1.19
+++ gtags.conf.in	20 Oct 2009 14:06:25 -0000
@@ -50,6 +50,14 @@ gtags:\
 	:GRTAGS=gtags-parser -r %s:\
 	:GSYMS=gtags-parser -s %s:
 #
+# 2-pass mode (experimental)
+#
+gtags-2pass:\
+	:tc=common:\
+	:GTAGS=gtags-parser %s:\
+	:GRTAGS=gtags-parser --both-ref-and-sym %s:\
+	:use_2pass_parser:
+#
 # [Exuberant Ctags]
 #
 # This ctags is distributed as a part of Vim editor.
Index: global/global.c
===================================================================
RCS file: /sources/global/global/global/global.c,v
retrieving revision 1.198
diff -u -p -r1.198 global.c
--- global/global.c	29 Jan 2009 09:30:09 -0000	1.198
+++ global/global.c	20 Oct 2009 14:06:26 -0000
@@ -874,7 +874,16 @@ parsefile(int argc, char **argv, const c
 	STRBUF *path_list = strbuf_open(MAXPATHLEN);
 	XARGS *xp;
 	char *ctags_x;
+	int skip_defined = 0, skip_undefined = 0;
 
+	if (getconfb("use_2pass_parser")) {
+		if (db == GRTAGS) {
+			skip_undefined = 1;
+		} else if (db == GSYMS) {
+			skip_defined = 1;
+			db = GRTAGS;
+		}
+	}
 	/*
 	 * teach parser where is dbpath.
 	 */
@@ -950,6 +959,10 @@ parsefile(int argc, char **argv, const c
 					recover(&ptable);
 					die("too small number of parts.\n'%s'", ctags_x);
 				}
+				if (skip_defined || skip_undefined) {
+					if (defined(ptable.part[PART_TAG].start) ? skip_defined : skip_undefined)
+						continue;
+				}
 				if (strcmp(curpath, ptable.part[PART_PATH].start)) {
 					strlimcpy(curpath, ptable.part[PART_PATH].start, sizeof(curpath));
 					convert_put(cv, curpath);
@@ -958,6 +971,17 @@ parsefile(int argc, char **argv, const c
 			}
 		} else {
 			while ((ctags_x = xargs_read(xp)) != NULL) {
+				if (skip_defined || skip_undefined) {
+					SPLIT ptable;
+
+					if (split((char *)ctags_x, 4, &ptable) < 4) {
+						recover(&ptable);
+						die("too small number of parts.\n'%s'", ctags_x);
+					}
+					if (defined(ptable.part[PART_TAG].start) ? skip_defined : skip_undefined)
+						continue;
+					recover(&ptable);
+				}
 				convert_put(cv, ctags_x);
 				count++;
 			}
Index: gtags/gtags.c
===================================================================
RCS file: /sources/global/global/gtags/gtags.c,v
retrieving revision 1.221
diff -u -p -r1.221 gtags.c
--- gtags/gtags.c	10 Oct 2009 06:37:05 -0000	1.221
+++ gtags/gtags.c	20 Oct 2009 14:06:26 -0000
@@ -90,6 +90,7 @@ int convert_type = PATH_RELATIVE;
 
 int extractmethod;
 int total;
+int two_pass_mode;
 
 static void
 usage(void)
@@ -400,6 +401,8 @@ main(int argc, char **argv)
 	openconf();
 	if (getconfb("extractmethod"))
 		extractmethod = 1;
+	if (getconfb("use_2pass_parser"))
+		two_pass_mode = 1;
 	strbuf_reset(sb);
 	/*
 	 * Pass the following information to gtags-parser(1)
@@ -440,7 +443,8 @@ main(int argc, char **argv)
  	 * create GTAGS, GRTAGS and GSYMS
 	 */
 	for (db = GTAGS; db < GTAGLIM; db++) {
-
+		if (two_pass_mode && db == GSYMS)
+			continue;
 		strbuf_reset(sb);
 		/*
 		 * get parser for db. (gtags-parser by default)
@@ -450,21 +454,28 @@ main(int argc, char **argv)
 		if (!usable(strmake(strbuf_value(sb), " \t")))
 			die("Parser '%s' not found or not executable.", strmake(strbuf_value(sb), " \t"));
 		if (vflag)
-			fprintf(stderr, "[%s] Creating '%s'.\n", now(), dbname(db));
+			fprintf(stderr, "[%s] Creating '%s'.\n", now(),
+				(two_pass_mode && db == GRTAGS) ? "GRTAGS and GSYMS" : dbname(db));
 		createtags(dbpath, cwd, db);
 		strbuf_reset(sb);
-		if (db == GTAGS) {
+		switch (db) {
+		case GTAGS:
 			if (getconfs("GTAGS_extra", sb))
 				if (system(strbuf_value(sb)))
 					fprintf(stderr, "GTAGS_extra command failed: %s\n", strbuf_value(sb));
-		} else if (db == GRTAGS) {
+			break;
+		case GRTAGS:
 			if (getconfs("GRTAGS_extra", sb))
 				if (system(strbuf_value(sb)))
 					fprintf(stderr, "GRTAGS_extra command failed: %s\n", strbuf_value(sb));
-		} else if (db == GSYMS) {
+			if (!two_pass_mode)
+				break;
+			/* FALLTHROUGH */
+		case GSYMS:
 			if (getconfs("GSYMS_extra", sb))
 				if (system(strbuf_value(sb)))
 					fprintf(stderr, "GSYMS_extra command failed: %s\n", strbuf_value(sb));
+			break;
 		}
 	}
 	/*
@@ -648,6 +659,8 @@ normal_update:
 		int db;
 
 		for (db = GTAGS; db < GTAGLIM; db++) {
+			if (two_pass_mode && db == GSYMS)
+				continue;
 			/*
 			 * GTAGS needed at least.
 			 */
@@ -655,7 +668,8 @@ normal_update:
 			    && !test("f", makepath(dbpath, dbname(db), NULL)))
 				continue;
 			if (vflag)
-				fprintf(stderr, "[%s] Updating '%s'.\n", now(), dbname(db));
+				fprintf(stderr, "[%s] Updating '%s'.\n", now(),
+					(two_pass_mode && db == GRTAGS) ? "GRTAGS and GSYMS" : dbname(db));
 			updatetags(dbpath, root, deleteset, addlist, db);
 		}
 		updated = 1;
@@ -664,7 +678,7 @@ normal_update:
 		const char *start, *end, *p;
 
 		if (vflag)
-			fprintf(stderr, "[%s] Updating '%s'.\n", now(), dbname(0));
+			fprintf(stderr, "[%s] Updating '%s'.\n", now(), dbname(GPATH));
 		gpath_open(dbpath, 2);
 		if (strbuf_getlen(deletelist) > 0) {
 			start = strbuf_value(deletelist);
@@ -731,7 +745,7 @@ verbose_updatetags(char *path, int seqno
 void
 updatetags(const char *dbpath, const char *root, IDSET *deleteset, STRBUF *addlist, int db)
 {
-	GTOP *gtop;
+	GTOP *gtop, *gtop2 = NULL;
 	STRBUF *comline = strbuf_open(0);
 	int seqno;
 
@@ -747,6 +761,11 @@ updatetags(const char *dbpath, const cha
 	if (!getconfs(dbname(db), comline))
 		die("cannot get tag command. (%s)", dbname(db));
 	gtop = gtags_open(dbpath, root, db, GTAGS_MODIFY, 0);
+	/*
+	 * On 2-pass mode, update GRTAGS and GSYMS concurrently.
+	 */
+	if (two_pass_mode && db == GRTAGS)
+		gtop2 = gtags_open(dbpath, root, GSYMS, GTAGS_MODIFY, 0);
 	if (vflag) {
 		char fid[32];
 		const char *path;
@@ -762,13 +781,18 @@ updatetags(const char *dbpath, const cha
 			fprintf(stderr, " [%d/%d] deleting tags of %s\n", seqno++, total, path + 2);
 		}
 	}
-	if (!idset_empty(deleteset))
+	if (!idset_empty(deleteset)) {
 		gtags_delete(gtop, deleteset);
+		if (gtop2 != NULL)
+			gtags_delete(gtop2, deleteset);
+	}
 	gtop->flags = 0;
 	if (extractmethod)
 		gtop->flags |= GTAGS_EXTRACTMETHOD;
 	if (debug)
 		gtop->flags |= GTAGS_DEBUG;
+	if (gtop2 != NULL)
+		gtop2->flags = gtop->flags;
 	/*
 	 * Compact format requires the tag records of the same file are
 	 * consecutive. We assume that the output of gtags-parser and
@@ -810,11 +834,16 @@ updatetags(const char *dbpath, const cha
 				else
 					p = tag;
 			}
-			gtags_put(gtop, p, ctags_x);
+			if (gtop2 == NULL || defined(p))
+				gtags_put(gtop, p, ctags_x);
+			else
+				gtags_put(gtop2, p, ctags_x);
 		}
 		total = xargs_close(xp);
 	}
 	gtags_close(gtop);
+	if (gtop2 != NULL)
+		gtags_close(gtop2);
 	strbuf_close(comline);
 }
 /*
@@ -839,7 +868,7 @@ verbose_createtags(char *path, int seqno
 void
 createtags(const char *dbpath, const char *root, int db)
 {
-	GTOP *gtop;
+	GTOP *gtop, *gtop2 = NULL;
 	XARGS *xp;
 	char *ctags_x;
 	STRBUF *comline = strbuf_open(0);
@@ -864,6 +893,13 @@ createtags(const char *dbpath, const cha
 	if (debug)
 		gtop->flags |= GTAGS_DEBUG;
 	/*
+	 * On 2-pass mode, create GRTAGS and GSYMS concurrently.
+	 */
+	if (two_pass_mode && db == GRTAGS) {
+		gtop2 = gtags_open(dbpath, root, GSYMS, GTAGS_CREATE, cflag ? GTAGS_COMPACT : 0);
+		gtop2->flags = gtop->flags;
+	}
+	/*
 	 * Compact format requires the tag records of the same file are
 	 * consecutive. We assume that the output of gtags-parser and
 	 * any plug-in parsers are consecutive for each file.
@@ -908,11 +944,16 @@ createtags(const char *dbpath, const cha
 			else
 				p = tag;
 		}
-		gtags_put(gtop, p, ctags_x);
+		if (gtop2 == NULL || defined(p))
+			gtags_put(gtop, p, ctags_x);
+		else
+			gtags_put(gtop2, p, ctags_x);
 	}
 	total = xargs_close(xp);
 	find_close();
 	gtags_close(gtop);
+	if (gtop2 != NULL)
+		gtags_close(gtop2);
 	strbuf_close(comline);
 }
 /*
Index: gtags-parser/C.c
===================================================================
RCS file: /sources/global/global/gtags-parser/C.c,v
retrieving revision 1.11
diff -u -p -r1.11 C.c
--- gtags-parser/C.c	10 Nov 2008 14:13:44 -0000	1.11
+++ gtags-parser/C.c	20 Oct 2009 14:06:26 -0000
@@ -44,9 +44,9 @@
 #include "c_res.h"
 
 static void C_family(const char *, int);
-static void process_attribute(int);
-static int function_definition(int, char *);
-static void condition_macro(int, int);
+static void process_attribute(void);
+static int function_definition(char *);
+static void condition_macro(int);
 static int seems_datatype(const char *);
 
 #define IS_TYPE_QUALIFIER(c)	((c) == C_CONST || (c) == C_RESTRICT || (c) == C_VOLATILE)
@@ -91,13 +91,13 @@ C(const char *file)
 /*
  *	i)	file	source file
  *	i)	type	TYPE_C, TYPE_YACC, TYPE_LEX
+ *	gi)	target	DEF, REF, SYM or REF_SYM
  */
 static void
 C_family(const char *file, int type)
 {
 	int c, cc;
 	int savelevel;
-	int target;
 	int startmacro, startsharp;
 	const char *interested = "{}=;";
 	STRBUF *sb = strbuf_open(0);
@@ -116,7 +116,6 @@ C_family(const char *file, int type)
 
 	level = piflevel = externclevel = 0;
 	savelevel = -1;
-	target = (sflag) ? SYM : (rflag) ? REF : DEF;
 	startmacro = startsharp = 0;
 
 	if (!opentoken(file))
@@ -131,7 +130,7 @@ C_family(const char *file, int type)
 		case SYMBOL:		/* symbol	*/
 			if (inC && peekc(0) == '('/* ) */) {
 				if (isnotfunction(token)) {
-					if (target == REF && defined(token))
+					if ((target == REF && defined(token)) || target == REF_SYM)
 						PUT(token, lineno, sp);
 				} else if (level > 0 || startmacro) {
 					if (target == REF) {
@@ -140,6 +139,8 @@ C_family(const char *file, int type)
 					} else if (target == SYM) {
 						if (!defined(token))
 							PUT(token, lineno, sp);
+					} else if (target == REF_SYM) {
+						PUT(token, lineno, sp);
 					}
 				} else if (level == 0 && !startmacro && !startsharp) {
 					char arg1[MAXTOKEN], savetok[MAXTOKEN], *saveline;
@@ -164,13 +165,13 @@ C_family(const char *file, int type)
 					 *
 					 * We should assume the first argument as a function name instead of 'SCM_DEFINE'.
 					 */
-					if (function_definition(target, arg1)) {
+					if (function_definition(arg1)) {
 						if (!strcmp(savetok, "SCM_DEFINE") && *arg1)
 							strlimcpy(savetok, arg1, sizeof(savetok));
 						if (target == DEF)
 							PUT(savetok, savelineno, saveline);
 					} else {
-						if (target == REF && defined(savetok))
+						if ((target == REF && defined(savetok)) || target == REF_SYM)
 							PUT(savetok, savelineno, saveline);
 					}
 				}
@@ -181,6 +182,8 @@ C_family(const char *file, int type)
 				} else if (target == SYM) {
 					if (!defined(token))
 						PUT(token, lineno, sp);
+				} else if (target == REF_SYM) {
+					PUT(token, lineno, sp);
 				}
 			}
 			break;
@@ -275,7 +278,7 @@ C_family(const char *file, int type)
 				if (target == DEF)
 					PUT(token, lineno, sp);
 				while ((c = nexttoken("()", c_reserved_word)) != EOF && c != '\n' && c != /* ( */ ')')
-					if (c == SYMBOL && target == SYM)
+					if (c == SYMBOL && (target == SYM || target == REF_SYM))
 						PUT(token, lineno, sp);
 				if (c == '\n')
 					pushbacktoken();
@@ -302,7 +305,7 @@ C_family(const char *file, int type)
 		case SHARP_ELIF:
 		case SHARP_ELSE:
 		case SHARP_ENDIF:
-			condition_macro(cc, target);
+			condition_macro(cc);
 			break;
 		case SHARP_SHARP:		/* ## */
 			(void)nexttoken(interested, c_reserved_word);
@@ -335,6 +338,8 @@ C_family(const char *file, int type)
 				} else if (target == SYM) {
 					if (!defined(token))
 						PUT(token, lineno, sp);
+				} else if (target == REF_SYM){
+					PUT(token, lineno, sp);
 				}
 				c = nexttoken(interested, c_reserved_word);
 			}
@@ -349,7 +354,7 @@ C_family(const char *file, int type)
 					case SHARP_ELIF:
 					case SHARP_ELSE:
 					case SHARP_ENDIF:
-						condition_macro(c, target);
+						condition_macro(c);
 						continue;
 					default:
 						break;
@@ -420,6 +425,8 @@ C_family(const char *file, int type)
 						} else if (target == SYM) {
 							if (!defined(token))
 								PUT(token, lineno, sp);
+						} else if (target == REF_SYM) {
+							PUT(token, lineno, sp);
 						}
 						c = nexttoken(interest_enum, c_reserved_word);
 					}
@@ -431,7 +438,7 @@ C_family(const char *file, int type)
 						case SHARP_ELIF:
 						case SHARP_ELSE:
 						case SHARP_ENDIF:
-							condition_macro(c, target);
+							condition_macro(c);
 							continue;
 						default:
 							break;
@@ -449,8 +456,9 @@ C_family(const char *file, int type)
 							if (c_ == C_ENUM) {
 								if (target == DEF && level > typedef_savelevel)
 									PUT(token, lineno, sp);
-								if (target == SYM && level == typedef_savelevel && !defined(token))
-									PUT(token, lineno, sp);
+								else if (level == typedef_savelevel)
+									if ((target == SYM && !defined(token)) || target == REF_SYM)
+										PUT(token, lineno, sp);
 							} else {
 								if (target == REF) {
 									if (level > typedef_savelevel && defined(token))
@@ -458,6 +466,8 @@ C_family(const char *file, int type)
 								} else if (target == SYM) {
 									if (!defined(token))
 										PUT(token, lineno, sp);
+								} else if (target == REF_SYM) {
+									PUT(token, lineno, sp);
 								} else if (target == DEF) {
 									/* save lastest token */
 									strlimcpy(savetok, token, sizeof(savetok));
@@ -475,7 +485,9 @@ C_family(const char *file, int type)
 				} else if (c == SYMBOL) {
 					if (target == REF && defined(token))
 						PUT(token, lineno, sp);
-					if (target == SYM && !defined(token))
+					else if (target == SYM && !defined(token))
+						PUT(token, lineno, sp);
+					else if (target == REF_SYM)
 						PUT(token, lineno, sp);
 				}
 				savetok[0] = 0;
@@ -487,7 +499,7 @@ C_family(const char *file, int type)
 					case SHARP_ELIF:
 					case SHARP_ELSE:
 					case SHARP_ENDIF:
-						condition_macro(c, target);
+						condition_macro(c);
 						continue;
 					default:
 						break;
@@ -498,12 +510,12 @@ C_family(const char *file, int type)
 						level--;
 					else if (c == SYMBOL) {
 						if (level > typedef_savelevel) {
-							if (target == SYM)
+							if (target == SYM || target == REF_SYM)
 								PUT(token, lineno, sp);
 						} else {
 							/* put latest token if any */
 							if (savetok[0]) {
-								if (target == SYM)
+								if (target == SYM || target == REF_SYM)
 									PUT(savetok, savelineno, sp);
 							}
 							/* save lastest token */
@@ -529,7 +541,7 @@ C_family(const char *file, int type)
 			}
 			break;
 		case C___ATTRIBUTE__:
-			process_attribute(target);
+			process_attribute();
 			break;
 		default:
 			break;
@@ -547,10 +559,10 @@ C_family(const char *file, int type)
 /*
  * process_attribute: skip attributes in __attribute__((...)).
  *
- *	r)	target type
+ *	gi)	target	DEF, REF, SYM or REF_SYM
  */
 static void
-process_attribute(int target)
+process_attribute(void)
 {
 	int brace = 0;
 	int c;
@@ -570,6 +582,8 @@ process_attribute(int target)
 			} else if (target == SYM) {
 				if (!defined(token))
 					PUT(token, lineno, sp);
+			} else if (target == REF_SYM) {
+				PUT(token, lineno, sp);
 			}
 		}
 		if (brace == 0)
@@ -579,12 +593,12 @@ process_attribute(int target)
 /*
  * function_definition: return if function definition or not.
  *
- *	i)	target	DEF, REF, SYMBOL
+ *	gi)	target	DEF, REF, SYM or REF_SYM
  *	o)	arg1	the first argument
  *	r)	target type
  */
 static int
-function_definition(int target, char arg1[MAXTOKEN])
+function_definition(char arg1[MAXTOKEN])
 {
 	int c;
 	int brace_level, isdefine;
@@ -599,7 +613,7 @@ function_definition(int target, char arg
 		case SHARP_ELIF:
 		case SHARP_ELSE:
 		case SHARP_ENDIF:
-			condition_macro(c, target);
+			condition_macro(c);
 			continue;
 		default:
 			break;
@@ -622,6 +636,8 @@ function_definition(int target, char arg
 			} else if (target == SYM) {
 				if (!seems_datatype(token) || !defined(token))
 					PUT(token, lineno, sp);
+			} else if (target == REF_SYM) {
+				PUT(token, lineno, sp);
 			}
 		}
 	}
@@ -636,10 +652,10 @@ function_definition(int target, char arg
 		case SHARP_ELIF:
 		case SHARP_ELSE:
 		case SHARP_ENDIF:
-			condition_macro(c, target);
+			condition_macro(c);
 			continue;
 		case C___ATTRIBUTE__:
-			process_attribute(target);
+			process_attribute();
 			continue;
 		default:
 			break;
@@ -670,6 +686,8 @@ function_definition(int target, char arg
 			} else if (target == SYM) {
 				if (!seems_datatype(token) || !defined(token))
 					PUT(token, lineno, sp);
+			} else if (target == REF_SYM) {
+				PUT(token, lineno, sp);
 			}
 		}
 	}
@@ -680,10 +698,10 @@ function_definition(int target, char arg
  * condition_macro: 
  *
  *	i)	cc	token
- *	i)	target	current target
+ *	gi)	target	DEF, REF, SYM or REF_SYM
  */
 static void
-condition_macro(int cc, int target)
+condition_macro(int cc)
 {
 	cur = &stack[piflevel];
 	if (cc == SHARP_IFDEF || cc == SHARP_IFNDEF || cc == SHARP_IF) {
@@ -731,13 +749,15 @@ condition_macro(int cc, int target)
 		}
 	}
 	while ((cc = nexttoken(NULL, c_reserved_word)) != EOF && cc != '\n') {
-                if (cc == SYMBOL && strcmp(token, "defined") != 0) {
+		if (cc == SYMBOL && strcmp(token, "defined") != 0) {
 			if (target == REF) {
 				if (defined(token))
-		                        PUT(token, lineno, sp);
+					PUT(token, lineno, sp);
 			} else if (target == SYM) {
 				if (!defined(token))
-		                	PUT(token, lineno, sp);
+			        	PUT(token, lineno, sp);
+			} else if (target == REF_SYM) {
+				PUT(token, lineno, sp);
 			}
 		}
 	}
Index: gtags-parser/Cpp.c
===================================================================
RCS file: /sources/global/global/gtags-parser/Cpp.c,v
retrieving revision 1.15
diff -u -p -r1.15 Cpp.c
--- gtags-parser/Cpp.c	4 Jan 2009 09:19:14 -0000	1.15
+++ gtags-parser/Cpp.c	20 Oct 2009 14:06:26 -0000
@@ -44,10 +44,10 @@
 #include "token.h"
 #include "cpp_res.h"
 
-static void process_attribute(int);
-static int function_definition(int);
+static void process_attribute(void);
+static int function_definition(void);
 static int seems_datatype(const char *);
-static void condition_macro(int, int);
+static void condition_macro(int);
 
 #define MAXCOMPLETENAME 1024            /* max size of complete name of class */
 #define MAXCLASSSTACK   100             /* max size of class stack */
@@ -75,7 +75,6 @@ Cpp(const char *file)
 {
 	int c, cc;
 	int savelevel;
-	int target;
 	int startclass, startthrow, startmacro, startsharp, startequal;
 	char classname[MAXTOKEN];
 	char completename[MAXCOMPLETENAME];
@@ -94,7 +93,6 @@ Cpp(const char *file)
 	stack[0].level = 0;
 	level = classlevel = piflevel = namespacelevel = 0;
 	savelevel = -1;
-	target = (sflag) ? SYM : (rflag) ? REF : DEF;
 	startclass = startthrow = startmacro = startsharp = startequal = 0;
 
 	if (!opentoken(file))
@@ -109,11 +107,11 @@ Cpp(const char *file)
 		switch (cc) {
 		case SYMBOL:		/* symbol	*/
 			if (startclass || startthrow) {
-				if (target == REF && defined(token))
+				if ((target == REF && defined(token)) || target == REF_SYM)
 					PUT(token, lineno, sp);
 			} else if (peekc(0) == '('/* ) */) {
 				if (isnotfunction(token)) {
-					if (target == REF && defined(token))
+					if ((target == REF && defined(token)) || target == REF_SYM)
 						PUT(token, lineno, sp);
 				} else if (level > stack[classlevel].level || startequal || startmacro) {
 					if (target == REF) {
@@ -122,6 +120,8 @@ Cpp(const char *file)
 					} else if (target == SYM) {
 						if (!defined(token))
 							PUT(token, lineno, sp);
+					} else if (target == REF_SYM) {
+						PUT(token, lineno, sp);
 					}
 				} else if (level == stack[classlevel].level && !startmacro && !startsharp && !startequal) {
 					char savetok[MAXTOKEN], *saveline;
@@ -131,12 +131,12 @@ Cpp(const char *file)
 					strbuf_reset(sb);
 					strbuf_puts(sb, sp);
 					saveline = strbuf_value(sb);
-					if (function_definition(target)) {
+					if (function_definition()) {
 						/* ignore constructor */
 						if (target == DEF && strcmp(stack[classlevel].classname, savetok))
 							PUT(savetok, savelineno, saveline);
 					} else {
-						if (target == REF && defined(savetok))
+						if ((target == REF && defined(savetok)) || target == REF_SYM)
 							PUT(savetok, savelineno, saveline);
 					}
 				}
@@ -147,6 +147,8 @@ Cpp(const char *file)
 				} else if (target == SYM) {
 					if (!defined(token))
 						PUT(token, lineno, sp);
+				} else if (target == REF_SYM) {
+					PUT(token, lineno, sp);
 				}
 			}
 			break;
@@ -157,7 +159,7 @@ Cpp(const char *file)
 			 */
 			if ((c = nexttoken(interested, cpp_reserved_word)) == CPP_NAMESPACE) {
 				if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL) {
-					if (target == REF)
+					if (target == REF || target == REF_SYM)
 						PUT(token, lineno, sp);
 				} else {
 					if (wflag)
@@ -300,7 +302,7 @@ Cpp(const char *file)
 				if (target == DEF)
 					PUT(token, lineno, sp);
 				while ((c = nexttoken("()", cpp_reserved_word)) != EOF && c != '\n' && c != /* ( */ ')')
-					if (c == SYMBOL && target == SYM)
+					if (c == SYMBOL && (target == SYM || target == REF_SYM))
 						PUT(token, lineno, sp);
 				if (c == '\n')
 					pushbacktoken();
@@ -327,14 +329,14 @@ Cpp(const char *file)
 		case SHARP_ELIF:
 		case SHARP_ELSE:
 		case SHARP_ENDIF:
-			condition_macro(cc, target);
+			condition_macro(cc);
 			break;
 		case SHARP_SHARP:		/* ## */
 			(void)nexttoken(interested, cpp_reserved_word);
 			break;
 		case CPP_NEW:
 			if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL)
-				if (target == REF && defined(token))
+				if ((target == REF && defined(token)) || target == REF_SYM)
 					PUT(token, lineno, sp);
 			break;
 		case CPP_STRUCT:
@@ -351,6 +353,8 @@ Cpp(const char *file)
 				} else if (target == SYM) {
 					if (!defined(token))
 						PUT(token, lineno, sp);
+				} else if (target == REF_SYM) {
+					PUT(token, lineno, sp);
 				}
 				c = nexttoken(interested, cpp_reserved_word);
 			}
@@ -365,7 +369,7 @@ Cpp(const char *file)
 					case SHARP_ELIF:
 					case SHARP_ELSE:
 					case SHARP_ENDIF:
-						condition_macro(c, target);
+						condition_macro(c);
 						continue;
 					default:
 						break;
@@ -395,7 +399,7 @@ Cpp(const char *file)
 						if (--level == 0)
 							break;
 					} else if (c == SYMBOL) {
-						if (target == SYM)
+						if (target == SYM || target == REF_SYM)
 							PUT(token, lineno, sp);
 					}
 				}
@@ -411,7 +415,7 @@ Cpp(const char *file)
 				} else if (c == ';') {
 					break;
 				} else if (c == SYMBOL) {
-					if (target == SYM)
+					if (target == SYM || target == REF_SYM)
 						PUT(token, lineno, sp);
 				}
 			}
@@ -475,6 +479,8 @@ Cpp(const char *file)
 						} else if (target == SYM) {
 							if (!defined(token))
 								PUT(token, lineno, sp);
+						} else if (target == REF_SYM) {
+							PUT(token, lineno, sp);
 						}
 						c = nexttoken(interest_enum, cpp_reserved_word);
 					}
@@ -486,7 +492,7 @@ Cpp(const char *file)
 						case SHARP_ELIF:
 						case SHARP_ELSE:
 						case SHARP_ENDIF:
-							condition_macro(c, target);
+							condition_macro(c);
 							continue;
 						default:
 							break;
@@ -504,7 +510,7 @@ Cpp(const char *file)
 							if (c_ == CPP_ENUM) {
 								if (target == DEF && level > typedef_savelevel)
 									PUT(token, lineno, sp);
-								if (target == SYM && level == typedef_savelevel)
+								if ((target == SYM || target == REF_SYM) && level == typedef_savelevel)
 									PUT(token, lineno, sp);
 							} else {
 								if (target == REF) {
@@ -513,6 +519,8 @@ Cpp(const char *file)
 								} else if (target == SYM) {
 									if (!defined(token))
 										PUT(token, lineno, sp);
+								} else if (target == REF_SYM) {
+									PUT(token, lineno, sp);
 								} else if (target == DEF) {
 									/* save lastest token */
 									strlimcpy(savetok, token, sizeof(savetok));
@@ -530,7 +538,9 @@ Cpp(const char *file)
 				} else if (c == SYMBOL) {
 					if (target == REF && defined(token))
 						PUT(token, lineno, sp);
-					if (target == SYM && !defined(token))
+					else if (target == SYM && !defined(token))
+						PUT(token, lineno, sp);
+					else if (target == REF_SYM)
 						PUT(token, lineno, sp);
 				}
 				savetok[0] = 0;
@@ -542,7 +552,7 @@ Cpp(const char *file)
 					case SHARP_ELIF:
 					case SHARP_ELSE:
 					case SHARP_ENDIF:
-						condition_macro(c, target);
+						condition_macro(c);
 						continue;
 					default:
 						break;
@@ -553,12 +563,12 @@ Cpp(const char *file)
 						level--;
 					else if (c == SYMBOL) {
 						if (level > typedef_savelevel) {
-							if (target == SYM)
+							if (target == SYM || target == REF_SYM)
 								PUT(token, lineno, sp);
 						} else {
 							/* put latest token if any */
 							if (savetok[0]) {
-								if (target == SYM)
+								if (target == SYM || target == REF_SYM)
 									PUT(savetok, savelineno, sp);
 							}
 							/* save lastest token */
@@ -584,7 +594,7 @@ Cpp(const char *file)
 			}
 			break;
 		case CPP___ATTRIBUTE__:
-			process_attribute(target);
+			process_attribute();
 			break;
 		default:
 			break;
@@ -602,10 +612,10 @@ Cpp(const char *file)
 /*
  * process_attribute: skip attributes in __attribute__((...)).
  *
- *	r)	target type
+ *	gi)	target	DEF, REF, SYM or REF_SYM
  */
 static void
-process_attribute(int target)
+process_attribute(void)
 {
 	int brace = 0;
 	int c;
@@ -625,6 +635,8 @@ process_attribute(int target)
 			} else if (target == SYM) {
 				if (!defined(token))
 					PUT(token, lineno, sp);
+			} else if (target == REF_SYM) {
+				PUT(token, lineno, sp);
 			}
 		}
 		if (brace == 0)
@@ -634,10 +646,11 @@ process_attribute(int target)
 /*
  * function_definition: return if function definition or not.
  *
+ *	gi)	target	DEF, REF, SYM or REF_SYM
  *	r)	target type
  */
 static int
-function_definition(int target)
+function_definition(void)
 {
 	int c;
 	int brace_level;
@@ -651,7 +664,7 @@ function_definition(int target)
 		case SHARP_ELIF:
 		case SHARP_ELSE:
 		case SHARP_ENDIF:
-			condition_macro(c, target);
+			condition_macro(c);
 			continue;
 		default:
 			break;
@@ -670,6 +683,8 @@ function_definition(int target)
 			} else if (target == SYM) {
 				if (!seems_datatype(token) || !defined(token))
 					PUT(token, lineno, sp);
+			} else if (target == REF_SYM) {
+				PUT(token, lineno, sp);
 			}
 		}
 	}
@@ -688,10 +703,10 @@ function_definition(int target)
 		case SHARP_ELIF:
 		case SHARP_ELSE:
 		case SHARP_ENDIF:
-			condition_macro(c, target);
+			condition_macro(c);
 			continue;
 		case CPP___ATTRIBUTE__:
-			process_attribute(target);
+			process_attribute();
 			continue;
 		default:
 			break;
@@ -717,6 +732,8 @@ function_definition(int target)
 			} else if (target == SYM) {
 				if (!seems_datatype(token) || !defined(token))
 					PUT(token, lineno, sp);
+			} else if (target == REF_SYM) {
+				PUT(token, lineno, sp);
 			}
 		}
 	}
@@ -727,10 +744,10 @@ function_definition(int target)
  * condition_macro: 
  *
  *	i)	cc	token
- *	i)	target	current target
+ *	gi)	target	DEF, REF, SYM or REF_SYM
  */
 static void
-condition_macro(int cc, int target)
+condition_macro(int cc)
 {
 	cur = &pifstack[piflevel];
 	if (cc == SHARP_IFDEF || cc == SHARP_IFNDEF || cc == SHARP_IF) {
@@ -778,13 +795,15 @@ condition_macro(int cc, int target)
 		}
 	}
 	while ((cc = nexttoken(NULL, cpp_reserved_word)) != EOF && cc != '\n') {
-                if (cc == SYMBOL && strcmp(token, "defined") != 0) {
+		if (cc == SYMBOL && strcmp(token, "defined") != 0) {
 			if (target == REF) {
 				if (defined(token))
-		                        PUT(token, lineno, sp);
+					PUT(token, lineno, sp);
 			} else if (target == SYM) {
 				if (!defined(token))
-		                	PUT(token, lineno, sp);
+					PUT(token, lineno, sp);
+			} else if (target == REF_SYM) {
+				PUT(token, lineno, sp);
 			}
 		}
 	}
Index: gtags-parser/asm_parse.y
===================================================================
RCS file: /sources/global/global/gtags-parser/asm_parse.y,v
retrieving revision 1.11
diff -u -p -r1.11 asm_parse.y
--- gtags-parser/asm_parse.y	8 Apr 2008 22:25:16 -0000	1.11
+++ gtags-parser/asm_parse.y	20 Oct 2009 14:06:26 -0000
@@ -49,7 +49,6 @@
 int yylex(void);
 void asm_initscan(void);
 
-int asm_target;
 const char *asm_input_file;
 STRBUF *asm_symtable;
 
@@ -83,26 +82,28 @@ input:	/* empty */
 
 line:	ASM_ENTRY '(' ASM_SYMBOL ')' error '\n'
 		{
-			if (asm_target == REF) {
+			if (target == DEF) {
+				PUT(GET_SYM($3), @3);
+			} else if (target == REF) {
 				char *sym = GET_SYM($1);
 
 				if (defined(sym))
 					PUT(sym, @1);
+			} else if (target == REF_SYM) {
+				PUT(GET_SYM($1), @1);
 			}
-			if (asm_target == DEF)
-				PUT(GET_SYM($3), @3);
 			strbuf_reset(asm_symtable);
 		}
 	| ASM_CALL ASM_SYMBOL error '\n'
 		{
-			if (asm_target == REF) {
+			if (target == REF || target == REF_SYM) {
 				char *sym = GET_SYM($2);
 
 				if (sym[0] == '_') {
 					int c = (unsigned char)sym[1];
 
 					if ((isalpha(c) || c == '_' || c >= 0x80)
-					    && defined(&sym[1]))
+					    && (target == REF_SYM || defined(&sym[1])))
 						PUT(&sym[1], @2);
 				}
 			}
@@ -110,7 +111,7 @@ line:	ASM_ENTRY '(' ASM_SYMBOL ')' error
 		}
 	| ASM_CALL ASM_EXT '(' ASM_SYMBOL ')' error '\n'
 		{
-			if (asm_target == REF) {
+			if (target == REF) {
 				char *sym;
 
 				sym = GET_SYM($2);
@@ -120,42 +121,45 @@ line:	ASM_ENTRY '(' ASM_SYMBOL ')' error
 				sym = GET_SYM($4);
 				if (defined(sym))
 					PUT(sym, @4);
+			} else if (target == REF_SYM) {
+				PUT(GET_SYM($2), @2);
+				PUT(GET_SYM($4), @4);
 			}
 			strbuf_reset(asm_symtable);
 		}
 	| "#define" ASM_SYMBOL error '\n'
 		{
-			if (asm_target == DEF)
+			if (target == DEF)
 				PUT(GET_SYM($2), @2);
 			strbuf_reset(asm_symtable);
 		}
 	| "#undef" ASM_SYMBOL error '\n'
 		{
-			if (asm_target == DEF)
+			if (target == DEF)
 				PUT(GET_SYM($2), @2);
 			strbuf_reset(asm_symtable);
 		}
 	| ASM_MACRO ASM_SYMBOL error '\n'
 		{
-			if (asm_target == DEF)
+			if (target == DEF)
 				PUT(GET_SYM($2), @2);
 			strbuf_reset(asm_symtable);
 		}
 	| ASM_LABEL ASM_MACRO error '\n'
 		{
-			if (asm_target == DEF)
+			if (target == DEF)
 				PUT(GET_SYM($1), @1);
 			strbuf_reset(asm_symtable);
 		}
 	| ASM_EQU ASM_SYMBOL ',' error '\n'
 		{
-			if (asm_target == DEF)
+			if (target == DEF)
 				PUT(GET_SYM($2), @2);
 			strbuf_reset(asm_symtable);
 		}
 	| ASM_LABEL ASM_EQU error '\n'
 		{
-			if (asm_target == DEF)
+			if (target == DEF)
 				PUT(GET_SYM($1), @1);
 			strbuf_reset(asm_symtable);
 		}
@@ -168,8 +172,6 @@ line:	ASM_ENTRY '(' ASM_SYMBOL ')' error
 void
 assembly(const char *file)
 {
-	asm_target = sflag ? SYM : rflag ? REF : DEF;
-
 	if (linetable_open(file) == -1)
 		die("'%s' cannot open.", file);
 	asm_input_file = file;
Index: gtags-parser/asm_scan.l
===================================================================
RCS file: /sources/global/global/gtags-parser/asm_scan.l,v
retrieving revision 1.13
diff -u -p -r1.13 asm_scan.l
--- gtags-parser/asm_scan.l	8 Apr 2008 22:25:16 -0000	1.13
+++ gtags-parser/asm_scan.l	20 Oct 2009 14:06:26 -0000
@@ -65,7 +65,6 @@
 	}								\
 } while (0)
 
-extern int asm_target;
 extern const char *asm_input_file;
 extern STRBUF *asm_symtable;
 
@@ -184,12 +183,14 @@ WORD		{ALPHA}{ALPHANUM}*
 			/* FALLTHROUGH */
 		case SHARP_IFDEF:
 		case SHARP_IFNDEF:
-			if (asm_target == REF) {
+			if (target == REF) {
 				if (defined(LEXTEXT))
 					PUT();
-			} else if (asm_target == SYM) {
+			} else if (target == SYM) {
 				if (!defined(LEXTEXT))
 					PUT();
+			} else if (target == REF_SYM) {
+				PUT();
 			}
 			break;
 		default:
Index: gtags-parser/gctags.c
===================================================================
RCS file: /sources/global/global/gtags-parser/gctags.c,v
retrieving revision 1.12
diff -u -p -r1.12 gctags.c
--- gtags-parser/gctags.c	18 Mar 2008 03:48:24 -0000	1.12
+++ gtags-parser/gctags.c	20 Oct 2009 14:06:26 -0000
@@ -59,13 +59,12 @@ int bflag;			/* -b: force level 1 block 
 int eflag;			/* -e: force level 1 block end */
 int nflag;			/* -n: doen't print tag */
 int qflag;			/* -q: quiet mode */
-int rflag;			/* -r: function reference */
-int sflag;			/* -s: collect symbols */
 int wflag;			/* -w: warning message */
 int vflag;			/* -v: verbose mode */
 int show_version;
 int show_help;
 int debug;
+int target = DEF;		/* DEF, REF, SYM, or REF_SYM */
 
 /*----------------------------------------------------------------------*/
 /* Parser switch                                                        */
@@ -148,6 +147,7 @@ static struct option const long_options[
 	{"warning", no_argument, NULL, 'w'},
 
 	/* long name only */
+	{"both-ref-and-sym", no_argument, &target, REF_SYM},
 	{"debug", no_argument, &debug, 1},
 	{"langmap", required_argument, NULL, 0},
 	{"version", no_argument, &show_version, 1},
@@ -184,12 +184,10 @@ main(int argc, char **argv)
 			qflag++;
 			break;
 		case 'r':
-			rflag++;
-			sflag = 0;
+			target = REF;
 			break;
 		case 's':
-			sflag++;
-			rflag = 0;
+			target = SYM;
 			break;
 		case 't':
 			break;
Index: gtags-parser/gctags.h
===================================================================
RCS file: /sources/global/global/gtags-parser/gctags.h,v
retrieving revision 1.6
diff -u -p -r1.6 gctags.h
--- gtags-parser/gctags.h	18 Mar 2008 03:48:24 -0000	1.6
+++ gtags-parser/gctags.h	20 Oct 2009 14:06:26 -0000
@@ -25,6 +25,7 @@
 #define DEF	1
 #define REF	2
 #define SYM	3
+#define REF_SYM	4	/* collect both reference snd symbol */
 
 #define NOTFUNCTION	".notfunction"
 #ifdef __DJGPP__
@@ -35,11 +36,10 @@
 extern int bflag;
 extern int eflag;
 extern int nflag;
-extern int rflag;
-extern int sflag;
 extern int vflag;
 extern int wflag;
 extern int debug;
+extern int target;
 
 #define PUT(tag, lno, line) do {					\
 	DBG_PRINT(level, line);						\
Index: gtags-parser/java.c
===================================================================
RCS file: /sources/global/global/gtags-parser/java.c,v
retrieving revision 1.7
diff -u -p -r1.7 java.c
--- gtags-parser/java.c	5 Jul 2007 06:52:00 -0000	1.7
+++ gtags-parser/java.c	20 Oct 2009 14:06:26 -0000
@@ -50,7 +50,6 @@ java(const char *file)
 {
 	int c;
 	int level;					/* brace level */
-	int target;
 	int startclass, startthrows, startequal;
 	char classname[MAXTOKEN];
 	char completename[MAXCOMPLETENAME];
@@ -67,7 +66,6 @@ java(const char *file)
 	stack[0].terminate = completename;
 	stack[0].level = 0;
 	level = classlevel = 0;
-	target = (sflag) ? SYM : ((rflag) ? REF : DEF);
 	startclass = startthrows = startequal = 0;
 
 	if (!opentoken(file))
@@ -82,17 +80,18 @@ java(const char *file)
 			if (c != SYMBOL)
 				break;
 			if (startclass || startthrows) {
-				if (target == REF && defined(token))
+				if ((target == REF && defined(token)) || target == REF_SYM)
 					PUT(token, lineno, sp);
 			} else if (peekc(0) == '('/* ) */) {
 				if (target == DEF && level == stack[classlevel].level && !startequal)
 					/* ignore constructor */
 					if (strcmp(stack[classlevel].classname, token))
 						PUT(token, lineno, sp);
-				if (target == REF && (level > stack[classlevel].level || startequal) && defined(token))
-					PUT(token, lineno, sp);
+				if (level > stack[classlevel].level || startequal)
+					if ((target == REF && defined(token)) || target == REF_SYM)
+						PUT(token, lineno, sp);
 			} else {
-				if (target == SYM)
+				if (target == SYM || target == REF_SYM)
 					PUT(token, lineno, sp);
 			}
 			break;
@@ -148,10 +147,10 @@ java(const char *file)
 		case JAVA_NEW:
 		case JAVA_INSTANCEOF:
 			while ((c = nexttoken(interested, java_reserved_word)) == SYMBOL && peekc(1) == '.')
-				if (target == SYM)
+				if (target == SYM || target == REF_SYM)
 					PUT(token, lineno, sp);
 			if (c == SYMBOL)
-				if (target == REF && defined(token))
+				if ((target == REF && defined(token)) || target == REF_SYM)
 					PUT(token, lineno, sp);
 			break;
 		case JAVA_THROWS:
Index: gtags-parser/php.l
===================================================================
RCS file: /sources/global/global/gtags-parser/php.l,v
retrieving revision 1.12
diff -u -p -r1.12 php.l
--- gtags-parser/php.l	5 Jul 2007 06:52:00 -0000	1.12
+++ gtags-parser/php.l	20 Oct 2009 14:06:26 -0000
@@ -281,7 +281,6 @@ void
 php(const char *file)
 {
 	int token;
-	int target = (sflag) ? SYM : (rflag) ? REF : DEF;
 
 	level = 0;
 	string = strbuf_open(0);
@@ -316,19 +315,19 @@ php(const char *file)
 			break;
 		case PHP_VARIABLE:
 			if (php_reserved_variable(LEXTEXT, LEXLENG)) {
-				if (target == SYM)
+				if (target == SYM || target == REF_SYM)
 					PUT(LEXTEXT, LEXLINENO, file);
 				if (LEXLEX() == PHP_LBRACK && LEXLEX() == PHP_STRING && LEXLEX() == PHP_RBRACK) {
 					char *str = strbuf_value(string);
 
 					if (strchr(str, '$') == 0)
-						if (target == SYM)
+						if (target == SYM || target == REF_SYM)
 							PUT(str, LEXLINENO, file);
 				}
 			} else if (!strcmp(LEXTEXT, "this")) {
 				;
 			} else {
-				if (target == SYM)
+				if (target == SYM || target == REF_SYM)
 					PUT(LEXTEXT, LEXLINENO, file);
 			}
 			break;
@@ -343,12 +342,14 @@ php(const char *file)
 			} else if (target == SYM) {
 				if (!defined(LEXTEXT))
 					PUT(LEXTEXT, LEXLINENO, file);
+			} else if (target == REF_SYM) {
+				PUT(LEXTEXT, LEXLINENO, file);
 			}
 			break;
 		case PHP_NEW:
 			if (LEXLEX() != PHP_TOKEN)
 				break;
-			if (target == REF)
+			if (target == REF || target == REF_SYM)
 				PUT(LEXTEXT, LEXLINENO, file);
 			break;
 		/*
@@ -365,6 +366,8 @@ php(const char *file)
 					} else if (target == SYM) {
 						if (!defined(LEXTEXT))
 							PUT(LEXTEXT, LEXLINENO, file);
+					} else if (target == REF_SYM) {
+						PUT(LEXTEXT, LEXLINENO, file);
 					}
 				}
 			}
