Hi Shigio and other Global developers,

I have created Zig parsers for Gtags and Htags version 6.6.10.

I don't program in Zig, but have tested it on a number of Zig source files.
Zig is an Open Source language, so you can download its source files.

I did modify makeincludeindex() to include the @import() functions of Zig,
but
it didn't seem to make any difference, so I removed the code.
The @import functions (like '#include' in C) are made into HTML links with
the
htags parser, and they work.

Had to change compress() for names beginning with '@' in them.
I don't think you need to change the version number of the format of the
Global databases. I have left the '@' character in as part of the name,
like in
the built-in function '@ptrToInt' for example, as this is what the text
editor
Kate also does when syntax hilighting Zig code. Thus it gets saved into the
databases as '@ptrToInt'.
But the HTML index htags generates, doesn't include an entry for names
beginning with '@' yet, maybe one day.

Also changed HTML_quoting() in 'htags/src2html.c' to help spot and make safe
funny characters in source files, like the ones in
'libdb/sqlite3.c' (0xB1 and 0xC4); but this change is not really necessary.

I thought I had gone wrong with the Zig function pointers, like 'xxx: fn
()',
that are in 'struct' statements, as some of them don't get the guide/icons
with
them, but these function pointers are not function definitions.
I will fix this in the next update of the Zig parsers.

I think I can add code to parse Zig function calls, so this could be a
future
enhancement.

I have also fixed some minor text messages, code and doxygen code, hope they
are ok.

Hope these parsers are useful for Global.

(Feature request: a Language Server Protocol [LSP] interface).

I will be sending another email soon, more bugs, mainly involving strcmp().
And one bug found in __bt_first() 'libdb/bt_seq.c' by CppCheck:

'if ((h = xxx()) == NULL) { if (h->pgno == save.page->pgno) ....}'



Simon Dommett
--- global-6.6.10/original_configure.ac	2023-05-09 00:50:00 +0100
+++ global-7.7.10/configure.ac	2023-08-16 21:39:35 +0100
@@ -405,7 +405,7 @@ dnl DEFAULTSKIP: You need not list files
 dnl		Such files are skipped even in case of not being in the list.
 dnl
 DEFAULTSKIP='HTML/,HTML.pub/,tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,SCCS/,RCS/,CVS/,CVSROOT/,{arch}/,autom4te.cache/,*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,*.o,*.a,*.so,*.lo,*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,*.min.js,*min.css'
-DEFAULTLANGMAP='c:.c.h,yacc:.y,asm:.s.S,java:.java,cpp:.c++.cc.hh.cpp.cxx.hxx.hpp.C.H,php:.php.php3.phtml'
+DEFAULTLANGMAP='c:.c.h,yacc:.y,asm:.s.S,java:.java,cpp:.c++.cc.hh.cpp.cxx.hxx.hpp.C.H,php:.php.php3.phtml,zig:.zig'
 DEFAULTINCLUDEFILESUFFIXES='h,hh,hxx,hpp,H,inc.php'
 AC_SUBST(DEFAULTSKIP)
 AC_SUBST(DEFAULTLANGMAP)
--- global-6.6.10/original_convert.pl	2023-05-09 00:50:00 +0100
+++ global-7.7.10/convert.pl	2023-08-12 19:51:02 +0100
@@ -88,6 +88,7 @@ sub langmapstatement {
 		'cpp'	=> 'C++',
 		'php'	=> 'PHP',
 		'asm'	=> 'assembly language',
+		'zig'	=> 'Zig',
 	);
 	my $line = '';
 	my @maps = split(/,/, $maps);
--- global-6.6.10/global/original_global.c	2023-05-09 00:50:01 +0100
+++ global-7.7.10/global/global.c	2023-08-14 18:40:05 +0100
@@ -219,7 +219,7 @@ struct option const long_options[] = {
 	{"through", no_argument, NULL, 'T'},
 	{"update", no_argument, NULL, 'u'},
 	{"verbose", no_argument, NULL, 'v'},
-	{"invert-match", optional_argument, NULL, 'V'},
+	{"invert-match", no_argument, NULL, 'V'},
 	{"cxref", no_argument, NULL, 'x'},
 
 	/* long name only */
--- global-6.6.10/original_gtags.conf	2023-05-09 00:50:47 +0100
+++ global-7.7.10/gtags.conf	2023-08-12 19:28:23 +0100
@@ -70,7 +70,7 @@ gtags:\
 	:tc=common:\
 	:tc=builtin-parser:
 builtin-parser:\
-	:langmap=c\:.c.h,yacc\:.y,asm\:.s.S,java\:.java,cpp\:.c++.cc.hh.cpp.cxx.hxx.hpp.C.H,php\:.php.php3.phtml:
+	:langmap=c\:.c.h,yacc\:.y,asm\:.s.S,java\:.java,cpp\:.c++.cc.hh.cpp.cxx.hxx.hpp.C.H,php\:.php.php3.phtml,zig\:.zig:
 #
 # skeleton for user's custom parser.
 #
--- global-6.6.10/htags/original_htags.c	2023-05-09 00:50:01 +0100
+++ global-7.7.10/htags/htags.c	2023-08-12 20:11:19 +0100
@@ -1571,7 +1571,7 @@ main(int argc, char **argv)
 		tim = statistics_time_start("Time of making definition index");
 		func_total = makedefineindex("defines.html", func_total, defines);
 		statistics_time_end(tim);
-		message("Total %d functions.", func_total);
+		message("Total %d definitions.", func_total);
 		/*
 		 * (6) make file index (files.html and files/)
 		 *     PRODUCE @files, %includes
--- global-6.6.10/htags/original_lexcommon.h	2023-05-09 00:50:01 +0100
+++ global-7.7.10/htags/lexcommon.h	2023-08-28 21:54:06 +0100
@@ -53,6 +53,13 @@ to generate language specific symbols.
 static int lexcommon_lineno;
 static int begin_line;
 
+#ifdef LN_STRING	/* defined in 'htags/zig.l' only */
+static int in_line_string;	/* 1 (TRUE) if inside a 'line string', each line begins with: '\\' (2 backslashes) */
+static int line_str_on;		/* 1 (TRUE) if 'string_begin' has been used. */
+static int in_comment;		/* 1 (TRUE) if 'comment_begin' has been used. */
+static int line_str_comment;	/* 1 (TRUE) if inside a 'line string' comment ('//\\') */
+#endif
+
 /*
  * If you want newline to terminate string, set this variable to 1.
  */
@@ -80,6 +87,8 @@ static int left_spaces;
 	left_spaces = 0;						\
 }
 
+#ifndef LN_STRING	/* defined in 'htags/zig.l' only */
+
 #define DEFAULT_YY_USER_ACTION {					\
 	if (begin_line) {						\
 		put_begin_of_line(LINENO);				\
@@ -117,6 +126,60 @@ static int left_spaces;
 	begin_line = 1;							\
 }
 
