Branch: refs/heads/master Author: Jiří Techet techet@gmail.com Committer: GitHub noreply@github.com Date: Tue, 14 May 2024 11:45:19 UTC Commit: 2d1b3d5cbc2c33f7371a7bb8393c454398a99759 https://github.com/geany/geany/commit/2d1b3d5cbc2c33f7371a7bb8393c454398a997...
Log Message: ----------- Merge pull request #3859 from techee/ctags_sync2
Sync our ctags to the latest tag version (p6.1.20240421.0)
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/colprint.c ctags/main/ctags.h ctags/main/debug.c ctags/main/debug.h ctags/main/dependency.c ctags/main/dependency.h ctags/main/dependency_p.h ctags/main/e_msoft.h ctags/main/entry.c ctags/main/entry.h ctags/main/error_p.h ctags/main/field.c ctags/main/field.h ctags/main/field_p.h ctags/main/fmt.c ctags/main/general.h ctags/main/htable.c ctags/main/htable.h ctags/main/interval_tree_generic.h ctags/main/keyword.c ctags/main/keyword.h ctags/main/kind.c ctags/main/lregex.c ctags/main/lregex_p.h ctags/main/lxpath.c ctags/main/lxpath.h ctags/main/lxpath_p.h ctags/main/main.c ctags/main/mbcs.c ctags/main/mini-geany.c ctags/main/nestlevel.c ctags/main/nestlevel.h ctags/main/numarray.c ctags/main/numarray.h ctags/main/options.c ctags/main/options_p.h ctags/main/param.c ctags/main/param.h ctags/main/param_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/rbtree.c ctags/main/rbtree.h ctags/main/rbtree_augmented.h ctags/main/read.c ctags/main/read.h ctags/main/read_p.h ctags/main/repoinfo.h ctags/main/routines.c ctags/main/routines.h ctags/main/script.c ctags/main/script_p.h ctags/main/seccomp.c ctags/main/selectors.c ctags/main/selectors.h ctags/main/sort.c ctags/main/strlist.c ctags/main/subparser.h ctags/main/subparser_p.h ctags/main/trace.h ctags/main/trashbox.c ctags/main/types.h ctags/main/unwindi.c ctags/main/utf8_str.c ctags/main/utf8_str.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 ctags/parsers/abaqus.c ctags/parsers/ada.c ctags/parsers/asciidoc.c ctags/parsers/asm.c ctags/parsers/autoit.c ctags/parsers/basic.c ctags/parsers/bibtex.c ctags/parsers/bibtex.h ctags/parsers/clojure.c ctags/parsers/cobol.c ctags/parsers/cpreprocessor.c ctags/parsers/cpreprocessor.h ctags/parsers/css.c ctags/parsers/cxx/cxx.c ctags/parsers/cxx/cxx_debug.c ctags/parsers/cxx/cxx_keyword.c ctags/parsers/cxx/cxx_keyword.h ctags/parsers/cxx/cxx_parser.c ctags/parsers/cxx/cxx_parser_block.c ctags/parsers/cxx/cxx_parser_function.c ctags/parsers/cxx/cxx_parser_internal.h ctags/parsers/cxx/cxx_parser_lambda.c ctags/parsers/cxx/cxx_parser_module.c ctags/parsers/cxx/cxx_parser_namespace.c ctags/parsers/cxx/cxx_parser_template.c ctags/parsers/cxx/cxx_parser_tokenizer.c ctags/parsers/cxx/cxx_parser_typedef.c ctags/parsers/cxx/cxx_parser_using.c ctags/parsers/cxx/cxx_parser_variable.c ctags/parsers/cxx/cxx_qtmoc.c ctags/parsers/cxx/cxx_scope.c ctags/parsers/cxx/cxx_scope.h ctags/parsers/cxx/cxx_side_chain.c ctags/parsers/cxx/cxx_side_chain.h ctags/parsers/cxx/cxx_tag.c ctags/parsers/cxx/cxx_tag.h ctags/parsers/cxx/cxx_token.c ctags/parsers/cxx/cxx_token.h ctags/parsers/cxx/cxx_token_chain.c ctags/parsers/cxx/cxx_token_chain.h ctags/parsers/diff.c ctags/parsers/erlang.c ctags/parsers/flex.c ctags/parsers/fortran.c ctags/parsers/gdscript.c ctags/parsers/geany_lcpp.h ctags/parsers/geany_matlab.c ctags/parsers/go.c ctags/parsers/haskell.c ctags/parsers/haxe.c ctags/parsers/html.c ctags/parsers/iniconf.c ctags/parsers/jscript.c ctags/parsers/jscript.h ctags/parsers/json.c ctags/parsers/julia.c ctags/parsers/ldscript.c ctags/parsers/lisp.c ctags/parsers/lua.c ctags/parsers/make.c ctags/parsers/markdown.c ctags/parsers/markdown.h ctags/parsers/matlab.c ctags/parsers/nsis.c ctags/parsers/objc.c ctags/parsers/ocaml.c ctags/parsers/pascal.c ctags/parsers/perl.c ctags/parsers/perl.h ctags/parsers/php.c ctags/parsers/powershell.c ctags/parsers/python.c ctags/parsers/r.c ctags/parsers/raku.c ctags/parsers/rst.c ctags/parsers/ruby.c ctags/parsers/ruby.h ctags/parsers/rust.c ctags/parsers/sh.c ctags/parsers/sh.h ctags/parsers/sql.c ctags/parsers/tcl.c ctags/parsers/tcloo.c ctags/parsers/tex.c ctags/parsers/typescript.c ctags/parsers/verilog.c ctags/parsers/vhdl.c meson.build src/tagmanager/tm_parser.c src/tagmanager/tm_parser.h src/tagmanager/tm_parsers.h tests/ctags/1795612.js.tags tests/ctags/1850914.js.tags tests/ctags/1878155.js.tags tests/ctags/1880687.js.tags tests/ctags/3470609.js.tags tests/ctags/Makefile.am tests/ctags/arraylist.js.tags tests/ctags/bracematch.js.tags tests/ctags/bug1950327.js.tags tests/ctags/bug2888482.js.tags tests/ctags/bug3571233.js.tags tests/ctags/class.ps1 tests/ctags/class.ps1.tags tests/ctags/complex-return.js.tags tests/ctags/enum.ps1 tests/ctags/enum.ps1.tags tests/ctags/js-class-related-unterminated.js.tags tests/ctags/js-const.js.tags tests/ctags/js-let.js.tags tests/ctags/js-string-continuation.js.tags tests/ctags/js-unknown-construct-nesting.js.tags tests/ctags/jsFunc_tutorial.js.tags tests/ctags/masm.asm.tags tests/ctags/matlab_backtracking.m.tags tests/ctags/matlab_test.m.tags tests/ctags/namespace.bas tests/ctags/namespace.bas.tags tests/ctags/parenthesis-rvalue.js.tags tests/ctags/secondary_fcn_name.js.tags tests/ctags/simple.js tests/ctags/simple.js.tags tests/ctags/simple.rst tests/ctags/simple.rst.tags tests/ctags/ui5.controller.js.tags tests/meson.build
Modified: ctags/Makefile.am 16 lines changed, 14 insertions(+), 2 deletions(-) =================================================================== @@ -23,6 +23,7 @@ parsers = \ parsers/cxx/cxx_parser.h \ parsers/cxx/cxx_parser_internal.h \ parsers/cxx/cxx_parser_lambda.c \ + parsers/cxx/cxx_parser_module.c \ parsers/cxx/cxx_parser_namespace.c \ parsers/cxx/cxx_parser_template.c \ parsers/cxx/cxx_parser_tokenizer.c \ @@ -32,6 +33,8 @@ parsers = \ parsers/cxx/cxx_qtmoc.c \ parsers/cxx/cxx_scope.c \ parsers/cxx/cxx_scope.h \ + parsers/cxx/cxx_side_chain.c \ + parsers/cxx/cxx_side_chain.h \ parsers/cxx/cxx_subparser.c \ parsers/cxx/cxx_subparser.h \ parsers/cxx/cxx_subparser_internal.h \ @@ -51,6 +54,7 @@ parsers = \ parsers/autoit.c \ parsers/basic.c \ parsers/bibtex.c \ + parsers/bibtex.h \ parsers/geany_c.c \ parsers/clojure.c \ parsers/cobol.c \ @@ -69,33 +73,37 @@ parsers = \ parsers/haxe.c \ parsers/html.c \ parsers/jscript.c \ + parsers/jscript.h \ parsers/json.c \ parsers/julia.c \ parsers/geany_lcpp.c \ parsers/geany_lcpp.h \ + parsers/ldscript.c \ parsers/lisp.c \ parsers/lua.c \ parsers/make.c \ parsers/make.h \ parsers/markdown.c \ parsers/markdown.h \ - parsers/geany_matlab.c \ + parsers/matlab.c \ parsers/nsis.c \ parsers/objc.c \ parsers/ocaml.c \ parsers/pascal.c \ parsers/perl.c \ parsers/perl.h \ - parsers/perl6.c \ parsers/php.c \ parsers/powershell.c \ parsers/python.c \ parsers/r.c \ parsers/r.h \ + parsers/raku.c \ parsers/rst.c \ parsers/ruby.c \ + parsers/ruby.h \ parsers/rust.c \ parsers/sh.c \ + parsers/sh.h \ parsers/sql.c \ parsers/tcl.c \ parsers/tcl.h \ @@ -148,6 +156,7 @@ libctags_la_SOURCES = \ main/htable.h \ main/inline.h \ main/interactive_p.h \ + main/interval_tree_generic.h \ main/keyword.c \ main/keyword.h \ main/keyword_p.h \ @@ -195,6 +204,7 @@ libctags_la_SOURCES = \ main/ptrarray.h \ main/rbtree.c \ main/rbtree.h \ + main/rbtree_augmented.h \ main/read.c \ main/read.h \ main/read_p.h \ @@ -226,6 +236,8 @@ libctags_la_SOURCES = \ main/types.h \ main/unwindi.c \ main/unwindi.h \ + main/utf8_str.c \ + main/utf8_str.h \ main/vstring.c \ main/vstring.h \ main/writer-ctags.c \
Modified: ctags/dsl/es.c 37 lines changed, 30 insertions(+), 7 deletions(-) =================================================================== @@ -30,6 +30,7 @@ #include <string.h> #include <errno.h> #include <limits.h> +#include <math.h>
#include <regex.h>
@@ -822,7 +823,6 @@ es_symbol_print(const EsObject* object, MIO* fp) unsigned char cc; unsigned char mask; int needs_bar; - int i;
string = es_symbol_get(object); if (!string) @@ -840,7 +840,7 @@ es_symbol_print(const EsObject* object, MIO* fp) { /* 0 => 1? */ mask = 0x2; - for (i = 0; i< len; i++) + for (size_t i = 0; i< len; i++) { c = string[i]; cc = get_char_class(c); @@ -854,7 +854,7 @@ es_symbol_print(const EsObject* object, MIO* fp) if (needs_bar) mio_printf(fp, "|");
- for (i = 0; i < len; i++) + for (size_t i = 0; i < len; i++) { c = string[i]; if (c == '\' || c == '|') @@ -1028,7 +1028,7 @@ es_string_print(const EsObject* object, MIO* fp) const char* string; char c; size_t len; - int i; + size_t i;
string = es_string_get(object); @@ -1352,6 +1352,29 @@ es_regex_exec (const EsObject* regex, 0, NULL, 0)? es_false: es_true; }
+EsObject* +es_regex_exec_extract_match_new (const EsObject* regex, + const EsObject* str, + unsigned int group) +{ + EsObject *r; + regmatch_t *pmatch = calloc(group + 1, sizeof(regmatch_t)); + if (!pmatch) + return ES_ERROR_MEMORY; + + const char *s = es_string_get (str); + if (regexec(((EsRegex*)regex)->code, s, group + 1, pmatch, 0)) + r = es_false; + else + r = pmatch[group].rm_so == -1 + ? es_nil: + es_string_newL(s + pmatch[group].rm_so, + pmatch[group].rm_eo - pmatch[group].rm_so); + + free (pmatch); + return r; +} + /* * Error */ @@ -2167,7 +2190,7 @@ static void dump_token (MIO* stream, const char* prefix, Token* seed) { const char* buf; - int i; + size_t i; char c;
@@ -2562,8 +2585,8 @@ is_real (const char* cstr, return 0; else if (*endptr != '\0') return 0; - - /* TODO: INF, NAN... */ + else if (isinf(*d) || isnan(*d)) + return 0; return 1; }
Modified: ctags/dsl/es.h 6 lines changed, 6 insertions(+), 0 deletions(-) =================================================================== @@ -159,6 +159,12 @@ int es_regex_p (const EsObject* object); EsObject* es_regex_exec (const EsObject* regex, const EsObject* str);
+/* Return #f if unmatched. + * Retrun NIL is the associate group is not in REGEX. */ +EsObject* es_regex_exec_extract_match_new (const EsObject* regex, + const EsObject* str, + unsigned int group); + /* * Foreign pointer */
Modified: ctags/dsl/optscript.c 240 lines changed, 180 insertions(+), 60 deletions(-) =================================================================== @@ -153,6 +153,7 @@ static EsObject* OPT_KEY_dstack; */
static EsObject* array_new (unsigned int attr); +static EsObject* array_shared_new (EsObject* original, unsigned int attr);
static EsObject* array_es_init_fat (void *fat, void *ptr, void *extra); static void array_es_free (void *ptr, void *fat); @@ -374,7 +375,9 @@ declop(execstack); * tested in typeattrconv.ps */ declop(type); declop(cvn); -/* cvlit, cvx, xcheck, executeonly, noacess, readonly, +declop(cvs); +declop(cvx); +/* cvlit, xcheck, executeonly, noacess, readonly, rcheck, wcheck, cvi, cvr, cvrs, cvs,... */
/* Operators for Virtual Memory Operators */ @@ -473,8 +476,8 @@ opt_init (void)
defOP (opt_system_dict, op_mark, "<<", 0, "- << mark"); defOP (opt_system_dict, op_mark, "[", 0, "- [ mark"); - defOP (opt_system_dict, op__make_array, "]", 1, "[ any1 ... anyn ] array"); - defOP (opt_system_dict, op__make_dict , ">>", 1, "<< key1 value1 ... keyn valuen >> dict"); + defOP (opt_system_dict, op__make_array, "]", 0, "[ any1 ... anyn ] array"); + defOP (opt_system_dict, op__make_dict , ">>", 0, "<< key1 value1 ... keyn valuen >> dict");
defop (opt_system_dict, _help, 0, "- _HELP -"); defop (opt_system_dict, pstack, 0, "|- any1 ... anyn PSTACK |- any1 ... anyn"); @@ -567,6 +570,8 @@ opt_init (void)
defop (opt_system_dict, type, 1, "any TYPE name"); defop (opt_system_dict, cvn, 1, "string CVN name"); + defop (opt_system_dict, cvs, 2, "any string CVS string"); + defop (opt_system_dict, cvx, 1, "any CVX any");
defop (opt_system_dict, null, 0, "- NULL null"); defop (opt_system_dict, bind, 1, "proc BIND proc"); @@ -642,12 +647,13 @@ opt_vm_new (MIO *in, MIO *out, MIO *err) }
void -opt_vm_clear (OptVM *vm) +opt_vm_clear (OptVM *vm, bool clear_app_data) { ptrArrayClear (vm->estack); ptrArrayClear (vm->ostack); vm_dstack_clear (vm); - vm->app_data = NULL; + if (clear_app_data) + vm->app_data = NULL; dict_op_clear (vm->error); }
@@ -1155,7 +1161,7 @@ name_or_number_new (const char* s, void *data) const char *t = s; while (*t) { - if (!isdigit ((int)*t)) + if (!isdigit ((unsigned char) *t)) { number = false; break; @@ -1970,6 +1976,14 @@ array_new (unsigned int attr) return es_fatptr_new (OPT_TYPE_ARRAY, a, &attr); }
+static EsObject* +array_shared_new (EsObject* original, unsigned int attr) +{ + ptrArray *a = es_pointer_get (original); + ptrArrayRef (a); + return es_fatptr_new (OPT_TYPE_ARRAY, a, &attr); +} + static EsObject* array_es_init_fat (void *fat, void *ptr, void *extra) { @@ -1988,9 +2002,6 @@ array_es_free (void *ptr, void *fat) static int array_es_equal (const void *a, const void *afat, const void *b, const void *bfat) { - if (((ArrayFat *)afat)->attr != ((ArrayFat *)bfat)->attr) - return 0; - if (ptrArrayIsEmpty ((ptrArray *)a) && ptrArrayIsEmpty ((ptrArray*)b)) return 1; else if (a == b) @@ -2126,7 +2137,11 @@ dict_op_def (EsObject* dict, EsObject *key, EsObject *val) key = es_object_ref (key); val = es_object_ref (val);
- hashTableUpdateItem (t, key, val); + if (hashTableUpdateOrPutItem (t, key, val)) + { + /* A key in the hashtable is reused. */ + es_object_unref (key); + } }
static bool @@ -2423,13 +2438,16 @@ GEN_PRINTER(op__print, vm_print_full (vm, elt, true, 0)) static EsObject* op__make_array (OptVM *vm, EsObject *name) { - int n = vm_ostack_counttomark (vm); - if (n < 0) + int n0 = vm_ostack_counttomark (vm); + if (n0 < 0) return OPT_ERR_UNMATCHEDMARK; + unsigned int n = (unsigned int)n0;
unsigned int count = vm_ostack_count (vm); + Assert(count > n); + EsObject *a = array_new (ATTR_READABLE | ATTR_WRITABLE); - for (int i = (int)(count - n); i < count; i++) + for (unsigned int i = count - n; i < count; i++) { EsObject *elt = ptrArrayItem (vm->ostack, i); array_op_add (a, elt); @@ -2461,7 +2479,14 @@ op__make_dict (OptVM *vm, EsObject *name) return OPT_ERR_TYPECHECK; }
- EsObject *d = dict_new (n % 2 + 1, ATTR_READABLE|ATTR_WRITABLE); /* FIXME: + 1 */ + /* A hashtable grows automatically when its filling rate is + * grater than 80%. If we put elements between `<<' and `>>' to a dictionary + * initialized with the size equal to the number of elements, the dictionary + * grows once during putting them. Making a 1/0.8 times larger dictionary can + * avoid the predictable growing. */ + int size = (10 * (n > 0? (n / 2): 1)) / 8; + + EsObject *d = dict_new (size, ATTR_READABLE|ATTR_WRITABLE); for (int i = 0; i < (n / 2); i++) { EsObject *val = ptrArrayLast (vm->ostack); @@ -2692,18 +2717,19 @@ op_copy (OptVM *vm, EsObject *name) if (!es_integer_p (nobj)) return op__copy_compound (vm, name, c, nobj);
- int n = es_integer_get (nobj); - if (n < 0) + int n0 = es_integer_get (nobj); + if (n0 < 0) return OPT_ERR_RANGECHECK; + unsigned int n = (unsigned int)n0;
c--;
- if (((int)c) - n < 0) + if (c < n) return OPT_ERR_UNDERFLOW;
ptrArrayDeleteLast(vm->ostack);
- for (int i = c - n; i < c; i++) + for (unsigned int i = c - n; i < c; i++) { EsObject * elt = ptrArrayItem (vm->ostack, i); vm_ostack_push (vm, elt); @@ -2751,6 +2777,8 @@ op_roll (OptVM *vm, EsObject *name) if (!es_integer_p (nobj)) return OPT_ERR_TYPECHECK; int n = es_integer_get (nobj); + if (n < 0) + return OPT_ERR_RANGECHECK;
if ((((int)c) - 2) < n) return OPT_ERR_UNDERFLOW; @@ -3026,8 +3054,10 @@ op_dict (OptVM *vm, EsObject *name) return OPT_ERR_TYPECHECK;
int n = es_integer_get (nobj); - if (n < 1) + if (n < 0) return OPT_ERR_RANGECHECK; + else if (n == 0) + n = 1;
ptrArrayDeleteLast (vm->ostack);
@@ -3728,7 +3758,7 @@ op_repeat (OptVM *vm, EsObject *name) ptrArrayDeleteLast (vm->ostack); ptrArrayDeleteLast (vm->ostack);
- EsObject *e = es_false;; + EsObject *e = es_false; for (int i = 0; i < n; i++) { e = vm_call_proc (vm, proc); @@ -3812,10 +3842,9 @@ op_for (OptVM *vm, EsObject *name) /* * Operators for type, attribute and their conversion */ -static EsObject* -op_type (OptVM *vm, EsObject *name) +static const char* +get_type_name (EsObject *o) { - EsObject *o = ptrArrayRemoveLast (vm->ostack); const char *n;
if (o == es_nil) @@ -3830,6 +3859,17 @@ op_type (OptVM *vm, EsObject *name) n = es_type_get_name (t); }
+ return n; +} + +static EsObject* +op_type (OptVM *vm, EsObject *name) +{ + EsObject *o = ptrArrayRemoveLast (vm->ostack); + const char *n; + + n = get_type_name (o); + EsObject *p = name_newS (n, ATTR_EXECUTABLE|ATTR_READABLE); vm_ostack_push (vm, p); es_object_unref (p); @@ -3854,6 +3894,85 @@ op_cvn (OptVM *vm, EsObject *name) return es_false; }
+static EsObject * +op_cvs (OptVM *vm, EsObject *name) +{ + EsObject *o = ptrArrayLast (vm->ostack); + if (es_object_get_type (o) != OPT_TYPE_STRING) + return OPT_ERR_TYPECHECK; + + EsObject *any = ptrArrayItemFromLast (vm->ostack, 1); + vString *vstr = es_pointer_get (o); + int t = es_object_get_type (any); + + if (t == OPT_TYPE_STRING) + { + vString *vany = es_pointer_get (any); + vStringCopy (vstr, vany); + } + else if (t == OPT_TYPE_NAME || t == ES_TYPE_SYMBOL) + { + if (t == OPT_TYPE_NAME) + any = es_pointer_get (any); + + const char *cany = es_symbol_get (any); + vStringCopyS (vstr, cany); + } + else if (t == ES_TYPE_INTEGER) + { + int iany = es_integer_get (any); +#define buf_len 13 + char buf[buf_len]; + if (!(snprintf (buf, buf_len, "%d", iany) > 0)) + buf [0] = '\0'; + vStringCopyS (vstr, buf); + } + else if (t == ES_TYPE_BOOLEAN) + vStringCopyS (vstr, any == es_true? "true": "false"); + else + { + const char *type_name = get_type_name (any); + vStringCopyS (vstr, "--"); + vStringCatS (vstr, type_name); + vStringCatS (vstr, "--"); + } + + es_object_ref (o); + ptrArrayDeleteLastInBatch (vm->ostack, 2); + vm_ostack_push (vm, o); + es_object_unref (o); + + return es_false; +} + +static EsObject* +op_cvx (OptVM *vm, EsObject *name) +{ + EsObject *o = ptrArrayLast (vm->ostack); + + if (es_object_get_type (o) == OPT_TYPE_ARRAY + && (! (((ArrayFat *)es_fatptr_get (o))->attr & ATTR_EXECUTABLE))) + { + EsObject *xarray = array_shared_new (o, + ((ArrayFat *)es_fatptr_get (o))->attr | ATTR_EXECUTABLE); + ptrArrayDeleteLast (vm->ostack); + vm_ostack_push (vm, xarray); + es_object_unref(xarray); + + } + else if (es_object_get_type (o) == OPT_TYPE_NAME + && (! (((NameFat *)es_fatptr_get (o))->attr & ATTR_EXECUTABLE))) + { + EsObject *symbol = es_pointer_get (o); + EsObject *xname = name_new (symbol, ((NameFat *)es_fatptr_get (o))->attr | ATTR_EXECUTABLE); + ptrArrayDeleteLast (vm->ostack); + vm_ostack_push (vm, xname); + es_object_unref(xname); + } + + return es_false; +} + /* * Misc operators @@ -4066,7 +4185,7 @@ op__put_str (OptVM *vm, EsObject *name, for (size_t i = 0; i < d; i++) vStringPut (vstr, ' '); if (c != 0) - vStringPut (vstr, (char)c); + vStringPut (vstr, c); }
ptrArrayDeleteLastInBatch (vm->ostack, 3); @@ -4097,11 +4216,9 @@ op__forall_array (OptVM *vm, EsObject *name, { ptrArray *a = es_pointer_get (obj); unsigned int c = ptrArrayCount (a); - if (((int)c) < 0) - return OPT_ERR_INTERNALERROR; /* TODO: integer overflow */
EsObject *e = es_false; - for (int i = 0; i < c; i++) + for (unsigned int i = 0; i < c; i++) { EsObject *o = ptrArrayItem (a, i); es_object_ref (o); @@ -4154,7 +4271,7 @@ static EsObject* op__forall_dict (OptVM *vm, EsObject *name, EsObject *proc, EsObject *obj) { - EsObject *r = es_false;; + EsObject *r = es_false; hashTable *ht = es_pointer_get (obj); struct dictForallData data = { .vm = vm, @@ -4173,11 +4290,9 @@ op__forall_string (OptVM *vm, EsObject *name, { vString *s = es_pointer_get (obj); unsigned int c = vStringLength (s); - if (((int)c) < 0) - return OPT_ERR_INTERNALERROR; /* TODO: integer overflow */
EsObject *e = es_false; - for (int i = 0; i < c; i++) + for (unsigned int i = 0; i < c; i++) { unsigned char chr = vStringChar (s, i); EsObject *o = es_integer_new (chr); @@ -4229,23 +4344,24 @@ op_forall (OptVM *vm, EsObject *name)
static EsObject* op__putinterval_array (OptVM *vm, EsObject *name, - ptrArray *srca, int index, ptrArray *dsta) + ptrArray *srca, unsigned int index, ptrArray *dsta) { unsigned int dlen = ptrArrayCount (dsta); unsigned int slen = ptrArrayCount (srca); if (dlen > index) { - if ((dlen - index) <= slen) + unsigned d = dlen - index; + if (d <= slen) { - ptrArrayDeleteLastInBatch (dsta, dlen - index); + ptrArrayDeleteLastInBatch (dsta, d); for (unsigned int i = 0; i < slen; i++) ptrArrayAdd (dsta, es_object_ref (ptrArrayItem (srca, i))); return es_false; } else { - for (size_t i = 0; i < slen; i++) - ptrArrayUpdate (dsta, ((size_t)index) + i, + for (unsigned int i = 0; i < slen; i++) + ptrArrayUpdate (dsta, index + i, es_object_ref (ptrArrayItem (srca, i)), es_nil); return es_false; @@ -4263,21 +4379,22 @@ op__putinterval_array (OptVM *vm, EsObject *name,
static EsObject* op__putinterval_string (OptVM *vm, EsObject *name, - vString *srcv, int index, vString *dstv) + vString *srcv, unsigned int index, vString *dstv) { - size_t dlen = vStringLength (dstv); + unsigned int dlen = vStringLength (dstv); if (dlen > index) { - size_t slen = vStringLength (srcv); - if ((dlen - index) <= slen) + unsigned int d = dlen - index; + unsigned int slen = vStringLength (srcv); + if (d <= slen) { - vStringTruncate (dstv, (size_t)index); + vStringTruncate (dstv, index); vStringCat (dstv, srcv); return es_false; } else { - for (size_t i = 0; i < slen; i++) + for (unsigned int i = 0; i < slen; i++) vStringChar (dstv, index + i) = vStringChar (srcv, i); return es_false; } @@ -4309,9 +4426,10 @@ op_putinterval (OptVM *vm, EsObject *name) else return OPT_ERR_TYPECHECK;
- int index = es_integer_get (indexobj); - if (index < 0) + int index0 = es_integer_get (indexobj); + if (index0 < 0) return OPT_ERR_RANGECHECK; + unsigned int index = (size_t)index0;
EsObject *r; if (t == OPT_TYPE_ARRAY) @@ -4334,39 +4452,39 @@ op_putinterval (OptVM *vm, EsObject *name) static EsObject* op__copyinterval_array (OptVM *vm, EsObject *name, ptrArray *dsta, - int count, - int index, + unsigned int count, + unsigned int index, ptrArray *srca) { - unsigned long srcl = ptrArrayCount (srca); + unsigned int srcl = ptrArrayCount (srca);
- if ((unsigned long)index > srcl) + if (index > srcl) return OPT_ERR_RANGECHECK;
- if ((unsigned long)(index + count) > srcl) + if ((index + count) > srcl) return OPT_ERR_RANGECHECK;
- for (unsigned int i = (unsigned int)index; i < index + count; i++) + for (unsigned int i = index; i < index + count; i++) ptrArrayAdd (dsta, es_object_ref (ptrArrayItem (srca, i))); return es_false; }
static EsObject* op__copyinterval_string (OptVM *vm, EsObject *name, vString *dsts, - int count, - int index, + unsigned int count, + unsigned int index, vString *srcs) { - size_t srcl = vStringLength (srcs); + unsigned int srcl = vStringLength (srcs);
- if ((size_t)index > srcl) + if (index > srcl) return OPT_ERR_RANGECHECK;
- if ((size_t)(index + count) > srcl) + if ((index + count) > srcl) return OPT_ERR_RANGECHECK;
- vStringNCatSUnsafe (dsts, vStringValue (srcs) + index, (size_t)count); + vStringNCatSUnsafe (dsts, vStringValue (srcs) + index, count); return es_false; }
@@ -4389,13 +4507,15 @@ op__copyinterval (OptVM *vm, EsObject *name) if (!es_integer_p (indexobj)) return OPT_ERR_TYPECHECK;
- int count = es_integer_get (countobj); - if (count < 0) + int count0 = es_integer_get (countobj); + if (count0 < 0) return OPT_ERR_RANGECHECK; + unsigned int count = (unsigned int)count0;
- int index = es_integer_get (indexobj); - if (index < 0) + int index0 = es_integer_get (indexobj); + if (index0 < 0) return OPT_ERR_RANGECHECK; + unsigned int index = (size_t)index0;
EsObject* r; if (t == OPT_TYPE_ARRAY)
Modified: ctags/dsl/optscript.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -41,7 +41,7 @@ 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_clear (OptVM *vm, bool clear_app_data); void opt_vm_dstack_push (OptVM *vm, EsObject *dict); void opt_vm_dstack_pop (OptVM *vm);
Modified: ctags/main/CommonPrelude.c 96 lines changed, 96 insertions(+), 0 deletions(-) =================================================================== @@ -119,6 +119,27 @@ const char ctagsCommonPrelude []= " exch copy pop\n" "} __bddef\n" "\n" +"(string _CHOP string)\n" +"/_chop {\n" +" mark exch {} forall pop _buildstring\n" +"} __bddef\n" +"\n" +"(string _CHOP_SPACE string)\n" +"/_chop_space {\n" +" dup length dup 0 gt {\n" +" % string length\n" +" 1 sub\n" +" % string `length - 1`\n" +" 1 index exch\n" +" % string string `length - 1`\n" +" get (\n\t\r\f\v ) exch _amember {\n" +" _chop\n" +" } if\n" +" } {\n" +" pop % pop the length\n" +" } ifelse\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" @@ -159,4 +180,79 @@ const char ctagsCommonPrelude []= " } forall\n" " pop\n" "} __bddef\n" +"\n" +"(array key _AINDEX nth:int true\n" +" array key _AINDEX false)\n" +"/_aindex {\n" +" 0 3 1 roll\n" +" % idx array key\n" +" exch {\n" +" % idx key elt\n" +" 1 index\n" +" eq {\n" +" % idx key\n" +" pop true exit\n" +" } {\n" +" % idx key\n" +" exch 1 add exch\n" +" } ifelse\n" +" } forall\n" +" dup true ne { pop pop false } if\n" +"} __bddef\n" +"\n" +"% define @1 ~ @9.\n" +"1 1 9 {\n" +" dup\n" +" mark (- @) 3 -1 roll ?0 add ( start:matchloc) _buildstring\n" +" exch dup\n" +" mark (@) 3 -1 roll ?0 add _buildstring cvn\n" +" exch\n" +" [ exch /start /_matchloc cvx ] cvx __bddef\n" +"} for\n" +"\n" +"% define 1@ ~ 9@.\n" +"1 1 9 {\n" +" dup\n" +" mark (- ) 3 -1 roll ?0 add (@ end:matchloc) _buildstring\n" +" exch dup\n" +" mark exch ?0 add (@) _buildstring cvn\n" +" exch\n" +" [ exch /end /_matchloc cvx ] cvx __bddef\n" +"} for\n" +"\n" +"(name:str kind:name matchloc _TAG tag\n" +" name:str kind:name _TAG tag)\n" +"/_tag {\n" +" dup type /nametype eq {\n" +" % name:str kind:name\n" +" null exch null\n" +" % name:str null kind:name null\n" +" } {\n" +" % name:str kind:name matchloc\n" +" null 3 1 roll null exch\n" +" % name:str null kind:name matchloc null\n" +" } ifelse\n" +" _foreignreftag\n" +"} __bddef\n" +"\n" +"(name:str kind:name role:name matchloc _REFTAG tag\n" +" name:str kind:name role:name _REFTAG tag)\n" +"/_reftag {\n" +" dup type /nametype eq {\n" +" % name:str kind:name role:name\n" +" null 3 1 roll\n" +" % name:str null kind:name role:name\n" +" } {\n" +" % name:str kind:name role:name matchloc\n" +" null 4 1 roll\n" +" % name:str null kind:name role:name matchloc\n" +" } ifelse\n" +" _foreignreftag\n" +"} __bddef\n" +"\n" +"(name:str language:name kind:name matchloc _FOREIGNTAG tag\n" +" name:str lang:name kind:name _FOREIGNTAG tag)\n" +"/_foreigntag {\n" +" null _foreignreftag\n" +"} __bddef\n" ;
Modified: ctags/main/args.c 6 lines changed, 3 insertions(+), 3 deletions(-) =================================================================== @@ -31,7 +31,7 @@ static char *nextStringArg (const char** const next) const char* start;
Assert (*next != NULL); - for (start = *next ; isspace ((int) *start) ; ++start) + for (start = *next ; isspace ((unsigned char) *start) ; ++start) ; if (*start == '\0') *next = start; @@ -40,7 +40,7 @@ static char *nextStringArg (const char** const next) size_t length; const char* end;
- for (end = start ; *end != '\0' && ! isspace ((int) *end) ; ++end) + for (end = start; *end != '\0' && ! isspace ((unsigned char) *end); ++end) ; length = end - start; Assert (length > 0); @@ -156,7 +156,7 @@ static char* nextFileLine (FILE* const fp)
static bool isCommentLine (char* line) { - while (isspace(*line)) + while (isspace((unsigned char) *line)) ++line; return (*line == '#'); }
Modified: ctags/main/colprint.c 11 lines changed, 7 insertions(+), 4 deletions(-) =================================================================== @@ -27,7 +27,7 @@ enum colprintJustification { struct colprintHeaderColumn { vString *value; enum colprintJustification justification; - unsigned int maxWidth; + size_t maxWidth; bool needPrefix; };
@@ -36,7 +36,7 @@ struct colprintTable { ptrArray *lines; };
-static void fillWithWhitespaces (int i, FILE *fp) +static void fillWithWhitespaces (size_t i, FILE *fp) { while (i-- > 0) { @@ -119,7 +119,7 @@ void colprintTableDelete (struct colprintTable *table)
static void colprintColumnPrintGeneric (vString *column, struct colprintHeaderColumn *spec, bool machinable, FILE *fp) { - int maxWidth = spec->maxWidth + (spec->needPrefix? 1: 0); + size_t maxWidth = spec->maxWidth + (spec->needPrefix? 1: 0);
if ((column == spec->value) && (spec->needPrefix)) { @@ -135,7 +135,10 @@ static void colprintColumnPrintGeneric (vString *column, struct colprintHeaderCo } else { - int padLen = maxWidth - vStringLength (column); + size_t padLen = 0; + size_t colLen = vStringLength (column); + if (colLen < maxWidth) + padLen = maxWidth - colLen; if (spec->justification == COLPRINT_LEFT || spec->justification == COLPRINT_LAST) {
Modified: ctags/main/ctags.h 50 lines changed, 48 insertions(+), 2 deletions(-) =================================================================== @@ -14,16 +14,62 @@ /* * MACROS */ + +/* VERSION.REVISION.PATCH: + + For incompatible changes for the command line interface (CLI) + of ctags or readtags commands, increment VERSION. + Removing a parameter of a parser is part of incompatible change + for the CLI. + When OUTPUT_VERSION_AGE set to 0, increment VERSION. Set REVISION + and PATCH to 0. + For changing setting versionAge member of a parser, increment + VERSION. Set REVISION and PATCH to 0. + When chaging VERSION, set REVISION and PATCH to 0. + + For uppper compatible changes for the CLI, + increment REVISION. + Adding a new parameter to a parser is an uppper compatible change. + When incrementing OUTPUT_VERSION_CURRENT but not setting + OUTPUT_VERSION_AGE to 0, increment REVISION. + For changing increment versionCurrent member of a parser but not + setting versionAge to 0, increment REVISION. + When changing REVISION, set PATCH to 0. + + For implementation changes like bug fixes, increment PATCH. */ + #if defined (HAVE_CONFIG_H) +/* You must update PACKAGE_VERSION in configure.ac, too. + * The --version option of readtags also prints this. */ # define PROGRAM_VERSION PACKAGE_VERSION #else -# define PROGRAM_VERSION "5.9.0" +# define PROGRAM_VERSION "6.1.0" #endif #define PROGRAM_NAME "Universal Ctags" #define PROGRAM_URL "https://ctags.io/" -#define PROGRAM_COPYRIGHT "Copyright (C) 2015" +#define PROGRAM_COPYRIGHT "Copyright (C) 2015-2023" #define AUTHOR_NAME "Universal Ctags Team"
+/* The concept of CURRENT and AGE is taken from libtool. + * However, we deleted REVISION in libtool when importing + * the concept of versioning from libtool. + * + * If common fields, common extras, pseudo tags have been added, + * removed or changed since last release, increment CURRENT. + * If they have been added since last release, increment AGE. + * If they have been removed since last release, set AGE to 0 + * + * From the command line of ctags, you can see the version + * information with --version and --version=NONE. + * + * In the tags file, !_TAGS_OUTPUT_VERSION shows the the version. + * + * Chaning for the command line interface, and implementation changes + * like bug fixes don't affect the CURRENT an AGE. + */ +#define OUTPUT_VERSION_CURRENT 0 +#define OUTPUT_VERSION_AGE 0 + /* * Constant */
Modified: ctags/main/debug.c 5 lines changed, 1 insertions(+), 4 deletions(-) =================================================================== @@ -51,10 +51,7 @@ extern void debugPutc (const int level, const int c) { if (debug (level) && c != EOF) { - if (c == STRING_SYMBOL) printf (""string""); - else if (c == CHAR_SYMBOL) printf ("'c'"); - else putchar (c); - + putchar (c); fflush (stdout); } }
Modified: ctags/main/debug.h 14 lines changed, 9 insertions(+), 5 deletions(-) =================================================================== @@ -24,6 +24,15 @@ * Macros */
+#if defined _MSC_VER +/* See https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros */ +# define ASSERT_FUNCTION __FUNCTION__ +#elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define ASSERT_FUNCTION __func__ +#else +# define ASSERT_FUNCTION ((const char*)0) +#endif + #ifdef DEBUG # define debug(level) ((ctags_debugLevel & (long)(level)) != 0) # define DebugStatement(x) x @@ -33,11 +42,6 @@ # define AssertNotReached() do {} while(0) # else /* We expect cc supports c99 standard. */ -# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -# define ASSERT_FUNCTION __func__ -# else -# define ASSERT_FUNCTION ((const char*)0) -# endif # define Assert(c) ((c) ? ((void)0) : debugAssert(#c, __FILE__, __LINE__, ASSERT_FUNCTION)) # define AssertNotReached() Assert(!"The control reaches unexpected place") # endif
Modified: ctags/main/dependency.c 26 lines changed, 23 insertions(+), 3 deletions(-) =================================================================== @@ -43,7 +43,7 @@ extern void linkDependencyAtInitializeParsing (depType dtype, { if (dtype == DEPTYPE_KIND_OWNER) linkKindDependency (masterKCB, slaveKCB); - else if (dtype == DEPTYPE_SUBPARSER) + else if (dtype == DEPTYPE_SUBPARSER || dtype == DEPTYPE_FOREIGNER) { slaveParser *s = xMalloc (1, slaveParser);
@@ -118,8 +118,9 @@ extern void initializeDependencies (parserDefinition *parser, for (i = 0; i < parser->dependencyCount; i++) { parserDependency *d = parser->dependencies + i; - if (d->type == DEPTYPE_SUBPARSER && - ((subparser *)(d->data))->direction & SUBPARSER_SUB_RUNS_BASE) + if ((d->type == DEPTYPE_SUBPARSER && + ((subparser *)(d->data))->direction & SUBPARSER_SUB_RUNS_BASE) + || (d->type == DEPTYPE_FOREIGNER)) { langType baseParser; baseParser = getNamedLanguage (d->upperParser, 0); @@ -320,6 +321,12 @@ extern void subparserColprintAddSubparsers (struct colprintTable *table, pushLanguage (scb->owner); foreachSlaveParser(tmp) { + if (tmp->type != DEPTYPE_SUBPARSER) + continue; + + if (!isLanguageVisible (tmp->id)) + continue; + struct colprintLine *line = colprintTableGetNewLine(table);
colprintLineAppendColumnCString (line, getLanguageName (tmp->id)); @@ -368,3 +375,16 @@ extern void subparserColprintTablePrint (struct colprintTable *table, colprintTableSort (table, subparserColprintCompareLines); colprintTablePrint (table, 0, withListHeader, machinable, fp); } + +extern const char *dependencyTypeString(enum eDepType e) +{ /* Generated by misc/enumstr.sh with cmdline: + misc/enumstr.sh main/dependency.h eDepType dependencyTypeString DEPTYPE_ */ + switch (e) + { + case DEPTYPE_KIND_OWNER: return "KIND_OWNER"; + case DEPTYPE_SUBPARSER: return "SUBPARSER"; + case DEPTYPE_FOREIGNER: return "FOREIGNER"; + case COUNT_DEPTYPES: return "COUNT_DEPTYPES"; + default: return "UNKNOWN"; + } +}
Modified: ctags/main/dependency.h 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -26,6 +26,7 @@ typedef enum eDepType { DEPTYPE_KIND_OWNER, DEPTYPE_SUBPARSER, + DEPTYPE_FOREIGNER, COUNT_DEPTYPES, } depType;
Modified: ctags/main/dependency_p.h 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -55,4 +55,5 @@ extern void finalizeDependencies (parserDefinition *parser, extern slaveParser *getFirstSlaveParser(struct slaveControlBlock *controlBlock); extern slaveParser *getNextSlaveParser(slaveParser *last);
+extern const char *dependencyTypeString(enum eDepType e); #endif /* CTAGS_MAIN_DEPENDENCY_PRIVATE_H */
Modified: ctags/main/e_msoft.h 1 lines changed, 0 insertions(+), 1 deletions(-) =================================================================== @@ -20,7 +20,6 @@ #define HAVE_DIRECT_H 1 #define HAVE_STRICMP 1 #define HAVE_STRNICMP 1 -#define HAVE_STRSTR 1 #define HAVE_STRERROR 1 #define HAVE__FINDFIRST 1 #define HAVE_FINDNEXT 1
Modified: ctags/main/entry.c 551 lines changed, 442 insertions(+), 109 deletions(-) =================================================================== @@ -44,6 +44,7 @@ #include "field.h" #include "fmt_p.h" #include "kind.h" +#include "interval_tree_generic.h" #include "nestlevel.h" #include "options_p.h" #include "ptag_p.h" @@ -74,7 +75,7 @@
/* Hack for ridiculous practice of Microsoft Visual C++. */ -#if defined (WIN32) && defined (_MSC_VER) +#if defined (_WIN32) && defined (_MSC_VER) # define chsize _chsize # define open _open # define close _close @@ -95,6 +96,7 @@ typedef struct eTagFile { int cork; unsigned int corkFlags; ptrArray *corkQueue; + struct rb_root intervaltab;
bool patternCacheValid; } tagFile; @@ -104,22 +106,31 @@ typedef struct sTagEntryInfoX { int corkIndex; struct rb_root symtab; struct rb_node symnode; + struct rb_node intervalnode; + unsigned long __intervalnode_subtree_last; } tagEntryInfoX;
/* * DATA DEFINITIONS */
static tagFile TagFile = { - NULL, /* tag file name */ - NULL, /* tag file directory (absolute) */ - NULL, /* file pointer */ - { 0, 0 }, /* numTags */ - { 0, 0 }, /* max */ - NULL, /* vLine */ - .cork = false, - .corkQueue = NULL, - .patternCacheValid = false, + NULL, /* tag file name */ + NULL, /* tag file directory (absolute) */ + NULL, /* file pointer */ + { 0, 0 }, /* numTags */ + { 0, 0 }, /* max */ + NULL, /* vLine */ + .cork = false, + .corkQueue = NULL, + /* .intervaltab = RB_ROOT, + * + * msvc doesn't accept the above expression: + * + * main\entry.c(128) : error C2099: initializer is not a constant + * + */ + .patternCacheValid = false, };
static bool TagsToStdout = false; @@ -135,6 +146,13 @@ extern int truncate (const char *path, off_t length); extern int ftruncate (int fd, off_t length); #endif
+#define INTERVAL_START(node) ((node)->slot.lineNumber) +#define INTERVAL_END(node) ((node)->slot.extensionFields._endLine) + +INTERVAL_TREE_DEFINE(tagEntryInfoX, intervalnode, + unsigned long, __intervalnode_subtree_last, + INTERVAL_START, INTERVAL_END, /*static*/, intervaltab) + /* * FUNCTION DEFINITIONS */ @@ -200,7 +218,7 @@ extern void makeFileTag (const char *const fileName) unnecessary read line loop. */ while (readLineFromInputFile () != NULL) ; /* Do nothing */ - tag.extensionFields.endLine = getInputLineNumber (); + setTagEndLine(&tag, getInputLineNumber ()); }
if (isFieldEnabled (FIELD_EPOCH)) @@ -669,7 +687,7 @@ static size_t appendInputLine (int putc_func (char , void *), const char *const const int next = *(p + 1); const int c = *p;
- if (c == CRETURN || c == NEWLINE) + if (c == '\r' || c == '\n') break;
if (patternLengthLimit != 0 && length >= patternLengthLimit && @@ -683,10 +701,10 @@ static size_t appendInputLine (int putc_func (char , void *), const char *const } /* If character is '', or a terminal '$', then quote it. */ - if (c == BACKSLASH || c == (Option.backward ? '?' : '/') || - (c == '$' && (next == NEWLINE || next == CRETURN))) + if (c == '\' || c == (Option.backward ? '?' : '/') || + (c == '$' && (next == '\n' || next == '\r'))) { - putc_func (BACKSLASH, data); + putc_func ('\', data); ++length; } putc_func (c, data); @@ -712,7 +730,7 @@ static int vstring_puts (const char* s, void *data) }
#ifdef DEBUG -static bool isPosSet(MIOPos pos) +static bool isPosSet (MIOPos pos) { char * p = (char *)&pos; bool r = false; @@ -725,7 +743,7 @@ static bool isPosSet(MIOPos pos) #endif
extern char *readLineFromBypassForTag (vString *const vLine, const tagEntryInfo *const tag, - long *const pSeekValue) + long *const pSeekValue) { Assert (isPosSet (tag->filePosition) || (tag->pattern == NULL)); return readLineFromBypass (vLine, tag->filePosition, pSeekValue); @@ -739,7 +757,7 @@ extern size_t truncateTagLineAfterTag ( char *const line, const char *const token, const bool discardNewline) { size_t len = 0; - char *p = strstr (line, token); + char *p = strrstr (line, token);
if (p != NULL) { @@ -783,7 +801,17 @@ static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_ lang = scope->langType; root_scope = scope; } - scope = getEntryInCorkQueue (scope->extensionFields.scopeIndex); + int scopeIndex = scope->extensionFields.scopeIndex; + scope = getEntryInCorkQueue (scopeIndex); + + if (scope && scope->extensionFields.scopeIndex == scopeIndex) + { + error (WARNING, + "interanl error: scope information made a loop structure: %s in %s:%lu", + scope->name, scope->inputFileName, scope->lineNumber); + /* Force break this while-loop. */ + scope = NULL; + } }
n = vStringNew (); @@ -804,7 +832,7 @@ static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_ }
extern void getTagScopeInformation (tagEntryInfo *const tag, - const char **kind, const char **name) + const char **kind, const char **name) { if (kind) *kind = NULL; @@ -813,9 +841,9 @@ extern void getTagScopeInformation (tagEntryInfo *const tag,
const tagEntryInfo * scope = getEntryInCorkQueue (tag->extensionFields.scopeIndex); if (tag->extensionFields.scopeKindIndex == KIND_GHOST_INDEX - && tag->extensionFields.scopeName == NULL - && scope - && ptrArrayCount (TagFile.corkQueue) > 0) + && tag->extensionFields.scopeName == NULL + && scope + && ptrArrayCount (TagFile.corkQueue) > 0) { char *full_qualified_scope_name = getFullQualifiedScopeNameFromCorkQueue(scope); Assert (full_qualified_scope_name); @@ -827,7 +855,7 @@ extern void getTagScopeInformation (tagEntryInfo *const tag, }
if (tag->extensionFields.scopeKindIndex != KIND_GHOST_INDEX && - tag->extensionFields.scopeName != NULL) + tag->extensionFields.scopeName != NULL) { if (kind) { @@ -845,9 +873,9 @@ extern void getTagScopeInformation (tagEntryInfo *const tag,
static int makePatternStringCommon (const tagEntryInfo *const tag, - int (* putc_func) (char , void *), - int (* puts_func) (const char* , void *), - void *output) + int (* putc_func) (char , void *), + int (* puts_func) (const char* , void *), + void *output) { int length = 0;
@@ -864,8 +892,8 @@ static int makePatternStringCommon (const tagEntryInfo *const tag, static vString *cached_pattern; static MIOPos cached_location; if (TagFile.patternCacheValid - && (! tag->truncateLineAfterTag) - && (memcmp (&tag->filePosition, &cached_location, sizeof(MIOPos)) == 0)) + && (! tag->truncateLineAfterTag) + && (memcmp (&tag->filePosition, &cached_location, sizeof(MIOPos)) == 0)) return puts_func (vStringValue (cached_pattern), output);
line = readLineFromBypassForTag (TagFile.vLine, tag, NULL); @@ -904,7 +932,7 @@ static int makePatternStringCommon (const tagEntryInfo *const tag, }
length += putc_func(searchChar, output); - if ((tag->boundaryInfo & BOUNDARY_START) == 0) + if ((tag->boundaryInfo & INPUT_BOUNDARY_START) == 0) length += putc_func('^', output); length += appendInputLine (putc_func, line, Option.patternLengthLimit, output, &omitted); @@ -928,7 +956,7 @@ extern char* makePatternString (const tagEntryInfo *const tag) return vStringDeleteUnwrap (pattern); }
-static tagField * tagFieldNew(fieldType ftype, const char *value, bool valueOwner) +static tagField* tagFieldNew (fieldType ftype, const char *value, bool valueOwner) { tagField *f = xMalloc (1, tagField);
@@ -969,11 +997,11 @@ static void attachParserFieldGeneric (tagEntryInfo *const tag, fieldType ftype, } }
-extern void attachParserField (tagEntryInfo *const tag, bool inCorkQueue, fieldType ftype, const char * value) +extern void attachParserField (tagEntryInfo *const tag, fieldType ftype, const char * value) { Assert (tag != NULL);
- if (inCorkQueue) + if (tag->inCorkQueue) { const char * v; v = eStrdup (value); @@ -993,7 +1021,7 @@ extern void attachParserFieldToCorkEntry (int index, { tagEntryInfo * tag = getEntryInCorkQueue (index); if (tag) - attachParserField (tag, true, ftype, value); + attachParserField (tag, ftype, value); }
extern const tagField* getParserFieldForIndex (const tagEntryInfo * tag, int index) @@ -1010,11 +1038,11 @@ extern const tagField* getParserFieldForIndex (const tagEntryInfo * tag, int ind } }
-extern const char* getParserFieldValueForType (tagEntryInfo *const tag, fieldType ftype) +extern const char* getParserFieldValueForType (const tagEntryInfo *const tag, fieldType ftype) { - for (int i = 0; i < tag->usedParserFields; i++) + for (unsigned int i = 0; i < tag->usedParserFields; i++) { - const tagField *f = getParserFieldForIndex (tag, i); + const tagField *f = getParserFieldForIndex (tag, (int)i); if (f && f->ftype == ftype) return f->value; } @@ -1049,23 +1077,53 @@ static tagEntryInfo *newNilTagEntry (unsigned int corkFlags) x->corkIndex = CORK_NIL; x->symtab = RB_ROOT; x->slot.kindIndex = KIND_FILE_INDEX; + x->slot.inputFileName = getInputFileName (); + x->slot.inputFileName = eStrdup (x->slot.inputFileName); + x->slot.sourceFileName = getSourceFileTagPath(); + if (x->slot.sourceFileName) + x->slot.sourceFileName = eStrdup (x->slot.sourceFileName); return &(x->slot); }
+static void copyExtraDynamic (const tagEntryInfo *const src, tagEntryInfo *const dst) +{ + if (dst->extraDynamic) + { + unsigned int n = countXtags () - XTAG_COUNT; + dst->extraDynamic = xCalloc ((n / 8) + 1, uint8_t); + memcpy (dst->extraDynamic, src->extraDynamic, (n / 8) + 1); + PARSER_TRASH_BOX(dst->extraDynamic, eFree); + } +} + static tagEntryInfoX *copyTagEntry (const tagEntryInfo *const tag, - unsigned int corkFlags) + const char *shareInputFileName, + const char *sharedSourceFileName, + unsigned int corkFlags) { tagEntryInfoX *x = xMalloc (1, tagEntryInfoX); x->symtab = RB_ROOT; x->corkIndex = CORK_NIL; + memset(&x->intervalnode, 0, sizeof (x->intervalnode)); + x->__intervalnode_subtree_last = 0; tagEntryInfo *slot = (tagEntryInfo *)x;
*slot = *tag;
if (slot->pattern) slot->pattern = eStrdup (slot->pattern);
- slot->inputFileName = eStrdup (slot->inputFileName); + if (slot->inputFileName == getInputFileName ()) + { + slot->inputFileName = shareInputFileName; + slot->isInputFileNameShared = 1; + } + else + { + slot->inputFileName = eStrdup (slot->inputFileName); + slot->isInputFileNameShared = 0; + } + slot->name = eStrdup (slot->name); if (slot->extensionFields.access) slot->extensionFields.access = eStrdup (slot->extensionFields.access); @@ -1086,16 +1144,29 @@ static tagEntryInfoX *copyTagEntry (const tagEntryInfo *const tag, slot->extensionFields.xpath = eStrdup (slot->extensionFields.xpath); #endif
+ copyExtraDynamic (tag, slot); if (slot->extraDynamic) + PARSER_TRASH_BOX_TAKE_BACK(slot->extraDynamic); + + if (slot->sourceFileName == NULL) + slot->isSourceFileNameShared = 0; + else if (strcmp(slot->sourceFileName, sharedSourceFileName) == 0) { - int n = countXtags () - XTAG_COUNT; - slot->extraDynamic = xCalloc ((n / 8) + 1, uint8_t); - memcpy (slot->extraDynamic, tag->extraDynamic, (n / 8) + 1); + /* strcmp() is needed here. + * sharedSourceFileName can be changed during parsing a file. + * So we cannot use the condition like: + * + * if (slot->sourceFileName == getSourceFileTagPath()) { ... } + * + */ + slot->sourceFileName = sharedSourceFileName; + slot->isSourceFileNameShared = 1; } - - if (slot->sourceFileName) + else + { slot->sourceFileName = eStrdup (slot->sourceFileName); - + slot->isSourceFileNameShared = 0; + }
slot->usedParserFields = 0; slot->parserFieldsDynamic = NULL; @@ -1136,11 +1207,19 @@ static void deleteTagEnry (void *data) tagEntryInfo *slot = data;
if (slot->kindIndex == KIND_FILE_INDEX) + { + eFree ((char *)slot->inputFileName); + if (slot->sourceFileName) + eFree ((char *)slot->sourceFileName); goto out; + }
if (slot->pattern) eFree ((char *)slot->pattern); - eFree ((char *)slot->inputFileName); + + if (!slot->isInputFileNameShared) + eFree ((char *)slot->inputFileName); + eFree ((char *)slot->name);
if (slot->extensionFields.access) @@ -1165,7 +1244,7 @@ static void deleteTagEnry (void *data) if (slot->extraDynamic) eFree (slot->extraDynamic);
- if (slot->sourceFileName) + if (slot->sourceFileName && !slot->isSourceFileNameShared) eFree ((char *)slot->sourceFileName);
clearParserFields (slot); @@ -1225,6 +1304,12 @@ static void corkSymtabPut (tagEntryInfoX *scope, const char* name, tagEntryInfoX rb_insert_color(&item->symnode, root); }
+static void corkSymtabUnlink (tagEntryInfoX *scope, tagEntryInfoX *item) +{ + struct rb_root *root = &scope->symtab; + rb_erase (&item->symnode, root); +} + extern bool foreachEntriesInScope (int corkIndex, const char *name, entryForeachFunc func, @@ -1306,7 +1391,7 @@ extern bool foreachEntriesInScope (int corkIndex, do { tagEntryInfoX *entry = container_of(cursor, tagEntryInfoX, symnode); - if (!revisited_rep || !name || strcmp(name, entry->slot.name)) + if (!revisited_rep || !name || !strcmp(name, entry->slot.name)) { verbose ("symtbl[< ] %s->%p\n", name, &entry->slot); if (!func (entry->corkIndex, &entry->slot, data)) @@ -1322,20 +1407,68 @@ extern bool foreachEntriesInScope (int corkIndex, return true; }
-static bool findName (int corkIndex, tagEntryInfo *entry, void *data) +struct countData { + bool onlyDefinitionTag; + unsigned int count; + entryForeachFunc func; + void *cbData; +}; + +static bool countEntryMaybe (int corkIndex, tagEntryInfo *entry, void *cbData) +{ + struct countData *data = cbData; + if (data->onlyDefinitionTag + && !isRoleAssigned (entry, ROLE_DEFINITION_INDEX)) + return true; + + if (data->func == NULL + || data->func (corkIndex, entry, data->cbData)) + data->count++; + return true; +} + +unsigned int countEntriesInScope (int corkIndex, bool onlyDefinitionTag, + entryForeachFunc func, void *cbData) { - int *index = data; + struct countData data = { + .onlyDefinitionTag = onlyDefinitionTag, + .count = 0, + .func = func, + .cbData = cbData, + };
- *index = corkIndex; + foreachEntriesInScope (corkIndex, NULL, + &countEntryMaybe, + &data); + + return data.count; +} + +struct anyEntryInScopeData { + int index; + bool onlyDefinitionTag; +}; + +static bool findName (int corkIndex, tagEntryInfo *entry, void *cbData) +{ + struct anyEntryInScopeData *data = cbData; + + if (data->onlyDefinitionTag && !isRoleAssigned (entry, ROLE_DEFINITION_INDEX)) + return true; + + data->index = corkIndex; return false; }
-int anyEntryInScope (int corkIndex, const char *name) +int anyEntryInScope (int corkIndex, const char *name, bool onlyDefinitionTag) { - int index = CORK_NIL; + struct anyEntryInScopeData data = { + .index = CORK_NIL, + .onlyDefinitionTag = onlyDefinitionTag, + };
- if (foreachEntriesInScope (corkIndex, name, findName, &index) == false) - return index; + if (foreachEntriesInScope (corkIndex, name, findName, &data) == false) + return data.index;
return CORK_NIL; } @@ -1344,6 +1477,7 @@ struct anyKindsEntryInScopeData { int index; const int *kinds; int count; + bool onlyDefinitionTag; };
static bool findNameOfKinds (int corkIndex, tagEntryInfo *entry, void *data) @@ -1353,7 +1487,9 @@ static bool findNameOfKinds (int corkIndex, tagEntryInfo *entry, void *data) for (int i = 0; i < kdata->count; i++) { int k = kdata->kinds [i]; - if (entry->kindIndex == k) + if (entry->kindIndex == k + && ((!kdata->onlyDefinitionTag) + || isRoleAssigned (entry, ROLE_DEFINITION_INDEX))) { kdata->index = corkIndex; return false; @@ -1363,19 +1499,22 @@ static bool findNameOfKinds (int corkIndex, tagEntryInfo *entry, void *data) }
int anyKindEntryInScope (int corkIndex, - const char *name, int kind) + const char *name, int kind, + bool onlyDefinitionTag) { - return anyKindsEntryInScope (corkIndex, name, &kind, 1); + return anyKindsEntryInScope (corkIndex, name, &kind, 1, onlyDefinitionTag); }
int anyKindsEntryInScope (int corkIndex, const char *name, - const int *kinds, int count) + const int *kinds, int count, + bool onlyDefinitionTag) { struct anyKindsEntryInScopeData data = { .index = CORK_NIL, .kinds = kinds, .count = count, + .onlyDefinitionTag = onlyDefinitionTag, };
if (foreachEntriesInScope (corkIndex, name, findNameOfKinds, &data) == false) @@ -1386,12 +1525,14 @@ int anyKindsEntryInScope (int corkIndex,
int anyKindsEntryInScopeRecursive (int corkIndex, const char *name, - const int *kinds, int count) + const int *kinds, int count, + bool onlyDefinitionTag) { struct anyKindsEntryInScopeData data = { .index = CORK_NIL, .kinds = kinds, .count = count, + .onlyDefinitionTag = onlyDefinitionTag, };
tagEntryInfo *e; @@ -1425,12 +1566,26 @@ extern void registerEntry (int corkIndex) } }
-static int queueTagEntry(const tagEntryInfo *const tag) +extern void unregisterEntry (int corkIndex) +{ + Assert (TagFile.corkFlags & CORK_SYMTAB); + Assert (corkIndex != CORK_NIL); + + tagEntryInfoX *e = ptrArrayItem (TagFile.corkQueue, corkIndex); + { + tagEntryInfoX *scope = ptrArrayItem (TagFile.corkQueue, e->slot.extensionFields.scopeIndex); + corkSymtabUnlink (scope, e); + } + +} + +static int queueTagEntry (const tagEntryInfo *const tag) { static bool warned;
int corkIndex; - tagEntryInfoX * entry = copyTagEntry (tag, + tagEntryInfo * nil = ptrArrayItem (TagFile.corkQueue, 0); + tagEntryInfoX * entry = copyTagEntry (tag, nil->inputFileName, nil->sourceFileName, TagFile.corkFlags);
if (ptrArrayCount (TagFile.corkQueue) == (size_t)INT_MAX) @@ -1451,9 +1606,82 @@ static int queueTagEntry(const tagEntryInfo *const tag) entry->corkIndex = corkIndex; entry->slot.inCorkQueue = 1;
+ /* Don't put FQ tags to interval table. + * About placeholder, a parser should call + * removeFromIntervalTabMaybe() explicitly. + */ + if (! isTagExtraBitMarked (&entry->slot, XTAG_FILE_NAMES) + && entry->slot.extensionFields._endLine > entry->slot.lineNumber + && !isTagExtraBitMarked (tag, XTAG_QUALIFIED_TAGS)) + { + intervaltab_insert(entry, &TagFile.intervaltab); + entry->slot.inIntevalTab = 1; + } return corkIndex; }
+extern void updateTagLine (tagEntryInfo *tag, unsigned long lineNumber, + MIOPos filePosition) +{ + tagEntryInfoX *entry = NULL; + if (tag->inIntevalTab) + { + entry = (tagEntryInfoX *)tag; + removeFromIntervalTabMaybe (entry->corkIndex); + } + + tag->lineNumber = lineNumber; + tag->filePosition = filePosition; + tag->boundaryInfo = getNestedInputBoundaryInfo (lineNumber); + + if (entry && tag->lineNumber < tag->extensionFields._endLine) + { + intervaltab_insert(entry, &TagFile.intervaltab); + tag->inIntevalTab = 1; + } +} + +extern void setTagEndLine(tagEntryInfo *tag, unsigned long endLine) +{ + if (endLine != 0 && endLine < tag->lineNumber) + { + error (WARNING, + "given end line (%lu) for the tag (%s) in the file (%s) is smaller than its start line: %lu", + endLine, + tag->name, + tag->inputFileName, + tag->lineNumber); + return; + } + + if (isTagExtraBitMarked (tag, XTAG_FILE_NAMES) + || !tag->inCorkQueue + || isTagExtraBitMarked (tag, XTAG_QUALIFIED_TAGS)) + { + tag->extensionFields._endLine = endLine; + return; + } + + tagEntryInfoX *entry = (tagEntryInfoX *)tag; + + if (tag->inIntevalTab) + removeFromIntervalTabMaybe (entry->corkIndex); + + tag->extensionFields._endLine = endLine; + if (endLine > tag->lineNumber) + { + intervaltab_insert(entry, &TagFile.intervaltab); + tag->inIntevalTab = 1; + } +} + +extern void setTagEndLineToCorkEntry (int corkIndex, unsigned long endLine) +{ + tagEntryInfo *entry = getEntryInCorkQueue (corkIndex); + if (entry) + setTagEndLine (entry, endLine); +} + extern void setupWriter (void *writerClientData) { writerSetup (TagFile.mio, writerClientData); @@ -1464,11 +1692,14 @@ extern bool teardownWriter (const char *filename) return writerTeardown (TagFile.mio, filename); }
-static bool isTagWritable(const tagEntryInfo *const tag) +static bool isTagWritable (const tagEntryInfo *const tag) { if (tag->placeholder) return false;
+ if (! isLanguageEnabled(tag->langType) ) + return false; + if (! isLanguageKindEnabled(tag->langType, tag->kindIndex)) return false;
@@ -1503,9 +1734,10 @@ static bool isTagWritable(const tagEntryInfo *const tag) } else if (isLanguageKindRefOnly(tag->langType, tag->kindIndex)) { - error (WARNING, "definition tag for refonly kind(%s) is made: %s", + error (WARNING, "PARSER BUG: a definition tag for a refonly kind(%s.%s) of is made: %s found in %s.", + getLanguageName(tag->langType), getLanguageKind(tag->langType, tag->kindIndex)->name, - tag->name); + tag->name, tag->inputFileName); /* This one is not so critical. */ }
@@ -1529,7 +1761,7 @@ static void writeTagEntry (const tagEntryInfo *const tag)
DebugStatement ( debugEntry (tag); )
-#ifdef WIN32 +#ifdef _WIN32 if (getFilenameSeparator(Option.useSlashAsFilenameSeparator) == FILENAME_SEP_USE_SLASH) { Assert (((const tagEntryInfo *)tag)->inputFileName); @@ -1544,8 +1776,8 @@ static void writeTagEntry (const tagEntryInfo *const tag) #endif
if (includeExtensionFlags () - && isXtagEnabled (XTAG_QUALIFIED_TAGS) - && doesInputLanguageRequestAutomaticFQTag () + && isXtagEnabled (XTAG_QUALIFIED_TAGS) + && doesInputLanguageRequestAutomaticFQTag (tag) && !isTagExtraBitMarked (tag, XTAG_QUALIFIED_TAGS) && !tag->skipAutoFQEmission) { @@ -1566,9 +1798,9 @@ static void writeTagEntry (const tagEntryInfo *const tag) }
extern bool writePseudoTag (const ptagDesc *desc, - const char *const fileName, - const char *const pattern, - const char *const parserName) + const char *const fileName, + const char *const pattern, + const char *const parserName) { int length;
@@ -1585,7 +1817,7 @@ extern bool writePseudoTag (const ptagDesc *desc, return true; }
-extern void corkTagFile(unsigned int corkFlags) +extern void corkTagFile (unsigned int corkFlags) { TagFile.cork++; if (TagFile.cork == 1) @@ -1594,10 +1826,11 @@ extern void corkTagFile(unsigned int corkFlags) TagFile.corkQueue = ptrArrayNew (deleteTagEnry); tagEntryInfo *nil = newNilTagEntry (corkFlags); ptrArrayAdd (TagFile.corkQueue, nil); + TagFile.intervaltab = RB_ROOT; } }
-extern void uncorkTagFile(void) +extern void uncorkTagFile (void) { unsigned int i;
@@ -1615,8 +1848,8 @@ extern void uncorkTagFile(void)
writeTagEntry (tag);
- if (doesInputLanguageRequestAutomaticFQTag () - && isXtagEnabled (XTAG_QUALIFIED_TAGS) + if (doesInputLanguageRequestAutomaticFQTag (tag) + && isXtagEnabled (XTAG_QUALIFIED_TAGS) && !isTagExtraBitMarked (tag, XTAG_QUALIFIED_TAGS) && !tag->skipAutoFQEmission && ((tag->extensionFields.scopeKindIndex != KIND_GHOST_INDEX @@ -1632,7 +1865,7 @@ extern void uncorkTagFile(void) TagFile.corkQueue = NULL; }
-extern tagEntryInfo *getEntryInCorkQueue (int n) +extern tagEntryInfo *getEntryInCorkQueue (int n) { if ((CORK_NIL < n) && (((size_t)n) < ptrArrayCount (TagFile.corkQueue))) return ptrArrayItem (TagFile.corkQueue, n); @@ -1647,22 +1880,29 @@ extern tagEntryInfo *getEntryOfNestingLevel (const NestingLevel *nl) return getEntryInCorkQueue (nl->corkIndex); }
-extern size_t countEntryInCorkQueue (void) +extern size_t countEntryInCorkQueue (void) { return ptrArrayCount (TagFile.corkQueue); }
-extern void markTagPlaceholder (tagEntryInfo *e, bool placeholder) +extern void markTagAsPlaceholder (tagEntryInfo *e, bool placeholder) { e->placeholder = placeholder; }
+extern void markCorkEntryAsPlaceholder (int index, bool placeholder) +{ + tagEntryInfo *e = getEntryInCorkQueue(index); + if (e) + markTagAsPlaceholder(e, placeholder); +} + extern int makePlaceholder (const char *const name) { tagEntryInfo e;
initTagEntry (&e, name, KIND_GHOST_INDEX); - markTagPlaceholder(&e, true); + markTagAsPlaceholder(&e, true);
/* * makePlaceholder may be called even before reading any bytes @@ -1690,8 +1930,9 @@ extern int makeTagEntry (const tagEntryInfo *const tag) if (tag->name [0] == '\0' && (!tag->placeholder)) { if (!doesInputLanguageAllowNullTag()) - error (WARNING, "ignoring null tag in %s(line: %lu)", - getInputFileName (), tag->lineNumber); + error (NOTICE, "ignoring null tag in %s(line: %lu, language: %s)", + getInputFileName (), tag->lineNumber, + getLanguageName (tag->langType)); goto out; }
@@ -1774,20 +2015,20 @@ extern int makeQualifiedTagEntry (const tagEntryInfo *const e) extern void setTagPositionFromTag (tagEntryInfo *const dst, const tagEntryInfo *const src) { - dst->lineNumber = src->lineNumber; - dst->filePosition = src->filePosition; + updateTagLine (dst, src->lineNumber, src->filePosition); + dst->boundaryInfo = src->boundaryInfo; }
static void initTagEntryFull (tagEntryInfo *const e, const char *const name, - unsigned long lineNumber, - langType langType_, - MIOPos filePosition, - const char *inputFileName, - int kindIndex, - roleBitsType roleBits, - const char *sourceFileName, - langType sourceLangType, - long sourceLineNumberDifference) + unsigned long lineNumber, + langType langType_, + MIOPos filePosition, + const char *inputFileName, + int kindIndex, + roleBitsType roleBits, + const char *sourceFileName, + langType sourceLangType, + long sourceLineNumberDifference) { int i;
@@ -1850,11 +2091,18 @@ extern void initTagEntry (tagEntryInfo *const e, const char *const name, }
extern void initRefTagEntry (tagEntryInfo *const e, const char *const name, - int kindIndex, int roleIndex) + int kindIndex, int roleIndex) { initForeignRefTagEntry (e, name, getInputLanguage (), kindIndex, roleIndex); }
+extern void initForeignTagEntry (tagEntryInfo *const e, const char *const name, + langType type, + int kindIndex) +{ + initForeignRefTagEntry (e, name, type, kindIndex, ROLE_DEFINITION_INDEX); +} + extern void initForeignRefTagEntry (tagEntryInfo *const e, const char *const name, langType langType, int kindIndex, int roleIndex) @@ -1871,7 +2119,7 @@ extern void initForeignRefTagEntry (tagEntryInfo *const e, const char *const nam getSourceLineNumber() - getInputLineNumber ()); }
-static void markTagExtraBitFull (tagEntryInfo *const tag, xtagType extra, bool mark) +static void markTagExtraBitFull (tagEntryInfo *const tag, xtagType extra, bool mark) { unsigned int index; unsigned int offset; @@ -1896,8 +2144,8 @@ static void markTagExtraBitFull (tagEntryInfo *const tag, xtagType extra, else { Assert (extra < countXtags ()); - - int n = countXtags () - XTAG_COUNT; + Assert (XTAG_COUNT <= countXtags ()); + unsigned int n = countXtags () - XTAG_COUNT; tag->extraDynamic = xCalloc ((n / 8) + 1, uint8_t); if (!tag->inCorkQueue) PARSER_TRASH_BOX(tag->extraDynamic, eFree); @@ -1911,12 +2159,12 @@ static void markTagExtraBitFull (tagEntryInfo *const tag, xtagType extra, slot [ index ] &= ~(1 << offset); }
-extern void markTagExtraBit (tagEntryInfo *const tag, xtagType extra) +extern void markTagExtraBit (tagEntryInfo *const tag, xtagType extra) { markTagExtraBitFull (tag, extra, true); }
-extern void unmarkTagExtraBit (tagEntryInfo *const tag, xtagType extra) +extern void unmarkTagExtraBit (tagEntryInfo *const tag, xtagType extra) { markTagExtraBitFull (tag, extra, false); } @@ -1955,7 +2203,43 @@ extern bool isTagExtra (const tagEntryInfo *const tag) return false; }
-static void assignRoleFull(tagEntryInfo *const e, int roleIndex, bool assign) +extern void resetTagCorkState (tagEntryInfo *const tag, + enum resetTagMemberAction xtagAction, + enum resetTagMemberAction parserFieldsAction) +{ + tagEntryInfo original = *tag; + + tag->inCorkQueue = 0; + + switch (xtagAction) + { + case RESET_TAG_MEMBER_COPY: + copyExtraDynamic (&original, tag); + break; + case RESET_TAG_MEMBER_CLEAR: + tag->extraDynamic = NULL; + break; + case RESET_TAG_MEMBER_DONTTOUCH: + break; + } + + switch (parserFieldsAction) + { + case RESET_TAG_MEMBER_COPY: + tag->usedParserFields = 0; + tag->parserFieldsDynamic = NULL; + copyParserFields (&original, tag); + break; + case RESET_TAG_MEMBER_CLEAR: + tag->usedParserFields = 0; + tag->parserFieldsDynamic = NULL; + break; + case RESET_TAG_MEMBER_DONTTOUCH: + break; + } +} + +static void assignRoleFull (tagEntryInfo *const e, int roleIndex, bool assign) { if (roleIndex == ROLE_DEFINITION_INDEX) { @@ -1979,20 +2263,25 @@ static void assignRoleFull(tagEntryInfo *const e, int roleIndex, bool assign) AssertNotReached(); }
-extern void assignRole(tagEntryInfo *const e, int roleIndex) +extern void assignRole (tagEntryInfo *const e, int roleIndex) { assignRoleFull(e, roleIndex, true); }
-extern bool isRoleAssigned(const tagEntryInfo *const e, int roleIndex) +extern void unassignRole (tagEntryInfo *const e, int roleIndex) +{ + assignRoleFull(e, roleIndex, false); +} + +extern bool isRoleAssigned (const tagEntryInfo *const e, int roleIndex) { if (roleIndex == ROLE_DEFINITION_INDEX) return (!e->extensionFields.roleBits); else return (e->extensionFields.roleBits & makeRoleBit(roleIndex)); }
-extern unsigned long numTagsAdded(void) +extern unsigned long numTagsAdded (void) { return TagFile.numTags.added; } @@ -2002,7 +2291,7 @@ extern void setNumTagsAdded (unsigned long nadded) TagFile.numTags.added = nadded; }
-extern unsigned long numTagsTotal(void) +extern unsigned long numTagsTotal (void) { return TagFile.numTags.added + TagFile.numTags.prev; } @@ -2012,15 +2301,15 @@ extern unsigned long maxTagsLine (void) return (unsigned long)TagFile.max.line; }
-extern void invalidatePatternCache(void) +extern void invalidatePatternCache (void) { TagFile.patternCacheValid = false; }
extern void tagFilePosition (MIOPos *p) { /* mini-geany doesn't set TagFile.mio. */ - if (TagFile.mio == NULL) + if (TagFile.mio == NULL) return;
if (mio_getpos (TagFile.mio, p) == -1) @@ -2031,7 +2320,7 @@ extern void tagFilePosition (MIOPos *p) extern void setTagFilePosition (MIOPos *p, bool truncation) { /* mini-geany doesn't set TagFile.mio. */ - if (TagFile.mio == NULL) + if (TagFile.mio == NULL) return;
@@ -2057,14 +2346,58 @@ extern const char* getTagFileDirectory (void) return TagFile.directory; }
-static bool markAsPlaceholder (int index, tagEntryInfo *e, void *data CTAGS_ATTR_UNUSED) +static bool markAsPlaceholderRecursively (int index, tagEntryInfo *e, void *data CTAGS_ATTR_UNUSED) { - e->placeholder = 1; + markTagAsPlaceholder (e, true); markAllEntriesInScopeAsPlaceholder (index); return true; }
extern void markAllEntriesInScopeAsPlaceholder (int index) { - foreachEntriesInScope (index, NULL, markAsPlaceholder, NULL); + foreachEntriesInScope (index, NULL, markAsPlaceholderRecursively, NULL); +} + +extern int queryIntervalTabByLine(unsigned long lineNum) +{ + return queryIntervalTabByRange(lineNum, lineNum); +} + +extern int queryIntervalTabByRange(unsigned long start, unsigned long end) +{ + int index = CORK_NIL; + + tagEntryInfoX *ex = intervaltab_iter_first(&TagFile.intervaltab, start, end); + while (ex) { + index = ex->corkIndex; + ex = intervaltab_iter_next(ex, start, end); + } + return index; +} + +extern int queryIntervalTabByCorkEntry(int corkIndex) +{ + Assert (corkIndex != CORK_NIL); + + tagEntryInfoX *ex = ptrArrayItem (TagFile.corkQueue, corkIndex); + tagEntryInfo *e = &ex->slot; + + if (e->extensionFields._endLine == 0) + return queryIntervalTabByLine(e->lineNumber); + return queryIntervalTabByRange(e->lineNumber, e->extensionFields._endLine); +} + +extern bool removeFromIntervalTabMaybe(int corkIndex) +{ + if (corkIndex == CORK_NIL) + return false; + + tagEntryInfoX *ex = ptrArrayItem (TagFile.corkQueue, corkIndex); + tagEntryInfo *e = &ex->slot; + if (!e->inIntevalTab) + return false; + + intervaltab_remove(ex, &TagFile.intervaltab); + e->inIntevalTab = 0; + return true; }
Modified: ctags/main/entry.h 159 lines changed, 126 insertions(+), 33 deletions(-) =================================================================== @@ -24,8 +24,6 @@ #include "ptrarray.h" #include "nestlevel.h"
-#include "script_p.h" - /* * MACROS */ @@ -44,26 +42,56 @@ typedef uint64_t roleBitsType; /* Information about the current tag candidate. */ struct sTagEntryInfo { + /* + * the bit fields parsers may access for setting DIRECTLY + */ unsigned int lineNumberEntry:1; /* pattern or line number entry */ 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; /* 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. */ + + /* + * the bit fields parser may access for setting via accessor + */ + unsigned int placeholder :1; /* is used only for keeping corkIndex based scope chain. + Put this entry to cork queue but + the tag is not printed: + * not printed as a tag entry, + * never used as a part of automatically generated FQ tag, and + * not printed as a part of scope. + See getTagScopeInformation() and + getFullQualifiedScopeNameFromCorkQueue. */ + + /* + * the bit fields only the main part can access. + */ + unsigned int isFileEntry :1; /* is this just an entry for a file name? */ 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 */ + unsigned int isInputFileNameShared: 1; /* shares the value for inputFileName. + * Set in the cork queue; don't touch this.*/ + unsigned int isSourceFileNameShared: 1; /* shares the value for sourceFileName. + * Set in the cork queue; don't touch this.*/ + unsigned int boundaryInfo: 2; /* info about nested input stream */ + unsigned int inIntevalTab:1; + + unsigned long lineNumber; /* line number of tag; + use updateTagLine() for updating this member. */ const char* pattern; /* pattern for locating input line * (may be NULL if not present) *//* */ - unsigned int boundaryInfo; /* info about nested input stream */ MIOPos filePosition; /* file position of line containing tag */ langType langType; /* language of input file */ - const char *inputFileName; /* name of input file */ + const char *inputFileName; /* name of input file. + You cannot modify the contents of buffer pointed + by this member of the tagEntryInfo returned from + getEntryInCorkQueue(). The buffer may be shared + between tag entries in the cork queue. + + Further more, modifying this member of the + tagEntryInfo returned from getEntryInCorkQueue() + may cause a memory leak. */ const char *name; /* name of the tag */ int kindIndex; /* kind descriptor */ uint8_t extra[ ((XTAG_COUNT) / 8) + 1 ]; @@ -82,8 +110,10 @@ struct sTagEntryInfo { const char* scopeName; int scopeIndex; /* cork queue entry for upper scope tag. This field is meaningful if the value - is not CORK_NIL and scope[0] and scope[1] are - NULL. */ + is not CORK_NIL, scopeKindIndex is KIND_GHOST_INDEX, + and scopeName is NULL. + CXX parser violates this rule; see the comment inside + cxxTagBegin(). */
const char* signature;
@@ -98,7 +128,7 @@ struct sTagEntryInfo { #ifdef HAVE_LIBXML const char* xpath; #endif - unsigned long endLine; + unsigned long _endLine; /* Don't set directly. Use setTagEndLine() */ time_t epoch; #define NO_NTH_FIELD -1 short nth; @@ -139,10 +169,24 @@ extern void initTagEntry (tagEntryInfo *const e, const char *const name, int kindIndex); extern void initRefTagEntry (tagEntryInfo *const e, const char *const name, int kindIndex, int roleIndex); + +/* initForeignRefTagEntry() is for making a tag for the language X when parsing + * source code of Y language. + * From the view point of the language Y, we call the language X a foreign + * language. + * + * When making a tag for a foreign with this function, you must declare the + * language X in the parser of Y with DEPTYPE_FOREIGNER dependency. + */ +extern void initForeignTagEntry (tagEntryInfo *const e, const char *const name, + langType type, + int kindIndex); extern void initForeignRefTagEntry (tagEntryInfo *const e, const char *const name, langType type, int kindIndex, int roleIndex); extern void assignRole(tagEntryInfo *const e, int roleIndex); +#define clearRoles(E) assignRole((E), ROLE_DEFINITION_INDEX) +extern void unassignRole(tagEntryInfo *const e, int roleIndex); extern bool isRoleAssigned(const tagEntryInfo *const e, int roleIndex);
extern int makeQualifiedTagEntry (const tagEntryInfo *const e); @@ -162,13 +206,15 @@ size_t countEntryInCorkQueue (void); * specified in the scopeIndex field of the tag specified with CORKINDEX. */ void registerEntry (int corkIndex); +void unregisterEntry (int corkIndex);
/* foreachEntriesInScope is for traversing the symbol table for a table * specified with CORKINDEX. If CORK_NIL is given, this function traverses * top-level entries. If name is NULL, this function traverses all entries * under the scope. * - * If FUNC returns false, this function returns false. + * If FUNC returns false, this function returns false immediately + * even if more entires in the scope. * 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. @@ -178,24 +224,40 @@ bool foreachEntriesInScope (int corkIndex, entryForeachFunc func, void *data);
+unsigned int countEntriesInScope (int corkIndex, bool onlyDefinitionTag, + entryForeachFunc func, void *data); + /* Return the cork index for NAME in the scope specified with CORKINDEX. * Even if more than one entries for NAME are in the scope, this function * just returns one of them. Returning CORK_NIL means there is no entry * for NAME. */ int anyEntryInScope (int corkIndex, - const char *name); + const char *name, + bool onlyDefinitionTag);
int anyKindEntryInScope (int corkIndex, - const char *name, int kind); + const char *name, int kind, + bool onlyDefinitionTag);
int anyKindsEntryInScope (int corkIndex, const char *name, - const int * kinds, int count); + const int * kinds, int count, + bool onlyDefinitionTag);
int anyKindsEntryInScopeRecursive (int corkIndex, const char *name, - const int * kinds, int count); + const int * kinds, int count, + bool onlyDefinitionTag); + +extern void updateTagLine(tagEntryInfo *tag, unsigned long lineNumber, MIOPos filePosition); +extern void setTagEndLine (tagEntryInfo *tag, unsigned long endLine); +extern void setTagEndLineToCorkEntry (int corkIndex, unsigned long endLine); + +extern int queryIntervalTabByLine(unsigned long lineNum); +extern int queryIntervalTabByRange(unsigned long startLine, unsigned long endLine); +extern int queryIntervalTabByCorkEntry(int corkIndex); +extern bool removeFromIntervalTabMaybe(int corkIndex);
extern void markTagExtraBit (tagEntryInfo *const tag, xtagType extra); extern void unmarkTagExtraBit (tagEntryInfo *const tag, xtagType extra); @@ -204,21 +266,53 @@ extern bool isTagExtraBitMarked (const tagEntryInfo *const tag, xtagType extra); /* If any extra bit is on, return true. */ extern bool isTagExtra (const tagEntryInfo *const tag);
+/* + In the following frequently used code-pattern: + + tagEntryInfo *original = getEntryInCorkQueue (index); + tagEntryInfo xtag = *original; + ... customize XTAG ... + makeTagEntry (&xtag); + + ORIGINAL and XTAG share some memory objects through their members. + TagEntryInfo::name is one of obvious ones. + When updating the member in the ... customize XTAG ... stage, you will + do: + + vStringValue *xtag_name = vStringNewInit (xtags->name); + ... customize XTAG_NAME with vString functions ... + xtag.name = vStringValue (xtag_name); + makeTagEntry (&xtag); + vStringDelete (xtag_name); + + There are some vague ones: extraDynamic and parserFieldsDynamic. + resetTagCorkState does: + + - mark the TAG is not in cork queue: set inCorkQueue 0. + - copy, clear, or dont touch the extraDynamic member. + - copy, clear, or dont touch the parserFieldsDynamic member. + +*/ + +enum resetTagMemberAction { + RESET_TAG_MEMBER_COPY, + RESET_TAG_MEMBER_CLEAR, + RESET_TAG_MEMBER_DONTTOUCH, +}; + +extern void resetTagCorkState (tagEntryInfo *const tag, + enum resetTagMemberAction xtagAction, + enum resetTagMemberAction parserFieldsAction); + /* Functions for attaching parser specific fields * - * Which function you should use? - * ------------------------------ + * Which function should I use? + * ---------------------------- * Case A: * * If your parser uses the Cork API, and your parser called * makeTagEntry () already, you can use both - * attachParserFieldToCorkEntry () and attachParserField (). Your - * parser has the cork index returned from makeTagEntry (). With the - * cork index, your parser can call attachParserFieldToCorkEntry (). - * If your parser already call getEntryInCorkQueue () to get the tag - * entry for the cork index, your parser can call attachParserField () - * with passing true for `inCorkQueue' parameter. attachParserField () - * is a bit faster than attachParserFieldToCorkEntry (). + * attachParserFieldToCorkEntry () and attachParserField (). * * attachParserField () and attachParserFieldToCorkEntry () duplicates * the memory object specified with `value' and stores the duplicated @@ -231,9 +325,7 @@ extern bool isTagExtra (const tagEntryInfo *const tag); * Case B: * * If your parser called one of initTagEntry () family but didn't call - * makeTagEntry () for a tagEntry yet, use attachParserField () with - * false for `inCorkQueue' whether your parser uses the Cork API or - * not. + * makeTagEntry () for a tagEntry yet, use attachParserField (). * * The parser (== caller) keeps the memory object specified with `value' * till calling makeTagEntry (). The parser must free the memory object @@ -260,12 +352,13 @@ extern bool isTagExtra (const tagEntryInfo *const tag); * The other data type and the combination of types are not implemented yet. * */ -extern void attachParserField (tagEntryInfo *const tag, bool inCorkQueue, fieldType ftype, const char* value); +extern void attachParserField (tagEntryInfo *const tag, fieldType ftype, const char* value); extern void attachParserFieldToCorkEntry (int index, fieldType ftype, const char* value); -extern const char* getParserFieldValueForType (tagEntryInfo *const tag, fieldType ftype); +extern const char* getParserFieldValueForType (const tagEntryInfo *const tag, fieldType ftype);
extern int makePlaceholder (const char *const name); -extern void markTagPlaceholder (tagEntryInfo *e, bool placeholder); +extern void markTagAsPlaceholder (tagEntryInfo *e, bool placeholder); +extern void markCorkEntryAsPlaceholder (int index, bool placeholder);
/* Marking all tag entries entries under the scope specified * with index recursively.
Modified: ctags/main/error_p.h 4 lines changed, 2 insertions(+), 2 deletions(-) =================================================================== @@ -16,11 +16,11 @@ #include "routines.h"
typedef bool (* errorPrintFunc) (const errorSelection selection, const char *const format, - va_list ap, void *data); + va_list ap, void *data) CTAGS_ATTR_PRINTF (2, 0);
extern void setErrorPrinter (errorPrintFunc printer, void *data);
extern bool stderrDefaultErrorPrinter (const errorSelection selection, const char *const format, va_list ap, - void *data); + void *data) CTAGS_ATTR_PRINTF (2, 0);
#endif
Modified: ctags/main/field.c 155 lines changed, 89 insertions(+), 66 deletions(-) =================================================================== @@ -32,9 +32,7 @@ #include "xtag_p.h"
#include "optscript.h" - -#define FIELD_NULL_LETTER_CHAR '-' -#define FIELD_NULL_LETTER_STRING "-" +#include "script_p.h"
typedef struct sFieldObject { fieldDefinition *def; @@ -100,6 +98,8 @@ static EsObject* getFieldValueForScope (const tagEntryInfo *, const fieldDefinit static EsObject* setFieldValueForScope (tagEntryInfo *, const fieldDefinition *, const EsObject *); static EsObject* checkFieldValueForScope (const fieldDefinition *, const EsObject *); static EsObject* getFieldValueForExtras (const tagEntryInfo *, const fieldDefinition *); +static EsObject* getFieldValueForAccess (const tagEntryInfo *, const fieldDefinition *); +static EsObject* setFieldValueForAccess (tagEntryInfo *, const fieldDefinition *, const EsObject *); static EsObject* getFieldValueForSignature (const tagEntryInfo *, const fieldDefinition *); static EsObject* setFieldValueForSignature (tagEntryInfo *, const fieldDefinition *, const EsObject *); static EsObject* getFieldValueForRoles (const tagEntryInfo *, const fieldDefinition *); @@ -108,7 +108,7 @@ static EsObject* checkFieldValueForLineCommon (const fieldDefinition *, const Es 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) +#define WITH_DEFAULT_VALUE(str) ((str)?(str):FIELD_NULL_LETTER_STRING)
static fieldDefinition fieldDefinitionsFixed [] = { [FIELD_NAME] = { @@ -223,7 +223,7 @@ static fieldDefinition fieldDefinitionsExuberant [] = { .dataType = FIELDTYPE_INTEGER, .getterValueType = "int", .getValueObject = getFieldValueForLineCommon, - .setterValueType = "matchlok|int", + .setterValueType = "matchloc|line:int", /* line <= getInputLineNumber(); */ .checkValueForSetter= checkFieldValueForLineCommon, .setValueObject = setFieldValueForLineCommon, }, @@ -298,6 +298,11 @@ static fieldDefinition fieldDefinitionsExuberant [] = { .doesContainAnyChar = NULL, .isValueAvailable = isAccessFieldAvailable, .dataType = FIELDTYPE_STRING, + .getterValueType = NULL, + .getValueObject = getFieldValueForAccess, + .setterValueType = NULL, + .checkValueForSetter= NULL, + .setValueObject = setFieldValueForAccess, }, [FIELD_IMPLEMENTATION - FIELD_ECTAGS_START] = { .letter = 'm', @@ -425,7 +430,7 @@ static fieldDefinition fieldDefinitionsUniversal [] = { .dataType = FIELDTYPE_INTEGER, .getterValueType = "int", .getValueObject = getFieldValueForLineCommon, - .setterValueType = "matchlok|int", + .setterValueType = "matchloc|int", .checkValueForSetter= checkFieldValueForLineCommon, .setValueObject = setFieldValueForLineCommon,
@@ -533,7 +538,7 @@ static fieldObject* getFieldObject(fieldType type) return fieldObjects + type; }
-extern fieldType getFieldTypeForOption (char letter) +extern fieldType getFieldTypeForLetter (char letter) { unsigned int i;
@@ -715,13 +720,13 @@ static bool doesContainAnyCharInInput (const tagEntryInfo *const tag, const char
static const char *renderFieldSignature (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b) { - return renderEscapedString (WITH_DEFUALT_VALUE (tag->extensionFields.signature), + return renderEscapedString (WITH_DEFAULT_VALUE (tag->extensionFields.signature), tag, b); }
static const char *renderFieldSignatureNoEscape (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b) { - return renderAsIs (b, WITH_DEFUALT_VALUE (tag->extensionFields.signature)); + return renderAsIs (b, WITH_DEFAULT_VALUE (tag->extensionFields.signature)); }
static bool doesContainAnyCharInSignature (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, const char *chars) @@ -758,7 +763,7 @@ static bool doesContainAnyCharInFieldScope (const tagEntryInfo *const tag, const
static const char *renderFieldInherits (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b) { - return renderEscapedString (WITH_DEFUALT_VALUE (tag->extensionFields.inheritance), + return renderEscapedString (WITH_DEFAULT_VALUE (tag->extensionFields.inheritance), tag, b); }
@@ -769,9 +774,9 @@ static const char *renderFieldTyperef (const tagEntryInfo *const tag, const char && tag->extensionFields.typeRef [1] == NULL) return renderAsIs (b, FIELD_NULL_LETTER_STRING);
- vStringCatS (b, WITH_DEFUALT_VALUE (tag->extensionFields.typeRef [0])); + vStringCatS (b, WITH_DEFAULT_VALUE (tag->extensionFields.typeRef [0])); vStringPut (b, ':'); - return renderEscapedName (false, WITH_DEFUALT_VALUE (tag->extensionFields.typeRef [1]), tag, b); + return renderEscapedName (false, WITH_DEFAULT_VALUE (tag->extensionFields.typeRef [1]), tag, b); }
@@ -855,13 +860,12 @@ extern bool doesFieldHaveTabOrNewlineChar (fieldType type, const tagEntryInfo * static const char* renderCompactInputLine (vString *b, const char *const line) { bool lineStarted = false; - const char *p; - int c;
/* Write everything up to, but not including, the newline. */ - for (p = line, c = *p ; c != NEWLINE && c != '\0' ; c = *++p) + for (const char *p = line; *p != '\n' && *p != '\0'; ++p) { + int c = (unsigned char) *p; if (lineStarted || ! isspace (c)) /* ignore leading spaces */ { lineStarted = true; @@ -871,11 +875,11 @@ static const char* renderCompactInputLine (vString *b, const char *const line)
/* Consume repeating white space. */ - while (next = *(p+1) , isspace (next) && next != NEWLINE) + while (next = (unsigned char) *(p+1), isspace (next) && next != '\n') ++p; c = ' '; /* force space character for any white space */ } - if (c != CRETURN || *(p + 1) != NEWLINE) + if (c != '\r' || *(p + 1) != '\n') vStringPut (b, c); } } @@ -995,14 +999,14 @@ static const char *renderFieldLanguage (const tagEntryInfo *const tag, l = getLanguageName(tag->langType); }
- return renderAsIs (b, WITH_DEFUALT_VALUE(l)); + return renderAsIs (b, WITH_DEFAULT_VALUE(l)); }
static const char *renderFieldAccess (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b) { - return renderAsIs (b, WITH_DEFUALT_VALUE (tag->extensionFields.access)); + return renderAsIs (b, WITH_DEFAULT_VALUE (tag->extensionFields.access)); }
static const char *renderFieldKindLetter (const tagEntryInfo *const tag, @@ -1020,7 +1024,7 @@ static const char *renderFieldImplementation (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b) { - return renderAsIs (b, WITH_DEFUALT_VALUE (tag->extensionFields.implementation)); + return renderAsIs (b, WITH_DEFAULT_VALUE (tag->extensionFields.implementation)); }
static const char *renderFieldFile (const tagEntryInfo *const tag, @@ -1064,9 +1068,9 @@ static const char *renderFieldExtras (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b) { - int i; + unsigned int i; bool hasExtra = false; - int c = countXtags(); + unsigned int c = countXtags();
for (i = 0; i < c; i++) { @@ -1119,9 +1123,9 @@ static const char *renderFieldEnd (const tagEntryInfo *const tag, { static char buf[21];
- if (tag->extensionFields.endLine != 0) + if (tag->extensionFields._endLine != 0) { - sprintf (buf, "%lu", tag->extensionFields.endLine); + sprintf (buf, "%lu", tag->extensionFields._endLine); return renderAsIs (b, buf); } else @@ -1133,11 +1137,16 @@ static const char *renderFieldEpoch (const tagEntryInfo *const tag, { #define buf_len 21 static char buf[buf_len]; - - if (snprintf (buf, buf_len, "%lld", (long long)tag->extensionFields.epoch) > 0) +#ifdef _MSC_VER +#define FMTLL "%I64d" +#else +#define FMTLL "%lld" +#endif + if (snprintf (buf, buf_len, FMTLL, (long long)tag->extensionFields.epoch) > 0) return renderAsIs (b, buf); else return NULL; +#undef FMTLL #undef buf_len }
@@ -1188,15 +1197,7 @@ 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; - - return false; + return isTagExtra (tag); }
static bool isXpathFieldAvailable (const tagEntryInfo *const tag) @@ -1210,7 +1211,7 @@ static bool isXpathFieldAvailable (const tagEntryInfo *const tag)
static bool isEndFieldAvailable (const tagEntryInfo *const tag) { - return (tag->extensionFields.endLine != 0)? true: false; + return (tag->extensionFields._endLine != 0)? true: false; }
static bool isEpochAvailable (const tagEntryInfo *const tag) @@ -1244,7 +1245,7 @@ extern bool enableField (fieldType type, bool state) else verbose ("enable field "%s"<%s>: %s\n", getFieldObject(type)->def->name, - getLanguageName (getFieldOwner(type)), + getLanguageName (getFieldLanguage(type)), (state? "yes": "no")); return old; } @@ -1254,7 +1255,7 @@ extern bool isCommonField (fieldType type) return (FIELD_BUILTIN_LAST < type)? false: true; }
-extern int getFieldOwner (fieldType type) +extern langType getFieldLanguage (fieldType type) { return getFieldObject(type)->language; } @@ -1277,7 +1278,7 @@ extern bool doesFieldHaveRenderer (fieldType type, bool noEscaping) return getFieldObject(type)->def->render? true: false; }
-extern int countFields (void) +extern unsigned int countFields (void) { return fieldObjectUsed; } @@ -1324,7 +1325,7 @@ extern int defineField (fieldDefinition *def, langType language) Assert (def->name); for (i = 0; i < strlen (def->name); i++) { - Assert ( isalpha (def->name [i]) ); + Assert ( isalpha ((unsigned char) def->name [i]) ); } def->letter = NUL_FIELD_LETTER;
@@ -1408,7 +1409,7 @@ static void fieldColprintAddLine (struct colprintTable *table, int i) bmask < FIELDTYPE_END_MARKER; bmask <<= 1, offset++) if (type & bmask) - typefields[offset] = fieldDataTypeFalgs[offset]; + typefields[offset] = fieldDataTypeFlags[offset]; } colprintLineAppendColumnCString (line, typefields); colprintLineAppendColumnBool (line, writerDoesTreatFieldAsFixed (i)); @@ -1705,8 +1706,12 @@ static EsObject* checkFieldValueForTyperef (const fieldDefinition *fdef, const E ; else if (es_integer_p (obj)) { - int index = es_integer_get (obj); - if (index >= countEntryInCorkQueue ()) + int index0 = es_integer_get (obj); + if (index0 < 0) + return OPT_ERR_RANGECHECK; + + unsigned int index = index0; + if (index == 0 || index >= countEntryInCorkQueue ()) return OPTSCRIPT_ERR_NOTAGENTRY; } else @@ -1721,10 +1726,10 @@ static EsObject* getFieldValueForScope (const tagEntryInfo *tag, const fieldDefi
static EsObject* setFieldValueForScope (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj) { - int index = es_integer_get (obj); + unsigned int index = es_integer_get (obj); if (index < countEntryInCorkQueue ()) { - tag->extensionFields.scopeIndex = index; + tag->extensionFields.scopeIndex = (int)index; return es_false; }
@@ -1749,12 +1754,12 @@ static EsObject* getFieldValueForExtras (const tagEntryInfo *tag, const fieldDef
EsObject* a = opt_array_new ();
- for (int i = 0; i < countXtags (); i++) + for (unsigned int i = 0; i < countXtags (); i++) { if (!isTagExtraBitMarked (tag, i)) continue;
- langType lang = getXtagOwner (i); + langType lang = getXtagLanguage (i); const char *lang_name = (lang == LANG_IGNORE) ? NULL : getLanguageName (lang); @@ -1777,23 +1782,43 @@ static EsObject* getFieldValueForExtras (const tagEntryInfo *tag, const fieldDef return a; }
-static EsObject* getFieldValueForSignature (const tagEntryInfo *tag, const fieldDefinition *fdef) +static EsObject* getFieldValueForCOMMON (const char *field, const tagEntryInfo *tag, const fieldDefinition *fdef) { - if (!tag->extensionFields.signature) + if (!field) return es_nil; - return (opt_name_new_from_cstr (tag->extensionFields.signature)); + return (opt_name_new_from_cstr (field)); }
-static EsObject* setFieldValueForSignature (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj) +static EsObject* setFieldValueForCOMMON (const char **field, tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj) { - if (tag->extensionFields.signature) - eFree ((char *)tag->extensionFields.signature); + if (*field) + eFree ((char *)*field);
const char *str = opt_string_get_cstr (obj); - tag->extensionFields.signature = eStrdup (str); + *field = eStrdup (str); return es_false; }
+static EsObject* getFieldValueForAccess (const tagEntryInfo *tag, const fieldDefinition *fdef) +{ + return getFieldValueForCOMMON(tag->extensionFields.access, tag, fdef); +} + +static EsObject* setFieldValueForAccess (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj) +{ + return setFieldValueForCOMMON(&tag->extensionFields.access, tag, fdef, obj); +} + +static EsObject* getFieldValueForSignature (const tagEntryInfo *tag, const fieldDefinition *fdef) +{ + return getFieldValueForCOMMON(tag->extensionFields.signature, tag, fdef); +} + +static EsObject* setFieldValueForSignature (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj) +{ + return setFieldValueForCOMMON(&tag->extensionFields.signature, tag, fdef, obj); +} + static void makeRolesArray (const tagEntryInfo *const tag, int roleIndex, void *data) { EsObject *a = data; @@ -1820,9 +1845,9 @@ static EsObject* getFieldValueForRoles (const tagEntryInfo *tag, const fieldDefi static EsObject* getFieldValueForLineCommon (const tagEntryInfo *tag, const fieldDefinition *fdef) { if (fdef->ftype == FIELD_END_LINE) - return ((int)tag->extensionFields.endLine == 0) + return ((int)tag->extensionFields._endLine == 0) ? es_nil - : es_integer_new ((int)tag->extensionFields.endLine); + : es_integer_new ((int)tag->extensionFields._endLine); else return ((int)tag->lineNumber == 0) ? es_nil @@ -1836,35 +1861,33 @@ static EsObject* checkFieldValueForLineCommon (const fieldDefinition *fdef, cons
static EsObject* setFieldValueForLineCommon (tagEntryInfo *tag, const fieldDefinition *fdef, const EsObject *obj) { - int l; + unsigned 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) + int l0 = es_integer_get (obj); + if (l0 < 1) return OPT_ERR_RANGECHECK;
+ l = (unsigned int)l0; /* If the new line number is too large, - we cannot fill tag->filePosition wit + we cannot fill tag->filePosition with getInputFilePositionForLine(); */ if (fdef->ftype == FIELD_LINE_NUMBER - && l < getInputLineNumber()) + && l > getInputLineNumber()) return OPT_ERR_RANGECHECK; } else return OPT_ERR_TYPECHECK;
if (fdef->ftype == FIELD_END_LINE) - tag->extensionFields.endLine = l; + setTagEndLine(tag, (unsigned long)l); else - { - tag->lineNumber = l; - tag->filePosition = getInputFilePositionForLine (l); - } + updateTagLine (tag, l, getInputFilePositionForLine (l));
return es_false; }
Modified: ctags/main/field.h 10 lines changed, 4 insertions(+), 6 deletions(-) =================================================================== @@ -20,7 +20,6 @@ #include "types.h"
#include "vstring.h" -#include "optscript.h"
/* * DATA DECLARATIONS @@ -70,7 +69,7 @@ typedef enum eFieldType { /* extension field content control */ FIELD_BUILTIN_LAST = FIELD_NTH, } fieldType ;
-#define fieldDataTypeFalgs "sib" /* used in --list-fields */ +#define fieldDataTypeFlags "sib" /* used in --list-fields */ typedef enum eFieldDataType { FIELDTYPE_STRING = 1 << 0, FIELDTYPE_INTEGER = 1 << 1, @@ -84,7 +83,6 @@ typedef const char* (*fieldRenderer)(const tagEntryInfo *const, const char *, vString *);
-#define FIELD_LETTER_NO_USE '\0' struct sFieldDefinition { /* letter, and ftype are initialized in the main part, not in a parser. */ @@ -101,13 +99,13 @@ struct sFieldDefinition { bool (* isValueAvailable) (const tagEntryInfo *const);
const char * getterValueType; - EsObject * (* getValueObject) (const tagEntryInfo *, const fieldDefinition *); + struct _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 *); + struct _EsObject * (* checkValueForSetter) (const fieldDefinition *, const struct _EsObject *); + struct _EsObject * (* setValueObject) (tagEntryInfo *, const fieldDefinition *, const struct _EsObject *);
fieldDataType dataType; /* used in json output */
Modified: ctags/main/field_p.h 12 lines changed, 9 insertions(+), 3 deletions(-) =================================================================== @@ -24,12 +24,15 @@ * DATA DECLARATIONS */
+#define FIELD_NULL_LETTER_CHAR '-' +#define FIELD_NULL_LETTER_STRING "-" +
/* * FUNCTION PROTOTYPES */
-extern fieldType getFieldTypeForOption (char letter); +extern fieldType getFieldTypeForLetter (char letter);
/* `getFieldTypeForName' is for looking for a field not owned by any parser, @@ -46,7 +49,10 @@ extern fieldType getFieldTypeForName (const char *name); extern fieldType getFieldTypeForNameAndLanguage (const char *fieldName, langType language); extern bool enableField (fieldType type, bool state); extern bool isCommonField (fieldType type); -extern int getFieldOwner (fieldType type); + +/* Return LANG_IGNORE if the field is a common field.*/ +extern langType getFieldLanguage (fieldType type); + extern const char* getFieldDescription (fieldType type); extern const char* getFieldName (fieldType type); extern unsigned char getFieldLetter (fieldType type); @@ -64,7 +70,7 @@ extern const char* renderFieldNoEscaping (fieldType type, const tagEntryInfo *ta extern bool doesFieldHaveTabOrNewlineChar (fieldType type, const tagEntryInfo *tag, int index);
extern void initFieldObjects (void); -extern int countFields (void); +extern unsigned int countFields (void);
/* language should be typed to langType. Use int here to avoid circular dependency */
Modified: ctags/main/fmt.c 12 lines changed, 7 insertions(+), 5 deletions(-) =================================================================== @@ -65,7 +65,7 @@ static int printTagField (fmtSpec* fspec, MIO* fp, const tagEntryInfo * tag) else { unsigned int findex; - const tagField *f; + const tagField *f = NULL;
for (findex = 0; findex < tag->usedParserFields; findex++) { @@ -74,8 +74,11 @@ static int printTagField (fmtSpec* fspec, MIO* fp, const tagEntryInfo * tag) break; }
- if (findex == tag->usedParserFields) + if (f == NULL || findex == tag->usedParserFields) + { + /* The condtion is redundant for suppressing the warning. */ str = ""; + } else if (isFieldEnabled (f->ftype)) { unsigned int dt = getFieldDataType (f->ftype); @@ -84,8 +87,7 @@ static int printTagField (fmtSpec* fspec, MIO* fp, const tagEntryInfo * tag) str = renderField (f->ftype, tag, findex); if ((dt & FIELDTYPE_BOOL) && str[0] == '\0') { - /* TODO: FIELD_NULL_LETTER_STRING */ - str = "-"; + str = FIELD_NULL_LETTER_STRING; } } else if (dt & FIELDTYPE_BOOL) @@ -198,7 +200,7 @@ static fmtElement** queueTagField (fmtElement **last, long width, bool truncatio else { language = LANG_IGNORE; - ftype = getFieldTypeForOption (field_letter); + ftype = getFieldTypeForLetter (field_letter); }
if (ftype == FIELD_UNKNOWN)
Modified: ctags/main/general.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -14,7 +14,7 @@ */ #if defined (HAVE_CONFIG_H) # include <config.h> -#elif defined (WIN32) +#elif defined (_WIN32) # include "e_msoft.h" #endif
Modified: ctags/main/htable.c 200 lines changed, 174 insertions(+), 26 deletions(-) =================================================================== @@ -11,6 +11,7 @@
#include "general.h" #include "htable.h" +#include "debug.h"
#ifndef MAIN #include <stdio.h> @@ -35,12 +36,14 @@ typedef struct sHashEntry hentry; struct sHashEntry { void *key; void *value; + unsigned int hash; hentry *next; };
struct sHashTable { hentry** table; unsigned int size; + unsigned int count; hashTableHashFunc hashfn; hashTableEqualFunc equalfn; hashTableDeleteFunc keyfreefn; @@ -56,13 +59,14 @@ struct chainTracker { hashTableEqualFunc equalfn; };
-static hentry* entry_new (void *key, void *value, hentry* next) +static hentry* entry_new (void *key, void *value, unsigned int hash, hentry* next) { hentry* entry = xMalloc (1, hentry);
entry->key = key; entry->value = value; entry->next = next; + entry->hash = hash;
return entry; } @@ -77,7 +81,9 @@ static void entry_reset (hentry* entry, keyfreefn (entry->key); if (valfreefn) valfreefn (entry@@ Diff output truncated at 100000 characters. @@
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).