[geany/geany] 589a34: Update to version p5.9.20211031.0 of ctags

Jiří Techet git-noreply at xxxxx
Thu Nov 25 11:02:52 UTC 2021


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   Enrico Tröger <enrico.troeger at uvena.de>
Date:        Thu, 25 Nov 2021 11:02:52 UTC
Commit:      589a3429e6f083c67ccb4d2ce5eae967aebd2632
             https://github.com/geany/geany/commit/589a3429e6f083c67ccb4d2ce5eae967aebd2632

Log Message:
-----------
Update to version p5.9.20211031.0 of ctags

This change was mostly made by the update-ctags.py script. Apart from
that, the ctags/Makefile.am file was updated to add newly added files
in ctags and also include headers from the new dsl directory
(inclusion of the dsl directory had to be performed in
src/tagmanager/Makefile.am file too).


Modified Paths:
--------------
    ctags/Makefile.am
    ctags/dsl/es.c
    ctags/dsl/es.h
    ctags/dsl/optscript.c
    ctags/dsl/optscript.h
    ctags/main/CommonPrelude.c
    ctags/main/args.c
    ctags/main/dependency.c
    ctags/main/entry.c
    ctags/main/entry.h
    ctags/main/entry_p.h
    ctags/main/error.c
    ctags/main/field.c
    ctags/main/field.h
    ctags/main/field_p.h
    ctags/main/flags.c
    ctags/main/flags_p.h
    ctags/main/fmt.c
    ctags/main/htable.c
    ctags/main/htable.h
    ctags/main/kind_p.h
    ctags/main/lregex-default.c
    ctags/main/lregex-pcre2.c
    ctags/main/lregex.c
    ctags/main/lregex_p.h
    ctags/main/main.c
    ctags/main/mio.c
    ctags/main/options.c
    ctags/main/options.h
    ctags/main/options_p.h
    ctags/main/parse.c
    ctags/main/parse.h
    ctags/main/parse_p.h
    ctags/main/parsers_p.h
    ctags/main/promise.c
    ctags/main/promise.h
    ctags/main/ptag.c
    ctags/main/ptag_p.h
    ctags/main/ptrarray.c
    ctags/main/ptrarray.h
    ctags/main/read.c
    ctags/main/read_p.h
    ctags/main/repoinfo.h
    ctags/main/routines.c
    ctags/main/routines.h
    ctags/main/routines_p.h
    ctags/main/script.c
    ctags/main/script_p.h
    ctags/main/seccomp.c
    ctags/main/selectors.c
    ctags/main/selectors.h
    ctags/main/strlist.c
    ctags/main/strlist.h
    ctags/main/subparser.h
    ctags/main/tokeninfo.c
    ctags/main/tokeninfo.h
    ctags/main/trace.c
    ctags/main/trace.h
    ctags/main/vstring.c
    ctags/main/vstring.h
    ctags/main/writer-ctags.c
    ctags/main/writer-json.c
    ctags/main/writer.c
    ctags/main/writer_p.h
    ctags/main/xtag.c
    ctags/main/xtag_p.h
    src/tagmanager/Makefile.am

Modified: ctags/Makefile.am
10 lines changed, 10 insertions(+), 0 deletions(-)
===================================================================
@@ -1,6 +1,7 @@
 AM_CPPFLAGS = \
 	-I$(srcdir)/main \
 	-I$(srcdir)/parsers \
+	-I$(srcdir)/dsl \
 	-DEXTERNAL_PARSER_LIST_FILE=\"$(top_srcdir)/src/tagmanager/tm_parsers.h\" \
 	-DG_LOG_DOMAIN=\"CTags\"
 AM_CFLAGS = \
@@ -58,11 +59,17 @@ parsers = \
 	parsers/geany_vhdl.c
 
 # skip cmd.c and mini-geany.c which define main()
+# also skip lregex-pcre2.c which we don't use
 libctags_la_SOURCES = \
+	dsl/optscript.c \
+	dsl/optscript.h \
+	dsl/es.c \
+	dsl/es.h \
 	main/args.c \
 	main/args_p.h \
 	main/colprint.c \
 	main/colprint_p.h \
+	main/CommonPrelude.c \
 	main/ctags.h \
 	main/debug.c \
 	main/debug.h \
@@ -99,6 +106,7 @@ libctags_la_SOURCES = \
 	main/lregex.c \
 	main/lregex.h \
 	main/lregex_p.h \
+	main/lregex-default.c \
 	main/lxpath.c \
 	main/lxpath.h \
 	main/lxpath_p.h \
@@ -144,6 +152,8 @@ libctags_la_SOURCES = \
 	main/routines.c \
 	main/routines.h \
 	main/routines_p.h \
+	main/script.c \
+	main/script_p.h \
 	main/seccomp.c \
 	main/selectors.c \
 	main/selectors.h \


Modified: ctags/dsl/es.c
3332 lines changed, 3332 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: ctags/dsl/es.h
274 lines changed, 274 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,274 @@
+/*
+  Copyright (c) 2009 Masatake YAMATO
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE. */
+
+#ifndef __ES_LANG_C_STDC99_H__
+#define __ES_LANG_C_STDC99_H__
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdio.h>
+
+#include "mio.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+enum _EsType {
+  ES_TYPE_NIL,
+  ES_TYPE_INTEGER,
+  ES_TYPE_REAL,
+  ES_TYPE_BOOLEAN,
+  ES_TYPE_SYMBOL,
+  ES_TYPE_STRING,
+  ES_TYPE_CONS,
+  ES_TYPE_REGEX,
+  /* ... */
+  ES_TYPE_ERROR,
+  /* ... */
+  ES_TYPE_BUILTIN_LAST = ES_TYPE_ERROR,
+  ES_TYPE_FOREIGNER_START,
+};
+typedef enum _EsType EsType;
+
+struct _EsObject;
+typedef struct _EsObject EsObject;
+
+const char* es_type_get_name        (int t);
+
+EsType      es_object_get_type      (const EsObject*      object);
+
+
+EsObject*   es_object_ref           (EsObject*       object);
+void        es_object_unref         (EsObject*       object);
+void        es_object_unref_batch   (EsObject*       array[],
+									 unsigned int    count);
+EsObject*   es_object_autounref     (EsObject*      object);
+
+int         es_object_equal         (const EsObject* self,
+									 const EsObject* other);
+
+int         es_atom                 (const EsObject* object);
+
+#define     ES_ERROR_MEMORY   es_error_intern("MEMORY-EXHAUSTED")
+#define     ES_ERROR_REGEX    es_error_intern("WRONG-REGEX-SYNTAX")
+
+/*
+ * Nil
+ */
+#define es_nil ((EsObject*)0)
+int         es_null                 (const EsObject* object);
+
+/*
+ * Integer
+ */
+EsObject*    es_integer_new (int                value);
+int          es_integer_p   (const EsObject*   object);
+int          es_integer_get (const EsObject*   object);
+
+
+/*
+ * Real
+ */
+EsObject*    es_real_new    (double             value);
+int          es_real_p      (const EsObject*   object);
+double       es_real_get    (const EsObject*   object);
+
+
+/*
+ * Use Integer as Real
+ */
+int          es_number_p    (const EsObject*   object);
+double       es_number_get  (const EsObject*   object);
+
+
+/*
+ * Boolean
+ */
+#define es_true             (es_boolean_new(1))
+#define es_false            (es_boolean_new(0))
+EsObject*    es_boolean_new (int                value);
+int          es_boolean_p   (const EsObject*   object);
+int          es_boolean_get (const EsObject*   object);
+
+/*
+ * String
+ */
+EsObject*    es_string_new  (const char*        value);
+EsObject*    es_string_newL (const char*        value, size_t length);
+int          es_string_p    (const EsObject*   object);
+const char*  es_string_get  (const EsObject*   object);
+
+
+/*
+ * Symbol
+ */
+EsObject*    es_symbol_intern  (const char*       name);
+int          es_symbol_p    (const EsObject*   object);
+const char*  es_symbol_get  (const EsObject*   object);
+
+void*        es_symbol_set_data (const EsObject*   object, void *data);
+void*        es_symbol_get_data (const EsObject*   object);
+
+/*
+ * Error
+ */
+
+EsObject*    es_error_intern (const char*        name);
+int          es_error_p      (const EsObject*   object);
+const char*  es_error_name   (const EsObject*   object);
+EsObject*    es_error_set_object (EsObject*   error, EsObject*   object);
+EsObject*    es_error_get_object (const EsObject*   error);
+
+
+/*
+ * Cons
+ */
+EsObject*    es_cons        (EsObject* car, EsObject* cdr);
+int          es_cons_p      (const EsObject* object);
+int          es_list_p      (const EsObject* object);
+EsObject*    es_car         (const EsObject* object);
+EsObject*    es_cdr         (const EsObject* object);
+
+
+/*
+ * Regex
+ */
+EsObject*    es_regex_compile (const char* pat,
+							   int case_insensitive);
+int          es_regex_p       (const EsObject* object);
+EsObject*    es_regex_exec    (const EsObject* regex,
+							   const EsObject* str);
+
+/*
+ * Foreign pointer
+ */
+EsType       es_type_define_pointer   (const char *name,
+									   void (* freefn) (void *),
+									   int  (* equalfn) (const void*, const void*),
+									   void (* printfn) (const void*, MIO *));
+
+/* If the type has sized fat area, the area is filled with zero. */
+EsObject*    es_pointer_new    (EsType type, void *ptr);
+void*        es_pointer_get    (const EsObject *object);
+void*        es_pointer_take   (EsObject *object);
+
+/*
+ * Fatptr: Foreign pointer with extra data
+ *
+ * init_fat () returns es_true if the initialization ends successfully.
+ * In failure case, init_fat () returns an error object.
+ */
+EsType       es_type_define_fatptr    (const char *name,
+									   size_t fat_size,
+									   EsObject *(* initfat_fn) (void *fat, void * ptr, void *extra),
+									   void (* freefn) (void * ptr, void *fat),
+									   int  (* equalfn) (const void* ptr_a, const void* fat_a,
+														 const void* ptr_b, const void* fat_b),
+									   void (* printfn) (const void* ptr, const void *fat, MIO *));
+/* If initfat_fn is given in the type, the new fat area will is
+ * initialized with the method.
+ * If initfat_fn is not given, and extra is not NULL, the contents
+ * pointed by extra is copied to the fat area.
+ * If initfat_fn is not given, and extra is NULL, the fat area
+ * is filled with zero as es_pointer_new does. */
+EsObject*    es_fatptr_new     (EsType type, void *ptr, void *extra);
+/* Access to the fat area. Use es_pointer_get to access the pointer. */
+void*        es_fatptr_get     (const EsObject *object);
+
+/*
+ * Print
+ */
+void         es_print           (const EsObject* object,
+								 MIO*           out);
+char*        es_print_to_string (EsObject*        object);
+
+/*
+ * Read
+ */
+EsObject*    es_read            (MIO* in);
+EsObject*    es_read_from_string(const char* in,
+								 const char** saveptr);
+
+#define      ES_READER_ERROR es_error_intern("READ-ERROR")
+#define      ES_READER_EOF   es_error_intern("EOF")
+
+/*
+ * Comment
+ */
+void         es_comment           (const char* comment,
+								   MIO*       out);
+char*        es_comment_to_string (const char* comment);
+
+/*
+ * Autounref pool
+ */
+void es_autounref_pool_push(void);
+void es_autounref_pool_pop (void);
+
+
+
+/*
+ * List builders
+ */
+EsObject* es_list     (EsObject* object,...);
+EsObject* es_append   (EsObject* list,...);
+EsObject* es_reverse  (EsObject* cons);
+
+#define      ES_PROC_UNIMPLEMENTED es_error_intern("PROC-UNIMPLEMENTED")
+EsObject* es_realize   (EsObject* fmt_object,...);
+EsObject* es_srealize  (const char* fmt,...);
+
+/* The value returned from FN treated as if it is returned from
+ * a *_new function. es_map may call es_object_unref() for the value.
+ * The value returned from es_map should be treated as if it is
+ * returned from a *_new function. The caller must free the returned
+ * value.
+ */
+EsObject* es_map   (EsObject * (*fn) (EsObject *, void *),
+					EsObject *list, void *user_data);
+
+/* Unlike es_map, the value returnd from FN is not accumulated.
+ * If FN returns a value other than #f, es_foreach stops the
+ * iteration immediately and returns the value.
+ */
+EsObject* es_foreach (EsObject * (*fn) (EsObject *, void *),
+					  EsObject *list, void *user_data);
+
+/* The memory management of es_map is also applicable to es_fold. */
+EsObject* es_fold (EsObject * (*kons) (EsObject *, EsObject *, void *),
+				   EsObject * knil, EsObject * list, void *user_data);
+
+/*
+ * Rich element accessors
+ */
+int        es_match        (EsObject* input, EsObject* fmt_object,...);
+int        es_smatch       (EsObject* input, const char* fmt,...);
+
+
+EsObject*  es_pget         (EsObject* plist, EsObject* key, EsObject* default_value);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* Not def: __ES_LANG_C_STDC_H__ */


Modified: ctags/dsl/optscript.c
4422 lines changed, 4422 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: ctags/dsl/optscript.h
88 lines changed, 88 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,88 @@
+/*
+*   Copyright (c) 2020, Masatake YAMATO
+*   Copyright (c) 2020, Red Hat, Inc.
+*
+*   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.
+*/
+
+#ifndef OPTSCRIPT_H
+#define OPTSCRIPT_H
+
+#include "general.h"
+
+#include "es.h"
+#include "mio.h"
+#include "ptrarray.h"
+
+typedef struct sOptVM OptVM;
+typedef EsObject* (* OptOperatorFn) (OptVM *, EsObject *);
+
+struct OptHelpExtender {
+	void        (* add)          (ptrArray *, void *);
+	const char* (* get_help_str) (EsObject *, void *);
+};
+
+int       opt_init (void);
+
+OptVM    *opt_vm_new          (MIO *in, MIO *out, MIO *err);
+void      opt_vm_delete       (OptVM *vm);
+
+EsObject *opt_vm_read         (OptVM *vm, MIO *in);
+EsObject *opt_vm_eval         (OptVM *vm, EsObject *obj);
+void      opt_vm_report_error (OptVM *vm, EsObject *eobj, MIO *err);
+
+void     *opt_vm_set_app_data (OptVM *vm, void *app_data);
+void     *opt_vm_get_app_data (OptVM *vm);
+
+char     *opt_vm_set_prompt   (OptVM *vm, char *prompt);
+void      opt_vm_print_prompt (OptVM *vm);
+
+int       opt_vm_help         (OptVM *vm, MIO *out,
+							   struct OptHelpExtender *extop, void *data);
+
+void      opt_vm_clear       (OptVM *vm);
+void      opt_vm_dstack_push (OptVM *vm, EsObject *dict);
+void      opt_vm_dstack_pop  (OptVM *vm);
+
+EsObject*  opt_vm_ostack_top  (OptVM *vm);
+EsObject*  opt_vm_ostack_peek  (OptVM *vm, int index_from_top);
+EsObject*  opt_vm_ostack_pop  (OptVM *vm);
+void       opt_vm_ostack_push (OptVM *vm, EsObject *obj);
+unsigned int opt_vm_ostack_count (OptVM *vm);
+
+EsObject *opt_dict_new       (unsigned int size);
+bool      opt_dict_known_and_get_cstr (EsObject *dict, const char* name, EsObject **val);
+bool      opt_dict_foreach   (EsObject *dict, bool (* fn) (EsObject *, EsObject *, void*), void *data);
+void      opt_dict_def       (EsObject *dict, EsObject *sym, EsObject *val);
+bool      opt_dict_undef     (EsObject *dict, EsObject *sym);
+void      opt_dict_clear     (EsObject *dict);
+
+EsObject *opt_array_new      (void);
+EsObject *opt_array_get      (const EsObject *array, unsigned int index);
+void      opt_array_put      (EsObject *array, unsigned int index, EsObject *obj);
+void      opt_array_add      (EsObject *array, EsObject *elt);
+
+unsigned int opt_array_length(const EsObject *array);
+
+EsObject *opt_operator_new   (OptOperatorFn op, const char *name, int arity, const char *help_str);
+
+EsObject *opt_string_new_from_cstr (const char *cstr);
+const char* opt_string_get_cstr (const EsObject *str);
+
+EsObject *opt_name_new_from_cstr (const char *cstr);
+const char* opt_name_get_cstr (const EsObject *name);
+
+extern EsObject *OPT_ERR_TYPECHECK;
+extern EsObject *OPT_ERR_QUIT;
+extern EsObject *OPT_ERR_RANGECHECK;
+extern EsObject *OPT_ERR_UNDERFLOW;
+
+extern int OPT_TYPE_ARRAY;
+extern int OPT_TYPE_DICT;
+extern int OPT_TYPE_OPERATOR;
+extern int OPT_TYPE_STRING;
+extern int OPT_TYPE_NAME;
+extern int OPT_TYPE_MARK;
+
+#endif


