xref: /btstack/3rd-party/yxml/yxml.c (revision 7bbeb3ad8cec0c1816689843bf9383cf4c644ef8)
1 /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT! */
2 
3 /* Copyright (c) 2013-2014 Yoran Heling
4 
5   Permission is hereby granted, free of charge, to any person obtaining
6   a copy of this software and associated documentation files (the
7   "Software"), to deal in the Software without restriction, including
8   without limitation the rights to use, copy, modify, merge, publish,
9   distribute, sublicense, and/or sell copies of the Software, and to
10   permit persons to whom the Software is furnished to do so, subject to
11   the following conditions:
12 
13   The above copyright notice and this permission notice shall be included
14   in all copies or substantial portions of the Software.
15 
16   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24 
25 #include <yxml.h>
26 #include <string.h>
27 
28 typedef enum {
29 	YXMLS_string,
30 	YXMLS_attr0,
31 	YXMLS_attr1,
32 	YXMLS_attr2,
33 	YXMLS_attr3,
34 	YXMLS_attr4,
35 	YXMLS_cd0,
36 	YXMLS_cd1,
37 	YXMLS_cd2,
38 	YXMLS_comment0,
39 	YXMLS_comment1,
40 	YXMLS_comment2,
41 	YXMLS_comment3,
42 	YXMLS_comment4,
43 	YXMLS_dt0,
44 	YXMLS_dt1,
45 	YXMLS_dt2,
46 	YXMLS_dt3,
47 	YXMLS_dt4,
48 	YXMLS_elem0,
49 	YXMLS_elem1,
50 	YXMLS_elem2,
51 	YXMLS_elem3,
52 	YXMLS_enc0,
53 	YXMLS_enc1,
54 	YXMLS_enc2,
55 	YXMLS_enc3,
56 	YXMLS_etag0,
57 	YXMLS_etag1,
58 	YXMLS_etag2,
59 	YXMLS_init,
60 	YXMLS_le0,
61 	YXMLS_le1,
62 	YXMLS_le2,
63 	YXMLS_le3,
64 	YXMLS_lee1,
65 	YXMLS_lee2,
66 	YXMLS_leq0,
67 	YXMLS_misc0,
68 	YXMLS_misc1,
69 	YXMLS_misc2,
70 	YXMLS_misc2a,
71 	YXMLS_misc3,
72 	YXMLS_pi0,
73 	YXMLS_pi1,
74 	YXMLS_pi2,
75 	YXMLS_pi3,
76 	YXMLS_pi4,
77 	YXMLS_std0,
78 	YXMLS_std1,
79 	YXMLS_std2,
80 	YXMLS_std3,
81 	YXMLS_ver0,
82 	YXMLS_ver1,
83 	YXMLS_ver2,
84 	YXMLS_ver3,
85 	YXMLS_xmldecl0,
86 	YXMLS_xmldecl1,
87 	YXMLS_xmldecl2,
88 	YXMLS_xmldecl3,
89 	YXMLS_xmldecl4,
90 	YXMLS_xmldecl5,
91 	YXMLS_xmldecl6,
92 	YXMLS_xmldecl7,
93 	YXMLS_xmldecl8,
94 	YXMLS_xmldecl9
95 } yxml_state_t;
96 
97 
98 #define yxml_isChar(c) 1
99 /* 0xd should be part of SP, too, but yxml_parse() already normalizes that into 0xa */
100 #define yxml_isSP(c) ((c == 0x20) || (c == 0x09) || (c == 0x0a))
101 #define yxml_isAlpha(c) ( ((c|32)-'a') < 26)
102 #define yxml_isNum(c) ((c-'0') < 10)
103 #define yxml_isHex(c) (yxml_isNum(c) || (((c|32)-'a') < 6))
104 #define yxml_isEncName(c) (yxml_isAlpha(c) || yxml_isNum(c) || (c == '.') || (c == '_') || (c == '-'))
105 #define yxml_isNameStart(c) (yxml_isAlpha(c) || (c == ':') || (c == '_') || (c >= 128))
106 #define yxml_isName(c) (yxml_isNameStart(c) || yxml_isNum(c) || (c == '-') || (c == '.'))
107 /* XXX: The valid characters are dependent on the quote char, hence the access to x->quote */
108 #define yxml_isAttValue(c) (yxml_isChar(c) && (c != x->quote) && (c != '<') && (c != '&'))
109 /* Anything between '&' and ';', the yxml_ref* functions will do further
110  * validation. Strictly speaking, this is "yxml_isName(c) || c == '#'", but
111  * this parser doesn't understand entities with '.', ':', etc, anwyay.  */
112 #define yxml_isRef(c) (yxml_isNum(c) || yxml_isAlpha(c) || (c == '#'))
113 
114 #define INTFROM5CHARS(a, b, c, d, e) ((((uint64_t)(a))<<32) | (((uint64_t)(b))<<24) | (((uint64_t)(c))<<16) | (((uint64_t)(d))<<8) | (uint64_t)(e))
115 
116 
117 /* Set the given char value to ch (0<=ch<=255).
118  * This can't be done with simple assignment because char may be signed, and
119  * unsigned-to-signed overflow is implementation defined in C. This function
120  * /looks/ inefficient, but gcc compiles it down to a single movb instruction
121  * on x86, even with -O0. */
yxml_setchar(char * dest,unsigned ch)122 static inline void yxml_setchar(char *dest, unsigned ch) {
123 	unsigned char _ch = ch;
124 	memcpy(dest, &_ch, 1);
125 }
126 
127 
128 /* Similar to yxml_setchar(), but will convert ch (any valid unicode point) to
129  * UTF-8 and appends a '\0'. dest must have room for at least 5 bytes. */
yxml_setutf8(char * dest,unsigned ch)130 static void yxml_setutf8(char *dest, unsigned ch) {
131 	if(ch <= 0x007F)
132 		yxml_setchar(dest++, ch);
133 	else if(ch <= 0x07FF) {
134 		yxml_setchar(dest++, 0xC0 | (ch>>6));
135 		yxml_setchar(dest++, 0x80 | (ch & 0x3F));
136 	} else if(ch <= 0xFFFF) {
137 		yxml_setchar(dest++, 0xE0 | (ch>>12));
138 		yxml_setchar(dest++, 0x80 | ((ch>>6) & 0x3F));
139 		yxml_setchar(dest++, 0x80 | (ch & 0x3F));
140 	} else {
141 		yxml_setchar(dest++, 0xF0 | (ch>>18));
142 		yxml_setchar(dest++, 0x80 | ((ch>>12) & 0x3F));
143 		yxml_setchar(dest++, 0x80 | ((ch>>6) & 0x3F));
144 		yxml_setchar(dest++, 0x80 | (ch & 0x3F));
145 	}
146 	*dest = 0;
147 }
148 
149 
yxml_datacontent(yxml_t * x,unsigned ch)150 static inline yxml_ret_t yxml_datacontent(yxml_t *x, unsigned ch) {
151 	yxml_setchar(x->data, ch);
152 	x->data[1] = 0;
153 	return YXML_CONTENT;
154 }
155 
156 
yxml_datapi1(yxml_t * x,unsigned ch)157 static inline yxml_ret_t yxml_datapi1(yxml_t *x, unsigned ch) {
158 	yxml_setchar(x->data, ch);
159 	x->data[1] = 0;
160 	return YXML_PICONTENT;
161 }
162 
163 
yxml_datapi2(yxml_t * x,unsigned ch)164 static inline yxml_ret_t yxml_datapi2(yxml_t *x, unsigned ch) {
165 	x->data[0] = '?';
166 	yxml_setchar(x->data+1, ch);
167 	x->data[2] = 0;
168 	return YXML_PICONTENT;
169 }
170 
171 
yxml_datacd1(yxml_t * x,unsigned ch)172 static inline yxml_ret_t yxml_datacd1(yxml_t *x, unsigned ch) {
173 	x->data[0] = ']';
174 	yxml_setchar(x->data+1, ch);
175 	x->data[2] = 0;
176 	return YXML_CONTENT;
177 }
178 
179 
yxml_datacd2(yxml_t * x,unsigned ch)180 static inline yxml_ret_t yxml_datacd2(yxml_t *x, unsigned ch) {
181 	x->data[0] = ']';
182 	x->data[1] = ']';
183 	yxml_setchar(x->data+2, ch);
184 	x->data[3] = 0;
185 	return YXML_CONTENT;
186 }
187 
188 
yxml_dataattr(yxml_t * x,unsigned ch)189 static inline yxml_ret_t yxml_dataattr(yxml_t *x, unsigned ch) {
190 	/* Normalize attribute values according to the XML spec section 3.3.3. */
191 	yxml_setchar(x->data, ((ch == 0x9) || (ch == 0xa)) ? 0x20 : ch);
192 	x->data[1] = 0;
193 	return YXML_ATTRVAL;
194 }
195 
196 
yxml_pushstack(yxml_t * x,char ** res,unsigned ch)197 static yxml_ret_t yxml_pushstack(yxml_t *x, char **res, unsigned ch) {
198 	if((x->stacklen+2) >= x->stacksize)
199 		return YXML_ESTACK;
200 	x->stacklen++;
201 	*res = (char *)x->stack+x->stacklen;
202 	x->stack[x->stacklen] = ch;
203 	x->stacklen++;
204 	x->stack[x->stacklen] = 0;
205 	return YXML_OK;
206 }
207 
208 
yxml_pushstackc(yxml_t * x,unsigned ch)209 static yxml_ret_t yxml_pushstackc(yxml_t *x, unsigned ch) {
210 	if((x->stacklen+1) >= x->stacksize)
211 		return YXML_ESTACK;
212 	x->stack[x->stacklen] = ch;
213 	x->stacklen++;
214 	x->stack[x->stacklen] = 0;
215 	return YXML_OK;
216 }
217 
218 
yxml_popstack(yxml_t * x)219 static void yxml_popstack(yxml_t *x) {
220 	do
221 		x->stacklen--;
222 	while(x->stack[x->stacklen]);
223 }
224 
225 
yxml_elemstart(yxml_t * x,unsigned ch)226 static inline yxml_ret_t yxml_elemstart  (yxml_t *x, unsigned ch) { return yxml_pushstack(x, &x->elem, ch); }
yxml_elemname(yxml_t * x,unsigned ch)227 static inline yxml_ret_t yxml_elemname   (yxml_t *x, unsigned ch) { return yxml_pushstackc(x, ch); }
yxml_elemnameend(yxml_t * x,unsigned ch)228 static inline yxml_ret_t yxml_elemnameend(yxml_t *x, unsigned ch) { (void) x; (void) ch; return YXML_ELEMSTART; }
229 
230 
231 /* Also used in yxml_elemcloseend(), since this function just removes the last
232  * element from the stack and returns ELEMEND. */
yxml_selfclose(yxml_t * x,unsigned ch)233 static yxml_ret_t yxml_selfclose(yxml_t *x, unsigned ch) {
234 	(void) ch;
235 	yxml_popstack(x);
236 	if(x->stacklen) {
237 		x->elem = (char *)x->stack+x->stacklen-1;
238 		while(*(x->elem-1))
239 			x->elem--;
240 		return YXML_ELEMEND;
241 	}
242 	x->elem = (char *)x->stack;
243 	x->state = YXMLS_misc3;
244 	return YXML_ELEMEND;
245 }
246 
247 
yxml_elemclose(yxml_t * x,unsigned ch)248 static inline yxml_ret_t yxml_elemclose(yxml_t *x, unsigned ch) {
249 	if(*((unsigned char *)x->elem) != ch)
250 		return YXML_ECLOSE;
251 	x->elem++;
252 	return YXML_OK;
253 }
254 
255 
yxml_elemcloseend(yxml_t * x,unsigned ch)256 static inline yxml_ret_t yxml_elemcloseend(yxml_t *x, unsigned ch) {
257 	if(*x->elem)
258 		return YXML_ECLOSE;
259 	return yxml_selfclose(x, ch);
260 }
261 
262 
yxml_attrstart(yxml_t * x,unsigned ch)263 static inline yxml_ret_t yxml_attrstart  (yxml_t *x, unsigned ch) { return yxml_pushstack(x, &x->attr, ch); }
yxml_attrname(yxml_t * x,unsigned ch)264 static inline yxml_ret_t yxml_attrname   (yxml_t *x, unsigned ch) { return yxml_pushstackc(x, ch); }
yxml_attrnameend(yxml_t * x,unsigned ch)265 static inline yxml_ret_t yxml_attrnameend(yxml_t *x, unsigned ch) { (void) x; (void) ch; return YXML_ATTRSTART; }
yxml_attrvalend(yxml_t * x,unsigned ch)266 static inline yxml_ret_t yxml_attrvalend (yxml_t *x, unsigned ch) { (void) ch; yxml_popstack(x); return YXML_ATTREND; }
267 
268 
yxml_pistart(yxml_t * x,unsigned ch)269 static inline yxml_ret_t yxml_pistart  (yxml_t *x, unsigned ch) { return yxml_pushstack(x, &x->pi, ch); }
yxml_piname(yxml_t * x,unsigned ch)270 static inline yxml_ret_t yxml_piname   (yxml_t *x, unsigned ch) { return yxml_pushstackc(x, ch); }
yxml_piabort(yxml_t * x,unsigned ch)271 static inline yxml_ret_t yxml_piabort  (yxml_t *x, unsigned ch) { (void) x; (void) ch; yxml_popstack(x); return YXML_OK; }
yxml_pinameend(yxml_t * x,unsigned ch)272 static inline yxml_ret_t yxml_pinameend(yxml_t *x, unsigned ch) { (void) ch;
273 	return (((x->pi[0]|32) == 'x') && ((x->pi[1]|32) == 'm') && ((x->pi[2]|32) == 'l') && !x->pi[3]) ? YXML_ESYN : YXML_PISTART;
274 }
yxml_pivalend(yxml_t * x,unsigned ch)275 static inline yxml_ret_t yxml_pivalend (yxml_t *x, unsigned ch) { (void) ch; yxml_popstack(x); x->pi = (char *)x->stack; return YXML_PIEND; }
276 
277 
yxml_refstart(yxml_t * x,unsigned ch)278 static inline yxml_ret_t yxml_refstart(yxml_t *x, unsigned ch) {
279 	(void) ch;
280 	memset(x->data, 0, sizeof(x->data));
281 	x->reflen = 0;
282 	return YXML_OK;
283 }
284 
285 
yxml_ref(yxml_t * x,unsigned ch)286 static yxml_ret_t yxml_ref(yxml_t *x, unsigned ch) {
287 	if(x->reflen >= (sizeof(x->data)-1))
288 		return YXML_EREF;
289 	yxml_setchar(x->data+x->reflen, ch);
290 	x->reflen++;
291 	return YXML_OK;
292 }
293 
294 
yxml_refend(yxml_t * x,yxml_ret_t ret)295 static yxml_ret_t yxml_refend(yxml_t *x, yxml_ret_t ret) {
296 	unsigned char *r = (unsigned char *)x->data;
297 	unsigned ch = 0;
298 	if(*r == '#') {
299 		if(r[1] == 'x')
300 			for(r += 2; yxml_isHex((unsigned)*r); r++)
301 				ch = (ch<<4) + ((*r <= '9') ? (*r-'0') : ((*r|32)-'a' + 10));
302 		else
303 			for(r++; yxml_isNum((unsigned)*r); r++)
304 				ch = (ch*10) + (*r-'0');
305 		if(*r)
306 			ch = 0;
307 	} else {
308 		uint64_t i = INTFROM5CHARS(r[0], r[1], r[2], r[3], r[4]);
309 		if        (i == INTFROM5CHARS('l','t', 0,  0, 0)){
310 			ch = '<';
311 		} else if (i == INTFROM5CHARS('g','t', 0,  0, 0)){
312 			ch = '>';
313 		} else if (i == INTFROM5CHARS('a','m','p', 0, 0)){
314 			ch =  '&';
315 		} else if (i == INTFROM5CHARS('a','p','o','s',0)){
316 			ch =  '\'';
317 		} else if (i == INTFROM5CHARS('q','u','o','t',0)){
318 			ch =  '"';
319 		} else {
320 			ch = 0;
321 		}
322 	}
323 
324 	/* Codepoints not allowed in the XML 1.1 definition of a Char */
325 	if(!ch || (ch > 0x10FFFF) || (ch == 0xFFFE) || (ch == 0xFFFF) || ((ch-0xDFFF) < 0x7FF))
326 		return YXML_EREF;
327 	yxml_setutf8(x->data, ch);
328 	return ret;
329 }
330 
331 
yxml_refcontent(yxml_t * x,unsigned ch)332 static inline yxml_ret_t yxml_refcontent(yxml_t *x, unsigned ch) { (void) ch; return yxml_refend(x, YXML_CONTENT); }
yxml_refattrval(yxml_t * x,unsigned ch)333 static inline yxml_ret_t yxml_refattrval(yxml_t *x, unsigned ch) { (void) ch; return yxml_refend(x, YXML_ATTRVAL); }
334 
335 
yxml_init(yxml_t * x,void * stack,size_t stacksize)336 void yxml_init(yxml_t *x, void *stack, size_t stacksize) {
337 	memset(x, 0, sizeof(*x));
338 	x->line = 1;
339 	x->stack = (unsigned char *) stack;
340 	x->stacksize = stacksize;
341 	*x->stack = 0;
342 	x->elem = x->pi = x->attr = (char *)x->stack;
343 	x->state = YXMLS_init;
344 }
345 
346 
yxml_parse(yxml_t * x,int _ch)347 yxml_ret_t yxml_parse(yxml_t *x, int _ch) {
348 	/* Ensure that characters are in the range of 0..255 rather than -126..125.
349 	 * All character comparisons are done with positive integers. */
350 	unsigned ch = (unsigned)(_ch+256) & 0xff;
351 	if(!ch)
352 		return YXML_ESYN;
353 	x->total++;
354 
355 	/* End-of-Line normalization, "\rX", "\r\n" and "\n" are recognized and
356 	 * normalized to a single '\n' as per XML 1.0 section 2.11. XML 1.1 adds
357 	 * some non-ASCII character sequences to this list, but we can only handle
358 	 * ASCII here without making assumptions about the input encoding. */
359 	if(x->ignore == ch) {
360 		x->ignore = 0;
361 		return YXML_OK;
362 	}
363 	x->ignore = (ch == 0xd) * 0xa;
364 	if((ch == 0xa) || (ch == 0xd)) {
365 		ch = 0xa;
366 		x->line++;
367 		x->byte = 0;
368 	}
369 	x->byte++;
370 
371 	switch((yxml_state_t)x->state) {
372 	case YXMLS_string:
373 		if(ch == *x->string) {
374 			x->string++;
375 			if(!*x->string)
376 				x->state = x->nextstate;
377 			return YXML_OK;
378 		}
379 		break;
380 	case YXMLS_attr0:
381 		if(yxml_isName(ch))
382 			return yxml_attrname(x, ch);
383 		if(yxml_isSP(ch)) {
384 			x->state = YXMLS_attr1;
385 			return yxml_attrnameend(x, ch);
386 		}
387 		if(ch == (unsigned char)'=') {
388 			x->state = YXMLS_attr2;
389 			return yxml_attrnameend(x, ch);
390 		}
391 		break;
392 	case YXMLS_attr1:
393 		if(yxml_isSP(ch))
394 			return YXML_OK;
395 		if(ch == (unsigned char)'=') {
396 			x->state = YXMLS_attr2;
397 			return YXML_OK;
398 		}
399 		break;
400 	case YXMLS_attr2:
401 		if(yxml_isSP(ch))
402 			return YXML_OK;
403 		if((ch == (unsigned char)'\'') || (ch == (unsigned char)'"')) {
404 			x->state = YXMLS_attr3;
405 			x->quote = ch;
406 			return YXML_OK;
407 		}
408 		break;
409 	case YXMLS_attr3:
410 		if(yxml_isAttValue(ch))
411 			return yxml_dataattr(x, ch);
412 		if(ch == (unsigned char)'&') {
413 			x->state = YXMLS_attr4;
414 			return yxml_refstart(x, ch);
415 		}
416 		if(x->quote == ch) {
417 			x->state = YXMLS_elem2;
418 			return yxml_attrvalend(x, ch);
419 		}
420 		break;
421 	case YXMLS_attr4:
422 		if(yxml_isRef(ch))
423 			return yxml_ref(x, ch);
424 		if(ch == (unsigned char)'\x3b') {
425 			x->state = YXMLS_attr3;
426 			return yxml_refattrval(x, ch);
427 		}
428 		break;
429 	case YXMLS_cd0:
430 		if(ch == (unsigned char)']') {
431 			x->state = YXMLS_cd1;
432 			return YXML_OK;
433 		}
434 		if(yxml_isChar(ch))
435 			return yxml_datacontent(x, ch);
436 		break;
437 	case YXMLS_cd1:
438 		if(ch == (unsigned char)']') {
439 			x->state = YXMLS_cd2;
440 			return YXML_OK;
441 		}
442 		if(yxml_isChar(ch)) {
443 			x->state = YXMLS_cd0;
444 			return yxml_datacd1(x, ch);
445 		}
446 		break;
447 	case YXMLS_cd2:
448 		if(ch == (unsigned char)']')
449 			return yxml_datacontent(x, ch);
450 		if(ch == (unsigned char)'>') {
451 			x->state = YXMLS_misc2;
452 			return YXML_OK;
453 		}
454 		if(yxml_isChar(ch)) {
455 			x->state = YXMLS_cd0;
456 			return yxml_datacd2(x, ch);
457 		}
458 		break;
459 	case YXMLS_comment0:
460 		if(ch == (unsigned char)'-') {
461 			x->state = YXMLS_comment1;
462 			return YXML_OK;
463 		}
464 		break;
465 	case YXMLS_comment1:
466 		if(ch == (unsigned char)'-') {
467 			x->state = YXMLS_comment2;
468 			return YXML_OK;
469 		}
470 		break;
471 	case YXMLS_comment2:
472 		if(ch == (unsigned char)'-') {
473 			x->state = YXMLS_comment3;
474 			return YXML_OK;
475 		}
476 		if(yxml_isChar(ch))
477 			return YXML_OK;
478 		break;
479 	case YXMLS_comment3:
480 		if(ch == (unsigned char)'-') {
481 			x->state = YXMLS_comment4;
482 			return YXML_OK;
483 		}
484 		if(yxml_isChar(ch)) {
485 			x->state = YXMLS_comment2;
486 			return YXML_OK;
487 		}
488 		break;
489 	case YXMLS_comment4:
490 		if(ch == (unsigned char)'>') {
491 			x->state = x->nextstate;
492 			return YXML_OK;
493 		}
494 		break;
495 	case YXMLS_dt0:
496 		if(ch == (unsigned char)'>') {
497 			x->state = YXMLS_misc1;
498 			return YXML_OK;
499 		}
500 		if((ch == (unsigned char)'\'') || (ch == (unsigned char)'"')) {
501 			x->state = YXMLS_dt1;
502 			x->quote = ch;
503 			x->nextstate = YXMLS_dt0;
504 			return YXML_OK;
505 		}
506 		if(ch == (unsigned char)'<') {
507 			x->state = YXMLS_dt2;
508 			return YXML_OK;
509 		}
510 		if(yxml_isChar(ch))
511 			return YXML_OK;
512 		break;
513 	case YXMLS_dt1:
514 		if(x->quote == ch) {
515 			x->state = x->nextstate;
516 			return YXML_OK;
517 		}
518 		if(yxml_isChar(ch))
519 			return YXML_OK;
520 		break;
521 	case YXMLS_dt2:
522 		if(ch == (unsigned char)'?') {
523 			x->state = YXMLS_pi0;
524 			x->nextstate = YXMLS_dt0;
525 			return YXML_OK;
526 		}
527 		if(ch == (unsigned char)'!') {
528 			x->state = YXMLS_dt3;
529 			return YXML_OK;
530 		}
531 		break;
532 	case YXMLS_dt3:
533 		if(ch == (unsigned char)'-') {
534 			x->state = YXMLS_comment1;
535 			x->nextstate = YXMLS_dt0;
536 			return YXML_OK;
537 		}
538 		if(yxml_isChar(ch)) {
539 			x->state = YXMLS_dt4;
540 			return YXML_OK;
541 		}
542 		break;
543 	case YXMLS_dt4:
544 		if((ch == (unsigned char)'\'') || (ch == (unsigned char)'"')) {
545 			x->state = YXMLS_dt1;
546 			x->quote = ch;
547 			x->nextstate = YXMLS_dt4;
548 			return YXML_OK;
549 		}
550 		if(ch == (unsigned char)'>') {
551 			x->state = YXMLS_dt0;
552 			return YXML_OK;
553 		}
554 		if(yxml_isChar(ch))
555 			return YXML_OK;
556 		break;
557 	case YXMLS_elem0:
558 		if(yxml_isName(ch))
559 			return yxml_elemname(x, ch);
560 		if(yxml_isSP(ch)) {
561 			x->state = YXMLS_elem1;
562 			return yxml_elemnameend(x, ch);
563 		}
564 		if(ch == (unsigned char)'/') {
565 			x->state = YXMLS_elem3;
566 			return yxml_elemnameend(x, ch);
567 		}
568 		if(ch == (unsigned char)'>') {
569 			x->state = YXMLS_misc2;
570 			return yxml_elemnameend(x, ch);
571 		}
572 		break;
573 	case YXMLS_elem1:
574 		if(yxml_isSP(ch))
575 			return YXML_OK;
576 		if(ch == (unsigned char)'/') {
577 			x->state = YXMLS_elem3;
578 			return YXML_OK;
579 		}
580 		if(ch == (unsigned char)'>') {
581 			x->state = YXMLS_misc2;
582 			return YXML_OK;
583 		}
584 		if(yxml_isNameStart(ch)) {
585 			x->state = YXMLS_attr0;
586 			return yxml_attrstart(x, ch);
587 		}
588 		break;
589 	case YXMLS_elem2:
590 		if(yxml_isSP(ch)) {
591 			x->state = YXMLS_elem1;
592 			return YXML_OK;
593 		}
594 		if(ch == (unsigned char)'/') {
595 			x->state = YXMLS_elem3;
596 			return YXML_OK;
597 		}
598 		if(ch == (unsigned char)'>') {
599 			x->state = YXMLS_misc2;
600 			return YXML_OK;
601 		}
602 		break;
603 	case YXMLS_elem3:
604 		if(ch == (unsigned char)'>') {
605 			x->state = YXMLS_misc2;
606 			return yxml_selfclose(x, ch);
607 		}
608 		break;
609 	case YXMLS_enc0:
610 		if(yxml_isSP(ch))
611 			return YXML_OK;
612 		if(ch == (unsigned char)'=') {
613 			x->state = YXMLS_enc1;
614 			return YXML_OK;
615 		}
616 		break;
617 	case YXMLS_enc1:
618 		if(yxml_isSP(ch))
619 			return YXML_OK;
620 		if((ch == (unsigned char)'\'') || (ch == (unsigned char)'"')) {
621 			x->state = YXMLS_enc2;
622 			x->quote = ch;
623 			return YXML_OK;
624 		}
625 		break;
626 	case YXMLS_enc2:
627 		if(yxml_isAlpha(ch)) {
628 			x->state = YXMLS_enc3;
629 			return YXML_OK;
630 		}
631 		break;
632 	case YXMLS_enc3:
633 		if(yxml_isEncName(ch))
634 			return YXML_OK;
635 		if(x->quote == ch) {
636 			x->state = YXMLS_xmldecl6;
637 			return YXML_OK;
638 		}
639 		break;
640 	case YXMLS_etag0:
641 		if(yxml_isNameStart(ch)) {
642 			x->state = YXMLS_etag1;
643 			return yxml_elemclose(x, ch);
644 		}
645 		break;
646 	case YXMLS_etag1:
647 		if(yxml_isName(ch))
648 			return yxml_elemclose(x, ch);
649 		if(yxml_isSP(ch)) {
650 			x->state = YXMLS_etag2;
651 			return yxml_elemcloseend(x, ch);
652 		}
653 		if(ch == (unsigned char)'>') {
654 			x->state = YXMLS_misc2;
655 			return yxml_elemcloseend(x, ch);
656 		}
657 		break;
658 	case YXMLS_etag2:
659 		if(yxml_isSP(ch))
660 			return YXML_OK;
661 		if(ch == (unsigned char)'>') {
662 			x->state = YXMLS_misc2;
663 			return YXML_OK;
664 		}
665 		break;
666 	case YXMLS_init:
667 		if(ch == (unsigned char)'\xef') {
668 			x->state = YXMLS_string;
669 			x->nextstate = YXMLS_misc0;
670 			x->string = (unsigned char *)"\xbb\xbf";
671 			return YXML_OK;
672 		}
673 		if(yxml_isSP(ch)) {
674 			x->state = YXMLS_misc0;
675 			return YXML_OK;
676 		}
677 		if(ch == (unsigned char)'<') {
678 			x->state = YXMLS_le0;
679 			return YXML_OK;
680 		}
681 		break;
682 	case YXMLS_le0:
683 		if(ch == (unsigned char)'!') {
684 			x->state = YXMLS_lee1;
685 			return YXML_OK;
686 		}
687 		if(ch == (unsigned char)'?') {
688 			x->state = YXMLS_leq0;
689 			return YXML_OK;
690 		}
691 		if(yxml_isNameStart(ch)) {
692 			x->state = YXMLS_elem0;
693 			return yxml_elemstart(x, ch);
694 		}
695 		break;
696 	case YXMLS_le1:
697 		if(ch == (unsigned char)'!') {
698 			x->state = YXMLS_lee1;
699 			return YXML_OK;
700 		}
701 		if(ch == (unsigned char)'?') {
702 			x->state = YXMLS_pi0;
703 			x->nextstate = YXMLS_misc1;
704 			return YXML_OK;
705 		}
706 		if(yxml_isNameStart(ch)) {
707 			x->state = YXMLS_elem0;
708 			return yxml_elemstart(x, ch);
709 		}
710 		break;
711 	case YXMLS_le2:
712 		if(ch == (unsigned char)'!') {
713 			x->state = YXMLS_lee2;
714 			return YXML_OK;
715 		}
716 		if(ch == (unsigned char)'?') {
717 			x->state = YXMLS_pi0;
718 			x->nextstate = YXMLS_misc2;
719 			return YXML_OK;
720 		}
721 		if(ch == (unsigned char)'/') {
722 			x->state = YXMLS_etag0;
723 			return YXML_OK;
724 		}
725 		if(yxml_isNameStart(ch)) {
726 			x->state = YXMLS_elem0;
727 			return yxml_elemstart(x, ch);
728 		}
729 		break;
730 	case YXMLS_le3:
731 		if(ch == (unsigned char)'!') {
732 			x->state = YXMLS_comment0;
733 			x->nextstate = YXMLS_misc3;
734 			return YXML_OK;
735 		}
736 		if(ch == (unsigned char)'?') {
737 			x->state = YXMLS_pi0;
738 			x->nextstate = YXMLS_misc3;
739 			return YXML_OK;
740 		}
741 		break;
742 	case YXMLS_lee1:
743 		if(ch == (unsigned char)'-') {
744 			x->state = YXMLS_comment1;
745 			x->nextstate = YXMLS_misc1;
746 			return YXML_OK;
747 		}
748 		if(ch == (unsigned char)'D') {
749 			x->state = YXMLS_string;
750 			x->nextstate = YXMLS_dt0;
751 			x->string = (unsigned char *)"OCTYPE";
752 			return YXML_OK;
753 		}
754 		break;
755 	case YXMLS_lee2:
756 		if(ch == (unsigned char)'-') {
757 			x->state = YXMLS_comment1;
758 			x->nextstate = YXMLS_misc2;
759 			return YXML_OK;
760 		}
761 		if(ch == (unsigned char)'[') {
762 			x->state = YXMLS_string;
763 			x->nextstate = YXMLS_cd0;
764 			x->string = (unsigned char *)"CDATA[";
765 			return YXML_OK;
766 		}
767 		break;
768 	case YXMLS_leq0:
769 		if(ch == (unsigned char)'x') {
770 			x->state = YXMLS_xmldecl0;
771 			x->nextstate = YXMLS_misc1;
772 			return yxml_pistart(x, ch);
773 		}
774 		if(yxml_isNameStart(ch)) {
775 			x->state = YXMLS_pi1;
776 			x->nextstate = YXMLS_misc1;
777 			return yxml_pistart(x, ch);
778 		}
779 		break;
780 	case YXMLS_misc0:
781 		if(yxml_isSP(ch))
782 			return YXML_OK;
783 		if(ch == (unsigned char)'<') {
784 			x->state = YXMLS_le0;
785 			return YXML_OK;
786 		}
787 		break;
788 	case YXMLS_misc1:
789 		if(yxml_isSP(ch))
790 			return YXML_OK;
791 		if(ch == (unsigned char)'<') {
792 			x->state = YXMLS_le1;
793 			return YXML_OK;
794 		}
795 		break;
796 	case YXMLS_misc2:
797 		if(ch == (unsigned char)'<') {
798 			x->state = YXMLS_le2;
799 			return YXML_OK;
800 		}
801 		if(ch == (unsigned char)'&') {
802 			x->state = YXMLS_misc2a;
803 			return yxml_refstart(x, ch);
804 		}
805 		if(yxml_isChar(ch))
806 			return yxml_datacontent(x, ch);
807 		break;
808 	case YXMLS_misc2a:
809 		if(yxml_isRef(ch))
810 			return yxml_ref(x, ch);
811 		if(ch == (unsigned char)'\x3b') {
812 			x->state = YXMLS_misc2;
813 			return yxml_refcontent(x, ch);
814 		}
815 		break;
816 	case YXMLS_misc3:
817 		if(yxml_isSP(ch))
818 			return YXML_OK;
819 		if(ch == (unsigned char)'<') {
820 			x->state = YXMLS_le3;
821 			return YXML_OK;
822 		}
823 		break;
824 	case YXMLS_pi0:
825 		if(yxml_isNameStart(ch)) {
826 			x->state = YXMLS_pi1;
827 			return yxml_pistart(x, ch);
828 		}
829 		break;
830 	case YXMLS_pi1:
831 		if(yxml_isName(ch))
832 			return yxml_piname(x, ch);
833 		if(ch == (unsigned char)'?') {
834 			x->state = YXMLS_pi4;
835 			return yxml_pinameend(x, ch);
836 		}
837 		if(yxml_isSP(ch)) {
838 			x->state = YXMLS_pi2;
839 			return yxml_pinameend(x, ch);
840 		}
841 		break;
842 	case YXMLS_pi2:
843 		if(ch == (unsigned char)'?') {
844 			x->state = YXMLS_pi3;
845 			return YXML_OK;
846 		}
847 		if(yxml_isChar(ch))
848 			return yxml_datapi1(x, ch);
849 		break;
850 	case YXMLS_pi3:
851 		if(ch == (unsigned char)'>') {
852 			x->state = x->nextstate;
853 			return yxml_pivalend(x, ch);
854 		}
855 		if(yxml_isChar(ch)) {
856 			x->state = YXMLS_pi2;
857 			return yxml_datapi2(x, ch);
858 		}
859 		break;
860 	case YXMLS_pi4:
861 		if(ch == (unsigned char)'>') {
862 			x->state = x->nextstate;
863 			return yxml_pivalend(x, ch);
864 		}
865 		break;
866 	case YXMLS_std0:
867 		if(yxml_isSP(ch))
868 			return YXML_OK;
869 		if(ch == (unsigned char)'=') {
870 			x->state = YXMLS_std1;
871 			return YXML_OK;
872 		}
873 		break;
874 	case YXMLS_std1:
875 		if(yxml_isSP(ch))
876 			return YXML_OK;
877 		if((ch == (unsigned char)'\'') || (ch == (unsigned char)'"')) {
878 			x->state = YXMLS_std2;
879 			x->quote = ch;
880 			return YXML_OK;
881 		}
882 		break;
883 	case YXMLS_std2:
884 		if(ch == (unsigned char)'y') {
885 			x->state = YXMLS_string;
886 			x->nextstate = YXMLS_std3;
887 			x->string = (unsigned char *)"es";
888 			return YXML_OK;
889 		}
890 		if(ch == (unsigned char)'n') {
891 			x->state = YXMLS_string;
892 			x->nextstate = YXMLS_std3;
893 			x->string = (unsigned char *)"o";
894 			return YXML_OK;
895 		}
896 		break;
897 	case YXMLS_std3:
898 		if(x->quote == ch) {
899 			x->state = YXMLS_xmldecl8;
900 			return YXML_OK;
901 		}
902 		break;
903 	case YXMLS_ver0:
904 		if(yxml_isSP(ch))
905 			return YXML_OK;
906 		if(ch == (unsigned char)'=') {
907 			x->state = YXMLS_ver1;
908 			return YXML_OK;
909 		}
910 		break;
911 	case YXMLS_ver1:
912 		if(yxml_isSP(ch))
913 			return YXML_OK;
914 		if((ch == (unsigned char)'\'') || (ch == (unsigned char)'"')) {
915 			x->state = YXMLS_string;
916 			x->quote = ch;
917 			x->nextstate = YXMLS_ver2;
918 			x->string = (unsigned char *)"1.";
919 			return YXML_OK;
920 		}
921 		break;
922 	case YXMLS_ver2:
923 		if(yxml_isNum(ch)) {
924 			x->state = YXMLS_ver3;
925 			return YXML_OK;
926 		}
927 		break;
928 	case YXMLS_ver3:
929 		if(yxml_isNum(ch))
930 			return YXML_OK;
931 		if(x->quote == ch) {
932 			x->state = YXMLS_xmldecl4;
933 			return YXML_OK;
934 		}
935 		break;
936 	case YXMLS_xmldecl0:
937 		if(ch == (unsigned char)'m') {
938 			x->state = YXMLS_xmldecl1;
939 			return yxml_piname(x, ch);
940 		}
941 		if(yxml_isName(ch)) {
942 			x->state = YXMLS_pi1;
943 			return yxml_piname(x, ch);
944 		}
945 		if(ch == (unsigned char)'?') {
946 			x->state = YXMLS_pi4;
947 			return yxml_pinameend(x, ch);
948 		}
949 		if(yxml_isSP(ch)) {
950 			x->state = YXMLS_pi2;
951 			return yxml_pinameend(x, ch);
952 		}
953 		break;
954 	case YXMLS_xmldecl1:
955 		if(ch == (unsigned char)'l') {
956 			x->state = YXMLS_xmldecl2;
957 			return yxml_piname(x, ch);
958 		}
959 		if(yxml_isName(ch)) {
960 			x->state = YXMLS_pi1;
961 			return yxml_piname(x, ch);
962 		}
963 		if(ch == (unsigned char)'?') {
964 			x->state = YXMLS_pi4;
965 			return yxml_pinameend(x, ch);
966 		}
967 		if(yxml_isSP(ch)) {
968 			x->state = YXMLS_pi2;
969 			return yxml_pinameend(x, ch);
970 		}
971 		break;
972 	case YXMLS_xmldecl2:
973 		if(yxml_isSP(ch)) {
974 			x->state = YXMLS_xmldecl3;
975 			return yxml_piabort(x, ch);
976 		}
977 		if(yxml_isName(ch)) {
978 			x->state = YXMLS_pi1;
979 			return yxml_piname(x, ch);
980 		}
981 		break;
982 	case YXMLS_xmldecl3:
983 		if(yxml_isSP(ch))
984 			return YXML_OK;
985 		if(ch == (unsigned char)'v') {
986 			x->state = YXMLS_string;
987 			x->nextstate = YXMLS_ver0;
988 			x->string = (unsigned char *)"ersion";
989 			return YXML_OK;
990 		}
991 		break;
992 	case YXMLS_xmldecl4:
993 		if(yxml_isSP(ch)) {
994 			x->state = YXMLS_xmldecl5;
995 			return YXML_OK;
996 		}
997 		if(ch == (unsigned char)'?') {
998 			x->state = YXMLS_xmldecl9;
999 			return YXML_OK;
1000 		}
1001 		break;
1002 	case YXMLS_xmldecl5:
1003 		if(yxml_isSP(ch))
1004 			return YXML_OK;
1005 		if(ch == (unsigned char)'?') {
1006 			x->state = YXMLS_xmldecl9;
1007 			return YXML_OK;
1008 		}
1009 		if(ch == (unsigned char)'e') {
1010 			x->state = YXMLS_string;
1011 			x->nextstate = YXMLS_enc0;
1012 			x->string = (unsigned char *)"ncoding";
1013 			return YXML_OK;
1014 		}
1015 		if(ch == (unsigned char)'s') {
1016 			x->state = YXMLS_string;
1017 			x->nextstate = YXMLS_std0;
1018 			x->string = (unsigned char *)"tandalone";
1019 			return YXML_OK;
1020 		}
1021 		break;
1022 	case YXMLS_xmldecl6:
1023 		if(yxml_isSP(ch)) {
1024 			x->state = YXMLS_xmldecl7;
1025 			return YXML_OK;
1026 		}
1027 		if(ch == (unsigned char)'?') {
1028 			x->state = YXMLS_xmldecl9;
1029 			return YXML_OK;
1030 		}
1031 		break;
1032 	case YXMLS_xmldecl7:
1033 		if(yxml_isSP(ch))
1034 			return YXML_OK;
1035 		if(ch == (unsigned char)'?') {
1036 			x->state = YXMLS_xmldecl9;
1037 			return YXML_OK;
1038 		}
1039 		if(ch == (unsigned char)'s') {
1040 			x->state = YXMLS_string;
1041 			x->nextstate = YXMLS_std0;
1042 			x->string = (unsigned char *)"tandalone";
1043 			return YXML_OK;
1044 		}
1045 		break;
1046 	case YXMLS_xmldecl8:
1047 		if(yxml_isSP(ch))
1048 			return YXML_OK;
1049 		if(ch == (unsigned char)'?') {
1050 			x->state = YXMLS_xmldecl9;
1051 			return YXML_OK;
1052 		}
1053 		break;
1054 	case YXMLS_xmldecl9:
1055 		if(ch == (unsigned char)'>') {
1056 			x->state = YXMLS_misc1;
1057 			return YXML_OK;
1058 		}
1059 		break;
1060 	default:
1061 		break;
1062 	}
1063 	return YXML_ESYN;
1064 }
1065 
1066 
yxml_eof(yxml_t * x)1067 yxml_ret_t yxml_eof(yxml_t *x) {
1068 	if(x->state != YXMLS_misc3)
1069 		return YXML_EEOF;
1070 	return YXML_OK;
1071 }
1072 
1073 
1074 /* vim: set noet sw=4 ts=4: */
1075