[geany/geany] 73a6dd: Merge pull request #3158 from techee/vhdl_sync

Jiří Techet git-noreply at geany.org
Thu May 12 22:55:45 UTC 2022


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   GitHub <noreply at github.com>
Date:        Thu, 12 May 2022 22:55:45 UTC
Commit:      73a6dd5b02aca5f9a8bd0f29c49d04d4fafe6869
             https://github.com/geany/geany/commit/73a6dd5b02aca5f9a8bd0f29c49d04d4fafe6869

Log Message:
-----------
Merge pull request #3158 from techee/vhdl_sync

Use the upstream VHDL parser


Modified Paths:
--------------
    ctags/Makefile.am
    ctags/parsers/geany_vhdl.c
    ctags/parsers/vhdl.c
    meson.build
    src/tagmanager/tm_parser.c
    tests/ctags/Makefile.am
    tests/ctags/bug2374109.vhd.tags
    tests/ctags/test.vhd
    tests/ctags/test.vhd.tags
    tests/ctags/vhdl-component.vhd
    tests/ctags/vhdl-component.vhd.tags
    tests/ctags/vhdl-local.vhd
    tests/ctags/vhdl-local.vhd.tags
    tests/ctags/vhdl-port.vhd
    tests/ctags/vhdl-port.vhd.tags
    tests/ctags/vhdl-process.vhd
    tests/ctags/vhdl-process.vhd.tags
    tests/ctags/vhdl-type.vhd
    tests/ctags/vhdl-type.vhd.tags
    tests/meson.build

Modified: ctags/Makefile.am
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -95,7 +95,7 @@ parsers = \
 	parsers/geany_tex.c \
 	parsers/txt2tags.c \
 	parsers/verilog.c \
-	parsers/geany_vhdl.c
+	parsers/vhdl.c
 
 # skip cmd.c and mini-geany.c which define main()
 # also skip lregex-pcre2.c which we don't use


Modified: ctags/parsers/geany_vhdl.c
289 lines changed, 0 insertions(+), 289 deletions(-)
===================================================================
@@ -1,289 +0,0 @@
-/*
-*   $Id: vhdl.c,v 1.0 2005/11/05
-*
-*   Copyright (c) 2005, Klaus Dannecker
-*
-*   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 the Vhdl HDL
-*   (Hardware Description Language).
-*
-*/
-
-/*
- *   INCLUDE FILES
- */
-#include "general.h"    /* must always come first */
-
-#include <string.h>
-#include <setjmp.h>
-
-#include "debug.h"
-#include "keyword.h"
-#include "parse.h"
-#include "read.h"
-#include "routines.h"
-#include "vstring.h"
-
-/*
- *   DATA DECLARATIONS
- */
-typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
-
-typedef enum {
-	K_UNDEFINED = -1,
-	K_CONSTANT,
-	K_TYPE,
-	K_VARIABLE,
-	K_ATTRIBUTE,
-	K_SIGNAL,
-	K_FUNCTION,
-	K_PROCEDURE,
-	K_COMPONENT,
-	K_PACKAGE,
-	K_PROCESS,
-	K_ENTITY,
-	K_ARCHITECTURE,
-	K_PORT,
-	K_BLOCK,
-	K_ALIAS
-} vhdlKind;
-
-/*
- *   DATA DEFINITIONS
- */
-static int Ungetc;
-static int Lang_vhdl;
-static jmp_buf Exception;
-static vString* Name=NULL;
-static vString* Lastname=NULL;
-static vString* Keyword=NULL;
-static vString* TagName=NULL;
-
-static kindDefinition VhdlKinds [] = {
-	{ true, 'c', "variable",     "constants" },
-	{ true, 't', "typedef",      "types" },
-	{ true, 'v', "variable",     "variables" },
-	{ true, 'a', "attribute",    "attributes" },
-	{ true, 's', "variable",     "signals" },
-	{ true, 'f', "function",     "functions" },
-	{ true, 'p', "function",     "procedure" },
-	{ true, 'k', "member",       "components" },
-	{ true, 'l', "namespace",    "packages" },
-	{ true, 'm', "member",       "process" },
-	{ true, 'n', "class",        "entity" },
-	{ true, 'o', "struct",       "architecture" },
-	{ true, 'u', "port",         "ports" },
-	{ true, 'b', "member",       "blocks" },
-	{ true, 'A', "typedef",      "alias" }
-};
-
-static keywordTable VhdlKeywordTable [] = {
-	{ "constant",     K_CONSTANT },
-	{ "variable",     K_VARIABLE },
-	{ "type",         K_TYPE },
-	{ "subtype",      K_TYPE },
-	{ "signal",       K_SIGNAL },
-	{ "function",     K_FUNCTION },
-	{ "procedure",    K_PROCEDURE },
-	{ "component",    K_COMPONENT },
-	{ "package",      K_PACKAGE },
-	{ "process",      K_PROCESS },
-	{ "entity",       K_ENTITY },
-	{ "architecture", K_ARCHITECTURE },
-	{ "inout",        K_PORT },
-	{ "in",           K_PORT },
-	{ "out",          K_PORT },
-	{ "block",        K_BLOCK },
-	{ "alias",        K_ALIAS }
-};
-
-
-/*
- *   FUNCTION DEFINITIONS
- */
-
-static void initialize (const langType language)
-{
-	Lang_vhdl = language;
-}
-
-static void vUngetc (int c)
-{
-	Assert (Ungetc == '\0');
-	Ungetc = c;
-}
-
-static int vGetc (void)
-{
-	int c;
-	if (Ungetc == '\0')
-		c = getcFromInputFile ();
-	else
-	{
-		c = Ungetc;
-		Ungetc = '\0';
-	}
-	if (c == '-')
-	{
-		int c2 = getcFromInputFile ();
-		if (c2 == EOF)
-			longjmp (Exception, (int) ExceptionEOF);
-		else if (c2 == '-')   /* strip comment until end-of-line */
-		{
-			do
-				c = getcFromInputFile ();
-			while (c != '\n'  &&  c != EOF);
-		}
-		else
-			Ungetc = c2;
-	}
-	if (c == EOF)
-		longjmp (Exception, (int) ExceptionEOF);
-	return c;
-}
-
-static bool isIdentifierCharacter (const int c)
-{
-	return (bool)(isalnum (c)  ||  c == '_'  ||  c == '`');
-}
-
-static int skipWhite (int c)
-{
-	while (c==' ')
-		c = vGetc ();
-	return c;
-}
-
-static bool readIdentifier (vString *const name, int c)
-{
-	vStringClear (name);
-	if (isIdentifierCharacter (c))
-	{
-		while (isIdentifierCharacter (c))
-		{
-			vStringPut (name, c);
-			c = vGetc ();
-		}
-		vUngetc (c);
-	}
-	return (bool)(name->length > 0);
-}
-
-static void tagNameList (const vhdlKind kind, int c)
-{
-	Assert (isIdentifierCharacter (c));
-	if (isIdentifierCharacter (c))
-	{
-		readIdentifier (TagName, c);
-		makeSimpleTag (TagName, kind);
-	}
-}
-
-static void findTag (vString *const name)
-{
-	int c = '\0';
-	vhdlKind kind;
-	vStringCopyToLower (Keyword, name);
-	kind = (vhdlKind)lookupKeyword (vStringValue (Keyword), Lang_vhdl);
-	if (kind == K_UNDEFINED)
-	{
-		c = skipWhite (vGetc ());
-		vStringCopyS(Lastname,vStringValue(name));
-		if (c == ':')
-		{
-			c = skipWhite (vGetc ());
-			if (isIdentifierCharacter (c))
-			{
-				readIdentifier (name, c);
-				vStringCopyToLower (Keyword, name);
-				lookupKeyword (vStringValue (Keyword), Lang_vhdl);
-				kind = (vhdlKind)lookupKeyword (vStringValue (Keyword), Lang_vhdl);
-				if (kind == K_PROCESS || kind == K_BLOCK || kind == K_PORT)
-				{
-					makeSimpleTag (Lastname, kind);
-				}
-			}
-		} else {
-			vUngetc (c);
-		}
-	}
-	else
-	{
-		if (kind == K_SIGNAL) {
-			while (c!=':') {
-				c = skipWhite (vGetc ());
-				if (c==',')
-					c = vGetc ();
-				if (isIdentifierCharacter (c))
-					tagNameList (kind, c);
-				else
-					break;
-				c = vGetc ();
-			}
-		}
-		else if (kind == K_PROCESS || kind == K_BLOCK) {
-			vStringCopyS(TagName,"unnamed");
-			makeSimpleTag (TagName, kind);
-		} else {
-			c = skipWhite (vGetc ());
-			if (c=='\"')
-				c = vGetc ();
-			if (isIdentifierCharacter (c))
-				tagNameList (kind, c);
-		}
-	}
-}
-
-static void findVhdlTags (void)
-{
-	volatile bool newStatement = true;
-	volatile int c = '\0';
-	exception_t exception = (exception_t) setjmp (Exception);
-	Name = vStringNew ();
-	Lastname = vStringNew ();
-	Keyword = vStringNew ();
-	TagName = vStringNew ();
-
-	if (exception == ExceptionNone) while (c != EOF)
-	{
-		c = vGetc ();
-		switch (c)
-		{
-			case ';':
-			case '\n':
-				newStatement = true;
-				break;
-
-			case ' ':
-			case '\t':
-				break;
-
-			default:
-				if (newStatement && readIdentifier (Name, c)) {
-					findTag (Name);
-				}
-				newStatement = false;
-				break;
-		}
-	}
-	vStringDelete (Name);
-	vStringDelete (Lastname);
-	vStringDelete (Keyword);
-	vStringDelete (TagName);
-}
-
-extern parserDefinition* VhdlParser (void)
-{
-	static const char *const extensions [] = { "vhdl", "vhd", NULL };
-	parserDefinition* def = parserNew ("Vhdl");
-	def->kindTable  = VhdlKinds;
-	def->kindCount  = ARRAY_SIZE (VhdlKinds);
-	def->extensions = extensions;
-	def->parser     = findVhdlTags;
-	def->initialize = initialize;
-	def->keywordTable = VhdlKeywordTable;
-	def->keywordCount = ARRAY_SIZE (VhdlKeywordTable);
-	return def;
-}


Modified: ctags/parsers/vhdl.c
1083 lines changed, 1083 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,1083 @@
+/*
+*   Copyright (c) 2008, Nicolas Vincent
+*
+*   This source code is released for free distribution under the terms of the
+*   GNU General Public License version 2 or (at your option) any later version.
+*
+*   This module contains functions for generating tags for VHDL files.
+*
+*   References:
+*     https://rti.etf.bg.ac.rs/rti/ri5rvl/tutorial/TUTORIAL/IEEE/HTML/1076_TOC.HTM
+*     https://tams.informatik.uni-hamburg.de/vhdl/tools/grammar/vhdl93-bnf.html
+*     http://www.vhdl.renerta.com/mobile/index.html
+*     https://www.hdlworks.com/hdl_corner/vhdl_ref/
+*     https://www.ics.uci.edu/~jmoorkan/vhdlref/Synario%20VHDL%20Manual.pdf
+*     http://atlas.physics.arizona.edu/~kjohns/downloads/vhdl/VHDL-xilinx-help.pdf
+*     http://www.csit-sun.pub.ro/resources/xilinx/synvhdl.pdf
+*     https://edg.uchicago.edu/~tang/VHDLref.pdf
+*/
+
+/*
+ *   INCLUDE FILES
+ */
+#include "general.h"	/* must always come first */
+
+#include <ctype.h>	/* to define isalpha () */
+#include <string.h>
+
+#include "debug.h"
+#include "entry.h"
+#include "keyword.h"
+#include "parse.h"
+#include "read.h"
+#include "routines.h"
+#include "vstring.h"
+#include "trace.h"
+
+/*
+ *   MACROS
+ */
+#define isType(token,t)     (bool) ((token)->type == (t))
+#define isKeyword(token,k)  (bool) ((token)->keyword == (k))
+#define isIdentChar1(c) (isalpha (c) || (c) == '_')
+#define isIdentChar(c) (isalpha (c) || isdigit (c) || (c) == '_')
+
+/*
+ *   DATA DECLARATIONS
+ */
+
+/*
+ * Used to specify type of keyword.
+ */
+enum eKeywordId {
+	KEYWORD_ABS,
+	KEYWORD_ACCESS,
+	KEYWORD_AFTER,
+	KEYWORD_ALIAS,
+	KEYWORD_ALL,
+	KEYWORD_AND,
+	KEYWORD_ARCHITECTURE,
+	KEYWORD_ARRAY,
+	KEYWORD_ASSERT,
+	KEYWORD_ATTRIBUTE,
+	KEYWORD_BEGIN,
+	KEYWORD_BLOCK,
+	KEYWORD_BODY,
+	KEYWORD_BUFFER,
+	KEYWORD_BUS,
+	KEYWORD_CASE,
+	KEYWORD_COMPONENT,
+	KEYWORD_CONFIGURATION,
+	KEYWORD_CONSTANT,
+	KEYWORD_DISCONNECT,
+	KEYWORD_DOWNTO,
+	KEYWORD_ELSE,
+	KEYWORD_ELSIF,
+	KEYWORD_END,
+	KEYWORD_ENTITY,
+	KEYWORD_EXIT,
+	KEYWORD_FILE,
+	KEYWORD_FOR,
+	KEYWORD_FUNCTION,
+	KEYWORD_GENERATE,
+	KEYWORD_GENERIC,
+	KEYWORD_GROUP,
+	KEYWORD_GUARDED,
+	KEYWORD_IF,
+	KEYWORD_IMPURE,
+	KEYWORD_IN,
+	KEYWORD_INERTIAL,
+	KEYWORD_INOUT,
+	KEYWORD_IS,
+	KEYWORD_LABEL,
+	KEYWORD_LIBRARY,
+	KEYWORD_LINKAGE,
+	KEYWORD_LITERAL,
+	KEYWORD_LOOP,
+	KEYWORD_MAP,
+	KEYWORD_MOD,
+	KEYWORD_NAND,
+	KEYWORD_NEW,
+	KEYWORD_NEXT,
+	KEYWORD_NOR,
+	KEYWORD_NOT,
+	KEYWORD_NULL,
+	KEYWORD_OF,
+	KEYWORD_ON,
+	KEYWORD_OPEN,
+	KEYWORD_OR,
+	KEYWORD_OTHERS,
+	KEYWORD_OUT,
+	KEYWORD_PACKAGE,
+	KEYWORD_PORT,
+	KEYWORD_POSTPONED,
+	KEYWORD_PROCEDURE,
+	KEYWORD_PROCESS,
+	KEYWORD_PURE,
+	KEYWORD_RANGE,
+	KEYWORD_RECORD,
+	KEYWORD_REGISTER,
+	KEYWORD_REJECT,
+	KEYWORD_RETURN,
+	KEYWORD_ROL,
+	KEYWORD_ROR,
+	KEYWORD_SELECT,
+	KEYWORD_SEVERITY,
+	KEYWORD_SIGNAL,
+	KEYWORD_SHARED,
+	KEYWORD_SLA,
+	KEYWORD_SLI,
+	KEYWORD_SRA,
+	KEYWORD_SRL,
+	KEYWORD_SUBTYPE,
+	KEYWORD_THEN,
+	KEYWORD_TO,
+	KEYWORD_TRANSPORT,
+	KEYWORD_TYPE,
+	KEYWORD_UNAFFECTED,
+	KEYWORD_UNITS,
+	KEYWORD_UNTIL,
+	KEYWORD_USE,
+	KEYWORD_VARIABLE,
+	KEYWORD_WAIT,
+	KEYWORD_WHEN,
+	KEYWORD_WHILE,
+	KEYWORD_WITH,
+	KEYWORD_XNOR,
+	KEYWORD_XOR
+};
+typedef int keywordId; /* to allow KEYWORD_NONE */
+
+typedef enum eTokenType {
+	TOKEN_NONE,		/* none */
+	TOKEN_EOF,		/* end-of-file */
+	TOKEN_OPEN_PAREN,	/* ( */
+	TOKEN_CLOSE_PAREN,	/* ) */
+	TOKEN_COMMA,		/* the comma character */
+	TOKEN_IDENTIFIER,
+	TOKEN_KEYWORD,
+	TOKEN_PERIOD,		/* . */
+	TOKEN_OPERATOR,
+	TOKEN_SEMICOLON,	/* the semicolon character */
+	TOKEN_COLON,		/* : */
+	TOKEN_STRING
+} tokenType;
+
+typedef struct sTokenInfo {
+	tokenType type;
+	keywordId keyword;
+	vString *string;		/* the name of the token */
+	unsigned long lineNumber;	/* line number of tag */
+	MIOPos filePosition;		/* file position of line containing name */
+} tokenInfo;
+
+/*
+ *   DATA DEFINITIONS
+ */
+static int Lang_vhdl;
+
+typedef enum {
+	VHDL_ENTITY_DESIGNED,
+} vhdlEntityRole;
+
+static roleDefinition VhdlEntityRoles [] = {
+	{ true, "desigend",
+	  "designed by an architecture" },
+};
+
+/* Used to index into the VhdlKinds table. */
+typedef enum {
+	VHDLTAG_UNDEFINED = -1,
+	VHDLTAG_CONSTANT,
+	VHDLTAG_TYPE,
+	VHDLTAG_SUBTYPE,
+	VHDLTAG_RECORD,
+	VHDLTAG_ENTITY,
+	VHDLTAG_COMPONENT,
+	VHDLTAG_PROTOTYPE,
+	VHDLTAG_FUNCTION,
+	VHDLTAG_PROCEDURE,
+	VHDLTAG_PACKAGE,
+	VHDLTAG_LOCAL,
+	VHDLTAG_ARCHITECTURE,
+	VHDLTAG_PORT,
+	VHDLTAG_GENERIC,
+	VHDLTAG_SIGNAL,
+	VHDLTAG_PROCESS,
+	VHDLTAG_VARIABLE,
+	VHDLTAG_ALIAS,
+} vhdlKind;
+
+static kindDefinition VhdlKinds[] = {
+	{true, 'c', "constant", "constant declarations"},
+	{true, 't', "type", "type definitions"},
+	{true, 'T', "subtype", "subtype definitions"},
+	{true, 'r', "record", "record names"},
+	{true, 'e', "entity", "entity declarations",
+	 .referenceOnly = false, ATTACH_ROLES(VhdlEntityRoles)},
+	{false, 'C', "component", "component declarations"},
+	{false, 'd', "prototype", "prototypes"},
+	{true, 'f', "function", "function prototypes and declarations"},
+	{true, 'p', "procedure", "procedure prototypes and declarations"},
+	{true, 'P', "package", "package definitions"},
+	{false, 'l', "local", "local definitions"},
+	{true, 'a', "architecture", "architectures"},
+	{true, 'q', "port", "port declarations"},
+	{true, 'g', "generic", "generic declarations"},
+	{true , 's', "signal", "signal declarations"},
+	{true, 'Q',  "process", "processes"},
+	{true, 'v',  "variable", "variables"},
+	{true, 'A',  "alias", "aliases"},
+};
+
+static const keywordTable VhdlKeywordTable[] = {
+	{"abs", KEYWORD_ABS},
+	{"access", KEYWORD_ACCESS},
+	{"after", KEYWORD_AFTER},
+	{"alias", KEYWORD_ALIAS},
+	{"all", KEYWORD_ALL},
+	{"and", KEYWORD_AND},
+	{"architecture", KEYWORD_ARCHITECTURE},
+	{"array", KEYWORD_ARRAY},
+	{"assert", KEYWORD_ASSERT},
+	{"attribute", KEYWORD_ATTRIBUTE},
+	{"begin", KEYWORD_BEGIN},
+	{"block", KEYWORD_BLOCK},
+	{"body", KEYWORD_BODY},
+	{"buffer", KEYWORD_BUFFER},
+	{"bus", KEYWORD_BUS},
+	{"case", KEYWORD_CASE},
+	{"component", KEYWORD_COMPONENT},
+	{"configuration", KEYWORD_CONFIGURATION},
+	{"constant", KEYWORD_CONSTANT},
+	{"disconnect", KEYWORD_DISCONNECT},
+	{"downto", KEYWORD_DOWNTO},
+	{"else", KEYWORD_ELSE},
+	{"elsif", KEYWORD_ELSIF},
+	{"end", KEYWORD_END},
+	{"entity", KEYWORD_ENTITY},
+	{"exit", KEYWORD_EXIT},
+	{"file", KEYWORD_FILE},
+	{"for", KEYWORD_FOR},
+	{"function", KEYWORD_FUNCTION},
+	{"generate", KEYWORD_GENERATE},
+	{"generic", KEYWORD_GENERIC},
+	{"group", KEYWORD_GROUP},
+	{"guarded", KEYWORD_GUARDED},
+	{"if", KEYWORD_IF},
+	{"impure", KEYWORD_IMPURE},
+	{"in", KEYWORD_IN},
+	{"inertial", KEYWORD_INERTIAL},
+	{"inout", KEYWORD_INOUT},
+	{"is", KEYWORD_IS},
+	{"label", KEYWORD_LABEL},
+	{"library", KEYWORD_LIBRARY},
+	{"linkage", KEYWORD_LINKAGE},
+	{"literal", KEYWORD_LITERAL},
+	{"loop", KEYWORD_LOOP},
+	{"map", KEYWORD_MAP},
+	{"mod", KEYWORD_MOD},
+	{"nand", KEYWORD_NAND},
+	{"new", KEYWORD_NEW},
+	{"next", KEYWORD_NEXT},
+	{"nor", KEYWORD_NOR},
+	{"not", KEYWORD_NOT},
+	{"null", KEYWORD_NULL},
+	{"of", KEYWORD_OF},
+	{"on", KEYWORD_ON},
+	{"open", KEYWORD_OPEN},
+	{"or", KEYWORD_OR},
+	{"others", KEYWORD_OTHERS},
+	{"out", KEYWORD_OUT},
+	{"package", KEYWORD_PACKAGE},
+	{"port", KEYWORD_PORT},
+	{"postponed", KEYWORD_POSTPONED},
+	{"procedure", KEYWORD_PROCEDURE},
+	{"process", KEYWORD_PROCESS},
+	{"pure", KEYWORD_PURE},
+	{"range", KEYWORD_RANGE},
+	{"record", KEYWORD_RECORD},
+	{"register", KEYWORD_REGISTER},
+	{"reject", KEYWORD_REJECT},
+	{"return", KEYWORD_RETURN},
+	{"rol", KEYWORD_ROL},
+	{"ror", KEYWORD_ROR},
+	{"select", KEYWORD_SELECT},
+	{"severity", KEYWORD_SEVERITY},
+	{"signal", KEYWORD_SIGNAL},
+	{"shared", KEYWORD_SHARED},
+	{"sla", KEYWORD_SLA},
+	{"sli", KEYWORD_SLI},
+	{"sra", KEYWORD_SRA},
+	{"srl", KEYWORD_SRL},
+	{"subtype", KEYWORD_SUBTYPE},
+	{"then", KEYWORD_THEN},
+	{"to", KEYWORD_TO},
+	{"transport", KEYWORD_TRANSPORT},
+	{"type", KEYWORD_TYPE},
+	{"unaffected", KEYWORD_UNAFFECTED},
+	{"units", KEYWORD_UNITS},
+	{"until", KEYWORD_UNTIL},
+	{"use", KEYWORD_USE},
+	{"variable", KEYWORD_VARIABLE},
+	{"wait", KEYWORD_WAIT},
+	{"when", KEYWORD_WHEN},
+	{"while", KEYWORD_WHILE},
+	{"with", KEYWORD_WITH},
+	{"xnor", KEYWORD_XNOR},
+	{"xor", KEYWORD_XOR}
+};
+
+typedef enum {
+	F_ARCHITECTURE,
+} vhdlField;
+
+static fieldDefinition VhdlFields [] = {
+	{ .name = "architecture",
+	  .description = "architecture designing the entity",
+	  .enabled = true },
+};
+
+/*
+ *   FUNCTION DECLARATIONS
+ */
+static void parseKeywords (tokenInfo * const token, tokenInfo * const label, int parent);
+
+/*
+ *   FUNCTION DEFINITIONS
+ */
+static bool isIdentifierMatch (const tokenInfo * const token,
+	const char *name)
+{
+	return (bool) (isType (token, TOKEN_IDENTIFIER) &&
+		strncasecmp (vStringValue (token->string), name,
+					 vStringLength (token->string)) == 0);
+}
+
+static bool isSemicolonOrKeywordOrIdent (const tokenInfo * const token,
+	const keywordId keyword, const char *name)
+{
+	return (bool) (isType (token, TOKEN_SEMICOLON)
+				   || isKeyword (token, keyword)
+				   || isIdentifierMatch (token, name));
+}
+
+static tokenInfo *newToken (void)
+{
+	tokenInfo *const token = xMalloc (1, tokenInfo);
+	token->type = TOKEN_NONE;
+	token->keyword = KEYWORD_NONE;
+	token->string = vStringNew ();
+	token->lineNumber = getInputLineNumber ();
+	token->filePosition = getInputFilePosition ();
+	return token;
+}
+
+static tokenInfo *copyToken (tokenInfo * const src)
+{
+	tokenInfo *dst = newToken ();
+	vStringCopy (dst->string, src->string);
+	return dst;
+}
+
+static void deleteToken (tokenInfo * const token)
+{
+	if (token != NULL)
+	{
+		vStringDelete (token->string);
+		eFree (token);
+	}
+}
+
+/*
+ *   Parsing functions
+ */
+
+static void parseString (vString * const string, const int delimiter)
+{
+	bool end = false;
+	while (!end)
+	{
+		int c = getcFromInputFile ();
+		if (c == EOF)
+			end = true;
+		else if (c == '\\')
+		{
+			c = getcFromInputFile ();	/* This maybe a ' or ". */
+			vStringPut (string, c);
+		}
+		else if (c == delimiter)
+			end = true;
+		else
+			vStringPut (string, c);
+	}
+}
+
+/*  Read a VHDL identifier beginning with "firstChar" and place it into "name".
+*/
+static void parseIdentifier (vString * const string, const int firstChar)
+{
+	int c = firstChar;
+	Assert (isIdentChar1 (c));
+	do
+	{
+		vStringPut (string, c);
+		c = getcFromInputFile ();
+	} while (isIdentChar (c));
+	if (!isspace (c))
+		ungetcToInputFile (c);	/* unget non-identifier character */
+}
+
+static void readToken (tokenInfo * const token)
+{
+	int c;
+
+	token->type = TOKEN_NONE;
+	token->keyword = KEYWORD_NONE;
+	vStringClear (token->string);
+
+  getNextChar:
+	do
+	{
+		c = getcFromInputFile ();
+		token->lineNumber = getInputLineNumber ();
+		token->filePosition = getInputFilePosition ();
+	}
+	while (c == '\t' || c == ' ' || c == '\n');
+
+	switch (c)
+	{
+	case EOF:
+		token->type = TOKEN_EOF;
+		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_COLON;
+		break;
+	case '.':
+		token->type = TOKEN_PERIOD;
+		break;
+	case ',':
+		token->type = TOKEN_COMMA;
+		break;
+	case '\'':	/* only single char are inside simple quotes */
+		break;	/* or it is for attributes so we don't care */
+	case '"':
+		token->type = TOKEN_STRING;
+		parseString (token->string, c);
+		token->lineNumber = getInputLineNumber ();
+		token->filePosition = getInputFilePosition ();
+		break;
+	case '-':
+		c = getcFromInputFile ();
+		if (c == '-')	/* start of a comment */
+		{
+			skipToCharacterInInputFile ('\n');
+			goto getNextChar;
+		}
+		else
+		{
+			if (!isspace (c))
+				ungetcToInputFile (c);
+			token->type = TOKEN_OPERATOR;
+		}
+		break;
+	default:
+		if (!isIdentChar1 (c))
+			token->type = TOKEN_NONE;
+		else
+		{
+			parseIdentifier (token->string, c);
+			token->lineNumber = getInputLineNumber ();
+			token->filePosition = getInputFilePosition ();
+			token->keyword = lookupCaseKeyword (vStringValue (token->string), Lang_vhdl);
+			if (isKeyword (token, KEYWORD_NONE))
+				token->type = TOKEN_IDENTIFIER;
+			else
+				token->type = TOKEN_KEYWORD;
+		}
+		break;
+	}
+}
+
+static bool skipToKeyword (const keywordId keyword)
+{
+	tokenInfo *const token = newToken ();
+	do
+	{
+		readToken (token);
+	}
+	while (!isType (token, TOKEN_EOF) && !isKeyword (token, keyword));
+
+	bool r = isKeyword (token, keyword);
+	deleteToken (token);
+	return r;
+}
+
+static void skipToMatched (tokenInfo * const token)
+{
+	int nest_level = 0;
+	tokenType open_token;
+	tokenType close_token;
+
+	switch (token->type)
+	{
+	case TOKEN_OPEN_PAREN:
+		open_token = TOKEN_OPEN_PAREN;
+		close_token = TOKEN_CLOSE_PAREN;
+		break;
+	default:
+		return;
+	}
+
+	/*
+	 * This routine will skip to a matching closing token.
+	 * It will also handle nested tokens like the (, ) below.
+	 *   (  name varchar(30), text binary(10)  )
+	 */
+	if (isType (token, open_token))
+	{
+		nest_level++;
+		while (!(isType (token, close_token) && (nest_level == 0)) && !isType (token, TOKEN_EOF))
+		{
+			readToken (token);
+			if (isType (token, open_token))
+			{
+				nest_level++;
+			}
+			if (isType (token, close_token))
+			{
+				if (nest_level > 0)
+				{
+					nest_level--;
+				}
+			}
+		}
+		readToken (token);
+	}
+}
+
+static int makeVhdlTagWithScope (tokenInfo * const token, const vhdlKind kind, int parent)
+{
+	const char *const name = vStringValue (token->string);
+	tagEntryInfo e;
+	initTagEntry (&e, name, kind);
+	e.lineNumber = token->lineNumber;
+	e.filePosition = token->filePosition;
+	e.extensionFields.scopeIndex = parent;
+	return makeTagEntry (&e);
+}
+
+static int makeVhdlTag (tokenInfo * const token, const vhdlKind kind)
+{
+	return makeVhdlTagWithScope (token, kind, CORK_NIL);
+}
+
+static void initialize (const langType language)
+{
+	Lang_vhdl = language;
+}
+
+static void parseTillEnd (tokenInfo * const token, int parent, const int end_keyword)
+{
+	bool ended = false;
+	tagEntryInfo *e = getEntryInCorkQueue (parent);
+	/* If e is NULL, the input may be broken as VHDL code
+	 * or unsupported syntax in this parser. */
+
+	do
+	{
+		readToken (token);
+		if (isKeyword (token, KEYWORD_END))
+		{
+			readToken (token);
+			if (e)
+				ended = isSemicolonOrKeywordOrIdent (token,
+													 end_keyword, e->name);
+			if (!isType (token, TOKEN_SEMICOLON))
+				skipToCharacterInInputFile (';');
+			if (ended)
+				e->extensionFields.endLine = getInputLineNumber ();
+		}
+		else
+		{
+			if (isType (token, TOKEN_EOF))
+			{
+				ended = true;
+			}
+			else
+			{
+				parseKeywords (token, NULL, parent);
+			}
+		}
+	} while (!ended);
+}
+
+static void parseTillBegin (tokenInfo * const token, int parent)
+{
+	bool begun = false;
+	do
+	{
+		readToken (token);
+		if (isKeyword (token, KEYWORD_BEGIN)
+			|| isType (token, TOKEN_EOF))
+			begun = true;
+		else
+			parseKeywords (token, NULL, parent);
+	} while (!begun);
+}
+
+static void parsePackage (tokenInfo * const token)
+{
+	tokenInfo *const name = newToken ();
+	tokenInfo *token_for_tagging = NULL;
+	Assert (isKeyword (token, KEYWORD_PACKAGE));
+	readToken (token);
+	if (isKeyword (token, KEYWORD_BODY))
+	{
+		readToken (name);
+		token_for_tagging = name;
+	}
+	else if (isType (token, TOKEN_IDENTIFIER))
+		token_for_tagging = token;
+
+	if (token_for_tagging)
+	{
+		int index = makeVhdlTag (token_for_tagging, VHDLTAG_PACKAGE);
+		parseTillEnd (token, index, KEYWORD_PACKAGE);
+	}
+
+	deleteToken (name);
+}
+
+
+static void parseDeclElement (tokenInfo * const token,
+							  vhdlKind kind, int parent,
+							  bool ended_with_semicolon)
+{
+	TRACE_ENTER ();
+	while (! (isType (token, TOKEN_EOF)
+			  || isType (token, TOKEN_CLOSE_PAREN)
+			  || (ended_with_semicolon && isType (token, TOKEN_SEMICOLON))))
+	{
+		if (isType (token, TOKEN_IDENTIFIER))
+		{
+			makeVhdlTagWithScope (token, kind, parent);
+			readToken (token);
+		}
+		else if (isType (token, TOKEN_COMMA))
+			readToken (token);
+		else if (isType (token, TOKEN_COLON))
+		{
+			do
+			{
+				readToken (token);
+				skipToMatched (token);
+				if (isType (token, TOKEN_CLOSE_PAREN)
+					|| isType (token, TOKEN_SEMICOLON))
+					break;
+			}
+			while (!isType (token, TOKEN_EOF));
+		}
+		else
+		{
+			/* Unexpected */
+			readToken (token);
+		}
+	}
+	TRACE_LEAVE ();
+}
+
+static void parseModuleDecl (tokenInfo * const token, int parent)
+{
+	TRACE_ENTER ();
+	while (! (isKeyword (token, KEYWORD_END)
+			  || isType (token, TOKEN_EOF)))
+	{
+		vhdlKind kind = VHDLTAG_UNDEFINED;
+		if (isKeyword (token, KEYWORD_PORT))
+			kind = VHDLTAG_PORT;
+		else if (isKeyword (token, KEYWORD_GENERIC))
+			kind = VHDLTAG_GENERIC;
+
+		if (kind != VHDLTAG_UNDEFINED)
+		{
+			readToken (token);
+			if (isType (token, TOKEN_OPEN_PAREN))
+			{
+				readToken (token);
+				parseDeclElement (token, kind, parent, false);
+			}
+		}
+		else
+			readToken (token);
+	}
+	TRACE_LEAVE ();
+}
+
+static void parseModule (tokenInfo * const token, int parent)
+{
+	tokenInfo *const name = newToken ();
+	const vhdlKind kind = isKeyword (token, KEYWORD_ENTITY) ?
+		VHDLTAG_ENTITY : VHDLTAG_COMPONENT;
+	Assert (isKeyword (token, KEYWORD_ENTITY) ||
+		isKeyword (token, KEYWORD_COMPONENT));
+	readToken (name);
+	readToken (token);
+	if (kind == VHDLTAG_COMPONENT || isKeyword (token, KEYWORD_IS))
+	{
+		int index = makeVhdlTagWithScope (name, kind, parent);
+		if (isKeyword (token, KEYWORD_IS))
+			readToken (token);
+		parseModuleDecl (token, index);
+
+		bool ended = isKeyword (token, KEYWORD_END);
+		if (!ended)
+			ended = skipToKeyword (KEYWORD_END);
+		skipToCharacterInInputFile (';');
+
+		if (ended)
+		{
+			tagEntryInfo *e = getEntryInCorkQueue (index);
+			if (e)
+				e->extensionFields.endLine = getInputLineNumber ();
+		}
+
+		if (kind == VHDLTAG_ENTITY)
+			registerEntry (index);
+	}
+	deleteToken (name);
+}
+
+static void parseRecord (tokenInfo * const token, int parent)
+{
+	tokenInfo *const name = newToken ();
+	Assert (isKeyword (token, KEYWORD_RECORD));
+	readToken (name);
+	do
+	{
+		readToken (token);	/* should be a colon */
+		skipToCharacterInInputFile (';');
+		makeVhdlTagWithScope (name, VHDLTAG_RECORD, parent);
+		readToken (name);
+	}
+	while (!isKeyword (name, KEYWORD_END) && !isType (name, TOKEN_EOF));
+	skipToCharacterInInputFile (';');
+
+	if (isKeyword (name, KEYWORD_END))
+	{
+		tagEntryInfo *e = getEntryInCorkQueue (parent);
+		if (e)
+			e->extensionFields.endLine = getInputLineNumber ();
+	}
+
+	deleteToken (name);
+}
+
+static void parseTypes (tokenInfo * const token, int parent)
+{
+	tokenInfo *const name = newToken ();
+	const vhdlKind kind = isKeyword (token, KEYWORD_TYPE) ?
+		VHDLTAG_TYPE : VHDLTAG_SUBTYPE;
+	Assert (isKeyword (token, KEYWORD_TYPE) ||
+		isKeyword (token, KEYWORD_SUBTYPE));
+	readToken (name);
+	readToken (token);
+	if (isKeyword (token, KEYWORD_IS))
+	{
+		readToken (token);	/* type */
+		if (isKeyword (token, KEYWORD_RECORD))
+		{
+			int index = makeVhdlTagWithScope (name, kind, parent);
+			/*TODO: make tags of the record's names */
+			parseRecord (token, index);
+		}
+		else
+		{
+			makeVhdlTagWithScope (name, kind, parent);
+		}
+	}
+	deleteToken (name);
+}
+
+static void parseConstant (int parent)
+{
+	vhdlKind parent_kind = VHDLTAG_UNDEFINED;
+	tagEntryInfo *e = getEntryInCorkQueue (parent);
+	if (e)
+		parent_kind = e->kindIndex;
+
+	vhdlKind kind;
+	switch (parent_kind)
+	{
+	case VHDLTAG_FUNCTION:
+	case VHDLTAG_PROCEDURE:
+		kind = VHDLTAG_LOCAL;
+		break;
+	default:
+		kind = VHDLTAG_CONSTANT;
+		break;
+	}
+
+	tokenInfo *const name = newToken ();
+	readToken (name);
+	makeVhdlTagWithScope (name, kind, parent);
+	skipToCharacterInInputFile (';');
+	deleteToken (name);
+}
+
+static void parseSubProgram (tokenInfo * const token, int parent)
+{
+	tokenInfo *const name = newToken ();
+	const vhdlKind kind = isKeyword (token, KEYWORD_FUNCTION) ?
+		VHDLTAG_FUNCTION : VHDLTAG_PROCEDURE;
+	const int end_keyword = token->keyword;
+	Assert (isKeyword (token, KEYWORD_FUNCTION) ||
+		isKeyword (token, KEYWORD_PROCEDURE));
+	readToken (name);	/* the name of the function or procedure */
+	readToken (token);
+	if (isType (token, TOKEN_OPEN_PAREN))
+	{
+		skipToMatched (token);
+	}
+
+	if (kind == VHDLTAG_FUNCTION)
+	{
+		if (isKeyword (token, KEYWORD_RETURN))
+		{
+			/* Read datatype */
+			readToken (token);
+			while (! isKeyword (token, KEYWORD_IS) &&
+					! isType (token, TOKEN_SEMICOLON) &&
+					! isType (token, TOKEN_EOF))
+			{
+				readToken (token);
+			}
+		}
+	}
+
+	if (isType (token, TOKEN_SEMICOLON))
+	{
+		makeVhdlTagWithScope (name, VHDLTAG_PROTOTYPE, parent);
+	}
+	else if (isKeyword (token, KEYWORD_IS))
+	{
+		int index = makeVhdlTagWithScope (name, kind, parent);
+		parseTillEnd (token, index, end_keyword);
+	}
+	deleteToken (name);
+}
+
+/*  architecture behavioral of ent is*/
+static void parseArchitecture (tokenInfo * const token)
+{
+	tokenInfo *const name = newToken ();
+
+	readToken (name);
+	if (!isType (name, TOKEN_IDENTIFIER))
+	{
+		skipToKeyword (KEYWORD_END);
+		skipToCharacterInInputFile (';');
+		deleteToken (name);
+		return;
+	}
+
+	int index = makeVhdlTag (name, VHDLTAG_ARCHITECTURE);
+	readToken (token);
+	if (isKeyword (token, KEYWORD_OF))
+	{
+		readToken (token);
+		if (isType (token, TOKEN_IDENTIFIER))
+		{
+			/* Filling scope field of this architecture.
+			   If the definition for the entity can be found in the symbol table,
+			   use its cork as the scope. If not, use the reference tag for the
+			   entity as fallback. */
+			int role_index = makeSimpleRefTag (token->string,
+											   VHDLTAG_ENTITY, VHDL_ENTITY_DESIGNED);
+			int entity_index = anyKindEntryInScope (CORK_NIL,
+													vStringValue (token->string),
+													VHDLTAG_ENTITY);
+			tagEntryInfo *e = getEntryInCorkQueue (index);
+			if (e)
+			{
+				e->extensionFields.scopeIndex = (
+					entity_index == CORK_NIL
+					? role_index
+					: entity_index);
+
+				/* TODO: append thes architecture name to
+				 * architecture: field of *e*. */
+			}
+
+			attachParserFieldToCorkEntry (role_index,
+										  VhdlFields[F_ARCHITECTURE].ftype,
+										  vStringValue (name->string));
+
+			readToken (token);
+			if (isKeyword (token, KEYWORD_IS))
+			{
+				parseTillBegin (token, index);
+				parseTillEnd (token, index, KEYWORD_ARCHITECTURE);
+			}
+		}
+	}
+	deleteToken (name);
+}
+
+static void parseSignal (tokenInfo * const token, int parent)
+{
+	readToken (token);
+	parseDeclElement (token, VHDLTAG_SIGNAL, parent, true);
+}
+
+static void parseLabel (tokenInfo * const name, int parent)
+{
+	tokenInfo *const token = newToken ();
+
+	readToken (token);
+	if (isType (token, TOKEN_COLON))
+	{
+		readToken (token);
+		if (isType (token, TOKEN_KEYWORD))
+			parseKeywords (token, name, parent);
+	}
+	deleteToken (token);
+}
+
+static void parseProcess (tokenInfo * const token, tokenInfo * const label, int parent)
+{
+	tokenInfo *process = label? label: copyToken (token);
+
+	if (label == NULL)
+	{
+		process->type = TOKEN_IDENTIFIER;
+		vStringClear (process->string);
+		anonGenerate (process->string, "anonProcess", VHDLTAG_PROCESS);
+	}
+
+	int index = makeVhdlTagWithScope (process, VHDLTAG_PROCESS, parent);
+
+	if (label == NULL)
+	{
+		tagEntryInfo *e = getEntryInCorkQueue (index);
+		if (e)
+			markTagExtraBit (e, XTAG_ANONYMOUS);
+		deleteToken (process);
+	}
+
+	skipToMatched (token);
+	parseTillBegin (token, index);
+	parseTillEnd (token, index, KEYWORD_PROCESS);
+}
+
+static void parseVariable (tokenInfo * const token, int parent)
+{
+	readToken (token);
+	parseDeclElement (token, VHDLTAG_VARIABLE, parent, true);
+}
+
+static void parseAlias (tokenInfo * const token, int parent)
+{
+	readToken (token);
+	parseDeclElement (token, VHDLTAG_ALIAS, parent, true);
+}
+
+/* TODO */
+/* records */
+static void parseKeywords (tokenInfo * const token, tokenInfo * const label, int index)
+{
+	switch (token->keyword)
+	{
+	case KEYWORD_END:
+		skipToCharacterInInputFile (';');
+		break;
+	case KEYWORD_CONSTANT:
+		parseConstant (index);
+		break;
+	case KEYWORD_TYPE:
+		parseTypes (token, index);
+		break;
+	case KEYWORD_SUBTYPE:
+		parseTypes (token, index);
+		break;
+	case KEYWORD_ENTITY:
+		parseModule (token, index);
+		break;
+	case KEYWORD_COMPONENT:
+		parseModule (token, index);
+		break;
+	case KEYWORD_FUNCTION:
+		parseSubProgram (token, index);
+		break;
+	case KEYWORD_PROCEDURE:
+		parseSubProgram (token, index);
+		break;
+	case KEYWORD_PACKAGE:
+		parsePackage (token);
+		break;
+	case KEYWORD_ARCHITECTURE:
+		parseArchitecture (token);
+		break;
+	case KEYWORD_SIGNAL:
+		parseSignal (token, index);
+		break;
+	case KEYWORD_PROCESS:
+		parseProcess (token, label, index);
+		break;
+	case KEYWORD_VARIABLE:
+		parseVariable (token, index);
+		break;
+	case KEYWORD_ALIAS:
+		parseAlias (token, index);
+		break;
+	default:
+		if (isType (token, TOKEN_IDENTIFIER))
+			parseLabel (token, index);
+		break;
+	}
+}
+
+static tokenType parseVhdlFile (tokenInfo * const token)
+{
+	do
+	{
+		readToken (token);
+		parseKeywords (token, NULL, CORK_NIL);
+	} while (!isKeyword (token, KEYWORD_END) && !isType (token, TOKEN_EOF));
+	return token->type;
+}
+
+static void findVhdlTags (void)
+{
+	tokenInfo *const token = newToken ();
+
+	while (parseVhdlFile (token) != TOKEN_EOF);
+
+	deleteToken (token);
+}
+
+extern parserDefinition *VhdlParser (void)
+{
+	static const char *const extensions[] = { "vhdl", "vhd", NULL };
+	parserDefinition *def = parserNew ("VHDL");
+	def->kindTable = VhdlKinds;
+	def->kindCount = ARRAY_SIZE (VhdlKinds);
+	def->extensions = extensions;
+	def->parser = findVhdlTags;
+	def->initialize = initialize;
+	def->keywordTable = VhdlKeywordTable;
+	def->keywordCount = ARRAY_SIZE (VhdlKeywordTable);
+	def->fieldTable = VhdlFields;
+	def->fieldCount = ARRAY_SIZE (VhdlFields);
+	def->useCork = CORK_QUEUE|CORK_SYMTAB;
+	return def;
+}


