LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 0001-Mixing-with-anjuta-tags-https-git.gnome.org-browse-a.patch of Package ctags (Project home:michals:arduino)

From 504c9e52393b1a3620de00878043271812adb887 Mon Sep 17 00:00:00 2001
From: Federico Fissore <federico@fissore.org>
Date: Fri, 23 Jan 2015 15:36:29 +0100
Subject: [PATCH 01/19] Mixing with anjuta-tags
 https://git.gnome.org/browse/anjuta/tree/plugins/symbol-db/anjuta-tags

---
 .gitignore         |   5 +
 acconfig.h         | 127 +++++++++++++++++
 ant.c              |   4 +-
 c.c                | 145 +++++++++++++++++--
 config.h           | 275 ++++++++++++++++++++++++++++++++++++
 ctags-utils.c      |  41 ++++++
 ctags-utils.h      |  38 +++++
 ctags-visitor.vala | 400 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 ctags.h            |   2 +-
 eiffel.c           |  20 ++-
 entry.c            |   6 +
 entry.h            |   3 +-
 falcon.c           | 149 ++++++++++++++++++++
 flex.c             |  55 +++++++-
 gir.c              | 216 +++++++++++++++++++++++++++++
 lregex.c           |   4 +-
 make.c             |   4 +-
 options.c          |   6 +-
 options.h          |   1 +
 parsers.h          |  47 +++++++
 php.c              |  24 ++--
 python.c           |   8 +-
 sort.c             |   4 +-
 sql.c              | 278 ++++++++++++++++++++++++++++++++-----
 test-cmd-line      |   1 +
 tex.c              |  35 ++---
 vala.c             | 103 ++++++++++++++
 verilog.c          |   3 +-
 28 files changed, 1900 insertions(+), 104 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 acconfig.h
 create mode 100644 config.h
 create mode 100644 ctags-utils.c
 create mode 100644 ctags-utils.h
 create mode 100644 ctags-visitor.vala
 create mode 100644 falcon.c
 create mode 100644 gir.c
 create mode 100644 test-cmd-line
 create mode 100644 vala.c

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..868b69d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.o
+Makefile
+config.log
+config.status
+ctags
diff --git a/acconfig.h b/acconfig.h
new file mode 100644
index 0000000..8431027
--- /dev/null
+++ b/acconfig.h
@@ -0,0 +1,127 @@
+/*
+*   $Id: acconfig.h 318 2003-04-01 05:02:21Z darren $
+*
+*   Copyright (c) 1998-2003, Darren Hiebert
+*
+*   This source code is released for free distribution under the terms of the
+*   GNU General Public License.
+*
+*   This module contains input source for generating config.h.in
+*/
+
+/*  Package name.
+ */
+#undef PACKAGE
+
+/*  Package version.
+ */
+#undef VERSION
+
+/*  Define to the appropriate type if <time.h> does not define this.
+ */
+#undef clock_t
+
+/*  Define to long if <stdio.h> does not define this.
+ */
+#undef fpos_t
+
+/*  Define to the appropriate size for tmpnam() if <stdio.h> does not define
+ *  this.
+ */
+#undef L_tmpnam
+
+/*  Define this macro if the field "st_ino" exists in struct stat in
+ *  <sys/stat.h>.
+ *  */
+#undef HAVE_STAT_ST_INO
+
+/*  Define remove to unlink if you have unlink(), but not remove().
+ */
+#undef remove
+
+/*  Define this value used by fseek() appropriately if <stdio.h>
+ *  (or <unistd.h> on SunOS 4.1.x) does not define them.
+ */
+#undef SEEK_SET
+
+/*  Define as the maximum integer on your system if not defined <limits.h>.
+ */
+#undef INT_MAX
+
+/*  You can define this label to be a string containing the name of a
+ *  site-specific configuration file containing site-wide default options. The
+ *  files /etc/ctags.conf and /usr/local/etc/ctags.conf are already checked,
+ *  so only define one here if you need a file somewhere else.
+ */
+#undef CUSTOM_CONFIGURATION_FILE
+
+/*  Define this label if you want macro tags (defined lables) to use patterns
+ *  in the EX command by default (original ctags behavior is to use line
+ *  numbers).
+ */
+#undef MACROS_USE_PATTERNS
+
+/*  Define this as desired.
+ *    1:  Original ctags format
+ *    2:  Extended ctags format with extension flags in EX-style comment.
+ */
+#define DEFAULT_FILE_FORMAT	2
+
+/*  Define this label if your system supports starting scripts with a line of
+ *  the form "#! /bin/sh" to select the interpreter to use for the script.
+ */
+#undef SYS_INTERPRETER
+
+/*  Define this label if your system uses case-insensitive file names
+ */
+#undef CASE_INSENSITIVE_FILENAMES
+
+/*  Define this label to use the system sort utility (which is probably more
+ *  efficient) over the internal sorting algorithm.
+ */
+#ifndef INTERNAL_SORT
+# undef EXTERNAL_SORT
+#endif
+
+/* If you wish to change the directory in which temporary files are stored,
+ * define this label to the directory desired.
+ */
+#undef TMPDIR
+
+/* Define this label if regcomp() is broken.
+ */
+#undef REGCOMP_BROKEN
+
+/* Define this label if you wish to check the regcomp() function at run time
+ * for correct behavior. This function is currently broken on Cygwin.
+ */
+#undef CHECK_REGCOMP
+
+/*  This corrects the problem of missing prototypes for certain functions
+ *  in some GNU installations (e.g. SunOS 4.1.x).
+ */
+#undef __USE_FIXED_PROTOTYPES__
+
+/*  Define this is you have a prototype for putenv() in <stdlib.h>, but
+ *  doesn't declare its argument as "const char *".
+ */
+#undef NON_CONST_PUTENV_PROTOTYPE
+
+/*  If you receive error or warning messages indicating that you are missing
+ *  a prototype for, or a type mismatch using, one of the following functions,
+ *  define the appropriate label and remake.
+ */
+#undef NEED_PROTO_REMOVE
+#undef NEED_PROTO_UNLINK
+#undef NEED_PROTO_MALLOC
+#undef NEED_PROTO_GETENV
+#undef NEED_PROTO_FGETPOS
+#undef NEED_PROTO_STAT
+#undef NEED_PROTO_LSTAT
+#undef NEED_PROTO_TRUNCATE
+#undef NEED_PROTO_FTRUNCATE
+
+/*----------------------------------------------------------------------------
+-	Lines below this are automatically generated by autoheader
+----------------------------------------------------------------------------*/
+/* @TOP@ */
diff --git a/ant.c b/ant.c
index eedfcec..bd01de4 100644
--- a/ant.c
+++ b/ant.c
@@ -24,9 +24,9 @@
 static void installAntRegex (const langType language)
 {
 	addTagRegex (language,
-		"^[ \t]*<[ \t]*project.*name=\"([^\"]+)\".*", "\\1", "p,project,projects", NULL);
+		"^[ \t]*<[ \t]*project[^>]+name=\"([^\"]+)\".*", "\\1", "p,project,projects", NULL);
 	addTagRegex (language,
-		"^[ \t]*<[ \t]*target.*name=\"([^\"]+)\".*", "\\1", "t,target,targets", NULL);
+		"^[ \t]*<[ \t]*target[^>]+name=\"([^\"]+)\".*", "\\1", "t,target,targets", NULL);
 }
 
 extern parserDefinition* AntParser ()
diff --git a/c.c b/c.c
index 0cf0a14..ccca3a4 100644
--- a/c.c
+++ b/c.c
@@ -48,7 +48,7 @@
 *   DATA DECLARATIONS
 */
 
