Branch: refs/heads/master Author: Jiřà Techet techet@gmail.com Committer: Enrico Tröger enrico.troeger@uvena.de Date: Thu, 25 Nov 2021 11:02:52 UTC Commit: 589a3429e6f083c67ccb4d2ce5eae967aebd2632 https://github.com/geany/geany/commit/589a3429e6f083c67ccb4d2ce5eae967aebd26...
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).