Modified: ctags/main/CommonPrelude.c
162 lines changed, 162 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,162 @@
+const char ctagsCommonPrelude []=
+"%\n"
+"% Copyright (c) 2021, Masatake YAMATO\n"
+"% Copyright (c) 2021, Red Hat, Inc.\n"
+"%\n"
+"% This source code is released for free distribution under the terms of the\n"
+"% GNU General Public License version 2 or (at your option) any later version.\n"
+"%\n"
+"\n"
+"%\n"
+"% The documentation table\n"
+"%\n"
+"\n"
+"% __PROCDOCS:dict<proc:name, doc:string>\n"
+"/__procdocs 30 dict def\n"
+"\n"
+"% name value __BDEF -\n"
+"/__bdef { bind def }  bind def\n"
+"\n"
+"% doc:string key:name any:val __DOCDEF -\n"
+"/__bddef {\n"
+"    1 index exch __bdef\n"
+"    exch __procdocs 3 1 roll put\n"
+"} __bdef\n"
+"\n"
+"\n"
+"%\n"
+"% procedures\n"
+"%\n"
+"(any n:int _NDUP any1 ... anyn)\n"
+"/_ndup { { dup } repeat } __bddef\n"
+"\n"
+"(x:any x:any _DEDUP x:any\n"
+" x:any y:any _DEDUP x:any y:any)\n"
+"/_dedup {\n"
+"    count 1 gt {\n"
+"        2 copy eq {\n"
+"            pop\n"
+"        } if\n"
+"    } if\n"
+"} __bddef\n"
+"\n"
+"(space:int space:int _DEDUP_SPACES space:int\n"
+" otherthanspace:int space:int _DEDUP_SPACES otherthanspace:int space:int)\n"
+"/_dedup_spaces {\n"
+"    count 0 gt {\n"
+"        dup ?\\_ eq {\n"
+"            _dedup\n"
+"        } if\n"
+"    } if\n"
+"} __bddef\n"
+"\n"
+"% 32 32 _dedup_spaces pstack clear (---) ==\n"
+"% 32 41 _dedup_spaces pstack clear (---) ==\n"
+"% 41 32 _dedup_spaces pstack clear (---) ==\n"
+"% 32 _dedup_spaces pstack clear (---) ==\n"
+"% 41 _dedup_spaces pstack clear (---) ==\n"
+"% quit\n"
+"\n"
+"/__buildstring {\n"
+"    {\n"
+"	    counttomark dup 1 eq {\n"
+"	        pop exch pop\n"
+"	        exit\n"
+"	    } {\n"
+"	        -1 roll 1 index exch _putlast!\n"
+"	    } ifelse\n"
+"    } loop\n"
+"} __bdef\n"
+"\n"
+"(mark char:int|substring:string... _BUILDSTRING string)\n"
+"/_buildstring {\n"
+"    0 string __buildstring\n"
+"} __bddef\n"
+"\n"
+"(string char:int|string _PUTLAST! -)\n"
+"/_putlast!  {\n"
+"    1 index length exch\n"
+"    dup type /integertype eq {\n"
+"	    put\n"
+"    } {\n"
+"	    putinterval\n"
+"    } ifelse\n"
+"} __bddef\n"
+"\n"
+"(target:string fromto:str _TR! -)\n"
+"/_tr! {\n"
+"    %\n"
+"    % () is not allowed.\n"
+"    % The reason must be be documented.\n"
+"    %\n"
+"    0 string\n"
+"    % str [int<from> int<to>] str'\n"
+"    2 index {\n"
+"	% str [int<from> int<to>] str' int<chr>\n"
+"	    dup 3 index 0 get\n"
+"	% str [int<from> int<to>] str' int<chr> int<chr> int<from>\n"
+"	    eq {% str [int<from> int<to>] str' int<chr>\n"
+"	        pop\n"
+"	        dup 2 index 1 get _putlast!\n"
+"	    } {% str [int<from> int<to>] str' int<chr>\n"
+"	        1 index exch _putlast!\n"
+"	    } ifelse\n"
+"    } forall\n"
+"    % str [int<from> int<to>] str'\n"
+"    exch pop\n"
+"    0 exch putinterval\n"
+"} __bddef\n"
+"\n"
+"(string _NORMALIZE_SPACES! -)\n"
+"/_normalize_spaces! {\n"
+"    dup\n"
+"    dup (\\n ) _tr!\n"
+"    dup (\\t ) _tr!\n"
+"    dup (\\r ) _tr!\n"
+"    dup (\\f ) _tr!\n"
+"    dup (\\v ) _tr!\n"
+"    mark exch { _dedup_spaces } forall _buildstring\n"
+"    exch copy pop\n"
+"} __bddef\n"
+"\n"
+"% /x mark 40 (a) 32 32 10 (b) 10 10 9 9 (xyz) 9 9 41 _buildstring def\n"
+"% x _normalize_spaces! x pstack\n"
+"\n"
+"(tag:int _SCOPEREF -)\n"
+"/_scoperef {\n"
+"    _scopetop not { 0 } if scope:\n"
+"} __bddef\n"
+"\n"
+"(tag:int _SCOPEPUSH -)\n"
+"/_scopepush {\n"
+"    dup _scoperef _scopeset\n"
+"} __bddef\n"
+"\n"
+"(string _ISSTRING string true\n"
+" any:!string _ISSTRING false)\n"
+"/_isstring {\n"
+"    dup type /stringtype eq {\n"
+"        true\n"
+"    } {\n"
+"        pop false\n"
+"    } ifelse\n"
+"} __bddef\n"
+"\n"
+"(array key _AMEMBER true|fales)\n"
+"/_amember {\n"
+"    false 3 1 roll\n"
+"    % false array key\n"
+"    exch {\n"
+"        % false key elt\n"
+"        1 index\n"
+"        % false key elt key\n"
+"        eq {\n"
+"            % false key\n"
+"            exch pop true exch\n"
+"            exit\n"
+"        } if\n"
+"        % false key\n"
+"    } forall\n"
+"    pop\n"
+"} __bddef\n"
+;


Modified: ctags/main/args.c
106 lines changed, 104 insertions(+), 2 deletions(-)
===================================================================
@@ -145,8 +145,8 @@ static char* nextFileLine (FILE* const fp)
 					c = ungetc (c, fp);
 			}
 			vStringStripTrailing (vs);
-			result = xMalloc (vStringLength (vs) + 1, char);
 			vStringStripLeading (vs);
+			result = xMalloc (vStringLength (vs) + 1, char);
 			strcpy (result, vStringValue (vs));
 		}
 		vStringDelete (vs);
@@ -161,18 +161,120 @@ static bool isCommentLine (char* line)
 	return (*line == '#');
 }
 
+static bool isOptscriptLine (char *line)
+{
+	size_t len = strlen (line);
+	if (len < 2)
+		return false;
+	if (line [len - 1] == '{' && line [len - 2] == '{')
+		return true;
+	return false;
+}
+
+static char* nextOptscriptLines (FILE* const fp, char *line)
+{
+	vString *vstr = vStringNewInit (line);
+	vStringPut (vstr, '\n');
+	eFree (line);
+
+	/* \n}}, \n=>1, }=>2, }=>3  */
+	int endMarkers = 0;
+	int c;
+	while (true)
+	{
+		c = fgetc (fp);
+		if (c == EOF)
+			break;
+
+		if (c == '\r' || c == '\n')
+		{
+			if (c == '\r')
+			{
+				c = fgetc (fp);
+				if (c != '\n')
+				{
+					ungetc(c, fp);
+					c = '\n';
+				}
+			}
+			if (c == '\n')
+			{
+				vStringPut (vstr, c);
+				if (endMarkers != 1)
+					endMarkers = 1;
+			}
+		}
+		else if (c == '}')
+		{
+			vStringPut (vstr, c);
+			if (endMarkers == 1 || endMarkers == 2)
+				endMarkers++;
+			if (endMarkers == 3)
+				break;
+		}
+		else
+		{
+			endMarkers = 0;
+			vStringPut (vstr, c);
+		}
+	}
+
+	if (c == EOF)
+	{
+		switch (endMarkers)
+		{
+		case 0:
+			vStringPut (vstr, '\n');
+			/* Fall through */
+		case 1:
+			vStringPut (vstr, '}');
+			/* Fall through */
+		case 2:
+			vStringPut (vstr, '}');
+		default:
+			break;
+		}
+	}
+
+	c = fgetc (fp);
+	while (c != EOF)
+	{
+		if (c == '\n')
+			break;
+		if (c == '\r')
+		{
+			c = fgetc (fp);
+			if (c == '\n')
+				break;
+			ungetc (c, fp);
+		}
+		c = fgetc (fp);
+	}
+	return vStringDeleteUnwrap (vstr);
+}
+
 static char* nextFileLineSkippingComments (FILE* const fp)
 {
 	char* result;
 	bool comment;
+	bool optscript;
 
 	do
 	{
 		result = nextFileLine (fp);
-		comment = (result && isCommentLine (result));
+		comment = false;
+		optscript = false;
+		if (result)
+		{
+			comment = isCommentLine (result);
+			optscript = isOptscriptLine (result);
+		}
 		if (comment)
 			eFree (result);
+		else if (optscript)
+			result = nextOptscriptLines (fp, result);
 	} while (comment);
+
 	return result;
 }
 


Modified: ctags/main/dependency.c
47 lines changed, 31 insertions(+), 16 deletions(-)
===================================================================
@@ -145,36 +145,38 @@ extern void notifyInputStart (void)
 {
 	subparser *s;
 
-	foreachSubparser(s, false)
-	{
-		langType lang = getSubparserLanguage (s);
-		notifyLanguageRegexInputStart (lang);
+	/* for running prelude of optlib */
+	langType lang = getInputLanguage ();
+	notifyLanguageRegexInputStart (lang);
 
+	foreachSubparser(s, true)
+	{
+		enterSubparser(s);
 		if (s->inputStart)
-		{
-			enterSubparser(s);
 			s->inputStart (s);
-			leaveSubparser();
-		}
+		/* propagate the event recursively */
+		notifyInputStart ();
+		leaveSubparser();
 	}
 }
 
 extern void notifyInputEnd   (void)
 {
 	subparser *s;
 
-	foreachSubparser(s, false)
+	foreachSubparser(s, true)
 	{
+		enterSubparser(s);
+		/* propagate the event recursively */
+		notifyInputEnd ();
 		if (s->inputEnd)
-		{
-			enterSubparser(s);
 			s->inputEnd (s);
-			leaveSubparser();
-		}
-
-		langType lang = getSubparserLanguage (s);
-		notifyLanguageRegexInputEnd (lang);
+		leaveSubparser();
 	}
+
+	/* for running sequel of optlib */
+	langType lang = getInputLanguage ();
+	notifyLanguageRegexInputEnd (lang);
 }
 
 extern void notifyMakeTagEntry (const tagEntryInfo *tag, int corkIndex)
@@ -292,6 +294,19 @@ extern slaveParser *getFirstSlaveParser (struct slaveControlBlock *scb)
 	return NULL;
 }
 
+extern subparser *getLanguageSubparser (langType sublang,
+										bool including_none_crafted_parser)
+{
+	subparser *s;
+
+	foreachSubparser (s, including_none_crafted_parser)
+	{
+		if (getSubparserLanguage (s) == sublang)
+			return s;
+	}
+	return NULL;
+}
+
 extern struct colprintTable * subparserColprintTableNew (void)
 {
 	return colprintTableNew ("L:NAME", "L:BASEPARSER", "L:DIRECTIONS", NULL);


Modified: ctags/main/entry.c
48 lines changed, 37 insertions(+), 11 deletions(-)
===================================================================
@@ -203,6 +203,9 @@ extern void makeFileTag (const char *const fileName)
 		tag.extensionFields.endLine = getInputLineNumber ();
 	}
 
+	if (isFieldEnabled (FIELD_EPOCH))
+		tag.extensionFields.epoch = getInputFileMtime ();
+
 	makeTagEntry (&tag);
 }
 
@@ -1066,8 +1069,6 @@ static tagEntryInfoX *copyTagEntry (const tagEntryInfo *const tag,
 	slot->name = eStrdup (slot->name);
 	if (slot->extensionFields.access)
 		slot->extensionFields.access = eStrdup (slot->extensionFields.access);
-	if (slot->extensionFields.fileScope)
-		slot->extensionFields.fileScope = eStrdup (slot->extensionFields.fileScope);
 	if (slot->extensionFields.implementation)
 		slot->extensionFields.implementation = eStrdup (slot->extensionFields.implementation);
 	if (slot->extensionFields.inheritance)
@@ -1144,8 +1145,6 @@ static void deleteTagEnry (void *data)
 
 	if (slot->extensionFields.access)
 		eFree ((char *)slot->extensionFields.access);
-	if (slot->extensionFields.fileScope)
-		eFree ((char *)slot->extensionFields.fileScope);
 	if (slot->extensionFields.implementation)
 		eFree ((char *)slot->extensionFields.implementation);
 	if (slot->extensionFields.inheritance)
@@ -1450,6 +1449,7 @@ static int queueTagEntry(const tagEntryInfo *const tag)
 
 	corkIndex = (int)ptrArrayAdd (TagFile.corkQueue, entry);
 	entry->corkIndex = corkIndex;
+	entry->slot.inCorkQueue = 1;
 
 	return corkIndex;
 }
