xref: /Universal-ctags/parsers/dtd.c (revision 3afb54752e930d14181e28896dcb669d3e4323b9)
1ebdab5e8SMasatake YAMATO /*
2ebdab5e8SMasatake YAMATO  *   Copyright (c) 2016, Masatake YAMATO
3ebdab5e8SMasatake YAMATO  *   Copyright (c) 2016, Red Hat, Inc.
4ebdab5e8SMasatake YAMATO  *
5ebdab5e8SMasatake YAMATO  *   This source code is released for free distribution under the terms of the
6ebdab5e8SMasatake YAMATO  *   GNU General Public License version 2 or (at your option) any later version.
7ebdab5e8SMasatake YAMATO  *
8ebdab5e8SMasatake YAMATO  *   This module contains functions for generating tags for DTD, data type
9ebdab5e8SMasatake YAMATO  *   definition explained in https://www.w3.org/TR/REC-xml/#sec-physical-struct
10ebdab5e8SMasatake YAMATO  *
11ebdab5e8SMasatake YAMATO  */
12ebdab5e8SMasatake YAMATO 
13ebdab5e8SMasatake YAMATO #include "general.h"
14ebdab5e8SMasatake YAMATO #include "tokeninfo.h"
15ebdab5e8SMasatake YAMATO 
16*3afb5475SMasatake YAMATO #include "debug.h"
17ebdab5e8SMasatake YAMATO #include "entry.h"
18ebdab5e8SMasatake YAMATO #include "keyword.h"
190d502ef0SMasatake YAMATO #include "parse.h"
20ebdab5e8SMasatake YAMATO #include "read.h"
21ebdab5e8SMasatake YAMATO #include "xtag.h"
22ebdab5e8SMasatake YAMATO 
23ebdab5e8SMasatake YAMATO 
24ebdab5e8SMasatake YAMATO static scopeSeparator DtdParameterEntrySeparators [] = {
25f92e6bf2SMasatake YAMATO 	{ KIND_WILDCARD_INDEX, "/%" },
26ebdab5e8SMasatake YAMATO };
27ebdab5e8SMasatake YAMATO 
28ebdab5e8SMasatake YAMATO static scopeSeparator DtdAttSeparators [] = {
29f92e6bf2SMasatake YAMATO 	{ KIND_WILDCARD_INDEX, "/@" },
30ebdab5e8SMasatake YAMATO };
31ebdab5e8SMasatake YAMATO 
32ebdab5e8SMasatake YAMATO typedef enum {
33ebdab5e8SMasatake YAMATO 	DTD_PARAMETER_ENTITY_ELEMENT_NAME,
34ebdab5e8SMasatake YAMATO 	DTD_PARAMETER_ENTITY_CONDITION,
35ebdab5e8SMasatake YAMATO 	DTD_PARAMETER_ENTITY_PART_OF_ATT_DEF,
36ebdab5e8SMasatake YAMATO } dtdEntityRole;
37ebdab5e8SMasatake YAMATO 
3813457258SMasatake YAMATO static roleDefinition DtdEntityRoles [] = {
39ebdab5e8SMasatake YAMATO 	{ true, "elementName", "element names" },
4026c671b5SMasatake YAMATO 	{ true, "condition",    "conditions" },
41ebdab5e8SMasatake YAMATO 	{ true, "partOfAttDef", "part of attribute definition" },
42ebdab5e8SMasatake YAMATO };
43ebdab5e8SMasatake YAMATO 
44ebdab5e8SMasatake YAMATO typedef enum {
45ebdab5e8SMasatake YAMATO 	DTD_ELEMENT_ATT_OWNER,
46ebdab5e8SMasatake YAMATO } dtdElementRole;
47ebdab5e8SMasatake YAMATO 
4813457258SMasatake YAMATO static roleDefinition DtdElementRoles [] = {
49ebdab5e8SMasatake YAMATO 	{ true, "attOwner", "attributes owner" },
50ebdab5e8SMasatake YAMATO };
51ebdab5e8SMasatake YAMATO 
52ebdab5e8SMasatake YAMATO typedef enum {
53ebdab5e8SMasatake YAMATO 	K_ENTITY,
54ebdab5e8SMasatake YAMATO 	K_PARAMETER_ENTITY,
55ebdab5e8SMasatake YAMATO 	// K_EXTERNAL_ENTITY,
56ebdab5e8SMasatake YAMATO 	// K_UNPARSED_ENTITY,
57ebdab5e8SMasatake YAMATO 	K_ELEMENT,
58ebdab5e8SMasatake YAMATO 	K_ATTRIBUTE,
59ebdab5e8SMasatake YAMATO 	K_NOTATION,
60ebdab5e8SMasatake YAMATO } dtdKind;
61ebdab5e8SMasatake YAMATO 
62e112e8abSMasatake YAMATO static kindDefinition DtdKinds [] = {
63ebdab5e8SMasatake YAMATO 	{ true, 'E', "entity",    "entities" },
64ebdab5e8SMasatake YAMATO 	{ true, 'p', "parameterEntity", "parameter entities",
65ebdab5e8SMasatake YAMATO 	  .referenceOnly = false, ATTACH_ROLES(DtdEntityRoles),
66ebdab5e8SMasatake YAMATO 	  ATTACH_SEPARATORS(DtdParameterEntrySeparators),
67ebdab5e8SMasatake YAMATO 	},
68ebdab5e8SMasatake YAMATO 	// { true, 'X', "externalEntity", "external entities" },
69ebdab5e8SMasatake YAMATO 	// { true, 'U', "unparsedEntity", "unparsed entities" },
70ebdab5e8SMasatake YAMATO 	{ true, 'e', "element",   "elements",
71ebdab5e8SMasatake YAMATO 	  .referenceOnly = false, ATTACH_ROLES(DtdElementRoles) },
72ebdab5e8SMasatake YAMATO 	{ true, 'a', "attribute", "attributes",
73ebdab5e8SMasatake YAMATO 	  ATTACH_SEPARATORS(DtdAttSeparators), },
74ebdab5e8SMasatake YAMATO 	{ true, 'n', "notation", "notations" },
75ebdab5e8SMasatake YAMATO 
76ebdab5e8SMasatake YAMATO };
77ebdab5e8SMasatake YAMATO 
78ebdab5e8SMasatake YAMATO enum {
79ebdab5e8SMasatake YAMATO 	KEYWORD_ENTITY,
80ebdab5e8SMasatake YAMATO 	KEYWORD_ELEMENT,
81ebdab5e8SMasatake YAMATO 	KEYWORD_ATTLIST,
82ebdab5e8SMasatake YAMATO 	KEYWORD_INCLUDE,
83ebdab5e8SMasatake YAMATO 	KEYWORD_IGNORE,
84ebdab5e8SMasatake YAMATO 	// KEYWORD_PUBLIC,
85ebdab5e8SMasatake YAMATO 	// KEYWORD_SYSTEM,
86ebdab5e8SMasatake YAMATO 	KEYWORD_NOTATION,
87ebdab5e8SMasatake YAMATO 	KEYWORD_FIXED,
88ebdab5e8SMasatake YAMATO 	KEYWORD_ATTR_TYPES,
89ebdab5e8SMasatake YAMATO 	KEYWORD_ATTR_DEFAULT_DECLS,
90ebdab5e8SMasatake YAMATO };
91ebdab5e8SMasatake YAMATO 
92ebdab5e8SMasatake YAMATO typedef int keywordId;
93ebdab5e8SMasatake YAMATO 
94ebdab5e8SMasatake YAMATO static const keywordTable DtdKeywordTable[] = {
95ebdab5e8SMasatake YAMATO 	{ "ENTITY",    KEYWORD_ENTITY   },
96ebdab5e8SMasatake YAMATO 	{ "ELEMENT",   KEYWORD_ELEMENT  },
97ebdab5e8SMasatake YAMATO 	{ "ATTLIST",   KEYWORD_ATTLIST },
98ebdab5e8SMasatake YAMATO 	{ "INCLUDE",   KEYWORD_INCLUDE  },
99ebdab5e8SMasatake YAMATO 	{ "IGNORE",    KEYWORD_IGNORE   },
100ebdab5e8SMasatake YAMATO 	// { "PUBLIC",    KEYWORD_PUBLIC   },
101ebdab5e8SMasatake YAMATO 	// { "SYSTEM",    KEYWORD_SYSTEM   },
102ebdab5e8SMasatake YAMATO 	{ "NOTATION",  KEYWORD_NOTATION },
103ebdab5e8SMasatake YAMATO 	{ "FIXED",     KEYWORD_FIXED    },
104ebdab5e8SMasatake YAMATO 	{ "CDATA",     KEYWORD_ATTR_TYPES },
105ebdab5e8SMasatake YAMATO 	{ "ID",        KEYWORD_ATTR_TYPES },
106ebdab5e8SMasatake YAMATO 	{ "IDREF",     KEYWORD_ATTR_TYPES },
107ebdab5e8SMasatake YAMATO 	{ "IDREFS",    KEYWORD_ATTR_TYPES },
108ebdab5e8SMasatake YAMATO 	{ "ENTITIES",  KEYWORD_ATTR_TYPES },
109ebdab5e8SMasatake YAMATO 	{ "NMTOKEN",   KEYWORD_ATTR_TYPES },
110ebdab5e8SMasatake YAMATO 	{ "NMTOKENS",  KEYWORD_ATTR_TYPES },
111ebdab5e8SMasatake YAMATO 	{ "REQUIRED",  KEYWORD_ATTR_DEFAULT_DECLS },
112ebdab5e8SMasatake YAMATO 	{ "IMPLIED",   KEYWORD_ATTR_DEFAULT_DECLS },
113ebdab5e8SMasatake YAMATO };
114ebdab5e8SMasatake YAMATO 
115ebdab5e8SMasatake YAMATO enum eTokenType {
116ebdab5e8SMasatake YAMATO 	/* 0..255 are the byte's value */
117ebdab5e8SMasatake YAMATO 	TOKEN_CLOSE = '>',
118ebdab5e8SMasatake YAMATO 	TOKEN_EOF = 256,
119ebdab5e8SMasatake YAMATO 	TOKEN_UNDEFINED,
120ebdab5e8SMasatake YAMATO 	TOKEN_KEYWORD,
121ebdab5e8SMasatake YAMATO 	TOKEN_IDENTIFIER,
122ebdab5e8SMasatake YAMATO 	TOKEN_OPEN,					/* <! */
123ebdab5e8SMasatake YAMATO 	TOKEN_STRING,
124ebdab5e8SMasatake YAMATO };
125ebdab5e8SMasatake YAMATO 
126ebdab5e8SMasatake YAMATO static void readToken (tokenInfo *const token, void *data CTAGS_ATTR_UNUSED);
127ebdab5e8SMasatake YAMATO static void clearToken (tokenInfo *token);
128ebdab5e8SMasatake YAMATO static void copyToken (tokenInfo *dest, tokenInfo *src, void *data CTAGS_ATTR_UNUSED);
129ebdab5e8SMasatake YAMATO 
130002dd246SMasatake YAMATO typedef struct sDtdToken {
131002dd246SMasatake YAMATO 	tokenInfo base;
132ebdab5e8SMasatake YAMATO 	int scopeIndex;
133002dd246SMasatake YAMATO } dtdToken;
134002dd246SMasatake YAMATO 
135002dd246SMasatake YAMATO #define DTD(TOKEN) ((dtdToken *)TOKEN)
136ebdab5e8SMasatake YAMATO 
137ebdab5e8SMasatake YAMATO static struct tokenInfoClass dtdTokenInfoClass = {
138ebdab5e8SMasatake YAMATO 	.nPreAlloc = 16,
139ebdab5e8SMasatake YAMATO 	.typeForUndefined = TOKEN_UNDEFINED,
140ebdab5e8SMasatake YAMATO 	.keywordNone      = KEYWORD_NONE,
141ebdab5e8SMasatake YAMATO 	.typeForKeyword   = TOKEN_KEYWORD,
142ebdab5e8SMasatake YAMATO 	.typeForEOF       = TOKEN_EOF,
143002dd246SMasatake YAMATO 	.extraSpace       = sizeof (dtdToken) - sizeof (tokenInfo),
144ebdab5e8SMasatake YAMATO 	.read             = readToken,
145ebdab5e8SMasatake YAMATO 	.clear            = clearToken,
146ebdab5e8SMasatake YAMATO 	.copy             = copyToken,
147ebdab5e8SMasatake YAMATO };
148ebdab5e8SMasatake YAMATO 
149ebdab5e8SMasatake YAMATO static langType Lang_dtd;
150ebdab5e8SMasatake YAMATO 
151ebdab5e8SMasatake YAMATO #define isIdentifierChar(c) (isalnum (c) || c == '-' || c == '_' || c == '.' \
152ebdab5e8SMasatake YAMATO 							 || c == ':')
153ebdab5e8SMasatake YAMATO 
newDtdToken(void)154ebdab5e8SMasatake YAMATO static tokenInfo *newDtdToken (void)
155ebdab5e8SMasatake YAMATO {
156ebdab5e8SMasatake YAMATO 	return newToken (&dtdTokenInfoClass);
157ebdab5e8SMasatake YAMATO }
158ebdab5e8SMasatake YAMATO 
clearToken(tokenInfo * token)159ebdab5e8SMasatake YAMATO static void clearToken (tokenInfo *token)
160ebdab5e8SMasatake YAMATO {
161002dd246SMasatake YAMATO 	DTD (token)->scopeIndex = CORK_NIL;
162ebdab5e8SMasatake YAMATO }
163ebdab5e8SMasatake YAMATO 
copyToken(tokenInfo * dest,tokenInfo * src,void * data CTAGS_ATTR_UNUSED)164ebdab5e8SMasatake YAMATO static void copyToken (tokenInfo *dest, tokenInfo *src, void *data CTAGS_ATTR_UNUSED)
165ebdab5e8SMasatake YAMATO {
166002dd246SMasatake YAMATO 	DTD (dest)->scopeIndex = DTD (src)->scopeIndex;
167ebdab5e8SMasatake YAMATO }
168ebdab5e8SMasatake YAMATO 
readToken(tokenInfo * const token,void * data CTAGS_ATTR_UNUSED)169ebdab5e8SMasatake YAMATO static void readToken (tokenInfo *const token, void *data CTAGS_ATTR_UNUSED)
170ebdab5e8SMasatake YAMATO {
171ebdab5e8SMasatake YAMATO 	int c, c0;
172ebdab5e8SMasatake YAMATO 
173ebdab5e8SMasatake YAMATO 	token->type		= TOKEN_UNDEFINED;
174ebdab5e8SMasatake YAMATO 	token->keyword	= KEYWORD_NONE;
175ebdab5e8SMasatake YAMATO 	vStringClear (token->string);
176ebdab5e8SMasatake YAMATO 
177ebdab5e8SMasatake YAMATO  retry:
178ebdab5e8SMasatake YAMATO 	do {
179ebdab5e8SMasatake YAMATO 		c = getcFromInputFile ();
180ebdab5e8SMasatake YAMATO 	} while (c == ' ' || c == '\t' || c == '\f' || c == '\n');
181ebdab5e8SMasatake YAMATO 
182ebdab5e8SMasatake YAMATO 	token->lineNumber   = getInputLineNumber ();
183ebdab5e8SMasatake YAMATO 	token->filePosition = getInputFilePosition ();
184ebdab5e8SMasatake YAMATO 
185ebdab5e8SMasatake YAMATO 	switch (c)
186ebdab5e8SMasatake YAMATO 	{
187ebdab5e8SMasatake YAMATO 	case EOF:
188ebdab5e8SMasatake YAMATO 		token->type = TOKEN_EOF;
189ebdab5e8SMasatake YAMATO 		break;
190ebdab5e8SMasatake YAMATO 	case ';':
191ebdab5e8SMasatake YAMATO 	case '&':
192ebdab5e8SMasatake YAMATO 	case '%':
193ebdab5e8SMasatake YAMATO 	case '>':
194ebdab5e8SMasatake YAMATO 	case '#':
195ebdab5e8SMasatake YAMATO 	case '?':
196ebdab5e8SMasatake YAMATO 	case '[':
197ebdab5e8SMasatake YAMATO 	case ']':
198ebdab5e8SMasatake YAMATO 	case '|':
199ebdab5e8SMasatake YAMATO 	case ',':
200ebdab5e8SMasatake YAMATO 	case '(':
201ebdab5e8SMasatake YAMATO 	case ')':
202ebdab5e8SMasatake YAMATO 	case '+':
203ebdab5e8SMasatake YAMATO 		token->type = c;
204ebdab5e8SMasatake YAMATO 		break;
205ebdab5e8SMasatake YAMATO 	case '<':
206ebdab5e8SMasatake YAMATO 		c0 = getcFromInputFile();
207ebdab5e8SMasatake YAMATO 		if (c0 == '!')
208ebdab5e8SMasatake YAMATO 		{
209ebdab5e8SMasatake YAMATO 			token->type = TOKEN_OPEN;
210ebdab5e8SMasatake YAMATO 			break;
211ebdab5e8SMasatake YAMATO 		}
212ebdab5e8SMasatake YAMATO 		else
213ebdab5e8SMasatake YAMATO 		{
214ebdab5e8SMasatake YAMATO 			ungetcToInputFile (c0);
215ebdab5e8SMasatake YAMATO 			token->type = c;
216ebdab5e8SMasatake YAMATO 			break;
217ebdab5e8SMasatake YAMATO 		}
218ebdab5e8SMasatake YAMATO 	case '-':
219ebdab5e8SMasatake YAMATO 		c0 = getcFromInputFile();
220ebdab5e8SMasatake YAMATO 		if (c0 == '-')
221ebdab5e8SMasatake YAMATO 		{
222ebdab5e8SMasatake YAMATO 			int c1, c2;
223ebdab5e8SMasatake YAMATO 
224ebdab5e8SMasatake YAMATO 			while ( (c1 = getcFromInputFile()) != EOF )
225ebdab5e8SMasatake YAMATO 			{
226ebdab5e8SMasatake YAMATO 				if (c1 == '-')
227ebdab5e8SMasatake YAMATO 				{
228ebdab5e8SMasatake YAMATO 					c2 = getcFromInputFile();
229ebdab5e8SMasatake YAMATO 					if (c2 == '-' || c2 == EOF)
230ebdab5e8SMasatake YAMATO 						goto retry;
231ebdab5e8SMasatake YAMATO 				}
232ebdab5e8SMasatake YAMATO 			}
233ebdab5e8SMasatake YAMATO 		}
234ebdab5e8SMasatake YAMATO 		else
235ebdab5e8SMasatake YAMATO 		{
236ebdab5e8SMasatake YAMATO 			ungetcToInputFile (c0);
237ebdab5e8SMasatake YAMATO 			token->type = c;
238ebdab5e8SMasatake YAMATO 		}
239ebdab5e8SMasatake YAMATO 		break;
240ebdab5e8SMasatake YAMATO 	case '"':
241ebdab5e8SMasatake YAMATO 	case '\'':
242ebdab5e8SMasatake YAMATO 		token->type = TOKEN_STRING;
243ebdab5e8SMasatake YAMATO 		while ((c0 = getcFromInputFile ()))
244ebdab5e8SMasatake YAMATO 		{
245ebdab5e8SMasatake YAMATO 			if (c0 == EOF || c0 == c)
246ebdab5e8SMasatake YAMATO 				break;
247ebdab5e8SMasatake YAMATO 			else
248ebdab5e8SMasatake YAMATO 				tokenPutc(token, c0);
249ebdab5e8SMasatake YAMATO 		}
250ebdab5e8SMasatake YAMATO 		break;
251ebdab5e8SMasatake YAMATO 	default:
252ebdab5e8SMasatake YAMATO 		if (isIdentifierChar(c))
253ebdab5e8SMasatake YAMATO 		{
254ebdab5e8SMasatake YAMATO 			tokenPutc(token, c);
255ebdab5e8SMasatake YAMATO 			while ((c = getcFromInputFile ()))
256ebdab5e8SMasatake YAMATO 			{
257ebdab5e8SMasatake YAMATO 				if (isIdentifierChar(c))
258ebdab5e8SMasatake YAMATO 					tokenPutc(token, c);
259ebdab5e8SMasatake YAMATO 				else
260ebdab5e8SMasatake YAMATO 				{
261ebdab5e8SMasatake YAMATO 					ungetcToInputFile (c);
262ebdab5e8SMasatake YAMATO 					break;
263ebdab5e8SMasatake YAMATO 				}
264ebdab5e8SMasatake YAMATO 			}
265ebdab5e8SMasatake YAMATO 			token->keyword = lookupKeyword (vStringValue (token->string),
266ebdab5e8SMasatake YAMATO 											Lang_dtd);
267ebdab5e8SMasatake YAMATO 			if (token->keyword == KEYWORD_NONE)
268ebdab5e8SMasatake YAMATO 				token->type = TOKEN_IDENTIFIER;
269ebdab5e8SMasatake YAMATO 			else
270ebdab5e8SMasatake YAMATO 				token->type = TOKEN_KEYWORD;
271ebdab5e8SMasatake YAMATO 
272ebdab5e8SMasatake YAMATO 		}
273ebdab5e8SMasatake YAMATO 		else
274ebdab5e8SMasatake YAMATO 			token->type = c;
275ebdab5e8SMasatake YAMATO 		break;
276ebdab5e8SMasatake YAMATO 	}
277ebdab5e8SMasatake YAMATO }
278ebdab5e8SMasatake YAMATO 
makeDtdTagMaybe(tagEntryInfo * const e,tokenInfo * const token,int kind,int role)279ebdab5e8SMasatake YAMATO static int makeDtdTagMaybe (tagEntryInfo *const e, tokenInfo *const token,
280ebdab5e8SMasatake YAMATO 							int kind, int role)
281ebdab5e8SMasatake YAMATO {
28224b256e3SMasatake YAMATO 	if (role == ROLE_DEFINITION_INDEX)
283ebdab5e8SMasatake YAMATO 	{
284ebdab5e8SMasatake YAMATO 		if (! DtdKinds[kind].enabled)
285ebdab5e8SMasatake YAMATO 			return CORK_NIL;
286ebdab5e8SMasatake YAMATO 	}
287ebdab5e8SMasatake YAMATO 	else if (! (isXtagEnabled (XTAG_REFERENCE_TAGS)
288ebdab5e8SMasatake YAMATO 				&& DtdKinds[kind].roles[role].enabled))
289ebdab5e8SMasatake YAMATO 		return CORK_NIL;
290ebdab5e8SMasatake YAMATO 
291ebdab5e8SMasatake YAMATO 	initRefTagEntry (e, tokenString (token),
29216a2541cSMasatake YAMATO 					 kind,
293ebdab5e8SMasatake YAMATO 					 role);
294ebdab5e8SMasatake YAMATO 	e->lineNumber = token->lineNumber;
295ebdab5e8SMasatake YAMATO 	e->filePosition = token->filePosition;
296002dd246SMasatake YAMATO 	e->extensionFields.scopeIndex = DTD (token)->scopeIndex;
297ebdab5e8SMasatake YAMATO 
298ebdab5e8SMasatake YAMATO 	return makeTagEntry (e);
299ebdab5e8SMasatake YAMATO }
300ebdab5e8SMasatake YAMATO 
backpatchEndField(int index,unsigned long lineNumber)301*3afb5475SMasatake YAMATO static void backpatchEndField (int index, unsigned long lineNumber)
302ebdab5e8SMasatake YAMATO {
303ebdab5e8SMasatake YAMATO 	tagEntryInfo *ep = getEntryInCorkQueue (index);
304ebdab5e8SMasatake YAMATO 
305ebdab5e8SMasatake YAMATO 	if (ep)
306ebdab5e8SMasatake YAMATO 		ep->extensionFields.endLine = lineNumber;
307ebdab5e8SMasatake YAMATO }
308ebdab5e8SMasatake YAMATO 
parseEntity(tokenInfo * const token)309ebdab5e8SMasatake YAMATO static void parseEntity (tokenInfo *const token)
310ebdab5e8SMasatake YAMATO {
311ebdab5e8SMasatake YAMATO 	tagEntryInfo e;
312*3afb5475SMasatake YAMATO 	int index = CORK_NIL;
313ebdab5e8SMasatake YAMATO 
314ebdab5e8SMasatake YAMATO 	tokenRead (token);
315ebdab5e8SMasatake YAMATO 	if (token->type == '%')
316ebdab5e8SMasatake YAMATO 	{
317ebdab5e8SMasatake YAMATO 		tokenRead (token);
318ebdab5e8SMasatake YAMATO 		if (tokenIsType(token, IDENTIFIER))
319ebdab5e8SMasatake YAMATO 			index = makeDtdTagMaybe (&e, token,
32024b256e3SMasatake YAMATO 									 K_PARAMETER_ENTITY, ROLE_DEFINITION_INDEX);
321ebdab5e8SMasatake YAMATO 	}
322ebdab5e8SMasatake YAMATO 	else if (tokenIsType(token, IDENTIFIER))
323ebdab5e8SMasatake YAMATO 		index = makeDtdTagMaybe (&e, token,
32424b256e3SMasatake YAMATO 								 K_ENTITY, ROLE_DEFINITION_INDEX);
325ebdab5e8SMasatake YAMATO 
326ebdab5e8SMasatake YAMATO 	if (tokenSkipToType (token, TOKEN_CLOSE) && (index != CORK_NIL))
327ebdab5e8SMasatake YAMATO 		backpatchEndField (index, token->lineNumber);
328ebdab5e8SMasatake YAMATO }
329ebdab5e8SMasatake YAMATO 
parserParameterEntityRef(tokenInfo * const token)330fa4d090aSMasatake YAMATO static tokenInfo *parserParameterEntityRef (tokenInfo *const token)
331ebdab5e8SMasatake YAMATO {
332ebdab5e8SMasatake YAMATO 	tokenRead (token);
333ebdab5e8SMasatake YAMATO 	if (tokenIsType(token, IDENTIFIER))
334ebdab5e8SMasatake YAMATO 	{
335ebdab5e8SMasatake YAMATO 		tokenInfo * identifier = newTokenByCopying (token);
336ebdab5e8SMasatake YAMATO 
337ebdab5e8SMasatake YAMATO 		tokenRead (token);
338ebdab5e8SMasatake YAMATO 
339ebdab5e8SMasatake YAMATO 		if (token->type == ';')
340ebdab5e8SMasatake YAMATO 			return identifier;
341ebdab5e8SMasatake YAMATO 		else
342ebdab5e8SMasatake YAMATO 		{
343a203ce0eSMasatake YAMATO 			tokenDelete (identifier);
344ebdab5e8SMasatake YAMATO 			return NULL;
345ebdab5e8SMasatake YAMATO 		}
346ebdab5e8SMasatake YAMATO 	}
347ebdab5e8SMasatake YAMATO 	return NULL;
348ebdab5e8SMasatake YAMATO }
349ebdab5e8SMasatake YAMATO 
parseElement(tokenInfo * const token,bool skipToClose)350ebdab5e8SMasatake YAMATO static void parseElement (tokenInfo *const token, bool skipToClose)
351ebdab5e8SMasatake YAMATO {
352ebdab5e8SMasatake YAMATO 	tagEntryInfo e;
353*3afb5475SMasatake YAMATO 	int original_index;
354ebdab5e8SMasatake YAMATO 
355ebdab5e8SMasatake YAMATO 	if (skipToClose)
356*3afb5475SMasatake YAMATO 		original_index = (int)countEntryInCorkQueue ();
357ebdab5e8SMasatake YAMATO 
358ebdab5e8SMasatake YAMATO 	tokenRead (token);
359ebdab5e8SMasatake YAMATO 	if (token->type == '%')
360ebdab5e8SMasatake YAMATO 	{
361ebdab5e8SMasatake YAMATO 		tokenInfo * identifier = parserParameterEntityRef (token);
362ebdab5e8SMasatake YAMATO 		if (identifier)
363ebdab5e8SMasatake YAMATO 		{
364ebdab5e8SMasatake YAMATO 			makeDtdTagMaybe (&e, identifier,
365ebdab5e8SMasatake YAMATO 							 K_PARAMETER_ENTITY,
366ebdab5e8SMasatake YAMATO 							 DTD_PARAMETER_ENTITY_ELEMENT_NAME);
367a203ce0eSMasatake YAMATO 			tokenDelete (identifier);
368ebdab5e8SMasatake YAMATO 		}
369ebdab5e8SMasatake YAMATO 	}
370ebdab5e8SMasatake YAMATO 	else if (tokenIsType(token, IDENTIFIER))
37124b256e3SMasatake YAMATO 		makeDtdTagMaybe (&e, token, K_ELEMENT, ROLE_DEFINITION_INDEX);
37269d5e9d9SMasatake YAMATO 	else if (token->type == '(')
373ebdab5e8SMasatake YAMATO 	{
374ebdab5e8SMasatake YAMATO 		do {
375ebdab5e8SMasatake YAMATO 			parseElement (token, false);
376ebdab5e8SMasatake YAMATO 		} while ((!tokenIsEOF (token))
377ebdab5e8SMasatake YAMATO 				 && (token->type != ')'));
378ebdab5e8SMasatake YAMATO 	}
379ebdab5e8SMasatake YAMATO 
380ebdab5e8SMasatake YAMATO 	if (skipToClose)
381ebdab5e8SMasatake YAMATO 	{
382*3afb5475SMasatake YAMATO 		int current_index = (int)countEntryInCorkQueue ();
383ebdab5e8SMasatake YAMATO 		if (tokenSkipToType (token, TOKEN_CLOSE)
384ebdab5e8SMasatake YAMATO 			&& (current_index > original_index))
385ebdab5e8SMasatake YAMATO 		{
386*3afb5475SMasatake YAMATO 			for (int index = original_index; index < current_index; index++)
387ebdab5e8SMasatake YAMATO 				backpatchEndField (index, token->lineNumber);
388ebdab5e8SMasatake YAMATO 		}
389ebdab5e8SMasatake YAMATO 	}
390ebdab5e8SMasatake YAMATO }
391ebdab5e8SMasatake YAMATO 
parseAttDefs(tokenInfo * const token)392ebdab5e8SMasatake YAMATO static void parseAttDefs (tokenInfo *const token)
393ebdab5e8SMasatake YAMATO {
394ebdab5e8SMasatake YAMATO 	/*  [53]   	AttDef	   ::=   	S Name S AttType S DefaultDecl */
395ebdab5e8SMasatake YAMATO 
396ebdab5e8SMasatake YAMATO 	do {
397ebdab5e8SMasatake YAMATO 		tokenRead (token);
398ebdab5e8SMasatake YAMATO 
399ebdab5e8SMasatake YAMATO 		/* Name */
400ebdab5e8SMasatake YAMATO 		if (tokenIsType(token, IDENTIFIER))
401ebdab5e8SMasatake YAMATO 		{
40286d17f9cSColomban Wendling 			tagEntryInfo e;
403ebdab5e8SMasatake YAMATO 			makeDtdTagMaybe (&e, token,
40424b256e3SMasatake YAMATO 							 K_ATTRIBUTE, ROLE_DEFINITION_INDEX);
405ebdab5e8SMasatake YAMATO 		}
406ebdab5e8SMasatake YAMATO 		else if (tokenIsKeyword(token, ATTR_TYPES)
407ebdab5e8SMasatake YAMATO 				 || tokenIsKeyword(token, ENTITY))
408ebdab5e8SMasatake YAMATO 			/* AttType -> just consuming */
409ebdab5e8SMasatake YAMATO 			;
410ebdab5e8SMasatake YAMATO 		else if (tokenIsKeyword(token, NOTATION))
411ebdab5e8SMasatake YAMATO 		{
412ebdab5e8SMasatake YAMATO 			/* AttType -> just consuming */
413ebdab5e8SMasatake YAMATO 			tokenRead (token);
414ebdab5e8SMasatake YAMATO 			if (token->type == '(')
415ebdab5e8SMasatake YAMATO 				tokenSkipToType (token, ')');
416ebdab5e8SMasatake YAMATO 		}
417ebdab5e8SMasatake YAMATO 		else if (token->type == '(')
418ebdab5e8SMasatake YAMATO 		{
419ebdab5e8SMasatake YAMATO 			/* AttType, TODO: Enumerated members can be tagged. */
420ebdab5e8SMasatake YAMATO 			tokenSkipToType (token, ')');
421ebdab5e8SMasatake YAMATO 		}
422ebdab5e8SMasatake YAMATO 		else if (token->type == '#')
423ebdab5e8SMasatake YAMATO 		{
424ebdab5e8SMasatake YAMATO 			/* DefaultDecl */
425ebdab5e8SMasatake YAMATO 			tokenRead (token);
426ebdab5e8SMasatake YAMATO 			if (tokenIsKeyword(token, FIXED))
427ebdab5e8SMasatake YAMATO 				tokenRead (token);
428ebdab5e8SMasatake YAMATO 			else if (tokenIsKeyword(token, ATTR_DEFAULT_DECLS))
42954ca6868SMasatake YAMATO 			{
43054ca6868SMasatake YAMATO 				/* Just consuming */
43154ca6868SMasatake YAMATO 			}
432ebdab5e8SMasatake YAMATO 		}
433ebdab5e8SMasatake YAMATO 		else if (tokenIsType (token, STRING))
434ebdab5e8SMasatake YAMATO 			;					/* DefaultDecl -> Just consuming */
435ebdab5e8SMasatake YAMATO 		else if (token->type == '%')
436ebdab5e8SMasatake YAMATO 		{
437ebdab5e8SMasatake YAMATO 			tokenInfo * identifier = parserParameterEntityRef (token);
438ebdab5e8SMasatake YAMATO 			if (identifier)
439ebdab5e8SMasatake YAMATO 			{
44086d17f9cSColomban Wendling 				tagEntryInfo e;
441ebdab5e8SMasatake YAMATO 				makeDtdTagMaybe (&e, identifier,
442ebdab5e8SMasatake YAMATO 								 K_PARAMETER_ENTITY,
443ebdab5e8SMasatake YAMATO 								 DTD_PARAMETER_ENTITY_PART_OF_ATT_DEF);
444a203ce0eSMasatake YAMATO 				tokenDelete (identifier);
445ebdab5e8SMasatake YAMATO 			}
446ebdab5e8SMasatake YAMATO 		}
447ebdab5e8SMasatake YAMATO 		else if (tokenIsType(token, CLOSE))
448ebdab5e8SMasatake YAMATO 		{
449002dd246SMasatake YAMATO 			DTD (token)->scopeIndex = CORK_NIL;
450ebdab5e8SMasatake YAMATO 			tokenUnread (token);
451ebdab5e8SMasatake YAMATO 			break;
452ebdab5e8SMasatake YAMATO 		}
453ebdab5e8SMasatake YAMATO 	} while (!tokenIsEOF (token));
454ebdab5e8SMasatake YAMATO }
455ebdab5e8SMasatake YAMATO 
parseAttlist(tokenInfo * const token)456ebdab5e8SMasatake YAMATO static void parseAttlist (tokenInfo *const token)
457ebdab5e8SMasatake YAMATO {
458ebdab5e8SMasatake YAMATO 	tagEntryInfo e;
459*3afb5475SMasatake YAMATO 	int index = CORK_NIL;
460ebdab5e8SMasatake YAMATO 
461ebdab5e8SMasatake YAMATO 	tokenRead (token);
462ebdab5e8SMasatake YAMATO 	if (token->type == '%')
463ebdab5e8SMasatake YAMATO 	{
464ebdab5e8SMasatake YAMATO 		tokenRead (token);
465ebdab5e8SMasatake YAMATO 		if (tokenIsType(token, IDENTIFIER))
466ebdab5e8SMasatake YAMATO 		{
467ebdab5e8SMasatake YAMATO 			tokenInfo * identifier = parserParameterEntityRef (token);
468ebdab5e8SMasatake YAMATO 			if (identifier)
469ebdab5e8SMasatake YAMATO 			{
470ebdab5e8SMasatake YAMATO 				index = makeDtdTagMaybe (&e, identifier,
471ebdab5e8SMasatake YAMATO 										 K_ENTITY,
472ebdab5e8SMasatake YAMATO 										 DTD_PARAMETER_ENTITY_ELEMENT_NAME);
473a203ce0eSMasatake YAMATO 				tokenDelete (identifier);
474ebdab5e8SMasatake YAMATO 
475002dd246SMasatake YAMATO 				DTD (token)->scopeIndex = index;
476ebdab5e8SMasatake YAMATO 				parseAttDefs (token);
477002dd246SMasatake YAMATO 				DTD (token)->scopeIndex = CORK_NIL;
478ebdab5e8SMasatake YAMATO 			}
479ebdab5e8SMasatake YAMATO 		}
480ebdab5e8SMasatake YAMATO 	}
481ebdab5e8SMasatake YAMATO 	else if (tokenIsType(token, IDENTIFIER))
482ebdab5e8SMasatake YAMATO 	{
483ebdab5e8SMasatake YAMATO 		tokenInfo * element = newTokenByCopying (token);
484ebdab5e8SMasatake YAMATO 
485ebdab5e8SMasatake YAMATO 		index = makeDtdTagMaybe (&e, element,
486ebdab5e8SMasatake YAMATO 								 K_ELEMENT, DTD_ELEMENT_ATT_OWNER);
487a203ce0eSMasatake YAMATO 		tokenDelete (element);
488ebdab5e8SMasatake YAMATO 
489002dd246SMasatake YAMATO 		DTD (token)->scopeIndex = index;
490ebdab5e8SMasatake YAMATO 		parseAttDefs (token);
491002dd246SMasatake YAMATO 		DTD (token)->scopeIndex = CORK_NIL;
492ebdab5e8SMasatake YAMATO 	}
493ebdab5e8SMasatake YAMATO 
494ebdab5e8SMasatake YAMATO 	tokenSkipToType (token, TOKEN_CLOSE);
495ebdab5e8SMasatake YAMATO 	backpatchEndField (index, token->lineNumber);
496ebdab5e8SMasatake YAMATO }
497ebdab5e8SMasatake YAMATO 
parseNotation(tokenInfo * const token)498ebdab5e8SMasatake YAMATO static void parseNotation (tokenInfo *const token)
499ebdab5e8SMasatake YAMATO {
500*3afb5475SMasatake YAMATO 	int index = CORK_NIL;
501ebdab5e8SMasatake YAMATO 	tagEntryInfo e;
502ebdab5e8SMasatake YAMATO 
503ebdab5e8SMasatake YAMATO 	tokenRead (token);
504ebdab5e8SMasatake YAMATO 	if (tokenIsType(token, IDENTIFIER))
505ebdab5e8SMasatake YAMATO 		index = makeDtdTagMaybe (&e, token,
50624b256e3SMasatake YAMATO 								 K_NOTATION, ROLE_DEFINITION_INDEX);
507ebdab5e8SMasatake YAMATO 
508ebdab5e8SMasatake YAMATO 	tokenSkipToType (token, TOKEN_CLOSE);
509ebdab5e8SMasatake YAMATO 	backpatchEndField (index, token->lineNumber);
510ebdab5e8SMasatake YAMATO }
511ebdab5e8SMasatake YAMATO 
512ebdab5e8SMasatake YAMATO 
513ebdab5e8SMasatake YAMATO static void parseSection (tokenInfo *const token);
514ebdab5e8SMasatake YAMATO 
parseDtdTag1(tokenInfo * const token)515ebdab5e8SMasatake YAMATO static void parseDtdTag1 (tokenInfo *const token)
516ebdab5e8SMasatake YAMATO {
517ebdab5e8SMasatake YAMATO 	if (tokenIsType(token, OPEN))
518ebdab5e8SMasatake YAMATO 	{
519ebdab5e8SMasatake YAMATO 		tokenRead (token);
520ebdab5e8SMasatake YAMATO 		if (tokenIsKeyword (token, ELEMENT))
521ebdab5e8SMasatake YAMATO 			parseElement(token, true);
522ebdab5e8SMasatake YAMATO 		else if (tokenIsKeyword (token, ATTLIST))
523ebdab5e8SMasatake YAMATO 			parseAttlist(token);
524ebdab5e8SMasatake YAMATO 		else if (tokenIsKeyword (token, ENTITY))
525ebdab5e8SMasatake YAMATO 			parseEntity(token);
526ebdab5e8SMasatake YAMATO 		else if (tokenIsKeyword (token, NOTATION))
527ebdab5e8SMasatake YAMATO 			parseNotation(token);
528ebdab5e8SMasatake YAMATO 		else if (token->type == '[')
529ebdab5e8SMasatake YAMATO 		{
530ebdab5e8SMasatake YAMATO 			tokenRead (token);
531ebdab5e8SMasatake YAMATO 			parseSection (token);
532ebdab5e8SMasatake YAMATO 			tokenSkipToType (token, ']');
533ebdab5e8SMasatake YAMATO 		}
534ebdab5e8SMasatake YAMATO 		else if (!tokenIsType(token, CLOSE))
535ebdab5e8SMasatake YAMATO 			tokenSkipToType (token, TOKEN_CLOSE);
536ebdab5e8SMasatake YAMATO 	}
537ebdab5e8SMasatake YAMATO }
538ebdab5e8SMasatake YAMATO 
parseSection(tokenInfo * const token)539ebdab5e8SMasatake YAMATO static void parseSection (tokenInfo *const token)
540ebdab5e8SMasatake YAMATO {
541ebdab5e8SMasatake YAMATO 	if (tokenIsKeyword(token, IGNORE))
542ebdab5e8SMasatake YAMATO 		tokenSkipToType (token, ']');
543ebdab5e8SMasatake YAMATO 	else
544ebdab5e8SMasatake YAMATO 	{
545ebdab5e8SMasatake YAMATO 		if (tokenIsKeyword (token, INCLUDE))
546ebdab5e8SMasatake YAMATO 		{
547ebdab5e8SMasatake YAMATO 			tokenRead (token);
548ebdab5e8SMasatake YAMATO 			if (token->type == '[')
549ebdab5e8SMasatake YAMATO 			{
550ebdab5e8SMasatake YAMATO 				do {
551ebdab5e8SMasatake YAMATO 					tokenRead (token);
552ebdab5e8SMasatake YAMATO 				} while ((!tokenIsEOF (token))
553ebdab5e8SMasatake YAMATO 						 && (token->type != ']'));
554ebdab5e8SMasatake YAMATO 			}
555ebdab5e8SMasatake YAMATO 		}
556ebdab5e8SMasatake YAMATO 		else if (token->type == '%')
557ebdab5e8SMasatake YAMATO 		{
558ebdab5e8SMasatake YAMATO 			tokenInfo *const condition = parserParameterEntityRef (token);
559ebdab5e8SMasatake YAMATO 			if (condition)
560ebdab5e8SMasatake YAMATO 			{
561ebdab5e8SMasatake YAMATO 				tagEntryInfo e;
562*3afb5475SMasatake YAMATO 				int index = makeDtdTagMaybe (&e, condition,
563ebdab5e8SMasatake YAMATO 											 K_PARAMETER_ENTITY,
564ebdab5e8SMasatake YAMATO 											 DTD_PARAMETER_ENTITY_CONDITION);
565a203ce0eSMasatake YAMATO 				tokenDelete (condition);
566ebdab5e8SMasatake YAMATO 				tokenRead (token);
567ebdab5e8SMasatake YAMATO 				if (token->type == '[')
568ebdab5e8SMasatake YAMATO 				{
569ebdab5e8SMasatake YAMATO 					do {
570ebdab5e8SMasatake YAMATO 						tokenRead (token);
571ebdab5e8SMasatake YAMATO 						parseDtdTag1 (token);
572ebdab5e8SMasatake YAMATO 					} while ((!tokenIsEOF (token))
573ebdab5e8SMasatake YAMATO 							 && (token->type != ']'));
574ebdab5e8SMasatake YAMATO 					if (token->type== ']')
575ebdab5e8SMasatake YAMATO 						backpatchEndField (index, token->lineNumber);
576ebdab5e8SMasatake YAMATO 				}
577ebdab5e8SMasatake YAMATO 			}
578ebdab5e8SMasatake YAMATO 		}
579ebdab5e8SMasatake YAMATO 	}
580ebdab5e8SMasatake YAMATO }
581ebdab5e8SMasatake YAMATO 
findDtdTags(void)582ebdab5e8SMasatake YAMATO static void findDtdTags (void)
583ebdab5e8SMasatake YAMATO {
584ebdab5e8SMasatake YAMATO 	tokenInfo *const token = newDtdToken ();
585ebdab5e8SMasatake YAMATO 
586ebdab5e8SMasatake YAMATO 	do {
587ebdab5e8SMasatake YAMATO 		tokenRead (token);
588ebdab5e8SMasatake YAMATO 		parseDtdTag1 (token);
589ebdab5e8SMasatake YAMATO 	} while (!tokenIsEOF (token));
590ebdab5e8SMasatake YAMATO 
591a203ce0eSMasatake YAMATO 	tokenDelete (token);
592ebdab5e8SMasatake YAMATO 
593ebdab5e8SMasatake YAMATO 	flashTokenBacklog (&dtdTokenInfoClass);
594ebdab5e8SMasatake YAMATO }
595ebdab5e8SMasatake YAMATO 
initialize(const langType language)596ebdab5e8SMasatake YAMATO static void initialize (const langType language)
597ebdab5e8SMasatake YAMATO {
598ebdab5e8SMasatake YAMATO 	Lang_dtd = language;
599ebdab5e8SMasatake YAMATO }
600ebdab5e8SMasatake YAMATO 
DtdParser(void)601ebdab5e8SMasatake YAMATO extern parserDefinition* DtdParser (void)
602ebdab5e8SMasatake YAMATO {
603ebdab5e8SMasatake YAMATO 	parserDefinition* def = parserNew ("DTD");
604ebdab5e8SMasatake YAMATO 
605ebdab5e8SMasatake YAMATO 	/* File name patters are picked from Linux kernel. */
606ebdab5e8SMasatake YAMATO 	static const char *const extensions [] = {
607ebdab5e8SMasatake YAMATO 		"dtd",
608ebdab5e8SMasatake YAMATO 		"mod",
609ebdab5e8SMasatake YAMATO 		NULL
610ebdab5e8SMasatake YAMATO 	};
611ebdab5e8SMasatake YAMATO 
612ebdab5e8SMasatake YAMATO 	def->initialize = initialize;
613ebdab5e8SMasatake YAMATO 	def->parser     = findDtdTags;
614ebdab5e8SMasatake YAMATO 
61509ae690fSMasatake YAMATO 	def->kindTable      = DtdKinds;
616ebdab5e8SMasatake YAMATO 	def->kindCount  = ARRAY_SIZE (DtdKinds);
617ebdab5e8SMasatake YAMATO 	def->extensions = extensions;
618ebdab5e8SMasatake YAMATO 
619ebdab5e8SMasatake YAMATO 	def->keywordTable = DtdKeywordTable;
620ebdab5e8SMasatake YAMATO 	def->keywordCount = ARRAY_SIZE (DtdKeywordTable);
621ebdab5e8SMasatake YAMATO 
6226b1a862eSMasatake YAMATO 	def->useCork    = CORK_QUEUE;
623ebdab5e8SMasatake YAMATO 	def->requestAutomaticFQTag = true;
624ebdab5e8SMasatake YAMATO 
625ebdab5e8SMasatake YAMATO 	return def;
626ebdab5e8SMasatake YAMATO }
627