+#else
+
+#define DEFAULT_YY_USER_ACTION {					\
+	if (begin_line) {						\
+		put_begin_of_line(LINENO);				\
+		switch (YY_START) {					\
+		case C_COMMENT:						\
+		case CPP_COMMENT:					\
+		case SHELL_COMMENT:					\
+			if ( !line_str_comment) {			\
+				echos(comment_begin);			\
+				in_comment = 1;				\
+			}						\
+			break;						\
+		}							\
+		begin_line = 0;						\
+	}								\
+}
+
+#define DEFAULT_END_OF_LINE_ACTION {					\
+	switch (YY_START) {						\
+	case CPP_COMMENT:						\
+	case SHELL_COMMENT:						\
+		yy_pop_state();						\
+		/* FALLTHROUGH */					\
+	case C_COMMENT:							\
+		echos(comment_end);					\
+		in_comment = 0;						\
+		break;							\
+	case STRING:							\
+	case LITERAL:							\
+		if (newline_terminate_string)				\
+			yy_pop_state();					\
+		break;							\
+	}								\
+	if (in_line_string && (line_str_on || in_comment)) {		\
+		if (in_comment) {					\
+			echos(comment_end);				\
+			in_comment = 0;					\
+		}							\
+		if (line_str_on) {					\
+			echos(string_end);				\
+			line_str_on = 0;				\
+		}							\
+	}								\
+	if (YY_START == PREPROCESSOR_LINE)				\
+		yy_pop_state();						\
+	put_end_of_line(LINENO);					\
+	/* for the next line */						\
+	LINENO++;							\
+	begin_line = 1;							\
+}
+#endif /* !LN_STRING */
+
 #define DEFAULT_BACKSLASH_NEWLINE_ACTION {				\
 	echoc('\\');							\
 	switch (YY_START) {						\
--- global-6.6.10/htags/original_Makefile.am	2023-05-09 00:50:01 +0100
+++ global-7.7.10/htags/Makefile.am	2023-08-12 19:58:51 +0100
@@ -14,7 +14,7 @@ bin_PROGRAMS= htags
 
 htags_SOURCES = htags.c defineindex.c dupindex.c fileindex.c cflowindex.c src2html.c \
 		anchor.c cache.c common.c incop.c path2url.c \
-		c.c cpp.c java.c php.c asm.c
+		c.c cpp.c java.c php.c asm.c zig.c
 
 SUBDIRS = icons jquery jquery/images
 
@@ -33,7 +33,7 @@ gtags_DATA = global.cgi completion.cgi d
 	jscode_suggest jscode_treeview style.css
 EXTRA_DIST = $(man_MANS) manual.in global.cgi.in completion.cgi.in dot_htaccess \
 		jscode_suggest jscode_treeview style.css \
-		const.h c.l cpp.l java.l php.l asm.l
+		const.h c.l cpp.l java.l php.l asm.l zig.l
 CLEANFILES = global.cgi completion.cgi
 # CGI scripts
 convert=sed -e 's!@PERLPATH@!$(PERL)!g' -e 's!@GLOBALPATH@!$(bindir)/global!g' -e 's!@GENERATOR@!$(PACKAGE_STRING)!g'
--- global-6.6.10/htags/original_manual.in	2023-05-09 00:50:01 +0100
+++ global-7.7.10/htags/manual.in	2023-08-14 18:33:56 +0100
@@ -144,6 +144,8 @@
 		Numbers are not given in list form.
 	@item{@option{-o}, @option{--other}}
 		Pick up not only source files but also other files for the file index.
+	@item{@option{-q}}
+		Quiet mode.
 	@item{@option{-s}, @option{--symbol}}
 		Make anchors not only for definitions and references
 		but also other symbols.
--- global-6.6.10/htags/original_src2html.c	2023-05-09 00:50:01 +0100
+++ global-7.7.10/htags/src2html.c	2023-08-28 21:59:11 +0100
@@ -64,6 +64,7 @@ void cpp_parser_init(FILE *);
 void java_parser_init(FILE *);
 void php_parser_init(FILE *);
 void asm_parser_init(FILE *);
+void zig_parser_init(FILE *);
 
 /*
  * executing procedures
@@ -73,6 +74,7 @@ int cpp_lex(void);
 int java_lex(void);
 int php_lex(void);
 int asm_lex(void);
+int zig_lex(void);
 
 /**
  * The first entry is default language.
@@ -84,7 +86,8 @@ struct lang_entry lang_switch[] = {
 	{"cpp",		cpp_parser_init,	cpp_lex},
 	{"java",	java_parser_init,	java_lex},
 	{"php",		php_parser_init,	php_lex},
-	{"asm",		asm_parser_init,	asm_lex}
+	{"asm",		asm_parser_init,	asm_lex},
+	{"zig",		zig_parser_init,	zig_lex}
 };
 #define DEFAULT_ENTRY &lang_switch[0]
 
@@ -170,12 +173,26 @@ echos(const char *s)
 static const char *
 HTML_quoting(int c)
 {
+	static char buf[32];
+	int n;
+
 	if (c == '<')
 		return quote_little;
 	else if (c == '>')
 		return quote_great;
 	else if (c == '&')
 		return quote_amp;
+	else if ( !isprint(c) && c != '\t' && c != '\n') {	/* Needs to be in here so detab_replacing() uses it */
+		if (c == 0) {
+			strcpy(buf, "&amp;#x00;");
+			return buf;
+		}
+		n = snprintf(buf, sizeof(buf), "&#x%02x;", (((unsigned char) c) & 0xff));
+		if (n < 0 || n >= sizeof(buf))
+			die("HTML_quoting: something is wrong. snprintf() returned: %d (c=0x%x)", n, c);
+		else
+			return buf;
+	}
 	return NULL;
 }
 /*
@@ -955,7 +972,7 @@ src2html(const char *src, const char *ht
 			fputs(header_begin, out);
 			fputs(title_define_index, out);
 			fputs_nl(header_end, out);
-			fputs_nl("This source file includes following definitions.", out);
+			fputs_nl("This source file includes the following definitions.", out);
 			fputs_nl(list_begin, out);
 			fputs(strbuf_value(define_index), out);
 			fputs_nl(list_end, out);
--- global-6.6.10/htags/original_common.h	2023-05-09 00:50:01 +0100
+++ global-7.7.10/htags/common.h	2023-08-18 22:53:47 +0100
@@ -127,6 +127,7 @@ void setup_xhtml(void);
 void save_current_path(const char *);
 char *get_current_dir(void);
 char *get_current_file(void);
+char *get_current_htags_path(void);
 const char *upperdir(const char *);
 const char *gen_insert_header(int);
 const char *gen_insert_footer(int);
--- global-6.6.10/htags/original_common.c	2023-05-09 00:50:01 +0100
+++ global-7.7.10/htags/common.c	2023-08-18 22:51:09 +0100
@@ -169,7 +169,7 @@ save_current_path(const char *path)
 
 	strlimcpy(current_path, path, sizeof(current_path));
 	/* Extract directory name and file name from path */
-	strlimcpy(current_dir, path, sizeof(current_path));
+	strlimcpy(current_dir, path, sizeof(current_dir));
 	startp = current_dir;
 	p = startp + strlen(current_dir);
 	while (p > startp) {
@@ -193,6 +193,12 @@ get_current_file(void)
 	return current_file;
 }
 