@@ -1652,12 +1652,17 @@ extern size_t        countEntryInCorkQueue (void)
 	return ptrArrayCount (TagFile.corkQueue);
 }
 
+extern void markTagPlaceholder (tagEntryInfo *e, bool placeholder)
+{
+	e->placeholder = placeholder;
+}
+
 extern int makePlaceholder (const char *const name)
 {
 	tagEntryInfo e;
 
 	initTagEntry (&e, name, KIND_GHOST_INDEX);
-	e.placeholder = 1;
+	markTagPlaceholder(&e, true);
 
 	/*
 	 * makePlaceholder may be called even before reading any bytes
@@ -1766,6 +1771,13 @@ extern int makeQualifiedTagEntry (const tagEntryInfo *const e)
 	return r;
 }
 
+extern void setTagPositionFromTag (tagEntryInfo *const dst,
+								   const tagEntryInfo *const src)
+{
+		dst->lineNumber = src->lineNumber;
+		dst->filePosition = src->filePosition;
+}
+
 static void initTagEntryFull (tagEntryInfo *const e, const char *const name,
 			      unsigned long lineNumber,
 			      langType langType_,
@@ -1802,6 +1814,8 @@ static void initTagEntryFull (tagEntryInfo *const e, const char *const name,
 	if (roleBits)
 		markTagExtraBit (e, XTAG_REFERENCE_TAGS);
 
+	e->extensionFields.nth = NO_NTH_FIELD;
+
 	if (doesParserRunAsGuest ())
 		markTagExtraBit (e, XTAG_GUEST);
 	if (doesSubparserRun ())
@@ -1885,8 +1899,9 @@ static void    markTagExtraBitFull     (tagEntryInfo *const tag, xtagType extra,
 
 		int n = countXtags () - XTAG_COUNT;
 		tag->extraDynamic = xCalloc ((n / 8) + 1, uint8_t);
-		PARSER_TRASH_BOX(tag->extraDynamic, eFree);
-		markTagExtraBit (tag, extra);
+		if (!tag->inCorkQueue)
+			PARSER_TRASH_BOX(tag->extraDynamic, eFree);
+		markTagExtraBitFull (tag, extra, mark);
 		return;
 	}
 
@@ -1914,7 +1929,6 @@ extern bool isTagExtraBitMarked (const tagEntryInfo *const tag, xtagType extra)
 		index = (extra / 8);
 		offset = (extra % 8);
 		slot = tag->extra;
-
 	}
 	else if (!tag->extraDynamic)
 		return false;
@@ -1924,14 +1938,13 @@ extern bool isTagExtraBitMarked (const tagEntryInfo *const tag, xtagType extra)
 		index = ((extra - XTAG_COUNT) / 8);
 		offset = ((extra - XTAG_COUNT) % 8);
 		slot = tag->extraDynamic;
-
 	}
 	return !! ((slot [ index ]) & (1 << offset));
 }
 
 extern bool isTagExtra (const tagEntryInfo *const tag)
 {
-	for (unsigned int i = 0; i < XTAG_COUNT; i++)
+	for (unsigned int i = 0; i < countXtags(); i++)
 		if (isTagExtraBitMarked (tag, i))
 			return true;
 	return false;
@@ -2010,15 +2023,28 @@ extern void tagFilePosition (MIOPos *p)
 			   "failed to get file position of the tag file\n");
 }
 
-extern void setTagFilePosition (MIOPos *p)
+extern void setTagFilePosition (MIOPos *p, bool truncation)
 {
 	/* mini-geany doesn't set TagFile.mio. */
 	if 	(TagFile.mio == NULL)
 		return;
 
+
+	long t0 = 0;
+	if (truncation)
+		t0 = mio_tell (TagFile.mio);
+
 	if (mio_setpos (TagFile.mio, p) == -1)
 		error (FATAL|PERROR,
 			   "failed to set file position of the tag file\n");
+
+	if (truncation)
+	{
+		long t1 = mio_tell (TagFile.mio);
+		if (!mio_try_resize (TagFile.mio, (size_t)t1))
+			error (FATAL|PERROR,
+				   "failed to truncate the tag file %ld -> %ld\n", t0, t1);
+	}
 }
 
 extern const char* getTagFileDirectory (void)


Modified: ctags/main/entry.h
17 lines changed, 13 insertions(+), 4 deletions(-)
===================================================================
@@ -16,13 +16,16 @@
 #include "types.h"
 
 #include <stdint.h>
+#include <time.h>
 
 #include "field.h"
 #include "xtag.h"
 #include "mio.h"
 #include "ptrarray.h"
 #include "nestlevel.h"
 
+#include "script_p.h"
+
 /*
 *   MACROS
 */