Modified: meson.build
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -639,7 +639,6 @@ ctags = static_library('ctags',
 	'ctags/parsers/geany_markdown.c',
 	'ctags/parsers/geany_matlab.c',
 	'ctags/parsers/geany_tex.c',
-	'ctags/parsers/geany_vhdl.c',
 	'ctags/parsers/go.c',
 	'ctags/parsers/haskell.c',
 	'ctags/parsers/haxe.c',
@@ -672,6 +671,7 @@ ctags = static_library('ctags',
 	'ctags/parsers/tcloo.c',
 	'ctags/parsers/txt2tags.c',
 	'ctags/parsers/verilog.c',
+	'ctags/parsers/vhdl.c',
 	c_args: geany_cflags + [ '-DG_LOG_DOMAIN="CTags"',
 	                         '-DEXTERNAL_PARSER_LIST_FILE="src/tagmanager/tm_parsers.h"' ],
 	dependencies: deps + [dep_fnmatch, dep_regex],


Modified: src/tagmanager/tm_parser.c
36 lines changed, 20 insertions(+), 16 deletions(-)
===================================================================
@@ -444,29 +444,32 @@ static TMParserMapGroup group_DIFF[] = {
 };
 
 static TMParserMapEntry map_VHDL[] = {
-	{'c', tm_tag_variable_t},
-	{'t', tm_tag_typedef_t},
-	{'v', tm_tag_variable_t},
-	{'a', tm_tag_undef_t},
-	{'s', tm_tag_variable_t},
-	{'f', tm_tag_function_t},
-	{'p', tm_tag_function_t},
-	{'k', tm_tag_member_t},
-	{'l', tm_tag_namespace_t},
-	{'m', tm_tag_member_t},
-	{'n', tm_tag_class_t},
-	{'o', tm_tag_struct_t},
-	{'u', tm_tag_undef_t},
-	{'b', tm_tag_member_t},
-	{'A', tm_tag_typedef_t},
+	{'c', tm_tag_variable_t},   // constant
+	{'t', tm_tag_typedef_t},    // type
+	{'T', tm_tag_typedef_t},    // subtype
+	{'r', tm_tag_undef_t},      // record
+	{'e', tm_tag_class_t},      // entity
+	{'C', tm_tag_member_t},     // component
+	{'d', tm_tag_undef_t},      // prototype
+	{'f', tm_tag_function_t},   // function
+	{'p', tm_tag_function_t},   // procedure
+	{'P', tm_tag_namespace_t},  // package
+	{'l', tm_tag_variable_t},   // local
+	{'a', tm_tag_struct_t},     // architecture
+	{'q', tm_tag_variable_t},   // port
+	{'g', tm_tag_undef_t},      // generic
+	{'s', tm_tag_variable_t},   // signal
+	{'Q', tm_tag_member_t},     // process
+	{'v', tm_tag_variable_t},   // variable
+	{'A', tm_tag_typedef_t},    // alias
 };
 static TMParserMapGroup group_VHDL[] = {
 	{_("Package"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
 	{_("Entities"), TM_ICON_CLASS, tm_tag_class_t},
 	{_("Architectures"), TM_ICON_STRUCT, tm_tag_struct_t},
 	{_("Types"), TM_ICON_OTHER, tm_tag_typedef_t},
 	{_("Functions / Procedures"), TM_ICON_METHOD, tm_tag_function_t},
-	{_("Variables / Signals"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Variables / Signals / Ports"), TM_ICON_VAR, tm_tag_variable_t},
 	{_("Processes / Blocks / Components"), TM_ICON_MEMBER, tm_tag_member_t},
 };
 
@@ -1519,6 +1522,7 @@ gboolean tm_parser_has_full_scope(TMParserType lang)
 		case TM_PARSER_TCLOO:
 		case TM_PARSER_TXT2TAGS:
 		case TM_PARSER_VALA:
+		case TM_PARSER_VHDL:
 		case TM_PARSER_VERILOG:
 		case TM_PARSER_ZEPHIR:
 			return TRUE;


Modified: tests/ctags/Makefile.am
6 lines changed, 5 insertions(+), 1 deletions(-)
===================================================================
@@ -327,7 +327,6 @@ test_sources = \
 	test.erl						\
 	test.go							\
 	test.py							\
-	test.vhd						\
 	test_input.rs					\
 	test_input2.rs					\
 	titles.t2t						\
@@ -337,6 +336,11 @@ test_sources = \
 	union.f							\
 	value.f							\
 	var-and-return-type.cpp			\
+	vhdl-component.vhd				\
+	vhdl-local.vhd					\
+	vhdl-port.vhd					\
+	vhdl-process.vhd				\
+	vhdl-type.vhd					\
 	whitespaces.php					\
 	$(NULL)
 test_results = $(test_sources:=.tags)


Modified: tests/ctags/bug2374109.vhd.tags
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1,3 +1,3 @@
 # format=tagmanager
 Pow2�16�0
-Result�16384�0
+Result�16384�Pow2�0


Modified: tests/ctags/test.vhd
8174 lines changed, 0 insertions(+), 8174 deletions(-)
===================================================================
No diff available, check online


Modified: tests/ctags/test.vhd.tags
358 lines changed, 0 insertions(+), 358 deletions(-)
===================================================================
@@ -1,358 +0,0 @@
-# format=tagmanager
-ADly�16384�0
-AND2�1�0
-AND2�64�0
-AtcStatusReg�16384�0
-BDly�16384�0
-BIDIR�1�0
-BIDIR�64�0
-B_Busy�16384�0
-Backoff�16384�0
-BidirBuf�1�0
-BidirBuf�64�0
-BidirCnt�1�0
-CaptureOutputs�16384�0
-ClkDly�16384�0
-ClkPeriod�16384�0
-Cnt�16384�0
-Cnt4Term�1�0
-Cnt4Term�64�0
-CntL�16384�0
-CntVal�16384�0
-Const�16384�0
-Counter�1�0
-CtrlBits�4096�0
-CtrlRegRange�16384�0
-DEC2x4�16�0
-DFF�1�0
-DFFE�1�0
-DFFE�64�0
-DFFE_SR�1�0
-DFFE_SR�64�0
-DLATCHH�1�0
-DLATCHH�64�0
-DelayMux�64�0
-Dont_Care�16384�0
-ErrorMsg�16384�0
-ErrorMsgLine�16384�0
-FEWGATES�1�0
-FlopOut�16384�0
-ForceShare�1�0
-FoundError�16384�0
-GatesPkg�256�0
-INVERTER�1�0
-INVERTER�64�0
-Idle�16384�0
-IntCtrlReg�16384�0
-IoIntStatReg�16384�0
-LPCI_Devsel_n�16384�0
-LPCI_Stop_n�16384�0
-LPCI_Trdy_n�16384�0
-Latc_stat_rd_n�16384�0
-Lint_ctrl_rd_n�16384�0
-Lio_int_stat_rd_n�16384�0
-Lmgmt_stat_rd_n�16384�0
-LoadCnt�1�0
-LoadCnt�64�0
-LoadVal�16384�0
-LogicFcn�1�0
-LoopCount�16384�0
-LoopStim�64�0
-Lrst_ctrl_rd_n�16384�0
-Lsio_dec_n�16384�0
-MgmtStatusReg�16384�0
-NumVectors�16384�0
-OR2�1�0
-OR2�64�0
-OrGate�16384�0
-OrGateDly�16384�0
-Pow�16�0
-Power�1�0
-Power�64�0
-PowerPkg�256�0
-PropDelay�16384�0
-Qout�16384�0
-Result�16384�0
-RollVal�16�0
-RstCtrlReg�16384�0
-SRFF�1�0
-S_Data�16384�0
-SimDFF�1�0
-SimDFF�64�0
-SimLoopDelay�16384�0
-SimModel�2048�0
-StimInputs�16384�0
-SuperIoRange�16384�0
-THREE�16384�0
-TRIBUF�1�0
-TRIBUF�64�0
-TRIBUF8�1�0
-TempVector�16384�0
-TestClk�16384�0
-Turn_Ar�16384�0
-VectorLine�16384�0
-VectorValid�16384�0
-a_and_b�16384�0
-accumL�16384�0
-accumulate�64�0
-accumulator�1�0
-adder�1�0
-andSignal�16384�0
-andTerm�16384�0
-asyncLdCnt�1�0
-asyncLoad�1�0
-atc_stat_rd_n�4096�0
-bad_charcode�16384�0
-basic�2048�0
-bcd2sevSeg�64�0
-behav�2048�0
-behave�2048�0
-behavior�2048�0
-behavioral�2048�0
-behaviour�2048�0
-bidirBuf�64�0
-bidirbuffer�1�0
-bitpos�16384�0
-body�256�0
-c�16384�0
-c_and_d�16384�0
-carry�16384�0
-char2char_t�4096�0
-charcode�16384�0
-charpos�16384�0
-clkGen�1�0
-clkTable�16384�0
-clkTableType�4096�0
-cnt�16384�0
-cntL�16384�0
-compare�1�0
-compare�64�0
-compareDC�1�0
-concat�2048�0
-concurrent�2048�0
-convertArith�1�0
-count8�1�0
-countL�16384�0
-counter�1�0
-counter�64�0
-curStProc�64�0
-currStProc�64�0
-currState�16384�0
-d�16384�0
-dataflow�2048�0
-decProcs�256�0
-decoder�1�0
-decoder�64�0
-decrement�64�0
-delayCnt�16384�0
-delayCntVal�16384�0
-delayReg�64�0
-delayreg�64�0
-demo�64�0
-dff�16�0
-dffTri�1�0
-digit�16384�0
-digit2int_t�4096�0
-done�16384�0
-downCnt�16384�0
-downCntData�16384�0
-downCntEn�16384�0
-downCntL�16384�0
-downCntLd�16384�0
-downCntr�64�0
-downCounter�1�0
-enable�64�0
-encode�64�0
-encoder�1�0
-endPulse�16384�0
-equalProc�64�0
-f_logic_to_character�16384�0
-f_logic_to_character_t�4096�0
-fcn�64�0
-flipFlop�1�0
-fsm�2048�0
-fsmType�4096�0
-funky�2048�0
-genXor�16384�0
-goodlength�16384�0
-hex_bits_per_digit�16384�0
-hex_logic_vector�16384�0
-hex_logic_vector_t�4096�0
-hexdigit2int�16384�0
-hexint2logic�16384�0
-hexint2logic_t�4096�0
-hierarchical�2048�0
-i�16384�0
-increment�64�0
-index�16384�0
-inputValInt�16384�0
-instance�2048�0
-int2hexdigit�16384�0
-int2hexdigit_t�4096�0
-int2octdigit�16384�0
-int2octdigit_t�4096�0
-int_ctrl_rd_n�4096�0
-integer_value�16384�0
-io1164�256�0
-io_int_stat_rd_n�4096�0
-isa_dec�1�0
-isx�16384�0
-la_n�16384�0
-lastAssignment�1�0
-lb_n�16384�0
-lc_n�16384�0
-ld_n�16384�0
-le_n�16384�0
-lengthReg�64�0
-lf_n�16384�0
-lg_n�16384�0
-loadCnt�1�0
-loadCnt�64�0
-loadCntTB�1�0
-loadDelayCnt�16384�0
-loadLengthCnt�16384�0
-loadVal�16384�0
-localRst�16384�0
-localSum�16384�0
-localY�16384�0
-logic_value�16384�0
-lookupTable�64�0
-loopDemo�2048�0
-loopXor�16384�0
-lowcase�16384�0
-m�16384�0
-maxhex_charcode�16384�0
-maxoct_charcode�16384�0
-mgmt_stat_rd_n�4096�0
-multiDriver�2048�0
-multiplier�1�0
-mux�1�0
-nextStProc�64�0
-nextState�16384�0
-notA�16384�0
-notB�16384�0
-not_c_and_d�16384�0
-numClks�4096�0
-numPatterns�4096�0
-nxtStProc�64�0
-oct_bits_per_digit�16384�0
-oct_logic_vector�16384�0
-oct_logic_vector_t�4096�0
-octdigit2int�16384�0
-octint2logic�16384�0
-octint2logic_t�4096�0
-oddParityGen�1�0
-oddParityLoop�1�0
-oe�16384�0
-old_l�16384�0
-one�16384�0
-outConProc�64�0
-outputs�64�0
-pAdderAttr�1�0
-paramDFF�1�0
-parameterize�2048�0
-pci_target�1�0
-pos�16384�0
-powerL�16384�0
-powerOfFour�1�0
-primitive�256�0
-priority_encoder�1�0
-progPulse�1�0
-progPulseFsm�1�0
-progPulseFsmType�4096�0
-pulse�64�0
-pulseCnt�16384�0
-pulseCntVal�16384�0
-pulseDelay�64�0
-pulseErr�1�0
-pulseLength�64�0
-pulseOutput�64�0
-q�16384�0
-qLocal�16384�0
-qualify�64�0
-read�16�0
-readVec�64�0
-read_hex�16�0
-read_oct�16�0
-reg�64�0
-reg�4096�0
-reg�16384�0
-regArray�4096�0
-regFile�1�0
-regProc�64�0
-registerFile�16384�0
-resFcnDemo�1�0
-resetLatch�64�0
-result�16384�0
-rst_ctrl_rd_n�4096�0
-rtl�2048�0
-scalable�2048�0
-scaleDFF�1�0
-scaleUpCnt�1�0
-scaleUpCnt�64�0
-scaleable�256�0
-scaleable�2048�0
-selectIn�16384�0
-sequential�2048�0
-sevenSegment�1�0
-sevenSegment�64�0
-sevenSegmentTB�1�0
-shift�64�0
-shifter�1�0
-signalDemo�1�0
-simHierarchy�1�0
-simModel�2048�0
-simPrimitives�256�0
-simple�2048�0
-sio_dec_n�4096�0
-stage0�16384�0
-stage1�16384�0
-stage2�16384�0
-stage3�16384�0
-stage4�16384�0
-startPulse�16384�0
-stateBits�4096�0
-stateTable�16384�0
-stateVec�4096�0
-struct_dffe�1�0
-struct_dffe_sr�1�0
-struct_dlatch�1�0
-structural�2048�0
-success�16384�0
-sum�64�0
-synthesis�2048�0
-tCQ�16384�0
-tH�16384�0
-tPD_A�16384�0
-tPD_B�16384�0
-tPD_Sel�16384�0
-tS�16384�0
-targetFsmType�4096�0
-tempSum�16384�0
-termCnt�16384�0
-test�1�0
-testVector�16384�0
-testbench�2048�0
-tri�16384�0
-tribufArrayType�4096�0
-tribufType�4096�0
-tribuffer�1�0
-typeConvert�1�0
-unnamed�64�0
-upper�4096�0
-vData�16384�0
-vLoad�16384�0
-vQ�16384�0
-vRst�16384�0
-vector�4096�0
-vectorArray�4096�0
-vectorTable�16384�0
-vectorType�4096�0
-verify�64�0
-waitDelayEnd�16384�0
-waitLengthEnd�16384�0
-wontWork�2048�0
-write�16�0
-write_hex�16�0
-write_oct�16�0
-x_charcode�16384�0


Modified: tests/ctags/vhdl-component.vhd
54 lines changed, 54 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,54 @@
+-- Taken from a comment https://github.com/universal-ctags/ctags/issues/2678
+-- submitted by @pidgeon777
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity ENTITY_TOP is
+  generic (
+    GEN : integer := 0
+  );
+  port (
+    INP : in std_logic
+  );
+end entity;
+
+architecture arch of ENTITY_TOP is
+  signal sig : std_logic := '0';
+
+  component ENTITY_1
+    generic (
+      GEN : integer := 0
+    );
+    port (
+      INP : in std_logic
+    );
+  end component;
+
+  component ENTITY_2
+    generic (
+      GEN : integer := 0
+    );
+    port (
+      INP : in std_logic
+    );
+  end component;
+
+begin
+
+  ENTITY_1_i : ENTITY_1
+  generic map(
+    GEN => 0
+  )
+  port map(
+    INP => '0'
+  );
+
+  ENTITY_2_i : ENTITY_2
+  generic map(
+    GEN => 0
+  )
+  port map(
+    INP => '0'
+  );
+
+end architecture;


Modified: tests/ctags/vhdl-component.vhd.tags
9 lines changed, 9 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,9 @@
+# format=tagmanager
+ENTITY_1�64�ENTITY_TOP.arch�0
+ENTITY_2�64�ENTITY_TOP.arch�0
+ENTITY_TOP�1�0
+INP�16384�ENTITY_TOP�0
+INP�16384�ENTITY_TOP.arch.ENTITY_1�0
+INP�16384�ENTITY_TOP.arch.ENTITY_2�0
+arch�2048�ENTITY_TOP�0
+sig�16384�ENTITY_TOP.arch�0


Modified: tests/ctags/vhdl-local.vhd
207 lines changed, 207 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,207 @@
+--
+-- Taken from rtl/commonlib/types_util.vhd of https://github.com/sergeykhbr/riscv_vhdl
+--
+-----------------------------------------------------------------------------
+--! @file
+--! @copyright Copyright 2015 GNSS Sensor Ltd. All right reserved.
+--! @author    Sergey Khabarov - sergeykhbr at gmail.com
+--! @brief	    Package for common testbenches implementation.
+------------------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+library std;
+use std.textio.all;
+
+package types_util is
+
+function strlen(s: in string) return integer;
+function StringToUVector(inStr: string) return std_ulogic_vector;
+function StringToSVector(inStr: string) return std_logic_vector;
+function UnsignedToSigned(inUnsigned: std_ulogic_vector) return std_logic_vector;
+function SignalFromString(inStr: string; ind : integer ) return std_logic;
+function SymbolToSVector(inStr: string; idx: integer) return std_logic_vector;
+
+function tost(v:std_logic_vector) return string;
+function tost(v:std_logic) return string;
+function tost(i : integer) return string;
+procedure print(s : string);
+
+end;
+
+package body types_util is
+
+  function strlen(s: in string) return integer is
+    variable n: integer:=0; variable sj: integer:=s'left;
+  begin
+    loop
+      if    sj>s'right then exit;
+      elsif s(sj)=NUL  then exit; --sequential if protects sj > length
+      else                  sj:=sj+1; n:=n+1;
+      end if;
+    end loop;
+    return n;
+  end strlen;
+
+  function SignalFromString(inStr: string; ind : integer ) return std_logic is
+    variable temp: std_logic := 'X';
+  begin
+    if(inStr(inStr'high-ind)='1')    then temp := '1';
+    elsif(inStr(inStr'high-ind)='0') then temp := '0';
+    end if;
+    return temp;
+  end function SignalFromString;
+
+
+  function StringToUVector(inStr: string) return std_ulogic_vector is
+    variable temp: std_ulogic_vector(inStr'range) := (others => 'X');
+  begin
+    for i in inStr'range loop --
+      if(inStr(inStr'high-i+1)='1')    then temp(i) := '1';
+      elsif(inStr(inStr'high-i+1)='0') then temp(i) := '0';
+      end if;
+    end loop;
+    return temp(inStr'high downto 1);
+  end function StringToUVector;
+  -- conversion function
+  
+  function StringToSVector(inStr: string) return std_logic_vector is
+    variable temp: std_logic_vector(inStr'range) := (others => 'X');
+  begin
+    for i in inStr'range loop --
+      if(inStr(inStr'high-i+1)='1')    then temp(i) := '1';
+      elsif(inStr(inStr'high-i+1)='0') then temp(i) := '0';
+      end if;
+    end loop;
+    return temp(inStr'high downto 1);
+  end function StringToSVector;
+
+  function SymbolToSVector(inStr: string; idx: integer) return std_logic_vector is
+    constant ss: string(1 to inStr'length) := inStr;
+    variable c : integer;
+    variable temp: std_logic_vector(7 downto 0) := (others => 'X');
+  begin
+    c := character'pos(ss(idx+1));
+    for i in 0 to 7 loop --
+      temp(i) := to_unsigned(c,8)(i);
+    end loop;
+    return temp;
+  end function SymbolToSVector;
+  
+
+  function UnsignedToSigned(inUnsigned: std_ulogic_vector) 
+    return std_logic_vector is
+    variable temp: std_logic_vector(inUnsigned'length-1 downto 0) := (others => 'X');
+    variable i: integer:=0;
+  begin
+    while i < inUnsigned'length loop
+      if(inUnsigned(i)='1')    then temp(i) := '1';
+      elsif(inUnsigned(i)='0') then temp(i) := '0';
+      end if;
+      i := i+1;
+    end loop;
+    return temp;
+  end function UnsignedToSigned;
+
+
+  subtype nibble is std_logic_vector(3 downto 0);
+
+  function todec(i:integer) return character is
+  begin
+    case i is
+    when 0 => return('0');
+    when 1 => return('1');
+    when 2 => return('2');
+    when 3 => return('3');
+    when 4 => return('4');
+    when 5 => return('5');
+    when 6 => return('6');
+    when 7 => return('7');
+    when 8 => return('8');
+    when 9 => return('9');
+    when others => return('0');
+    end case;
+  end;
+
+
+  function tohex(n:nibble) return character is
+  begin
+    case n is
+    when "0000" => return('0');
+    when "0001" => return('1');
+    when "0010" => return('2');
+    when "0011" => return('3');
+    when "0100" => return('4');
+    when "0101" => return('5');
+    when "0110" => return('6');
+    when "0111" => return('7');
+    when "1000" => return('8');
+    when "1001" => return('9');
+    when "1010" => return('a');
+    when "1011" => return('b');
+    when "1100" => return('c');
+    when "1101" => return('d');
+    when "1110" => return('e');
+    when "1111" => return('f');
+    when others => return('X');
+    end case;
+  end;
+
+
+  function tost(v:std_logic_vector) return string is
+    constant vlen : natural := v'length; --'
+    constant slen : natural := (vlen+3)/4;
+    variable vv : std_logic_vector(0 to slen*4-1) := (others => '0');
+    variable s : string(1 to slen);
+    variable nz : boolean := false;
+    variable index : integer := -1;
+    variable vector : bit_vector(0 TO 7);
+    alias reverse_vector : bit_vector
+       ( vector'length DOWNTO 1 )
+         IS vector ;
+  begin
+    vv(slen*4-vlen to slen*4-1) := v;
+    for i in 0 to slen-1 loop
+      if (vv(i*4 to i*4+3) = "0000") and nz and (i /= (slen-1)) then
+        index := i;
+      else
+        nz := false;
+        s(i+1) := tohex(vv(i*4 to i*4+3));
+      end if;
+    end loop;
+    if ((index +2) = slen) then return(s(slen to slen));
+    else return(string'("0x") & s(index+2 to slen)); end if; --'
+  end;
+
+
+  function tost(v:std_logic) return string is
+  begin
+    if to_x01(v) = '1' then return("1"); else return("0"); end if;
+  end;
+
+
+  function tost(i : integer) return string is
+    variable L : line;
+    variable s, x : string(1 to 128);
+    variable n, tmp : integer := 0;
+  begin
+    tmp := i;
+    if i < 0 then tmp := -i; end if;
+    loop
+      s(128-n) := todec(tmp mod 10);
+      tmp := tmp / 10;
+      n := n+1;
+      if tmp = 0 then exit; end if;
+    end loop;
+    x(1 to n) := s(129-n to 128);
+    if i < 0 then return "-" & x(1 to n); end if;
+    return(x(1 to n));
+  end;
+
+  procedure print(s : string) is
+    variable L : line;
+  begin
+    L := new string'(s); writeline(output, L);
+  end;
+
+end;


Modified: tests/ctags/vhdl-local.vhd.tags
36 lines changed, 36 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,36 @@
+# format=tagmanager
+L�16384�types_util.print�0
+L�16384�types_util.tost�0
+SignalFromString�16�types_util�0
+StringToSVector�16�types_util�0
+StringToUVector�16�types_util�0
+SymbolToSVector�16�types_util�0
+UnsignedToSigned�16�types_util�0
+c�16384�types_util.SymbolToSVector�0
+i�16384�types_util.UnsignedToSigned�0
+index�16384�types_util.tost�0
+n�16384�types_util.strlen�0
+n�16384�types_util.tost�0
+nibble�4096�types_util�0
+nz�16384�types_util.tost�0
+print�16�types_util�0
+reverse_vector�4096�types_util.tost�0
+s�16384�types_util.tost�0
+sj�16384�types_util.strlen�0
+slen�16384�types_util.tost�0
+ss�16384�types_util.SymbolToSVector�0
+strlen�16�types_util�0
+temp�16384�types_util.SignalFromString�0
+temp�16384�types_util.StringToSVector�0
+temp�16384�types_util.StringToUVector�0
+temp�16384�types_util.SymbolToSVector�0
+temp�16384�types_util.UnsignedToSigned�0
+tmp�16384�types_util.tost�0
+todec�16�types_util�0
+tohex�16�types_util�0
+tost�16�types_util�0
+types_util�256�0
+vector�16384�types_util.tost�0
+vlen�16384�types_util.tost�0
+vv�16384�types_util.tost�0
+x�16384�types_util.tost�0


Modified: tests/ctags/vhdl-port.vhd
5 lines changed, 5 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,5 @@
+-- https://www.ics.uci.edu/~jmoorkan/vhdlref/Synario%20VHDL%20Manual.pdf
+entity logical_ops_1 is
+  port (a, b, c, d: in bit;
+        m: out bit);
+end logical_ops_1;


Modified: tests/ctags/vhdl-port.vhd.tags
7 lines changed, 7 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,7 @@
+# format=tagmanager
+a�16384�logical_ops_1�0
+b�16384�logical_ops_1�0
+c�16384�logical_ops_1�0
+d�16384�logical_ops_1�0
+logical_ops_1�1�0
+m�16384�logical_ops_1�0


Modified: tests/ctags/vhdl-process.vhd
51 lines changed, 51 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,51 @@
+--
+-- Taken from rtl/riverlib/core/stacktrbuf.vhd of https://github.com/sergeykhbr/riscv_vhdl
+--
+-----------------------------------------------------------------------------
+--! @file
+--! @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
+--! @author    Sergey Khabarov - sergeykhbr at gmail.com
+--! @brief     Stack trace buffer on hardware level.
+------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+library commonlib;
+use commonlib.types_common.all;
+
+entity StackTraceBuffer is 
+  generic (
+    abits : integer := 5;
+    dbits : integer := 64
+  );
+  port (
+    i_clk   : in std_logic;
+    i_raddr : in std_logic_vector(abits-1 downto 0);
+    o_rdata : out std_logic_vector(dbits-1 downto 0);
+    i_we    : in std_logic;
+    i_waddr : in std_logic_vector(abits-1 downto 0);
+    i_wdata : in std_logic_vector(dbits-1 downto 0)
+  );
+end; 
+ 
+architecture arch_StackTraceBuffer of StackTraceBuffer is
+
+  type ram_type is array ((2**abits)-1 downto 0) of std_logic_vector (dbits-1 downto 0);
+  signal stackbuf    : ram_type;
+  signal raddr       : std_logic_vector(abits-1 downto 0);
+
+begin
+
+  -- registers:
+  regs : process(i_clk) begin 
+    if rising_edge(i_clk) then 
+      if i_we = '1' then
+        stackbuf(conv_integer(i_waddr)) <= i_wdata; 
+      end if;
+      raddr <= i_raddr;
+    end if;
+  end process;
+  
+  o_rdata <= stackbuf(conv_integer(raddr));
+
+end;


Modified: tests/ctags/vhdl-process.vhd.tags
13 lines changed, 13 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,13 @@
+# format=tagmanager
+StackTraceBuffer�1�0
+arch_StackTraceBuffer�2048�StackTraceBuffer�0
+i_clk�16384�StackTraceBuffer�0
+i_raddr�16384�StackTraceBuffer�0
+i_waddr�16384�StackTraceBuffer�0
+i_wdata�16384�StackTraceBuffer�0
+i_we�16384�StackTraceBuffer�0
+o_rdata�16384�StackTraceBuffer�0
+raddr�16384�StackTraceBuffer.arch_StackTraceBuffer�0
+ram_type�4096�StackTraceBuffer.arch_StackTraceBuffer�0
+regs�64�StackTraceBuffer.arch_StackTraceBuffer�0
+stackbuf�16384�StackTraceBuffer.arch_StackTraceBuffer�0


Modified: tests/ctags/vhdl-type.vhd
325 lines changed, 325 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,325 @@
+--
+-- Taken from rtl/misclib/types_misc.vhd of https://github.com/sergeykhbr/riscv_vhdl
+--
+--!
+--! Copyright 2018 Sergey Khabarov, sergeykhbr at gmail.com
+--!
+--! Licensed under the Apache License, Version 2.0 (the "License");
+--! you may not use this file except in compliance with the License.
+--! You may obtain a copy of the License at
+--!
+--!     http://www.apache.org/licenses/LICENSE-2.0
+--! Unless required by applicable law or agreed to in writing, software
+--! distributed under the License is distributed on an "AS IS" BASIS,
+--! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+--! See the License for the specific language governing permissions and
+--! limitations under the License.
+--!
+
+--! Standard library.
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+library commonlib;
+use commonlib.types_common.all;
+--! Technology definition library.
+library techmap;
+use techmap.gencomp.all;
+--! CPU, System Bus and common peripheries library.
+library ambalib;
+use ambalib.types_amba4.all;
+use ambalib.types_bus0.all;
+
+--! @brief   Declaration of components visible on SoC top level.
+package types_misc is
+
+--! @defgroup irq_id_group AXI4 interrupt generic IDs.
+--! @ingroup axi4_config_generic_group
+--! @details Unique indentificator of the interrupt pin also used
+--!          as an index in the interrupts bus.
+--! @{
+
+--! Zero interrupt index must be unused.
+constant CFG_IRQ_UNUSED         : integer := 0;
+--! UART_A interrupt pin.
+constant CFG_IRQ_UART1          : integer := 1;
+--! Ethernet MAC interrupt pin.
+constant CFG_IRQ_ETHMAC         : integer := 2;
+--! GP Timers interrupt pin
+constant CFG_IRQ_GPTIMERS       : integer := 3;
+--! GNSS Engine IRQ pin that generates 1 msec pulses.
+constant CFG_IRQ_GNSSENGINE     : integer := 4;
+--! Total number of used interrupts in a system
+constant CFG_IRQ_TOTAL          : integer := 5;
+--! @}
+
+--! @brief SOC global reset former.
+--! @details This module produces output reset signal in a case if
+--!          button 'Reset' was pushed or PLL isn't a 'lock' state.
+--! param[in]  inSysReset Button generated signal
+--! param[in]  inSysClk Clock from the PLL. Bus clock.
+--! param[out] outReset Output reset signal with active 'High' (1 = reset).
+component reset_global
+port (
+  inSysReset  : in std_ulogic;
+  inSysClk    : in std_ulogic;
+  outReset    : out std_ulogic );
+end component;
+
+
+--! Boot ROM with AXI4 interface declaration.
+component axi4_rom is
+generic (
+    memtech  : integer := inferred;
+    async_reset : boolean := false;
+    xaddr    : integer := 0;
+    xmask    : integer := 16#fffff#;
+    sim_hexfile : string
+  );
+port (
+    clk  : in std_logic;
+    nrst : in std_logic;
+    cfg  : out axi4_slave_config_type;
+    i    : in  axi4_slave_in_type;
+    o    : out axi4_slave_out_type
+  );
+end component; 
+
+--! Internal RAM with AXI4 interface declaration.
+component axi4_sram is
+  generic (
+    memtech  : integer := inferred;
+    async_reset : boolean := false;
+    xaddr    : integer := 0;
+    xmask    : integer := 16#fffff#;
+    abits    : integer := 17;
+    init_file : string := "" -- only for 'inferred'
+  );
+  port (
+    clk  : in std_logic;
+    nrst : in std_logic;
+    cfg  : out axi4_slave_config_type;
+    i    : in  axi4_slave_in_type;
+    o    : out axi4_slave_out_type
+  );
+end component; 
+
+--! AXI4 to SPI brdige for external Flash IC Micron M25AA1024
+type spi_in_type is record
+    SDI : std_logic;
+end record;
+
+type spi_out_type is record
+    SDO : std_logic;
+    SCK : std_logic;
+    nCS : std_logic;
+    nWP : std_logic;
+    nHOLD : std_logic;
+    RESET : std_logic;
+end record;
+
+constant spi_out_none : spi_out_type := (
+  '0', '0', '1', '1', '1', '0'
+);
+
+component axi4_flashspi is
+  generic (
+    async_reset : boolean := false;
+    xaddr   : integer := 0;
+    xmask   : integer := 16#fffff#;
+    wait_while_write : boolean := true  -- hold AXI bus response until end of write cycle
+  );
+  port (
+    clk    : in  std_logic;
+    nrst   : in  std_logic;
+    cfg    : out axi4_slave_config_type;
+    i_spi  : in  spi_in_type;
+    o_spi  : out spi_out_type;
+    i_axi  : in  axi4_slave_in_type;
+    o_axi  : out axi4_slave_out_type  );
+end component; 
+
+--! @brief AXI4 GPIO controller
+component axi4_gpio is
+  generic (
+    async_reset : boolean := false;
+    xaddr    : integer := 0;
+    xmask    : integer := 16#fffff#;
+    xirq     : integer := 0;
+    width    : integer := 12
+  );
+  port (
+    clk  : in std_logic;
+    nrst : in std_logic;
+    cfg  : out axi4_slave_config_type;
+    i    : in  axi4_slave_in_type;
+    o    : out axi4_slave_out_type;
+    i_gpio : in std_logic_vector(width-1 downto 0);
+    o_gpio : out std_logic_vector(width-1 downto 0);
+    o_gpio_dir : out std_logic_vector(width-1 downto 0)
+  );
+end component; 
+
+type uart_in_type is record
+  rd   	: std_ulogic;
+  cts   : std_ulogic;
+end record;
+
+type uart_out_type is record
+  td   	: std_ulogic;
+  rts   : std_ulogic;
+end record;
+
+--! UART with the AXI4 interface declaration.
+component axi4_uart is
+  generic (
+    async_reset : boolean := false;
+    xaddr   : integer := 0;
+    xmask   : integer := 16#fffff#;
+    xirq    : integer := 0;
+    fifosz  : integer := 16
+  );
+  port (
+    clk    : in  std_logic;
+    nrst   : in  std_logic;
+    cfg    : out axi4_slave_config_type;
+    i_uart : in  uart_in_type;
+    o_uart : out uart_out_type;
+    i_axi  : in  axi4_slave_in_type;
+    o_axi  : out axi4_slave_out_type;
+    o_irq  : out std_logic);
+end component;
+
+--! Test Access Point via UART (debug access)
+component uart_tap is
+  port (
+    nrst     : in std_logic;
+    clk      : in std_logic;
+    i_uart   : in  uart_in_type;
+    o_uart   : out uart_out_type;
+    i_msti   : in axi4_master_in_type;
+    o_msto   : out axi4_master_out_type;
+    o_mstcfg : out axi4_master_config_type
+  );
+end component; 
+
+-- JTAG TAP
+component tap_jtag is
+  generic (
+    ainst  : integer range 0 to 255 := 2;
+    dinst  : integer range 0 to 255 := 3);
+  port (
+    nrst  : in std_logic;
+    clk  : in std_logic;
+    i_tck   : in std_logic;   -- in: Test Clock
+    i_ntrst   : in std_logic;   -- in: 
+    i_tms   : in std_logic;   -- in: Test Mode State
+    i_tdi   : in std_logic;   -- in: Test Data Input
+    o_tdo   : out std_logic;   -- out: Test Data Output
+    o_jtag_vref : out std_logic;
+    i_msti   : in axi4_master_in_type;
+    o_msto   : out axi4_master_out_type;
+    o_mstcfg : out axi4_master_config_type
+    );
+end component;
+
+
+--! @brief   Interrupt controller with the AXI4 interface declaration.
+--! @details To rise interrupt on certain CPU HostIO interface is used.
+component axi4_irqctrl is
+  generic (
+    async_reset : boolean := false;
+    xaddr    : integer := 0;
+    xmask    : integer := 16#fffff#
+  );
+  port 
+ (
+    clk    : in std_logic;
+    nrst   : in std_logic;
+    i_irqs : in std_logic_vector(CFG_IRQ_TOTAL-1 downto 1);
+    o_cfg  : out axi4_slave_config_type;
+    i_axi  : in axi4_slave_in_type;
+    o_axi  : out axi4_slave_out_type;
+    o_irq_meip : out std_logic
+  );
+  end component;
+
+  --! @brief   General Purpose Timers with the AXI interface.
+  --! @details This module provides high precision counter and
+  --!          generic number of GP timers.
+  component axi4_gptimers is
+  generic (
+    async_reset : boolean := false;
+    xaddr   : integer := 0;
+    xmask   : integer := 16#fffff#;
+    xirq    : integer := 0;
+    tmr_total  : integer := 2
+  );
+  port (
+    clk    : in  std_logic;
+    nrst   : in  std_logic;
+    cfg    : out axi4_slave_config_type;
+    i_axi  : in  axi4_slave_in_type;
+    o_axi  : out axi4_slave_out_type;
+    o_pwm : out std_logic_vector(tmr_total-1 downto 0);
+    o_irq  : out std_logic
+  );
+  end component; 
+
+--! @brief   Plug-n-Play support module with AXI4 interface declaration.
+--! @details Each device in a system hase to implements sideband signal
+--!          structure 'nasti_slave_config_type' that allows FW to
+--!          detect Hardware configuration in a run-time.
+--! @todo Implements PnP signals for all Masters devices.
+component axi4_pnp is
+  generic (
+    async_reset : boolean := false;
+    xaddr   : integer := 0;
+    xmask   : integer := 16#fffff#;
+    tech    : integer := 0;
+    hw_id   : std_logic_vector(31 downto 0) := X"20170101"
+  );
+  port (
+    sys_clk : in  std_logic;
+    adc_clk : in  std_logic;
+    nrst   : in  std_logic;
+    mstcfg : in  bus0_xmst_cfg_vector;
+    slvcfg : in  bus0_xslv_cfg_vector;
+    cfg    : out  axi4_slave_config_type;
+    i      : in  axi4_slave_in_type;
+    o      : out axi4_slave_out_type;
+    -- OTP Timing control
+    i_otp_busy : in std_logic;
+    o_otp_cfg_rsetup : out std_logic_vector(3 downto 0);
+    o_otp_cfg_wadrsetup : out std_logic_vector(3 downto 0);
+    o_otp_cfg_wactive : out std_logic_vector(31 downto 0);
+    o_otp_cfg_whold : out std_logic_vector(3 downto 0)
+  );
+end component; 
+
+component axi4_otp is
+  generic (
+    async_reset : boolean := false;
+    xaddr   : integer := 0;
+    xmask   : integer := 16#ffffe#
+  );
+  port (
+    clk    : in  std_logic;
+    nrst   : in  std_logic;
+    cfg    : out axi4_slave_config_type;
+    i_axi  : in  axi4_slave_in_type;
+    o_axi  : out axi4_slave_out_type;
+    o_otp_we     : out  std_ulogic;
+    o_otp_re     : out  std_ulogic;
+    o_otp_addr   : out std_logic_vector(11 downto 0);
+    o_otp_wdata  : out std_logic_vector(15 downto 0);
+    i_otp_rdata  : in std_logic_vector(15 downto 0);
+    i_cfg_rsetup : in std_logic_vector(3 downto 0);
+    i_cfg_wadrsetup : in std_logic_vector(3 downto 0);
+    i_cfg_wactive : in std_logic_vector(31 downto 0);
+    i_cfg_whold : in std_logic_vector(3 downto 0);
+    o_busy : out std_logic
+  );
+end component; 
+
+end; -- package declaration


Modified: tests/ctags/vhdl-type.vhd.tags
121 lines changed, 121 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,121 @@
+# format=tagmanager
+CFG_IRQ_ETHMAC�16384�types_misc�0
+CFG_IRQ_GNSSENGINE�16384�types_misc�0
+CFG_IRQ_GPTIMERS�16384�types_misc�0
+CFG_IRQ_TOTAL�16384�types_misc�0
+CFG_IRQ_UART1�16384�types_misc�0
+CFG_IRQ_UNUSED�16384�types_misc�0
+adc_clk�16384�types_misc.axi4_pnp�0
+axi4_flashspi�64�types_misc�0
+axi4_gpio�64�types_misc�0
+axi4_gptimers�64�types_misc�0
+axi4_irqctrl�64�types_misc�0
+axi4_otp�64�types_misc�0
+axi4_pnp�64�types_misc�0
+axi4_rom�64�types_misc�0
+axi4_sram�64�types_misc�0
+axi4_uart�64�types_misc�0
+cfg�16384�types_misc.axi4_flashspi�0
+cfg�16384�types_misc.axi4_gpio�0
+cfg�16384�types_misc.axi4_gptimers�0
+cfg�16384�types_misc.axi4_otp�0
+cfg�16384�types_misc.axi4_pnp�0
+cfg�16384�types_misc.axi4_rom�0
+cfg�16384�types_misc.axi4_sram�0
+cfg�16384�types_misc.axi4_uart�0
+clk�16384�types_misc.axi4_flashspi�0
+clk�16384�types_misc.axi4_gpio�0
+clk�16384�types_misc.axi4_gptimers�0
+clk�16384�types_misc.axi4_irqctrl�0
+clk�16384�types_misc.axi4_otp�0
+clk�16384�types_misc.axi4_rom�0
+clk�16384�types_misc.axi4_sram�0
+clk�16384�types_misc.axi4_uart�0
+clk�16384�types_misc.tap_jtag�0
+clk�16384�types_misc.uart_tap�0
+i�16384�types_misc.axi4_gpio�0
+i�16384�types_misc.axi4_pnp�0
+i�16384�types_misc.axi4_rom�0
+i�16384�types_misc.axi4_sram�0
+i_axi�16384�types_misc.axi4_flashspi�0
+i_axi�16384�types_misc.axi4_gptimers�0
+i_axi�16384�types_misc.axi4_irqctrl�0
+i_axi�16384�types_misc.axi4_otp�0
+i_axi�16384�types_misc.axi4_uart�0
+i_cfg_rsetup�16384�types_misc.axi4_otp�0
+i_cfg_wactive�16384�types_misc.axi4_otp�0
+i_cfg_wadrsetup�16384�types_misc.axi4_otp�0
+i_cfg_whold�16384�types_misc.axi4_otp�0
+i_gpio�16384�types_misc.axi4_gpio�0
+i_irqs�16384�types_misc.axi4_irqctrl�0
+i_msti�16384�types_misc.tap_jtag�0
+i_msti�16384�types_misc.uart_tap�0
+i_ntrst�16384�types_misc.tap_jtag�0
+i_otp_busy�16384�types_misc.axi4_pnp�0
+i_otp_rdata�16384�types_misc.axi4_otp�0
+i_spi�16384�types_misc.axi4_flashspi�0
+i_tck�16384�types_misc.tap_jtag�0
+i_tdi�16384�types_misc.tap_jtag�0
+i_tms�16384�types_misc.tap_jtag�0
+i_uart�16384�types_misc.axi4_uart�0
+i_uart�16384�types_misc.uart_tap�0
+inSysClk�16384�types_misc.reset_global�0
+inSysReset�16384�types_misc.reset_global�0
+mstcfg�16384�types_misc.axi4_pnp�0
+nrst�16384�types_misc.axi4_flashspi�0
+nrst�16384�types_misc.axi4_gpio�0
+nrst�16384�types_misc.axi4_gptimers�0
+nrst�16384�types_misc.axi4_irqctrl�0
+nrst�16384�types_misc.axi4_otp�0
+nrst�16384�types_misc.axi4_pnp�0
+nrst�16384�types_misc.axi4_rom�0
+nrst�16384�types_misc.axi4_sram�0
+nrst�16384�types_misc.axi4_uart�0
+nrst�16384�types_misc.tap_jtag�0
+nrst�16384�types_misc.uart_tap�0
+o�16384�types_misc.axi4_gpio�0
+o�16384�types_misc.axi4_pnp�0
+o�16384�types_misc.axi4_rom�0
+o�16384�types_misc.axi4_sram�0
+o_axi�16384�types_misc.axi4_flashspi�0
+o_axi�16384�types_misc.axi4_gptimers�0
+o_axi�16384�types_misc.axi4_irqctrl�0
+o_axi�16384�types_misc.axi4_otp�0
+o_axi�16384�types_misc.axi4_uart�0
+o_busy�16384�types_misc.axi4_otp�0
+o_cfg�16384�types_misc.axi4_irqctrl�0
+o_gpio�16384�types_misc.axi4_gpio�0
+o_gpio_dir�16384�types_misc.axi4_gpio�0
+o_irq�16384�types_misc.axi4_gptimers�0
+o_irq�16384�types_misc.axi4_uart�0
+o_irq_meip�16384�types_misc.axi4_irqctrl�0
+o_jtag_vref�16384�types_misc.tap_jtag�0
+o_mstcfg�16384�types_misc.tap_jtag�0
+o_mstcfg�16384�types_misc.uart_tap�0
+o_msto�16384�types_misc.tap_jtag�0
+o_msto�16384�types_misc.uart_tap�0
+o_otp_addr�16384�types_misc.axi4_otp�0
+o_otp_cfg_rsetup�16384�types_misc.axi4_pnp�0
+o_otp_cfg_wactive�16384�types_misc.axi4_pnp�0
+o_otp_cfg_wadrsetup�16384�types_misc.axi4_pnp�0
+o_otp_cfg_whold�16384�types_misc.axi4_pnp�0
+o_otp_re�16384�types_misc.axi4_otp�0
+o_otp_wdata�16384�types_misc.axi4_otp�0
+o_otp_we�16384�types_misc.axi4_otp�0
+o_pwm�16384�types_misc.axi4_gptimers�0
+o_spi�16384�types_misc.axi4_flashspi�0
+o_tdo�16384�types_misc.tap_jtag�0
+o_uart�16384�types_misc.axi4_uart�0
+o_uart�16384�types_misc.uart_tap�0
+outReset�16384�types_misc.reset_global�0
+reset_global�64�types_misc�0
+slvcfg�16384�types_misc.axi4_pnp�0
+spi_in_type�4096�types_misc�0
+spi_out_none�16384�types_misc�0
+spi_out_type�4096�types_misc�0
+sys_clk�16384�types_misc.axi4_pnp�0
+tap_jtag�64�types_misc�0
+types_misc�256�0
+uart_in_type�4096�types_misc�0
+uart_out_type�4096�types_misc�0
+uart_tap�64�types_misc�0


Modified: tests/meson.build
6 lines changed, 5 insertions(+), 1 deletions(-)
===================================================================
@@ -323,7 +323,6 @@ ctags_tests = files([
 	'ctags/test.erl.tags',
 	'ctags/test.go.tags',
 	'ctags/test.py.tags',
-	'ctags/test.vhd.tags',
 	'ctags/test_input.rs.tags',
 	'ctags/test_input2.rs.tags',
 	'ctags/titles.t2t.tags',
@@ -333,6 +332,11 @@ ctags_tests = files([
 	'ctags/union.f.tags',
 	'ctags/value.f.tags',
 	'ctags/var-and-return-type.cpp.tags',
+	'ctags/vhdl-component.vhd.tags',
+	'ctags/vhdl-local.vhd.tags',
+	'ctags/vhdl-port.vhd.tags',
+	'ctags/vhdl-process.vhd.tags',
+	'ctags/vhdl-type.vhd.tags',
 	'ctags/whitespaces.php.tags'
 ])
 



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list