1a086aff1SMasatake YAMATO /*
2a086aff1SMasatake YAMATO * Copyright (c) 2015, Masatake YAMATO
3a086aff1SMasatake YAMATO * Copyright (c) 2015, Red Hat, Inc.
4a086aff1SMasatake YAMATO *
5a086aff1SMasatake YAMATO * This source code is released for free distribution under the terms of the
6a086aff1SMasatake YAMATO * GNU General Public License version 2 or (at your option) any later version.
7a086aff1SMasatake YAMATO *
84582fa5cSMasatake YAMATO * This module contains functions for xpath meta parser.
9a086aff1SMasatake YAMATO */
10a086aff1SMasatake YAMATO
11a086aff1SMasatake YAMATO #include "general.h" /* must always come first */
12a086aff1SMasatake YAMATO #include "debug.h"
13a086aff1SMasatake YAMATO #include "entry.h"
14a086aff1SMasatake YAMATO #include "options.h"
150d502ef0SMasatake YAMATO #include "parse_p.h"
16a086aff1SMasatake YAMATO #include "read.h"
17b5df137eSMasatake YAMATO #include "read_p.h"
18a086aff1SMasatake YAMATO #include "routines.h"
19a086aff1SMasatake YAMATO #include "xtag.h"
20a086aff1SMasatake YAMATO
21a086aff1SMasatake YAMATO #ifdef HAVE_LIBXML
22a086aff1SMasatake YAMATO #include <libxml/xpath.h>
23a086aff1SMasatake YAMATO #include <libxml/tree.h>
24a086aff1SMasatake YAMATO
simpleXpathMakeTag(xmlNode * node,const char * xpath,const tagXpathMakeTagSpec * spec,void * userData)25a086aff1SMasatake YAMATO static void simpleXpathMakeTag (xmlNode *node,
26513a7223SMasatake YAMATO const char *xpath,
27a086aff1SMasatake YAMATO const tagXpathMakeTagSpec *spec,
28a086aff1SMasatake YAMATO void *userData)
29a086aff1SMasatake YAMATO {
30a086aff1SMasatake YAMATO tagEntryInfo tag;
31a086aff1SMasatake YAMATO xmlChar* str;
3276a4ccb4SMasatake YAMATO char *path;
3327542d8bSMasatake YAMATO int kind;
34a086aff1SMasatake YAMATO
35a086aff1SMasatake YAMATO str = xmlNodeGetContent(node);
36a086aff1SMasatake YAMATO if (str == NULL)
37a086aff1SMasatake YAMATO return;
38a086aff1SMasatake YAMATO
3927542d8bSMasatake YAMATO if (spec->kind == KIND_GHOST_INDEX && spec->decideKind)
40513a7223SMasatake YAMATO kind = spec->decideKind (node, xpath, spec, userData);
4127542d8bSMasatake YAMATO else
4227542d8bSMasatake YAMATO kind = spec->kind;
4327542d8bSMasatake YAMATO Assert (kind != KIND_GHOST_INDEX);
4427542d8bSMasatake YAMATO
4524b256e3SMasatake YAMATO if (spec->role == ROLE_DEFINITION_INDEX)
4627542d8bSMasatake YAMATO initTagEntry (&tag, (char *)str, kind);
47a086aff1SMasatake YAMATO else if (isXtagEnabled(XTAG_REFERENCE_TAGS))
48a086aff1SMasatake YAMATO initRefTagEntry (&tag, (char *)str,
4927542d8bSMasatake YAMATO kind,
50a086aff1SMasatake YAMATO spec->role);
51a086aff1SMasatake YAMATO else
52a086aff1SMasatake YAMATO goto out;
53a086aff1SMasatake YAMATO
54a086aff1SMasatake YAMATO
5572b5694cSMasatake YAMATO tag.lineNumber = XML_GET_LINE (node);
56a086aff1SMasatake YAMATO tag.filePosition = getInputFilePositionForLine (tag.lineNumber);
57a086aff1SMasatake YAMATO
5876a4ccb4SMasatake YAMATO path = (char *)xmlGetNodePath (node);
5976a4ccb4SMasatake YAMATO tag.extensionFields.xpath = path;
6076a4ccb4SMasatake YAMATO
61a086aff1SMasatake YAMATO if (spec->make)
62513a7223SMasatake YAMATO spec->make (node, xpath, spec, &tag, userData);
63a086aff1SMasatake YAMATO else
64a086aff1SMasatake YAMATO makeTagEntry (&tag);
65a086aff1SMasatake YAMATO
6676a4ccb4SMasatake YAMATO if (path)
6776a4ccb4SMasatake YAMATO xmlFree (path);
68a086aff1SMasatake YAMATO out:
69a086aff1SMasatake YAMATO xmlFree (str);
70a086aff1SMasatake YAMATO }
71a086aff1SMasatake YAMATO
addTagXpath(const langType language CTAGS_ATTR_UNUSED,tagXpathTable * xpathTable)728ccb7ee9SJiří Techet extern void addTagXpath (const langType language CTAGS_ATTR_UNUSED, tagXpathTable *xpathTable)
73a086aff1SMasatake YAMATO {
74a086aff1SMasatake YAMATO Assert (xpathTable->xpath);
75a086aff1SMasatake YAMATO Assert (!xpathTable->xpathCompiled);
76a086aff1SMasatake YAMATO
77a086aff1SMasatake YAMATO verbose ("compile a xpath expression: %s\n", (xmlChar *)xpathTable->xpath);
78a086aff1SMasatake YAMATO xpathTable->xpathCompiled = xmlXPathCompile ((xmlChar *)xpathTable->xpath);
79a086aff1SMasatake YAMATO if (!xpathTable->xpathCompiled)
80a086aff1SMasatake YAMATO error (WARNING, "Failed to compile the Xpath expression: %s", xpathTable->xpath);
81a086aff1SMasatake YAMATO }
82a086aff1SMasatake YAMATO
removeTagXpath(const langType language CTAGS_ATTR_UNUSED,tagXpathTable * xpathTable)83eb480042SMasatake YAMATO extern void removeTagXpath (const langType language CTAGS_ATTR_UNUSED, tagXpathTable *xpathTable)
84eb480042SMasatake YAMATO {
85eb480042SMasatake YAMATO if (xpathTable->xpathCompiled)
86eb480042SMasatake YAMATO {
87eb480042SMasatake YAMATO xmlXPathFreeCompExpr (xpathTable->xpathCompiled);
88eb480042SMasatake YAMATO xpathTable->xpathCompiled = NULL;
89eb480042SMasatake YAMATO }
90eb480042SMasatake YAMATO }
91eb480042SMasatake YAMATO
findXMLTagsCore(xmlXPathContext * ctx,xmlNode * root,const tagXpathTableTable * xpathTableTable,void * userData)92a086aff1SMasatake YAMATO static void findXMLTagsCore (xmlXPathContext *ctx, xmlNode *root,
93a086aff1SMasatake YAMATO const tagXpathTableTable *xpathTableTable,
94971e7196SMasatake YAMATO void *userData)
95a086aff1SMasatake YAMATO {
96e5f9cc19SMasatake YAMATO unsigned int i;
97e5f9cc19SMasatake YAMATO int j;
98a086aff1SMasatake YAMATO xmlNode * node;
99a086aff1SMasatake YAMATO
100a086aff1SMasatake YAMATO Assert (root);
101a086aff1SMasatake YAMATO Assert (xpathTableTable);
102a086aff1SMasatake YAMATO
103a086aff1SMasatake YAMATO for (i = 0; i < xpathTableTable->count; ++i)
104a086aff1SMasatake YAMATO {
105a086aff1SMasatake YAMATO xmlXPathObject *object;
106a086aff1SMasatake YAMATO xmlNodeSet *set;
107a086aff1SMasatake YAMATO const tagXpathTable *elt = xpathTableTable->table + i;
108a086aff1SMasatake YAMATO
109a086aff1SMasatake YAMATO if (! elt->xpathCompiled)
110a086aff1SMasatake YAMATO continue;
111a086aff1SMasatake YAMATO
112a086aff1SMasatake YAMATO #if 0
113a086aff1SMasatake YAMATO /* Older version of libxml2 doesn't have xmlXPathSetContextNode. */
114a086aff1SMasatake YAMATO if (xmlXPathSetContextNode (root, ctx) != 0)
115a086aff1SMasatake YAMATO {
116a086aff1SMasatake YAMATO error (WARNING, "Failed to set node to XpathContext");
117a086aff1SMasatake YAMATO return;
118a086aff1SMasatake YAMATO }
119a086aff1SMasatake YAMATO #else
120a086aff1SMasatake YAMATO ctx->node = root;
121a086aff1SMasatake YAMATO #endif
122a086aff1SMasatake YAMATO
123a086aff1SMasatake YAMATO object = xmlXPathCompiledEval (elt->xpathCompiled, ctx);
124a086aff1SMasatake YAMATO if (!object)
125a086aff1SMasatake YAMATO continue;
126a086aff1SMasatake YAMATO
127a086aff1SMasatake YAMATO set = object->nodesetval;
128a086aff1SMasatake YAMATO
129a086aff1SMasatake YAMATO if (set)
130a086aff1SMasatake YAMATO {
131a391a8f5SMasatake YAMATO for (j = 0; j < xmlXPathNodeSetGetLength (set); ++j)
132a086aff1SMasatake YAMATO {
133a391a8f5SMasatake YAMATO node = xmlXPathNodeSetItem(set, j);
134a086aff1SMasatake YAMATO if (elt->specType == LXPATH_TABLE_DO_MAKE)
135971e7196SMasatake YAMATO simpleXpathMakeTag (node, elt->xpath, &(elt->spec.makeTagSpec), userData);
136a086aff1SMasatake YAMATO else
137513a7223SMasatake YAMATO elt->spec.recurSpec.enter (node, elt->xpath, &(elt->spec.recurSpec), ctx, userData);
138a086aff1SMasatake YAMATO }
139a086aff1SMasatake YAMATO }
140a086aff1SMasatake YAMATO xmlXPathFreeObject (object);
141a086aff1SMasatake YAMATO }
142a086aff1SMasatake YAMATO }
143a086aff1SMasatake YAMATO
suppressWarning(void * ctx CTAGS_ATTR_UNUSED,const char * msg CTAGS_ATTR_UNUSED,...)1448ccb7ee9SJiří Techet static void suppressWarning (void *ctx CTAGS_ATTR_UNUSED, const char *msg CTAGS_ATTR_UNUSED, ...)
1457900fd5dSMasatake YAMATO {
1467900fd5dSMasatake YAMATO }
1477900fd5dSMasatake YAMATO
makeXMLDoc(void)14831cb4225SMasatake YAMATO static xmlDocPtr makeXMLDoc (void)
14931cb4225SMasatake YAMATO {
15031cb4225SMasatake YAMATO const unsigned char* data;
15131cb4225SMasatake YAMATO size_t size;
15262c9a9aaSMasatake YAMATO xmlDocPtr doc;
15331cb4225SMasatake YAMATO
154eab04be2SMasatake YAMATO doc = getInputFileUserData ();
155eab04be2SMasatake YAMATO if (doc)
156eab04be2SMasatake YAMATO {
157eab04be2SMasatake YAMATO verbose ("reuse xml doc data\n");
158eab04be2SMasatake YAMATO return doc;
159eab04be2SMasatake YAMATO }
160eab04be2SMasatake YAMATO
161c0732dcaSMasatake YAMATO data = getInputFileData (&size);
16231cb4225SMasatake YAMATO if (data)
16331cb4225SMasatake YAMATO {
164*27650e32SMasatake YAMATO xmlSetGenericErrorFunc (NULL, suppressWarning);
16531cb4225SMasatake YAMATO xmlLineNumbersDefault (1);
16631cb4225SMasatake YAMATO doc = xmlParseMemory((const char*)data, size);
16731cb4225SMasatake YAMATO }
16831cb4225SMasatake YAMATO
16931cb4225SMasatake YAMATO return doc;
17031cb4225SMasatake YAMATO }
17131cb4225SMasatake YAMATO
findXMLTagsFull(xmlXPathContext * ctx,xmlNode * root,int tableTableIndex,void (* runAfter)(xmlXPathContext *,xmlNode *,void *),void * userData)172f511f9ebSMasatake YAMATO extern void findXMLTagsFull (xmlXPathContext *ctx, xmlNode *root,
1730fde73e0SMasatake YAMATO int tableTableIndex,
174f511f9ebSMasatake YAMATO void (* runAfter) (xmlXPathContext *, xmlNode *, void *),
175971e7196SMasatake YAMATO void *userData)
176a086aff1SMasatake YAMATO {
177ce990805SThomas Braun bool usedAsEntryPoint = false;
178a086aff1SMasatake YAMATO xmlDocPtr doc = NULL;
179a086aff1SMasatake YAMATO
1800fde73e0SMasatake YAMATO const langType lang = getInputLanguage();
1810fde73e0SMasatake YAMATO const tagXpathTableTable *xpathTableTable
1820fde73e0SMasatake YAMATO = getXpathTableTable (lang, tableTableIndex);
1830fde73e0SMasatake YAMATO
184a086aff1SMasatake YAMATO if (ctx == NULL)
185a086aff1SMasatake YAMATO {
186ce990805SThomas Braun usedAsEntryPoint = true;
187a086aff1SMasatake YAMATO
188a086aff1SMasatake YAMATO findRegexTags ();
1897900fd5dSMasatake YAMATO
19031cb4225SMasatake YAMATO doc = makeXMLDoc ();
19131cb4225SMasatake YAMATO
192a086aff1SMasatake YAMATO if (doc == NULL)
193a086aff1SMasatake YAMATO {
194a086aff1SMasatake YAMATO verbose ("could not parse %s as a XML file\n", getInputFileName());
195a086aff1SMasatake YAMATO return;
196a086aff1SMasatake YAMATO }
197a086aff1SMasatake YAMATO
198a086aff1SMasatake YAMATO ctx = xmlXPathNewContext (doc);
199a086aff1SMasatake YAMATO if (ctx == NULL)
200a086aff1SMasatake YAMATO error (FATAL, "failed to make a new xpath context for %s", getInputFileName());
201a086aff1SMasatake YAMATO
202a086aff1SMasatake YAMATO root = xmlDocGetRootElement(doc);
203a086aff1SMasatake YAMATO if (root == NULL)
204a086aff1SMasatake YAMATO {
205a086aff1SMasatake YAMATO verbose ("could not get the root node for %s\n", getInputFileName());
206a086aff1SMasatake YAMATO goto out;
207a086aff1SMasatake YAMATO }
208a086aff1SMasatake YAMATO }
209a086aff1SMasatake YAMATO
210971e7196SMasatake YAMATO findXMLTagsCore (ctx, root, xpathTableTable, userData);
211f511f9ebSMasatake YAMATO if (runAfter)
212f511f9ebSMasatake YAMATO (* runAfter) (ctx, root, userData);
213a086aff1SMasatake YAMATO
214a086aff1SMasatake YAMATO out:
215b31c2380SMasatake YAMATO if (usedAsEntryPoint)
216a086aff1SMasatake YAMATO {
217a086aff1SMasatake YAMATO xmlXPathFreeContext (ctx);
218eab04be2SMasatake YAMATO
219eab04be2SMasatake YAMATO if (doc != getInputFileUserData ())
220a086aff1SMasatake YAMATO xmlFreeDoc (doc);
221a086aff1SMasatake YAMATO }
222a086aff1SMasatake YAMATO }
223a086aff1SMasatake YAMATO
224a086aff1SMasatake YAMATO #else
225a086aff1SMasatake YAMATO
addTagXpath(const langType language,tagXpathTable * xpathTable)226a086aff1SMasatake YAMATO extern void addTagXpath (const langType language, tagXpathTable *xpathTable)
227a086aff1SMasatake YAMATO {
228a086aff1SMasatake YAMATO xpathTable->xpathCompiled = NULL;
229a086aff1SMasatake YAMATO }
230a086aff1SMasatake YAMATO
removeTagXpath(const langType language CTAGS_ATTR_UNUSED,tagXpathTable * xpathTable CTAGS_ATTR_UNUSED)231eb480042SMasatake YAMATO extern void removeTagXpath (const langType language CTAGS_ATTR_UNUSED, tagXpathTable *xpathTable CTAGS_ATTR_UNUSED)
232eb480042SMasatake YAMATO {
233eb480042SMasatake YAMATO }
234eb480042SMasatake YAMATO
findXMLTagsFull(xmlXPathContext * ctx,xmlNode * root,int tableTableIndex,void (* runAfter)(xmlXPathContext *,xmlNode *,void *),void * userData)235f511f9ebSMasatake YAMATO extern void findXMLTagsFull (xmlXPathContext *ctx, xmlNode *root,
236971e7196SMasatake YAMATO int tableTableIndex,
237f511f9ebSMasatake YAMATO void (* runAfter) (xmlXPathContext *, xmlNode *, void *),
238971e7196SMasatake YAMATO void *userData)
239a086aff1SMasatake YAMATO {
240a086aff1SMasatake YAMATO }
241a086aff1SMasatake YAMATO
242a086aff1SMasatake YAMATO #endif
243f511f9ebSMasatake YAMATO
findXMLTags(xmlXPathContext * ctx,xmlNode * root,int tableTableIndex,void * userData)244f511f9ebSMasatake YAMATO extern void findXMLTags (xmlXPathContext *ctx, xmlNode *root,
245f511f9ebSMasatake YAMATO int tableTableIndex,
246f511f9ebSMasatake YAMATO void *userData)
247f511f9ebSMasatake YAMATO {
248f511f9ebSMasatake YAMATO findXMLTagsFull (ctx, root, tableTableIndex, NULL, userData);
249f511f9ebSMasatake YAMATO }
250