@@ -45,13 +48,14 @@ struct sTagEntryInfo {
 	unsigned int isFileScope    :1;  /* is tag visible only within input file? */
 	unsigned int isFileEntry    :1;  /* is this just an entry for a file name? */
 	unsigned int truncateLineAfterTag :1;  /* truncate tag line at end of tag name? */
-	unsigned int placeholder    :1;	 /* This is just a part of scope context.
+	unsigned int placeholder    :1;	 /* is used only for keeping corkIndex based scope chain.
 					    Put this entry to cork queue but
 					    don't print it to tags file. */
 	unsigned int skipAutoFQEmission:1; /* If a parser makes a fq tag for the
 										  current tag by itself, set this. */
 	unsigned int isPseudoTag:1;	/* Used only in xref output.
 								   If a tag is a pseudo, set this. */
+	unsigned int inCorkQueue:1;
 
 	unsigned long lineNumber;     /* line number of tag */
 	const char* pattern;	      /* pattern for locating input line
@@ -67,7 +71,6 @@ struct sTagEntryInfo {
 
 	struct {
 		const char* access;
-		const char* fileScope;
 		const char* implementation;
 		const char* inheritance;
 
@@ -96,6 +99,9 @@ struct sTagEntryInfo {
 		const char* xpath;
 #endif
 		unsigned long endLine;
+		time_t epoch;
+#define NO_NTH_FIELD -1
+		short nth;
 	} extensionFields;  /* list of extension fields*/
 
 	/* `usedParserFields' tracks how many parser own fields are
@@ -141,6 +147,7 @@ extern bool isRoleAssigned(const tagEntryInfo *const e, int roleIndex);
 
 extern int makeQualifiedTagEntry (const tagEntryInfo *const e);
 
+extern void setTagPositionFromTag (tagEntryInfo *const dst, const tagEntryInfo *const src);
 
 #define CORK_NIL 0
 tagEntryInfo *getEntryInCorkQueue   (int n);
@@ -162,8 +169,9 @@ void          registerEntry (int corkIndex);
  * under the scope.
  *
  * If FUNC returns false, this function returns false.
- * If FUNC never returns false, this func returns true.
- * If FUNC is not called because no node for NAME in the symbol table.
+ * If FUNC never returns false, this function returns true.
+ * If FUNC is not called because no node for NAME in the symbol table,
+ * this function returns true.
  */
 bool          foreachEntriesInScope (int corkIndex,
 									 const char *name, /* or NULL */
@@ -256,6 +264,7 @@ extern void attachParserFieldToCorkEntry (int index, fieldType ftype, const char
 extern const char* getParserFieldValueForType (tagEntryInfo *const tag, fieldType ftype);
 
 extern int makePlaceholder (const char *const name);
+extern void markTagPlaceholder (tagEntryInfo *e, bool placeholder);
 
 /* Marking all tag entries entries under the scope specified
  * with index recursively.


Modified: ctags/main/entry_p.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -39,7 +39,7 @@ extern unsigned long numTagsTotal(void);
 extern unsigned long maxTagsLine(void);
 extern void invalidatePatternCache(void);
 extern void tagFilePosition (MIOPos *p);
-extern void setTagFilePosition (MIOPos *p);
+extern void setTagFilePosition (MIOPos *p, bool truncation);
 extern const char* getTagFileDirectory (void);
 extern void getTagScopeInformation (tagEntryInfo *const tag,
 				    const char **kind, const char **name);


Modified: ctags/main/error.c
8 lines changed, 7 insertions(+), 1 deletions(-)
===================================================================
@@ -35,7 +35,8 @@ extern bool stderrDefaultErrorPrinter (const errorSelection selection,
 					  va_list ap, void *data CTAGS_ATTR_UNUSED)
 {
 	fprintf (stderr, "%s: %s", getExecutableName (),
-		 selected (selection, WARNING) ? "Warning: " : "");
+		 selected (selection, WARNING) ? "Warning: " :
+		 selected (selection, NOTICE) ? "Notice: " : "");
 	vfprintf (stderr, format, ap);
 	if (selected (selection, PERROR))
 	{
@@ -56,6 +57,9 @@ extern void error (const errorSelection selection,
 	va_list ap;
 	bool shouldExit;
 
+	if (Option.quiet && selected (selection, NOTICE))
+		return;
+
 	va_start (ap, format);
 	shouldExit = (* errorPrinter) (selection, format, ap, errorPrinterData);
 	va_end (ap);
@@ -77,6 +81,8 @@ bool jsonErrorPrinter (const errorSelection selection, const char *const format,
 	json_t *response = json_object ();
 	json_object_set_new (response, "_type", json_string ("error"));
 	json_object_set_new (response, "message", json_string (reason));
+	if (selected (selection, NOTICE))
+		json_object_set_new (response, "notice", json_true ());
 	if (selected (selection, WARNING))
 		json_object_set_new (response, "warning", json_true ());
 	if (selected (selection, FATAL))


Modified: ctags/main/field.c
1036 lines changed, 846 insertions(+), 190 deletions(-)
===================================================================
@@ -31,6 +31,8 @@
 #include "writer_p.h"
 #include "xtag_p.h"
 
+#include "optscript.h"
+
 #define FIELD_NULL_LETTER_CHAR '-'
 #define FIELD_NULL_LETTER_STRING "-"
 
@@ -67,13 +69,14 @@ static const char *renderFieldExtras (const tagEntryInfo *const tag, const char
 static const char *renderFieldXpath (const tagEntryInfo *const tag, const char *value, vString* b);
 static const char *renderFieldScopeKindName(const tagEntryInfo *const tag, const char *value, vString* b);
 static const char *renderFieldEnd (const tagEntryInfo *const tag, const char *value, vString* b);
+static const char *renderFieldEpoch (const tagEntryInfo *const tag, const char *value, vString* b);
+static const char *renderFieldNth (const tagEntryInfo *const tag, const char *value, vString* b);
 
 static bool doesContainAnyCharInName (const tagEntryInfo *const tag, const char *value, const char *chars);
 static bool doesContainAnyCharInInput (const tagEntryInfo *const tag, const char*value, const char *chars);
 static bool doesContainAnyCharInFieldScope (const tagEntryInfo *const tag, const char *value, const char *chars);
 static bool doesContainAnyCharInSignature (const tagEntryInfo *const tag, const char *value, const char *chars);
 
-static bool     isLanguageFieldAvailable  (const tagEntryInfo *const tag);
 static bool     isTyperefFieldAvailable   (const tagEntryInfo *const tag);
 static bool     isFileFieldAvailable      (const tagEntryInfo *const tag);
 static bool     isInheritsFieldAvailable  (const tagEntryInfo *const tag);
@@ -83,150 +86,372 @@ static bool     isSignatureFieldAvailable (const tagEntryInfo *const tag);
 static bool     isExtrasFieldAvailable    (const tagEntryInfo *const tag);
 static bool     isXpathFieldAvailable     (const tagEntryInfo *const tag);
 static bool     isEndFieldAvailable       (const tagEntryInfo *const tag);
-
-
-#define DEFINE_FIELD(L, N, V, H, DT, RE)				\
-	DEFINE_FIELD_FULL (L, N, V, H, NULL, DT, RE, NULL, NULL)
-#define DEFINE_FIELD_FULL(L, N, V, H, A, DT, RE, RN, DCAC)	\
-	{					\
-		.letter        = L,		\
-		.name          = N,		\
-		.description   = H,		\
-		.enabled       = V,		\
-		.render        = RE,		\
-		.renderNoEscaping= RN,		\
-		.doesContainAnyChar = DCAC, \
-		.isValueAvailable = A,		\
-		.dataType = DT, \
-	}
+static bool     isEpochAvailable          (const tagEntryInfo *const tag);
+static bool     isNthAvailable            (const tagEntryInfo *const tag);
+
+static EsObject* getFieldValueForName (const tagEntryInfo *, const fieldDefinition *);
+static EsObject* setFieldValueForName (tagEntryInfo *, const fieldDefinition *, const EsObject *);
+static EsObject* getFieldValueForInput (const tagEntryInfo *, const fieldDefinition *);
+static EsObject* getFieldValueForKind (const tagEntryInfo *, const fieldDefinition *);
+static EsObject* getFieldValueForTyperef (const tagEntryInfo *, const fieldDefinition *);
+static EsObject* setFieldValueForTyperef (tagEntryInfo *, const fieldDefinition *, const EsObject *);
+static EsObject* checkFieldValueForTyperef (const fieldDefinition *, const EsObject *);
+static EsObject* getFieldValueForScope (const tagEntryInfo *, const fieldDefinition *);
+static EsObject* setFieldValueForScope (tagEntryInfo *, const fieldDefinition *, const EsObject *);
+static EsObject* checkFieldValueForScope (const fieldDefinition *, const EsObject *);
+static EsObject* getFieldValueForExtras (const tagEntryInfo *, const fieldDefinition *);
+static EsObject* getFieldValueForSignature (const tagEntryInfo *, const fieldDefinition *);
+static EsObject* setFieldValueForSignature (tagEntryInfo *, const fieldDefinition *, const EsObject *);
+static EsObject* getFieldValueForRoles (const tagEntryInfo *, const fieldDefinition *);
+static EsObject* getFieldValueForLineCommon (const tagEntryInfo *, const fieldDefinition *);
+static EsObject* checkFieldValueForLineCommon (const fieldDefinition *, const EsObject *);
+static EsObject* setFieldValueForLineCommon (tagEntryInfo *, const fieldDefinition *, const EsObject *);
+static EsObject* setFieldValueForInherits (tagEntryInfo *, const fieldDefinition *, const EsObject *);
 
 #define WITH_DEFUALT_VALUE(str) ((str)?(str):FIELD_NULL_LETTER_STRING)
 
 static fieldDefinition fieldDefinitionsFixed [] = {
-        /* FIXED FIELDS */
-	DEFINE_FIELD_FULL ('N', "name",     true,
-			  "tag name",
-			  NULL,
-			  FIELDTYPE_STRING,
-			  renderFieldName, renderFieldNameNoEscape,
-			  doesContainAnyCharInName),
-	DEFINE_FIELD_FULL ('F', "input",    true,
-			   "input file",
-			   NULL,
-			   FIELDTYPE_STRING,
-			   renderFieldInput, renderFieldInputNoEscape,
-			   doesContainAnyCharInInput),
-	DEFINE_FIELD ('P', "pattern",  true,
-			   "pattern",
-			   FIELDTYPE_STRING|FIELDTYPE_BOOL,
-			   renderFieldPattern),
+	[FIELD_NAME] = {
+		.letter             = 'N',
+		.name               = "name",
+		.description        = "tag name",
+		.enabled            = true,
+		.render             = renderFieldName,
+		.renderNoEscaping   = renderFieldNameNoEscape,
+		.doesContainAnyChar = doesContainAnyCharInName,
+		.isValueAvailable   = NULL,
+		.dataType           = FIELDTYPE_STRING,
+		.getterValueType    = NULL,
+		.getValueObject     = getFieldValueForName,
+		.setterValueType    = NULL,
+		.checkValueForSetter= NULL,
+		.setValueObject     = setFieldValueForName,
+	},
+	[FIELD_INPUT_FILE] = {
+		.letter             = 'F',
+		.name               = "input",
+		.description        = "input file",
+		.enabled            = true,
+		.render             = renderFieldInput,
+		.renderNoEscaping   = renderFieldInputNoEscape,
+		.doesContainAnyChar = doesContainAnyCharInInput,
+		.isValueAvailable   = NULL,
+		.dataType           = FIELDTYPE_STRING,
+		.getterValueType    = NULL,
+		.getValueObject     = getFieldValueForInput,
+		.setterValueType    = NULL,
+		.checkValueForSetter= NULL,
+		.setValueObject     = NULL,
+	},
+	[FIELD_PATTERN] = {
+		.letter             = 'P',
+		.name               = "pattern",
+		.description        = "pattern",
+		.enabled            = true,
+		.render             = renderFieldPattern,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = NULL,
+		.dataType           = FIELDTYPE_STRING|FIELDTYPE_BOOL,
+	},
 };
 
 static fieldDefinition fieldDefinitionsExuberant [] = {
-	DEFINE_FIELD ('C', "compact",        false,
-			   "compact input line (used only in xref output)",
-			   FIELDTYPE_STRING,
-			   renderFieldCompactInputLine),
-
-	/* EXTENSION FIELDS */
-	DEFINE_FIELD_FULL ('a', "access",         false,
-		      "Access (or export) of class members",
-			  isAccessFieldAvailable,
-			  FIELDTYPE_STRING,
-		      renderFieldAccess, NULL, NULL),
-	DEFINE_FIELD_FULL ('f', "file",           true,
-		      "File-restricted scoping",
-			  isFileFieldAvailable,
-			  FIELDTYPE_BOOL,
-		      renderFieldFile, NULL, NULL),
-	DEFINE_FIELD_FULL ('i', "inherits",       false,
-		      "Inheritance information",
-			  isInheritsFieldAvailable,
-			  FIELDTYPE_STRING|FIELDTYPE_BOOL,
-		      renderFieldInherits, NULL, NULL),
-	DEFINE_FIELD ('K', NULL,             false,
-		      "Kind of tag in long-name form",
-		      FIELDTYPE_STRING,
-		      renderFieldKindName),
-	DEFINE_FIELD ('k', NULL,             true,
-			   "Kind of tag in one-letter form",
-			   FIELDTYPE_STRING,
-			   renderFieldKindLetter),
-	DEFINE_FIELD_FULL ('l', "language",       false,
-			   "Language of input file containing tag",
-			   isLanguageFieldAvailable,
-			   FIELDTYPE_STRING,
-			   renderFieldLanguage, NULL, NULL),
-	DEFINE_FIELD_FULL ('m', "implementation", false,
-			   "Implementation information",
-			   isImplementationFieldAvailable,
-			   FIELDTYPE_STRING,
-			   renderFieldImplementation, NULL, NULL),
-	DEFINE_FIELD ('n', "line",           false,
-			   "Line number of tag definition",
-			   FIELDTYPE_INTEGER,
-			   renderFieldLineNumber),
-	DEFINE_FIELD_FULL ('S', "signature",     false,
-			   "Signature of routine (e.g. prototype or parameter list)",
-			   isSignatureFieldAvailable,
-			   FIELDTYPE_STRING,
-			   renderFieldSignature, renderFieldSignatureNoEscape,
-			   doesContainAnyCharInSignature),
-	DEFINE_FIELD_FULL ('s', NULL,             true,
-			   "[tags output] scope (kind:name) of tag definition, [xref and json output] name of scope",
-			   NULL,
-			   FIELDTYPE_STRING,
-			   renderFieldScope, renderFieldScopeNoEscape,
-			   doesContainAnyCharInFieldScope),
-	DEFINE_FIELD_FULL ('t', "typeref",        true,
-			   "Type and name of a variable or typedef",
-			   isTyperefFieldAvailable,
-			   FIELDTYPE_STRING,
-			   renderFieldTyperef, NULL, NULL),
-	DEFINE_FIELD ('z', "kind",           false,
-			   "[tags output] prepend \"kind:\" to k/ (or K/) field output, [xref and json output] kind in long-name form",
-			   FIELDTYPE_STRING,
-			   /* Following renderer is for handling --_xformat=%{kind};
-			      and is not for tags output. */
-			   renderFieldKindName),
+	[FIELD_COMPACT_INPUT_LINE - FIELD_ECTAGS_START] = {
+		.letter             = 'C',
+		.name               = "compact",
+		.description        = "compact input line (used only in xref output)",
+		.enabled            = false,
+		.render             = renderFieldCompactInputLine,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = NULL,
+		.dataType           = FIELDTYPE_STRING,
+	},
+	[FIELD_FILE_SCOPE - FIELD_ECTAGS_START] = {
+		.letter             = 'f',
+		.name               = "file",
+		.description        = "File-restricted scoping",
+		.enabled            = true,
+		.render             = renderFieldFile,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = isFileFieldAvailable,
+		.dataType           = FIELDTYPE_BOOL,
+	},
+	[FIELD_KIND_LONG - FIELD_ECTAGS_START] = {
+		.letter             = 'K',
+		.name               = NULL,
+		.description        = "Kind of tag in long-name form",
+		.enabled            = false,
+		.render             = renderFieldKindName,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = NULL,
+		.dataType           = FIELDTYPE_STRING,
+	},
+	[FIELD_KIND - FIELD_ECTAGS_START] = {
+		.letter             ='k',
+		.name               = NULL,
+		.description        = "Kind of tag in one-letter form",
+		.enabled            = true,
+		.render             = renderFieldKindLetter,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = NULL,
+		.dataType           = FIELDTYPE_STRING,
+	},
+	[FIELD_LANGUAGE - FIELD_ECTAGS_START] = {
+		.letter             = 'l',
+		.name               = "language",
+		.description        = "Language of input file containing tag",
+		.enabled            = false,
+		.render             = renderFieldLanguage,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.dataType           = FIELDTYPE_STRING,
+	},
+	[FIELD_LINE_NUMBER - FIELD_ECTAGS_START] = {
+		.letter             = 'n',
+		.name               = "line",
+		.description        = "Line number of tag definition",
+		.enabled            = false,
+		.render             = renderFieldLineNumber,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = NULL,
+		.dataType           = FIELDTYPE_INTEGER,
+		.getterValueType    = "int",
+		.getValueObject     = getFieldValueForLineCommon,
+		.setterValueType    = "matchlok|int",
+		.checkValueForSetter= checkFieldValueForLineCommon,
+		.setValueObject     = setFieldValueForLineCommon,
+	},
+	[FIELD_SCOPE - FIELD_ECTAGS_START] = {
+		.letter				= 's',
+		.name				= NULL,
+		.description		= "[tags output] scope (kind:name) of tag definition, [xref and json output] name of scope",
+		.enabled			= true,
+		.render				= renderFieldScope,
+		.renderNoEscaping	= renderFieldScopeNoEscape,
+		.doesContainAnyChar = doesContainAnyCharInFieldScope,
+		.isValueAvailable	= NULL,
+		.dataType			= FIELDTYPE_STRING,
+	},
+	[FIELD_TYPE_REF - FIELD_ECTAGS_START] = {
+		.letter				= 't',
+		.name				= "typeref",
+		.description		= "Type and name of a variable or typedef",
+		.enabled			= true,
+		.render				= renderFieldTyperef,
+		.renderNoEscaping	= NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable	= isTyperefFieldAvailable,
+		.dataType			= FIELDTYPE_STRING,
+		.getterValueType    = "[string string]",
+		.getValueObject     = getFieldValueForTyperef,
+		.setterValueType    = "[string string]|string|index:int|false",
+		.checkValueForSetter= checkFieldValueForTyperef,
+		.setValueObject     = setFieldValueForTyperef,
+	},
+	[FIELD_KIND_KEY - FIELD_ECTAGS_START] = {
+		.letter				= 'z',
+		.name				= "kind",
+		.description		= "[tags output] prepend \"kind:\" to k/ (or K/) field output, [xref and json output] kind in long-name form",
+		.enabled			= false,
+		/* Following renderer is for handling --_xformat=%{kind};
+		   and is not for tags output. */
+		.render				= renderFieldKindName,
+		.renderNoEscaping	= NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable	= NULL,
+		.dataType			= FIELDTYPE_STRING,
+		.getterValueType    = "name",
+		.getValueObject     = getFieldValueForKind,
+		.setterValueType    = NULL,
+		.checkValueForSetter= NULL,
+		.setValueObject     = NULL,
+	},
+	[FIELD_INHERITANCE - FIELD_ECTAGS_START] = {
+		.letter             = 'i',
+		.name               = "inherits",
+		.description        = "Inheritance information",
+		.enabled            = false,
+		.render             = renderFieldInherits,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = isInheritsFieldAvailable,
+		.dataType           = FIELDTYPE_STRING|FIELDTYPE_BOOL,
+		.getterValueType    = NULL,
+		.getValueObject     = NULL,
+		.setterValueType    = NULL,
+		.checkValueForSetter= NULL,
+		.setValueObject     = setFieldValueForInherits,
+	},
+	[FIELD_ACCESS - FIELD_ECTAGS_START] = {
+		.letter             = 'a',
+		.name               = "access",
+		.description        = "Access (or export) of class members",
+		.enabled            = false,
+		.render             = renderFieldAccess,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = isAccessFieldAvailable,
+		.dataType           = FIELDTYPE_STRING,
+	},
+	[FIELD_IMPLEMENTATION - FIELD_ECTAGS_START] = {
+		.letter             = 'm',
+		.name               = "implementation",
+		.description        = "Implementation information",
+		.enabled            = false,
+		.render             = renderFieldImplementation,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = isImplementationFieldAvailable,
+		.dataType           = FIELDTYPE_STRING,
+
+	},
+	[FIELD_SIGNATURE - FIELD_ECTAGS_START] = {
+		.letter				= 'S',
+		.name				= "signature",
+		.description		= "Signature of routine (e.g. prototype or parameter list)",
+		.enabled			= false,
+		.render				= renderFieldSignature,
+		.renderNoEscaping	= renderFieldSignatureNoEscape,
+		.doesContainAnyChar = doesContainAnyCharInSignature,
+		.isValueAvailable	= isSignatureFieldAvailable,
+		.dataType			= FIELDTYPE_STRING,
+		.getterValueType    = NULL,
+		.getValueObject     = getFieldValueForSignature,
+		.setterValueType    = NULL,
+		.checkValueForSetter= NULL,
+		.setValueObject     = setFieldValueForSignature,
+	},
 };
 
 static fieldDefinition fieldDefinitionsUniversal [] = {
-	DEFINE_FIELD ('r', "roles",    false,
-			   "Roles",
-			   FIELDTYPE_STRING,
-			   renderFieldRoles),
-	DEFINE_FIELD ('R',  NULL,     false,
-			   "Marker (R or D) representing whether tag is definition or reference",
-			   FIELDTYPE_STRING,
-			   renderFieldRefMarker),
-	DEFINE_FIELD_FULL ('Z', "scope",   false,
-			  "[tags output] prepend \"scope:\" key to s/scope field output, [xref and json output] the same as s/ field",
-			   NULL,
-			   FIELDTYPE_STRING,
-			   /* Following renderer is for handling --_xformat=%{scope};
-			      and is not for tags output. */
-			   renderFieldScope, renderFieldScopeNoEscape,
-			   doesContainAnyCharInFieldScope),
-	DEFINE_FIELD_FULL ('E', "extras",   false,
-			   "Extra tag type information",
-			   isExtrasFieldAvailable,
-			   FIELDTYPE_STRING,
-			   renderFieldExtras, NULL, NULL),
-	DEFINE_FIELD_FULL ('x', "xpath",   false,
-			   "xpath for the tag",
-			   isXpathFieldAvailable,
-			   FIELDTYPE_STRING,
-			   renderFieldXpath, NULL, NULL),
-	DEFINE_FIELD ('p', "scopeKind", false,
-			   "[tags output] no effect, [xref and json output] kind of scope in long-name form",
-			   FIELDTYPE_STRING,
-			   renderFieldScopeKindName),
-	DEFINE_FIELD_FULL ('e', "end", false,
-			   "end lines of various items",
-			   isEndFieldAvailable,
-			   FIELDTYPE_INTEGER,
-			   renderFieldEnd, NULL, NULL),
+	[FIELD_REF_MARK - FIELDS_UCTAGS_START] = {
+		.letter             = 'R',
+		.name				= NULL,
+		.description		= "Marker (R or D) representing whether tag is definition or reference",
+		.enabled			= false,
+		.render				= renderFieldRefMarker,
+		.renderNoEscaping	= NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable	= NULL,
+		.dataType			= FIELDTYPE_STRING,
+	},
+	[FIELD_SCOPE_KEY - FIELDS_UCTAGS_START] = {
+		.letter             = 'Z',
+		.name               = "scope",
+		.description        = "[tags output] prepend \"scope:\" key to s/scope field output, [xref and json output] the same as s/ field",
+		.enabled            = false,
+		/* Following renderer is for handling --_xformat=%{scope};
+		   and is not for tags output. */
+		.render             = renderFieldScope,
+		.renderNoEscaping   = renderFieldScopeNoEscape,
+		.doesContainAnyChar = doesContainAnyCharInFieldScope,
+		.isValueAvailable   = NULL,
+		.dataType           = FIELDTYPE_STRING,
+		.getterValueType    = "int",
+		.getValueObject     = getFieldValueForScope,
+		.setterValueType    = "int",
+		.checkValueForSetter= checkFieldValueForScope,
+		.setValueObject     = setFieldValueForScope,
+	},
+	[FIELD_SCOPE_KIND_LONG - FIELDS_UCTAGS_START] = {
+		.letter				= 'p',
+		.name				= "scopeKind",
+		.description		= "[tags output] no effect, [xref and json output] kind of scope in long-name form",
+		.enabled			= false,
+		.render				= renderFieldScopeKindName,
+		.renderNoEscaping	= NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable	= NULL,
+		.dataType			= FIELDTYPE_STRING,
+	},
+	[FIELD_ROLES - FIELDS_UCTAGS_START] = {
+		.letter             = 'r',
+		.name               = "roles",
+		.description        = "Roles",
+		.enabled            = false,
+		.render             = renderFieldRoles,
+		.renderNoEscaping   = NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable   = NULL,
+		.dataType           = FIELDTYPE_STRING,
+		.getterValueType    = "[ role1:name ... rolen:name ]",
+		.getValueObject     = getFieldValueForRoles,
+		.setterValueType    = NULL,
+		.checkValueForSetter= NULL,
+		.setValueObject     = NULL,
+	},
+	[FIELD_EXTRAS - FIELDS_UCTAGS_START] = {
+		.letter				= 'E',
+		.name				= "extras",
+		.description		= "Extra tag type information",
+		.enabled			= false,
+		.render				= renderFieldExtras,
+		.renderNoEscaping	= NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable	= isExtrasFieldAvailable,
+		.dataType			= FIELDTYPE_STRING,
+		.getterValueType    = "[ extra1:name ... extran:name ]",
+		.getValueObject     = getFieldValueForExtras,
+		.setterValueType    = NULL,
+		.checkValueForSetter= NULL,
+		.setValueObject     = NULL,
+	},
+	[FIELD_XPATH - FIELDS_UCTAGS_START] = {
+		.letter				= 'x',
+		.name				= "xpath",
+		.description		= "xpath for the tag",
+		.enabled			= false,
+		.render				= renderFieldXpath,
+		.renderNoEscaping	= NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable	= isXpathFieldAvailable,
+		.dataType			= FIELDTYPE_STRING,
+	},
+	[FIELD_END_LINE - FIELDS_UCTAGS_START] = {
+		.letter				= 'e',
+		.name				= "end",
+		.description		= "end lines of various items",
+		.enabled			= false,
+		.render				= renderFieldEnd,
+		.renderNoEscaping	= NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable	= isEndFieldAvailable,
+		.dataType			= FIELDTYPE_INTEGER,
+		.getterValueType    = "int",
+		.getValueObject     = getFieldValueForLineCommon,
+		.setterValueType    = "matchlok|int",
+		.checkValueForSetter= checkFieldValueForLineCommon,
+		.setValueObject     = setFieldValueForLineCommon,
+
+	},
+	[FIELD_EPOCH - FIELDS_UCTAGS_START] = {
+		.letter				= 'T',
+		.name				= "epoch",
+		.description		= "the last modified time of the input file (only for F/file kind tag)",
+		.enabled			= true,
+		.render				= renderFieldEpoch,
+		.renderNoEscaping	= NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable	= isEpochAvailable,
+		.dataType			= FIELDTYPE_INTEGER,
+	},
+	[FIELD_NTH - FIELDS_UCTAGS_START] = {
+		.letter				= 'o',
+		.name				= "nth",
+		.description		= "the order in the parent scope",
+		.enabled			= false,
+		.render				= renderFieldNth,
+		.renderNoEscaping	= NULL,
+		.doesContainAnyChar = NULL,
+		.isValueAvailable	= isNthAvailable,
+		.dataType			= FIELDTYPE_INTEGER,
+	},
 };
 
 
@@ -258,6 +483,7 @@ extern void initFieldObjects (void)
 		fobj->nameWithPrefix = fobj->def->name;
 		fobj->language = LANG_IGNORE;
 		fobj->sibling  = FIELD_UNKNOWN;
+		fobj->def->ftype = i + fieldObjectUsed;
 	}
 	fieldObjectUsed += ARRAY_SIZE (fieldDefinitionsFixed);
 
@@ -269,6 +495,7 @@ extern void initFieldObjects (void)
 		fobj->nameWithPrefix = fobj->def->name;
 		fobj->language = LANG_IGNORE;
 		fobj->sibling  = FIELD_UNKNOWN;
+		fobj->def->ftype = i + fieldObjectUsed;
 	}
 	fieldObjectUsed += ARRAY_SIZE (fieldDefinitionsExuberant);
 
@@ -293,6 +520,7 @@ extern void initFieldObjects (void)
 			fobj->nameWithPrefix = NULL;
 		fobj->language = LANG_IGNORE;
 		fobj->sibling  = FIELD_UNKNOWN;
+		fobj->def->ftype = i + fieldObjectUsed;
 	}
 	fieldObjectUsed += ARRAY_SIZE (fieldDefinitionsUniversal);
 
@@ -704,32 +932,51 @@ static const char *renderFieldLineNumber (const tagEntryInfo *const tag,
 	return vStringValue (b);
 }
 
-static const char *renderFieldRoles (const tagEntryInfo *const tag,
-				    const char *value CTAGS_ATTR_UNUSED,
-				    vString* b)
+struct renderRoleData {
+	vString* b;
+	int nRoleWritten;
+};
+
+static void renderRoleByIndex (const tagEntryInfo *const tag, int roleIndex, void *data)
+{
+	struct renderRoleData *rdata = data;
+
+	if (!isLanguageRoleEnabled (tag->langType, tag->kindIndex, roleIndex))
+		return;
+
+	if (rdata->nRoleWritten > 0)
+		vStringPut(rdata->b, ',');
+
+	const roleDefinition * role = getTagRole(tag, roleIndex);
+	renderRole (role, rdata->b);
+	rdata->nRoleWritten++;
+}
+
+static roleBitsType foreachRoleBits (const tagEntryInfo *const tag,
+									 void (* fn) (const tagEntryInfo *const, int, void *),
+									 void *data)
 {
 	roleBitsType rbits = tag->extensionFields.roleBits;
-	const roleDefinition * role;
-	if (rbits)
-	{
-		int roleCount = countLanguageRoles (tag->langType, tag->kindIndex);
-		int nRoleWritten = 0;
+	if (!rbits)
+		return rbits;
 
-		for (int roleIndex = 0; roleIndex < roleCount; roleIndex++)
-		{
-			if (((rbits >> roleIndex) & (roleBitsType)1)
-				&& isLanguageRoleEnabled (tag->langType, tag->kindIndex, roleIndex))
-			{
-				if (nRoleWritten > 0)
-					vStringPut(b, ',');
+	int roleCount = countLanguageRoles (tag->langType, tag->kindIndex);
 
-				role = getTagRole(tag, roleIndex);
-				renderRole (role, b);
-				nRoleWritten++;
-			}
-		}
+	for (int roleIndex = 0; roleIndex < roleCount; roleIndex++)
+	{
+		if ((rbits >> roleIndex) & (roleBitsType)1)
+			fn (tag, roleIndex, data);
 	}
-	else
+	return rbits;
+}
+
+static const char *renderFieldRoles (const tagEntryInfo *const tag,
+				    const char *value CTAGS_ATTR_UNUSED,
+				    vString* b)
+{
+	struct renderRoleData data = { .b = b, .nRoleWritten = 0 };
+
+	if (!foreachRoleBits (tag, renderRoleByIndex, &data))
 		vStringCatS (b, ROLE_DEFINITION_NAME);
 	return vStringValue (b);
 }
@@ -743,7 +990,10 @@ static const char *renderFieldLanguage (const tagEntryInfo *const tag,
 	if (Option.lineDirectives && (tag->sourceLangType != LANG_IGNORE))
 		l = getLanguageName(tag->sourceLangType);
 	else
+	{
+		Assert (tag->langType != LANG_IGNORE);
 		l = getLanguageName(tag->langType);
+	}
 
 	return renderAsIs (b, WITH_DEFUALT_VALUE(l));
 }
@@ -878,9 +1128,31 @@ static const char *renderFieldEnd (const tagEntryInfo *const tag,
 		return NULL;
 }
 
-static bool     isLanguageFieldAvailable (const tagEntryInfo *const tag)
+static const char *renderFieldEpoch (const tagEntryInfo *const tag,
+									  const char *value, vString* b)
 {
-	return (tag->langType == LANG_IGNORE)? false: true;
+#define buf_len 21
+	static char buf[buf_len];
+
+	if (snprintf (buf, buf_len, "%lld", (long long)tag->extensionFields.epoch) > 0)
+		return renderAsIs (b, buf);
+	else
+		return NULL;
+#undef buf_len
+}
+
+static const char *renderFieldNth (const tagEntryInfo *const tag,
+								   const char *value, vString* b)
+{
+#define buf_len 12
+	static char buf[buf_len];
+
+	if (tag->extensionFields.nth > NO_NTH_FIELD
+		&& snprintf (buf, buf_len, "%d", (int)tag->extensionFields.nth) > 0)
+		return renderAsIs (b, buf);
+	else
+		return NULL;
+#undef buf_len
 }
 
 static bool     isTyperefFieldAvailable  (const tagEntryInfo *const tag)
@@ -917,13 +1189,12 @@ static bool     isSignatureFieldAvailable (const tagEntryInfo *const tag)
 static bool     isExtrasFieldAvailable     (const tagEntryInfo *const tag)
 {
 	unsigned int i;
+
+	if (tag->extraDynamic)
+		return true;
 	for (i = 0; i < sizeof (tag->extra); i++)
-	{
 		if (tag->extra [i])
 			return true;
-		else if (tag->extraDynamic)
-			return true;
-	}
 
 	return false;
 }
@@ -942,46 +1213,39 @@ static bool     isEndFieldAvailable       (const tagEntryInfo *const tag)
 	return (tag->extensionFields.endLine != 0)? true: false;
 }
 
+static bool isEpochAvailable (const tagEntryInfo *const tag)
+{
+	return (tag->kindIndex == KIND_FILE_INDEX)
+		? true
+		: false;
+}
+
+static bool isNthAvailable (const tagEntryInfo *const tag)
+{
+	Assert (tag->langType >= NO_NTH_FIELD);
+	return (tag->extensionFields.nth != NO_NTH_FIELD)? true: false;
+}
+
 extern bool isFieldEnabled (fieldType type)
 {
 	return getFieldObject(type)->def->enabled;
 }
 
-extern bool enableField (fieldType type, bool state, bool warnIfFixedField)
+extern bool enableField (fieldType type, bool state)
 {
 	fieldDefinition *def = getFieldObject(type)->def;
 	bool old = def->enabled;
-	if (writerDoesTreatFieldAsFixed (type))
-	{
-		if ((!state) && warnIfFixedField)
-		{
-			if (def->name && def->letter != NUL_FIELD_LETTER)
-				error(WARNING, "Cannot disable fixed field: '%c'{%s}",
-				      def->letter, def->name);
-			else if (def->name)
-				error(WARNING, "Cannot disable fixed field: {%s}",
-				      def->name);
-			else if (def->letter != NUL_FIELD_LETTER)
-				error(WARNING, "Cannot disable fixed field: '%c'",
-				      getFieldObject(type)->def->letter);
-			else
-				AssertNotReached();
-		}
-	}
-	else
-	{
-		getFieldObject(type)->def->enabled = state;
+	getFieldObject(type)->def->enabled = state;
 
-		if (isCommonField (type))
-			verbose ("enable field \"%s\": %s\n",
+	if (isCommonField (type))
+		verbose ("enable field \"%s\": %s\n",
 				 getFieldObject(type)->def->name,
 				 (state? "yes": "no"));
-		else
-			verbose ("enable field \"%s\"<%s>: %s\n",
+	else
+		verbose ("enable field \"%s\"<%s>: %s\n",
 				 getFieldObject(type)->def->name,
 				 getLanguageName (getFieldOwner(type)),
 				 (state? "yes": "no"));
-	}
 	return old;
 }
 
@@ -1000,6 +1264,11 @@ extern unsigned int getFieldDataType (fieldType type)
 	return getFieldObject(type)->def->dataType;
 }
 
+extern bool isFieldValueAvailableAlways (fieldType type)
+{
+	return getFieldObject(type)->def->isValueAvailable == NULL;
+}
+
 extern bool doesFieldHaveRenderer (fieldType type, bool noEscaping)
 {
 	if (noEscaping)
@@ -1101,11 +1370,14 @@ extern int defineField (fieldDefinition *def, langType language)
 #define FIELD_COL_LANGUAGE    3
 #define FIELD_COL_JSTYPE      4
 #define FIELD_COL_FIXED       5
-#define FIELD_COL_DESCRIPTION 6
+#define FIELD_COL_OPERATOR    6
+#define FIELD_COL_DESCRIPTION 7
+
 extern struct colprintTable * fieldColprintTableNew (void)
 {
 	return colprintTableNew ("L:LETTER", "L:NAME", "L:ENABLED",
-							 "L:LANGUAGE", "L:JSTYPE", "L:FIXED", "L:DESCRIPTION", NULL);
+							 "L:LANGUAGE", "L:JSTYPE", "L:FIXED",
+							 "L:OP", "L:DESCRIPTION", NULL);
 }
 
 static void  fieldColprintAddLine (struct colprintTable *table, int i)
@@ -1140,6 +1412,13 @@ static void  fieldColprintAddLine (struct colprintTable *table, int i)
 	}
 	colprintLineAppendColumnCString (line, typefields);
 	colprintLineAppendColumnBool (line, writerDoesTreatFieldAsFixed (i));
+
+	char operator[] = {'-', '-', '\0'};
+	if (fdef->getValueObject)
+		operator[0] = 'r';
+	if (fdef->setValueObject)
+		operator[1] = 'w';
+	colprintLineAppendColumnCString (line, operator);
 	colprintLineAppendColumnCString (line, fdef->description);
 }
 
@@ -1235,3 +1514,380 @@ extern void fieldColprintTablePrint (struct colprintTable *table,
 	colprintTableSort (table, fieldColprintCompareLines);
 	colprintTablePrint (table, 0, withListHeader, machinable, fp);
 }
