summaryrefslogtreecommitdiffstats
path: root/parser/html/javasrc/TreeBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'parser/html/javasrc/TreeBuilder.java')
-rw-r--r--parser/html/javasrc/TreeBuilder.java6558
1 files changed, 0 insertions, 6558 deletions
diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java
deleted file mode 100644
index 5e83d1847..000000000
--- a/parser/html/javasrc/TreeBuilder.java
+++ /dev/null
@@ -1,6558 +0,0 @@
-/*
- * Copyright (c) 2007 Henri Sivonen
- * Copyright (c) 2007-2015 Mozilla Foundation
- * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
- * Foundation, and Opera Software ASA.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * The comments following this one that use the same comment syntax as this
- * comment are quotes from the WHATWG HTML 5 spec as of 27 June 2007
- * amended as of June 28 2007.
- * That document came with this statement:
- * "© Copyright 2004-2007 Apple Computer, Inc., Mozilla Foundation, and
- * Opera Software ASA. You are granted a license to use, reproduce and
- * create derivative works of this document."
- */
-
-package nu.validator.htmlparser.impl;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-
-import nu.validator.htmlparser.annotation.Auto;
-import nu.validator.htmlparser.annotation.Const;
-import nu.validator.htmlparser.annotation.IdType;
-import nu.validator.htmlparser.annotation.Inline;
-import nu.validator.htmlparser.annotation.Literal;
-import nu.validator.htmlparser.annotation.Local;
-import nu.validator.htmlparser.annotation.NoLength;
-import nu.validator.htmlparser.annotation.NsUri;
-import nu.validator.htmlparser.common.DoctypeExpectation;
-import nu.validator.htmlparser.common.DocumentMode;
-import nu.validator.htmlparser.common.DocumentModeHandler;
-import nu.validator.htmlparser.common.Interner;
-import nu.validator.htmlparser.common.TokenHandler;
-import nu.validator.htmlparser.common.XmlViolationPolicy;
-
-public abstract class TreeBuilder<T> implements TokenHandler,
- TreeBuilderState<T> {
-
- /**
- * Array version of U+FFFD.
- */
- private static final @NoLength char[] REPLACEMENT_CHARACTER = { '\uFFFD' };
-
- // Start dispatch groups
-
- final static int OTHER = 0;
-
- final static int A = 1;
-
- final static int BASE = 2;
-
- final static int BODY = 3;
-
- final static int BR = 4;
-
- final static int BUTTON = 5;
-
- final static int CAPTION = 6;
-
- final static int COL = 7;
-
- final static int COLGROUP = 8;
-
- final static int FORM = 9;
-
- final static int FRAME = 10;
-
- final static int FRAMESET = 11;
-
- final static int IMAGE = 12;
-
- final static int INPUT = 13;
-
- final static int ISINDEX = 14;
-
- final static int LI = 15;
-
- final static int LINK_OR_BASEFONT_OR_BGSOUND = 16;
-
- final static int MATH = 17;
-
- final static int META = 18;
-
- final static int SVG = 19;
-
- final static int HEAD = 20;
-
- final static int HR = 22;
-
- final static int HTML = 23;
-
- final static int NOBR = 24;
-
- final static int NOFRAMES = 25;
-
- final static int NOSCRIPT = 26;
-
- final static int OPTGROUP = 27;
-
- final static int OPTION = 28;
-
- final static int P = 29;
-
- final static int PLAINTEXT = 30;
-
- final static int SCRIPT = 31;
-
- final static int SELECT = 32;
-
- final static int STYLE = 33;
-
- final static int TABLE = 34;
-
- final static int TEXTAREA = 35;
-
- final static int TITLE = 36;
-
- final static int TR = 37;
-
- final static int XMP = 38;
-
- final static int TBODY_OR_THEAD_OR_TFOOT = 39;
-
- final static int TD_OR_TH = 40;
-
- final static int DD_OR_DT = 41;
-
- final static int H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 = 42;
-
- final static int MARQUEE_OR_APPLET = 43;
-
- final static int PRE_OR_LISTING = 44;
-
- final static int B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U = 45;
-
- final static int UL_OR_OL_OR_DL = 46;
-
- final static int IFRAME = 47;
-
- final static int EMBED = 48;
-
- final static int AREA_OR_WBR = 49;
-
- final static int DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU = 50;
-
- final static int ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY = 51;
-
- final static int RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR = 52;
-
- final static int RB_OR_RTC = 53;
-
- final static int PARAM_OR_SOURCE_OR_TRACK = 55;
-
- final static int MGLYPH_OR_MALIGNMARK = 56;
-
- final static int MI_MO_MN_MS_MTEXT = 57;
-
- final static int ANNOTATION_XML = 58;
-
- final static int FOREIGNOBJECT_OR_DESC = 59;
-
- final static int NOEMBED = 60;
-
- final static int FIELDSET = 61;
-
- final static int OUTPUT = 62;
-
- final static int OBJECT = 63;
-
- final static int FONT = 64;
-
- final static int KEYGEN = 65;
-
- final static int MENUITEM = 66;
-
- final static int TEMPLATE = 67;
-
- final static int IMG = 68;
-
- final static int RT_OR_RP = 69;
-
- // start insertion modes
-
- private static final int IN_ROW = 0;
-
- private static final int IN_TABLE_BODY = 1;
-
- private static final int IN_TABLE = 2;
-
- private static final int IN_CAPTION = 3;
-
- private static final int IN_CELL = 4;
-
- private static final int FRAMESET_OK = 5;
-
- private static final int IN_BODY = 6;
-
- private static final int IN_HEAD = 7;
-
- private static final int IN_HEAD_NOSCRIPT = 8;
-
- // no fall-through
-
- private static final int IN_COLUMN_GROUP = 9;
-
- // no fall-through
-
- private static final int IN_SELECT_IN_TABLE = 10;
-
- private static final int IN_SELECT = 11;
-
- // no fall-through
-
- private static final int AFTER_BODY = 12;
-
- // no fall-through
-
- private static final int IN_FRAMESET = 13;
-
- private static final int AFTER_FRAMESET = 14;
-
- // no fall-through
-
- private static final int INITIAL = 15;
-
- // could add fall-through
-
- private static final int BEFORE_HTML = 16;
-
- // could add fall-through
-
- private static final int BEFORE_HEAD = 17;
-
- // no fall-through
-
- private static final int AFTER_HEAD = 18;
-
- // no fall-through
-
- private static final int AFTER_AFTER_BODY = 19;
-
- // no fall-through
-
- private static final int AFTER_AFTER_FRAMESET = 20;
-
- // no fall-through
-
- private static final int TEXT = 21;
-
- private static final int IN_TEMPLATE = 22;
-
- // start charset states
-
- private static final int CHARSET_INITIAL = 0;
-
- private static final int CHARSET_C = 1;
-
- private static final int CHARSET_H = 2;
-
- private static final int CHARSET_A = 3;
-
- private static final int CHARSET_R = 4;
-
- private static final int CHARSET_S = 5;
-
- private static final int CHARSET_E = 6;
-
- private static final int CHARSET_T = 7;
-
- private static final int CHARSET_EQUALS = 8;
-
- private static final int CHARSET_SINGLE_QUOTED = 9;
-
- private static final int CHARSET_DOUBLE_QUOTED = 10;
-
- private static final int CHARSET_UNQUOTED = 11;
-
- // end pseudo enums
-
- // [NOCPP[
-
- private final static String[] HTML4_PUBLIC_IDS = {
- "-//W3C//DTD HTML 4.0 Frameset//EN",
- "-//W3C//DTD HTML 4.0 Transitional//EN",
- "-//W3C//DTD HTML 4.0//EN", "-//W3C//DTD HTML 4.01 Frameset//EN",
- "-//W3C//DTD HTML 4.01 Transitional//EN",
- "-//W3C//DTD HTML 4.01//EN" };
-
- // ]NOCPP]
-
- @Literal private final static String[] QUIRKY_PUBLIC_IDS = {
- "+//silmaril//dtd html pro v0r11 19970101//",
- "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
- "-//as//dtd html 3.0 aswedit + extensions//",
- "-//ietf//dtd html 2.0 level 1//",
- "-//ietf//dtd html 2.0 level 2//",
- "-//ietf//dtd html 2.0 strict level 1//",
- "-//ietf//dtd html 2.0 strict level 2//",
- "-//ietf//dtd html 2.0 strict//",
- "-//ietf//dtd html 2.0//",
- "-//ietf//dtd html 2.1e//",
- "-//ietf//dtd html 3.0//",
- "-//ietf//dtd html 3.2 final//",
- "-//ietf//dtd html 3.2//",
- "-//ietf//dtd html 3//",
- "-//ietf//dtd html level 0//",
- "-//ietf//dtd html level 1//",
- "-//ietf//dtd html level 2//",
- "-//ietf//dtd html level 3//",
- "-//ietf//dtd html strict level 0//",
- "-//ietf//dtd html strict level 1//",
- "-//ietf//dtd html strict level 2//",
- "-//ietf//dtd html strict level 3//",
- "-//ietf//dtd html strict//",
- "-//ietf//dtd html//",
- "-//metrius//dtd metrius presentational//",
- "-//microsoft//dtd internet explorer 2.0 html strict//",
- "-//microsoft//dtd internet explorer 2.0 html//",
- "-//microsoft//dtd internet explorer 2.0 tables//",
- "-//microsoft//dtd internet explorer 3.0 html strict//",
- "-//microsoft//dtd internet explorer 3.0 html//",
- "-//microsoft//dtd internet explorer 3.0 tables//",
- "-//netscape comm. corp.//dtd html//",
- "-//netscape comm. corp.//dtd strict html//",
- "-//o'reilly and associates//dtd html 2.0//",
- "-//o'reilly and associates//dtd html extended 1.0//",
- "-//o'reilly and associates//dtd html extended relaxed 1.0//",
- "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//",
- "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
- "-//spyglass//dtd html 2.0 extended//",
- "-//sq//dtd html 2.0 hotmetal + extensions//",
- "-//sun microsystems corp.//dtd hotjava html//",
- "-//sun microsystems corp.//dtd hotjava strict html//",
- "-//w3c//dtd html 3 1995-03-24//", "-//w3c//dtd html 3.2 draft//",
- "-//w3c//dtd html 3.2 final//", "-//w3c//dtd html 3.2//",
- "-//w3c//dtd html 3.2s draft//", "-//w3c//dtd html 4.0 frameset//",
- "-//w3c//dtd html 4.0 transitional//",
- "-//w3c//dtd html experimental 19960712//",
- "-//w3c//dtd html experimental 970421//", "-//w3c//dtd w3 html//",
- "-//w3o//dtd w3 html 3.0//", "-//webtechs//dtd mozilla html 2.0//",
- "-//webtechs//dtd mozilla html//" };
-
- private static final int NOT_FOUND_ON_STACK = Integer.MAX_VALUE;
-
- // [NOCPP[
-
- private static final @Local String HTML_LOCAL = "html";
-
- // ]NOCPP]
-
- private int mode = INITIAL;
-
- private int originalMode = INITIAL;
-
- /**
- * Used only when moving back to IN_BODY.
- */
- private boolean framesetOk = true;
-
- protected Tokenizer tokenizer;
-
- // [NOCPP[
-
- protected ErrorHandler errorHandler;
-
- private DocumentModeHandler documentModeHandler;
-
- private DoctypeExpectation doctypeExpectation = DoctypeExpectation.HTML;
-
- private LocatorImpl firstCommentLocation;
-
- // ]NOCPP]
-
- private boolean scriptingEnabled = false;
-
- private boolean needToDropLF;
-
- // [NOCPP[
-
- private boolean wantingComments;
-
- // ]NOCPP]
-
- private boolean fragment;
-
- private @Local String contextName;
-
- private @NsUri String contextNamespace;
-
- private T contextNode;
-
- /**
- * Stack of template insertion modes
- */
- private @Auto int[] templateModeStack;
-
- /**
- * Current template mode stack pointer.
- */
- private int templateModePtr = -1;
-
- private @Auto StackNode<T>[] stack;
-
- private int currentPtr = -1;
-
- private @Auto StackNode<T>[] listOfActiveFormattingElements;
-
- private int listPtr = -1;
-
- private T formPointer;
-
- private T headPointer;
-
- /**
- * Used to work around Gecko limitations. Not used in Java.
- */
- private T deepTreeSurrogateParent;
-
- protected @Auto char[] charBuffer;
-
- protected int charBufferLen = 0;
-
- private boolean quirks = false;
-
- private boolean isSrcdocDocument = false;
-
- // [NOCPP[
-
- private boolean reportingDoctype = true;
-
- private XmlViolationPolicy namePolicy = XmlViolationPolicy.ALTER_INFOSET;
-
- private final Map<String, LocatorImpl> idLocations = new HashMap<String, LocatorImpl>();
-
- private boolean html4;
-
- // ]NOCPP]
-
- protected TreeBuilder() {
- fragment = false;
- }
-
- /**
- * Reports an condition that would make the infoset incompatible with XML
- * 1.0 as fatal.
- *
- * @throws SAXException
- * @throws SAXParseException
- */
- protected void fatal() throws SAXException {
- }
-
- // [NOCPP[
-
- protected final void fatal(Exception e) throws SAXException {
- SAXParseException spe = new SAXParseException(e.getMessage(),
- tokenizer, e);
- if (errorHandler != null) {
- errorHandler.fatalError(spe);
- }
- throw spe;
- }
-
- final void fatal(String s) throws SAXException {
- SAXParseException spe = new SAXParseException(s, tokenizer);
- if (errorHandler != null) {
- errorHandler.fatalError(spe);
- }
- throw spe;
- }
-
- /**
- * Reports a Parse Error.
- *
- * @param message
- * the message
- * @throws SAXException
- */
- final void err(String message) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck(message);
- }
-
- /**
- * Reports a Parse Error without checking if an error handler is present.
- *
- * @param message
- * the message
- * @throws SAXException
- */
- final void errNoCheck(String message) throws SAXException {
- SAXParseException spe = new SAXParseException(message, tokenizer);
- errorHandler.error(spe);
- }
-
- private void errListUnclosedStartTags(int eltPos) throws SAXException {
- if (currentPtr != -1) {
- for (int i = currentPtr; i > eltPos; i--) {
- reportUnclosedElementNameAndLocation(i);
- }
- }
- }
-
- /**
- * Reports the name and location of an unclosed element.
- *
- * @throws SAXException
- */
- private final void reportUnclosedElementNameAndLocation(int pos) throws SAXException {
- StackNode<T> node = stack[pos];
- if (node.isOptionalEndTag()) {
- return;
- }
- TaintableLocatorImpl locator = node.getLocator();
- if (locator.isTainted()) {
- return;
- }
- locator.markTainted();
- SAXParseException spe = new SAXParseException(
- "Unclosed element \u201C" + node.popName + "\u201D.", locator);
- errorHandler.error(spe);
- }
-
- /**
- * Reports a warning
- *
- * @param message
- * the message
- * @throws SAXException
- */
- final void warn(String message) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- SAXParseException spe = new SAXParseException(message, tokenizer);
- errorHandler.warning(spe);
- }
-
- /**
- * Reports a warning with an explicit locator
- *
- * @param message
- * the message
- * @throws SAXException
- */
- final void warn(String message, Locator locator) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- SAXParseException spe = new SAXParseException(message, locator);
- errorHandler.warning(spe);
- }
-
- // ]NOCPP]
-
- @SuppressWarnings("unchecked") public final void startTokenization(Tokenizer self) throws SAXException {
- tokenizer = self;
- stack = new StackNode[64];
- templateModeStack = new int[64];
- listOfActiveFormattingElements = new StackNode[64];
- needToDropLF = false;
- originalMode = INITIAL;
- templateModePtr = -1;
- currentPtr = -1;
- listPtr = -1;
- formPointer = null;
- headPointer = null;
- deepTreeSurrogateParent = null;
- // [NOCPP[
- html4 = false;
- idLocations.clear();
- wantingComments = wantsComments();
- firstCommentLocation = null;
- // ]NOCPP]
- start(fragment);
- charBufferLen = 0;
- charBuffer = null;
- framesetOk = true;
- if (fragment) {
- T elt;
- if (contextNode != null) {
- elt = contextNode;
- } else {
- elt = createHtmlElementSetAsRoot(tokenizer.emptyAttributes());
- }
- // When the context node is not in the HTML namespace, contrary
- // to the spec, the first node on the stack is not set to "html"
- // in the HTML namespace. Instead, it is set to a node that has
- // the characteristics of the appropriate "adjusted current node".
- // This way, there is no need to perform "adjusted current node"
- // checks during tree construction. Instead, it's sufficient to
- // just look at the current node. However, this also means that it
- // is not safe to treat "html" in the HTML namespace as a sentinel
- // that ends stack popping. Instead, stack popping loops that are
- // meant not to pop the first element on the stack need to check
- // for currentPos becoming zero.
- if (contextNamespace == "http://www.w3.org/2000/svg") {
- ElementName elementName = ElementName.SVG;
- if ("title" == contextName || "desc" == contextName
- || "foreignObject" == contextName) {
- // These elements are all alike and we don't care about
- // the exact name.
- elementName = ElementName.FOREIGNOBJECT;
- }
- // This is the SVG variant of the StackNode constructor.
- StackNode<T> node = new StackNode<T>(elementName,
- elementName.camelCaseName, elt
- // [NOCPP[
- , errorHandler == null ? null
- : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- currentPtr++;
- stack[currentPtr] = node;
- tokenizer.setStateAndEndTagExpectation(Tokenizer.DATA,
- contextName);
- // The frameset-ok flag is set even though <frameset> never
- // ends up being allowed as HTML frameset in the fragment case.
- mode = FRAMESET_OK;
- } else if (contextNamespace == "http://www.w3.org/1998/Math/MathML") {
- ElementName elementName = ElementName.MATH;
- if ("mi" == contextName || "mo" == contextName
- || "mn" == contextName || "ms" == contextName
- || "mtext" == contextName) {
- // These elements are all alike and we don't care about
- // the exact name.
- elementName = ElementName.MTEXT;
- } else if ("annotation-xml" == contextName) {
- elementName = ElementName.ANNOTATION_XML;
- // Blink does not check the encoding attribute of the
- // annotation-xml element innerHTML is being set on.
- // Let's do the same at least until
- // https://www.w3.org/Bugs/Public/show_bug.cgi?id=26783
- // is resolved.
- }
- // This is the MathML variant of the StackNode constructor.
- StackNode<T> node = new StackNode<T>(elementName, elt,
- elementName.name, false
- // [NOCPP[
- , errorHandler == null ? null
- : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- currentPtr++;
- stack[currentPtr] = node;
- tokenizer.setStateAndEndTagExpectation(Tokenizer.DATA,
- contextName);
- // The frameset-ok flag is set even though <frameset> never
- // ends up being allowed as HTML frameset in the fragment case.
- mode = FRAMESET_OK;
- } else { // html
- StackNode<T> node = new StackNode<T>(ElementName.HTML, elt
- // [NOCPP[
- , errorHandler == null ? null
- : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- currentPtr++;
- stack[currentPtr] = node;
- if ("template" == contextName) {
- pushTemplateMode(IN_TEMPLATE);
- }
- resetTheInsertionMode();
- formPointer = getFormPointerForContext(contextNode);
- if ("title" == contextName || "textarea" == contextName) {
- tokenizer.setStateAndEndTagExpectation(Tokenizer.RCDATA,
- contextName);
- } else if ("style" == contextName || "xmp" == contextName
- || "iframe" == contextName || "noembed" == contextName
- || "noframes" == contextName
- || (scriptingEnabled && "noscript" == contextName)) {
- tokenizer.setStateAndEndTagExpectation(Tokenizer.RAWTEXT,
- contextName);
- } else if ("plaintext" == contextName) {
- tokenizer.setStateAndEndTagExpectation(Tokenizer.PLAINTEXT,
- contextName);
- } else if ("script" == contextName) {
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.SCRIPT_DATA, contextName);
- } else {
- tokenizer.setStateAndEndTagExpectation(Tokenizer.DATA,
- contextName);
- }
- }
- contextName = null;
- contextNode = null;
- } else {
- mode = INITIAL;
- // If we are viewing XML source, put a foreign element permanently
- // on the stack so that cdataSectionAllowed() returns true.
- // CPPONLY: if (tokenizer.isViewingXmlSource()) {
- // CPPONLY: T elt = createElement("http://www.w3.org/2000/svg",
- // CPPONLY: "svg",
- // CPPONLY: tokenizer.emptyAttributes(), null);
- // CPPONLY: StackNode<T> node = new StackNode<T>(ElementName.SVG,
- // CPPONLY: "svg",
- // CPPONLY: elt);
- // CPPONLY: currentPtr++;
- // CPPONLY: stack[currentPtr] = node;
- // CPPONLY: }
- }
- }
-
- public final void doctype(@Local String name, String publicIdentifier,
- String systemIdentifier, boolean forceQuirks) throws SAXException {
- needToDropLF = false;
- if (!isInForeign() && mode == INITIAL) {
- // [NOCPP[
- if (reportingDoctype) {
- // ]NOCPP]
- String emptyString = Portability.newEmptyString();
- appendDoctypeToDocument(name == null ? "" : name,
- publicIdentifier == null ? emptyString
- : publicIdentifier,
- systemIdentifier == null ? emptyString
- : systemIdentifier);
- Portability.releaseString(emptyString);
- // [NOCPP[
- }
- switch (doctypeExpectation) {
- case HTML:
- // ]NOCPP]
- if (isQuirky(name, publicIdentifier, systemIdentifier,
- forceQuirks)) {
- errQuirkyDoctype();
- documentModeInternal(DocumentMode.QUIRKS_MODE,
- publicIdentifier, systemIdentifier, false);
- } else if (isAlmostStandards(publicIdentifier,
- systemIdentifier)) {
- // [NOCPP[
- if (firstCommentLocation != null) {
- warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.",
- firstCommentLocation);
- }
- // ]NOCPP]
- errAlmostStandardsDoctype();
- documentModeInternal(
- DocumentMode.ALMOST_STANDARDS_MODE,
- publicIdentifier, systemIdentifier, false);
- } else {
- // [NOCPP[
- if (firstCommentLocation != null) {
- warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.",
- firstCommentLocation);
- }
- if ((Portability.literalEqualsString(
- "-//W3C//DTD HTML 4.0//EN", publicIdentifier) && (systemIdentifier == null || Portability.literalEqualsString(
- "http://www.w3.org/TR/REC-html40/strict.dtd",
- systemIdentifier)))
- || (Portability.literalEqualsString(
- "-//W3C//DTD HTML 4.01//EN",
- publicIdentifier) && (systemIdentifier == null || Portability.literalEqualsString(
- "http://www.w3.org/TR/html4/strict.dtd",
- systemIdentifier)))
- || (Portability.literalEqualsString(
- "-//W3C//DTD XHTML 1.0 Strict//EN",
- publicIdentifier) && Portability.literalEqualsString(
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd",
- systemIdentifier))
- || (Portability.literalEqualsString(
- "-//W3C//DTD XHTML 1.1//EN",
- publicIdentifier) && Portability.literalEqualsString(
- "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd",
- systemIdentifier))
-
- ) {
- warn("Obsolete doctype. Expected \u201C<!DOCTYPE html>\u201D.");
- } else if (!((systemIdentifier == null || Portability.literalEqualsString(
- "about:legacy-compat", systemIdentifier)) && publicIdentifier == null)) {
- err("Legacy doctype. Expected \u201C<!DOCTYPE html>\u201D.");
- }
- // ]NOCPP]
- documentModeInternal(DocumentMode.STANDARDS_MODE,
- publicIdentifier, systemIdentifier, false);
- }
- // [NOCPP[
- break;
- case HTML401_STRICT:
- html4 = true;
- tokenizer.turnOnAdditionalHtml4Errors();
- if (isQuirky(name, publicIdentifier, systemIdentifier,
- forceQuirks)) {
- err("Quirky doctype. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D.");
- documentModeInternal(DocumentMode.QUIRKS_MODE,
- publicIdentifier, systemIdentifier, true);
- } else if (isAlmostStandards(publicIdentifier,
- systemIdentifier)) {
- if (firstCommentLocation != null) {
- warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.",
- firstCommentLocation);
- }
- err("Almost standards mode doctype. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D.");
- documentModeInternal(
- DocumentMode.ALMOST_STANDARDS_MODE,
- publicIdentifier, systemIdentifier, true);
- } else {
- if (firstCommentLocation != null) {
- warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.",
- firstCommentLocation);
- }
- if ("-//W3C//DTD HTML 4.01//EN".equals(publicIdentifier)) {
- if (!"http://www.w3.org/TR/html4/strict.dtd".equals(systemIdentifier)) {
- warn("The doctype did not contain the system identifier prescribed by the HTML 4.01 specification. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D.");
- }
- } else {
- err("The doctype was not the HTML 4.01 Strict doctype. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D.");
- }
- documentModeInternal(DocumentMode.STANDARDS_MODE,
- publicIdentifier, systemIdentifier, true);
- }
- break;
- case HTML401_TRANSITIONAL:
- html4 = true;
- tokenizer.turnOnAdditionalHtml4Errors();
- if (isQuirky(name, publicIdentifier, systemIdentifier,
- forceQuirks)) {
- err("Quirky doctype. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D.");
- documentModeInternal(DocumentMode.QUIRKS_MODE,
- publicIdentifier, systemIdentifier, true);
- } else if (isAlmostStandards(publicIdentifier,
- systemIdentifier)) {
- if (firstCommentLocation != null) {
- warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.",
- firstCommentLocation);
- }
- if ("-//W3C//DTD HTML 4.01 Transitional//EN".equals(publicIdentifier)
- && systemIdentifier != null) {
- if (!"http://www.w3.org/TR/html4/loose.dtd".equals(systemIdentifier)) {
- warn("The doctype did not contain the system identifier prescribed by the HTML 4.01 specification. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D.");
- }
- } else {
- err("The doctype was not a non-quirky HTML 4.01 Transitional doctype. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D.");
- }
- documentModeInternal(
- DocumentMode.ALMOST_STANDARDS_MODE,
- publicIdentifier, systemIdentifier, true);
- } else {
- if (firstCommentLocation != null) {
- warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.",
- firstCommentLocation);
- }
- err("The doctype was not the HTML 4.01 Transitional doctype. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D.");
- documentModeInternal(DocumentMode.STANDARDS_MODE,
- publicIdentifier, systemIdentifier, true);
- }
- break;
- case AUTO:
- html4 = isHtml4Doctype(publicIdentifier);
- if (html4) {
- tokenizer.turnOnAdditionalHtml4Errors();
- }
- if (isQuirky(name, publicIdentifier, systemIdentifier,
- forceQuirks)) {
- err("Quirky doctype. Expected e.g. \u201C<!DOCTYPE html>\u201D.");
- documentModeInternal(DocumentMode.QUIRKS_MODE,
- publicIdentifier, systemIdentifier, html4);
- } else if (isAlmostStandards(publicIdentifier,
- systemIdentifier)) {
- if (firstCommentLocation != null) {
- warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.",
- firstCommentLocation);
- }
- if ("-//W3C//DTD HTML 4.01 Transitional//EN".equals(publicIdentifier)) {
- if (!"http://www.w3.org/TR/html4/loose.dtd".equals(systemIdentifier)) {
- warn("The doctype did not contain the system identifier prescribed by the HTML 4.01 specification. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D.");
- }
- } else {
- err("Almost standards mode doctype. Expected e.g. \u201C<!DOCTYPE html>\u201D.");
- }
- documentModeInternal(
- DocumentMode.ALMOST_STANDARDS_MODE,
- publicIdentifier, systemIdentifier, html4);
- } else {
- if (firstCommentLocation != null) {
- warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.",
- firstCommentLocation);
- }
- if ("-//W3C//DTD HTML 4.01//EN".equals(publicIdentifier)) {
- if (!"http://www.w3.org/TR/html4/strict.dtd".equals(systemIdentifier)) {
- warn("The doctype did not contain the system identifier prescribed by the HTML 4.01 specification. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D.");
- }
- } else if ("-//W3C//DTD XHTML 1.0 Strict//EN".equals(publicIdentifier)) {
- if (!"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd".equals(systemIdentifier)) {
- warn("The doctype did not contain the system identifier prescribed by the XHTML 1.0 specification. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\u201D.");
- }
- } else if ("//W3C//DTD XHTML 1.1//EN".equals(publicIdentifier)) {
- if (!"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd".equals(systemIdentifier)) {
- warn("The doctype did not contain the system identifier prescribed by the XHTML 1.1 specification. Expected \u201C<!DOCTYPE HTML PUBLIC \"//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\u201D.");
- }
- } else if (!((systemIdentifier == null || Portability.literalEqualsString(
- "about:legacy-compat", systemIdentifier)) && publicIdentifier == null)) {
- err("Unexpected doctype. Expected, e.g., \u201C<!DOCTYPE html>\u201D.");
- }
- documentModeInternal(DocumentMode.STANDARDS_MODE,
- publicIdentifier, systemIdentifier, html4);
- }
- break;
- case NO_DOCTYPE_ERRORS:
- if (isQuirky(name, publicIdentifier, systemIdentifier,
- forceQuirks)) {
- documentModeInternal(DocumentMode.QUIRKS_MODE,
- publicIdentifier, systemIdentifier, false);
- } else if (isAlmostStandards(publicIdentifier,
- systemIdentifier)) {
- documentModeInternal(
- DocumentMode.ALMOST_STANDARDS_MODE,
- publicIdentifier, systemIdentifier, false);
- } else {
- documentModeInternal(DocumentMode.STANDARDS_MODE,
- publicIdentifier, systemIdentifier, false);
- }
- break;
- }
- // ]NOCPP]
-
- /*
- *
- * Then, switch to the root element mode of the tree construction
- * stage.
- */
- mode = BEFORE_HTML;
- return;
- }
- /*
- * A DOCTYPE token Parse error.
- */
- errStrayDoctype();
- /*
- * Ignore the token.
- */
- return;
- }
-
- // [NOCPP[
-
- private boolean isHtml4Doctype(String publicIdentifier) {
- if (publicIdentifier != null
- && (Arrays.binarySearch(TreeBuilder.HTML4_PUBLIC_IDS,
- publicIdentifier) > -1)) {
- return true;
- }
- return false;
- }
-
- // ]NOCPP]
-
- public final void comment(@NoLength char[] buf, int start, int length)
- throws SAXException {
- needToDropLF = false;
- // [NOCPP[
- if (firstCommentLocation == null) {
- firstCommentLocation = new LocatorImpl(tokenizer);
- }
- if (!wantingComments) {
- return;
- }
- // ]NOCPP]
- if (!isInForeign()) {
- switch (mode) {
- case INITIAL:
- case BEFORE_HTML:
- case AFTER_AFTER_BODY:
- case AFTER_AFTER_FRAMESET:
- /*
- * A comment token Append a Comment node to the Document
- * object with the data attribute set to the data given in
- * the comment token.
- */
- appendCommentToDocument(buf, start, length);
- return;
- case AFTER_BODY:
- /*
- * A comment token Append a Comment node to the first
- * element in the stack of open elements (the html element),
- * with the data attribute set to the data given in the
- * comment token.
- */
- flushCharacters();
- appendComment(stack[0].node, buf, start, length);
- return;
- default:
- break;
- }
- }
- /*
- * A comment token Append a Comment node to the current node with the
- * data attribute set to the data given in the comment token.
- */
- flushCharacters();
- appendComment(stack[currentPtr].node, buf, start, length);
- return;
- }
-
- /**
- * @see nu.validator.htmlparser.common.TokenHandler#characters(char[], int,
- * int)
- */
- public final void characters(@Const @NoLength char[] buf, int start, int length)
- throws SAXException {
- // Note: Can't attach error messages to EOF in C++ yet
-
- // CPPONLY: if (tokenizer.isViewingXmlSource()) {
- // CPPONLY: return;
- // CPPONLY: }
- if (needToDropLF) {
- needToDropLF = false;
- if (buf[start] == '\n') {
- start++;
- length--;
- if (length == 0) {
- return;
- }
- }
- }
-
- // optimize the most common case
- switch (mode) {
- case IN_BODY:
- case IN_CELL:
- case IN_CAPTION:
- if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
- reconstructTheActiveFormattingElements();
- }
- // fall through
- case TEXT:
- accumulateCharacters(buf, start, length);
- return;
- case IN_TABLE:
- case IN_TABLE_BODY:
- case IN_ROW:
- accumulateCharactersForced(buf, start, length);
- return;
- default:
- int end = start + length;
- charactersloop: for (int i = start; i < end; i++) {
- switch (buf[i]) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '\u000C':
- /*
- * A character token that is one of one of U+0009
- * CHARACTER TABULATION, U+000A LINE FEED (LF),
- * U+000C FORM FEED (FF), or U+0020 SPACE
- */
- switch (mode) {
- case INITIAL:
- case BEFORE_HTML:
- case BEFORE_HEAD:
- /*
- * Ignore the token.
- */
- start = i + 1;
- continue;
- case IN_HEAD:
- case IN_HEAD_NOSCRIPT:
- case AFTER_HEAD:
- case IN_COLUMN_GROUP:
- case IN_FRAMESET:
- case AFTER_FRAMESET:
- /*
- * Append the character to the current node.
- */
- continue;
- case FRAMESET_OK:
- case IN_TEMPLATE:
- case IN_BODY:
- case IN_CELL:
- case IN_CAPTION:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- start = i;
- }
-
- /*
- * Reconstruct the active formatting
- * elements, if any.
- */
- if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
- flushCharacters();
- reconstructTheActiveFormattingElements();
- }
- /*
- * Append the token's character to the
- * current node.
- */
- break charactersloop;
- case IN_SELECT:
- case IN_SELECT_IN_TABLE:
- break charactersloop;
- case IN_TABLE:
- case IN_TABLE_BODY:
- case IN_ROW:
- accumulateCharactersForced(buf, i, 1);
- start = i + 1;
- continue;
- case AFTER_BODY:
- case AFTER_AFTER_BODY:
- case AFTER_AFTER_FRAMESET:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- start = i;
- }
- /*
- * Reconstruct the active formatting
- * elements, if any.
- */
- flushCharacters();
- reconstructTheActiveFormattingElements();
- /*
- * Append the token's character to the
- * current node.
- */
- continue;
- }
- default:
- /*
- * A character token that is not one of one of
- * U+0009 CHARACTER TABULATION, U+000A LINE FEED
- * (LF), U+000C FORM FEED (FF), or U+0020 SPACE
- */
- switch (mode) {
- case INITIAL:
- /*
- * Parse error.
- */
- // [NOCPP[
- switch (doctypeExpectation) {
- case AUTO:
- err("Non-space characters found without seeing a doctype first. Expected e.g. \u201C<!DOCTYPE html>\u201D.");
- break;
- case HTML:
- // XXX figure out a way to report this in the Gecko View Source case
- err("Non-space characters found without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D.");
- break;
- case HTML401_STRICT:
- err("Non-space characters found without seeing a doctype first. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D.");
- break;
- case HTML401_TRANSITIONAL:
- err("Non-space characters found without seeing a doctype first. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D.");
- break;
- case NO_DOCTYPE_ERRORS:
- }
- // ]NOCPP]
- /*
- *
- * Set the document to quirks mode.
- */
- documentModeInternal(
- DocumentMode.QUIRKS_MODE, null,
- null, false);
- /*
- * Then, switch to the root element mode of
- * the tree construction stage
- */
- mode = BEFORE_HTML;
- /*
- * and reprocess the current token.
- */
- i--;
- continue;
- case BEFORE_HTML:
- /*
- * Create an HTMLElement node with the tag
- * name html, in the HTML namespace. Append
- * it to the Document object.
- */
- // No need to flush characters here,
- // because there's nothing to flush.
- appendHtmlElementToDocumentAndPush();
- /* Switch to the main mode */
- mode = BEFORE_HEAD;
- /*
- * reprocess the current token.
- */
- i--;
- continue;
- case BEFORE_HEAD:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- start = i;
- }
- /*
- * /Act as if a start tag token with the tag
- * name "head" and no attributes had been
- * seen,
- */
- flushCharacters();
- appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES);
- mode = IN_HEAD;
- /*
- * then reprocess the current token.
- *
- * This will result in an empty head element
- * being generated, with the current token
- * being reprocessed in the "after head"
- * insertion mode.
- */
- i--;
- continue;
- case IN_HEAD:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- start = i;
- }
- /*
- * Act as if an end tag token with the tag
- * name "head" had been seen,
- */
- flushCharacters();
- pop();
- mode = AFTER_HEAD;
- /*
- * and reprocess the current token.
- */
- i--;
- continue;
- case IN_HEAD_NOSCRIPT:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- start = i;
- }
- /*
- * Parse error. Act as if an end tag with
- * the tag name "noscript" had been seen
- */
- errNonSpaceInNoscriptInHead();
- flushCharacters();
- pop();
- mode = IN_HEAD;
- /*
- * and reprocess the current token.
- */
- i--;
- continue;
- case AFTER_HEAD:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- start = i;
- }
- /*
- * Act as if a start tag token with the tag
- * name "body" and no attributes had been
- * seen,
- */
- flushCharacters();
- appendToCurrentNodeAndPushBodyElement();
- mode = FRAMESET_OK;
- /*
- * and then reprocess the current token.
- */
- i--;
- continue;
- case FRAMESET_OK:
- framesetOk = false;
- mode = IN_BODY;
- i--;
- continue;
- case IN_TEMPLATE:
- case IN_BODY:
- case IN_CELL:
- case IN_CAPTION:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- start = i;
- }
- /*
- * Reconstruct the active formatting
- * elements, if any.
- */
- if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
- flushCharacters();
- reconstructTheActiveFormattingElements();
- }
- /*
- * Append the token's character to the
- * current node.
- */
- break charactersloop;
- case IN_TABLE:
- case IN_TABLE_BODY:
- case IN_ROW:
- accumulateCharactersForced(buf, i, 1);
- start = i + 1;
- continue;
- case IN_COLUMN_GROUP:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- start = i;
- }
- /*
- * Act as if an end tag with the tag name
- * "colgroup" had been seen, and then, if
- * that token wasn't ignored, reprocess the
- * current token.
- */
- if (currentPtr == 0 || stack[currentPtr].getGroup() ==
- TreeBuilder.TEMPLATE) {
- errNonSpaceInColgroupInFragment();
- start = i + 1;
- continue;
- }
- flushCharacters();
- pop();
- mode = IN_TABLE;
- i--;
- continue;
- case IN_SELECT:
- case IN_SELECT_IN_TABLE:
- break charactersloop;
- case AFTER_BODY:
- errNonSpaceAfterBody();
- fatal();
- mode = framesetOk ? FRAMESET_OK : IN_BODY;
- i--;
- continue;
- case IN_FRAMESET:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- // start index is adjusted below.
- }
- /*
- * Parse error.
- */
- errNonSpaceInFrameset();
- /*
- * Ignore the token.
- */
- start = i + 1;
- continue;
- case AFTER_FRAMESET:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- // start index is adjusted below.
- }
- /*
- * Parse error.
- */
- errNonSpaceAfterFrameset();
- /*
- * Ignore the token.
- */
- start = i + 1;
- continue;
- case AFTER_AFTER_BODY:
- /*
- * Parse error.
- */
- errNonSpaceInTrailer();
- /*
- * Switch back to the main mode and
- * reprocess the token.
- */
- mode = framesetOk ? FRAMESET_OK : IN_BODY;
- i--;
- continue;
- case AFTER_AFTER_FRAMESET:
- if (start < i) {
- accumulateCharacters(buf, start, i
- - start);
- // start index is adjusted below.
- }
- /*
- * Parse error.
- */
- errNonSpaceInTrailer();
- /*
- * Ignore the token.
- */
- start = i + 1;
- continue;
- }
- }
- }
- if (start < end) {
- accumulateCharacters(buf, start, end - start);
- }
- }
- }
-
- /**
- * @see nu.validator.htmlparser.common.TokenHandler#zeroOriginatingReplacementCharacter()
- */
- public void zeroOriginatingReplacementCharacter() throws SAXException {
- if (mode == TEXT) {
- accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
- return;
- }
- if (currentPtr >= 0) {
- if (isSpecialParentInForeign(stack[currentPtr])) {
- return;
- }
- accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
- }
- }
-
- public final void eof() throws SAXException {
- flushCharacters();
- // Note: Can't attach error messages to EOF in C++ yet
- eofloop: for (;;) {
- switch (mode) {
- case INITIAL:
- /*
- * Parse error.
- */
- // [NOCPP[
- switch (doctypeExpectation) {
- case AUTO:
- err("End of file seen without seeing a doctype first. Expected e.g. \u201C<!DOCTYPE html>\u201D.");
- break;
- case HTML:
- err("End of file seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D.");
- break;
- case HTML401_STRICT:
- err("End of file seen without seeing a doctype first. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D.");
- break;
- case HTML401_TRANSITIONAL:
- err("End of file seen without seeing a doctype first. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D.");
- break;
- case NO_DOCTYPE_ERRORS:
- }
- // ]NOCPP]
- /*
- *
- * Set the document to quirks mode.
- */
- documentModeInternal(DocumentMode.QUIRKS_MODE, null, null,
- false);
- /*
- * Then, switch to the root element mode of the tree
- * construction stage
- */
- mode = BEFORE_HTML;
- /*
- * and reprocess the current token.
- */
- continue;
- case BEFORE_HTML:
- /*
- * Create an HTMLElement node with the tag name html, in the
- * HTML namespace. Append it to the Document object.
- */
- appendHtmlElementToDocumentAndPush();
- // XXX application cache manifest
- /* Switch to the main mode */
- mode = BEFORE_HEAD;
- /*
- * reprocess the current token.
- */
- continue;
- case BEFORE_HEAD:
- appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES);
- mode = IN_HEAD;
- continue;
- case IN_HEAD:
- // [NOCPP[
- if (errorHandler != null && currentPtr > 1) {
- errEofWithUnclosedElements();
- }
- // ]NOCPP]
- while (currentPtr > 0) {
- popOnEof();
- }
- mode = AFTER_HEAD;
- continue;
- case IN_HEAD_NOSCRIPT:
- // [NOCPP[
- errEofWithUnclosedElements();
- // ]NOCPP]
- while (currentPtr > 1) {
- popOnEof();
- }
- mode = IN_HEAD;
- continue;
- case AFTER_HEAD:
- appendToCurrentNodeAndPushBodyElement();
- mode = IN_BODY;
- continue;
- case IN_TABLE_BODY:
- case IN_ROW:
- case IN_TABLE:
- case IN_SELECT_IN_TABLE:
- case IN_SELECT:
- case IN_COLUMN_GROUP:
- case FRAMESET_OK:
- case IN_CAPTION:
- case IN_CELL:
- case IN_BODY:
- // [NOCPP[
- // i > 0 to stop in time in the foreign fragment case.
- openelementloop: for (int i = currentPtr; i > 0; i--) {
- int group = stack[i].getGroup();
- switch (group) {
- case DD_OR_DT:
- case LI:
- case P:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TD_OR_TH:
- case BODY:
- case HTML:
- break;
- default:
- errEofWithUnclosedElements();
- break openelementloop;
- }
- }
- // ]NOCPP]
-
- if (isTemplateModeStackEmpty()) {
- break eofloop;
- }
-
- // fall through to IN_TEMPLATE
- case IN_TEMPLATE:
- int eltPos = findLast("template");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- assert fragment;
- break eofloop;
- }
- if (errorHandler != null) {
- errUnclosedElements(eltPos, "template");
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- clearTheListOfActiveFormattingElementsUpToTheLastMarker();
- popTemplateMode();
- resetTheInsertionMode();
-
- // Reprocess token.
- continue;
- case TEXT:
- // [NOCPP[
- if (errorHandler != null) {
- errNoCheck("End of file seen when expecting text or an end tag.");
- errListUnclosedStartTags(0);
- }
- // ]NOCPP]
- // XXX mark script as already executed
- if (originalMode == AFTER_HEAD) {
- popOnEof();
- }
- popOnEof();
- mode = originalMode;
- continue;
- case IN_FRAMESET:
- // [NOCPP[
- if (errorHandler != null && currentPtr > 0) {
- errEofWithUnclosedElements();
- }
- // ]NOCPP]
- break eofloop;
- case AFTER_BODY:
- case AFTER_FRAMESET:
- case AFTER_AFTER_BODY:
- case AFTER_AFTER_FRAMESET:
- default:
- // [NOCPP[
- if (currentPtr == 0) { // This silliness is here to poison
- // buggy compiler optimizations in
- // GWT
- System.currentTimeMillis();
- }
- // ]NOCPP]
- break eofloop;
- }
- }
- while (currentPtr > 0) {
- popOnEof();
- }
- if (!fragment) {
- popOnEof();
- }
- /* Stop parsing. */
- }
-
- /**
- * @see nu.validator.htmlparser.common.TokenHandler#endTokenization()
- */
- public final void endTokenization() throws SAXException {
- formPointer = null;
- headPointer = null;
- deepTreeSurrogateParent = null;
- templateModeStack = null;
- if (stack != null) {
- while (currentPtr > -1) {
- stack[currentPtr].release();
- currentPtr--;
- }
- stack = null;
- }
- if (listOfActiveFormattingElements != null) {
- while (listPtr > -1) {
- if (listOfActiveFormattingElements[listPtr] != null) {
- listOfActiveFormattingElements[listPtr].release();
- }
- listPtr--;
- }
- listOfActiveFormattingElements = null;
- }
- // [NOCPP[
- idLocations.clear();
- // ]NOCPP]
- charBuffer = null;
- end();
- }
-
- public final void startTag(ElementName elementName,
- HtmlAttributes attributes, boolean selfClosing) throws SAXException {
- flushCharacters();
-
- // [NOCPP[
- if (errorHandler != null) {
- // ID uniqueness
- @IdType String id = attributes.getId();
- if (id != null) {
- LocatorImpl oldLoc = idLocations.get(id);
- if (oldLoc != null) {
- err("Duplicate ID \u201C" + id + "\u201D.");
- errorHandler.warning(new SAXParseException(
- "The first occurrence of ID \u201C" + id
- + "\u201D was here.", oldLoc));
- } else {
- idLocations.put(id, new LocatorImpl(tokenizer));
- }
- }
- }
- // ]NOCPP]
-
- int eltPos;
- needToDropLF = false;
- starttagloop: for (;;) {
- int group = elementName.getGroup();
- @Local String name = elementName.name;
- if (isInForeign()) {
- StackNode<T> currentNode = stack[currentPtr];
- @NsUri String currNs = currentNode.ns;
- if (!(currentNode.isHtmlIntegrationPoint() || (currNs == "http://www.w3.org/1998/Math/MathML" && ((currentNode.getGroup() == MI_MO_MN_MS_MTEXT && group != MGLYPH_OR_MALIGNMARK) || (currentNode.getGroup() == ANNOTATION_XML && group == SVG))))) {
- switch (group) {
- case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
- case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
- case BODY:
- case BR:
- case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
- case DD_OR_DT:
- case UL_OR_OL_OR_DL:
- case EMBED:
- case IMG:
- case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
- case HEAD:
- case HR:
- case LI:
- case META:
- case NOBR:
- case P:
- case PRE_OR_LISTING:
- case TABLE:
- case FONT:
- // re-check FONT to deal with the special case
- if (!(group == FONT && !(attributes.contains(AttributeName.COLOR)
- || attributes.contains(AttributeName.FACE) || attributes.contains(AttributeName.SIZE)))) {
- errHtmlStartTagInForeignContext(name);
- if (!fragment) {
- while (!isSpecialParentInForeign(stack[currentPtr])) {
- pop();
- }
- continue starttagloop;
- } // else fall thru
- }
- // else fall thru
- default:
- if ("http://www.w3.org/2000/svg" == currNs) {
- attributes.adjustForSvg();
- if (selfClosing) {
- appendVoidElementToCurrentMayFosterSVG(
- elementName, attributes);
- selfClosing = false;
- } else {
- appendToCurrentNodeAndPushElementMayFosterSVG(
- elementName, attributes);
- }
- attributes = null; // CPP
- break starttagloop;
- } else {
- attributes.adjustForMath();
- if (selfClosing) {
- appendVoidElementToCurrentMayFosterMathML(
- elementName, attributes);
- selfClosing = false;
- } else {
- appendToCurrentNodeAndPushElementMayFosterMathML(
- elementName, attributes);
- }
- attributes = null; // CPP
- break starttagloop;
- }
- } // switch
- } // foreignObject / annotation-xml
- }
- switch (mode) {
- case IN_TEMPLATE:
- switch (group) {
- case COL:
- popTemplateMode();
- pushTemplateMode(IN_COLUMN_GROUP);
- mode = IN_COLUMN_GROUP;
- // Reprocess token.
- continue;
- case CAPTION:
- case COLGROUP:
- case TBODY_OR_THEAD_OR_TFOOT:
- popTemplateMode();
- pushTemplateMode(IN_TABLE);
- mode = IN_TABLE;
- // Reprocess token.
- continue;
- case TR:
- popTemplateMode();
- pushTemplateMode(IN_TABLE_BODY);
- mode = IN_TABLE_BODY;
- // Reprocess token.
- continue;
- case TD_OR_TH:
- popTemplateMode();
- pushTemplateMode(IN_ROW);
- mode = IN_ROW;
- // Reprocess token.
- continue;
- case META:
- checkMetaCharset(attributes);
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case TITLE:
- startTagTitleInHead(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- case BASE:
- case LINK_OR_BASEFONT_OR_BGSOUND:
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case SCRIPT:
- startTagScriptInHead(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- case NOFRAMES:
- case STYLE:
- startTagGenericRawText(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- case TEMPLATE:
- startTagTemplateInHead(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- default:
- popTemplateMode();
- pushTemplateMode(IN_BODY);
- mode = IN_BODY;
- // Reprocess token.
- continue;
- }
- case IN_ROW:
- switch (group) {
- case TD_OR_TH:
- clearStackBackTo(findLastOrRoot(TreeBuilder.TR));
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- mode = IN_CELL;
- insertMarker();
- attributes = null; // CPP
- break starttagloop;
- case CAPTION:
- case COL:
- case COLGROUP:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TR:
- eltPos = findLastOrRoot(TreeBuilder.TR);
- if (eltPos == 0) {
- assert fragment || isTemplateContents();
- errNoTableRowToClose();
- break starttagloop;
- }
- clearStackBackTo(eltPos);
- pop();
- mode = IN_TABLE_BODY;
- continue;
- default:
- // fall through to IN_TABLE
- }
- case IN_TABLE_BODY:
- switch (group) {
- case TR:
- clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- mode = IN_ROW;
- attributes = null; // CPP
- break starttagloop;
- case TD_OR_TH:
- errStartTagInTableBody(name);
- clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
- appendToCurrentNodeAndPushElement(
- ElementName.TR,
- HtmlAttributes.EMPTY_ATTRIBUTES);
- mode = IN_ROW;
- continue;
- case CAPTION:
- case COL:
- case COLGROUP:
- case TBODY_OR_THEAD_OR_TFOOT:
- eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
- if (eltPos == 0 || stack[eltPos].getGroup() == TEMPLATE) {
- assert fragment || isTemplateContents();
- errStrayStartTag(name);
- break starttagloop;
- } else {
- clearStackBackTo(eltPos);
- pop();
- mode = IN_TABLE;
- continue;
- }
- default:
- // fall through to IN_TABLE
- }
- case IN_TABLE:
- intableloop: for (;;) {
- switch (group) {
- case CAPTION:
- clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
- insertMarker();
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- mode = IN_CAPTION;
- attributes = null; // CPP
- break starttagloop;
- case COLGROUP:
- clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- mode = IN_COLUMN_GROUP;
- attributes = null; // CPP
- break starttagloop;
- case COL:
- clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
- appendToCurrentNodeAndPushElement(
- ElementName.COLGROUP,
- HtmlAttributes.EMPTY_ATTRIBUTES);
- mode = IN_COLUMN_GROUP;
- continue starttagloop;
- case TBODY_OR_THEAD_OR_TFOOT:
- clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- mode = IN_TABLE_BODY;
- attributes = null; // CPP
- break starttagloop;
- case TR:
- case TD_OR_TH:
- clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
- appendToCurrentNodeAndPushElement(
- ElementName.TBODY,
- HtmlAttributes.EMPTY_ATTRIBUTES);
- mode = IN_TABLE_BODY;
- continue starttagloop;
- case TEMPLATE:
- // fall through to IN_HEAD
- break intableloop;
- case TABLE:
- errTableSeenWhileTableOpen();
- eltPos = findLastInTableScope(name);
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- assert fragment || isTemplateContents();
- break starttagloop;
- }
- generateImpliedEndTags();
- if (errorHandler != null && !isCurrent("table")) {
- errNoCheckUnclosedElementsOnStack();
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- resetTheInsertionMode();
- continue starttagloop;
- case SCRIPT:
- // XXX need to manage much more stuff
- // here if
- // supporting
- // document.write()
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.SCRIPT_DATA, elementName);
- attributes = null; // CPP
- break starttagloop;
- case STYLE:
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.RAWTEXT, elementName);
- attributes = null; // CPP
- break starttagloop;
- case INPUT:
- errStartTagInTable(name);
- if (!Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "hidden",
- attributes.getValue(AttributeName.TYPE))) {
- break intableloop;
- }
- appendVoidElementToCurrent(
- name, attributes,
- formPointer);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case FORM:
- if (formPointer != null || isTemplateContents()) {
- errFormWhenFormOpen();
- break starttagloop;
- } else {
- errStartTagInTable(name);
- appendVoidFormToCurrent(attributes);
- attributes = null; // CPP
- break starttagloop;
- }
- default:
- errStartTagInTable(name);
- // fall through to IN_BODY
- break intableloop;
- }
- }
- case IN_CAPTION:
- switch (group) {
- case CAPTION:
- case COL:
- case COLGROUP:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TR:
- case TD_OR_TH:
- errStrayStartTag(name);
- eltPos = findLastInTableScope("caption");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- break starttagloop;
- }
- generateImpliedEndTags();
- if (errorHandler != null && currentPtr != eltPos) {
- errNoCheckUnclosedElementsOnStack();
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- clearTheListOfActiveFormattingElementsUpToTheLastMarker();
- mode = IN_TABLE;
- continue;
- default:
- // fall through to IN_BODY
- }
- case IN_CELL:
- switch (group) {
- case CAPTION:
- case COL:
- case COLGROUP:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TR:
- case TD_OR_TH:
- eltPos = findLastInTableScopeTdTh();
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errNoCellToClose();
- break starttagloop;
- } else {
- closeTheCell(eltPos);
- continue;
- }
- default:
- // fall through to IN_BODY
- }
- case FRAMESET_OK:
- switch (group) {
- case FRAMESET:
- if (mode == FRAMESET_OK) {
- if (currentPtr == 0 || stack[1].getGroup() != BODY) {
- assert fragment || isTemplateContents();
- errStrayStartTag(name);
- break starttagloop;
- } else {
- errFramesetStart();
- detachFromParent(stack[1].node);
- while (currentPtr > 0) {
- pop();
- }
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- mode = IN_FRAMESET;
- attributes = null; // CPP
- break starttagloop;
- }
- } else {
- errStrayStartTag(name);
- break starttagloop;
- }
- // NOT falling through!
- case PRE_OR_LISTING:
- case LI:
- case DD_OR_DT:
- case BUTTON:
- case MARQUEE_OR_APPLET:
- case OBJECT:
- case TABLE:
- case AREA_OR_WBR:
- case BR:
- case EMBED:
- case IMG:
- case INPUT:
- case KEYGEN:
- case HR:
- case TEXTAREA:
- case XMP:
- case IFRAME:
- case SELECT:
- if (mode == FRAMESET_OK
- && !(group == INPUT && Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "hidden",
- attributes.getValue(AttributeName.TYPE)))) {
- framesetOk = false;
- mode = IN_BODY;
- }
- // fall through to IN_BODY
- default:
- // fall through to IN_BODY
- }
- case IN_BODY:
- inbodyloop: for (;;) {
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- case BASE:
- case LINK_OR_BASEFONT_OR_BGSOUND:
- case META:
- case STYLE:
- case SCRIPT:
- case TITLE:
- case TEMPLATE:
- // Fall through to IN_HEAD
- break inbodyloop;
- case BODY:
- if (currentPtr == 0 || stack[1].getGroup() != BODY || isTemplateContents()) {
- assert fragment || isTemplateContents();
- errStrayStartTag(name);
- break starttagloop;
- }
- errFooSeenWhenFooOpen(name);
- framesetOk = false;
- if (mode == FRAMESET_OK) {
- mode = IN_BODY;
- }
- if (addAttributesToBody(attributes)) {
- attributes = null; // CPP
- }
- break starttagloop;
- case P:
- case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
- case UL_OR_OL_OR_DL:
- case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY:
- implicitlyCloseP();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
- implicitlyCloseP();
- if (stack[currentPtr].getGroup() == H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
- errHeadingWhenHeadingOpen();
- pop();
- }
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case FIELDSET:
- implicitlyCloseP();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes, formPointer);
- attributes = null; // CPP
- break starttagloop;
- case PRE_OR_LISTING:
- implicitlyCloseP();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- needToDropLF = true;
- attributes = null; // CPP
- break starttagloop;
- case FORM:
- if (formPointer != null && !isTemplateContents()) {
- errFormWhenFormOpen();
- break starttagloop;
- } else {
- implicitlyCloseP();
- appendToCurrentNodeAndPushFormElementMayFoster(attributes);
- attributes = null; // CPP
- break starttagloop;
- }
- case LI:
- case DD_OR_DT:
- eltPos = currentPtr;
- for (;;) {
- StackNode<T> node = stack[eltPos]; // weak
- // ref
- if (node.getGroup() == group) { // LI or
- // DD_OR_DT
- generateImpliedEndTagsExceptFor(node.name);
- if (errorHandler != null
- && eltPos != currentPtr) {
- errUnclosedElementsImplied(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- break;
- } else if (eltPos == 0 || (node.isSpecial()
- && (node.ns != "http://www.w3.org/1999/xhtml"
- || (node.name != "p"
- && node.name != "address"
- && node.name != "div")))) {
- break;
- }
- eltPos--;
- }
- implicitlyCloseP();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case PLAINTEXT:
- implicitlyCloseP();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.PLAINTEXT, elementName);
- attributes = null; // CPP
- break starttagloop;
- case A:
- int activeAPos = findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker("a");
- if (activeAPos != -1) {
- errFooSeenWhenFooOpen(name);
- StackNode<T> activeA = listOfActiveFormattingElements[activeAPos];
- activeA.retain();
- adoptionAgencyEndTag("a");
- removeFromStack(activeA);
- activeAPos = findInListOfActiveFormattingElements(activeA);
- if (activeAPos != -1) {
- removeFromListOfActiveFormattingElements(activeAPos);
- }
- activeA.release();
- }
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushFormattingElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
- case FONT:
- reconstructTheActiveFormattingElements();
- maybeForgetEarlierDuplicateFormattingElement(elementName.name, attributes);
- appendToCurrentNodeAndPushFormattingElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case NOBR:
- reconstructTheActiveFormattingElements();
- if (TreeBuilder.NOT_FOUND_ON_STACK != findLastInScope("nobr")) {
- errFooSeenWhenFooOpen(name);
- adoptionAgencyEndTag("nobr");
- reconstructTheActiveFormattingElements();
- }
- appendToCurrentNodeAndPushFormattingElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case BUTTON:
- eltPos = findLastInScope(name);
- if (eltPos != TreeBuilder.NOT_FOUND_ON_STACK) {
- errFooSeenWhenFooOpen(name);
- generateImpliedEndTags();
- if (errorHandler != null
- && !isCurrent(name)) {
- errUnclosedElementsImplied(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- continue starttagloop;
- } else {
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes, formPointer);
- attributes = null; // CPP
- break starttagloop;
- }
- case OBJECT:
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes, formPointer);
- insertMarker();
- attributes = null; // CPP
- break starttagloop;
- case MARQUEE_OR_APPLET:
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- insertMarker();
- attributes = null; // CPP
- break starttagloop;
- case TABLE:
- // The only quirk. Blame Hixie and
- // Acid2.
- if (!quirks) {
- implicitlyCloseP();
- }
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- mode = IN_TABLE;
- attributes = null; // CPP
- break starttagloop;
- case BR:
- case EMBED:
- case AREA_OR_WBR:
- reconstructTheActiveFormattingElements();
- // FALL THROUGH to PARAM_OR_SOURCE_OR_TRACK
- // CPPONLY: case MENUITEM:
- case PARAM_OR_SOURCE_OR_TRACK:
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case HR:
- implicitlyCloseP();
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case IMAGE:
- errImage();
- elementName = ElementName.IMG;
- continue starttagloop;
- case IMG:
- case KEYGEN:
- case INPUT:
- reconstructTheActiveFormattingElements();
- appendVoidElementToCurrentMayFoster(
- name, attributes,
- formPointer);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case ISINDEX:
- errIsindex();
- if (formPointer != null && !isTemplateContents()) {
- break starttagloop;
- }
- implicitlyCloseP();
- HtmlAttributes formAttrs = new HtmlAttributes(0);
- int actionIndex = attributes.getIndex(AttributeName.ACTION);
- if (actionIndex > -1) {
- formAttrs.addAttribute(
- AttributeName.ACTION,
- attributes.getValueNoBoundsCheck(actionIndex)
- // [NOCPP[
- , XmlViolationPolicy.ALLOW
- // ]NOCPP]
- // CPPONLY: , attributes.getLineNoBoundsCheck(actionIndex)
- );
- }
- appendToCurrentNodeAndPushFormElementMayFoster(formAttrs);
- appendVoidElementToCurrentMayFoster(
- ElementName.HR,
- HtmlAttributes.EMPTY_ATTRIBUTES);
- appendToCurrentNodeAndPushElementMayFoster(
- ElementName.LABEL,
- HtmlAttributes.EMPTY_ATTRIBUTES);
- int promptIndex = attributes.getIndex(AttributeName.PROMPT);
- if (promptIndex > -1) {
- @Auto char[] prompt = Portability.newCharArrayFromString(attributes.getValueNoBoundsCheck(promptIndex));
- appendCharacters(stack[currentPtr].node,
- prompt, 0, prompt.length);
- } else {
- appendIsindexPrompt(stack[currentPtr].node);
- }
- HtmlAttributes inputAttributes = new HtmlAttributes(
- 0);
- inputAttributes.addAttribute(
- AttributeName.NAME,
- Portability.newStringFromLiteral("isindex")
- // [NOCPP[
- , XmlViolationPolicy.ALLOW
- // ]NOCPP]
- // CPPONLY: , tokenizer.getLineNumber()
- );
- for (int i = 0; i < attributes.getLength(); i++) {
- AttributeName attributeQName = attributes.getAttributeNameNoBoundsCheck(i);
- if (AttributeName.NAME == attributeQName
- || AttributeName.PROMPT == attributeQName) {
- attributes.releaseValue(i);
- } else if (AttributeName.ACTION != attributeQName) {
- inputAttributes.addAttribute(
- attributeQName,
- attributes.getValueNoBoundsCheck(i)
- // [NOCPP[
- , XmlViolationPolicy.ALLOW
- // ]NOCPP]
- // CPPONLY: , attributes.getLineNoBoundsCheck(i)
- );
- }
- }
- attributes.clearWithoutReleasingContents();
- appendVoidElementToCurrentMayFoster(
- "input",
- inputAttributes, formPointer);
- pop(); // label
- appendVoidElementToCurrentMayFoster(
- ElementName.HR,
- HtmlAttributes.EMPTY_ATTRIBUTES);
- pop(); // form
-
- if (!isTemplateContents()) {
- formPointer = null;
- }
-
- selfClosing = false;
- // Portability.delete(formAttrs);
- // Portability.delete(inputAttributes);
- // Don't delete attributes, they are deleted
- // later
- break starttagloop;
- case TEXTAREA:
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes, formPointer);
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.RCDATA, elementName);
- originalMode = mode;
- mode = TEXT;
- needToDropLF = true;
- attributes = null; // CPP
- break starttagloop;
- case XMP:
- implicitlyCloseP();
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.RAWTEXT, elementName);
- attributes = null; // CPP
- break starttagloop;
- case NOSCRIPT:
- if (!scriptingEnabled) {
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- } else {
- // fall through
- }
- case NOFRAMES:
- case IFRAME:
- case NOEMBED:
- startTagGenericRawText(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- case SELECT:
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes, formPointer);
- switch (mode) {
- case IN_TABLE:
- case IN_CAPTION:
- case IN_COLUMN_GROUP:
- case IN_TABLE_BODY:
- case IN_ROW:
- case IN_CELL:
- mode = IN_SELECT_IN_TABLE;
- break;
- default:
- mode = IN_SELECT;
- break;
- }
- attributes = null; // CPP
- break starttagloop;
- case OPTGROUP:
- case OPTION:
- if (isCurrent("option")) {
- pop();
- }
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case RB_OR_RTC:
- eltPos = findLastInScope("ruby");
- if (eltPos != NOT_FOUND_ON_STACK) {
- generateImpliedEndTags();
- }
- if (eltPos != currentPtr) {
- if (eltPos == NOT_FOUND_ON_STACK) {
- errStartTagSeenWithoutRuby(name);
- } else {
- errUnclosedChildrenInRuby();
- }
- }
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case RT_OR_RP:
- eltPos = findLastInScope("ruby");
- if (eltPos != NOT_FOUND_ON_STACK) {
- generateImpliedEndTagsExceptFor("rtc");
- }
- if (eltPos != currentPtr) {
- if (!isCurrent("rtc")) {
- if (eltPos == NOT_FOUND_ON_STACK) {
- errStartTagSeenWithoutRuby(name);
- } else {
- errUnclosedChildrenInRuby();
- }
- }
- }
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case MATH:
- reconstructTheActiveFormattingElements();
- attributes.adjustForMath();
- if (selfClosing) {
- appendVoidElementToCurrentMayFosterMathML(
- elementName, attributes);
- selfClosing = false;
- } else {
- appendToCurrentNodeAndPushElementMayFosterMathML(
- elementName, attributes);
- }
- attributes = null; // CPP
- break starttagloop;
- case SVG:
- reconstructTheActiveFormattingElements();
- attributes.adjustForSvg();
- if (selfClosing) {
- appendVoidElementToCurrentMayFosterSVG(
- elementName,
- attributes);
- selfClosing = false;
- } else {
- appendToCurrentNodeAndPushElementMayFosterSVG(
- elementName, attributes);
- }
- attributes = null; // CPP
- break starttagloop;
- case CAPTION:
- case COL:
- case COLGROUP:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TR:
- case TD_OR_TH:
- case FRAME:
- case FRAMESET:
- case HEAD:
- errStrayStartTag(name);
- break starttagloop;
- case OUTPUT:
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes, formPointer);
- attributes = null; // CPP
- break starttagloop;
- default:
- reconstructTheActiveFormattingElements();
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- }
- }
- case IN_HEAD:
- inheadloop: for (;;) {
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- case BASE:
- case LINK_OR_BASEFONT_OR_BGSOUND:
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case META:
- // Fall through to IN_HEAD_NOSCRIPT
- break inheadloop;
- case TITLE:
- startTagTitleInHead(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- case NOSCRIPT:
- if (scriptingEnabled) {
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.RAWTEXT, elementName);
- } else {
- appendToCurrentNodeAndPushElementMayFoster(
- elementName,
- attributes);
- mode = IN_HEAD_NOSCRIPT;
- }
- attributes = null; // CPP
- break starttagloop;
- case SCRIPT:
- startTagScriptInHead(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- case STYLE:
- case NOFRAMES:
- startTagGenericRawText(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- case HEAD:
- /* Parse error. */
- errFooSeenWhenFooOpen(name);
- /* Ignore the token. */
- break starttagloop;
- case TEMPLATE:
- startTagTemplateInHead(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- default:
- pop();
- mode = AFTER_HEAD;
- continue starttagloop;
- }
- }
- case IN_HEAD_NOSCRIPT:
- switch (group) {
- case HTML:
- // XXX did Hixie really mean to omit "base"
- // here?
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- case LINK_OR_BASEFONT_OR_BGSOUND:
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case META:
- checkMetaCharset(attributes);
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case STYLE:
- case NOFRAMES:
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.RAWTEXT, elementName);
- attributes = null; // CPP
- break starttagloop;
- case HEAD:
- errFooSeenWhenFooOpen(name);
- break starttagloop;
- case NOSCRIPT:
- errFooSeenWhenFooOpen(name);
- break starttagloop;
- default:
- errBadStartTagInHead(name);
- pop();
- mode = IN_HEAD;
- continue;
- }
- case IN_COLUMN_GROUP:
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- case COL:
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- case TEMPLATE:
- startTagTemplateInHead(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- default:
- if (currentPtr == 0 || stack[currentPtr].getGroup() == TEMPLATE) {
- assert fragment || isTemplateContents();
- errGarbageInColgroup();
- break starttagloop;
- }
- pop();
- mode = IN_TABLE;
- continue;
- }
- case IN_SELECT_IN_TABLE:
- switch (group) {
- case CAPTION:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TR:
- case TD_OR_TH:
- case TABLE:
- errStartTagWithSelectOpen(name);
- eltPos = findLastInTableScope("select");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- assert fragment;
- break starttagloop; // http://www.w3.org/Bugs/Public/show_bug.cgi?id=8375
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- resetTheInsertionMode();
- continue;
- default:
- // fall through to IN_SELECT
- }
- case IN_SELECT:
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- case OPTION:
- if (isCurrent("option")) {
- pop();
- }
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case OPTGROUP:
- if (isCurrent("option")) {
- pop();
- }
- if (isCurrent("optgroup")) {
- pop();
- }
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case SELECT:
- errStartSelectWhereEndSelectExpected();
- eltPos = findLastInTableScope(name);
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- assert fragment;
- errNoSelectInTableScope();
- break starttagloop;
- } else {
- while (currentPtr >= eltPos) {
- pop();
- }
- resetTheInsertionMode();
- break starttagloop;
- }
- case INPUT:
- case TEXTAREA:
- case KEYGEN:
- errStartTagWithSelectOpen(name);
- eltPos = findLastInTableScope("select");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- assert fragment;
- break starttagloop;
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- resetTheInsertionMode();
- continue;
- case SCRIPT:
- startTagScriptInHead(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- case TEMPLATE:
- startTagTemplateInHead(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- default:
- errStrayStartTag(name);
- break starttagloop;
- }
- case AFTER_BODY:
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- default:
- errStrayStartTag(name);
- mode = framesetOk ? FRAMESET_OK : IN_BODY;
- continue;
- }
- case IN_FRAMESET:
- switch (group) {
- case FRAMESET:
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- attributes = null; // CPP
- break starttagloop;
- case FRAME:
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- attributes = null; // CPP
- break starttagloop;
- default:
- // fall through to AFTER_FRAMESET
- }
- case AFTER_FRAMESET:
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- case NOFRAMES:
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.RAWTEXT, elementName);
- attributes = null; // CPP
- break starttagloop;
- default:
- errStrayStartTag(name);
- break starttagloop;
- }
- case INITIAL:
- /*
- * Parse error.
- */
- // [NOCPP[
- switch (doctypeExpectation) {
- case AUTO:
- err("Start tag seen without seeing a doctype first. Expected e.g. \u201C<!DOCTYPE html>\u201D.");
- break;
- case HTML:
- // ]NOCPP]
- errStartTagWithoutDoctype();
- // [NOCPP[
- break;
- case HTML401_STRICT:
- err("Start tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D.");
- break;
- case HTML401_TRANSITIONAL:
- err("Start tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D.");
- break;
- case NO_DOCTYPE_ERRORS:
- }
- // ]NOCPP]
- /*
- *
- * Set the document to quirks mode.
- */
- documentModeInternal(DocumentMode.QUIRKS_MODE, null, null,
- false);
- /*
- * Then, switch to the root element mode of the tree
- * construction stage
- */
- mode = BEFORE_HTML;
- /*
- * and reprocess the current token.
- */
- continue;
- case BEFORE_HTML:
- switch (group) {
- case HTML:
- // optimize error check and streaming SAX by
- // hoisting
- // "html" handling here.
- if (attributes == HtmlAttributes.EMPTY_ATTRIBUTES) {
- // This has the right magic side effect
- // that
- // it
- // makes attributes in SAX Tree mutable.
- appendHtmlElementToDocumentAndPush();
- } else {
- appendHtmlElementToDocumentAndPush(attributes);
- }
- // XXX application cache should fire here
- mode = BEFORE_HEAD;
- attributes = null; // CPP
- break starttagloop;
- default:
- /*
- * Create an HTMLElement node with the tag name
- * html, in the HTML namespace. Append it to the
- * Document object.
- */
- appendHtmlElementToDocumentAndPush();
- /* Switch to the main mode */
- mode = BEFORE_HEAD;
- /*
- * reprocess the current token.
- */
- continue;
- }
- case BEFORE_HEAD:
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- case HEAD:
- /*
- * A start tag whose tag name is "head"
- *
- * Create an element for the token.
- *
- * Set the head element pointer to this new element
- * node.
- *
- * Append the new element to the current node and
- * push it onto the stack of open elements.
- */
- appendToCurrentNodeAndPushHeadElement(attributes);
- /*
- * Change the insertion mode to "in head".
- */
- mode = IN_HEAD;
- attributes = null; // CPP
- break starttagloop;
- default:
- /*
- * Any other start tag token
- *
- * Act as if a start tag token with the tag name
- * "head" and no attributes had been seen,
- */
- appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES);
- mode = IN_HEAD;
- /*
- * then reprocess the current token.
- *
- * This will result in an empty head element being
- * generated, with the current token being
- * reprocessed in the "after head" insertion mode.
- */
- continue;
- }
- case AFTER_HEAD:
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- case BODY:
- if (attributes.getLength() == 0) {
- // This has the right magic side effect
- // that
- // it
- // makes attributes in SAX Tree mutable.
- appendToCurrentNodeAndPushBodyElement();
- } else {
- appendToCurrentNodeAndPushBodyElement(attributes);
- }
- framesetOk = false;
- mode = IN_BODY;
- attributes = null; // CPP
- break starttagloop;
- case FRAMESET:
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- mode = IN_FRAMESET;
- attributes = null; // CPP
- break starttagloop;
- case TEMPLATE:
- errFooBetweenHeadAndBody(name);
- pushHeadPointerOntoStack();
- StackNode<T> headOnStack = stack[currentPtr];
- startTagTemplateInHead(elementName, attributes);
- removeFromStack(headOnStack);
- attributes = null; // CPP
- break starttagloop;
- case BASE:
- case LINK_OR_BASEFONT_OR_BGSOUND:
- errFooBetweenHeadAndBody(name);
- pushHeadPointerOntoStack();
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- pop(); // head
- attributes = null; // CPP
- break starttagloop;
- case META:
- errFooBetweenHeadAndBody(name);
- checkMetaCharset(attributes);
- pushHeadPointerOntoStack();
- appendVoidElementToCurrentMayFoster(
- elementName,
- attributes);
- selfClosing = false;
- pop(); // head
- attributes = null; // CPP
- break starttagloop;
- case SCRIPT:
- errFooBetweenHeadAndBody(name);
- pushHeadPointerOntoStack();
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.SCRIPT_DATA, elementName);
- attributes = null; // CPP
- break starttagloop;
- case STYLE:
- case NOFRAMES:
- errFooBetweenHeadAndBody(name);
- pushHeadPointerOntoStack();
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.RAWTEXT, elementName);
- attributes = null; // CPP
- break starttagloop;
- case TITLE:
- errFooBetweenHeadAndBody(name);
- pushHeadPointerOntoStack();
- appendToCurrentNodeAndPushElement(
- elementName,
- attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(
- Tokenizer.RCDATA, elementName);
- attributes = null; // CPP
- break starttagloop;
- case HEAD:
- errStrayStartTag(name);
- break starttagloop;
- default:
- appendToCurrentNodeAndPushBodyElement();
- mode = FRAMESET_OK;
- continue;
- }
- case AFTER_AFTER_BODY:
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- default:
- errStrayStartTag(name);
- fatal();
- mode = framesetOk ? FRAMESET_OK : IN_BODY;
- continue;
- }
- case AFTER_AFTER_FRAMESET:
- switch (group) {
- case HTML:
- errStrayStartTag(name);
- if (!fragment && !isTemplateContents()) {
- addAttributesToHtml(attributes);
- attributes = null; // CPP
- }
- break starttagloop;
- case NOFRAMES:
- startTagGenericRawText(elementName, attributes);
- attributes = null; // CPP
- break starttagloop;
- default:
- errStrayStartTag(name);
- break starttagloop;
- }
- case TEXT:
- assert false;
- break starttagloop; // Avoid infinite loop if the assertion
- // fails
- }
- }
- if (selfClosing) {
- errSelfClosing();
- }
- // CPPONLY: if (mBuilder == null && attributes != HtmlAttributes.EMPTY_ATTRIBUTES) {
- // CPPONLY: Portability.delete(attributes);
- // CPPONLY: }
- }
-
- private void startTagTitleInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException {
- appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(Tokenizer.RCDATA, elementName);
- }
-
- private void startTagGenericRawText(ElementName elementName, HtmlAttributes attributes) throws SAXException {
- appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(Tokenizer.RAWTEXT, elementName);
- }
-
- private void startTagScriptInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException {
- // XXX need to manage much more stuff here if supporting document.write()
- appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
- originalMode = mode;
- mode = TEXT;
- tokenizer.setStateAndEndTagExpectation(Tokenizer.SCRIPT_DATA, elementName);
- }
-
- private void startTagTemplateInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException {
- appendToCurrentNodeAndPushElement(elementName, attributes);
- insertMarker();
- framesetOk = false;
- originalMode = mode;
- mode = IN_TEMPLATE;
- pushTemplateMode(IN_TEMPLATE);
- }
-
- private boolean isTemplateContents() {
- return TreeBuilder.NOT_FOUND_ON_STACK != findLast("template");
- }
-
- private boolean isTemplateModeStackEmpty() {
- return templateModePtr == -1;
- }
-
- private boolean isSpecialParentInForeign(StackNode<T> stackNode) {
- @NsUri String ns = stackNode.ns;
- return ("http://www.w3.org/1999/xhtml" == ns)
- || (stackNode.isHtmlIntegrationPoint())
- || (("http://www.w3.org/1998/Math/MathML" == ns) && (stackNode.getGroup() == MI_MO_MN_MS_MTEXT));
- }
-
- /**
- *
- * <p>
- * C++ memory note: The return value must be released.
- *
- * @return
- * @throws SAXException
- * @throws StopSniffingException
- */
- public static String extractCharsetFromContent(String attributeValue
- // CPPONLY: , TreeBuilder tb
- ) {
- // This is a bit ugly. Converting the string to char array in order to
- // make the portability layer smaller.
- int charsetState = CHARSET_INITIAL;
- int start = -1;
- int end = -1;
- @Auto char[] buffer = Portability.newCharArrayFromString(attributeValue);
-
- charsetloop: for (int i = 0; i < buffer.length; i++) {
- char c = buffer[i];
- switch (charsetState) {
- case CHARSET_INITIAL:
- switch (c) {
- case 'c':
- case 'C':
- charsetState = CHARSET_C;
- continue;
- default:
- continue;
- }
- case CHARSET_C:
- switch (c) {
- case 'h':
- case 'H':
- charsetState = CHARSET_H;
- continue;
- default:
- charsetState = CHARSET_INITIAL;
- continue;
- }
- case CHARSET_H:
- switch (c) {
- case 'a':
- case 'A':
- charsetState = CHARSET_A;
- continue;
- default:
- charsetState = CHARSET_INITIAL;
- continue;
- }
- case CHARSET_A:
- switch (c) {
- case 'r':
- case 'R':
- charsetState = CHARSET_R;
- continue;
- default:
- charsetState = CHARSET_INITIAL;
- continue;
- }
- case CHARSET_R:
- switch (c) {
- case 's':
- case 'S':
- charsetState = CHARSET_S;
- continue;
- default:
- charsetState = CHARSET_INITIAL;
- continue;
- }
- case CHARSET_S:
- switch (c) {
- case 'e':
- case 'E':
- charsetState = CHARSET_E;
- continue;
- default:
- charsetState = CHARSET_INITIAL;
- continue;
- }
- case CHARSET_E:
- switch (c) {
- case 't':
- case 'T':
- charsetState = CHARSET_T;
- continue;
- default:
- charsetState = CHARSET_INITIAL;
- continue;
- }
- case CHARSET_T:
- switch (c) {
- case '\t':
- case '\n':
- case '\u000C':
- case '\r':
- case ' ':
- continue;
- case '=':
- charsetState = CHARSET_EQUALS;
- continue;
- default:
- return null;
- }
- case CHARSET_EQUALS:
- switch (c) {
- case '\t':
- case '\n':
- case '\u000C':
- case '\r':
- case ' ':
- continue;
- case '\'':
- start = i + 1;
- charsetState = CHARSET_SINGLE_QUOTED;
- continue;
- case '\"':
- start = i + 1;
- charsetState = CHARSET_DOUBLE_QUOTED;
- continue;
- default:
- start = i;
- charsetState = CHARSET_UNQUOTED;
- continue;
- }
- case CHARSET_SINGLE_QUOTED:
- switch (c) {
- case '\'':
- end = i;
- break charsetloop;
- default:
- continue;
- }
- case CHARSET_DOUBLE_QUOTED:
- switch (c) {
- case '\"':
- end = i;
- break charsetloop;
- default:
- continue;
- }
- case CHARSET_UNQUOTED:
- switch (c) {
- case '\t':
- case '\n':
- case '\u000C':
- case '\r':
- case ' ':
- case ';':
- end = i;
- break charsetloop;
- default:
- continue;
- }
- }
- }
- String charset = null;
- if (start != -1) {
- if (end == -1) {
- end = buffer.length;
- }
- charset = Portability.newStringFromBuffer(buffer, start, end
- - start
- // CPPONLY: , tb
- );
- }
- return charset;
- }
-
- private void checkMetaCharset(HtmlAttributes attributes)
- throws SAXException {
- String charset = attributes.getValue(AttributeName.CHARSET);
- if (charset != null) {
- if (tokenizer.internalEncodingDeclaration(charset)) {
- requestSuspension();
- return;
- }
- return;
- }
- if (!Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "content-type",
- attributes.getValue(AttributeName.HTTP_EQUIV))) {
- return;
- }
- String content = attributes.getValue(AttributeName.CONTENT);
- if (content != null) {
- String extract = TreeBuilder.extractCharsetFromContent(content
- // CPPONLY: , this
- );
- // remember not to return early without releasing the string
- if (extract != null) {
- if (tokenizer.internalEncodingDeclaration(extract)) {
- requestSuspension();
- }
- }
- Portability.releaseString(extract);
- }
- }
-
- public final void endTag(ElementName elementName) throws SAXException {
- flushCharacters();
- needToDropLF = false;
- int eltPos;
- int group = elementName.getGroup();
- @Local String name = elementName.name;
- endtagloop: for (;;) {
- if (isInForeign()) {
- if (stack[currentPtr].name != name) {
- if (currentPtr == 0) {
- errStrayEndTag(name);
- } else {
- errEndTagDidNotMatchCurrentOpenElement(name, stack[currentPtr].popName);
- }
- }
- eltPos = currentPtr;
- for (;;) {
- if (eltPos == 0) {
- assert fragment: "We can get this close to the root of the stack in foreign content only in the fragment case.";
- break endtagloop;
- }
- if (stack[eltPos].name == name) {
- while (currentPtr >= eltPos) {
- pop();
- }
- break endtagloop;
- }
- if (stack[--eltPos].ns == "http://www.w3.org/1999/xhtml") {
- break;
- }
- }
- }
- switch (mode) {
- case IN_TEMPLATE:
- switch (group) {
- case TEMPLATE:
- // fall through to IN_HEAD
- break;
- default:
- errStrayEndTag(name);
- break endtagloop;
- }
- case IN_ROW:
- switch (group) {
- case TR:
- eltPos = findLastOrRoot(TreeBuilder.TR);
- if (eltPos == 0) {
- assert fragment || isTemplateContents();
- errNoTableRowToClose();
- break endtagloop;
- }
- clearStackBackTo(eltPos);
- pop();
- mode = IN_TABLE_BODY;
- break endtagloop;
- case TABLE:
- eltPos = findLastOrRoot(TreeBuilder.TR);
- if (eltPos == 0) {
- assert fragment || isTemplateContents();
- errNoTableRowToClose();
- break endtagloop;
- }
- clearStackBackTo(eltPos);
- pop();
- mode = IN_TABLE_BODY;
- continue;
- case TBODY_OR_THEAD_OR_TFOOT:
- if (findLastInTableScope(name) == TreeBuilder.NOT_FOUND_ON_STACK) {
- errStrayEndTag(name);
- break endtagloop;
- }
- eltPos = findLastOrRoot(TreeBuilder.TR);
- if (eltPos == 0) {
- assert fragment || isTemplateContents();
- errNoTableRowToClose();
- break endtagloop;
- }
- clearStackBackTo(eltPos);
- pop();
- mode = IN_TABLE_BODY;
- continue;
- case BODY:
- case CAPTION:
- case COL:
- case COLGROUP:
- case HTML:
- case TD_OR_TH:
- errStrayEndTag(name);
- break endtagloop;
- default:
- // fall through to IN_TABLE
- }
- case IN_TABLE_BODY:
- switch (group) {
- case TBODY_OR_THEAD_OR_TFOOT:
- eltPos = findLastOrRoot(name);
- if (eltPos == 0) {
- errStrayEndTag(name);
- break endtagloop;
- }
- clearStackBackTo(eltPos);
- pop();
- mode = IN_TABLE;
- break endtagloop;
- case TABLE:
- eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
- if (eltPos == 0 || stack[eltPos].getGroup() == TEMPLATE) {
- assert fragment || isTemplateContents();
- errStrayEndTag(name);
- break endtagloop;
- }
- clearStackBackTo(eltPos);
- pop();
- mode = IN_TABLE;
- continue;
- case BODY:
- case CAPTION:
- case COL:
- case COLGROUP:
- case HTML:
- case TD_OR_TH:
- case TR:
- errStrayEndTag(name);
- break endtagloop;
- default:
- // fall through to IN_TABLE
- }
- case IN_TABLE:
- switch (group) {
- case TABLE:
- eltPos = findLast("table");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- assert fragment || isTemplateContents();
- errStrayEndTag(name);
- break endtagloop;
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- resetTheInsertionMode();
- break endtagloop;
- case BODY:
- case CAPTION:
- case COL:
- case COLGROUP:
- case HTML:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TD_OR_TH:
- case TR:
- errStrayEndTag(name);
- break endtagloop;
- case TEMPLATE:
- // fall through to IN_HEAD
- break;
- default:
- errStrayEndTag(name);
- // fall through to IN_BODY
- }
- case IN_CAPTION:
- switch (group) {
- case CAPTION:
- eltPos = findLastInTableScope("caption");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- break endtagloop;
- }
- generateImpliedEndTags();
- if (errorHandler != null && currentPtr != eltPos) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- clearTheListOfActiveFormattingElementsUpToTheLastMarker();
- mode = IN_TABLE;
- break endtagloop;
- case TABLE:
- errTableClosedWhileCaptionOpen();
- eltPos = findLastInTableScope("caption");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- break endtagloop;
- }
- generateImpliedEndTags();
- if (errorHandler != null && currentPtr != eltPos) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- clearTheListOfActiveFormattingElementsUpToTheLastMarker();
- mode = IN_TABLE;
- continue;
- case BODY:
- case COL:
- case COLGROUP:
- case HTML:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TD_OR_TH:
- case TR:
- errStrayEndTag(name);
- break endtagloop;
- default:
- // fall through to IN_BODY
- }
- case IN_CELL:
- switch (group) {
- case TD_OR_TH:
- eltPos = findLastInTableScope(name);
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errStrayEndTag(name);
- break endtagloop;
- }
- generateImpliedEndTags();
- if (errorHandler != null && !isCurrent(name)) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- clearTheListOfActiveFormattingElementsUpToTheLastMarker();
- mode = IN_ROW;
- break endtagloop;
- case TABLE:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TR:
- if (findLastInTableScope(name) == TreeBuilder.NOT_FOUND_ON_STACK) {
- assert name == "tbody" || name == "tfoot" || name == "thead" || fragment || isTemplateContents();
- errStrayEndTag(name);
- break endtagloop;
- }
- closeTheCell(findLastInTableScopeTdTh());
- continue;
- case BODY:
- case CAPTION:
- case COL:
- case COLGROUP:
- case HTML:
- errStrayEndTag(name);
- break endtagloop;
- default:
- // fall through to IN_BODY
- }
- case FRAMESET_OK:
- case IN_BODY:
- switch (group) {
- case BODY:
- if (!isSecondOnStackBody()) {
- assert fragment || isTemplateContents();
- errStrayEndTag(name);
- break endtagloop;
- }
- assert currentPtr >= 1;
- if (errorHandler != null) {
- uncloseloop1: for (int i = 2; i <= currentPtr; i++) {
- switch (stack[i].getGroup()) {
- case DD_OR_DT:
- case LI:
- case OPTGROUP:
- case OPTION: // is this possible?
- case P:
- case RB_OR_RTC:
- case RT_OR_RP:
- case TD_OR_TH:
- case TBODY_OR_THEAD_OR_TFOOT:
- break;
- default:
- errEndWithUnclosedElements(name);
- break uncloseloop1;
- }
- }
- }
- mode = AFTER_BODY;
- break endtagloop;
- case HTML:
- if (!isSecondOnStackBody()) {
- assert fragment || isTemplateContents();
- errStrayEndTag(name);
- break endtagloop;
- }
- if (errorHandler != null) {
- uncloseloop2: for (int i = 0; i <= currentPtr; i++) {
- switch (stack[i].getGroup()) {
- case DD_OR_DT:
- case LI:
- case P:
- case RB_OR_RTC:
- case RT_OR_RP:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TD_OR_TH:
- case BODY:
- case HTML:
- break;
- default:
- errEndWithUnclosedElements(name);
- break uncloseloop2;
- }
- }
- }
- mode = AFTER_BODY;
- continue;
- case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
- case UL_OR_OL_OR_DL:
- case PRE_OR_LISTING:
- case FIELDSET:
- case BUTTON:
- case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY:
- eltPos = findLastInScope(name);
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errStrayEndTag(name);
- } else {
- generateImpliedEndTags();
- if (errorHandler != null && !isCurrent(name)) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- }
- break endtagloop;
- case FORM:
- if (!isTemplateContents()) {
- if (formPointer == null) {
- errStrayEndTag(name);
- break endtagloop;
- }
- formPointer = null;
- eltPos = findLastInScope(name);
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errStrayEndTag(name);
- break endtagloop;
- }
- generateImpliedEndTags();
- if (errorHandler != null && !isCurrent(name)) {
- errUnclosedElements(eltPos, name);
- }
- removeFromStack(eltPos);
- break endtagloop;
- } else {
- eltPos = findLastInScope(name);
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errStrayEndTag(name);
- break endtagloop;
- }
- generateImpliedEndTags();
- if (errorHandler != null && !isCurrent(name)) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- break endtagloop;
- }
- case P:
- eltPos = findLastInButtonScope("p");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errNoElementToCloseButEndTagSeen("p");
- // XXX Can the 'in foreign' case happen anymore?
- if (isInForeign()) {
- errHtmlStartTagInForeignContext(name);
- // Check for currentPtr for the fragment
- // case.
- while (currentPtr >= 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
- pop();
- }
- }
- appendVoidElementToCurrentMayFoster(
- elementName,
- HtmlAttributes.EMPTY_ATTRIBUTES);
- break endtagloop;
- }
- generateImpliedEndTagsExceptFor("p");
- assert eltPos != TreeBuilder.NOT_FOUND_ON_STACK;
- if (errorHandler != null && eltPos != currentPtr) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- break endtagloop;
- case LI:
- eltPos = findLastInListScope(name);
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errNoElementToCloseButEndTagSeen(name);
- } else {
- generateImpliedEndTagsExceptFor(name);
- if (errorHandler != null
- && eltPos != currentPtr) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- }
- break endtagloop;
- case DD_OR_DT:
- eltPos = findLastInScope(name);
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errNoElementToCloseButEndTagSeen(name);
- } else {
- generateImpliedEndTagsExceptFor(name);
- if (errorHandler != null
- && eltPos != currentPtr) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- }
- break endtagloop;
- case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
- eltPos = findLastInScopeHn();
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errStrayEndTag(name);
- } else {
- generateImpliedEndTags();
- if (errorHandler != null && !isCurrent(name)) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- }
- break endtagloop;
- case OBJECT:
- case MARQUEE_OR_APPLET:
- eltPos = findLastInScope(name);
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errStrayEndTag(name);
- } else {
- generateImpliedEndTags();
- if (errorHandler != null && !isCurrent(name)) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- clearTheListOfActiveFormattingElementsUpToTheLastMarker();
- }
- break endtagloop;
- case BR:
- errEndTagBr();
- if (isInForeign()) {
- // XXX can this happen anymore?
- errHtmlStartTagInForeignContext(name);
- // Check for currentPtr for the fragment
- // case.
- while (currentPtr >= 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
- pop();
- }
- }
- reconstructTheActiveFormattingElements();
- appendVoidElementToCurrentMayFoster(
- elementName,
- HtmlAttributes.EMPTY_ATTRIBUTES);
- break endtagloop;
- case TEMPLATE:
- // fall through to IN_HEAD;
- break;
- case AREA_OR_WBR:
- // CPPONLY: case MENUITEM:
- case PARAM_OR_SOURCE_OR_TRACK:
- case EMBED:
- case IMG:
- case IMAGE:
- case INPUT:
- case KEYGEN: // XXX??
- case HR:
- case ISINDEX:
- case IFRAME:
- case NOEMBED: // XXX???
- case NOFRAMES: // XXX??
- case SELECT:
- case TABLE:
- case TEXTAREA: // XXX??
- errStrayEndTag(name);
- break endtagloop;
- case NOSCRIPT:
- if (scriptingEnabled) {
- errStrayEndTag(name);
- break endtagloop;
- } else {
- // fall through
- }
- case A:
- case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
- case FONT:
- case NOBR:
- if (adoptionAgencyEndTag(name)) {
- break endtagloop;
- }
- // else handle like any other tag
- default:
- if (isCurrent(name)) {
- pop();
- break endtagloop;
- }
-
- eltPos = currentPtr;
- for (;;) {
- StackNode<T> node = stack[eltPos];
- if (node.ns == "http://www.w3.org/1999/xhtml" && node.name == name) {
- generateImpliedEndTags();
- if (errorHandler != null
- && !isCurrent(name)) {
- errUnclosedElements(eltPos, name);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- break endtagloop;
- } else if (eltPos == 0 || node.isSpecial()) {
- errStrayEndTag(name);
- break endtagloop;
- }
- eltPos--;
- }
- }
- case IN_HEAD:
- switch (group) {
- case HEAD:
- pop();
- mode = AFTER_HEAD;
- break endtagloop;
- case BR:
- case HTML:
- case BODY:
- pop();
- mode = AFTER_HEAD;
- continue;
- case TEMPLATE:
- endTagTemplateInHead();
- break endtagloop;
- default:
- errStrayEndTag(name);
- break endtagloop;
- }
- case IN_HEAD_NOSCRIPT:
- switch (group) {
- case NOSCRIPT:
- pop();
- mode = IN_HEAD;
- break endtagloop;
- case BR:
- errStrayEndTag(name);
- pop();
- mode = IN_HEAD;
- continue;
- default:
- errStrayEndTag(name);
- break endtagloop;
- }
- case IN_COLUMN_GROUP:
- switch (group) {
- case COLGROUP:
- if (currentPtr == 0 || stack[currentPtr].getGroup() ==
- TreeBuilder.TEMPLATE) {
- assert fragment || isTemplateContents();
- errGarbageInColgroup();
- break endtagloop;
- }
- pop();
- mode = IN_TABLE;
- break endtagloop;
- case COL:
- errStrayEndTag(name);
- break endtagloop;
- case TEMPLATE:
- endTagTemplateInHead();
- break endtagloop;
- default:
- if (currentPtr == 0 || stack[currentPtr].getGroup() ==
- TreeBuilder.TEMPLATE) {
- assert fragment || isTemplateContents();
- errGarbageInColgroup();
- break endtagloop;
- }
- pop();
- mode = IN_TABLE;
- continue;
- }
- case IN_SELECT_IN_TABLE:
- switch (group) {
- case CAPTION:
- case TABLE:
- case TBODY_OR_THEAD_OR_TFOOT:
- case TR:
- case TD_OR_TH:
- errEndTagSeenWithSelectOpen(name);
- if (findLastInTableScope(name) != TreeBuilder.NOT_FOUND_ON_STACK) {
- eltPos = findLastInTableScope("select");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- assert fragment;
- break endtagloop; // http://www.w3.org/Bugs/Public/show_bug.cgi?id=8375
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- resetTheInsertionMode();
- continue;
- } else {
- break endtagloop;
- }
- default:
- // fall through to IN_SELECT
- }
- case IN_SELECT:
- switch (group) {
- case OPTION:
- if (isCurrent("option")) {
- pop();
- break endtagloop;
- } else {
- errStrayEndTag(name);
- break endtagloop;
- }
- case OPTGROUP:
- if (isCurrent("option")
- && "optgroup" == stack[currentPtr - 1].name) {
- pop();
- }
- if (isCurrent("optgroup")) {
- pop();
- } else {
- errStrayEndTag(name);
- }
- break endtagloop;
- case SELECT:
- eltPos = findLastInTableScope("select");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- assert fragment;
- errStrayEndTag(name);
- break endtagloop;
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- resetTheInsertionMode();
- break endtagloop;
- case TEMPLATE:
- endTagTemplateInHead();
- break endtagloop;
- default:
- errStrayEndTag(name);
- break endtagloop;
- }
- case AFTER_BODY:
- switch (group) {
- case HTML:
- if (fragment) {
- errStrayEndTag(name);
- break endtagloop;
- } else {
- mode = AFTER_AFTER_BODY;
- break endtagloop;
- }
- default:
- errEndTagAfterBody();
- mode = framesetOk ? FRAMESET_OK : IN_BODY;
- continue;
- }
- case IN_FRAMESET:
- switch (group) {
- case FRAMESET:
- if (currentPtr == 0) {
- assert fragment;
- errStrayEndTag(name);
- break endtagloop;
- }
- pop();
- if ((!fragment) && !isCurrent("frameset")) {
- mode = AFTER_FRAMESET;
- }
- break endtagloop;
- default:
- errStrayEndTag(name);
- break endtagloop;
- }
- case AFTER_FRAMESET:
- switch (group) {
- case HTML:
- mode = AFTER_AFTER_FRAMESET;
- break endtagloop;
- default:
- errStrayEndTag(name);
- break endtagloop;
- }
- case INITIAL:
- /*
- * Parse error.
- */
- // [NOCPP[
- switch (doctypeExpectation) {
- case AUTO:
- err("End tag seen without seeing a doctype first. Expected e.g. \u201C<!DOCTYPE html>\u201D.");
- break;
- case HTML:
- // ]NOCPP]
- errEndTagSeenWithoutDoctype();
- // [NOCPP[
- break;
- case HTML401_STRICT:
- err("End tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D.");
- break;
- case HTML401_TRANSITIONAL:
- err("End tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D.");
- break;
- case NO_DOCTYPE_ERRORS:
- }
- // ]NOCPP]
- /*
- *
- * Set the document to quirks mode.
- */
- documentModeInternal(DocumentMode.QUIRKS_MODE, null, null,
- false);
- /*
- * Then, switch to the root element mode of the tree
- * construction stage
- */
- mode = BEFORE_HTML;
- /*
- * and reprocess the current token.
- */
- continue;
- case BEFORE_HTML:
- switch (group) {
- case HEAD:
- case BR:
- case HTML:
- case BODY:
- /*
- * Create an HTMLElement node with the tag name
- * html, in the HTML namespace. Append it to the
- * Document object.
- */
- appendHtmlElementToDocumentAndPush();
- /* Switch to the main mode */
- mode = BEFORE_HEAD;
- /*
- * reprocess the current token.
- */
- continue;
- default:
- errStrayEndTag(name);
- break endtagloop;
- }
- case BEFORE_HEAD:
- switch (group) {
- case HEAD:
- case BR:
- case HTML:
- case BODY:
- appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES);
- mode = IN_HEAD;
- continue;
- default:
- errStrayEndTag(name);
- break endtagloop;
- }
- case AFTER_HEAD:
- switch (group) {
- case TEMPLATE:
- endTagTemplateInHead();
- break endtagloop;
- case HTML:
- case BODY:
- case BR:
- appendToCurrentNodeAndPushBodyElement();
- mode = FRAMESET_OK;
- continue;
- default:
- errStrayEndTag(name);
- break endtagloop;
- }
- case AFTER_AFTER_BODY:
- errStrayEndTag(name);
- mode = framesetOk ? FRAMESET_OK : IN_BODY;
- continue;
- case AFTER_AFTER_FRAMESET:
- errStrayEndTag(name);
- break endtagloop;
- case TEXT:
- // XXX need to manage insertion point here
- pop();
- if (originalMode == AFTER_HEAD) {
- silentPop();
- }
- mode = originalMode;
- break endtagloop;
- }
- } // endtagloop
- }
-
- private void endTagTemplateInHead() throws SAXException {
- int eltPos = findLast("template");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- errStrayEndTag("template");
- return;
- }
- generateImpliedEndTags();
- if (errorHandler != null && !isCurrent("template")) {
- errUnclosedElements(eltPos, "template");
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- clearTheListOfActiveFormattingElementsUpToTheLastMarker();
- popTemplateMode();
- resetTheInsertionMode();
- }
-
- private int findLastInTableScopeOrRootTemplateTbodyTheadTfoot() {
- for (int i = currentPtr; i > 0; i--) {
- if (stack[i].getGroup() == TreeBuilder.TBODY_OR_THEAD_OR_TFOOT ||
- stack[i].getGroup() == TreeBuilder.TEMPLATE) {
- return i;
- }
- }
- return 0;
- }
-
- private int findLast(@Local String name) {
- for (int i = currentPtr; i > 0; i--) {
- if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) {
- return i;
- }
- }
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
-
- private int findLastInTableScope(@Local String name) {
- for (int i = currentPtr; i > 0; i--) {
- if (stack[i].ns == "http://www.w3.org/1999/xhtml") {
- if (stack[i].name == name) {
- return i;
- } else if (stack[i].name == "table" || stack[i].name == "template") {
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
- }
- }
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
-
- private int findLastInButtonScope(@Local String name) {
- for (int i = currentPtr; i > 0; i--) {
- if (stack[i].ns == "http://www.w3.org/1999/xhtml") {
- if (stack[i].name == name) {
- return i;
- } else if (stack[i].name == "button") {
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
- }
-
- if (stack[i].isScoping()) {
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
- }
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
-
- private int findLastInScope(@Local String name) {
- for (int i = currentPtr; i > 0; i--) {
- if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) {
- return i;
- } else if (stack[i].isScoping()) {
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
- }
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
-
- private int findLastInListScope(@Local String name) {
- for (int i = currentPtr; i > 0; i--) {
- if (stack[i].ns == "http://www.w3.org/1999/xhtml") {
- if (stack[i].name == name) {
- return i;
- } else if (stack[i].name == "ul" || stack[i].name == "ol") {
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
- }
-
- if (stack[i].isScoping()) {
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
- }
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
-
- private int findLastInScopeHn() {
- for (int i = currentPtr; i > 0; i--) {
- if (stack[i].getGroup() == TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
- return i;
- } else if (stack[i].isScoping()) {
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
- }
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
-
- private void generateImpliedEndTagsExceptFor(@Local String name)
- throws SAXException {
- for (;;) {
- StackNode<T> node = stack[currentPtr];
- switch (node.getGroup()) {
- case P:
- case LI:
- case DD_OR_DT:
- case OPTION:
- case OPTGROUP:
- case RB_OR_RTC:
- case RT_OR_RP:
- if (node.ns == "http://www.w3.org/1999/xhtml" && node.name == name) {
- return;
- }
- pop();
- continue;
- default:
- return;
- }
- }
- }
-
- private void generateImpliedEndTags() throws SAXException {
- for (;;) {
- switch (stack[currentPtr].getGroup()) {
- case P:
- case LI:
- case DD_OR_DT:
- case OPTION:
- case OPTGROUP:
- case RB_OR_RTC:
- case RT_OR_RP:
- pop();
- continue;
- default:
- return;
- }
- }
- }
-
- private boolean isSecondOnStackBody() {
- return currentPtr >= 1 && stack[1].getGroup() == TreeBuilder.BODY;
- }
-
- private void documentModeInternal(DocumentMode m, String publicIdentifier,
- String systemIdentifier, boolean html4SpecificAdditionalErrorChecks)
- throws SAXException {
-
- if (isSrcdocDocument) {
- // Srcdoc documents are always rendered in standards mode.
- quirks = false;
- if (documentModeHandler != null) {
- documentModeHandler.documentMode(
- DocumentMode.STANDARDS_MODE
- // [NOCPP[
- , null, null, false
- // ]NOCPP]
- );
- }
- return;
- }
-
- quirks = (m == DocumentMode.QUIRKS_MODE);
- if (documentModeHandler != null) {
- documentModeHandler.documentMode(
- m
- // [NOCPP[
- , publicIdentifier, systemIdentifier,
- html4SpecificAdditionalErrorChecks
- // ]NOCPP]
- );
- }
- // [NOCPP[
- documentMode(m, publicIdentifier, systemIdentifier,
- html4SpecificAdditionalErrorChecks);
- // ]NOCPP]
- }
-
- private boolean isAlmostStandards(String publicIdentifier,
- String systemIdentifier) {
- if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "-//w3c//dtd xhtml 1.0 transitional//en", publicIdentifier)) {
- return true;
- }
- if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "-//w3c//dtd xhtml 1.0 frameset//en", publicIdentifier)) {
- return true;
- }
- if (systemIdentifier != null) {
- if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "-//w3c//dtd html 4.01 transitional//en", publicIdentifier)) {
- return true;
- }
- if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "-//w3c//dtd html 4.01 frameset//en", publicIdentifier)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean isQuirky(@Local String name, String publicIdentifier,
- String systemIdentifier, boolean forceQuirks) {
- if (forceQuirks) {
- return true;
- }
- if (name != HTML_LOCAL) {
- return true;
- }
- if (publicIdentifier != null) {
- for (int i = 0; i < TreeBuilder.QUIRKY_PUBLIC_IDS.length; i++) {
- if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
- TreeBuilder.QUIRKY_PUBLIC_IDS[i], publicIdentifier)) {
- return true;
- }
- }
- if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier)
- || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "-/w3c/dtd html 4.0 transitional/en",
- publicIdentifier)
- || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "html", publicIdentifier)) {
- return true;
- }
- }
- if (systemIdentifier == null) {
- if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "-//w3c//dtd html 4.01 transitional//en", publicIdentifier)) {
- return true;
- } else if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "-//w3c//dtd html 4.01 frameset//en", publicIdentifier)) {
- return true;
- }
- } else if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd",
- systemIdentifier)) {
- return true;
- }
- return false;
- }
-
- private void closeTheCell(int eltPos) throws SAXException {
- generateImpliedEndTags();
- if (errorHandler != null && eltPos != currentPtr) {
- errUnclosedElementsCell(eltPos);
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- clearTheListOfActiveFormattingElementsUpToTheLastMarker();
- mode = IN_ROW;
- return;
- }
-
- private int findLastInTableScopeTdTh() {
- for (int i = currentPtr; i > 0; i--) {
- @Local String name = stack[i].name;
- if (stack[i].ns == "http://www.w3.org/1999/xhtml") {
- if ("td" == name || "th" == name) {
- return i;
- } else if (name == "table" || name == "template") {
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
- }
- }
- return TreeBuilder.NOT_FOUND_ON_STACK;
- }
-
- private void clearStackBackTo(int eltPos) throws SAXException {
- int eltGroup = stack[eltPos].getGroup();
- while (currentPtr > eltPos) { // > not >= intentional
- if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml"
- && stack[currentPtr].getGroup() == TEMPLATE
- && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltPos == 0)) {
- return;
- }
- pop();
- }
- }
-
- private void resetTheInsertionMode() {
- StackNode<T> node;
- @Local String name;
- @NsUri String ns;
- for (int i = currentPtr; i >= 0; i--) {
- node = stack[i];
- name = node.name;
- ns = node.ns;
- if (i == 0) {
- if (!(contextNamespace == "http://www.w3.org/1999/xhtml" && (contextName == "td" || contextName == "th"))) {
- if (fragment) {
- // Make sure we are parsing a fragment otherwise the context element doesn't make sense.
- name = contextName;
- ns = contextNamespace;
- }
- } else {
- mode = framesetOk ? FRAMESET_OK : IN_BODY; // XXX from Hixie's email
- return;
- }
- }
- if ("select" == name) {
- int ancestorIndex = i;
- while (ancestorIndex > 0) {
- StackNode<T> ancestor = stack[ancestorIndex--];
- if ("http://www.w3.org/1999/xhtml" == ancestor.ns) {
- if ("template" == ancestor.name) {
- break;
- }
- if ("table" == ancestor.name) {
- mode = IN_SELECT_IN_TABLE;
- return;
- }
- }
- }
- mode = IN_SELECT;
- return;
- } else if ("td" == name || "th" == name) {
- mode = IN_CELL;
- return;
- } else if ("tr" == name) {
- mode = IN_ROW;
- return;
- } else if ("tbody" == name || "thead" == name || "tfoot" == name) {
- mode = IN_TABLE_BODY;
- return;
- } else if ("caption" == name) {
- mode = IN_CAPTION;
- return;
- } else if ("colgroup" == name) {
- mode = IN_COLUMN_GROUP;
- return;
- } else if ("table" == name) {
- mode = IN_TABLE;
- return;
- } else if ("http://www.w3.org/1999/xhtml" != ns) {
- mode = framesetOk ? FRAMESET_OK : IN_BODY;
- return;
- } else if ("template" == name) {
- assert templateModePtr >= 0;
- mode = templateModeStack[templateModePtr];
- return;
- } else if ("head" == name) {
- if (name == contextName) {
- mode = framesetOk ? FRAMESET_OK : IN_BODY; // really
- } else {
- mode = IN_HEAD;
- }
- return;
- } else if ("body" == name) {
- mode = framesetOk ? FRAMESET_OK : IN_BODY;
- return;
- } else if ("frameset" == name) {
- // TODO: Fragment case. Add error reporting.
- mode = IN_FRAMESET;
- return;
- } else if ("html" == name) {
- if (headPointer == null) {
- // TODO: Fragment case. Add error reporting.
- mode = BEFORE_HEAD;
- } else {
- mode = AFTER_HEAD;
- }
- return;
- } else if (i == 0) {
- mode = framesetOk ? FRAMESET_OK : IN_BODY;
- return;
- }
- }
- }
-
- /**
- * @throws SAXException
- *
- */
- private void implicitlyCloseP() throws SAXException {
- int eltPos = findLastInButtonScope("p");
- if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
- return;
- }
- generateImpliedEndTagsExceptFor("p");
- if (errorHandler != null && eltPos != currentPtr) {
- errUnclosedElementsImplied(eltPos, "p");
- }
- while (currentPtr >= eltPos) {
- pop();
- }
- }
-
- private boolean debugOnlyClearLastStackSlot() {
- stack[currentPtr] = null;
- return true;
- }
-
- private boolean debugOnlyClearLastListSlot() {
- listOfActiveFormattingElements[listPtr] = null;
- return true;
- }
-
- private void pushTemplateMode(int mode) {
- templateModePtr++;
- if (templateModePtr == templateModeStack.length) {
- int[] newStack = new int[templateModeStack.length + 64];
- System.arraycopy(templateModeStack, 0, newStack, 0, templateModeStack.length);
- templateModeStack = newStack;
- }
- templateModeStack[templateModePtr] = mode;
- }
-
- @SuppressWarnings("unchecked") private void push(StackNode<T> node) throws SAXException {
- currentPtr++;
- if (currentPtr == stack.length) {
- StackNode<T>[] newStack = new StackNode[stack.length + 64];
- System.arraycopy(stack, 0, newStack, 0, stack.length);
- stack = newStack;
- }
- stack[currentPtr] = node;
- elementPushed(node.ns, node.popName, node.node);
- }
-
- @SuppressWarnings("unchecked") private void silentPush(StackNode<T> node) throws SAXException {
- currentPtr++;
- if (currentPtr == stack.length) {
- StackNode<T>[] newStack = new StackNode[stack.length + 64];
- System.arraycopy(stack, 0, newStack, 0, stack.length);
- stack = newStack;
- }
- stack[currentPtr] = node;
- }
-
- @SuppressWarnings("unchecked") private void append(StackNode<T> node) {
- listPtr++;
- if (listPtr == listOfActiveFormattingElements.length) {
- StackNode<T>[] newList = new StackNode[listOfActiveFormattingElements.length + 64];
- System.arraycopy(listOfActiveFormattingElements, 0, newList, 0,
- listOfActiveFormattingElements.length);
- listOfActiveFormattingElements = newList;
- }
- listOfActiveFormattingElements[listPtr] = node;
- }
-
- @Inline private void insertMarker() {
- append(null);
- }
-
- private void clearTheListOfActiveFormattingElementsUpToTheLastMarker() {
- while (listPtr > -1) {
- if (listOfActiveFormattingElements[listPtr] == null) {
- --listPtr;
- return;
- }
- listOfActiveFormattingElements[listPtr].release();
- --listPtr;
- }
- }
-
- @Inline private boolean isCurrent(@Local String name) {
- return stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" &&
- name == stack[currentPtr].name;
- }
-
- private void removeFromStack(int pos) throws SAXException {
- if (currentPtr == pos) {
- pop();
- } else {
- fatal();
- stack[pos].release();
- System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos);
- assert debugOnlyClearLastStackSlot();
- currentPtr--;
- }
- }
-
- private void removeFromStack(StackNode<T> node) throws SAXException {
- if (stack[currentPtr] == node) {
- pop();
- } else {
- int pos = currentPtr - 1;
- while (pos >= 0 && stack[pos] != node) {
- pos--;
- }
- if (pos == -1) {
- // dead code?
- return;
- }
- fatal();
- node.release();
- System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos);
- currentPtr--;
- }
- }
-
- private void removeFromListOfActiveFormattingElements(int pos) {
- assert listOfActiveFormattingElements[pos] != null;
- listOfActiveFormattingElements[pos].release();
- if (pos == listPtr) {
- assert debugOnlyClearLastListSlot();
- listPtr--;
- return;
- }
- assert pos < listPtr;
- System.arraycopy(listOfActiveFormattingElements, pos + 1,
- listOfActiveFormattingElements, pos, listPtr - pos);
- assert debugOnlyClearLastListSlot();
- listPtr--;
- }
-
- /**
- * Adoption agency algorithm.
- *
- * @param name subject as described in the specified algorithm.
- * @return Returns true if the algorithm has completed and there is nothing remaining to
- * be done. Returns false if the algorithm needs to "act as described in the 'any other
- * end tag' entry" as described in the specified algorithm.
- * @throws SAXException
- */
- private boolean adoptionAgencyEndTag(@Local String name) throws SAXException {
- // This check intends to ensure that for properly nested tags, closing tags will match
- // against the stack instead of the listOfActiveFormattingElements.
- if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" &&
- stack[currentPtr].name == name &&
- findInListOfActiveFormattingElements(stack[currentPtr]) == -1) {
- // If the current element matches the name but isn't on the list of active
- // formatting elements, then it is possible that the list was mangled by the Noah's Ark
- // clause. In this case, we want to match the end tag against the stack instead of
- // proceeding with the AAA algorithm that may match against the list of
- // active formatting elements (and possibly mangle the tree in unexpected ways).
- pop();
- return true;
- }
-
- // If you crash around here, perhaps some stack node variable claimed to
- // be a weak ref isn't.
- for (int i = 0; i < 8; ++i) {
- int formattingEltListPos = listPtr;
- while (formattingEltListPos > -1) {
- StackNode<T> listNode = listOfActiveFormattingElements[formattingEltListPos]; // weak ref
- if (listNode == null) {
- formattingEltListPos = -1;
- break;
- } else if (listNode.name == name) {
- break;
- }
- formattingEltListPos--;
- }
- if (formattingEltListPos == -1) {
- return false;
- }
- // this *looks* like a weak ref to the list of formatting elements
- StackNode<T> formattingElt = listOfActiveFormattingElements[formattingEltListPos];
- int formattingEltStackPos = currentPtr;
- boolean inScope = true;
- while (formattingEltStackPos > -1) {
- StackNode<T> node = stack[formattingEltStackPos]; // weak ref
- if (node == formattingElt) {
- break;
- } else if (node.isScoping()) {
- inScope = false;
- }
- formattingEltStackPos--;
- }
- if (formattingEltStackPos == -1) {
- errNoElementToCloseButEndTagSeen(name);
- removeFromListOfActiveFormattingElements(formattingEltListPos);
- return true;
- }
- if (!inScope) {
- errNoElementToCloseButEndTagSeen(name);
- return true;
- }
- // stackPos now points to the formatting element and it is in scope
- if (formattingEltStackPos != currentPtr) {
- errEndTagViolatesNestingRules(name);
- }
- int furthestBlockPos = formattingEltStackPos + 1;
- while (furthestBlockPos <= currentPtr) {
- StackNode<T> node = stack[furthestBlockPos]; // weak ref
- assert furthestBlockPos > 0: "How is formattingEltStackPos + 1 not > 0?";
- if (node.isSpecial()) {
- break;
- }
- furthestBlockPos++;
- }
- if (furthestBlockPos > currentPtr) {
- // no furthest block
- while (currentPtr >= formattingEltStackPos) {
- pop();
- }
- removeFromListOfActiveFormattingElements(formattingEltListPos);
- return true;
- }
- StackNode<T> commonAncestor = stack[formattingEltStackPos - 1]; // weak ref
- StackNode<T> furthestBlock = stack[furthestBlockPos]; // weak ref
- // detachFromParent(furthestBlock.node); XXX AAA CHANGE
- int bookmark = formattingEltListPos;
- int nodePos = furthestBlockPos;
- StackNode<T> lastNode = furthestBlock; // weak ref
- int j = 0;
- for (;;) {
- ++j;
- nodePos--;
- if (nodePos == formattingEltStackPos) {
- break;
- }
- StackNode<T> node = stack[nodePos]; // weak ref
- int nodeListPos = findInListOfActiveFormattingElements(node);
-
- if (j > 3 && nodeListPos != -1) {
- removeFromListOfActiveFormattingElements(nodeListPos);
-
- // Adjust the indices into the list to account
- // for the removal of nodeListPos.
- if (nodeListPos <= formattingEltListPos) {
- formattingEltListPos--;
- }
- if (nodeListPos <= bookmark) {
- bookmark--;
- }
-
- // Update position to reflect removal from list.
- nodeListPos = -1;
- }
-
- if (nodeListPos == -1) {
- assert formattingEltStackPos < nodePos;
- assert bookmark < nodePos;
- assert furthestBlockPos > nodePos;
- removeFromStack(nodePos); // node is now a bad pointer in C++
- furthestBlockPos--;
- continue;
- }
- // now node is both on stack and in the list
- if (nodePos == furthestBlockPos) {
- bookmark = nodeListPos + 1;
- }
- // if (hasChildren(node.node)) { XXX AAA CHANGE
- assert node == listOfActiveFormattingElements[nodeListPos];
- assert node == stack[nodePos];
- T clone = createElement("http://www.w3.org/1999/xhtml",
- node.name, node.attributes.cloneAttributes(null), commonAncestor.node);
- StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
- node.name, clone, node.popName, node.attributes
- // [NOCPP[
- , node.getLocator()
- // ]NOCPP]
- ); // creation ownership goes to stack
- node.dropAttributes(); // adopt ownership to newNode
- stack[nodePos] = newNode;
- newNode.retain(); // retain for list
- listOfActiveFormattingElements[nodeListPos] = newNode;
- node.release(); // release from stack
- node.release(); // release from list
- node = newNode;
- // } XXX AAA CHANGE
- detachFromParent(lastNode.node);
- appendElement(lastNode.node, node.node);
- lastNode = node;
- }
- if (commonAncestor.isFosterParenting()) {
- fatal();
- detachFromParent(lastNode.node);
- insertIntoFosterParent(lastNode.node);
- } else {
- detachFromParent(lastNode.node);
- appendElement(lastNode.node, commonAncestor.node);
- }
- T clone = createElement("http://www.w3.org/1999/xhtml",
- formattingElt.name,
- formattingElt.attributes.cloneAttributes(null), furthestBlock.node);
- StackNode<T> formattingClone = new StackNode<T>(
- formattingElt.getFlags(), formattingElt.ns,
- formattingElt.name, clone, formattingElt.popName,
- formattingElt.attributes
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- ); // Ownership transfers to stack below
- formattingElt.dropAttributes(); // transfer ownership to
- // formattingClone
- appendChildrenToNewParent(furthestBlock.node, clone);
- appendElement(clone, furthestBlock.node);
- removeFromListOfActiveFormattingElements(formattingEltListPos);
- insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
- assert formattingEltStackPos < furthestBlockPos;
- removeFromStack(formattingEltStackPos);
- // furthestBlockPos is now off by one and points to the slot after
- // it
- insertIntoStack(formattingClone, furthestBlockPos);
- }
- return true;
- }
-
- private void insertIntoStack(StackNode<T> node, int position)
- throws SAXException {
- assert currentPtr + 1 < stack.length;
- assert position <= currentPtr + 1;
- if (position == currentPtr + 1) {
- push(node);
- } else {
- System.arraycopy(stack, position, stack, position + 1,
- (currentPtr - position) + 1);
- currentPtr++;
- stack[position] = node;
- }
- }
-
- private void insertIntoListOfActiveFormattingElements(
- StackNode<T> formattingClone, int bookmark) {
- formattingClone.retain();
- assert listPtr + 1 < listOfActiveFormattingElements.length;
- if (bookmark <= listPtr) {
- System.arraycopy(listOfActiveFormattingElements, bookmark,
- listOfActiveFormattingElements, bookmark + 1,
- (listPtr - bookmark) + 1);
- }
- listPtr++;
- listOfActiveFormattingElements[bookmark] = formattingClone;
- }
-
- private int findInListOfActiveFormattingElements(StackNode<T> node) {
- for (int i = listPtr; i >= 0; i--) {
- if (node == listOfActiveFormattingElements[i]) {
- return i;
- }
- }
- return -1;
- }
-
- private int findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
- @Local String name) {
- for (int i = listPtr; i >= 0; i--) {
- StackNode<T> node = listOfActiveFormattingElements[i];
- if (node == null) {
- return -1;
- } else if (node.name == name) {
- return i;
- }
- }
- return -1;
- }
-
-
- private void maybeForgetEarlierDuplicateFormattingElement(
- @Local String name, HtmlAttributes attributes) throws SAXException {
- int candidate = -1;
- int count = 0;
- for (int i = listPtr; i >= 0; i--) {
- StackNode<T> node = listOfActiveFormattingElements[i];
- if (node == null) {
- break;
- }
- if (node.name == name && node.attributes.equalsAnother(attributes)) {
- candidate = i;
- ++count;
- }
- }
- if (count >= 3) {
- removeFromListOfActiveFormattingElements(candidate);
- }
- }
-
- private int findLastOrRoot(@Local String name) {
- for (int i = currentPtr; i > 0; i--) {
- if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) {
- return i;
- }
- }
- return 0;
- }
-
- private int findLastOrRoot(int group) {
- for (int i = currentPtr; i > 0; i--) {
- if (stack[i].getGroup() == group) {
- return i;
- }
- }
- return 0;
- }
-
- /**
- * Attempt to add attribute to the body element.
- * @param attributes the attributes
- * @return <code>true</code> iff the attributes were added
- * @throws SAXException
- */
- private boolean addAttributesToBody(HtmlAttributes attributes)
- throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- if (currentPtr >= 1) {
- StackNode<T> body = stack[1];
- if (body.getGroup() == TreeBuilder.BODY) {
- addAttributesToElement(body.node, attributes);
- return true;
- }
- }
- return false;
- }
-
- private void addAttributesToHtml(HtmlAttributes attributes)
- throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- addAttributesToElement(stack[0].node, attributes);
- }
-
- private void pushHeadPointerOntoStack() throws SAXException {
- assert headPointer != null;
- assert mode == AFTER_HEAD;
- fatal();
- silentPush(new StackNode<T>(ElementName.HEAD, headPointer
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- ));
- }
-
- /**
- * @throws SAXException
- *
- */
- private void reconstructTheActiveFormattingElements() throws SAXException {
- if (listPtr == -1) {
- return;
- }
- StackNode<T> mostRecent = listOfActiveFormattingElements[listPtr];
- if (mostRecent == null || isInStack(mostRecent)) {
- return;
- }
- int entryPos = listPtr;
- for (;;) {
- entryPos--;
- if (entryPos == -1) {
- break;
- }
- if (listOfActiveFormattingElements[entryPos] == null) {
- break;
- }
- if (isInStack(listOfActiveFormattingElements[entryPos])) {
- break;
- }
- }
- while (entryPos < listPtr) {
- entryPos++;
- StackNode<T> entry = listOfActiveFormattingElements[entryPos];
- StackNode<T> currentNode = stack[currentPtr];
-
- T clone;
- if (currentNode.isFosterParenting()) {
- clone = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", entry.name,
- entry.attributes.cloneAttributes(null));
- } else {
- clone = createElement("http://www.w3.org/1999/xhtml", entry.name,
- entry.attributes.cloneAttributes(null), currentNode.node);
- appendElement(clone, currentNode.node);
- }
-
- StackNode<T> entryClone = new StackNode<T>(entry.getFlags(),
- entry.ns, entry.name, clone, entry.popName,
- entry.attributes
- // [NOCPP[
- , entry.getLocator()
- // ]NOCPP]
- );
-
- entry.dropAttributes(); // transfer ownership to entryClone
-
- push(entryClone);
- // stack takes ownership of the local variable
- listOfActiveFormattingElements[entryPos] = entryClone;
- // overwriting the old entry on the list, so release & retain
- entry.release();
- entryClone.retain();
- }
- }
-
- private void insertIntoFosterParent(T child) throws SAXException {
- int tablePos = findLastOrRoot(TreeBuilder.TABLE);
- int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE);
-
- if (templatePos >= tablePos) {
- appendElement(child, stack[templatePos].node);
- return;
- }
-
- StackNode<T> node = stack[tablePos];
- insertFosterParentedChild(child, node.node, stack[tablePos - 1].node);
- }
-
- private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
- HtmlAttributes attributes) throws SAXException {
- return createAndInsertFosterParentedElement(ns, name, attributes, null);
- }
-
- private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
- HtmlAttributes attributes, T form) throws SAXException {
- int tablePos = findLastOrRoot(TreeBuilder.TABLE);
- int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE);
-
- if (templatePos >= tablePos) {
- T child = createElement(ns, name, attributes, form, stack[templatePos].node);
- appendElement(child, stack[templatePos].node);
- return child;
- }
-
- StackNode<T> node = stack[tablePos];
- return createAndInsertFosterParentedElement(ns, name, attributes, form, node.node, stack[tablePos - 1].node);
- }
-
- private boolean isInStack(StackNode<T> node) {
- for (int i = currentPtr; i >= 0; i--) {
- if (stack[i] == node) {
- return true;
- }
- }
- return false;
- }
-
- private void popTemplateMode() {
- templateModePtr--;
- }
-
- private void pop() throws SAXException {
- StackNode<T> node = stack[currentPtr];
- assert debugOnlyClearLastStackSlot();
- currentPtr--;
- elementPopped(node.ns, node.popName, node.node);
- node.release();
- }
-
- private void silentPop() throws SAXException {
- StackNode<T> node = stack[currentPtr];
- assert debugOnlyClearLastStackSlot();
- currentPtr--;
- node.release();
- }
-
- private void popOnEof() throws SAXException {
- StackNode<T> node = stack[currentPtr];
- assert debugOnlyClearLastStackSlot();
- currentPtr--;
- markMalformedIfScript(node.node);
- elementPopped(node.ns, node.popName, node.node);
- node.release();
- }
-
- // [NOCPP[
- private void checkAttributes(HtmlAttributes attributes, @NsUri String ns)
- throws SAXException {
- if (errorHandler != null) {
- int len = attributes.getXmlnsLength();
- for (int i = 0; i < len; i++) {
- AttributeName name = attributes.getXmlnsAttributeName(i);
- if (name == AttributeName.XMLNS) {
- if (html4) {
- err("Attribute \u201Cxmlns\u201D not allowed here. (HTML4-only error.)");
- } else {
- String xmlns = attributes.getXmlnsValue(i);
- if (!ns.equals(xmlns)) {
- err("Bad value \u201C"
- + xmlns
- + "\u201D for the attribute \u201Cxmlns\u201D (only \u201C"
- + ns + "\u201D permitted here).");
- switch (namePolicy) {
- case ALTER_INFOSET:
- // fall through
- case ALLOW:
- warn("Attribute \u201Cxmlns\u201D is not serializable as XML 1.0.");
- break;
- case FATAL:
- fatal("Attribute \u201Cxmlns\u201D is not serializable as XML 1.0.");
- break;
- }
- }
- }
- } else if (ns != "http://www.w3.org/1999/xhtml"
- && name == AttributeName.XMLNS_XLINK) {
- String xmlns = attributes.getXmlnsValue(i);
- if (!"http://www.w3.org/1999/xlink".equals(xmlns)) {
- err("Bad value \u201C"
- + xmlns
- + "\u201D for the attribute \u201Cxmlns:link\u201D (only \u201Chttp://www.w3.org/1999/xlink\u201D permitted here).");
- switch (namePolicy) {
- case ALTER_INFOSET:
- // fall through
- case ALLOW:
- warn("Attribute \u201Cxmlns:xlink\u201D with a value other than \u201Chttp://www.w3.org/1999/xlink\u201D is not serializable as XML 1.0 without changing document semantics.");
- break;
- case FATAL:
- fatal("Attribute \u201Cxmlns:xlink\u201D with a value other than \u201Chttp://www.w3.org/1999/xlink\u201D is not serializable as XML 1.0 without changing document semantics.");
- break;
- }
- }
- } else {
- err("Attribute \u201C" + attributes.getXmlnsLocalName(i)
- + "\u201D not allowed here.");
- switch (namePolicy) {
- case ALTER_INFOSET:
- // fall through
- case ALLOW:
- warn("Attribute with the local name \u201C"
- + attributes.getXmlnsLocalName(i)
- + "\u201D is not serializable as XML 1.0.");
- break;
- case FATAL:
- fatal("Attribute with the local name \u201C"
- + attributes.getXmlnsLocalName(i)
- + "\u201D is not serializable as XML 1.0.");
- break;
- }
- }
- }
- }
- attributes.processNonNcNames(this, namePolicy);
- }
-
- private String checkPopName(@Local String name) throws SAXException {
- if (NCName.isNCName(name)) {
- return name;
- } else {
- switch (namePolicy) {
- case ALLOW:
- warn("Element name \u201C" + name
- + "\u201D cannot be represented as XML 1.0.");
- return name;
- case ALTER_INFOSET:
- warn("Element name \u201C" + name
- + "\u201D cannot be represented as XML 1.0.");
- return NCName.escapeName(name);
- case FATAL:
- fatal("Element name \u201C" + name
- + "\u201D cannot be represented as XML 1.0.");
- }
- }
- return null; // keep compiler happy
- }
-
- // ]NOCPP]
-
- private void appendHtmlElementToDocumentAndPush(HtmlAttributes attributes)
- throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- T elt = createHtmlElementSetAsRoot(attributes);
- StackNode<T> node = new StackNode<T>(ElementName.HTML,
- elt
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- push(node);
- }
-
- private void appendHtmlElementToDocumentAndPush() throws SAXException {
- appendHtmlElementToDocumentAndPush(tokenizer.emptyAttributes());
- }
-
- private void appendToCurrentNodeAndPushHeadElement(HtmlAttributes attributes)
- throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- T currentNode = stack[currentPtr].node;
- T elt = createElement("http://www.w3.org/1999/xhtml", "head", attributes, currentNode);
- appendElement(elt, currentNode);
- headPointer = elt;
- StackNode<T> node = new StackNode<T>(ElementName.HEAD,
- elt
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- push(node);
- }
-
- private void appendToCurrentNodeAndPushBodyElement(HtmlAttributes attributes)
- throws SAXException {
- appendToCurrentNodeAndPushElement(ElementName.BODY,
- attributes);
- }
-
- private void appendToCurrentNodeAndPushBodyElement() throws SAXException {
- appendToCurrentNodeAndPushBodyElement(tokenizer.emptyAttributes());
- }
-
- private void appendToCurrentNodeAndPushFormElementMayFoster(
- HtmlAttributes attributes) throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
-
- T elt;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", "form", attributes);
- } else {
- elt = createElement("http://www.w3.org/1999/xhtml", "form", attributes, current.node);
- appendElement(elt, current.node);
- }
-
- if (!isTemplateContents()) {
- formPointer = elt;
- }
-
- StackNode<T> node = new StackNode<T>(ElementName.FORM,
- elt
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- push(node);
- }
-
- private void appendToCurrentNodeAndPushFormattingElementMayFoster(
- ElementName elementName, HtmlAttributes attributes)
- throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- // This method can't be called for custom elements
- HtmlAttributes clone = attributes.cloneAttributes(null);
- // Attributes must not be read after calling createElement, because
- // createElement may delete attributes in C++.
- T elt;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name, attributes);
- } else {
- elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, current.node);
- appendElement(elt, current.node);
- }
- StackNode<T> node = new StackNode<T>(elementName, elt, clone
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- push(node);
- append(node);
- node.retain(); // append doesn't retain itself
- }
-
- private void appendToCurrentNodeAndPushElement(ElementName elementName,
- HtmlAttributes attributes)
- throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- // This method can't be called for custom elements
- T currentNode = stack[currentPtr].node;
- T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, currentNode);
- appendElement(elt, currentNode);
- if (ElementName.TEMPLATE == elementName) {
- elt = getDocumentFragmentForTemplate(elt);
- }
- StackNode<T> node = new StackNode<T>(elementName, elt
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- push(node);
- }
-
- private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName,
- HtmlAttributes attributes)
- throws SAXException {
- @Local String popName = elementName.name;
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- if (elementName.isCustom()) {
- popName = checkPopName(popName);
- }
- // ]NOCPP]
- T elt;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes);
- } else {
- elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node);
- appendElement(elt, current.node);
- }
- StackNode<T> node = new StackNode<T>(elementName, elt, popName
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- push(node);
- }
-
- private void appendToCurrentNodeAndPushElementMayFosterMathML(
- ElementName elementName, HtmlAttributes attributes)
- throws SAXException {
- @Local String popName = elementName.name;
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML");
- if (elementName.isCustom()) {
- popName = checkPopName(popName);
- }
- // ]NOCPP]
- boolean markAsHtmlIntegrationPoint = false;
- if (ElementName.ANNOTATION_XML == elementName
- && annotationXmlEncodingPermitsHtml(attributes)) {
- markAsHtmlIntegrationPoint = true;
- }
- // Attributes must not be read after calling createElement(), since
- // createElement may delete the object in C++.
- T elt;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
- } else {
- elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node);
- appendElement(elt, current.node);
- }
- StackNode<T> node = new StackNode<T>(elementName, elt, popName,
- markAsHtmlIntegrationPoint
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- push(node);
- }
-
- // [NOCPP[
- T getDocumentFragmentForTemplate(T template) {
- return template;
- }
-
- T getFormPointerForContext(T context) {
- return null;
- }
- // ]NOCPP]
-
- private boolean annotationXmlEncodingPermitsHtml(HtmlAttributes attributes) {
- String encoding = attributes.getValue(AttributeName.ENCODING);
- if (encoding == null) {
- return false;
- }
- return Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "application/xhtml+xml", encoding)
- || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
- "text/html", encoding);
- }
-
- private void appendToCurrentNodeAndPushElementMayFosterSVG(
- ElementName elementName, HtmlAttributes attributes)
- throws SAXException {
- @Local String popName = elementName.camelCaseName;
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/2000/svg");
- if (elementName.isCustom()) {
- popName = checkPopName(popName);
- }
- // ]NOCPP]
- T elt;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes);
- } else {
- elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node);
- appendElement(elt, current.node);
- }
- StackNode<T> node = new StackNode<T>(elementName, popName, elt
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- push(node);
- }
-
- private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName,
- HtmlAttributes attributes, T form)
- throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- // Can't be called for custom elements
- T elt;
- T formOwner = form == null || fragment || isTemplateContents() ? null : form;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name,
- attributes, formOwner);
- } else {
- elt = createElement("http://www.w3.org/1999/xhtml", elementName.name,
- attributes, formOwner, current.node);
- appendElement(elt, current.node);
- }
- StackNode<T> node = new StackNode<T>(elementName, elt
- // [NOCPP[
- , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
- );
- push(node);
- }
-
- private void appendVoidElementToCurrentMayFoster(
- @Local String name, HtmlAttributes attributes, T form) throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- // Can't be called for custom elements
- T elt;
- T formOwner = form == null || fragment || isTemplateContents() ? null : form;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", name,
- attributes, formOwner);
- } else {
- elt = createElement("http://www.w3.org/1999/xhtml", name,
- attributes, formOwner, current.node);
- appendElement(elt, current.node);
- }
- elementPushed("http://www.w3.org/1999/xhtml", name, elt);
- elementPopped("http://www.w3.org/1999/xhtml", name, elt);
- }
-
- private void appendVoidElementToCurrentMayFoster(
- ElementName elementName, HtmlAttributes attributes)
- throws SAXException {
- @Local String popName = elementName.name;
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- if (elementName.isCustom()) {
- popName = checkPopName(popName);
- }
- // ]NOCPP]
- T elt;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes);
- } else {
- elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node);
- appendElement(elt, current.node);
- }
- elementPushed("http://www.w3.org/1999/xhtml", popName, elt);
- elementPopped("http://www.w3.org/1999/xhtml", popName, elt);
- }
-
- private void appendVoidElementToCurrentMayFosterSVG(
- ElementName elementName, HtmlAttributes attributes)
- throws SAXException {
- @Local String popName = elementName.camelCaseName;
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/2000/svg");
- if (elementName.isCustom()) {
- popName = checkPopName(popName);
- }
- // ]NOCPP]
- T elt;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes);
- } else {
- elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node);
- appendElement(elt, current.node);
- }
- elementPushed("http://www.w3.org/2000/svg", popName, elt);
- elementPopped("http://www.w3.org/2000/svg", popName, elt);
- }
-
- private void appendVoidElementToCurrentMayFosterMathML(
- ElementName elementName, HtmlAttributes attributes)
- throws SAXException {
- @Local String popName = elementName.name;
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML");
- if (elementName.isCustom()) {
- popName = checkPopName(popName);
- }
- // ]NOCPP]
- T elt;
- StackNode<T> current = stack[currentPtr];
- if (current.isFosterParenting()) {
- fatal();
- elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
- } else {
- elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node);
- appendElement(elt, current.node);
- }
- elementPushed("http://www.w3.org/1998/Math/MathML", popName, elt);
- elementPopped("http://www.w3.org/1998/Math/MathML", popName, elt);
- }
-
- private void appendVoidElementToCurrent(
- @Local String name, HtmlAttributes attributes, T form) throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- // Can't be called for custom elements
- T currentNode = stack[currentPtr].node;
- T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes,
- form == null || fragment || isTemplateContents() ? null : form, currentNode);
- appendElement(elt, currentNode);
- elementPushed("http://www.w3.org/1999/xhtml", name, elt);
- elementPopped("http://www.w3.org/1999/xhtml", name, elt);
- }
-
- private void appendVoidFormToCurrent(HtmlAttributes attributes) throws SAXException {
- // [NOCPP[
- checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
- // ]NOCPP]
- T currentNode = stack[currentPtr].node;
- T elt = createElement("http://www.w3.org/1999/xhtml", "form",
- attributes, currentNode);
- formPointer = elt;
- // ownership transferred to form pointer
- appendElement(elt, currentNode);
- elementPushed("http://www.w3.org/1999/xhtml", "form", elt);
- elementPopped("http://www.w3.org/1999/xhtml", "form", elt);
- }
-
- // [NOCPP[
-
- private final void accumulateCharactersForced(@Const @NoLength char[] buf,
- int start, int length) throws SAXException {
- System.arraycopy(buf, start, charBuffer, charBufferLen, length);
- charBufferLen += length;
- }
-
- @Override public void ensureBufferSpace(int inputLength)
- throws SAXException {
- // TODO: Unify Tokenizer.strBuf and TreeBuilder.charBuffer so that
- // this method becomes unnecessary.
- int worstCase = charBufferLen + inputLength;
- if (charBuffer == null) {
- // Add an arbitrary small value to avoid immediate reallocation
- // once there are a few characters in the buffer.
- charBuffer = new char[worstCase + 128];
- } else if (worstCase > charBuffer.length) {
- // HotSpot reportedly allocates memory with 8-byte accuracy, so
- // there's no point in trying to do math here to avoid slop.
- // Maybe we should add some small constant to worstCase here
- // but not doing that without profiling. In C++ with jemalloc,
- // the corresponding method should do math to round up here
- // to avoid slop.
- char[] newBuf = new char[worstCase];
- System.arraycopy(charBuffer, 0, newBuf, 0, charBufferLen);
- charBuffer = newBuf;
- }
- }
-
- // ]NOCPP]
-
- protected void accumulateCharacters(@Const @NoLength char[] buf, int start,
- int length) throws SAXException {
- appendCharacters(stack[currentPtr].node, buf, start, length);
- }
-
- // ------------------------------- //
-
- protected final void requestSuspension() {
- tokenizer.requestSuspension();
- }
-
- protected abstract T createElement(@NsUri String ns, @Local String name,
- HtmlAttributes attributes, T intendedParent) throws SAXException;
-
- protected T createElement(@NsUri String ns, @Local String name,
- HtmlAttributes attributes, T form, T intendedParent) throws SAXException {
- return createElement("http://www.w3.org/1999/xhtml", name, attributes, intendedParent);
- }
-
- protected abstract T createHtmlElementSetAsRoot(HtmlAttributes attributes)
- throws SAXException;
-
- protected abstract void detachFromParent(T element) throws SAXException;
-
- protected abstract boolean hasChildren(T element) throws SAXException;
-
- protected abstract void appendElement(T child, T newParent)
- throws SAXException;
-
- protected abstract void appendChildrenToNewParent(T oldParent, T newParent)
- throws SAXException;
-
- protected abstract void insertFosterParentedChild(T child, T table,
- T stackParent) throws SAXException;
-
- // We don't generate CPP code for this method because it is not used in generated CPP
- // code. Instead, the form owner version of this method is called with a null form owner.
- // [NOCPP[
-
- protected abstract T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
- HtmlAttributes attributes, T table, T stackParent) throws SAXException;
-
- // ]NOCPP]
-
- protected T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
- HtmlAttributes attributes, T form, T table, T stackParent) throws SAXException {
- return createAndInsertFosterParentedElement(ns, name, attributes, table, stackParent);
- };
-
- protected abstract void insertFosterParentedCharacters(
- @NoLength char[] buf, int start, int length, T table, T stackParent)
- throws SAXException;
-
- protected abstract void appendCharacters(T parent, @NoLength char[] buf,
- int start, int length) throws SAXException;
-
- protected abstract void appendIsindexPrompt(T parent) throws SAXException;
-
- protected abstract void appendComment(T parent, @NoLength char[] buf,
- int start, int length) throws SAXException;
-
- protected abstract void appendCommentToDocument(@NoLength char[] buf,
- int start, int length) throws SAXException;
-
- protected abstract void addAttributesToElement(T element,
- HtmlAttributes attributes) throws SAXException;
-
- protected void markMalformedIfScript(T elt) throws SAXException {
-
- }
-
- protected void start(boolean fragmentMode) throws SAXException {
-
- }
-
- protected void end() throws SAXException {
-
- }
-
- protected void appendDoctypeToDocument(@Local String name,
- String publicIdentifier, String systemIdentifier)
- throws SAXException {
-
- }
-
- protected void elementPushed(@NsUri String ns, @Local String name, T node)
- throws SAXException {
-
- }
-
- protected void elementPopped(@NsUri String ns, @Local String name, T node)
- throws SAXException {
-
- }
-
- // [NOCPP[
-
- protected void documentMode(DocumentMode m, String publicIdentifier,
- String systemIdentifier, boolean html4SpecificAdditionalErrorChecks)
- throws SAXException {
-
- }
-
- /**
- * @see nu.validator.htmlparser.common.TokenHandler#wantsComments()
- */
- public boolean wantsComments() {
- return wantingComments;
- }
-
- public void setIgnoringComments(boolean ignoreComments) {
- wantingComments = !ignoreComments;
- }
-
- /**
- * Sets the errorHandler.
- *
- * @param errorHandler
- * the errorHandler to set
- */
- public final void setErrorHandler(ErrorHandler errorHandler) {
- this.errorHandler = errorHandler;
- }
-
- /**
- * Returns the errorHandler.
- *
- * @return the errorHandler
- */
- public ErrorHandler getErrorHandler() {
- return errorHandler;
- }
-
- /**
- * The argument MUST be an interned string or <code>null</code>.
- *
- * @param context
- */
- public final void setFragmentContext(@Local String context) {
- this.contextName = context;
- this.contextNamespace = "http://www.w3.org/1999/xhtml";
- this.contextNode = null;
- this.fragment = (contextName != null);
- this.quirks = false;
- }
-
- // ]NOCPP]
-
- /**
- * @see nu.validator.htmlparser.common.TokenHandler#cdataSectionAllowed()
- */
- @Inline public boolean cdataSectionAllowed() throws SAXException {
- return isInForeign();
- }
-
- private boolean isInForeign() {
- return currentPtr >= 0
- && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml";
- }
-
- private boolean isInForeignButNotHtmlOrMathTextIntegrationPoint() {
- if (currentPtr < 0) {
- return false;
- }
- return !isSpecialParentInForeign(stack[currentPtr]);
- }
-
- /**
- * The argument MUST be an interned string or <code>null</code>.
- *
- * @param context
- */
- public final void setFragmentContext(@Local String context,
- @NsUri String ns, T node, boolean quirks) {
- // [NOCPP[
- if (!((context == null && ns == null)
- || "http://www.w3.org/1999/xhtml" == ns
- || "http://www.w3.org/2000/svg" == ns || "http://www.w3.org/1998/Math/MathML" == ns)) {
- throw new IllegalArgumentException(
- "The namespace must be the HTML, SVG or MathML namespace (or null when the local name is null). Got: "
- + ns);
- }
- // ]NOCPP]
- this.contextName = context;
- this.contextNamespace = ns;
- this.contextNode = node;
- this.fragment = (contextName != null);
- this.quirks = quirks;
- }
-
- protected final T currentNode() {
- return stack[currentPtr].node;
- }
-
- /**
- * Returns the scriptingEnabled.
- *
- * @return the scriptingEnabled
- */
- public boolean isScriptingEnabled() {
- return scriptingEnabled;
- }
-
- /**
- * Sets the scriptingEnabled.
- *
- * @param scriptingEnabled
- * the scriptingEnabled to set
- */
- public void setScriptingEnabled(boolean scriptingEnabled) {
- this.scriptingEnabled = scriptingEnabled;
- }
-
- public void setIsSrcdocDocument(boolean isSrcdocDocument) {
- this.isSrcdocDocument = isSrcdocDocument;
- }
-
- // [NOCPP[
-
- /**
- * Sets the doctypeExpectation.
- *
- * @param doctypeExpectation
- * the doctypeExpectation to set
- */
- public void setDoctypeExpectation(DoctypeExpectation doctypeExpectation) {
- this.doctypeExpectation = doctypeExpectation;
- }
-
- public void setNamePolicy(XmlViolationPolicy namePolicy) {
- this.namePolicy = namePolicy;
- }
-
- /**
- * Sets the documentModeHandler.
- *
- * @param documentModeHandler
- * the documentModeHandler to set
- */
- public void setDocumentModeHandler(DocumentModeHandler documentModeHandler) {
- this.documentModeHandler = documentModeHandler;
- }
-
- /**
- * Sets the reportingDoctype.
- *
- * @param reportingDoctype
- * the reportingDoctype to set
- */
- public void setReportingDoctype(boolean reportingDoctype) {
- this.reportingDoctype = reportingDoctype;
- }
-
- // ]NOCPP]
-
- /**
- * Flushes the pending characters. Public for document.write use cases only.
- * @throws SAXException
- */
- public final void flushCharacters() throws SAXException {
- if (charBufferLen > 0) {
- if ((mode == IN_TABLE || mode == IN_TABLE_BODY || mode == IN_ROW)
- && charBufferContainsNonWhitespace()) {
- errNonSpaceInTable();
- reconstructTheActiveFormattingElements();
- if (!stack[currentPtr].isFosterParenting()) {
- // reconstructing gave us a new current node
- appendCharacters(currentNode(), charBuffer, 0,
- charBufferLen);
- charBufferLen = 0;
- return;
- }
-
- int tablePos = findLastOrRoot(TreeBuilder.TABLE);
- int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE);
-
- if (templatePos >= tablePos) {
- appendCharacters(stack[templatePos].node, charBuffer, 0, charBufferLen);
- charBufferLen = 0;
- return;
- }
-
- StackNode<T> tableElt = stack[tablePos];
- insertFosterParentedCharacters(charBuffer, 0, charBufferLen,
- tableElt.node, stack[tablePos - 1].node);
- charBufferLen = 0;
- return;
- }
- appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
- charBufferLen = 0;
- }
- }
-
- private boolean charBufferContainsNonWhitespace() {
- for (int i = 0; i < charBufferLen; i++) {
- switch (charBuffer[i]) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '\u000C':
- continue;
- default:
- return true;
- }
- }
- return false;
- }
-
- /**
- * Creates a comparable snapshot of the tree builder state. Snapshot
- * creation is only supported immediately after a script end tag has been
- * processed. In C++ the caller is responsible for calling
- * <code>delete</code> on the returned object.
- *
- * @return a snapshot.
- * @throws SAXException
- */
- @SuppressWarnings("unchecked") public TreeBuilderState<T> newSnapshot()
- throws SAXException {
- StackNode<T>[] listCopy = new StackNode[listPtr + 1];
- for (int i = 0; i < listCopy.length; i++) {
- StackNode<T> node = listOfActiveFormattingElements[i];
- if (node != null) {
- StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
- node.name, node.node, node.popName,
- node.attributes.cloneAttributes(null)
- // [NOCPP[
- , node.getLocator()
- // ]NOCPP]
- );
- listCopy[i] = newNode;
- } else {
- listCopy[i] = null;
- }
- }
- StackNode<T>[] stackCopy = new StackNode[currentPtr + 1];
- for (int i = 0; i < stackCopy.length; i++) {
- StackNode<T> node = stack[i];
- int listIndex = findInListOfActiveFormattingElements(node);
- if (listIndex == -1) {
- StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
- node.name, node.node, node.popName,
- null
- // [NOCPP[
- , node.getLocator()
- // ]NOCPP]
- );
- stackCopy[i] = newNode;
- } else {
- stackCopy[i] = listCopy[listIndex];
- stackCopy[i].retain();
- }
- }
- int[] templateModeStackCopy = new int[templateModePtr + 1];
- System.arraycopy(templateModeStack, 0, templateModeStackCopy, 0,
- templateModeStackCopy.length);
- return new StateSnapshot<T>(stackCopy, listCopy, templateModeStackCopy, formPointer,
- headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk,
- needToDropLF, quirks);
- }
-
- public boolean snapshotMatches(TreeBuilderState<T> snapshot) {
- StackNode<T>[] stackCopy = snapshot.getStack();
- int stackLen = snapshot.getStackLength();
- StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements();
- int listLen = snapshot.getListOfActiveFormattingElementsLength();
- int[] templateModeStackCopy = snapshot.getTemplateModeStack();
- int templateModeStackLen = snapshot.getTemplateModeStackLength();
-
- if (stackLen != currentPtr + 1
- || listLen != listPtr + 1
- || templateModeStackLen != templateModePtr + 1
- || formPointer != snapshot.getFormPointer()
- || headPointer != snapshot.getHeadPointer()
- || deepTreeSurrogateParent != snapshot.getDeepTreeSurrogateParent()
- || mode != snapshot.getMode()
- || originalMode != snapshot.getOriginalMode()
- || framesetOk != snapshot.isFramesetOk()
- || needToDropLF != snapshot.isNeedToDropLF()
- || quirks != snapshot.isQuirks()) { // maybe just assert quirks
- return false;
- }
- for (int i = listLen - 1; i >= 0; i--) {
- if (listCopy[i] == null
- && listOfActiveFormattingElements[i] == null) {
- continue;
- } else if (listCopy[i] == null
- || listOfActiveFormattingElements[i] == null) {
- return false;
- }
- if (listCopy[i].node != listOfActiveFormattingElements[i].node) {
- return false; // it's possible that this condition is overly
- // strict
- }
- }
- for (int i = stackLen - 1; i >= 0; i--) {
- if (stackCopy[i].node != stack[i].node) {
- return false;
- }
- }
- for (int i = templateModeStackLen - 1; i >=0; i--) {
- if (templateModeStackCopy[i] != templateModeStack[i]) {
- return false;
- }
- }
- return true;
- }
-
- @SuppressWarnings("unchecked") public void loadState(
- TreeBuilderState<T> snapshot, Interner interner)
- throws SAXException {
- StackNode<T>[] stackCopy = snapshot.getStack();
- int stackLen = snapshot.getStackLength();
- StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements();
- int listLen = snapshot.getListOfActiveFormattingElementsLength();
- int[] templateModeStackCopy = snapshot.getTemplateModeStack();
- int templateModeStackLen = snapshot.getTemplateModeStackLength();
-
- for (int i = 0; i <= listPtr; i++) {
- if (listOfActiveFormattingElements[i] != null) {
- listOfActiveFormattingElements[i].release();
- }
- }
- if (listOfActiveFormattingElements.length < listLen) {
- listOfActiveFormattingElements = new StackNode[listLen];
- }
- listPtr = listLen - 1;
-
- for (int i = 0; i <= currentPtr; i++) {
- stack[i].release();
- }
- if (stack.length < stackLen) {
- stack = new StackNode[stackLen];
- }
- currentPtr = stackLen - 1;
-
- if (templateModeStack.length < templateModeStackLen) {
- templateModeStack = new int[templateModeStackLen];
- }
- templateModePtr = templateModeStackLen - 1;
-
- for (int i = 0; i < listLen; i++) {
- StackNode<T> node = listCopy[i];
- if (node != null) {
- StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
- Portability.newLocalFromLocal(node.name, interner), node.node,
- Portability.newLocalFromLocal(node.popName, interner),
- node.attributes.cloneAttributes(null)
- // [NOCPP[
- , node.getLocator()
- // ]NOCPP]
- );
- listOfActiveFormattingElements[i] = newNode;
- } else {
- listOfActiveFormattingElements[i] = null;
- }
- }
- for (int i = 0; i < stackLen; i++) {
- StackNode<T> node = stackCopy[i];
- int listIndex = findInArray(node, listCopy);
- if (listIndex == -1) {
- StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
- Portability.newLocalFromLocal(node.name, interner), node.node,
- Portability.newLocalFromLocal(node.popName, interner),
- null
- // [NOCPP[
- , node.getLocator()
- // ]NOCPP]
- );
- stack[i] = newNode;
- } else {
- stack[i] = listOfActiveFormattingElements[listIndex];
- stack[i].retain();
- }
- }
- System.arraycopy(templateModeStackCopy, 0, templateModeStack, 0, templateModeStackLen);
- formPointer = snapshot.getFormPointer();
- headPointer = snapshot.getHeadPointer();
- deepTreeSurrogateParent = snapshot.getDeepTreeSurrogateParent();
- mode = snapshot.getMode();
- originalMode = snapshot.getOriginalMode();
- framesetOk = snapshot.isFramesetOk();
- needToDropLF = snapshot.isNeedToDropLF();
- quirks = snapshot.isQuirks();
- }
-
- private int findInArray(StackNode<T> node, StackNode<T>[] arr) {
- for (int i = listPtr; i >= 0; i--) {
- if (node == arr[i]) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * @see nu.validator.htmlparser.impl.TreeBuilderState#getFormPointer()
- */
- public T getFormPointer() {
- return formPointer;
- }
-
- /**
- * Returns the headPointer.
- *
- * @return the headPointer
- */
- public T getHeadPointer() {
- return headPointer;
- }
-
- /**
- * Returns the deepTreeSurrogateParent.
- *
- * @return the deepTreeSurrogateParent
- */
- public T getDeepTreeSurrogateParent() {
- return deepTreeSurrogateParent;
- }
-
- /**
- * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElements()
- */
- public StackNode<T>[] getListOfActiveFormattingElements() {
- return listOfActiveFormattingElements;
- }
-
- /**
- * @see nu.validator.htmlparser.impl.TreeBuilderState#getStack()
- */
- public StackNode<T>[] getStack() {
- return stack;
- }
-
- /**
- * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStack()
- */
- public int[] getTemplateModeStack() {
- return templateModeStack;
- }
-
- /**
- * Returns the mode.
- *
- * @return the mode
- */
- public int getMode() {
- return mode;
- }
-
- /**
- * Returns the originalMode.
- *
- * @return the originalMode
- */
- public int getOriginalMode() {
- return originalMode;
- }
-
- /**
- * Returns the framesetOk.
- *
- * @return the framesetOk
- */
- public boolean isFramesetOk() {
- return framesetOk;
- }
-
- /**
- * Returns the needToDropLF.
- *
- * @return the needToDropLF
- */
- public boolean isNeedToDropLF() {
- return needToDropLF;
- }
-
- /**
- * Returns the quirks.
- *
- * @return the quirks
- */
- public boolean isQuirks() {
- return quirks;
- }
-
- /**
- * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElementsLength()
- */
- public int getListOfActiveFormattingElementsLength() {
- return listPtr + 1;
- }
-
- /**
- * @see nu.validator.htmlparser.impl.TreeBuilderState#getStackLength()
- */
- public int getStackLength() {
- return currentPtr + 1;
- }
-
- /**
- * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStackLength()
- */
- public int getTemplateModeStackLength() {
- return templateModePtr + 1;
- }
-
- /**
- * Reports a stray start tag.
- * @param name the name of the stray tag
- *
- * @throws SAXException
- */
- private void errStrayStartTag(@Local String name) throws SAXException {
- err("Stray start tag \u201C" + name + "\u201D.");
- }
-
- /**
- * Reports a stray end tag.
- * @param name the name of the stray tag
- *
- * @throws SAXException
- */
- private void errStrayEndTag(@Local String name) throws SAXException {
- err("Stray end tag \u201C" + name + "\u201D.");
- }
-
- /**
- * Reports a state when elements expected to be closed were not.
- *
- * @param eltPos the position of the start tag on the stack of the element
- * being closed.
- * @param name the name of the end tag
- *
- * @throws SAXException
- */
- private void errUnclosedElements(int eltPos, @Local String name) throws SAXException {
- errNoCheck("End tag \u201C" + name + "\u201D seen, but there were open elements.");
- errListUnclosedStartTags(eltPos);
- }
-
- /**
- * Reports a state when elements expected to be closed ahead of an implied
- * end tag but were not.
- *
- * @param eltPos the position of the start tag on the stack of the element
- * being closed.
- * @param name the name of the end tag
- *
- * @throws SAXException
- */
- private void errUnclosedElementsImplied(int eltPos, String name) throws SAXException {
- errNoCheck("End tag \u201C" + name + "\u201D implied, but there were open elements.");
- errListUnclosedStartTags(eltPos);
- }
-
- /**
- * Reports a state when elements expected to be closed ahead of an implied
- * table cell close.
- *
- * @param eltPos the position of the start tag on the stack of the element
- * being closed.
- * @throws SAXException
- */
- private void errUnclosedElementsCell(int eltPos) throws SAXException {
- errNoCheck("A table cell was implicitly closed, but there were open elements.");
- errListUnclosedStartTags(eltPos);
- }
-
- private void errStrayDoctype() throws SAXException {
- err("Stray doctype.");
- }
-
- private void errAlmostStandardsDoctype() throws SAXException {
- if (!isSrcdocDocument) {
- err("Almost standards mode doctype. Expected \u201C<!DOCTYPE html>\u201D.");
- }
- }
-
- private void errQuirkyDoctype() throws SAXException {
- if (!isSrcdocDocument) {
- err("Quirky doctype. Expected \u201C<!DOCTYPE html>\u201D.");
- }
- }
-
- private void errNonSpaceInTrailer() throws SAXException {
- err("Non-space character in page trailer.");
- }
-
- private void errNonSpaceAfterFrameset() throws SAXException {
- err("Non-space after \u201Cframeset\u201D.");
- }
-
- private void errNonSpaceInFrameset() throws SAXException {
- err("Non-space in \u201Cframeset\u201D.");
- }
-
- private void errNonSpaceAfterBody() throws SAXException {
- err("Non-space character after body.");
- }
-
- private void errNonSpaceInColgroupInFragment() throws SAXException {
- err("Non-space in \u201Ccolgroup\u201D when parsing fragment.");
- }
-
- private void errNonSpaceInNoscriptInHead() throws SAXException {
- err("Non-space character inside \u201Cnoscript\u201D inside \u201Chead\u201D.");
- }
-
- private void errFooBetweenHeadAndBody(@Local String name) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("\u201C" + name + "\u201D element between \u201Chead\u201D and \u201Cbody\u201D.");
- }
-
- private void errStartTagWithoutDoctype() throws SAXException {
- if (!isSrcdocDocument) {
- err("Start tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D.");
- }
- }
-
- private void errNoSelectInTableScope() throws SAXException {
- err("No \u201Cselect\u201D in table scope.");
- }
-
- private void errStartSelectWhereEndSelectExpected() throws SAXException {
- err("\u201Cselect\u201D start tag where end tag expected.");
- }
-
- private void errStartTagWithSelectOpen(@Local String name)
- throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("\u201C" + name
- + "\u201D start tag with \u201Cselect\u201D open.");
- }
-
- private void errBadStartTagInHead(@Local String name) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("Bad start tag in \u201C" + name
- + "\u201D in \u201Chead\u201D.");
- }
-
- private void errImage() throws SAXException {
- err("Saw a start tag \u201Cimage\u201D.");
- }
-
- private void errIsindex() throws SAXException {
- err("\u201Cisindex\u201D seen.");
- }
-
- private void errFooSeenWhenFooOpen(@Local String name) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("An \u201C" + name + "\u201D start tag seen but an element of the same type was already open.");
- }
-
- private void errHeadingWhenHeadingOpen() throws SAXException {
- err("Heading cannot be a child of another heading.");
- }
-
- private void errFramesetStart() throws SAXException {
- err("\u201Cframeset\u201D start tag seen.");
- }
-
- private void errNoCellToClose() throws SAXException {
- err("No cell to close.");
- }
-
- private void errStartTagInTable(@Local String name) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("Start tag \u201C" + name
- + "\u201D seen in \u201Ctable\u201D.");
- }
-
- private void errFormWhenFormOpen() throws SAXException {
- err("Saw a \u201Cform\u201D start tag, but there was already an active \u201Cform\u201D element. Nested forms are not allowed. Ignoring the tag.");
- }
-
- private void errTableSeenWhileTableOpen() throws SAXException {
- err("Start tag for \u201Ctable\u201D seen but the previous \u201Ctable\u201D is still open.");
- }
-
- private void errStartTagInTableBody(@Local String name) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("\u201C" + name + "\u201D start tag in table body.");
- }
-
- private void errEndTagSeenWithoutDoctype() throws SAXException {
- if (!isSrcdocDocument) {
- err("End tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D.");
- }
- }
-
- private void errEndTagAfterBody() throws SAXException {
- err("Saw an end tag after \u201Cbody\u201D had been closed.");
- }
-
- private void errEndTagSeenWithSelectOpen(@Local String name) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("\u201C" + name
- + "\u201D end tag with \u201Cselect\u201D open.");
- }
-
- private void errGarbageInColgroup() throws SAXException {
- err("Garbage in \u201Ccolgroup\u201D fragment.");
- }
-
- private void errEndTagBr() throws SAXException {
- err("End tag \u201Cbr\u201D.");
- }
-
- private void errNoElementToCloseButEndTagSeen(@Local String name)
- throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("No \u201C" + name + "\u201D element in scope but a \u201C"
- + name + "\u201D end tag seen.");
- }
-
- private void errHtmlStartTagInForeignContext(@Local String name)
- throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("HTML start tag \u201C" + name
- + "\u201D in a foreign namespace context.");
- }
-
- private void errTableClosedWhileCaptionOpen() throws SAXException {
- err("\u201Ctable\u201D closed but \u201Ccaption\u201D was still open.");
- }
-
- private void errNoTableRowToClose() throws SAXException {
- err("No table row to close.");
- }
-
- private void errNonSpaceInTable() throws SAXException {
- err("Misplaced non-space characters insided a table.");
- }
-
- private void errUnclosedChildrenInRuby() throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("Unclosed children in \u201Cruby\u201D.");
- }
-
- private void errStartTagSeenWithoutRuby(@Local String name) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("Start tag \u201C"
- + name
- + "\u201D seen without a \u201Cruby\u201D element being open.");
- }
-
- private void errSelfClosing() throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("Self-closing syntax (\u201C/>\u201D) used on a non-void HTML element. Ignoring the slash and treating as a start tag.");
- }
-
- private void errNoCheckUnclosedElementsOnStack() throws SAXException {
- errNoCheck("Unclosed elements on stack.");
- }
-
- private void errEndTagDidNotMatchCurrentOpenElement(@Local String name,
- @Local String currOpenName) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("End tag \u201C"
- + name
- + "\u201D did not match the name of the current open element (\u201C"
- + currOpenName + "\u201D).");
- }
-
- private void errEndTagViolatesNestingRules(@Local String name) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("End tag \u201C" + name + "\u201D violates nesting rules.");
- }
-
- private void errEofWithUnclosedElements() throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("End of file seen and there were open elements.");
- // just report all remaining unclosed elements
- errListUnclosedStartTags(0);
- }
-
- /**
- * Reports arriving at/near end of document with unclosed elements remaining.
- *
- * @param message
- * the message
- * @throws SAXException
- */
- private void errEndWithUnclosedElements(@Local String name) throws SAXException {
- if (errorHandler == null) {
- return;
- }
- errNoCheck("End tag for \u201C"
- + name
- + "\u201D seen, but there were unclosed elements.");
- // just report all remaining unclosed elements
- errListUnclosedStartTags(0);
- }
-}