1c3416965SMasatake YAMATO /*
2c3416965SMasatake YAMATO *
3c3416965SMasatake YAMATO * Copyright (c) 2019, Masatake YAMATO
4c3416965SMasatake YAMATO * Copyright (c) 2019, Red Hat, K.K.
5c3416965SMasatake YAMATO *
6c3416965SMasatake YAMATO * This source code is released for free distribution under the terms of the
7c3416965SMasatake YAMATO * GNU General Public License version 2 or (at your option) any later version.
8c3416965SMasatake YAMATO *
9c3416965SMasatake YAMATO * This module contains functions for generating tags for id="..." in a XML file
10c3416965SMasatake YAMATO */
11c3416965SMasatake YAMATO
12c3416965SMasatake YAMATO #include "general.h" /* must always come first */
13c3416965SMasatake YAMATO #include "entry.h"
14c3416965SMasatake YAMATO #include "options.h"
15c3416965SMasatake YAMATO #include "parse.h"
16c3416965SMasatake YAMATO #include "read.h"
17c3416965SMasatake YAMATO #include "routines.h"
18c3416965SMasatake YAMATO #include "selectors.h"
19bbc76549SMasatake YAMATO #include "subparser.h"
20bbc76549SMasatake YAMATO #include "xml.h"
21bbc76549SMasatake YAMATO
22bbc76549SMasatake YAMATO static void makeTagWithNotification (xmlNode *node,
23bbc76549SMasatake YAMATO const char *xpath,
24bbc76549SMasatake YAMATO const tagXpathMakeTagSpec *spec,
25bbc76549SMasatake YAMATO tagEntryInfo *tag,
26bbc76549SMasatake YAMATO void *userData);
27c3416965SMasatake YAMATO
28c3416965SMasatake YAMATO typedef enum {
29c3416965SMasatake YAMATO K_ID,
30b0667671SMasatake YAMATO K_NSPREFIX,
31ce60e3e5SMasatake YAMATO K_ROOT,
32c3416965SMasatake YAMATO } xmlKind;
33c3416965SMasatake YAMATO
34ce60e3e5SMasatake YAMATO #define ROOT_ELT_LETTER 'r'
35ce60e3e5SMasatake YAMATO static const char ROOT_ELT_LETTER_STR[2] = {ROOT_ELT_LETTER, '\0'};
36c3416965SMasatake YAMATO static kindDefinition XmlKinds [] = {
37c3416965SMasatake YAMATO { true, 'i', "id", "id attributes" },
38b0667671SMasatake YAMATO { true, 'n', "nsprefix", "namespace prefixes" },
39ce60e3e5SMasatake YAMATO { true, ROOT_ELT_LETTER, "root", "root elements" },
40c3416965SMasatake YAMATO };
41c3416965SMasatake YAMATO
42c3416965SMasatake YAMATO enum xmlXpathTables {
43c3416965SMasatake YAMATO TABLE_MAIN,
44b0667671SMasatake YAMATO TABLE_ID,
45c3416965SMasatake YAMATO };
46c3416965SMasatake YAMATO
47b0667671SMasatake YAMATO typedef enum {
48b0667671SMasatake YAMATO F_NS_URI,
49b0667671SMasatake YAMATO } xmlField;
50b0667671SMasatake YAMATO
51b0667671SMasatake YAMATO static fieldDefinition XmlFields [] = {
52b0667671SMasatake YAMATO {
53b0667671SMasatake YAMATO .name = "uri",
54b0667671SMasatake YAMATO .description = "uri associated with name prefix",
55b0667671SMasatake YAMATO .enabled = true,
56b0667671SMasatake YAMATO }
57b0667671SMasatake YAMATO };
58b0667671SMasatake YAMATO
59b0667671SMasatake YAMATO static void findNsPrefix (xmlNode *node,
60b0667671SMasatake YAMATO const char *xpath,
61b0667671SMasatake YAMATO const struct sTagXpathRecurSpec *spec,
62b0667671SMasatake YAMATO xmlXPathContext *ctx,
63b0667671SMasatake YAMATO void *userData);
64b0667671SMasatake YAMATO
65c3416965SMasatake YAMATO static tagXpathTable XmlXpathMainTable [] = {
66b0667671SMasatake YAMATO { "//*",
67b0667671SMasatake YAMATO LXPATH_TABLE_DO_RECUR,
68b0667671SMasatake YAMATO { .recurSpec = { .enter = findNsPrefix, .nextTable = TABLE_ID } }
69b0667671SMasatake YAMATO },
70b0667671SMasatake YAMATO };
71b0667671SMasatake YAMATO
72b0667671SMasatake YAMATO static tagXpathTable XmlXpathIdTable [] = {
73b0667671SMasatake YAMATO { "./@id",
74c3416965SMasatake YAMATO LXPATH_TABLE_DO_MAKE,
75bbc76549SMasatake YAMATO { .makeTagSpec = { K_ID, ROLE_DEFINITION_INDEX,
76bbc76549SMasatake YAMATO .make = makeTagWithNotification,} }
77c3416965SMasatake YAMATO },
78c3416965SMasatake YAMATO };
79c3416965SMasatake YAMATO
80c3416965SMasatake YAMATO static tagXpathTableTable xmlXpathTableTable[] = {
81c3416965SMasatake YAMATO [TABLE_MAIN] = { ARRAY_AND_SIZE (XmlXpathMainTable) },
82b0667671SMasatake YAMATO [TABLE_ID] = { ARRAY_AND_SIZE (XmlXpathIdTable) },
83c3416965SMasatake YAMATO };
84c3416965SMasatake YAMATO
85ce60e3e5SMasatake YAMATO /* Pick up the root element specifier from "<!DOCTYPE...", and
86ce60e3e5SMasatake YAMATO * run DTD parser for the "[" ... "]>" area.
87ce60e3e5SMasatake YAMATO *
88ce60e3e5SMasatake YAMATO * optlib2c translates the following .ctags elements:
89ce60e3e5SMasatake YAMATO * ==========================================================
90ce60e3e5SMasatake YAMATO * --langdef=Xml
91ce60e3e5SMasatake YAMATO * --kinddef-Xml=r,root,root elements
92ce60e3e5SMasatake YAMATO * --mline-regex-Xml=/<!DOCTYPE[[:space:]]+([a-zA-Z0-9]+)[[:space:]]+[^[]+\[((.|[\n])+)\]>/\1/r/{mgroup=1}{_guest=DTD,2start,2end}
93ce60e3e5SMasatake YAMATO * ==========================================================
94ce60e3e5SMasatake YAMATO */
95ce60e3e5SMasatake YAMATO static tagRegexTable XmlTagRegexTable [] = {
96ce60e3e5SMasatake YAMATO {"<!DOCTYPE[[:space:]]+([a-zA-Z0-9]+)[[:space:]]+[^[]*\\[((.|[\n])+)\\]>", "\\1",
97ce60e3e5SMasatake YAMATO ROOT_ELT_LETTER_STR, "{mgroup=1}{_guest=DTD,2start,2end}", NULL, true},
98ce60e3e5SMasatake YAMATO };
99ce60e3e5SMasatake YAMATO
makeTagWithNotificationCommon(tagEntryInfo * tag,xmlNode * node)100bbc76549SMasatake YAMATO static int makeTagWithNotificationCommon (tagEntryInfo *tag,
101bbc76549SMasatake YAMATO xmlNode *node)
102bbc76549SMasatake YAMATO {
103bbc76549SMasatake YAMATO int n = makeTagEntry (tag);
104bbc76549SMasatake YAMATO
105bbc76549SMasatake YAMATO subparser *sub;
106bbc76549SMasatake YAMATO foreachSubparser (sub, false)
107bbc76549SMasatake YAMATO {
108bbc76549SMasatake YAMATO xmlSubparser *xmlsub = (xmlSubparser *)sub;
109bbc76549SMasatake YAMATO
110bbc76549SMasatake YAMATO if (xmlsub->makeTagEntryWithNodeNotify)
111bbc76549SMasatake YAMATO {
112bbc76549SMasatake YAMATO enterSubparser(sub);
113bbc76549SMasatake YAMATO xmlsub->makeTagEntryWithNodeNotify (xmlsub, node, tag);
114bbc76549SMasatake YAMATO leaveSubparser();
115bbc76549SMasatake YAMATO }
116bbc76549SMasatake YAMATO }
117bbc76549SMasatake YAMATO return n;
118bbc76549SMasatake YAMATO }
119bbc76549SMasatake YAMATO
makeTagWithNotification(xmlNode * node,const char * xpath CTAGS_ATTR_UNUSED,const tagXpathMakeTagSpec * spec CTAGS_ATTR_UNUSED,tagEntryInfo * tag,void * userData CTAGS_ATTR_UNUSED)120bbc76549SMasatake YAMATO static void makeTagWithNotification (xmlNode *node,
121bbc76549SMasatake YAMATO const char *xpath CTAGS_ATTR_UNUSED,
122bbc76549SMasatake YAMATO const tagXpathMakeTagSpec *spec CTAGS_ATTR_UNUSED,
123bbc76549SMasatake YAMATO tagEntryInfo *tag,
124bbc76549SMasatake YAMATO void *userData CTAGS_ATTR_UNUSED)
125bbc76549SMasatake YAMATO {
126bbc76549SMasatake YAMATO makeTagWithNotificationCommon (tag, node);
127bbc76549SMasatake YAMATO }
128bbc76549SMasatake YAMATO
makeNsPrefixTag(const char * name,xmlNode * node,xmlNsPtr ns)129b0667671SMasatake YAMATO static int makeNsPrefixTag (const char *name, xmlNode *node, xmlNsPtr ns)
130b0667671SMasatake YAMATO {
131b0667671SMasatake YAMATO int n = CORK_NIL;
132b0667671SMasatake YAMATO tagEntryInfo tag;
1330376b965SMasatake YAMATO vString *anon = NULL;
134b0667671SMasatake YAMATO
1350376b965SMasatake YAMATO if (name)
136b0667671SMasatake YAMATO initTagEntry (&tag, name, K_NSPREFIX);
1370376b965SMasatake YAMATO else
1380376b965SMasatake YAMATO {
1390376b965SMasatake YAMATO anon = anonGenerateNew ("ns", K_NSPREFIX);
1400376b965SMasatake YAMATO initTagEntry (&tag, vStringValue (anon), K_NSPREFIX);
1410376b965SMasatake YAMATO markTagExtraBit (&tag, XTAG_ANONYMOUS);
1420376b965SMasatake YAMATO }
143b0667671SMasatake YAMATO /* TODO
144b0667671SMasatake YAMATO * - move this code block to lxpath.c.
145b0667671SMasatake YAMATO * - adjust the line number for nsprefixes forward. */
146b0667671SMasatake YAMATO tag.lineNumber = XML_GET_LINE (node);
147b0667671SMasatake YAMATO tag.filePosition = getInputFilePositionForLine (tag.lineNumber);
148b0667671SMasatake YAMATO char *p = (char *)xmlGetNodePath (node);
149b0667671SMasatake YAMATO if (ns->href && *ns->href)
150*aa4def17SMasatake YAMATO attachParserField (&tag, false, XmlFields [F_NS_URI].ftype, (char *)ns->href);
151b0667671SMasatake YAMATO
152bbc76549SMasatake YAMATO n = makeTagWithNotificationCommon (&tag, node);
153b0667671SMasatake YAMATO if (p)
154b0667671SMasatake YAMATO xmlFree (p);
1550376b965SMasatake YAMATO if (anon)
1560376b965SMasatake YAMATO vStringDelete (anon);
157b0667671SMasatake YAMATO
158b0667671SMasatake YAMATO return n;
159b0667671SMasatake YAMATO }
160b0667671SMasatake YAMATO
findNsPrefix(xmlNode * node,const char * xpath,const struct sTagXpathRecurSpec * spec,xmlXPathContext * ctx,void * userData)161b0667671SMasatake YAMATO static void findNsPrefix (xmlNode *node,
162b0667671SMasatake YAMATO const char *xpath,
163b0667671SMasatake YAMATO const struct sTagXpathRecurSpec *spec,
164b0667671SMasatake YAMATO xmlXPathContext *ctx,
165b0667671SMasatake YAMATO void *userData)
166b0667671SMasatake YAMATO {
167b0667671SMasatake YAMATO for (xmlNsPtr ns = node->nsDef; ns; ns = ns->next)
168b0667671SMasatake YAMATO makeNsPrefixTag ((char *)ns->prefix, node, ns);
169b0667671SMasatake YAMATO
170b0667671SMasatake YAMATO findXMLTags (ctx, node, spec->nextTable, userData);
171b0667671SMasatake YAMATO }
172b0667671SMasatake YAMATO
runAfter(xmlXPathContext * ctx,xmlNode * root,void * user_data)173f511f9ebSMasatake YAMATO static void runAfter (xmlXPathContext *ctx, xmlNode *root, void *user_data)
174f511f9ebSMasatake YAMATO {
175f511f9ebSMasatake YAMATO subparser *sub;
176f511f9ebSMasatake YAMATO foreachSubparser (sub, false)
177f511f9ebSMasatake YAMATO {
178f511f9ebSMasatake YAMATO xmlSubparser *xmlsub = (xmlSubparser *)sub;
179f511f9ebSMasatake YAMATO if (xmlsub->runXPathEngine)
180f511f9ebSMasatake YAMATO {
181f511f9ebSMasatake YAMATO enterSubparser(sub);
182f511f9ebSMasatake YAMATO xmlsub->runXPathEngine (xmlsub, ctx, root);
183f511f9ebSMasatake YAMATO leaveSubparser();
184f511f9ebSMasatake YAMATO }
185f511f9ebSMasatake YAMATO }
186f511f9ebSMasatake YAMATO }
187f511f9ebSMasatake YAMATO
188c3416965SMasatake YAMATO static void
findXmlTags(void)189c3416965SMasatake YAMATO findXmlTags (void)
190c3416965SMasatake YAMATO {
191f511f9ebSMasatake YAMATO findXMLTagsFull (NULL, NULL, TABLE_MAIN, runAfter, NULL);
192c3416965SMasatake YAMATO }
193c3416965SMasatake YAMATO
194c3416965SMasatake YAMATO extern parserDefinition*
XmlParser(void)195c3416965SMasatake YAMATO XmlParser (void)
196c3416965SMasatake YAMATO {
197c3416965SMasatake YAMATO static const char *const extensions [] = { "xml", NULL };
198c3416965SMasatake YAMATO parserDefinition* const def = parserNew ("XML");
199c3416965SMasatake YAMATO static selectLanguage selectors[] = { selectByXpathFileSpec, NULL };
200c3416965SMasatake YAMATO
201c3416965SMasatake YAMATO def->kindTable = XmlKinds;
202c3416965SMasatake YAMATO def->kindCount = ARRAY_SIZE (XmlKinds);
203c3416965SMasatake YAMATO def->extensions = extensions;
204c3416965SMasatake YAMATO def->parser = findXmlTags;
205c3416965SMasatake YAMATO def->tagXpathTableTable = xmlXpathTableTable;
206c3416965SMasatake YAMATO def->tagXpathTableCount = ARRAY_SIZE (xmlXpathTableTable);
207c3416965SMasatake YAMATO def->selectLanguage = selectors;
208b0667671SMasatake YAMATO def->fieldTable = XmlFields;
209b0667671SMasatake YAMATO def->fieldCount = ARRAY_SIZE (XmlFields);
210ce60e3e5SMasatake YAMATO def->tagRegexTable = XmlTagRegexTable;
211ce60e3e5SMasatake YAMATO def->tagRegexCount = ARRAY_SIZE(XmlTagRegexTable);
212b0667671SMasatake YAMATO
213c3416965SMasatake YAMATO return def;
214c3416965SMasatake YAMATO }
215