+
+extern const char * getFieldGetterValueType (fieldType type)
+{
+	fieldObject *fobj = getFieldObject (type);
+	return (fobj? fobj->def->getterValueType: NULL);
+}
+
+extern EsObject * getFieldValue (fieldType type, const tagEntryInfo *tag)
+{
+	fieldObject* fobj;
+
+	fobj = getFieldObject (type);
+	if (fobj && fobj->def->getValueObject)
+		return fobj->def->getValueObject (tag, fobj->def);
+	return es_nil;
+}
+
+extern bool hasFieldGetter (fieldType type)
+{
+	fieldObject *fobj = getFieldObject (type);
+	return (fobj && fobj->def->getValueObject);
+}
+
+extern const char * getFieldSetterValueType (fieldType type)
+{
+	fieldObject *fobj = getFieldObject (type);
+	return (fobj? fobj->def->setterValueType: NULL);
+}
+
+extern EsObject * setFieldValue (fieldType type, tagEntryInfo *tag, const EsObject *val)
+{
+	fieldObject *fobj;
+
+	fobj = getFieldObject (type);
+	if (fobj && fobj->def->setValueObject)
+		return fobj->def->setValueObject (tag, fobj->def, val);
+	return es_false;
+}
+
+extern bool hasFieldSetter (fieldType type)
+{
+	fieldObject *fobj = getFieldObject (type);
+	return (fobj && fobj->def->setValueObject);
+}
+
+
+extern bool hasFieldValueCheckerForSetter (fieldType type)
+{
+	fieldObject *fobj = getFieldObject (type);
+	return (fobj && fobj->def->checkValueForSetter);
+}
+
+extern EsObject* checkFieldValueForSetter (fieldType type, const EsObject *val)
+{
+	fieldObject *fobj = getFieldObject (type);
+	return fobj->def->checkValueForSetter (fobj->def, val);
+}
+
+static EsObject* getFieldValueForName (const tagEntryInfo *tag, const fieldDefinition *fdef)
+{
+	return opt_string_new_from_cstr (tag->name);
+}
+
+static EsObject* setFieldValueForName (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *val)
+{
+	eFree ((char*) tag->name);
+	const char *cstr = opt_string_get_cstr (val);
+	tag->name = eStrdup (cstr);
+	return es_false;
+}
+
+static EsObject* getFieldValueForInput (const tagEntryInfo *tag, const fieldDefinition *fdef)
+{
+	return opt_string_new_from_cstr (tag->inputFileName);
+}
+
+static EsObject* getFieldValueForKind (const tagEntryInfo *tag, const fieldDefinition *fdef)
+{
+	const char *kind_name = getLanguageKindName (tag->langType, tag->kindIndex);
+	return opt_name_new_from_cstr (kind_name);
+}
+
+static EsObject* getFieldValueForTyperef (const tagEntryInfo *tag, const fieldDefinition *fdef)
+{
+	if (tag->extensionFields.typeRef [0] == NULL
+		&& tag->extensionFields.typeRef [1] == NULL)
+		return es_nil;
+
+	EsObject *a = opt_array_new ();
+	EsObject *e0 = tag->extensionFields.typeRef [0]
+		? opt_string_new_from_cstr(tag->extensionFields.typeRef [0])
+		: es_false;
+	EsObject *e1 = tag->extensionFields.typeRef [1]
+		? opt_string_new_from_cstr(tag->extensionFields.typeRef [1])
+		: es_false;
+	opt_array_put (a, 0, e0);
+	opt_array_put (a, 1, e1);
+	es_object_unref (e0);
+	es_object_unref (e1);
+	return a;
+}
+
+static EsObject* setFieldValueForTyperef (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
+{
+	const char *tmp[2] = {NULL, NULL};
+
+	for (int i = 0 ; i < 2; i++)
+	{
+		if (tag->extensionFields.typeRef [i])
+			tmp [i] = tag->extensionFields.typeRef [i];
+	}
+
+	if (es_boolean_p (obj))
+	{
+		for (int i = 0 ; i < 2; i++)
+		{
+			if (tag->extensionFields.typeRef [i])
+				tag->extensionFields.typeRef [i] = NULL;
+		}
+	}
+	else if (es_object_get_type (obj) == OPT_TYPE_ARRAY)
+	{
+		for (int i = 0 ; i < 2; i++)
+		{
+			EsObject *e = opt_array_get (obj, i);
+			if (es_boolean_p (e))
+			{
+				if (tag->extensionFields.typeRef [i])
+					tag->extensionFields.typeRef [i] = NULL;
+			}
+			else if (es_object_get_type (e) == OPT_TYPE_STRING)
+			{
+				tag->extensionFields.typeRef [i] = eStrdup (opt_string_get_cstr (e));
+			}
+		}
+	}
+	else if (es_object_get_type (obj) == OPT_TYPE_STRING)
+	{
+		const char *str = opt_string_get_cstr (obj);
+		tag->extensionFields.typeRef [0] = eStrdup ("typename");
+		tag->extensionFields.typeRef [1] = eStrdup (str);
+	}
+	else if (es_integer_p (obj))
+	{
+		int index = es_integer_get (obj);
+		tagEntryInfo *e = getEntryInCorkQueue (index);
+		if (e)
+		{
+			const char *name = e->name;
+			const char *kindName = getLanguageKindName (e->langType, e->kindIndex);
+
+			tag->extensionFields.typeRef [0] = eStrdup (kindName);
+			tag->extensionFields.typeRef [1] = eStrdup (name);
+		}
+	}
+	else
+	{
+		AssertNotReached();
+		return OPT_ERR_TYPECHECK;
+	}
+
+	for (int i = 0; i < 2; i++)
+		if (tmp [i])
+			eFree ((char*)tmp[i]);
+
+	return es_false;
+}
+
+static EsObject* checkFieldValueForTyperef (const fieldDefinition *fdef, const EsObject *obj)
+{
+	if (es_boolean_p (obj))
+	{
+		if (!es_object_equal (es_false, obj))
+			return OPT_ERR_TYPECHECK;
+	}
+	else if (es_object_get_type (obj) == OPT_TYPE_ARRAY)
+	{
+		if (opt_array_length (obj) != 2)
+			return OPT_ERR_TYPECHECK;
+
+		for (unsigned int i = 0; i < 2; i++)
+		{
+			EsObject *e = opt_array_get (obj, i);
+			if (es_object_get_type (e) != OPT_TYPE_STRING)
+				return OPT_ERR_TYPECHECK;
+		}
+	}
+	else if (es_object_get_type (obj) == OPT_TYPE_STRING)
+		;
+	else if (es_integer_p (obj))
+	{
+		int index = es_integer_get (obj);
+		if (index >= countEntryInCorkQueue ())
+			return OPTSCRIPT_ERR_NOTAGENTRY;
+	}
+	else
+		return OPT_ERR_TYPECHECK;
+	return es_false;
+}
+
+static EsObject* getFieldValueForScope (const tagEntryInfo *tag, const fieldDefinition *fdef)
+{
+	return es_integer_new (tag->extensionFields.scopeIndex);
+}
+
+static EsObject* setFieldValueForScope (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
+{
+	int index = es_integer_get (obj);
+	if (index < countEntryInCorkQueue ())
+	{
+		tag->extensionFields.scopeIndex = index;
+		return es_false;
+	}
+
+	return OPTSCRIPT_ERR_NOTAGENTRY;
+}
+
+static EsObject* checkFieldValueForScope (const fieldDefinition *fdef, const EsObject *obj)
+{
+	if (!es_integer_p (obj))
+		return OPT_ERR_TYPECHECK;
+
+	if (es_integer_get (obj) < 0)
+		return OPT_ERR_RANGECHECK;
+
+	return es_false;
+}
+
+static EsObject* getFieldValueForExtras (const tagEntryInfo *tag, const fieldDefinition *fdef)
+{
+	if (!isTagExtra (tag))
+		return es_nil;
+
+	EsObject* a = opt_array_new ();
+
+	for (int i = 0; i < countXtags (); i++)
+	{
+		if (!isTagExtraBitMarked (tag, i))
+			continue;
+
+		langType lang = getXtagOwner (i);
+		const char *lang_name = (lang == LANG_IGNORE)
+			? NULL
+			: getLanguageName (lang);
+		const char *extra_name = getXtagName (i);
+
+		EsObject *extra;
+		if (lang_name == NULL)
+			extra = opt_name_new_from_cstr (extra_name);
+		else
+		{
+			vString *tmp = vStringNewInit (lang_name);
+			vStringPut (tmp, '.');
+			vStringCatS (tmp, extra_name);
+			extra = opt_name_new_from_cstr (vStringValue (tmp));
+			vStringDelete (tmp);
+		}
+		opt_array_add (a, extra);
+		es_object_unref (extra);
+	}
+	return a;
+}
+
+static EsObject* getFieldValueForSignature (const tagEntryInfo *tag, const fieldDefinition *fdef)
+{
+	if (!tag->extensionFields.signature)
+		return es_nil;
+	return (opt_name_new_from_cstr (tag->extensionFields.signature));
+}
+
+static EsObject* setFieldValueForSignature (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
+{
+	if (tag->extensionFields.signature)
+		eFree ((char *)tag->extensionFields.signature);
+
+	const char *str = opt_string_get_cstr (obj);
+	tag->extensionFields.signature = eStrdup (str);
+	return es_false;
+}
+
+static void makeRolesArray (const tagEntryInfo *const tag, int roleIndex, void *data)
+{
+	EsObject *a = data;
+
+	const roleDefinition *role = getTagRole (tag, roleIndex);
+	EsObject *r = opt_name_new_from_cstr (role->name);
+	opt_array_add (a, r);
+	es_object_unref (r);
+}
+
+static EsObject* getFieldValueForRoles (const tagEntryInfo *tag, const fieldDefinition *fdef)
+{
+	EsObject *a = opt_array_new ();
+
+	if (!foreachRoleBits (tag, makeRolesArray, a))
+	{
+		EsObject *r = opt_name_new_from_cstr (ROLE_DEFINITION_NAME);
+		opt_array_add (a, r);
+		es_object_unref (r);
+	}
+	return a;
+}
+
+static EsObject* getFieldValueForLineCommon (const tagEntryInfo *tag, const fieldDefinition *fdef)
+{
+	if (fdef->ftype == FIELD_END_LINE)
+		return ((int)tag->extensionFields.endLine == 0)
+			? es_nil
+			: es_integer_new ((int)tag->extensionFields.endLine);
+	else
+		return ((int)tag->lineNumber == 0)
+			? es_nil
+			: es_integer_new ((int)tag->lineNumber);
+}
+
+static EsObject* checkFieldValueForLineCommon (const fieldDefinition *fdef, const EsObject *obj)
+{
+	return es_false;
+}
+
+static EsObject* setFieldValueForLineCommon (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
+{
+	int l;
+	if (es_object_get_type (obj) == OPT_TYPE_MATCHLOC)
+	{
+		matchLoc *loc = es_pointer_get (obj);
+		l = loc->line;
+	}
+	else if (es_integer_p (obj))
+	{
+		l = es_integer_get (obj);
+		if (l < 1)
+			return OPT_ERR_RANGECHECK;
+
+		/* If the new line number is too large,
+		   we cannot fill tag->filePosition wit
+		   getInputFilePositionForLine(); */
+		if (fdef->ftype == FIELD_LINE_NUMBER
+			&& l < getInputLineNumber())
+			return OPT_ERR_RANGECHECK;
+	}
+	else
+		return OPT_ERR_TYPECHECK;
+
+	if (fdef->ftype == FIELD_END_LINE)
+		tag->extensionFields.endLine = l;
+	else
+	{
+		tag->lineNumber = l;
+		tag->filePosition = getInputFilePositionForLine (l);
+	}
+
+	return es_false;
+}
+
+static EsObject* setFieldValueForInherits (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj)
+{
+	if (es_object_get_type (obj) == OPT_TYPE_STRING)
+	{
+		if (tag->extensionFields.inheritance)
+			eFree ((void *)tag->extensionFields.inheritance);
+		const char *str = opt_string_get_cstr (obj);
+		tag->extensionFields.inheritance = eStrdup (str);
+	}
+	else if (es_object_equal (es_false, obj))
+	{
+		if (tag->extensionFields.inheritance)
+		{
+			eFree ((void *)tag->extensionFields.inheritance);
+			tag->extensionFields.inheritance = NULL;
+		}
+	}
+	else
+		return OPT_ERR_RANGECHECK; /* true is not acceptable. */
+
+	return es_false;
+}


Modified: ctags/main/field.h
43 lines changed, 31 insertions(+), 12 deletions(-)
===================================================================
@@ -20,6 +20,7 @@
 #include "types.h"
 
 #include "vstring.h"
+#include "optscript.h"
 
 /*
 *   DATA DECLARATIONS
@@ -32,32 +33,41 @@ typedef enum eFieldType { /* extension field content control */
 	FIELD_NAME,
 	FIELD_INPUT_FILE,
 	FIELD_PATTERN,
-	FIELD_COMPACT_INPUT_LINE,
+
+	FIELD_ECTAGS_START,
+	FIELD_COMPACT_INPUT_LINE = FIELD_ECTAGS_START,
 
 	/* EXTENSION FIELDS */
-	FIELD_EXTENSION_START,
-	FIELD_ACCESS = FIELD_EXTENSION_START,
-	FIELD_FILE_SCOPE,
-	FIELD_INHERITANCE,
+	FIELD_JSON_LOOP_START,
+	FIELD_FILE_SCOPE = FIELD_JSON_LOOP_START,
 	FIELD_KIND_LONG,
 	FIELD_KIND,
 	FIELD_LANGUAGE,
-	FIELD_IMPLEMENTATION,
 	FIELD_LINE_NUMBER,
-	FIELD_SIGNATURE,
 	FIELD_SCOPE,
 	FIELD_TYPE_REF,
 	FIELD_KIND_KEY,
+	FIELD_ECTAGS_LOOP_START,
+	FIELD_INHERITANCE = FIELD_ECTAGS_LOOP_START,
+	FIELD_ACCESS,
+	FIELD_IMPLEMENTATION,
+	FIELD_SIGNATURE,
+	FIELD_ECTAGS_LOOP_LAST = FIELD_SIGNATURE,
 
-	/* EXTENSION FIELDS NEWLY INTRODUCED IN UCTAGS */
-	FIELD_ROLES,
-	FIELD_REF_MARK,
+	/* Extension fields newly introduced in Universal Ctags. */
+	FIELDS_UCTAGS_START,
+	FIELD_REF_MARK = FIELDS_UCTAGS_START,
 	FIELD_SCOPE_KEY,
+	FIELD_SCOPE_KIND_LONG,
+	FIELD_UCTAGS_LOOP_START,
+	FIELD_ROLES = FIELD_UCTAGS_LOOP_START,
 	FIELD_EXTRAS,
 	FIELD_XPATH,
-	FIELD_SCOPE_KIND_LONG,
 	FIELD_END_LINE,
-	FIELD_BUILTIN_LAST = FIELD_END_LINE,
+	FIELD_EPOCH,
+	FIELD_NTH,
+
+	FIELD_BUILTIN_LAST = FIELD_NTH,
 } fieldType ;
 
 #define fieldDataTypeFalgs "sib" /* used in --list-fields */
@@ -90,6 +100,15 @@ struct sFieldDefinition {
 
 	bool (* isValueAvailable) (const tagEntryInfo *const);
 
+	const char * getterValueType;
+	EsObject * (* getValueObject) (const tagEntryInfo *, const fieldDefinition *);
+	const char * setterValueType;
+
+	/* Return es_false if passed value is acceptable.
+	   Return an error object is unacceptable. */
+	EsObject * (* checkValueForSetter) (const fieldDefinition *, const EsObject *);
+	EsObject * (* setValueObject) (tagEntryInfo *, const fieldDefinition *, const EsObject *);
+
 	fieldDataType dataType; /* used in json output */
 
 	unsigned int ftype;	/* Given from the main part */


Modified: ctags/main/field_p.h
15 lines changed, 13 insertions(+), 2 deletions(-)
===================================================================
@@ -18,6 +18,7 @@
 #include "general.h"
 #include "colprint_p.h"
 #include "field.h"
+#include "optscript.h"
 
 /*
 *   DATA DECLARATIONS
@@ -43,14 +44,14 @@ extern fieldType getFieldTypeForOption (char letter);
    internally, each parser is not initialized. `LANG_IGNORE' is a bit faster. */
 extern fieldType getFieldTypeForName (const char *name);
 extern fieldType getFieldTypeForNameAndLanguage (const char *fieldName, langType language);
-extern bool enableField (fieldType type, bool state, bool warnIfFixedField);
+extern bool enableField (fieldType type, bool state);
 extern bool isCommonField (fieldType type);
 extern int     getFieldOwner (fieldType type);
 extern const char* getFieldDescription (fieldType type);
 extern const char* getFieldName (fieldType type);
 extern unsigned char getFieldLetter (fieldType type);
 extern unsigned int getFieldDataType (fieldType type);
-extern void printFields (int language);
+extern bool isFieldValueAvailableAlways (fieldType type);
 
 /* Whether the field specified with TYPE has a
    method for rendering in the current format. */
@@ -77,4 +78,14 @@ extern void fieldColprintAddLanguageLines (struct colprintTable *table, langType
 extern void fieldColprintTablePrint (struct colprintTable *table,
 									 bool withListHeader, bool machinable, FILE *fp);
 
+/* tag is assumed that it is in the cork queue. */
+extern EsObject * getFieldValue (fieldType type, const tagEntryInfo *tag);
+extern bool hasFieldGetter (fieldType type);
+extern const char * getFieldGetterValueType (fieldType type);
+extern EsObject * setFieldValue (fieldType type, tagEntryInfo *tag, const EsObject *val);
+extern bool hasFieldSetter (fieldType type);
+extern const char * getFieldSetterValueType (fieldType type);
+extern bool hasFieldValueCheckerForSetter (fieldType type);
+extern EsObject *checkFieldValueForSetter (fieldType type, const EsObject *val);
+
 #endif	/* CTAGS_MAIN_FIELD_PRIVATE_H */


Modified: ctags/main/flags.c
13 lines changed, 10 insertions(+), 3 deletions(-)
===================================================================
@@ -21,18 +21,24 @@
 #include "vstring.h"
 #include "routines.h"
 
-void flagsEval (const char* flags_original, flagDefinition* defs, unsigned int ndefs, void* data)
+extern const char *flagsEval (const char* flags_original, flagDefinition* defs, unsigned int ndefs, void* data)
 {
 	unsigned int i, j;
 	char *flags;
+	const char *optscript = NULL;
 
 	if (!flags_original)
-		return;
+		return NULL;
 
 	flags = eStrdup (flags_original);
 	for (i = 0 ; flags [i] != '\0' ; ++i)
 	{
-		if (flags [i] == LONG_FLAGS_OPEN)
+		if (flags [i] == LONG_FLAGS_OPEN && flags [i + 1] == LONG_FLAGS_OPEN)
+		{
+			optscript = flags_original + i;
+			break;
+		}
+		else if (flags [i] == LONG_FLAGS_OPEN)
 		{
 			const char* aflag = flags + i + 1;
 			char* needle_close_paren = strchr(aflag, LONG_FLAGS_CLOSE);
@@ -74,6 +80,7 @@ void flagsEval (const char* flags_original, flagDefinition* defs, unsigned int n
 				defs[j].shortProc(flags[i], data);
 	}
 	eFree (flags);
+	return optscript;
 }
 
 extern struct colprintTable * flagsColprintTableNew (void)


Modified: ctags/main/flags_p.h
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -27,7 +27,8 @@ typedef struct sFlagDefinition {
 	const char *description;
 } flagDefinition;
 
-extern void flagsEval (const char* flags, flagDefinition* defs, unsigned int ndefs, void* data);
+/* Return {{optscript}} part. */
+extern const char*  flagsEval (const char* flags, flagDefinition* defs, unsigned int ndefs, void* data);
 extern struct colprintTable * flagsColprintTableNew (void);
 extern void flagsColprintAddDefinitions (struct colprintTable *table, flagDefinition* def, unsigned int ndefs);
 extern void flagsColprintTablePrint (struct colprintTable *table,


Modified: ctags/main/fmt.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -230,13 +230,13 @@ static fmtElement** queueTagField (fmtElement **last, long width, bool truncatio
 	else
 		cur->spec.field.raw_fmtstr = NULL;
 
-	enableField (ftype, true, false);
+	enableField (ftype, true);
 	if (language == LANG_AUTO)
 	{
 		fieldType ftype_next = ftype;
 
 		while ((ftype_next = nextSiblingField (ftype_next)) != FIELD_UNKNOWN)
-			enableField (ftype_next, true, false);
+			enableField (ftype_next, true);
 	}
 
 	cur->printer = printTagField;


Modified: ctags/main/htable.c
94 lines changed, 70 insertions(+), 24 deletions(-)
===================================================================
@@ -43,8 +43,10 @@ struct sHashTable {
 	unsigned int size;
 	hashTableHashFunc hashfn;
 	hashTableEqualFunc equalfn;
-	hashTableFreeFunc keyfreefn;
-	hashTableFreeFunc valfreefn;
+	hashTableDeleteFunc keyfreefn;
+	hashTableDeleteFunc valfreefn;
+	void *valForNotUnknownKey;
+	hashTableDeleteFunc valForNotUnknownKeyfreefn;
 };
 
 struct chainTracker {
@@ -65,45 +67,55 @@ static hentry* entry_new (void *key, void *value, hentry* next)
 	return entry;
 }
 
-static hentry* entry_destroy (hentry* entry,
-			      hashTableFreeFunc keyfreefn,
-			      hashTableFreeFunc valfreefn)
+static void entry_reset  (hentry* entry,
+						  void *newkey,
+						  void *newval,
+						  hashTableDeleteFunc keyfreefn,
+						  hashTableDeleteFunc valfreefn)
 {
-	hentry* tmp;
-
 	if (keyfreefn)
 		keyfreefn (entry->key);
 	if (valfreefn)
 		valfreefn (entry->value);
-	entry->key = NULL;
-	entry->value = NULL;
+	entry->key = newkey;
+	entry->value = newval;
+}
+
+static hentry* entry_destroy (hentry* entry,
+			      hashTableDeleteFunc keyfreefn,
+			      hashTableDeleteFunc valfreefn)
+{
+	hentry* tmp;
+
+	entry_reset (entry, NULL, NULL, keyfreefn, valfreefn);
 	tmp = entry->next;
 	eFree (entry);
 
 	return tmp;
 }
 
 static void  entry_reclaim (hentry* entry,
-			    hashTableFreeFunc keyfreefn,
-			    hashTableFreeFunc valfreefn)
+			    hashTableDeleteFunc keyfreefn,
+			    hashTableDeleteFunc valfreefn)
 {
 	while (entry)
 		entry = entry_destroy (entry, keyfreefn, valfreefn);
 }
 
-static void *entry_find (hentry* entry, const void* const key, hashTableEqualFunc equalfn)
+static void *entry_find (hentry* entry, const void* const key, hashTableEqualFunc equalfn,
+						 void *valForNotUnknownKey)
 {
 	while (entry)
 	{
 		if (equalfn( key, entry->key))
 			return entry->value;
 		entry = entry->next;
 	}
-	return NULL;
+	return valForNotUnknownKey;
 }
 
 static bool		entry_delete (hentry **entry, const void *key, hashTableEqualFunc equalfn,
-			      hashTableFreeFunc keyfreefn, hashTableFreeFunc valfreefn)
+			      hashTableDeleteFunc keyfreefn, hashTableDeleteFunc valfreefn)
 {
 	while (*entry)
 	{
@@ -112,7 +124,22 @@ static bool		entry_delete (hentry **entry, const void *key, hashTableEqualFunc e
 			*entry = entry_destroy (*entry, keyfreefn, valfreefn);
 			return true;
 		}
+		entry = &((*entry)->next);
+	}
+	return false;
+}
 
+static bool		entry_update (hentry *entry, void *key, void *value, hashTableEqualFunc equalfn,
+			      hashTableDeleteFunc keyfreefn, hashTableDeleteFunc valfreefn)
+{
+	while (entry)
+	{
+		if (equalfn (key, entry->key))
+		{
+			entry_reset (entry, key, value, keyfreefn, valfreefn);
+			return true;
+		}
+		entry = entry->next;
 	}
 	return false;
 }
@@ -131,8 +158,8 @@ static bool  entry_foreach (hentry *entry, hashTableForeachFunc proc, void *user
 extern hashTable *hashTableNew    (unsigned int size,
 				   hashTableHashFunc hashfn,
 				   hashTableEqualFunc equalfn,
-				   hashTableFreeFunc keyfreefn,
-				   hashTableFreeFunc valfreefn)
+				   hashTableDeleteFunc keyfreefn,
+				   hashTableDeleteFunc valfreefn)
 {
 	hashTable *htable;
 
@@ -144,16 +171,21 @@ extern hashTable *hashTableNew    (unsigned int size,
 	htable->equalfn = equalfn;
 	htable->keyfreefn = keyfreefn;
 	htable->valfreefn = valfreefn;
+	htable->valForNotUnknownKey = NULL;
+	htable->valForNotUnknownKeyfreefn = NULL;
 
 	return htable;
 }
 
-extern hashTable* hashTableIntNew (unsigned int size,
-								   hashTableHashFunc hashfn,
-								   hashTableEqualFunc equalfn,
-								   hashTableFreeFunc keyfreefn)
+extern void hashTableSetValueForUnknownKey (hashTable *htable,
+											void *val,
+											hashTableDeleteFunc valfreefn)
 {
-	return hashTableNew (size, hashfn, equalfn, keyfreefn, NULL);
+	if (htable->valfreefn)
+		htable->valfreefn (htable->valForNotUnknownKey);
+
+	htable->valForNotUnknownKey = val;
+	htable->valForNotUnknownKeyfreefn = valfreefn;
 }
 
 extern void       hashTableDelete (hashTable *htable)
@@ -163,6 +195,8 @@ extern void       hashTableDelete (hashTable *htable)
 
 	hashTableClear (htable);
 
+	if (htable->valForNotUnknownKeyfreefn)
+		htable->valForNotUnknownKeyfreefn (htable->valForNotUnknownKey);
 	eFree (htable->table);
 	eFree (htable);
 }
@@ -196,7 +230,7 @@ extern void*      hashTableGetItem   (hashTable *htable, const void * key)
 	unsigned int i;
 
 	i = htable->hashfn (key) % htable->size;
-	return entry_find(htable->table[i], key, htable->equalfn);
+	return entry_find(htable->table[i], key, htable->equalfn, htable->valForNotUnknownKey);
 }
 
 extern bool     hashTableDeleteItem (hashTable *htable, const void *key)
@@ -208,9 +242,21 @@ extern bool     hashTableDeleteItem (hashTable *htable, const void *key)
 			    htable->equalfn, htable->keyfreefn, htable->valfreefn);
 }
 
+extern bool    hashTableUpdateItem (hashTable *htable, void *key, void *value)
+{
+	unsigned int i;
+
+	i = htable->hashfn (key) % htable->size;
+	bool r = entry_update(htable->table[i], key, value,
+						  htable->equalfn, htable->keyfreefn, htable->valfreefn);
+	if (!r)
+		htable->table[i] = entry_new(key, value, htable->table[i]);
+	return r;
+}
+
 extern bool    hashTableHasItem    (hashTable *htable, const void *key)
 {
-	return hashTableGetItem (htable, key)? true: false;
+	return hashTableGetItem (htable, key) == htable->valForNotUnknownKey? false: true;
 }
 
 extern bool       hashTableForeachItem (hashTable *htable, hashTableForeachFunc proc, void *user_data)
@@ -258,7 +304,7 @@ static bool count (const void *const key CTAGS_ATTR_UNUSED, void *value CTAGS_AT
 	return true;
 }
 
-extern int        hashTableCountItem   (hashTable *htable)
+extern unsigned int hashTableCountItem   (hashTable *htable)
 {
 	int c = 0;
 	hashTableForeachItem (htable, count, &c);


Modified: ctags/main/htable.h
23 lines changed, 15 insertions(+), 8 deletions(-)
===================================================================
@@ -30,7 +30,7 @@
 typedef struct sHashTable hashTable;
 typedef unsigned int (* hashTableHashFunc)  (const void * const key);
 typedef bool      (* hashTableEqualFunc) (const void* a, const void* b);
-typedef void         (* hashTableFreeFunc)  (void * ptr);
+typedef void         (* hashTableDeleteFunc)  (void * ptr);
 
 /* To continue interation, return true.
  * To break interation, return false. */
@@ -51,15 +51,26 @@ bool hashInteq (const void * a, const void * b);
 extern hashTable* hashTableNew         (unsigned int size,
 					hashTableHashFunc hashfn,
 					hashTableEqualFunc equalfn,
-					hashTableFreeFunc keyfreefn,
-					hashTableFreeFunc valfreefn);
+					hashTableDeleteFunc keyfreefn,
+					hashTableDeleteFunc valfreefn);
+
+/* By default, hashTableGetItem() returns NULL for a unknown key.
+ * It means you cannot store NULL as a value for a key.
+ * With hashTableSetValueForUnknownKey(), you can specific
+ * an alternative address representing the value for for unknown
+ * keys.
+ */
+extern void hashTableSetValueForUnknownKey (hashTable *htable,
+											void *val,
+											hashTableDeleteFunc valfreefn);
 
 extern void       hashTableDelete      (hashTable *htable);
 extern void       hashTableClear       (hashTable *htable);
 extern void       hashTablePutItem     (hashTable *htable, void *key, void *value);
 extern void*      hashTableGetItem     (hashTable *htable, const void * key);
 extern bool    hashTableHasItem     (hashTable * htable, const void * key);
 extern bool    hashTableDeleteItem  (hashTable *htable, const void *key);
+extern bool       hashTableUpdateItem  (hashTable *htable, void *key, void *value);
 
 /* Return true if proc never returns false; proc returns true for all
  * the items, or htable holds no item.
@@ -74,12 +85,8 @@ extern bool       hashTableForeachItem (hashTable *htable, hashTableForeachFunc
  * key. */
 extern bool       hashTableForeachItemOnChain (hashTable *htable, const void *key, hashTableForeachFunc proc, void *user_data);
 
-extern int        hashTableCountItem   (hashTable *htable);
+extern unsigned int hashTableCountItem   (hashTable *htable);
 
-extern hashTable* hashTableIntNew (unsigned int size,
-								   hashTableHashFunc hashfn,
-								   hashTableEqualFunc equalfn,
-								   hashTableFreeFunc keyfreefn);
 #define HT_PTR_TO_INT(P) ((int)(intptr_t)(P))
 #define HT_INT_TO_PTR(P) ((void*)(intptr_t)(P))
 #define HT_PTR_TO_UINT(P) ((unsigned int)(uintptr_t)(P))


Modified: ctags/main/kind_p.h
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -13,6 +13,7 @@
 */
 
 #include "general.h"
+#include "kind.h"
 #include "vstring.h"
 
 


Modified: ctags/main/lregex-default.c
127 lines changed, 127 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,127 @@
+/*
+*   Copyright (c) 2000-2003, Darren Hiebert
+*
+*   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 applying regular expression matching.
+*
+*   The code for utilizing the Gnu regex package with regards to processing the
+*   regex option and checking for regex matches was adapted from routines in
+*   Gnu etags.
+*/
+
+/*
+*   INCLUDE FILES
+*/
+#include "general.h"  /* must always come first */
+
+#include <regex.h>
+#include "lregex_p.h"
+
+/*
+*    FUNCTION DECLARATIONS
+*/
+static int match (struct regexBackend *backend,
+				  void *code, const char *input, size_t size,
+				  regmatch_t pmatch[BACK_REFERENCE_COUNT]);
+static regexCompiledCode compile (struct regexBackend *backend,
+								  const char *const regexp,
+								  int flags);
+static void delete_code (void *code);
+static void set_icase_flag (int *flags);
+
+/*
+*    DATA DEFINITIONS
+*/
+static struct regexBackend defaultRegexBackend = {
+	.fdefs = NULL,
+	.fdef_count = 0,
+	.set_icase_flag = set_icase_flag,
+	.compile = compile,
+	.match = match,
+	.delete_code = delete_code,
+};
+
+/*
+*    FUNCTOIN DEFINITIONS
+*/
+extern void basic_regex_flag_short (char c, void* data)
+{
+	struct flagDefsDescriptor *desc = data;
+
+	if (desc->backend)
+		error (FATAL, "regex backed is specified twice: %c", c);
+
+	desc->backend = &defaultRegexBackend;
+	desc->flags   = (desc->regptype == REG_PARSER_MULTI_TABLE)? 0: REG_NEWLINE;
+}
+
+extern void basic_regex_flag_long (const char* const s, const char* const unused CTAGS_ATTR_UNUSED, void* data)
+{
+	struct flagDefsDescriptor *desc = data;
+
+	if (desc->backend)
+		error (FATAL, "regex backed is specified twice: %s", s);
+
+	basic_regex_flag_short ('b', data);
+}
+
+extern void extend_regex_flag_short (char c, void* data)
+{
+	struct flagDefsDescriptor *desc = data;
+
+	if (desc->backend)
+		error (FATAL, "regex backed is specified twice: %c", c);
+
+	desc->backend = &defaultRegexBackend;
+	desc->flags   = REG_EXTENDED;
+	desc->flags  |= (desc->regptype == REG_PARSER_MULTI_TABLE)? 0: REG_NEWLINE;
+}
+
+extern void extend_regex_flag_long (const char* const s, const char* const unused CTAGS_ATTR_UNUSED, void* data)
+{
+	struct flagDefsDescriptor *desc = data;
+
+	if (desc->backend)
+		error (FATAL, "regex backed is specified twice: %s", s);
+
+	extend_regex_flag_short('e', data);
+}
+
+static void delete_code (void *code)
+{
+	regex_t *regex_code = code;
+	regfree (regex_code);
+	eFree (regex_code);
+}
+
+static regexCompiledCode compile (struct regexBackend *backend,
+								  const char *const regexp,
+								  int flags)
+{
+	regex_t *regex_code = xMalloc (1, regex_t);
+	int errcode = regcomp (regex_code, regexp, flags);
+	if (errcode != 0)
+	{
+		char errmsg[256];
+		regerror (errcode, regex_code, errmsg, 256);
+		error (WARNING, "regcomp: %s", errmsg);
+		regfree (regex_code);
+		eFree (regex_code);
+		return (regexCompiledCode) { .backend = NULL, .code = NULL };
+	}
+	return (regexCompiledCode) { .backend = &defaultRegexBackend, .code = regex_code };
+}
+
+static int match (struct regexBackend *backend,
+				  void *code, const char *input, size_t size CTAGS_ATTR_UNUSED,
+				  regmatch_t pmatch[BACK_REFERENCE_COUNT])
+{
+	return regexec ((regex_t *)code, input, BACK_REFERENCE_COUNT, pmatch, 0);
+}
+
+static void set_icase_flag (int *flags)
+{
+	*flags |= REG_ICASE;
+}


Modified: ctags/main/lregex-pcre2.c
140 lines changed, 140 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,140 @@
+/*
+*  Copyright (c) 2021, Red Hat, Inc.
+*  Copyright (c) 2021, Masatake YAMATO
+*
+*   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 applying regular expression matching.
+*
+*   The code for utilizing the Gnu regex package with regards to processing the
+*   regex option and checking for regex matches was adapted from routines in
+*   Gnu etags.
+*/
+
+/*
+*   INCLUDE FILES
+*/
+#include "general.h"  /* must always come first */
+
+#ifdef HAVE_PCRE2
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+#endif
+
+#include "lregex_p.h"
+#include "trashbox.h"
+
+#include <string.h>
+
+/*
+*    FUNCTION DECLARATIONS
+*/
+static int match (struct regexBackend *backend,
+				  void *code, const char *input, size_t size,
+				  regmatch_t pmatch[BACK_REFERENCE_COUNT]);
+static regexCompiledCode compile (struct regexBackend *backend,
+								  const char *const regexp,
+								  int flags);
+static void delete_code (void *code);
+static void set_icase_flag (int *flags);
+
+/*
+*    DATA DEFINITIONS
+*/
+static struct regexBackend pcre2RegexBackend = {
+	.fdefs = NULL,
+	.fdef_count = 0,
+	.set_icase_flag = set_icase_flag,
+	.compile = compile,
+	.match = match,
+	.delete_code = delete_code,
+};
+
+/*
+*    FUNCTOIN DEFINITIONS
+*/
+extern void pcre2_regex_flag_short (char c, void* data)
+{
+	struct flagDefsDescriptor *desc = data;
+
+	if (desc->backend)
+		error (FATAL, "regex backed is specified twice: %c", c);
+
+	desc->backend = &pcre2RegexBackend;
+	desc->flags   = (desc->regptype == REG_PARSER_MULTI_TABLE)? PCRE2_DOTALL: PCRE2_MULTILINE;
+}
+
+extern void pcre2_regex_flag_long (const char* const s, const char* const unused CTAGS_ATTR_UNUSED, void* data)
+{
+	struct flagDefsDescriptor *desc = data;
+
+	if (desc->backend)
+		error (FATAL, "regex backed is specified twice: %s", s);
+
+	pcre2_regex_flag_short ('p', data);
+}
+
+static void delete_code (void *code)
+{
+	pcre2_code_free (code);
+}
+
+static regexCompiledCode compile (struct regexBackend *backend,
+								  const char *const regexp,
+								  int flags)
+{
+	int errornumber;
+	PCRE2_SIZE erroroffset;
+	pcre2_code *regex_code = pcre2_compile((PCRE2_SPTR)regexp,
+										   PCRE2_ZERO_TERMINATED,
+										   (uint32_t) flags,
+										   &errornumber,
+										   &erroroffset,
+										   NULL);
+	if (regex_code == NULL)
+	{
+		PCRE2_UCHAR buffer[256];
+		pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
+		error (WARNING, "PCRE2 compilation failed at offset %d: %s", (int)erroroffset,
+			   buffer);
+		return (regexCompiledCode) { .backend = NULL, .code = NULL };
+	}
+	return (regexCompiledCode) { .backend = &pcre2RegexBackend, .code = regex_code };
+}
+
+static int match (struct regexBackend *backend,
+				  void *code, const char *input, size_t size,
+				  regmatch_t pmatch[BACK_REFERENCE_COUNT])
+{
+	static pcre2_match_data *match_data;
+	if (match_data == NULL)
+	{
+		match_data = pcre2_match_data_create (BACK_REFERENCE_COUNT, NULL);
+		DEFAULT_TRASH_BOX (match_data, pcre2_match_data_free);
+	}
+
+	int rc = pcre2_match (code, (PCRE2_SPTR)input, size,
+						  0, 0, match_data, NULL);
+	if (rc > 0)
+	{
+		PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
+		if (ovector[0] <= ovector[1])
+		{
+			memset (pmatch, 0, sizeof(pmatch[0]) * BACK_REFERENCE_COUNT);
+			for (int i = 0; i < BACK_REFERENCE_COUNT; i++)
+			{
+				pmatch [i].rm_so = (i < rc)? ovector [2*i]  : -1;
+				pmatch [i].rm_eo = (i < rc)? ovector [2*i+1]: -1;
+
+			}
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static void set_icase_flag (int *flags)
+{
+	*flags |= PCRE2_CASELESS;
+}


Modified: ctags/main/lregex.c
1542 lines changed, 1406 insertions(+), 136 deletions(-)
===================================================================
@@ -23,7 +23,6 @@
 #ifdef HAVE_SYS_TYPES_H
 # include <sys/types.h>  /* declare off_t (not known to regex.h on FreeBSD) */
 #endif
-#include <regex.h>
 
 #include <inttypes.h>
 
@@ -35,12 +34,15 @@
 #include "htable.h"
 #include "kind.h"
 #include "options.h"
+#include "optscript.h"
 #include "parse_p.h"
 #include "promise.h"
 #include "read.h"
 #include "read_p.h"
 #include "routines.h"
 #include "routines_p.h"
+#include "script_p.h"
+#include "trace.h"
 #include "trashbox.h"
 #include "xtag_p.h"
 
@@ -50,9 +52,6 @@ static bool regexAvailable = false;
 *   MACROS
 */
 
-/* Back-references \0 through \9 */
-#define BACK_REFERENCE_COUNT 10
-
 /* The max depth of taction=enter/leave stack */
 #define MTABLE_STACK_MAX_DEPTH 64
 
@@ -64,6 +63,7 @@ static bool regexAvailable = false;
    Tmain cases. */
 #define MTABLE_MOTIONLESS_MAX (MTABLE_STACK_MAX_DEPTH + 1)
 
+#define DEFAULT_REGEX_BACKEND "e"
 
 /*
 *   DATA DECLARATIONS
@@ -137,7 +137,7 @@ struct mTableActionSpec {
 };
 
 typedef struct {
-	regex_t *pattern;
+	regexCompiledCode pattern;
 	enum pType type;
 	bool exclusive;
 	bool accept_empty_name;
@@ -172,6 +172,9 @@ typedef struct {
 		char *message_string;
 	} message;
 
+	char *optscript_src;
+	EsObject *optscript;
+
 	int refcount;
 } regexPattern;
 
@@ -206,6 +209,17 @@ struct guestRequest {
 	struct boundaryInRequest boundary[2];
 };
 
+typedef struct {
+	const char *line;
+	const char *start;
+	const regexPattern* const patbuf;
+	const regmatch_t* const pmatch;
+	int nmatch;
+	struct mTableActionSpec taction;
+	bool advanceto;
+	unsigned int advanceto_delta;
+} scriptWindow;
+
 struct lregexControlBlock {
 	int currentScope;
 	ptrArray *entries [2];
@@ -215,12 +229,21 @@ struct lregexControlBlock {
 
 	struct guestRequest *guest_req;
 
+	EsObject *local_dict;
+
+	ptrArray *hook[SCRIPT_HOOK_MAX];
+	ptrArray *hook_code[SCRIPT_HOOK_MAX];
+
 	langType owner;
+
+	scriptWindow *window;
 };
 
 /*
 *   DATA DEFINITIONS
 */
+static OptVM *optvm;
+static EsObject *lregex_dict = es_nil;
 
 /*
 *   FUNCTION DEFINITIONS
@@ -237,6 +260,15 @@ static bool   guestRequestIsFilled(struct guestRequest *);
 static void   guestRequestClear (struct guestRequest *);
 static void   guestRequestSubmit (struct guestRequest *);
 
+static EsObject *scriptRead (OptVM *vm, const char *src);
+static void scriptSetup (OptVM *vm, struct lregexControlBlock *lcb, int corkIndex, scriptWindow *window);
+static EsObject* scriptEval (OptVM *vm, EsObject *optscript);
+static void scriptEvalHook (OptVM *vm, struct lregexControlBlock *lcb, enum scriptHook hook);
+static void scriptTeardown (OptVM *vm, struct lregexControlBlock *lcb);
+
+static char* make_match_string (scriptWindow *window, int group);
+static matchLoc *make_mloc (scriptWindow *window, int group, bool start);
+
 static void deleteTable (void *ptrn)
 {
 	struct regexTable *t = ptrn;
@@ -261,9 +293,7 @@ static void deletePattern (regexPattern *p)
 	if (p->refcount > 0)
 		return;
 
-	regfree (p->pattern);
-	eFree (p->pattern);
-	p->pattern = NULL;
+	p->pattern.backend->delete_code (p->pattern.code);
 
 	if (p->type == PTRN_TAG)
 	{
@@ -285,6 +315,11 @@ static void deletePattern (regexPattern *p)
 	if (p->anonymous_tag_prefix)
 		eFree (p->anonymous_tag_prefix);
 
+	if (p->optscript)
+		es_object_unref (p->optscript);
+	if (p->optscript_src)
+		eFree (p->optscript_src);
+
 	eFree (p);
 }
 
@@ -304,6 +339,13 @@ extern struct lregexControlBlock* allocLregexControlBlock (parserDefinition *par
 	lcb->tables = ptrArrayNew(deleteTable);
 	lcb->tstack = ptrArrayNew(NULL);
 	lcb->guest_req = guestRequestNew ();
+	lcb->local_dict = es_nil;
+
+	for (int i = 0; i< SCRIPT_HOOK_MAX; i++)
+	{
+		lcb->hook[i] = ptrArrayNew (eFree);
+		lcb->hook_code[i] = ptrArrayNew ((ptrArrayDeleteFunc)es_object_unref);
+	}
 	lcb->owner = parser->id;
 
 	return lcb;
@@ -327,6 +369,18 @@ extern void freeLregexControlBlock (struct lregexControlBlock* lcb)
 	guestRequestDelete (lcb->guest_req);
 	lcb->guest_req = NULL;
 
+	es_object_unref (lcb->local_dict);
+	lcb->local_dict = es_nil;
+
+	for (int i = 0; i < SCRIPT_HOOK_MAX; i++)
+	{
+		ptrArrayDelete (lcb->hook[i]);
+		lcb->hook[i] = NULL;
+
+		ptrArrayDelete (lcb->hook_code[i]);
+		lcb->hook_code[i] = NULL;
+	}
+
 	eFree (lcb);
 }
 
@@ -335,11 +389,11 @@ extern void freeLregexControlBlock (struct lregexControlBlock* lcb)
 */
 
 static void initRegexTag (tagEntryInfo *e,
-		const vString* const name, int kindIndex, int roleIndex, int scopeIndex, int placeholder,
+		const char * name, int kindIndex, int roleIndex, int scopeIndex, int placeholder,
 		unsigned long line, MIOPos *pos, int xtag_type)
 {
-	Assert (name != NULL  &&  ((vStringLength (name) > 0) || placeholder));
-	initRefTagEntry (e, vStringValue (name), kindIndex, roleIndex);
+	Assert (name != NULL  &&  ((name[0] != '\0') || placeholder));
+	initRefTagEntry (e, name, kindIndex, roleIndex);
 	e->extensionFields.scopeIndex = scopeIndex;
 	e->placeholder = !!placeholder;
 	if (line)
@@ -364,7 +418,7 @@ static void initRegexTag (tagEntryInfo *e,
  * Returns pointer to terminating separator.  Works in place.  Null
  * terminates name string.
  */
-static char* scanSeparators (char* name, enum regexParserType regptype)
+static char* scanSepara@@ Diff output truncated at 100000 characters. @@

--------------
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