+char *
+get_current_htags_path(void)
+{
+	return current_path;
+}
+
 /**
  * Generate upper directory.
  *
--- global-6.6.10/htags/nul	1970-01-01 00:00:00 +0000
+++ global-7.7.10/htags/zig.l	2023-08-28 22:23:47 +0100
@@ -0,0 +1,404 @@
+%top{
+/*
+ * Contributed by Simon Dommett, 2023.
+ *
+ * Zig source code parser for htags.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif
+#include "global.h"
+#include "anchor.h"
+#include "incop.h"
+#include "common.h"
+#include "htags.h"
+#include "../libparser/zig_res.h"
+
+#define lex_symbol_generation_rule(x) zig_ ## x
+
+#undef DBG_PRINT
+
+#ifndef NDEBUG 		/* see: assert.h */
+extern int debug;	/* defined in htags.c */
+
+/* DBG_PRINT defined before #include "lexcommon.h" so we can use inside 'lexcommon.h' */
+#define DBG_PRINT if (debug) debug_print
+#else
+#define DBG_PRINT debug_print
+#endif /* NDEBUG */
+
+#define DBG_SHOW_FLAGS  debug_show_flags
+
+#define LN_STRING 99		/* so don't need to change c.l, php.l, etc */
+#include "lexcommon.h"
+#undef LN_STRING
+
+/*
+ * For debugging.
+ * (use '--debug' on htags)
+ */
+static void
+debug_print(const char *s, ...)
+{
+#ifndef NDEBUG
+        va_list ap;
+
+        va_start(ap, s);
+        (void) vfprintf(stderr, s, ap);
+        fflush(stderr);
+        va_end(ap);
+#endif
+}
+
+#ifdef ECHO
+#undef ECHO
+#endif
+#define ECHO	echos(LEXTEXT)
+
+#define YY_USER_ACTION DEFAULT_YY_USER_ACTION
+
+#ifndef LEXLINENO
+#define LEXLINENO LINENO
+#endif
+
+#define LEFT_BRACE '('
+
+/* static int line_str_debug; */
+
+static char *cur_fname;
+
+enum { INITIAL=0, ZIG, C_COMMENT, CPP_COMMENT, SHELL_COMMENT, STRING, LITERAL,
+	PREPROCESSOR_LINE, LN_STRING, LN_STRING_2, IMPORT, };
+
+/* For debugging */
+static char *
+state2name(int state)
+{
+#ifndef NDEBUG
+	char *s;
+	switch (state) {
+		case INITIAL:		s = "INITIAL"; break;
+		case ZIG: 		s = "ZIG"; break;
+		case C_COMMENT: 	s = "C_COMMENT"; break;
+		case CPP_COMMENT: 	s = "CPP_COMMENT"; break;
+		case SHELL_COMMENT: 	s = "SHELL_COMMENT"; break;
+		case STRING: 		s = "STRING"; break;
+		case LITERAL: 		s = "LITERAL"; break;
+		case PREPROCESSOR_LINE: s = "PREPROCESSOR_LINE"; break;
+		case LN_STRING: 	s = "LN_STRING"; break;
+		case LN_STRING_2:	s = "LN_STRING_2"; break;
+		case IMPORT: 		s = "IMPORT"; break;
+		default: 		s = "-UNKNOWN-"; break;
+	}
+	return s;
+#else
+	return NULL;
+#endif
+}
+
+static void
+debug_show_flags(const char *id, int in_comment, int line_str_on, int line_str_comment, int line_number)
+{
+#ifndef NDEBUG
+	if (debug) {
+		/* Output to HTML file: */
+		put_string("(#");
+		put_string(id);
+		put_char(':');
+		if (in_comment)		put_char('C'); else put_char('-');
+		if (line_str_on)	put_char('S'); else put_char('-');
+		if (line_str_comment)	put_char('L'); else put_char('-');
+		put_string("#)");
+		/* And to stderr: */
+		DBG_PRINT("<LSTR %s:%d:%c%c%c>\n", id, line_number, (in_comment ? 'C':'-'),
+				(line_str_on ? 'S':'-'), (line_str_comment ? 'L':'-'));
+	}
+#endif
+}
+
+ /* end of '%top' */
+}
+
+ /* Definitions */
+
+ /* hexadecimal integer */
+HX		[0-9A-Fa-f]
+HXU		"_"?{HX}
+HEX_INT		{HX}{HXU}*
+HEX		0x{HEX_INT}
+ /* octal integer */
+OC		[0-7]
+OCU		"_"?{OC}
+OCT		0o{OC}{OCU}*
+ /* binary integer */
+BN		[01]
+BNU		"_"?{BN}
+BIN		0b{BN}{BNU}*
+ /* decimal integer */
+DC		[0-9]
+DCU		"_"?{DC}
+DEC		{DC}{DCU}*
+ /* N		{DC}+ */
+
+ /* float */
+FH1		"0x"{HEX_INT}\.{HEX_INT}([pP][-+]?{DEC})?
+FH2		"0x"{HEX_INT}([pP][-+]?{DEC})?
+F1		{DEC}\.{DEC}([eE][-+]?{DEC})?
+F2		{DEC}[eE][-+]?{DEC}
+
+NUMBER		[-+]?({DEC}|{HEX}|{OCT}|{BIN}|{F1}|{F2}|{FH1}|{FH2})
+ALPHA		[a-zA-Z_]
+ALPHANUM	[a-zA-Z0-9_]
+WORD		@?{ALPHA}{ALPHANUM}*
+
+%s ZIG C_COMMENT CPP_COMMENT SHELL_COMMENT STRING LITERAL PREPROCESSOR_LINE LN_STRING LN_STRING_2 IMPORT
+%option 8bit noyywrap noyy_top_state stack never-interactive prefix="zig_"
+%%
+
+<<EOF>>	{ DEFAULT_END_OF_LINE_ACTION; yyterminate(); }
+
+ /* Comment (only one line ones in Zig) */
+<INITIAL>"//"	{ DBG_PRINT("<COMMENT/%d>\n", LEXLINENO);
+			echos(comment_begin); ECHO; yy_push_state(CPP_COMMENT); }
+
+ /* Line string */
+<INITIAL>"\\\\"		{ DBG_PRINT("<LSTR id-20/%d/string_begin>\n", LEXLINENO);
+				echos(string_begin); ECHO; yy_push_state(LN_STRING);
+				in_line_string = 1; line_str_on = 1;
+			}
+<LN_STRING>(\r\n|\n|\r)[ \t]*("\\\\"|[;,)}:]|"//") 	{
+						char *p;
+						p = LEXTEXT;
+
+						DEFAULT_END_OF_LINE_ACTION;
+
+						while (*p == '\n' || *p == '\r')
+							++p;
+						while (*p == ' ' || *p == '\t') {
+							put_char(*p);
+							++p;
+						}
+
+						DBG_SHOW_FLAGS("1V", in_comment, line_str_on, line_str_comment, LEXLINENO);
+
+						if (line_str_comment) {
+							if (in_comment) {
+								echos(comment_end);
+								in_comment = 0;
+							}
+							line_str_comment = 0;
+						}
+
+						if (p[0] != '\\') {
+							if (YY_START == CPP_COMMENT) {
+								yy_pop_state();
+							}
+
+							if (line_str_on) {
+								/*echos(string_end);*/
+								line_str_on = 0;
+							}
+							/*DBG_PRINT("<LSTR id-31b:%d/state=%s/p='%s'>\n", LEXLINENO, state2name(YY_START), p);*/
+
+							if (p[0] == '/' && p[1] == '/') {
+								line_str_comment = 1;
+								in_comment = 1;
+								echos(comment_begin);
+								yy_push_state(CPP_COMMENT);
+								put_string(p);
+							} else {
+								/* End of line string */
+
+								/*DBG_PRINT("<LSTR id-33a/state=%s>\n", state2name(YY_START));*/
+								put_string(p);
+								yy_pop_state();
+								line_str_comment = 0;
+								in_comment = 0;
+								in_line_string = 0;
+							}
+							/*DBG_PRINT("<LSTR id-37:%d/state=%s/p='%s'>\n", LEXLINENO, state2name(YY_START), p);*/
+						} else {
+							/*DBG_PRINT("<LSTR id-41:%d/state=%s/'%s'>\n", LEXLINENO, state2name(YY_START), LEXTEXT);*/
+
+							echos(string_begin);
+							line_str_on = 1;
+							put_string(p);
+							}
+						DBG_SHOW_FLAGS("2W", in_comment, line_str_on, line_str_comment, LEXLINENO);
+						}
+<LN_STRING>(\r\n|\n|\r)		{ warning("\\n and/or \\r in LINE STRING [+%d %s]", LEXLINENO, cur_fname); }
+<LN_STRING>[^\n\r]+		{ 	char *p = LEXTEXT;
+					while (*p == ' ' || *p == '\t') {
+						put_char(*p);
+						++p;
+					}
+					DBG_SHOW_FLAGS("3X", in_comment, line_str_on, line_str_comment, LEXLINENO);
+
+					if (line_str_comment) {
+						if (in_comment == 0) {
+							echos(comment_begin);
+							in_comment = 1;
+						}
+					} else {
+						if (line_str_on == 0) {
+							echos(string_begin);
+							line_str_on = 1;
+						}
+					}
+					/*DBG_PRINT("<LSTR id-57/%d/state=%s/'%s'>\n", LEXLINENO, state2name(YY_START), LEXTEXT);*/
+
+					put_string(p);
+					if (line_str_on) {
+						echos(string_end);
+						line_str_on = 0;
+					}
+					if (in_comment) {
+						in_comment = 0;
+						echos(comment_end);
+					}
+					DBG_SHOW_FLAGS("4Y", in_comment, line_str_on, line_str_comment, LEXLINENO);
+				}
+
+ /* String */
+<INITIAL>\"	{ echos(string_begin); ECHO; yy_push_state(STRING); }
+<STRING>\\.	{ put_char(LEXTEXT[0]); put_char(LEXTEXT[1]); }
+<STRING>\"	{ ECHO; yy_pop_state(); echos(string_end); }
+<STRING>.	{ put_char(LEXTEXT[0]); }
+
+ /* Literal */
+<INITIAL>\'	{ ECHO; yy_push_state(LITERAL); }
+<LITERAL>\\.	{ put_char(LEXTEXT[0]); put_char(LEXTEXT[1]); }
+<LITERAL>\'	{ ECHO; yy_pop_state(); }
+<LITERAL>.	{ put_char(LEXTEXT[0]); }
+
+<INITIAL>"@import("	{ ECHO; yy_push_state(IMPORT); }
+<IMPORT>\"[^\"\n\r]+\"	{
+				char path[MAXPATHLEN];
+				char original_fname[MAXPATHLEN];
+				//const char *basename;
+				size_t n = 0;
+				const char *cp = &LEXTEXT[1];
+				const char *dotptr = NULL;
+				char *p = path;
+				int x;
+
+				if (LEXLENG >= MAXPATHLEN) {
+					die("error, @import() filename too big [+%d %s]",
+						LEXLINENO, cur_fname);
+				}
+				original_fname[0] = '\0';
+				path[0] = '\0';
+
+				/* simulate strncpy() and find filename extension */
+				while (*cp != '"' && (*p = *cp) != '\0' && n < LEXLENG-2) {
+					if (*p == '.')
+						dotptr = p;
+					else if (*p == '/' || *p == '\\')
+						dotptr = NULL;
+					p++;
+					cp++;
+					++n;
+				}
+				if (*p != '\0')
+					*p = '\0';
+
+				if (dotptr != NULL) {
+					x = strcmp(dotptr, ".zig");
+				} else
+					x = 2;
+
+				/* If has no extension, add '.zig', or has '.zig' extension, use filename, else ignore. */
+				if (dotptr == NULL || x == 0) {
+					char tmp[MAXPATHLEN];
+	                                //char normalized_path[MAXPATHLEN];
+
+					strcpy(original_fname, path);
+					if (x != 0)
+						strcpy(p, ".zig");
+				
+					/***********************************************************
+					basename = locatestring(path, "/", MATCH_LAST);
+					if (basename == NULL)
+						basename = locatestring(path, "\\", MATCH_LAST);
+					if (basename != NULL)
+						basename++;
+					else
+						basename = path;
+					***********************************************************/
+
+					//normalized_path[0] = '\0';
+					//snprintf(tmp, sizeof(tmp), "%s/%s", get_current_dir(), basename);
+					snprintf(tmp, sizeof(tmp), "%s", path);
+
+					/*
+					 * pick up the file only when it exists.
+					 */
+							/* [had problems with normalize(), so done it like this] */
+					if ( test("fr", tmp)) {
+						put_char('"');
+						put_include_anchor_direct(tmp, original_fname);
+						put_char('"');
+						x = 1;
+					} else {
+						x = 0;
+					}
+				} else {
+	                                x = 0;
+                                }
+                                if(x != 1) {
+					echos(string_begin);
+					put_char('"');
+					if (original_fname[0] != '\0')
+						put_string(original_fname);
+					else
+						put_string(path);
+	                                put_char('"');
+					echos(string_end);
+				}
+			}
+<IMPORT>")"		{ ECHO; yy_pop_state(); }
+
+<INITIAL>{NUMBER}	{ ECHO; }
+
+<INITIAL>{WORD}	{
+		if ( zig_reserved_word(LEXTEXT, LEXLENG))
+			put_reserved_word(LEXTEXT);
+		else {
+			struct anchor *a = anchor_get(LEXTEXT, LEXLENG, 0, LINENO);
+
+                        if (a) {
+                                put_anchor( gettag(a), a->type, LINENO);
+                                a->done = 1;
+                        } else if (grtags_is_empty) {
+                                put_anchor_force(LEXTEXT, LEXLENG, LINENO);
+                        } else {
+                                ECHO;
+                        }
+                }
+	}
+
+<INITIAL>[{}]	{ put_brace(LEXTEXT); }
+
+(\r\n|\n|\r)		{ /*DBG_PRINT("<NL/%d>\n", LEXLINENO);*/ DEFAULT_END_OF_LINE_ACTION; }
+<INITIAL,CPP_COMMENT>.	{ /*DBG_PRINT("<./%d>\n", LEXLINENO);*/ put_char(LEXTEXT[0]); }
+
+%%
+
+void
+zig_parser_init(FILE *ip)
+{
+	newline_terminate_string = 1;
+	in_line_string = 0;
+	line_str_on = 0;
+	in_comment = 0;
+	line_str_comment = 0;
+	cur_fname = get_current_htags_path() + 2;	/* + 2 to skip './' */
+
+	DEFAULT_BEGIN_OF_FILE_ACTION;
+	BEGIN INITIAL;
+}
--- global-6.6.10/libparser/original_internal.h	2023-05-09 00:50:00 +0100
+++ global-7.7.10/libparser/internal.h	2023-08-12 19:15:06 +0100
@@ -46,6 +46,7 @@ void Cpp(const struct parser_param *);
 void java(const struct parser_param *);
 void php(const struct parser_param *);
 void assembly(const struct parser_param *);
