1 /*
2 *
3 * Copyright (c) 2016, Masatake YAMATO
4 * Copyright (c) 2016, Red Hat, K.K.
5 *
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License version 2 or (at your option) any later version.
8 *
9 * This module contains functions for generating tags for RelaxNG.
10 *
11 * https://www.oasis-open.org/committees/relax-ng/spec-20010811.html
12 *
13 */
14
15 #include "general.h" /* must always come first */
16 #include "entry.h"
17 #include "parse.h"
18 #include "read.h"
19 #include "xml.h"
20
21 typedef enum {
22 K_ELEMENT,
23 K_ATTRIBUTE,
24 K_NAMED_PATTERN,
25 } relaxngKind;
26
27 static kindDefinition RelaxNGKinds [] = {
28 { true, 'e', "element", "elements" },
29 { true, 'a', "attribute", "attributes" },
30 { true, 'n', "namedPattern", "named patterns" },
31 };
32
33 enum relaxngXpathTable {
34 TABLE_MAIN, TABLE_ELEMENT_NAME, TABLE_PATTERN, TABLE_GRAMMAR, TABLE_DEFINE_NAME,
35 };
36
37 static void relaxngMakeAndFindTagsUnderElement (xmlNode *node,
38 const char *xpath,
39 const struct sTagXpathRecurSpec *spec,
40 xmlXPathContext *ctx,
41 void *userData);
42 static void relaxngMakeAndFindTagsUnderDefine (xmlNode *node,
43 const char *xpath,
44 const struct sTagXpathRecurSpec *spec,
45 xmlXPathContext *ctx,
46 void *userData);
47
48 static void relaxngFindTags (xmlNode *node,
49 const char *xpath,
50 const struct sTagXpathRecurSpec *spec,
51 xmlXPathContext *ctx,
52 void *userData);
53
54
55 static tagXpathTable relaxngXpathMainTable [] = {
56 { "/*[local-name()='element']",
57 LXPATH_TABLE_DO_RECUR,
58 { .recurSpec = { relaxngMakeAndFindTagsUnderElement, TABLE_PATTERN } }
59 },
60 { "/*[local-name()='grammar']",
61 LXPATH_TABLE_DO_RECUR,
62 { .recurSpec = { relaxngFindTags, TABLE_GRAMMAR } }
63 },
64 };
65
66 static void makeTagWithScope (xmlNode *node,
67 const char *xpath,
68 const struct sTagXpathMakeTagSpec *spec,
69 struct sTagEntryInfo *tag,
70 void *userData);
71
72 static tagXpathTable relaxngXpathPatternTable [] = {
73 { "./*[local-name()='element']",
74 LXPATH_TABLE_DO_RECUR,
75 { .recurSpec = { relaxngMakeAndFindTagsUnderElement, TABLE_PATTERN } }
76 },
77 { "./*[local-name()='attribute']/@name",
78 LXPATH_TABLE_DO_MAKE,
79 { .makeTagSpec = { K_ATTRIBUTE, ROLE_DEFINITION_INDEX,
80 makeTagWithScope } }
81 },
82 { "./*[not(local-name()='element')][not(local-name()='attribute')]",
83 LXPATH_TABLE_DO_RECUR,
84 { .recurSpec = { relaxngFindTags, TABLE_PATTERN } }
85 },
86 };
87
88
89 static void makeTagWithUpdatingScope (xmlNode *node,
90 const char *xpath,
91 const struct sTagXpathMakeTagSpec *spec,
92 struct sTagEntryInfo *tag,
93 void *userData);
94
95 static tagXpathTable relaxngXpathElementNameTable [] = {
96 { "@name",
97 LXPATH_TABLE_DO_MAKE,
98 { .makeTagSpec = { K_ELEMENT, ROLE_DEFINITION_INDEX,
99 makeTagWithUpdatingScope } }
100 },
101 };
102
103 static tagXpathTable relaxngXpathGrammerTable [] = {
104 { "./*[local-name()='start']",
105 LXPATH_TABLE_DO_RECUR,
106 { .recurSpec = { relaxngFindTags, TABLE_PATTERN } }
107 },
108 { "./*[local-name()='define']",
109 LXPATH_TABLE_DO_RECUR,
110 { .recurSpec = { relaxngMakeAndFindTagsUnderDefine, TABLE_PATTERN } }
111 }
112 };
113
114 static tagXpathTable relaxngXpathDefineNameTable [] = {
115 { "@name",
116 LXPATH_TABLE_DO_MAKE,
117 { .makeTagSpec = { K_NAMED_PATTERN, ROLE_DEFINITION_INDEX,
118 makeTagWithUpdatingScope } }
119 },
120 };
121
122 static tagXpathTableTable relaxngXpathTableTable[] = {
123 [TABLE_MAIN] = { ARRAY_AND_SIZE (relaxngXpathMainTable) },
124 [TABLE_ELEMENT_NAME] = { ARRAY_AND_SIZE (relaxngXpathElementNameTable) },
125 [TABLE_PATTERN] = { ARRAY_AND_SIZE (relaxngXpathPatternTable) },
126 [TABLE_GRAMMAR] = { ARRAY_AND_SIZE (relaxngXpathGrammerTable) },
127 [TABLE_DEFINE_NAME] = { ARRAY_AND_SIZE (relaxngXpathDefineNameTable) },
128 };
129
130
131 static void
relaxngMakeAndFindTags(xmlNode * node,const char * xpath,const struct sTagXpathRecurSpec * spec,xmlXPathContext * ctx,int nextTable,void * userData)132 relaxngMakeAndFindTags(xmlNode *node,
133 const char *xpath,
134 const struct sTagXpathRecurSpec *spec,
135 xmlXPathContext *ctx,
136 int nextTable,
137 void *userData)
138 {
139 int corkIndex = *(int *)userData;
140
141 findXMLTags (ctx, node, nextTable, &corkIndex);
142
143 relaxngFindTags (node, xpath, spec, ctx, &corkIndex);
144 }
145
146 static void
relaxngMakeAndFindTagsUnderElement(xmlNode * node,const char * xpath,const struct sTagXpathRecurSpec * spec,xmlXPathContext * ctx,void * userData)147 relaxngMakeAndFindTagsUnderElement (xmlNode *node,
148 const char *xpath,
149 const struct sTagXpathRecurSpec *spec,
150 xmlXPathContext *ctx,
151 void *userData)
152 {
153 relaxngMakeAndFindTags (node, xpath, spec, ctx, TABLE_ELEMENT_NAME, userData);
154 }
155
156 static void
relaxngMakeAndFindTagsUnderDefine(xmlNode * node,const char * xpath,const struct sTagXpathRecurSpec * spec,xmlXPathContext * ctx,void * userData)157 relaxngMakeAndFindTagsUnderDefine (xmlNode *node,
158 const char *xpath,
159 const struct sTagXpathRecurSpec *spec,
160 xmlXPathContext *ctx,
161 void *userData)
162 {
163 relaxngMakeAndFindTags (node, xpath, spec, ctx, TABLE_DEFINE_NAME, userData);
164 }
165
166 static void
relaxngFindTags(xmlNode * node,const char * xpath CTAGS_ATTR_UNUSED,const struct sTagXpathRecurSpec * spec,xmlXPathContext * ctx,void * userData)167 relaxngFindTags (xmlNode *node,
168 const char *xpath CTAGS_ATTR_UNUSED,
169 const struct sTagXpathRecurSpec *spec,
170 xmlXPathContext *ctx,
171 void *userData)
172 {
173 int corkIndex = *(int *)userData;
174
175 findXMLTags (ctx, node, spec->nextTable, &corkIndex);
176 }
177
178 static void
setScope(struct sTagEntryInfo * tag,int index)179 setScope (struct sTagEntryInfo *tag, int index)
180 {
181 tag->extensionFields.scopeKindIndex = KIND_GHOST_INDEX;
182 tag->extensionFields.scopeName = NULL;
183 tag->extensionFields.scopeIndex = index;
184
185 }
186
187 static void
makeTagWithUpdatingScope(xmlNode * node CTAGS_ATTR_UNUSED,const char * xpath CTAGS_ATTR_UNUSED,const struct sTagXpathMakeTagSpec * spec CTAGS_ATTR_UNUSED,struct sTagEntryInfo * tag,void * userData)188 makeTagWithUpdatingScope (xmlNode *node CTAGS_ATTR_UNUSED,
189 const char *xpath CTAGS_ATTR_UNUSED,
190 const struct sTagXpathMakeTagSpec *spec CTAGS_ATTR_UNUSED,
191 struct sTagEntryInfo *tag,
192 void *userData)
193 {
194 int *corkIndex = userData;
195
196
197 #if 0
198 if (*corkIndex == CORK_NIL)
199 /* TODO: mark tag as an entry point */
200 ;
201 #endif
202
203 setScope (tag, *corkIndex);
204
205 *corkIndex = makeTagEntry (tag);
206 }
207
208
209 static void
findRelaxNGTags(void)210 findRelaxNGTags (void)
211 {
212 scheduleRunningBaseparser (RUN_DEFAULT_SUBPARSERS);
213 }
214
215 static void
makeTagWithScope(xmlNode * node CTAGS_ATTR_UNUSED,const char * xpath CTAGS_ATTR_UNUSED,const struct sTagXpathMakeTagSpec * spec CTAGS_ATTR_UNUSED,struct sTagEntryInfo * tag,void * userData)216 makeTagWithScope (xmlNode *node CTAGS_ATTR_UNUSED,
217 const char *xpath CTAGS_ATTR_UNUSED,
218 const struct sTagXpathMakeTagSpec *spec CTAGS_ATTR_UNUSED,
219 struct sTagEntryInfo *tag,
220 void *userData)
221 {
222 setScope (tag, *(int *)userData);
223
224 makeTagEntry (tag);
225 }
226
227 static void
runXPathEngine(xmlSubparser * s,xmlXPathContext * ctx,xmlNode * root)228 runXPathEngine(xmlSubparser *s,
229 xmlXPathContext *ctx, xmlNode *root)
230 {
231 int corkIndex = CORK_NIL;
232
233 findXMLTags (ctx, root, TABLE_MAIN, &corkIndex);
234 }
235
236 static xmlSubparser relaxngSubparser = {
237 .subparser = {
238 .direction = SUBPARSER_BI_DIRECTION,
239 },
240 .runXPathEngine = runXPathEngine,
241 };
242
243 extern parserDefinition*
RelaxNGParser(void)244 RelaxNGParser (void)
245 {
246 static const char *const extensions [] = { "rng", NULL };
247 parserDefinition* const def = parserNew ("RelaxNG");
248 /* static selectLanguage selectors[] = { selectByDTD, NULL }; */
249 static parserDependency dependencies [] = {
250 [0] = { DEPTYPE_SUBPARSER, "XML", &relaxngSubparser },
251 };
252
253 def->kindTable = RelaxNGKinds;
254 def->kindCount = ARRAY_SIZE (RelaxNGKinds);
255 def->extensions = extensions;
256 def->parser = findRelaxNGTags;
257 def->tagXpathTableTable = relaxngXpathTableTable;
258 def->tagXpathTableCount = ARRAY_SIZE (relaxngXpathTableTable);
259 def->useCork = CORK_QUEUE;
260 /* def->selectLanguage = selectors; */
261 def->dependencies = dependencies;
262 def->dependencyCount = ARRAY_SIZE (dependencies);
263
264 return def;
265 }
266