1 /*
2  * This file is part of Hubbub.
3  * Licensed under the MIT License,
4  *                http://www.opensource.org/licenses/mit-license.php
5  * Copyright 2008 Andrew Sidwell <takkaria@netsurf-browser.org>
6  */
7 
8 #include <assert.h>
9 #include <string.h>
10 
11 #include "treebuilder/modes.h"
12 #include "treebuilder/internal.h"
13 #include "treebuilder/treebuilder.h"
14 #include "utils/utils.h"
15 
16 
17 /**
18  * Handle token in "after body" insertion mode
19  *
20  * \param treebuilder  The treebuilder instance
21  * \param token        The token to handle
22  * \return True to reprocess token, false otherwise
23  */
handle_after_body(hubbub_treebuilder * treebuilder,const hubbub_token * token)24 hubbub_error handle_after_body(hubbub_treebuilder *treebuilder,
25 		const hubbub_token *token)
26 {
27 	hubbub_error err = HUBBUB_OK;
28 
29 	switch (token->type) {
30 	case HUBBUB_TOKEN_CHARACTER:
31 	{
32 		/* mostly cribbed from process_characters_expect_whitespace */
33 		const uint8_t *data = token->data.character.ptr;
34 		size_t len = token->data.character.len;
35 		size_t c;
36 
37 		/* Scan for whitespace */
38 		for (c = 0; c < len; c++) {
39 			if (data[c] != 0x09 && data[c] != 0x0A &&
40 					data[c] != 0x0C && data[c] != 0x20)
41 				break;
42 		}
43 
44 		/* Whitespace characters in token, so handle as in body */
45 		if (c > 0) {
46 			hubbub_token temp = *token;
47 			temp.data.character.len = c;
48 
49 			err = handle_in_body(treebuilder, &temp);
50 			if (err != HUBBUB_OK)
51 				return err;
52 		}
53 
54 		/* Anything else, switch to in body */
55 		if (c != len) {
56 			/* Update token data to strip leading whitespace */
57 			((hubbub_token *) token)->data.character.ptr += c;
58 			((hubbub_token *) token)->data.character.len -= c;
59 
60 			treebuilder->context.mode = IN_BODY;
61 			err = HUBBUB_REPROCESS;
62 		}
63 	}
64 		break;
65 	case HUBBUB_TOKEN_COMMENT:
66 		err = process_comment_append(treebuilder, token,
67 				treebuilder->context.element_stack[
68 				0].node);
69 		break;
70 	case HUBBUB_TOKEN_DOCTYPE:
71 		/** \todo parse error */
72 		break;
73 	case HUBBUB_TOKEN_START_TAG:
74 	{
75 		element_type type = element_type_from_name(treebuilder,
76 				&token->data.tag.name);
77 
78 		if (type == HTML) {
79 			/* Process as if "in body" */
80 			err = handle_in_body(treebuilder, token);
81 		} else {
82 			/** \todo parse error */
83 			treebuilder->context.mode = IN_BODY;
84 			err = HUBBUB_REPROCESS;
85 		}
86 	}
87 		break;
88 	case HUBBUB_TOKEN_END_TAG:
89 	{
90 		element_type type = element_type_from_name(treebuilder,
91 				&token->data.tag.name);
92 
93 		if (type == HTML) {
94 			/** \todo fragment case */
95 			/** \todo parse error */
96 			treebuilder->context.mode = AFTER_AFTER_BODY;
97 		} else {
98 			/** \todo parse error */
99 			treebuilder->context.mode = IN_BODY;
100 			err = HUBBUB_REPROCESS;
101 		}
102 	}
103 		break;
104 	case HUBBUB_TOKEN_EOF:
105 		break;
106 	}
107 
108 	return err;
109 }
110 
111