+void zig(const struct parser_param *);
 
 void dbg_print(int, const char *);
 
--- global-6.6.10/libparser/original_Makefile.am	2023-05-09 00:50:00 +0100
+++ global-7.7.10/libparser/Makefile.am	2023-08-16 21:49:10 +0100
@@ -13,9 +13,9 @@
 noinst_LIBRARIES = libgloparser.a
 
 noinst_HEADERS = parser.h internal.h asm_parse.h \
-		c_res.h cpp_res.h java_res.h php_res.h asm_res.h asm_parse.h
+		c_res.h cpp_res.h java_res.h php_res.h asm_res.h asm_parse.h zig_res.h
 
-libgloparser_a_SOURCES = parser.c C.c Cpp.c asm_parse.c asm_scan.c java.c php.c
+libgloparser_a_SOURCES = parser.c C.c Cpp.c asm_parse.c asm_scan.c java.c php.c zig.c
 
 AM_CPPFLAGS = @AM_CPPFLAGS@
 
@@ -26,4 +26,5 @@ EXTRA_DIST = reserved.pl HACKING \
 		cpp_res.in cpp_res.gpf \
 		java_res.in java_res.gpf \
 		php_res.in php_res.gpf php.l \
-		asm_res.in asm_res.gpf asm_parse.y asm_scan.l
+		asm_res.in asm_res.gpf asm_parse.y asm_scan.l \
+		zig_res.in zig_res.gpf zig.l
--- global-6.6.10/libparser/original_parser.c	2023-05-09 00:50:00 +0100
+++ global-7.7.10/libparser/parser.c	2023-08-12 19:16:43 +0100
@@ -281,7 +281,8 @@ static const struct lang_entry lang_swit
 	{"cpp",		Cpp,		"Cpp",		"built-in"},
 	{"java",	java,		"java",		"built-in"},
 	{"php",		php,		"php",		"built-in"},
