Kaydet (Commit) 3390e2ac authored tarafından Jiří Techet's avatar Jiří Techet

Move ctags "API" from Geany to ctags

This commit basically just moves stuff from tm_ctags_wrappers.c/h to
ctags. The "api.h" file has been renamed to "ctags-api.h" to make it
clearer it belongs to ctags when included.

The code also tries to completely isolate ctags from the caller;
previously we were using tagEntryInfo to pass information to Geany. This
however required including entry.h which added lots of other stuff we
don't want in the API. Instead create an auxiliary struct that holds
all the needed information from tagEntryInfo (currently only the stuff
used by Geany) and copy all the info from tagEntryInfo before invoking
the callback.
üst 32dfa287
......@@ -53,11 +53,11 @@ parsers = \
parsers/vhdl.c
libctags_la_SOURCES = \
main/api.c \
main/api.h \
main/args.c \
main/args.h \
main/ctags.h \
main/ctags-api.c \
main/ctags-api.h \
main/debug.h \
main/debug.c \
main/dependency.h \
......
/*
* Copyright (c) 2016, Jiri Techet
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Defines ctags API when compiled as a library.
*/
#ifdef CTAGS_LIB
#include "general.h" /* must always come first */
#include "api.h"
#endif /* CTAGS_LIB */
/*
* Copyright (c) 2016, Jiri Techet
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Defines ctags API when compiled as a library.
*/
#ifndef CTAGS_API_H
#define CTAGS_API_H
#ifdef CTAGS_LIB
typedef bool (*tagEntryFunction) (const tagEntryInfo *const tag, void *userData);
typedef bool (*passStartCallback) (void *userData);
#endif /* CTAGS_LIB */
#endif /* CTAGS_API_H */
/*
* tm_ctags_wrappers.c - this file is part of Geany, a fast and lightweight IDE
*
* Copyright 2016 Jiri Techet <techet(at)gmail(dot)com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "tm_ctags_wrappers.h"
#include "general.h"
#include "entry.h"
#include "parse.h"
#include "read.h"
#include "api.h"
* Copyright (c) 2016, Jiri Techet
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Defines ctags API when compiled as a library.
*/
#include "general.h" /* must always come first */
#ifdef CTAGS_LIB
#include "ctags-api.h"
#include "types.h"
#include "routines.h"
#include "error.h"
#include "output.h"
#include "parse.h"
#include "options.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct {
TMCtagsNewTagCallback tag_callback;
TMCtagsPassStartCallback pass_callback;
gpointer user_data;
} CallbackUserData;
extern bool nofatalErrorPrinter (const errorSelection selection,
static bool nofatalErrorPrinter (const errorSelection selection,
const char *const format,
va_list ap, void *data CTAGS_ATTR_UNUSED)
{
......@@ -55,7 +40,7 @@ extern bool nofatalErrorPrinter (const errorSelection selection,
return false;
}
void tm_ctags_init(void)
extern void ctagsInit(void)
{
setErrorPrinter (nofatalErrorPrinter, NULL);
setTagWriter (&ctagsWriter);
......@@ -65,54 +50,46 @@ void tm_ctags_init(void)
initializeParsing ();
initOptions ();
initializeParser (LANG_AUTO);
}
static bool tag_callback_internal(const tagEntryInfo *tag, gpointer user_data)
{
CallbackUserData *callback_data = user_data;
return callback_data->tag_callback(tag, callback_data->user_data);
/* make sure all parsers are initialized */
initializeParser (LANG_AUTO);
}
static bool pass_callback_internal(gpointer user_data)
{
CallbackUserData *callback_data = user_data;
return callback_data->pass_callback(callback_data->user_data);
}
void tm_ctags_parse(guchar *buffer, gsize buffer_size,
const gchar *file_name, TMParserType lang, TMCtagsNewTagCallback tag_callback,
TMCtagsPassStartCallback pass_callback, gpointer user_data)
extern void ctagsParse(unsigned char *buffer, size_t bufferSize,
const char *fileName, const langType language,
tagEntryFunction tagCallback, passStartCallback passCallback,
void *userData)
{
CallbackUserData callback_data = {tag_callback, pass_callback, user_data};
g_return_if_fail(buffer || file_name);
if (buffer == NULL && fileName == NULL)
{
error(FATAL, "Neither buffer nor file provided to ctagsParse()");
return;
}
createTagsWithFallback(buffer, buffer_size, file_name, lang,
tag_callback_internal, pass_callback_internal, &callback_data);
createTagsWithFallback(buffer, bufferSize, fileName, language,
tagCallback, passCallback, userData);
}
const gchar *tm_ctags_get_lang_name(TMParserType lang)
extern const char *ctagsGetLangName(int lang)
{
return getLanguageName(lang);
}
TMParserType tm_ctags_get_named_lang(const gchar *name)
extern int ctagsGetNamedLang(const char *name)
{
return getNamedLanguage(name, 0);
}
const gchar *tm_ctags_get_lang_kinds(TMParserType lang)
extern const char *ctagsGetLangKinds(int lang)
{
guint i;
unsigned int i;
parserDefinition *def = LanguageTable[lang];
static gchar kinds[257];
static char kinds[257];
for (i = 0; i < def->kindCount; i++)
kinds[i] = def->kinds[i].letter;
......@@ -122,9 +99,9 @@ const gchar *tm_ctags_get_lang_kinds(TMParserType lang)
}
const gchar *tm_ctags_get_kind_name(gchar kind, TMParserType lang)
extern const char *ctagsGetKindName(char kind, int lang)
{
guint i;
unsigned int i;
parserDefinition *def = LanguageTable[lang];
for (i = 0; i < def->kindCount; i++)
......@@ -136,27 +113,29 @@ const gchar *tm_ctags_get_kind_name(gchar kind, TMParserType lang)
}
gchar tm_ctags_get_kind_from_name(const gchar *name, TMParserType lang)
extern char ctagsGetKindFromName(const char *name, int lang)
{
guint i;
unsigned int i;
parserDefinition *def = LanguageTable[lang];
for (i = 0; i < def->kindCount; i++)
{
if (g_strcmp0(def->kinds[i].name, name) == 0)
if (strcmp(def->kinds[i].name, name) == 0)
return def->kinds[i].letter;
}
return '-';
}
gboolean tm_ctags_is_using_regex_parser(TMParserType lang)
extern bool ctagsIsUsingRegexParser(int lang)
{
return LanguageTable[lang]->method & METHOD_REGEX;
}
guint tm_ctags_get_lang_count(void)
extern unsigned int ctagsGetLangCount(void)
{
return countParsers();
}
#endif /* CTAGS_LIB */
/*
* Copyright (c) 2016, Jiri Techet
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Defines ctags API when compiled as a library.
*/
#ifndef CTAGS_API_H
#define CTAGS_API_H
#include "general.h" /* must always come first */
#ifdef CTAGS_LIB
#include <stdlib.h>
#include <stdbool.h>
typedef struct {
const char *name;
const char *signature;
const char *scopeName;
const char *inheritance;
const char *varType;
const char *access;
const char *implementation;
char kindLetter;
bool isFileScope;
unsigned long lineNumber;
} ctagsTag;
/* Callback invoked for every tag found by the parser. The return value is
* currently unused. */
typedef bool (*tagEntryFunction) (const ctagsTag *const tag, void *userData);
/* Callback invoked at the beginning of every parsing pass. The return value is
* currently unused */
typedef bool (*passStartCallback) (void *userData);
extern void ctagsInit(void);
extern void ctagsParse(unsigned char *buffer, size_t bufferSize,
const char *fileName, const int language,
tagEntryFunction tagCallback, passStartCallback passCallback,
void *userData);
extern const char *ctagsGetLangName(int lang);
extern int ctagsGetNamedLang(const char *name);
extern const char *ctagsGetLangKinds(int lang);
extern const char *ctagsGetKindName(char kind, int lang);
extern char ctagsGetKindFromName(const char *name, int lang);
extern bool ctagsIsUsingRegexParser(int lang);
extern unsigned int ctagsGetLangCount(void);
#endif /* CTAGS_LIB */
#endif /* CTAGS_API_H */
......@@ -1084,6 +1084,22 @@ static void buildFqTagCache (const tagEntryInfo *const tag)
renderFieldEscaped (FIELD_SCOPE, tag, NO_PARSER_FIELD);
}
#ifdef CTAGS_LIB
static void initCtagsTag(ctagsTag *tag, const tagEntryInfo *info)
{
tag->name = info->name;
tag->signature = info->extensionFields.signature;
tag->scopeName = info->extensionFields.scopeName;
tag->inheritance = info->extensionFields.inheritance;
tag->varType = info->extensionFields.varType;
tag->access = info->extensionFields.access;
tag->implementation = info->extensionFields.implementation;
tag->kindLetter = info->kind->letter;
tag->isFileScope = info->isFileScope;
tag->lineNumber = info->lineNumber;
}
#endif
static void writeTagEntry (const tagEntryInfo *const tag)
{
int length = 0;
......@@ -1108,7 +1124,12 @@ static void writeTagEntry (const tagEntryInfo *const tag)
getTagScopeInformation((tagEntryInfo *)tag, NULL, NULL);
if (TagEntryFunction != NULL)
length = TagEntryFunction(tag, TagEntryUserData);
{
ctagsTag t;
initCtagsTag(&t, tag);
length = TagEntryFunction(&t, TagEntryUserData);
}
#else
length = writer->writeEntry (TagFile.mio, tag, writerData);
#endif
......
......@@ -23,7 +23,7 @@
#include "xtag.h"
#include "mio.h"
#include "nestlevel.h"
#include "api.h"
#include "ctags-api.h"
/*
* MACROS
......
......@@ -20,7 +20,7 @@
#include "kind.h"
#include "parsers.h" /* contains list of parsers */
#include "strlist.h"
#include "api.h"
#include "ctags-api.h"
#ifdef HAVE_LIBXML
#include <libxml/xpath.h>
......
......@@ -25,8 +25,6 @@ libtagmanager_la_SOURCES =\
tm_tag.h \
tm_tag.c \
tm_workspace.h \
tm_workspace.c \
tm_ctags_wrappers.h \
tm_ctags_wrappers.c
tm_workspace.c
libtagmanager_la_LIBADD = $(top_builddir)/ctags/libctags.la $(GTK_LIBS)
/*
* tm_ctags_wrappers.h - this file is part of Geany, a fast and lightweight IDE
*
* Copyright 2016 Jiri Techet <techet(at)gmail(dot)com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef TM_CTAGS_WRAPPERS
#define TM_CTAGS_WRAPPERS
#include <glib.h>
#include "tm_parser.h"
#include "entry.h" /* for sTagEntryInfo */
G_BEGIN_DECLS
/* Callback invoked for every tag found by the parser. The return value is
* currently unused. */
typedef gboolean (*TMCtagsNewTagCallback) (const tagEntryInfo *const tag,
void *user_data);
/* Callback invoked at the beginning of every parsing pass. The return value is
* currently unused */
typedef gboolean (*TMCtagsPassStartCallback) (void *user_data);
void tm_ctags_init(void);
void tm_ctags_parse(guchar *buffer, gsize buffer_size,
const gchar *file_name, TMParserType lang, TMCtagsNewTagCallback tag_callback,
TMCtagsPassStartCallback pass_callback, gpointer user_data);
const gchar *tm_ctags_get_lang_name(TMParserType lang);
TMParserType tm_ctags_get_named_lang(const gchar *name);
const gchar *tm_ctags_get_lang_kinds(TMParserType lang);
const gchar *tm_ctags_get_kind_name(gchar kind, TMParserType lang);
gchar tm_ctags_get_kind_from_name(const gchar *name, TMParserType lang);
gboolean tm_ctags_is_using_regex_parser(TMParserType lang);
guint tm_ctags_get_lang_count(void);
G_END_DECLS
#endif /* TM_CTAGS_WRAPPERS */
......@@ -19,7 +19,7 @@
*/
#include "tm_parser.h"
#include "tm_ctags_wrappers.h"
#include "ctags-api.h"
#include <string.h>
......@@ -591,28 +591,28 @@ void tm_parser_verify_type_mappings(void)
{
TMParserType lang;
if (TM_PARSER_COUNT > tm_ctags_get_lang_count())
if (TM_PARSER_COUNT > ctagsGetLangCount())
g_error("More parsers defined in Geany than in ctags");
for (lang = 0; lang < TM_PARSER_COUNT; lang++)
{
const gchar *kinds = tm_ctags_get_lang_kinds(lang);
const gchar *kinds = ctagsGetLangKinds(lang);
TMParserMap *map = &parser_map[lang];
gchar presence_map[256];
guint i;
if (! map->entries || map->size < 1)
g_error("No tag types in TM for %s, is the language listed in parser_map?",
tm_ctags_get_lang_name(lang));
ctagsGetLangName(lang));
/* TODO: check also regex parser mappings. At the moment there's no way
* to access regex parser definitions in ctags */
if (tm_ctags_is_using_regex_parser(lang))
if (ctagsIsUsingRegexParser(lang))
continue;
if (map->size != strlen(kinds))
g_error("Different number of tag types in TM (%d) and ctags (%d) for %s",
map->size, (int)strlen(kinds), tm_ctags_get_lang_name(lang));
map->size, (int)strlen(kinds), ctagsGetLangName(lang));
memset(presence_map, 0, sizeof(presence_map));
for (i = 0; i < map->size; i++)
......@@ -634,10 +634,10 @@ void tm_parser_verify_type_mappings(void)
}
if (!ctags_found)
g_error("Tag type '%c' found in TM but not in ctags for %s",
map->entries[i].kind, tm_ctags_get_lang_name(lang));
map->entries[i].kind, ctagsGetLangName(lang));
if (!tm_found)
g_error("Tag type '%c' found in ctags but not in TM for %s",
kinds[i], tm_ctags_get_lang_name(lang));
kinds[i], ctagsGetLangName(lang));
presence_map[(unsigned char) map->entries[i].kind]++;
}
......@@ -646,7 +646,7 @@ void tm_parser_verify_type_mappings(void)
{
if (presence_map[i] > 1)
g_error("Duplicate tag type '%c' found for %s",
(gchar)i, tm_ctags_get_lang_name(lang));
(gchar)i, ctagsGetLangName(lang));
}
}
}
......@@ -30,7 +30,7 @@
#include "tm_source_file.h"
#include "tm_tag.h"
#include "tm_parser.h"
#include "tm_ctags_wrappers.h"
#include "ctags-api.h"
typedef struct
{
......@@ -164,7 +164,7 @@ static char get_tag_access(const char *access)
}
/*
Initializes a TMTag structure with information from a tagEntryInfo struct
Initializes a TMTag structure with information from a ctagsTag struct
used by the ctags parsers. Note that the TMTag structure must be malloc()ed
before calling this function.
@param tag The TMTag structure to initialize
......@@ -172,14 +172,14 @@ static char get_tag_access(const char *access)
@param tag_entry Tag information gathered by the ctags parser
@return TRUE on success, FALSE on failure
*/
static gboolean init_tag(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag_entry)
static gboolean init_tag(TMTag *tag, TMSourceFile *file, const ctagsTag *tag_entry)
{
TMTagType type;
if (!tag_entry)
return FALSE;
type = tm_parser_get_tag_type(tag_entry->kind->letter, file->lang);
type = tm_parser_get_tag_type(tag_entry->kindLetter, file->lang);
if (!tag_entry->name || type == tm_tag_undef_t)
return FALSE;
......@@ -188,19 +188,19 @@ static gboolean init_tag(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag
tag->local = tag_entry->isFileScope;
tag->pointerOrder = 0; /* backward compatibility (use var_type instead) */
tag->line = tag_entry->lineNumber;
if (NULL != tag_entry->extensionFields.signature)
tag->arglist = g_strdup(tag_entry->extensionFields.signature);
if ((NULL != tag_entry->extensionFields.scopeName) &&
(0 != tag_entry->extensionFields.scopeName[0]))
tag->scope = g_strdup(tag_entry->extensionFields.scopeName);
if (tag_entry->extensionFields.inheritance != NULL)
tag->inheritance = g_strdup(tag_entry->extensionFields.inheritance);
if (tag_entry->extensionFields.varType != NULL)
tag->var_type = g_strdup(tag_entry->extensionFields.varType);
if (tag_entry->extensionFields.access != NULL)
tag->access = get_tag_access(tag_entry->extensionFields.access);
if (tag_entry->extensionFields.implementation != NULL)
tag->impl = get_tag_impl(tag_entry->extensionFields.implementation);
if (NULL != tag_entry->signature)
tag->arglist = g_strdup(tag_entry->signature);
if ((NULL != tag_entry->scopeName) &&
(0 != tag_entry->scopeName[0]))
tag->scope = g_strdup(tag_entry->scopeName);
if (tag_entry->inheritance != NULL)
tag->inheritance = g_strdup(tag_entry->inheritance);
if (tag_entry->varType != NULL)
tag->var_type = g_strdup(tag_entry->varType);
if (tag_entry->access != NULL)
tag->access = get_tag_access(tag_entry->access);
if (tag_entry->implementation != NULL)
tag->impl = get_tag_impl(tag_entry->implementation);
if ((tm_tag_macro_t == tag->type) && (NULL != tag->arglist))
tag->type = tm_tag_macro_with_arg_t;
tag->file = file;
......@@ -417,7 +417,7 @@ static gboolean init_tag_from_file_ctags(TMTag *tag, TMSourceFile *file, FILE *f
const gchar *kind = value ? value : key;
if (kind[0] && kind[1])
tag->type = tm_parser_get_tag_type(tm_ctags_get_kind_from_name(kind, lang), lang);
tag->type = tm_parser_get_tag_type(ctagsGetKindFromName(kind, lang), lang);
else
tag->type = tm_parser_get_tag_type(*kind, lang);
}
......@@ -631,7 +631,7 @@ static void update_python_arglist(const TMTag *tag, TMSourceFile *current_source
}
/* new parsing pass ctags callback function */
static gboolean ctags_pass_start(void *user_data)
static bool ctags_pass_start(void *user_data)
{
TMSourceFile *current_source_file = user_data;
......@@ -640,7 +640,7 @@ static gboolean ctags_pass_start(void *user_data)
}
/* new tag ctags callback function */
static gboolean ctags_new_tag(const tagEntryInfo *const tag,
static bool ctags_new_tag(const ctagsTag *const tag,
void *user_data)
{
TMSourceFile *current_source_file = user_data;
......@@ -697,7 +697,7 @@ static gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_
if (name == NULL)
source_file->lang = TM_PARSER_NONE;
else
source_file->lang = tm_ctags_get_named_lang(name);
source_file->lang = ctagsGetNamedLang(name);
return TRUE;
}
......@@ -814,7 +814,7 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
tm_tags_array_free(source_file->tags_array, FALSE);
tm_ctags_parse(use_buffer ? text_buf : NULL, buf_size, file_name,
ctagsParse(use_buffer ? text_buf : NULL, buf_size, file_name,
source_file->lang, ctags_new_tag, ctags_pass_start, source_file);
return !retry;
......@@ -826,7 +826,7 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
*/
const gchar *tm_source_file_get_lang_name(TMParserType lang)
{
return tm_ctags_get_lang_name(lang);
return ctagsGetLangName(lang);
}
/* Gets the language index for \a name.
......@@ -835,5 +835,5 @@ const gchar *tm_source_file_get_lang_name(TMParserType lang)
*/
TMParserType tm_source_file_get_named_lang(const gchar *name)
{
return tm_ctags_get_named_lang(name);
return ctagsGetNamedLang(name);
}
......@@ -12,7 +12,7 @@
#include <glib-object.h>
#include "tm_tag.h"
#include "tm_ctags_wrappers.h"
#include "ctags-api.h"
#define TAG_NEW(T) ((T) = g_slice_new0(TMTag))
......
......@@ -31,7 +31,7 @@
#include <glib/gstdio.h>
#include "tm_workspace.h"
#include "tm_ctags_wrappers.h"
#include "ctags-api.h"
#include "tm_tag.h"
#include "tm_parser.h"
......@@ -78,7 +78,7 @@ static gboolean tm_create_workspace(void)
theWorkspace->typename_array = g_ptr_array_new();
theWorkspace->global_typename_array = g_ptr_array_new();
tm_ctags_init();
ctagsInit();
tm_parser_verify_type_mappings();
return TRUE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment