Branch: refs/heads/master
Author: Jiří Techet <techet(a)gmail.com>
Committer: GitHub <noreply(a)github.com>
Date: Thu, 12 May 2022 23:11:49 UTC
Commit: f0ecf92e89309a23f914383ebb2968d665df911a
https://github.com/geany/geany/commit/f0ecf92e89309a23f914383ebb2968d665df9…
Log Message:
-----------
Merge pull request #3159 from techee/tex_sync
Use the upstream latex parser
Modified Paths:
--------------
ctags/Makefile.am
ctags/parsers/geany_tex.c
ctags/parsers/tex.c
ctags/parsers/tex.h
meson.build
src/tagmanager/tm_parser.c
tests/ctags/3526726.tex.tags
tests/ctags/bug2886870.tex.tags
tests/ctags/intro.tex.tags
tests/ctags/intro_orig.tex
tests/ctags/intro_orig.tex.tags
Modified: ctags/Makefile.am
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -93,7 +93,8 @@ parsers = \
parsers/tcl.c \
parsers/tcl.h \
parsers/tcloo.c \
- parsers/geany_tex.c \
+ parsers/tex.c \
+ parsers/tex.h \
parsers/txt2tags.c \
parsers/verilog.c \
parsers/vhdl.c
Modified: ctags/parsers/geany_tex.c
242 lines changed, 0 insertions(+), 242 deletions(-)
===================================================================
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 2000-2001, Jérôme Plût
- * Copyright (c) 2006, Enrico Tröger
- *
- * This source code is released for free distribution under the terms of the
- * GNU General Public License.
- *
- * This module contains functions for generating tags for source files
- * for the TeX formatting system.
- */
-
-/*
-* INCLUDE FILES
-*/
-#include "general.h" /* must always come first */
-
-#include <ctype.h>
-#include <string.h>
-
-#include "parse.h"
-#include "read.h"
-#include "vstring.h"
-#include "routines.h"
-
-/*
-* DATA DEFINITIONS
-*/
-typedef enum {
- K_COMMAND,
- K_ENVIRONMENT,
- K_SECTION,
- K_SUBSECTION,
- K_SUBSUBSECTION,
- K_CHAPTER,
- K_LABEL
-} TeXKind;
-
-static kindDefinition TeXKinds[] = {
- { true, 'f', "function", "command definitions" },
- { true, 'c', "class", "environment definitions" },
- { true, 'm', "member", "labels, sections and bibliography" },
- { true, 'd', "macro", "subsections" },
- { true, 'v', "variable", "subsubsections" },
- { true, 'n', "namespace", "chapters"},
- { true, 's', "struct", "labels and bibliography" }
-};
-
-#define TEX_BRACES (1<<0)
-#define TEX_BSLASH (1<<1)
-#define TEX_LABEL (1<<2)
-
-/*
-* FUNCTION DEFINITIONS
-*/
-
-static int getWord(const char * ref, const char **ptr)
-{
- const char *p = *ptr;
-
- while ((*ref != '\0') && (*p != '\0') && (*ref == *p))
- ref++, p++;
-
-
- if (*ref)
- return false;
-
- if (*p == '*') /* to allow something like \section*{foobar} */
- p++;
-
- *ptr = p;
- return true;
-}
-
-static void createTag(int flags, TeXKind kind, const char * l)
-{
- vString *name = vStringNew ();
-
- while ((*l == ' '))
- l++;
- if (flags & (TEX_BRACES | TEX_LABEL))
- {
- if (*l == '[')
- {
- while (*l != ']')
- {
- if (*l == '\0')
- goto no_tag;
- l++;
- }
- l++; /* skip the closing square bracket */
- }
- if (*l != '{')
- goto no_tag;
- l++;
- }
- if (flags & TEX_BSLASH)
- {
- if ((*(l++)) != '\\')
- goto no_tag;
- }
- if (flags & TEX_LABEL)
- {
- do
- {
- vStringPut(name, (int) *l);
- ++l;
- } while ((*l != '\0') && (*l != '}'));
- if (name->buffer[0] != '}')
- makeSimpleTag(name, kind);
- }
- else if (isalpha((int) *l) || *l == '@')
- {
- do
- {
- vStringPut (name, (int) *l);
- ++l;
- } while (isalpha((int) *l) || *l == '@');
- makeSimpleTag(name, kind);
- }
- else
- {
- vStringPut(name, (int) *l);
- makeSimpleTag(name, kind);
- }
-
-no_tag:
- vStringDelete(name);
-}
-
-static void findTeXTags(void)
-{
- const char *line;
-
- while ((line = (const char*)readLineFromInputFile()) != NULL)
- {
- const char *cp = line;
- /*int escaped = 0;*/
-
- for (; *cp != '\0'; cp++)
- {
- if (*cp == '%')
- break;
- if (*cp == '\\')
- {
- cp++;
-
- /* \newcommand{\command} */
- if (getWord("newcommand", &cp)
- || getWord("providecommand", &cp)
- || getWord("renewcommand", &cp)
- )
- {
- createTag (TEX_BRACES|TEX_BSLASH, K_COMMAND, cp);
- continue;
- }
-
- /* \DeclareMathOperator{\command} */
- else if (getWord("DeclareMathOperator", &cp))
- {
- if (*cp == '*')
- cp++;
- createTag(TEX_BRACES|TEX_BSLASH, K_COMMAND, cp);
- continue;
- }
-
- /* \def\command */
- else if (getWord("def", &cp))
- {
- createTag(TEX_BSLASH, K_COMMAND, cp);
- continue;
- }
-
- /* \newenvironment{name} */
- else if ( getWord("newenvironment", &cp)
- || getWord("newtheorem", &cp)
- || getWord("begin", &cp)
- )
- {
- createTag(TEX_BRACES, K_ENVIRONMENT, cp);
- continue;
- }
-
- /* \bibitem[label]{key} */
- else if (getWord("bibitem", &cp))
- {
- while (*cp == ' ')
- cp++;
- if (*(cp++) != '[')
- break;
- while ((*cp != '\0') && (*cp != ']'))
- cp++;
- if (*(cp++) != ']')
- break;
- createTag(TEX_LABEL, K_LABEL, cp);
- continue;
- }
-
- /* \label{key} */
- else if (getWord("label", &cp))
- {
- createTag(TEX_LABEL, K_LABEL, cp);
- continue;
- }
- /* \section{key} */
- else if (getWord("section", &cp))
- {
- createTag(TEX_LABEL, K_SECTION, cp);
- continue;
- }
- /* \subsection{key} */
- else if (getWord("subsection", &cp))
- {
- createTag(TEX_LABEL, K_SUBSECTION, cp);
- continue;
- }
- /* \subsubsection{key} */
- else if (getWord("subsubsection", &cp))
- {
- createTag(TEX_LABEL, K_SUBSUBSECTION, cp);
- continue;
- }
- /* \chapter{key} */
- else if (getWord("chapter", &cp))
- {
- createTag(TEX_LABEL, K_CHAPTER, cp);
- continue;
- }
- }
- }
- }
-}
-
-extern parserDefinition* TexParser (void)
-{
- static const char *const extensions [] = { "tex", "sty", "idx", NULL };
- parserDefinition * def = parserNew ("LaTeX");
- def->kindTable = TeXKinds;
- def->kindCount = ARRAY_SIZE (TeXKinds);
- def->extensions = extensions;
- def->parser = findTeXTags;
- return def;
-}
Modified: ctags/parsers/tex.c
1253 lines changed, 1253 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,1253 @@
+/*
+ * Copyright (c) 2008, David Fishburn
+ * Copyright (c) 2012, Jan Larres
+ *
+ * This source code is released for free distribution under the terms of the
+ * GNU General Public License version 2 or (at your option) any later version.
+ *
+ * This module contains functions for generating tags for TeX language files.
+ *
+ * Tex language reference:
+ * http://en.wikibooks.org/wiki/TeX#The_Structure_of_TeX
+ */
+
+/*
+ * INCLUDE FILES
+ */
+#include "general.h" /* must always come first */
+#include <ctype.h> /* to define isalpha () */
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+#include <string.h>
+
+#include "debug.h"
+#include "entry.h"
+#include "keyword.h"
+#include "parse.h"
+#include "read.h"
+#include "routines.h"
+#include "vstring.h"
+
+#include "tex.h"
+
+/*
+ * MACROS
+ */
+#define isType(token,t) (bool) ((token)->type == (t))
+#define isKeyword(token,k) (bool) ((token)->keyword == (k))
+#define isIdentChar(c) \
+ (isalpha (c) || isdigit (c) || (c) >= 0x80 || (c) == '$' || \
+ (c) == '_' || (c) == '#' || (c) == '-' || (c) == '.' || (c) == ':')
+
+/*
+ * DATA DECLARATIONS
+ */
+
+/*
+ * Used to specify type of keyword.
+ */
+enum eKeywordId {
+ KEYWORD_part,
+ KEYWORD_chapter,
+ KEYWORD_section,
+ KEYWORD_subsection,
+ KEYWORD_subsubsection,
+ KEYWORD_paragraph,
+ KEYWORD_subparagraph,
+ KEYWORD_label,
+ KEYWORD_include,
+ KEYWORD_input,
+ KEYWORD_begin,
+ KEYWORD_end,
+ KEYWORD_bibitem,
+ KEYWORD_bibliography,
+ KEYWORD_newcommand,
+ KEYWORD_renewcommand,
+ KEYWORD_providecommand,
+ KEYWORD_def,
+ KEYWORD_declaremathoperator,
+ KEYWORD_newenvironment,
+ KEYWORD_renewenvironment,
+ KEYWORD_newtheorem,
+ KEYWORD_newcounter,
+};
+typedef int keywordId; /* to allow KEYWORD_NONE */
+
+enum eTokenType {
+ /* 0..255 are the byte's value. Some are named for convenience */
+ TOKEN_OPEN_PAREN = '(',
+ TOKEN_CLOSE_PAREN = ')',
+ TOKEN_OPEN_CURLY = '{',
+ TOKEN_CLOSE_CURLY = '}',
+ TOKEN_OPEN_SQUARE = '[',
+ TOKEN_CLOSE_SQUARE = ']',
+ TOKEN_STAR = '*',
+ /* above is special types */
+ TOKEN_UNDEFINED = 256,
+ TOKEN_KEYWORD,
+ TOKEN_IDENTIFIER,
+ TOKEN_STRING,
+};
+typedef int tokenType;
+
+typedef struct sTokenInfo {
+ tokenType type;
+ keywordId keyword;
+ vString * string;
+ vString * scope;
+ unsigned long lineNumber;
+ MIOPos filePosition;
+} tokenInfo;
+
+/*
+ * DATA DEFINITIONS
+ */
+
+static langType Lang_tex;
+
+static vString *lastPart;
+static vString *lastChapter;
+static vString *lastSection;
+static vString *lastSubS;
+static vString *lastSubSubS;
+
+typedef enum {
+ TEXTAG_PART,
+ TEXTAG_CHAPTER,
+ TEXTAG_SECTION,
+ TEXTAG_SUBSECTION,
+ TEXTAG_SUBSUBSECTION,
+ TEXTAG_PARAGRAPH,
+ TEXTAG_SUBPARAGRAPH,
+ TEXTAG_LABEL,
+ TEXTAG_XINPUT,
+ TEXTAG_BIBITEM,
+ TEXTAG_COMMAND,
+ TEXTAG_OPERATOR,
+ TEXTAG_ENVIRONMENT,
+ TEXTAG_THEOREM,
+ TEXTAG_COUNTER,
+ TEXTAG_COUNT
+} texKind;
+
+typedef enum {
+ TEX_XINPUT_INCLUDED,
+ TEX_XINPUT_INPUT,
+ TEX_XINPUT_BIBLIOGRAPHY,
+} texInputRole;
+
+typedef enum {
+ TEX_ENVIRONMENT_USED,
+} texEnvironmentRole;
+
+static roleDefinition TexInputRoles [] = {
+ { true, "included",
+ "external input file specified with \\include" },
+ { true, "input",
+ "external input file specified with \\input" },
+ { true, "bibliography",
+ "bibliography (.bib) file" },
+};
+
+static roleDefinition TexEnvironmentRoles [] = {
+ { false, "used", "environment usage introduced by \\begin{MyEnv}" },
+};
+
+static kindDefinition TexKinds [] = {
+ { true, 'p', "part", "parts" },
+ { true, 'c', "chapter", "chapters" },
+ { true, 's', "section", "sections" },
+ { true, 'u', "subsection", "subsections" },
+ { true, 'b', "subsubsection", "subsubsections" },
+ { true, 'P', "paragraph", "paragraphs" },
+ { true, 'G', "subparagraph", "subparagraphs" },
+ { true, 'l', "label", "labels" },
+ { true, 'i', "xinput", "external input files",
+ .referenceOnly = true, ATTACH_ROLES(TexInputRoles) },
+ { true, 'B', "bibitem", "bibliography items" },
+ { true, 'C', "command", "command created with \\newcommand" },
+ { true, 'o', "operator", "math operator created with \\DeclareMathOperator" },
+ { true, 'e', "environment", "environment created with \\newenvironment",
+ .referenceOnly = false, ATTACH_ROLES(TexEnvironmentRoles) },
+ { true, 't', "theorem", "theorem created with \\newtheorem" },
+ { true, 'N', "counter", "counter created with \\newcounter" },
+};
+
+static const keywordTable TexKeywordTable [] = {
+ /* keyword keyword ID */
+ { "part", KEYWORD_part },
+ { "chapter", KEYWORD_chapter },
+ { "section", KEYWORD_section },
+ { "subsection", KEYWORD_subsection },
+ { "subsubsection", KEYWORD_subsubsection },
+ { "paragraph", KEYWORD_paragraph },
+ { "subparagraph", KEYWORD_subparagraph },
+ { "label", KEYWORD_label },
+ { "include", KEYWORD_include },
+ { "input", KEYWORD_input },
+ { "begin", KEYWORD_begin },
+ { "end", KEYWORD_end },
+ { "bibitem", KEYWORD_bibitem },
+ { "bibliography", KEYWORD_bibliography },
+ { "newcommand", KEYWORD_newcommand },
+ { "renewcommand", KEYWORD_renewcommand },
+ { "providecommand", KEYWORD_providecommand },
+ { "def", KEYWORD_def },
+ { "DeclareMathOperator", KEYWORD_declaremathoperator },
+ { "newenvironment", KEYWORD_newenvironment },
+ { "renewenvironment", KEYWORD_renewenvironment},
+ { "newtheorem", KEYWORD_newtheorem },
+ { "newcounter", KEYWORD_newcounter },
+};
+
+/*
+ * FUNCTION DECLARATIONS
+ */
+
+static bool notifyReadingIdentifier (tokenInfo *id_token, bool *tokenUnprocessed);
+static bool notifyReadingBeginEnvironment (tokenInfo *token, vString *envName, bool *tokenUnprocessed);
+static bool notifyReadingEndEnvironment (vString *envName);
+
+
+/*
+ * FUNCTION DEFINITIONS
+ */
+
+static tokenInfo *newToken (void)
+{
+ tokenInfo *const token = xMalloc (1, tokenInfo);
+
+ token->type = TOKEN_UNDEFINED;
+ token->keyword = KEYWORD_NONE;
+ token->string = vStringNew ();
+ token->scope = vStringNew ();
+ token->lineNumber = getInputLineNumber ();
+ token->filePosition = getInputFilePosition ();
+
+ return token;
+}
+
+static void deleteToken (tokenInfo *const token)
+{
+ vStringDelete (token->string);
+ vStringDelete (token->scope);
+ eFree (token);
+}
+
+static int getScopeInfo(texKind kind, vString *const parentName)
+{
+ int parentKind = KIND_GHOST_INDEX;
+ int i;
+
+ /*
+ * Put labels separately instead of under their scope.
+ * Is this The Right Thing To Do?
+ */
+ if (kind >= TEXTAG_LABEL) {
+ goto out;
+ }
+
+ /*
+ * This abuses the enum internals somewhat, but it should be ok in this
+ * case.
+ */
+ /* TODO: This loop and conditions can be squashed. */
+ for (i = kind - 1; i >= TEXTAG_PART; --i) {
+ if (i == TEXTAG_SUBSECTION && vStringLength(lastSubS) > 0) {
+ parentKind = i;
+ break;
+ } else if (i == TEXTAG_SECTION && vStringLength(lastSection) > 0) {
+ parentKind = i;
+ break;
+ } else if (i == TEXTAG_CHAPTER && vStringLength(lastChapter) > 0) {
+ parentKind = i;
+ break;
+ } else if (i == TEXTAG_PART && vStringLength(lastPart) > 0) {
+ parentKind = i;
+ break;
+ }
+ }
+
+ /*
+ * Is '""' the best way to separate scopes? It has to be something that
+ * should ideally never occur in normal LaTeX text.
+ */
+ for (i = TEXTAG_PART; i < (int)kind; ++i) {
+ if (i == TEXTAG_PART && vStringLength(lastPart) > 0) {
+ vStringCat(parentName, lastPart);
+ } else if (i == TEXTAG_CHAPTER && vStringLength(lastChapter) > 0) {
+ if (vStringLength(parentName) > 0) {
+ vStringCatS(parentName, "\"\"");
+ }
+ vStringCat(parentName, lastChapter);
+ } else if (i == TEXTAG_SECTION && vStringLength(lastSection) > 0) {
+ if (vStringLength(parentName) > 0) {
+ vStringCatS(parentName, "\"\"");
+ }
+ vStringCat(parentName, lastSection);
+ } else if (i == TEXTAG_SUBSECTION && vStringLength(lastSubS) > 0) {
+ if (vStringLength(parentName) > 0) {
+ vStringCatS(parentName, "\"\"");
+ }
+ vStringCat(parentName, lastSubS);
+ }
+ }
+ out:
+ return parentKind;
+}
+
+/*
+ * Tag generation functions
+ */
+
+struct symbolData {
+ langType lang;
+ int kind;
+ int *corkQueue;
+};
+
+static bool findTheName (int corkIndex, tagEntryInfo *entry, void *data)
+{
+ struct symbolData *symbolData = data;
+
+ if (entry->langType == symbolData->lang && entry->kindIndex == symbolData->kind)
+ {
+ /* TODO: The case operation should be removed */
+ *symbolData->corkQueue = corkIndex;
+ return false;
+ }
+ return true;
+}
+
+static int makeTexTag (tokenInfo *const token, int kind,
+ int roleIndex, bool unique, int scopeIndex)
+{
+ int corkQueue = CORK_NIL;
+ const char *const name = vStringValue (token->string);
+
+ if (unique)
+ {
+ struct symbolData data = {
+ .lang = getInputLanguage(),
+ .kind = kind,
+ .corkQueue = &corkQueue,
+ };
+ /* TODO: The case operation should be removed */
+ if (foreachEntriesInScope (scopeIndex, name, findTheName, (void *)&data) == false)
+ return *data.corkQueue;
+ }
+
+ tagEntryInfo e;
+ initTagEntry (&e, name, kind);
+
+ e.lineNumber = token->lineNumber;
+ e.filePosition = token->filePosition;
+
+ vString *parentName = NULL;
+
+
+ if (unique)
+ e.extensionFields.scopeIndex = scopeIndex;
+
+ /* Filling e.extensionFields.scopeKindIndex and
+ * e.extensionFields.scopeName can be filled from "kind" parameter
+ * of this function only when Tex parser calls this function. The
+ * fields cannot be filled with a kind defined in a subparser.
+ * Subparsers may fill the scope after running strategy. So in the
+ * context of a subparser, filling the scope fields here is not
+ * needed.
+ */
+ if (Lang_tex == getInputLanguage ())
+ {
+ int parentKind = KIND_GHOST_INDEX;
+ parentName = vStringNew();
+ parentKind = getScopeInfo(kind, parentName);
+ if (parentKind != KIND_GHOST_INDEX) {
+ e.extensionFields.scopeKindIndex = parentKind;
+ e.extensionFields.scopeName = vStringValue(parentName);
+ }
+ }
+
+ assignRole (&e, roleIndex);
+
+ corkQueue = makeTagEntry (&e);
+ vStringDelete (parentName); /* NULL is o.k. */
+
+ if (unique && corkQueue != CORK_NIL)
+ registerEntry (corkQueue);
+
+ return corkQueue;
+}
+
+/*
+ * Parsing functions
+ */
+
+/*
+ * Read a C identifier beginning with "firstChar" and places it into
+ * "name".
+ */
+static void parseIdentifier (vString *const string, const int firstChar)
+{
+ int c = firstChar;
+ Assert (isIdentChar (c));
+ do
+ {
+ vStringPut (string, c);
+ c = getcFromInputFile ();
+ } while (c != EOF && isIdentChar (c));
+
+ if (c != EOF)
+ ungetcToInputFile (c); /* unget non-identifier character */
+}
+
+static bool readTokenFull (tokenInfo *const token, const bool includeWhitespaces)
+{
+ int c;
+ int whitespaces = -1;
+
+ token->type = TOKEN_UNDEFINED;
+ token->keyword = KEYWORD_NONE;
+ vStringClear (token->string);
+
+getNextChar:
+
+ do
+ {
+ c = getcFromInputFile ();
+ whitespaces++;
+ }
+ while (c == '\t' || c == ' ' || c == '\n');
+
+ token->lineNumber = getInputLineNumber ();
+ token->filePosition = getInputFilePosition ();
+
+ if (includeWhitespaces && whitespaces > 0 && c != '%' && c != EOF)
+ {
+ ungetcToInputFile (c);
+ c = ' ';
+ }
+
+ token->type = (unsigned char) c;
+ switch (c)
+ {
+ case EOF: return false;
+
+ case '\\':
+ /*
+ * All Tex tags start with a backslash.
+ * Check if the next character is an alpha character
+ * else it is not a potential tex tag.
+ */
+ c = getcFromInputFile ();
+ if (! isalpha (c))
+ ungetcToInputFile (c);
+ else
+ {
+ vStringPut (token->string, '\\');
+ parseIdentifier (token->string, c);
+ token->keyword = lookupKeyword (vStringValue (token->string) + 1, Lang_tex);
+ if (isKeyword (token, KEYWORD_NONE))
+ token->type = TOKEN_IDENTIFIER;
+ else
+ token->type = TOKEN_KEYWORD;
+ }
+ break;
+
+ case '%':
+ skipToCharacterInInputFile ('\n'); /* % are single line comments */
+ goto getNextChar;
+ break;
+
+ default:
+ if (isIdentChar (c))
+ {
+ parseIdentifier (token->string, c);
+ token->type = TOKEN_IDENTIFIER;
+ }
+ break;
+ }
+ return true;
+}
+
+static bool readToken (tokenInfo *const token)
+{
+ return readTokenFull (token, false);
+}
+
+static void copyToken (tokenInfo *const dest, tokenInfo *const src)
+{
+ dest->lineNumber = src->lineNumber;
+ dest->filePosition = src->filePosition;
+ dest->type = src->type;
+ dest->keyword = src->keyword;
+ vStringCopy (dest->string, src->string);
+ vStringCopy (dest->scope, src->scope);
+}
+
+static void updateScopeInfo (texKind kind, vString *fullname)
+{
+ switch (kind)
+ {
+ case TEXTAG_PART:
+ vStringCopy(lastPart, fullname);
+ vStringClear(lastChapter);
+ vStringClear(lastSection);
+ vStringClear(lastSubS);
+ vStringClear(lastSubSubS);
+ break;
+ case TEXTAG_CHAPTER:
+ vStringCopy(lastChapter, fullname);
+ vStringClear(lastSection);
+ vStringClear(lastSubS);
+ vStringClear(lastSubSubS);
+ break;
+ case TEXTAG_SECTION:
+ vStringCopy(lastSection, fullname);
+ vStringClear(lastSubS);
+ vStringClear(lastSubSubS);
+ break;
+ case TEXTAG_SUBSECTION:
+ vStringCopy(lastSubS, fullname);
+ vStringClear(lastSubSubS);
+ break;
+ case TEXTAG_SUBSUBSECTION:
+ vStringCopy(lastSubSubS, fullname);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Scanning functions
+ */
+
+/* STRATEGY array represents the sequence of * expected tokens. If an
+ * input token matches the current * expectation (the current strategy),
+ * parseWithStrategy() runs * the actions attached to the strategy.
+ *
+ * The actions are making a tag with the kind specified with kindIndex
+ * field of the current strategy and/or storing a name to NAME field
+ * of the current strategy.
+ *
+ * If the input token doesn't much the current strategy, above actions
+ * are not run. If TEX_NAME_FLAG_OPTIONAL is specified in FLAGS field
+ * of the current specified, parseWithStrategy() tries the next
+ * strategy of STRATEGY array without reading a new token. If
+ * TEX_NAME_FLAG_OPTIONAL is not in FLAGS field, parseWithStrategy()
+ * returns the control to its caller immediately.
+ *
+ * TOKENUNPROCESSED is used for both input and output. As input,
+ * TOKENUNPROCESSED tells whether parseWithStrategy() should read a
+ * new token before matching the STRATEGY array or not. If
+ * TOKENUNPROCESSED is true, parseWithStrategy function reads a new
+ * token before matching. As output, TOKENUNPROCESSED tells the
+ * caller of parseWithStrategy() that a new token is already stored to
+ * TOKEN but parseWithStrategy() has not processed yet.
+ */
+static bool parseWithStrategy (tokenInfo *token,
+ struct TexParseStrategy *strategy,
+ bool *tokenUnprocessed)
+{
+ bool next_token = !*tokenUnprocessed;
+ tokenInfo * name = NULL;
+ bool eof = false;
+ bool exclusive = false;
+
+ for (struct TexParseStrategy *s = strategy; s->type != 0; ++s)
+ s->corkIndex = CORK_NIL;
+
+ for (struct TexParseStrategy *s = strategy; !eof && s->type != 0; ++s)
+ {
+ if (s->kindIndex != KIND_GHOST_INDEX || s->name)
+ {
+ name = newToken ();
+ break;
+ }
+ }
+
+ for (struct TexParseStrategy *s = strategy; !eof && s->type != 0; ++s)
+ {
+ bool capture_name = s->kindIndex != KIND_GHOST_INDEX || s->name;
+
+ if (next_token)
+ {
+ if (!readToken (token))
+ {
+ eof = true;
+ break;
+ }
+ }
+
+ if ((s->type == '<' && isType (token, '<'))
+ || (s->type == '[' && isType (token, '[')))
+ {
+ tokenType terminator = (s->type == '<') ? '>' : ']';
+
+ next_token = true;
+
+
+ if (!readToken (token))
+ {
+ eof = true;
+ break;
+ }
+ if (capture_name)
+ {
+ copyToken (name, token);
+ vStringClear (name->string);
+ }
+
+ while (! isType (token, terminator))
+ {
+ if (capture_name && isType (token, TOKEN_IDENTIFIER))
+ {
+ if (vStringLength (name->string) > 0)
+ vStringPut (name->string, ' ');
+ vStringCat (name->string, token->string);
+ }
+
+ if (!readTokenFull (token,
+ s->flags & TEX_NAME_FLAG_INCLUDING_WHITESPACE))
+ {
+ eof = true;
+ break;
+ }
+ }
+ if (!exclusive && capture_name && vStringLength (name->string) > 0)
+ {
+ if (s->kindIndex != KIND_GHOST_INDEX)
+ s->corkIndex = makeTexTag (name, s->kindIndex, s->roleIndex,
+ s->unique, s->scopeIndex);
+
+ if (s->name)
+ vStringCopy(s->name, name->string);
+
+ if (s->flags & TEX_NAME_FLAG_EXCLUSIVE)
+ exclusive = true;
+ }
+ }
+ else if (s->type == '*' && isType (token, '*'))
+ next_token = true;
+ else if (((s->type == '{' || s->type == '\\') && isType (token, '{')) ||
+ (s->type == '\\' && isType (token, TOKEN_IDENTIFIER)))
+ {
+ int depth = 1;
+ bool missing_parens = isType (token, TOKEN_IDENTIFIER);
+
+ next_token = true;
+
+ if (!missing_parens && !readToken (token))
+ {
+ eof = true;
+ break;
+ }
+ if (capture_name)
+ {
+ copyToken (name, token);
+ vStringClear (name->string);
+ }
+ if (missing_parens)
+ {
+ vStringCat (name->string, token->string);
+ depth = 0;
+ }
+
+ /* Handle the case the code like \section{} */
+ if (isType (token, '}'))
+ break;
+ while (depth > 0)
+ {
+ if (capture_name)
+ {
+ if (isType (token, TOKEN_IDENTIFIER) || isType (token, TOKEN_KEYWORD))
+ vStringCat (name->string, token->string);
+ else
+ vStringPut (name->string, token->type);
+ }
+ if (!readTokenFull (token,
+ s->flags & TEX_NAME_FLAG_INCLUDING_WHITESPACE))
+ {
+ eof = true;
+ break;
+ }
+ else if (isType (token, TOKEN_OPEN_CURLY))
+ depth++;
+ else if (isType (token, TOKEN_CLOSE_CURLY))
+ depth--;
+ }
+ if (!exclusive && depth == 0 && capture_name && vStringLength (name->string) > 0)
+ {
+ vStringStripTrailing (name->string);
+
+ if (s->kindIndex != KIND_GHOST_INDEX)
+ s->corkIndex = makeTexTag (name, s->kindIndex, s->roleIndex,
+ s->unique, s->scopeIndex);
+
+ if (s->name)
+ vStringCopy(s->name, name->string);
+
+ if (s->flags & TEX_NAME_FLAG_EXCLUSIVE)
+ exclusive = true;
+
+ }
+ }
+ else if (s->flags & TEX_NAME_FLAG_OPTIONAL)
+ /* Apply next strategy to the same token */
+ next_token = false;
+ else
+ {
+ *tokenUnprocessed = true;
+ break;
+ }
+ }
+
+ /* The last token is optional and not present - let the caller know */
+ if (!next_token)
+ *tokenUnprocessed = true;
+
+ if (name)
+ deleteToken (name);
+
+ return eof;
+}
+
+static bool parseTagFull (tokenInfo *const token, texKind kind, int roleIndex, bool enterSquare, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ vString *taggedName = vStringNew();
+
+ /*
+ * Tex tags are of these formats:
+ * \keyword{any number of words}
+ * \keyword[short desc]{any number of words}
+ * \keyword*[short desc]{any number of words}
+ *
+ * When a keyword is found, loop through all words within
+ * the curly braces for the tag name.
+ *
+ * If the keyword is label like \label, words in the square
+ * brackets should be skipped. This can be controlled
+ * with `enterSquare' parameter; true is for tagging, and
+ * false is for skipping.
+ */
+
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ /* .kindIndex is initialized dynamically. */
+ },
+ {
+ .type = '*',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = TEX_NAME_FLAG_INCLUDING_WHITESPACE,
+ .kindIndex = kind,
+ .roleIndex = roleIndex,
+ .name = taggedName,
+ .unique = false,
+ },
+ {
+ .type = 0
+ }
+ };
+
+
+ if (enterSquare)
+ {
+ strategy [0].kindIndex = kind;
+ strategy [0].roleIndex = roleIndex;
+ strategy [0].flags |= TEX_NAME_FLAG_EXCLUSIVE;
+ strategy [0].name = taggedName;
+ strategy [0].unique = false;
+ }
+ else
+ {
+ strategy [0].kindIndex = KIND_GHOST_INDEX;
+ strategy [0].name = NULL;
+ }
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ {
+ eof = true;
+ goto out;
+ }
+
+ /*
+ * save the name of the last section definitions for scope-resolution
+ * later
+ */
+ if (vStringLength (taggedName) > 0)
+ updateScopeInfo (kind, taggedName);
+
+ out:
+ vStringDelete (taggedName);
+
+ return eof;
+}
+
+static bool parseTag (tokenInfo *const token, texKind kind,
+ bool enterSquare, bool *tokenUnprocessed)
+{
+ return parseTagFull (token, kind, ROLE_DEFINITION_INDEX,
+ enterSquare, tokenUnprocessed);
+}
+
+static bool parseEnv (tokenInfo *const token, bool begin, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ vString *envName = vStringNew ();
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '{',
+ .flags = TEX_NAME_FLAG_INCLUDING_WHITESPACE,
+ .kindIndex = begin ? TEXTAG_ENVIRONMENT : KIND_GHOST_INDEX,
+ .roleIndex = TEX_ENVIRONMENT_USED,
+ .name = envName,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ {
+ eof = true;
+ goto out;
+ }
+
+
+ if (vStringLength (envName) > 0)
+ {
+ if (begin)
+ eof = notifyReadingBeginEnvironment (token, envName, tokenUnprocessed);
+ else
+ eof = notifyReadingEndEnvironment (envName);
+ }
+
+ out:
+ vStringDelete (envName);
+
+ return eof;
+
+}
+
+static bool parseNewcommandFull (tokenInfo *const token, bool *tokenUnprocessed, texKind kind)
+{
+ bool eof = false;
+
+ /* \newcommand{cmd}[args][opt]{def} */
+ /* \newcommand\cmd[args][opt]{def} */
+ /* \def\cmd{replacement} */
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '\\',
+ .flags = 0,
+ .kindIndex = kind,
+ .roleIndex = ROLE_DEFINITION_INDEX,
+ .name = NULL,
+ .unique = false,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ eof = true;
+
+ return eof;
+}
+
+static bool parseNewcommand (tokenInfo *const token, bool *tokenUnprocessed)
+{
+ return parseNewcommandFull (token, tokenUnprocessed, TEXTAG_COMMAND);
+}
+
+static bool parseNewEnvironment (tokenInfo *const token, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ /* \newenvironment{nam}[args]{begdef}{enddef} */
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = TEXTAG_ENVIRONMENT,
+ .roleIndex = ROLE_DEFINITION_INDEX,
+ .name = NULL,
+ .unique = false,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ eof = true;
+
+ return eof;
+}
+
+static bool parseNewTheorem (tokenInfo *const token, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ /* \newtheorem{name}{title}
+ \newtheorem{name}{title}[numbered_within]
+ \newtheorem{name}[numbered_like]{title} */
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = TEXTAG_THEOREM,
+ .roleIndex = ROLE_DEFINITION_INDEX,
+ .name = NULL,
+ .unique = false,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ eof = true;
+
+ return eof;
+}
+
+static bool parseNewcounter (tokenInfo *const token, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ /* \newcounter {counter}[parentCounter] */
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = TEXTAG_COUNTER,
+ .roleIndex = ROLE_DEFINITION_INDEX,
+ .name = NULL,
+ .unique = false,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ eof = true;
+
+ return eof;
+}
+
+static void parseTexFile (tokenInfo *const token)
+{
+ bool eof = false;
+ bool tokenUnprocessed = false;
+
+ do
+ {
+ if (!tokenUnprocessed)
+ {
+ if (!readToken (token))
+ break;
+ }
+ tokenUnprocessed = false;
+
+ if (isType (token, TOKEN_KEYWORD))
+ {
+ switch (token->keyword)
+ {
+ case KEYWORD_part:
+ eof = parseTag (token, TEXTAG_PART, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_chapter:
+ eof = parseTag (token, TEXTAG_CHAPTER, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_section:
+ eof = parseTag (token, TEXTAG_SECTION, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_subsection:
+ eof = parseTag (token, TEXTAG_SUBSECTION, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_subsubsection:
+ eof = parseTag (token, TEXTAG_SUBSUBSECTION, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_paragraph:
+ eof = parseTag (token, TEXTAG_PARAGRAPH, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_subparagraph:
+ eof = parseTag (token, TEXTAG_SUBPARAGRAPH, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_label:
+ eof = parseTag (token, TEXTAG_LABEL, false, &tokenUnprocessed);
+ break;
+ case KEYWORD_include:
+ eof = parseTagFull (token, TEXTAG_XINPUT, TEX_XINPUT_INCLUDED,
+ false, &tokenUnprocessed);
+ break;
+ case KEYWORD_input:
+ eof = parseTagFull (token, TEXTAG_XINPUT, TEX_XINPUT_INPUT,
+ false, &tokenUnprocessed);
+ break;
+ case KEYWORD_begin:
+ eof = parseEnv (token, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_end:
+ eof = parseEnv (token, false, &tokenUnprocessed);
+ break;
+ case KEYWORD_bibitem:
+ eof = parseTag (token, TEXTAG_BIBITEM, false, &tokenUnprocessed);
+ break;
+ case KEYWORD_bibliography:
+ eof = parseTagFull (token, TEXTAG_XINPUT, TEX_XINPUT_BIBLIOGRAPHY,
+ false, &tokenUnprocessed);
+ break;
+ case KEYWORD_newcommand:
+ case KEYWORD_renewcommand:
+ case KEYWORD_providecommand:
+ case KEYWORD_def:
+ eof = parseNewcommand (token, &tokenUnprocessed);
+ break;
+ case KEYWORD_declaremathoperator:
+ eof = parseNewcommandFull (token, &tokenUnprocessed, TEXTAG_OPERATOR);
+ break;
+ case KEYWORD_newenvironment:
+ case KEYWORD_renewenvironment:
+ eof = parseNewEnvironment (token, &tokenUnprocessed);
+ break;
+ case KEYWORD_newtheorem:
+ eof = parseNewTheorem (token, &tokenUnprocessed);
+ break;
+ case KEYWORD_newcounter:
+ eof = parseNewcounter (token, &tokenUnprocessed);
+ break;
+ default:
+ break;
+ }
+ }
+ else if (isType (token, TOKEN_IDENTIFIER))
+ eof = notifyReadingIdentifier (token, &tokenUnprocessed);
+ if (eof)
+ break;
+ } while (true);
+}
+
+static void initialize (const langType language)
+{
+ Assert (ARRAY_SIZE (TexKinds) == TEXTAG_COUNT);
+ Lang_tex = language;
+
+ lastPart = vStringNew();
+ lastChapter = vStringNew();
+ lastSection = vStringNew();
+ lastSubS = vStringNew();
+ lastSubSubS = vStringNew();
+}
+
+static void finalize (const langType language CTAGS_ATTR_UNUSED,
+ bool initialized)
+{
+ if (initialized)
+ {
+ vStringDelete(lastPart);
+ lastPart = NULL;
+ vStringDelete(lastChapter);
+ lastChapter = NULL;
+ vStringDelete(lastSection);
+ lastSection = NULL;
+ vStringDelete(lastSubS);
+ lastSubS = NULL;
+ vStringDelete(lastSubSubS);
+ lastSubSubS = NULL;
+ }
+}
+
+static void findTexTags (void)
+{
+ tokenInfo *const token = newToken ();
+
+ vStringClear(lastPart);
+ vStringClear(lastChapter);
+ vStringClear(lastSection);
+ vStringClear(lastSubS);
+ vStringClear(lastSubSubS);
+
+ parseTexFile (token);
+
+ deleteToken (token);
+}
+
+static bool notifyReadingIdentifier (tokenInfo *id_token, bool *tokenUnprocessed)
+{
+ subparser *sub;
+ bool eof = false;
+
+ foreachSubparser (sub, false)
+ {
+ texSubparser *texsub = (texSubparser *)sub;
+
+ if (texsub->readIdentifierNotify)
+ {
+ struct TexParseStrategy *strategy;
+
+ enterSubparser(sub);
+
+ strategy = texsub->readIdentifierNotify (texsub, id_token->string);
+
+ if (strategy)
+ {
+ eof = parseWithStrategy (id_token, strategy, tokenUnprocessed);
+ if (texsub->reportStrategicParsing)
+ texsub->reportStrategicParsing (texsub, strategy);
+ }
+
+ leaveSubparser();
+
+ if (strategy)
+ break;
+ }
+ }
+
+ return eof;
+}
+
+static bool notifyReadingBeginEnvironment (tokenInfo *token,
+ vString *envName,
+ bool *tokenUnprocessed)
+{
+ subparser *sub;
+ bool eof = false;
+
+ foreachSubparser (sub, false)
+ {
+ texSubparser *texsub = (texSubparser *)sub;
+
+ if (texsub->readEnviromentBeginNotify)
+ {
+ struct TexParseStrategy *strategy;
+
+ enterSubparser (sub);
+ strategy = texsub->readEnviromentBeginNotify (texsub, envName);
+ if (strategy)
+ {
+ eof = parseWithStrategy (token, strategy, tokenUnprocessed);
+ if (texsub->reportStrategicParsing)
+ texsub->reportStrategicParsing (texsub, strategy);
+ }
+ leaveSubparser ();
+ if (strategy)
+ break;
+ }
+ }
+
+ return eof;
+}
+
+static bool notifyReadingEndEnvironment (vString *envName)
+{
+ subparser *sub;
+
+ foreachSubparser (sub, false)
+ {
+ texSubparser *texsub = (texSubparser *)sub;
+
+ if (texsub->readEnviromentEndNotify)
+ {
+ bool consuming;
+
+ enterSubparser (sub);
+ consuming = texsub->readEnviromentEndNotify (texsub, envName);
+ leaveSubparser ();
+ if (consuming)
+ break;
+ }
+ }
+
+ return false;
+}
+
+/* Create parser definition structure */
+extern parserDefinition* TexParser (void)
+{
+ static const char *const extensions [] = { "tex", NULL };
+ parserDefinition *const def = parserNew ("Tex");
+ def->extensions = extensions;
+ /*
+ * New definitions for parsing instead of regex
+ */
+ def->kindTable = TexKinds;
+ def->kindCount = ARRAY_SIZE (TexKinds);
+ def->parser = findTexTags;
+ def->initialize = initialize;
+ def->finalize = finalize;
+ def->keywordTable = TexKeywordTable;
+ def->keywordCount = ARRAY_SIZE (TexKeywordTable);
+ def->useCork = CORK_QUEUE | CORK_SYMTAB;
+ return def;
+}
Modified: ctags/parsers/tex.h
114 lines changed, 114 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2020, 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.
+*
+* Tex base parser interface exported to subparsers
+*/
+
+#ifndef CTAGS_PARSER_TEX_H
+#define CTAGS_PARSER_TEX_H
+
+/*
+* INCLUDE FILES
+*/
+
+#include "general.h" /* must always come first */
+
+#include "subparser.h"
+#include "vstring.h"
+
+
+/*
+* DATA DEFINITIONS
+*/
+
+/* Parsing strategy */
+
+enum TexNameFlag {
+ /* Allow that the type of input token doesn't match
+ * the type of strategy. In stread of aborting,
+ * apply the next strategy to the same token. */
+ TEX_NAME_FLAG_OPTIONAL = (1 << 0),
+
+ /* When reading tokens inside pair,
+ * whitespaces are considered as parts of a token or not. */
+ TEX_NAME_FLAG_INCLUDING_WHITESPACE = (1 << 1),
+
+ /* If a tag is created with this strategy, don't
+ * create a tag in its successor strategies. */
+ TEX_NAME_FLAG_EXCLUSIVE = (1 << 2),
+};
+
+struct TexParseStrategy {
+ /* Expected token type '<', '[', '*', '{', and '\\' are supported.
+ * 0 means the end of strategies. '\\' means {} pair may be omitted.
+ *
+ * A string between <>, [], or {} (pairs) can be tagged or store to
+ * a vString. See kindIndex and name field of this structure.
+ */
+ int type;
+
+ /* Bits combination of enum TexNameFlag */
+ unsigned int flags;
+
+ /* Kind and role for making a tag for the string surrounded by one of pairs.
+ * If you don't need to make a tag for the string,
+ * specify KIND_GHOST_INDEX. */
+ int kindIndex;
+ int roleIndex;
+
+ /* If a tag is made, Tex parser stores its cork index here. */
+ int corkIndex;
+
+ /* Store the string surrounded by one of paris.
+ * If you don't need to store the string, set NULL here. */
+ vString *name;
+
+ /* If true, make at most one tag for the name in the scope specified
+ * with scopeIndex. When making a tag, scopeIndex is set to
+ * extensionFields.scopeIndex only if unique is true.
+ * scopeIndex is never referred if unique if false. */
+ bool unique;
+ int scopeIndex;
+};
+
+typedef struct sTexSubparser texSubparser;
+struct sTexSubparser {
+ subparser subparser;
+
+ /* When Tex parser reads an \begin{foo}, it calls
+ * this method.
+ *
+ * A subparser having interests in successor tokens may return strategies.
+ * If it doesn't, just return NULL; Tex base parser may call the next subparser.
+ */
+ struct TexParseStrategy * (* readEnviromentBeginNotify) (texSubparser *s,
+ vString *env);
+ /* When Tex parser reads an \end{foo}, it calls
+ * this method.
+ *
+ * If this method returns true, Tex base parser may call the next subparser.
+ * If it returns false, Tex base parser stops calling the rest of subparsers.
+ */
+ bool (* readEnviromentEndNotify) (texSubparser *s, vString *env);
+
+ /* When Tex parser reads an \identifier, it calls
+ * this method.
+ *
+ * A subparser having interests in successor tokens may return strategies.
+ * If it has no interest, just return NULL; Tex base parser may call next subparser.
+ */
+ struct TexParseStrategy *(* readIdentifierNotify) (texSubparser *s,
+ vString *identifier);
+
+ /* After Tex parser runs the strategies returned from readIdentifierNotify
+ * method, Tex parser calls this method to notify the subparser the result
+ * of running the strategies; corkIndex and/or name fields of strategies
+ * may be filled. */
+ void (* reportStrategicParsing) (texSubparser *s,
+ const struct TexParseStrategy *strategy);
+};
+
+#endif /* CTAGS_PARSER_TEX_H */
Modified: meson.build
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -637,7 +637,6 @@ ctags = static_library('ctags',
'ctags/parsers/geany_lcpp.c',
'ctags/parsers/geany_lcpp.h',
'ctags/parsers/geany_matlab.c',
- 'ctags/parsers/geany_tex.c',
'ctags/parsers/go.c',
'ctags/parsers/haskell.c',
'ctags/parsers/haxe.c',
@@ -670,6 +669,8 @@ ctags = static_library('ctags',
'ctags/parsers/tcl.c',
'ctags/parsers/tcl.h',
'ctags/parsers/tcloo.c',
+ 'ctags/parsers/tex.c',
+ 'ctags/parsers/tex.h',
'ctags/parsers/txt2tags.c',
'ctags/parsers/verilog.c',
'ctags/parsers/vhdl.c',
Modified: src/tagmanager/tm_parser.c
29 lines changed, 21 insertions(+), 8 deletions(-)
===================================================================
@@ -204,22 +204,32 @@ static TMParserMapGroup group_PYTHON[] = {
};
static TMParserMapEntry map_LATEX[] = {
- {'f', tm_tag_function_t},
- {'c', tm_tag_class_t},
- {'m', tm_tag_member_t},
- {'d', tm_tag_macro_t},
- {'v', tm_tag_variable_t},
- {'n', tm_tag_namespace_t},
- {'s', tm_tag_struct_t},
+ {'p', tm_tag_enum_t}, // part
+ {'c', tm_tag_namespace_t}, // chapter
+ {'s', tm_tag_member_t}, // section
+ {'u', tm_tag_macro_t}, // subsection
+ {'b', tm_tag_variable_t}, // subsubsection
+ {'P', tm_tag_undef_t}, // paragraph
+ {'G', tm_tag_undef_t}, // subparagraph
+ {'l', tm_tag_struct_t}, // label
+ {'i', tm_tag_undef_t}, // xinput
+ {'B', tm_tag_field_t}, // bibitem
+ {'C', tm_tag_function_t}, // command
+ {'o', tm_tag_function_t}, // operator
+ {'e', tm_tag_class_t}, // environment
+ {'t', tm_tag_class_t}, // theorem
+ {'N', tm_tag_undef_t}, // counter
};
static TMParserMapGroup group_LATEX[] = {
{_("Command"), TM_ICON_NONE, tm_tag_function_t},
{_("Environment"), TM_ICON_NONE, tm_tag_class_t},
+ {_("Part"), TM_ICON_NONE, tm_tag_enum_t},
+ {_("Chapter"), TM_ICON_NONE, tm_tag_namespace_t},
{_("Section"), TM_ICON_NONE, tm_tag_member_t},
{_("Subsection"), TM_ICON_NONE, tm_tag_macro_t},
{_("Subsubsection"), TM_ICON_NONE, tm_tag_variable_t},
+ {_("Bibitem"), TM_ICON_NONE, tm_tag_field_t},
{_("Label"), TM_ICON_NONE, tm_tag_struct_t},
- {_("Chapter"), TM_ICON_NONE, tm_tag_namespace_t},
};
// no scope information
@@ -1472,6 +1482,7 @@ const gchar *tm_parser_scope_separator(TMParserType lang)
case TM_PARSER_ZEPHIR:
return "::";
+ case TM_PARSER_LATEX:
case TM_PARSER_MARKDOWN:
case TM_PARSER_TXT2TAGS:
return "\"\"";
@@ -1495,6 +1506,7 @@ const gchar *tm_parser_scope_separator_printable(TMParserType lang)
{
case TM_PARSER_ASCIIDOC:
case TM_PARSER_CONF:
+ case TM_PARSER_LATEX:
case TM_PARSER_MARKDOWN:
case TM_PARSER_REST:
case TM_PARSER_TXT2TAGS:
@@ -1523,6 +1535,7 @@ gboolean tm_parser_has_full_scope(TMParserType lang)
case TM_PARSER_JAVA:
case TM_PARSER_JAVASCRIPT:
case TM_PARSER_JSON:
+ case TM_PARSER_LATEX:
case TM_PARSER_LUA:
case TM_PARSER_MARKDOWN:
case TM_PARSER_PHP:
Modified: tests/ctags/3526726.tex.tags
266 lines changed, 130 insertions(+), 136 deletions(-)
===================================================================
@@ -1,155 +1,149 @@
# format=tagmanager
- I think I found a bug in Snort. Now what?�65536�0
- I've got RedHat and ....�65536�0
-A Rule with PCRE causes a failure to load snort.conf. Why?�65536�0
-After I add new rules or comment out rules how do I make Snort reload?�65536�0
-Are rule keywords ORed or ANDed together?�65536�0
-Are there other output systems for Snort besides ``Barnyard''?\label{spoolers�65536�0
-BASE appears to be broken in Lynx �65536�0
+A Rule with PCRE causes a failure to load snort.conf. Why?�65536�Problems�0
+After I add new rules or comment out rules how do I make Snort reload?�65536�Rules and Alerts�0
+Are rule keywords ORed or ANDed together?�65536�Rules and Alerts�0
+Are there other output systems for Snort besides ``Barnyard''?\label{spoolers}�65536�Getting Fancy�0
+BASE appears to be broken in Lynx�65536�Problems�0
Background�64�0
-Can Snort be evaded by the use of polymorphic mutators on shellcode?�65536�0
-Can Snort trigger a rule by MAC addresses?�65536�0
-Can priorities be assigned to alerts using BASE? �65536�0
+Can Snort be evaded by the use of polymorphic mutators on shellcode?�65536�Background�0
+Can Snort trigger a rule by MAC addresses?�65536�Rules and Alerts�0
+Can priorities be assigned to alerts using BASE?�65536�Rules and Alerts�0
Configuring Snort�64�0
Development�64�0
-Does Snort handle IP defragmentation?�65536�0
-Does Snort log the full packets when it generates alerts? �65536�0
-Does Snort perform TCP stream reassembly?�65536�0
-Does Snort perform stateful protocol analysis?�65536�0
-Does snort see packets filtered by IPTables/IPChains/IPF/PF?�65536�0
-Errors loading rules files�65536�0
+Does Snort handle IP defragmentation?�65536�Background�0
+Does Snort log the full packets when it generates alerts?�65536�Background�0
+Does Snort perform TCP stream reassembly?�65536�Background�0
+Does Snort perform stateful protocol analysis?�65536�Background�0
+Does snort see packets filtered by IPTables/IPChains/IPF/PF?�65536�Rules and Alerts�0
+Errors loading rules files�65536�Rules and Alerts�0
Getting Fancy�64�0
Getting Started�64�0
-How can I deactivate a rule?�65536�0
-How can I define an address to be anything except some hosts?�65536�0
-How can I examine logged packets in more detail?�65536�0
-How can I protect web servers running on ports other than 80?�65536�0
-How can I run Snort on multiple interfaces simultaneously?�65536�0
-How can I specify a list of ports in a rule?�65536�0
-How can I test Snort without having an Ethernet card or a connection to other computers? �65536�0
-How can I use Snort to log HTTP URLs or SMTP traffic?�65536�0
-How do I build this BASE thing?�65536�0
-How do I configure stream4?�65536�0
-How do I get Snort and ACID working?�65536�0
-How do I get Snort to e-mail me alerts?�65536�0
-How do I get Snort to log the packet payload as well as the header?�65536�0
-How do I ignore traffic coming from a particular host or hosts?�65536�0
-How do I log a specific type of traffic and send alerts to syslog?�65536�0
-How do I log to multiple databases or output plugins?�65536�0
-How do I process those Snort logs into reports?�65536�0
-How do I run Snort?�65536�0
-How do I set EXTERNAL\_NET?�65536�0
-How do I setup a receive-only ethernet cable?�65536�0
-How do I setup snort on a `stealth' interface? �65536�0
-How do I test Snort alerts and logging?�65536�0
-How do I turn off ``spp:possible EVASIVE RST detection'' alerts?�65536�0
-How do I understand this traffic and do IDS alert analysis?�65536�0
-How do I use a remote syslog machine?�65536�0
-How do you get Snort to ignore some traffic?�65536�0
-How do you pronounce the names of some of these guys who work on Snort?�65536�0
-How do you put Snort in debug mode? �65536�0
-How does rule ordering work?�65536�0
-How long can address lists, variables, or rules be?�65536�0
-How to start Snort as a win32 service? �65536�0
-I am getting `snort [pid] uses obsolete (PF\_INET, SOCK\_PACKET)' warnings. What's wrong?�65536�0
-I am getting too many ``IIS Unicode attack detected'' and/or ``CGI Null Byte attack detected'' false positives. How can I turn this detection off? �65536�0
-I am still getting bombarded with spp\_portscan messages even though the IP that I am getting the portscan from is in my \$DNS\_SERVERs var �65536�0
-I am using Snort on Windows and receive an ``OpenPcap() error upon startup: ERROR: OpenPcap() device open: Error opening adapter'' message. What's wrong? �65536�0
-I have one network card and two aliases, how can I force Snort to ``listen'' on both addresses?�65536�0
-I hear people talking about ``Barnyard''. What's that?\label{barnyard�65536�0
-I just downloaded a new ruleset and now Snort fails, complaining about the�65536�0
-I try to start Snort and it gives an error like ``ERROR: Unable to open�65536�0
-I want to build a Snort box. Will this $<$Insert list of hardware$>$ handle $<$this much$>$ traffic? �65536�0
-I'm getting large amounts of $<$some alerts type$>$. What should I do? Where can I go to find out more about it? �65536�0
-I'm getting lots of *ICMP Ping Speedera*, is this bad?�65536�0
-I'm not seeing any interfaces listed under Win32.�65536�0
-I'm on a switched network, can I still use Snort?�65536�0
+How can I deactivate a rule?�65536�Rules and Alerts�0
+How can I define an address to be anything except some hosts?�65536�Rules and Alerts�0
+How can I examine logged packets in more detail?�65536�Getting Fancy�0
+How can I protect web servers running on ports other than 80?�65536�Rules and Alerts�0
+How can I run Snort on multiple interfaces simultaneously?�65536�Configuring Snort�0
+How can I specify a list of ports in a rule?�65536�Rules and Alerts�0
+How can I test Snort without having an Ethernet card or a connection to other computers?�65536�Getting Fancy�0
+How can I use Snort to log HTTP URLs or SMTP traffic?�65536�Getting Fancy�0
+How do I build this BASE thing?�65536�Configuring Snort�0
+How do I configure stream4?�65536�Configuring Snort�0
+How do I get Snort and ACID working?�65536�Configuring Snort�0
+How do I get Snort to e-mail me alerts?�65536�Getting Fancy�0
+How do I get Snort to log the packet payload as well as the header?�65536�Configuring Snort�0
+How do I ignore traffic coming from a particular host or hosts?�65536�Configuring Snort�0
+How do I log a specific type of traffic and send alerts to syslog?�65536�Getting Fancy�0
+How do I log to multiple databases or output plugins?�65536�Getting Fancy�0
+How do I process those Snort logs into reports?�65536�Getting Fancy�0
+How do I run Snort?�65536�Getting Started�0
+How do I set EXTERNAL\_NET?�65536�Configuring Snort�0
+How do I setup a receive-only ethernet cable?�65536�Configuring Snort�0
+How do I setup snort on a `stealth' interface?�65536�Configuring Snort�0
+How do I test Snort alerts and logging?�65536�Rules and Alerts�0
+How do I turn off ``spp:possible EVASIVE RST detection'' alerts?�65536�Rules and Alerts�0
+How do I understand this traffic and do IDS alert analysis?�65536�Getting Fancy�0
+How do I use a remote syslog machine?�65536�Configuring Snort�0
+How do you get Snort to ignore some traffic?�65536�Configuring Snort�0
+How do you pronounce the names of some of these guys who work on Snort?�65536�Background�0
+How do you put Snort in debug mode?�65536�Development�0
+How does rule ordering work?�65536�Configuring Snort�0
+How long can address lists, variables, or rules be?�65536�Rules and Alerts�0
+How to start Snort as a win32 service?�65536�Getting Fancy�0
+I am getting `snort [pid] uses obsolete (PF\_INET, SOCK\_PACKET)' warnings. What's wrong?�65536�Problems�0
+I am getting too many ``IIS Unicode attack detected'' and/or ``CGI Null Byte attack detected'' false positives. How can I turn this detection off?�65536�Rules and Alerts�0
+I am still getting bombarded with spp\_portscan messages even though the IP that I am getting the portscan from is in my \$DNS\_SERVERs var�65536�Problems�0
+I am using Snort on Windows and receive an ``OpenPcap() error upon startup: ERROR: OpenPcap() device open: Error opening adapter'' message. What's wrong?�65536�Problems�0
+I have one network card and two aliases, how can I force Snort to ``listen'' on both addresses?�65536�Configuring Snort�0
+I hear people talking about ``Barnyard''. What's that?\label{barnyard}�65536�Getting Fancy�0
+I just downloaded a new ruleset and now Snort fails, complaining about the rules.�65536�Problems�0
+I think I found a bug in Snort. Now what?�65536�Problems�0
+I try to start Snort and it gives an error like ``ERROR: Unable to open rules file: /root/.snortrc or /root//root/.snortrc.'' What can I do to fix this?�65536�Problems�0
+I want to build a Snort box. Will this $<$Insert list of hardware$>$ handle $<$this much$>$ traffic?�65536�Getting Started�0
+I'm getting large amounts of $<$some alerts type$>$. What should I do? Where can I go to find out more about it?�65536�Rules and Alerts�0
+I'm getting lots of *ICMP Ping Speedera*, is this bad?�65536�Problems�0
+I'm not seeing any interfaces listed under Win32.�65536�Problems�0
+I'm on a switched network, can I still use Snort?�65536�Background�0
+I've got RedHat and ....�65536�Getting Started�0
IDSCenter�2048�0
-Is Fyodor Yarochkin the same Fyodor who wrote nmap?�65536�0
-Is Snort vulnerable to IDS noise generators like ``Stick'' and ``Snot''?�65536�0
-Is it possible to have Snort call an external program when an alert is raised?�65536�0
-Is it possible with snort to add a ipfilter/ipfw rule to a firewall? �65536�0
-Is there a private SID number range so my rules don't conflict?�65536�0
-It's not working on Win32, how can I tell if my problem is Snort or�65536�0
-Libpcap complains about permissions problems, what's going on?�65536�0
+Is Fyodor Yarochkin the same Fyodor who wrote nmap?�65536�Background�0
+Is Snort vulnerable to IDS noise generators like ``Stick'' and ``Snot''?�65536�Background�0
+Is it possible to have Snort call an external program when an alert is raised?�65536�Getting Fancy�0
+Is it possible with snort to add a ipfilter/ipfw rule to a firewall?�65536�Getting Fancy�0
+Is there a private SID number range so my rules don't conflict?�65536�Rules and Alerts�0
+It's not working on Win32, how can I tell if my problem is Snort or WinPcap?�65536�Problems�0
+Libpcap complains about permissions problems, what's going on?�65536�Getting Started�0
Miscellaneous�64�0
-My /var/log/snort directory gets very large...�65536�0
-My BASE db connection times-out when performing long operations (e.g.�65536�0
-My IP address is assigned dynamically to my interface, can I use Snort with it?�65536�0
-My network spans multiple subnets. How do I define HOME\_NET?�65536�0
-My snort crashes, how do I restart it?�65536�0
-On HPUX I get device lan0 open: recv\_ack: promisc\_phys: Invalid argument�65536�0
-Portscans are not being logged to my database �65536�0
+My /var/log/snort directory gets very large...�65536�Problems�0
+My BASE db connection times-out when performing long operations (e.g. deleting a large number of alerts).�65536�Problems�0
+My IP address is assigned dynamically to my interface, can I use Snort with it?�65536�Configuring Snort�0
+My network spans multiple subnets. How do I define HOME\_NET?�65536�Configuring Snort�0
+My snort crashes, how do I restart it?�65536�Problems�0
+On HPUX I get device lan0 open: recv\_ack: promisc\_phys: Invalid argument�65536�Problems�0
+Portscans are not being logged to my database�65536�Problems�0
Problems�64�0
Rules and Alerts�64�0
-SMB alerts aren't working, what's wrong? �65536�0
-Snort complains about the ``react'' keyword...�65536�0
-Snort fails to respond to a kill signal on Linux. Why?�65536�0
-Snort is behind a firewall (ipf/pf/ipchains/ipfilter) and awfully quiet...�65536�0
-Snort is dying with a `can not create file' error and I have plenty of diskspace. What's wrong?�65536�0
-Snort is not logging to my database�65536�0
-Snort is not logging to syslog�65536�0
-Snort says BACKDOOR SIGNATURE... does my machine have a Trojan? �65536�0
-Snort says ``Garbage Packet with Null Pointer discarded!'' Huh?�65536�0
-Snort says ``Ran Out Of Space.'' Huh?�65536�0
-Snort says ``Rule IP addr (``1.1.1.1'') didn't x-late, WTF?''�65536�0
-Trying to install snort it says: ``bad interpreter: No such file or�65536�0
-What about `SMB Name Wildcard' alerts? �65536�0
-What about ``CGI Null Byte attacks?'' �65536�0
-What about all these false alarms? �65536�0
-What are CIDR netmasks? �65536�0
-What are HOME\_NET and EXTERNAL\_NET?�65536�0
-What are all these ICMP files in subdirectories under /var/log/snort? �65536�0
-What are all these ``ICMP destination unreachable'' alerts? �65536�0
-What are some resources that I can use to understand more about source�65536�0
-What are these IDS codes in the alert names? �65536�0
-What do the numbers (ie: [116:56:1]) in front of a Snort alert mean?�65536�0
-What is the best way to use Snort to block attack traffic?�65536�0
-What is the difference between ``Alerting'' and ``Logging''?�65536�0
-What is the use of the ``-r'' switch to read tcpdump files? �65536�0
-What the heck is a SYNFIN scan?�65536�0
-What the heck is a SYNFIN scan? �65536�0
-What the heck is a ``Stealth scan''?�65536�0
-What version of Winpcap do I need?\label{winpcap�65536�0
-What's this about a Snort drinking game?�65536�0
-Where are my log files located? What are they named?�65536�0
-Where can I get more reading and courses about IDS?\label{courses�65536�0
-Where do I find binary packages for BlueHat BSD-Linux-RT?�65536�0
-Where do I get more help on Snort?�65536�0
-Where do I get the latest version of Winpcap?�65536�0
-Where do I get the latest version of libpcap? �65536�0
-Where do the distance and within keywords work from to modify content�65536�0
-Where does one obtain new/modifed rules? How do you merge them in?�65536�0
-Where's a good place to physically put a Snort sensor?�65536�0
-Which takes precedence, commandline or rule file ?�65536�0
-Why am I seeing so many ``SMTP RCPT TO overflow'' alerts ?�65536�0
-Why are my unified alert times off by +/- N hours?�65536�0
-Why are there no subdirectories under /var/log/snort for IP addresses?�65536�0
-Why can't snort see one of the 10Mbps or 100Mbps traffic on my autoswitch hub?�65536�0
-Why do certain alerts seem to have `unknown' IPs in BASE? �65536�0
-Why do many Snort rules have the flags P (TCP PuSH) and A (TCP ACK) set? �65536�0
-Why does Snort complain about /var/log/snort?�65536�0
-Why does building Snort complain about missing references? �65536�0
-Why does building snort fail with errors about yylex and lex\_init? �65536�0
-Why does chrooted Snort die when I send it a SIGHUP? \label{chroot�65536�0
-Why does snort report ``Packet loss statistics are unavailable under Linux?''�65536�0
-Why does the `error deleting alert' message occur when attempting to delete an alert with BASE? �65536�0
-Why does the portscan plugin log ``stealth'' packets even though the host is in the portscan-ignorehosts list? �65536�0
-Why does the program generate alerts on packets that have pass rules? �65536�0
-barnyard�2048�0
+SMB alerts aren't working, what's wrong?�65536�Problems�0
+Snort complains about the ``react'' keyword...�65536�Getting Fancy�0
+Snort fails to respond to a kill signal on Linux. Why?�65536�Problems�0
+Snort is behind a firewall (ipf/pf/ipchains/ipfilter) and awfully quiet...�65536�Rules and Alerts�0
+Snort is dying with a `can not create file' error and I have plenty of diskspace. What's wrong?�65536�Problems�0
+Snort is not logging to my database�65536�Problems�0
+Snort is not logging to syslog�65536�Problems�0
+Snort says BACKDOOR SIGNATURE... does my machine have a Trojan?�65536�Rules and Alerts�0
+Snort says ``Garbage Packet with Null Pointer discarded!'' Huh?�65536�Problems�0
+Snort says ``Ran Out Of Space.'' Huh?�65536�Problems�0
+Snort says ``Rule IP addr (``1.1.1.1'') didn't x-late, WTF?''�65536�Rules and Alerts�0
+Trying to install snort it says: ``bad interpreter: No such file or directory''�65536�Problems�0
+What about `SMB Name Wildcard' alerts?�65536�Rules and Alerts�0
+What about ``CGI Null Byte attacks?''�65536�Rules and Alerts�0
+What about all these false alarms?�65536�Rules and Alerts�0
+What are CIDR netmasks?�65536�Getting Started�0
+What are HOME\_NET and EXTERNAL\_NET?�65536�Configuring Snort�0
+What are all these ICMP files in subdirectories under /var/log/snort?�65536�Rules and Alerts�0
+What are all these ``ICMP destination unreachable'' alerts?�65536�Rules and Alerts�0
+What are some resources that I can use to understand more about source addresses logged and where they are coming from?�65536�Getting Fancy�0
+What are these IDS codes in the alert names?�65536�Rules and Alerts�0
+What do the numbers (ie: [116:56:1]) in front of a Snort alert mean?�65536�Rules and Alerts�0
+What is the best way to use Snort to block attack traffic?�65536�Getting Fancy�0
+What is the difference between ``Alerting'' and ``Logging''?�65536�Rules and Alerts�0
+What is the use of the ``-r'' switch to read tcpdump files?�65536�Getting Started�0
+What the heck is a SYNFIN scan?�65536�Configuring Snort�0
+What the heck is a SYNFIN scan?�65536�Rules and Alerts�0
+What the heck is a ``Stealth scan''?�65536�Configuring Snort�0
+What version of Winpcap do I need?\label{winpcap}�65536�Getting Started�0
+What's this about a Snort drinking game?�65536�Miscellaneous�0
+Where are my log files located? What are they named?�65536�Getting Started�0
+Where can I get more reading and courses about IDS?\label{courses}�65536�Background�0
+Where do I find binary packages for BlueHat BSD-Linux-RT?�65536�Getting Started�0
+Where do I get more help on Snort?�65536�Background�0
+Where do I get the latest version of Winpcap?�65536�Getting Started�0
+Where do I get the latest version of libpcap?�65536�Getting Started�0
+Where do the distance and within keywords work from to modify content searches in rules?�65536�Rules and Alerts�0
+Where does one obtain new/modifed rules? How do you merge them in?�65536�Configuring Snort�0
+Where's a good place to physically put a Snort sensor?�65536�Getting Started�0
+Which takes precedence, commandline or rule file ?�65536�Configuring Snort�0
+Why am I seeing so many ``SMTP RCPT TO overflow'' alerts ?�65536�Problems�0
+Why are my unified alert times off by +/- N hours?�65536�Problems�0
+Why are there no subdirectories under /var/log/snort for IP addresses?�65536�Configuring Snort�0
+Why can't snort see one of the 10Mbps or 100Mbps traffic on my autoswitch hub?�65536�Problems�0
+Why do certain alerts seem to have `unknown' IPs in BASE?�65536�Rules and Alerts�0
+Why do many Snort rules have the flags P (TCP PuSH) and A (TCP ACK) set?�65536�Rules and Alerts�0
+Why does Snort complain about /var/log/snort?�65536�Getting Started�0
+Why does building Snort complain about missing references?�65536�Getting Started�0
+Why does building snort fail with errors about yylex and lex\_init?�65536�Getting Started�0
+Why does chrooted Snort die when I send it a SIGHUP? \label{chroot}�65536�Problems�0
+Why does snort report ``Packet loss statistics are unavailable under Linux?''�65536�Problems�0
+Why does the `error deleting alert' message occur when attempting to delete an alert with BASE?�65536�Problems�0
+Why does the portscan plugin log ``stealth'' packets even though the host is in the portscan-ignorehosts list?�65536�Configuring Snort�0
+Why does the program generate alerts on packets that have pass rules?�65536�Rules and Alerts�0
+\myquote�16�0
+\myref�16�0
center�1�0
-chroot�2048�0
-courses�2048�0
document�1�0
enumerate�1�0
itemize�1�0
latexonly�1�0
-myquote�16�0
-myref�16�0
-quote�1�0
-spoolers�2048�0
stealth�2048�0
stream4�2048�0
tabular�1�0
verbatim�1�0
-winpcap�2048�0
Modified: tests/ctags/bug2886870.tex.tags
19 lines changed, 10 insertions(+), 9 deletions(-)
===================================================================
@@ -1,16 +1,19 @@
# format=tagmanager
-Common Greek letters�65536�0
+Common Greek letters�65536�Special Symbols�0
Equations�64�0
Figures�64�0
Introduction�64�0
Lists�64�0
Literal text�64�0
Special Symbols�64�0
-Special symbols�65536�0
+Special symbols�65536�Special Symbols�0
Tables�64�0
-Test for ctags�16384�0
-\color{red�64�0
-\label{morefig�64�0
+Test for ctags�16384�Special Symbols""Common Greek letters�0
+\color{red}Use of Color�64�0
+\label{morefig}Subfigures�64�0
+\lb�16�0
+\rb�16�0
+\rv�16�0
align�1�0
cases�1�0
center�1�0
@@ -26,14 +29,12 @@ fig:qm/complexfunctions
fig:typical�2048�0
figure�1�0
itemize�1�0
-lb�16�0
-morefig�2048�0
+latex�8�0
pmatrix�1�0
-rb�16�0
-rv�16�0
subequations�1�0
tab:5/tc�2048�0
table�1�0
tabular�1�0
thebibliography�1�0
verbatim�1�0
+website�8�0
Modified: tests/ctags/intro.tex.tags
18 lines changed, 11 insertions(+), 7 deletions(-)
===================================================================
@@ -1,10 +1,14 @@
# format=tagmanager
-Introduction�64�0
+Introduction�64�chapter text�0
+Part1�2�0
+Part2�2�0
chapter text�256�0
-chapter2�256�0
-section1 text�64�0
-section4 text�64�0
-subsection2�65536�0
-subsubsection3 with extra text�16384�0
-subsubsection6 with extra text�16384�0
+chapter2�256�Part2�0
+section1 text�64�chapter text�0
+short section4�64�Part1�0
+shorter intro2�64�Part2�0
+subsec5 text�65536�Part2""shorter intro2�0
+subsection2�65536�Part1�0
+subsubsection3 with extra text�16384�Part1""subsection2�0
+subsubsection6 with extra text�16384�Part2""shorter intro2""subsec5 text�0
verbatim�1�0
Modified: tests/ctags/intro_orig.tex
15 lines changed, 15 insertions(+), 0 deletions(-)
===================================================================
@@ -20,6 +20,21 @@
\setlength{\marginparpush}{1.0cm}
\setlength{\textwidth}{150mm}
+\newenvironment{boxed}
+ {\begin{center}
+ \begin{tabular}{|p{0.9\textwidth}|}
+ \hline\\
+ }
+ {
+ \\\\\hline
+ \end{tabular}
+ \end{center}
+ }
+
+\DeclareMathOperator{\End}{End}
+
+\newtheorem{theorem1}{Theorem}
+
\begin{comment}
\pagestyle{empty} % use if page numbers not wanted
\end{comment}
Modified: tests/ctags/intro_orig.tex.tags
20 lines changed, 12 insertions(+), 8 deletions(-)
===================================================================
@@ -1,16 +1,21 @@
# format=tagmanager
-Common Greek letters�65536�0
+Common Greek letters�65536�Special Symbols�0
Equations�64�0
Figures�64�0
Introduction�64�0
Lists�64�0
Literal text�64�0
Special Symbols�64�0
-Special symbols�65536�0
+Special symbols�65536�Special Symbols�0
Tables�64�0
-\color{red�64�0
-\label{morefig�64�0
+\End�16�0
+\color{red}Use of Color�64�0
+\label{morefig}Subfigures�64�0
+\lb�16�0
+\rb�16�0
+\rv�16�0
align�1�0
+boxed�1�0
cases�1�0
center�1�0
comment�1�0
@@ -25,14 +30,13 @@ fig:qm/complexfunctions
fig:typical�2048�0
figure�1�0
itemize�1�0
-lb�16�0
-morefig�2048�0
+latex�8�0
pmatrix�1�0
-rb�16�0
-rv�16�0
subequations�1�0
tab:5/tc�2048�0
table�1�0
tabular�1�0
thebibliography�1�0
+theorem1�1�0
verbatim�1�0
+website�8�0
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
Branch: refs/heads/master
Author: Jiří Techet <techet(a)gmail.com>
Committer: Jiří Techet <techet(a)gmail.com>
Date: Thu, 12 May 2022 23:04:38 UTC
Commit: 38c3656d1c25c9ab79ead94160641c3e95075804
https://github.com/geany/geany/commit/38c3656d1c25c9ab79ead94160641c3e95075…
Log Message:
-----------
Update to the upstream latex parser
The new parser reports scope so update the corresponding functions.
In addition this patch adds new root "Part" for reporting parts and
adds a separate "Bibitem" root (bibitem and label items used to be
reported together which I think is a bit confusing).
Modified Paths:
--------------
ctags/Makefile.am
ctags/parsers/geany_tex.c
ctags/parsers/tex.c
ctags/parsers/tex.h
meson.build
src/tagmanager/tm_parser.c
tests/ctags/3526726.tex.tags
tests/ctags/bug2886870.tex.tags
tests/ctags/intro.tex.tags
tests/ctags/intro_orig.tex
tests/ctags/intro_orig.tex.tags
Modified: ctags/Makefile.am
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -93,7 +93,8 @@ parsers = \
parsers/tcl.c \
parsers/tcl.h \
parsers/tcloo.c \
- parsers/geany_tex.c \
+ parsers/tex.c \
+ parsers/tex.h \
parsers/txt2tags.c \
parsers/verilog.c \
parsers/vhdl.c
Modified: ctags/parsers/geany_tex.c
242 lines changed, 0 insertions(+), 242 deletions(-)
===================================================================
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 2000-2001, Jérôme Plût
- * Copyright (c) 2006, Enrico Tröger
- *
- * This source code is released for free distribution under the terms of the
- * GNU General Public License.
- *
- * This module contains functions for generating tags for source files
- * for the TeX formatting system.
- */
-
-/*
-* INCLUDE FILES
-*/
-#include "general.h" /* must always come first */
-
-#include <ctype.h>
-#include <string.h>
-
-#include "parse.h"
-#include "read.h"
-#include "vstring.h"
-#include "routines.h"
-
-/*
-* DATA DEFINITIONS
-*/
-typedef enum {
- K_COMMAND,
- K_ENVIRONMENT,
- K_SECTION,
- K_SUBSECTION,
- K_SUBSUBSECTION,
- K_CHAPTER,
- K_LABEL
-} TeXKind;
-
-static kindDefinition TeXKinds[] = {
- { true, 'f', "function", "command definitions" },
- { true, 'c', "class", "environment definitions" },
- { true, 'm', "member", "labels, sections and bibliography" },
- { true, 'd', "macro", "subsections" },
- { true, 'v', "variable", "subsubsections" },
- { true, 'n', "namespace", "chapters"},
- { true, 's', "struct", "labels and bibliography" }
-};
-
-#define TEX_BRACES (1<<0)
-#define TEX_BSLASH (1<<1)
-#define TEX_LABEL (1<<2)
-
-/*
-* FUNCTION DEFINITIONS
-*/
-
-static int getWord(const char * ref, const char **ptr)
-{
- const char *p = *ptr;
-
- while ((*ref != '\0') && (*p != '\0') && (*ref == *p))
- ref++, p++;
-
-
- if (*ref)
- return false;
-
- if (*p == '*') /* to allow something like \section*{foobar} */
- p++;
-
- *ptr = p;
- return true;
-}
-
-static void createTag(int flags, TeXKind kind, const char * l)
-{
- vString *name = vStringNew ();
-
- while ((*l == ' '))
- l++;
- if (flags & (TEX_BRACES | TEX_LABEL))
- {
- if (*l == '[')
- {
- while (*l != ']')
- {
- if (*l == '\0')
- goto no_tag;
- l++;
- }
- l++; /* skip the closing square bracket */
- }
- if (*l != '{')
- goto no_tag;
- l++;
- }
- if (flags & TEX_BSLASH)
- {
- if ((*(l++)) != '\\')
- goto no_tag;
- }
- if (flags & TEX_LABEL)
- {
- do
- {
- vStringPut(name, (int) *l);
- ++l;
- } while ((*l != '\0') && (*l != '}'));
- if (name->buffer[0] != '}')
- makeSimpleTag(name, kind);
- }
- else if (isalpha((int) *l) || *l == '@')
- {
- do
- {
- vStringPut (name, (int) *l);
- ++l;
- } while (isalpha((int) *l) || *l == '@');
- makeSimpleTag(name, kind);
- }
- else
- {
- vStringPut(name, (int) *l);
- makeSimpleTag(name, kind);
- }
-
-no_tag:
- vStringDelete(name);
-}
-
-static void findTeXTags(void)
-{
- const char *line;
-
- while ((line = (const char*)readLineFromInputFile()) != NULL)
- {
- const char *cp = line;
- /*int escaped = 0;*/
-
- for (; *cp != '\0'; cp++)
- {
- if (*cp == '%')
- break;
- if (*cp == '\\')
- {
- cp++;
-
- /* \newcommand{\command} */
- if (getWord("newcommand", &cp)
- || getWord("providecommand", &cp)
- || getWord("renewcommand", &cp)
- )
- {
- createTag (TEX_BRACES|TEX_BSLASH, K_COMMAND, cp);
- continue;
- }
-
- /* \DeclareMathOperator{\command} */
- else if (getWord("DeclareMathOperator", &cp))
- {
- if (*cp == '*')
- cp++;
- createTag(TEX_BRACES|TEX_BSLASH, K_COMMAND, cp);
- continue;
- }
-
- /* \def\command */
- else if (getWord("def", &cp))
- {
- createTag(TEX_BSLASH, K_COMMAND, cp);
- continue;
- }
-
- /* \newenvironment{name} */
- else if ( getWord("newenvironment", &cp)
- || getWord("newtheorem", &cp)
- || getWord("begin", &cp)
- )
- {
- createTag(TEX_BRACES, K_ENVIRONMENT, cp);
- continue;
- }
-
- /* \bibitem[label]{key} */
- else if (getWord("bibitem", &cp))
- {
- while (*cp == ' ')
- cp++;
- if (*(cp++) != '[')
- break;
- while ((*cp != '\0') && (*cp != ']'))
- cp++;
- if (*(cp++) != ']')
- break;
- createTag(TEX_LABEL, K_LABEL, cp);
- continue;
- }
-
- /* \label{key} */
- else if (getWord("label", &cp))
- {
- createTag(TEX_LABEL, K_LABEL, cp);
- continue;
- }
- /* \section{key} */
- else if (getWord("section", &cp))
- {
- createTag(TEX_LABEL, K_SECTION, cp);
- continue;
- }
- /* \subsection{key} */
- else if (getWord("subsection", &cp))
- {
- createTag(TEX_LABEL, K_SUBSECTION, cp);
- continue;
- }
- /* \subsubsection{key} */
- else if (getWord("subsubsection", &cp))
- {
- createTag(TEX_LABEL, K_SUBSUBSECTION, cp);
- continue;
- }
- /* \chapter{key} */
- else if (getWord("chapter", &cp))
- {
- createTag(TEX_LABEL, K_CHAPTER, cp);
- continue;
- }
- }
- }
- }
-}
-
-extern parserDefinition* TexParser (void)
-{
- static const char *const extensions [] = { "tex", "sty", "idx", NULL };
- parserDefinition * def = parserNew ("LaTeX");
- def->kindTable = TeXKinds;
- def->kindCount = ARRAY_SIZE (TeXKinds);
- def->extensions = extensions;
- def->parser = findTeXTags;
- return def;
-}
Modified: ctags/parsers/tex.c
1253 lines changed, 1253 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,1253 @@
+/*
+ * Copyright (c) 2008, David Fishburn
+ * Copyright (c) 2012, Jan Larres
+ *
+ * This source code is released for free distribution under the terms of the
+ * GNU General Public License version 2 or (at your option) any later version.
+ *
+ * This module contains functions for generating tags for TeX language files.
+ *
+ * Tex language reference:
+ * http://en.wikibooks.org/wiki/TeX#The_Structure_of_TeX
+ */
+
+/*
+ * INCLUDE FILES
+ */
+#include "general.h" /* must always come first */
+#include <ctype.h> /* to define isalpha () */
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+#include <string.h>
+
+#include "debug.h"
+#include "entry.h"
+#include "keyword.h"
+#include "parse.h"
+#include "read.h"
+#include "routines.h"
+#include "vstring.h"
+
+#include "tex.h"
+
+/*
+ * MACROS
+ */
+#define isType(token,t) (bool) ((token)->type == (t))
+#define isKeyword(token,k) (bool) ((token)->keyword == (k))
+#define isIdentChar(c) \
+ (isalpha (c) || isdigit (c) || (c) >= 0x80 || (c) == '$' || \
+ (c) == '_' || (c) == '#' || (c) == '-' || (c) == '.' || (c) == ':')
+
+/*
+ * DATA DECLARATIONS
+ */
+
+/*
+ * Used to specify type of keyword.
+ */
+enum eKeywordId {
+ KEYWORD_part,
+ KEYWORD_chapter,
+ KEYWORD_section,
+ KEYWORD_subsection,
+ KEYWORD_subsubsection,
+ KEYWORD_paragraph,
+ KEYWORD_subparagraph,
+ KEYWORD_label,
+ KEYWORD_include,
+ KEYWORD_input,
+ KEYWORD_begin,
+ KEYWORD_end,
+ KEYWORD_bibitem,
+ KEYWORD_bibliography,
+ KEYWORD_newcommand,
+ KEYWORD_renewcommand,
+ KEYWORD_providecommand,
+ KEYWORD_def,
+ KEYWORD_declaremathoperator,
+ KEYWORD_newenvironment,
+ KEYWORD_renewenvironment,
+ KEYWORD_newtheorem,
+ KEYWORD_newcounter,
+};
+typedef int keywordId; /* to allow KEYWORD_NONE */
+
+enum eTokenType {
+ /* 0..255 are the byte's value. Some are named for convenience */
+ TOKEN_OPEN_PAREN = '(',
+ TOKEN_CLOSE_PAREN = ')',
+ TOKEN_OPEN_CURLY = '{',
+ TOKEN_CLOSE_CURLY = '}',
+ TOKEN_OPEN_SQUARE = '[',
+ TOKEN_CLOSE_SQUARE = ']',
+ TOKEN_STAR = '*',
+ /* above is special types */
+ TOKEN_UNDEFINED = 256,
+ TOKEN_KEYWORD,
+ TOKEN_IDENTIFIER,
+ TOKEN_STRING,
+};
+typedef int tokenType;
+
+typedef struct sTokenInfo {
+ tokenType type;
+ keywordId keyword;
+ vString * string;
+ vString * scope;
+ unsigned long lineNumber;
+ MIOPos filePosition;
+} tokenInfo;
+
+/*
+ * DATA DEFINITIONS
+ */
+
+static langType Lang_tex;
+
+static vString *lastPart;
+static vString *lastChapter;
+static vString *lastSection;
+static vString *lastSubS;
+static vString *lastSubSubS;
+
+typedef enum {
+ TEXTAG_PART,
+ TEXTAG_CHAPTER,
+ TEXTAG_SECTION,
+ TEXTAG_SUBSECTION,
+ TEXTAG_SUBSUBSECTION,
+ TEXTAG_PARAGRAPH,
+ TEXTAG_SUBPARAGRAPH,
+ TEXTAG_LABEL,
+ TEXTAG_XINPUT,
+ TEXTAG_BIBITEM,
+ TEXTAG_COMMAND,
+ TEXTAG_OPERATOR,
+ TEXTAG_ENVIRONMENT,
+ TEXTAG_THEOREM,
+ TEXTAG_COUNTER,
+ TEXTAG_COUNT
+} texKind;
+
+typedef enum {
+ TEX_XINPUT_INCLUDED,
+ TEX_XINPUT_INPUT,
+ TEX_XINPUT_BIBLIOGRAPHY,
+} texInputRole;
+
+typedef enum {
+ TEX_ENVIRONMENT_USED,
+} texEnvironmentRole;
+
+static roleDefinition TexInputRoles [] = {
+ { true, "included",
+ "external input file specified with \\include" },
+ { true, "input",
+ "external input file specified with \\input" },
+ { true, "bibliography",
+ "bibliography (.bib) file" },
+};
+
+static roleDefinition TexEnvironmentRoles [] = {
+ { false, "used", "environment usage introduced by \\begin{MyEnv}" },
+};
+
+static kindDefinition TexKinds [] = {
+ { true, 'p', "part", "parts" },
+ { true, 'c', "chapter", "chapters" },
+ { true, 's', "section", "sections" },
+ { true, 'u', "subsection", "subsections" },
+ { true, 'b', "subsubsection", "subsubsections" },
+ { true, 'P', "paragraph", "paragraphs" },
+ { true, 'G', "subparagraph", "subparagraphs" },
+ { true, 'l', "label", "labels" },
+ { true, 'i', "xinput", "external input files",
+ .referenceOnly = true, ATTACH_ROLES(TexInputRoles) },
+ { true, 'B', "bibitem", "bibliography items" },
+ { true, 'C', "command", "command created with \\newcommand" },
+ { true, 'o', "operator", "math operator created with \\DeclareMathOperator" },
+ { true, 'e', "environment", "environment created with \\newenvironment",
+ .referenceOnly = false, ATTACH_ROLES(TexEnvironmentRoles) },
+ { true, 't', "theorem", "theorem created with \\newtheorem" },
+ { true, 'N', "counter", "counter created with \\newcounter" },
+};
+
+static const keywordTable TexKeywordTable [] = {
+ /* keyword keyword ID */
+ { "part", KEYWORD_part },
+ { "chapter", KEYWORD_chapter },
+ { "section", KEYWORD_section },
+ { "subsection", KEYWORD_subsection },
+ { "subsubsection", KEYWORD_subsubsection },
+ { "paragraph", KEYWORD_paragraph },
+ { "subparagraph", KEYWORD_subparagraph },
+ { "label", KEYWORD_label },
+ { "include", KEYWORD_include },
+ { "input", KEYWORD_input },
+ { "begin", KEYWORD_begin },
+ { "end", KEYWORD_end },
+ { "bibitem", KEYWORD_bibitem },
+ { "bibliography", KEYWORD_bibliography },
+ { "newcommand", KEYWORD_newcommand },
+ { "renewcommand", KEYWORD_renewcommand },
+ { "providecommand", KEYWORD_providecommand },
+ { "def", KEYWORD_def },
+ { "DeclareMathOperator", KEYWORD_declaremathoperator },
+ { "newenvironment", KEYWORD_newenvironment },
+ { "renewenvironment", KEYWORD_renewenvironment},
+ { "newtheorem", KEYWORD_newtheorem },
+ { "newcounter", KEYWORD_newcounter },
+};
+
+/*
+ * FUNCTION DECLARATIONS
+ */
+
+static bool notifyReadingIdentifier (tokenInfo *id_token, bool *tokenUnprocessed);
+static bool notifyReadingBeginEnvironment (tokenInfo *token, vString *envName, bool *tokenUnprocessed);
+static bool notifyReadingEndEnvironment (vString *envName);
+
+
+/*
+ * FUNCTION DEFINITIONS
+ */
+
+static tokenInfo *newToken (void)
+{
+ tokenInfo *const token = xMalloc (1, tokenInfo);
+
+ token->type = TOKEN_UNDEFINED;
+ token->keyword = KEYWORD_NONE;
+ token->string = vStringNew ();
+ token->scope = vStringNew ();
+ token->lineNumber = getInputLineNumber ();
+ token->filePosition = getInputFilePosition ();
+
+ return token;
+}
+
+static void deleteToken (tokenInfo *const token)
+{
+ vStringDelete (token->string);
+ vStringDelete (token->scope);
+ eFree (token);
+}
+
+static int getScopeInfo(texKind kind, vString *const parentName)
+{
+ int parentKind = KIND_GHOST_INDEX;
+ int i;
+
+ /*
+ * Put labels separately instead of under their scope.
+ * Is this The Right Thing To Do?
+ */
+ if (kind >= TEXTAG_LABEL) {
+ goto out;
+ }
+
+ /*
+ * This abuses the enum internals somewhat, but it should be ok in this
+ * case.
+ */
+ /* TODO: This loop and conditions can be squashed. */
+ for (i = kind - 1; i >= TEXTAG_PART; --i) {
+ if (i == TEXTAG_SUBSECTION && vStringLength(lastSubS) > 0) {
+ parentKind = i;
+ break;
+ } else if (i == TEXTAG_SECTION && vStringLength(lastSection) > 0) {
+ parentKind = i;
+ break;
+ } else if (i == TEXTAG_CHAPTER && vStringLength(lastChapter) > 0) {
+ parentKind = i;
+ break;
+ } else if (i == TEXTAG_PART && vStringLength(lastPart) > 0) {
+ parentKind = i;
+ break;
+ }
+ }
+
+ /*
+ * Is '""' the best way to separate scopes? It has to be something that
+ * should ideally never occur in normal LaTeX text.
+ */
+ for (i = TEXTAG_PART; i < (int)kind; ++i) {
+ if (i == TEXTAG_PART && vStringLength(lastPart) > 0) {
+ vStringCat(parentName, lastPart);
+ } else if (i == TEXTAG_CHAPTER && vStringLength(lastChapter) > 0) {
+ if (vStringLength(parentName) > 0) {
+ vStringCatS(parentName, "\"\"");
+ }
+ vStringCat(parentName, lastChapter);
+ } else if (i == TEXTAG_SECTION && vStringLength(lastSection) > 0) {
+ if (vStringLength(parentName) > 0) {
+ vStringCatS(parentName, "\"\"");
+ }
+ vStringCat(parentName, lastSection);
+ } else if (i == TEXTAG_SUBSECTION && vStringLength(lastSubS) > 0) {
+ if (vStringLength(parentName) > 0) {
+ vStringCatS(parentName, "\"\"");
+ }
+ vStringCat(parentName, lastSubS);
+ }
+ }
+ out:
+ return parentKind;
+}
+
+/*
+ * Tag generation functions
+ */
+
+struct symbolData {
+ langType lang;
+ int kind;
+ int *corkQueue;
+};
+
+static bool findTheName (int corkIndex, tagEntryInfo *entry, void *data)
+{
+ struct symbolData *symbolData = data;
+
+ if (entry->langType == symbolData->lang && entry->kindIndex == symbolData->kind)
+ {
+ /* TODO: The case operation should be removed */
+ *symbolData->corkQueue = corkIndex;
+ return false;
+ }
+ return true;
+}
+
+static int makeTexTag (tokenInfo *const token, int kind,
+ int roleIndex, bool unique, int scopeIndex)
+{
+ int corkQueue = CORK_NIL;
+ const char *const name = vStringValue (token->string);
+
+ if (unique)
+ {
+ struct symbolData data = {
+ .lang = getInputLanguage(),
+ .kind = kind,
+ .corkQueue = &corkQueue,
+ };
+ /* TODO: The case operation should be removed */
+ if (foreachEntriesInScope (scopeIndex, name, findTheName, (void *)&data) == false)
+ return *data.corkQueue;
+ }
+
+ tagEntryInfo e;
+ initTagEntry (&e, name, kind);
+
+ e.lineNumber = token->lineNumber;
+ e.filePosition = token->filePosition;
+
+ vString *parentName = NULL;
+
+
+ if (unique)
+ e.extensionFields.scopeIndex = scopeIndex;
+
+ /* Filling e.extensionFields.scopeKindIndex and
+ * e.extensionFields.scopeName can be filled from "kind" parameter
+ * of this function only when Tex parser calls this function. The
+ * fields cannot be filled with a kind defined in a subparser.
+ * Subparsers may fill the scope after running strategy. So in the
+ * context of a subparser, filling the scope fields here is not
+ * needed.
+ */
+ if (Lang_tex == getInputLanguage ())
+ {
+ int parentKind = KIND_GHOST_INDEX;
+ parentName = vStringNew();
+ parentKind = getScopeInfo(kind, parentName);
+ if (parentKind != KIND_GHOST_INDEX) {
+ e.extensionFields.scopeKindIndex = parentKind;
+ e.extensionFields.scopeName = vStringValue(parentName);
+ }
+ }
+
+ assignRole (&e, roleIndex);
+
+ corkQueue = makeTagEntry (&e);
+ vStringDelete (parentName); /* NULL is o.k. */
+
+ if (unique && corkQueue != CORK_NIL)
+ registerEntry (corkQueue);
+
+ return corkQueue;
+}
+
+/*
+ * Parsing functions
+ */
+
+/*
+ * Read a C identifier beginning with "firstChar" and places it into
+ * "name".
+ */
+static void parseIdentifier (vString *const string, const int firstChar)
+{
+ int c = firstChar;
+ Assert (isIdentChar (c));
+ do
+ {
+ vStringPut (string, c);
+ c = getcFromInputFile ();
+ } while (c != EOF && isIdentChar (c));
+
+ if (c != EOF)
+ ungetcToInputFile (c); /* unget non-identifier character */
+}
+
+static bool readTokenFull (tokenInfo *const token, const bool includeWhitespaces)
+{
+ int c;
+ int whitespaces = -1;
+
+ token->type = TOKEN_UNDEFINED;
+ token->keyword = KEYWORD_NONE;
+ vStringClear (token->string);
+
+getNextChar:
+
+ do
+ {
+ c = getcFromInputFile ();
+ whitespaces++;
+ }
+ while (c == '\t' || c == ' ' || c == '\n');
+
+ token->lineNumber = getInputLineNumber ();
+ token->filePosition = getInputFilePosition ();
+
+ if (includeWhitespaces && whitespaces > 0 && c != '%' && c != EOF)
+ {
+ ungetcToInputFile (c);
+ c = ' ';
+ }
+
+ token->type = (unsigned char) c;
+ switch (c)
+ {
+ case EOF: return false;
+
+ case '\\':
+ /*
+ * All Tex tags start with a backslash.
+ * Check if the next character is an alpha character
+ * else it is not a potential tex tag.
+ */
+ c = getcFromInputFile ();
+ if (! isalpha (c))
+ ungetcToInputFile (c);
+ else
+ {
+ vStringPut (token->string, '\\');
+ parseIdentifier (token->string, c);
+ token->keyword = lookupKeyword (vStringValue (token->string) + 1, Lang_tex);
+ if (isKeyword (token, KEYWORD_NONE))
+ token->type = TOKEN_IDENTIFIER;
+ else
+ token->type = TOKEN_KEYWORD;
+ }
+ break;
+
+ case '%':
+ skipToCharacterInInputFile ('\n'); /* % are single line comments */
+ goto getNextChar;
+ break;
+
+ default:
+ if (isIdentChar (c))
+ {
+ parseIdentifier (token->string, c);
+ token->type = TOKEN_IDENTIFIER;
+ }
+ break;
+ }
+ return true;
+}
+
+static bool readToken (tokenInfo *const token)
+{
+ return readTokenFull (token, false);
+}
+
+static void copyToken (tokenInfo *const dest, tokenInfo *const src)
+{
+ dest->lineNumber = src->lineNumber;
+ dest->filePosition = src->filePosition;
+ dest->type = src->type;
+ dest->keyword = src->keyword;
+ vStringCopy (dest->string, src->string);
+ vStringCopy (dest->scope, src->scope);
+}
+
+static void updateScopeInfo (texKind kind, vString *fullname)
+{
+ switch (kind)
+ {
+ case TEXTAG_PART:
+ vStringCopy(lastPart, fullname);
+ vStringClear(lastChapter);
+ vStringClear(lastSection);
+ vStringClear(lastSubS);
+ vStringClear(lastSubSubS);
+ break;
+ case TEXTAG_CHAPTER:
+ vStringCopy(lastChapter, fullname);
+ vStringClear(lastSection);
+ vStringClear(lastSubS);
+ vStringClear(lastSubSubS);
+ break;
+ case TEXTAG_SECTION:
+ vStringCopy(lastSection, fullname);
+ vStringClear(lastSubS);
+ vStringClear(lastSubSubS);
+ break;
+ case TEXTAG_SUBSECTION:
+ vStringCopy(lastSubS, fullname);
+ vStringClear(lastSubSubS);
+ break;
+ case TEXTAG_SUBSUBSECTION:
+ vStringCopy(lastSubSubS, fullname);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Scanning functions
+ */
+
+/* STRATEGY array represents the sequence of * expected tokens. If an
+ * input token matches the current * expectation (the current strategy),
+ * parseWithStrategy() runs * the actions attached to the strategy.
+ *
+ * The actions are making a tag with the kind specified with kindIndex
+ * field of the current strategy and/or storing a name to NAME field
+ * of the current strategy.
+ *
+ * If the input token doesn't much the current strategy, above actions
+ * are not run. If TEX_NAME_FLAG_OPTIONAL is specified in FLAGS field
+ * of the current specified, parseWithStrategy() tries the next
+ * strategy of STRATEGY array without reading a new token. If
+ * TEX_NAME_FLAG_OPTIONAL is not in FLAGS field, parseWithStrategy()
+ * returns the control to its caller immediately.
+ *
+ * TOKENUNPROCESSED is used for both input and output. As input,
+ * TOKENUNPROCESSED tells whether parseWithStrategy() should read a
+ * new token before matching the STRATEGY array or not. If
+ * TOKENUNPROCESSED is true, parseWithStrategy function reads a new
+ * token before matching. As output, TOKENUNPROCESSED tells the
+ * caller of parseWithStrategy() that a new token is already stored to
+ * TOKEN but parseWithStrategy() has not processed yet.
+ */
+static bool parseWithStrategy (tokenInfo *token,
+ struct TexParseStrategy *strategy,
+ bool *tokenUnprocessed)
+{
+ bool next_token = !*tokenUnprocessed;
+ tokenInfo * name = NULL;
+ bool eof = false;
+ bool exclusive = false;
+
+ for (struct TexParseStrategy *s = strategy; s->type != 0; ++s)
+ s->corkIndex = CORK_NIL;
+
+ for (struct TexParseStrategy *s = strategy; !eof && s->type != 0; ++s)
+ {
+ if (s->kindIndex != KIND_GHOST_INDEX || s->name)
+ {
+ name = newToken ();
+ break;
+ }
+ }
+
+ for (struct TexParseStrategy *s = strategy; !eof && s->type != 0; ++s)
+ {
+ bool capture_name = s->kindIndex != KIND_GHOST_INDEX || s->name;
+
+ if (next_token)
+ {
+ if (!readToken (token))
+ {
+ eof = true;
+ break;
+ }
+ }
+
+ if ((s->type == '<' && isType (token, '<'))
+ || (s->type == '[' && isType (token, '[')))
+ {
+ tokenType terminator = (s->type == '<') ? '>' : ']';
+
+ next_token = true;
+
+
+ if (!readToken (token))
+ {
+ eof = true;
+ break;
+ }
+ if (capture_name)
+ {
+ copyToken (name, token);
+ vStringClear (name->string);
+ }
+
+ while (! isType (token, terminator))
+ {
+ if (capture_name && isType (token, TOKEN_IDENTIFIER))
+ {
+ if (vStringLength (name->string) > 0)
+ vStringPut (name->string, ' ');
+ vStringCat (name->string, token->string);
+ }
+
+ if (!readTokenFull (token,
+ s->flags & TEX_NAME_FLAG_INCLUDING_WHITESPACE))
+ {
+ eof = true;
+ break;
+ }
+ }
+ if (!exclusive && capture_name && vStringLength (name->string) > 0)
+ {
+ if (s->kindIndex != KIND_GHOST_INDEX)
+ s->corkIndex = makeTexTag (name, s->kindIndex, s->roleIndex,
+ s->unique, s->scopeIndex);
+
+ if (s->name)
+ vStringCopy(s->name, name->string);
+
+ if (s->flags & TEX_NAME_FLAG_EXCLUSIVE)
+ exclusive = true;
+ }
+ }
+ else if (s->type == '*' && isType (token, '*'))
+ next_token = true;
+ else if (((s->type == '{' || s->type == '\\') && isType (token, '{')) ||
+ (s->type == '\\' && isType (token, TOKEN_IDENTIFIER)))
+ {
+ int depth = 1;
+ bool missing_parens = isType (token, TOKEN_IDENTIFIER);
+
+ next_token = true;
+
+ if (!missing_parens && !readToken (token))
+ {
+ eof = true;
+ break;
+ }
+ if (capture_name)
+ {
+ copyToken (name, token);
+ vStringClear (name->string);
+ }
+ if (missing_parens)
+ {
+ vStringCat (name->string, token->string);
+ depth = 0;
+ }
+
+ /* Handle the case the code like \section{} */
+ if (isType (token, '}'))
+ break;
+ while (depth > 0)
+ {
+ if (capture_name)
+ {
+ if (isType (token, TOKEN_IDENTIFIER) || isType (token, TOKEN_KEYWORD))
+ vStringCat (name->string, token->string);
+ else
+ vStringPut (name->string, token->type);
+ }
+ if (!readTokenFull (token,
+ s->flags & TEX_NAME_FLAG_INCLUDING_WHITESPACE))
+ {
+ eof = true;
+ break;
+ }
+ else if (isType (token, TOKEN_OPEN_CURLY))
+ depth++;
+ else if (isType (token, TOKEN_CLOSE_CURLY))
+ depth--;
+ }
+ if (!exclusive && depth == 0 && capture_name && vStringLength (name->string) > 0)
+ {
+ vStringStripTrailing (name->string);
+
+ if (s->kindIndex != KIND_GHOST_INDEX)
+ s->corkIndex = makeTexTag (name, s->kindIndex, s->roleIndex,
+ s->unique, s->scopeIndex);
+
+ if (s->name)
+ vStringCopy(s->name, name->string);
+
+ if (s->flags & TEX_NAME_FLAG_EXCLUSIVE)
+ exclusive = true;
+
+ }
+ }
+ else if (s->flags & TEX_NAME_FLAG_OPTIONAL)
+ /* Apply next strategy to the same token */
+ next_token = false;
+ else
+ {
+ *tokenUnprocessed = true;
+ break;
+ }
+ }
+
+ /* The last token is optional and not present - let the caller know */
+ if (!next_token)
+ *tokenUnprocessed = true;
+
+ if (name)
+ deleteToken (name);
+
+ return eof;
+}
+
+static bool parseTagFull (tokenInfo *const token, texKind kind, int roleIndex, bool enterSquare, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ vString *taggedName = vStringNew();
+
+ /*
+ * Tex tags are of these formats:
+ * \keyword{any number of words}
+ * \keyword[short desc]{any number of words}
+ * \keyword*[short desc]{any number of words}
+ *
+ * When a keyword is found, loop through all words within
+ * the curly braces for the tag name.
+ *
+ * If the keyword is label like \label, words in the square
+ * brackets should be skipped. This can be controlled
+ * with `enterSquare' parameter; true is for tagging, and
+ * false is for skipping.
+ */
+
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ /* .kindIndex is initialized dynamically. */
+ },
+ {
+ .type = '*',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = TEX_NAME_FLAG_INCLUDING_WHITESPACE,
+ .kindIndex = kind,
+ .roleIndex = roleIndex,
+ .name = taggedName,
+ .unique = false,
+ },
+ {
+ .type = 0
+ }
+ };
+
+
+ if (enterSquare)
+ {
+ strategy [0].kindIndex = kind;
+ strategy [0].roleIndex = roleIndex;
+ strategy [0].flags |= TEX_NAME_FLAG_EXCLUSIVE;
+ strategy [0].name = taggedName;
+ strategy [0].unique = false;
+ }
+ else
+ {
+ strategy [0].kindIndex = KIND_GHOST_INDEX;
+ strategy [0].name = NULL;
+ }
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ {
+ eof = true;
+ goto out;
+ }
+
+ /*
+ * save the name of the last section definitions for scope-resolution
+ * later
+ */
+ if (vStringLength (taggedName) > 0)
+ updateScopeInfo (kind, taggedName);
+
+ out:
+ vStringDelete (taggedName);
+
+ return eof;
+}
+
+static bool parseTag (tokenInfo *const token, texKind kind,
+ bool enterSquare, bool *tokenUnprocessed)
+{
+ return parseTagFull (token, kind, ROLE_DEFINITION_INDEX,
+ enterSquare, tokenUnprocessed);
+}
+
+static bool parseEnv (tokenInfo *const token, bool begin, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ vString *envName = vStringNew ();
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '{',
+ .flags = TEX_NAME_FLAG_INCLUDING_WHITESPACE,
+ .kindIndex = begin ? TEXTAG_ENVIRONMENT : KIND_GHOST_INDEX,
+ .roleIndex = TEX_ENVIRONMENT_USED,
+ .name = envName,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ {
+ eof = true;
+ goto out;
+ }
+
+
+ if (vStringLength (envName) > 0)
+ {
+ if (begin)
+ eof = notifyReadingBeginEnvironment (token, envName, tokenUnprocessed);
+ else
+ eof = notifyReadingEndEnvironment (envName);
+ }
+
+ out:
+ vStringDelete (envName);
+
+ return eof;
+
+}
+
+static bool parseNewcommandFull (tokenInfo *const token, bool *tokenUnprocessed, texKind kind)
+{
+ bool eof = false;
+
+ /* \newcommand{cmd}[args][opt]{def} */
+ /* \newcommand\cmd[args][opt]{def} */
+ /* \def\cmd{replacement} */
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '\\',
+ .flags = 0,
+ .kindIndex = kind,
+ .roleIndex = ROLE_DEFINITION_INDEX,
+ .name = NULL,
+ .unique = false,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ eof = true;
+
+ return eof;
+}
+
+static bool parseNewcommand (tokenInfo *const token, bool *tokenUnprocessed)
+{
+ return parseNewcommandFull (token, tokenUnprocessed, TEXTAG_COMMAND);
+}
+
+static bool parseNewEnvironment (tokenInfo *const token, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ /* \newenvironment{nam}[args]{begdef}{enddef} */
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = TEXTAG_ENVIRONMENT,
+ .roleIndex = ROLE_DEFINITION_INDEX,
+ .name = NULL,
+ .unique = false,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ eof = true;
+
+ return eof;
+}
+
+static bool parseNewTheorem (tokenInfo *const token, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ /* \newtheorem{name}{title}
+ \newtheorem{name}{title}[numbered_within]
+ \newtheorem{name}[numbered_like]{title} */
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = TEXTAG_THEOREM,
+ .roleIndex = ROLE_DEFINITION_INDEX,
+ .name = NULL,
+ .unique = false,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ eof = true;
+
+ return eof;
+}
+
+static bool parseNewcounter (tokenInfo *const token, bool *tokenUnprocessed)
+{
+ bool eof = false;
+ /* \newcounter {counter}[parentCounter] */
+ struct TexParseStrategy strategy [] = {
+ {
+ .type = '{',
+ .flags = 0,
+ .kindIndex = TEXTAG_COUNTER,
+ .roleIndex = ROLE_DEFINITION_INDEX,
+ .name = NULL,
+ .unique = false,
+ },
+ {
+ .type = '[',
+ .flags = TEX_NAME_FLAG_OPTIONAL,
+ .kindIndex = KIND_GHOST_INDEX,
+ .name = NULL,
+ },
+ {
+ .type = 0
+ }
+ };
+
+ if (parseWithStrategy (token, strategy, tokenUnprocessed))
+ eof = true;
+
+ return eof;
+}
+
+static void parseTexFile (tokenInfo *const token)
+{
+ bool eof = false;
+ bool tokenUnprocessed = false;
+
+ do
+ {
+ if (!tokenUnprocessed)
+ {
+ if (!readToken (token))
+ break;
+ }
+ tokenUnprocessed = false;
+
+ if (isType (token, TOKEN_KEYWORD))
+ {
+ switch (token->keyword)
+ {
+ case KEYWORD_part:
+ eof = parseTag (token, TEXTAG_PART, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_chapter:
+ eof = parseTag (token, TEXTAG_CHAPTER, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_section:
+ eof = parseTag (token, TEXTAG_SECTION, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_subsection:
+ eof = parseTag (token, TEXTAG_SUBSECTION, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_subsubsection:
+ eof = parseTag (token, TEXTAG_SUBSUBSECTION, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_paragraph:
+ eof = parseTag (token, TEXTAG_PARAGRAPH, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_subparagraph:
+ eof = parseTag (token, TEXTAG_SUBPARAGRAPH, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_label:
+ eof = parseTag (token, TEXTAG_LABEL, false, &tokenUnprocessed);
+ break;
+ case KEYWORD_include:
+ eof = parseTagFull (token, TEXTAG_XINPUT, TEX_XINPUT_INCLUDED,
+ false, &tokenUnprocessed);
+ break;
+ case KEYWORD_input:
+ eof = parseTagFull (token, TEXTAG_XINPUT, TEX_XINPUT_INPUT,
+ false, &tokenUnprocessed);
+ break;
+ case KEYWORD_begin:
+ eof = parseEnv (token, true, &tokenUnprocessed);
+ break;
+ case KEYWORD_end:
+ eof = parseEnv (token, false, &tokenUnprocessed);
+ break;
+ case KEYWORD_bibitem:
+ eof = parseTag (token, TEXTAG_BIBITEM, false, &tokenUnprocessed);
+ break;
+ case KEYWORD_bibliography:
+ eof = parseTagFull (token, TEXTAG_XINPUT, TEX_XINPUT_BIBLIOGRAPHY,
+ false, &tokenUnprocessed);
+ break;
+ case KEYWORD_newcommand:
+ case KEYWORD_renewcommand:
+ case KEYWORD_providecommand:
+ case KEYWORD_def:
+ eof = parseNewcommand (token, &tokenUnprocessed);
+ break;
+ case KEYWORD_declaremathoperator:
+ eof = parseNewcommandFull (token, &tokenUnprocessed, TEXTAG_OPERATOR);
+ break;
+ case KEYWORD_newenvironment:
+ case KEYWORD_renewenvironment:
+ eof = parseNewEnvironment (token, &tokenUnprocessed);
+ break;
+ case KEYWORD_newtheorem:
+ eof = parseNewTheorem (token, &tokenUnprocessed);
+ break;
+ case KEYWORD_newcounter:
+ eof = parseNewcounter (token, &tokenUnprocessed);
+ break;
+ default:
+ break;
+ }
+ }
+ else if (isType (token, TOKEN_IDENTIFIER))
+ eof = notifyReadingIdentifier (token, &tokenUnprocessed);
+ if (eof)
+ break;
+ } while (true);
+}
+
+static void initialize (const langType language)
+{
+ Assert (ARRAY_SIZE (TexKinds) == TEXTAG_COUNT);
+ Lang_tex = language;
+
+ lastPart = vStringNew();
+ lastChapter = vStringNew();
+ lastSection = vStringNew();
+ lastSubS = vStringNew();
+ lastSubSubS = vStringNew();
+}
+
+static void finalize (const langType language CTAGS_ATTR_UNUSED,
+ bool initialized)
+{
+ if (initialized)
+ {
+ vStringDelete(lastPart);
+ lastPart = NULL;
+ vStringDelete(lastChapter);
+ lastChapter = NULL;
+ vStringDelete(lastSection);
+ lastSection = NULL;
+ vStringDelete(lastSubS);
+ lastSubS = NULL;
+ vStringDelete(lastSubSubS);
+ lastSubSubS = NULL;
+ }
+}
+
+static void findTexTags (void)
+{
+ tokenInfo *const token = newToken ();
+
+ vStringClear(lastPart);
+ vStringClear(lastChapter);
+ vStringClear(lastSection);
+ vStringClear(lastSubS);
+ vStringClear(lastSubSubS);
+
+ parseTexFile (token);
+
+ deleteToken (token);
+}
+
+static bool notifyReadingIdentifier (tokenInfo *id_token, bool *tokenUnprocessed)
+{
+ subparser *sub;
+ bool eof = false;
+
+ foreachSubparser (sub, false)
+ {
+ texSubparser *texsub = (texSubparser *)sub;
+
+ if (texsub->readIdentifierNotify)
+ {
+ struct TexParseStrategy *strategy;
+
+ enterSubparser(sub);
+
+ strategy = texsub->readIdentifierNotify (texsub, id_token->string);
+
+ if (strategy)
+ {
+ eof = parseWithStrategy (id_token, strategy, tokenUnprocessed);
+ if (texsub->reportStrategicParsing)
+ texsub->reportStrategicParsing (texsub, strategy);
+ }
+
+ leaveSubparser();
+
+ if (strategy)
+ break;
+ }
+ }
+
+ return eof;
+}
+
+static bool notifyReadingBeginEnvironment (tokenInfo *token,
+ vString *envName,
+ bool *tokenUnprocessed)
+{
+ subparser *sub;
+ bool eof = false;
+
+ foreachSubparser (sub, false)
+ {
+ texSubparser *texsub = (texSubparser *)sub;
+
+ if (texsub->readEnviromentBeginNotify)
+ {
+ struct TexParseStrategy *strategy;
+
+ enterSubparser (sub);
+ strategy = texsub->readEnviromentBeginNotify (texsub, envName);
+ if (strategy)
+ {
+ eof = parseWithStrategy (token, strategy, tokenUnprocessed);
+ if (texsub->reportStrategicParsing)
+ texsub->reportStrategicParsing (texsub, strategy);
+ }
+ leaveSubparser ();
+ if (strategy)
+ break;
+ }
+ }
+
+ return eof;
+}
+
+static bool notifyReadingEndEnvironment (vString *envName)
+{
+ subparser *sub;
+
+ foreachSubparser (sub, false)
+ {
+ texSubparser *texsub = (texSubparser *)sub;
+
+ if (texsub->readEnviromentEndNotify)
+ {
+ bool consuming;
+
+ enterSubparser (sub);
+ consuming = texsub->readEnviromentEndNotify (texsub, envName);
+ leaveSubparser ();
+ if (consuming)
+ break;
+ }
+ }
+
+ return false;
+}
+
+/* Create parser definition structure */
+extern parserDefinition* TexParser (void)
+{
+ static const char *const extensions [] = { "tex", NULL };
+ parserDefinition *const def = parserNew ("Tex");
+ def->extensions = extensions;
+ /*
+ * New definitions for parsing instead of regex
+ */
+ def->kindTable = TexKinds;
+ def->kindCount = ARRAY_SIZE (TexKinds);
+ def->parser = findTexTags;
+ def->initialize = initialize;
+ def->finalize = finalize;
+ def->keywordTable = TexKeywordTable;
+ def->keywordCount = ARRAY_SIZE (TexKeywordTable);
+ def->useCork = CORK_QUEUE | CORK_SYMTAB;
+ return def;
+}
Modified: ctags/parsers/tex.h
114 lines changed, 114 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2020, 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.
+*
+* Tex base parser interface exported to subparsers
+*/
+
+#ifndef CTAGS_PARSER_TEX_H
+#define CTAGS_PARSER_TEX_H
+
+/*
+* INCLUDE FILES
+*/
+
+#include "general.h" /* must always come first */
+
+#include "subparser.h"
+#include "vstring.h"
+
+
+/*
+* DATA DEFINITIONS
+*/
+
+/* Parsing strategy */
+
+enum TexNameFlag {
+ /* Allow that the type of input token doesn't match
+ * the type of strategy. In stread of aborting,
+ * apply the next strategy to the same token. */
+ TEX_NAME_FLAG_OPTIONAL = (1 << 0),
+
+ /* When reading tokens inside pair,
+ * whitespaces are considered as parts of a token or not. */
+ TEX_NAME_FLAG_INCLUDING_WHITESPACE = (1 << 1),
+
+ /* If a tag is created with this strategy, don't
+ * create a tag in its successor strategies. */
+ TEX_NAME_FLAG_EXCLUSIVE = (1 << 2),
+};
+
+struct TexParseStrategy {
+ /* Expected token type '<', '[', '*', '{', and '\\' are supported.
+ * 0 means the end of strategies. '\\' means {} pair may be omitted.
+ *
+ * A string between <>, [], or {} (pairs) can be tagged or store to
+ * a vString. See kindIndex and name field of this structure.
+ */
+ int type;
+
+ /* Bits combination of enum TexNameFlag */
+ unsigned int flags;
+
+ /* Kind and role for making a tag for the string surrounded by one of pairs.
+ * If you don't need to make a tag for the string,
+ * specify KIND_GHOST_INDEX. */
+ int kindIndex;
+ int roleIndex;
+
+ /* If a tag is made, Tex parser stores its cork index here. */
+ int corkIndex;
+
+ /* Store the string surrounded by one of paris.
+ * If you don't need to store the string, set NULL here. */
+ vString *name;
+
+ /* If true, make at most one tag for the name in the scope specified
+ * with scopeIndex. When making a tag, scopeIndex is set to
+ * extensionFields.scopeIndex only if unique is true.
+ * scopeIndex is never referred if unique if false. */
+ bool unique;
+ int scopeIndex;
+};
+
+typedef struct sTexSubparser texSubparser;
+struct sTexSubparser {
+ subparser subparser;
+
+ /* When Tex parser reads an \begin{foo}, it calls
+ * this method.
+ *
+ * A subparser having interests in successor tokens may return strategies.
+ * If it doesn't, just return NULL; Tex base parser may call the next subparser.
+ */
+ struct TexParseStrategy * (* readEnviromentBeginNotify) (texSubparser *s,
+ vString *env);
+ /* When Tex parser reads an \end{foo}, it calls
+ * this method.
+ *
+ * If this method returns true, Tex base parser may call the next subparser.
+ * If it returns false, Tex base parser stops calling the rest of subparsers.
+ */
+ bool (* readEnviromentEndNotify) (texSubparser *s, vString *env);
+
+ /* When Tex parser reads an \identifier, it calls
+ * this method.
+ *
+ * A subparser having interests in successor tokens may return strategies.
+ * If it has no interest, just return NULL; Tex base parser may call next subparser.
+ */
+ struct TexParseStrategy *(* readIdentifierNotify) (texSubparser *s,
+ vString *identifier);
+
+ /* After Tex parser runs the strategies returned from readIdentifierNotify
+ * method, Tex parser calls this method to notify the subparser the result
+ * of running the strategies; corkIndex and/or name fields of strategies
+ * may be filled. */
+ void (* reportStrategicParsing) (texSubparser *s,
+ const struct TexParseStrategy *strategy);
+};
+
+#endif /* CTAGS_PARSER_TEX_H */
Modified: meson.build
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -637,7 +637,6 @@ ctags = static_library('ctags',
'ctags/parsers/geany_lcpp.c',
'ctags/parsers/geany_lcpp.h',
'ctags/parsers/geany_matlab.c',
- 'ctags/parsers/geany_tex.c',
'ctags/parsers/go.c',
'ctags/parsers/haskell.c',
'ctags/parsers/haxe.c',
@@ -670,6 +669,8 @@ ctags = static_library('ctags',
'ctags/parsers/tcl.c',
'ctags/parsers/tcl.h',
'ctags/parsers/tcloo.c',
+ 'ctags/parsers/tex.c',
+ 'ctags/parsers/tex.h',
'ctags/parsers/txt2tags.c',
'ctags/parsers/verilog.c',
'ctags/parsers/vhdl.c',
Modified: src/tagmanager/tm_parser.c
29 lines changed, 21 insertions(+), 8 deletions(-)
===================================================================
@@ -204,22 +204,32 @@ static TMParserMapGroup group_PYTHON[] = {
};
static TMParserMapEntry map_LATEX[] = {
- {'f', tm_tag_function_t},
- {'c', tm_tag_class_t},
- {'m', tm_tag_member_t},
- {'d', tm_tag_macro_t},
- {'v', tm_tag_variable_t},
- {'n', tm_tag_namespace_t},
- {'s', tm_tag_struct_t},
+ {'p', tm_tag_enum_t}, // part
+ {'c', tm_tag_namespace_t}, // chapter
+ {'s', tm_tag_member_t}, // section
+ {'u', tm_tag_macro_t}, // subsection
+ {'b', tm_tag_variable_t}, // subsubsection
+ {'P', tm_tag_undef_t}, // paragraph
+ {'G', tm_tag_undef_t}, // subparagraph
+ {'l', tm_tag_struct_t}, // label
+ {'i', tm_tag_undef_t}, // xinput
+ {'B', tm_tag_field_t}, // bibitem
+ {'C', tm_tag_function_t}, // command
+ {'o', tm_tag_function_t}, // operator
+ {'e', tm_tag_class_t}, // environment
+ {'t', tm_tag_class_t}, // theorem
+ {'N', tm_tag_undef_t}, // counter
};
static TMParserMapGroup group_LATEX[] = {
{_("Command"), TM_ICON_NONE, tm_tag_function_t},
{_("Environment"), TM_ICON_NONE, tm_tag_class_t},
+ {_("Part"), TM_ICON_NONE, tm_tag_enum_t},
+ {_("Chapter"), TM_ICON_NONE, tm_tag_namespace_t},
{_("Section"), TM_ICON_NONE, tm_tag_member_t},
{_("Subsection"), TM_ICON_NONE, tm_tag_macro_t},
{_("Subsubsection"), TM_ICON_NONE, tm_tag_variable_t},
+ {_("Bibitem"), TM_ICON_NONE, tm_tag_field_t},
{_("Label"), TM_ICON_NONE, tm_tag_struct_t},
- {_("Chapter"), TM_ICON_NONE, tm_tag_namespace_t},
};
// no scope information
@@ -1472,6 +1482,7 @@ const gchar *tm_parser_scope_separator(TMParserType lang)
case TM_PARSER_ZEPHIR:
return "::";
+ case TM_PARSER_LATEX:
case TM_PARSER_MARKDOWN:
case TM_PARSER_TXT2TAGS:
return "\"\"";
@@ -1495,6 +1506,7 @@ const gchar *tm_parser_scope_separator_printable(TMParserType lang)
{
case TM_PARSER_ASCIIDOC:
case TM_PARSER_CONF:
+ case TM_PARSER_LATEX:
case TM_PARSER_MARKDOWN:
case TM_PARSER_REST:
case TM_PARSER_TXT2TAGS:
@@ -1523,6 +1535,7 @@ gboolean tm_parser_has_full_scope(TMParserType lang)
case TM_PARSER_JAVA:
case TM_PARSER_JAVASCRIPT:
case TM_PARSER_JSON:
+ case TM_PARSER_LATEX:
case TM_PARSER_LUA:
case TM_PARSER_MARKDOWN:
case TM_PARSER_PHP:
Modified: tests/ctags/3526726.tex.tags
266 lines changed, 130 insertions(+), 136 deletions(-)
===================================================================
@@ -1,155 +1,149 @@
# format=tagmanager
- I think I found a bug in Snort. Now what?�65536�0
- I've got RedHat and ....�65536�0
-A Rule with PCRE causes a failure to load snort.conf. Why?�65536�0
-After I add new rules or comment out rules how do I make Snort reload?�65536�0
-Are rule keywords ORed or ANDed together?�65536�0
-Are there other output systems for Snort besides ``Barnyard''?\label{spoolers�65536�0
-BASE appears to be broken in Lynx �65536�0
+A Rule with PCRE causes a failure to load snort.conf. Why?�65536�Problems�0
+After I add new rules or comment out rules how do I make Snort reload?�65536�Rules and Alerts�0
+Are rule keywords ORed or ANDed together?�65536�Rules and Alerts�0
+Are there other output systems for Snort besides ``Barnyard''?\label{spoolers}�65536�Getting Fancy�0
+BASE appears to be broken in Lynx�65536�Problems�0
Background�64�0
-Can Snort be evaded by the use of polymorphic mutators on shellcode?�65536�0
-Can Snort trigger a rule by MAC addresses?�65536�0
-Can priorities be assigned to alerts using BASE? �65536�0
+Can Snort be evaded by the use of polymorphic mutators on shellcode?�65536�Background�0
+Can Snort trigger a rule by MAC addresses?�65536�Rules and Alerts�0
+Can priorities be assigned to alerts using BASE?�65536�Rules and Alerts�0
Configuring Snort�64�0
Development�64�0
-Does Snort handle IP defragmentation?�65536�0
-Does Snort log the full packets when it generates alerts? �65536�0
-Does Snort perform TCP stream reassembly?�65536�0
-Does Snort perform stateful protocol analysis?�65536�0
-Does snort see packets filtered by IPTables/IPChains/IPF/PF?�65536�0
-Errors loading rules files�65536�0
+Does Snort handle IP defragmentation?�65536�Background�0
+Does Snort log the full packets when it generates alerts?�65536�Background�0
+Does Snort perform TCP stream reassembly?�65536�Background�0
+Does Snort perform stateful protocol analysis?�65536�Background�0
+Does snort see packets filtered by IPTables/IPChains/IPF/PF?�65536�Rules and Alerts�0
+Errors loading rules files�65536�Rules and Alerts�0
Getting Fancy�64�0
Getting Started�64�0
-How can I deactivate a rule?�65536�0
-How can I define an address to be anything except some hosts?�65536�0
-How can I examine logged packets in more detail?�65536�0
-How can I protect web servers running on ports other than 80?�65536�0
-How can I run Snort on multiple interfaces simultaneously?�65536�0
-How can I specify a list of ports in a rule?�65536�0
-How can I test Snort without having an Ethernet card or a connection to other computers? �65536�0
-How can I use Snort to log HTTP URLs or SMTP traffic?�65536�0
-How do I build this BASE thing?�65536�0
-How do I configure stream4?�65536�0
-How do I get Snort and ACID working?�65536�0
-How do I get Snort to e-mail me alerts?�65536�0
-How do I get Snort to log the packet payload as well as the header?�65536�0
-How do I ignore traffic coming from a particular host or hosts?�65536�0
-How do I log a specific type of traffic and send alerts to syslog?�65536�0
-How do I log to multiple databases or output plugins?�65536�0
-How do I process those Snort logs into reports?�65536�0
-How do I run Snort?�65536�0
-How do I set EXTERNAL\_NET?�65536�0
-How do I setup a receive-only ethernet cable?�65536�0
-How do I setup snort on a `stealth' interface? �65536�0
-How do I test Snort alerts and logging?�65536�0
-How do I turn off ``spp:possible EVASIVE RST detection'' alerts?�65536�0
-How do I understand this traffic and do IDS alert analysis?�65536�0
-How do I use a remote syslog machine?�65536�0
-How do you get Snort to ignore some traffic?�65536�0
-How do you pronounce the names of some of these guys who work on Snort?�65536�0
-How do you put Snort in debug mode? �65536�0
-How does rule ordering work?�65536�0
-How long can address lists, variables, or rules be?�65536�0
-How to start Snort as a win32 service? �65536�0
-I am getting `snort [pid] uses obsolete (PF\_INET, SOCK\_PACKET)' warnings. What's wrong?�65536�0
-I am getting too many ``IIS Unicode attack detected'' and/or ``CGI Null Byte attack detected'' false positives. How can I turn this detection off? �65536�0
-I am still getting bombarded with spp\_portscan messages even though the IP that I am getting the portscan from is in my \$DNS\_SERVERs var �65536�0
-I am using Snort on Windows and receive an ``OpenPcap() error upon startup: ERROR: OpenPcap() device open: Error opening adapter'' message. What's wrong? �65536�0
-I have one network card and two aliases, how can I force Snort to ``listen'' on both addresses?�65536�0
-I hear people talking about ``Barnyard''. What's that?\label{barnyard�65536�0
-I just downloaded a new ruleset and now Snort fails, complaining about the�65536�0
-I try to start Snort and it gives an error like ``ERROR: Unable to open�65536�0
-I want to build a Snort box. Will this $<$Insert list of hardware$>$ handle $<$this much$>$ traffic? �65536�0
-I'm getting large amounts of $<$some alerts type$>$. What should I do? Where can I go to find out more about it? �65536�0
-I'm getting lots of *ICMP Ping Speedera*, is this bad?�65536�0
-I'm not seeing any interfaces listed under Win32.�65536�0
-I'm on a switched network, can I still use Snort?�65536�0
+How can I deactivate a rule?�65536�Rules and Alerts�0
+How can I define an address to be anything except some hosts?�65536�Rules and Alerts�0
+How can I examine logged packets in more detail?�65536�Getting Fancy�0
+How can I protect web servers running on ports other than 80?�65536�Rules and Alerts�0
+How can I run Snort on multiple interfaces simultaneously?�65536�Configuring Snort�0
+How can I specify a list of ports in a rule?�65536�Rules and Alerts�0
+How can I test Snort without having an Ethernet card or a connection to other computers?�65536�Getting Fancy�0
+How can I use Snort to log HTTP URLs or SMTP traffic?�65536�Getting Fancy�0
+How do I build this BASE thing?�65536�Configuring Snort�0
+How do I configure stream4?�65536�Configuring Snort�0
+How do I get Snort and ACID working?�65536�Configuring Snort�0
+How do I get Snort to e-mail me alerts?�65536�Getting Fancy�0
+How do I get Snort to log the packet payload as well as the header?�65536�Configuring Snort�0
+How do I ignore traffic coming from a particular host or hosts?�65536�Configuring Snort�0
+How do I log a specific type of traffic and send alerts to syslog?�65536�Getting Fancy�0
+How do I log to multiple databases or output plugins?�65536�Getting Fancy�0
+How do I process those Snort logs into reports?�65536�Getting Fancy�0
+How do I run Snort?�65536�Getting Started�0
+How do I set EXTERNAL\_NET?�65536�Configuring Snort�0
+How do I setup a receive-only ethernet cable?�65536�Configuring Snort�0
+How do I setup snort on a `stealth' interface?�65536�Configuring Snort�0
+How do I test Snort alerts and logging?�65536�Rules and Alerts�0
+How do I turn off ``spp:possible EVASIVE RST detection'' alerts?�65536�Rules and Alerts�0
+How do I understand this traffic and do IDS alert analysis?�65536�Getting Fancy�0
+How do I use a remote syslog machine?�65536�Configuring Snort�0
+How do you get Snort to ignore some traffic?�65536�Configuring Snort�0
+How do you pronounce the names of some of these guys who work on Snort?�65536�Background�0
+How do you put Snort in debug mode?�65536�Development�0
+How does rule ordering work?�65536�Configuring Snort�0
+How long can address lists, variables, or rules be?�65536�Rules and Alerts�0
+How to start Snort as a win32 service?�65536�Getting Fancy�0
+I am getting `snort [pid] uses obsolete (PF\_INET, SOCK\_PACKET)' warnings. What's wrong?�65536�Problems�0
+I am getting too many ``IIS Unicode attack detected'' and/or ``CGI Null Byte attack detected'' false positives. How can I turn this detection off?�65536�Rules and Alerts�0
+I am still getting bombarded with spp\_portscan messages even though the IP that I am getting the portscan from is in my \$DNS\_SERVERs var�65536�Problems�0
+I am using Snort on Windows and receive an ``OpenPcap() error upon startup: ERROR: OpenPcap() device open: Error opening adapter'' message. What's wrong?�65536�Problems�0
+I have one network card and two aliases, how can I force Snort to ``listen'' on both addresses?�65536�Configuring Snort�0
+I hear people talking about ``Barnyard''. What's that?\label{barnyard}�65536�Getting Fancy�0
+I just downloaded a new ruleset and now Snort fails, complaining about the rules.�65536�Problems�0
+I think I found a bug in Snort. Now what?�65536�Problems�0
+I try to start Snort and it gives an error like ``ERROR: Unable to open rules file: /root/.snortrc or /root//root/.snortrc.'' What can I do to fix this?�65536�Problems�0
+I want to build a Snort box. Will this $<$Insert list of hardware$>$ handle $<$this much$>$ traffic?�65536�Getting Started�0
+I'm getting large amounts of $<$some alerts type$>$. What should I do? Where can I go to find out more about it?�65536�Rules and Alerts�0
+I'm getting lots of *ICMP Ping Speedera*, is this bad?�65536�Problems�0
+I'm not seeing any interfaces listed under Win32.�65536�Problems�0
+I'm on a switched network, can I still use Snort?�65536�Background�0
+I've got RedHat and ....�65536�Getting Started�0
IDSCenter�2048�0
-Is Fyodor Yarochkin the same Fyodor who wrote nmap?�65536�0
-Is Snort vulnerable to IDS noise generators like ``Stick'' and ``Snot''?�65536�0
-Is it possible to have Snort call an external program when an alert is raised?�65536�0
-Is it possible with snort to add a ipfilter/ipfw rule to a firewall? �65536�0
-Is there a private SID number range so my rules don't conflict?�65536�0
-It's not working on Win32, how can I tell if my problem is Snort or�65536�0
-Libpcap complains about permissions problems, what's going on?�65536�0
+Is Fyodor Yarochkin the same Fyodor who wrote nmap?�65536�Background�0
+Is Snort vulnerable to IDS noise generators like ``Stick'' and ``Snot''?�65536�Background�0
+Is it possible to have Snort call an external program when an alert is raised?�65536�Getting Fancy�0
+Is it possible with snort to add a ipfilter/ipfw rule to a firewall?�65536�Getting Fancy�0
+Is there a private SID number range so my rules don't conflict?�65536�Rules and Alerts�0
+It's not working on Win32, how can I tell if my problem is Snort or WinPcap?�65536�Problems�0
+Libpcap complains about permissions problems, what's going on?�65536�Getting Started�0
Miscellaneous�64�0
-My /var/log/snort directory gets very large...�65536�0
-My BASE db connection times-out when performing long operations (e.g.�65536�0
-My IP address is assigned dynamically to my interface, can I use Snort with it?�65536�0
-My network spans multiple subnets. How do I define HOME\_NET?�65536�0
-My snort crashes, how do I restart it?�65536�0
-On HPUX I get device lan0 open: recv\_ack: promisc\_phys: Invalid argument�65536�0
-Portscans are not being logged to my database �65536�0
+My /var/log/snort directory gets very large...�65536�Problems�0
+My BASE db connection times-out when performing long operations (e.g. deleting a large number of alerts).�65536�Problems�0
+My IP address is assigned dynamically to my interface, can I use Snort with it?�65536�Configuring Snort�0
+My network spans multiple subnets. How do I define HOME\_NET?�65536�Configuring Snort�0
+My snort crashes, how do I restart it?�65536�Problems�0
+On HPUX I get device lan0 open: recv\_ack: promisc\_phys: Invalid argument�65536�Problems�0
+Portscans are not being logged to my database�65536�Problems�0
Problems�64�0
Rules and Alerts�64�0
-SMB alerts aren't working, what's wrong? �65536�0
-Snort complains about the ``react'' keyword...�65536�0
-Snort fails to respond to a kill signal on Linux. Why?�65536�0
-Snort is behind a firewall (ipf/pf/ipchains/ipfilter) and awfully quiet...�65536�0
-Snort is dying with a `can not create file' error and I have plenty of diskspace. What's wrong?�65536�0
-Snort is not logging to my database�65536�0
-Snort is not logging to syslog�65536�0
-Snort says BACKDOOR SIGNATURE... does my machine have a Trojan? �65536�0
-Snort says ``Garbage Packet with Null Pointer discarded!'' Huh?�65536�0
-Snort says ``Ran Out Of Space.'' Huh?�65536�0
-Snort says ``Rule IP addr (``1.1.1.1'') didn't x-late, WTF?''�65536�0
-Trying to install snort it says: ``bad interpreter: No such file or�65536�0
-What about `SMB Name Wildcard' alerts? �65536�0
-What about ``CGI Null Byte attacks?'' �65536�0
-What about all these false alarms? �65536�0
-What are CIDR netmasks? �65536�0
-What are HOME\_NET and EXTERNAL\_NET?�65536�0
-What are all these ICMP files in subdirectories under /var/log/snort? �65536�0
-What are all these ``ICMP destination unreachable'' alerts? �65536�0
-What are some resources that I can use to understand more about source�65536�0
-What are these IDS codes in the alert names? �65536�0
-What do the numbers (ie: [116:56:1]) in front of a Snort alert mean?�65536�0
-What is the best way to use Snort to block attack traffic?�65536�0
-What is the difference between ``Alerting'' and ``Logging''?�65536�0
-What is the use of the ``-r'' switch to read tcpdump files? �65536�0
-What the heck is a SYNFIN scan?�65536�0
-What the heck is a SYNFIN scan? �65536�0
-What the heck is a ``Stealth scan''?�65536�0
-What version of Winpcap do I need?\label{winpcap�65536�0
-What's this about a Snort drinking game?�65536�0
-Where are my log files located? What are they named?�65536�0
-Where can I get more reading and courses about IDS?\label{courses�65536�0
-Where do I find binary packages for BlueHat BSD-Linux-RT?�65536�0
-Where do I get more help on Snort?�65536�0
-Where do I get the latest version of Winpcap?�65536�0
-Where do I get the latest version of libpcap? �65536�0
-Where do the distance and within keywords work from to modify content�65536�0
-Where does one obtain new/modifed rules? How do you merge them in?�65536�0
-Where's a good place to physically put a Snort sensor?�65536�0
-Which takes precedence, commandline or rule file ?�65536�0
-Why am I seeing so many ``SMTP RCPT TO overflow'' alerts ?�65536�0
-Why are my unified alert times off by +/- N hours?�65536�0
-Why are there no subdirectories under /var/log/snort for IP addresses?�65536�0
-Why can't snort see one of the 10Mbps or 100Mbps traffic on my autoswitch hub?�65536�0
-Why do certain alerts seem to have `unknown' IPs in BASE? �65536�0
-Why do many Snort rules have the flags P (TCP PuSH) and A (TCP ACK) set? �65536�0
-Why does Snort complain about /var/log/snort?�65536�0
-Why does building Snort complain about missing references? �65536�0
-Why does building snort fail with errors about yylex and lex\_init? �65536�0
-Why does chrooted Snort die when I send it a SIGHUP? \label{chroot�65536�0
-Why does snort report ``Packet loss statistics are unavailable under Linux?''�65536�0
-Why does the `error deleting alert' message occur when attempting to delete an alert with BASE? �65536�0
-Why does the portscan plugin log ``stealth'' packets even though the host is in the portscan-ignorehosts list? �65536�0
-Why does the program generate alerts on packets that have pass rules? �65536�0
-barnyard�2048�0
+SMB alerts aren't working, what's wrong?�65536�Problems�0
+Snort complains about the ``react'' keyword...�65536�Getting Fancy�0
+Snort fails to respond to a kill signal on Linux. Why?�65536�Problems�0
+Snort is behind a firewall (ipf/pf/ipchains/ipfilter) and awfully quiet...�65536�Rules and Alerts�0
+Snort is dying with a `can not create file' error and I have plenty of diskspace. What's wrong?�65536�Problems�0
+Snort is not logging to my database�65536�Problems�0
+Snort is not logging to syslog�65536�Problems�0
+Snort says BACKDOOR SIGNATURE... does my machine have a Trojan?�65536�Rules and Alerts�0
+Snort says ``Garbage Packet with Null Pointer discarded!'' Huh?�65536�Problems�0
+Snort says ``Ran Out Of Space.'' Huh?�65536�Problems�0
+Snort says ``Rule IP addr (``1.1.1.1'') didn't x-late, WTF?''�65536�Rules and Alerts�0
+Trying to install snort it says: ``bad interpreter: No such file or directory''�65536�Problems�0
+What about `SMB Name Wildcard' alerts?�65536�Rules and Alerts�0
+What about ``CGI Null Byte attacks?''�65536�Rules and Alerts�0
+What about all these false alarms?�65536�Rules and Alerts�0
+What are CIDR netmasks?�65536�Getting Started�0
+What are HOME\_NET and EXTERNAL\_NET?�65536�Configuring Snort�0
+What are all these ICMP files in subdirectories under /var/log/snort?�65536�Rules and Alerts�0
+What are all these ``ICMP destination unreachable'' alerts?�65536�Rules and Alerts�0
+What are some resources that I can use to understand more about source addresses logged and where they are coming from?�65536�Getting Fancy�0
+What are these IDS codes in the alert names?�65536�Rules and Alerts�0
+What do the numbers (ie: [116:56:1]) in front of a Snort alert mean?�65536�Rules and Alerts�0
+What is the best way to use Snort to block attack traffic?�65536�Getting Fancy�0
+What is the difference between ``Alerting'' and ``Logging''?�65536�Rules and Alerts�0
+What is the use of the ``-r'' switch to read tcpdump files?�65536�Getting Started�0
+What the heck is a SYNFIN scan?�65536�Configuring Snort�0
+What the heck is a SYNFIN scan?�65536�Rules and Alerts�0
+What the heck is a ``Stealth scan''?�65536�Configuring Snort�0
+What version of Winpcap do I need?\label{winpcap}�65536�Getting Started�0
+What's this about a Snort drinking game?�65536�Miscellaneous�0
+Where are my log files located? What are they named?�65536�Getting Started�0
+Where can I get more reading and courses about IDS?\label{courses}�65536�Background�0
+Where do I find binary packages for BlueHat BSD-Linux-RT?�65536�Getting Started�0
+Where do I get more help on Snort?�65536�Background�0
+Where do I get the latest version of Winpcap?�65536�Getting Started�0
+Where do I get the latest version of libpcap?�65536�Getting Started�0
+Where do the distance and within keywords work from to modify content searches in rules?�65536�Rules and Alerts�0
+Where does one obtain new/modifed rules? How do you merge them in?�65536�Configuring Snort�0
+Where's a good place to physically put a Snort sensor?�65536�Getting Started�0
+Which takes precedence, commandline or rule file ?�65536�Configuring Snort�0
+Why am I seeing so many ``SMTP RCPT TO overflow'' alerts ?�65536�Problems�0
+Why are my unified alert times off by +/- N hours?�65536�Problems�0
+Why are there no subdirectories under /var/log/snort for IP addresses?�65536�Configuring Snort�0
+Why can't snort see one of the 10Mbps or 100Mbps traffic on my autoswitch hub?�65536�Problems�0
+Why do certain alerts seem to have `unknown' IPs in BASE?�65536�Rules and Alerts�0
+Why do many Snort rules have the flags P (TCP PuSH) and A (TCP ACK) set?�65536�Rules and Alerts�0
+Why does Snort complain about /var/log/snort?�65536�Getting Started�0
+Why does building Snort complain about missing references?�65536�Getting Started�0
+Why does building snort fail with errors about yylex and lex\_init?�65536�Getting Started�0
+Why does chrooted Snort die when I send it a SIGHUP? \label{chroot}�65536�Problems�0
+Why does snort report ``Packet loss statistics are unavailable under Linux?''�65536�Problems�0
+Why does the `error deleting alert' message occur when attempting to delete an alert with BASE?�65536�Problems�0
+Why does the portscan plugin log ``stealth'' packets even though the host is in the portscan-ignorehosts list?�65536�Configuring Snort�0
+Why does the program generate alerts on packets that have pass rules?�65536�Rules and Alerts�0
+\myquote�16�0
+\myref�16�0
center�1�0
-chroot�2048�0
-courses�2048�0
document�1�0
enumerate�1�0
itemize�1�0
latexonly�1�0
-myquote�16�0
-myref�16�0
-quote�1�0
-spoolers�2048�0
stealth�2048�0
stream4�2048�0
tabular�1�0
verbatim�1�0
-winpcap�2048�0
Modified: tests/ctags/bug2886870.tex.tags
19 lines changed, 10 insertions(+), 9 deletions(-)
===================================================================
@@ -1,16 +1,19 @@
# format=tagmanager
-Common Greek letters�65536�0
+Common Greek letters�65536�Special Symbols�0
Equations�64�0
Figures�64�0
Introduction�64�0
Lists�64�0
Literal text�64�0
Special Symbols�64�0
-Special symbols�65536�0
+Special symbols�65536�Special Symbols�0
Tables�64�0
-Test for ctags�16384�0
-\color{red�64�0
-\label{morefig�64�0
+Test for ctags�16384�Special Symbols""Common Greek letters�0
+\color{red}Use of Color�64�0
+\label{morefig}Subfigures�64�0
+\lb�16�0
+\rb�16�0
+\rv�16�0
align�1�0
cases�1�0
center�1�0
@@ -26,14 +29,12 @@ fig:qm/complexfunctions
fig:typical�2048�0
figure�1�0
itemize�1�0
-lb�16�0
-morefig�2048�0
+latex�8�0
pmatrix�1�0
-rb�16�0
-rv�16�0
subequations�1�0
tab:5/tc�2048�0
table�1�0
tabular�1�0
thebibliography�1�0
verbatim�1�0
+website�8�0
Modified: tests/ctags/intro.tex.tags
18 lines changed, 11 insertions(+), 7 deletions(-)
===================================================================
@@ -1,10 +1,14 @@
# format=tagmanager
-Introduction�64�0
+Introduction�64�chapter text�0
+Part1�2�0
+Part2�2�0
chapter text�256�0
-chapter2�256�0
-section1 text�64�0
-section4 text�64�0
-subsection2�65536�0
-subsubsection3 with extra text�16384�0
-subsubsection6 with extra text�16384�0
+chapter2�256�Part2�0
+section1 text�64�chapter text�0
+short section4�64�Part1�0
+shorter intro2�64�Part2�0
+subsec5 text�65536�Part2""shorter intro2�0
+subsection2�65536�Part1�0
+subsubsection3 with extra text�16384�Part1""subsection2�0
+subsubsection6 with extra text�16384�Part2""shorter intro2""subsec5 text�0
verbatim�1�0
Modified: tests/ctags/intro_orig.tex
15 lines changed, 15 insertions(+), 0 deletions(-)
===================================================================
@@ -20,6 +20,21 @@
\setlength{\marginparpush}{1.0cm}
\setlength{\textwidth}{150mm}
+\newenvironment{boxed}
+ {\begin{center}
+ \begin{tabular}{|p{0.9\textwidth}|}
+ \hline\\
+ }
+ {
+ \\\\\hline
+ \end{tabular}
+ \end{center}
+ }
+
+\DeclareMathOperator{\End}{End}
+
+\newtheorem{theorem1}{Theorem}
+
\begin{comment}
\pagestyle{empty} % use if page numbers not wanted
\end{comment}
Modified: tests/ctags/intro_orig.tex.tags
20 lines changed, 12 insertions(+), 8 deletions(-)
===================================================================
@@ -1,16 +1,21 @@
# format=tagmanager
-Common Greek letters�65536�0
+Common Greek letters�65536�Special Symbols�0
Equations�64�0
Figures�64�0
Introduction�64�0
Lists�64�0
Literal text�64�0
Special Symbols�64�0
-Special symbols�65536�0
+Special symbols�65536�Special Symbols�0
Tables�64�0
-\color{red�64�0
-\label{morefig�64�0
+\End�16�0
+\color{red}Use of Color�64�0
+\label{morefig}Subfigures�64�0
+\lb�16�0
+\rb�16�0
+\rv�16�0
align�1�0
+boxed�1�0
cases�1�0
center�1�0
comment�1�0
@@ -25,14 +30,13 @@ fig:qm/complexfunctions
fig:typical�2048�0
figure�1�0
itemize�1�0
-lb�16�0
-morefig�2048�0
+latex�8�0
pmatrix�1�0
-rb�16�0
-rv�16�0
subequations�1�0
tab:5/tc�2048�0
table�1�0
tabular�1�0
thebibliography�1�0
+theorem1�1�0
verbatim�1�0
+website�8�0
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).