-	{"asm",		assembly,	"assembly",	"built-in"}
+	{"asm",		assembly,	"assembly",	"built-in"},
+	{"zig",		zig,		"Zig",		"built-in"}
 };
 #define DEFAULT_ENTRY &lang_switch[0]
 /**
--- global-6.6.10/libparser/nul	1970-01-01 00:00:00 +0000
+++ global-7.7.10/libparser/zig.l	2023-08-29 20:27:59 +0100
@@ -0,0 +1,350 @@
+%top{
+/*
+ * Contributed by Simon Dommett, 2023.
+ *
+ * Zig source code parser for gtags.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include <ctype.h>
+
+#include "internal.h"
+#include "die.h"
+#include "gparam.h"
+#include "linetable.h"
+#include "strbuf.h"
+#include "zig_res.h"
+
+#define lex_symbol_generation_rule(x) zig_ ## x
+
+#define LEXLEX		lex_symbol_generation_rule(lex)
+#define LEXTEXT		lex_symbol_generation_rule(text)
+#define LEXLENG		lex_symbol_generation_rule(leng)
+#define LEXRESTART	lex_symbol_generation_rule(restart)
+#define LEXLINENO	lex_symbol_generation_rule(lineno)
+
+#define YY_DECL  int LEXLEX(const struct parser_param *param)
+
+#define ZIG_TOKEN		1
+#define ZIG_STRING		2
+#define ZIG_FUNCTION		3
+#define ZIG_FUNCPOINTER		4
+#define ZIG_FUNCALL		5
+#define ZIG_LPAREN		'('
+#define ZIG_RPAREN		')'
+#define ZIG_LBRACE		'{'
+#define ZIG_RBRACE		'}'
+#define ZIG_LBRACK		'['
+#define ZIG_RBRACK		']'
+
+static void debug_print(const char *, ...);
+static int level;			/* block nest level */
+static STRBUF *string;			/* string */
+
+static const char *cur_filename;
+
+/*
+ * For debugging.
+ * (use '--debug' on gtags)
+ */
+static void
+debug_print(const char *s, ...)
+{
+	va_list ap;
+
+	va_start(ap, s);
+	(void) vfprintf(stderr, s, ap);
+	fflush(stderr);
+	va_end(ap);
+}
+
+#undef DBG_PRINT
+#define DBG_PRINT if (!(param->flags & PARSER_DEBUG)) ; else debug_print
+
+#undef YYLMAX
+#define YYLMAX 1024
+
+#undef ECHO
+#define ECHO  DBG_PRINT("%s", LEXTEXT)
+
+#undef PUT
+#define PUT(type, tag, lno) do {					\
+	char *line_image = linetable_get(lno, NULL);			\
+	char *nl = strchr((const char *) line_image, '\n');		\
+	if (nl != NULL)							\
+		*nl = '\0';						\
+	param->put(type, tag, lno, param->file, line_image, param->arg);\
+	if (nl != NULL)							\
+		*nl = '\n';						\
+	} while (0)
+
+/*
+ * IO routine.
+ */
+#define YY_INPUT(buf, result, max_size) \
+	do { \
+		if ((result = linetable_read(buf, max_size)) == -1) \
+			result = YY_NULL; \
+	} while (0)
+
+ /* end of '%top' */
+}
+
+ /* Definitions */
+
+ /* hexadecimal integer */
+HX		[0-9A-Fa-f]
+HXU		"_"?{HX}
+HEX_INT		{HX}{HXU}*
+HEX		0x{HEX_INT}
+ /* octal integer */
+OC		[0-7]
+OCU		"_"?{OC}
+OCT		0o{OC}{OCU}*
+ /* binary integer */
+BN		[01]
+BNU		"_"?{BN}
+BIN		0b{BN}{BNU}*
+ /* decimal integer */
+DC		[0-9]
+DCU		"_"?{DC}
+DEC		{DC}{DCU}*
+ /* N		{DC}+ */
+
+ /* float */
+FH1		"0x"{HEX_INT}\.{HEX_INT}([pP][-+]?{DEC})?
+FH2		"0x"{HEX_INT}([pP][-+]?{DEC})?
+F1		{DEC}\.{DEC}([eE][-+]?{DEC})?
+F2		{DEC}[eE][-+]?{DEC}
+
+NUMBER		[-+]?({DEC}|{HEX}|{OCT}|{BIN}|{F1}|{F2}|{FH1}|{FH2})
+ALPHA		[a-zA-Z_]
+ALPHANUM	[a-zA-Z0-9_]
+WORD		@?{ALPHA}{ALPHANUM}*
+
+%x  ZIG STRING LITERAL FUNC INCLMODE FUNC_CALL
+%option 8bit noyywrap nounput yylineno never-interactive prefix="zig_"
+%%
+
+[ \t]+			{ ECHO; }
+
+ /* Comment */
+"//"[^\n\r]*		{ DBG_PRINT("<%s>", LEXTEXT); }		/* also is '//!' and '///' */
+
+ /* Line string */
+"\\\\"[^\n\r]*		{ DBG_PRINT("<S:%s>", LEXTEXT); }
+
+"@"\"			{ strbuf_reset(string); BEGIN STRING;  /* FIXME: @"name" @"x y" [id name with almost any char within] */ }
+
+ /* String */
+\"			{ strbuf_reset(string); BEGIN STRING; }
+<STRING>\\.		{ strbuf_puts(string, LEXTEXT); }
+<STRING><<EOF>>		{ param->die("error, unterminated string [+%d %s]",
+				LEXLINENO, cur_filename); }
+<STRING>\"		{
+				DBG_PRINT("<S:%s>", strbuf_value(string));
+				BEGIN INITIAL;
+				return ZIG_STRING;
+			}
+<STRING>.		{ strbuf_putc(string, LEXTEXT[0]); }
+
+ /* Literal */
+\'			{ strbuf_reset(string); BEGIN LITERAL; }
+<LITERAL>\\.		{ strbuf_puts(string, LEXTEXT); }
+<LITERAL>\'		{
+				DBG_PRINT("<L:%s>", strbuf_value(string));
+				BEGIN INITIAL;
+				return ZIG_STRING;
+			}
+<LITERAL>.		{ strbuf_putc(string, LEXTEXT[0]); }
+
+ /* function pointer called 'alloc': alloc: *const fn (ctx: *anyopaque, len: usize, ptr_align: u8, ret_addr: usize) ?[*]u8 */
+{WORD}":"([ \t]+"*const")?[ \t]+"fn"[ \t]+"("	{	/* this version is inside a 'struct' */
+						char *p = strchr(LEXTEXT, ':');
+						*p = '\0';
+						LEXLENG = (yy_size_t)(p - LEXTEXT);
+						DBG_PRINT("<F:%s>", LEXTEXT);
+						return ZIG_FUNCPOINTER;
+						}
+
+("pub"[ \t]+)?"fn"[ \t]+	{ BEGIN FUNC;		/* function definition */ }
+<FUNC>"("			{ BEGIN INITIAL; 	/* unnamed function */ }
+<FUNC>{WORD}"("		{
+				LEXTEXT[LEXLENG-1] = '\0';	/* remove the '(' */
+				--LEXLENG;
+				DBG_PRINT("<F:%s>", LEXTEXT);
+				BEGIN INITIAL;
+				return ZIG_FUNCTION;
+			}
+
+ /* [ \t]*"pub"?[ \t]+"const"?{WORD}"="[ \t]+"struct"[ \t]+"{" { / * struct like in C, but also with function definitions within * /
+			} */
+
+  /* Number (just scan over and ignore) */
+{NUMBER}	{ DBG_PRINT("<N:%s>", LEXTEXT); }
+
+ /* TODO: make: 'u8', 'usize', 'u21', 'u16', 'u64', 'u32', 'i32', a keyword ? (is a data type) */
+
+"@import("\"		{ BEGIN INCLMODE; }
+<INCLMODE>[^"\n\r]+	{ DBG_PRINT("<I:%s>", LEXTEXT); }
+<INCLMODE>\"")"		{ BEGIN INITIAL; }
+
+"|"\*?{WORD}([ \t]*","[ \t]*{WORD})*"|"[ \t]+	{
+			char *s1, *s2, *p;
+			char id[IDENTLEN];
+			size_t n;
+
+			s1 = strchr(LEXTEXT, '|');
+			if (s1 != NULL) {
+				++s1;
+				s2 = strchr(s1, '|');
+				if (s2 != NULL) {
+				  do {
+					if (*s1 == '*')
+						++s1;
+					while (*s1 == ' ' || *s1 == '\t')
+						++s1;
+					if (*s1 == ',')
+						++s1;
+					while (*s1 == ' ' || *s1 == '\t')
+						++s1;
+					p = s1;
+					n = 0;
+					while ( (isalnum(*s1) || *s1 == '_') && s1 < s2) {
+						id[n] = *s1;
+						++n;
+						++s1;
+
+						if (n >= sizeof(id))
+							param->die("error, name too big in '%s' line %d",
+								param->file, LEXLINENO);
+					}
+					id[n] = '\0';
+
+					if (n > 0) {
+						DBG_PRINT("<|N|:%s>", id);
+						PUT(PARSER_DEF, id, LEXLINENO);
+					}
+				    } while(n > 0);
+				}
+			}
+		}
+
+ /* Name (scan over and return it; keyword, function, variable) */
+{WORD}		{
+			int id;
+			if (LEXTEXT[0] == '@')
+				id = 0;		/* built-in function */
+			else
+				id = zig_reserved_word(LEXTEXT, LEXLENG);
+			if (id) {
+				DBG_PRINT("<Reserved:%s/%d>", LEXTEXT, LEXLINENO);
+				return id;
+			} else {
+				/*BEGIN FUNC_CALL;*/ 
+				DBG_PRINT("<T:%s/%d>", LEXTEXT, LEXLINENO);
+				return ZIG_TOKEN;
+			}
+		}
+ /********************************
+ <FUNC_CALL>("."{WORD})*"("	{ ECHO; braklevel = 0; }
+ <FUNC_CALL>"("		{ ECHO; braklevel++; }
+ <FUNC_CALL>")"		{ ECHO; if (braklevel == 0) { BEGIN INITIAL; / * end of function call * / }
+				else { --braklevel; } }
+ <FUNC_CALL>\\.		{ ECHO; }	// TODO: need to do strings, comments, newlines, etc with '<FUNC_CALL>' if get a ')' within them.
+ <FUNC_CALL>.		{ ECHO; }
+ ********************************/
+
+ /********************************
+ ({WORD}".")*{WORD}"("	{ 	/ * function call * /
+			LEXTEXT[LEXLENG-1] = '\0';		/ * remove the '(' * /
+			--LEXLENG;
+			DBG_PRINT("<C:%s/%d>", LEXTEXT, LEXLINENO);
+			return ZIG_FUNCALL;
+			}
+ ********************************/
+
+ /* Operator (mainly scan over and ignore) */
+[{}]			{
+				int c = LEXTEXT[0];
+				if (c == ZIG_LBRACE)
+					level++;
+				else
+					level--;
+				DBG_PRINT("%c[%d]", c, level);
+				return c;
+			}
+[][()]			{ ECHO; return LEXTEXT[0]; }
+[-+*/%&^|]=?	|
+[=><!]=		|
+"=>"		|
+[+|<>*]{2}=?	|
+[<>]		|
+\.[?*]		|
+\.{2,3}		{ ECHO; }	/* range: .. or ... */
+
+[-+]"%"=?	|
+[-+]"|"=?	|
+\*[%|]=?	|
+"<<|"=?		|
+"~"		|
+"->"		{ ECHO; }
+
+(\r\n|\r|\n)	{ ECHO; }
+.		{ ECHO; }
+
+%%
+
+/**
+ * zig: read ZIG file and pickup tag entries.
+ *
+ *	@param[in]	param	pointer to struct parser_param
+ */
+void
+zig(const struct parser_param *param)
+{
+	int token;
+
+	level = 0;
+	string = strbuf_open(0);
+
+	if (linetable_open(param->file) == -1)
+		die("'%s' cannot open.", param->file);
+
+	cur_filename = param->file;
+	BEGIN(INITIAL);
+	LEXRESTART(NULL);
+	LEXLINENO = 1;
+	while ((token = LEXLEX(param)) != 0) {
+		switch (token) {
+		case ZIG_FUNCTION:
+		case ZIG_FUNCPOINTER:
+				/* if(LEXTEXT[0] == '@') built-in zig function */
+			PUT(PARSER_DEF, LEXTEXT, LEXLINENO);
+			break;
+		case ZIG_FUNCALL:	/* also see ZIG_TOKEN below */
+			PUT(PARSER_REF_SYM, LEXTEXT, LEXLINENO);
+			break;
+		/* case ZIG_STRING: */
+		case ZIG_TOKEN:
+			PUT(PARSER_REF_SYM, LEXTEXT, LEXLINENO);
+			/* if (LEXLEX(param) == ZIG_LPAREN)
+				PUT_X(PARSER_REF_CALL, LEXTEXT, LEXLINENO, parent_object);	// future extention ?
+			*/
+			break;
+		default:
+			break;
+		}
+	}
+	linetable_close();
+	strbuf_close(string);
+} /* zig() */
--- global-6.6.10/libparser/nul	1970-01-01 00:00:00 +0000
+++ global-7.7.10/libparser/zig_res.gpf	2023-07-30 17:17:05 +0100
@@ -0,0 +1,135 @@
+%{
+#include "strmake.h"
+#define START_VARIABLE	1001
+#define START_WORD	2001
+#define START_SHARP	3001
+#define START_YACC	4001
+#define IS_RESERVED_WORD(a)	((a) >= START_WORD)
+#define IS_RESERVED_VARIABLE(a)	((a) >= START_VARIABLE && (a) < START_WORD)
+#define IS_RESERVED_SHARP(a)	((a) >= START_SHARP && (a) < START_YACC)
+#define IS_RESERVED_YACC(a)	((a) >= START_YACC)
+
+#define ZIG_ALIGN	2001
+#define ZIG_ALLOWZERO	2002
+#define ZIG_AND	2003
+#define ZIG_ANYFRAME	2004
+#define ZIG_ANYTYPE	2005
+#define ZIG_ASM	2006
+#define ZIG_ASYNC	2007
+#define ZIG_AWAIT	2008
+#define ZIG_BOOL	2009
+#define ZIG_BREAK	2010
+#define ZIG_CALLCONV	2011
+#define ZIG_CATCH	2012
+#define ZIG_COMPTIME	2013
+#define ZIG_CONST	2014
+#define ZIG_CONTINUE	2015
+#define ZIG_DEFER	2016
+#define ZIG_ELSE	2017
+#define ZIG_ENUM	2018
+#define ZIG_ERRDEFER	2019
+#define ZIG_ERROR	2020
+#define ZIG_EXPORT	2021
+#define ZIG_EXTERN	2022
+#define ZIG_FALSE	2023
+#define ZIG_FN	2024
+#define ZIG_FOR	2025
+#define ZIG_IF	2026
+#define ZIG_INLINE	2027
+#define ZIG_NOALIAS	2028
+#define ZIG_NOINLINE	2029
+#define ZIG_NORETURN	2030
+#define ZIG_NOSUSPEND	2031
+#define ZIG_NULL	2032
+#define ZIG_OR	2033
+#define ZIG_OPAQUE	2034
+#define ZIG_ORELSE	2035
+#define ZIG_PACKED	2036
+#define ZIG_PUB	2037
+#define ZIG_RESUME	2038
+#define ZIG_RETURN	2039
+#define ZIG_LINKSECTION	2040
+#define ZIG_SELF	2041
+#define ZIG_STRUCT	2042
+#define ZIG_SUSPEND	2043
+#define ZIG_SWITCH	2044
+#define ZIG_TEST	2045
+#define ZIG_THREADLOCAL	2046
+#define ZIG_TRUE	2047
+#define ZIG_TRY	2048
+#define ZIG_UNDEFINED	2049
+#define ZIG_UNION	2050
+#define ZIG_UNREACHABLE	2051
+#define ZIG_USINGNAMESPACE	2052
+#define ZIG_VAR	2053
+#define ZIG_VOID	2054
+#define ZIG_VOLATILE	2055
+#define ZIG_WHILE	2056
+%}
+struct keyword { char *name; int token; }
+%%
+align, ZIG_ALIGN
+allowzero, ZIG_ALLOWZERO
+and, ZIG_AND
+anyframe, ZIG_ANYFRAME
+anytype, ZIG_ANYTYPE
+asm, ZIG_ASM
+async, ZIG_ASYNC
+await, ZIG_AWAIT
+bool, ZIG_BOOL
+break, ZIG_BREAK
+callconv, ZIG_CALLCONV
+catch, ZIG_CATCH
+comptime, ZIG_COMPTIME
+const, ZIG_CONST
+continue, ZIG_CONTINUE
+defer, ZIG_DEFER
+else, ZIG_ELSE
+enum, ZIG_ENUM
+errdefer, ZIG_ERRDEFER
+error, ZIG_ERROR
+export, ZIG_EXPORT
+extern, ZIG_EXTERN
+false, ZIG_FALSE
+fn, ZIG_FN
+for, ZIG_FOR
+if, ZIG_IF
+inline, ZIG_INLINE
+noalias, ZIG_NOALIAS
+noinline, ZIG_NOINLINE
+noreturn, ZIG_NORETURN
+nosuspend, ZIG_NOSUSPEND
+null, ZIG_NULL
+or, ZIG_OR
+opaque, ZIG_OPAQUE
+orelse, ZIG_ORELSE
+packed, ZIG_PACKED
+pub, ZIG_PUB
+resume, ZIG_RESUME
+return, ZIG_RETURN
+linksection, ZIG_LINKSECTION
+self, ZIG_SELF
+struct, ZIG_STRUCT
+suspend, ZIG_SUSPEND
+switch, ZIG_SWITCH
+test, ZIG_TEST
+threadlocal, ZIG_THREADLOCAL
+true, ZIG_TRUE
+try, ZIG_TRY
+undefined, ZIG_UNDEFINED
+union, ZIG_UNION
+unreachable, ZIG_UNREACHABLE
+usingnamespace, ZIG_USINGNAMESPACE
+var, ZIG_VAR
+void, ZIG_VOID
+volatile, ZIG_VOLATILE
+while, ZIG_WHILE
+%%
+int
+zig_reserved_word(const char *str, int len)
+{
+	struct keyword *keyword;
+
+	keyword = zig_lookup(str, len);
+	return (keyword && IS_RESERVED_WORD(keyword->token)) ? keyword->token : 0;
+}
--- global-6.6.10/libparser/nul	1970-01-01 00:00:00 +0000
+++ global-7.7.10/libparser/zig_res.h	2023-07-30 17:17:06 +0100
@@ -0,0 +1,272 @@
+/* ANSI-C code produced by gperf version 3.0.4 */
+/* Command-line: gperf --language=ANSI-C --struct-type --slot-name=name --hash-fn-name=zig_hash --lookup-fn-name=zig_lookup  */
+/* Computed positions: -k'2-3' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <[email protected]>."
+#endif
+
+
+#include "strmake.h"
+#define START_VARIABLE	1001
+#define START_WORD	2001
+#define START_SHARP	3001
+#define START_YACC	4001
+#define IS_RESERVED_WORD(a)	((a) >= START_WORD)
+#define IS_RESERVED_VARIABLE(a)	((a) >= START_VARIABLE && (a) < START_WORD)
+#define IS_RESERVED_SHARP(a)	((a) >= START_SHARP && (a) < START_YACC)
+#define IS_RESERVED_YACC(a)	((a) >= START_YACC)
+
+#define ZIG_ALIGN	2001
+#define ZIG_ALLOWZERO	2002
+#define ZIG_AND	2003
+#define ZIG_ANYFRAME	2004
+#define ZIG_ANYTYPE	2005
+#define ZIG_ASM	2006
+#define ZIG_ASYNC	2007
+#define ZIG_AWAIT	2008
+#define ZIG_BOOL	2009
+#define ZIG_BREAK	2010
+#define ZIG_CALLCONV	2011
+#define ZIG_CATCH	2012
+#define ZIG_COMPTIME	2013
+#define ZIG_CONST	2014
+#define ZIG_CONTINUE	2015
+#define ZIG_DEFER	2016
+#define ZIG_ELSE	2017
+#define ZIG_ENUM	2018
+#define ZIG_ERRDEFER	2019
+#define ZIG_ERROR	2020
+#define ZIG_EXPORT	2021
+#define ZIG_EXTERN	2022
+#define ZIG_FALSE	2023
+#define ZIG_FN	2024
+#define ZIG_FOR	2025
+#define ZIG_IF	2026
+#define ZIG_INLINE	2027
+#define ZIG_NOALIAS	2028
+#define ZIG_NOINLINE	2029
+#define ZIG_NORETURN	2030
+#define ZIG_NOSUSPEND	2031
+#define ZIG_NULL	2032
+#define ZIG_OR	2033
+#define ZIG_OPAQUE	2034
+#define ZIG_ORELSE	2035
+#define ZIG_PACKED	2036
+#define ZIG_PUB	2037
+#define ZIG_RESUME	2038
+#define ZIG_RETURN	2039
+#define ZIG_LINKSECTION	2040
+#define ZIG_SELF	2041
+#define ZIG_STRUCT	2042
+#define ZIG_SUSPEND	2043
+#define ZIG_SWITCH	2044
+#define ZIG_TEST	2045
+#define ZIG_THREADLOCAL	2046
+#define ZIG_TRUE	2047
+#define ZIG_TRY	2048
+#define ZIG_UNDEFINED	2049
+#define ZIG_UNION	2050
+#define ZIG_UNREACHABLE	2051
+#define ZIG_USINGNAMESPACE	2052
+#define ZIG_VAR	2053
+#define ZIG_VOID	2054
+#define ZIG_VOLATILE	2055
+#define ZIG_WHILE	2056
+struct keyword { char *name; int token; };
+
+#define TOTAL_KEYWORDS 56
+#define MIN_WORD_LENGTH 2
+#define MAX_WORD_LENGTH 14
+#define MIN_HASH_VALUE 4
+#define MAX_HASH_VALUE 91
+/* maximum key range = 88, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+zig_hash (register const char *str, register unsigned int len)
+{
+  static unsigned char asso_values[] =
+    {
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 30,  0, 45,
+      35, 50, 20, 92,  0, 25, 92, 92, 20, 40,
+      15,  0, 40, 92,  5,  0, 35, 60, 92,  5,
+      25, 60, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+      92, 92, 92, 92, 92, 92
+    };
+  register int hval = len;
+
+  switch (hval)
+    {
+      default:
+        hval += asso_values[(unsigned char)str[2]];
+      /*FALLTHROUGH*/
+      case 2:
+        hval += asso_values[(unsigned char)str[1]];
+        break;
+    }
+  return hval;
+}
+
+#ifdef __GNUC__
+__inline
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+struct keyword *
+zig_lookup (register const char *str, register unsigned int len)
+{
+  static struct keyword wordlist[] =
+    {
+      {""}, {""}, {""}, {""},
+      {"bool", ZIG_BOOL},
+      {""}, {""},
+      {"or", ZIG_OR},
+      {"for", ZIG_FOR},
+      {"nosuspend", ZIG_NOSUSPEND},
+      {""}, {""}, {""},
+      {"noreturn", ZIG_NORETURN},
+      {""},
+      {"error", ZIG_ERROR},
+      {"threadlocal", ZIG_THREADLOCAL},
+      {"fn", ZIG_FN},
+      {"errdefer", ZIG_ERRDEFER},
+      {""},
+      {"const", ZIG_CONST},
+      {""},
+      {"if", ZIG_IF},
+      {"continue", ZIG_CONTINUE},
+      {"else", ZIG_ELSE},
+      {""}, {""}, {""},
+      {"volatile", ZIG_VOLATILE},
+      {"void", ZIG_VOID},
+      {"while", ZIG_WHILE},
+      {"unreachable", ZIG_UNREACHABLE},
+      {""},
+      {"noinline", ZIG_NOINLINE},
+      {""}, {""},
+      {"switch", ZIG_SWITCH},
+      {"noalias", ZIG_NOALIAS},
+      {"var", ZIG_VAR},
+      {"usingnamespace", ZIG_USINGNAMESPACE},
+      {"await", ZIG_AWAIT},
+      {"inline", ZIG_INLINE},
+      {""},
+      {"asm", ZIG_ASM},
+      {""},
+      {"union", ZIG_UNION},
+      {"struct", ZIG_STRUCT},
+      {""},
+      {"comptime", ZIG_COMPTIME},
+      {"allowzero", ZIG_ALLOWZERO},
+      {"align", ZIG_ALIGN},
+      {"linksection", ZIG_LINKSECTION},
+      {""},
+      {"and", ZIG_AND},
+      {"test", ZIG_TEST},
+      {"false", ZIG_FALSE},
+      {"resume", ZIG_RESUME},
+      {""},
+      {"callconv", ZIG_CALLCONV},
+      {"undefined", ZIG_UNDEFINED},
+      {"break", ZIG_BREAK},
+      {"orelse", ZIG_ORELSE},
+      {""},
+      {"pub", ZIG_PUB},
+      {""},
+      {"async", ZIG_ASYNC},
+      {"extern", ZIG_EXTERN},
+      {"suspend", ZIG_SUSPEND},
+      {"try", ZIG_TRY},
+      {"true", ZIG_TRUE},
+      {"catch", ZIG_CATCH},
+      {"export", ZIG_EXPORT},
+      {""}, {""},
+      {"self", ZIG_SELF},
+      {"defer", ZIG_DEFER},
+      {"opaque", ZIG_OPAQUE},
+      {""}, {""},
+      {"enum", ZIG_ENUM},
+      {""},
+      {"packed", ZIG_PACKED},
+      {"anytype", ZIG_ANYTYPE},
+      {"anyframe", ZIG_ANYFRAME},
+      {"null", ZIG_NULL},
+      {""}, {""}, {""}, {""}, {""}, {""},
+      {"return", ZIG_RETURN}
+    };
+
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = zig_hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= 0)
+        {
+          register const char *s = wordlist[key].name;
+
+          if (*str == *s && !strcmp (str + 1, s + 1))
+            return &wordlist[key];
+        }
+    }
+  return 0;
+}
+
+int
+zig_reserved_word(const char *str, int len)
+{
+	struct keyword *keyword;
+
+	keyword = zig_lookup(str, len);
+	return (keyword && IS_RESERVED_WORD(keyword->token)) ? keyword->token : 0;
+}
--- global-6.6.10/libparser/nul	1970-01-01 00:00:00 +0000
+++ global-7.7.10/libparser/zig_res.in	2023-08-29 17:05:47 +0100
@@ -0,0 +1,58 @@
+; zig keywords, 24-jul-2023
+
+align		word
+allowzero	word
+and		word
+anyframe	word
+anytype		word
+asm		word
+async		word
+await		word
+bool		word
+break		word
+callconv	word
+catch		word
+comptime	word
+const		word
+continue	word
+defer		word
+else		word
+enum		word
+errdefer	word
+error		word
+export		word
+extern		word
+false		word
+fn		word
+for		word
+if		word
+inline		word
+noalias		word
+noinline	word
+noreturn	word
+nosuspend	word
+null		word
+or		word
+opaque		word
+orelse		word
+packed		word
+pub		word
+resume		word
+return		word
+linksection	word
+self		word
+struct		word
+suspend		word
+switch		word
+test		word
+threadlocal	word
+true		word
+try		word
+undefined	word
+union		word
+unreachable	word
+usingnamespace	word
+var		word
+void		word
+volatile	word
+while		word
--- global-6.6.10/libutil/original_compress.c	2023-05-09 00:50:01 +0100
+++ global-7.7.10/libutil/compress.c	2023-08-12 21:07:12 +0100
@@ -166,6 +166,7 @@ abbrev_dump(void)
  *
  *	@param[in]	in	source line
  *	@param[in]	name	replaced string