-enum { NumTokens = 3 };
+enum { NumTokens = 15 };
 
 typedef enum eException {
 	ExceptionNone, ExceptionEOF, ExceptionFormattingError,
@@ -119,6 +119,8 @@ typedef enum eTokenType {
 	TOKEN_PAREN_NAME,    /* a single name in parentheses */
 	TOKEN_SEMICOLON,     /* the semicolon character */
 	TOKEN_SPEC,          /* a storage class specifier, qualifier, type, etc. */
+	TOKEN_STAR,          /* pointer * detection */
+	TOKEN_AMPERSAND,	 /* ampersand & detection */
 	TOKEN_COUNT
 } tokenType;
 
@@ -259,6 +261,7 @@ static langType Lang_java;
 static langType Lang_vera;
 static vString *Signature;
 static boolean CollectingSignature;
+static vString *ReturnType;
 
 /* Number used to uniquely identify anonymous structs and unions. */
 static int AnonymousID = 0;
@@ -564,7 +567,7 @@ static const char *implementationString (const impType imp)
 /*
 *   Debugging functions
 */
-
+#define DEBUG
 #ifdef DEBUG
 
 #define boolString(c)   ((c) ? "TRUE" : "FALSE")
@@ -573,7 +576,7 @@ static const char *tokenString (const tokenType type)
 {
 	static const char *const names [] = {
 		"none", "args", "}", "{", "colon", "comma", "double colon", "keyword",
-		"name", "package", "paren-name", "semicolon", "specifier"
+		"name", "package", "paren-name", "semicolon", "specifier", "star", "ampersand"
 	};
 	Assert (sizeof (names) / sizeof (names [0]) == TOKEN_COUNT);
 	Assert ((int) type < TOKEN_COUNT);
@@ -637,13 +640,13 @@ static void __unused__ pt (tokenInfo *const token)
 static void __unused__ ps (statementInfo *const st)
 {
 	unsigned int i;
-	printf ("scope: %s   decl: %s   gotName: %s   gotParenName: %s\n",
+	printf ("scope: %s   decl: %s   gotName: %s   gotParenName: %s isPointer: %s\n",
 		scopeString (st->scope), declString (st->declaration),
-		boolString (st->gotName), boolString (st->gotParenName));
+		boolString (st->gotName), boolString (st->gotParenName), boolString (st->isPointer));
 	printf ("haveQualifyingName: %s\n", boolString (st->haveQualifyingName));
 	printf ("access: %s   default: %s\n", accessString (st->member.access),
 		accessString (st->member.accessDefault));
-	printf ("token  : ");
+	printf ("active token  : ");
 	pt (activeToken (st));
 	for (i = 1  ;  i < (unsigned int) NumTokens  ;  ++i)
 	{
@@ -982,8 +985,15 @@ static void addOtherFields (tagEntryInfo* const tag, const tagType type,
 		case TAG_FUNCTION:
 		case TAG_METHOD:
 		case TAG_PROTOTYPE:
-			if (vStringLength (Signature) > 0)
+			if (vStringLength (Signature) > 0) 
+			{
 				tag->extensionFields.signature = vStringValue (Signature);
+			}
+
+			if (vStringLength (ReturnType) > 0) 
+			{				
+				tag->extensionFields.returnType = vStringValue (ReturnType);
+			}
 		case TAG_CLASS:
 		case TAG_ENUM:
 		case TAG_ENUMERATOR:
@@ -1156,7 +1166,7 @@ static void makeTag (const tokenInfo *const token,
 
 		findScopeHierarchy (scope, st);
 		addOtherFields (&e, type, st, scope, typeRef);
-
+		
 		makeTagEntry (&e);
 		makeExtraTagEntry (type, &e, scope);
 		vStringDelete (scope);
@@ -1377,6 +1387,8 @@ static void skipToMatch (const char *const pair)
 	{
 		if (CollectingSignature)
 			vStringPut (Signature, c);
+		
+
 		if (c == begin)
 		{
 			++matchLevel;
@@ -2073,7 +2085,7 @@ static void processAngleBracket (void)
 			cppUngetc (c);
 		}
 	} else {
-		cppUngetc (c);
+		cppUngetc (c);		
 	}
 }
 
@@ -2102,6 +2114,106 @@ static void parseJavaAnnotation (statementInfo *const st)
 	}
 }
 
+static void parseReturnType (statementInfo *const st)
+{
+	int i;
+	int lower_bound;
+	tokenInfo * finding_tok;
+	
+	/* FIXME TODO: if java language must be supported then impement this here
+	 * removing the current FIXME */
+	if (!isLanguage (Lang_c) && !isLanguage (Lang_cpp))
+	{		
+		return;
+	}
+	
+	vStringClear (ReturnType);	
+
+	finding_tok = prevToken (st, 1);
+	
+	if (isType (finding_tok, TOKEN_NONE))
+		return;
+	
+	finding_tok = prevToken (st, 2);
+		
+	if (finding_tok->type == TOKEN_DOUBLE_COLON)
+	{
+		/* get the total number of double colons */
+		int j;
+		int num_colons = 0;
+
+		/* we already are at 2nd token */
+		/* the +=2 means that colons are usually found at even places */
+		for (j = 2; j < NumTokens; j+=2)
+		{
+			tokenInfo *curr_tok;
+			curr_tok = prevToken (st, j);
+			if (curr_tok->type == TOKEN_DOUBLE_COLON)
+				num_colons++;
+			else
+				break;
+		}
+
+		/*printf ("FOUND colons %d\n", num_colons);*/
+		lower_bound = 2 * num_colons + 1;
+	}
+	else
+		lower_bound = 1;
+	
+	for (i = (unsigned int) NumTokens;  i > lower_bound;  i--)
+	{
+		tokenInfo * curr_tok;
+		curr_tok = prevToken (st, i);	
+
+		switch (curr_tok->type)
+		{
+			case TOKEN_PAREN_NAME:
+			case TOKEN_NONE:
+				continue;
+				break;
+			
+			case TOKEN_DOUBLE_COLON:
+				/* usually C++ class scope */
+				vStringCatS (ReturnType, "::");				
+				break;
+
+			case TOKEN_STAR:
+				/* pointers */
+				vStringPut (ReturnType, '*');
+				break;
+
+			case TOKEN_AMPERSAND:
+				/* references */
+				vStringPut (ReturnType, '&');
+				break;
+
+			case TOKEN_KEYWORD:
+				vStringPut (ReturnType, ' ');
+				
+			default:
+				vStringCat (ReturnType, curr_tok->name);
+				break;				
+		}
+	}
+
+	/* clear any white space from the front */
+	vStringStripLeading (ReturnType);
+
+	/* .. and from the tail too */
+	vStringStripTrailing (ReturnType);
+
+	/* put and end marker */
+	vStringTerminate (ReturnType);
+
+	/*/
+	printf ("~~~~~ statement ---->\n");
+	ps (st);
+	printf ("NumTokens: %d\n", NumTokens);
+	printf ("FOUND ReturnType: %s\n", vStringValue (ReturnType));	
+	printf ("<~~~~~\n");
+	//*/
+}
+
 static int parseParens (statementInfo *const st, parenInfo *const info)
 {
 	tokenInfo *const token = activeToken (st);
@@ -2301,6 +2413,7 @@ static void analyzeParens (statementInfo *const st)
 
 		initParenInfo (&info);
 		parseParens (st, &info);
+		parseReturnType (st);
 		c = skipToNonWhite ();
 		cppUngetc (c);
 		if (info.invalidContents)
@@ -2536,9 +2649,15 @@ static void nextToken (statementInfo *const st)
 		switch (c)
 		{
 			case EOF: longjmp (Exception, (int) ExceptionEOF);  break;
-			case '(': analyzeParens (st);                       break;
+			/* analyze functions and co */
+			case '(': analyzeParens (st);						break;
 			case '<': processAngleBracket ();                   break;
-			case '*': st->haveQualifyingName = FALSE;           break;
+			case '*': 
+				st->haveQualifyingName = FALSE;
+				setToken (st, TOKEN_STAR);
+				break;
+			case '&': setToken (st, TOKEN_AMPERSAND);			break;
+				
 			case ',': setToken (st, TOKEN_COMMA);               break;
 			case ':': processColon (st);                        break;
 			case ';': setToken (st, TOKEN_SEMICOLON);           break;
@@ -2654,6 +2773,7 @@ static void nest (statementInfo *const st, const unsigned int nestLevel)
 		case DECL_FUNCTION:
 		case DECL_TASK:
 			st->inFunction = TRUE;
+
 			/* fall through */
 		default:
 			if (includeTag (TAG_LOCAL, FALSE))
@@ -2765,6 +2885,7 @@ static void createTags (const unsigned int nestLevel,
 
 		nextToken (st);
 		token = activeToken (st);
+		
 		if (isType (token, TOKEN_BRACE_CLOSE))
 		{
 			if (nestLevel > 0)
@@ -2801,6 +2922,7 @@ static boolean findCTags (const unsigned int passCount)
 	Assert (passCount < 3);
 	cppInit ((boolean) (passCount > 1), isLanguage (Lang_csharp));
 	Signature = vStringNew ();
+	ReturnType = vStringNew ();
 
 	exception = (exception_t) setjmp (Exception);
 	retry = FALSE;
@@ -2817,6 +2939,7 @@ static boolean findCTags (const unsigned int passCount)
 		}
 	}
 	vStringDelete (Signature);
+	vStringDelete (ReturnType);
 	cppTerminate ();
 	return retry;
 }
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..d33e48b
--- /dev/null
+++ b/config.h
@@ -0,0 +1,275 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+/*
+*   $Id: acconfig.h 318 2003-04-01 05:02:21Z darren $
+*
+*   Copyright (c) 1998-2003, Darren Hiebert
+*
+*   This source code is released for free distribution under the terms of the
+*   GNU General Public License.
+*
+*   This module contains input source for generating config.h.in
+*/
+
+/*  Package name.
+ */
+/* #undef PACKAGE */
+
+/*  Package version.
+ */
+/* #undef VERSION */
+
+/*  Define to the appropriate type if <time.h> does not define this.
+ */
+/* #undef clock_t */
+
+/*  Define to long if <stdio.h> does not define this.
+ */
+/* #undef fpos_t */
+
+/*  Define to the appropriate size for tmpnam() if <stdio.h> does not define
+ *  this.
+ */
+/* #undef L_tmpnam */
+
+/*  Define this macro if the field "st_ino" exists in struct stat in
+ *  <sys/stat.h>.
+ *  */
+#define HAVE_STAT_ST_INO 1
+
+/*  Define remove to unlink if you have unlink(), but not remove().
+ */
+/* #undef remove */
+
+/*  Define this value used by fseek() appropriately if <stdio.h>
+ *  (or <unistd.h> on SunOS 4.1.x) does not define them.
+ */
+/* #undef SEEK_SET */
+
+/*  Define as the maximum integer on your system if not defined <limits.h>.
+ */
+/* #undef INT_MAX */
+
+/*  You can define this label to be a string containing the name of a
+ *  site-specific configuration file containing site-wide default options. The
+ *  files /etc/ctags.conf and /usr/local/etc/ctags.conf are already checked,
+ *  so only define one here if you need a file somewhere else.
+ */
+/* #undef CUSTOM_CONFIGURATION_FILE */
+
+/*  Define this label if you want macro tags (defined lables) to use patterns
+ *  in the EX command by default (original ctags behavior is to use line
+ *  numbers).
+ */
+/* #undef MACROS_USE_PATTERNS */
+
+/*  Define this as desired.
+ *    1:  Original ctags format
+ *    2:  Extended ctags format with extension flags in EX-style comment.
+ */
+#define DEFAULT_FILE_FORMAT 2
+
+/*  Define this label if your system supports starting scripts with a line of
+ *  the form "#! /bin/sh" to select the interpreter to use for the script.
+ */
+#define SYS_INTERPRETER 1
+
+/*  Define this label if your system uses case-insensitive file names
+ */
+/* #undef CASE_INSENSITIVE_FILENAMES */
+
+/*  Define this label to use the system sort utility (which is probably more
+ *  efficient) over the internal sorting algorithm.
+ */
+#ifndef INTERNAL_SORT
+# define EXTERNAL_SORT 1
+#endif
+
+/* If you wish to change the directory in which temporary files are stored,
+ * define this label to the directory desired.
+ */
+#define TMPDIR "/tmp"
+
+/* Define this label if regcomp() is broken.
+ */
+/* #undef REGCOMP_BROKEN */
+
+/* Define this label if you wish to check the regcomp() function at run time
+ * for correct behavior. This function is currently broken on Cygwin.
+ */
+/* #undef CHECK_REGCOMP */
+
+/*  This corrects the problem of missing prototypes for certain functions
+ *  in some GNU installations (e.g. SunOS 4.1.x).
+ */
+/* #undef __USE_FIXED_PROTOTYPES__ */
+
+/*  Define this is you have a prototype for putenv() in <stdlib.h>, but
+ *  doesn't declare its argument as "const char *".
+ */
+/* #undef NON_CONST_PUTENV_PROTOTYPE */
+
+/*  If you receive error or warning messages indicating that you are missing
+ *  a prototype for, or a type mismatch using, one of the following functions,
+ *  define the appropriate label and remake.
+ */
+/* #undef NEED_PROTO_REMOVE */
+/* #undef NEED_PROTO_UNLINK */
+/* #undef NEED_PROTO_MALLOC */
+/* #undef NEED_PROTO_GETENV */
+/* #undef NEED_PROTO_FGETPOS */
+/* #undef NEED_PROTO_STAT */
+/* #undef NEED_PROTO_LSTAT */
+/* #undef NEED_PROTO_TRUNCATE */
+/* #undef NEED_PROTO_FTRUNCATE */
+
+/*----------------------------------------------------------------------------
+-	Lines below this are automatically generated by autoheader
+----------------------------------------------------------------------------*/
+
+/* Define to 1 if you have the `chmod' function. */
+/* #undef HAVE_CHMOD */
+
+/* Define to 1 if you have the `chsize' function. */
+/* #undef HAVE_CHSIZE */
+
+/* Define to 1 if you have the `clock' function. */
+#define HAVE_CLOCK 1
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fgetpos' function. */
+#define HAVE_FGETPOS 1
+
+/* Define to 1 if you have the `findfirst' function. */
+/* #undef HAVE_FINDFIRST */
+
+/* Define to 1 if you have the `fnmatch' function. */
+#define HAVE_FNMATCH 1
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#define HAVE_FNMATCH_H 1
+
+/* Define to 1 if you have the `ftruncate' function. */
+/* #undef HAVE_FTRUNCATE */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `opendir' function. */
+#define HAVE_OPENDIR 1
+
+/* Define to 1 if you have the `putenv' function. */
+/* #undef HAVE_PUTENV */
+
+/* Define to 1 if you have the `regcomp' function. */
+#define HAVE_REGCOMP 1
+
+/* Define to 1 if you have the `remove' function. */
+#define HAVE_REMOVE 1
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the <stat.h> header file. */
+/* #undef HAVE_STAT_H */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strnicmp' function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the <sys/dir.h> header file. */
+#define HAVE_SYS_DIR_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/times.h> header file. */
+#define HAVE_SYS_TIMES_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `tempnam' function. */
+/* #undef HAVE_TEMPNAM */
+
+/* Define to 1 if you have the `times' function. */
+/* #undef HAVE_TIMES */
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the `truncate' function. */
+#define HAVE_TRUNCATE 1
+
+/* Define to 1 if you have the <types.h> header file. */
+/* #undef HAVE_TYPES_H */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `_findfirst' function. */
+/* #undef HAVE__FINDFIRST */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `long int' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
diff --git a/ctags-utils.c b/ctags-utils.c
new file mode 100644
index 0000000..0db7745
--- /dev/null
+++ b/ctags-utils.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Massimo Cora' 2010 <maxcvs@email.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+ */
+
+#include "ctags-utils.h"
+
+void
+get_file_pos (gint line, fpos_t *fpos, FILE *f)
+{
+	vString * str = vStringNew ();
+	gint i;
+	g_assert (fseek (f, 0, SEEK_SET) == 0);
+
+	for (i = 0;i < line - 1; i++)
+	{
+		if (readLine (str, f) == NULL)
+		{
+			vStringDelete (str);
+			return;
+		}
+	}
+
+	vStringDelete (str);
+	g_assert (fgetpos (f, fpos) == 0);
+}
+
+
diff --git a/ctags-utils.h b/ctags-utils.h
new file mode 100644
index 0000000..41283bf
--- /dev/null
+++ b/ctags-utils.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Massimo Cora' 2010 <maxcvs@email.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+ */
+
+#include "general.h"	/* must always come first */
+#include "read.h"
+#include <assert.h>
+#include <glib.h>
+#include <string.h>
+
+
+/**
+ * IMPORTANT NOTE 
+ *
+ * This file should contain functions/helpers that aren't strictly 
+ * ctags-standardized and that can be used in extra parsers (i.e. parser
+ * not included with ctags distribution).
+ * Doing so and keeping separate standard/extra files should make 
+ * an upgrade of ctags easier.
+ */
+ 
+
+void get_file_pos (gint line, fpos_t *fpos, FILE *f);
+
diff --git a/ctags-visitor.vala b/ctags-visitor.vala
new file mode 100644
index 0000000..f7c050a
--- /dev/null
+++ b/ctags-visitor.vala
@@ -0,0 +1,400 @@
+/*
+ * ctags-visitor.vala
+ *
+ * Copyright 2008, 2010 Abderrahim Kitouni <a.kitouni@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+using Vala;
+
+public struct CTagsEntry {
+	public int line_number;
+	public string name;
+	public string kind_name;
+	public char kind;
+	public string access;
+	public string implementation;
+	public string inheritance;
+	public string scope[2];
+	public string signature;
+	public string typeref;
+	public string returntype;
+}
+
+class DummyReport : Report {
+	public override void warn (SourceReference? source, string message) {}
+	public override void err (SourceReference? source, string message) {}
+}
+
+[CCode (has_target=false)]
+public delegate void CTagsEntryMaker (CTagsEntry entry);
+
+public class CTagsVisitor : CodeVisitor {
+	Parser vala_parser;
+	Genie.Parser genie_parser;
+	GLib.List<CTagsEntry?> taglist;
+	public CTagsVisitor () {
+		vala_parser = new Parser();
+		genie_parser = new Genie.Parser();
+	}
+	/* helper functions */
+	static string get_access (Symbol sym) {
+		switch (sym.access) {
+		case SymbolAccessibility.PRIVATE : return "private";
+		case SymbolAccessibility.INTERNAL : return "internal";
+		case SymbolAccessibility.PROTECTED : return "protected";
+		case SymbolAccessibility.PUBLIC : return "public";
+		}
+		assert_not_reached ();
+	}
+	static string to_string (Iterable<DataType> seq, string sep = ",") {
+		var str = new StringBuilder();
+		var first = true;
+		foreach (var type in seq) {
+			if(first) {
+				first = false;
+			} else {
+				str.append(sep);
+			}
+			str.append(type.to_qualified_string());
+		}
+		return str.str;
+	}
+	static string? implementation (Symbol sym) {
+		var list = new GLib.List<string>();
+
+		if (sym is Vala.Signal) {
+			var sig = (Vala.Signal)sym;
+			if (sig.is_virtual)
+				list.append("virtual");
+		} else if (sym is Class) {
+			var cls = (Class)sym;
+			if (cls.is_abstract)
+				list.append("abstract");
+		} else if (sym is Method) {
+			var meth = (Method)sym;
+			if (meth.is_abstract)
+				list.append("abstract");
+			else if (meth.is_virtual)
+				list.append("virtual");
+		} else if (sym is Property) {
+			var prop = (Property)sym;
+			if (prop.is_abstract)
+				list.append("abstract");
+			else if (prop.is_virtual)
+				list.append("virtual");
+		} else
+			return_val_if_reached(null);
+
+		var ret = new StringBuilder();
+		var first = true;
+		foreach (var str in list) {
+			if(first) {
+				first = false;
+			} else {
+				ret.append(",");
+			}
+			ret.append(str);
+		}
+		return ret.str;
+	}
+	static string signature (Vala.List<Vala.Parameter> parameter) {
+		var ret = new StringBuilder("(");
+		var first = true;
+		foreach (var p in parameter) {
+			if(first) {
+				first = false;
+			} else {
+				ret.append(",");
+			}
+			if (p.ellipsis) {
+				ret.append("...");
+			} else {
+				ret.append (p.variable_type.to_qualified_string());
+				ret.append (" ");
+				ret.append (p.name);
+			}
+		}
+		ret.append (")");
+		return ret.str;
+	}
+	static string[] scope (Symbol s) {
+		string scope[2];
+		var par = s.parent_symbol;
+		if (par != null && par.name != null) {
+			if (par is Class)
+				scope[0] = "class";
+			else if (par is Struct)
+				scope[0] = "struct";
+			else if (par is Interface)
+				scope[0] = "interface";
+			else
+				return scope;
+			scope[1] = par.name;
+		}
+		return scope;
+	}
+	/*static void print_tag(CTagsEntry en) {
+		stdout.printf("%s: %s at %d\n", en.name, en.kind_name, en.line_number);
+	}*/
+
+	public override void visit_source_file (SourceFile source_file) {
+		source_file.accept_children (this);
+	}
+
+	public override void visit_class (Class cl) {
+		var entry = CTagsEntry();
+
+		entry.line_number = cl.source_reference.begin.line;
+		entry.name = cl.name;
+		entry.kind_name = "class";
+		entry.kind = 'c';
+		entry.access = get_access (cl);
+		entry.implementation = implementation(cl);
+		entry.inheritance = to_string(cl.get_base_types(), ",");
+		entry.scope = scope (cl);
+
+		taglist.append(entry);
+//		print_tag(entry);
+		cl.accept_children(this);
+	}
+	public override void visit_struct (Struct st) {
+		var entry = CTagsEntry();
+		entry.line_number = st.source_reference.begin.line;
+		entry.name = st.name;
+		entry.kind_name = "struct";
+		entry.kind = 's';
+		entry.access = get_access (st);
+		entry.scope = scope (st);
+
+		taglist.append(entry);
+//		print_tag(entry);
+		st.accept_children(this);
+	}
+	public override void visit_interface (Interface iface) {
+		var entry = CTagsEntry();
+
+		entry.line_number = iface.source_reference.begin.line;
+		entry.name = iface.name;
+		entry.kind_name = "interface";
+		entry.kind = 'i';
+		entry.access = get_access (iface);
+		entry.inheritance = to_string(iface.get_prerequisites());
+		entry.scope = scope (iface);
+
+		taglist.append(entry);
+//		print_tag(entry);
+		iface.accept_children(this);
+	}
+
+	public override void visit_enum (Vala.Enum en) {
+		var entry = CTagsEntry();
+
+		entry.line_number = en.source_reference.begin.line;
+		entry.name = en.name;
+		entry.kind_name = "enum";
+		entry.kind = 'e';
+		entry.access = get_access (en);
+		entry.scope = scope (en);
+
+		taglist.append(entry);
+//		print_tag(entry);
+		en.accept_children(this);
+	}
+	public override void visit_error_domain (ErrorDomain edomain) {
+		var entry = CTagsEntry();
+
+		entry.line_number = edomain.source_reference.begin.line;
+		entry.name = edomain.name;
+		entry.kind_name = "errordomain";
+		entry.kind = 'E';
+		entry.access = get_access (edomain);
+		entry.scope = scope (edomain);
+
+		taglist.append(entry);
+//		print_tag(entry);
+		edomain.accept_children(this);
+	}
+
+	public override void visit_enum_value (Vala.EnumValue ev) {
+		var entry = CTagsEntry();
+
+		entry.line_number = ev.source_reference.begin.line;
+		entry.name = ev.name;
+		entry.kind_name = "enumvalue";
+		entry.kind = 'v';
+		entry.access = get_access (ev);
+		entry.scope = scope (ev);
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_error_code (ErrorCode ecode) {
+		var entry = CTagsEntry();
+
+		//entry.line_number = ecode.source_reference.begin.line;
+		entry.name = ecode.name;
+		entry.kind_name = "errorcode";
+		entry.kind = 'r';
+		entry.access = get_access (ecode);
+		entry.scope = scope (ecode);
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+
+	public override void visit_delegate (Delegate d) {
+		var entry = CTagsEntry();
+
+		entry.line_number = d.source_reference.begin.line;
+		entry.name = d.name;
+		entry.kind_name = "delegate";
+		entry.kind = 'd';
+		entry.access = get_access (d);
+		entry.scope = scope (d);
+		entry.returntype = d.return_type.to_qualified_string();
+		entry.signature = signature(d.get_parameters());
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_signal (Vala.Signal sig) {
+		var entry = CTagsEntry();
+
+		entry.line_number = sig.source_reference.begin.line;
+		entry.name = sig.name;
+		entry.kind_name = "signal";
+		entry.kind = 'S';
+		entry.access = get_access (sig);
+		entry.implementation = implementation(sig);
+		entry.scope = scope (sig);
+		entry.returntype = sig.return_type.to_qualified_string();
+		entry.signature = signature(sig.get_parameters());
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_field (Field f) {
+		var entry = CTagsEntry();
+
+		entry.line_number = f.source_reference.begin.line;
+		entry.name = f.name;
+		entry.kind_name = "field";
+		entry.kind = 'f';
+		entry.access = get_access (f);
+		entry.scope = scope (f);
+		entry.typeref = f.variable_type.to_qualified_string();
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_constant (Constant c) {
+		var entry = CTagsEntry();
+
+		entry.line_number = c.source_reference.begin.line;
+		entry.name = c.name;
+		entry.kind_name = "field";
+		entry.kind = 'f';
+		entry.access = get_access (c);
+		entry.scope = scope (c);
+		entry.typeref = c.type_reference.to_qualified_string();
+  
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_property (Property prop) {
+		var entry = CTagsEntry();
+
+		entry.line_number = prop.source_reference.begin.line;
+		entry.name = prop.name;
+		entry.kind_name = "property";
+		entry.kind = 'p';
+		entry.access = get_access (prop);
+		entry.implementation = implementation(prop);
+		entry.scope = scope (prop);
+		entry.typeref = prop.property_type.to_qualified_string();
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+
+	public override void visit_method (Method m) {
+		var entry = CTagsEntry();
+
+		entry.line_number = m.source_reference.begin.line;
+		entry.name = m.name;
+		entry.kind_name = "method";
+		entry.kind = 'm';
+		entry.access = get_access (m);
+		entry.implementation = implementation(m);
+		entry.scope = scope (m);
+		entry.returntype = m.return_type.to_qualified_string();
+		entry.signature = signature(m.get_parameters());
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+
+	public override void visit_local_variable (LocalVariable local) {
+		var entry = CTagsEntry();
+
+		entry.line_number = local.source_reference.begin.line;
+		entry.name = local.name;
+		entry.kind_name = "local";
+		entry.kind = 'l';
+		entry.access = get_access (local);
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+
+	public void parse_vala (string filename, CTagsEntryMaker maker ) {
+		taglist = new GLib.List<CTagsEntry?>();
+		/* We create a context for every source file so that Parser.parse(context)
+		 * don't parse a file multiple times causing errors. Parser.parse_file(source_file)
+		 * assumes that Parser.context is the same as source_file.context anyway */
+		var context = new CodeContext();
+		context.report = new DummyReport();
+		var source_file = new SourceFile(context, filename.has_suffix("vapi") ? SourceFileType.PACKAGE : SourceFileType.SOURCE, filename);
+
+		CodeContext.push(context);
+		context.add_source_file(source_file);
+		vala_parser.parse(context);
+		context.accept(this);
+		foreach (var tagentry in taglist) {
+			maker(tagentry);
+		}
+		taglist = null;
+		CodeContext.pop();
+	}
+	public void parse_genie (string filename, CTagsEntryMaker maker ) {
+		taglist = new GLib.List<CTagsEntry?>();
+		var context = new CodeContext();
+		context.report = new DummyReport();
+		var source_file = new SourceFile(context, SourceFileType.SOURCE, filename);
+		context.add_source_file(source_file);
+
+		CodeContext.push(context);
+		genie_parser.parse(context);
+		context.accept(this);
+		foreach (var tagentry in taglist) {
+			maker(tagentry);
+		}
+		taglist = null;
+		CodeContext.pop();
+		}
+}
diff --git a/ctags.h b/ctags.h
index f8884af..fb5ca5b 100644
--- a/ctags.h
+++ b/ctags.h
@@ -15,7 +15,7 @@
 *   MACROS
 */
 #ifndef PROGRAM_VERSION
-# define PROGRAM_VERSION "5.8"
+# define PROGRAM_VERSION "Development"
 #endif
 #define PROGRAM_NAME      "Exuberant Ctags"
 #define PROGRAM_URL       "http://ctags.sourceforge.net"
diff --git a/eiffel.c b/eiffel.c
index b504ac3..e2f5a5c 100644
--- a/eiffel.c
+++ b/eiffel.c
@@ -1,5 +1,5 @@
 /*
-*   $Id: eiffel.c 706 2009-06-28 23:09:30Z dhiebert $
+*   $Id: eiffel.c 748 2009-11-06 02:44:42Z dhiebert $
 *
 *   Copyright (c) 1998-2002, Darren Hiebert
 *
@@ -53,13 +53,15 @@ typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
  */
 typedef enum eKeywordId {
 	KEYWORD_NONE = -1,
-	KEYWORD_alias, KEYWORD_all, KEYWORD_and, KEYWORD_as, KEYWORD_assign,
+	KEYWORD_alias, KEYWORD_all, KEYWORD_and,
+	KEYWORD_as, KEYWORD_assign, KEYWORD_attached,
 	KEYWORD_check, KEYWORD_class, KEYWORD_convert, KEYWORD_create,
 	KEYWORD_creation, KEYWORD_Current,
-	KEYWORD_debug, KEYWORD_deferred, KEYWORD_do, KEYWORD_else,
-	KEYWORD_elseif, KEYWORD_end, KEYWORD_ensure, KEYWORD_expanded,
-	KEYWORD_export, KEYWORD_external, KEYWORD_false, KEYWORD_feature,
-	KEYWORD_from, KEYWORD_frozen, KEYWORD_if, KEYWORD_implies,
+	KEYWORD_debug, KEYWORD_deferred, KEYWORD_detachable, KEYWORD_do,
+	KEYWORD_else, KEYWORD_elseif, KEYWORD_end, KEYWORD_ensure,
+	KEYWORD_expanded, KEYWORD_export, KEYWORD_external,
+	KEYWORD_false, KEYWORD_feature, KEYWORD_from, KEYWORD_frozen,
+	KEYWORD_if, KEYWORD_implies,
 	KEYWORD_indexing, KEYWORD_infix, KEYWORD_inherit, KEYWORD_inspect,
 	KEYWORD_invariant, KEYWORD_is, KEYWORD_like, KEYWORD_local,
 	KEYWORD_loop, KEYWORD_not, KEYWORD_obsolete, KEYWORD_old, KEYWORD_once,
@@ -154,6 +156,7 @@ static const keywordDesc EiffelKeywordTable [] = {
 	{ "and",            KEYWORD_and        },
 	{ "as",             KEYWORD_as         },
 	{ "assign",         KEYWORD_assign     },
+	{ "attached",       KEYWORD_attached   },
 	{ "check",          KEYWORD_check      },
 	{ "class",          KEYWORD_class      },
 	{ "convert",        KEYWORD_convert    },
@@ -162,6 +165,7 @@ static const keywordDesc EiffelKeywordTable [] = {
 	{ "current",        KEYWORD_Current    },
 	{ "debug",          KEYWORD_debug      },
 	{ "deferred",       KEYWORD_deferred   },
+	{ "detachable",     KEYWORD_detachable },
 	{ "do",             KEYWORD_do         },
 	{ "else",           KEYWORD_else       },
 	{ "elseif",         KEYWORD_elseif     },
@@ -870,7 +874,9 @@ static boolean parseType (tokenInfo *const token)
 	}
 	else
 	{
-		if (isKeyword (id, KEYWORD_expanded))
+		if (isKeyword (id, KEYWORD_attached) ||
+		    isKeyword (id, KEYWORD_detachable) ||
+		    isKeyword (id, KEYWORD_expanded))
 		{
 			copyToken (id, token);
 			readToken (token);
diff --git a/entry.c b/entry.c
index 3890e50..28bfe07 100644
--- a/entry.c
+++ b/entry.c
@@ -761,6 +761,11 @@ static int addExtensionFields (const tagEntryInfo *const tag)
 		length += fprintf (TagFile.fp, "%s\tsignature:%s", sep,
 				tag->extensionFields.signature);
 
+	if (Option.extensionFields.returnType &&
+			tag->extensionFields.returnType != NULL)
+		length += fprintf (TagFile.fp, "%s\treturntype:%s", sep,
+				tag->extensionFields.returnType);
+	
 	return length;
 #undef sep
 }
@@ -836,6 +841,7 @@ extern void initTagEntry (tagEntryInfo *const e, const char *const name)
 {
 	Assert (File.source.name != NULL);
 	memset (e, 0, sizeof (tagEntryInfo));
+
 	e->lineNumberEntry = (boolean) (Option.locate == EX_LINENUM);
 	e->lineNumber      = getSourceLineNumber ();
 	e->language        = getSourceLanguageName ();
diff --git a/entry.h b/entry.h
index 2365c50..323c1c5 100644
--- a/entry.h
+++ b/entry.h
@@ -72,7 +72,8 @@ typedef struct sTagEntryInfo {
 		const char* inheritance;
 		const char* scope [2];    /* value and key */
 		const char* signature;
-
+		const char* returnType;
+		
 		/* type (union/struct/etc.) and name for a variable or typedef. */
 		const char* typeRef [2];  /* e.g., "struct" and struct name */
 
diff --git a/falcon.c b/falcon.c
new file mode 100644
index 0000000..2730462
--- /dev/null
+++ b/falcon.c
@@ -0,0 +1,149 @@
+/*
+ * $Id$
+ * 
+ * Copyright (c) 2011, 2012 Steven Oliver <oliver.steven@gmail.com>
+ * 
+ * This source code is released for free distribution under the terms of the
+ * GNU General Public License.
+ * 
+ * This module contains functions for generating tags for Falcon language
+ * files.
+ */
+
+
+/* 
+ * INCLUDE FILES 
+ */
+#include "general.h"
+
+#include <string.h>
+#include <ctype.h>   
+
+#include "parse.h"
+#include "read.h"  
+
+/*
+ * Data Definitions
+ */
+typedef enum eFalconKinds {
+    K_CLASS,
+    K_FUNCTION,
+    K_MEMBER,
+    K_VARIABLE,
+    K_NAMESPACE
+} falconKind;
+
+static kindOption FalconKinds [] = {
+    {TRUE, 'c', "class",     "classes" },
+    {TRUE, 'f', "function",  "functions"},
+    {TRUE, 'm', "member",    "class members"},
+    {TRUE, 'v', "variable",  "variables"},
+    {TRUE, 'i', "namespace", "imports"}
+};
+
+/* 
+ * Function Definitions
+ */
+
+static boolean isIdentifierChar (int c)
+{
+    return (boolean) (isalnum (c) || c == '_');
+}
+
+static const char *skipSpace (const char *cp)
+{
+    while (isspace ((int) *cp))
+        ++cp;
+        
+    return cp;
+}
+
+static const char *skipString (const char *cp)
+{
+    const char *start = cp;
+    int escaped = 0;
+    
+    for (cp++; *cp; cp++)
+    {
+        if (escaped)
+            escaped--;
+        else if (*cp == '\\')
+            escaped++;
+        else if (*cp == *start)
+            return cp + 1;
+    }
+    
+    return cp;
+}
+
+static void findFalconTags (void)
+{
+    vString *name = vStringNew ();
+    const unsigned char *line;
+
+    while ((line = fileReadLine ()) != NULL)
+    {
+        const unsigned char *cp = line;
+
+        if (*cp == '#')
+            continue;
+
+        if (strncmp ((const char*) cp, "function", (size_t) 8) == 0)
+        {
+            cp += 8;
+            cp = skipSpace (cp);
+            
+            while (isIdentifierChar ((int) *cp))
+            {
+                vStringPut (name, (int) *cp);
+                ++cp;
+            }
+            vStringTerminate (name);
+            makeSimpleTag (name, FalconKinds, K_FUNCTION);
+            vStringClear (name);
+        }
+        else if (strncmp ((const char*) cp, "class", (size_t) 5) == 0)
+        {
+            cp += 5;
+            cp = skipSpace (cp);
+            
+            while (isIdentifierChar ((int) *cp))
+            {
+                vStringPut (name, (int) *cp);
+                ++cp;
+            }
+            vStringTerminate (name);
+            makeSimpleTag (name, FalconKinds, K_CLASS);
+            vStringClear (name);
+        }
+        else if (strncmp ((const char*) cp, "load", (size_t) 4) == 0)
+        {
+            cp += 4;
+            cp = skipSpace (cp);
+            
+            while (isIdentifierChar ((int) *cp))
+            {
+                vStringPut (name, (int) *cp);
+                ++cp;
+            }
+            vStringTerminate (name);
+            makeSimpleTag (name, FalconKinds, K_NAMESPACE);
+            vStringClear (name);
+        }
+    }
+    vStringDelete (name);
+}
+
+/* 
+ * Parser definition structure
+ */
+extern parserDefinition* FalconParser (void)
+{
+    static const char *const extensions [] = { "fal", "ftd", NULL };
+    parserDefinition *def = parserNew ("Falcon");
+    def->kinds      = FalconKinds;
+    def->kindCount  = KIND_COUNT (FalconKinds);
+    def->extensions = extensions;
+    def->parser     = findFalconTags;
+    return def;
+}
diff --git a/flex.c b/flex.c
index 06ca243..038ac4e 100644
--- a/flex.c
+++ b/flex.c
@@ -80,7 +80,8 @@ typedef enum eKeywordId {
 	KEYWORD_id,
 	KEYWORD_script,
 	KEYWORD_cdata,
-	KEYWORD_mx
+	KEYWORD_mx,
+	KEYWORD_override
 } keywordId;
 
 /*	Used to determine whether keyword is valid for the token language and
@@ -184,7 +185,8 @@ static const keywordDesc FlexKeywordTable [] = {
 	{ "id",			KEYWORD_id					},
 	{ "script",		KEYWORD_script				},
 	{ "cdata",		KEYWORD_cdata				},
-	{ "mx",			KEYWORD_mx					}
+	{ "mx",			KEYWORD_mx					},
+	{ "override",	KEYWORD_override			}
 };
 
 /*
@@ -726,7 +728,7 @@ static void skipArgumentList (tokenInfo *const token)
 	 * Other databases can have arguments with fully declared
 	 * datatypes:
 	 *	 (	name varchar(30), text binary(10)  )
-	 * So we must check for nested open and closing parantheses
+	 * So we must check for nested open and closing parentheses
 	 */
 
 	if (isType (token, TOKEN_OPEN_PAREN))	/* arguments? */
@@ -1780,7 +1782,7 @@ static boolean parseStatement (tokenInfo *const token)
 			if (isType (token, TOKEN_CLOSE_CURLY)) 
 			{
 				/*
-				 * Assume the closing parantheses terminates
+				 * Assume the closing parenthesis terminates
 				 * this statements.
 				 */
 				is_terminated = TRUE;
@@ -2154,6 +2156,33 @@ static boolean parseActionScript (tokenInfo *const token)
 		{
 			if (isType(token, TOKEN_KEYWORD))
 			{
+				if (isKeyword (token, KEYWORD_private)   ||
+				    isKeyword (token, KEYWORD_public)    ||
+				    isKeyword (token, KEYWORD_override)  )
+				{
+					/*
+					 * Methods can be defined as:
+					 *     private function f_name
+					 *     public override function f_name
+					 *     override private function f_name
+					 * Ignore these keywords if present.
+					 */
+					readToken (token);
+				}
+				if (isKeyword (token, KEYWORD_private)   ||
+				    isKeyword (token, KEYWORD_public)    ||
+				    isKeyword (token, KEYWORD_override)  )
+				{
+					/*
+					 * Methods can be defined as:
+					 *     private function f_name
+					 *     public override function f_name
+					 *     override private function f_name
+					 * Ignore these keywords if present.
+					 */
+					readToken (token);
+				}
+
 				switch (token->keyword)
 				{
 					case KEYWORD_function:	parseFunction (token); break;
@@ -2178,11 +2207,14 @@ static void parseFlexFile (tokenInfo *const token)
 		{
 			parseMXML (token);
 		} 
-		if (isType (token, TOKEN_LESS_THAN))
+		else if (isType (token, TOKEN_LESS_THAN))
 		{
 			readToken (token);
 			if (isType (token, TOKEN_QUESTION_MARK))
 			{
+				/*
+				 * <?xml version="1.0" encoding="utf-8"?>
+				 */
 				readToken (token);
 				while (! isType (token, TOKEN_QUESTION_MARK) )
 				{
@@ -2190,6 +2222,19 @@ static void parseFlexFile (tokenInfo *const token)
 				} 
 				readToken (token);
 			}
+			else if (isKeyword (token, KEYWORD_NONE))
+			{
+				/*
+				 * This is a simple XML tag, read until the closing statement
+				 * <something .... >
+				 * </something>
+				 */
+				readToken (token);
+				while (! isType (token, TOKEN_GREATER_THAN) )
+				{
+					readToken (token);
+				} 
+			}
 		} 
 		else 
 		{
diff --git a/gir.c b/gir.c
new file mode 100644
index 0000000..517472b
--- /dev/null
+++ b/gir.c
@@ -0,0 +1,216 @@
+#include "general.h"	/* must always come first */
+#include "debug.h"
+#include "entry.h"
+#include "keyword.h"
+#include "parse.h"
+#include "read.h"
+#include "routines.h"
+#include "string.h"
+#include "vstring.h"
+#include <glib.h>
+#include <assert.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include "ctags-utils.h"
+
+static kindOption Kinds [] = {
+	{ TRUE,  'f', "function",	  "functions"},
+	{ TRUE,  'c', "class",		  "classes"},
+	{ TRUE,  'm', "method",		  "methods"},
+	{ TRUE,  'p', "property",	  "properties"},
+	{ TRUE,  'v', "variable",	  "global variables"}
+};
+
+static void
+initialize (const langType language)
+{
+}
+
+static void
+parse_function (xmlNode *node, const gchar *parent)
+{
+	xmlNode *i, *k;
+	gchar *name;
+	tagEntryInfo *tag;
+
+	g_assert (node != NULL);
+
+	name = (gchar*)xmlGetProp (node, (xmlChar*)"name");
+	if (!name)
+		return;
+
+	tag = (tagEntryInfo*)malloc (sizeof (tagEntryInfo));
+	initTagEntry (tag, name);
+	get_file_pos (node->line, &tag->filePosition, File.fp);
+	tag->lineNumber = node->line;
+	tag->isFileScope	= 1;
+	tag->kindName = "function";
+	tag->kind = 'f';
+	if (parent) {
+		tag->kindName = "member";
+		tag->kind = 'm';
+		tag->extensionFields.scope[0] = "class";
+		tag->extensionFields.scope[1] = parent;
+	}
+
+	for (i = node->children; i; i = i->next)
+	{
+		if (!i->name)
+			continue;
+		if (strcmp ((const gchar*)i->name, "return-value") == 0)
+		{
+			for (k = i->children; k; k = k->next)
+			{
+				const gchar *tmp;
+				if (!k->name)
+					continue;
+				tmp = (const gchar*)xmlGetProp (k, (const xmlChar*)"name");
+				if (!tmp)
+					continue;
+				tag->extensionFields.returnType = tmp;
+			}
+		}
+		if (strcmp ((const gchar*)i->name, "parameters") == 0)
+		{
+			for (k = i->children; k; k = k->next)
+			{
+/*TODO:				const gchar *name;
+				if (!k->name)
+					continue;
+				name = (const gchar*)xmlGetProp (node, (const xmlChar*)"name");
+				if (!name)
+					continue;
+				tmp = g_new (Argument, 1);
+				tmp->name = g_strdup (name);
+				tmp->types = NULL;
+				ret->args = g_list_append (ret->args, tmp);*/
+			}
+		}
+	}
+	makeTagEntry (tag);
+}
+
+static void makeTags (xmlNode *node, const gchar *parent);
+
+static void
+parse_class (xmlNode *node)
+{
+	xmlNode *i;
+	gchar *name;
+
+	g_assert (node);
+
+	name = (gchar*)xmlGetProp (node, (const xmlChar*)"name");
+	if (!name)
+		return;
+
+	tagEntryInfo *tag = (tagEntryInfo*)malloc (sizeof (tagEntryInfo));
+	initTagEntry (tag, name);
+	tag->isFileScope = 1;
+	tag->kindName = "class";
+	tag->kind = 'c';
+	get_file_pos (node->line, &tag->filePosition, File.fp);
+	tag->lineNumber = node->line;
+	makeTagEntry (tag);
+
+	for (i = node->children; i; i = i->next)
+	{
+		makeTags (i, name);
+	}
+}
+
+static void
+makeTags (xmlNode *node, const gchar *parent)
+{
+	g_assert (node != NULL);
+	g_assert (node->name != NULL);
+
+	if (strcmp ((const gchar*)node->name, "text") == 0
+			|| strcmp ((const gchar*)node->name, "implements") == 0)
+		return;
+	if (strcmp ((const gchar*)node->name, "enumeration") == 0
+			|| strcmp ((const gchar*)node->name, "union") == 0
+			|| strcmp ((const gchar*)node->name, "namespace") == 0
+			|| strcmp ((const gchar*)node->name, "class") == 0
+			|| strcmp ((const gchar*)node->name, "record") == 0
+			|| strcmp ((const gchar*)node->name, "bitfield") == 0
+			|| strcmp ((const gchar*)node->name, "interface") == 0)
+	{
+		parse_class (node);
+		return;
+	}
+	if (strcmp ((const gchar*)node->name, "function") == 0 || strcmp ((const gchar*)node->name, "method") == 0
+			|| strcmp ((const gchar*)node->name, "callback") == 0
+			|| strcmp ((const gchar*)node->name, "constructor") == 0)
+	{
+		parse_function (node, parent);
+		return;
+	}
+	if (strcmp ((const gchar*)node->name, "alias") == 0 ||
+			strcmp ((const gchar*)node->name, "constant") == 0 ||
+			strcmp ((const gchar*)node->name, "signal") == 0 ||
+			strcmp ((const gchar*)node->name, "field") == 0 ||
+			strcmp ((const gchar*)node->name, "property") == 0 ||
+			strcmp ((const gchar*)node->name, "member") == 0)
+	{
+		gchar *name = (gchar*)xmlGetProp (node, (const xmlChar*)"name");
+		if (!name)
+			return;
+		tagEntryInfo *tag = (tagEntryInfo*)malloc (sizeof (tagEntryInfo));
+		initTagEntry (tag, name);
+		tag->isFileScope	= 1;
+		tag->kindName = "variable";
+		tag->kind = 'v';
+		get_file_pos (node->line, &tag->filePosition, File.fp);
+		tag->lineNumber = node->line;
+		if (parent) {
+			tag->kindName = "member";
+			tag->kind = 'm';
+			tag->extensionFields.scope[0] = "class";
+			tag->extensionFields.scope[1] = parent;
+		}
+		makeTagEntry (tag);
+		return;
+	}
+}
+
+static void
+findTags (void)
+{
+	xmlNode *i;
+	xmlDocPtr doc = xmlParseFile(getInputFileName());
+	xmlNode *root;
+
+	if (doc == NULL) {
+		g_warning ("could not parse file");
+	}
+	root = xmlDocGetRootElement(doc);
+	for (i = root->children; i; i = i->next)
+	{
+		xmlNode *j;
+		if (!i->name)
+			continue;
+		if (strcmp ((const char*)i->name, "namespace") !=0)
+			continue;
+		for (j = i->children; j; j = j->next)
+		{
+			makeTags (j, NULL);
+		}
+	}
+}
+
+extern parserDefinition*
+GirParser (void)
+{
+	static const char *const extensions [] = { "gir", NULL };
+	parserDefinition *const def = parserNew ("GObject-Introspection");
+	def->extensions = extensions;
+
+	def->kinds = Kinds;
+	def->kindCount = KIND_COUNT (Kinds);
+	def->parser = findTags;
+	def->initialize = initialize;
+
+	return def;
+}
diff --git a/lregex.c b/lregex.c
index 59f5df6..37d7ea0 100644
--- a/lregex.c
+++ b/lregex.c
@@ -1,5 +1,5 @@
 /*
-*   $Id: lregex.c 576 2007-06-30 04:16:23Z elliotth $
+*   $Id: lregex.c 747 2009-11-06 02:33:37Z dhiebert $
 *
 *   Copyright (c) 2000-2003, Darren Hiebert
 *
@@ -408,7 +408,7 @@ static void processLanguageRegex (const langType language,
 		const char* regexfile = parameter + 1;
 		FILE* const fp = fopen (regexfile, "r");
 		if (fp == NULL)
-			error (WARNING | PERROR, regexfile);
+			error (WARNING | PERROR, "%s", regexfile);
 		else
 		{
 			vString* const regex = vStringNew ();
diff --git a/make.c b/make.c
index f468b5a..7b56830 100644
--- a/make.c
+++ b/make.c
@@ -1,5 +1,5 @@
 /*
-*   $Id: make.c 681 2008-10-12 22:43:00Z dhiebert $
+*   $Id: make.c 751 2010-02-27 17:41:57Z elliotth $
 *
 *   Copyright (c) 2000-2005, Darren Hiebert
 *
@@ -100,7 +100,7 @@ static void skipToMatch (const char *const pair)
 			++matchLevel;
 		else if (c == end)
 			--matchLevel;
-		else if (c == '\n')
+		else if (c == '\n' || c == EOF)
 			break;
 	}
 	if (c == EOF)
diff --git a/options.c b/options.c
index d26627f..1bee61d 100644
--- a/options.c
+++ b/options.c
@@ -119,6 +119,7 @@ optionValues Option = {
 		FALSE,  /* -fields=n */
 		TRUE,   /* -fields=s */
 		FALSE,  /* -fields=S */
+		FALSE,	/* -fields=T */
 		TRUE    /* -fields=t */
 	},
 	NULL,       /* -I */
@@ -208,7 +209,7 @@ static optionDescription LongOptionDescription [] = {
  {1,"  --extra=[+|-]flags"},
  {1,"      Include extra tag entries for selected information (flags: \"fq\")."},
  {1,"  --fields=[+|-]flags"},
- {1,"      Include selected extension fields (flags: \"afmikKlnsStz\") [fks]."},
+ {1,"      Include selected extension fields (flags: \"afmikKlnsStTz\") [fks]."},
  {1,"  --file-scope=[yes|no]"},
  {1,"       Should tags scoped only for a single file (e.g. \"static\" tags"},
  {1,"       be included in the output [yes]?"},
@@ -291,7 +292,7 @@ static const char* const License2 =
 "\n"
 "You should have received a copy of the GNU General Public License\n"
 "along with this program; if not, write to the Free Software\n"
-"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n";
+"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n";
 
 /*  Contains a set of strings describing the set of "features" compiled into
  *  the code.
@@ -859,6 +860,7 @@ static void processFieldsOption (
 		case 'S': field->signature      = mode; break;
 		case 'z': field->kindKey        = mode; break;
 		case 't': field->typeRef        = mode; break;
+		case 'T': field->returnType		= mode; break;		
 
 		default: error(WARNING, "Unsupported parameter '%c' for \"%s\" option",
 					c, option);
diff --git a/options.h b/options.h
index 34150e7..28b276f 100644
--- a/options.h
+++ b/options.h
@@ -77,6 +77,7 @@ struct sExtFields {  /* extension field content control */
 	boolean lineNumber;
 	boolean scope;
 	boolean signature;
+	boolean returnType;
 	boolean typeRef;
 };
 
diff --git a/parsers.h b/parsers.h
index 3dcc8ae..e4a50e1 100644
--- a/parsers.h
+++ b/parsers.h
@@ -15,6 +15,7 @@
 #define _PARSERS_H
 
 /* Add the name of any new parser definition function here */
+#ifndef ENABLE_VALA
 #define PARSER_LIST \
 	AntParser, \
 	AsmParser, \
@@ -57,6 +58,52 @@
 	VhdlParser, \
 	VimParser, \
 	YaccParser
+#else
+#define PARSER_LIST \
+	AntParser, \
+	AsmParser, \
+	AspParser, \
+	AwkParser, \
+	BasicParser, \
+	BetaParser, \
+	CParser, \
+	CppParser, \
+	CsharpParser, \
+	CobolParser, \
+	DosBatchParser, \
+	EiffelParser, \
+	ErlangParser, \
+	FlexParser, \
+	FortranParser, \
+	GenieParser, \
+	HtmlParser, \
+	JavaParser, \
+	JavaScriptParser, \
+	LispParser, \
+	LuaParser, \
+	MakefileParser, \
+	MatLabParser, \
+	OcamlParser, \
+	PascalParser, \
+	PerlParser, \
+	PhpParser, \
+	PythonParser, \
+	RexxParser, \
+	RubyParser, \
+	SchemeParser, \
+	ShParser, \
+	SlangParser, \
+	SmlParser, \
+	SqlParser, \
+	TclParser, \
+	TexParser, \
+	ValaParse, \
+	VeraParser, \
+	VerilogParser, \
+	VhdlParser, \
+	VimParser, \
+	YaccParser
+#endif
 
 #endif  /* _PARSERS_H */
 
diff --git a/php.c b/php.c
index 0dd60c5..90e096a 100644
--- a/php.c
+++ b/php.c
@@ -1,5 +1,5 @@
 /*
-*   $Id: php.c 624 2007-09-15 22:53:31Z jafl $
+*   $Id: php.c 734 2009-08-20 23:33:54Z jafl $
 *
 *   Copyright (c) 2000, Jesus Castagnetto <jmcastagnetto@zkey.com>
 *
@@ -64,17 +64,17 @@ static kindOption PhpKinds [] = {
 
 static void installPHPRegex (const langType language)
 {
-	addTagRegex(language, "(^|[ \t])class[ \t]+([" ALPHA "_][" ALNUM "_]*)",
-		"\\2", "c,class,classes", NULL);
-	addTagRegex(language, "(^|[ \t])interface[ \t]+([" ALPHA "_][" ALNUM "_]*)",
-		"\\2", "i,interface,interfaces", NULL);
-	addTagRegex(language, "(^|[ \t])define[ \t]*\\([ \t]*['\"]?([" ALPHA "_][" ALNUM "_]*)",
-		"\\2", "d,define,constant definitions", NULL);
-	addTagRegex(language, "(^|[ \t])function[ \t]+&?[ \t]*([" ALPHA "_][" ALNUM "_]*)",
-		"\\2", "f,function,functions", NULL);
-	addTagRegex(language, "(^|[ \t])(\\$|::\\$|\\$this->)([" ALPHA "_][" ALNUM "_]*)[ \t]*=",
-		"\\3", "v,variable,variables", NULL);
-	addTagRegex(language, "(^|[ \t])(var|public|protected|private|static)[ \t]+\\$([" ALPHA "_][" ALNUM "_]*)[ \t]*[=;]",
+	addTagRegex(language, "^[ \t]*((final|abstract)[ \t]+)*class[ \t]+([" ALPHA "_][" ALNUM "_]*)",
+		"\\3", "c,class,classes", NULL);
+	addTagRegex(language, "^[ \t]*interface[ \t]+([" ALPHA "_][" ALNUM "_]*)",
+		"\\1", "i,interface,interfaces", NULL);
+	addTagRegex(language, "^[ \t]*define[ \t]*\\([ \t]*['\"]?([" ALPHA "_][" ALNUM "_]*)",
+		"\\1", "d,define,constant definitions", NULL);
+	addTagRegex(language, "^[ \t]*((static|public|protected|private)[ \t]+)*function[ \t]+&?[ \t]*([" ALPHA "_][" ALNUM "_]*)",
+		"\\3", "f,function,functions", NULL);
+	addTagRegex(language, "^[ \t]*(\\$|::\\$|\\$this->)([" ALPHA "_][" ALNUM "_]*)[ \t]*=",
+		"\\2", "v,variable,variables", NULL);
+	addTagRegex(language, "^[ \t]*((var|public|protected|private|static)[ \t]+)+\\$([" ALPHA "_][" ALNUM "_]*)[ \t]*[=;]",
 		"\\3", "v,variable,variables", NULL);
 
 	/* function regex is covered by PHP regex */
diff --git a/python.c b/python.c
index 5fdf31b..a90d072 100644
--- a/python.c
+++ b/python.c
@@ -1,5 +1,5 @@
 /*
-*   $Id: python.c 720 2009-07-07 03:55:23Z dhiebert $
+*   $Id: python.c 752 2010-02-27 17:52:46Z elliotth $
 *
 *   Copyright (c) 2000-2003, Darren Hiebert
 *
@@ -240,7 +240,7 @@ static const char *skipEverything (const char *cp)
 {
 	for (; *cp; cp++)
 	{
-		if (*cp == '"' || *cp == '\'')
+		if (*cp == '"' || *cp == '\'' || *cp == '#')
 		{
 			cp = skipString(cp);
 			if (!*cp) break;
@@ -398,7 +398,9 @@ static void parseFunction (const char *cp, vString *const def,
 	cp = parseIdentifier (cp, def);
 	arglist = parseArglist (cp);
 	makeFunctionTag (def, parent, is_class_parent, arglist);
-	eFree (arglist);
+	if (arglist != NULL) {
+		eFree (arglist);
+	}
 }
 
 /* Get the combined name of a nested symbol. Classes are separated with ".",
diff --git a/sort.c b/sort.c
index 09ba87a..c58defc 100644
--- a/sort.c
+++ b/sort.c
@@ -1,5 +1,5 @@
 /*
-*   $Id: sort.c 498 2007-02-17 22:43:15Z dhiebert $
+*   $Id: sort.c 747 2009-11-06 02:33:37Z dhiebert $
 *
 *   Copyright (c) 1996-2002, Darren Hiebert
 *
@@ -109,7 +109,7 @@ static void failedSort (FILE *const fp, const char* msg)
 	if (fp != NULL)
 		fclose (fp);
 	if (msg == NULL)
-		error (FATAL | PERROR, cannotSort);
+		error (FATAL | PERROR, "%s", cannotSort);
 	else
 		error (FATAL, "%s: %s", msg, cannotSort);
 }
diff --git a/sql.c b/sql.c
index efe7e5d..6c0c76a 100644
--- a/sql.c
+++ b/sql.c
@@ -1,5 +1,5 @@
 /*
- *	$Id: sql.c 703 2009-03-14 22:06:12Z dfishburn $
+ *	$Id: sql.c 745 2009-10-27 02:42:55Z dfishburn $
  *
  *	Copyright (c) 2002-2003, Darren Hiebert
  *
@@ -65,9 +65,14 @@ typedef enum eKeywordId {
 	KEYWORD_end,
 	KEYWORD_function,
 	KEYWORD_if,
+	KEYWORD_else,
+	KEYWORD_elseif,
+	KEYWORD_endif,
 	KEYWORD_loop,
+	KEYWORD_while,
 	KEYWORD_case,
 	KEYWORD_for,
+	KEYWORD_do,
 	KEYWORD_call,
 	KEYWORD_package,
 	KEYWORD_pragma,
@@ -114,6 +119,7 @@ typedef enum eKeywordId {
 	KEYWORD_ml_conn_dnet,
 	KEYWORD_ml_conn_java,
 	KEYWORD_ml_conn_chk,
+	KEYWORD_ml_prop,
 	KEYWORD_local,
 	KEYWORD_temporary,
 	KEYWORD_drop,
@@ -140,6 +146,7 @@ typedef enum eTokenType {
 	TOKEN_BLOCK_LABEL_END,
 	TOKEN_CHARACTER,
 	TOKEN_CLOSE_PAREN,
+	TOKEN_COLON,
 	TOKEN_SEMICOLON,
 	TOKEN_COMMA,
 	TOKEN_IDENTIFIER,
@@ -154,7 +161,8 @@ typedef enum eTokenType {
 	TOKEN_OPEN_SQUARE,
 	TOKEN_CLOSE_SQUARE,
 	TOKEN_TILDE,
-	TOKEN_FORWARD_SLASH
+	TOKEN_FORWARD_SLASH,
+	TOKEN_EQUAL
 } tokenType;
 
 typedef struct sTokenInfoSQL {
@@ -198,6 +206,7 @@ typedef enum {
 	SQLTAG_SYNONYM,
 	SQLTAG_MLTABLE,
 	SQLTAG_MLCONN,
+	SQLTAG_MLPROP,
 	SQLTAG_COUNT
 } sqlKind;
 
@@ -223,7 +232,8 @@ static kindOption SqlKinds [] = {
 	{ TRUE,  'V', "view",		  "views"				   },
 	{ TRUE,  'n', "synonym",	  "synonyms"			   },
 	{ TRUE,  'x', "mltable",	  "MobiLink Table Scripts" },
-	{ TRUE,  'y', "mlconn",		  "MobiLink Conn Scripts"  }
+	{ TRUE,  'y', "mlconn",		  "MobiLink Conn Scripts"  },
+	{ TRUE,  'z', "mlprop",		  "MobiLink Properties "   }
 };
 
 static const keywordDesc SqlKeywordTable [] = {
@@ -237,9 +247,14 @@ static const keywordDesc SqlKeywordTable [] = {
 	{ "end",							KEYWORD_end				      },
 	{ "function",						KEYWORD_function		      },
 	{ "if",								KEYWORD_if				      },
+	{ "else",							KEYWORD_else			      },
+	{ "elseif",							KEYWORD_elseif			      },
+	{ "endif",							KEYWORD_endif			      },
 	{ "loop",							KEYWORD_loop			      },
+	{ "while",							KEYWORD_while			      },
 	{ "case",							KEYWORD_case			      },
 	{ "for",							KEYWORD_for				      },
+	{ "do",								KEYWORD_do				      },
 	{ "call",							KEYWORD_call			      },
 	{ "package",						KEYWORD_package			      },
 	{ "pragma",							KEYWORD_pragma			      },
@@ -286,6 +301,7 @@ static const keywordDesc SqlKeywordTable [] = {
 	{ "ml_add_dnet_connection_script",	KEYWORD_ml_conn_dnet	      },
 	{ "ml_add_java_connection_script",	KEYWORD_ml_conn_java	      },
 	{ "ml_add_lang_conn_script_chk",	KEYWORD_ml_conn_chk 	      },
+	{ "ml_add_property",				KEYWORD_ml_prop		 	      },
 	{ "local",							KEYWORD_local			      },
 	{ "temporary",						KEYWORD_temporary		      },
 	{ "drop",							KEYWORD_drop			      },
@@ -303,6 +319,7 @@ static const keywordDesc SqlKeywordTable [] = {
 
 /* Recursive calls */
 static void parseBlock (tokenInfo *const token, const boolean local);
+static void parseDeclare (tokenInfo *const token, const boolean local);
 static void parseKeywords (tokenInfo *const token);
 static void parseSqlFile (tokenInfo *const token);
 
@@ -541,6 +558,7 @@ getNextChar:
 		case EOF: longjmp (Exception, (int)ExceptionEOF);	break;
 		case '(': token->type = TOKEN_OPEN_PAREN;		break;
 		case ')': token->type = TOKEN_CLOSE_PAREN;		break;
+		case ':': token->type = TOKEN_COLON;			break;
 		case ';': token->type = TOKEN_SEMICOLON;		break;
 		case '.': token->type = TOKEN_PERIOD;			break;
 		case ',': token->type = TOKEN_COMMA;			break;
@@ -549,6 +567,7 @@ getNextChar:
 		case '~': token->type = TOKEN_TILDE;			break;
 		case '[': token->type = TOKEN_OPEN_SQUARE;		break;
 		case ']': token->type = TOKEN_CLOSE_SQUARE;		break;
+		case '=': token->type = TOKEN_EQUAL;			break;
 
 		case '\'':
 		case '"':
@@ -770,7 +789,7 @@ static void skipArgumentList (tokenInfo *const token)
 	 * Other databases can have arguments with fully declared
 	 * datatypes:
 	 *	 (	name varchar(30), text binary(10)  )
-	 * So we must check for nested open and closing parantheses
+	 * So we must check for nested open and closing parentheses
 	 */
 
 	if (isType (token, TOKEN_OPEN_PAREN))	/* arguments? */
@@ -848,7 +867,7 @@ static void parseSubProgram (tokenInfo *const token)
 			/*
 			 * Read token after which could be the
 			 * command terminator if a prototype
-			 * or an open parantheses
+			 * or an open parenthesis
 			 */
 			readToken (token);
 			if (isType (token, TOKEN_OPEN_PAREN))
@@ -870,6 +889,7 @@ static void parseSubProgram (tokenInfo *const token)
 					isKeyword (token, KEYWORD_internal) ||
 					isKeyword (token, KEYWORD_external) ||
 					isKeyword (token, KEYWORD_url) ||
+					isType (token, TOKEN_EQUAL) ||
 					isCmdTerm (token)
 				)
 			  )
@@ -900,6 +920,12 @@ static void parseSubProgram (tokenInfo *const token)
 
 			vStringClear (token->scope);
 		} 
+		if ( isType (token, TOKEN_EQUAL) )
+			readToken (token);
+
+		if ( isKeyword (token, KEYWORD_declare) )
+			parseDeclare (token, FALSE);
+
 		if (isKeyword (token, KEYWORD_is) || 
 				isKeyword (token, KEYWORD_begin) )
 		{
@@ -1066,18 +1092,18 @@ static void parseDeclare (tokenInfo *const token, const boolean local)
 			case KEYWORD_type:		parseType (token); break;
 
 			default:
-									if (isType (token, TOKEN_IDENTIFIER))
-									{
-										if (local)
-										{
-											makeSqlTag (token, SQLTAG_LOCAL_VARIABLE);
-										} 
-										else 
-										{
-											makeSqlTag (token, SQLTAG_VARIABLE);
-										}
-									}
-									break;
+				if (isType (token, TOKEN_IDENTIFIER))
+				{
+					if (local)
+					{
+						makeSqlTag (token, SQLTAG_LOCAL_VARIABLE);
+					} 
+					else 
+					{
+						makeSqlTag (token, SQLTAG_VARIABLE);
+					}
+				}
+				break;
 		}
 		findToken (token, TOKEN_SEMICOLON);
 		readToken (token);
@@ -1164,12 +1190,13 @@ static void parseLabel (tokenInfo *const token)
 	}
 }
 
-static void parseStatements (tokenInfo *const token)
+static void parseStatements (tokenInfo *const token, const boolean exit_on_endif )
 {
 	boolean isAnsi   = TRUE;
 	boolean stmtTerm = FALSE;
 	do
 	{
+
 		if (isType (token, TOKEN_BLOCK_LABEL_BEGIN))
 			parseLabel (token);
 		else
@@ -1210,6 +1237,7 @@ static void parseStatements (tokenInfo *const token)
 					 */
 					while (! isKeyword (token, KEYWORD_then))
 						readToken (token);
+
 					readToken (token);
 					continue;
 
@@ -1220,6 +1248,15 @@ static void parseStatements (tokenInfo *const token)
 					 *	IF...THEN
 					 *	END IF;
 					 *
+					 *	IF...THEN
+					 *	ELSE
+					 *	END IF;
+					 *
+					 *	IF...THEN
+					 *	ELSEIF...THEN
+					 *	ELSE
+					 *	END IF;
+					 *
 					 *	or non-ANSI
 					 *	IF ...
 					 *	BEGIN
@@ -1248,7 +1285,22 @@ static void parseStatements (tokenInfo *const token)
 					else
 					{
 						readToken (token);
-						parseStatements (token);
+
+						while( ! (isKeyword (token, KEYWORD_end ) ||
+						          isKeyword (token, KEYWORD_endif ) ) 
+								)
+						{
+							if ( isKeyword (token, KEYWORD_else) ||
+									isKeyword (token, KEYWORD_elseif)    )
+								readToken (token);
+
+							parseStatements (token, TRUE);
+
+							if ( isCmdTerm(token) )
+								readToken (token);
+
+						}
+
 						/* 
 						 * parseStatements returns when it finds an END, an IF
 						 * should follow the END for ANSI anyway.
@@ -1258,7 +1310,13 @@ static void parseStatements (tokenInfo *const token)
 						if( isKeyword (token, KEYWORD_end ) )
 							readToken (token);
 
-						if( ! isKeyword (token, KEYWORD_if ) )
+						if( isKeyword (token, KEYWORD_if ) || isKeyword (token, KEYWORD_endif ) )
+						{
+							readToken (token);
+							if ( isCmdTerm(token) )
+								stmtTerm = TRUE;
+						} 
+						else 
 						{
 							/*
 							 * Well we need to do something here.
@@ -1284,14 +1342,64 @@ static void parseStatements (tokenInfo *const token)
 					 *	END CASE;
 					 *	
 					 *	FOR loop_name AS cursor_name CURSOR FOR ...
+					 *	DO
 					 *	END FOR;
 					 */
+					if( isKeyword (token, KEYWORD_for ) )
+					{
+						/* loop name */
+						readToken (token);
+						/* AS */
+						readToken (token);
+
+						while ( ! isKeyword (token, KEYWORD_is) )
+						{
+							/*
+							 * If this is not an AS keyword this is 
+							 * not a proper FOR statement and should 
+							 * simply be ignored
+							 */
+							return;
+						}
+
+						while ( ! isKeyword (token, KEYWORD_do) )
+							readToken (token);
+					}
+
+
 					readToken (token);
-					parseStatements (token);
+					while( ! isKeyword (token, KEYWORD_end ) )
+					{
+						/*
+						if ( isKeyword (token, KEYWORD_else) ||
+								isKeyword (token, KEYWORD_elseif)    )
+							readToken (token);
+							*/
+
+						parseStatements (token, FALSE);
+
+						if ( isCmdTerm(token) )
+							readToken (token);
+					}
+
 
 					if( isKeyword (token, KEYWORD_end ) )
 						readToken (token);
 
+					/*
+					 * Typically ended with 
+					 *    END LOOP [loop name];
+					 *    END CASE
+					 *    END FOR [loop name];
+					 */
+					if ( isKeyword (token, KEYWORD_loop) ||
+							isKeyword (token, KEYWORD_case) ||
+							isKeyword (token, KEYWORD_for)    )
+						readToken (token);
+
+					if ( isCmdTerm(token) )
+						stmtTerm = TRUE;
+
 					break;
 
 				case KEYWORD_create:
@@ -1324,11 +1432,36 @@ static void parseStatements (tokenInfo *const token)
 			 *
 			 * So we must read to the first semi-colon or an END block
 			 */
-			while ( ! stmtTerm && 
-					! (   isKeyword (token, KEYWORD_end) ||
-						 (isCmdTerm(token))              )	  
+			while ( ! stmtTerm                               && 
+					! (   isKeyword (token, KEYWORD_end)     ||
+						 (isCmdTerm(token))              )	 
 					)
 			{
+				if (   isKeyword (token, KEYWORD_endif)   &&
+						 exit_on_endif                   )	  
+					return;
+
+				if (isType (token, TOKEN_COLON) )
+				{
+					/*
+					 * A : can signal a loop name 
+					 *    myloop:
+					 *    LOOP 
+					 *        LEAVE myloop;
+					 *    END LOOP;
+					 * Unfortunately, labels do not have a
+					 * cmd terminator, therefore we have to check 
+					 * if the next token is a keyword and process 
+					 * it accordingly.
+					 */
+					readToken (token);
+					if ( isKeyword (token, KEYWORD_loop) ||
+							isKeyword (token, KEYWORD_while) ||
+							isKeyword (token, KEYWORD_for) )
+						/* parseStatements (token); */
+						return;
+				}
+
 				readToken (token);
 
 				if (isType (token, TOKEN_OPEN_PAREN)  ||
@@ -1336,6 +1469,20 @@ static void parseStatements (tokenInfo *const token)
 				    isType (token, TOKEN_OPEN_SQUARE)  )
 						skipToMatched (token);
 
+				/*
+				 * Since we know how to parse various statements 
+				 * if we detect them, parse them to completion
+				 */
+				if (isType (token, TOKEN_BLOCK_LABEL_BEGIN) ||
+						isKeyword (token, KEYWORD_exception) ||
+						isKeyword (token, KEYWORD_loop) ||
+						isKeyword (token, KEYWORD_case) ||
+						isKeyword (token, KEYWORD_for) ||
+						isKeyword (token, KEYWORD_begin)    )
+					parseStatements (token, FALSE);
+				else if (isKeyword (token, KEYWORD_if))
+					parseStatements (token, TRUE);
+
 			}
 		}
 		/*
@@ -1343,11 +1490,12 @@ static void parseStatements (tokenInfo *const token)
 		 * See comment above, now, only read if the current token 
 		 * is not a command terminator.
 		 */
-		if ( isCmdTerm(token) )
-		{
-			readToken (token);
-		}
-	} while (! isKeyword (token, KEYWORD_end) && ! stmtTerm );
+		if ( isCmdTerm(token) && ! stmtTerm )
+			stmtTerm = TRUE;
+				
+	} while (! isKeyword (token, KEYWORD_end) && 
+			 ! (exit_on_endif && isKeyword (token, KEYWORD_endif) ) && 
+			 ! stmtTerm );
 }
 
 static void parseBlock (tokenInfo *const token, const boolean local)
@@ -1378,7 +1526,10 @@ static void parseBlock (tokenInfo *const token, const boolean local)
 		token->begin_end_nest_lvl++;
 		while (! isKeyword (token, KEYWORD_end))
 		{
-			parseStatements (token);
+			parseStatements (token, FALSE);
+
+			if ( isCmdTerm(token) )
+				readToken (token);
 		}
 		token->begin_end_nest_lvl--;
 
@@ -1994,6 +2145,70 @@ static void parseMLConn (tokenInfo *const token)
 	deleteToken (event);
 }
 
+static void parseMLProp (tokenInfo *const token)
+{
+	tokenInfo *const component     = newToken ();
+	tokenInfo *const prop_set_name = newToken ();
+	tokenInfo *const prop_name     = newToken ();
+
+	/*
+	 * This deals with these formats
+     *   ml_add_property ( 
+     *       'comp_name', 
+     *       'prop_set_name', 
+     *       'prop_name', 
+     *       'prop_value'
+     *   )
+	 */
+
+	readToken (token);
+	if ( isType (token, TOKEN_OPEN_PAREN) )
+	{
+		readToken (component);
+		readToken (token);
+		while (!(isType (token, TOKEN_COMMA) ||
+					isType (token, TOKEN_CLOSE_PAREN)
+				))
+		{
+			readToken (token);
+		}
+
+		if (isType (token, TOKEN_COMMA))
+		{
+			readToken (prop_set_name);
+			readToken (token);
+			while (!(isType (token, TOKEN_COMMA) ||
+						isType (token, TOKEN_CLOSE_PAREN)
+					))
+			{
+				readToken (token);
+			}
+
+			if (isType (token, TOKEN_COMMA))
+			{
+				readToken (prop_name);
+
+				if (isType (component, TOKEN_STRING) && 
+						isType (prop_set_name, TOKEN_STRING) && 
+						isType (prop_name, TOKEN_STRING) )
+				{
+					addToScope(component, prop_set_name->string);
+					addToScope(component, prop_name->string);
+					makeSqlTag (component, SQLTAG_MLPROP);
+				}
+			} 
+			if( !isType (token, TOKEN_CLOSE_PAREN) )
+				findToken (token, TOKEN_CLOSE_PAREN);
+		} 
+	}
+
+	findCmdTerm (token, TRUE);
+
+	deleteToken (component);
+	deleteToken (prop_set_name);
+	deleteToken (prop_name);
+}
+
 static void parseComment (tokenInfo *const token)
 {
 	/*
@@ -2039,7 +2254,7 @@ static void parseKeywords (tokenInfo *const token)
 			case KEYWORD_drop:			parseDrop (token); break;
 			case KEYWORD_event:			parseEvent (token); break;
 			case KEYWORD_function:		parseSubProgram (token); break;
-			case KEYWORD_if:			parseStatements (token); break;
+			case KEYWORD_if:			parseStatements (token, FALSE); break;
 			case KEYWORD_index:			parseIndex (token); break;
 			case KEYWORD_ml_table:		parseMLTable (token); break;
 			case KEYWORD_ml_table_lang: parseMLTable (token); break;
@@ -2051,6 +2266,7 @@ static void parseKeywords (tokenInfo *const token)
 			case KEYWORD_ml_conn_dnet:	parseMLConn (token); break;
 			case KEYWORD_ml_conn_java:	parseMLConn (token); break;
 			case KEYWORD_ml_conn_chk:	parseMLConn (token); break;
+			case KEYWORD_ml_prop:		parseMLProp (token); break;
 			case KEYWORD_package:		parsePackage (token); break;
 			case KEYWORD_procedure:		parseSubProgram (token); break;
 			case KEYWORD_publication:	parsePublication (token); break;
diff --git a/test-cmd-line b/test-cmd-line
new file mode 100644
index 0000000..980f6b9
--- /dev/null
+++ b/test-cmd-line
@@ -0,0 +1 @@
+./anjuta_tags --sort=no --fields=afmiKlnsStTz --c++-kinds=+p foo.cpp ; cat tags
diff --git a/tex.c b/tex.c
index a285797..0c6714e 100644
--- a/tex.c
+++ b/tex.c
@@ -53,7 +53,8 @@ typedef enum eKeywordId {
 	KEYWORD_subsubsection,
 	KEYWORD_part,
 	KEYWORD_paragraph,
-	KEYWORD_subparagraph
+	KEYWORD_subparagraph,
+	KEYWORD_include
 } keywordId;
 
 /*	Used to determine whether keyword is valid for the token language and
@@ -68,27 +69,15 @@ typedef enum eTokenType {
 	TOKEN_UNDEFINED,
 	TOKEN_CHARACTER,
 	TOKEN_CLOSE_PAREN,
-	TOKEN_SEMICOLON,
-	TOKEN_COLON,
 	TOKEN_COMMA,
 	TOKEN_KEYWORD,
 	TOKEN_OPEN_PAREN,
-	TOKEN_OPERATOR,
 	TOKEN_IDENTIFIER,
 	TOKEN_STRING,
-	TOKEN_PERIOD,
 	TOKEN_OPEN_CURLY,
 	TOKEN_CLOSE_CURLY,
-	TOKEN_EQUAL_SIGN,
-	TOKEN_EXCLAMATION,
-	TOKEN_FORWARD_SLASH,
 	TOKEN_OPEN_SQUARE,
 	TOKEN_CLOSE_SQUARE,
-	TOKEN_OPEN_MXML,
-	TOKEN_CLOSE_MXML,
-	TOKEN_CLOSE_SGML,
-	TOKEN_LESS_THAN,
-	TOKEN_GREATER_THAN,
 	TOKEN_QUESTION_MARK,
 	TOKEN_STAR
 } tokenType;
@@ -118,6 +107,7 @@ typedef enum {
 	TEXTAG_PART,
 	TEXTAG_PARAGRAPH,
 	TEXTAG_SUBPARAGRAPH,
+	TEXTAG_INCLUDE,
 	TEXTAG_COUNT
 } texKind;
 
@@ -128,7 +118,8 @@ static kindOption TexKinds [] = {
 	{ TRUE,  'b', "subsubsection",	  "subsubsections"	   },
 	{ TRUE,  'p', "part",			  "parts"			   },
 	{ TRUE,  'P', "paragraph",		  "paragraphs"		   },
-	{ TRUE,  'G', "subparagraph",	  "subparagraphs"	   }
+	{ TRUE,  'G', "subparagraph",	  "subparagraphs"	   },
+	{ TRUE,  'i', "include",	  	  "includes"		   }
 };
 
 static const keywordDesc TexKeywordTable [] = {
@@ -139,7 +130,8 @@ static const keywordDesc TexKeywordTable [] = {
 	{ "subsubsection",	KEYWORD_subsubsection		},
 	{ "part",			KEYWORD_part				},
 	{ "paragraph",		KEYWORD_paragraph			},
-	{ "subparagraph",	KEYWORD_subparagraph		}
+	{ "subparagraph",	KEYWORD_subparagraph		},
+	{ "include",		KEYWORD_include				}
 };
 
 /*
@@ -150,7 +142,7 @@ static boolean isIdentChar (const int c)
 {
 	return (boolean)
 		(isalpha (c) || isdigit (c) || c == '$' || 
-		  c == '_' || c == '#');
+		  c == '_' || c == '#' || c == '-' || c == '.');
 }
 
 static void buildTexKeywordHash (void)
@@ -297,16 +289,11 @@ getNextChar:
 		case EOF: longjmp (Exception, (int)ExceptionEOF);	break;
 		case '(': token->type = TOKEN_OPEN_PAREN;			break;
 		case ')': token->type = TOKEN_CLOSE_PAREN;			break;
-		case ';': token->type = TOKEN_SEMICOLON;			break;
 		case ',': token->type = TOKEN_COMMA;				break;
-		case '.': token->type = TOKEN_PERIOD;				break;
-		case ':': token->type = TOKEN_COLON;				break;
 		case '{': token->type = TOKEN_OPEN_CURLY;			break;
 		case '}': token->type = TOKEN_CLOSE_CURLY;			break;
-		case '=': token->type = TOKEN_EQUAL_SIGN;			break;
 		case '[': token->type = TOKEN_OPEN_SQUARE;			break;
 		case ']': token->type = TOKEN_CLOSE_SQUARE;			break;
-		case '?': token->type = TOKEN_QUESTION_MARK;		break;
 		case '*': token->type = TOKEN_STAR;					break;
 
 		case '\'':
@@ -427,7 +414,8 @@ static boolean parseTag (tokenInfo *const token, texKind kind)
 		readToken (token);
 		while (! isType (token, TOKEN_CLOSE_CURLY) )
 		{
-			if (isType (token, TOKEN_IDENTIFIER) && useLongName)
+			/* if (isType (token, TOKEN_IDENTIFIER) && useLongName) */
+			if (useLongName)
 			{
 				if (fullname->length > 0)
 					vStringCatS (fullname, " ");
@@ -479,6 +467,9 @@ static void parseTexFile (tokenInfo *const token)
 				case KEYWORD_subparagraph:	
 					parseTag (token, TEXTAG_SUBPARAGRAPH); 
 					break;
+				case KEYWORD_include:	
+					parseTag (token, TEXTAG_INCLUDE); 
+					break;
 				default:
 					break;
 			}
diff --git a/vala.c b/vala.c
new file mode 100644
index 0000000..555ffc5
--- /dev/null
+++ b/vala.c
@@ -0,0 +1,103 @@
+/*
+ * vala.c
+ *
+ * Copyright 2008 Abderrahim Kitouni <a.kitouni@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/*
+ *   INCLUDE FILES
+ */
+#include "general.h"  /* must always come first */
+#include "parse.h"
+#include "read.h"
+
+#include "entry.h"
+#include "ctags-vala.h"
+
+CTagsVisitor *visitor;
+/* using different data structure because fpos_t isn't available in Vala*/
+static void make_ctags_entry (CTagsEntry* entry) {
+	tagEntryInfo tag;
+	initTagEntry(&tag, entry->name);
+
+	tag.lineNumberEntry = TRUE;
+	tag.lineNumber = entry->line_number;
+	tag.kindName = entry->kind_name;
+	tag.kind = entry->kind;
+	/* FIXME: add filePosition */
+	tag.extensionFields.access = entry->access;
+	tag.extensionFields.implementation = entry->implementation;
+	tag.extensionFields.inheritance = entry->inheritance;
+	tag.extensionFields.scope[0] = entry->scope[0];
+	tag.extensionFields.scope[1] = entry->scope[1];
+	tag.extensionFields.typeRef[0] = entry->typeref;
+	tag.extensionFields.returnType = entry->returntype;
+	tag.extensionFields.signature = entry->signature;
+	makeTagEntry(&tag);
+}
+
+static kindOption ValaKinds [] = {
+	{ TRUE,	'c', "class", "Classes" },
+	{ TRUE, 's', "struct", "Structures" },
+	{ TRUE, 'i', "interface", "Interfaces" },
+	{ TRUE, 'e', "enum", "Enumerations" },
+	{ TRUE, 'v', "enumvalue", "Enumeration Values" },
+	{ TRUE, 'E', "errordomain", "Error domains" },
+	{ TRUE, 'r', "errorcode", "Error codes" },
+	{ TRUE, 'd', "delegate", "Delegates" },
+	{ TRUE, 'S', "signal", "Signals" },
+	{ TRUE,	'f', "field", "Fields" },
+	{ TRUE,	'p', "property", "Properties" },
+	{ TRUE, 'm', "method", "Methods" },
+	{ FALSE, 'l', "local", "Local variables" },
+};
+
+static void findValaTags (void) {
+	if (visitor == NULL) {
+		visitor = ctags_visitor_new();
+	}
+	ctags_visitor_parse_vala (visitor, getSourceFileName(), (CTagsEntryMaker) make_ctags_entry);
+}
+
+extern parserDefinition *ValaParse(void) {
+	g_type_init();
+	static const char *const extensions [] = { "vala", "vapi", NULL };
+	parserDefinition* def = parserNew ("Vala");
+	def->kinds      = ValaKinds;
+	def->kindCount  = KIND_COUNT (ValaKinds);
+	def->extensions = extensions;
+	def->parser     = findValaTags;
+	return def;
+}
+
+static void findGenieTags (void) {
+	if (visitor == NULL) {
+		visitor = ctags_visitor_new();
+	}
+	ctags_visitor_parse_genie (visitor, getSourceFileName(), (CTagsEntryMaker) make_ctags_entry);
+}
+
+extern parserDefinition *GenieParser(void) {
+	static const char *const extensions [] = { "gs", NULL };
+	parserDefinition* def = parserNew ("Genie");
+	def->kinds      = ValaKinds;
+	def->kindCount  = KIND_COUNT (ValaKinds);
+	def->extensions = extensions;
+	def->parser     = findGenieTags;
+	return def;
+}
diff --git a/verilog.c b/verilog.c
index 814f5b0..52afc31 100644
--- a/verilog.c
+++ b/verilog.c
@@ -1,5 +1,5 @@
 /*
-*   $Id: verilog.c 573 2007-06-26 05:41:27Z elliotth $
+*   $Id: verilog.c 753 2010-02-27 17:53:32Z elliotth $
 * 
 *   Copyright (c) 2003, Darren Hiebert
 * 
@@ -232,6 +232,7 @@ static void tagNameList (const verilogKind kind, int c)
 		c = skipWhite (c);
 		if (c == '=')
 		{
+			c = skipWhite (vGetc ());
 			if (c == '{')
 				skipPastMatch ("{}");
 			else
-- 
2.11.0