[geany/geany] 92382d: Update to latest ctags main
Jiří Techet
git-noreply at xxxxx
Sun Feb 7 21:32:14 UTC 2021
Branch: refs/heads/master
Author: Jiří Techet <techet at gmail.com>
Committer: Jiří Techet <techet at gmail.com>
Date: Wed, 18 Nov 2020 21:22:41 UTC
Commit: 92382dcdbcccb7f531569dc291c33e275a2a9e44
https://github.com/geany/geany/commit/92382dcdbcccb7f531569dc291c33e275a2a9e44
Log Message:
-----------
Update to latest ctags main
See commit 2aa034a30dc54f5db18db2c9140821f64426283e upstream.
Modified Paths:
--------------
configure.ac
ctags/Makefile.am
ctags/main/args.c
ctags/main/args_p.h
ctags/main/cmd.c
ctags/main/colprint.c
ctags/main/colprint_p.h
ctags/main/ctags-api.c
ctags/main/ctags-api.h
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/entry_p.h
ctags/main/entry_private.c
ctags/main/error.c
ctags/main/error_p.h
ctags/main/field.c
ctags/main/field.h
ctags/main/field_p.h
ctags/main/flags.c
ctags/main/flags_p.h
ctags/main/fmt.c
ctags/main/fmt_p.h
ctags/main/gcc-attr.h
ctags/main/general.h
ctags/main/gvars.h
ctags/main/htable.c
ctags/main/htable.h
ctags/main/interactive_p.h
ctags/main/keyword.c
ctags/main/keyword.h
ctags/main/keyword_p.h
ctags/main/kind.c
ctags/main/kind.h
ctags/main/kind_p.h
ctags/main/lcpp.c
ctags/main/lcpp.h
ctags/main/lregex.c
ctags/main/lregex.h
ctags/main/lregex_p.h
ctags/main/lxcmd.c
ctags/main/lxpath.c
ctags/main/lxpath.h
ctags/main/lxpath_p.h
ctags/main/main.c
ctags/main/main.h
ctags/main/main_p.h
ctags/main/mbcs.c
ctags/main/mbcs.h
ctags/main/mbcs_p.h
ctags/main/mini-geany.c
ctags/main/mio.c
ctags/main/mio.h
ctags/main/nestlevel.c
ctags/main/nestlevel.h
ctags/main/numarray.c
ctags/main/numarray.h
ctags/main/objpool.c
ctags/main/options.c
ctags/main/options.h
ctags/main/options_p.h
ctags/main/output-ctags.c
ctags/main/output.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.h
ctags/main/parsers_p.h
ctags/main/pcoproc.c
ctags/main/pcoproc.h
ctags/main/portable-dirent_p.h
ctags/main/portable-scandir.c
ctags/main/promise.c
ctags/main/promise.h
ctags/main/promise_p.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/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/routines_p.h
ctags/main/seccomp.c
ctags/main/selectors.c
ctags/main/selectors.h
ctags/main/sort.c
ctags/main/sort_p.h
ctags/main/stats.c
ctags/main/stats_p.h
ctags/main/strlist.c
ctags/main/strlist.h
ctags/main/subparser.h
ctags/main/subparser_p.h
ctags/main/tokeninfo.c
ctags/main/tokeninfo.h
ctags/main/trace.c
ctags/main/trace.h
ctags/main/trashbox.h
ctags/main/trashbox_p.h
ctags/main/types.h
ctags/main/unwindi.c
ctags/main/unwindi.h
ctags/main/vstring.c
ctags/main/vstring.h
ctags/main/writer-ctags.c
ctags/main/writer-etags.c
ctags/main/writer-json.c
ctags/main/writer-xref.c
ctags/main/writer.c
ctags/main/writer_p.h
ctags/main/xtag.c
ctags/main/xtag.h
ctags/main/xtag_p.h
Modified: configure.ac
3 lines changed, 1 insertions(+), 2 deletions(-)
===================================================================
@@ -43,8 +43,7 @@ AC_CHECK_HEADERS([fcntl.h glob.h stdlib.h sys/time.h errno.h limits.h])
# Checks for dependencies needed by ctags
AC_CHECK_HEADERS([fnmatch.h direct.h io.h sys/dir.h])
-AC_DEFINE([USE_STDBOOL_H], [1], [whether or not to use <stdbool.h>.])
-AC_DEFINE([CTAGS_LIB], [1], [compile ctags as a library.])
+AC_DEFINE([HAVE_STDBOOL_H], [1], [whether or not to use <stdbool.h>.])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_OFF_T
Modified: ctags/Makefile.am
81 lines changed, 61 insertions(+), 20 deletions(-)
===================================================================
@@ -1,6 +1,7 @@
AM_CPPFLAGS = \
-I$(srcdir)/main \
-I$(srcdir)/parsers \
+ -DEXTERNAL_PARSER_LIST_FILE=\"$(top_srcdir)/src/tagmanager/tm_parsers.h\" \
-DG_LOG_DOMAIN=\"CTags\"
AM_CFLAGS = \
$(GTK_CFLAGS) \
@@ -30,6 +31,8 @@ parsers = \
parsers/html.c \
parsers/jscript.c \
parsers/json.c \
+ parsers/lcpp.c \
+ parsers/lcpp.h \
parsers/lua.c \
parsers/make.c \
parsers/markdown.c \
@@ -53,44 +56,56 @@ parsers = \
parsers/verilog.c \
parsers/vhdl.c
+# skip cmd.c and mini-geany.c which define main()
libctags_la_SOURCES = \
main/args.c \
- main/args.h \
+ main/args_p.h \
+ main/colprint.c \
+ main/colprint_p.h \
main/ctags.h \
- main/ctags-api.c \
- main/ctags-api.h \
- main/debug.h \
main/debug.c \
- main/dependency.h \
+ main/debug.h \
main/dependency.c \
+ main/dependency.h \
+ main/dependency_p.h \
main/e_msoft.h \
main/entry.c \
main/entry.h \
+ main/entry_p.h \
+ main/entry_private.c \
main/error.c \
- main/error.h \
+ main/error_p.h \
main/field.c \
main/field.h \
+ main/field_p.h \
main/flags.c \
- main/flags.h \
+ main/flags_p.h \
main/fmt.c \
- main/fmt.h \
+ main/fmt_p.h \
main/gcc-attr.h \
main/general.h \
+ main/gvars.h \
main/htable.c \
main/htable.h \
main/inline.h \
+ main/interactive_p.h \
main/keyword.c \
main/keyword.h \
+ main/keyword_p.h \
main/kind.c \
main/kind.h \
- main/lcpp.c \
- main/lcpp.h \
+ main/kind_p.h \
main/lregex.c \
- main/lxcmd.c \
+ main/lregex.h \
+ main/lregex_p.h \
main/lxpath.c \
+ main/lxpath.h \
+ main/lxpath_p.h \
main/main.c \
- main/main.h \
+ main/main_p.h \
+ main/mbcs.c \
main/mbcs.h \
+ main/mbcs_p.h \
main/mio.c \
main/mio.h \
main/nestlevel.c \
@@ -101,37 +116,63 @@ libctags_la_SOURCES = \
main/objpool.h \
main/options.c \
main/options.h \
- main/output-ctags.c \
- main/output.h \
+ main/options_p.h \
+ main/param.c \
+ main/param.h \
+ main/param_p.h \
main/parse.c \
main/parse.h \
- main/parsers.h \
- main/pcoproc.c \
- main/pcoproc.h \
+ main/parse_p.h \
+ main/parsers_p.h \
+ main/portable-dirent_p.h \
+ main/portable-scandir.c \
main/promise.c \
main/promise.h \
+ main/promise_p.h \
main/ptag.c \
- main/ptag.h \
+ main/ptag_p.h \
main/ptrarray.c \
main/ptrarray.h \
+ main/rbtree.c \
+ main/rbtree.h \
main/read.c \
main/read.h \
+ main/read_p.h \
main/repoinfo.c \
main/repoinfo.h \
main/routines.c \
main/routines.h \
+ main/routines_p.h \
+ main/seccomp.c \
main/selectors.c \
main/selectors.h \
main/sort.c \
- main/sort.h \
+ main/sort_p.h \
+ main/stats.c \
+ main/stats_p.h \
main/strlist.c \
main/strlist.h \
+ main/subparser.h \
+ main/subparser_p.h \
+ main/tokeninfo.c \
+ main/tokeninfo.h \
+ main/trace.c \
main/trace.h \
main/trashbox.c \
main/trashbox.h \
+ main/trashbox_p.h \
main/types.h \
+ main/unwindi.c \
+ main/unwindi.h \
main/vstring.c \
main/vstring.h \
- main/xtag.h \
+ main/writer-ctags.c \
+ main/writer-etags.c \
+ main/writer-json.c \
+ main/writer-xref.c \
+ main/writer.c \
+ main/writer_p.h \
main/xtag.c \
+ main/xtag.h \
+ main/xtag_p.h \
$(parsers)
Modified: ctags/main/args.c
6 lines changed, 4 insertions(+), 2 deletions(-)
===================================================================
@@ -16,9 +16,10 @@
#include <string.h>
#include <ctype.h>
-#include "args.h"
+#include "args_p.h"
#include "debug.h"
#include "routines.h"
+#include "vstring.h"
/*
* FUNCTION DEFINITIONS
@@ -281,7 +282,8 @@ extern void argForth (Arguments* const current)
extern void argDelete (Arguments* const current)
{
Assert (current != NULL);
- if (current->type == ARG_STRING && current->item != NULL)
+ if ((current->type == ARG_STRING
+ || current->type == ARG_FILE) && current->item != NULL)
eFree (current->item);
memset (current, 0, sizeof (Arguments));
eFree (current);
Modified: ctags/main/args_p.h
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -6,8 +6,8 @@
*
* Defines external interface to command line argument reading.
*/
-#ifndef CTAGS_MAIN_ARGS_H
-#define CTAGS_MAIN_ARGS_H
+#ifndef CTAGS_MAIN_ARGS_PRIVATE_H
+#define CTAGS_MAIN_ARGS_PRIVATE_H
/*
* INCLUDE FILES
@@ -54,4 +54,4 @@ extern void argSetLineMode (Arguments* const current);
extern void argForth (Arguments* const current);
extern void argDelete (Arguments* const current);
-#endif /* CTAGS_MAIN_ARGS_H */
+#endif /* CTAGS_MAIN_ARGS_PRIVATE_H */
Modified: ctags/main/cmd.c
22 lines changed, 22 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,22 @@
+/*
+* Copyright (c) 1998-2002, Darren Hiebert
+*
+* This source code is released for free distribution under the terms of the
+* GNU General Public License version 2 or (at your option) any later version.
+*/
+
+/*
+* INCLUDE FILES
+*/
+#include "general.h" /* must always come first */
+
+#include "main_p.h"
+
+
+/*
+* FUNCTION DEFINITIONS
+*/
+int main(int argc, char **argv)
+{
+ return ctags_cli_main (argc, argv);
+}
Modified: ctags/main/colprint.c
295 lines changed, 295 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,295 @@
+/*
+* Copyright (c) 2017 Masatake YAMATO
+*
+* This source code is released for free distribution under the terms of the
+* GNU General Public License version 2 or (at your option) any later version.
+*
+*/
+#include "general.h" /* must always come first */
+
+#include "colprint_p.h"
+#include "ptrarray.h"
+#include "routines.h"
+#include "strlist.h"
+#include "vstring.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+enum colprintJustification {
+ COLPRINT_LEFT, /* L:... */
+ COLPRINT_RIGHT, /* R:... */
+ COLPRINT_LAST,
+};
+
+struct colprintHeaderColumn {
+ vString *value;
+ enum colprintJustification justification;
+ unsigned int maxWidth;
+ bool needPrefix;
+};
+
+struct colprintTable {
+ ptrArray *header;
+ ptrArray *lines;
+};
+
+static void fillWithWhitespaces (int i, FILE *fp)
+{
+ while (i-- > 0)
+ {
+ fputc(' ', fp);
+ }
+}
+
+static struct colprintHeaderColumn * colprintHeaderColumnNew (const char* spec)
+{
+ int offset = 2;
+ struct colprintHeaderColumn *headerCol = xCalloc (1, struct colprintHeaderColumn);
+
+ if (strstr(spec, "L:") == spec)
+ headerCol->justification = COLPRINT_LEFT;
+ else if (strstr(spec, "R:") == spec)
+ headerCol->justification = COLPRINT_RIGHT;
+ else
+ {
+ headerCol->justification = COLPRINT_LEFT;
+ offset = 0;
+ }
+
+ headerCol->value = vStringNewInit(spec + offset);
+ headerCol->maxWidth = vStringLength(headerCol->value);
+ return headerCol;
+}
+
+static void colprintHeaderColumnDelete (struct colprintHeaderColumn * headerCol)
+{
+ vStringDelete (headerCol->value);
+ eFree (headerCol);
+}
+
+struct colprintTable *colprintTableNew (const char* columnHeader, ... /* NULL TERMINATED */)
+{
+ char *tmp;
+ va_list ap;
+ struct colprintTable *table;
+ struct colprintHeaderColumn *headerCol;
+
+
+ table = xCalloc (1, struct colprintTable);
+ table->header = ptrArrayNew ((ptrArrayDeleteFunc)colprintHeaderColumnDelete);
+ table->lines = ptrArrayNew ((ptrArrayDeleteFunc)stringListDelete);
+
+ headerCol = colprintHeaderColumnNew(columnHeader);
+ ptrArrayAdd (table->header, headerCol);
+
+ va_start(ap, columnHeader);
+ while (1)
+ {
+ tmp = va_arg(ap, char*);
+ if (tmp)
+ {
+ headerCol = colprintHeaderColumnNew(tmp);
+ ptrArrayAdd (table->header, headerCol);
+ }
+ else
+ break;
+ }
+ va_end(ap);
+
+ struct colprintHeaderColumn *last_col = ptrArrayLast (table->header);
+ if (last_col)
+ last_col->justification = COLPRINT_LAST;
+
+ return table;
+}
+
+void colprintTableDelete (struct colprintTable *table)
+{
+ ptrArrayDelete(table->header);
+ table->header = NULL;
+
+ ptrArrayDelete(table->lines);
+ table->header = NULL;
+
+ eFree (table);
+}
+
+static void colprintColumnPrintGeneric (vString *column, struct colprintHeaderColumn *spec, bool machinable, FILE *fp)
+{
+ int maxWidth = spec->maxWidth + (spec->needPrefix? 1: 0);
+
+ if ((column == spec->value) && (spec->needPrefix))
+ {
+ fputc('#', fp);
+ maxWidth--;
+ }
+
+ if (machinable)
+ {
+ fputs (vStringValue (column), fp);
+ if (spec->justification != COLPRINT_LAST)
+ fputc ('\t', fp);
+ }
+ else
+ {
+ int padLen = maxWidth - vStringLength (column);
+ if (spec->justification == COLPRINT_LEFT
+ || spec->justification == COLPRINT_LAST)
+ {
+ fputs (vStringValue (column), fp);
+ if (spec->justification != COLPRINT_LAST)
+ {
+ fillWithWhitespaces (padLen, fp);
+ fputc (' ', fp);
+ }
+ }
+ else
+ {
+ fillWithWhitespaces (padLen, fp);
+ fputs (vStringValue (column), fp);
+ fputc (' ', fp);
+ }
+ }
+}
+
+static void colprintHeaderColumnPrint (struct colprintHeaderColumn *headerCol, bool machinable, FILE* fp)
+{
+ colprintColumnPrintGeneric (headerCol->value, headerCol, machinable, fp);
+}
+
+static void colprintHeaderPrint (ptrArray *header, unsigned int startFrom, bool withHeader, bool machinable, FILE *fp)
+{
+ unsigned int i;
+
+ if (!withHeader)
+ return;
+
+ for (i = startFrom; i < ptrArrayCount(header); i++)
+ {
+ struct colprintHeaderColumn *headerCol = ptrArrayItem (header, i);
+ colprintHeaderColumnPrint (headerCol, machinable, fp);
+ }
+ fputc('\n', fp);
+}
+
+static void colprintLinePrint (stringList *line, unsigned int startFrom, ptrArray *header, bool machinable, FILE *fp)
+{
+ unsigned int i;
+
+ for (i = startFrom; i < stringListCount (line); i++)
+ {
+ vString *value = stringListItem(line, i);
+ struct colprintHeaderColumn *spec = ptrArrayItem (header, i);
+ colprintColumnPrintGeneric(value, spec, machinable, fp);
+ }
+}
+static void colprintLinesPrint (ptrArray *lines, unsigned int startFrom, ptrArray *header, bool machinable, FILE *fp)
+{
+ unsigned int i;
+
+ for (i = 0; i < ptrArrayCount (lines); i++)
+ {
+ stringList *line = ptrArrayItem (lines, i);
+ colprintLinePrint (line, startFrom, header, machinable, fp);
+ fputc('\n', fp);
+ }
+}
+
+static void colprintUpdateMaxWidths (ptrArray *header, ptrArray *lines, unsigned int startFrom)
+{
+ for (unsigned int c = 0; c < ptrArrayCount(header); c++)
+ {
+ struct colprintHeaderColumn *spec = ptrArrayItem (header, c);
+
+ if (c == startFrom)
+ spec->needPrefix = true;
+ else
+ spec->needPrefix = false;
+ }
+
+ for (unsigned int c = 0; c < ptrArrayCount(header); c++)
+ {
+ struct colprintHeaderColumn *spec = ptrArrayItem (header, c);
+
+ for (unsigned int l = 0; l < ptrArrayCount(lines); l++)
+ {
+ struct colprintLine *line = ptrArrayItem(lines, l);
+ vString *column = ptrArrayItem((ptrArray *)line, c);
+ if (spec->maxWidth < vStringLength(column))
+ spec->maxWidth = vStringLength(column);
+ }
+ }
+}
+
+void colprintTablePrint (struct colprintTable *table, unsigned int startFrom, bool withHeader, bool machinable, FILE *fp)
+{
+ colprintUpdateMaxWidths (table->header, table->lines, startFrom);
+
+ colprintHeaderPrint (table->header, startFrom, withHeader, machinable, fp);
+ colprintLinesPrint (table->lines, startFrom, table->header, machinable, fp);
+}
+
+void colprintTableSort (struct colprintTable *table, int (* compareFn) (struct colprintLine *, struct colprintLine *))
+{
+ ptrArraySort (table->lines, (int (*) (const void *, const void *))compareFn);
+}
+
+struct colprintLine *colprintTableGetNewLine (struct colprintTable *table)
+{
+ stringList *line = stringListNew ();
+
+ ptrArrayAdd (table->lines, line);
+ return (struct colprintLine *)line;
+}
+
+static void colprintLineAppendColumn (struct colprintLine *line, vString *column)
+{
+ stringList *slist = (stringList *)line;
+ stringListAdd (slist, column);
+}
+
+void colprintLineAppendColumnCString (struct colprintLine *line, const char *column)
+{
+ vString* vcol = vStringNewInit (column? column: "");
+ colprintLineAppendColumn (line, vcol);
+}
+
+void colprintLineAppendColumnVString (struct colprintLine *line, vString* column)
+{
+ colprintLineAppendColumnCString(line, vStringValue (column));
+}
+
+void colprintLineAppendColumnChar (struct colprintLine *line, char column)
+{
+ vString* vcol = vStringNew ();
+ vStringPut (vcol, column);
+ colprintLineAppendColumn (line, vcol);
+}
+
+void colprintLineAppendColumnInt (struct colprintLine *line, unsigned int column)
+{
+ char buf[12];
+
+ snprintf(buf, 12, "%u", column);
+ colprintLineAppendColumnCString (line, buf);
+}
+
+void colprintLineAppendColumnBool (struct colprintLine *line, bool column)
+{
+ colprintLineAppendColumnCString (line, column? "yes": "no");
+}
+
+const char *colprintLineGetColumn (struct colprintLine *line, unsigned int column)
+{
+ stringList *slist = (stringList *)line;
+ if (column <= stringListCount(slist))
+ {
+ vString *vstr = stringListItem (slist, column);
+ return vStringValue (vstr);
+ }
+ else
+ return NULL;
+}
Modified: ctags/main/colprint_p.h
37 lines changed, 37 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2017 Masatake YAMATO
+*
+* This source code is released for free distribution under the terms of the
+* GNU General Public License version 2 or (at your option) any later version.
+*
+*/
+#ifndef CTAGS_MAIN_COLPRINT_PRIVATE_H
+#define CTAGS_MAIN_COLPRINT_PRIVATE_H
+
+#include "general.h"
+
+#include "vstring.h"
+#include <stdio.h>
+
+struct colprintTable;
+struct colprintLine;
+
+/* Each column must have a prefix for specifying justification: "L:" or "R:". */
+struct colprintTable *colprintTableNew (const char* columnHeader, ... /* NULL TERMINATED */);
+void colprintTableDelete (struct colprintTable *table);
+void colprintTablePrint (struct colprintTable *table, unsigned int startFrom, bool withHeader, bool machinable, FILE *fp);
+void colprintTableSort (struct colprintTable *table, int (* compareFn) (struct colprintLine *, struct colprintLine *));
+
+struct colprintLine *colprintTableGetNewLine (struct colprintTable *table);
+
+void colprintLineAppendColumnCString (struct colprintLine *line, const char* column);
+void colprintLineAppendColumnVString (struct colprintLine *line, vString* column);
+void colprintLineAppendColumnChar (struct colprintLine *line, char column);
+void colprintLineAppendColumnInt (struct colprintLine *line, unsigned int column);
+
+/* Appends "yes" or "no". */
+void colprintLineAppendColumnBool (struct colprintLine *line, bool column);
+
+const char *colprintLineGetColumn (struct colprintLine *line, unsigned int column);
+
+#endif /* CTAGS_MAIN_COLPRINT_PRIVATE_H */
Modified: ctags/main/ctags-api.c
144 lines changed, 0 insertions(+), 144 deletions(-)
===================================================================
@@ -1,144 +0,0 @@
-/*
-* Copyright (c) 2016, Jiri Techet
-*
-* This source code is released for free distribution under the terms of the
-* GNU General Public License version 2 or (at your option) any later version.
-*
-* Defines ctags API when compiled as a library.
-*/
-
-#include "general.h" /* must always come first */
-
-#ifdef CTAGS_LIB
-
-#include "ctags-api.h"
-#include "types.h"
-#include "routines.h"
-#include "error.h"
-#include "output.h"
-#include "parse.h"
-#include "options.h"
-#include "trashbox.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-static bool nofatalErrorPrinter (const errorSelection selection,
- const char *const format,
- va_list ap, void *data CTAGS_ATTR_UNUSED)
-{
- fprintf (stderr, "%s: ", (selection & WARNING) ? "Warning: " : "Error");
- vfprintf (stderr, format, ap);
- if (selection & PERROR)
-#ifdef HAVE_STRERROR
- fprintf (stderr, " : %s", strerror (errno));
-#else
- perror (" ");
-#endif
- fputs ("\n", stderr);
-
- return false;
-}
-
-extern void ctagsInit(void)
-{
- setErrorPrinter (nofatalErrorPrinter, NULL);
- setTagWriter (&ctagsWriter);
-
- checkRegex ();
- initFieldDescs ();
-
- initializeParsing ();
- initOptions ();
-
- initDefaultTrashBox ();
-
- /* make sure all parsers are initialized */
- initializeParser (LANG_AUTO);
-}
-
-
-
-extern void ctagsParse(unsigned char *buffer, size_t bufferSize,
- const char *fileName, const langType language,
- tagEntryFunction tagCallback, passStartCallback passCallback,
- void *userData)
-{
- if (buffer == NULL && fileName == NULL)
- {
- error(FATAL, "Neither buffer nor file provided to ctagsParse()");
- return;
- }
-
- createTagsWithFallback(buffer, bufferSize, fileName, language,
- tagCallback, passCallback, userData);
-}
-
-
-extern const char *ctagsGetLangName(int lang)
-{
- return getLanguageName(lang);
-}
-
-
-extern int ctagsGetNamedLang(const char *name)
-{
- return getNamedLanguage(name, 0);
-}
-
-
-extern const char *ctagsGetLangKinds(int lang)
-{
- const parserDefinition *def = getParserDefinition(lang);
- unsigned int i;
- static char kinds[257];
-
- for (i = 0; i < def->kindCount; i++)
- kinds[i] = def->kindTable[i].letter;
- kinds[i] = '\0';
-
- return kinds;
-}
-
-
-extern const char *ctagsGetKindName(char kind, int lang)
-{
- const parserDefinition *def = getParserDefinition(lang);
- unsigned int i;
-
- for (i = 0; i < def->kindCount; i++)
- {
- if (def->kindTable[i].letter == kind)
- return def->kindTable[i].name;
- }
- return "unknown";
-}
-
-
-extern char ctagsGetKindFromName(const char *name, int lang)
-{
- const parserDefinition *def = getParserDefinition(lang);
- unsigned int i;
-
- for (i = 0; i < def->kindCount; i++)
- {
- if (strcmp(def->kindTable[i].name, name) == 0)
- return def->kindTable[i].letter;
- }
- return '-';
-}
-
-
-extern bool ctagsIsUsingRegexParser(int lang)
-{
- return getParserDefinition(lang)->method & METHOD_REGEX;
-}
-
-
-extern unsigned int ctagsGetLangCount(void)
-{
- return countParsers();
-}
-
-#endif /* CTAGS_LIB */
Modified: ctags/main/ctags-api.h
57 lines changed, 0 insertions(+), 57 deletions(-)
===================================================================
@@ -1,57 +0,0 @@
-/*
-* Copyright (c) 2016, Jiri Techet
-*
-* This source code is released for free distribution under the terms of the
-* GNU General Public License version 2 or (at your option) any later version.
-*
-* Defines ctags API when compiled as a library.
-*/
-#ifndef CTAGS_API_H
-#define CTAGS_API_H
-
-#include "general.h" /* must always come first */
-
-#ifdef CTAGS_LIB
-
-#include <stdlib.h>
-#include <stdbool.h>
-
-typedef struct {
- const char *name;
- const char *signature;
- const char *scopeName;
- const char *inheritance;
- const char *varType;
- const char *access;
- const char *implementation;
- char kindLetter;
- bool isFileScope;
- unsigned long lineNumber;
- int lang;
-} ctagsTag;
-
-/* Callback invoked for every tag found by the parser. The return value is
- * currently unused. */
-typedef bool (*tagEntryFunction) (const ctagsTag *const tag, void *userData);
-
-/* Callback invoked at the beginning of every parsing pass. The return value is
- * currently unused */
-typedef bool (*passStartCallback) (void *userData);
-
-
-extern void ctagsInit(void);
-extern void ctagsParse(unsigned char *buffer, size_t bufferSize,
- const char *fileName, const int language,
- tagEntryFunction tagCallback, passStartCallback passCallback,
- void *userData);
-extern const char *ctagsGetLangName(int lang);
-extern int ctagsGetNamedLang(const char *name);
-extern const char *ctagsGetLangKinds(int lang);
-extern const char *ctagsGetKindName(char kind, int lang);
-extern char ctagsGetKindFromName(const char *name, int lang);
-extern bool ctagsIsUsingRegexParser(int lang);
-extern unsigned int ctagsGetLangCount(void);
-
-#endif /* CTAGS_LIB */
-
-#endif /* CTAGS_API_H */
Modified: ctags/main/ctags.h
10 lines changed, 8 insertions(+), 2 deletions(-)
===================================================================
@@ -17,7 +17,7 @@
#if defined (HAVE_CONFIG_H)
# define PROGRAM_VERSION PACKAGE_VERSION
#else
-# define PROGRAM_VERSION "0.0.0"
+# define PROGRAM_VERSION "5.9.0"
#endif
#define PROGRAM_NAME "Universal Ctags"
#define PROGRAM_URL "https://ctags.io/"
@@ -30,5 +30,11 @@
extern const char* ctags_repoinfo;
#define CTAGS_FIELD_PREFIX "UCTAGS"
-
+/*
+ * Reserved words
+ */
+#define RSV_LANGMAP_DEFAULT "default"
+#define RSV_LANG_ALL "all"
+#define RSV_LANG_AUTO "auto"
+#define RSV_NONE "NONE"
#endif /* CTAGS_MAIN_CTAGS_H */
Modified: ctags/main/debug.c
103 lines changed, 99 insertions(+), 4 deletions(-)
===================================================================
@@ -16,16 +16,22 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+#include <string.h>
#include "debug.h"
+#include "entry_p.h"
#include "options.h"
+#include "parse_p.h"
#include "read.h"
+#include "read_p.h"
/*
* FUNCTION DEFINITIONS
*/
#ifdef DEBUG
+#include "htable.h"
+
extern void lineBreak (void) {} /* provides a line-specified break point */
@@ -74,11 +80,16 @@ extern void debugEntry (const tagEntryInfo *const tag)
if (debug (DEBUG_PARSE))
{
- printf ("<#%s%s:%s", scope, tag->kind->name, tag->name);
-
- if (tag->extensionFields.scopeKind != NULL &&
+ langType lang = (tag->extensionFields.scopeLangType == LANG_AUTO)
+ ? tag->langType
+ : tag->extensionFields.scopeLangType;
+ kindDefinition *scopeKindDef = getLanguageKind(lang,
+ tag->extensionFields.scopeKindIndex);
+ printf ("<#%s%s:%s", scope, getTagKindName(tag), tag->name);
+
+ if (tag->extensionFields.scopeKindIndex != KIND_GHOST_INDEX &&
tag->extensionFields.scopeName != NULL)
- printf (" [%s:%s]", tag->extensionFields.scopeKind->name,
+ printf (" [%s:%s]", scopeKindDef->name,
tag->extensionFields.scopeName);
if (isFieldEnabled (FIELD_INHERITANCE) &&
@@ -125,4 +136,88 @@ extern void debugAssert (const char *assertion, const char *file, unsigned int l
abort();
}
+static int debugScopeDepth;
+#define DEBUG_INDENT_UNIT 4
+
+static char debugPrefix[DEBUG_INDENT_UNIT + 1];
+
+extern void debugInit (void)
+{
+ memset(debugPrefix, ' ', DEBUG_INDENT_UNIT);
+ debugPrefix[DEBUG_INDENT_UNIT] = '\0';
+}
+
+extern void debugIndent(void)
+{
+ for(int i=0;i< debugScopeDepth;i++)
+ fputs(debugPrefix, stderr);
+}
+
+extern void debugInc(void)
+{
+ debugScopeDepth++;
+}
+
+extern void debugDec(void)
+{
+ debugScopeDepth--;
+ if(debugScopeDepth < 0)
+ debugScopeDepth = 0;
+}
+
+
+
+struct circularRefChecker {
+ hashTable *visitTable;
+ int counter;
+};
+
+extern void circularRefCheckerDestroy (struct circularRefChecker * checker)
+{
+ hashTableDelete (checker->visitTable);
+ checker->visitTable = NULL;
+ eFree (checker);
+}
+
+extern struct circularRefChecker * circularRefCheckerNew (void)
+{
+ Assert (sizeof(void *) >= sizeof(int));
+
+ struct circularRefChecker *c = xMalloc (1, struct circularRefChecker);
+
+ c->visitTable = hashTableNew (17, hashPtrhash, hashPtreq, NULL, NULL);
+ c->counter = 0;
+
+ return c;
+}
+
+extern int circularRefCheckerCheck (struct circularRefChecker *c, void *ptr)
+{
+ union conv {
+ int i;
+ void *ptr;
+ } v;
+
+ v.ptr = hashTableGetItem(c->visitTable, ptr);
+ if (v.ptr)
+ return v.i;
+ else
+ {
+ v.i = ++c->counter;
+ hashTablePutItem (c->visitTable, ptr, v.ptr);
+ return 0;
+ }
+}
+
+extern int circularRefCheckerGetCurrent (struct circularRefChecker *c)
+{
+ return c->counter;
+}
+
+extern void circularRefCheckClear (struct circularRefChecker *c)
+{
+ hashTableClear (c->visitTable);
+ c->counter = 0;
+}
+
#endif
Modified: ctags/main/debug.h
32 lines changed, 26 insertions(+), 6 deletions(-)
===================================================================
@@ -14,27 +14,26 @@
*/
#include "general.h" /* must always come first */
+#include "gvars.h"
+#include "types.h"
#ifdef DEBUG
# include <assert.h>
#endif
-#include "entry.h"
/*
* Macros
*/
#ifdef DEBUG
-# define debug(level) ((Option.debugLevel & (long)(level)) != 0)
+# define debug(level) ((ctags_debugLevel & (long)(level)) != 0)
# define DebugStatement(x) x
# define PrintStatus(x) if (debug(DEBUG_STATUS)) printf x;
# ifdef NDEBUG
# define Assert(c) do {} while(0)
# define AssertNotReached() do {} while(0)
# else
- /* based on glibc's assert.h __ASSERT_FUNCTION */
-# if defined (__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 4))
-# define ASSERT_FUNCTION __PRETTY_FUNCTION__
-# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+ /* We expect cc supports c99 standard. */
+# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
# define ASSERT_FUNCTION __func__
# else
# define ASSERT_FUNCTION ((const char*)0)
@@ -52,6 +51,10 @@
# endif
#endif
+#ifdef DEBUG
+/* This makes valgrind report an error earlier. */
+#define DISABLE_OBJPOOL
+#endif
/*
* Data declarations
*/
@@ -79,4 +82,21 @@ extern void debugCppIgnore (const bool ignore);
extern void debugEntry (const tagEntryInfo *const tag);
extern void debugAssert (const char *assertion, const char *file, unsigned int line, const char *function) attr__noreturn;
+#ifdef DEBUG
+#define DEBUG_INIT() debugInit()
+extern void debugInit (void);
+extern void debugIndent(void);
+extern void debugInc(void);
+extern void debugDec(void);
+
+struct circularRefChecker;
+extern struct circularRefChecker * circularRefCheckerNew (void);
+extern void circularRefCheckerDestroy (struct circularRefChecker * checker);
+extern int circularRefCheckerCheck (struct circularRefChecker *c, void *ptr);
+extern int circularRefCheckerGetCurrent (struct circularRefChecker *c);
+extern void circularRefCheckClear (struct circularRefChecker *c);
+
+#else
+#define DEBUG_INIT() do { } while(0)
+#endif /* DEBUG */
#endif /* CTAGS_MAIN_DEBUG_H */
Modified: ctags/main/dependency.c
353 lines changed, 303 insertions(+), 50 deletions(-)
===================================================================
@@ -12,91 +12,344 @@
#include "general.h" /* must always come first */
+#include "debug.h"
#include "dependency.h"
-#include "parse.h"
+#include "options.h"
+#include "parse_p.h"
+#include "read.h"
+#include "read_p.h"
+#include "routines.h"
+#include "subparser.h"
+#include "subparser_p.h"
+#include "xtag.h"
#include <string.h>
+struct slaveControlBlock {
+ slaveParser *slaveParsers; /* The parsers on this list must be initialized when
+ this parser is initialized. */
+ subparser *subparsersDefault;
+ subparser *subparsersInUse;
+ langType owner;
+};
-static void linkKinds (kindDefinition *masterKind, kindDefinition *slaveKind)
+extern void linkDependencyAtInitializeParsing (depType dtype,
+ parserDefinition *const master,
+ struct slaveControlBlock *masterSCB,
+ struct kindControlBlock *masterKCB,
+ parserDefinition *const slave,
+ struct kindControlBlock *slaveKCB,
+ void *data)
{
- kindDefinition *tail;
+ if (dtype == DEPTYPE_KIND_OWNER)
+ linkKindDependency (masterKCB, slaveKCB);
+ else if (dtype == DEPTYPE_SUBPARSER)
+ {
+ slaveParser *s = xMalloc (1, slaveParser);
- slaveKind->master = masterKind;
+ s->type = dtype;
+ s->id = slave->id;
+ s->data = data;
- tail = slaveKind;
- while (tail->slave)
- {
- tail->enabled = masterKind->enabled;
- tail = tail->slave;
+ s->next = masterSCB->slaveParsers;
+ masterSCB->slaveParsers = s;
}
+}
- tail->slave = masterKind->slave;
- masterKind->slave = slaveKind;
+static void attachSubparser (struct slaveControlBlock *base_sb, subparser *subparser)
+{
+ subparser->next = base_sb->subparsersDefault;
+ base_sb->subparsersDefault = subparser;
}
-static void linkKindDependency (parserDefinition *const masterParser,
- parserDefinition *const slaveParser)
+
+extern struct slaveControlBlock *allocSlaveControlBlock (parserDefinition *parser)
{
- unsigned int k_slave, k_master;
- kindDefinition *kind_slave, *kind_master;
+ struct slaveControlBlock *cb;
- for (k_slave = 0; k_slave < slaveParser->kindCount; k_slave++)
+ cb = xMalloc (1, struct slaveControlBlock);
+ cb->slaveParsers = NULL;
+ cb->subparsersDefault = NULL;
+ cb->subparsersInUse = NULL;
+ cb->owner = parser->id;
+
+ return cb;
+}
+
+extern void freeSlaveControlBlock (struct slaveControlBlock *cb)
+{
+ eFree (cb);
+}
+
+extern void initializeDependencies (parserDefinition *parser,
+ struct slaveControlBlock *cb)
+{
+ unsigned int i;
+ slaveParser *sp;
+
+ /* Initialize slaves */
+ sp = cb->slaveParsers;
+ while (sp != NULL)
{
- if (slaveParser->kindTable [k_slave].syncWith == LANG_AUTO)
+ if (sp->type == DEPTYPE_SUBPARSER)
{
- kind_slave = slaveParser->kindTable + k_slave;
- for (k_master = 0; k_master < masterParser->kindCount; k_master++)
+ subparser *sub;
+
+ sub = (subparser *)sp->data;
+ sub->slaveParser = sp;
+ }
+
+ if (sp->type == DEPTYPE_KIND_OWNER
+ || (sp->type == DEPTYPE_SUBPARSER &&
+ (((subparser *)sp->data)->direction & SUBPARSER_BASE_RUNS_SUB)))
+ {
+ initializeParser (sp->id);
+ if (sp->type == DEPTYPE_SUBPARSER
+ && isXtagEnabled (XTAG_SUBPARSER))
{
- kind_master = masterParser->kindTable + k_master;
- if ((kind_slave->letter == kind_master->letter)
- && (strcmp (kind_slave->name, kind_master->name) == 0))
- {
- linkKinds (kind_master, kind_slave);
- kind_slave->syncWith = masterParser->id;
- kind_master->syncWith = masterParser->id;
- break;
- }
+ subparser *subparser = sp->data;
+ attachSubparser (cb, subparser);
}
}
+ sp = sp->next;
+ }
+
+ /* Initialize masters that act as base parsers. */
+ 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)
+ {
+ langType baseParser;
+ baseParser = getNamedLanguage (d->upperParser, 0);
+ Assert (baseParser != LANG_IGNORE);
+ initializeParser (baseParser);
+ }
}
}
-extern void linkDependencyAtInitializeParsing (depType dtype,
- parserDefinition *const masterParser,
- parserDefinition *const slaveParser)
+extern void finalizeDependencies (parserDefinition *parser,
+ struct slaveControlBlock *cb)
{
- if (dtype == DEPTYPE_KIND_OWNER)
- linkKindDependency (masterParser, slaveParser);
- else if (dtype == DEPTYPE_SUBPARSER)
+ while (cb->slaveParsers)
{
- subparser *s = xMalloc (1, subparser);
+ slaveParser *sp = cb->slaveParsers;
+ cb->slaveParsers = sp->next;
+ sp->next = NULL;
+ eFree (sp);
+ }
+}
+
+extern void notifyInputStart (void)
+{
+ subparser *s;
- s->id = slaveParser->id;
- s->next = masterParser->subparsers;
- masterParser->subparsers = s;
+ foreachSubparser(s, false)
+ {
+ langType lang = getSubparserLanguage (s);
+ notifyLanguageRegexInputStart (lang);
+
+ if (s->inputStart)
+ {
+ enterSubparser(s);
+ s->inputStart (s);
+ leaveSubparser();
+ }
}
}
-extern void initializeSubparsers (const parserDefinition *parser)
+extern void notifyInputEnd (void)
{
- subparser *sp;
+ subparser *s;
+
+ foreachSubparser(s, false)
+ {
+ if (s->inputEnd)
+ {
+ enterSubparser(s);
+ s->inputEnd (s);
+ leaveSubparser();
+ }
+
+ langType lang = getSubparserLanguage (s);
+ notifyLanguageRegexInputEnd (lang);
+ }
+}
- for (sp = parser->subparsers; sp; sp = sp->next)
- initializeParser (sp->id);
+extern void notifyMakeTagEntry (const tagEntryInfo *tag, int corkIndex)
+{
+ subparser *s;
+
+ foreachSubparser(s, false)
+ {
+ if (s->makeTagEntryNotify)
+ {
+ enterSubparser(s);
+ s->makeTagEntryNotify (s, tag, corkIndex);
+ leaveSubparser();
+ }
+ }
+}
+
+extern langType getSubparserLanguage (subparser *s)
+{
+ return s->slaveParser->id;
+}
+
+extern void chooseExclusiveSubparser (subparser *s, void *data)
+{
+ if (s->exclusiveSubparserChosenNotify)
+ {
+ s->chosenAsExclusiveSubparser = true;
+ enterSubparser(s);
+ s->exclusiveSubparserChosenNotify (s, data);
+ verbose ("%s is chosen as exclusive subparser\n",
+ getLanguageName (getSubparserLanguage (s)));
+ leaveSubparser();
+ }
}
-extern void finalizeSubparsers (parserDefinition *parser)
+extern subparser *getFirstSubparser(struct slaveControlBlock *controlBlock)
+{
+ if (controlBlock)
+ return controlBlock->subparsersInUse;
+ return NULL;
+}
+
+extern void useDefaultSubparsers (struct slaveControlBlock *controlBlock)
+{
+ controlBlock->subparsersInUse = controlBlock->subparsersDefault;
+}
+
+extern void useSpecifiedSubparser (struct slaveControlBlock *controlBlock, subparser *s)
+{
+ s->schedulingBaseparserExplicitly = true;
+ controlBlock->subparsersInUse = s;
+}
+
+extern void setupSubparsersInUse (struct slaveControlBlock *controlBlock)
+{
+ if (!controlBlock->subparsersInUse)
+ useDefaultSubparsers(controlBlock);
+}
+
+extern subparser* teardownSubparsersInUse (struct slaveControlBlock *controlBlock)
{
- subparser *sp;
subparser *tmp;
+ subparser *s = NULL;
- for (sp = parser->subparsers; sp;)
+ tmp = controlBlock->subparsersInUse;
+ controlBlock->subparsersInUse = NULL;
+
+ if (tmp && tmp->schedulingBaseparserExplicitly)
{
- tmp = sp;
- sp = sp->next;
- tmp->next = NULL;
- eFree (tmp);
+ tmp->schedulingBaseparserExplicitly = false;
+ s = tmp;
}
- parser->subparsers = NULL;
+
+ if (s)
+ return s;
+
+ while (tmp)
+ {
+ if (tmp->chosenAsExclusiveSubparser)
+ {
+ s = tmp;
+ }
+ tmp = tmp->next;
+ }
+
+ return s;
+}
+
+
+static int subparserDepth;
+
+extern void enterSubparser(subparser *subparser)
+{
+ subparserDepth++;
+ pushLanguage (getSubparserLanguage (subparser));
+}
+
+extern void leaveSubparser(void)
+{
+ popLanguage ();
+ subparserDepth--;
+}
+
+extern bool doesSubparserRun (void)
+{
+ if (getLanguageForBaseParser () == getInputLanguage())
+ return false;
+ return subparserDepth;
+}
+
+extern slaveParser *getFirstSlaveParser (struct slaveControlBlock *scb)
+{
+ if (scb)
+ return scb->slaveParsers;
+ return NULL;
+}
+
+extern struct colprintTable * subparserColprintTableNew (void)
+{
+ return colprintTableNew ("L:NAME", "L:BASEPARSER", "L:DIRECTIONS", NULL);
+}
+
+extern void subparserColprintAddSubparsers (struct colprintTable *table,
+ struct slaveControlBlock *scb)
+{
+ slaveParser *tmp;
+
+ pushLanguage (scb->owner);
+ foreachSlaveParser(tmp)
+ {
+ struct colprintLine *line = colprintTableGetNewLine(table);
+
+ colprintLineAppendColumnCString (line, getLanguageName (tmp->id));
+ colprintLineAppendColumnCString (line, getLanguageName (scb->owner));
+
+ const char *direction;
+ switch (((subparser *)tmp->data)->direction)
+ {
+ case SUBPARSER_BASE_RUNS_SUB:
+ direction = "base => sub {shared}";
+ break;
+ case SUBPARSER_SUB_RUNS_BASE:
+ direction = "base <= sub {dedicated}";
+ break;
+ case SUBPARSER_BI_DIRECTION:
+ direction = "base <> sub {bidirectional}";
+ break;
+ default:
+ direction = "UNKNOWN(INTERNAL BUG)";
+ break;
+ }
+ colprintLineAppendColumnCString (line, direction);
+ }
+ popLanguage ();
+}
+
+static int subparserColprintCompareLines (struct colprintLine *a , struct colprintLine *b)
+{
+ const char *a_name = colprintLineGetColumn (a, 0);
+ const char *b_name = colprintLineGetColumn (b, 0);
+
+ int r;
+ r = strcmp (a_name, b_name);
+ if (r != 0)
+ return r;
+
+ const char *a_baseparser = colprintLineGetColumn (a, 1);
+ const char *b_baseparser = colprintLineGetColumn (b, 1);
+
+ return strcmp(a_baseparser, b_baseparser);
+}
+
+extern void subparserColprintTablePrint (struct colprintTable *table,
+ bool withListHeader, bool machinable, FILE *fp)
+{
+ colprintTableSort (table, subparserColprintCompareLines);
+ colprintTablePrint (table, 0, withListHeader, machinable, fp);
}
Modified: ctags/main/dependency.h
26 lines changed, 13 insertions(+), 13 deletions(-)
===================================================================
@@ -12,34 +12,34 @@
#ifndef CTAGS_MAIN_DEPENDENCY_H
#define CTAGS_MAIN_DEPENDENCY_H
-#include "general.h"
+/*
+* INCLUDE FILES
+*/
+#include "general.h" /* must always come first */
#include "types.h"
+/*
+* DATA DECLARATIONS
+*/
typedef enum eDepType {
DEPTYPE_KIND_OWNER,
DEPTYPE_SUBPARSER,
COUNT_DEPTYPES,
} depType;
-typedef struct sParserDependency {
+struct sParserDependency {
depType type;
const char *upperParser;
void *data;
-} parserDependency;
-
-extern void linkDependencyAtInitializeParsing (depType dtype,
- parserDefinition *const masterParser,
- parserDefinition *const slaveParser);
+};
-typedef struct sSubparser subparser;
-struct sSubparser {
+struct sSlaveParser {
+ depType type;
langType id;
- subparser *next;
+ void *data;
+ slaveParser *next;
};
-extern void initializeSubparsers (const parserDefinition *parser);
-extern void finalizeSubparsers (parserDefinition *parser);
-
#endif /* CTAGS_MAIN_DEPENDENCY_H */
Modified: ctags/main/dependency_p.h
58 lines changed, 58 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,58 @@
+/*
+ *
+ * Copyright (c) 2016, Red Hat, Inc.
+ * Copyright (c) 2016, Masatake YAMATO
+ *
+ * Author: Masatake YAMATO <yamato at redhat.com>
+ *
+ * This source code is released for free distribution under the terms of the
+ * GNU General Public License version 2 or (at your option) any later version.
+ *
+ */
+#ifndef CTAGS_MAIN_DEPENDENCY_PRIVATE_H
+#define CTAGS_MAIN_DEPENDENCY_PRIVATE_H
+
+/*
+* INCLUDE FILES
+*/
+#include "general.h" /* must always come first */
+
+#include "dependency.h"
+#include "kind.h"
+#include "types.h"
+
+/*
+* MACROS
+*/
+#define foreachSlaveParser(VAR) \
+ VAR = NULL; \
+ while ((VAR = getNextSlaveParser (VAR)) != NULL)
+
+
+/*
+* DATA DECLARATIONS
+*/
+struct slaveControlBlock; /* Opaque data type for parse.c */
+
+/*
+* FUNCTION PROTOTYPES
+*/
+extern void linkDependencyAtInitializeParsing (depType dtype,
+ parserDefinition *const master,
+ struct slaveControlBlock *masterSCB,
+ struct kindControlBlock *masterKCB,
+ parserDefinition *const slave,
+ struct kindControlBlock *slaveKCB,
+ void *data);
+
+extern struct slaveControlBlock *allocSlaveControlBlock (parserDefinition *parser);
+extern void freeSlaveControlBlock (struct slaveControlBlock *cb);
+extern void initializeDependencies (parserDefinition *parser,
+ struct slaveControlBlock *cb);
+extern void finalizeDependencies (parserDefinition *parser,
+ struct slaveControlBlock *cb);
+
+extern slaveParser *getFirstSlaveParser(struct slaveControlBlock *controlBlock);
+extern slaveParser *getNextSlaveParser(slaveParser *last);
+
+#endif /* CTAGS_MAIN_DEPENDENCY_PRIVATE_H */
Modified: ctags/main/e_msoft.h
23 lines changed, 10 insertions(+), 13 deletions(-)
===================================================================
@@ -14,34 +14,30 @@
#define MSDOS_STYLE_PATH 1
#define HAVE_FCNTL_H 1
#define HAVE_IO_H 1
-#define HAVE_LIMITS_H 1
-#define HAVE_STDLIB_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TYPES_H 1
-#define HAVE_TIME_H 1
-#define HAVE_CLOCK 1
#define HAVE_CHSIZE 1
-#define HAVE_FGETPOS 1
+#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
-#define HAVE_TEMPNAM 1
+#define findfirst_t intptr_t
+#define HAVE_MKSTEMP 1
#define HAVE_FNMATCH 1
#define HAVE_FNMATCH_H 1
#define HAVE_PUTENV 1
-#define tempnam(dir,pfx) _tempnam(dir,pfx)
#define TMPDIR "\\"
+int mkstemp (char *template_name);
+
#ifdef _MSC_VER
-# define HAVE__FINDFIRST 1
-# define HAVE_DIRECT_H 1
# if _MSC_VER < 1900
# define snprintf _snprintf
# endif
-# define findfirst_t intptr_t
#if (_MSC_VER >= 1800) // Visual Studio 2013 or newer
#define HAVE_STDBOOL_H 1
@@ -58,14 +54,15 @@ typedef enum { false, true } bool;
# include <_mingw.h>
# define HAVE_STDBOOL_H 1
-# define HAVE_DIR_H 1
# define HAVE_DIRENT_H 1
-# define HAVE__FINDFIRST 1
-# define findfirst_t long
# define ffblk _finddata_t
# define FA_DIREC _A_SUBDIR
# define ff_name name
+# if defined(__USE_MINGW_ANSI_STDIO) && defined(__MINGW64_VERSION_MAJOR)
+# define HAVE_ASPRINTF 1
+# endif
+
#endif
#endif
Modified: ctags/main/entry.c
1190 lines changed, 880 insertions(+), 310 deletions(-)
===================================================================
@@ -36,20 +36,30 @@
# include <io.h>
#endif
+#include <stdint.h>
+#include <limits.h> /* to define INT_MAX */
+
#include "debug.h"
-#include "entry.h"
+#include "entry_p.h"
#include "field.h"
-#include "fmt.h"
+#include "fmt_p.h"
#include "kind.h"
-#include "main.h"
-#include "options.h"
-#include "output.h"
-#include "ptag.h"
+#include "nestlevel.h"
+#include "options_p.h"
+#include "ptag_p.h"
+#include "rbtree.h"
#include "read.h"
+#include "read_p.h"
#include "routines.h"
-#include "sort.h"
+#include "routines_p.h"
+#include "parse_p.h"
+#include "ptrarray.h"
+#include "sort_p.h"
#include "strlist.h"
-#include "xtag.h"
+#include "subparser_p.h"
+#include "trashbox.h"
+#include "writer_p.h"
+#include "xtag_p.h"
/*
* MACROS
@@ -82,43 +92,38 @@ typedef struct eTagFile {
struct sMax { size_t line, tag; } max;
vString *vLine;
- unsigned int cork;
- struct sCorkQueue {
- struct sTagEntryInfo* queue;
- unsigned int length;
- unsigned int count;
- } corkQueue;
+ int cork;
+ unsigned int corkFlags;
+ ptrArray *corkQueue;
bool patternCacheValid;
} tagFile;
+typedef struct sTagEntryInfoX {
+ tagEntryInfo slot;
+ int corkIndex;
+ struct rb_root symtab;
+ struct rb_node symnode;
+} tagEntryInfoX;
+
/*
* DATA DEFINITIONS
*/
-tagFile TagFile = {
+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 = {
- .queue = NULL,
- .length = 0,
- .count = 0
- },
+ .corkQueue = NULL,
.patternCacheValid = false,
};
static bool TagsToStdout = false;
-#ifdef CTAGS_LIB
-static tagEntryFunction TagEntryFunction = NULL;
-static void *TagEntryUserData = NULL;
-#endif
-
/*
* FUNCTION PROTOTYPES
*/
@@ -152,10 +157,8 @@ extern const char *tagFileName (void)
extern void abort_if_ferror(MIO *const mio)
{
-#ifndef CTAGS_LIB
- if (mio_error (mio))
+ if (mio != NULL && mio_error (mio))
error (FATAL | PERROR, "cannot write tag file");
-#endif
}
static void rememberMaxLengths (const size_t nameLength, const size_t lineLength)
@@ -169,52 +172,38 @@ static void rememberMaxLengths (const size_t nameLength, const size_t lineLength
static void addCommonPseudoTags (void)
{
- int i;
-
- for (i = 0; i < PTAG_COUNT; i++)
+ for (int i = 0; i < PTAG_COUNT; i++)
{
if (isPtagCommonInParsers (i))
- makePtagIfEnabled (i, NULL);
+ makePtagIfEnabled (i, LANG_IGNORE, &Option);
}
}
extern void makeFileTag (const char *const fileName)
{
- xtagType xtag = XTAG_UNKNOWN;
-
- if (isXtagEnabled(XTAG_FILE_NAMES))
- xtag = XTAG_FILE_NAMES;
-
- if (xtag != XTAG_UNKNOWN)
- {
- tagEntryInfo tag;
- kindDefinition *kind;
-
- kind = getInputLanguageFileKind();
- Assert (kind);
- kind->enabled = isXtagEnabled(XTAG_FILE_NAMES);
-
- /* TODO: you can return here if enabled == false. */
+ tagEntryInfo tag;
- initTagEntry (&tag, baseFilename (fileName), KIND_FILE_INDEX);
+ if (!isXtagEnabled(XTAG_FILE_NAMES))
+ return;
- tag.isFileEntry = true;
- tag.lineNumberEntry = true;
- markTagExtraBit (&tag, xtag);
+ initTagEntry (&tag, baseFilename (fileName), KIND_FILE_INDEX);
- tag.lineNumber = 1;
- if (isFieldEnabled (FIELD_END))
- {
- /* isFieldEnabled is called again in the rendering
- stage. However, it is called here for avoiding
- unnecessary read line loop. */
- while (readLineFromInputFile () != NULL)
- ; /* Do nothing */
- tag.extensionFields.endLine = getInputLineNumber ();
- }
+ tag.isFileEntry = true;
+ tag.lineNumberEntry = true;
+ markTagExtraBit (&tag, XTAG_FILE_NAMES);
- makeTagEntry (&tag);
+ tag.lineNumber = 1;
+ if (isFieldEnabled (FIELD_END_LINE))
+ {
+ /* isFieldEnabled is called again in the rendering
+ stage. However, it is called here for avoiding
+ unnecessary read line loop. */
+ while (readLineFromInputFile () != NULL)
+ ; /* Do nothing */
+ tag.extensionFields.endLine = getInputLineNumber ();
}
+
+ makeTagEntry (&tag);
}
static void updateSortedFlag (
@@ -382,7 +371,7 @@ static bool isTagFile (const char *const filename)
ok = true;
else
ok = (bool) (isCtagsLine (line) || isEtagsLine (line));
- mio_free (mio);
+ mio_unref (mio);
}
return ok;
}
@@ -399,9 +388,13 @@ extern void openTagFile (void)
*/
if (TagsToStdout)
{
- /* Open a tempfile with read and write mode. Read mode is used when
- * write the result to stdout. */
- TagFile.mio = tempFile ("w+", &TagFile.name);
+ if (Option.interactive == INTERACTIVE_SANDBOX)
+ {
+ TagFile.mio = mio_new_memory (NULL, 0, eRealloc, eFreeNoNullCheck);
+ TagFile.name = NULL;
+ }
+ else
+ TagFile.mio = tempFile ("w+", &TagFile.name);
if (isXtagEnabled (XTAG_PSEUDO_TAGS))
addCommonPseudoTags ();
}
@@ -431,7 +424,7 @@ extern void openTagFile (void)
if (TagFile.mio != NULL)
{
TagFile.numTags.prev = updatePseudoTags (TagFile.mio);
- mio_free (TagFile.mio);
+ mio_unref (TagFile.mio);
TagFile.mio = mio_new_file (TagFile.name, "a+");
}
}
@@ -445,10 +438,14 @@ extern void openTagFile (void)
if (TagFile.mio == NULL)
error (FATAL | PERROR, "cannot open tag file");
}
- if (TagsToStdout)
- TagFile.directory = eStrdup (CurrentDirectory);
- else
- TagFile.directory = absoluteDirname (TagFile.name);
+
+ if (TagFile.directory == NULL)
+ {
+ if (TagsToStdout)
+ TagFile.directory = eStrdup (CurrentDirectory);
+ else
+ TagFile.directory = absoluteDirname (TagFile.name);
+ }
}
#ifdef USE_REPLACEMENT_TRUNCATE
@@ -485,19 +482,20 @@ static void copyFile (const char *const from, const char *const to, const long s
else
{
copyBytes (fromMio, toMio, size);
- mio_free (toMio);
+ mio_unref (toMio);
}
- mio_free (fromMio);
+ mio_unref (fromMio);
}
}
/* Replacement for missing library function.
*/
static int replacementTruncate (const char *const name, const long size)
{
+#define WHOLE_FILE -1L
char *tempName = NULL;
MIO *mio = tempFile ("w", &tempName);
- mio_free (mio);
+ mio_unref (mio);
copyFile (name, tempName, size);
copyFile (tempName, name, WHOLE_FILE);
remove (tempName);
@@ -532,7 +530,7 @@ static void internalSortTagFile (void)
TagFile.numTags.added + TagFile.numTags.prev);
if (! TagsToStdout)
- mio_free (mio);
+ mio_unref (mio);
}
#endif
@@ -558,6 +556,12 @@ static void resizeTagFile (const long newSize)
{
int result;
+ if (!TagFile.name)
+ {
+ mio_try_resize (TagFile.mio, newSize);
+ return;
+ }
+
#ifdef USE_REPLACEMENT_TRUNCATE
result = replacementTruncate (TagFile.name, newSize);
#else
@@ -605,30 +609,35 @@ extern void closeTagFile (const bool resize)
if (Option.etags)
writeEtagsIncludes (TagFile.mio);
mio_flush (TagFile.mio);
+
abort_if_ferror (TagFile.mio);
desiredSize = mio_tell (TagFile.mio);
mio_seek (TagFile.mio, 0L, SEEK_END);
size = mio_tell (TagFile.mio);
if (! TagsToStdout)
/* The tag file should be closed before resizing. */
- if (mio_free (TagFile.mio) != 0)
+ if (mio_unref (TagFile.mio) != 0)
error (FATAL | PERROR, "cannot close tag file");
if (resize && desiredSize < size)
{
DebugStatement (
debugPrintf (DEBUG_STATUS, "shrinking %s from %ld to %ld bytes\n",
- TagFile.name, size, desiredSize); )
+ TagFile.name? TagFile.name: "<mio>", size, desiredSize); )
resizeTagFile (desiredSize);
}
sortTagFile ();
if (TagsToStdout)
{
- if (mio_free (TagFile.mio) != 0)
+ if (mio_unref (TagFile.mio) != 0)
error (FATAL | PERROR, "cannot close tag file");
- remove (tagFileName ()); /* remove temporary file */
+ if (TagFile.name)
+ remove (TagFile.name); /* remove temporary file */
}
- eFree (TagFile.name);
+
+ TagFile.mio = NULL;
+ if (TagFile.name)
+ eFree (TagFile.name);
TagFile.name = NULL;
}
@@ -641,10 +650,13 @@ extern void closeTagFile (const bool resize)
* are doubled and a leading '^' or trailing '$' is also quoted. End of line
* characters (line feed or carriage return) are dropped.
*/
-static size_t appendInputLine (int putc_func (char , void *), const char *const line, void * data, bool *omitted)
+static size_t appendInputLine (int putc_func (char , void *), const char *const line,
+ unsigned int patternLengthLimit,
+ void * data, bool *omitted)
{
size_t length = 0;
const char *p;
+ int extraLength = 0;
/* Write everything up to, but not including, a line end character.
*/
@@ -657,7 +669,11 @@ static size_t appendInputLine (int putc_func (char , void *), const char *const
if (c == CRETURN || c == NEWLINE)
break;
- if (Option.patternLengthLimit != 0 && length >= Option.patternLengthLimit)
+ if (patternLengthLimit != 0 && length >= patternLengthLimit &&
+ /* Do not cut inside a multi-byte UTF-8 character, but safe-guard it not to
+ * allow more than one extra valid UTF-8 character in case it's not actually
+ * UTF-8. To do that, limit to an extra 3 UTF-8 sub-bytes (0b10xxxxxx). */
+ ((((unsigned char) c) & 0xc0) != 0x80 || ++extraLength > 3))
{
*omitted = true;
break;
@@ -687,11 +703,12 @@ static int vstring_putc (char c, void *data)
static int vstring_puts (const char* s, void *data)
{
vString *str = data;
- int len = vStringLength (str);
+ size_t len = vStringLength (str);
vStringCatS (str, s);
- return vStringLength (str) - len;
+ return (int) (vStringLength (str) - len);
}
+#ifdef DEBUG
static bool isPosSet(MIOPos pos)
{
char * p = (char *)&pos;
@@ -702,26 +719,23 @@ static bool isPosSet(MIOPos pos)
r |= p[i];
return r;
}
+#endif
-extern char *readLineFromBypassAnyway (vString *const vLine, const tagEntryInfo *const tag,
+extern char *readLineFromBypassForTag (vString *const vLine, const tagEntryInfo *const tag,
long *const pSeekValue)
{
- char * line;
-
- if (isPosSet (tag->filePosition) || (tag->pattern == NULL))
- line = readLineFromBypass (vLine, tag->filePosition, pSeekValue);
- else
- line = readLineFromBypassSlow (vLine, tag->lineNumber, tag->pattern, pSeekValue);
-
- return line;
+ Assert (isPosSet (tag->filePosition) || (tag->pattern == NULL));
+ return readLineFromBypass (vLine, tag->filePosition, pSeekValue);
}
/* Truncates the text line containing the tag at the character following the
* tag, providing a character which designates the end of the tag.
+ * Returns the length of the truncated line (or 0 if it doesn't truncate).
*/
-extern void truncateTagLine (
+extern size_t truncateTagLineAfterTag (
char *const line, const char *const token, const bool discardNewline)
{
+ size_t len = 0;
char *p = strstr (line, token);
if (p != NULL)
@@ -730,7 +744,10 @@ extern void truncateTagLine (
if (*p != '\0' && ! (*p == '\n' && discardNewline))
++p; /* skip past character terminating character */
*p = '\0';
+ len = p - line;
}
+
+ return len;
}
static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_scope)
@@ -739,6 +756,7 @@ static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_
int kindIndex = KIND_GHOST_INDEX;
langType lang;
const tagEntryInfo *scope = inner_scope;
+ const tagEntryInfo *root_scope = NULL;
stringList *queue = stringListNew ();
vString *v;
vString *n;
@@ -760,11 +778,16 @@ static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_
stringListAdd (queue, v);
kindIndex = scope->kindIndex;
lang = scope->langType;
+ root_scope = scope;
}
scope = getEntryInCorkQueue (scope->extensionFields.scopeIndex);
}
n = vStringNew ();
+ sep = root_scope? scopeSeparatorFor (root_scope->langType, root_scope->kindIndex, KIND_GHOST_INDEX): NULL;
+ if (sep)
+ vStringCatS(n, sep);
+
while ((c = stringListCount (queue)) > 0)
{
v = stringListLast (queue);
@@ -785,16 +808,13 @@ extern void getTagScopeInformation (tagEntryInfo *const tag,
if (name)
*name = NULL;
+ const tagEntryInfo * scope = getEntryInCorkQueue (tag->extensionFields.scopeIndex);
if (tag->extensionFields.scopeKindIndex == KIND_GHOST_INDEX
&& tag->extensionFields.scopeName == NULL
- && tag->extensionFields.scopeIndex != CORK_NIL
- && TagFile.corkQueue.count > 0)
+ && scope
+ && ptrArrayCount (TagFile.corkQueue) > 0)
{
- const tagEntryInfo * scope = NULL;
- char *full_qualified_scope_name = NULL;
-
- scope = getEntryInCorkQueue (tag->extensionFields.scopeIndex);
- full_qualified_scope_name = getFullQualifiedScopeNameFromCorkQueue(scope);
+ char *full_qualified_scope_name = getFullQualifiedScopeNameFromCorkQueue(scope);
Assert (full_qualified_scope_name);
/* Make the information reusable to generate full qualified entry, and xformat output*/
@@ -821,9 +841,9 @@ extern void getTagScopeInformation (tagEntryInfo *const tag,
}
-extern int makePatternStringCommon (const tagEntryInfo *const tag,
- int putc_func (char , void *),
- int puts_func (const char* , void *),
+static int makePatternStringCommon (const tagEntryInfo *const tag,
+ int (* putc_func) (char , void *),
+ int (* puts_func) (const char* , void *),
void *output)
{
int length = 0;
@@ -845,20 +865,33 @@ extern int makePatternStringCommon (const tagEntryInfo *const tag,
&& (memcmp (&tag->filePosition, &cached_location, sizeof(MIOPos)) == 0))
return puts_func (vStringValue (cached_pattern), output);
- line = readLineFromBypass (TagFile.vLine, tag->filePosition, NULL);
+ line = readLineFromBypassForTag (TagFile.vLine, tag, NULL);
if (line == NULL)
- error (FATAL, "could not read tag line from %s at line %lu", getInputFileName (),tag->lineNumber);
+ {
+ /* This can be occurs if the size of input file is zero, and
+ an empty regex pattern (//) matches to the input. */
+ line = "";
+ line_len = 0;
+ }
+ else
+ line_len = vStringLength (TagFile.vLine);
+
if (tag->truncateLineAfterTag)
- truncateTagLine (line, tag->name, false);
+ {
+ size_t truncted_len;
+
+ truncted_len = truncateTagLineAfterTag (line, tag->name, false);
+ if (truncted_len > 0)
+ line_len = truncted_len;
+ }
- line_len = strlen (line);
searchChar = Option.backward ? '?' : '/';
- terminator = (bool) (line [line_len - 1] == '\n') ? "$": "";
+ terminator = (line_len > 0 && (line [line_len - 1] == '\n')) ? "$": "";
if (!tag->truncateLineAfterTag)
{
making_cache = true;
- cached_pattern = vStringNewOrClear (cached_pattern);
+ cached_pattern = vStringNewOrClearWithAutoRelease (cached_pattern);
puts_o_func = puts_func;
o_output = output;
@@ -870,7 +903,8 @@ extern int makePatternStringCommon (const tagEntryInfo *const tag,
length += putc_func(searchChar, output);
if ((tag->boundaryInfo & BOUNDARY_START) == 0)
length += putc_func('^', output);
- length += appendInputLine (putc_func, line, output, &omitted);
+ length += appendInputLine (putc_func, line, Option.patternLengthLimit,
+ output, &omitted);
length += puts_func (omitted? "": terminator, output);
length += putc_func (searchChar, output);
@@ -891,30 +925,97 @@ extern char* makePatternString (const tagEntryInfo *const tag)
return vStringDeleteUnwrap (pattern);
}
-extern void attachParserField (tagEntryInfo *const tag, fieldType ftype, const char * value)
+static tagField * tagFieldNew(fieldType ftype, const char *value, bool valueOwner)
{
- Assert (tag->usedParserFields < PRE_ALLOCATED_PARSER_FIELDS);
+ tagField *f = xMalloc (1, tagField);
- tag->parserFields [tag->usedParserFields].ftype = ftype;
- tag->parserFields [tag->usedParserFields].value = value;
- tag->usedParserFields++;
+ f->ftype = ftype;
+ f->value = value;
+ f->valueOwner = valueOwner;
+ return f;
}
-extern void attachParserFieldToCorkEntry (int index,
- fieldType type,
- const char *value)
+static void tagFieldDelete (tagField * f)
{
- tagEntryInfo * tag;
- const char * v;
+ if (f->valueOwner)
+ eFree((void *)f->value);
+ eFree (f);
+}
- if (index == CORK_NIL)
- return;
+static void attachParserFieldGeneric (tagEntryInfo *const tag, fieldType ftype, const char * value,
+ bool valueOwner)
+{
+ if (tag->usedParserFields < PRE_ALLOCATED_PARSER_FIELDS)
+ {
+ tag->parserFields [tag->usedParserFields].ftype = ftype;
+ tag->parserFields [tag->usedParserFields].value = value;
+ tag->parserFields [tag->usedParserFields].valueOwner = valueOwner;
+ tag->usedParserFields++;
+ }
+ else if (tag->parserFieldsDynamic == NULL)
+ {
+ tag->parserFieldsDynamic = ptrArrayNew((ptrArrayDeleteFunc)tagFieldDelete);
+ PARSER_TRASH_BOX(tag->parserFieldsDynamic, ptrArrayDelete);
+ attachParserFieldGeneric (tag, ftype, value, valueOwner);
+ }
+ else
+ {
+ tagField *f = tagFieldNew (ftype, value, valueOwner);
+ ptrArrayAdd(tag->parserFieldsDynamic, f);
+ tag->usedParserFields++;
+ }
+}
- tag = getEntryInCorkQueue(index);
+extern void attachParserField (tagEntryInfo *const tag, bool inCorkQueue, fieldType ftype, const char * value)
+{
Assert (tag != NULL);
- v = eStrdup (value);
- attachParserField (tag, type, v);
+ if (inCorkQueue)
+ {
+ const char * v;
+ v = eStrdup (value);
+
+ bool dynfields_allocated = tag->parserFieldsDynamic? true: false;
+ attachParserFieldGeneric (tag, ftype, v, true);
+ if (!dynfields_allocated && tag->parserFieldsDynamic)
+ PARSER_TRASH_BOX_TAKE_BACK(tag->parserFieldsDynamic);
+ }
+ else
+ attachParserFieldGeneric (tag, ftype, value, false);
+}
+
+extern void attachParserFieldToCorkEntry (int index,
+ fieldType ftype,
+ const char *value)
+{
+ tagEntryInfo * tag = getEntryInCorkQueue (index);
+ if (tag)
+ attachParserField (tag, true, ftype, value);
+}
+
+extern const tagField* getParserFieldForIndex (const tagEntryInfo * tag, int index)
+{
+ if (index < 0
+ || tag->usedParserFields <= ((unsigned int)index) )
+ return NULL;
+ else if (index < PRE_ALLOCATED_PARSER_FIELDS)
+ return tag->parserFields + index;
+ else
+ {
+ unsigned int n = index - PRE_ALLOCATED_PARSER_FIELDS;
+ return ptrArrayItem(tag->parserFieldsDynamic, n);
+ }
+}
+
+extern const char* getParserFieldValueForType (tagEntryInfo *const tag, fieldType ftype)
+{
+ for (int i = 0; i < tag->usedParserFields; i++)
+ {
+ const tagField *f = getParserFieldForIndex (tag, i);
+ if (f && f->ftype == ftype)
+ return f->value;
+ }
+ return NULL;
}
static void copyParserFields (const tagEntryInfo *const tag, tagEntryInfo* slot)
@@ -924,24 +1025,42 @@ static void copyParserFields (const tagEntryInfo *const tag, tagEntryInfo* slot)
for (i = 0; i < tag->usedParserFields; i++)
{
- value = tag->parserFields [i].value;
+ const tagField *f = getParserFieldForIndex (tag, i);
+ Assert(f);
+
+ value = f->value;
if (value)
value = eStrdup (value);
- attachParserField (slot,
- tag->parserFields [i].ftype,
- value);
+ attachParserFieldGeneric (slot,
+ f->ftype,
+ value,
+ true);
}
+
}
-static void recordTagEntryInQueue (const tagEntryInfo *const tag, tagEntryInfo* slot)
+static tagEntryInfo *newNilTagEntry (unsigned int corkFlags)
{
+ tagEntryInfoX *x = xCalloc (1, tagEntryInfoX);
+ x->corkIndex = CORK_NIL;
+ x->symtab = RB_ROOT;
+ x->slot.kindIndex = KIND_FILE_INDEX;
+ return &(x->slot);
+}
+
+static tagEntryInfoX *copyTagEntry (const tagEntryInfo *const tag,
+ unsigned int corkFlags)
+{
+ tagEntryInfoX *x = xMalloc (1, tagEntryInfoX);
+ x->symtab = RB_ROOT;
+ x->corkIndex = CORK_NIL;
+ tagEntryInfo *slot = (tagEntryInfo *)x;
+
*slot = *tag;
if (slot->pattern)
slot->pattern = eStrdup (slot->pattern);
- else if (!slot->lineNumberEntry)
- slot->pattern = makePatternString (slot);
slot->inputFileName = eStrdup (slot->inputFileName);
slot->name = eStrdup (slot->name);
@@ -961,39 +1080,63 @@ static void recordTagEntryInQueue (const tagEntryInfo *const tag, tagEntryInfo*
slot->extensionFields.typeRef[0] = eStrdup (slot->extensionFields.typeRef[0]);
if (slot->extensionFields.typeRef[1])
slot->extensionFields.typeRef[1] = eStrdup (slot->extensionFields.typeRef[1]);
-/* GEANY DIFF */
- if (slot->extensionFields.varType)
- slot->extensionFields.varType = eStrdup (slot->extensionFields.varType);
-/* GEANY DIFF END */
#ifdef HAVE_LIBXML
if (slot->extensionFields.xpath)
slot->extensionFields.xpath = eStrdup (slot->extensionFields.xpath);
#endif
+ if (slot->extraDynamic)
+ {
+ int n = countXtags () - XTAG_COUNT;
+ slot->extraDynamic = xCalloc ((n / 8) + 1, uint8_t);
+ memcpy (slot->extraDynamic, tag->extraDynamic, (n / 8) + 1);
+ }
+
if (slot->sourceFileName)
slot->sourceFileName = eStrdup (slot->sourceFileName);
+
slot->usedParserFields = 0;
+ slot->parserFieldsDynamic = NULL;
copyParserFields (tag, slot);
+ if (slot->parserFieldsDynamic)
+ PARSER_TRASH_BOX_TAKE_BACK(slot->parserFieldsDynamic);
+
+ return x;
}
static void clearParserFields (tagEntryInfo *const tag)
{
- unsigned int i;
+ unsigned int i, n;
const char* value;
- for (i = 0; i < tag->usedParserFields; i++)
+ if ( tag->usedParserFields < PRE_ALLOCATED_PARSER_FIELDS )
+ n = tag->usedParserFields;
+ else
+ n = PRE_ALLOCATED_PARSER_FIELDS;
+
+ for (i = 0; i < n; i++)
{
value = tag->parserFields[i].value;
- if (value)
+ if (value && tag->parserFields[i].valueOwner)
eFree ((char *)value);
tag->parserFields[i].value = NULL;
tag->parserFields[i].ftype = FIELD_UNKNOWN;
}
+ if (tag->parserFieldsDynamic)
+ {
+ ptrArrayDelete (tag->parserFieldsDynamic);
+ tag->parserFieldsDynamic = NULL;
+ }
}
-static void clearTagEntryInQueue (tagEntryInfo* slot)
+static void deleteTagEnry (void *data)
{
+ tagEntryInfo *slot = data;
+
+ if (slot->kindIndex == KIND_FILE_INDEX)
+ goto out;
+
if (slot->pattern)
eFree ((char *)slot->pattern);
eFree ((char *)slot->inputFileName);
@@ -1015,139 +1158,409 @@ static void clearTagEntryInQueue (tagEntryInfo* slot)
eFree ((char *)slot->extensionFields.typeRef[0]);
if (slot->extensionFields.typeRef[1])
eFree ((char *)slot->extensionFields.typeRef[1]);
-/* GEANY DIFF */
- if (slot->extensionFields.varType)
- eFree ((char *)slot->extensionFields.varType);
-/* GEANY DIFF END */
#ifdef HAVE_LIBXML
if (slot->extensionFields.xpath)
eFree ((char *)slot->extensionFields.xpath);
#endif
+ if (slot->extraDynamic)
+ eFree (slot->extraDynamic);
+
if (slot->sourceFileName)
eFree ((char *)slot->sourceFileName);
clearParserFields (slot);
+
+ out:
+ eFree (slot);
}
-static unsigned int queueTagEntry(const tagEntryInfo *const tag)
+static void corkSymtabPut (tagEntryInfoX *scope, const char* name, tagEntryInfoX *item)
{
- unsigned int i;
- void *tmp;
- tagEntryInfo * slot;
+ struct rb_root *root = &scope->symtab;
+
+ struct rb_node **new = &(root->rb_node), *parent = NULL;
- if (! (TagFile.corkQueue.count < TagFile.corkQueue.length))
+ while (*new)
{
- if (!TagFile.corkQueue.length)
- TagFile.corkQueue.length = 1;
+ tagEntryInfoX *this = container_of(*new, tagEntryInfoX, symnode);
+ int result = strcmp(item->slot.name, this->slot.name);
+
+ parent = *new;
- tmp = eRealloc (TagFile.corkQueue.queue,
- sizeof (*TagFile.corkQueue.queue) * TagFile.corkQueue.length * 2);
+ if (result < 0)
+ new = &((*new)->rb_left);
+ else if (result > 0)
+ new = &((*new)->rb_right);
+ else
+ {
+ unsigned long lthis = this->slot.lineNumber;
+ unsigned long litem = item->slot.lineNumber;
+
+ /* Comparing lineNumber */
+ if (litem < lthis)
+ new = &((*new)->rb_left);
+ else if (litem > lthis)
+ new = &((*new)->rb_right);
+ else
+ {
+ /* Comparing memory address */
+ if (item < this)
+ new = &((*new)->rb_left);
+ else if (item > this)
+ new = &((*new)->rb_right);
+ else
+ {
+ AssertNotReached(); /* registering the same object twice. */
+ return;
+ }
+ }
+ }
+ }
- TagFile.corkQueue.length *= 2;
- TagFile.corkQueue.queue = tmp;
+ verbose ("symtbl[:=] %s<-%s/%p (line: %lu)\n",
+ *new? container_of(*new, tagEntryInfoX, symnode)->slot.name: "*root*",
+ item->slot.name, &item->slot, item->slot.lineNumber);
+ /* Add new node and rebalance tree. */
+ rb_link_node(&item->symnode, parent, new);
+ rb_insert_color(&item->symnode, root);
+}
+
+extern bool foreachEntriesInScope (int corkIndex,
+ const char *name,
+ entryForeachFunc func,
+ void *data)
+{
+ tagEntryInfoX *x = ptrArrayItem (TagFile.corkQueue, corkIndex);
+
+ struct rb_root *root = &x->symtab;
+ tagEntryInfoX *rep = NULL;
+
+ /* More than one tag can have a same name.
+ * Visit them from the last.
+ *
+ * 1. find one of them as the representative,
+ * 2. find the last one of them from the representative with rb_next,
+ * 3. call FUNC iteratively from the last to the first.
+ */
+ if (name)
+ {
+ struct rb_node *node = root->rb_node;
+ while (node)
+ {
+ tagEntryInfoX *entry = container_of(node, tagEntryInfoX, symnode);
+ int result;
+
+ result = strcmp(name, entry->slot.name);
+
+ if (result < 0)
+ node = node->rb_left;
+ else if (result > 0)
+ node = node->rb_right;
+ else
+ {
+ rep = entry;
+ break;
+ }
+ }
+ if (rep == NULL)
+ return true;
+
+ verbose("symtbl[<>] %s->%p\n", name, &rep->slot);
+ }
+
+ struct rb_node *last;
+
+ if (name)
+ {
+ struct rb_node *tmp = &rep->symnode;
+ last = tmp;
+
+ while ((tmp = rb_next (tmp)))
+ {
+ tagEntryInfoX *entry = container_of(tmp, tagEntryInfoX, symnode);
+ if (strcmp(name, entry->slot.name) == 0)
+ {
+ verbose ("symtbl[ >] %s->%p\n", name, &container_of(tmp, tagEntryInfoX, symnode)->slot);
+ last = tmp;
+ }
+ else
+ break;
+ }
+ }
+ else
+ {
+ last = rb_last(root);
+ verbose ("last for %d<%p>: %p\n", corkIndex, root, last);
}
- i = TagFile.corkQueue.count;
- TagFile.corkQueue.count++;
+ if (!last)
+ {
+ verbose ("symtbl[>V] %s->%p\n", name? name: "(null)", NULL);
+ return true; /* Nothing here in this node. */
+ }
+ verbose ("symtbl[>|] %s->%p\n", name, &container_of(last, tagEntryInfoX, symnode)->slot);
- slot = TagFile.corkQueue.queue + i;
- recordTagEntryInQueue (tag, slot);
+ struct rb_node *cursor = last;
+ bool revisited_rep = false;
+ do
+ {
+ tagEntryInfoX *entry = container_of(cursor, tagEntryInfoX, symnode);
+ if (!revisited_rep || !name || strcmp(name, entry->slot.name))
+ {
+ verbose ("symtbl[< ] %s->%p\n", name, &entry->slot);
+ if (!func (entry->corkIndex, &entry->slot, data))
+ return false;
+ if (cursor == &rep->symnode)
+ revisited_rep = true;
+ }
+ else if (name)
+ break;
+ }
+ while ((cursor = rb_prev(cursor)));
- return i;
+ return true;
}
+static bool findName (int corkIndex, tagEntryInfo *entry, void *data)
+{
+ int *index = data;
-static void *writerData;
-static tagWriter *writer;
+ *index = corkIndex;
+ return false;
+}
-extern void setTagWriter (tagWriter *t)
+int anyEntryInScope (int corkIndex, const char *name)
{
- writer = t;
+ int index = CORK_NIL;
+
+ if (foreachEntriesInScope (corkIndex, name, findName, &index) == false)
+ return index;
+
+ return CORK_NIL;
}
-extern bool outpuFormatUsedStdoutByDefault (void)
+struct anyKindsEntryInScopeData {
+ int index;
+ const int *kinds;
+ int count;
+};
+
+static bool findNameOfKinds (int corkIndex, tagEntryInfo *entry, void *data)
{
- return writer->useStdoutByDefault;
+ struct anyKindsEntryInScopeData * kdata = data;
+
+ for (int i = 0; i < kdata->count; i++)
+ {
+ int k = kdata->kinds [i];
+ if (entry->kindIndex == k)
+ {
+ kdata->index = corkIndex;
+ return false;
+ }
+ }
+ return true;
}
-extern void setupWriter (void)
+int anyKindEntryInScope (int corkIndex,
+ const char *name, int kind)
{
- if (writer->preWriteEntry)
- writerData = writer->preWriteEntry (TagFile.mio);
- else
- writerData = NULL;
+ return anyKindsEntryInScope (corkIndex, name, &kind, 1);
}
-extern void teardownWriter (const char *filename)
+int anyKindsEntryInScope (int corkIndex,
+ const char *name,
+ const int *kinds, int count)
{
- if (writer->postWriteEntry)
- writer->postWriteEntry (TagFile.mio, filename, writerData);
+ struct anyKindsEntryInScopeData data = {
+ .index = CORK_NIL,
+ .kinds = kinds,
+ .count = count,
+ };
+
+ if (foreachEntriesInScope (corkIndex, name, findNameOfKinds, &data) == false)
+ return data.index;
+
+ return CORK_NIL;
}
-static void buildFqTagCache (const tagEntryInfo *const tag)
+int anyKindsEntryInScopeRecursive (int corkIndex,
+ const char *name,
+ const int *kinds, int count)
{
- renderFieldEscaped (FIELD_SCOPE_KIND_LONG, tag, NO_PARSER_FIELD);
- renderFieldEscaped (FIELD_SCOPE, tag, NO_PARSER_FIELD);
+ struct anyKindsEntryInScopeData data = {
+ .index = CORK_NIL,
+ .kinds = kinds,
+ .count = count,
+ };
+
+ tagEntryInfo *e;
+ do
+ {
+ if (foreachEntriesInScope (corkIndex, name, findNameOfKinds, &data) == false)
+ return data.index;
+
+ if (corkIndex == CORK_NIL)
+ break;
+
+ e = getEntryInCorkQueue (corkIndex);
+ if (!e)
+ break;
+ corkIndex = e->extensionFields.scopeIndex;
+ }
+ while (1);
+
+ return CORK_NIL;
}
-#ifdef CTAGS_LIB
-static void initCtagsTag(ctagsTag *tag, const tagEntryInfo *info)
+extern void registerEntry (int corkIndex)
{
- tag->name = info->name;
- tag->signature = info->extensionFields.signature;
- tag->scopeName = info->extensionFields.scopeName;
- tag->inheritance = info->extensionFields.inheritance;
- tag->varType = info->extensionFields.varType;
- tag->access = info->extensionFields.access;
- tag->implementation = info->extensionFields.implementation;
- tag->kindLetter = getLanguageKind(info->langType, info->kindIndex)->letter;
- tag->isFileScope = info->isFileScope;
- tag->lineNumber = info->lineNumber;
- tag->lang = info->langType;
+ Assert (TagFile.corkFlags & CORK_SYMTAB);
+ Assert (corkIndex != CORK_NIL);
+
+ tagEntryInfoX *e = ptrArrayItem (TagFile.corkQueue, corkIndex);
+ {
+ tagEntryInfoX *scope = ptrArrayItem (TagFile.corkQueue, e->slot.extensionFields.scopeIndex);
+ corkSymtabPut (scope, e->slot.name, e);
+ }
+}
+
+static int queueTagEntry(const tagEntryInfo *const tag)
+{
+ static bool warned;
+
+ int corkIndex;
+ tagEntryInfoX * entry = copyTagEntry (tag,
+ TagFile.corkFlags);
+
+ if (ptrArrayCount (TagFile.corkQueue) == (size_t)INT_MAX)
+ {
+ if (!warned)
+ {
+ warned = true;
+ error (WARNING,
+ "The tag entry queue overflows; drop the tag entry at %lu in %s",
+ tag->lineNumber,
+ tag->inputFileName);
+ }
+ return CORK_NIL;
+ }
+ warned = false;
+
+ corkIndex = (int)ptrArrayAdd (TagFile.corkQueue, entry);
+ entry->corkIndex = corkIndex;
+
+ return corkIndex;
+}
+
+extern void setupWriter (void *writerClientData)
+{
+ writerSetup (TagFile.mio, writerClientData);
+}
+
+extern bool teardownWriter (const char *filename)
+{
+ return writerTeardown (TagFile.mio, filename);
+}
+
+static bool isTagWritable(const tagEntryInfo *const tag)
+{
+ if (tag->placeholder)
+ return false;
+
+ if (! isLanguageKindEnabled(tag->langType, tag->kindIndex))
+ return false;
+
+ if (tag->extensionFields.roleBits)
+ {
+ size_t available_roles;
+
+ if (!isXtagEnabled (XTAG_REFERENCE_TAGS))
+ return false;
+
+ available_roles = countLanguageRoles(tag->langType,
+ tag->kindIndex);
+ if (tag->extensionFields.roleBits >=
+ (makeRoleBit(available_roles)))
+ return false;
+
+ /* TODO: optimization
+ A Bitmasks representing all enabled roles can be calculated at the
+ end of initializing the parser. Calculating each time when checking
+ a tag entry is not needed. */
+ for (unsigned int roleIndex = 0; roleIndex < available_roles; roleIndex++)
+ {
+ if (isRoleAssigned(tag, roleIndex))
+ {
+ if (isLanguageRoleEnabled (tag->langType, tag->kindIndex,
+ roleIndex))
+ return true;
+ }
+
+ }
+ return false;
+ }
+ else if (isLanguageKindRefOnly(tag->langType, tag->kindIndex))
+ {
+ error (WARNING, "definition tag for refonly kind(%s) is made: %s",
+ getLanguageKind(tag->langType, tag->kindIndex)->name,
+ tag->name);
+ /* This one is not so critical. */
+ }
+
+ if (!isXtagEnabled(XTAG_ANONYMOUS)
+ && isTagExtraBitMarked(tag, XTAG_ANONYMOUS))
+ return false;
+
+ return true;
+}
+
+static void buildFqTagCache (tagEntryInfo *const tag)
+{
+ getTagScopeInformation (tag, NULL, NULL);
}
-#endif
static void writeTagEntry (const tagEntryInfo *const tag)
{
int length = 0;
- if (tag->placeholder)
- return;
-#ifndef CTAGS_LIB
- if (! tag->kind->enabled)
- return;
-#endif
- if (tag->extensionFields.roleIndex != ROLE_INDEX_DEFINITION
- && ! isXtagEnabled (XTAG_REFERENCE_TAGS))
- return;
+ Assert (tag->kindIndex != KIND_GHOST_INDEX);
DebugStatement ( debugEntry (tag); )
- Assert (writer);
+
+#ifdef WIN32
+ if (getFilenameSeparator(Option.useSlashAsFilenameSeparator) == FILENAME_SEP_USE_SLASH)
+ {
+ Assert (((const tagEntryInfo *)tag)->inputFileName);
+ char *c = (char *)(((tagEntryInfo *const)tag)->inputFileName);
+ while (*c)
+ {
+ if (*c == PATH_SEPARATOR)
+ *c = OUTPUT_PATH_SEPARATOR;
+ c++;
+ }
+ }
+#endif
if (includeExtensionFlags ()
&& isXtagEnabled (XTAG_QUALIFIED_TAGS)
- && doesInputLanguageRequestAutomaticFQTag ())
- buildFqTagCache (tag);
+ && doesInputLanguageRequestAutomaticFQTag ()
+ && !isTagExtraBitMarked (tag, XTAG_QUALIFIED_TAGS)
+ && !tag->skipAutoFQEmission)
+ {
+ /* const is discarded to update the cache field of TAG. */
+ buildFqTagCache ( (tagEntryInfo *const)tag);
+ }
-#ifdef CTAGS_LIB
- getTagScopeInformation((tagEntryInfo *)tag, NULL, NULL);
+ length = writerWriteTag (TagFile.mio, tag);
- if (TagEntryFunction != NULL)
+ if (length > 0)
{
- ctagsTag t;
-
- initCtagsTag(&t, tag);
- length = TagEntryFunction(&t, TagEntryUserData);
+ ++TagFile.numTags.added;
+ rememberMaxLengths (strlen (tag->name), (size_t) length);
}
-#else
- length = writer->writeEntry (TagFile.mio, tag, writerData);
-#endif
-
- ++TagFile.numTags.added;
- rememberMaxLengths (strlen (tag->name), (size_t) length);
- DebugStatement ( mio_flush (TagFile.mio); )
+ DebugStatement ( if (TagFile.mio) mio_flush (TagFile.mio); )
abort_if_ferror (TagFile.mio);
}
@@ -1159,11 +1572,11 @@ extern bool writePseudoTag (const ptagDesc *desc,
{
int length;
- if (writer->writePtagEntry == NULL)
+ length = writerWritePtag (TagFile.mio, desc, fileName,
+ pattern, parserName);
+ if (length < 0)
return false;
- length = writer->writePtagEntry (TagFile.mio, desc, fileName,
- pattern, parserName, writerData);
abort_if_ferror (TagFile.mio);
++TagFile.numTags.added;
@@ -1172,15 +1585,15 @@ extern bool writePseudoTag (const ptagDesc *desc,
return true;
}
-extern void corkTagFile(void)
+extern void corkTagFile(unsigned int corkFlags)
{
TagFile.cork++;
if (TagFile.cork == 1)
{
- TagFile.corkQueue.length = 1;
- TagFile.corkQueue.count = 1;
- TagFile.corkQueue.queue = eMalloc (sizeof (*TagFile.corkQueue.queue));
- memset (TagFile.corkQueue.queue, 0, sizeof (*TagFile.corkQueue.queue));
+ TagFile.corkFlags = corkFlags;
+ TagFile.corkQueue = ptrArrayNew (deleteTagEnry);
+ tagEntryInfo *nil = newNilTagEntry (corkFlags);
+ ptrArrayAdd (TagFile.corkQueue, nil);
}
}
@@ -1193,32 +1606,36 @@ extern void uncorkTagFile(void)
if (TagFile.cork > 0)
return ;
- for (i = 1; i < TagFile.corkQueue.count; i++)
+ for (i = 1; i < ptrArrayCount (TagFile.corkQueue); i++)
{
- tagEntryInfo *tag = TagFile.corkQueue.queue + i;
+ tagEntryInfo *tag = ptrArrayItem (TagFile.corkQueue, i);
+
+ if (!isTagWritable(tag))
+ continue;
+
writeTagEntry (tag);
+
if (doesInputLanguageRequestAutomaticFQTag ()
&& isXtagEnabled (XTAG_QUALIFIED_TAGS)
- && (tag->extensionFields.scopeKindIndex != KIND_GHOST_INDEX)
- && tag->extensionFields.scopeName
- && tag->extensionFields.scopeIndex)
+ && !isTagExtraBitMarked (tag, XTAG_QUALIFIED_TAGS)
+ && !tag->skipAutoFQEmission
+ && ((tag->extensionFields.scopeKindIndex != KIND_GHOST_INDEX
+ && tag->extensionFields.scopeName != NULL
+ && tag->extensionFields.scopeIndex != CORK_NIL)
+ || (tag->extensionFields.scopeKindIndex == KIND_GHOST_INDEX
+ && tag->extensionFields.scopeName == NULL
+ && tag->extensionFields.scopeIndex == CORK_NIL)))
makeQualifiedTagEntry (tag);
}
- for (i = 1; i < TagFile.corkQueue.count; i++)
- clearTagEntryInQueue (TagFile.corkQueue.queue + i);
- memset (TagFile.corkQueue.queue, 0,
- sizeof (*TagFile.corkQueue.queue) * TagFile.corkQueue.count);
- TagFile.corkQueue.count = 0;
- eFree (TagFile.corkQueue.queue);
- TagFile.corkQueue.queue = NULL;
- TagFile.corkQueue.length = 0;
+ ptrArrayDelete (TagFile.corkQueue);
+ TagFile.corkQueue = NULL;
}
-extern tagEntryInfo *getEntryInCorkQueue (unsigned int n)
+extern tagEntryInfo *getEntryInCorkQueue (int n)
{
- if ((CORK_NIL < n) && (n < TagFile.corkQueue.count))
- return TagFile.corkQueue.queue + n;
+ if ((CORK_NIL < n) && (((size_t)n) < ptrArrayCount (TagFile.corkQueue)))
+ return ptrArrayItem (TagFile.corkQueue, n);
else
return NULL;
}
@@ -1232,25 +1649,38 @@ extern tagEntryInfo *getEntryOfNestingLevel (const NestingLevel *nl)
extern size_t countEntryInCorkQueue (void)
{
- return TagFile.corkQueue.count;
+ return ptrArrayCount (TagFile.corkQueue);
+}
+
+extern int makePlaceholder (const char *const name)
+{
+ tagEntryInfo e;
+
+ initTagEntry (&e, name, KIND_GHOST_INDEX);
+ e.placeholder = 1;
+
+ /*
+ * makePlaceholder may be called even before reading any bytes
+ * from the input stream. In such case, initTagEntry fills
+ * the lineNumber field of the placeholder tag with 0.
+ * This breaks an assertion in makeTagEntry. Following adjustment
+ * is for avoiding it.
+ */
+ if (e.lineNumber == 0)
+ e.lineNumber = 1;
+
+ return makeTagEntry (&e);
}
extern int makeTagEntry (const tagEntryInfo *const tag)
{
int r = CORK_NIL;
Assert (tag->name != NULL);
+ Assert(tag->lineNumber > 0);
-#ifndef CTAGS_LIB
- if (getInputLanguageFileKind() != tag->kind)
- {
- if (! isInputLanguageKindEnabled (tag->kind->letter) &&
- (tag->extensionFields.roleIndex == ROLE_INDEX_DEFINITION))
- return CORK_NIL;
- if ((tag->extensionFields.roleIndex != ROLE_INDEX_DEFINITION)
- && (! tag->kind->roles[tag->extensionFields.roleIndex].enabled))
- return CORK_NIL;
- }
-#endif
+ if (!TagFile.cork)
+ if (!isTagWritable (tag))
+ goto out;
if (tag->name [0] == '\0' && (!tag->placeholder))
{
@@ -1264,6 +1694,10 @@ extern int makeTagEntry (const tagEntryInfo *const tag)
r = queueTagEntry (tag);
else
writeTagEntry (tag);
+
+ if (r != CORK_NIL)
+ notifyMakeTagEntry (tag, r);
+
out:
return r;
}
@@ -1272,7 +1706,7 @@ extern int makeQualifiedTagEntry (const tagEntryInfo *const e)
{
int r = CORK_NIL;
tagEntryInfo x;
- char xk;
+ int xk;
const char *sep;
static vString *fqn;
@@ -1281,7 +1715,7 @@ extern int makeQualifiedTagEntry (const tagEntryInfo *const e)
x = *e;
markTagExtraBit (&x, XTAG_QUALIFIED_TAGS);
- fqn = vStringNewOrClear (fqn);
+ fqn = vStringNewOrClearWithAutoRelease (fqn);
if (e->extensionFields.scopeName)
{
@@ -1298,7 +1732,7 @@ extern int makeQualifiedTagEntry (const tagEntryInfo *const e)
if (sep == NULL)
{
/* No root separator. The name of the
- oritinal tag and that of full qualified tag
+ optional tag and that of full qualified tag
are the same; recording the full qualified tag
is meaningless. */
return r;
@@ -1310,53 +1744,35 @@ extern int makeQualifiedTagEntry (const tagEntryInfo *const e)
x.name = vStringValue (fqn);
/* makeExtraTagEntry of c.c doesn't clear scope
- releated fields. */
+ related fields. */
#if 0
x.extensionFields.scopeKind = NULL;
x.extensionFields.scopeName = NULL;
+ x.extensionFields.scopeIndex = CORK_NIL;
#endif
+
+ bool in_subparser
+ = isTagExtraBitMarked (&x,
+ XTAG_SUBPARSER);
+
+ if (in_subparser)
+ pushLanguage(x.langType);
+
r = makeTagEntry (&x);
+
+ if (in_subparser)
+ popLanguage();
}
return r;
}
-extern void initTagEntry (tagEntryInfo *const e, const char *const name,
- int kindIndex)
-{
- initTagEntryFull(e, name,
- getInputLineNumber (),
- getInputLanguage (),
- getInputFilePosition (),
- getInputFileTagPath (),
- kindIndex,
- ROLE_INDEX_DEFINITION,
- getSourceFileTagPath(),
- getSourceLanguage(),
- getSourceLineNumber() - getInputLineNumber ());
-}
-
-extern void initRefTagEntry (tagEntryInfo *const e, const char *const name,
- int kindIndex, int roleIndex)
-{
- initTagEntryFull(e, name,
- getInputLineNumber (),
- getInputLanguage (),
- getInputFilePosition (),
- getInputFileTagPath (),
- kindIndex,
- roleIndex,
- getSourceFileTagPath(),
- getSourceLanguage(),
- getSourceLineNumber() - getInputLineNumber ());
-}
-
-extern void initTagEntryFull (tagEntryInfo *const e, const char *const name,
+static void initTagEntryFull (tagEntryInfo *const e, const char *const name,
unsigned long lineNumber,
langType langType_,
MIOPos filePosition,
const char *inputFileName,
int kindIndex,
- int roleIndex,
+ roleBitsType roleBits,
const char *sourceFileName,
langType sourceLangType,
long sourceLineNumberDifference)
@@ -1380,12 +1796,17 @@ extern void initTagEntryFull (tagEntryInfo *const e, const char *const name,
Assert (kindIndex < 0 || kindIndex < (int)countLanguageKinds(langType_));
e->kindIndex = kindIndex;
- Assert (roleIndex >= ROLE_INDEX_DEFINITION);
- Assert (kind == NULL || roleIndex < kind->nRoles);
- e->extensionFields.roleIndex = roleIndex;
- if (roleIndex > ROLE_INDEX_DEFINITION)
+ Assert (roleBits == 0
+ || (roleBits < (makeRoleBit(countLanguageRoles(langType_, kindIndex)))));
+ e->extensionFields.roleBits = roleBits;
+ if (roleBits)
markTagExtraBit (e, XTAG_REFERENCE_TAGS);
+ if (doesParserRunAsGuest ())
+ markTagExtraBit (e, XTAG_GUEST);
+ if (doesSubparserRun ())
+ markTagExtraBit (e, XTAG_SUBPARSER);
+
e->sourceLangType = sourceLangType;
e->sourceFileName = sourceFileName;
e->sourceLineNumberDifference = sourceLineNumberDifference;
@@ -1394,30 +1815,163 @@ extern void initTagEntryFull (tagEntryInfo *const e, const char *const name,
for ( i = 0; i < PRE_ALLOCATED_PARSER_FIELDS; i++ )
e->parserFields[i].ftype = FIELD_UNKNOWN;
+
+ if (isParserMarkedNoEmission ())
+ e->placeholder = 1;
}
-extern void markTagExtraBit (tagEntryInfo *const tag, xtagType extra)
+extern void initTagEntry (tagEntryInfo *const e, const char *const name,
+ int kindIndex)
+{
+ initTagEntryFull(e, name,
+ getInputLineNumber (),
+ getInputLanguage (),
+ getInputFilePosition (),
+ getInputFileTagPath (),
+ kindIndex,
+ 0,
+ getSourceFileTagPath(),
+ getSourceLanguage(),
+ getSourceLineNumber() - getInputLineNumber ());
+}
+
+extern void initRefTagEntry (tagEntryInfo *const e, const char *const name,
+ int kindIndex, int roleIndex)
+{
+ initForeignRefTagEntry (e, name, getInputLanguage (), kindIndex, roleIndex);
+}
+
+extern void initForeignRefTagEntry (tagEntryInfo *const e, const char *const name,
+ langType langType,
+ int kindIndex, int roleIndex)
+{
+ initTagEntryFull(e, name,
+ getInputLineNumber (),
+ langType,
+ getInputFilePosition (),
+ getInputFileTagPath (),
+ kindIndex,
+ makeRoleBit(roleIndex),
+ getSourceFileTagPath(),
+ getSourceLanguage(),
+ getSourceLineNumber() - getInputLineNumber ());
+}
+
+static void markTagExtraBitFull (tagEntryInfo *const tag, xtagType extra, bool mark)
{
unsigned int index;
unsigned int offset;
+ uint8_t *slot;
- Assert (extra < XTAG_COUNT);
Assert (extra != XTAG_UNKNOWN);
- index = (extra / 8);
- offset = (extra % 8);
- tag->extra [ index ] |= (1 << offset);
+ if (extra < XTAG_COUNT)
+ {
+ index = (extra / 8);
+ offset = (extra % 8);
+ slot = tag->extra;
+ }
+ else if (tag->extraDynamic)
+ {
+ Assert (extra < countXtags ());
+
+ index = ((extra - XTAG_COUNT) / 8);
+ offset = ((extra - XTAG_COUNT) % 8);
+ slot = tag->extraDynamic;
+ }
+ else
+ {
+ Assert (extra < countXtags ());
+
+ int n = countXtags () - XTAG_COUNT;
+ tag->extraDynamic = xCalloc ((n / 8) + 1, uint8_t);
+ PARSER_TRASH_BOX(tag->extraDynamic, eFree);
+ markTagExtraBit (tag, extra);
+ return;
+ }
+
+ if (mark)
+ slot [ index ] |= (1 << offset);
+ else
+ slot [ index ] &= ~(1 << offset);
+}
+
+extern void markTagExtraBit (tagEntryInfo *const tag, xtagType extra)
+{
+ markTagExtraBitFull (tag, extra, true);
}
extern bool isTagExtraBitMarked (const tagEntryInfo *const tag, xtagType extra)
{
- unsigned int index = (extra / 8);
- unsigned int offset = (extra % 8);
+ unsigned int index;
+ unsigned int offset;
+ const uint8_t *slot;
- Assert (extra < XTAG_COUNT);
Assert (extra != XTAG_UNKNOWN);
- return !! ((tag->extra [ index ]) & (1 << offset));
+ if (extra < XTAG_COUNT)
+ {
+ index = (extra / 8);
+ offset = (extra % 8);
+ slot = tag->extra;
+
+ }
+ else if (!tag->extraDynamic)
+ return false;
+ else
+ {
+ Assert (extra < countXtags ());
+ index = ((extra - XTAG_COUNT) / 8);
+ offset = ((extra - XTAG_COUNT) % 8);
+ slot = tag->extraDynamic;
+
+ }
+ return !! ((slot [ index ]) & (1 << offset));
+}
+
+extern bool isTagExtra (const tagEntryInfo *const tag)
+{
+ for (unsigned int i = 0; i < XTAG_COUNT; i++)
+ if (isTagExtraBitMarked (tag, i))
+ return true;
+ return false;
+}
+
+static void assignRoleFull(tagEntryInfo *const e, int roleIndex, bool assign)
+{
+ if (roleIndex == ROLE_DEFINITION_INDEX)
+ {
+ if (assign)
+ {
+ e->extensionFields.roleBits = 0;
+ markTagExtraBitFull (e, XTAG_REFERENCE_TAGS, false);
+ }
+ }
+ else if (roleIndex > ROLE_DEFINITION_INDEX)
+ {
+ Assert (roleIndex < (int)countLanguageRoles(e->langType, e->kindIndex));
+
+ if (assign)
+ e->extensionFields.roleBits |= (makeRoleBit(roleIndex));
+ else
+ e->extensionFields.roleBits &= ~(makeRoleBit(roleIndex));
+ markTagExtraBitFull (e, XTAG_REFERENCE_TAGS, e->extensionFields.roleBits);
+ }
+ else
+ AssertNotReached();
+}
+
+extern void assignRole(tagEntryInfo *const e, int roleIndex)
+{
+ assignRoleFull(e, roleIndex, true);
+}
+
+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)
@@ -1447,23 +2001,39 @@ extern void invalidatePatternCache(void)
extern void tagFilePosition (MIOPos *p)
{
- mio_getpos (TagFile.mio, p);
+ /* mini-geany doesn't set TagFile.mio. */
+ if (TagFile.mio == NULL)
+ return;
+
+ if (mio_getpos (TagFile.mio, p) == -1)
+ error (FATAL|PERROR,
+ "failed to get file position of the tag file\n");
}
extern void setTagFilePosition (MIOPos *p)
{
- mio_setpos (TagFile.mio, p);
+ /* mini-geany doesn't set TagFile.mio. */
+ if (TagFile.mio == NULL)
+ return;
+
+ if (mio_setpos (TagFile.mio, p) == -1)
+ error (FATAL|PERROR,
+ "failed to set file position of the tag file\n");
}
extern const char* getTagFileDirectory (void)
{
return TagFile.directory;
}
-#ifdef CTAGS_LIB
-extern void setTagEntryFunction(tagEntryFunction entry_function, void *user_data)
+static bool markAsPlaceholder (int index, tagEntryInfo *e, void *data CTAGS_ATTR_UNUSED)
{
- TagEntryFunction = entry_function;
- TagEntryUserData = user_data;
+ e->placeholder = 1;
+ markAllEntriesInScopeAsPlaceholder (index);
+ return true;
+}
+
+extern void markAllEntriesInScopeAsPlaceholder (int index)
+{
+ foreachEntriesInScope (index, NULL, markAsPlaceholder, NULL);
}
-#endif
Modified: ctags/main/entry.h
207 lines changed, 146 insertions(+), 61 deletions(-)
===================================================================
@@ -16,30 +16,28 @@
#include "types.h"
#include <stdint.h>
-#include <stdio.h>
#include "field.h"
-#include "kind.h"
-#include "vstring.h"
#include "xtag.h"
#include "mio.h"
+#include "ptrarray.h"
#include "nestlevel.h"
-#include "ctags-api.h"
/*
* MACROS
*/
-#define WHOLE_FILE -1L
-#define includeExtensionFlags() (Option.tagFileFormat > 1)
/*
* DATA DECLARATIONS
*/
typedef struct sTagField {
fieldType ftype;
const char* value;
+ bool valueOwner; /* used only in parserFieldsDynamic */
} tagField;
+typedef uint64_t roleBitsType;
+
/* Information about the current tag candidate.
*/
struct sTagEntryInfo {
@@ -50,6 +48,10 @@ struct sTagEntryInfo {
unsigned int placeholder :1; /* This is just a part of scope context.
Put this entry to cork queue but
don't print it to tags file. */
+ unsigned int skipAutoFQEmission:1; /* If a parser makes a fq tag for the
+ current tag by itself, set this. */
+ unsigned int isPseudoTag:1; /* Used only in xref output.
+ If a tag is a pseudo, set this. */
unsigned long lineNumber; /* line number of tag */
const char* pattern; /* pattern for locating input line
@@ -60,7 +62,8 @@ struct sTagEntryInfo {
const char *inputFileName; /* name of input file */
const char *name; /* name of the tag */
int kindIndex; /* kind descriptor */
- unsigned char extra[ ((XTAG_COUNT) / 8) + 1 ];
+ uint8_t extra[ ((XTAG_COUNT) / 8) + 1 ];
+ uint8_t *extraDynamic; /* Dynamically allocated but freed by per parser TrashBox */
struct {
const char* access;
@@ -84,23 +87,27 @@ struct sTagEntryInfo {
/* type (union/struct/etc.) and name for a variable or typedef. */
const char* typeRef [2]; /* e.g., "struct" and struct name */
-/* GEANY DIFF */
- const char *varType;
-/* GEANY DIFF END */
-
-#define ROLE_INDEX_DEFINITION -1
- int roleIndex; /* for role of reference tag */
+#define ROLE_DEFINITION_INDEX -1
+#define ROLE_DEFINITION_NAME "def"
+#define ROLE_MAX_COUNT (sizeof(roleBitsType) * 8)
+ roleBitsType roleBits; /* for role of reference tag */
#ifdef HAVE_LIBXML
const char* xpath;
#endif
unsigned long endLine;
} extensionFields; /* list of extension fields*/
+ /* `usedParserFields' tracks how many parser own fields are
+ used. If it is a few (less than PRE_ALLOCATED_PARSER_FIELDS),
+ statically allocated parserFields is used. If more fields than
+ PRE_ALLOCATED_PARSER_FIELDS is defined and attached, parserFieldsDynamic
+ is used. */
+ unsigned int usedParserFields;
#define PRE_ALLOCATED_PARSER_FIELDS 5
#define NO_PARSER_FIELD -1
- unsigned int usedParserFields;
tagField parserFields [PRE_ALLOCATED_PARSER_FIELDS];
+ ptrArray * parserFieldsDynamic;
/* Following source* fields are used only when #line is found
in input and --line-directive is given in ctags command line. */
@@ -109,6 +116,9 @@ struct sTagEntryInfo {
unsigned long sourceLineNumberDifference;
};
+typedef bool (* entryForeachFunc) (int corkIndex,
+ tagEntryInfo * entry,
+ void * data);
/*
* GLOBAL VARIABLES
@@ -118,71 +128,146 @@ struct sTagEntryInfo {
/*
* FUNCTION PROTOTYPES
*/
-extern void freeTagFileResources (void);
-extern const char *tagFileName (void);
-extern void openTagFile (void);
-extern void closeTagFile (const bool resize);
-extern void setupWriter (void);
-extern void teardownWriter (const char *inputFilename);
extern int makeTagEntry (const tagEntryInfo *const tag);
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);
-extern void initTagEntryFull (tagEntryInfo *const e, const char *const name,
- unsigned long lineNumber,
- langType langType_,
- MIOPos filePosition,
- const char *inputFileName,
- int kindIndex,
- int roleIndex,
- const char *sourceFileName,
- langType sourceLangType,
- long sourceLineNumberDifference);
+extern void initForeignRefTagEntry (tagEntryInfo *const e, const char *const name,
+ langType type,
+ int kindIndex, int roleIndex);
+extern void assignRole(tagEntryInfo *const e, int roleIndex);
+extern bool isRoleAssigned(const tagEntryInfo *const e, int roleIndex);
+
extern int makeQualifiedTagEntry (const tagEntryInfo *const e);
-extern unsigned long numTagsAdded(void);
-extern void setNumTagsAdded (unsigned long nadded);
-extern unsigned long numTagsTotal(void);
-extern unsigned long maxTagsLine(void);
-extern void invalidatePatternCache(void);
-extern void tagFilePosition (MIOPos *p);
-extern void setTagFilePosition (MIOPos *p);
-extern const char* getTagFileDirectory (void);
-extern void getTagScopeInformation (tagEntryInfo *const tag,
- const char **kind, const char **name);
-/* Getting line associated with tag */
-extern char *readLineFromBypassAnyway (vString *const vLine, const tagEntryInfo *const tag,
- long *const pSeekValue);
+#define CORK_NIL 0
+tagEntryInfo *getEntryInCorkQueue (int n);
+tagEntryInfo *getEntryOfNestingLevel (const NestingLevel *nl);
+size_t countEntryInCorkQueue (void);
+
+/* If a parser sets (CORK_QUEUE and )CORK_SYMTAB to useCork,
+ * the parsesr can use symbol lookup tables for the current input.
+ * Each scope has a symbol lookup table.
+ * To register an tag to the table, use registerEntry().
+ * registerEntry registers CORKINDEX to a symbol table of a parent tag
+ * specified in the scopeIndex field of the tag specified with CORKINDEX.
+ */
+void registerEntry (int corkIndex);
-/* Generating pattern associated tag, caller must do eFree for the returned value. */
-extern char* makePatternString (const tagEntryInfo *const tag);
+/* 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 never returns false, this func returns true.
+ * If FUNC is not called because no node for NAME in the symbol table.
+ */
+bool foreachEntriesInScope (int corkIndex,
+ const char *name, /* or NULL */
+ 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);
-/* language is optional: can be NULL. */
-extern bool writePseudoTag (const ptagDesc *pdesc,
- const char *const fileName,
- const char *const pattern,
- const char *const parserName);
+int anyKindEntryInScope (int corkIndex,
+ const char *name, int kind);
-#define CORK_NIL 0
-void corkTagFile(void);
-void uncorkTagFile(void);
-tagEntryInfo *getEntryInCorkQueue (unsigned int n);
-tagEntryInfo *getEntryOfNestingLevel (const NestingLevel *nl);
-size_t countEntryInCorkQueue (void);
+int anyKindsEntryInScope (int corkIndex,
+ const char *name,
+ const int * kinds, int count);
-extern void makeFileTag (const char *const fileName);
+int anyKindsEntryInScopeRecursive (int corkIndex,
+ const char *name,
+ const int * kinds, int count);
extern void markTagExtraBit (tagEntryInfo *const tag, xtagType extra);
extern bool isTagExtraBitMarked (const tagEntryInfo *const tag, xtagType extra);
-extern void attachParserField (tagEntryInfo *const tag, fieldType ftype, const char* value);
+/* If any extra bit is on, return true. */
+extern bool isTagExtra (const tagEntryInfo *const tag);
+
+/* Functions for attaching parser specific fields
+ *
+ * Which function you should 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 ().
+ *
+ * attachParserField () and attachParserFieldToCorkEntry () duplicates
+ * the memory object specified with `value' and stores the duplicated
+ * object to the entry on the cork queue. So the parser must/can free
+ * the original one passed to the functions after calling. The cork
+ * queue manages the life of the duplicated object. It is not the
+ * parser's concern.
+ *
+ *
+ * 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.
+ *
+ * The parser (== caller) keeps the memory object specified with `value'
+ * till calling makeTagEntry (). The parser must free the memory object
+ * after calling makeTagEntry () if it is allocated dynamically in the
+ * parser side.
+ *
+ * Interpretation of VALUE
+ * -----------------------
+ * For FIELDTYPE_STRING:
+ * Both json writer and xref writer prints it as-is.
+ *
+ * For FIELDTYPE_STRING|FIELDTYPE_BOOL:
+ * If VALUE points "" (empty C string), the json writer prints it as
+ * false, and the xref writer prints it as -.
+ * If VALUE points a non-empty C string, Both json writer and xref
+ * writer print it as-is.
+ *
+ * For FIELDTYPE_BOOL
+ * The json writer always prints true.
+ * The xref writer always prints the name of field.
+ * Set "" explicitly though the value pointed by VALUE is not referred,
+ *
+ *
+ * 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 attachParserFieldToCorkEntry (int index, fieldType ftype, const char* value);
+extern const char* getParserFieldValueForType (tagEntryInfo *const tag@@ Diff output truncated at 100000 characters. @@
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list