1 /*
2  Copyright (C) 2015-2017 Alexander Borisov
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 
18  Author: lex.borisov@gmail.com (Alexander Borisov)
19 */
20 
21 #include "myhtml/rules.h"
22 
myhtml_insertion_fix_emit_for_text_begin_ws(myhtml_token_t * token,myhtml_token_node_t * node)23 void myhtml_insertion_fix_emit_for_text_begin_ws(myhtml_token_t* token, myhtml_token_node_t* node)
24 {
25     myhtml_token_node_wait_for_done(token, node);
26     mycore_string_crop_whitespace_from_begin(&node->str);
27 }
28 
myhtml_insertion_fix_split_for_text_begin_ws(myhtml_tree_t * tree,myhtml_token_node_t * token)29 myhtml_token_node_t * myhtml_insertion_fix_split_for_text_begin_ws(myhtml_tree_t* tree, myhtml_token_node_t* token)
30 {
31     myhtml_token_node_wait_for_done(tree->token, token);
32     size_t len = mycore_string_whitespace_from_begin(&token->str);
33 
34     if(len == 0)
35         return NULL;
36 
37     // create new ws token and insert
38     myhtml_token_node_t* new_token = myhtml_token_node_create(tree->token, tree->mcasync_rules_token_id);
39 
40     if(new_token == NULL)
41         return NULL;
42 
43     mycore_string_init(tree->mchar, tree->mchar_node_id, &new_token->str, (len + 2));
44 
45     mycore_string_append(&new_token->str, token->str.data, len);
46 
47     new_token->type |= MyHTML_TOKEN_TYPE_DONE;
48 
49     // and cut ws for original
50     token->str.data    = mchar_async_crop_first_chars_without_cache(token->str.data, len);
51     token->str.length -= len;
52 
53     return new_token;
54 }
55 
myhtml_insertion_fix_for_null_char_drop_all(myhtml_tree_t * tree,myhtml_token_node_t * token)56 void myhtml_insertion_fix_for_null_char_drop_all(myhtml_tree_t* tree, myhtml_token_node_t* token)
57 {
58     myhtml_token_node_wait_for_done(tree->token, token);
59 
60     mycore_string_t *str = &token->str;
61     size_t len = str->length;
62     size_t offset = 0;
63 
64     for (size_t i = 0; i < len; ++i)
65     {
66         if (str->data[i] == '\0')
67         {
68             size_t next_non_null = i;
69             while ((next_non_null < len) && str->data[next_non_null] == '\0') {++next_non_null;}
70 
71             str->length = str->length - (next_non_null - i);
72 
73             size_t next_null = next_non_null;
74             while ((next_null < len) && str->data[next_null] != '\0') {++next_null;}
75 
76             memmove(&str->data[(i - offset)], &str->data[next_non_null], (next_null - next_non_null));
77 
78             i = next_null - 1;
79 
80             offset++;
81         }
82     }
83 }
84 
myhtml_insertion_mode_initial(myhtml_tree_t * tree,myhtml_token_node_t * token)85 bool myhtml_insertion_mode_initial(myhtml_tree_t* tree, myhtml_token_node_t* token)
86 {
87     switch (token->tag_id)
88     {
89         case MyHTML_TAG__TEXT:
90         {
91             if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE) {
92                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:INFO */
93                 return false;
94             }
95 
96             myhtml_insertion_fix_emit_for_text_begin_ws(tree->token, token);
97 
98             // default, other token
99             tree->compat_mode = MyHTML_TREE_COMPAT_MODE_QUIRKS;
100             tree->insert_mode = MyHTML_INSERTION_MODE_BEFORE_HTML;
101             break;
102         }
103 
104         case MyHTML_TAG__COMMENT:
105         {
106             myhtml_tree_node_insert_comment(tree, token, tree->document);
107             return false;
108         }
109 
110         case MyHTML_TAG__DOCTYPE:
111         {
112             myhtml_token_node_wait_for_done(tree->token, token);
113 
114             myhtml_token_release_and_check_doctype_attributes(tree->token, token, &tree->doctype);
115 
116             if((tree->parse_flags & MyHTML_TREE_PARSE_FLAGS_WITHOUT_DOCTYPE_IN_TREE) == 0)
117                 myhtml_tree_node_insert_doctype(tree, token);
118 
119             // fix for tokenizer
120             if(tree->doctype.is_html == false &&
121                (tree->doctype.attr_public == NULL ||
122                tree->doctype.attr_system == NULL))
123             {
124                 tree->compat_mode = MyHTML_TREE_COMPAT_MODE_QUIRKS;
125             }
126 
127             tree->insert_mode = MyHTML_INSERTION_MODE_BEFORE_HTML;
128             return false;
129         }
130 
131         default:
132             tree->compat_mode = MyHTML_TREE_COMPAT_MODE_QUIRKS;
133             tree->insert_mode = MyHTML_INSERTION_MODE_BEFORE_HTML;
134             break;
135     }
136 
137     return true;
138 }
139 
myhtml_insertion_mode_before_html(myhtml_tree_t * tree,myhtml_token_node_t * token)140 bool myhtml_insertion_mode_before_html(myhtml_tree_t* tree, myhtml_token_node_t* token)
141 {
142     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
143     {
144         switch (token->tag_id) {
145             case MyHTML_TAG_BR:
146             case MyHTML_TAG_HTML:
147             case MyHTML_TAG_HEAD:
148             case MyHTML_TAG_BODY:
149             {
150                 myhtml_tree_node_insert_root(tree, NULL, MyHTML_NAMESPACE_HTML);
151 
152                 /* %EXTERNAL% VALIDATOR:RULES TAG STATUS:ELEMENT_MISSING_NEED LEVEL:INFO TAG_ID:MyHTML_TAG_HTML NS:MyHTML_NAMESPACE_HTML */
153 
154                 tree->insert_mode = MyHTML_INSERTION_MODE_BEFORE_HEAD;
155                 return true;
156             }
157 
158             default: {
159                 // parse error
160                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:WARNING */
161                 break;
162             }
163         }
164     }
165     else {
166         switch (token->tag_id)
167         {
168             case MyHTML_TAG__DOCTYPE: {
169                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:WARNING */
170                 break;
171             }
172 
173             case MyHTML_TAG__COMMENT:
174             {
175                 myhtml_tree_node_insert_comment(tree, token, tree->document);
176                 break;
177             }
178 
179             case MyHTML_TAG__TEXT:
180             {
181                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE) {
182                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:INFO */
183                     break;
184                 }
185 
186                 myhtml_insertion_fix_emit_for_text_begin_ws(tree->token, token);
187 
188                 // default, other token
189                 myhtml_tree_node_insert_root(tree, NULL, MyHTML_NAMESPACE_HTML);
190                 tree->insert_mode = MyHTML_INSERTION_MODE_BEFORE_HEAD;
191                 return true;
192             }
193 
194             case MyHTML_TAG_HTML:
195             {
196                 myhtml_tree_node_insert_root(tree, token, MyHTML_NAMESPACE_HTML);
197                 tree->insert_mode = MyHTML_INSERTION_MODE_BEFORE_HEAD;
198                 break;
199             }
200 
201             default:
202             {
203                 myhtml_tree_node_insert_root(tree, NULL, MyHTML_NAMESPACE_HTML);
204                 /* %EXTERNAL% VALIDATOR:RULES TAG STATUS:ELEMENT_MISSING_NEED LEVEL:INFO TAG_ID:MyHTML_TAG_HTML NS:MyHTML_NAMESPACE_HTML */
205 
206                 tree->insert_mode = MyHTML_INSERTION_MODE_BEFORE_HEAD;
207                 return true;
208             }
209         }
210     }
211 
212     return false;
213 }
214 
myhtml_insertion_mode_before_head(myhtml_tree_t * tree,myhtml_token_node_t * token)215 bool myhtml_insertion_mode_before_head(myhtml_tree_t* tree, myhtml_token_node_t* token)
216 {
217     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
218     {
219         switch (token->tag_id) {
220             case MyHTML_TAG_BR:
221             case MyHTML_TAG_HTML:
222             case MyHTML_TAG_HEAD:
223             case MyHTML_TAG_BODY:
224             {
225                 tree->node_head = myhtml_tree_node_insert(tree, MyHTML_TAG_HEAD, MyHTML_NAMESPACE_HTML);
226                 /* %EXTERNAL% VALIDATOR:RULES TAG STATUS:ELEMENT_MISSING_NEED LEVEL:INFO TAG_ID:MyHTML_TAG_HEAD NS:MyHTML_NAMESPACE_HTML */
227 
228                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD;
229                 return true;
230             }
231 
232             default: {
233                 // parse error
234                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
235                 break;
236             }
237         }
238     }
239     else {
240         switch (token->tag_id)
241         {
242             case MyHTML_TAG__TEXT:
243             {
244                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE) {
245                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:INFO */
246                     break;
247                 }
248 
249                 myhtml_insertion_fix_emit_for_text_begin_ws(tree->token, token);
250 
251                 // default, other token
252                 tree->node_head = myhtml_tree_node_insert(tree, MyHTML_TAG_HEAD, MyHTML_NAMESPACE_HTML);
253                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD;
254                 return true;
255             }
256 
257             case MyHTML_TAG__COMMENT:
258             {
259                 myhtml_tree_node_insert_comment(tree, token, 0);
260                 break;
261             }
262 
263             case MyHTML_TAG__DOCTYPE: {
264                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
265                 break;
266             }
267 
268             case MyHTML_TAG_HTML:
269             {
270                 return myhtml_insertion_mode_in_body(tree, token);
271             }
272 
273             case MyHTML_TAG_HEAD:
274             {
275                 tree->node_head = myhtml_tree_node_insert_html_element(tree, token);
276                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD;
277                 break;
278             }
279 
280             default:
281             {
282                 tree->node_head = myhtml_tree_node_insert(tree, MyHTML_TAG_HEAD, MyHTML_NAMESPACE_HTML);
283                 /* %EXTERNAL% VALIDATOR:RULES TAG STATUS:ELEMENT_MISSING_NEED LEVEL:INFO TAG_ID:MyHTML_TAG_HEAD NS:MyHTML_NAMESPACE_HTML */
284 
285                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD;
286                 return true;
287             }
288         }
289     }
290 
291     return false;
292 }
293 
myhtml_insertion_mode_in_head(myhtml_tree_t * tree,myhtml_token_node_t * token)294 bool myhtml_insertion_mode_in_head(myhtml_tree_t* tree, myhtml_token_node_t* token)
295 {
296     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
297     {
298         switch (token->tag_id) {
299             case MyHTML_TAG_HEAD:
300             {
301                 myhtml_tree_open_elements_pop(tree);
302                 tree->insert_mode = MyHTML_INSERTION_MODE_AFTER_HEAD;
303                 break;
304             }
305 
306             case MyHTML_TAG_BR:
307             case MyHTML_TAG_HTML:
308             case MyHTML_TAG_BODY:
309             {
310                 myhtml_tree_open_elements_pop(tree);
311                 tree->insert_mode = MyHTML_INSERTION_MODE_AFTER_HEAD;
312                 return true;
313             }
314 
315             case MyHTML_TAG_TEMPLATE:
316             {
317                 if(myhtml_tree_open_elements_find_by_tag_idx_reverse(tree, MyHTML_TAG_TEMPLATE, MyHTML_NAMESPACE_HTML, NULL) == NULL)
318                 {
319                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:WARNING */
320                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_ANY NEED_TAG_ID:MyHTML_TAG_TEMPLATE NEED_NS:MyHTML_NAMESPACE_HTML */
321 
322                     break;
323                 }
324 
325                 // oh God...
326                 myhtml_tree_generate_all_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
327 
328                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
329                 if(current_node && current_node->tag_id != MyHTML_TAG_TEMPLATE) {
330                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED_CLOSE_BEFORE LEVEL:WARNING */
331                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_TEMPLATE NEED_NS:MyHTML_NAMESPACE_HTML */
332                 }
333 
334                 myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_TEMPLATE, MyHTML_NAMESPACE_HTML, false);
335                 myhtml_tree_active_formatting_up_to_last_marker(tree);
336                 myhtml_tree_template_insertion_pop(tree);
337                 myhtml_tree_reset_insertion_mode_appropriately(tree);
338 
339                 break;
340             }
341 
342             default: {
343                 // parse error
344                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:WARNING */
345                 break;
346             }
347         }
348     }
349     else {
350         switch (token->tag_id)
351         {
352             case MyHTML_TAG__TEXT:
353             {
354                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE)
355                 {
356                     myhtml_tree_node_insert_text(tree, token);
357                     break;
358                 }
359 
360                 myhtml_token_node_t* new_token = myhtml_insertion_fix_split_for_text_begin_ws(tree, token);
361                 if(new_token)
362                     myhtml_tree_node_insert_text(tree, new_token);
363 
364                 // default, other token
365                 myhtml_tree_open_elements_pop(tree);
366                 tree->insert_mode = MyHTML_INSERTION_MODE_AFTER_HEAD;
367                 return true;
368             }
369 
370             case MyHTML_TAG__COMMENT:
371             {
372                 myhtml_tree_node_insert_comment(tree, token, 0);
373                 break;
374             }
375 
376             case MyHTML_TAG__DOCTYPE: {
377                 // parse error
378                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
379                 break;
380             }
381 
382             case MyHTML_TAG_HTML:
383             {
384                 return myhtml_insertion_mode_in_body(tree, token);
385             }
386 
387             case MyHTML_TAG_BASE:
388             case MyHTML_TAG_BASEFONT:
389             case MyHTML_TAG_BGSOUND:
390             case MyHTML_TAG_LINK:
391             {
392                 myhtml_tree_node_insert_html_element(tree, token);
393                 myhtml_tree_open_elements_pop(tree);
394                 break;
395             }
396 
397             case MyHTML_TAG_META:
398             {
399                 myhtml_tree_node_insert_html_element(tree, token);
400                 myhtml_tree_open_elements_pop(tree);
401 
402                 // if the element has an http-equiv attribute
403                 break;
404             }
405 
406             case MyHTML_TAG_TITLE:
407             {
408                 myhtml_tree_node_insert_html_element(tree, token);
409 
410                 tree->orig_insert_mode = tree->insert_mode;
411                 tree->insert_mode = MyHTML_INSERTION_MODE_TEXT;
412                 tree->state_of_builder = MyHTML_TOKENIZER_STATE_RCDATA;
413 
414                 break;
415             }
416 
417             case MyHTML_TAG_NOSCRIPT:
418             {
419                 if(tree->flags & MyHTML_TREE_FLAGS_SCRIPT) {
420                     myhtml_tree_node_insert_html_element(tree, token);
421 
422                     tree->orig_insert_mode = tree->insert_mode;
423                     tree->insert_mode = MyHTML_INSERTION_MODE_TEXT;
424                     tree->state_of_builder = MyHTML_TOKENIZER_STATE_RAWTEXT;
425                 }
426                 else {
427                     myhtml_tree_node_insert_html_element(tree, token);
428                     tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD_NOSCRIPT;
429                 }
430 
431                 break;
432             }
433 
434             case MyHTML_TAG_STYLE:
435             case MyHTML_TAG_NOFRAMES:
436             {
437                 myhtml_tree_node_insert_html_element(tree, token);
438 
439                 tree->orig_insert_mode = tree->insert_mode;
440                 tree->insert_mode = MyHTML_INSERTION_MODE_TEXT;
441                 tree->state_of_builder = MyHTML_TOKENIZER_STATE_RAWTEXT;
442 
443                 break;
444             }
445 
446             case MyHTML_TAG_SCRIPT:
447             {
448                 // state 1
449                 enum myhtml_tree_insertion_mode insert_mode;
450                 myhtml_tree_node_t* adjusted_location = myhtml_tree_appropriate_place_inserting(tree, NULL, &insert_mode);
451 
452                 // state 2
453                 myhtml_tree_node_t* node = myhtml_tree_node_create(tree);
454 
455                 node->tag_id      = MyHTML_TAG_SCRIPT;
456                 node->token        = token;
457                 node->ns = MyHTML_NAMESPACE_HTML;
458                 node->flags        = MyHTML_TREE_NODE_PARSER_INSERTED|MyHTML_TREE_NODE_BLOCKING;
459 
460                 myhtml_tree_node_insert_by_mode(adjusted_location, node, insert_mode);
461                 myhtml_tree_open_elements_append(tree, node);
462 
463                 tree->orig_insert_mode = tree->insert_mode;
464                 tree->insert_mode = MyHTML_INSERTION_MODE_TEXT;
465                 tree->state_of_builder = MyHTML_TOKENIZER_STATE_SCRIPT_DATA;
466 
467                 break;
468             }
469 
470             case MyHTML_TAG_TEMPLATE:
471             {
472                 myhtml_tree_node_insert_html_element(tree, token);
473                 myhtml_tree_active_formatting_append(tree, tree->myhtml->marker); // set marker
474 
475                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
476 
477                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TEMPLATE;
478                 myhtml_tree_template_insertion_append(tree, MyHTML_INSERTION_MODE_IN_TEMPLATE);
479 
480                 break;
481             }
482 
483             case MyHTML_TAG_HEAD: {
484                 // parse error
485                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY LEVEL:WARNING */
486                 break;
487             }
488 
489             default:
490             {
491                 myhtml_tree_open_elements_pop(tree);
492 
493                 tree->insert_mode = MyHTML_INSERTION_MODE_AFTER_HEAD;
494                 return true;
495             }
496         }
497     }
498 
499     return false;
500 }
501 
myhtml_insertion_mode_in_head_noscript(myhtml_tree_t * tree,myhtml_token_node_t * token)502 bool myhtml_insertion_mode_in_head_noscript(myhtml_tree_t* tree, myhtml_token_node_t* token)
503 {
504     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
505     {
506         switch (token->tag_id) {
507             case MyHTML_TAG_NOSCRIPT:
508             {
509                 myhtml_tree_open_elements_pop(tree);
510                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD;
511                 break;
512             }
513 
514             case MyHTML_TAG_BR:
515             {
516                 myhtml_tree_open_elements_pop(tree);
517                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD;
518                 return true;
519             }
520 
521             default: {
522                 // parse error
523                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
524                 break;
525             }
526         }
527     }
528     else {
529         switch (token->tag_id)
530         {
531             case MyHTML_TAG__DOCTYPE: {
532                 // parse error
533                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
534                 break;
535             }
536 
537             case MyHTML_TAG_HTML:
538             {
539                 return myhtml_insertion_mode_in_body(tree, token);
540             }
541 
542             case MyHTML_TAG__TEXT:
543             {
544                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE)
545                     return myhtml_insertion_mode_in_head(tree, token);
546 
547                 // default, other token
548                 myhtml_tree_open_elements_pop(tree);
549                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD;
550                 return true;
551             }
552 
553             case MyHTML_TAG_BASEFONT:
554             case MyHTML_TAG_BGSOUND:
555             case MyHTML_TAG_LINK:
556             case MyHTML_TAG_META:
557             case MyHTML_TAG_NOFRAMES:
558             case MyHTML_TAG_STYLE:
559             case MyHTML_TAG__COMMENT:
560                 return myhtml_insertion_mode_in_head(tree, token);
561 
562             case MyHTML_TAG_HEAD:
563             case MyHTML_TAG_NOSCRIPT: {
564                 // parse error
565                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY LEVEL:WARNING */
566                 break;
567             }
568 
569             default:
570             {
571                 // parse error
572                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
573 
574                 myhtml_tree_open_elements_pop(tree);
575                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD;
576                 return true;
577             }
578         }
579     }
580 
581     return false;
582 }
583 
myhtml_insertion_mode_after_head(myhtml_tree_t * tree,myhtml_token_node_t * token)584 bool myhtml_insertion_mode_after_head(myhtml_tree_t* tree, myhtml_token_node_t* token)
585 {
586     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
587     {
588         switch (token->tag_id) {
589             case MyHTML_TAG_BR:
590             case MyHTML_TAG_HTML:
591             case MyHTML_TAG_BODY:
592             {
593                 tree->node_body = myhtml_tree_node_insert(tree, MyHTML_TAG_BODY, MyHTML_NAMESPACE_HTML);
594                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
595 
596                 /* %EXTERNAL% VALIDATOR:RULES TAG STATUS:ELEMENT_MISSING_NEED LEVEL:INFO TAG_ID:MyHTML_TAG_BODY NS:MyHTML_NAMESPACE_HTML */
597                 return true;
598             }
599 
600             case MyHTML_TAG_TEMPLATE:
601             {
602                 return myhtml_insertion_mode_in_head(tree, token);
603             }
604 
605             default: {
606                 // parse error
607                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
608                 break;
609             }
610         }
611     }
612     else {
613         switch (token->tag_id)
614         {
615             case MyHTML_TAG__TEXT:
616             {
617                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE)
618                 {
619                     myhtml_tree_node_insert_text(tree, token);
620                     break;
621                 }
622 
623                 myhtml_token_node_t* new_token = myhtml_insertion_fix_split_for_text_begin_ws(tree, token);
624                 if(new_token)
625                     myhtml_tree_node_insert_text(tree, new_token);
626 
627                 // default, other token
628                 tree->node_body = myhtml_tree_node_insert(tree, MyHTML_TAG_BODY, MyHTML_NAMESPACE_HTML);
629                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
630                 return true;
631             }
632 
633             case MyHTML_TAG__COMMENT:
634                 myhtml_tree_node_insert_comment(tree, token, 0);
635                 break;
636 
637             case MyHTML_TAG__DOCTYPE: {
638                 // parse error
639                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
640                 break;
641             }
642 
643             case MyHTML_TAG_HTML:
644                 return myhtml_insertion_mode_in_body(tree, token);
645 
646             case MyHTML_TAG_BODY:
647             {
648                 tree->node_body = myhtml_tree_node_insert_html_element(tree, token);
649 
650                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
651                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
652                 break;
653             }
654 
655             case MyHTML_TAG_FRAMESET:
656                 myhtml_tree_node_insert_html_element(tree, token);
657                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_FRAMESET;
658                 break;
659 
660             case MyHTML_TAG_BASE:
661             case MyHTML_TAG_BASEFONT:
662             case MyHTML_TAG_BGSOUND:
663             case MyHTML_TAG_LINK:
664             case MyHTML_TAG_META:
665             case MyHTML_TAG_NOFRAMES:
666             case MyHTML_TAG_SCRIPT:
667             case MyHTML_TAG_STYLE:
668             case MyHTML_TAG_TEMPLATE:
669             case MyHTML_TAG_TITLE:
670             {
671                 // parse error
672                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
673 
674                 myhtml_tree_open_elements_append(tree, tree->node_head);
675                 myhtml_insertion_mode_in_head(tree, token);
676                 myhtml_tree_open_elements_remove(tree, tree->node_head);
677             }
678 
679             case MyHTML_TAG_HEAD: {
680                 // parse error
681                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY LEVEL:WARNING */
682                 break;
683             }
684 
685             default:
686             {
687                 tree->node_body = myhtml_tree_node_insert(tree, MyHTML_TAG_BODY, MyHTML_NAMESPACE_HTML);
688                 /* %EXTERNAL% VALIDATOR:RULES TAG STATUS:ELEMENT_MISSING_NEED LEVEL:INFO TAG_ID:MyHTML_TAG_BODY NS:MyHTML_NAMESPACE_HTML */
689 
690                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
691                 return true;
692             }
693         }
694     }
695 
696     return false;
697 }
698 
myhtml_insertion_mode_in_body_other_end_tag(myhtml_tree_t * tree,myhtml_token_node_t * token)699 bool myhtml_insertion_mode_in_body_other_end_tag(myhtml_tree_t* tree, myhtml_token_node_t* token)
700 {
701     // step 1
702     size_t i = tree->open_elements->length;
703     while(i) {
704         i--;
705 
706         myhtml_tree_node_t* node = tree->open_elements->list[i];
707 
708         // step 2
709         if(node->tag_id == token->tag_id && node->ns == MyHTML_NAMESPACE_HTML) {
710             myhtml_tree_generate_implied_end_tags(tree, token->tag_id, MyHTML_NAMESPACE_HTML);
711 
712             myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
713             if(current_node->tag_id != node->tag_id) {
714                 // parse error
715                 /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
716                 /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:node->tag_id NEED_NS:node->ns */
717             }
718 
719             myhtml_tree_open_elements_pop_until_by_node(tree, node, false);
720 
721             return false;
722         }
723 
724         const myhtml_tag_context_t *tag_ctx = myhtml_tag_get_by_id(tree->tags, node->tag_id);
725         if(tag_ctx->cats[ node->ns ] & MyHTML_TAG_CATEGORIES_SPECIAL) {
726             // parse error
727             /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
728             break;
729         }
730     }
731 
732     return false;
733 }
734 
myhtml_insertion_mode_in_body(myhtml_tree_t * tree,myhtml_token_node_t * token)735 bool myhtml_insertion_mode_in_body(myhtml_tree_t* tree, myhtml_token_node_t* token)
736 {
737     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
738     {
739         switch (token->tag_id) {
740             case MyHTML_TAG_TEMPLATE:
741             {
742                 return myhtml_insertion_mode_in_head(tree, token);
743             }
744 
745             case MyHTML_TAG_BODY:
746             {
747                 myhtml_tree_node_t* body_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_BODY, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE);
748 
749                 if(body_node == NULL) {
750                     // parse error
751                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
752                     break;
753                 }
754 
755                 for (size_t i = 0; i < tree->open_elements->length; i++) {
756                     switch (tree->open_elements->list[i]->tag_id) {
757                         case MyHTML_TAG_DD:
758                         case MyHTML_TAG_DT:
759                         case MyHTML_TAG_LI:
760                         case MyHTML_TAG_MENUITEM:
761                         case MyHTML_TAG_OPTGROUP:
762                         case MyHTML_TAG_OPTION:
763                         case MyHTML_TAG_P:
764                         case MyHTML_TAG_RB:
765                         case MyHTML_TAG_RP:
766                         case MyHTML_TAG_RT:
767                         case MyHTML_TAG_RTC:
768                         case MyHTML_TAG_TBODY:
769                         case MyHTML_TAG_TD:
770                         case MyHTML_TAG_TFOOT:
771                         case MyHTML_TAG_TH:
772                         case MyHTML_TAG_THEAD:
773                         case MyHTML_TAG_TR:
774                         case MyHTML_TAG_BODY:
775                         case MyHTML_TAG_HTML:
776                             // set parse error
777                             break;
778 
779                         default:
780                             break;
781                     }
782                 }
783 
784                 tree->insert_mode = MyHTML_INSERTION_MODE_AFTER_BODY;
785                 break;
786             }
787 
788             case MyHTML_TAG_HTML:
789             {
790                 myhtml_tree_node_t* body_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_BODY, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE);
791 
792                 if(body_node == NULL) {
793                     // parse error
794                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
795                     break;
796                 }
797 
798                 for (size_t i = 0; i < tree->open_elements->length; i++) {
799                     switch (tree->open_elements->list[i]->tag_id) {
800                         case MyHTML_TAG_DD:
801                         case MyHTML_TAG_DT:
802                         case MyHTML_TAG_LI:
803                         case MyHTML_TAG_MENUITEM:
804                         case MyHTML_TAG_OPTGROUP:
805                         case MyHTML_TAG_OPTION:
806                         case MyHTML_TAG_P:
807                         case MyHTML_TAG_RB:
808                         case MyHTML_TAG_RP:
809                         case MyHTML_TAG_RT:
810                         case MyHTML_TAG_RTC:
811                         case MyHTML_TAG_TBODY:
812                         case MyHTML_TAG_TD:
813                         case MyHTML_TAG_TFOOT:
814                         case MyHTML_TAG_TH:
815                         case MyHTML_TAG_THEAD:
816                         case MyHTML_TAG_TR:
817                         case MyHTML_TAG_BODY:
818                         case MyHTML_TAG_HTML:
819                             // set parse error
820                             break;
821 
822                         default:
823                             break;
824                     }
825                 }
826                 tree->insert_mode = MyHTML_INSERTION_MODE_AFTER_BODY;
827 
828                 return true;
829             }
830 
831             case MyHTML_TAG_ADDRESS:
832             case MyHTML_TAG_ARTICLE:
833             case MyHTML_TAG_ASIDE:
834             case MyHTML_TAG_BLOCKQUOTE:
835             case MyHTML_TAG_BUTTON:
836             case MyHTML_TAG_CENTER:
837             case MyHTML_TAG_DETAILS:
838             case MyHTML_TAG_DIALOG:
839             case MyHTML_TAG_DIR:
840             case MyHTML_TAG_DIV:
841             case MyHTML_TAG_DL:
842             case MyHTML_TAG_FIELDSET:
843             case MyHTML_TAG_FIGCAPTION:
844             case MyHTML_TAG_FIGURE:
845             case MyHTML_TAG_FOOTER:
846             case MyHTML_TAG_HEADER:
847             case MyHTML_TAG_HGROUP:
848             case MyHTML_TAG_LISTING:
849             case MyHTML_TAG_MAIN:
850             case MyHTML_TAG_MENU:
851             case MyHTML_TAG_NAV:
852             case MyHTML_TAG_OL:
853             case MyHTML_TAG_PRE:
854             case MyHTML_TAG_SECTION:
855             case MyHTML_TAG_SUMMARY:
856             case MyHTML_TAG_UL:
857             {
858                 if(myhtml_tree_element_in_scope(tree, token->tag_id, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE) == NULL) {
859                     // parse error
860                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
861 
862                     break;
863                 }
864 
865                 // step 1
866                 myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
867 
868                 // step 2
869                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
870                 if(myhtml_is_html_node(current_node, token->tag_id) == false) {
871                     // parse error
872                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
873                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:token->tag_id NEED_NS:MyHTML_NAMESPACE_HTML */
874                 }
875 
876                 // step 3
877                 myhtml_tree_open_elements_pop_until(tree, token->tag_id, MyHTML_NAMESPACE_HTML, false);
878                 break;
879             }
880 
881             case MyHTML_TAG_FORM:
882             {
883                 myhtml_tree_node_t* template_node = myhtml_tree_open_elements_find_by_tag_idx(tree, MyHTML_TAG_TEMPLATE, MyHTML_NAMESPACE_HTML, NULL);
884 
885                 if(template_node == NULL)
886                 {
887                     // step 1
888                     myhtml_tree_node_t* node = tree->node_form;
889 
890                     // step 2
891                     tree->node_form = NULL;
892 
893                     // step 3
894                     if(node == NULL || myhtml_tree_element_in_scope_by_node(node, MyHTML_TAG_CATEGORIES_SCOPE) == false) {
895                         // parse error
896                         /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
897 
898                         break;
899                     }
900 
901                     // step 4
902                     myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
903 
904                     // step 5
905                     myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
906                     if(current_node != node) {
907                         // parse error
908                         /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
909                         /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:node->tag_id NEED_NS:node->ns */
910                     }
911 
912                     // step 6
913                     myhtml_tree_open_elements_remove(tree, node);
914                 }
915                 else {
916                     // step 1
917                     myhtml_tree_node_t* form_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_FORM, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE);
918 
919                     if(form_node == NULL) {
920                         // parse error
921                         /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
922 
923                         break;
924                     }
925 
926                     // step 2
927                     myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
928 
929                     // step 3
930                     myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
931                     if(myhtml_is_html_node(current_node, MyHTML_TAG_FORM) == false) {
932                         // parse error
933                         /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
934                         /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_FORM NEED_NS:MyHTML_NAMESPACE_HTML */
935                     }
936 
937                     // step 4
938                     myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_FORM, MyHTML_NAMESPACE_HTML, false);
939                 }
940 
941                 break;
942             }
943 
944             case MyHTML_TAG_P:
945             {
946                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON) == NULL) {
947                     // parse error
948                     myhtml_tree_node_insert(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML);
949                 }
950 
951                 myhtml_tree_tags_close_p(tree, token);
952                 break;
953             }
954 
955             case MyHTML_TAG_LI:
956             {
957                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_LI, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_LIST_ITEM) == NULL) {
958                     // parse error
959                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
960                     break;
961                 }
962 
963                 // step 1
964                 myhtml_tree_generate_implied_end_tags(tree, MyHTML_TAG_LI, MyHTML_NAMESPACE_HTML);
965 
966                 // step 2
967                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
968                 if(myhtml_is_html_node(current_node, MyHTML_TAG_LI) == false) {
969                     // parse error
970                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
971                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_LI NEED_NS:MyHTML_NAMESPACE_HTML */
972                 }
973 
974                 // step 3
975                 myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_LI, MyHTML_NAMESPACE_HTML, false);
976 
977                 break;
978             }
979 
980             case MyHTML_TAG_DT:
981             case MyHTML_TAG_DD:
982             {
983                 if(myhtml_tree_element_in_scope(tree, token->tag_id, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE) == NULL) {
984                     // parse error
985                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
986                     break;
987                 }
988 
989                 // step 1
990                 myhtml_tree_generate_implied_end_tags(tree, token->tag_id, MyHTML_NAMESPACE_HTML);
991 
992                 // step 2
993                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
994                 if(myhtml_is_html_node(current_node, token->tag_id) == false) {
995                     // parse error
996                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
997                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:token->tag_id NEED_NS:MyHTML_NAMESPACE_HTML */
998                 }
999 
1000                 // step 3
1001                 myhtml_tree_open_elements_pop_until(tree, token->tag_id, MyHTML_NAMESPACE_HTML, false);
1002 
1003                 break;
1004             }
1005 
1006             case MyHTML_TAG_H1:
1007             case MyHTML_TAG_H2:
1008             case MyHTML_TAG_H3:
1009             case MyHTML_TAG_H4:
1010             case MyHTML_TAG_H5:
1011             case MyHTML_TAG_H6:
1012             {
1013                 myhtml_tree_node_t** list = tree->open_elements->list;
1014 
1015                 myhtml_tree_node_t* node = NULL;
1016                 size_t i = tree->open_elements->length;
1017                 while(i) {
1018                     i--;
1019 
1020                     const myhtml_tag_context_t *tag_ctx = myhtml_tag_get_by_id(tree->tags, list[i]->tag_id);
1021 
1022                     if((list[i]->tag_id == MyHTML_TAG_H1 ||
1023                        list[i]->tag_id == MyHTML_TAG_H2  ||
1024                        list[i]->tag_id == MyHTML_TAG_H3  ||
1025                        list[i]->tag_id == MyHTML_TAG_H4  ||
1026                        list[i]->tag_id == MyHTML_TAG_H5  ||
1027                        list[i]->tag_id == MyHTML_TAG_H6) &&
1028                        list[i]->ns == MyHTML_NAMESPACE_HTML) {
1029                         node = list[i];
1030                         break;
1031                     }
1032                     else if(tag_ctx->cats[list[i]->ns] & MyHTML_TAG_CATEGORIES_SCOPE)
1033                         break;
1034                 }
1035 
1036                 if(node == NULL) {
1037                     // parse error
1038                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
1039                     break;
1040                 }
1041 
1042                 // step 1
1043                 myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
1044 
1045                 // step 2
1046                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1047                 if(myhtml_is_html_node(current_node, token->tag_id) == false) {
1048                     // parse error
1049                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
1050                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:token->tag_id NEED_NS:MyHTML_NAMESPACE_HTML */
1051                 }
1052 
1053                 // step 3
1054                 while(tree->open_elements->length) {
1055                     tree->open_elements->length--;
1056 
1057                     if((list[tree->open_elements->length]->tag_id == MyHTML_TAG_H1 ||
1058                        list[tree->open_elements->length]->tag_id == MyHTML_TAG_H2 ||
1059                        list[tree->open_elements->length]->tag_id == MyHTML_TAG_H3 ||
1060                        list[tree->open_elements->length]->tag_id == MyHTML_TAG_H4 ||
1061                        list[tree->open_elements->length]->tag_id == MyHTML_TAG_H5 ||
1062                        list[tree->open_elements->length]->tag_id == MyHTML_TAG_H6) &&
1063                        list[tree->open_elements->length]->ns == MyHTML_NAMESPACE_HTML)
1064                     {
1065                         break;
1066                     }
1067                 }
1068 
1069                 break;
1070             }
1071 
1072             case MyHTML_TAG_A:
1073             case MyHTML_TAG_B:
1074             case MyHTML_TAG_BIG:
1075             case MyHTML_TAG_CODE:
1076             case MyHTML_TAG_EM:
1077             case MyHTML_TAG_FONT:
1078             case MyHTML_TAG_I:
1079             case MyHTML_TAG_NOBR:
1080             case MyHTML_TAG_S:
1081             case MyHTML_TAG_SMALL:
1082             case MyHTML_TAG_STRIKE:
1083             case MyHTML_TAG_STRONG:
1084             case MyHTML_TAG_TT:
1085             case MyHTML_TAG_U:
1086             {
1087                 myhtml_tree_adoption_agency_algorithm(tree, token, token->tag_id);
1088                     //myhtml_insertion_mode_in_body_other_end_tag(tree, token);
1089 
1090                 break;
1091             }
1092 
1093             case MyHTML_TAG_APPLET:
1094             case MyHTML_TAG_MARQUEE:
1095             case MyHTML_TAG_OBJECT:
1096             {
1097                 if(myhtml_tree_element_in_scope(tree, token->tag_id, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE) == NULL) {
1098                     // parse error
1099                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
1100                     break;
1101                 }
1102 
1103                 // step 1
1104                 myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
1105 
1106                 // step 2
1107                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1108                 if(myhtml_is_html_node(current_node, token->tag_id) == false) {
1109                     // parse error
1110                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
1111                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:token->tag_id NEED_NS:MyHTML_NAMESPACE_HTML */
1112                 }
1113 
1114                 // step 3
1115                 myhtml_tree_open_elements_pop_until(tree, token->tag_id, MyHTML_NAMESPACE_HTML, false);
1116 
1117                 // step 4
1118                 myhtml_tree_active_formatting_up_to_last_marker(tree);
1119 
1120                 break;
1121             }
1122 
1123             case MyHTML_TAG_BR:
1124             {
1125                 // parse error
1126                 /* %EXTERNAL% VALIDATOR:RULES CONVERT STATUS:ELEMENT_BAD LEVEL:ERROR FROM_TAG_ID:MyHTML_TAG_BR FROM_NS:MyHTML_NAMESPACE_HTML FROM_TYPE:MyHTML_TOKEN_TYPE_CLOSE TO_TAG_ID:MyHTML_TAG_BR TO_NS:MyHTML_NAMESPACE_HTML TO_TYPE:MyHTML_TOKEN_TYPE_OPEN */
1127 
1128                 if(token->attr_first) {
1129                     token->attr_first = NULL;
1130                 }
1131 
1132                 if(token->attr_last) {
1133                     token->attr_last = NULL;
1134                 }
1135 
1136                 myhtml_tree_active_formatting_reconstruction(tree);
1137 
1138                 if (token->type & MyHTML_TOKEN_TYPE_DONE) {
1139                     token->type = MyHTML_TOKEN_TYPE_OPEN | MyHTML_TOKEN_TYPE_DONE;
1140                 } else {
1141                     token->type = MyHTML_TOKEN_TYPE_OPEN;
1142                 }
1143 
1144                 myhtml_tree_node_insert_html_element(tree, token);
1145                 myhtml_tree_open_elements_pop(tree);
1146 
1147                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1148 
1149                 break;
1150             }
1151 
1152             default:
1153             {
1154                 return myhtml_insertion_mode_in_body_other_end_tag(tree, token);
1155             }
1156         }
1157     }
1158     // open elements
1159     else {
1160         switch (token->tag_id)
1161         {
1162             case MyHTML_TAG__TEXT:
1163             {
1164                 if(token->type & MyHTML_TOKEN_TYPE_NULL) {
1165                     // parse error
1166                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:NULL_CHAR ACTION:IGNORE LEVEL:ERROR */
1167 
1168                     myhtml_insertion_fix_for_null_char_drop_all(tree, token);
1169 
1170                     if(token->str.length) {
1171                         myhtml_tree_active_formatting_reconstruction(tree);
1172                         myhtml_tree_node_insert_text(tree, token);
1173 
1174                         if((token->type & MyHTML_TOKEN_TYPE_WHITESPACE) == 0)
1175                             tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1176                     }
1177                 }
1178                 else {
1179                     myhtml_tree_active_formatting_reconstruction(tree);
1180                     myhtml_tree_node_insert_text(tree, token);
1181 
1182                     if((token->type & MyHTML_TOKEN_TYPE_WHITESPACE) == 0)
1183                         tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1184                 }
1185 
1186                 break;
1187             }
1188 
1189             case MyHTML_TAG__COMMENT:
1190                 myhtml_tree_node_insert_comment(tree, token, 0);
1191                 break;
1192 
1193             case MyHTML_TAG__DOCTYPE: {
1194                 // parse error
1195                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:WARNING */
1196                 break;
1197             }
1198 
1199             case MyHTML_TAG_HTML:
1200             {
1201                 if(myhtml_tree_open_elements_find_by_tag_idx(tree, MyHTML_TAG_TEMPLATE, MyHTML_NAMESPACE_HTML, NULL)) {
1202                     // parse error
1203                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:WARNING */
1204                     break;
1205                 }
1206 
1207                 // parse error
1208                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:WARNING */
1209 
1210                 if(tree->open_elements->length > 0) {
1211                     myhtml_tree_node_t* top_node = tree->open_elements->list[0];
1212 
1213                     if(top_node->token) {
1214                         myhtml_token_node_wait_for_done(tree->token, token);
1215                         myhtml_token_node_wait_for_done(tree->token, top_node->token);
1216                         myhtml_token_node_attr_copy_with_check(tree->token, token, top_node->token, tree->mcasync_rules_attr_id);
1217                     }
1218                     else {
1219                         top_node->token = token;
1220                     }
1221                 }
1222 
1223                 break;
1224             }
1225 
1226             case MyHTML_TAG_BASE:
1227             case MyHTML_TAG_BASEFONT:
1228             case MyHTML_TAG_BGSOUND:
1229             case MyHTML_TAG_LINK:
1230             case MyHTML_TAG_META:
1231             case MyHTML_TAG_NOFRAMES:
1232             case MyHTML_TAG_SCRIPT:
1233             case MyHTML_TAG_STYLE:
1234             case MyHTML_TAG_TEMPLATE:
1235             case MyHTML_TAG_TITLE:
1236             {
1237                 return myhtml_insertion_mode_in_head(tree, token);
1238             }
1239 
1240             case MyHTML_TAG_BODY:
1241             {
1242                 // parse error
1243                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:WARNING */
1244 
1245                 if(tree->open_elements->length > 1)
1246                 {
1247                     if(!(tree->open_elements->list[1]->tag_id == MyHTML_TAG_BODY &&
1248                          tree->open_elements->list[1]->ns == MyHTML_NAMESPACE_HTML) ||
1249                        myhtml_tree_open_elements_find_by_tag_idx(tree, MyHTML_TAG_TEMPLATE, MyHTML_NAMESPACE_HTML, NULL))
1250                     {
1251                         // parse error
1252                         /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:WARNING */
1253 
1254                         break;
1255                     }
1256                 }
1257                 else
1258                     break;
1259 
1260                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1261 
1262                 if(tree->open_elements->length > 1) {
1263                     myhtml_tree_node_t* top_node = tree->open_elements->list[1];
1264 
1265                     if(top_node->token) {
1266                         myhtml_token_node_wait_for_done(tree->token, token);
1267                         myhtml_token_node_wait_for_done(tree->token, top_node->token);
1268                         myhtml_token_node_attr_copy_with_check(tree->token, token, top_node->token, tree->mcasync_rules_attr_id);
1269                     }
1270                     else {
1271                         top_node->token = token;
1272                     }
1273                 }
1274 
1275                 break;
1276             }
1277 
1278             case MyHTML_TAG_FRAMESET:
1279             {
1280                 // parse error
1281                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
1282 
1283                 if(tree->open_elements->length > 1)
1284                 {
1285                     if(!(tree->open_elements->list[1]->tag_id == MyHTML_TAG_BODY &&
1286                          tree->open_elements->list[1]->ns == MyHTML_NAMESPACE_HTML))
1287                     {
1288                         // parse error
1289                         /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
1290 
1291                         break;
1292                     }
1293                 }
1294                 else
1295                     break;
1296 
1297                 if((tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK) == 0) {
1298                     // parse error
1299                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
1300 
1301                     break;
1302                 }
1303 
1304                 myhtml_tree_node_t* node = tree->open_elements->list[1];
1305 
1306                 myhtml_tree_node_remove(node);
1307                 myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_HTML, MyHTML_NAMESPACE_HTML, true);
1308 
1309                 myhtml_tree_node_insert_html_element(tree, token);
1310 
1311                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_FRAMESET;
1312                 break;
1313             }
1314 
1315             case MyHTML_TAG__END_OF_FILE:
1316             {
1317                 if(tree->template_insertion->length)
1318                     return myhtml_insertion_mode_in_template(tree, token);
1319 
1320                 myhtml_tree_node_t** list = tree->open_elements->list;
1321                 for(size_t i = 0; i < tree->open_elements->length; i++) {
1322                     if(list[i]->tag_id != MyHTML_TAG_DD       && list[i]->tag_id != MyHTML_TAG_DT       &&
1323                        list[i]->tag_id != MyHTML_TAG_LI       && list[i]->tag_id != MyHTML_TAG_MENUITEM &&
1324                        list[i]->tag_id != MyHTML_TAG_OPTGROUP && list[i]->tag_id != MyHTML_TAG_OPTION   &&
1325                        list[i]->tag_id != MyHTML_TAG_P        && list[i]->tag_id != MyHTML_TAG_RB       &&
1326                        list[i]->tag_id != MyHTML_TAG_RP       && list[i]->tag_id != MyHTML_TAG_RT       &&
1327                        list[i]->tag_id != MyHTML_TAG_RTC      && list[i]->tag_id != MyHTML_TAG_TBODY    &&
1328                        list[i]->tag_id != MyHTML_TAG_TD       && list[i]->tag_id != MyHTML_TAG_TFOOT    &&
1329                        list[i]->tag_id != MyHTML_TAG_TH       && list[i]->tag_id != MyHTML_TAG_THEAD    &&
1330                        list[i]->tag_id != MyHTML_TAG_TR       && list[i]->tag_id != MyHTML_TAG_BODY     &&
1331                        list[i]->tag_id != MyHTML_TAG_HTML     && list[i]->ns != MyHTML_NAMESPACE_HTML)
1332                     {
1333                         // parse error
1334                     }
1335                 }
1336 
1337                 myhtml_rules_stop_parsing(tree);
1338                 break;
1339             }
1340 
1341             case MyHTML_TAG_ADDRESS:
1342             case MyHTML_TAG_ARTICLE:
1343             case MyHTML_TAG_ASIDE:
1344             case MyHTML_TAG_BLOCKQUOTE:
1345             case MyHTML_TAG_CENTER:
1346             case MyHTML_TAG_DETAILS:
1347             case MyHTML_TAG_DIALOG:
1348             case MyHTML_TAG_DIR:
1349             case MyHTML_TAG_DIV:
1350             case MyHTML_TAG_DL:
1351             case MyHTML_TAG_FIELDSET:
1352             case MyHTML_TAG_FIGCAPTION:
1353             case MyHTML_TAG_FIGURE:
1354             case MyHTML_TAG_FOOTER:
1355             case MyHTML_TAG_HEADER:
1356             case MyHTML_TAG_HGROUP:
1357             case MyHTML_TAG_MAIN:
1358             case MyHTML_TAG_NAV:
1359             case MyHTML_TAG_OL:
1360             case MyHTML_TAG_P:
1361             case MyHTML_TAG_SECTION:
1362             case MyHTML_TAG_SUMMARY:
1363             case MyHTML_TAG_UL:
1364             {
1365                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1366                     myhtml_tree_tags_close_p(tree, token);
1367                 }
1368 
1369                 myhtml_tree_node_insert_html_element(tree, token);
1370                 break;
1371             }
1372 
1373             case MyHTML_TAG_MENU:
1374             {
1375                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1376                     myhtml_tree_tags_close_p(tree, token);
1377                 }
1378 
1379                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1380 
1381                 if(myhtml_is_html_node(current_node, MyHTML_TAG_MENUITEM))
1382                     myhtml_tree_open_elements_pop(tree);
1383 
1384                 myhtml_tree_node_insert_html_element(tree, token);
1385                 break;
1386             }
1387 
1388             case MyHTML_TAG_H1:
1389             case MyHTML_TAG_H2:
1390             case MyHTML_TAG_H3:
1391             case MyHTML_TAG_H4:
1392             case MyHTML_TAG_H5:
1393             case MyHTML_TAG_H6:
1394             {
1395                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1396                     myhtml_tree_tags_close_p(tree, token);
1397                 }
1398 
1399                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1400 
1401                 switch (current_node->tag_id) {
1402                     case MyHTML_TAG_H1:
1403                         case MyHTML_TAG_H2:
1404                         case MyHTML_TAG_H3:
1405                         case MyHTML_TAG_H4:
1406                         case MyHTML_TAG_H5:
1407                         case MyHTML_TAG_H6:
1408 
1409                         if(current_node->ns == MyHTML_NAMESPACE_HTML) {
1410                             // parse error
1411                             /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:WARNING */
1412                             myhtml_tree_open_elements_pop(tree);
1413                         }
1414 
1415                         break;
1416 
1417                     default:
1418                         break;
1419                 }
1420 
1421                 myhtml_tree_node_insert_html_element(tree, token);
1422                 break;
1423             }
1424 
1425             case MyHTML_TAG_PRE:
1426             case MyHTML_TAG_LISTING:
1427             {
1428                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1429                     myhtml_tree_tags_close_p(tree, token);
1430                 }
1431 
1432                 myhtml_tree_node_insert_html_element(tree, token);
1433 
1434                 // If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move on to the next one.
1435                 // (Newlines at the start of pre blocks are ignored as an authoring convenience.)
1436                 // !!! see dispatcher (myhtml_rules_tree_dispatcher) for this
1437                 tree->flags |= MyHTML_TREE_FLAGS_PARSE_FLAG|MyHTML_TREE_FLAGS_PARSE_FLAG_EMIT_NEWLINE;
1438 
1439                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1440                 break;
1441             }
1442 
1443             case MyHTML_TAG_FORM:
1444             {
1445                 myhtml_tree_node_t* is_in_node = myhtml_tree_open_elements_find_by_tag_idx(tree, MyHTML_TAG_TEMPLATE, MyHTML_NAMESPACE_HTML, NULL);
1446                 if(tree->node_form && is_in_node == NULL) {
1447                     // parse error
1448                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
1449                     break;
1450                 }
1451 
1452                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1453                     myhtml_tree_tags_close_p(tree, token);
1454                 }
1455 
1456                 myhtml_tree_node_t* current = myhtml_tree_node_insert_html_element(tree, token);
1457 
1458                 if(is_in_node == NULL)
1459                     tree->node_form = current;
1460 
1461                 break;
1462             }
1463 
1464             case MyHTML_TAG_LI:
1465             {
1466                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1467 
1468                 size_t oel_index = tree->open_elements->length;
1469 
1470                 while (oel_index) {
1471                     oel_index--;
1472 
1473                     myhtml_tree_node_t* node = tree->open_elements->list[oel_index];
1474                     const myhtml_tag_context_t *tag_ctx = myhtml_tag_get_by_id(tree->tags, node->tag_id);
1475 
1476                     /* 3 */
1477                     if(myhtml_is_html_node(node, MyHTML_TAG_LI)) {
1478                         /* 3.1 */
1479                         myhtml_tree_generate_implied_end_tags(tree, MyHTML_TAG_LI, MyHTML_NAMESPACE_HTML);
1480 
1481                         /* 3.2 */
1482                         myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1483                         if(myhtml_is_html_node(current_node, MyHTML_TAG_LI) == false) {
1484                             // parse error
1485                             /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
1486                             /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_LI NEED_NS:MyHTML_NAMESPACE_HTML */
1487                         }
1488 
1489                         /* 3.3 */
1490                         myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_LI, MyHTML_NAMESPACE_HTML, false);
1491                         break;
1492                     }
1493                     else if(tag_ctx->cats[node->ns] & MyHTML_TAG_CATEGORIES_SPECIAL)
1494                     {
1495                         if(!((node->tag_id == MyHTML_TAG_ADDRESS || node->tag_id == MyHTML_TAG_DIV ||
1496                              node->tag_id == MyHTML_TAG_P) && node->ns == MyHTML_NAMESPACE_HTML))
1497                                 break;
1498                     }
1499                 }
1500 
1501                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1502                     myhtml_tree_tags_close_p(tree, token);
1503                 }
1504 
1505                 myhtml_tree_node_insert_html_element(tree, token);
1506                 break;
1507             }
1508 
1509             case MyHTML_TAG_DT:
1510             case MyHTML_TAG_DD:
1511             {
1512                 // this is copy/past
1513                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1514 
1515                 size_t oel_index = tree->open_elements->length;
1516 
1517                 while (oel_index) {
1518                     oel_index--;
1519 
1520                     myhtml_tree_node_t* node = tree->open_elements->list[oel_index];
1521                     const myhtml_tag_context_t *tag_ctx = myhtml_tag_get_by_id(tree->tags, node->tag_id);
1522 
1523                     if(myhtml_is_html_node(node, MyHTML_TAG_DD)) {
1524                         myhtml_tree_generate_implied_end_tags(tree, MyHTML_TAG_DD, MyHTML_NAMESPACE_HTML);
1525 
1526                         /* 3.2 */
1527                         myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1528                         if(myhtml_is_html_node(current_node, MyHTML_TAG_DD)) {
1529                             // parse error
1530                             /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
1531                             /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_DD NEED_NS:MyHTML_NAMESPACE_HTML */
1532                         }
1533 
1534                         myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_DD, MyHTML_NAMESPACE_HTML, false);
1535                         break;
1536                     }
1537                     else if(myhtml_is_html_node(node, MyHTML_TAG_DT)) {
1538                         myhtml_tree_generate_implied_end_tags(tree, MyHTML_TAG_DT, MyHTML_NAMESPACE_HTML);
1539 
1540                         /* 3.2 */
1541                         myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1542                         if(myhtml_is_html_node(current_node, MyHTML_TAG_DT)) {
1543                             // parse error
1544                             /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
1545                             /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_DT NEED_NS:MyHTML_NAMESPACE_HTML */
1546                         }
1547 
1548                         myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_DT, MyHTML_NAMESPACE_HTML, false);
1549                         break;
1550                     }
1551                     else if(tag_ctx->cats[node->ns] & MyHTML_TAG_CATEGORIES_SPECIAL)
1552                     {
1553                         if(!((node->tag_id == MyHTML_TAG_ADDRESS || node->tag_id == MyHTML_TAG_DIV ||
1554                              node->tag_id == MyHTML_TAG_P) && node->ns == MyHTML_NAMESPACE_HTML))
1555                                 break;
1556                     }
1557                 }
1558 
1559                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1560                     myhtml_tree_tags_close_p(tree, token);
1561                 }
1562 
1563                 myhtml_tree_node_insert_html_element(tree, token);
1564                 break;
1565             }
1566 
1567             case MyHTML_TAG_PLAINTEXT:
1568             {
1569                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1570                     myhtml_tree_tags_close_p(tree, token);
1571                 }
1572 
1573                 myhtml_tree_node_insert_html_element(tree, token);
1574 
1575                 tree->state_of_builder = MyHTML_TOKENIZER_STATE_PLAINTEXT;
1576                 break;
1577             }
1578 
1579             case MyHTML_TAG_BUTTON:
1580             {
1581                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_BUTTON, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE)) {
1582                     // parse error
1583                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
1584 
1585                     myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
1586                     myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_BUTTON, MyHTML_NAMESPACE_HTML, false);
1587                 }
1588 
1589                 myhtml_tree_active_formatting_reconstruction(tree);
1590                 myhtml_tree_node_insert_html_element(tree, token);
1591 
1592                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1593                 break;
1594             }
1595 
1596             case MyHTML_TAG_A:
1597             {
1598                 myhtml_tree_node_t* node = myhtml_tree_active_formatting_between_last_marker(tree, MyHTML_TAG_A, NULL);
1599 
1600                 if(node) {
1601                     // parse error
1602                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
1603 
1604                     myhtml_tree_adoption_agency_algorithm(tree, token, MyHTML_TAG_A);
1605                     node = myhtml_tree_active_formatting_between_last_marker(tree, MyHTML_TAG_A, NULL);
1606 
1607                     if(node) {
1608                         myhtml_tree_open_elements_remove(tree, node);
1609                         myhtml_tree_active_formatting_remove(tree, node);
1610                     }
1611                 }
1612 
1613                 myhtml_tree_active_formatting_reconstruction(tree);
1614 
1615                 myhtml_tree_node_t* current = myhtml_tree_node_insert_html_element(tree, token);
1616                 myhtml_tree_active_formatting_append_with_check(tree, current);
1617                 break;
1618             }
1619 
1620             case MyHTML_TAG_B:
1621             case MyHTML_TAG_BIG:
1622             case MyHTML_TAG_CODE:
1623             case MyHTML_TAG_EM:
1624             case MyHTML_TAG_FONT:
1625             case MyHTML_TAG_I:
1626             case MyHTML_TAG_S:
1627             case MyHTML_TAG_SMALL:
1628             case MyHTML_TAG_STRIKE:
1629             case MyHTML_TAG_STRONG:
1630             case MyHTML_TAG_TT:
1631             case MyHTML_TAG_U:
1632             {
1633                 myhtml_tree_active_formatting_reconstruction(tree);
1634 
1635                 myhtml_tree_node_t* current = myhtml_tree_node_insert_html_element(tree, token);
1636                 myhtml_tree_active_formatting_append_with_check(tree, current);
1637                 break;
1638             }
1639 
1640             case MyHTML_TAG_NOBR:
1641             {
1642                 myhtml_tree_active_formatting_reconstruction(tree);
1643 
1644                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_NOBR, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE)) {
1645                     // parse error
1646                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
1647 
1648                     myhtml_tree_adoption_agency_algorithm(tree, token, MyHTML_TAG_NOBR);
1649                     myhtml_tree_active_formatting_reconstruction(tree);
1650                 }
1651 
1652                 myhtml_tree_node_t* current = myhtml_tree_node_insert_html_element(tree, token);
1653                 myhtml_tree_active_formatting_append_with_check(tree, current);
1654                 break;
1655             }
1656 
1657             case MyHTML_TAG_APPLET:
1658             case MyHTML_TAG_MARQUEE:
1659             case MyHTML_TAG_OBJECT:
1660             {
1661                 myhtml_tree_active_formatting_reconstruction(tree);
1662 
1663                 myhtml_tree_node_insert_html_element(tree, token);
1664                 myhtml_tree_active_formatting_append(tree, tree->myhtml->marker); // marker
1665 
1666                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1667                 break;
1668             }
1669 
1670             case MyHTML_TAG_TABLE:
1671             {
1672                 if((tree->compat_mode & MyHTML_TREE_COMPAT_MODE_QUIRKS) == 0 &&
1673                    myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON))
1674                 {
1675                     myhtml_tree_tags_close_p(tree, token);
1676                 }
1677 
1678                 myhtml_tree_node_insert_html_element(tree, token);
1679                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1680 
1681                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
1682                 break;
1683             }
1684 
1685             case MyHTML_TAG_AREA:
1686             case MyHTML_TAG_BR:
1687             case MyHTML_TAG_EMBED:
1688             case MyHTML_TAG_IMG:
1689             case MyHTML_TAG_KEYGEN:
1690             case MyHTML_TAG_WBR:
1691             {
1692                 myhtml_tree_active_formatting_reconstruction(tree);
1693 
1694                 myhtml_tree_node_insert_html_element(tree, token);
1695                 myhtml_tree_open_elements_pop(tree);
1696 
1697                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1698                 break;
1699             }
1700 
1701             case MyHTML_TAG_INPUT:
1702             {
1703                 myhtml_tree_active_formatting_reconstruction(tree);
1704 
1705                 myhtml_tree_node_insert_html_element(tree, token);
1706                 myhtml_tree_open_elements_pop(tree);
1707 
1708                 myhtml_token_node_wait_for_done(tree->token, token);
1709                 if(myhtml_token_attr_match_case(tree->token, token, "type", 4, "hidden", 6) == NULL) {
1710                     tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1711                 }
1712 
1713                 break;
1714             }
1715 
1716             case MyHTML_TAG_PARAM:
1717             case MyHTML_TAG_SOURCE:
1718             case MyHTML_TAG_TRACK:
1719             {
1720                 myhtml_tree_node_insert_html_element(tree, token);
1721                 myhtml_tree_open_elements_pop(tree);
1722                 break;
1723             }
1724 
1725             case MyHTML_TAG_HR:
1726             {
1727                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1728                     myhtml_tree_tags_close_p(tree, token);
1729                 }
1730 
1731                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1732 
1733                 if(myhtml_is_html_node(current_node, MyHTML_TAG_MENUITEM))
1734                     myhtml_tree_open_elements_pop(tree);
1735 
1736                 myhtml_tree_node_insert_html_element(tree, token);
1737                 myhtml_tree_open_elements_pop(tree);
1738 
1739                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1740                 break;
1741             }
1742 
1743             case MyHTML_TAG_IMAGE:
1744             {
1745                 // parse error
1746                 /* %EXTERNAL% VALIDATOR:RULES CONVERT STATUS:ELEMENT_CONVERT LEVEL:ERROR FROM_TAG_ID:MyHTML_TAG_IMAGE FROM_NS:MyHTML_NAMESPACE_ANY FROM_TYPE:MyHTML_TOKEN_TYPE_OPEN TO_TAG_ID:MyHTML_TAG_IMG TO_NS:MyHTML_NAMESPACE_ANY TO_TYPE:MyHTML_TOKEN_TYPE_OPEN */
1747 
1748                 token->tag_id = MyHTML_TAG_IMG;
1749                 return true;
1750             }
1751 
1752             case MyHTML_TAG_TEXTAREA:
1753             {
1754                 myhtml_tree_node_insert_html_element(tree, token);
1755 
1756                 // If the next token is a U+000A LINE FEED (LF) character token,
1757                 // then ignore that token and move on to the next one.
1758                 // (Newlines at the start of textarea elements are ignored as an authoring convenience.)
1759                 // !!! see dispatcher (myhtml_rules_tree_dispatcher) for this
1760                 tree->flags |= MyHTML_TREE_FLAGS_PARSE_FLAG|MyHTML_TREE_FLAGS_PARSE_FLAG_EMIT_NEWLINE;
1761 
1762                 tree->orig_insert_mode = tree->insert_mode;
1763                 tree->flags           ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1764                 tree->insert_mode      = MyHTML_INSERTION_MODE_TEXT;
1765                 tree->state_of_builder = MyHTML_TOKENIZER_STATE_RCDATA;
1766 
1767                 break;
1768             }
1769 
1770             case MyHTML_TAG_XMP:
1771             {
1772                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_P, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_BUTTON)) {
1773                     myhtml_tree_tags_close_p(tree, token);
1774                 }
1775 
1776                 myhtml_tree_active_formatting_reconstruction(tree);
1777 
1778                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1779                 tree->state_of_builder = MyHTML_TOKENIZER_STATE_RAWTEXT;
1780 
1781                 myhtml_tree_generic_raw_text_element_parsing_algorithm(tree, token);
1782                 break;
1783             }
1784 
1785             case MyHTML_TAG_IFRAME:
1786             {
1787                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1788                 tree->state_of_builder = MyHTML_TOKENIZER_STATE_RAWTEXT;
1789 
1790                 myhtml_tree_generic_raw_text_element_parsing_algorithm(tree, token);
1791                 break;
1792             }
1793 
1794             case MyHTML_TAG_NOEMBED:
1795             {
1796                 tree->state_of_builder = MyHTML_TOKENIZER_STATE_RAWTEXT;
1797                 myhtml_tree_generic_raw_text_element_parsing_algorithm(tree, token);
1798                 break;
1799             }
1800 
1801             case MyHTML_TAG_NOSCRIPT:
1802             {
1803                 if(tree->flags & MyHTML_TREE_FLAGS_SCRIPT) {
1804                     tree->state_of_builder = MyHTML_TOKENIZER_STATE_RAWTEXT;
1805                     myhtml_tree_generic_raw_text_element_parsing_algorithm(tree, token);
1806                 }
1807                 else {
1808                     myhtml_tree_active_formatting_reconstruction(tree);
1809                     myhtml_tree_node_insert_html_element(tree, token);
1810                 }
1811 //                else {
1812 //                    myhtml_tree_node_insert_html_element(tree, token);
1813 //                    tree->insert_mode = MyHTML_INSERTION_MODE_IN_HEAD_NOSCRIPT;
1814 //                }
1815 
1816                 break;
1817             }
1818 
1819             case MyHTML_TAG_SELECT:
1820             {
1821                 myhtml_tree_active_formatting_reconstruction(tree);
1822 
1823                 myhtml_tree_node_insert_html_element(tree, token);
1824 
1825                 tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
1826 
1827                 if(tree->insert_mode == MyHTML_INSERTION_MODE_IN_TABLE ||
1828                    tree->insert_mode == MyHTML_INSERTION_MODE_IN_CAPTION ||
1829                    tree->insert_mode == MyHTML_INSERTION_MODE_IN_TABLE_BODY ||
1830                    tree->insert_mode == MyHTML_INSERTION_MODE_IN_ROW ||
1831                    tree->insert_mode == MyHTML_INSERTION_MODE_IN_CELL)
1832                 {
1833                     tree->insert_mode = MyHTML_INSERTION_MODE_IN_SELECT_IN_TABLE;
1834                 }
1835                 else
1836                     tree->insert_mode = MyHTML_INSERTION_MODE_IN_SELECT;
1837 
1838                 break;
1839             }
1840 
1841             case MyHTML_TAG_OPTGROUP:
1842             case MyHTML_TAG_OPTION:
1843             {
1844                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1845 
1846                 if(myhtml_is_html_node(current_node, MyHTML_TAG_OPTION))
1847                     myhtml_tree_open_elements_pop(tree);
1848 
1849                 myhtml_tree_active_formatting_reconstruction(tree);
1850 
1851                 myhtml_tree_node_insert_html_element(tree, token);
1852                 break;
1853             }
1854 
1855             case MyHTML_TAG_MENUITEM:
1856             {
1857                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1858 
1859                 if(myhtml_is_html_node(current_node, MyHTML_TAG_MENUITEM))
1860                     myhtml_tree_open_elements_pop(tree);
1861 
1862                 myhtml_tree_active_formatting_reconstruction(tree);
1863 
1864                 myhtml_tree_node_insert_html_element(tree, token);
1865                 break;
1866             }
1867 
1868             case MyHTML_TAG_RB:
1869             case MyHTML_TAG_RTC:
1870             {
1871                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_RUBY, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE)) {
1872                     myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
1873                 }
1874 
1875                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1876                 if(current_node->tag_id != MyHTML_TAG_RUBY) {
1877                     // parse error
1878                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
1879                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_RUBY NEED_NS:MyHTML_NAMESPACE_HTML */
1880                 }
1881 
1882                 myhtml_tree_node_insert_html_element(tree, token);
1883                 break;
1884             }
1885 
1886             case MyHTML_TAG_RP:
1887             case MyHTML_TAG_RT:
1888             {
1889                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_RUBY, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE)) {
1890                     myhtml_tree_generate_implied_end_tags(tree, MyHTML_TAG_RTC, MyHTML_NAMESPACE_HTML);
1891                 }
1892 
1893                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1894                 if(current_node->tag_id != MyHTML_TAG_RTC && current_node->tag_id != MyHTML_TAG_RUBY) {
1895                     // parse error
1896                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
1897                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_RTC NEED_NS:MyHTML_NAMESPACE_HTML */
1898                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_RUBY NEED_NS:MyHTML_NAMESPACE_HTML */
1899                 }
1900 
1901                 myhtml_tree_node_insert_html_element(tree, token);
1902                 break;
1903             }
1904 
1905             case MyHTML_TAG_MATH:
1906             {
1907                 myhtml_tree_active_formatting_reconstruction(tree);
1908 
1909                 myhtml_token_node_wait_for_done(tree->token, token);
1910 
1911                 myhtml_token_adjust_mathml_attributes(token);
1912                 myhtml_token_adjust_foreign_attributes(token);
1913 
1914                 myhtml_tree_node_t* current_node = myhtml_tree_node_insert_foreign_element(tree, token);
1915                 current_node->ns = MyHTML_NAMESPACE_MATHML;
1916 
1917                 if(token->type & MyHTML_TOKEN_TYPE_CLOSE_SELF)
1918                     myhtml_tree_open_elements_pop(tree);
1919 
1920                 break;
1921             }
1922 
1923             case MyHTML_TAG_SVG:
1924             {
1925                 myhtml_tree_active_formatting_reconstruction(tree);
1926 
1927                 myhtml_token_node_wait_for_done(tree->token, token);
1928 
1929                 myhtml_token_adjust_svg_attributes(token);
1930                 myhtml_token_adjust_foreign_attributes(token);
1931 
1932                 myhtml_tree_node_t* current_node = myhtml_tree_node_insert_foreign_element(tree, token);
1933                 current_node->ns = MyHTML_NAMESPACE_SVG;
1934 
1935                 if(token->type & MyHTML_TOKEN_TYPE_CLOSE_SELF)
1936                     myhtml_tree_open_elements_pop(tree);
1937 
1938                 break;
1939             }
1940 
1941             case MyHTML_TAG_CAPTION:
1942             case MyHTML_TAG_COL:
1943             case MyHTML_TAG_COLGROUP:
1944             case MyHTML_TAG_FRAME:
1945             case MyHTML_TAG_HEAD:
1946             case MyHTML_TAG_TBODY:
1947             case MyHTML_TAG_TD:
1948             case MyHTML_TAG_TFOOT:
1949             case MyHTML_TAG_TH:
1950             case MyHTML_TAG_THEAD:
1951             case MyHTML_TAG_TR:
1952             {
1953                 // parse error
1954                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
1955                 break;
1956             }
1957 
1958             default:
1959             {
1960                 myhtml_tree_active_formatting_reconstruction(tree);
1961                 myhtml_tree_node_insert_html_element(tree, token);
1962 
1963                 break;
1964             }
1965         }
1966     }
1967 
1968     return false;
1969 }
1970 
myhtml_insertion_mode_text(myhtml_tree_t * tree,myhtml_token_node_t * token)1971 bool myhtml_insertion_mode_text(myhtml_tree_t* tree, myhtml_token_node_t* token)
1972 {
1973     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
1974     {
1975         switch (token->tag_id) {
1976             case MyHTML_TAG_SCRIPT:
1977             {
1978                 // new document.write is not works; set back
1979                 myhtml_tree_open_elements_pop(tree);
1980                 tree->insert_mode = tree->orig_insert_mode;
1981                 break;
1982             }
1983 
1984             default:
1985             {
1986                 myhtml_tree_open_elements_pop(tree);
1987                 tree->insert_mode = tree->orig_insert_mode;
1988                 break;
1989             }
1990         }
1991     }
1992     else {
1993         if(token->tag_id == MyHTML_TAG__END_OF_FILE)
1994         {
1995             // parse error
1996             /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:PREMATURE_TERMINATION LEVEL:ERROR */
1997 
1998             myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
1999 
2000             if(current_node->tag_id == MyHTML_TAG_SCRIPT)
2001                 current_node->flags |= MyHTML_TREE_FLAGS_ALREADY_STARTED;
2002 
2003             myhtml_tree_open_elements_pop(tree);
2004 
2005             tree->insert_mode = tree->orig_insert_mode;
2006             return true;
2007         }
2008 
2009         myhtml_tree_node_insert_text(tree, token);
2010     }
2011 
2012     return false;
2013 }
2014 
myhtml_insertion_mode_in_table(myhtml_tree_t * tree,myhtml_token_node_t * token)2015 bool myhtml_insertion_mode_in_table(myhtml_tree_t* tree, myhtml_token_node_t* token)
2016 {
2017     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
2018     {
2019         switch (token->tag_id) {
2020             case MyHTML_TAG_TABLE:
2021             {
2022                 myhtml_tree_node_t* table_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TABLE, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2023 
2024                 if(table_node == NULL) {
2025                      // parse error
2026                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2027                     break;
2028                 }
2029 
2030                 myhtml_tree_open_elements_pop_until_by_node(tree, table_node, false);
2031                 myhtml_tree_reset_insertion_mode_appropriately(tree);
2032 
2033                 break;
2034             }
2035 
2036             case MyHTML_TAG_BODY:
2037             case MyHTML_TAG_CAPTION:
2038             case MyHTML_TAG_COL:
2039             case MyHTML_TAG_COLGROUP:
2040             case MyHTML_TAG_HTML:
2041             case MyHTML_TAG_TBODY:
2042             case MyHTML_TAG_TD:
2043             case MyHTML_TAG_TFOOT:
2044             case MyHTML_TAG_TH:
2045             case MyHTML_TAG_THEAD:
2046             case MyHTML_TAG_TR:
2047             {
2048                 // parse error
2049                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
2050                 break;
2051             }
2052 
2053             case MyHTML_TAG_TEMPLATE:
2054             {
2055                 return myhtml_insertion_mode_in_head(tree, token);
2056             }
2057 
2058             default: {
2059                 // parse error
2060                 tree->foster_parenting = true;
2061                 myhtml_insertion_mode_in_body(tree, token);
2062                 tree->foster_parenting = false;
2063 
2064                 break;
2065             }
2066         }
2067     }
2068     else {
2069         switch (token->tag_id)
2070         {
2071             case MyHTML_TAG__TEXT:
2072             {
2073                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2074 
2075                 if((current_node->tag_id == MyHTML_TAG_TABLE  ||
2076                    current_node->tag_id  == MyHTML_TAG_TBODY  ||
2077                    current_node->tag_id  == MyHTML_TAG_TFOOT  ||
2078                    current_node->tag_id  == MyHTML_TAG_THEAD  ||
2079                    current_node->tag_id  == MyHTML_TAG_TR)    &&
2080                    current_node->ns == MyHTML_NAMESPACE_HTML)
2081                 {
2082                     myhtml_tree_token_list_clean(tree->token_list);
2083 
2084                     tree->orig_insert_mode = tree->insert_mode;
2085                     tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE_TEXT;
2086 
2087                     return true;
2088                 }
2089                 else {
2090                     tree->foster_parenting = true;
2091                     myhtml_insertion_mode_in_body(tree, token);
2092                     tree->foster_parenting = false;
2093 
2094                     break;
2095                 }
2096             }
2097 
2098             case MyHTML_TAG__COMMENT:
2099                 myhtml_tree_node_insert_comment(tree, token, 0);
2100                 break;
2101 
2102             case MyHTML_TAG__DOCTYPE: {
2103                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:WARNING */
2104                 break;
2105             }
2106 
2107             case MyHTML_TAG_CAPTION:
2108             {
2109                 myhtml_tree_clear_stack_back_table_context(tree);
2110 
2111                 myhtml_tree_node_insert_html_element(tree, token);
2112                 myhtml_tree_active_formatting_append(tree, tree->myhtml->marker);
2113 
2114                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_CAPTION;
2115                 break;
2116             }
2117 
2118             case MyHTML_TAG_COLGROUP:
2119             {
2120                 myhtml_tree_clear_stack_back_table_context(tree);
2121 
2122                 myhtml_tree_node_insert_html_element(tree, token);
2123 
2124                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_COLUMN_GROUP;
2125                 break;
2126             }
2127 
2128             case MyHTML_TAG_COL:
2129             {
2130                 myhtml_tree_clear_stack_back_table_context(tree);
2131                 myhtml_tree_node_insert(tree, MyHTML_TAG_COLGROUP, MyHTML_NAMESPACE_HTML);
2132 
2133                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_COLUMN_GROUP;
2134                 return true;
2135             }
2136 
2137             case MyHTML_TAG_TBODY:
2138             case MyHTML_TAG_TFOOT:
2139             case MyHTML_TAG_THEAD:
2140             {
2141                 myhtml_tree_clear_stack_back_table_context(tree);
2142 
2143                 myhtml_tree_node_insert_html_element(tree, token);
2144 
2145                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE_BODY;
2146                 break;
2147             }
2148 
2149             case MyHTML_TAG_TD:
2150             case MyHTML_TAG_TH:
2151             case MyHTML_TAG_TR:
2152             {
2153                 myhtml_tree_clear_stack_back_table_context(tree);
2154                 myhtml_tree_node_insert(tree, MyHTML_TAG_TBODY, MyHTML_NAMESPACE_HTML);
2155 
2156                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE_BODY;
2157                 return true;
2158             }
2159 
2160             case MyHTML_TAG_TABLE:
2161             {
2162                 // parse error
2163                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
2164 
2165                 myhtml_tree_node_t* table_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TABLE, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2166 
2167                 if(table_node == NULL) {
2168                     // parse error
2169                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
2170 
2171                     break;
2172                 }
2173 
2174                 myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_TABLE, MyHTML_NAMESPACE_HTML, false);
2175                 myhtml_tree_reset_insertion_mode_appropriately(tree);
2176 
2177                 return true;
2178             }
2179 
2180             case MyHTML_TAG_STYLE:
2181             case MyHTML_TAG_SCRIPT:
2182             case MyHTML_TAG_TEMPLATE:
2183             {
2184                 return myhtml_insertion_mode_in_head(tree, token);
2185             }
2186 
2187             case MyHTML_TAG_INPUT:
2188             {
2189                 myhtml_token_node_wait_for_done(tree->token, token);
2190 
2191                 if(myhtml_token_attr_match_case(tree->token, token, "type", 4, "hidden", 6) == NULL) {
2192                     tree->foster_parenting = true;
2193                     myhtml_insertion_mode_in_body(tree, token);
2194                     tree->foster_parenting = false;
2195 
2196                     break;
2197                 }
2198 
2199                 // parse error
2200                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
2201 
2202                 myhtml_tree_node_insert_html_element(tree, token);
2203                 myhtml_tree_open_elements_pop(tree);
2204 
2205                 token->type |= MyHTML_TOKEN_TYPE_CLOSE_SELF;
2206                 break;
2207             }
2208 
2209             case MyHTML_TAG_FORM:
2210             {
2211                 // parse error
2212                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
2213 
2214                 myhtml_tree_node_t* template = myhtml_tree_open_elements_find_by_tag_idx(tree, MyHTML_TAG_TEMPLATE, MyHTML_NAMESPACE_HTML, NULL);
2215                 if(tree->node_form || template)
2216                     break;
2217 
2218                 tree->node_form = myhtml_tree_node_insert_html_element(tree, token);
2219 
2220                 myhtml_tree_open_elements_pop(tree);
2221             }
2222 
2223             case MyHTML_TAG__END_OF_FILE:
2224                 return myhtml_insertion_mode_in_body(tree, token);
2225 
2226             default:
2227             {
2228                 // parse error
2229                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
2230 
2231                 tree->foster_parenting = true;
2232                 myhtml_insertion_mode_in_body(tree, token);
2233                 tree->foster_parenting = false;
2234 
2235                 break;
2236             }
2237         }
2238     }
2239 
2240     return false;
2241 }
2242 
myhtml_insertion_mode_in_table_text(myhtml_tree_t * tree,myhtml_token_node_t * token)2243 bool myhtml_insertion_mode_in_table_text(myhtml_tree_t* tree, myhtml_token_node_t* token)
2244 {
2245     // skip NULL, we replaced earlier
2246     if(token->tag_id == MyHTML_TAG__TEXT)
2247     {
2248         if(token->type & MyHTML_TOKEN_TYPE_NULL) {
2249             // parse error
2250             /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:NULL_CHAR ACTION:IGNORE LEVEL:ERROR */
2251 
2252             myhtml_insertion_fix_for_null_char_drop_all(tree, token);
2253 
2254             if(token->str.length)
2255                 myhtml_tree_token_list_append(tree->token_list, token);
2256         }
2257         else
2258             myhtml_tree_token_list_append(tree->token_list, token);
2259     }
2260     else {
2261         myhtml_tree_token_list_t* token_list = tree->token_list;
2262         bool is_not_ws = false;
2263 
2264         for(size_t i = 0; i < token_list->length; i++) {
2265             if((token_list->list[i]->type & MyHTML_TOKEN_TYPE_WHITESPACE) == 0) {
2266                 is_not_ws = true;
2267                 break;
2268             }
2269         }
2270 
2271         if(is_not_ws)
2272         {
2273             for(size_t i = 0; i < token_list->length; i++) {
2274                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR TOKEN:token_list->list[i] */
2275 
2276                 tree->foster_parenting = true;
2277                 myhtml_insertion_mode_in_body(tree, token_list->list[i]);
2278                 tree->foster_parenting = false;
2279             }
2280         }
2281         else {
2282             for(size_t i = 0; i < token_list->length; i++) {
2283                 myhtml_tree_node_insert_text(tree, token_list->list[i]);
2284             }
2285         }
2286 
2287         tree->insert_mode = tree->orig_insert_mode;
2288         return true;
2289     }
2290 
2291     return false;
2292 }
2293 
myhtml_insertion_mode_in_caption(myhtml_tree_t * tree,myhtml_token_node_t * token)2294 bool myhtml_insertion_mode_in_caption(myhtml_tree_t* tree, myhtml_token_node_t* token)
2295 {
2296     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
2297     {
2298         switch (token->tag_id) {
2299             case MyHTML_TAG_CAPTION:
2300             {
2301                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_CAPTION, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE) == NULL) {
2302                     // parse error
2303                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2304                     break;
2305                 }
2306 
2307                 myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
2308 
2309                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2310                 if(myhtml_is_html_node(current_node, MyHTML_TAG_CAPTION) == false) {
2311                     // parse error
2312                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
2313                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_CAPTION NEED_NS:MyHTML_NAMESPACE_HTML */
2314                 }
2315 
2316                 myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_CAPTION, MyHTML_NAMESPACE_HTML, false);
2317                 myhtml_tree_active_formatting_up_to_last_marker(tree);
2318 
2319                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2320                 break;
2321             }
2322 
2323             case MyHTML_TAG_TABLE:
2324             {
2325                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_CAPTION, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE) == NULL) {
2326                     // parse error
2327                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2328                     break;
2329                 }
2330 
2331                 myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
2332 
2333                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2334                 if(myhtml_is_html_node(current_node, MyHTML_TAG_CAPTION) == false) {
2335                     // parse error
2336                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
2337                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_CAPTION NEED_NS:MyHTML_NAMESPACE_HTML */
2338                 }
2339 
2340                 myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_CAPTION, MyHTML_NAMESPACE_HTML, false);
2341                 myhtml_tree_active_formatting_up_to_last_marker(tree);
2342 
2343                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2344                 return true;
2345             }
2346 
2347             case MyHTML_TAG_BODY:
2348             case MyHTML_TAG_COL:
2349             case MyHTML_TAG_COLGROUP:
2350             case MyHTML_TAG_HTML:
2351             case MyHTML_TAG_TBODY:
2352             case MyHTML_TAG_TD:
2353             case MyHTML_TAG_TFOOT:
2354             case MyHTML_TAG_TH:
2355             case MyHTML_TAG_THEAD:
2356             case MyHTML_TAG_TR:
2357             {
2358                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
2359                 break;
2360             }
2361 
2362             default:
2363                 return myhtml_insertion_mode_in_body(tree, token);
2364         }
2365     }
2366     else {
2367         switch (token->tag_id)
2368         {
2369             case MyHTML_TAG_CAPTION:
2370             case MyHTML_TAG_COL:
2371             case MyHTML_TAG_COLGROUP:
2372             case MyHTML_TAG_TBODY:
2373             case MyHTML_TAG_TD:
2374             case MyHTML_TAG_TFOOT:
2375             case MyHTML_TAG_TH:
2376             case MyHTML_TAG_THEAD:
2377             case MyHTML_TAG_TR:
2378             {
2379                 if(myhtml_tree_element_in_scope(tree, MyHTML_TAG_CAPTION, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE) == NULL) {
2380                     // parse error
2381                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2382                     break;
2383                 }
2384 
2385                 myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
2386 
2387                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2388                 if(myhtml_is_html_node(current_node, MyHTML_TAG_CAPTION) == false) {
2389                     // parse error
2390                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
2391                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:MyHTML_TAG_CAPTION NEED_NS:MyHTML_NAMESPACE_HTML */
2392                 }
2393 
2394                 myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_CAPTION, MyHTML_NAMESPACE_HTML, false);
2395                 myhtml_tree_active_formatting_up_to_last_marker(tree);
2396 
2397                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2398                 return true;
2399             }
2400 
2401             default:
2402                 return myhtml_insertion_mode_in_body(tree, token);
2403         }
2404     }
2405 
2406     return false;
2407 }
2408 
myhtml_insertion_mode_in_column_group(myhtml_tree_t * tree,myhtml_token_node_t * token)2409 bool myhtml_insertion_mode_in_column_group(myhtml_tree_t* tree, myhtml_token_node_t* token)
2410 {
2411     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
2412     {
2413         switch (token->tag_id) {
2414             case MyHTML_TAG_COLGROUP:
2415             {
2416                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2417 
2418                 if(current_node && myhtml_is_html_node(current_node, MyHTML_TAG_COLGROUP)) {
2419                     myhtml_tree_open_elements_pop(tree);
2420 
2421                     tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2422                     return false;
2423                 }
2424 
2425                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2426                 break;
2427             }
2428 
2429             case MyHTML_TAG_COL:
2430             {
2431                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
2432 
2433                 break;
2434             }
2435 
2436             case MyHTML_TAG_TEMPLATE:
2437             {
2438                 return myhtml_insertion_mode_in_head(tree, token);
2439             }
2440 
2441             default: {
2442                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2443 
2444                 if(current_node && myhtml_is_html_node(current_node, MyHTML_TAG_COLGROUP)) {
2445                     myhtml_tree_open_elements_pop(tree);
2446 
2447                     tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2448                     return true;
2449                 }
2450 
2451                 // parse error
2452                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2453                 break;
2454             }
2455         }
2456     }
2457     else {
2458         switch (token->tag_id)
2459         {
2460             case MyHTML_TAG__TEXT:
2461             {
2462                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE) {
2463                     myhtml_tree_node_insert_text(tree, token);
2464                     break;
2465                 }
2466 
2467                 myhtml_token_node_t* new_token = myhtml_insertion_fix_split_for_text_begin_ws(tree, token);
2468                 if(new_token)
2469                     myhtml_tree_node_insert_text(tree, new_token);
2470 
2471                 /* default: */
2472                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2473 
2474                 if(current_node && myhtml_is_html_node(current_node, MyHTML_TAG_COLGROUP)) {
2475                     myhtml_tree_open_elements_pop(tree);
2476 
2477                     tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2478                     return true;
2479                 }
2480 
2481                 // parse error
2482                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2483                 break;
2484             }
2485 
2486             case MyHTML_TAG__COMMENT:
2487             {
2488                 myhtml_tree_node_insert_comment(tree, token, 0);
2489                 break;
2490             }
2491 
2492             case MyHTML_TAG__DOCTYPE: {
2493                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
2494                 break;
2495             }
2496             case MyHTML_TAG_HTML:
2497             {
2498                 return myhtml_insertion_mode_in_body(tree, token);
2499             }
2500 
2501             case MyHTML_TAG_COL:
2502             {
2503                 myhtml_tree_node_insert_html_element(tree, token);
2504                 myhtml_tree_open_elements_pop(tree);
2505                 break;
2506             }
2507 
2508             case MyHTML_TAG_TEMPLATE:
2509             {
2510                 return myhtml_insertion_mode_in_head(tree, token);
2511             }
2512 
2513             case MyHTML_TAG__END_OF_FILE:
2514                 return myhtml_insertion_mode_in_body(tree, token);
2515 
2516             default:
2517             {
2518                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2519 
2520                 if(current_node && myhtml_is_html_node(current_node, MyHTML_TAG_COLGROUP)) {
2521                     myhtml_tree_open_elements_pop(tree);
2522 
2523                     tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2524                     return true;
2525                 }
2526 
2527                 // parse error
2528                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2529                 break;
2530             }
2531         }
2532     }
2533 
2534     return false;
2535 }
2536 
myhtml_insertion_mode_in_table_body(myhtml_tree_t * tree,myhtml_token_node_t * token)2537 bool myhtml_insertion_mode_in_table_body(myhtml_tree_t* tree, myhtml_token_node_t* token)
2538 {
2539     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
2540     {
2541         switch (token->tag_id) {
2542             case MyHTML_TAG_TBODY:
2543             case MyHTML_TAG_TFOOT:
2544             case MyHTML_TAG_THEAD:
2545             {
2546                 myhtml_tree_node_t* node = myhtml_tree_element_in_scope(tree, token->tag_id, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2547 
2548                 if(node == NULL) {
2549                     // parse error
2550                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2551                     break;
2552                 }
2553 
2554                 myhtml_tree_clear_stack_back_table_body_context(tree);
2555                 myhtml_tree_open_elements_pop(tree);
2556 
2557                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2558                 break;
2559             }
2560 
2561             case MyHTML_TAG_TABLE:
2562             {
2563                 myhtml_tree_node_t* tbody_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TBODY, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2564                 myhtml_tree_node_t* tfoot_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TFOOT, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2565                 myhtml_tree_node_t* thead_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_THEAD, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2566 
2567                 if(tbody_node == NULL && tfoot_node == NULL && thead_node == NULL) {
2568                     // parse error
2569                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2570                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_THEAD NEED_NS:MyHTML_NAMESPACE_HTML */
2571                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_TBODY NEED_NS:MyHTML_NAMESPACE_HTML */
2572                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_TFOOT NEED_NS:MyHTML_NAMESPACE_HTML */
2573                     break;
2574                 }
2575 
2576                 myhtml_tree_clear_stack_back_table_body_context(tree);
2577                 myhtml_tree_open_elements_pop(tree);
2578 
2579                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2580                 return true;
2581             }
2582 
2583             case MyHTML_TAG_BODY:
2584             case MyHTML_TAG_CAPTION:
2585             case MyHTML_TAG_COL:
2586             case MyHTML_TAG_COLGROUP:
2587             case MyHTML_TAG_HTML:
2588             case MyHTML_TAG_TD:
2589             case MyHTML_TAG_TH:
2590             case MyHTML_TAG_TR:
2591             {
2592                 // parse error
2593                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
2594                 break;
2595             }
2596 
2597             default:
2598                 return myhtml_insertion_mode_in_table(tree, token);
2599         }
2600     }
2601     else {
2602         switch (token->tag_id)
2603         {
2604             case MyHTML_TAG_TR:
2605             {
2606                 myhtml_tree_clear_stack_back_table_body_context(tree);
2607 
2608                 myhtml_tree_node_insert_html_element(tree, token);
2609 
2610                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_ROW;
2611                 break;
2612             }
2613 
2614             case MyHTML_TAG_TH:
2615             case MyHTML_TAG_TD:
2616             {
2617                 // parse error
2618                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
2619 
2620                 myhtml_tree_clear_stack_back_table_body_context(tree);
2621 
2622                 myhtml_tree_node_insert(tree, MyHTML_TAG_TR, MyHTML_NAMESPACE_HTML);
2623 
2624                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_ROW;
2625                 return true;
2626             }
2627 
2628             case MyHTML_TAG_CAPTION:
2629             case MyHTML_TAG_COL:
2630             case MyHTML_TAG_COLGROUP:
2631             case MyHTML_TAG_TBODY:
2632             case MyHTML_TAG_TFOOT:
2633             case MyHTML_TAG_THEAD:
2634             {
2635                 myhtml_tree_node_t* tbody_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TBODY, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2636                 myhtml_tree_node_t* tfoot_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TFOOT, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2637                 myhtml_tree_node_t* thead_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_THEAD, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2638 
2639                 if(tbody_node == NULL && tfoot_node == NULL && thead_node == NULL) {
2640                     // parse error
2641                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2642                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_THEAD NEED_NS:MyHTML_NAMESPACE_HTML */
2643                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_TBODY NEED_NS:MyHTML_NAMESPACE_HTML */
2644                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_TFOOT NEED_NS:MyHTML_NAMESPACE_HTML */
2645                     break;
2646                 }
2647 
2648                 myhtml_tree_clear_stack_back_table_body_context(tree);
2649                 myhtml_tree_open_elements_pop(tree);
2650 
2651                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
2652                 return true;
2653             }
2654 
2655             default:
2656                 return myhtml_insertion_mode_in_table(tree, token);
2657         }
2658     }
2659 
2660     return false;
2661 }
2662 
myhtml_insertion_mode_in_row(myhtml_tree_t * tree,myhtml_token_node_t * token)2663 bool myhtml_insertion_mode_in_row(myhtml_tree_t* tree, myhtml_token_node_t* token)
2664 {
2665     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
2666     {
2667         switch (token->tag_id) {
2668             case MyHTML_TAG_TR:
2669             {
2670                 myhtml_tree_node_t* tr_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TR, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2671 
2672                 if(tr_node == NULL) {
2673                     // parse error
2674                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2675                     break;
2676                 }
2677 
2678                 myhtml_tree_clear_stack_back_table_row_context(tree);
2679 
2680                 myhtml_tree_open_elements_pop(tree);
2681 
2682                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE_BODY;
2683                 break;
2684             }
2685 
2686             case MyHTML_TAG_TABLE:
2687             {
2688                 myhtml_tree_node_t* tr_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TR, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2689 
2690                 if(tr_node == NULL) {
2691                     // parse error
2692                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2693                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_TR NEED_NS:MyHTML_NAMESPACE_HTML */
2694                     break;
2695                 }
2696 
2697                 myhtml_tree_clear_stack_back_table_row_context(tree);
2698                 myhtml_tree_open_elements_pop(tree);
2699 
2700                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE_BODY;
2701                 return true;
2702             }
2703 
2704             case MyHTML_TAG_TBODY:
2705             case MyHTML_TAG_TFOOT:
2706             case MyHTML_TAG_THEAD:
2707             {
2708                 myhtml_tree_node_t* node = myhtml_tree_element_in_scope(tree, token->tag_id, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2709                 if(node == NULL) {
2710                     // parse error
2711                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2712                     break;
2713                 }
2714 
2715                 myhtml_tree_node_t* tr_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TR, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2716                 if(tr_node == NULL)
2717                     break;
2718 
2719                 myhtml_tree_clear_stack_back_table_row_context(tree);
2720                 myhtml_tree_open_elements_pop(tree);
2721 
2722                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE_BODY;
2723                 return true;
2724             }
2725 
2726             case MyHTML_TAG_BODY:
2727             case MyHTML_TAG_CAPTION:
2728             case MyHTML_TAG_COL:
2729             case MyHTML_TAG_COLGROUP:
2730             case MyHTML_TAG_HTML:
2731             case MyHTML_TAG_TD:
2732             case MyHTML_TAG_TH:
2733             {
2734                 // parse error
2735                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
2736                 break;
2737             }
2738 
2739             default:
2740                 return myhtml_insertion_mode_in_table(tree, token);
2741         }
2742     }
2743     else {
2744         switch (token->tag_id)
2745         {
2746             case MyHTML_TAG_TH:
2747             case MyHTML_TAG_TD:
2748             {
2749                 myhtml_tree_clear_stack_back_table_row_context(tree);
2750 
2751                 myhtml_tree_node_insert_html_element(tree, token);
2752                 myhtml_tree_active_formatting_append(tree, tree->myhtml->marker);
2753 
2754                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_CELL;
2755                 break;
2756             }
2757             case MyHTML_TAG_CAPTION:
2758             case MyHTML_TAG_COL:
2759             case MyHTML_TAG_COLGROUP:
2760             case MyHTML_TAG_TBODY:
2761             case MyHTML_TAG_TFOOT:
2762             case MyHTML_TAG_THEAD:
2763             case MyHTML_TAG_TR:
2764             {
2765                 myhtml_tree_node_t* tr_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TR, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2766 
2767                 if(tr_node == NULL) {
2768                     // parse error
2769                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2770                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_TR NEED_NS:MyHTML_NAMESPACE_HTML */
2771                     break;
2772                 }
2773 
2774                 myhtml_tree_clear_stack_back_table_row_context(tree);
2775                 myhtml_tree_open_elements_pop(tree);
2776 
2777                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE_BODY;
2778                 return true;
2779             }
2780 
2781             default:
2782                 return myhtml_insertion_mode_in_table(tree, token);
2783         }
2784     }
2785 
2786     return false;
2787 }
2788 
myhtml_insertion_mode_in_cell(myhtml_tree_t * tree,myhtml_token_node_t * token)2789 bool myhtml_insertion_mode_in_cell(myhtml_tree_t* tree, myhtml_token_node_t* token)
2790 {
2791     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
2792     {
2793         switch (token->tag_id) {
2794             case MyHTML_TAG_TD:
2795             case MyHTML_TAG_TH:
2796             {
2797                 myhtml_tree_node_t* node = myhtml_tree_element_in_scope(tree, token->tag_id, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2798 
2799                 if(node == NULL) {
2800                     // parse error
2801                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2802                     break;
2803                 }
2804 
2805                 myhtml_tree_generate_implied_end_tags(tree, 0, MyHTML_NAMESPACE_UNDEF);
2806 
2807                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2808 
2809                 if(myhtml_is_html_node(current_node, token->tag_id) == false)
2810                 {
2811                     // parse error
2812                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
2813                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:NULL HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:token->tag_id NEED_NS:MyHTML_NAMESPACE_HTML */
2814                 }
2815 
2816                 myhtml_tree_open_elements_pop_until(tree, token->tag_id, MyHTML_NAMESPACE_HTML, false);
2817 
2818                 myhtml_tree_active_formatting_up_to_last_marker(tree);
2819 
2820                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_ROW;
2821                 break;
2822             }
2823 
2824             case MyHTML_TAG_BODY:
2825             case MyHTML_TAG_CAPTION:
2826             case MyHTML_TAG_COL:
2827             case MyHTML_TAG_COLGROUP:
2828             case MyHTML_TAG_HTML:
2829             {
2830                 // parse error
2831                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
2832                 break;
2833             }
2834 
2835 
2836             case MyHTML_TAG_TABLE:
2837             case MyHTML_TAG_TBODY:
2838             case MyHTML_TAG_TFOOT:
2839             case MyHTML_TAG_THEAD:
2840             case MyHTML_TAG_TR:
2841             {
2842                 myhtml_tree_node_t* node = myhtml_tree_element_in_scope(tree, token->tag_id, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2843 
2844                 if(node == NULL) {
2845                     // parse error
2846                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2847                     break;
2848                 }
2849 
2850                 node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TD, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2851                 if(node) {
2852                     myhtml_tree_close_cell(tree, node, token);
2853                 }
2854                 else {
2855                     node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TH, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2856                     if(node)
2857                         myhtml_tree_close_cell(tree, node, token);
2858                 }
2859 
2860                 return true;
2861             }
2862 
2863             default:
2864                 return myhtml_insertion_mode_in_table(tree, token);
2865         }
2866     }
2867     else {
2868         switch (token->tag_id)
2869         {
2870             case MyHTML_TAG_CAPTION:
2871             case MyHTML_TAG_COL:
2872             case MyHTML_TAG_COLGROUP:
2873             case MyHTML_TAG_TBODY:
2874             case MyHTML_TAG_TD:
2875             case MyHTML_TAG_TFOOT:
2876             case MyHTML_TAG_TH:
2877             case MyHTML_TAG_THEAD:
2878             case MyHTML_TAG_TR:
2879             {
2880                 myhtml_tree_node_t* td_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TD, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2881                 myhtml_tree_node_t* th_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_TH, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
2882 
2883                 if(td_node == NULL && th_node == NULL) {
2884                     // parse error
2885                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2886                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_TD NEED_NS:MyHTML_NAMESPACE_HTML */
2887                     /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:NULL NEED:NULL HAVE_TAG_ID:MyHTML_TAG__UNDEF HAVE_NS:MyHTML_NAMESPACE_UNDEF NEED_TAG_ID:MyHTML_TAG_TH NEED_NS:MyHTML_NAMESPACE_HTML */
2888 
2889                     break;
2890                 }
2891 
2892                 myhtml_tree_close_cell(tree, (td_node == NULL ? th_node : td_node), token);
2893 
2894                 return true;
2895             }
2896 
2897             default:
2898                 return myhtml_insertion_mode_in_body(tree, token);
2899         }
2900     }
2901 
2902     return false;
2903 }
2904 
myhtml_insertion_mode_in_select(myhtml_tree_t * tree,myhtml_token_node_t * token)2905 bool myhtml_insertion_mode_in_select(myhtml_tree_t* tree, myhtml_token_node_t* token)
2906 {
2907     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
2908     {
2909         switch (token->tag_id) {
2910             case MyHTML_TAG_OPTGROUP:
2911             {
2912                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2913 
2914                 if(myhtml_is_html_node(current_node, MyHTML_TAG_OPTION))
2915                 {
2916                     if(tree->open_elements->length > 1) {
2917                         myhtml_tree_node_t *optgrp_node = tree->open_elements->list[ tree->open_elements->length - 2 ];
2918 
2919                         if(myhtml_is_html_node(optgrp_node, MyHTML_TAG_OPTGROUP))
2920                         {
2921                             myhtml_tree_open_elements_pop(tree);
2922                         }
2923                     }
2924                 }
2925 
2926                 current_node = myhtml_tree_current_node(tree);
2927 
2928                 if(myhtml_is_html_node(current_node, MyHTML_TAG_OPTGROUP))
2929                     myhtml_tree_open_elements_pop(tree);
2930                 else {
2931                     // parse error
2932                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_NO_EXPECTED ACTION:IGNORE LEVEL:ERROR */
2933 
2934                     break;
2935                 }
2936 
2937                 break;
2938             }
2939 
2940             case MyHTML_TAG_OPTION:
2941             {
2942                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
2943 
2944                 if(myhtml_is_html_node(current_node, MyHTML_TAG_OPTION))
2945                     myhtml_tree_open_elements_pop(tree);
2946                 else {
2947                     // parse error
2948                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2949 
2950                     break;
2951                 }
2952 
2953                 break;
2954             }
2955 
2956             case MyHTML_TAG_SELECT:
2957             {
2958                 myhtml_tree_node_t* select_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_SELECT, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_SELECT);
2959 
2960                 if(select_node == NULL) {
2961                     // parse error
2962                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
2963                     break;
2964                 }
2965 
2966                 myhtml_tree_open_elements_pop_until_by_node(tree, select_node, false);
2967                 myhtml_tree_reset_insertion_mode_appropriately(tree);
2968 
2969                 break;
2970             }
2971 
2972             case MyHTML_TAG_TEMPLATE:
2973                 return myhtml_insertion_mode_in_head(tree, token);
2974 
2975             default: {
2976                 // parse error
2977                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
2978 
2979                 break;
2980             }
2981         }
2982     }
2983     else {
2984         switch (token->tag_id)
2985         {
2986             case MyHTML_TAG__TEXT: {
2987                 if(token->type & MyHTML_TOKEN_TYPE_NULL) {
2988                     // parse error
2989                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:NULL_CHAR ACTION:IGNORE LEVEL:ERROR */
2990 
2991                     myhtml_insertion_fix_for_null_char_drop_all(tree, token);
2992 
2993                     if(token->str.length)
2994                         myhtml_tree_node_insert_text(tree, token);
2995                 }
2996                 else
2997                     myhtml_tree_node_insert_text(tree, token);
2998 
2999                 break;
3000             }
3001 
3002             case MyHTML_TAG__COMMENT:
3003                 myhtml_tree_node_insert_comment(tree, token, NULL);
3004                 break;
3005 
3006             case MyHTML_TAG__DOCTYPE: {
3007                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
3008 
3009                 break;
3010             }
3011 
3012             case MyHTML_TAG_HTML:
3013                 return myhtml_insertion_mode_in_body(tree, token);
3014 
3015             case MyHTML_TAG_OPTION:
3016             {
3017                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
3018 
3019                 if(myhtml_is_html_node(current_node, token->tag_id))
3020                     myhtml_tree_open_elements_pop(tree);
3021 
3022                 myhtml_tree_node_insert_html_element(tree, token);
3023                 break;
3024             }
3025 
3026             case MyHTML_TAG_OPTGROUP:
3027             {
3028                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
3029 
3030                 if(current_node->tag_id == MyHTML_TAG_OPTION &&
3031                    current_node->ns == MyHTML_NAMESPACE_HTML)
3032                     myhtml_tree_open_elements_pop(tree);
3033 
3034                 current_node = myhtml_tree_current_node(tree);
3035 
3036                 if(current_node->tag_id == token->tag_id &&
3037                    current_node->ns == MyHTML_NAMESPACE_HTML)
3038                     myhtml_tree_open_elements_pop(tree);
3039 
3040                 myhtml_tree_node_insert_html_element(tree, token);
3041                 break;
3042             }
3043 
3044             case MyHTML_TAG_SELECT:
3045             {
3046                 // parse error
3047                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
3048 
3049                 myhtml_tree_node_t* select_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_SELECT, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_SELECT);
3050 
3051                 if(select_node == NULL) {
3052                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
3053 
3054                     break;
3055                 }
3056 
3057                 myhtml_tree_open_elements_pop_until_by_node(tree, select_node, false);
3058                 myhtml_tree_reset_insertion_mode_appropriately(tree);
3059 
3060                 break;
3061             }
3062 
3063             case MyHTML_TAG_INPUT:
3064             case MyHTML_TAG_KEYGEN:
3065             case MyHTML_TAG_TEXTAREA:
3066             {
3067                 // parse error
3068                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
3069 
3070                 myhtml_tree_node_t* select_node = myhtml_tree_element_in_scope(tree, MyHTML_TAG_SELECT, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_SELECT);
3071 
3072                 if(select_node == NULL) {
3073                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
3074 
3075                     break;
3076                 }
3077 
3078                 myhtml_tree_open_elements_pop_until_by_node(tree, select_node, false);
3079                 myhtml_tree_reset_insertion_mode_appropriately(tree);
3080 
3081                 return true;
3082             }
3083 
3084             case MyHTML_TAG_SCRIPT:
3085             case MyHTML_TAG_TEMPLATE:
3086                 return myhtml_insertion_mode_in_head(tree, token);
3087 
3088             case MyHTML_TAG__END_OF_FILE:
3089                 return myhtml_insertion_mode_in_body(tree, token);
3090 
3091             default: {
3092                 // parse error
3093                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
3094                 break;
3095             }
3096         }
3097     }
3098 
3099     return false;
3100 }
3101 
myhtml_insertion_mode_in_select_in_table(myhtml_tree_t * tree,myhtml_token_node_t * token)3102 bool myhtml_insertion_mode_in_select_in_table(myhtml_tree_t* tree, myhtml_token_node_t* token)
3103 {
3104     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
3105     {
3106         switch (token->tag_id) {
3107             case MyHTML_TAG_CAPTION:
3108             case MyHTML_TAG_TABLE:
3109             case MyHTML_TAG_TBODY:
3110             case MyHTML_TAG_TFOOT:
3111             case MyHTML_TAG_THEAD:
3112             case MyHTML_TAG_TR:
3113             case MyHTML_TAG_TD:
3114             case MyHTML_TAG_TH:
3115             {
3116                 // parse error
3117                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
3118 
3119                 myhtml_tree_node_t* some_node = myhtml_tree_element_in_scope(tree, token->tag_id, MyHTML_NAMESPACE_HTML, MyHTML_TAG_CATEGORIES_SCOPE_TABLE);
3120 
3121                 if(some_node == NULL) {
3122                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_OPEN_NOT_FOUND ACTION:IGNORE LEVEL:ERROR */
3123 
3124                     break;
3125                 }
3126 
3127                 myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_SELECT, MyHTML_NAMESPACE_HTML, false);
3128                 myhtml_tree_reset_insertion_mode_appropriately(tree);
3129 
3130                 return true;
3131             }
3132 
3133             default:
3134                 return myhtml_insertion_mode_in_select(tree, token);
3135         }
3136     }
3137     else {
3138         switch (token->tag_id)
3139         {
3140             case MyHTML_TAG_CAPTION:
3141             case MyHTML_TAG_TABLE:
3142             case MyHTML_TAG_TBODY:
3143             case MyHTML_TAG_TFOOT:
3144             case MyHTML_TAG_THEAD:
3145             case MyHTML_TAG_TR:
3146             case MyHTML_TAG_TD:
3147             case MyHTML_TAG_TH:
3148             {
3149                 // parse error
3150                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION LEVEL:ERROR */
3151 
3152                 myhtml_tree_open_elements_pop_until(tree, MyHTML_TAG_SELECT, MyHTML_NAMESPACE_HTML, false);
3153                 myhtml_tree_reset_insertion_mode_appropriately(tree);
3154 
3155                 return true;
3156             }
3157 
3158             default:
3159                 return myhtml_insertion_mode_in_select(tree, token);
3160         }
3161     }
3162 
3163     return false;
3164 }
3165 
myhtml_insertion_mode_in_template(myhtml_tree_t * tree,myhtml_token_node_t * token)3166 bool myhtml_insertion_mode_in_template(myhtml_tree_t* tree, myhtml_token_node_t* token)
3167 {
3168     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
3169     {
3170         switch (token->tag_id) {
3171             case MyHTML_TAG_TEMPLATE:
3172                 return myhtml_insertion_mode_in_body(tree, token);
3173 
3174             default: {
3175                 // parse error
3176                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
3177 
3178                 break;
3179             }
3180         }
3181     }
3182     else {
3183         switch (token->tag_id)
3184         {
3185             case MyHTML_TAG__TEXT:
3186             case MyHTML_TAG__COMMENT:
3187             case MyHTML_TAG__DOCTYPE:
3188                 return myhtml_insertion_mode_in_body(tree, token);
3189 
3190             case MyHTML_TAG_BASE:
3191             case MyHTML_TAG_BASEFONT:
3192             case MyHTML_TAG_BGSOUND:
3193             case MyHTML_TAG_LINK:
3194             case MyHTML_TAG_META:
3195             case MyHTML_TAG_NOFRAMES:
3196             case MyHTML_TAG_SCRIPT:
3197             case MyHTML_TAG_STYLE:
3198             case MyHTML_TAG_TEMPLATE:
3199             case MyHTML_TAG_TITLE:
3200                 return myhtml_insertion_mode_in_head(tree, token);
3201 
3202             case MyHTML_TAG_CAPTION:
3203             case MyHTML_TAG_COLGROUP:
3204             case MyHTML_TAG_TBODY:
3205             case MyHTML_TAG_TFOOT:
3206             case MyHTML_TAG_THEAD:
3207                 myhtml_tree_template_insertion_pop(tree);
3208                 myhtml_tree_template_insertion_append(tree, MyHTML_INSERTION_MODE_IN_TABLE);
3209 
3210                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE;
3211                 return true;
3212 
3213             case MyHTML_TAG_COL:
3214                 myhtml_tree_template_insertion_pop(tree);
3215                 myhtml_tree_template_insertion_append(tree, MyHTML_INSERTION_MODE_IN_COLUMN_GROUP);
3216 
3217                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_COLUMN_GROUP;
3218                 return true;
3219 
3220             case MyHTML_TAG_TR:
3221                 myhtml_tree_template_insertion_pop(tree);
3222                 myhtml_tree_template_insertion_append(tree, MyHTML_INSERTION_MODE_IN_TABLE_BODY);
3223 
3224                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_TABLE_BODY;
3225                 return true;
3226 
3227             case MyHTML_TAG_TD:
3228             case MyHTML_TAG_TH:
3229                 myhtml_tree_template_insertion_pop(tree);
3230                 myhtml_tree_template_insertion_append(tree, MyHTML_INSERTION_MODE_IN_ROW);
3231 
3232                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_ROW;
3233                 return true;
3234 
3235             case MyHTML_TAG__END_OF_FILE:
3236             {
3237                 myhtml_tree_node_t* node = myhtml_tree_open_elements_find_by_tag_idx(tree, MyHTML_TAG_TEMPLATE, MyHTML_NAMESPACE_HTML, NULL);
3238 
3239                 if(node == NULL) {
3240                     myhtml_rules_stop_parsing(tree);
3241                     break;
3242                 }
3243 
3244                 // parse error
3245                 /* %EXTERNAL% VALIDATOR:RULES TAG STATUS:ELEMENT_NOT_CLOSED LEVEL:ERROR TAG_ID:MyHTML_TAG_TEMPLATE NS:MyHTML_NAMESPACE_HTML */
3246 
3247                 myhtml_tree_open_elements_pop_until_by_node(tree, node, false);
3248                 myhtml_tree_active_formatting_up_to_last_marker(tree);
3249                 myhtml_tree_template_insertion_pop(tree);
3250                 myhtml_tree_reset_insertion_mode_appropriately(tree);
3251 
3252                 return true;
3253             }
3254 
3255              default:
3256                 myhtml_tree_template_insertion_pop(tree);
3257                 myhtml_tree_template_insertion_append(tree, MyHTML_INSERTION_MODE_IN_BODY);
3258 
3259                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
3260                 return true;
3261         }
3262     }
3263 
3264     return false;
3265 }
3266 
myhtml_insertion_mode_after_body(myhtml_tree_t * tree,myhtml_token_node_t * token)3267 bool myhtml_insertion_mode_after_body(myhtml_tree_t* tree, myhtml_token_node_t* token)
3268 {
3269     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
3270     {
3271         switch (token->tag_id) {
3272             case MyHTML_TAG_HTML:
3273             {
3274                 if(tree->fragment) {
3275                     // parse error
3276                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_NO_EXPECTED ACTION:IGNORE LEVEL:ERROR */
3277 
3278                     break;
3279                 }
3280 
3281                 tree->insert_mode = MyHTML_INSERTION_MODE_AFTER_AFTER_BODY;
3282                 break;
3283             }
3284 
3285             default: {
3286                 // parse error
3287                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY LEVEL:ERROR */
3288 
3289                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
3290                 return true;
3291             }
3292         }
3293     }
3294     else {
3295         switch (token->tag_id)
3296         {
3297             case MyHTML_TAG__TEXT:
3298             {
3299                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE)
3300                     return myhtml_insertion_mode_in_body(tree, token);
3301 
3302                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
3303                 return true;
3304             }
3305 
3306             case MyHTML_TAG__COMMENT:
3307             {
3308                 if(tree->open_elements->length == 0) {
3309                     MyCORE_DEBUG_ERROR("after body state; open_elements length < 1");
3310                     break;
3311                 }
3312 
3313                 myhtml_tree_node_t* adjusted_location = tree->open_elements->list[0];
3314 
3315                 // state 2
3316                 myhtml_tree_node_t* node = myhtml_tree_node_create(tree);
3317 
3318                 node->tag_id      = MyHTML_TAG__COMMENT;
3319                 node->token        = token;
3320                 node->ns = adjusted_location->ns;
3321 
3322                 myhtml_tree_node_add_child(adjusted_location, node);
3323 
3324                 break;
3325             }
3326 
3327             case MyHTML_TAG__DOCTYPE: {
3328                 // parse error
3329                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
3330 
3331                 break;
3332             }
3333             case MyHTML_TAG_HTML:
3334                 return myhtml_insertion_mode_in_body(tree, token);
3335 
3336             case MyHTML_TAG__END_OF_FILE:
3337                 myhtml_rules_stop_parsing(tree);
3338                 break;
3339 
3340             default: {
3341                 // parse error
3342                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY LEVEL:ERROR */
3343 
3344                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
3345                 return true;
3346             }
3347         }
3348     }
3349 
3350     return false;
3351 }
3352 
myhtml_insertion_mode_in_frameset(myhtml_tree_t * tree,myhtml_token_node_t * token)3353 bool myhtml_insertion_mode_in_frameset(myhtml_tree_t* tree, myhtml_token_node_t* token)
3354 {
3355     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
3356     {
3357         switch (token->tag_id) {
3358             case MyHTML_TAG_FRAMESET:
3359             {
3360                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
3361 
3362                 if(current_node == tree->document->child) {
3363                     // parse error
3364                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_NO_EXPECTED ACTION:IGNORE LEVEL:ERROR */
3365 
3366                     break;
3367                 }
3368 
3369                 myhtml_tree_open_elements_pop(tree);
3370 
3371                 current_node = myhtml_tree_current_node(tree);
3372 
3373                 if(tree->fragment == NULL &&
3374                    !(current_node->tag_id == MyHTML_TAG_FRAMESET &&
3375                      current_node->ns == MyHTML_NAMESPACE_HTML))
3376                 {
3377                     tree->insert_mode = MyHTML_INSERTION_MODE_AFTER_FRAMESET;
3378                 }
3379 
3380                 break;
3381             }
3382 
3383             default: {
3384                 // parse error
3385                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
3386 
3387                 break;
3388             }
3389         }
3390     }
3391     else {
3392         switch (token->tag_id)
3393         {
3394             case MyHTML_TAG__TEXT:
3395             {
3396                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE) {
3397                     myhtml_tree_node_insert_text(tree, token);
3398                     break;
3399                 }
3400 
3401                 // parse error
3402                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
3403 
3404                 myhtml_token_node_wait_for_done(tree->token, token);
3405                 mycore_string_stay_only_whitespace(&token->str);
3406 
3407                 if(token->str.length)
3408                     myhtml_tree_node_insert_text(tree, token);
3409 
3410                 break;
3411             }
3412 
3413             case MyHTML_TAG__COMMENT:
3414             {
3415                 myhtml_tree_node_insert_comment(tree, token, NULL);
3416                 break;
3417             }
3418 
3419             case MyHTML_TAG__DOCTYPE: {
3420                 // parse error
3421                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
3422 
3423                 break;
3424             }
3425 
3426             case MyHTML_TAG_HTML:
3427                 return myhtml_insertion_mode_in_body(tree, token);
3428 
3429             case MyHTML_TAG_FRAMESET:
3430                 myhtml_tree_node_insert_html_element(tree, token);
3431                 break;
3432 
3433             case MyHTML_TAG_FRAME:
3434                 myhtml_tree_node_insert_html_element(tree, token);
3435                 myhtml_tree_open_elements_pop(tree);
3436                 break;
3437 
3438             case MyHTML_TAG_NOFRAMES:
3439                 return myhtml_insertion_mode_in_head(tree, token);
3440 
3441             case MyHTML_TAG__END_OF_FILE:
3442             {
3443                 myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
3444 
3445                 if(current_node == tree->document->child) {
3446                     // parse error
3447                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
3448                 }
3449 
3450                 myhtml_rules_stop_parsing(tree);
3451                 break;
3452             }
3453 
3454             default: {
3455                 // parse error
3456                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
3457 
3458                 break;
3459             }
3460         }
3461     }
3462 
3463     return false;
3464 }
3465 
myhtml_insertion_mode_after_frameset(myhtml_tree_t * tree,myhtml_token_node_t * token)3466 bool myhtml_insertion_mode_after_frameset(myhtml_tree_t* tree, myhtml_token_node_t* token)
3467 {
3468     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
3469     {
3470         switch (token->tag_id) {
3471             case MyHTML_TAG_HTML:
3472                 tree->insert_mode = MyHTML_INSERTION_MODE_AFTER_AFTER_FRAMESET;
3473                 break;
3474 
3475             default: {
3476                 // parse error
3477                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
3478 
3479                 break;
3480             }
3481         }
3482     }
3483     else {
3484         switch (token->tag_id)
3485         {
3486             case MyHTML_TAG__TEXT:
3487             {
3488                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE) {
3489                     myhtml_tree_node_insert_text(tree, token);
3490                     break;
3491                 }
3492 
3493                 // parse error
3494                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
3495 
3496                 myhtml_token_node_wait_for_done(tree->token, token);
3497                 mycore_string_stay_only_whitespace(&token->str);
3498 
3499                 if(token->str.length)
3500                     myhtml_tree_node_insert_text(tree, token);
3501 
3502                 break;
3503             }
3504 
3505             case MyHTML_TAG__COMMENT:
3506             {
3507                 myhtml_tree_node_insert_comment(tree, token, NULL);
3508                 break;
3509             }
3510 
3511             case MyHTML_TAG__DOCTYPE: {
3512                 // parse error
3513                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
3514                 break;
3515             }
3516 
3517             case MyHTML_TAG_HTML:
3518                 return myhtml_insertion_mode_in_body(tree, token);
3519 
3520             case MyHTML_TAG_NOFRAMES:
3521                 return myhtml_insertion_mode_in_head(tree, token);
3522 
3523             case MyHTML_TAG__END_OF_FILE:
3524                 myhtml_rules_stop_parsing(tree);
3525                 break;
3526 
3527             default: {
3528                 // parse error
3529                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY ACTION:IGNORE LEVEL:ERROR */
3530 
3531                 break;
3532             }
3533         }
3534     }
3535 
3536     return false;
3537 }
3538 
myhtml_insertion_mode_after_after_body(myhtml_tree_t * tree,myhtml_token_node_t * token)3539 bool myhtml_insertion_mode_after_after_body(myhtml_tree_t* tree, myhtml_token_node_t* token)
3540 {
3541     if(token->type & MyHTML_TOKEN_TYPE_CLOSE)
3542     {
3543         tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
3544         return true;
3545     }
3546     else {
3547         switch (token->tag_id)
3548         {
3549             case MyHTML_TAG__COMMENT:
3550             {
3551                 myhtml_tree_node_t* adjusted_location = tree->document;
3552                 myhtml_tree_node_t* node = myhtml_tree_node_create(tree);
3553 
3554                 node->tag_id      = MyHTML_TAG__COMMENT;
3555                 node->token        = token;
3556                 node->ns = adjusted_location->ns;
3557 
3558                 myhtml_tree_node_add_child(adjusted_location, node);
3559                 break;
3560             }
3561 
3562             case MyHTML_TAG__TEXT:
3563             {
3564                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE)
3565                     return myhtml_insertion_mode_in_body(tree, token);
3566 
3567                 // parse error
3568                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
3569 
3570                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
3571                 return true;
3572             }
3573 
3574             case MyHTML_TAG_HTML:
3575             case MyHTML_TAG__DOCTYPE:
3576                 return myhtml_insertion_mode_in_body(tree, token);
3577 
3578             case MyHTML_TAG__END_OF_FILE:
3579                 myhtml_rules_stop_parsing(tree);
3580                 break;
3581 
3582             default: {
3583                 // parse error
3584                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
3585 
3586                 tree->insert_mode = MyHTML_INSERTION_MODE_IN_BODY;
3587                 return true;
3588             }
3589         }
3590     }
3591 
3592     return false;
3593 }
3594 
myhtml_insertion_mode_after_after_frameset(myhtml_tree_t * tree,myhtml_token_node_t * token)3595 bool myhtml_insertion_mode_after_after_frameset(myhtml_tree_t* tree, myhtml_token_node_t* token)
3596 {
3597     if(token->type & MyHTML_TOKEN_TYPE_CLOSE) {
3598         // parse error
3599         /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY LEVEL:ERROR */
3600 
3601         return false;
3602     }
3603     else {
3604         switch (token->tag_id)
3605         {
3606             case MyHTML_TAG__COMMENT:
3607             {
3608                 myhtml_tree_node_t* adjusted_location = tree->document;
3609                 myhtml_tree_node_t* node = myhtml_tree_node_create(tree);
3610 
3611                 node->tag_id      = MyHTML_TAG__COMMENT;
3612                 node->token        = token;
3613                 node->ns = adjusted_location->ns;
3614 
3615                 myhtml_tree_node_add_child(adjusted_location, node);
3616                 break;
3617             }
3618 
3619             case MyHTML_TAG__TEXT:
3620             {
3621                 if(token->type & MyHTML_TOKEN_TYPE_WHITESPACE)
3622                     return myhtml_insertion_mode_in_body(tree, token);
3623 
3624                 myhtml_token_node_t* new_token = myhtml_insertion_fix_split_for_text_begin_ws(tree, token);
3625                 if(new_token)
3626                     return myhtml_insertion_mode_in_body(tree, new_token);
3627 
3628                 // parse error
3629                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY LEVEL:ERROR */
3630 
3631                 break;
3632             }
3633 
3634             case MyHTML_TAG_HTML:
3635             case MyHTML_TAG__DOCTYPE:
3636                 return myhtml_insertion_mode_in_body(tree, token);
3637 
3638             case MyHTML_TAG__END_OF_FILE:
3639                 myhtml_rules_stop_parsing(tree);
3640                 break;
3641 
3642             case MyHTML_TAG_NOFRAMES:
3643                 return myhtml_insertion_mode_in_head(tree, token);
3644 
3645             default: {
3646                 // parse error
3647                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_UNNECESSARY LEVEL:ERROR */
3648                 break;
3649             }
3650         }
3651     }
3652 
3653     return false;
3654 }
3655 
myhtml_insertion_mode_in_foreign_content_end_other(myhtml_tree_t * tree,myhtml_tree_node_t * current_node,myhtml_token_node_t * token)3656 bool myhtml_insertion_mode_in_foreign_content_end_other(myhtml_tree_t* tree, myhtml_tree_node_t* current_node, myhtml_token_node_t* token)
3657 {
3658     if(current_node->tag_id != token->tag_id) {
3659         // parse error
3660         /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
3661         /* %EXTERNAL% VALIDATOR:RULES HAVE_NEED_ADD HAVE:current_node->token NEED:token HAVE_TAG_ID:current_node->tag_id HAVE_NS:current_node->ns NEED_TAG_ID:token->tag_id NEED_NS:MyHTML_NAMESPACE_HTML */
3662     }
3663 
3664     if(tree->open_elements->length)
3665     {
3666         myhtml_tree_node_t** list = tree->open_elements->list;
3667         size_t i = tree->open_elements->length - 1;
3668 
3669         while (i)
3670         {
3671             current_node = list[i];
3672 
3673             if(current_node->tag_id == token->tag_id) {
3674                 myhtml_tree_open_elements_pop_until_by_node(tree, current_node, false);
3675                 return false;
3676             }
3677 
3678             i--;
3679 
3680             if(list[i]->ns == MyHTML_NAMESPACE_HTML)
3681                 break;
3682         }
3683     }
3684 
3685     return tree->myhtml->insertion_func[tree->insert_mode](tree, token);
3686 }
3687 
myhtml_insertion_mode_in_foreign_content_start_other(myhtml_tree_t * tree,myhtml_token_node_t * token)3688 bool myhtml_insertion_mode_in_foreign_content_start_other(myhtml_tree_t* tree, myhtml_token_node_t* token)
3689 {
3690     myhtml_tree_node_t* adjusted_node = myhtml_tree_adjusted_current_node(tree);
3691 
3692     myhtml_token_node_wait_for_done(tree->token, token);
3693 
3694     if(adjusted_node->ns == MyHTML_NAMESPACE_MATHML) {
3695         myhtml_token_adjust_mathml_attributes(token);
3696     }
3697     else if(adjusted_node->ns == MyHTML_NAMESPACE_SVG) {
3698         myhtml_token_adjust_svg_attributes(token);
3699     }
3700 
3701     myhtml_token_adjust_foreign_attributes(token);
3702 
3703     myhtml_tree_node_t* node = myhtml_tree_node_insert_foreign_element(tree, token);
3704     node->ns = adjusted_node->ns;
3705 
3706     if(token->type & MyHTML_TOKEN_TYPE_CLOSE_SELF)
3707     {
3708         if(token->tag_id == MyHTML_TAG_SCRIPT &&
3709            node->ns == MyHTML_NAMESPACE_SVG)
3710         {
3711             return myhtml_insertion_mode_in_foreign_content_end_other(tree, myhtml_tree_current_node(tree), token);
3712         }
3713         else {
3714             myhtml_tree_open_elements_pop(tree);
3715         }
3716     }
3717 
3718     return false;
3719 }
3720 
myhtml_insertion_mode_in_foreign_content(myhtml_tree_t * tree,myhtml_token_node_t * token)3721 bool myhtml_insertion_mode_in_foreign_content(myhtml_tree_t* tree, myhtml_token_node_t* token)
3722 {
3723     if(token->type & MyHTML_TOKEN_TYPE_CLOSE) {
3724         myhtml_tree_node_t* current_node = myhtml_tree_current_node(tree);
3725 
3726         if(token->tag_id == MyHTML_TAG_SCRIPT &&
3727            current_node->tag_id == MyHTML_TAG_SCRIPT &&
3728            current_node->ns == MyHTML_NAMESPACE_SVG)
3729         {
3730             myhtml_tree_open_elements_pop(tree);
3731             // TODO: now script is disable, skip this
3732             return false;
3733         }
3734 
3735         return myhtml_insertion_mode_in_foreign_content_end_other(tree, current_node, token);
3736     }
3737     else {
3738         switch (token->tag_id)
3739         {
3740             case MyHTML_TAG__TEXT:
3741             {
3742                 if(token->type & MyHTML_TOKEN_TYPE_NULL) {
3743                     // parse error
3744                     /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:NULL_CHAR LEVEL:ERROR */
3745 
3746                     myhtml_token_node_wait_for_done(tree->token, token);
3747                     myhtml_token_set_replacement_character_for_null_token(tree, token);
3748                 }
3749 
3750                 myhtml_tree_node_insert_text(tree, token);
3751 
3752                 if((token->type & MyHTML_TOKEN_TYPE_WHITESPACE) == 0)
3753                     tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_FRAMESET_OK);
3754 
3755                 break;
3756             }
3757 
3758             case MyHTML_TAG__COMMENT:
3759                 myhtml_tree_node_insert_comment(tree, token, NULL);
3760                 break;
3761 
3762             case MyHTML_TAG__DOCTYPE: {
3763                 // parse error
3764                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_WRONG_LOCATION ACTION:IGNORE LEVEL:ERROR */
3765 
3766                 break;
3767             }
3768 
3769             case MyHTML_TAG_B:
3770             case MyHTML_TAG_BIG:
3771             case MyHTML_TAG_BLOCKQUOTE:
3772             case MyHTML_TAG_BODY:
3773             case MyHTML_TAG_BR:
3774             case MyHTML_TAG_CENTER:
3775             case MyHTML_TAG_CODE:
3776             case MyHTML_TAG_DD:
3777             case MyHTML_TAG_DIV:
3778             case MyHTML_TAG_DL:
3779             case MyHTML_TAG_DT:
3780             case MyHTML_TAG_EM:
3781             case MyHTML_TAG_EMBED:
3782             case MyHTML_TAG_H1:
3783             case MyHTML_TAG_H2:
3784             case MyHTML_TAG_H3:
3785             case MyHTML_TAG_H4:
3786             case MyHTML_TAG_H5:
3787             case MyHTML_TAG_H6:
3788             case MyHTML_TAG_HEAD:
3789             case MyHTML_TAG_HR:
3790             case MyHTML_TAG_I:
3791             case MyHTML_TAG_IMG:
3792             case MyHTML_TAG_LI:
3793             case MyHTML_TAG_LISTING:
3794             case MyHTML_TAG_MENU:
3795             case MyHTML_TAG_META:
3796             case MyHTML_TAG_NOBR:
3797             case MyHTML_TAG_OL:
3798             case MyHTML_TAG_P:
3799             case MyHTML_TAG_PRE:
3800             case MyHTML_TAG_RUBY:
3801             case MyHTML_TAG_S:
3802             case MyHTML_TAG_SMALL:
3803             case MyHTML_TAG_SPAN:
3804             case MyHTML_TAG_STRONG:
3805             case MyHTML_TAG_STRIKE:
3806             case MyHTML_TAG_SUB:
3807             case MyHTML_TAG_SUP:
3808             case MyHTML_TAG_TABLE:
3809             case MyHTML_TAG_TT:
3810             case MyHTML_TAG_U:
3811             case MyHTML_TAG_UL:
3812             case MyHTML_TAG_VAR:
3813             case MyHTML_TAG_FONT:
3814             {
3815                 // parse error
3816                 /* %EXTERNAL% VALIDATOR:RULES TOKEN STATUS:ELEMENT_NO_EXPECTED LEVEL:ERROR */
3817 
3818                 if(token->tag_id == MyHTML_TAG_FONT)
3819                 {
3820                     myhtml_token_node_wait_for_done(tree->token, token);
3821 
3822                     if(myhtml_token_attr_by_name(token, "color", 5) == NULL &&
3823                        myhtml_token_attr_by_name(token, "face" , 4) == NULL &&
3824                        myhtml_token_attr_by_name(token, "size" , 4) == NULL)
3825                     {
3826                         return myhtml_insertion_mode_in_foreign_content_start_other(tree, token);
3827                     }
3828                 }
3829 
3830                 if(tree->fragment == NULL) {
3831                     myhtml_tree_node_t* current_node;
3832 
3833                     do {
3834                         myhtml_tree_open_elements_pop(tree);
3835                         current_node = myhtml_tree_current_node(tree);
3836                     }
3837                     while(current_node && !(myhtml_tree_is_mathml_integration_point(tree, current_node) ||
3838                                             myhtml_tree_is_html_integration_point(tree, current_node) ||
3839                                             current_node->ns == MyHTML_NAMESPACE_HTML));
3840 
3841                     return true;
3842                 }
3843             }
3844 
3845             default:
3846                 return myhtml_insertion_mode_in_foreign_content_start_other(tree, token);
3847         }
3848     }
3849 
3850     return false;
3851 }
3852 
myhtml_rules_stop_parsing(myhtml_tree_t * tree)3853 void myhtml_rules_stop_parsing(myhtml_tree_t* tree)
3854 {
3855     // THIS! IS! -(SPARTA!)- STOP PARSING
3856 }
3857 
myhtml_rules_check_for_first_newline(myhtml_tree_t * tree,myhtml_token_node_t * token)3858 bool myhtml_rules_check_for_first_newline(myhtml_tree_t* tree, myhtml_token_node_t* token)
3859 {
3860     if(tree->flags & MyHTML_TREE_FLAGS_PARSE_FLAG) {
3861         if(tree->flags &MyHTML_TREE_FLAGS_PARSE_FLAG_EMIT_NEWLINE)
3862         {
3863             if(token->tag_id == MyHTML_TAG__TEXT) {
3864                 myhtml_token_node_wait_for_done(tree->token, token);
3865 
3866                 if(token->str.length > 0) {
3867                     if(token->str.data[0] == '\n') {
3868                         token->str.data = mchar_async_crop_first_chars_without_cache(token->str.data, 1);
3869 
3870                         token->str.length--;
3871 
3872                         if(token->str.length == 0) {
3873                             tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_PARSE_FLAG);
3874                             return true;
3875                         }
3876                     }
3877                 }
3878                 else
3879                     return true;
3880             }
3881         }
3882 
3883         tree->flags ^= (tree->flags & MyHTML_TREE_FLAGS_PARSE_FLAG);
3884     }
3885 
3886     return false;
3887 }
3888 
myhtml_rules_tree_dispatcher(myhtml_tree_t * tree,myhtml_token_node_t * token)3889 bool myhtml_rules_tree_dispatcher(myhtml_tree_t* tree, myhtml_token_node_t* token)
3890 {
3891     // for textarea && pre && listen
3892     if(myhtml_rules_check_for_first_newline(tree, token)) {
3893         tree->token_last_done = token;
3894 
3895         return false;
3896     }
3897 
3898     if(tree->state_of_builder != MyHTML_TOKENIZER_STATE_DATA)
3899         tree->state_of_builder = MyHTML_TOKENIZER_STATE_DATA;
3900 
3901     bool reprocess = false;
3902     myhtml_tree_node_t* adjusted_node = myhtml_tree_adjusted_current_node(tree);
3903 
3904     if(tree->open_elements->length == 0 || adjusted_node->ns == MyHTML_NAMESPACE_HTML) {
3905         reprocess = tree->myhtml->insertion_func[tree->insert_mode](tree, token);
3906     }
3907     else if(myhtml_tree_is_mathml_integration_point(tree, adjusted_node) &&
3908             ((token->tag_id == MyHTML_TAG__TEXT ||
3909               (token->tag_id != MyHTML_TAG_MGLYPH && token->tag_id != MyHTML_TAG_MALIGNMARK)) &&
3910              (token->type & MyHTML_TOKEN_TYPE_CLOSE) == 0))
3911     {
3912             reprocess = tree->myhtml->insertion_func[tree->insert_mode](tree, token);
3913     }
3914     else if(adjusted_node->tag_id == MyHTML_TAG_ANNOTATION_XML &&
3915        adjusted_node->ns == MyHTML_NAMESPACE_MATHML &&
3916        token->tag_id == MyHTML_TAG_SVG && (token->type & MyHTML_TOKEN_TYPE_CLOSE) == 0)
3917     {
3918         reprocess = tree->myhtml->insertion_func[tree->insert_mode](tree, token);
3919     }
3920     else if(myhtml_tree_is_html_integration_point(tree, adjusted_node) &&
3921             ((token->type & MyHTML_TOKEN_TYPE_CLOSE) == 0 || token->tag_id == MyHTML_TAG__TEXT))
3922     {
3923         reprocess = tree->myhtml->insertion_func[tree->insert_mode](tree, token);
3924     }
3925     else if(token->tag_id == MyHTML_TAG__END_OF_FILE)
3926         reprocess = tree->myhtml->insertion_func[tree->insert_mode](tree, token);
3927     else
3928         reprocess = myhtml_insertion_mode_in_foreign_content(tree, token);
3929 
3930     if(reprocess == false) {
3931         tree->token_last_done = token;
3932     }
3933 
3934     return reprocess;
3935 }
3936 
myhtml_rules_init(myhtml_t * myhtml)3937 mystatus_t myhtml_rules_init(myhtml_t* myhtml)
3938 {
3939     myhtml->insertion_func = (myhtml_insertion_f*)mycore_malloc(sizeof(myhtml_insertion_f) * MyHTML_INSERTION_MODE_LAST_ENTRY);
3940 
3941     if(myhtml->insertion_func == NULL)
3942         return MyHTML_STATUS_RULES_ERROR_MEMORY_ALLOCATION;
3943 
3944     myhtml->insertion_func[MyHTML_INSERTION_MODE_INITIAL] = myhtml_insertion_mode_initial;
3945     myhtml->insertion_func[MyHTML_INSERTION_MODE_BEFORE_HTML] = myhtml_insertion_mode_before_html;
3946     myhtml->insertion_func[MyHTML_INSERTION_MODE_BEFORE_HEAD] = myhtml_insertion_mode_before_head;
3947     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_HEAD] = myhtml_insertion_mode_in_head;
3948     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_HEAD_NOSCRIPT] = myhtml_insertion_mode_in_head_noscript;
3949     myhtml->insertion_func[MyHTML_INSERTION_MODE_AFTER_HEAD] = myhtml_insertion_mode_after_head;
3950     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_BODY] = myhtml_insertion_mode_in_body;
3951     myhtml->insertion_func[MyHTML_INSERTION_MODE_TEXT] = myhtml_insertion_mode_text;
3952     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_TABLE] = myhtml_insertion_mode_in_table;
3953     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_TABLE_TEXT] = myhtml_insertion_mode_in_table_text;
3954     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_CAPTION] = myhtml_insertion_mode_in_caption;
3955     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_COLUMN_GROUP] = myhtml_insertion_mode_in_column_group;
3956     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_TABLE_BODY] = myhtml_insertion_mode_in_table_body;
3957     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_ROW] = myhtml_insertion_mode_in_row;
3958     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_CELL] = myhtml_insertion_mode_in_cell;
3959     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_SELECT] = myhtml_insertion_mode_in_select;
3960     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_SELECT_IN_TABLE] = myhtml_insertion_mode_in_select_in_table;
3961     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_TEMPLATE] = myhtml_insertion_mode_in_template;
3962     myhtml->insertion_func[MyHTML_INSERTION_MODE_AFTER_BODY] = myhtml_insertion_mode_after_body;
3963     myhtml->insertion_func[MyHTML_INSERTION_MODE_IN_FRAMESET] = myhtml_insertion_mode_in_frameset;
3964     myhtml->insertion_func[MyHTML_INSERTION_MODE_AFTER_FRAMESET] = myhtml_insertion_mode_after_frameset;
3965     myhtml->insertion_func[MyHTML_INSERTION_MODE_AFTER_AFTER_BODY] = myhtml_insertion_mode_after_after_body;
3966     myhtml->insertion_func[MyHTML_INSERTION_MODE_AFTER_AFTER_FRAMESET] = myhtml_insertion_mode_after_after_frameset;
3967 
3968     return MyHTML_STATUS_OK;
3969 }
3970 
3971 
3972