+ *	@param[in,out]	sb	compressed result
  *	@return		compressed string
  */
 char *
@@ -197,8 +198,13 @@ compress(const char *in, const char *nam
 		}
 		spaces = 0;
 		if (*p == '@') {
-			strbuf_puts(sb, "@@");
-			p++;
+			if (name[0] == '@' && !strncmp(p, name, length)) {
+				strbuf_puts(sb, "@n");
+				p += length;
+			} else {
+				strbuf_puts(sb, "@@");
+				++p;
+			}
 		} else if (!strncmp(p, name, length)) {
 			strbuf_puts(sb, "@n");
 			p += length;
@@ -244,6 +250,7 @@ compress(const char *in, const char *nam
  *
  *	@param[in]	in	compressed string
  *	@param[in]	name	replaced string
+ *	@param[in,out]	sb	uncompressed result
  *	@return		uncompressed string
  */
 char *
--- global-6.6.10/libutil/original_gtagsop.c	2023-05-09 00:50:01 +0100
+++ global-7.7.10/libutil/gtagsop.c	2023-08-14 18:12:58 +0100
@@ -231,20 +231,20 @@ seekto(const char *string, int n)
  *
  * [History of format version]
  *
-  GLOBAL-1.0 - 1.8     no idea about format version.
-  GLOBAL-1.9 - 2.24    understand format version.
-                       support format version 1 (default).
-                       if (format > 1) then print error message.
-  GLOBAL-3.0 - 4.5     support format version 1 and 2.
-                       if (format > 2) then print error message.
-  GLOBAL-4.5.1 - 4.8.7 support format version 1, 2 and 3.
-                       if (format > 3) then print error message.
-  GLOBAL-5.0 -	5.3	support format version only 4.
-                       if (format !=  4) then print error message.
-  GLOBAL-5.4 - 5.8.2	support format version 4 and 5
-                       if (format > 5 || format < 4) then print error message.
-  GLOBAL-5.9 -		support only format version 6
-                       if (format > 6 || format < 6) then print error message.
+ * GLOBAL-1.0 - 1.8     no idea about format version.
+ * GLOBAL-1.9 - 2.24    understand format version.
+ *                      support format version 1 (default).
+ *                      if (format > 1) then print error message.
+ * GLOBAL-3.0 - 4.5     support format version 1 and 2.
+ *                      if (format > 2) then print error message.
+ * GLOBAL-4.5.1 - 4.8.7 support format version 1, 2 and 3.
+ *                      if (format > 3) then print error message.
+ * GLOBAL-5.0 -	5.3	support format version only 4.
+ *                      if (format !=  4) then print error message.
+ * GLOBAL-5.4 - 5.8.2	support format version 4 and 5
+ *                      if (format > 5 || format < 4) then print error message.
+ * GLOBAL-5.9 -		support only format version 6
+ *                      if (format > 6 || format < 6) then print error message.
  *
  * In GLOBAL-5.0, we threw away the compatibility with the past formats.
  * Though we could continue the support for older formats, it seemed
--- global-6.6.10/libutil/original_langmap.h	2023-05-09 00:50:47 +0100
+++ global-7.7.10/libutil/langmap.h	2023-08-12 19:18:53 +0100
@@ -20,7 +20,7 @@
 #ifndef _LANGMAP_H_
 #define _LANGMAP_H_
 
-#define DEFAULTLANGMAP  "c:.c.h,yacc:.y,asm:.s.S,java:.java,cpp:.c++.cc.hh.cpp.cxx.hxx.hpp.C.H,php:.php.php3.phtml"
+#define DEFAULTLANGMAP  "c:.c.h,yacc:.y,asm:.s.S,java:.java,cpp:.c++.cc.hh.cpp.cxx.hxx.hpp.C.H,php:.php.php3.phtml,zig:.zig"
 #define DEFAULTSKIP     "HTML/,HTML.pub/,tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,SCCS/,RCS/,CVS/,CVSROOT/,{arch}/,autom4te.cache/,*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,*.o,*.a,*.so,*.lo,*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,*.min.js,*min.css"
 #define DEFAULTINCLUDEFILESUFFIXES "h,hh,hxx,hpp,H,inc.php"
 
--- global-6.6.10/libutil/original_strmake.c	2023-05-09 00:50:01 +0100
+++ global-7.7.10/libutil/strmake.c	2023-08-14 18:17:37 +0100
@@ -149,7 +149,7 @@ strcmp_withterm(const char *s1, const ch
 /**
  * strcpy with terminate character.
  *
- *	@param[in]	b	buffer
+ *	@param[out]	b	buffer
  *	@param[in]	s	string
  *	@param[in]	size	buffer size
  *	@param[in]	term	terminate character
--- global-6.6.10/original_reconf.sh	2023-05-09 00:50:00 +0100
+++ global-7.7.10/reconf.sh	2023-08-12 20:05:25 +0100
@@ -75,7 +75,7 @@ done
 #
 echo "- Preparing parser source ..."
 (cd libparser; set -x
-for lang in c cpp java php asm; do
+for lang in c cpp java php asm zig; do
 	name=${lang}_res
 	perl ./reserved.pl --prefix=$lang ${lang}_res.in > ${name}.gpf
 	option=`perl ./reserved.pl --prefix=$lang --option`
@@ -92,7 +92,7 @@ for lang in c cpp java php asm; do
 done
 )
 (cd htags; set -x
-for lang in c cpp java php asm; do
+for lang in c cpp java php asm zig; do
 	flex -o$lang.c $lang.l
 done
 )

Reply via email to