From 46690c0b8f1e5b47bcbd4a2732233e539cfbf7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrico=20Tr=C3=B6ger?= Date: Wed, 11 Jan 2006 18:50:44 +0000 Subject: [PATCH] added tagmanager support for filetype DocBook and LaTeX git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@123 ea778897-0a13-0410-b9d1-a72fbfd435f5 --- tagmanager/Makefile.am | 5 +- tagmanager/docbook.c | 190 +++++++++++++++++++++++++++++++++++ tagmanager/parsers.h | 1 + tagmanager/tex.c | 222 ++++++++++++++++++++++++++++++----------- 4 files changed, 356 insertions(+), 62 deletions(-) create mode 100644 tagmanager/docbook.c diff --git a/tagmanager/Makefile.am b/tagmanager/Makefile.am index 32a2cd92..e5f81a03 100644 --- a/tagmanager/Makefile.am +++ b/tagmanager/Makefile.am @@ -1,4 +1,6 @@ ## Process this file with automake to produce Makefile.in +# $Id$ + SUBDIRS = include INCLUDES = -Iinclude $(PACKAGE_CFLAGS) # -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED \ @@ -15,7 +17,6 @@ libtagmanager_a_SOURCES =\ sort.h\ vstring.h\ args.h\ - conf.c\ ctags.h\ entry.h\ get.h\ @@ -26,6 +27,8 @@ libtagmanager_a_SOURCES =\ args.c\ args.h\ c.c\ + conf.c\ + docbook.c\ make.c\ tex.c\ pascal.c\ diff --git a/tagmanager/docbook.c b/tagmanager/docbook.c new file mode 100644 index 00000000..d0b57e0d --- /dev/null +++ b/tagmanager/docbook.c @@ -0,0 +1,190 @@ +/* +* $Id$ +* +* Copyright (c) 2001-2002, Darren Hiebert +* 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 the DocBook language, +* to extract the id attribute from section and chapter tags. +* The code is based on pascal.c from tagmanager. +* +* TODO: skip commented blocks like +* +*/ + +/* +* INCLUDE FILES +*/ +#include "general.h" /* must always come first */ + +#include + +#include "entry.h" +#include "parse.h" +#include "read.h" +#include "vstring.h" + +/* +* DATA DEFINITIONS +*/ +typedef enum { + K_SECTION, + K_CHAPTER +} docbookKind; + +static kindOption DocBookKinds [] = { + { TRUE, 'c', "class", "sections"}, + { TRUE, 'n', "namespace", "chapters"}, +}; + +/* +* FUNCTION DEFINITIONS +*/ + +static void createDocBookTag (tagEntryInfo* const tag, + const vString* const name, const int kind) +{ + if (DocBookKinds[kind].enabled && name != NULL && vStringLength (name) > 0) + { + initTagEntry (tag, vStringValue (name)); + + tag->kindName = DocBookKinds [kind].name; + tag->kind = DocBookKinds [kind].letter; + } + else + initTagEntry (tag, NULL); +} + +static void makeDocBookTag (const tagEntryInfo* const tag) +{ + if (tag->name != NULL) makeTagEntry(tag); +} + +static const unsigned char* dbp; + +#define starttoken(c) ((int) c == '"') +//#define intoken(c) ((isalnum ((int) c) || isspace((int) c)) && (int) c != '"') +#define intoken(c) ((isalnum ((int) c) || (int) c == '_') && (int) c != '"') +#define endtoken(c) (! intoken (c)) + +static boolean tail (const char *cp) +{ + boolean result = FALSE; + register int len = 0; + + while (*cp != '\0' && tolower ((int) *cp) == tolower ((int) dbp [len])) + cp++, len++; + if (*cp == '\0' && !intoken (dbp [len])) + { + dbp += len; + result = TRUE; + } + return result; +} + +/* Algorithm adapted from from GNU etags. */ +static void findDocBookTags (void) +{ + vString *name = vStringNew (); + tagEntryInfo tag; + docbookKind kind = K_SECTION; + /* each of these flags is TRUE iff: */ + boolean get_tagname = FALSE;/* point is after tag, so next item = potential tag */ + boolean found_tag = FALSE; /* point is after a potential tag */ + boolean verify_tag = FALSE; + + dbp = fileReadLine (); + + while (dbp != NULL) + { + int c = *dbp++; + + if (c == '\0') /* if end of line */ + { + dbp = fileReadLine (); + if (dbp == NULL || *dbp == '\0') + continue; + if (!((found_tag && verify_tag) || get_tagname)) + c = *dbp++; /* only if don't need *dbp pointing + to the beginning of the name of the tag */ + } + if ((c == '"' || c == '>') && found_tag) // end of proc or fn stmt + { + verify_tag = TRUE; + continue; + } + if (found_tag && verify_tag && *dbp != ' ') + { + if (*dbp == '\0') + continue; + + if (found_tag && verify_tag) // not external proc, so make tag + { + found_tag = FALSE; + verify_tag = FALSE; + makeDocBookTag(&tag); + continue; + } + } + if (get_tagname) /* grab name of proc or fn */ + { + const unsigned char *cp; + + if (*dbp == '\0') continue; + + /* grab block name */ + while (isspace((int) *dbp)) ++dbp; + while ((int) *dbp != 'i') ++dbp; + while ((int) *dbp != 'd') ++dbp; + while ((int) *dbp != '"') ++dbp; + ++dbp; + for (cp = dbp ; *cp != '\0' && !endtoken(*cp); cp++) continue; + vStringNCopyS(name, (const char*) dbp, cp - dbp); + createDocBookTag(&tag, name, kind); + //printf("%s\n", name); + dbp = cp; /* set dbp to e-o-token */ + get_tagname = FALSE; + found_tag = TRUE; + } + else if (!found_tag) + { + switch (tolower ((int) c)) + { + case 's': + { + if (tail ("ection")) + { + get_tagname = TRUE; + kind = K_SECTION; + } + break; + } + case 'c': + { + if (tail ("hapter")) + { + get_tagname = TRUE; + kind = K_CHAPTER; + } + break; + } + } /* while not eof */ + } +} +} + +extern parserDefinition* DocBookParser (void) +{ + static const char *const extensions [] = { "d", "docbook", NULL }; + parserDefinition* def = parserNew ("Docbook"); + def->extensions = extensions; + def->kinds = DocBookKinds; + def->kindCount = KIND_COUNT (DocBookKinds); + def->parser = findDocBookTags; + return def; +} + +/* vi:set tabstop=8 shiftwidth=4: */ diff --git a/tagmanager/parsers.h b/tagmanager/parsers.h index f6277ab8..d1eeff08 100644 --- a/tagmanager/parsers.h +++ b/tagmanager/parsers.h @@ -25,6 +25,7 @@ PythonParser, \ TexParser, \ ConfParser, \ + DocBookParser, \ ShParser #endif /* _PARSERS_H */ diff --git a/tagmanager/tex.c b/tagmanager/tex.c index 167a1c82..d211524b 100644 --- a/tagmanager/tex.c +++ b/tagmanager/tex.c @@ -1,12 +1,15 @@ /* -* -* Copyright (c) 2005, Enrico Troeger -* -* 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 (la)tex files. -*/ + * $Id$ + * + * 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 @@ -14,6 +17,7 @@ #include "general.h" /* must always come first */ #include +#include #include "parse.h" #include "read.h" @@ -23,80 +27,176 @@ * DATA DEFINITIONS */ typedef enum { - K_KEYWORD -} texKind; + K_COMMAND, + K_ENVIRONMENT, + K_LABEL +} TeXKind; -static kindOption TexKinds [] = { - { TRUE, 's', "symbol", "symbols"} +static kindOption TeXKinds[] = { + /* Commands - including \newcommand, \providecommand, \renewcommand, + * \def, \DeclareMathOperator. */ + { TRUE, 'c', "class", "command definitions" }, + /* Environment - \newenvironment, \newtheorem */ + { TRUE, 'n', "namespace", "environment definitions" }, + /* Labels - \label, \bibitem. */ + { TRUE, 't', "typedef", "labels and bibliography" } }; +#define TEX_BRACES (1<<0) +#define TEX_BSLASH (1<<1) +#define TEX_LABEL (1<<2) + /* * FUNCTION DEFINITIONS */ -static boolean isIdentifier (int c) +static int getWord (const char * ref, const unsigned char ** pointer) { - return (boolean)(isalnum (c) || c == '\\'); + const char * p = *pointer; + + while ((*ref != '\0') && (*p != '\0') && (*ref == *p)) + ref++, p++; + + if (*ref) + return FALSE; + + *pointer = p; + return TRUE; } -static void findTexTags (void) +static void createTag (int flags, TeXKind kind, const char * l) +{ + vString *name = vStringNew (); + + while ((*l == ' ')) + l++; + if (flags & (TEX_BRACES | TEX_LABEL)) + { + if ((*(l++)) != '{') + goto no_tag; + } + if (flags & TEX_BSLASH) + { + if ((*(l++)) != '\\') + goto no_tag; + } + if (flags & TEX_LABEL) + { + do + { + vStringPut (name, (int) *l); + ++l; + } while ((*l != '\0') && (*l != '}')); + vStringTerminate (name); + makeSimpleTag (name, TeXKinds, kind); + } + else if (isalpha ((int) *l) || *l == '@') + { + do + { + vStringPut (name, (int) *l); + ++l; + } while (isalpha ((int) *l) || *l == '@'); + vStringTerminate (name); + makeSimpleTag (name, TeXKinds, kind); + } + else + { + vStringPut (name, (int) *l); + vStringTerminate (name); + makeSimpleTag (name, TeXKinds, kind); + } + + no_tag: + vStringDelete (name); +} + +static void findTeXTags (void) { - vString *name = vStringNew (); const unsigned char *line; while ((line = fileReadLine ()) != NULL) { - const unsigned char* cp = line; - boolean possible = TRUE; + const unsigned char *cp = line; + //int escaped = 0; - while (isspace ((int) *cp)) - ++cp; - if (*cp == '#') - continue; + for (; *cp != '\0'; cp++) + { + if (*cp == '%') + break; + if (*cp == '\\') + { + cp++; - while (*cp != '\0') - { - /* We look for any sequence of identifier characters following - * either a white space or a colon and followed by either = or := - */ - if (possible && isIdentifier ((int) *cp)) - { - while (isIdentifier ((int) *cp)) - { - vStringPut (name, (int) *cp); - ++cp; - } - vStringTerminate (name); - while (isspace ((int) *cp)) - ++cp; - if ( *cp == ':') - ++cp; - if ( *cp == '=') - makeSimpleTag (name, TexKinds, K_KEYWORD); - vStringClear (name); - } - else if (isspace ((int) *cp) || *cp == ':') - possible = TRUE; - else - possible = FALSE; - if (*cp != '\0') - ++cp; - } + /* \newcommand{\command} */ + if (getWord ("newcommand", &cp) + || getWord ("providecommand", &cp) + || getWord ("renewcommand", &cp) + ) + { + createTag (TEX_BRACES|TEX_BSLASH, K_COMMAND, cp); + continue; + } + + /* \DeclareMathOperator{\command} */ + if (getWord ("DeclareMathOperator", &cp)) + { + if (*cp == '*') + cp++; + createTag (TEX_BRACES|TEX_BSLASH, K_COMMAND, cp); + continue; + } + + /* \def\command */ + if (getWord ("def", &cp)) + { + createTag (TEX_BSLASH, K_COMMAND, cp); + continue; + } + + /* \newenvironment{name} */ + if ( getWord ("newenvironment", &cp) + || getWord ("newtheorem", &cp) + ) + { + createTag (TEX_BRACES, K_ENVIRONMENT, cp); + continue; + } + + /* \bibitem[label]{key} */ + 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} */ + if (getWord ("label", &cp)) + { + createTag (TEX_LABEL, K_LABEL, cp); + continue; + } + } + } } - vStringDelete (name); } extern parserDefinition* TexParser (void) { - //static const char *const patterns [] = { "[Mm]akefile", NULL }; - static const char *const extensions [] = { "tex", NULL }; - parserDefinition* const def = parserNew ("Tex"); - def->kinds = TexKinds; - def->kindCount = KIND_COUNT (TexKinds); - //def->patterns = patterns; - def->extensions = extensions; - def->parser = findTexTags; - return def; + static const char *const extensions [] = { "tex", "sty", "cls", NULL }; + parserDefinition * def = parserNew ("Tex"); + def->kinds = TeXKinds; + def->kindCount = KIND_COUNT (TeXKinds); + def->extensions = extensions; + def->parser = findTeXTags; + return def; } -/* vi:set tabstop=8 shiftwidth=4: */