1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/parser/html/javasrc/TreeBuilder.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,6356 @@ 1.4 +/* 1.5 + * Copyright (c) 2007 Henri Sivonen 1.6 + * Copyright (c) 2007-2011 Mozilla Foundation 1.7 + * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla 1.8 + * Foundation, and Opera Software ASA. 1.9 + * 1.10 + * Permission is hereby granted, free of charge, to any person obtaining a 1.11 + * copy of this software and associated documentation files (the "Software"), 1.12 + * to deal in the Software without restriction, including without limitation 1.13 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1.14 + * and/or sell copies of the Software, and to permit persons to whom the 1.15 + * Software is furnished to do so, subject to the following conditions: 1.16 + * 1.17 + * The above copyright notice and this permission notice shall be included in 1.18 + * all copies or substantial portions of the Software. 1.19 + * 1.20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1.21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1.22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1.23 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1.24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1.25 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 1.26 + * DEALINGS IN THE SOFTWARE. 1.27 + */ 1.28 + 1.29 +/* 1.30 + * The comments following this one that use the same comment syntax as this 1.31 + * comment are quotes from the WHATWG HTML 5 spec as of 27 June 2007 1.32 + * amended as of June 28 2007. 1.33 + * That document came with this statement: 1.34 + * "© Copyright 2004-2007 Apple Computer, Inc., Mozilla Foundation, and 1.35 + * Opera Software ASA. You are granted a license to use, reproduce and 1.36 + * create derivative works of this document." 1.37 + */ 1.38 + 1.39 +package nu.validator.htmlparser.impl; 1.40 + 1.41 +import java.util.Arrays; 1.42 +import java.util.HashMap; 1.43 +import java.util.Map; 1.44 + 1.45 +import nu.validator.htmlparser.annotation.Auto; 1.46 +import nu.validator.htmlparser.annotation.Const; 1.47 +import nu.validator.htmlparser.annotation.IdType; 1.48 +import nu.validator.htmlparser.annotation.Inline; 1.49 +import nu.validator.htmlparser.annotation.Literal; 1.50 +import nu.validator.htmlparser.annotation.Local; 1.51 +import nu.validator.htmlparser.annotation.NoLength; 1.52 +import nu.validator.htmlparser.annotation.NsUri; 1.53 +import nu.validator.htmlparser.common.DoctypeExpectation; 1.54 +import nu.validator.htmlparser.common.DocumentMode; 1.55 +import nu.validator.htmlparser.common.DocumentModeHandler; 1.56 +import nu.validator.htmlparser.common.Interner; 1.57 +import nu.validator.htmlparser.common.TokenHandler; 1.58 +import nu.validator.htmlparser.common.XmlViolationPolicy; 1.59 + 1.60 +import org.xml.sax.ErrorHandler; 1.61 +import org.xml.sax.Locator; 1.62 +import org.xml.sax.SAXException; 1.63 +import org.xml.sax.SAXParseException; 1.64 + 1.65 +public abstract class TreeBuilder<T> implements TokenHandler, 1.66 + TreeBuilderState<T> { 1.67 + 1.68 + /** 1.69 + * Array version of U+FFFD. 1.70 + */ 1.71 + private static final @NoLength char[] REPLACEMENT_CHARACTER = { '\uFFFD' }; 1.72 + 1.73 + // Start dispatch groups 1.74 + 1.75 + final static int OTHER = 0; 1.76 + 1.77 + final static int A = 1; 1.78 + 1.79 + final static int BASE = 2; 1.80 + 1.81 + final static int BODY = 3; 1.82 + 1.83 + final static int BR = 4; 1.84 + 1.85 + final static int BUTTON = 5; 1.86 + 1.87 + final static int CAPTION = 6; 1.88 + 1.89 + final static int COL = 7; 1.90 + 1.91 + final static int COLGROUP = 8; 1.92 + 1.93 + final static int FORM = 9; 1.94 + 1.95 + final static int FRAME = 10; 1.96 + 1.97 + final static int FRAMESET = 11; 1.98 + 1.99 + final static int IMAGE = 12; 1.100 + 1.101 + final static int INPUT = 13; 1.102 + 1.103 + final static int ISINDEX = 14; 1.104 + 1.105 + final static int LI = 15; 1.106 + 1.107 + final static int LINK_OR_BASEFONT_OR_BGSOUND = 16; 1.108 + 1.109 + final static int MATH = 17; 1.110 + 1.111 + final static int META = 18; 1.112 + 1.113 + final static int SVG = 19; 1.114 + 1.115 + final static int HEAD = 20; 1.116 + 1.117 + final static int HR = 22; 1.118 + 1.119 + final static int HTML = 23; 1.120 + 1.121 + final static int NOBR = 24; 1.122 + 1.123 + final static int NOFRAMES = 25; 1.124 + 1.125 + final static int NOSCRIPT = 26; 1.126 + 1.127 + final static int OPTGROUP = 27; 1.128 + 1.129 + final static int OPTION = 28; 1.130 + 1.131 + final static int P = 29; 1.132 + 1.133 + final static int PLAINTEXT = 30; 1.134 + 1.135 + final static int SCRIPT = 31; 1.136 + 1.137 + final static int SELECT = 32; 1.138 + 1.139 + final static int STYLE = 33; 1.140 + 1.141 + final static int TABLE = 34; 1.142 + 1.143 + final static int TEXTAREA = 35; 1.144 + 1.145 + final static int TITLE = 36; 1.146 + 1.147 + final static int TR = 37; 1.148 + 1.149 + final static int XMP = 38; 1.150 + 1.151 + final static int TBODY_OR_THEAD_OR_TFOOT = 39; 1.152 + 1.153 + final static int TD_OR_TH = 40; 1.154 + 1.155 + final static int DD_OR_DT = 41; 1.156 + 1.157 + final static int H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 = 42; 1.158 + 1.159 + final static int MARQUEE_OR_APPLET = 43; 1.160 + 1.161 + final static int PRE_OR_LISTING = 44; 1.162 + 1.163 + 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; 1.164 + 1.165 + final static int UL_OR_OL_OR_DL = 46; 1.166 + 1.167 + final static int IFRAME = 47; 1.168 + 1.169 + final static int EMBED = 48; 1.170 + 1.171 + final static int AREA_OR_WBR = 49; 1.172 + 1.173 + final static int DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU = 50; 1.174 + 1.175 + 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; 1.176 + 1.177 + final static int RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR = 52; 1.178 + 1.179 + final static int RT_OR_RP = 53; 1.180 + 1.181 + final static int PARAM_OR_SOURCE_OR_TRACK = 55; 1.182 + 1.183 + final static int MGLYPH_OR_MALIGNMARK = 56; 1.184 + 1.185 + final static int MI_MO_MN_MS_MTEXT = 57; 1.186 + 1.187 + final static int ANNOTATION_XML = 58; 1.188 + 1.189 + final static int FOREIGNOBJECT_OR_DESC = 59; 1.190 + 1.191 + final static int NOEMBED = 60; 1.192 + 1.193 + final static int FIELDSET = 61; 1.194 + 1.195 + final static int OUTPUT_OR_LABEL = 62; 1.196 + 1.197 + final static int OBJECT = 63; 1.198 + 1.199 + final static int FONT = 64; 1.200 + 1.201 + final static int KEYGEN = 65; 1.202 + 1.203 + final static int MENUITEM = 66; 1.204 + 1.205 + final static int TEMPLATE = 67; 1.206 + 1.207 + final static int IMG = 68; 1.208 + 1.209 + // start insertion modes 1.210 + 1.211 + private static final int IN_ROW = 0; 1.212 + 1.213 + private static final int IN_TABLE_BODY = 1; 1.214 + 1.215 + private static final int IN_TABLE = 2; 1.216 + 1.217 + private static final int IN_CAPTION = 3; 1.218 + 1.219 + private static final int IN_CELL = 4; 1.220 + 1.221 + private static final int FRAMESET_OK = 5; 1.222 + 1.223 + private static final int IN_BODY = 6; 1.224 + 1.225 + private static final int IN_HEAD = 7; 1.226 + 1.227 + private static final int IN_HEAD_NOSCRIPT = 8; 1.228 + 1.229 + // no fall-through 1.230 + 1.231 + private static final int IN_COLUMN_GROUP = 9; 1.232 + 1.233 + // no fall-through 1.234 + 1.235 + private static final int IN_SELECT_IN_TABLE = 10; 1.236 + 1.237 + private static final int IN_SELECT = 11; 1.238 + 1.239 + // no fall-through 1.240 + 1.241 + private static final int AFTER_BODY = 12; 1.242 + 1.243 + // no fall-through 1.244 + 1.245 + private static final int IN_FRAMESET = 13; 1.246 + 1.247 + private static final int AFTER_FRAMESET = 14; 1.248 + 1.249 + // no fall-through 1.250 + 1.251 + private static final int INITIAL = 15; 1.252 + 1.253 + // could add fall-through 1.254 + 1.255 + private static final int BEFORE_HTML = 16; 1.256 + 1.257 + // could add fall-through 1.258 + 1.259 + private static final int BEFORE_HEAD = 17; 1.260 + 1.261 + // no fall-through 1.262 + 1.263 + private static final int AFTER_HEAD = 18; 1.264 + 1.265 + // no fall-through 1.266 + 1.267 + private static final int AFTER_AFTER_BODY = 19; 1.268 + 1.269 + // no fall-through 1.270 + 1.271 + private static final int AFTER_AFTER_FRAMESET = 20; 1.272 + 1.273 + // no fall-through 1.274 + 1.275 + private static final int TEXT = 21; 1.276 + 1.277 + private static final int IN_TEMPLATE = 22; 1.278 + 1.279 + // start charset states 1.280 + 1.281 + private static final int CHARSET_INITIAL = 0; 1.282 + 1.283 + private static final int CHARSET_C = 1; 1.284 + 1.285 + private static final int CHARSET_H = 2; 1.286 + 1.287 + private static final int CHARSET_A = 3; 1.288 + 1.289 + private static final int CHARSET_R = 4; 1.290 + 1.291 + private static final int CHARSET_S = 5; 1.292 + 1.293 + private static final int CHARSET_E = 6; 1.294 + 1.295 + private static final int CHARSET_T = 7; 1.296 + 1.297 + private static final int CHARSET_EQUALS = 8; 1.298 + 1.299 + private static final int CHARSET_SINGLE_QUOTED = 9; 1.300 + 1.301 + private static final int CHARSET_DOUBLE_QUOTED = 10; 1.302 + 1.303 + private static final int CHARSET_UNQUOTED = 11; 1.304 + 1.305 + // end pseudo enums 1.306 + 1.307 + // [NOCPP[ 1.308 + 1.309 + private final static String[] HTML4_PUBLIC_IDS = { 1.310 + "-//W3C//DTD HTML 4.0 Frameset//EN", 1.311 + "-//W3C//DTD HTML 4.0 Transitional//EN", 1.312 + "-//W3C//DTD HTML 4.0//EN", "-//W3C//DTD HTML 4.01 Frameset//EN", 1.313 + "-//W3C//DTD HTML 4.01 Transitional//EN", 1.314 + "-//W3C//DTD HTML 4.01//EN" }; 1.315 + 1.316 + // ]NOCPP] 1.317 + 1.318 + @Literal private final static String[] QUIRKY_PUBLIC_IDS = { 1.319 + "+//silmaril//dtd html pro v0r11 19970101//", 1.320 + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", 1.321 + "-//as//dtd html 3.0 aswedit + extensions//", 1.322 + "-//ietf//dtd html 2.0 level 1//", 1.323 + "-//ietf//dtd html 2.0 level 2//", 1.324 + "-//ietf//dtd html 2.0 strict level 1//", 1.325 + "-//ietf//dtd html 2.0 strict level 2//", 1.326 + "-//ietf//dtd html 2.0 strict//", 1.327 + "-//ietf//dtd html 2.0//", 1.328 + "-//ietf//dtd html 2.1e//", 1.329 + "-//ietf//dtd html 3.0//", 1.330 + "-//ietf//dtd html 3.2 final//", 1.331 + "-//ietf//dtd html 3.2//", 1.332 + "-//ietf//dtd html 3//", 1.333 + "-//ietf//dtd html level 0//", 1.334 + "-//ietf//dtd html level 1//", 1.335 + "-//ietf//dtd html level 2//", 1.336 + "-//ietf//dtd html level 3//", 1.337 + "-//ietf//dtd html strict level 0//", 1.338 + "-//ietf//dtd html strict level 1//", 1.339 + "-//ietf//dtd html strict level 2//", 1.340 + "-//ietf//dtd html strict level 3//", 1.341 + "-//ietf//dtd html strict//", 1.342 + "-//ietf//dtd html//", 1.343 + "-//metrius//dtd metrius presentational//", 1.344 + "-//microsoft//dtd internet explorer 2.0 html strict//", 1.345 + "-//microsoft//dtd internet explorer 2.0 html//", 1.346 + "-//microsoft//dtd internet explorer 2.0 tables//", 1.347 + "-//microsoft//dtd internet explorer 3.0 html strict//", 1.348 + "-//microsoft//dtd internet explorer 3.0 html//", 1.349 + "-//microsoft//dtd internet explorer 3.0 tables//", 1.350 + "-//netscape comm. corp.//dtd html//", 1.351 + "-//netscape comm. corp.//dtd strict html//", 1.352 + "-//o'reilly and associates//dtd html 2.0//", 1.353 + "-//o'reilly and associates//dtd html extended 1.0//", 1.354 + "-//o'reilly and associates//dtd html extended relaxed 1.0//", 1.355 + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", 1.356 + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", 1.357 + "-//spyglass//dtd html 2.0 extended//", 1.358 + "-//sq//dtd html 2.0 hotmetal + extensions//", 1.359 + "-//sun microsystems corp.//dtd hotjava html//", 1.360 + "-//sun microsystems corp.//dtd hotjava strict html//", 1.361 + "-//w3c//dtd html 3 1995-03-24//", "-//w3c//dtd html 3.2 draft//", 1.362 + "-//w3c//dtd html 3.2 final//", "-//w3c//dtd html 3.2//", 1.363 + "-//w3c//dtd html 3.2s draft//", "-//w3c//dtd html 4.0 frameset//", 1.364 + "-//w3c//dtd html 4.0 transitional//", 1.365 + "-//w3c//dtd html experimental 19960712//", 1.366 + "-//w3c//dtd html experimental 970421//", "-//w3c//dtd w3 html//", 1.367 + "-//w3o//dtd w3 html 3.0//", "-//webtechs//dtd mozilla html 2.0//", 1.368 + "-//webtechs//dtd mozilla html//" }; 1.369 + 1.370 + private static final int NOT_FOUND_ON_STACK = Integer.MAX_VALUE; 1.371 + 1.372 + // [NOCPP[ 1.373 + 1.374 + private static final @Local String HTML_LOCAL = "html"; 1.375 + 1.376 + // ]NOCPP] 1.377 + 1.378 + private int mode = INITIAL; 1.379 + 1.380 + private int originalMode = INITIAL; 1.381 + 1.382 + /** 1.383 + * Used only when moving back to IN_BODY. 1.384 + */ 1.385 + private boolean framesetOk = true; 1.386 + 1.387 + protected Tokenizer tokenizer; 1.388 + 1.389 + // [NOCPP[ 1.390 + 1.391 + protected ErrorHandler errorHandler; 1.392 + 1.393 + private DocumentModeHandler documentModeHandler; 1.394 + 1.395 + private DoctypeExpectation doctypeExpectation = DoctypeExpectation.HTML; 1.396 + 1.397 + private LocatorImpl firstCommentLocation; 1.398 + 1.399 + // ]NOCPP] 1.400 + 1.401 + private boolean scriptingEnabled = false; 1.402 + 1.403 + private boolean needToDropLF; 1.404 + 1.405 + // [NOCPP[ 1.406 + 1.407 + private boolean wantingComments; 1.408 + 1.409 + // ]NOCPP] 1.410 + 1.411 + private boolean fragment; 1.412 + 1.413 + private @Local String contextName; 1.414 + 1.415 + private @NsUri String contextNamespace; 1.416 + 1.417 + private T contextNode; 1.418 + 1.419 + /** 1.420 + * Stack of template insertion modes 1.421 + */ 1.422 + private @Auto int[] templateModeStack; 1.423 + 1.424 + /** 1.425 + * Current template mode stack pointer. 1.426 + */ 1.427 + private int templateModePtr = -1; 1.428 + 1.429 + private @Auto StackNode<T>[] stack; 1.430 + 1.431 + private int currentPtr = -1; 1.432 + 1.433 + private @Auto StackNode<T>[] listOfActiveFormattingElements; 1.434 + 1.435 + private int listPtr = -1; 1.436 + 1.437 + private T formPointer; 1.438 + 1.439 + private T headPointer; 1.440 + 1.441 + /** 1.442 + * Used to work around Gecko limitations. Not used in Java. 1.443 + */ 1.444 + private T deepTreeSurrogateParent; 1.445 + 1.446 + protected @Auto char[] charBuffer; 1.447 + 1.448 + protected int charBufferLen = 0; 1.449 + 1.450 + private boolean quirks = false; 1.451 + 1.452 + private boolean isSrcdocDocument = false; 1.453 + 1.454 + // [NOCPP[ 1.455 + 1.456 + private boolean reportingDoctype = true; 1.457 + 1.458 + private XmlViolationPolicy namePolicy = XmlViolationPolicy.ALTER_INFOSET; 1.459 + 1.460 + private final Map<String, LocatorImpl> idLocations = new HashMap<String, LocatorImpl>(); 1.461 + 1.462 + private boolean html4; 1.463 + 1.464 + // ]NOCPP] 1.465 + 1.466 + protected TreeBuilder() { 1.467 + fragment = false; 1.468 + } 1.469 + 1.470 + /** 1.471 + * Reports an condition that would make the infoset incompatible with XML 1.472 + * 1.0 as fatal. 1.473 + * 1.474 + * @throws SAXException 1.475 + * @throws SAXParseException 1.476 + */ 1.477 + protected void fatal() throws SAXException { 1.478 + } 1.479 + 1.480 + // [NOCPP[ 1.481 + 1.482 + protected final void fatal(Exception e) throws SAXException { 1.483 + SAXParseException spe = new SAXParseException(e.getMessage(), 1.484 + tokenizer, e); 1.485 + if (errorHandler != null) { 1.486 + errorHandler.fatalError(spe); 1.487 + } 1.488 + throw spe; 1.489 + } 1.490 + 1.491 + final void fatal(String s) throws SAXException { 1.492 + SAXParseException spe = new SAXParseException(s, tokenizer); 1.493 + if (errorHandler != null) { 1.494 + errorHandler.fatalError(spe); 1.495 + } 1.496 + throw spe; 1.497 + } 1.498 + 1.499 + /** 1.500 + * Reports a Parse Error. 1.501 + * 1.502 + * @param message 1.503 + * the message 1.504 + * @throws SAXException 1.505 + */ 1.506 + final void err(String message) throws SAXException { 1.507 + if (errorHandler == null) { 1.508 + return; 1.509 + } 1.510 + errNoCheck(message); 1.511 + } 1.512 + 1.513 + /** 1.514 + * Reports a Parse Error without checking if an error handler is present. 1.515 + * 1.516 + * @param message 1.517 + * the message 1.518 + * @throws SAXException 1.519 + */ 1.520 + final void errNoCheck(String message) throws SAXException { 1.521 + SAXParseException spe = new SAXParseException(message, tokenizer); 1.522 + errorHandler.error(spe); 1.523 + } 1.524 + 1.525 + private void errListUnclosedStartTags(int eltPos) throws SAXException { 1.526 + if (currentPtr != -1) { 1.527 + for (int i = currentPtr; i > eltPos; i--) { 1.528 + reportUnclosedElementNameAndLocation(i); 1.529 + } 1.530 + } 1.531 + } 1.532 + 1.533 + /** 1.534 + * Reports the name and location of an unclosed element. 1.535 + * 1.536 + * @throws SAXException 1.537 + */ 1.538 + private final void reportUnclosedElementNameAndLocation(int pos) throws SAXException { 1.539 + StackNode<T> node = stack[pos]; 1.540 + if (node.isOptionalEndTag()) { 1.541 + return; 1.542 + } 1.543 + TaintableLocatorImpl locator = node.getLocator(); 1.544 + if (locator.isTainted()) { 1.545 + return; 1.546 + } 1.547 + locator.markTainted(); 1.548 + SAXParseException spe = new SAXParseException( 1.549 + "Unclosed element \u201C" + node.popName + "\u201D.", locator); 1.550 + errorHandler.error(spe); 1.551 + } 1.552 + 1.553 + /** 1.554 + * Reports a warning 1.555 + * 1.556 + * @param message 1.557 + * the message 1.558 + * @throws SAXException 1.559 + */ 1.560 + final void warn(String message) throws SAXException { 1.561 + if (errorHandler == null) { 1.562 + return; 1.563 + } 1.564 + SAXParseException spe = new SAXParseException(message, tokenizer); 1.565 + errorHandler.warning(spe); 1.566 + } 1.567 + 1.568 + /** 1.569 + * Reports a warning with an explicit locator 1.570 + * 1.571 + * @param message 1.572 + * the message 1.573 + * @throws SAXException 1.574 + */ 1.575 + final void warn(String message, Locator locator) throws SAXException { 1.576 + if (errorHandler == null) { 1.577 + return; 1.578 + } 1.579 + SAXParseException spe = new SAXParseException(message, locator); 1.580 + errorHandler.warning(spe); 1.581 + } 1.582 + 1.583 + // ]NOCPP] 1.584 + 1.585 + @SuppressWarnings("unchecked") public final void startTokenization(Tokenizer self) throws SAXException { 1.586 + tokenizer = self; 1.587 + stack = new StackNode[64]; 1.588 + templateModeStack = new int[64]; 1.589 + listOfActiveFormattingElements = new StackNode[64]; 1.590 + needToDropLF = false; 1.591 + originalMode = INITIAL; 1.592 + templateModePtr = -1; 1.593 + currentPtr = -1; 1.594 + listPtr = -1; 1.595 + formPointer = null; 1.596 + headPointer = null; 1.597 + deepTreeSurrogateParent = null; 1.598 + // [NOCPP[ 1.599 + html4 = false; 1.600 + idLocations.clear(); 1.601 + wantingComments = wantsComments(); 1.602 + firstCommentLocation = null; 1.603 + // ]NOCPP] 1.604 + start(fragment); 1.605 + charBufferLen = 0; 1.606 + charBuffer = new char[1024]; 1.607 + framesetOk = true; 1.608 + if (fragment) { 1.609 + T elt; 1.610 + if (contextNode != null) { 1.611 + elt = contextNode; 1.612 + } else { 1.613 + elt = createHtmlElementSetAsRoot(tokenizer.emptyAttributes()); 1.614 + } 1.615 + StackNode<T> node = new StackNode<T>(ElementName.HTML, elt 1.616 + // [NOCPP[ 1.617 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.618 + // ]NOCPP] 1.619 + ); 1.620 + currentPtr++; 1.621 + stack[currentPtr] = node; 1.622 + if ("template" == contextName) { 1.623 + pushTemplateMode(IN_TEMPLATE); 1.624 + } 1.625 + resetTheInsertionMode(); 1.626 + formPointer = getFormPointerForContext(contextNode); 1.627 + if ("title" == contextName || "textarea" == contextName) { 1.628 + tokenizer.setStateAndEndTagExpectation(Tokenizer.RCDATA, contextName); 1.629 + } else if ("style" == contextName || "xmp" == contextName 1.630 + || "iframe" == contextName || "noembed" == contextName 1.631 + || "noframes" == contextName 1.632 + || (scriptingEnabled && "noscript" == contextName)) { 1.633 + tokenizer.setStateAndEndTagExpectation(Tokenizer.RAWTEXT, contextName); 1.634 + } else if ("plaintext" == contextName) { 1.635 + tokenizer.setStateAndEndTagExpectation(Tokenizer.PLAINTEXT, contextName); 1.636 + } else if ("script" == contextName) { 1.637 + tokenizer.setStateAndEndTagExpectation(Tokenizer.SCRIPT_DATA, 1.638 + contextName); 1.639 + } else { 1.640 + tokenizer.setStateAndEndTagExpectation(Tokenizer.DATA, contextName); 1.641 + } 1.642 + contextName = null; 1.643 + contextNode = null; 1.644 + } else { 1.645 + mode = INITIAL; 1.646 + // If we are viewing XML source, put a foreign element permanently 1.647 + // on the stack so that cdataSectionAllowed() returns true. 1.648 + // CPPONLY: if (tokenizer.isViewingXmlSource()) { 1.649 + // CPPONLY: T elt = createElement("http://www.w3.org/2000/svg", 1.650 + // CPPONLY: "svg", 1.651 + // CPPONLY: tokenizer.emptyAttributes()); 1.652 + // CPPONLY: StackNode<T> node = new StackNode<T>(ElementName.SVG, 1.653 + // CPPONLY: "svg", 1.654 + // CPPONLY: elt); 1.655 + // CPPONLY: currentPtr++; 1.656 + // CPPONLY: stack[currentPtr] = node; 1.657 + // CPPONLY: } 1.658 + } 1.659 + } 1.660 + 1.661 + public final void doctype(@Local String name, String publicIdentifier, 1.662 + String systemIdentifier, boolean forceQuirks) throws SAXException { 1.663 + needToDropLF = false; 1.664 + if (!isInForeign() && mode == INITIAL) { 1.665 + // [NOCPP[ 1.666 + if (reportingDoctype) { 1.667 + // ]NOCPP] 1.668 + String emptyString = Portability.newEmptyString(); 1.669 + appendDoctypeToDocument(name == null ? "" : name, 1.670 + publicIdentifier == null ? emptyString 1.671 + : publicIdentifier, 1.672 + systemIdentifier == null ? emptyString 1.673 + : systemIdentifier); 1.674 + Portability.releaseString(emptyString); 1.675 + // [NOCPP[ 1.676 + } 1.677 + switch (doctypeExpectation) { 1.678 + case HTML: 1.679 + // ]NOCPP] 1.680 + if (isQuirky(name, publicIdentifier, systemIdentifier, 1.681 + forceQuirks)) { 1.682 + errQuirkyDoctype(); 1.683 + documentModeInternal(DocumentMode.QUIRKS_MODE, 1.684 + publicIdentifier, systemIdentifier, false); 1.685 + } else if (isAlmostStandards(publicIdentifier, 1.686 + systemIdentifier)) { 1.687 + // [NOCPP[ 1.688 + if (firstCommentLocation != null) { 1.689 + warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.", 1.690 + firstCommentLocation); 1.691 + } 1.692 + // ]NOCPP] 1.693 + errAlmostStandardsDoctype(); 1.694 + documentModeInternal( 1.695 + DocumentMode.ALMOST_STANDARDS_MODE, 1.696 + publicIdentifier, systemIdentifier, false); 1.697 + } else { 1.698 + // [NOCPP[ 1.699 + if (firstCommentLocation != null) { 1.700 + warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.", 1.701 + firstCommentLocation); 1.702 + } 1.703 + if ((Portability.literalEqualsString( 1.704 + "-//W3C//DTD HTML 4.0//EN", publicIdentifier) && (systemIdentifier == null || Portability.literalEqualsString( 1.705 + "http://www.w3.org/TR/REC-html40/strict.dtd", 1.706 + systemIdentifier))) 1.707 + || (Portability.literalEqualsString( 1.708 + "-//W3C//DTD HTML 4.01//EN", 1.709 + publicIdentifier) && (systemIdentifier == null || Portability.literalEqualsString( 1.710 + "http://www.w3.org/TR/html4/strict.dtd", 1.711 + systemIdentifier))) 1.712 + || (Portability.literalEqualsString( 1.713 + "-//W3C//DTD XHTML 1.0 Strict//EN", 1.714 + publicIdentifier) && Portability.literalEqualsString( 1.715 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd", 1.716 + systemIdentifier)) 1.717 + || (Portability.literalEqualsString( 1.718 + "-//W3C//DTD XHTML 1.1//EN", 1.719 + publicIdentifier) && Portability.literalEqualsString( 1.720 + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd", 1.721 + systemIdentifier)) 1.722 + 1.723 + ) { 1.724 + warn("Obsolete doctype. Expected \u201C<!DOCTYPE html>\u201D."); 1.725 + } else if (!((systemIdentifier == null || Portability.literalEqualsString( 1.726 + "about:legacy-compat", systemIdentifier)) && publicIdentifier == null)) { 1.727 + err("Legacy doctype. Expected \u201C<!DOCTYPE html>\u201D."); 1.728 + } 1.729 + // ]NOCPP] 1.730 + documentModeInternal(DocumentMode.STANDARDS_MODE, 1.731 + publicIdentifier, systemIdentifier, false); 1.732 + } 1.733 + // [NOCPP[ 1.734 + break; 1.735 + case HTML401_STRICT: 1.736 + html4 = true; 1.737 + tokenizer.turnOnAdditionalHtml4Errors(); 1.738 + if (isQuirky(name, publicIdentifier, systemIdentifier, 1.739 + forceQuirks)) { 1.740 + err("Quirky doctype. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\u201D."); 1.741 + documentModeInternal(DocumentMode.QUIRKS_MODE, 1.742 + publicIdentifier, systemIdentifier, true); 1.743 + } else if (isAlmostStandards(publicIdentifier, 1.744 + systemIdentifier)) { 1.745 + if (firstCommentLocation != null) { 1.746 + warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.", 1.747 + firstCommentLocation); 1.748 + } 1.749 + 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."); 1.750 + documentModeInternal( 1.751 + DocumentMode.ALMOST_STANDARDS_MODE, 1.752 + publicIdentifier, systemIdentifier, true); 1.753 + } else { 1.754 + if (firstCommentLocation != null) { 1.755 + warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.", 1.756 + firstCommentLocation); 1.757 + } 1.758 + if ("-//W3C//DTD HTML 4.01//EN".equals(publicIdentifier)) { 1.759 + if (!"http://www.w3.org/TR/html4/strict.dtd".equals(systemIdentifier)) { 1.760 + 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."); 1.761 + } 1.762 + } else { 1.763 + 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."); 1.764 + } 1.765 + documentModeInternal(DocumentMode.STANDARDS_MODE, 1.766 + publicIdentifier, systemIdentifier, true); 1.767 + } 1.768 + break; 1.769 + case HTML401_TRANSITIONAL: 1.770 + html4 = true; 1.771 + tokenizer.turnOnAdditionalHtml4Errors(); 1.772 + if (isQuirky(name, publicIdentifier, systemIdentifier, 1.773 + forceQuirks)) { 1.774 + err("Quirky doctype. Expected \u201C<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\u201D."); 1.775 + documentModeInternal(DocumentMode.QUIRKS_MODE, 1.776 + publicIdentifier, systemIdentifier, true); 1.777 + } else if (isAlmostStandards(publicIdentifier, 1.778 + systemIdentifier)) { 1.779 + if (firstCommentLocation != null) { 1.780 + warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.", 1.781 + firstCommentLocation); 1.782 + } 1.783 + if ("-//W3C//DTD HTML 4.01 Transitional//EN".equals(publicIdentifier) 1.784 + && systemIdentifier != null) { 1.785 + if (!"http://www.w3.org/TR/html4/loose.dtd".equals(systemIdentifier)) { 1.786 + 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."); 1.787 + } 1.788 + } else { 1.789 + 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."); 1.790 + } 1.791 + documentModeInternal( 1.792 + DocumentMode.ALMOST_STANDARDS_MODE, 1.793 + publicIdentifier, systemIdentifier, true); 1.794 + } else { 1.795 + if (firstCommentLocation != null) { 1.796 + warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.", 1.797 + firstCommentLocation); 1.798 + } 1.799 + 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."); 1.800 + documentModeInternal(DocumentMode.STANDARDS_MODE, 1.801 + publicIdentifier, systemIdentifier, true); 1.802 + } 1.803 + break; 1.804 + case AUTO: 1.805 + html4 = isHtml4Doctype(publicIdentifier); 1.806 + if (html4) { 1.807 + tokenizer.turnOnAdditionalHtml4Errors(); 1.808 + } 1.809 + if (isQuirky(name, publicIdentifier, systemIdentifier, 1.810 + forceQuirks)) { 1.811 + err("Quirky doctype. Expected e.g. \u201C<!DOCTYPE html>\u201D."); 1.812 + documentModeInternal(DocumentMode.QUIRKS_MODE, 1.813 + publicIdentifier, systemIdentifier, html4); 1.814 + } else if (isAlmostStandards(publicIdentifier, 1.815 + systemIdentifier)) { 1.816 + if (firstCommentLocation != null) { 1.817 + warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.", 1.818 + firstCommentLocation); 1.819 + } 1.820 + if ("-//W3C//DTD HTML 4.01 Transitional//EN".equals(publicIdentifier)) { 1.821 + if (!"http://www.w3.org/TR/html4/loose.dtd".equals(systemIdentifier)) { 1.822 + 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."); 1.823 + } 1.824 + } else { 1.825 + err("Almost standards mode doctype. Expected e.g. \u201C<!DOCTYPE html>\u201D."); 1.826 + } 1.827 + documentModeInternal( 1.828 + DocumentMode.ALMOST_STANDARDS_MODE, 1.829 + publicIdentifier, systemIdentifier, html4); 1.830 + } else { 1.831 + if (firstCommentLocation != null) { 1.832 + warn("Comments seen before doctype. Internet Explorer will go into the quirks mode.", 1.833 + firstCommentLocation); 1.834 + } 1.835 + if ("-//W3C//DTD HTML 4.01//EN".equals(publicIdentifier)) { 1.836 + if (!"http://www.w3.org/TR/html4/strict.dtd".equals(systemIdentifier)) { 1.837 + 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."); 1.838 + } 1.839 + } else if ("-//W3C//DTD XHTML 1.0 Strict//EN".equals(publicIdentifier)) { 1.840 + if (!"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd".equals(systemIdentifier)) { 1.841 + 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."); 1.842 + } 1.843 + } else if ("//W3C//DTD XHTML 1.1//EN".equals(publicIdentifier)) { 1.844 + if (!"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd".equals(systemIdentifier)) { 1.845 + 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."); 1.846 + } 1.847 + } else if (!((systemIdentifier == null || Portability.literalEqualsString( 1.848 + "about:legacy-compat", systemIdentifier)) && publicIdentifier == null)) { 1.849 + err("Unexpected doctype. Expected, e.g., \u201C<!DOCTYPE html>\u201D."); 1.850 + } 1.851 + documentModeInternal(DocumentMode.STANDARDS_MODE, 1.852 + publicIdentifier, systemIdentifier, html4); 1.853 + } 1.854 + break; 1.855 + case NO_DOCTYPE_ERRORS: 1.856 + if (isQuirky(name, publicIdentifier, systemIdentifier, 1.857 + forceQuirks)) { 1.858 + documentModeInternal(DocumentMode.QUIRKS_MODE, 1.859 + publicIdentifier, systemIdentifier, false); 1.860 + } else if (isAlmostStandards(publicIdentifier, 1.861 + systemIdentifier)) { 1.862 + documentModeInternal( 1.863 + DocumentMode.ALMOST_STANDARDS_MODE, 1.864 + publicIdentifier, systemIdentifier, false); 1.865 + } else { 1.866 + documentModeInternal(DocumentMode.STANDARDS_MODE, 1.867 + publicIdentifier, systemIdentifier, false); 1.868 + } 1.869 + break; 1.870 + } 1.871 + // ]NOCPP] 1.872 + 1.873 + /* 1.874 + * 1.875 + * Then, switch to the root element mode of the tree construction 1.876 + * stage. 1.877 + */ 1.878 + mode = BEFORE_HTML; 1.879 + return; 1.880 + } 1.881 + /* 1.882 + * A DOCTYPE token Parse error. 1.883 + */ 1.884 + errStrayDoctype(); 1.885 + /* 1.886 + * Ignore the token. 1.887 + */ 1.888 + return; 1.889 + } 1.890 + 1.891 + // [NOCPP[ 1.892 + 1.893 + private boolean isHtml4Doctype(String publicIdentifier) { 1.894 + if (publicIdentifier != null 1.895 + && (Arrays.binarySearch(TreeBuilder.HTML4_PUBLIC_IDS, 1.896 + publicIdentifier) > -1)) { 1.897 + return true; 1.898 + } 1.899 + return false; 1.900 + } 1.901 + 1.902 + // ]NOCPP] 1.903 + 1.904 + public final void comment(@NoLength char[] buf, int start, int length) 1.905 + throws SAXException { 1.906 + needToDropLF = false; 1.907 + // [NOCPP[ 1.908 + if (firstCommentLocation == null) { 1.909 + firstCommentLocation = new LocatorImpl(tokenizer); 1.910 + } 1.911 + if (!wantingComments) { 1.912 + return; 1.913 + } 1.914 + // ]NOCPP] 1.915 + if (!isInForeign()) { 1.916 + switch (mode) { 1.917 + case INITIAL: 1.918 + case BEFORE_HTML: 1.919 + case AFTER_AFTER_BODY: 1.920 + case AFTER_AFTER_FRAMESET: 1.921 + /* 1.922 + * A comment token Append a Comment node to the Document 1.923 + * object with the data attribute set to the data given in 1.924 + * the comment token. 1.925 + */ 1.926 + appendCommentToDocument(buf, start, length); 1.927 + return; 1.928 + case AFTER_BODY: 1.929 + /* 1.930 + * A comment token Append a Comment node to the first 1.931 + * element in the stack of open elements (the html element), 1.932 + * with the data attribute set to the data given in the 1.933 + * comment token. 1.934 + */ 1.935 + flushCharacters(); 1.936 + appendComment(stack[0].node, buf, start, length); 1.937 + return; 1.938 + default: 1.939 + break; 1.940 + } 1.941 + } 1.942 + /* 1.943 + * A comment token Append a Comment node to the current node with the 1.944 + * data attribute set to the data given in the comment token. 1.945 + */ 1.946 + flushCharacters(); 1.947 + appendComment(stack[currentPtr].node, buf, start, length); 1.948 + return; 1.949 + } 1.950 + 1.951 + /** 1.952 + * @see nu.validator.htmlparser.common.TokenHandler#characters(char[], int, 1.953 + * int) 1.954 + */ 1.955 + public final void characters(@Const @NoLength char[] buf, int start, int length) 1.956 + throws SAXException { 1.957 + // Note: Can't attach error messages to EOF in C++ yet 1.958 + 1.959 + // CPPONLY: if (tokenizer.isViewingXmlSource()) { 1.960 + // CPPONLY: return; 1.961 + // CPPONLY: } 1.962 + if (needToDropLF) { 1.963 + needToDropLF = false; 1.964 + if (buf[start] == '\n') { 1.965 + start++; 1.966 + length--; 1.967 + if (length == 0) { 1.968 + return; 1.969 + } 1.970 + } 1.971 + } 1.972 + 1.973 + // optimize the most common case 1.974 + switch (mode) { 1.975 + case IN_BODY: 1.976 + case IN_CELL: 1.977 + case IN_CAPTION: 1.978 + if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) { 1.979 + reconstructTheActiveFormattingElements(); 1.980 + } 1.981 + // fall through 1.982 + case TEXT: 1.983 + accumulateCharacters(buf, start, length); 1.984 + return; 1.985 + case IN_TABLE: 1.986 + case IN_TABLE_BODY: 1.987 + case IN_ROW: 1.988 + accumulateCharactersForced(buf, start, length); 1.989 + return; 1.990 + default: 1.991 + int end = start + length; 1.992 + charactersloop: for (int i = start; i < end; i++) { 1.993 + switch (buf[i]) { 1.994 + case ' ': 1.995 + case '\t': 1.996 + case '\n': 1.997 + case '\r': 1.998 + case '\u000C': 1.999 + /* 1.1000 + * A character token that is one of one of U+0009 1.1001 + * CHARACTER TABULATION, U+000A LINE FEED (LF), 1.1002 + * U+000C FORM FEED (FF), or U+0020 SPACE 1.1003 + */ 1.1004 + switch (mode) { 1.1005 + case INITIAL: 1.1006 + case BEFORE_HTML: 1.1007 + case BEFORE_HEAD: 1.1008 + /* 1.1009 + * Ignore the token. 1.1010 + */ 1.1011 + start = i + 1; 1.1012 + continue; 1.1013 + case IN_HEAD: 1.1014 + case IN_HEAD_NOSCRIPT: 1.1015 + case AFTER_HEAD: 1.1016 + case IN_COLUMN_GROUP: 1.1017 + case IN_FRAMESET: 1.1018 + case AFTER_FRAMESET: 1.1019 + /* 1.1020 + * Append the character to the current node. 1.1021 + */ 1.1022 + continue; 1.1023 + case FRAMESET_OK: 1.1024 + case IN_TEMPLATE: 1.1025 + case IN_BODY: 1.1026 + case IN_CELL: 1.1027 + case IN_CAPTION: 1.1028 + if (start < i) { 1.1029 + accumulateCharacters(buf, start, i 1.1030 + - start); 1.1031 + start = i; 1.1032 + } 1.1033 + 1.1034 + /* 1.1035 + * Reconstruct the active formatting 1.1036 + * elements, if any. 1.1037 + */ 1.1038 + if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) { 1.1039 + flushCharacters(); 1.1040 + reconstructTheActiveFormattingElements(); 1.1041 + } 1.1042 + /* 1.1043 + * Append the token's character to the 1.1044 + * current node. 1.1045 + */ 1.1046 + break charactersloop; 1.1047 + case IN_SELECT: 1.1048 + case IN_SELECT_IN_TABLE: 1.1049 + break charactersloop; 1.1050 + case IN_TABLE: 1.1051 + case IN_TABLE_BODY: 1.1052 + case IN_ROW: 1.1053 + accumulateCharactersForced(buf, i, 1); 1.1054 + start = i + 1; 1.1055 + continue; 1.1056 + case AFTER_BODY: 1.1057 + case AFTER_AFTER_BODY: 1.1058 + case AFTER_AFTER_FRAMESET: 1.1059 + if (start < i) { 1.1060 + accumulateCharacters(buf, start, i 1.1061 + - start); 1.1062 + start = i; 1.1063 + } 1.1064 + /* 1.1065 + * Reconstruct the active formatting 1.1066 + * elements, if any. 1.1067 + */ 1.1068 + flushCharacters(); 1.1069 + reconstructTheActiveFormattingElements(); 1.1070 + /* 1.1071 + * Append the token's character to the 1.1072 + * current node. 1.1073 + */ 1.1074 + continue; 1.1075 + } 1.1076 + default: 1.1077 + /* 1.1078 + * A character token that is not one of one of 1.1079 + * U+0009 CHARACTER TABULATION, U+000A LINE FEED 1.1080 + * (LF), U+000C FORM FEED (FF), or U+0020 SPACE 1.1081 + */ 1.1082 + switch (mode) { 1.1083 + case INITIAL: 1.1084 + /* 1.1085 + * Parse error. 1.1086 + */ 1.1087 + // [NOCPP[ 1.1088 + switch (doctypeExpectation) { 1.1089 + case AUTO: 1.1090 + err("Non-space characters found without seeing a doctype first. Expected e.g. \u201C<!DOCTYPE html>\u201D."); 1.1091 + break; 1.1092 + case HTML: 1.1093 + // XXX figure out a way to report this in the Gecko View Source case 1.1094 + err("Non-space characters found without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D."); 1.1095 + break; 1.1096 + case HTML401_STRICT: 1.1097 + 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."); 1.1098 + break; 1.1099 + case HTML401_TRANSITIONAL: 1.1100 + 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."); 1.1101 + break; 1.1102 + case NO_DOCTYPE_ERRORS: 1.1103 + } 1.1104 + // ]NOCPP] 1.1105 + /* 1.1106 + * 1.1107 + * Set the document to quirks mode. 1.1108 + */ 1.1109 + documentModeInternal( 1.1110 + DocumentMode.QUIRKS_MODE, null, 1.1111 + null, false); 1.1112 + /* 1.1113 + * Then, switch to the root element mode of 1.1114 + * the tree construction stage 1.1115 + */ 1.1116 + mode = BEFORE_HTML; 1.1117 + /* 1.1118 + * and reprocess the current token. 1.1119 + */ 1.1120 + i--; 1.1121 + continue; 1.1122 + case BEFORE_HTML: 1.1123 + /* 1.1124 + * Create an HTMLElement node with the tag 1.1125 + * name html, in the HTML namespace. Append 1.1126 + * it to the Document object. 1.1127 + */ 1.1128 + // No need to flush characters here, 1.1129 + // because there's nothing to flush. 1.1130 + appendHtmlElementToDocumentAndPush(); 1.1131 + /* Switch to the main mode */ 1.1132 + mode = BEFORE_HEAD; 1.1133 + /* 1.1134 + * reprocess the current token. 1.1135 + */ 1.1136 + i--; 1.1137 + continue; 1.1138 + case BEFORE_HEAD: 1.1139 + if (start < i) { 1.1140 + accumulateCharacters(buf, start, i 1.1141 + - start); 1.1142 + start = i; 1.1143 + } 1.1144 + /* 1.1145 + * /Act as if a start tag token with the tag 1.1146 + * name "head" and no attributes had been 1.1147 + * seen, 1.1148 + */ 1.1149 + flushCharacters(); 1.1150 + appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES); 1.1151 + mode = IN_HEAD; 1.1152 + /* 1.1153 + * then reprocess the current token. 1.1154 + * 1.1155 + * This will result in an empty head element 1.1156 + * being generated, with the current token 1.1157 + * being reprocessed in the "after head" 1.1158 + * insertion mode. 1.1159 + */ 1.1160 + i--; 1.1161 + continue; 1.1162 + case IN_HEAD: 1.1163 + if (start < i) { 1.1164 + accumulateCharacters(buf, start, i 1.1165 + - start); 1.1166 + start = i; 1.1167 + } 1.1168 + /* 1.1169 + * Act as if an end tag token with the tag 1.1170 + * name "head" had been seen, 1.1171 + */ 1.1172 + flushCharacters(); 1.1173 + pop(); 1.1174 + mode = AFTER_HEAD; 1.1175 + /* 1.1176 + * and reprocess the current token. 1.1177 + */ 1.1178 + i--; 1.1179 + continue; 1.1180 + case IN_HEAD_NOSCRIPT: 1.1181 + if (start < i) { 1.1182 + accumulateCharacters(buf, start, i 1.1183 + - start); 1.1184 + start = i; 1.1185 + } 1.1186 + /* 1.1187 + * Parse error. Act as if an end tag with 1.1188 + * the tag name "noscript" had been seen 1.1189 + */ 1.1190 + errNonSpaceInNoscriptInHead(); 1.1191 + flushCharacters(); 1.1192 + pop(); 1.1193 + mode = IN_HEAD; 1.1194 + /* 1.1195 + * and reprocess the current token. 1.1196 + */ 1.1197 + i--; 1.1198 + continue; 1.1199 + case AFTER_HEAD: 1.1200 + if (start < i) { 1.1201 + accumulateCharacters(buf, start, i 1.1202 + - start); 1.1203 + start = i; 1.1204 + } 1.1205 + /* 1.1206 + * Act as if a start tag token with the tag 1.1207 + * name "body" and no attributes had been 1.1208 + * seen, 1.1209 + */ 1.1210 + flushCharacters(); 1.1211 + appendToCurrentNodeAndPushBodyElement(); 1.1212 + mode = FRAMESET_OK; 1.1213 + /* 1.1214 + * and then reprocess the current token. 1.1215 + */ 1.1216 + i--; 1.1217 + continue; 1.1218 + case FRAMESET_OK: 1.1219 + framesetOk = false; 1.1220 + mode = IN_BODY; 1.1221 + i--; 1.1222 + continue; 1.1223 + case IN_TEMPLATE: 1.1224 + case IN_BODY: 1.1225 + case IN_CELL: 1.1226 + case IN_CAPTION: 1.1227 + if (start < i) { 1.1228 + accumulateCharacters(buf, start, i 1.1229 + - start); 1.1230 + start = i; 1.1231 + } 1.1232 + /* 1.1233 + * Reconstruct the active formatting 1.1234 + * elements, if any. 1.1235 + */ 1.1236 + if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) { 1.1237 + flushCharacters(); 1.1238 + reconstructTheActiveFormattingElements(); 1.1239 + } 1.1240 + /* 1.1241 + * Append the token's character to the 1.1242 + * current node. 1.1243 + */ 1.1244 + break charactersloop; 1.1245 + case IN_TABLE: 1.1246 + case IN_TABLE_BODY: 1.1247 + case IN_ROW: 1.1248 + accumulateCharactersForced(buf, i, 1); 1.1249 + start = i + 1; 1.1250 + continue; 1.1251 + case IN_COLUMN_GROUP: 1.1252 + if (start < i) { 1.1253 + accumulateCharacters(buf, start, i 1.1254 + - start); 1.1255 + start = i; 1.1256 + } 1.1257 + /* 1.1258 + * Act as if an end tag with the tag name 1.1259 + * "colgroup" had been seen, and then, if 1.1260 + * that token wasn't ignored, reprocess the 1.1261 + * current token. 1.1262 + */ 1.1263 + if (currentPtr == 0 || stack[currentPtr].getGroup() == 1.1264 + TreeBuilder.TEMPLATE) { 1.1265 + errNonSpaceInColgroupInFragment(); 1.1266 + start = i + 1; 1.1267 + continue; 1.1268 + } 1.1269 + flushCharacters(); 1.1270 + pop(); 1.1271 + mode = IN_TABLE; 1.1272 + i--; 1.1273 + continue; 1.1274 + case IN_SELECT: 1.1275 + case IN_SELECT_IN_TABLE: 1.1276 + break charactersloop; 1.1277 + case AFTER_BODY: 1.1278 + errNonSpaceAfterBody(); 1.1279 + fatal(); 1.1280 + mode = framesetOk ? FRAMESET_OK : IN_BODY; 1.1281 + i--; 1.1282 + continue; 1.1283 + case IN_FRAMESET: 1.1284 + if (start < i) { 1.1285 + accumulateCharacters(buf, start, i 1.1286 + - start); 1.1287 + start = i; 1.1288 + } 1.1289 + /* 1.1290 + * Parse error. 1.1291 + */ 1.1292 + errNonSpaceInFrameset(); 1.1293 + /* 1.1294 + * Ignore the token. 1.1295 + */ 1.1296 + start = i + 1; 1.1297 + continue; 1.1298 + case AFTER_FRAMESET: 1.1299 + if (start < i) { 1.1300 + accumulateCharacters(buf, start, i 1.1301 + - start); 1.1302 + start = i; 1.1303 + } 1.1304 + /* 1.1305 + * Parse error. 1.1306 + */ 1.1307 + errNonSpaceAfterFrameset(); 1.1308 + /* 1.1309 + * Ignore the token. 1.1310 + */ 1.1311 + start = i + 1; 1.1312 + continue; 1.1313 + case AFTER_AFTER_BODY: 1.1314 + /* 1.1315 + * Parse error. 1.1316 + */ 1.1317 + errNonSpaceInTrailer(); 1.1318 + /* 1.1319 + * Switch back to the main mode and 1.1320 + * reprocess the token. 1.1321 + */ 1.1322 + mode = framesetOk ? FRAMESET_OK : IN_BODY; 1.1323 + i--; 1.1324 + continue; 1.1325 + case AFTER_AFTER_FRAMESET: 1.1326 + errNonSpaceInTrailer(); 1.1327 + /* 1.1328 + * Switch back to the main mode and 1.1329 + * reprocess the token. 1.1330 + */ 1.1331 + mode = IN_FRAMESET; 1.1332 + i--; 1.1333 + continue; 1.1334 + } 1.1335 + } 1.1336 + } 1.1337 + if (start < end) { 1.1338 + accumulateCharacters(buf, start, end - start); 1.1339 + } 1.1340 + } 1.1341 + } 1.1342 + 1.1343 + /** 1.1344 + * @see nu.validator.htmlparser.common.TokenHandler#zeroOriginatingReplacementCharacter() 1.1345 + */ 1.1346 + public void zeroOriginatingReplacementCharacter() throws SAXException { 1.1347 + if (mode == TEXT) { 1.1348 + accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1); 1.1349 + return; 1.1350 + } 1.1351 + if (currentPtr >= 0) { 1.1352 + if (isSpecialParentInForeign(stack[currentPtr])) { 1.1353 + return; 1.1354 + } 1.1355 + accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1); 1.1356 + } 1.1357 + } 1.1358 + 1.1359 + public final void eof() throws SAXException { 1.1360 + flushCharacters(); 1.1361 + // Note: Can't attach error messages to EOF in C++ yet 1.1362 + eofloop: for (;;) { 1.1363 + switch (mode) { 1.1364 + case INITIAL: 1.1365 + /* 1.1366 + * Parse error. 1.1367 + */ 1.1368 + // [NOCPP[ 1.1369 + switch (doctypeExpectation) { 1.1370 + case AUTO: 1.1371 + err("End of file seen without seeing a doctype first. Expected e.g. \u201C<!DOCTYPE html>\u201D."); 1.1372 + break; 1.1373 + case HTML: 1.1374 + err("End of file seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D."); 1.1375 + break; 1.1376 + case HTML401_STRICT: 1.1377 + 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."); 1.1378 + break; 1.1379 + case HTML401_TRANSITIONAL: 1.1380 + 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."); 1.1381 + break; 1.1382 + case NO_DOCTYPE_ERRORS: 1.1383 + } 1.1384 + // ]NOCPP] 1.1385 + /* 1.1386 + * 1.1387 + * Set the document to quirks mode. 1.1388 + */ 1.1389 + documentModeInternal(DocumentMode.QUIRKS_MODE, null, null, 1.1390 + false); 1.1391 + /* 1.1392 + * Then, switch to the root element mode of the tree 1.1393 + * construction stage 1.1394 + */ 1.1395 + mode = BEFORE_HTML; 1.1396 + /* 1.1397 + * and reprocess the current token. 1.1398 + */ 1.1399 + continue; 1.1400 + case BEFORE_HTML: 1.1401 + /* 1.1402 + * Create an HTMLElement node with the tag name html, in the 1.1403 + * HTML namespace. Append it to the Document object. 1.1404 + */ 1.1405 + appendHtmlElementToDocumentAndPush(); 1.1406 + // XXX application cache manifest 1.1407 + /* Switch to the main mode */ 1.1408 + mode = BEFORE_HEAD; 1.1409 + /* 1.1410 + * reprocess the current token. 1.1411 + */ 1.1412 + continue; 1.1413 + case BEFORE_HEAD: 1.1414 + appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES); 1.1415 + mode = IN_HEAD; 1.1416 + continue; 1.1417 + case IN_HEAD: 1.1418 + // [NOCPP[ 1.1419 + if (errorHandler != null && currentPtr > 1) { 1.1420 + errEofWithUnclosedElements(); 1.1421 + } 1.1422 + // ]NOCPP] 1.1423 + while (currentPtr > 0) { 1.1424 + popOnEof(); 1.1425 + } 1.1426 + mode = AFTER_HEAD; 1.1427 + continue; 1.1428 + case IN_HEAD_NOSCRIPT: 1.1429 + // [NOCPP[ 1.1430 + errEofWithUnclosedElements(); 1.1431 + // ]NOCPP] 1.1432 + while (currentPtr > 1) { 1.1433 + popOnEof(); 1.1434 + } 1.1435 + mode = IN_HEAD; 1.1436 + continue; 1.1437 + case AFTER_HEAD: 1.1438 + appendToCurrentNodeAndPushBodyElement(); 1.1439 + mode = IN_BODY; 1.1440 + continue; 1.1441 + case IN_TABLE_BODY: 1.1442 + case IN_ROW: 1.1443 + case IN_TABLE: 1.1444 + case IN_SELECT_IN_TABLE: 1.1445 + case IN_SELECT: 1.1446 + case IN_COLUMN_GROUP: 1.1447 + case FRAMESET_OK: 1.1448 + case IN_CAPTION: 1.1449 + case IN_CELL: 1.1450 + case IN_BODY: 1.1451 + // [NOCPP[ 1.1452 + openelementloop: for (int i = currentPtr; i >= 0; i--) { 1.1453 + int group = stack[i].getGroup(); 1.1454 + switch (group) { 1.1455 + case DD_OR_DT: 1.1456 + case LI: 1.1457 + case P: 1.1458 + case TBODY_OR_THEAD_OR_TFOOT: 1.1459 + case TD_OR_TH: 1.1460 + case BODY: 1.1461 + case HTML: 1.1462 + break; 1.1463 + default: 1.1464 + errEofWithUnclosedElements(); 1.1465 + break openelementloop; 1.1466 + } 1.1467 + } 1.1468 + // ]NOCPP] 1.1469 + 1.1470 + if (isTemplateModeStackEmpty()) { 1.1471 + break eofloop; 1.1472 + } 1.1473 + 1.1474 + // fall through to IN_TEMPLATE 1.1475 + case IN_TEMPLATE: 1.1476 + int eltPos = findLast("template"); 1.1477 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.1478 + assert fragment; 1.1479 + break eofloop; 1.1480 + } 1.1481 + if (errorHandler != null) { 1.1482 + errUnclosedElements(eltPos, "template"); 1.1483 + } 1.1484 + while (currentPtr >= eltPos) { 1.1485 + pop(); 1.1486 + } 1.1487 + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); 1.1488 + popTemplateMode(); 1.1489 + resetTheInsertionMode(); 1.1490 + 1.1491 + // Reprocess token. 1.1492 + continue; 1.1493 + case TEXT: 1.1494 + // [NOCPP[ 1.1495 + if (errorHandler != null) { 1.1496 + errNoCheck("End of file seen when expecting text or an end tag."); 1.1497 + errListUnclosedStartTags(0); 1.1498 + } 1.1499 + // ]NOCPP] 1.1500 + // XXX mark script as already executed 1.1501 + if (originalMode == AFTER_HEAD) { 1.1502 + popOnEof(); 1.1503 + } 1.1504 + popOnEof(); 1.1505 + mode = originalMode; 1.1506 + continue; 1.1507 + case IN_FRAMESET: 1.1508 + // [NOCPP[ 1.1509 + if (errorHandler != null && currentPtr > 0) { 1.1510 + errEofWithUnclosedElements(); 1.1511 + } 1.1512 + // ]NOCPP] 1.1513 + break eofloop; 1.1514 + case AFTER_BODY: 1.1515 + case AFTER_FRAMESET: 1.1516 + case AFTER_AFTER_BODY: 1.1517 + case AFTER_AFTER_FRAMESET: 1.1518 + default: 1.1519 + // [NOCPP[ 1.1520 + if (currentPtr == 0) { // This silliness is here to poison 1.1521 + // buggy compiler optimizations in 1.1522 + // GWT 1.1523 + System.currentTimeMillis(); 1.1524 + } 1.1525 + // ]NOCPP] 1.1526 + break eofloop; 1.1527 + } 1.1528 + } 1.1529 + while (currentPtr > 0) { 1.1530 + popOnEof(); 1.1531 + } 1.1532 + if (!fragment) { 1.1533 + popOnEof(); 1.1534 + } 1.1535 + /* Stop parsing. */ 1.1536 + } 1.1537 + 1.1538 + /** 1.1539 + * @see nu.validator.htmlparser.common.TokenHandler#endTokenization() 1.1540 + */ 1.1541 + public final void endTokenization() throws SAXException { 1.1542 + formPointer = null; 1.1543 + headPointer = null; 1.1544 + deepTreeSurrogateParent = null; 1.1545 + templateModeStack = null; 1.1546 + if (stack != null) { 1.1547 + while (currentPtr > -1) { 1.1548 + stack[currentPtr].release(); 1.1549 + currentPtr--; 1.1550 + } 1.1551 + stack = null; 1.1552 + } 1.1553 + if (listOfActiveFormattingElements != null) { 1.1554 + while (listPtr > -1) { 1.1555 + if (listOfActiveFormattingElements[listPtr] != null) { 1.1556 + listOfActiveFormattingElements[listPtr].release(); 1.1557 + } 1.1558 + listPtr--; 1.1559 + } 1.1560 + listOfActiveFormattingElements = null; 1.1561 + } 1.1562 + // [NOCPP[ 1.1563 + idLocations.clear(); 1.1564 + // ]NOCPP] 1.1565 + charBuffer = null; 1.1566 + end(); 1.1567 + } 1.1568 + 1.1569 + public final void startTag(ElementName elementName, 1.1570 + HtmlAttributes attributes, boolean selfClosing) throws SAXException { 1.1571 + flushCharacters(); 1.1572 + 1.1573 + // [NOCPP[ 1.1574 + if (errorHandler != null) { 1.1575 + // ID uniqueness 1.1576 + @IdType String id = attributes.getId(); 1.1577 + if (id != null) { 1.1578 + LocatorImpl oldLoc = idLocations.get(id); 1.1579 + if (oldLoc != null) { 1.1580 + err("Duplicate ID \u201C" + id + "\u201D."); 1.1581 + errorHandler.warning(new SAXParseException( 1.1582 + "The first occurrence of ID \u201C" + id 1.1583 + + "\u201D was here.", oldLoc)); 1.1584 + } else { 1.1585 + idLocations.put(id, new LocatorImpl(tokenizer)); 1.1586 + } 1.1587 + } 1.1588 + } 1.1589 + // ]NOCPP] 1.1590 + 1.1591 + int eltPos; 1.1592 + needToDropLF = false; 1.1593 + starttagloop: for (;;) { 1.1594 + int group = elementName.getGroup(); 1.1595 + @Local String name = elementName.name; 1.1596 + if (isInForeign()) { 1.1597 + StackNode<T> currentNode = stack[currentPtr]; 1.1598 + @NsUri String currNs = currentNode.ns; 1.1599 + 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))))) { 1.1600 + switch (group) { 1.1601 + case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: 1.1602 + case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: 1.1603 + case BODY: 1.1604 + case BR: 1.1605 + case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR: 1.1606 + case DD_OR_DT: 1.1607 + case UL_OR_OL_OR_DL: 1.1608 + case EMBED: 1.1609 + case IMG: 1.1610 + case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: 1.1611 + case HEAD: 1.1612 + case HR: 1.1613 + case LI: 1.1614 + case META: 1.1615 + case NOBR: 1.1616 + case P: 1.1617 + case PRE_OR_LISTING: 1.1618 + case TABLE: 1.1619 + errHtmlStartTagInForeignContext(name); 1.1620 + while (!isSpecialParentInForeign(stack[currentPtr])) { 1.1621 + pop(); 1.1622 + } 1.1623 + continue starttagloop; 1.1624 + case FONT: 1.1625 + if (attributes.contains(AttributeName.COLOR) 1.1626 + || attributes.contains(AttributeName.FACE) 1.1627 + || attributes.contains(AttributeName.SIZE)) { 1.1628 + errHtmlStartTagInForeignContext(name); 1.1629 + while (!isSpecialParentInForeign(stack[currentPtr])) { 1.1630 + pop(); 1.1631 + } 1.1632 + continue starttagloop; 1.1633 + } 1.1634 + // else fall thru 1.1635 + default: 1.1636 + if ("http://www.w3.org/2000/svg" == currNs) { 1.1637 + attributes.adjustForSvg(); 1.1638 + if (selfClosing) { 1.1639 + appendVoidElementToCurrentMayFosterSVG( 1.1640 + elementName, attributes); 1.1641 + selfClosing = false; 1.1642 + } else { 1.1643 + appendToCurrentNodeAndPushElementMayFosterSVG( 1.1644 + elementName, attributes); 1.1645 + } 1.1646 + attributes = null; // CPP 1.1647 + break starttagloop; 1.1648 + } else { 1.1649 + attributes.adjustForMath(); 1.1650 + if (selfClosing) { 1.1651 + appendVoidElementToCurrentMayFosterMathML( 1.1652 + elementName, attributes); 1.1653 + selfClosing = false; 1.1654 + } else { 1.1655 + appendToCurrentNodeAndPushElementMayFosterMathML( 1.1656 + elementName, attributes); 1.1657 + } 1.1658 + attributes = null; // CPP 1.1659 + break starttagloop; 1.1660 + } 1.1661 + } // switch 1.1662 + } // foreignObject / annotation-xml 1.1663 + } 1.1664 + switch (mode) { 1.1665 + case IN_TEMPLATE: 1.1666 + switch (group) { 1.1667 + case COL: 1.1668 + popTemplateMode(); 1.1669 + pushTemplateMode(IN_COLUMN_GROUP); 1.1670 + mode = IN_COLUMN_GROUP; 1.1671 + // Reprocess token. 1.1672 + continue; 1.1673 + case CAPTION: 1.1674 + case COLGROUP: 1.1675 + case TBODY_OR_THEAD_OR_TFOOT: 1.1676 + popTemplateMode(); 1.1677 + pushTemplateMode(IN_TABLE); 1.1678 + mode = IN_TABLE; 1.1679 + // Reprocess token. 1.1680 + continue; 1.1681 + case TR: 1.1682 + popTemplateMode(); 1.1683 + pushTemplateMode(IN_TABLE_BODY); 1.1684 + mode = IN_TABLE_BODY; 1.1685 + // Reprocess token. 1.1686 + continue; 1.1687 + case TD_OR_TH: 1.1688 + popTemplateMode(); 1.1689 + pushTemplateMode(IN_ROW); 1.1690 + mode = IN_ROW; 1.1691 + // Reprocess token. 1.1692 + continue; 1.1693 + case META: 1.1694 + checkMetaCharset(attributes); 1.1695 + appendVoidElementToCurrentMayFoster( 1.1696 + elementName, 1.1697 + attributes); 1.1698 + selfClosing = false; 1.1699 + attributes = null; // CPP 1.1700 + break starttagloop; 1.1701 + case TITLE: 1.1702 + startTagTitleInHead(elementName, attributes); 1.1703 + attributes = null; // CPP 1.1704 + break starttagloop; 1.1705 + case BASE: 1.1706 + case LINK_OR_BASEFONT_OR_BGSOUND: 1.1707 + appendVoidElementToCurrentMayFoster( 1.1708 + elementName, 1.1709 + attributes); 1.1710 + selfClosing = false; 1.1711 + attributes = null; // CPP 1.1712 + break starttagloop; 1.1713 + case SCRIPT: 1.1714 + startTagScriptInHead(elementName, attributes); 1.1715 + attributes = null; // CPP 1.1716 + break starttagloop; 1.1717 + case NOFRAMES: 1.1718 + case STYLE: 1.1719 + startTagGenericRawText(elementName, attributes); 1.1720 + attributes = null; // CPP 1.1721 + break starttagloop; 1.1722 + case TEMPLATE: 1.1723 + startTagTemplateInHead(elementName, attributes); 1.1724 + attributes = null; // CPP 1.1725 + break starttagloop; 1.1726 + default: 1.1727 + popTemplateMode(); 1.1728 + pushTemplateMode(IN_BODY); 1.1729 + mode = IN_BODY; 1.1730 + // Reprocess token. 1.1731 + continue; 1.1732 + } 1.1733 + case IN_ROW: 1.1734 + switch (group) { 1.1735 + case TD_OR_TH: 1.1736 + clearStackBackTo(findLastOrRoot(TreeBuilder.TR)); 1.1737 + appendToCurrentNodeAndPushElement( 1.1738 + elementName, 1.1739 + attributes); 1.1740 + mode = IN_CELL; 1.1741 + insertMarker(); 1.1742 + attributes = null; // CPP 1.1743 + break starttagloop; 1.1744 + case CAPTION: 1.1745 + case COL: 1.1746 + case COLGROUP: 1.1747 + case TBODY_OR_THEAD_OR_TFOOT: 1.1748 + case TR: 1.1749 + eltPos = findLastOrRoot(TreeBuilder.TR); 1.1750 + if (eltPos == 0) { 1.1751 + assert fragment || isTemplateContents(); 1.1752 + errNoTableRowToClose(); 1.1753 + break starttagloop; 1.1754 + } 1.1755 + clearStackBackTo(eltPos); 1.1756 + pop(); 1.1757 + mode = IN_TABLE_BODY; 1.1758 + continue; 1.1759 + default: 1.1760 + // fall through to IN_TABLE 1.1761 + } 1.1762 + case IN_TABLE_BODY: 1.1763 + switch (group) { 1.1764 + case TR: 1.1765 + clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot()); 1.1766 + appendToCurrentNodeAndPushElement( 1.1767 + elementName, 1.1768 + attributes); 1.1769 + mode = IN_ROW; 1.1770 + attributes = null; // CPP 1.1771 + break starttagloop; 1.1772 + case TD_OR_TH: 1.1773 + errStartTagInTableBody(name); 1.1774 + clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot()); 1.1775 + appendToCurrentNodeAndPushElement( 1.1776 + ElementName.TR, 1.1777 + HtmlAttributes.EMPTY_ATTRIBUTES); 1.1778 + mode = IN_ROW; 1.1779 + continue; 1.1780 + case CAPTION: 1.1781 + case COL: 1.1782 + case COLGROUP: 1.1783 + case TBODY_OR_THEAD_OR_TFOOT: 1.1784 + eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot(); 1.1785 + if (eltPos == 0 || stack[eltPos].getGroup() == TEMPLATE) { 1.1786 + assert fragment || isTemplateContents(); 1.1787 + errStrayStartTag(name); 1.1788 + break starttagloop; 1.1789 + } else { 1.1790 + clearStackBackTo(eltPos); 1.1791 + pop(); 1.1792 + mode = IN_TABLE; 1.1793 + continue; 1.1794 + } 1.1795 + default: 1.1796 + // fall through to IN_TABLE 1.1797 + } 1.1798 + case IN_TABLE: 1.1799 + intableloop: for (;;) { 1.1800 + switch (group) { 1.1801 + case CAPTION: 1.1802 + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); 1.1803 + insertMarker(); 1.1804 + appendToCurrentNodeAndPushElement( 1.1805 + elementName, 1.1806 + attributes); 1.1807 + mode = IN_CAPTION; 1.1808 + attributes = null; // CPP 1.1809 + break starttagloop; 1.1810 + case COLGROUP: 1.1811 + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); 1.1812 + appendToCurrentNodeAndPushElement( 1.1813 + elementName, 1.1814 + attributes); 1.1815 + mode = IN_COLUMN_GROUP; 1.1816 + attributes = null; // CPP 1.1817 + break starttagloop; 1.1818 + case COL: 1.1819 + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); 1.1820 + appendToCurrentNodeAndPushElement( 1.1821 + ElementName.COLGROUP, 1.1822 + HtmlAttributes.EMPTY_ATTRIBUTES); 1.1823 + mode = IN_COLUMN_GROUP; 1.1824 + continue starttagloop; 1.1825 + case TBODY_OR_THEAD_OR_TFOOT: 1.1826 + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); 1.1827 + appendToCurrentNodeAndPushElement( 1.1828 + elementName, 1.1829 + attributes); 1.1830 + mode = IN_TABLE_BODY; 1.1831 + attributes = null; // CPP 1.1832 + break starttagloop; 1.1833 + case TR: 1.1834 + case TD_OR_TH: 1.1835 + clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE)); 1.1836 + appendToCurrentNodeAndPushElement( 1.1837 + ElementName.TBODY, 1.1838 + HtmlAttributes.EMPTY_ATTRIBUTES); 1.1839 + mode = IN_TABLE_BODY; 1.1840 + continue starttagloop; 1.1841 + case TEMPLATE: 1.1842 + // fall through to IN_HEAD 1.1843 + break intableloop; 1.1844 + case TABLE: 1.1845 + errTableSeenWhileTableOpen(); 1.1846 + eltPos = findLastInTableScope(name); 1.1847 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.1848 + assert fragment || isTemplateContents(); 1.1849 + break starttagloop; 1.1850 + } 1.1851 + generateImpliedEndTags(); 1.1852 + // XXX is the next if dead code? 1.1853 + if (errorHandler != null && !isCurrent("table")) { 1.1854 + errNoCheckUnclosedElementsOnStack(); 1.1855 + } 1.1856 + while (currentPtr >= eltPos) { 1.1857 + pop(); 1.1858 + } 1.1859 + resetTheInsertionMode(); 1.1860 + continue starttagloop; 1.1861 + case SCRIPT: 1.1862 + // XXX need to manage much more stuff 1.1863 + // here if 1.1864 + // supporting 1.1865 + // document.write() 1.1866 + appendToCurrentNodeAndPushElement( 1.1867 + elementName, 1.1868 + attributes); 1.1869 + originalMode = mode; 1.1870 + mode = TEXT; 1.1871 + tokenizer.setStateAndEndTagExpectation( 1.1872 + Tokenizer.SCRIPT_DATA, elementName); 1.1873 + attributes = null; // CPP 1.1874 + break starttagloop; 1.1875 + case STYLE: 1.1876 + appendToCurrentNodeAndPushElement( 1.1877 + elementName, 1.1878 + attributes); 1.1879 + originalMode = mode; 1.1880 + mode = TEXT; 1.1881 + tokenizer.setStateAndEndTagExpectation( 1.1882 + Tokenizer.RAWTEXT, elementName); 1.1883 + attributes = null; // CPP 1.1884 + break starttagloop; 1.1885 + case INPUT: 1.1886 + errStartTagInTable(name); 1.1887 + if (!Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.1888 + "hidden", 1.1889 + attributes.getValue(AttributeName.TYPE))) { 1.1890 + break intableloop; 1.1891 + } 1.1892 + appendVoidElementToCurrent( 1.1893 + name, attributes, 1.1894 + formPointer); 1.1895 + selfClosing = false; 1.1896 + attributes = null; // CPP 1.1897 + break starttagloop; 1.1898 + case FORM: 1.1899 + if (formPointer != null || isTemplateContents()) { 1.1900 + errFormWhenFormOpen(); 1.1901 + break starttagloop; 1.1902 + } else { 1.1903 + errStartTagInTable(name); 1.1904 + appendVoidFormToCurrent(attributes); 1.1905 + attributes = null; // CPP 1.1906 + break starttagloop; 1.1907 + } 1.1908 + default: 1.1909 + errStartTagInTable(name); 1.1910 + // fall through to IN_BODY 1.1911 + break intableloop; 1.1912 + } 1.1913 + } 1.1914 + case IN_CAPTION: 1.1915 + switch (group) { 1.1916 + case CAPTION: 1.1917 + case COL: 1.1918 + case COLGROUP: 1.1919 + case TBODY_OR_THEAD_OR_TFOOT: 1.1920 + case TR: 1.1921 + case TD_OR_TH: 1.1922 + errStrayStartTag(name); 1.1923 + eltPos = findLastInTableScope("caption"); 1.1924 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.1925 + break starttagloop; 1.1926 + } 1.1927 + generateImpliedEndTags(); 1.1928 + if (errorHandler != null && currentPtr != eltPos) { 1.1929 + errNoCheckUnclosedElementsOnStack(); 1.1930 + } 1.1931 + while (currentPtr >= eltPos) { 1.1932 + pop(); 1.1933 + } 1.1934 + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); 1.1935 + mode = IN_TABLE; 1.1936 + continue; 1.1937 + default: 1.1938 + // fall through to IN_BODY 1.1939 + } 1.1940 + case IN_CELL: 1.1941 + switch (group) { 1.1942 + case CAPTION: 1.1943 + case COL: 1.1944 + case COLGROUP: 1.1945 + case TBODY_OR_THEAD_OR_TFOOT: 1.1946 + case TR: 1.1947 + case TD_OR_TH: 1.1948 + eltPos = findLastInTableScopeTdTh(); 1.1949 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.1950 + errNoCellToClose(); 1.1951 + break starttagloop; 1.1952 + } else { 1.1953 + closeTheCell(eltPos); 1.1954 + continue; 1.1955 + } 1.1956 + default: 1.1957 + // fall through to IN_BODY 1.1958 + } 1.1959 + case FRAMESET_OK: 1.1960 + switch (group) { 1.1961 + case FRAMESET: 1.1962 + if (mode == FRAMESET_OK) { 1.1963 + if (currentPtr == 0 || stack[1].getGroup() != BODY) { 1.1964 + assert fragment || isTemplateContents(); 1.1965 + errStrayStartTag(name); 1.1966 + break starttagloop; 1.1967 + } else { 1.1968 + errFramesetStart(); 1.1969 + detachFromParent(stack[1].node); 1.1970 + while (currentPtr > 0) { 1.1971 + pop(); 1.1972 + } 1.1973 + appendToCurrentNodeAndPushElement( 1.1974 + elementName, 1.1975 + attributes); 1.1976 + mode = IN_FRAMESET; 1.1977 + attributes = null; // CPP 1.1978 + break starttagloop; 1.1979 + } 1.1980 + } else { 1.1981 + errStrayStartTag(name); 1.1982 + break starttagloop; 1.1983 + } 1.1984 + // NOT falling through! 1.1985 + case PRE_OR_LISTING: 1.1986 + case LI: 1.1987 + case DD_OR_DT: 1.1988 + case BUTTON: 1.1989 + case MARQUEE_OR_APPLET: 1.1990 + case OBJECT: 1.1991 + case TABLE: 1.1992 + case AREA_OR_WBR: 1.1993 + case BR: 1.1994 + case EMBED: 1.1995 + case IMG: 1.1996 + case INPUT: 1.1997 + case KEYGEN: 1.1998 + case HR: 1.1999 + case TEXTAREA: 1.2000 + case XMP: 1.2001 + case IFRAME: 1.2002 + case SELECT: 1.2003 + if (mode == FRAMESET_OK 1.2004 + && !(group == INPUT && Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.2005 + "hidden", 1.2006 + attributes.getValue(AttributeName.TYPE)))) { 1.2007 + framesetOk = false; 1.2008 + mode = IN_BODY; 1.2009 + } 1.2010 + // fall through to IN_BODY 1.2011 + default: 1.2012 + // fall through to IN_BODY 1.2013 + } 1.2014 + case IN_BODY: 1.2015 + inbodyloop: for (;;) { 1.2016 + switch (group) { 1.2017 + case HTML: 1.2018 + errStrayStartTag(name); 1.2019 + if (!fragment && !isTemplateContents()) { 1.2020 + addAttributesToHtml(attributes); 1.2021 + attributes = null; // CPP 1.2022 + } 1.2023 + break starttagloop; 1.2024 + case BASE: 1.2025 + case LINK_OR_BASEFONT_OR_BGSOUND: 1.2026 + case META: 1.2027 + case STYLE: 1.2028 + case SCRIPT: 1.2029 + case TITLE: 1.2030 + case TEMPLATE: 1.2031 + // Fall through to IN_HEAD 1.2032 + break inbodyloop; 1.2033 + case BODY: 1.2034 + if (currentPtr == 0 || stack[1].getGroup() != BODY || isTemplateContents()) { 1.2035 + assert fragment || isTemplateContents(); 1.2036 + errStrayStartTag(name); 1.2037 + break starttagloop; 1.2038 + } 1.2039 + errFooSeenWhenFooOpen(name); 1.2040 + framesetOk = false; 1.2041 + if (mode == FRAMESET_OK) { 1.2042 + mode = IN_BODY; 1.2043 + } 1.2044 + if (addAttributesToBody(attributes)) { 1.2045 + attributes = null; // CPP 1.2046 + } 1.2047 + break starttagloop; 1.2048 + case P: 1.2049 + case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: 1.2050 + case UL_OR_OL_OR_DL: 1.2051 + 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: 1.2052 + implicitlyCloseP(); 1.2053 + appendToCurrentNodeAndPushElementMayFoster( 1.2054 + elementName, 1.2055 + attributes); 1.2056 + attributes = null; // CPP 1.2057 + break starttagloop; 1.2058 + case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: 1.2059 + implicitlyCloseP(); 1.2060 + if (stack[currentPtr].getGroup() == H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) { 1.2061 + errHeadingWhenHeadingOpen(); 1.2062 + pop(); 1.2063 + } 1.2064 + appendToCurrentNodeAndPushElementMayFoster( 1.2065 + elementName, 1.2066 + attributes); 1.2067 + attributes = null; // CPP 1.2068 + break starttagloop; 1.2069 + case FIELDSET: 1.2070 + implicitlyCloseP(); 1.2071 + appendToCurrentNodeAndPushElementMayFoster( 1.2072 + elementName, 1.2073 + attributes, formPointer); 1.2074 + attributes = null; // CPP 1.2075 + break starttagloop; 1.2076 + case PRE_OR_LISTING: 1.2077 + implicitlyCloseP(); 1.2078 + appendToCurrentNodeAndPushElementMayFoster( 1.2079 + elementName, 1.2080 + attributes); 1.2081 + needToDropLF = true; 1.2082 + attributes = null; // CPP 1.2083 + break starttagloop; 1.2084 + case FORM: 1.2085 + if (formPointer != null && !isTemplateContents()) { 1.2086 + errFormWhenFormOpen(); 1.2087 + break starttagloop; 1.2088 + } else { 1.2089 + implicitlyCloseP(); 1.2090 + appendToCurrentNodeAndPushFormElementMayFoster(attributes); 1.2091 + attributes = null; // CPP 1.2092 + break starttagloop; 1.2093 + } 1.2094 + case LI: 1.2095 + case DD_OR_DT: 1.2096 + eltPos = currentPtr; 1.2097 + for (;;) { 1.2098 + StackNode<T> node = stack[eltPos]; // weak 1.2099 + // ref 1.2100 + if (node.getGroup() == group) { // LI or 1.2101 + // DD_OR_DT 1.2102 + generateImpliedEndTagsExceptFor(node.name); 1.2103 + if (errorHandler != null 1.2104 + && eltPos != currentPtr) { 1.2105 + errUnclosedElementsImplied(eltPos, name); 1.2106 + } 1.2107 + while (currentPtr >= eltPos) { 1.2108 + pop(); 1.2109 + } 1.2110 + break; 1.2111 + } else if (node.isSpecial() 1.2112 + && (node.ns != "http://www.w3.org/1999/xhtml" 1.2113 + || (node.name != "p" 1.2114 + && node.name != "address" 1.2115 + && node.name != "div"))) { 1.2116 + break; 1.2117 + } 1.2118 + eltPos--; 1.2119 + } 1.2120 + implicitlyCloseP(); 1.2121 + appendToCurrentNodeAndPushElementMayFoster( 1.2122 + elementName, 1.2123 + attributes); 1.2124 + attributes = null; // CPP 1.2125 + break starttagloop; 1.2126 + case PLAINTEXT: 1.2127 + implicitlyCloseP(); 1.2128 + appendToCurrentNodeAndPushElementMayFoster( 1.2129 + elementName, 1.2130 + attributes); 1.2131 + tokenizer.setStateAndEndTagExpectation( 1.2132 + Tokenizer.PLAINTEXT, elementName); 1.2133 + attributes = null; // CPP 1.2134 + break starttagloop; 1.2135 + case A: 1.2136 + int activeAPos = findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker("a"); 1.2137 + if (activeAPos != -1) { 1.2138 + errFooSeenWhenFooOpen(name); 1.2139 + StackNode<T> activeA = listOfActiveFormattingElements[activeAPos]; 1.2140 + activeA.retain(); 1.2141 + adoptionAgencyEndTag("a"); 1.2142 + removeFromStack(activeA); 1.2143 + activeAPos = findInListOfActiveFormattingElements(activeA); 1.2144 + if (activeAPos != -1) { 1.2145 + removeFromListOfActiveFormattingElements(activeAPos); 1.2146 + } 1.2147 + activeA.release(); 1.2148 + } 1.2149 + reconstructTheActiveFormattingElements(); 1.2150 + appendToCurrentNodeAndPushFormattingElementMayFoster( 1.2151 + elementName, 1.2152 + attributes); 1.2153 + attributes = null; // CPP 1.2154 + break starttagloop; 1.2155 + case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: 1.2156 + case FONT: 1.2157 + reconstructTheActiveFormattingElements(); 1.2158 + maybeForgetEarlierDuplicateFormattingElement(elementName.name, attributes); 1.2159 + appendToCurrentNodeAndPushFormattingElementMayFoster( 1.2160 + elementName, 1.2161 + attributes); 1.2162 + attributes = null; // CPP 1.2163 + break starttagloop; 1.2164 + case NOBR: 1.2165 + reconstructTheActiveFormattingElements(); 1.2166 + if (TreeBuilder.NOT_FOUND_ON_STACK != findLastInScope("nobr")) { 1.2167 + errFooSeenWhenFooOpen(name); 1.2168 + adoptionAgencyEndTag("nobr"); 1.2169 + reconstructTheActiveFormattingElements(); 1.2170 + } 1.2171 + appendToCurrentNodeAndPushFormattingElementMayFoster( 1.2172 + elementName, 1.2173 + attributes); 1.2174 + attributes = null; // CPP 1.2175 + break starttagloop; 1.2176 + case BUTTON: 1.2177 + eltPos = findLastInScope(name); 1.2178 + if (eltPos != TreeBuilder.NOT_FOUND_ON_STACK) { 1.2179 + errFooSeenWhenFooOpen(name); 1.2180 + generateImpliedEndTags(); 1.2181 + if (errorHandler != null 1.2182 + && !isCurrent(name)) { 1.2183 + errUnclosedElementsImplied(eltPos, name); 1.2184 + } 1.2185 + while (currentPtr >= eltPos) { 1.2186 + pop(); 1.2187 + } 1.2188 + continue starttagloop; 1.2189 + } else { 1.2190 + reconstructTheActiveFormattingElements(); 1.2191 + appendToCurrentNodeAndPushElementMayFoster( 1.2192 + elementName, 1.2193 + attributes, formPointer); 1.2194 + attributes = null; // CPP 1.2195 + break starttagloop; 1.2196 + } 1.2197 + case OBJECT: 1.2198 + reconstructTheActiveFormattingElements(); 1.2199 + appendToCurrentNodeAndPushElementMayFoster( 1.2200 + elementName, 1.2201 + attributes, formPointer); 1.2202 + insertMarker(); 1.2203 + attributes = null; // CPP 1.2204 + break starttagloop; 1.2205 + case MARQUEE_OR_APPLET: 1.2206 + reconstructTheActiveFormattingElements(); 1.2207 + appendToCurrentNodeAndPushElementMayFoster( 1.2208 + elementName, 1.2209 + attributes); 1.2210 + insertMarker(); 1.2211 + attributes = null; // CPP 1.2212 + break starttagloop; 1.2213 + case TABLE: 1.2214 + // The only quirk. Blame Hixie and 1.2215 + // Acid2. 1.2216 + if (!quirks) { 1.2217 + implicitlyCloseP(); 1.2218 + } 1.2219 + appendToCurrentNodeAndPushElementMayFoster( 1.2220 + elementName, 1.2221 + attributes); 1.2222 + mode = IN_TABLE; 1.2223 + attributes = null; // CPP 1.2224 + break starttagloop; 1.2225 + case BR: 1.2226 + case EMBED: 1.2227 + case AREA_OR_WBR: 1.2228 + reconstructTheActiveFormattingElements(); 1.2229 + // FALL THROUGH to PARAM_OR_SOURCE_OR_TRACK 1.2230 + // CPPONLY: case MENUITEM: 1.2231 + case PARAM_OR_SOURCE_OR_TRACK: 1.2232 + appendVoidElementToCurrentMayFoster( 1.2233 + elementName, 1.2234 + attributes); 1.2235 + selfClosing = false; 1.2236 + attributes = null; // CPP 1.2237 + break starttagloop; 1.2238 + case HR: 1.2239 + implicitlyCloseP(); 1.2240 + appendVoidElementToCurrentMayFoster( 1.2241 + elementName, 1.2242 + attributes); 1.2243 + selfClosing = false; 1.2244 + attributes = null; // CPP 1.2245 + break starttagloop; 1.2246 + case IMAGE: 1.2247 + errImage(); 1.2248 + elementName = ElementName.IMG; 1.2249 + continue starttagloop; 1.2250 + case IMG: 1.2251 + case KEYGEN: 1.2252 + case INPUT: 1.2253 + reconstructTheActiveFormattingElements(); 1.2254 + appendVoidElementToCurrentMayFoster( 1.2255 + name, attributes, 1.2256 + formPointer); 1.2257 + selfClosing = false; 1.2258 + attributes = null; // CPP 1.2259 + break starttagloop; 1.2260 + case ISINDEX: 1.2261 + errIsindex(); 1.2262 + if (formPointer != null && !isTemplateContents()) { 1.2263 + break starttagloop; 1.2264 + } 1.2265 + implicitlyCloseP(); 1.2266 + HtmlAttributes formAttrs = new HtmlAttributes(0); 1.2267 + int actionIndex = attributes.getIndex(AttributeName.ACTION); 1.2268 + if (actionIndex > -1) { 1.2269 + formAttrs.addAttribute( 1.2270 + AttributeName.ACTION, 1.2271 + attributes.getValueNoBoundsCheck(actionIndex) 1.2272 + // [NOCPP[ 1.2273 + , XmlViolationPolicy.ALLOW 1.2274 + // ]NOCPP] 1.2275 + ); 1.2276 + } 1.2277 + appendToCurrentNodeAndPushFormElementMayFoster(formAttrs); 1.2278 + appendVoidElementToCurrentMayFoster( 1.2279 + ElementName.HR, 1.2280 + HtmlAttributes.EMPTY_ATTRIBUTES); 1.2281 + appendToCurrentNodeAndPushElementMayFoster( 1.2282 + ElementName.LABEL, 1.2283 + HtmlAttributes.EMPTY_ATTRIBUTES); 1.2284 + int promptIndex = attributes.getIndex(AttributeName.PROMPT); 1.2285 + if (promptIndex > -1) { 1.2286 + @Auto char[] prompt = Portability.newCharArrayFromString(attributes.getValueNoBoundsCheck(promptIndex)); 1.2287 + appendCharacters(stack[currentPtr].node, 1.2288 + prompt, 0, prompt.length); 1.2289 + } else { 1.2290 + appendIsindexPrompt(stack[currentPtr].node); 1.2291 + } 1.2292 + HtmlAttributes inputAttributes = new HtmlAttributes( 1.2293 + 0); 1.2294 + inputAttributes.addAttribute( 1.2295 + AttributeName.NAME, 1.2296 + Portability.newStringFromLiteral("isindex") 1.2297 + // [NOCPP[ 1.2298 + , XmlViolationPolicy.ALLOW 1.2299 + // ]NOCPP] 1.2300 + ); 1.2301 + for (int i = 0; i < attributes.getLength(); i++) { 1.2302 + AttributeName attributeQName = attributes.getAttributeNameNoBoundsCheck(i); 1.2303 + if (AttributeName.NAME == attributeQName 1.2304 + || AttributeName.PROMPT == attributeQName) { 1.2305 + attributes.releaseValue(i); 1.2306 + } else if (AttributeName.ACTION != attributeQName) { 1.2307 + inputAttributes.addAttribute( 1.2308 + attributeQName, 1.2309 + attributes.getValueNoBoundsCheck(i) 1.2310 + // [NOCPP[ 1.2311 + , XmlViolationPolicy.ALLOW 1.2312 + // ]NOCPP] 1.2313 + 1.2314 + ); 1.2315 + } 1.2316 + } 1.2317 + attributes.clearWithoutReleasingContents(); 1.2318 + appendVoidElementToCurrentMayFoster( 1.2319 + "input", 1.2320 + inputAttributes, formPointer); 1.2321 + pop(); // label 1.2322 + appendVoidElementToCurrentMayFoster( 1.2323 + ElementName.HR, 1.2324 + HtmlAttributes.EMPTY_ATTRIBUTES); 1.2325 + pop(); // form 1.2326 + 1.2327 + if (!isTemplateContents()) { 1.2328 + formPointer = null; 1.2329 + } 1.2330 + 1.2331 + selfClosing = false; 1.2332 + // Portability.delete(formAttrs); 1.2333 + // Portability.delete(inputAttributes); 1.2334 + // Don't delete attributes, they are deleted 1.2335 + // later 1.2336 + break starttagloop; 1.2337 + case TEXTAREA: 1.2338 + appendToCurrentNodeAndPushElementMayFoster( 1.2339 + elementName, 1.2340 + attributes, formPointer); 1.2341 + tokenizer.setStateAndEndTagExpectation( 1.2342 + Tokenizer.RCDATA, elementName); 1.2343 + originalMode = mode; 1.2344 + mode = TEXT; 1.2345 + needToDropLF = true; 1.2346 + attributes = null; // CPP 1.2347 + break starttagloop; 1.2348 + case XMP: 1.2349 + implicitlyCloseP(); 1.2350 + reconstructTheActiveFormattingElements(); 1.2351 + appendToCurrentNodeAndPushElementMayFoster( 1.2352 + elementName, 1.2353 + attributes); 1.2354 + originalMode = mode; 1.2355 + mode = TEXT; 1.2356 + tokenizer.setStateAndEndTagExpectation( 1.2357 + Tokenizer.RAWTEXT, elementName); 1.2358 + attributes = null; // CPP 1.2359 + break starttagloop; 1.2360 + case NOSCRIPT: 1.2361 + if (!scriptingEnabled) { 1.2362 + reconstructTheActiveFormattingElements(); 1.2363 + appendToCurrentNodeAndPushElementMayFoster( 1.2364 + elementName, 1.2365 + attributes); 1.2366 + attributes = null; // CPP 1.2367 + break starttagloop; 1.2368 + } else { 1.2369 + // fall through 1.2370 + } 1.2371 + case NOFRAMES: 1.2372 + case IFRAME: 1.2373 + case NOEMBED: 1.2374 + startTagGenericRawText(elementName, attributes); 1.2375 + attributes = null; // CPP 1.2376 + break starttagloop; 1.2377 + case SELECT: 1.2378 + reconstructTheActiveFormattingElements(); 1.2379 + appendToCurrentNodeAndPushElementMayFoster( 1.2380 + elementName, 1.2381 + attributes, formPointer); 1.2382 + switch (mode) { 1.2383 + case IN_TABLE: 1.2384 + case IN_CAPTION: 1.2385 + case IN_COLUMN_GROUP: 1.2386 + case IN_TABLE_BODY: 1.2387 + case IN_ROW: 1.2388 + case IN_CELL: 1.2389 + mode = IN_SELECT_IN_TABLE; 1.2390 + break; 1.2391 + default: 1.2392 + mode = IN_SELECT; 1.2393 + break; 1.2394 + } 1.2395 + attributes = null; // CPP 1.2396 + break starttagloop; 1.2397 + case OPTGROUP: 1.2398 + case OPTION: 1.2399 + if (isCurrent("option")) { 1.2400 + pop(); 1.2401 + } 1.2402 + reconstructTheActiveFormattingElements(); 1.2403 + appendToCurrentNodeAndPushElementMayFoster( 1.2404 + elementName, 1.2405 + attributes); 1.2406 + attributes = null; // CPP 1.2407 + break starttagloop; 1.2408 + case RT_OR_RP: 1.2409 + eltPos = findLastInScope("ruby"); 1.2410 + if (eltPos != NOT_FOUND_ON_STACK) { 1.2411 + generateImpliedEndTags(); 1.2412 + } 1.2413 + if (eltPos != currentPtr) { 1.2414 + if (eltPos != NOT_FOUND_ON_STACK) { 1.2415 + errStartTagSeenWithoutRuby(name); 1.2416 + } else { 1.2417 + errUnclosedChildrenInRuby(); 1.2418 + } 1.2419 + } 1.2420 + appendToCurrentNodeAndPushElementMayFoster( 1.2421 + elementName, 1.2422 + attributes); 1.2423 + attributes = null; // CPP 1.2424 + break starttagloop; 1.2425 + case MATH: 1.2426 + reconstructTheActiveFormattingElements(); 1.2427 + attributes.adjustForMath(); 1.2428 + if (selfClosing) { 1.2429 + appendVoidElementToCurrentMayFosterMathML( 1.2430 + elementName, attributes); 1.2431 + selfClosing = false; 1.2432 + } else { 1.2433 + appendToCurrentNodeAndPushElementMayFosterMathML( 1.2434 + elementName, attributes); 1.2435 + } 1.2436 + attributes = null; // CPP 1.2437 + break starttagloop; 1.2438 + case SVG: 1.2439 + reconstructTheActiveFormattingElements(); 1.2440 + attributes.adjustForSvg(); 1.2441 + if (selfClosing) { 1.2442 + appendVoidElementToCurrentMayFosterSVG( 1.2443 + elementName, 1.2444 + attributes); 1.2445 + selfClosing = false; 1.2446 + } else { 1.2447 + appendToCurrentNodeAndPushElementMayFosterSVG( 1.2448 + elementName, attributes); 1.2449 + } 1.2450 + attributes = null; // CPP 1.2451 + break starttagloop; 1.2452 + case CAPTION: 1.2453 + case COL: 1.2454 + case COLGROUP: 1.2455 + case TBODY_OR_THEAD_OR_TFOOT: 1.2456 + case TR: 1.2457 + case TD_OR_TH: 1.2458 + case FRAME: 1.2459 + case FRAMESET: 1.2460 + case HEAD: 1.2461 + errStrayStartTag(name); 1.2462 + break starttagloop; 1.2463 + case OUTPUT_OR_LABEL: 1.2464 + reconstructTheActiveFormattingElements(); 1.2465 + appendToCurrentNodeAndPushElementMayFoster( 1.2466 + elementName, 1.2467 + attributes, formPointer); 1.2468 + attributes = null; // CPP 1.2469 + break starttagloop; 1.2470 + default: 1.2471 + reconstructTheActiveFormattingElements(); 1.2472 + appendToCurrentNodeAndPushElementMayFoster( 1.2473 + elementName, 1.2474 + attributes); 1.2475 + attributes = null; // CPP 1.2476 + break starttagloop; 1.2477 + } 1.2478 + } 1.2479 + case IN_HEAD: 1.2480 + inheadloop: for (;;) { 1.2481 + switch (group) { 1.2482 + case HTML: 1.2483 + errStrayStartTag(name); 1.2484 + if (!fragment && !isTemplateContents()) { 1.2485 + addAttributesToHtml(attributes); 1.2486 + attributes = null; // CPP 1.2487 + } 1.2488 + break starttagloop; 1.2489 + case BASE: 1.2490 + case LINK_OR_BASEFONT_OR_BGSOUND: 1.2491 + appendVoidElementToCurrentMayFoster( 1.2492 + elementName, 1.2493 + attributes); 1.2494 + selfClosing = false; 1.2495 + attributes = null; // CPP 1.2496 + break starttagloop; 1.2497 + case META: 1.2498 + // Fall through to IN_HEAD_NOSCRIPT 1.2499 + break inheadloop; 1.2500 + case TITLE: 1.2501 + startTagTitleInHead(elementName, attributes); 1.2502 + attributes = null; // CPP 1.2503 + break starttagloop; 1.2504 + case NOSCRIPT: 1.2505 + if (scriptingEnabled) { 1.2506 + appendToCurrentNodeAndPushElement( 1.2507 + elementName, 1.2508 + attributes); 1.2509 + originalMode = mode; 1.2510 + mode = TEXT; 1.2511 + tokenizer.setStateAndEndTagExpectation( 1.2512 + Tokenizer.RAWTEXT, elementName); 1.2513 + } else { 1.2514 + appendToCurrentNodeAndPushElementMayFoster( 1.2515 + elementName, 1.2516 + attributes); 1.2517 + mode = IN_HEAD_NOSCRIPT; 1.2518 + } 1.2519 + attributes = null; // CPP 1.2520 + break starttagloop; 1.2521 + case SCRIPT: 1.2522 + startTagScriptInHead(elementName, attributes); 1.2523 + attributes = null; // CPP 1.2524 + break starttagloop; 1.2525 + case STYLE: 1.2526 + case NOFRAMES: 1.2527 + startTagGenericRawText(elementName, attributes); 1.2528 + attributes = null; // CPP 1.2529 + break starttagloop; 1.2530 + case HEAD: 1.2531 + /* Parse error. */ 1.2532 + errFooSeenWhenFooOpen(name); 1.2533 + /* Ignore the token. */ 1.2534 + break starttagloop; 1.2535 + case TEMPLATE: 1.2536 + startTagTemplateInHead(elementName, attributes); 1.2537 + attributes = null; // CPP 1.2538 + break starttagloop; 1.2539 + default: 1.2540 + pop(); 1.2541 + mode = AFTER_HEAD; 1.2542 + continue starttagloop; 1.2543 + } 1.2544 + } 1.2545 + case IN_HEAD_NOSCRIPT: 1.2546 + switch (group) { 1.2547 + case HTML: 1.2548 + // XXX did Hixie really mean to omit "base" 1.2549 + // here? 1.2550 + errStrayStartTag(name); 1.2551 + if (!fragment && !isTemplateContents()) { 1.2552 + addAttributesToHtml(attributes); 1.2553 + attributes = null; // CPP 1.2554 + } 1.2555 + break starttagloop; 1.2556 + case LINK_OR_BASEFONT_OR_BGSOUND: 1.2557 + appendVoidElementToCurrentMayFoster( 1.2558 + elementName, 1.2559 + attributes); 1.2560 + selfClosing = false; 1.2561 + attributes = null; // CPP 1.2562 + break starttagloop; 1.2563 + case META: 1.2564 + checkMetaCharset(attributes); 1.2565 + appendVoidElementToCurrentMayFoster( 1.2566 + elementName, 1.2567 + attributes); 1.2568 + selfClosing = false; 1.2569 + attributes = null; // CPP 1.2570 + break starttagloop; 1.2571 + case STYLE: 1.2572 + case NOFRAMES: 1.2573 + appendToCurrentNodeAndPushElement( 1.2574 + elementName, 1.2575 + attributes); 1.2576 + originalMode = mode; 1.2577 + mode = TEXT; 1.2578 + tokenizer.setStateAndEndTagExpectation( 1.2579 + Tokenizer.RAWTEXT, elementName); 1.2580 + attributes = null; // CPP 1.2581 + break starttagloop; 1.2582 + case HEAD: 1.2583 + errFooSeenWhenFooOpen(name); 1.2584 + break starttagloop; 1.2585 + case NOSCRIPT: 1.2586 + errFooSeenWhenFooOpen(name); 1.2587 + break starttagloop; 1.2588 + default: 1.2589 + errBadStartTagInHead(name); 1.2590 + pop(); 1.2591 + mode = IN_HEAD; 1.2592 + continue; 1.2593 + } 1.2594 + case IN_COLUMN_GROUP: 1.2595 + switch (group) { 1.2596 + case HTML: 1.2597 + errStrayStartTag(name); 1.2598 + if (!fragment && !isTemplateContents()) { 1.2599 + addAttributesToHtml(attributes); 1.2600 + attributes = null; // CPP 1.2601 + } 1.2602 + break starttagloop; 1.2603 + case COL: 1.2604 + appendVoidElementToCurrentMayFoster( 1.2605 + elementName, 1.2606 + attributes); 1.2607 + selfClosing = false; 1.2608 + attributes = null; // CPP 1.2609 + break starttagloop; 1.2610 + case TEMPLATE: 1.2611 + startTagTemplateInHead(elementName, attributes); 1.2612 + attributes = null; // CPP 1.2613 + break starttagloop; 1.2614 + default: 1.2615 + if (currentPtr == 0 || stack[currentPtr].getGroup() == TEMPLATE) { 1.2616 + assert fragment || isTemplateContents(); 1.2617 + errGarbageInColgroup(); 1.2618 + break starttagloop; 1.2619 + } 1.2620 + pop(); 1.2621 + mode = IN_TABLE; 1.2622 + continue; 1.2623 + } 1.2624 + case IN_SELECT_IN_TABLE: 1.2625 + switch (group) { 1.2626 + case CAPTION: 1.2627 + case TBODY_OR_THEAD_OR_TFOOT: 1.2628 + case TR: 1.2629 + case TD_OR_TH: 1.2630 + case TABLE: 1.2631 + errStartTagWithSelectOpen(name); 1.2632 + eltPos = findLastInTableScope("select"); 1.2633 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.2634 + assert fragment; 1.2635 + break starttagloop; // http://www.w3.org/Bugs/Public/show_bug.cgi?id=8375 1.2636 + } 1.2637 + while (currentPtr >= eltPos) { 1.2638 + pop(); 1.2639 + } 1.2640 + resetTheInsertionMode(); 1.2641 + continue; 1.2642 + default: 1.2643 + // fall through to IN_SELECT 1.2644 + } 1.2645 + case IN_SELECT: 1.2646 + switch (group) { 1.2647 + case HTML: 1.2648 + errStrayStartTag(name); 1.2649 + if (!fragment) { 1.2650 + addAttributesToHtml(attributes); 1.2651 + attributes = null; // CPP 1.2652 + } 1.2653 + break starttagloop; 1.2654 + case OPTION: 1.2655 + if (isCurrent("option")) { 1.2656 + pop(); 1.2657 + } 1.2658 + appendToCurrentNodeAndPushElement( 1.2659 + elementName, 1.2660 + attributes); 1.2661 + attributes = null; // CPP 1.2662 + break starttagloop; 1.2663 + case OPTGROUP: 1.2664 + if (isCurrent("option")) { 1.2665 + pop(); 1.2666 + } 1.2667 + if (isCurrent("optgroup")) { 1.2668 + pop(); 1.2669 + } 1.2670 + appendToCurrentNodeAndPushElement( 1.2671 + elementName, 1.2672 + attributes); 1.2673 + attributes = null; // CPP 1.2674 + break starttagloop; 1.2675 + case SELECT: 1.2676 + errStartSelectWhereEndSelectExpected(); 1.2677 + eltPos = findLastInTableScope(name); 1.2678 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.2679 + assert fragment; 1.2680 + errNoSelectInTableScope(); 1.2681 + break starttagloop; 1.2682 + } else { 1.2683 + while (currentPtr >= eltPos) { 1.2684 + pop(); 1.2685 + } 1.2686 + resetTheInsertionMode(); 1.2687 + break starttagloop; 1.2688 + } 1.2689 + case INPUT: 1.2690 + case TEXTAREA: 1.2691 + case KEYGEN: 1.2692 + errStartTagWithSelectOpen(name); 1.2693 + eltPos = findLastInTableScope("select"); 1.2694 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.2695 + assert fragment; 1.2696 + break starttagloop; 1.2697 + } 1.2698 + while (currentPtr >= eltPos) { 1.2699 + pop(); 1.2700 + } 1.2701 + resetTheInsertionMode(); 1.2702 + continue; 1.2703 + case SCRIPT: 1.2704 + startTagScriptInHead(elementName, attributes); 1.2705 + attributes = null; // CPP 1.2706 + break starttagloop; 1.2707 + case TEMPLATE: 1.2708 + startTagTemplateInHead(elementName, attributes); 1.2709 + attributes = null; // CPP 1.2710 + break starttagloop; 1.2711 + default: 1.2712 + errStrayStartTag(name); 1.2713 + break starttagloop; 1.2714 + } 1.2715 + case AFTER_BODY: 1.2716 + switch (group) { 1.2717 + case HTML: 1.2718 + errStrayStartTag(name); 1.2719 + if (!fragment && !isTemplateContents()) { 1.2720 + addAttributesToHtml(attributes); 1.2721 + attributes = null; // CPP 1.2722 + } 1.2723 + break starttagloop; 1.2724 + default: 1.2725 + errStrayStartTag(name); 1.2726 + mode = framesetOk ? FRAMESET_OK : IN_BODY; 1.2727 + continue; 1.2728 + } 1.2729 + case IN_FRAMESET: 1.2730 + switch (group) { 1.2731 + case FRAMESET: 1.2732 + appendToCurrentNodeAndPushElement( 1.2733 + elementName, 1.2734 + attributes); 1.2735 + attributes = null; // CPP 1.2736 + break starttagloop; 1.2737 + case FRAME: 1.2738 + appendVoidElementToCurrentMayFoster( 1.2739 + elementName, 1.2740 + attributes); 1.2741 + selfClosing = false; 1.2742 + attributes = null; // CPP 1.2743 + break starttagloop; 1.2744 + default: 1.2745 + // fall through to AFTER_FRAMESET 1.2746 + } 1.2747 + case AFTER_FRAMESET: 1.2748 + switch (group) { 1.2749 + case HTML: 1.2750 + errStrayStartTag(name); 1.2751 + if (!fragment && !isTemplateContents()) { 1.2752 + addAttributesToHtml(attributes); 1.2753 + attributes = null; // CPP 1.2754 + } 1.2755 + break starttagloop; 1.2756 + case NOFRAMES: 1.2757 + appendToCurrentNodeAndPushElement( 1.2758 + elementName, 1.2759 + attributes); 1.2760 + originalMode = mode; 1.2761 + mode = TEXT; 1.2762 + tokenizer.setStateAndEndTagExpectation( 1.2763 + Tokenizer.RAWTEXT, elementName); 1.2764 + attributes = null; // CPP 1.2765 + break starttagloop; 1.2766 + default: 1.2767 + errStrayStartTag(name); 1.2768 + break starttagloop; 1.2769 + } 1.2770 + case INITIAL: 1.2771 + /* 1.2772 + * Parse error. 1.2773 + */ 1.2774 + // [NOCPP[ 1.2775 + switch (doctypeExpectation) { 1.2776 + case AUTO: 1.2777 + err("Start tag seen without seeing a doctype first. Expected e.g. \u201C<!DOCTYPE html>\u201D."); 1.2778 + break; 1.2779 + case HTML: 1.2780 + // ]NOCPP] 1.2781 + errStartTagWithoutDoctype(); 1.2782 + // [NOCPP[ 1.2783 + break; 1.2784 + case HTML401_STRICT: 1.2785 + 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."); 1.2786 + break; 1.2787 + case HTML401_TRANSITIONAL: 1.2788 + 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."); 1.2789 + break; 1.2790 + case NO_DOCTYPE_ERRORS: 1.2791 + } 1.2792 + // ]NOCPP] 1.2793 + /* 1.2794 + * 1.2795 + * Set the document to quirks mode. 1.2796 + */ 1.2797 + documentModeInternal(DocumentMode.QUIRKS_MODE, null, null, 1.2798 + false); 1.2799 + /* 1.2800 + * Then, switch to the root element mode of the tree 1.2801 + * construction stage 1.2802 + */ 1.2803 + mode = BEFORE_HTML; 1.2804 + /* 1.2805 + * and reprocess the current token. 1.2806 + */ 1.2807 + continue; 1.2808 + case BEFORE_HTML: 1.2809 + switch (group) { 1.2810 + case HTML: 1.2811 + // optimize error check and streaming SAX by 1.2812 + // hoisting 1.2813 + // "html" handling here. 1.2814 + if (attributes == HtmlAttributes.EMPTY_ATTRIBUTES) { 1.2815 + // This has the right magic side effect 1.2816 + // that 1.2817 + // it 1.2818 + // makes attributes in SAX Tree mutable. 1.2819 + appendHtmlElementToDocumentAndPush(); 1.2820 + } else { 1.2821 + appendHtmlElementToDocumentAndPush(attributes); 1.2822 + } 1.2823 + // XXX application cache should fire here 1.2824 + mode = BEFORE_HEAD; 1.2825 + attributes = null; // CPP 1.2826 + break starttagloop; 1.2827 + default: 1.2828 + /* 1.2829 + * Create an HTMLElement node with the tag name 1.2830 + * html, in the HTML namespace. Append it to the 1.2831 + * Document object. 1.2832 + */ 1.2833 + appendHtmlElementToDocumentAndPush(); 1.2834 + /* Switch to the main mode */ 1.2835 + mode = BEFORE_HEAD; 1.2836 + /* 1.2837 + * reprocess the current token. 1.2838 + */ 1.2839 + continue; 1.2840 + } 1.2841 + case BEFORE_HEAD: 1.2842 + switch (group) { 1.2843 + case HTML: 1.2844 + errStrayStartTag(name); 1.2845 + if (!fragment && !isTemplateContents()) { 1.2846 + addAttributesToHtml(attributes); 1.2847 + attributes = null; // CPP 1.2848 + } 1.2849 + break starttagloop; 1.2850 + case HEAD: 1.2851 + /* 1.2852 + * A start tag whose tag name is "head" 1.2853 + * 1.2854 + * Create an element for the token. 1.2855 + * 1.2856 + * Set the head element pointer to this new element 1.2857 + * node. 1.2858 + * 1.2859 + * Append the new element to the current node and 1.2860 + * push it onto the stack of open elements. 1.2861 + */ 1.2862 + appendToCurrentNodeAndPushHeadElement(attributes); 1.2863 + /* 1.2864 + * Change the insertion mode to "in head". 1.2865 + */ 1.2866 + mode = IN_HEAD; 1.2867 + attributes = null; // CPP 1.2868 + break starttagloop; 1.2869 + default: 1.2870 + /* 1.2871 + * Any other start tag token 1.2872 + * 1.2873 + * Act as if a start tag token with the tag name 1.2874 + * "head" and no attributes had been seen, 1.2875 + */ 1.2876 + appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES); 1.2877 + mode = IN_HEAD; 1.2878 + /* 1.2879 + * then reprocess the current token. 1.2880 + * 1.2881 + * This will result in an empty head element being 1.2882 + * generated, with the current token being 1.2883 + * reprocessed in the "after head" insertion mode. 1.2884 + */ 1.2885 + continue; 1.2886 + } 1.2887 + case AFTER_HEAD: 1.2888 + switch (group) { 1.2889 + case HTML: 1.2890 + errStrayStartTag(name); 1.2891 + if (!fragment && !isTemplateContents()) { 1.2892 + addAttributesToHtml(attributes); 1.2893 + attributes = null; // CPP 1.2894 + } 1.2895 + break starttagloop; 1.2896 + case BODY: 1.2897 + if (attributes.getLength() == 0) { 1.2898 + // This has the right magic side effect 1.2899 + // that 1.2900 + // it 1.2901 + // makes attributes in SAX Tree mutable. 1.2902 + appendToCurrentNodeAndPushBodyElement(); 1.2903 + } else { 1.2904 + appendToCurrentNodeAndPushBodyElement(attributes); 1.2905 + } 1.2906 + framesetOk = false; 1.2907 + mode = IN_BODY; 1.2908 + attributes = null; // CPP 1.2909 + break starttagloop; 1.2910 + case FRAMESET: 1.2911 + appendToCurrentNodeAndPushElement( 1.2912 + elementName, 1.2913 + attributes); 1.2914 + mode = IN_FRAMESET; 1.2915 + attributes = null; // CPP 1.2916 + break starttagloop; 1.2917 + case TEMPLATE: 1.2918 + errFooBetweenHeadAndBody(name); 1.2919 + pushHeadPointerOntoStack(); 1.2920 + StackNode<T> headOnStack = stack[currentPtr]; 1.2921 + startTagTemplateInHead(elementName, attributes); 1.2922 + removeFromStack(headOnStack); 1.2923 + attributes = null; // CPP 1.2924 + break starttagloop; 1.2925 + case BASE: 1.2926 + case LINK_OR_BASEFONT_OR_BGSOUND: 1.2927 + errFooBetweenHeadAndBody(name); 1.2928 + pushHeadPointerOntoStack(); 1.2929 + appendVoidElementToCurrentMayFoster( 1.2930 + elementName, 1.2931 + attributes); 1.2932 + selfClosing = false; 1.2933 + pop(); // head 1.2934 + attributes = null; // CPP 1.2935 + break starttagloop; 1.2936 + case META: 1.2937 + errFooBetweenHeadAndBody(name); 1.2938 + checkMetaCharset(attributes); 1.2939 + pushHeadPointerOntoStack(); 1.2940 + appendVoidElementToCurrentMayFoster( 1.2941 + elementName, 1.2942 + attributes); 1.2943 + selfClosing = false; 1.2944 + pop(); // head 1.2945 + attributes = null; // CPP 1.2946 + break starttagloop; 1.2947 + case SCRIPT: 1.2948 + errFooBetweenHeadAndBody(name); 1.2949 + pushHeadPointerOntoStack(); 1.2950 + appendToCurrentNodeAndPushElement( 1.2951 + elementName, 1.2952 + attributes); 1.2953 + originalMode = mode; 1.2954 + mode = TEXT; 1.2955 + tokenizer.setStateAndEndTagExpectation( 1.2956 + Tokenizer.SCRIPT_DATA, elementName); 1.2957 + attributes = null; // CPP 1.2958 + break starttagloop; 1.2959 + case STYLE: 1.2960 + case NOFRAMES: 1.2961 + errFooBetweenHeadAndBody(name); 1.2962 + pushHeadPointerOntoStack(); 1.2963 + appendToCurrentNodeAndPushElement( 1.2964 + elementName, 1.2965 + attributes); 1.2966 + originalMode = mode; 1.2967 + mode = TEXT; 1.2968 + tokenizer.setStateAndEndTagExpectation( 1.2969 + Tokenizer.RAWTEXT, elementName); 1.2970 + attributes = null; // CPP 1.2971 + break starttagloop; 1.2972 + case TITLE: 1.2973 + errFooBetweenHeadAndBody(name); 1.2974 + pushHeadPointerOntoStack(); 1.2975 + appendToCurrentNodeAndPushElement( 1.2976 + elementName, 1.2977 + attributes); 1.2978 + originalMode = mode; 1.2979 + mode = TEXT; 1.2980 + tokenizer.setStateAndEndTagExpectation( 1.2981 + Tokenizer.RCDATA, elementName); 1.2982 + attributes = null; // CPP 1.2983 + break starttagloop; 1.2984 + case HEAD: 1.2985 + errStrayStartTag(name); 1.2986 + break starttagloop; 1.2987 + default: 1.2988 + appendToCurrentNodeAndPushBodyElement(); 1.2989 + mode = FRAMESET_OK; 1.2990 + continue; 1.2991 + } 1.2992 + case AFTER_AFTER_BODY: 1.2993 + switch (group) { 1.2994 + case HTML: 1.2995 + errStrayStartTag(name); 1.2996 + if (!fragment && !isTemplateContents()) { 1.2997 + addAttributesToHtml(attributes); 1.2998 + attributes = null; // CPP 1.2999 + } 1.3000 + break starttagloop; 1.3001 + default: 1.3002 + errStrayStartTag(name); 1.3003 + fatal(); 1.3004 + mode = framesetOk ? FRAMESET_OK : IN_BODY; 1.3005 + continue; 1.3006 + } 1.3007 + case AFTER_AFTER_FRAMESET: 1.3008 + switch (group) { 1.3009 + case HTML: 1.3010 + errStrayStartTag(name); 1.3011 + if (!fragment && !isTemplateContents()) { 1.3012 + addAttributesToHtml(attributes); 1.3013 + attributes = null; // CPP 1.3014 + } 1.3015 + break starttagloop; 1.3016 + case NOFRAMES: 1.3017 + startTagGenericRawText(elementName, attributes); 1.3018 + attributes = null; // CPP 1.3019 + break starttagloop; 1.3020 + default: 1.3021 + errStrayStartTag(name); 1.3022 + break starttagloop; 1.3023 + } 1.3024 + case TEXT: 1.3025 + assert false; 1.3026 + break starttagloop; // Avoid infinite loop if the assertion 1.3027 + // fails 1.3028 + } 1.3029 + } 1.3030 + if (selfClosing) { 1.3031 + errSelfClosing(); 1.3032 + } 1.3033 + // CPPONLY: if (mBuilder == null && attributes != HtmlAttributes.EMPTY_ATTRIBUTES) { 1.3034 + // CPPONLY: Portability.delete(attributes); 1.3035 + // CPPONLY: } 1.3036 + } 1.3037 + 1.3038 + private void startTagTitleInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException { 1.3039 + appendToCurrentNodeAndPushElementMayFoster(elementName, attributes); 1.3040 + originalMode = mode; 1.3041 + mode = TEXT; 1.3042 + tokenizer.setStateAndEndTagExpectation(Tokenizer.RCDATA, elementName); 1.3043 + } 1.3044 + 1.3045 + private void startTagGenericRawText(ElementName elementName, HtmlAttributes attributes) throws SAXException { 1.3046 + appendToCurrentNodeAndPushElementMayFoster(elementName, attributes); 1.3047 + originalMode = mode; 1.3048 + mode = TEXT; 1.3049 + tokenizer.setStateAndEndTagExpectation(Tokenizer.RAWTEXT, elementName); 1.3050 + } 1.3051 + 1.3052 + private void startTagScriptInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException { 1.3053 + // XXX need to manage much more stuff here if supporting document.write() 1.3054 + appendToCurrentNodeAndPushElementMayFoster(elementName, attributes); 1.3055 + originalMode = mode; 1.3056 + mode = TEXT; 1.3057 + tokenizer.setStateAndEndTagExpectation(Tokenizer.SCRIPT_DATA, elementName); 1.3058 + } 1.3059 + 1.3060 + private void startTagTemplateInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException { 1.3061 + appendToCurrentNodeAndPushElement(elementName, attributes); 1.3062 + insertMarker(); 1.3063 + framesetOk = false; 1.3064 + originalMode = mode; 1.3065 + mode = IN_TEMPLATE; 1.3066 + pushTemplateMode(IN_TEMPLATE); 1.3067 + } 1.3068 + 1.3069 + private boolean isTemplateContents() { 1.3070 + return TreeBuilder.NOT_FOUND_ON_STACK != findLast("template"); 1.3071 + } 1.3072 + 1.3073 + private boolean isTemplateModeStackEmpty() { 1.3074 + return templateModePtr == -1; 1.3075 + } 1.3076 + 1.3077 + private boolean isSpecialParentInForeign(StackNode<T> stackNode) { 1.3078 + @NsUri String ns = stackNode.ns; 1.3079 + return ("http://www.w3.org/1999/xhtml" == ns) 1.3080 + || (stackNode.isHtmlIntegrationPoint()) 1.3081 + || (("http://www.w3.org/1998/Math/MathML" == ns) && (stackNode.getGroup() == MI_MO_MN_MS_MTEXT)); 1.3082 + } 1.3083 + 1.3084 + /** 1.3085 + * 1.3086 + * <p> 1.3087 + * C++ memory note: The return value must be released. 1.3088 + * 1.3089 + * @return 1.3090 + * @throws SAXException 1.3091 + * @throws StopSniffingException 1.3092 + */ 1.3093 + public static String extractCharsetFromContent(String attributeValue) { 1.3094 + // This is a bit ugly. Converting the string to char array in order to 1.3095 + // make the portability layer smaller. 1.3096 + int charsetState = CHARSET_INITIAL; 1.3097 + int start = -1; 1.3098 + int end = -1; 1.3099 + @Auto char[] buffer = Portability.newCharArrayFromString(attributeValue); 1.3100 + 1.3101 + charsetloop: for (int i = 0; i < buffer.length; i++) { 1.3102 + char c = buffer[i]; 1.3103 + switch (charsetState) { 1.3104 + case CHARSET_INITIAL: 1.3105 + switch (c) { 1.3106 + case 'c': 1.3107 + case 'C': 1.3108 + charsetState = CHARSET_C; 1.3109 + continue; 1.3110 + default: 1.3111 + continue; 1.3112 + } 1.3113 + case CHARSET_C: 1.3114 + switch (c) { 1.3115 + case 'h': 1.3116 + case 'H': 1.3117 + charsetState = CHARSET_H; 1.3118 + continue; 1.3119 + default: 1.3120 + charsetState = CHARSET_INITIAL; 1.3121 + continue; 1.3122 + } 1.3123 + case CHARSET_H: 1.3124 + switch (c) { 1.3125 + case 'a': 1.3126 + case 'A': 1.3127 + charsetState = CHARSET_A; 1.3128 + continue; 1.3129 + default: 1.3130 + charsetState = CHARSET_INITIAL; 1.3131 + continue; 1.3132 + } 1.3133 + case CHARSET_A: 1.3134 + switch (c) { 1.3135 + case 'r': 1.3136 + case 'R': 1.3137 + charsetState = CHARSET_R; 1.3138 + continue; 1.3139 + default: 1.3140 + charsetState = CHARSET_INITIAL; 1.3141 + continue; 1.3142 + } 1.3143 + case CHARSET_R: 1.3144 + switch (c) { 1.3145 + case 's': 1.3146 + case 'S': 1.3147 + charsetState = CHARSET_S; 1.3148 + continue; 1.3149 + default: 1.3150 + charsetState = CHARSET_INITIAL; 1.3151 + continue; 1.3152 + } 1.3153 + case CHARSET_S: 1.3154 + switch (c) { 1.3155 + case 'e': 1.3156 + case 'E': 1.3157 + charsetState = CHARSET_E; 1.3158 + continue; 1.3159 + default: 1.3160 + charsetState = CHARSET_INITIAL; 1.3161 + continue; 1.3162 + } 1.3163 + case CHARSET_E: 1.3164 + switch (c) { 1.3165 + case 't': 1.3166 + case 'T': 1.3167 + charsetState = CHARSET_T; 1.3168 + continue; 1.3169 + default: 1.3170 + charsetState = CHARSET_INITIAL; 1.3171 + continue; 1.3172 + } 1.3173 + case CHARSET_T: 1.3174 + switch (c) { 1.3175 + case '\t': 1.3176 + case '\n': 1.3177 + case '\u000C': 1.3178 + case '\r': 1.3179 + case ' ': 1.3180 + continue; 1.3181 + case '=': 1.3182 + charsetState = CHARSET_EQUALS; 1.3183 + continue; 1.3184 + default: 1.3185 + return null; 1.3186 + } 1.3187 + case CHARSET_EQUALS: 1.3188 + switch (c) { 1.3189 + case '\t': 1.3190 + case '\n': 1.3191 + case '\u000C': 1.3192 + case '\r': 1.3193 + case ' ': 1.3194 + continue; 1.3195 + case '\'': 1.3196 + start = i + 1; 1.3197 + charsetState = CHARSET_SINGLE_QUOTED; 1.3198 + continue; 1.3199 + case '\"': 1.3200 + start = i + 1; 1.3201 + charsetState = CHARSET_DOUBLE_QUOTED; 1.3202 + continue; 1.3203 + default: 1.3204 + start = i; 1.3205 + charsetState = CHARSET_UNQUOTED; 1.3206 + continue; 1.3207 + } 1.3208 + case CHARSET_SINGLE_QUOTED: 1.3209 + switch (c) { 1.3210 + case '\'': 1.3211 + end = i; 1.3212 + break charsetloop; 1.3213 + default: 1.3214 + continue; 1.3215 + } 1.3216 + case CHARSET_DOUBLE_QUOTED: 1.3217 + switch (c) { 1.3218 + case '\"': 1.3219 + end = i; 1.3220 + break charsetloop; 1.3221 + default: 1.3222 + continue; 1.3223 + } 1.3224 + case CHARSET_UNQUOTED: 1.3225 + switch (c) { 1.3226 + case '\t': 1.3227 + case '\n': 1.3228 + case '\u000C': 1.3229 + case '\r': 1.3230 + case ' ': 1.3231 + case ';': 1.3232 + end = i; 1.3233 + break charsetloop; 1.3234 + default: 1.3235 + continue; 1.3236 + } 1.3237 + } 1.3238 + } 1.3239 + String charset = null; 1.3240 + if (start != -1) { 1.3241 + if (end == -1) { 1.3242 + end = buffer.length; 1.3243 + } 1.3244 + charset = Portability.newStringFromBuffer(buffer, start, end 1.3245 + - start); 1.3246 + } 1.3247 + return charset; 1.3248 + } 1.3249 + 1.3250 + private void checkMetaCharset(HtmlAttributes attributes) 1.3251 + throws SAXException { 1.3252 + String charset = attributes.getValue(AttributeName.CHARSET); 1.3253 + if (charset != null) { 1.3254 + if (tokenizer.internalEncodingDeclaration(charset)) { 1.3255 + requestSuspension(); 1.3256 + return; 1.3257 + } 1.3258 + return; 1.3259 + } 1.3260 + if (!Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.3261 + "content-type", 1.3262 + attributes.getValue(AttributeName.HTTP_EQUIV))) { 1.3263 + return; 1.3264 + } 1.3265 + String content = attributes.getValue(AttributeName.CONTENT); 1.3266 + if (content != null) { 1.3267 + String extract = TreeBuilder.extractCharsetFromContent(content); 1.3268 + // remember not to return early without releasing the string 1.3269 + if (extract != null) { 1.3270 + if (tokenizer.internalEncodingDeclaration(extract)) { 1.3271 + requestSuspension(); 1.3272 + } 1.3273 + } 1.3274 + Portability.releaseString(extract); 1.3275 + } 1.3276 + } 1.3277 + 1.3278 + public final void endTag(ElementName elementName) throws SAXException { 1.3279 + flushCharacters(); 1.3280 + needToDropLF = false; 1.3281 + int eltPos; 1.3282 + int group = elementName.getGroup(); 1.3283 + @Local String name = elementName.name; 1.3284 + endtagloop: for (;;) { 1.3285 + if (isInForeign()) { 1.3286 + if (stack[currentPtr].name != name) { 1.3287 + errEndTagDidNotMatchCurrentOpenElement(name, stack[currentPtr].popName); 1.3288 + } 1.3289 + eltPos = currentPtr; 1.3290 + for (;;) { 1.3291 + if (stack[eltPos].name == name) { 1.3292 + while (currentPtr >= eltPos) { 1.3293 + pop(); 1.3294 + } 1.3295 + break endtagloop; 1.3296 + } 1.3297 + if (stack[--eltPos].ns == "http://www.w3.org/1999/xhtml") { 1.3298 + break; 1.3299 + } 1.3300 + } 1.3301 + } 1.3302 + switch (mode) { 1.3303 + case IN_TEMPLATE: 1.3304 + switch (group) { 1.3305 + case TEMPLATE: 1.3306 + // fall through to IN_HEAD 1.3307 + break; 1.3308 + default: 1.3309 + errStrayEndTag(name); 1.3310 + break endtagloop; 1.3311 + } 1.3312 + case IN_ROW: 1.3313 + switch (group) { 1.3314 + case TR: 1.3315 + eltPos = findLastOrRoot(TreeBuilder.TR); 1.3316 + if (eltPos == 0) { 1.3317 + assert fragment || isTemplateContents(); 1.3318 + errNoTableRowToClose(); 1.3319 + break endtagloop; 1.3320 + } 1.3321 + clearStackBackTo(eltPos); 1.3322 + pop(); 1.3323 + mode = IN_TABLE_BODY; 1.3324 + break endtagloop; 1.3325 + case TABLE: 1.3326 + eltPos = findLastOrRoot(TreeBuilder.TR); 1.3327 + if (eltPos == 0) { 1.3328 + assert fragment || isTemplateContents(); 1.3329 + errNoTableRowToClose(); 1.3330 + break endtagloop; 1.3331 + } 1.3332 + clearStackBackTo(eltPos); 1.3333 + pop(); 1.3334 + mode = IN_TABLE_BODY; 1.3335 + continue; 1.3336 + case TBODY_OR_THEAD_OR_TFOOT: 1.3337 + if (findLastInTableScope(name) == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3338 + errStrayEndTag(name); 1.3339 + break endtagloop; 1.3340 + } 1.3341 + eltPos = findLastOrRoot(TreeBuilder.TR); 1.3342 + if (eltPos == 0) { 1.3343 + assert fragment || isTemplateContents(); 1.3344 + errNoTableRowToClose(); 1.3345 + break endtagloop; 1.3346 + } 1.3347 + clearStackBackTo(eltPos); 1.3348 + pop(); 1.3349 + mode = IN_TABLE_BODY; 1.3350 + continue; 1.3351 + case BODY: 1.3352 + case CAPTION: 1.3353 + case COL: 1.3354 + case COLGROUP: 1.3355 + case HTML: 1.3356 + case TD_OR_TH: 1.3357 + errStrayEndTag(name); 1.3358 + break endtagloop; 1.3359 + default: 1.3360 + // fall through to IN_TABLE 1.3361 + } 1.3362 + case IN_TABLE_BODY: 1.3363 + switch (group) { 1.3364 + case TBODY_OR_THEAD_OR_TFOOT: 1.3365 + eltPos = findLastOrRoot(name); 1.3366 + if (eltPos == 0) { 1.3367 + errStrayEndTag(name); 1.3368 + break endtagloop; 1.3369 + } 1.3370 + clearStackBackTo(eltPos); 1.3371 + pop(); 1.3372 + mode = IN_TABLE; 1.3373 + break endtagloop; 1.3374 + case TABLE: 1.3375 + eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot(); 1.3376 + if (eltPos == 0 || stack[eltPos].getGroup() == TEMPLATE) { 1.3377 + assert fragment || isTemplateContents(); 1.3378 + errStrayEndTag(name); 1.3379 + break endtagloop; 1.3380 + } 1.3381 + clearStackBackTo(eltPos); 1.3382 + pop(); 1.3383 + mode = IN_TABLE; 1.3384 + continue; 1.3385 + case BODY: 1.3386 + case CAPTION: 1.3387 + case COL: 1.3388 + case COLGROUP: 1.3389 + case HTML: 1.3390 + case TD_OR_TH: 1.3391 + case TR: 1.3392 + errStrayEndTag(name); 1.3393 + break endtagloop; 1.3394 + default: 1.3395 + // fall through to IN_TABLE 1.3396 + } 1.3397 + case IN_TABLE: 1.3398 + switch (group) { 1.3399 + case TABLE: 1.3400 + eltPos = findLast("table"); 1.3401 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3402 + assert fragment || isTemplateContents(); 1.3403 + errStrayEndTag(name); 1.3404 + break endtagloop; 1.3405 + } 1.3406 + while (currentPtr >= eltPos) { 1.3407 + pop(); 1.3408 + } 1.3409 + resetTheInsertionMode(); 1.3410 + break endtagloop; 1.3411 + case BODY: 1.3412 + case CAPTION: 1.3413 + case COL: 1.3414 + case COLGROUP: 1.3415 + case HTML: 1.3416 + case TBODY_OR_THEAD_OR_TFOOT: 1.3417 + case TD_OR_TH: 1.3418 + case TR: 1.3419 + errStrayEndTag(name); 1.3420 + break endtagloop; 1.3421 + case TEMPLATE: 1.3422 + // fall through to IN_HEAD 1.3423 + break; 1.3424 + default: 1.3425 + errStrayEndTag(name); 1.3426 + // fall through to IN_BODY 1.3427 + } 1.3428 + case IN_CAPTION: 1.3429 + switch (group) { 1.3430 + case CAPTION: 1.3431 + eltPos = findLastInTableScope("caption"); 1.3432 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3433 + break endtagloop; 1.3434 + } 1.3435 + generateImpliedEndTags(); 1.3436 + if (errorHandler != null && currentPtr != eltPos) { 1.3437 + errUnclosedElements(eltPos, name); 1.3438 + } 1.3439 + while (currentPtr >= eltPos) { 1.3440 + pop(); 1.3441 + } 1.3442 + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); 1.3443 + mode = IN_TABLE; 1.3444 + break endtagloop; 1.3445 + case TABLE: 1.3446 + errTableClosedWhileCaptionOpen(); 1.3447 + eltPos = findLastInTableScope("caption"); 1.3448 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3449 + break endtagloop; 1.3450 + } 1.3451 + generateImpliedEndTags(); 1.3452 + if (errorHandler != null && currentPtr != eltPos) { 1.3453 + errUnclosedElements(eltPos, name); 1.3454 + } 1.3455 + while (currentPtr >= eltPos) { 1.3456 + pop(); 1.3457 + } 1.3458 + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); 1.3459 + mode = IN_TABLE; 1.3460 + continue; 1.3461 + case BODY: 1.3462 + case COL: 1.3463 + case COLGROUP: 1.3464 + case HTML: 1.3465 + case TBODY_OR_THEAD_OR_TFOOT: 1.3466 + case TD_OR_TH: 1.3467 + case TR: 1.3468 + errStrayEndTag(name); 1.3469 + break endtagloop; 1.3470 + default: 1.3471 + // fall through to IN_BODY 1.3472 + } 1.3473 + case IN_CELL: 1.3474 + switch (group) { 1.3475 + case TD_OR_TH: 1.3476 + eltPos = findLastInTableScope(name); 1.3477 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3478 + errStrayEndTag(name); 1.3479 + break endtagloop; 1.3480 + } 1.3481 + generateImpliedEndTags(); 1.3482 + if (errorHandler != null && !isCurrent(name)) { 1.3483 + errUnclosedElements(eltPos, name); 1.3484 + } 1.3485 + while (currentPtr >= eltPos) { 1.3486 + pop(); 1.3487 + } 1.3488 + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); 1.3489 + mode = IN_ROW; 1.3490 + break endtagloop; 1.3491 + case TABLE: 1.3492 + case TBODY_OR_THEAD_OR_TFOOT: 1.3493 + case TR: 1.3494 + if (findLastInTableScope(name) == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3495 + assert name == "tbody" || name == "tfoot" || name == "thead" || fragment || isTemplateContents(); 1.3496 + errStrayEndTag(name); 1.3497 + break endtagloop; 1.3498 + } 1.3499 + closeTheCell(findLastInTableScopeTdTh()); 1.3500 + continue; 1.3501 + case BODY: 1.3502 + case CAPTION: 1.3503 + case COL: 1.3504 + case COLGROUP: 1.3505 + case HTML: 1.3506 + errStrayEndTag(name); 1.3507 + break endtagloop; 1.3508 + default: 1.3509 + // fall through to IN_BODY 1.3510 + } 1.3511 + case FRAMESET_OK: 1.3512 + case IN_BODY: 1.3513 + switch (group) { 1.3514 + case BODY: 1.3515 + if (!isSecondOnStackBody()) { 1.3516 + assert fragment || isTemplateContents(); 1.3517 + errStrayEndTag(name); 1.3518 + break endtagloop; 1.3519 + } 1.3520 + assert currentPtr >= 1; 1.3521 + if (errorHandler != null) { 1.3522 + uncloseloop1: for (int i = 2; i <= currentPtr; i++) { 1.3523 + switch (stack[i].getGroup()) { 1.3524 + case DD_OR_DT: 1.3525 + case LI: 1.3526 + case OPTGROUP: 1.3527 + case OPTION: // is this possible? 1.3528 + case P: 1.3529 + case RT_OR_RP: 1.3530 + case TD_OR_TH: 1.3531 + case TBODY_OR_THEAD_OR_TFOOT: 1.3532 + break; 1.3533 + default: 1.3534 + errEndWithUnclosedElements(name); 1.3535 + break uncloseloop1; 1.3536 + } 1.3537 + } 1.3538 + } 1.3539 + mode = AFTER_BODY; 1.3540 + break endtagloop; 1.3541 + case HTML: 1.3542 + if (!isSecondOnStackBody()) { 1.3543 + assert fragment || isTemplateContents(); 1.3544 + errStrayEndTag(name); 1.3545 + break endtagloop; 1.3546 + } 1.3547 + if (errorHandler != null) { 1.3548 + uncloseloop2: for (int i = 0; i <= currentPtr; i++) { 1.3549 + switch (stack[i].getGroup()) { 1.3550 + case DD_OR_DT: 1.3551 + case LI: 1.3552 + case P: 1.3553 + case TBODY_OR_THEAD_OR_TFOOT: 1.3554 + case TD_OR_TH: 1.3555 + case BODY: 1.3556 + case HTML: 1.3557 + break; 1.3558 + default: 1.3559 + errEndWithUnclosedElements(name); 1.3560 + break uncloseloop2; 1.3561 + } 1.3562 + } 1.3563 + } 1.3564 + mode = AFTER_BODY; 1.3565 + continue; 1.3566 + case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU: 1.3567 + case UL_OR_OL_OR_DL: 1.3568 + case PRE_OR_LISTING: 1.3569 + case FIELDSET: 1.3570 + case BUTTON: 1.3571 + 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: 1.3572 + eltPos = findLastInScope(name); 1.3573 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3574 + errStrayEndTag(name); 1.3575 + } else { 1.3576 + generateImpliedEndTags(); 1.3577 + if (errorHandler != null && !isCurrent(name)) { 1.3578 + errUnclosedElements(eltPos, name); 1.3579 + } 1.3580 + while (currentPtr >= eltPos) { 1.3581 + pop(); 1.3582 + } 1.3583 + } 1.3584 + break endtagloop; 1.3585 + case FORM: 1.3586 + if (!isTemplateContents()) { 1.3587 + if (formPointer == null) { 1.3588 + errStrayEndTag(name); 1.3589 + break endtagloop; 1.3590 + } 1.3591 + formPointer = null; 1.3592 + eltPos = findLastInScope(name); 1.3593 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3594 + errStrayEndTag(name); 1.3595 + break endtagloop; 1.3596 + } 1.3597 + generateImpliedEndTags(); 1.3598 + if (errorHandler != null && !isCurrent(name)) { 1.3599 + errUnclosedElements(eltPos, name); 1.3600 + } 1.3601 + removeFromStack(eltPos); 1.3602 + break endtagloop; 1.3603 + } else { 1.3604 + eltPos = findLastInScope(name); 1.3605 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3606 + errStrayEndTag(name); 1.3607 + break endtagloop; 1.3608 + } 1.3609 + generateImpliedEndTags(); 1.3610 + if (errorHandler != null && !isCurrent(name)) { 1.3611 + errUnclosedElements(eltPos, name); 1.3612 + } 1.3613 + while (currentPtr >= eltPos) { 1.3614 + pop(); 1.3615 + } 1.3616 + break endtagloop; 1.3617 + } 1.3618 + case P: 1.3619 + eltPos = findLastInButtonScope("p"); 1.3620 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3621 + errNoElementToCloseButEndTagSeen("p"); 1.3622 + // XXX Can the 'in foreign' case happen anymore? 1.3623 + if (isInForeign()) { 1.3624 + errHtmlStartTagInForeignContext(name); 1.3625 + while (stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") { 1.3626 + pop(); 1.3627 + } 1.3628 + } 1.3629 + appendVoidElementToCurrentMayFoster( 1.3630 + elementName, 1.3631 + HtmlAttributes.EMPTY_ATTRIBUTES); 1.3632 + break endtagloop; 1.3633 + } 1.3634 + generateImpliedEndTagsExceptFor("p"); 1.3635 + assert eltPos != TreeBuilder.NOT_FOUND_ON_STACK; 1.3636 + if (errorHandler != null && eltPos != currentPtr) { 1.3637 + errUnclosedElements(eltPos, name); 1.3638 + } 1.3639 + while (currentPtr >= eltPos) { 1.3640 + pop(); 1.3641 + } 1.3642 + break endtagloop; 1.3643 + case LI: 1.3644 + eltPos = findLastInListScope(name); 1.3645 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3646 + errNoElementToCloseButEndTagSeen(name); 1.3647 + } else { 1.3648 + generateImpliedEndTagsExceptFor(name); 1.3649 + if (errorHandler != null 1.3650 + && eltPos != currentPtr) { 1.3651 + errUnclosedElements(eltPos, name); 1.3652 + } 1.3653 + while (currentPtr >= eltPos) { 1.3654 + pop(); 1.3655 + } 1.3656 + } 1.3657 + break endtagloop; 1.3658 + case DD_OR_DT: 1.3659 + eltPos = findLastInScope(name); 1.3660 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3661 + errNoElementToCloseButEndTagSeen(name); 1.3662 + } else { 1.3663 + generateImpliedEndTagsExceptFor(name); 1.3664 + if (errorHandler != null 1.3665 + && eltPos != currentPtr) { 1.3666 + errUnclosedElements(eltPos, name); 1.3667 + } 1.3668 + while (currentPtr >= eltPos) { 1.3669 + pop(); 1.3670 + } 1.3671 + } 1.3672 + break endtagloop; 1.3673 + case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: 1.3674 + eltPos = findLastInScopeHn(); 1.3675 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3676 + errStrayEndTag(name); 1.3677 + } else { 1.3678 + generateImpliedEndTags(); 1.3679 + if (errorHandler != null && !isCurrent(name)) { 1.3680 + errUnclosedElements(eltPos, name); 1.3681 + } 1.3682 + while (currentPtr >= eltPos) { 1.3683 + pop(); 1.3684 + } 1.3685 + } 1.3686 + break endtagloop; 1.3687 + case OBJECT: 1.3688 + case MARQUEE_OR_APPLET: 1.3689 + eltPos = findLastInScope(name); 1.3690 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3691 + errStrayEndTag(name); 1.3692 + } else { 1.3693 + generateImpliedEndTags(); 1.3694 + if (errorHandler != null && !isCurrent(name)) { 1.3695 + errUnclosedElements(eltPos, name); 1.3696 + } 1.3697 + while (currentPtr >= eltPos) { 1.3698 + pop(); 1.3699 + } 1.3700 + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); 1.3701 + } 1.3702 + break endtagloop; 1.3703 + case BR: 1.3704 + errEndTagBr(); 1.3705 + if (isInForeign()) { 1.3706 + errHtmlStartTagInForeignContext(name); 1.3707 + while (stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") { 1.3708 + pop(); 1.3709 + } 1.3710 + } 1.3711 + reconstructTheActiveFormattingElements(); 1.3712 + appendVoidElementToCurrentMayFoster( 1.3713 + elementName, 1.3714 + HtmlAttributes.EMPTY_ATTRIBUTES); 1.3715 + break endtagloop; 1.3716 + case TEMPLATE: 1.3717 + // fall through to IN_HEAD; 1.3718 + break; 1.3719 + case AREA_OR_WBR: 1.3720 + // CPPONLY: case MENUITEM: 1.3721 + case PARAM_OR_SOURCE_OR_TRACK: 1.3722 + case EMBED: 1.3723 + case IMG: 1.3724 + case IMAGE: 1.3725 + case INPUT: 1.3726 + case KEYGEN: // XXX?? 1.3727 + case HR: 1.3728 + case ISINDEX: 1.3729 + case IFRAME: 1.3730 + case NOEMBED: // XXX??? 1.3731 + case NOFRAMES: // XXX?? 1.3732 + case SELECT: 1.3733 + case TABLE: 1.3734 + case TEXTAREA: // XXX?? 1.3735 + errStrayEndTag(name); 1.3736 + break endtagloop; 1.3737 + case NOSCRIPT: 1.3738 + if (scriptingEnabled) { 1.3739 + errStrayEndTag(name); 1.3740 + break endtagloop; 1.3741 + } else { 1.3742 + // fall through 1.3743 + } 1.3744 + case A: 1.3745 + case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: 1.3746 + case FONT: 1.3747 + case NOBR: 1.3748 + if (adoptionAgencyEndTag(name)) { 1.3749 + break endtagloop; 1.3750 + } 1.3751 + // else handle like any other tag 1.3752 + default: 1.3753 + if (isCurrent(name)) { 1.3754 + pop(); 1.3755 + break endtagloop; 1.3756 + } 1.3757 + 1.3758 + eltPos = currentPtr; 1.3759 + for (;;) { 1.3760 + StackNode<T> node = stack[eltPos]; 1.3761 + if (node.ns == "http://www.w3.org/1999/xhtml" && node.name == name) { 1.3762 + generateImpliedEndTags(); 1.3763 + if (errorHandler != null 1.3764 + && !isCurrent(name)) { 1.3765 + errUnclosedElements(eltPos, name); 1.3766 + } 1.3767 + while (currentPtr >= eltPos) { 1.3768 + pop(); 1.3769 + } 1.3770 + break endtagloop; 1.3771 + } else if (node.isSpecial()) { 1.3772 + errStrayEndTag(name); 1.3773 + break endtagloop; 1.3774 + } 1.3775 + eltPos--; 1.3776 + } 1.3777 + } 1.3778 + case IN_HEAD: 1.3779 + switch (group) { 1.3780 + case HEAD: 1.3781 + pop(); 1.3782 + mode = AFTER_HEAD; 1.3783 + break endtagloop; 1.3784 + case BR: 1.3785 + case HTML: 1.3786 + case BODY: 1.3787 + pop(); 1.3788 + mode = AFTER_HEAD; 1.3789 + continue; 1.3790 + case TEMPLATE: 1.3791 + endTagTemplateInHead(); 1.3792 + break endtagloop; 1.3793 + default: 1.3794 + errStrayEndTag(name); 1.3795 + break endtagloop; 1.3796 + } 1.3797 + case IN_HEAD_NOSCRIPT: 1.3798 + switch (group) { 1.3799 + case NOSCRIPT: 1.3800 + pop(); 1.3801 + mode = IN_HEAD; 1.3802 + break endtagloop; 1.3803 + case BR: 1.3804 + errStrayEndTag(name); 1.3805 + pop(); 1.3806 + mode = IN_HEAD; 1.3807 + continue; 1.3808 + default: 1.3809 + errStrayEndTag(name); 1.3810 + break endtagloop; 1.3811 + } 1.3812 + case IN_COLUMN_GROUP: 1.3813 + switch (group) { 1.3814 + case COLGROUP: 1.3815 + if (currentPtr == 0 || stack[currentPtr].getGroup() == 1.3816 + TreeBuilder.TEMPLATE) { 1.3817 + assert fragment || isTemplateContents(); 1.3818 + errGarbageInColgroup(); 1.3819 + break endtagloop; 1.3820 + } 1.3821 + pop(); 1.3822 + mode = IN_TABLE; 1.3823 + break endtagloop; 1.3824 + case COL: 1.3825 + errStrayEndTag(name); 1.3826 + break endtagloop; 1.3827 + case TEMPLATE: 1.3828 + endTagTemplateInHead(); 1.3829 + break endtagloop; 1.3830 + default: 1.3831 + if (currentPtr == 0 || stack[currentPtr].getGroup() == 1.3832 + TreeBuilder.TEMPLATE) { 1.3833 + assert fragment || isTemplateContents(); 1.3834 + errGarbageInColgroup(); 1.3835 + break endtagloop; 1.3836 + } 1.3837 + pop(); 1.3838 + mode = IN_TABLE; 1.3839 + continue; 1.3840 + } 1.3841 + case IN_SELECT_IN_TABLE: 1.3842 + switch (group) { 1.3843 + case CAPTION: 1.3844 + case TABLE: 1.3845 + case TBODY_OR_THEAD_OR_TFOOT: 1.3846 + case TR: 1.3847 + case TD_OR_TH: 1.3848 + errEndTagSeenWithSelectOpen(name); 1.3849 + if (findLastInTableScope(name) != TreeBuilder.NOT_FOUND_ON_STACK) { 1.3850 + eltPos = findLastInTableScope("select"); 1.3851 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3852 + assert fragment; 1.3853 + break endtagloop; // http://www.w3.org/Bugs/Public/show_bug.cgi?id=8375 1.3854 + } 1.3855 + while (currentPtr >= eltPos) { 1.3856 + pop(); 1.3857 + } 1.3858 + resetTheInsertionMode(); 1.3859 + continue; 1.3860 + } else { 1.3861 + break endtagloop; 1.3862 + } 1.3863 + default: 1.3864 + // fall through to IN_SELECT 1.3865 + } 1.3866 + case IN_SELECT: 1.3867 + switch (group) { 1.3868 + case OPTION: 1.3869 + if (isCurrent("option")) { 1.3870 + pop(); 1.3871 + break endtagloop; 1.3872 + } else { 1.3873 + errStrayEndTag(name); 1.3874 + break endtagloop; 1.3875 + } 1.3876 + case OPTGROUP: 1.3877 + if (isCurrent("option") 1.3878 + && "optgroup" == stack[currentPtr - 1].name) { 1.3879 + pop(); 1.3880 + } 1.3881 + if (isCurrent("optgroup")) { 1.3882 + pop(); 1.3883 + } else { 1.3884 + errStrayEndTag(name); 1.3885 + } 1.3886 + break endtagloop; 1.3887 + case SELECT: 1.3888 + eltPos = findLastInTableScope("select"); 1.3889 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.3890 + assert fragment; 1.3891 + errStrayEndTag(name); 1.3892 + break endtagloop; 1.3893 + } 1.3894 + while (currentPtr >= eltPos) { 1.3895 + pop(); 1.3896 + } 1.3897 + resetTheInsertionMode(); 1.3898 + break endtagloop; 1.3899 + case TEMPLATE: 1.3900 + endTagTemplateInHead(); 1.3901 + break endtagloop; 1.3902 + default: 1.3903 + errStrayEndTag(name); 1.3904 + break endtagloop; 1.3905 + } 1.3906 + case AFTER_BODY: 1.3907 + switch (group) { 1.3908 + case HTML: 1.3909 + if (fragment) { 1.3910 + errStrayEndTag(name); 1.3911 + break endtagloop; 1.3912 + } else { 1.3913 + mode = AFTER_AFTER_BODY; 1.3914 + break endtagloop; 1.3915 + } 1.3916 + default: 1.3917 + errEndTagAfterBody(); 1.3918 + mode = framesetOk ? FRAMESET_OK : IN_BODY; 1.3919 + continue; 1.3920 + } 1.3921 + case IN_FRAMESET: 1.3922 + switch (group) { 1.3923 + case FRAMESET: 1.3924 + if (currentPtr == 0) { 1.3925 + assert fragment; 1.3926 + errStrayEndTag(name); 1.3927 + break endtagloop; 1.3928 + } 1.3929 + pop(); 1.3930 + if ((!fragment) && !isCurrent("frameset")) { 1.3931 + mode = AFTER_FRAMESET; 1.3932 + } 1.3933 + break endtagloop; 1.3934 + default: 1.3935 + errStrayEndTag(name); 1.3936 + break endtagloop; 1.3937 + } 1.3938 + case AFTER_FRAMESET: 1.3939 + switch (group) { 1.3940 + case HTML: 1.3941 + mode = AFTER_AFTER_FRAMESET; 1.3942 + break endtagloop; 1.3943 + default: 1.3944 + errStrayEndTag(name); 1.3945 + break endtagloop; 1.3946 + } 1.3947 + case INITIAL: 1.3948 + /* 1.3949 + * Parse error. 1.3950 + */ 1.3951 + // [NOCPP[ 1.3952 + switch (doctypeExpectation) { 1.3953 + case AUTO: 1.3954 + err("End tag seen without seeing a doctype first. Expected e.g. \u201C<!DOCTYPE html>\u201D."); 1.3955 + break; 1.3956 + case HTML: 1.3957 + // ]NOCPP] 1.3958 + errEndTagSeenWithoutDoctype(); 1.3959 + // [NOCPP[ 1.3960 + break; 1.3961 + case HTML401_STRICT: 1.3962 + 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."); 1.3963 + break; 1.3964 + case HTML401_TRANSITIONAL: 1.3965 + 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."); 1.3966 + break; 1.3967 + case NO_DOCTYPE_ERRORS: 1.3968 + } 1.3969 + // ]NOCPP] 1.3970 + /* 1.3971 + * 1.3972 + * Set the document to quirks mode. 1.3973 + */ 1.3974 + documentModeInternal(DocumentMode.QUIRKS_MODE, null, null, 1.3975 + false); 1.3976 + /* 1.3977 + * Then, switch to the root element mode of the tree 1.3978 + * construction stage 1.3979 + */ 1.3980 + mode = BEFORE_HTML; 1.3981 + /* 1.3982 + * and reprocess the current token. 1.3983 + */ 1.3984 + continue; 1.3985 + case BEFORE_HTML: 1.3986 + switch (group) { 1.3987 + case HEAD: 1.3988 + case BR: 1.3989 + case HTML: 1.3990 + case BODY: 1.3991 + /* 1.3992 + * Create an HTMLElement node with the tag name 1.3993 + * html, in the HTML namespace. Append it to the 1.3994 + * Document object. 1.3995 + */ 1.3996 + appendHtmlElementToDocumentAndPush(); 1.3997 + /* Switch to the main mode */ 1.3998 + mode = BEFORE_HEAD; 1.3999 + /* 1.4000 + * reprocess the current token. 1.4001 + */ 1.4002 + continue; 1.4003 + default: 1.4004 + errStrayEndTag(name); 1.4005 + break endtagloop; 1.4006 + } 1.4007 + case BEFORE_HEAD: 1.4008 + switch (group) { 1.4009 + case HEAD: 1.4010 + case BR: 1.4011 + case HTML: 1.4012 + case BODY: 1.4013 + appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES); 1.4014 + mode = IN_HEAD; 1.4015 + continue; 1.4016 + default: 1.4017 + errStrayEndTag(name); 1.4018 + break endtagloop; 1.4019 + } 1.4020 + case AFTER_HEAD: 1.4021 + switch (group) { 1.4022 + case TEMPLATE: 1.4023 + endTagTemplateInHead(); 1.4024 + break endtagloop; 1.4025 + case HTML: 1.4026 + case BODY: 1.4027 + case BR: 1.4028 + appendToCurrentNodeAndPushBodyElement(); 1.4029 + mode = FRAMESET_OK; 1.4030 + continue; 1.4031 + default: 1.4032 + errStrayEndTag(name); 1.4033 + break endtagloop; 1.4034 + } 1.4035 + case AFTER_AFTER_BODY: 1.4036 + errStrayEndTag(name); 1.4037 + mode = framesetOk ? FRAMESET_OK : IN_BODY; 1.4038 + continue; 1.4039 + case AFTER_AFTER_FRAMESET: 1.4040 + errStrayEndTag(name); 1.4041 + break endtagloop; 1.4042 + case TEXT: 1.4043 + // XXX need to manage insertion point here 1.4044 + pop(); 1.4045 + if (originalMode == AFTER_HEAD) { 1.4046 + silentPop(); 1.4047 + } 1.4048 + mode = originalMode; 1.4049 + break endtagloop; 1.4050 + } 1.4051 + } // endtagloop 1.4052 + } 1.4053 + 1.4054 + private void endTagTemplateInHead() throws SAXException { 1.4055 + int eltPos = findLast("template"); 1.4056 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.4057 + errStrayEndTag("template"); 1.4058 + return; 1.4059 + } 1.4060 + generateImpliedEndTags(); 1.4061 + if (errorHandler != null && !isCurrent("template")) { 1.4062 + errUnclosedElements(eltPos, "template"); 1.4063 + } 1.4064 + while (currentPtr >= eltPos) { 1.4065 + pop(); 1.4066 + } 1.4067 + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); 1.4068 + popTemplateMode(); 1.4069 + resetTheInsertionMode(); 1.4070 + } 1.4071 + 1.4072 + private int findLastInTableScopeOrRootTemplateTbodyTheadTfoot() { 1.4073 + for (int i = currentPtr; i > 0; i--) { 1.4074 + if (stack[i].getGroup() == TreeBuilder.TBODY_OR_THEAD_OR_TFOOT || 1.4075 + stack[i].getGroup() == TreeBuilder.TEMPLATE) { 1.4076 + return i; 1.4077 + } 1.4078 + } 1.4079 + return 0; 1.4080 + } 1.4081 + 1.4082 + private int findLast(@Local String name) { 1.4083 + for (int i = currentPtr; i > 0; i--) { 1.4084 + if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) { 1.4085 + return i; 1.4086 + } 1.4087 + } 1.4088 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4089 + } 1.4090 + 1.4091 + private int findLastInTableScope(@Local String name) { 1.4092 + for (int i = currentPtr; i > 0; i--) { 1.4093 + if (stack[i].ns == "http://www.w3.org/1999/xhtml") { 1.4094 + if (stack[i].name == name) { 1.4095 + return i; 1.4096 + } else if (stack[i].name == "table" || stack[i].name == "template") { 1.4097 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4098 + } 1.4099 + } 1.4100 + } 1.4101 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4102 + } 1.4103 + 1.4104 + private int findLastInButtonScope(@Local String name) { 1.4105 + for (int i = currentPtr; i > 0; i--) { 1.4106 + if (stack[i].ns == "http://www.w3.org/1999/xhtml") { 1.4107 + if (stack[i].name == name) { 1.4108 + return i; 1.4109 + } else if (stack[i].name == "button") { 1.4110 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4111 + } 1.4112 + } 1.4113 + 1.4114 + if (stack[i].isScoping()) { 1.4115 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4116 + } 1.4117 + } 1.4118 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4119 + } 1.4120 + 1.4121 + private int findLastInScope(@Local String name) { 1.4122 + for (int i = currentPtr; i > 0; i--) { 1.4123 + if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) { 1.4124 + return i; 1.4125 + } else if (stack[i].isScoping()) { 1.4126 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4127 + } 1.4128 + } 1.4129 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4130 + } 1.4131 + 1.4132 + private int findLastInListScope(@Local String name) { 1.4133 + for (int i = currentPtr; i > 0; i--) { 1.4134 + if (stack[i].ns == "http://www.w3.org/1999/xhtml") { 1.4135 + if (stack[i].name == name) { 1.4136 + return i; 1.4137 + } else if (stack[i].name == "ul" || stack[i].name == "ol") { 1.4138 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4139 + } 1.4140 + } 1.4141 + 1.4142 + if (stack[i].isScoping()) { 1.4143 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4144 + } 1.4145 + } 1.4146 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4147 + } 1.4148 + 1.4149 + private int findLastInScopeHn() { 1.4150 + for (int i = currentPtr; i > 0; i--) { 1.4151 + if (stack[i].getGroup() == TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) { 1.4152 + return i; 1.4153 + } else if (stack[i].isScoping()) { 1.4154 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4155 + } 1.4156 + } 1.4157 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4158 + } 1.4159 + 1.4160 + private void generateImpliedEndTagsExceptFor(@Local String name) 1.4161 + throws SAXException { 1.4162 + for (;;) { 1.4163 + StackNode<T> node = stack[currentPtr]; 1.4164 + switch (node.getGroup()) { 1.4165 + case P: 1.4166 + case LI: 1.4167 + case DD_OR_DT: 1.4168 + case OPTION: 1.4169 + case OPTGROUP: 1.4170 + case RT_OR_RP: 1.4171 + if (node.ns == "http://www.w3.org/1999/xhtml" && node.name == name) { 1.4172 + return; 1.4173 + } 1.4174 + pop(); 1.4175 + continue; 1.4176 + default: 1.4177 + return; 1.4178 + } 1.4179 + } 1.4180 + } 1.4181 + 1.4182 + private void generateImpliedEndTags() throws SAXException { 1.4183 + for (;;) { 1.4184 + switch (stack[currentPtr].getGroup()) { 1.4185 + case P: 1.4186 + case LI: 1.4187 + case DD_OR_DT: 1.4188 + case OPTION: 1.4189 + case OPTGROUP: 1.4190 + case RT_OR_RP: 1.4191 + pop(); 1.4192 + continue; 1.4193 + default: 1.4194 + return; 1.4195 + } 1.4196 + } 1.4197 + } 1.4198 + 1.4199 + private boolean isSecondOnStackBody() { 1.4200 + return currentPtr >= 1 && stack[1].getGroup() == TreeBuilder.BODY; 1.4201 + } 1.4202 + 1.4203 + private void documentModeInternal(DocumentMode m, String publicIdentifier, 1.4204 + String systemIdentifier, boolean html4SpecificAdditionalErrorChecks) 1.4205 + throws SAXException { 1.4206 + 1.4207 + if (isSrcdocDocument) { 1.4208 + // Srcdoc documents are always rendered in standards mode. 1.4209 + quirks = false; 1.4210 + if (documentModeHandler != null) { 1.4211 + documentModeHandler.documentMode( 1.4212 + DocumentMode.STANDARDS_MODE 1.4213 + // [NOCPP[ 1.4214 + , null, null, false 1.4215 + // ]NOCPP] 1.4216 + ); 1.4217 + } 1.4218 + return; 1.4219 + } 1.4220 + 1.4221 + quirks = (m == DocumentMode.QUIRKS_MODE); 1.4222 + if (documentModeHandler != null) { 1.4223 + documentModeHandler.documentMode( 1.4224 + m 1.4225 + // [NOCPP[ 1.4226 + , publicIdentifier, systemIdentifier, 1.4227 + html4SpecificAdditionalErrorChecks 1.4228 + // ]NOCPP] 1.4229 + ); 1.4230 + } 1.4231 + // [NOCPP[ 1.4232 + documentMode(m, publicIdentifier, systemIdentifier, 1.4233 + html4SpecificAdditionalErrorChecks); 1.4234 + // ]NOCPP] 1.4235 + } 1.4236 + 1.4237 + private boolean isAlmostStandards(String publicIdentifier, 1.4238 + String systemIdentifier) { 1.4239 + if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4240 + "-//w3c//dtd xhtml 1.0 transitional//en", publicIdentifier)) { 1.4241 + return true; 1.4242 + } 1.4243 + if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4244 + "-//w3c//dtd xhtml 1.0 frameset//en", publicIdentifier)) { 1.4245 + return true; 1.4246 + } 1.4247 + if (systemIdentifier != null) { 1.4248 + if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4249 + "-//w3c//dtd html 4.01 transitional//en", publicIdentifier)) { 1.4250 + return true; 1.4251 + } 1.4252 + if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4253 + "-//w3c//dtd html 4.01 frameset//en", publicIdentifier)) { 1.4254 + return true; 1.4255 + } 1.4256 + } 1.4257 + return false; 1.4258 + } 1.4259 + 1.4260 + private boolean isQuirky(@Local String name, String publicIdentifier, 1.4261 + String systemIdentifier, boolean forceQuirks) { 1.4262 + if (forceQuirks) { 1.4263 + return true; 1.4264 + } 1.4265 + if (name != HTML_LOCAL) { 1.4266 + return true; 1.4267 + } 1.4268 + if (publicIdentifier != null) { 1.4269 + for (int i = 0; i < TreeBuilder.QUIRKY_PUBLIC_IDS.length; i++) { 1.4270 + if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( 1.4271 + TreeBuilder.QUIRKY_PUBLIC_IDS[i], publicIdentifier)) { 1.4272 + return true; 1.4273 + } 1.4274 + } 1.4275 + if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4276 + "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier) 1.4277 + || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4278 + "-/w3c/dtd html 4.0 transitional/en", 1.4279 + publicIdentifier) 1.4280 + || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4281 + "html", publicIdentifier)) { 1.4282 + return true; 1.4283 + } 1.4284 + } 1.4285 + if (systemIdentifier == null) { 1.4286 + if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4287 + "-//w3c//dtd html 4.01 transitional//en", publicIdentifier)) { 1.4288 + return true; 1.4289 + } else if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4290 + "-//w3c//dtd html 4.01 frameset//en", publicIdentifier)) { 1.4291 + return true; 1.4292 + } 1.4293 + } else if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.4294 + "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd", 1.4295 + systemIdentifier)) { 1.4296 + return true; 1.4297 + } 1.4298 + return false; 1.4299 + } 1.4300 + 1.4301 + private void closeTheCell(int eltPos) throws SAXException { 1.4302 + generateImpliedEndTags(); 1.4303 + if (errorHandler != null && eltPos != currentPtr) { 1.4304 + errUnclosedElementsCell(eltPos); 1.4305 + } 1.4306 + while (currentPtr >= eltPos) { 1.4307 + pop(); 1.4308 + } 1.4309 + clearTheListOfActiveFormattingElementsUpToTheLastMarker(); 1.4310 + mode = IN_ROW; 1.4311 + return; 1.4312 + } 1.4313 + 1.4314 + private int findLastInTableScopeTdTh() { 1.4315 + for (int i = currentPtr; i > 0; i--) { 1.4316 + @Local String name = stack[i].name; 1.4317 + if (stack[i].ns == "http://www.w3.org/1999/xhtml") { 1.4318 + if ("td" == name || "th" == name) { 1.4319 + return i; 1.4320 + } else if (name == "table" || name == "template") { 1.4321 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4322 + } 1.4323 + } 1.4324 + } 1.4325 + return TreeBuilder.NOT_FOUND_ON_STACK; 1.4326 + } 1.4327 + 1.4328 + private void clearStackBackTo(int eltPos) throws SAXException { 1.4329 + int eltGroup = stack[eltPos].getGroup(); 1.4330 + while (currentPtr > eltPos) { // > not >= intentional 1.4331 + if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" 1.4332 + && stack[currentPtr].getGroup() == TEMPLATE 1.4333 + && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltGroup == HTML)) { 1.4334 + return; 1.4335 + } 1.4336 + pop(); 1.4337 + } 1.4338 + } 1.4339 + 1.4340 + private void resetTheInsertionMode() { 1.4341 + StackNode<T> node; 1.4342 + @Local String name; 1.4343 + @NsUri String ns; 1.4344 + for (int i = currentPtr; i >= 0; i--) { 1.4345 + node = stack[i]; 1.4346 + name = node.name; 1.4347 + ns = node.ns; 1.4348 + if (i == 0) { 1.4349 + if (!(contextNamespace == "http://www.w3.org/1999/xhtml" && (contextName == "td" || contextName == "th"))) { 1.4350 + if (fragment) { 1.4351 + // Make sure we are parsing a fragment otherwise the context element doesn't make sense. 1.4352 + name = contextName; 1.4353 + ns = contextNamespace; 1.4354 + } 1.4355 + } else { 1.4356 + mode = framesetOk ? FRAMESET_OK : IN_BODY; // XXX from Hixie's email 1.4357 + return; 1.4358 + } 1.4359 + } 1.4360 + if ("select" == name) { 1.4361 + int ancestorIndex = i; 1.4362 + while (ancestorIndex > 0) { 1.4363 + StackNode<T> ancestor = stack[ancestorIndex--]; 1.4364 + if ("http://www.w3.org/1999/xhtml" == ancestor.ns) { 1.4365 + if ("template" == ancestor.name) { 1.4366 + break; 1.4367 + } 1.4368 + if ("table" == ancestor.name) { 1.4369 + mode = IN_SELECT_IN_TABLE; 1.4370 + return; 1.4371 + } 1.4372 + } 1.4373 + } 1.4374 + mode = IN_SELECT; 1.4375 + return; 1.4376 + } else if ("td" == name || "th" == name) { 1.4377 + mode = IN_CELL; 1.4378 + return; 1.4379 + } else if ("tr" == name) { 1.4380 + mode = IN_ROW; 1.4381 + return; 1.4382 + } else if ("tbody" == name || "thead" == name || "tfoot" == name) { 1.4383 + mode = IN_TABLE_BODY; 1.4384 + return; 1.4385 + } else if ("caption" == name) { 1.4386 + mode = IN_CAPTION; 1.4387 + return; 1.4388 + } else if ("colgroup" == name) { 1.4389 + mode = IN_COLUMN_GROUP; 1.4390 + return; 1.4391 + } else if ("table" == name) { 1.4392 + mode = IN_TABLE; 1.4393 + return; 1.4394 + } else if ("http://www.w3.org/1999/xhtml" != ns) { 1.4395 + mode = framesetOk ? FRAMESET_OK : IN_BODY; 1.4396 + return; 1.4397 + } else if ("template" == name) { 1.4398 + assert templateModePtr >= 0; 1.4399 + mode = templateModeStack[templateModePtr]; 1.4400 + return; 1.4401 + } else if ("head" == name) { 1.4402 + if (name == contextName) { 1.4403 + mode = framesetOk ? FRAMESET_OK : IN_BODY; // really 1.4404 + } else { 1.4405 + mode = IN_HEAD; 1.4406 + } 1.4407 + return; 1.4408 + } else if ("body" == name) { 1.4409 + mode = framesetOk ? FRAMESET_OK : IN_BODY; 1.4410 + return; 1.4411 + } else if ("frameset" == name) { 1.4412 + // TODO: Fragment case. Add error reporting. 1.4413 + mode = IN_FRAMESET; 1.4414 + return; 1.4415 + } else if ("html" == name) { 1.4416 + if (headPointer == null) { 1.4417 + // TODO: Fragment case. Add error reporting. 1.4418 + mode = BEFORE_HEAD; 1.4419 + } else { 1.4420 + mode = AFTER_HEAD; 1.4421 + } 1.4422 + return; 1.4423 + } else if (i == 0) { 1.4424 + mode = framesetOk ? FRAMESET_OK : IN_BODY; 1.4425 + return; 1.4426 + } 1.4427 + } 1.4428 + } 1.4429 + 1.4430 + /** 1.4431 + * @throws SAXException 1.4432 + * 1.4433 + */ 1.4434 + private void implicitlyCloseP() throws SAXException { 1.4435 + int eltPos = findLastInButtonScope("p"); 1.4436 + if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) { 1.4437 + return; 1.4438 + } 1.4439 + generateImpliedEndTagsExceptFor("p"); 1.4440 + if (errorHandler != null && eltPos != currentPtr) { 1.4441 + errUnclosedElementsImplied(eltPos, "p"); 1.4442 + } 1.4443 + while (currentPtr >= eltPos) { 1.4444 + pop(); 1.4445 + } 1.4446 + } 1.4447 + 1.4448 + private boolean debugOnlyClearLastStackSlot() { 1.4449 + stack[currentPtr] = null; 1.4450 + return true; 1.4451 + } 1.4452 + 1.4453 + private boolean debugOnlyClearLastListSlot() { 1.4454 + listOfActiveFormattingElements[listPtr] = null; 1.4455 + return true; 1.4456 + } 1.4457 + 1.4458 + private void pushTemplateMode(int mode) { 1.4459 + templateModePtr++; 1.4460 + if (templateModePtr == templateModeStack.length) { 1.4461 + int[] newStack = new int[templateModeStack.length + 64]; 1.4462 + System.arraycopy(templateModeStack, 0, newStack, 0, templateModeStack.length); 1.4463 + templateModeStack = newStack; 1.4464 + } 1.4465 + templateModeStack[templateModePtr] = mode; 1.4466 + } 1.4467 + 1.4468 + @SuppressWarnings("unchecked") private void push(StackNode<T> node) throws SAXException { 1.4469 + currentPtr++; 1.4470 + if (currentPtr == stack.length) { 1.4471 + StackNode<T>[] newStack = new StackNode[stack.length + 64]; 1.4472 + System.arraycopy(stack, 0, newStack, 0, stack.length); 1.4473 + stack = newStack; 1.4474 + } 1.4475 + stack[currentPtr] = node; 1.4476 + elementPushed(node.ns, node.popName, node.node); 1.4477 + } 1.4478 + 1.4479 + @SuppressWarnings("unchecked") private void silentPush(StackNode<T> node) throws SAXException { 1.4480 + currentPtr++; 1.4481 + if (currentPtr == stack.length) { 1.4482 + StackNode<T>[] newStack = new StackNode[stack.length + 64]; 1.4483 + System.arraycopy(stack, 0, newStack, 0, stack.length); 1.4484 + stack = newStack; 1.4485 + } 1.4486 + stack[currentPtr] = node; 1.4487 + } 1.4488 + 1.4489 + @SuppressWarnings("unchecked") private void append(StackNode<T> node) { 1.4490 + listPtr++; 1.4491 + if (listPtr == listOfActiveFormattingElements.length) { 1.4492 + StackNode<T>[] newList = new StackNode[listOfActiveFormattingElements.length + 64]; 1.4493 + System.arraycopy(listOfActiveFormattingElements, 0, newList, 0, 1.4494 + listOfActiveFormattingElements.length); 1.4495 + listOfActiveFormattingElements = newList; 1.4496 + } 1.4497 + listOfActiveFormattingElements[listPtr] = node; 1.4498 + } 1.4499 + 1.4500 + @Inline private void insertMarker() { 1.4501 + append(null); 1.4502 + } 1.4503 + 1.4504 + private void clearTheListOfActiveFormattingElementsUpToTheLastMarker() { 1.4505 + while (listPtr > -1) { 1.4506 + if (listOfActiveFormattingElements[listPtr] == null) { 1.4507 + --listPtr; 1.4508 + return; 1.4509 + } 1.4510 + listOfActiveFormattingElements[listPtr].release(); 1.4511 + --listPtr; 1.4512 + } 1.4513 + } 1.4514 + 1.4515 + @Inline private boolean isCurrent(@Local String name) { 1.4516 + return stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" && 1.4517 + name == stack[currentPtr].name; 1.4518 + } 1.4519 + 1.4520 + private void removeFromStack(int pos) throws SAXException { 1.4521 + if (currentPtr == pos) { 1.4522 + pop(); 1.4523 + } else { 1.4524 + fatal(); 1.4525 + stack[pos].release(); 1.4526 + System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos); 1.4527 + assert debugOnlyClearLastStackSlot(); 1.4528 + currentPtr--; 1.4529 + } 1.4530 + } 1.4531 + 1.4532 + private void removeFromStack(StackNode<T> node) throws SAXException { 1.4533 + if (stack[currentPtr] == node) { 1.4534 + pop(); 1.4535 + } else { 1.4536 + int pos = currentPtr - 1; 1.4537 + while (pos >= 0 && stack[pos] != node) { 1.4538 + pos--; 1.4539 + } 1.4540 + if (pos == -1) { 1.4541 + // dead code? 1.4542 + return; 1.4543 + } 1.4544 + fatal(); 1.4545 + node.release(); 1.4546 + System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos); 1.4547 + currentPtr--; 1.4548 + } 1.4549 + } 1.4550 + 1.4551 + private void removeFromListOfActiveFormattingElements(int pos) { 1.4552 + assert listOfActiveFormattingElements[pos] != null; 1.4553 + listOfActiveFormattingElements[pos].release(); 1.4554 + if (pos == listPtr) { 1.4555 + assert debugOnlyClearLastListSlot(); 1.4556 + listPtr--; 1.4557 + return; 1.4558 + } 1.4559 + assert pos < listPtr; 1.4560 + System.arraycopy(listOfActiveFormattingElements, pos + 1, 1.4561 + listOfActiveFormattingElements, pos, listPtr - pos); 1.4562 + assert debugOnlyClearLastListSlot(); 1.4563 + listPtr--; 1.4564 + } 1.4565 + 1.4566 + /** 1.4567 + * Adoption agency algorithm. 1.4568 + * 1.4569 + * @param name subject as described in the specified algorithm. 1.4570 + * @return Returns true if the algorithm has completed and there is nothing remaining to 1.4571 + * be done. Returns false if the algorithm needs to "act as described in the 'any other 1.4572 + * end tag' entry" as described in the specified algorithm. 1.4573 + * @throws SAXException 1.4574 + */ 1.4575 + private boolean adoptionAgencyEndTag(@Local String name) throws SAXException { 1.4576 + // This check intends to ensure that for properly nested tags, closing tags will match 1.4577 + // against the stack instead of the listOfActiveFormattingElements. 1.4578 + if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" && 1.4579 + stack[currentPtr].name == name && 1.4580 + findInListOfActiveFormattingElements(stack[currentPtr]) == -1) { 1.4581 + // If the current element matches the name but isn't on the list of active 1.4582 + // formatting elements, then it is possible that the list was mangled by the Noah's Ark 1.4583 + // clause. In this case, we want to match the end tag against the stack instead of 1.4584 + // proceeding with the AAA algorithm that may match against the list of 1.4585 + // active formatting elements (and possibly mangle the tree in unexpected ways). 1.4586 + pop(); 1.4587 + return true; 1.4588 + } 1.4589 + 1.4590 + // If you crash around here, perhaps some stack node variable claimed to 1.4591 + // be a weak ref isn't. 1.4592 + for (int i = 0; i < 8; ++i) { 1.4593 + int formattingEltListPos = listPtr; 1.4594 + while (formattingEltListPos > -1) { 1.4595 + StackNode<T> listNode = listOfActiveFormattingElements[formattingEltListPos]; // weak ref 1.4596 + if (listNode == null) { 1.4597 + formattingEltListPos = -1; 1.4598 + break; 1.4599 + } else if (listNode.name == name) { 1.4600 + break; 1.4601 + } 1.4602 + formattingEltListPos--; 1.4603 + } 1.4604 + if (formattingEltListPos == -1) { 1.4605 + return false; 1.4606 + } 1.4607 + // this *looks* like a weak ref to the list of formatting elements 1.4608 + StackNode<T> formattingElt = listOfActiveFormattingElements[formattingEltListPos]; 1.4609 + int formattingEltStackPos = currentPtr; 1.4610 + boolean inScope = true; 1.4611 + while (formattingEltStackPos > -1) { 1.4612 + StackNode<T> node = stack[formattingEltStackPos]; // weak ref 1.4613 + if (node == formattingElt) { 1.4614 + break; 1.4615 + } else if (node.isScoping()) { 1.4616 + inScope = false; 1.4617 + } 1.4618 + formattingEltStackPos--; 1.4619 + } 1.4620 + if (formattingEltStackPos == -1) { 1.4621 + errNoElementToCloseButEndTagSeen(name); 1.4622 + removeFromListOfActiveFormattingElements(formattingEltListPos); 1.4623 + return true; 1.4624 + } 1.4625 + if (!inScope) { 1.4626 + errNoElementToCloseButEndTagSeen(name); 1.4627 + return true; 1.4628 + } 1.4629 + // stackPos now points to the formatting element and it is in scope 1.4630 + if (formattingEltStackPos != currentPtr) { 1.4631 + errEndTagViolatesNestingRules(name); 1.4632 + } 1.4633 + int furthestBlockPos = formattingEltStackPos + 1; 1.4634 + while (furthestBlockPos <= currentPtr) { 1.4635 + StackNode<T> node = stack[furthestBlockPos]; // weak ref 1.4636 + if (node.isSpecial()) { 1.4637 + break; 1.4638 + } 1.4639 + furthestBlockPos++; 1.4640 + } 1.4641 + if (furthestBlockPos > currentPtr) { 1.4642 + // no furthest block 1.4643 + while (currentPtr >= formattingEltStackPos) { 1.4644 + pop(); 1.4645 + } 1.4646 + removeFromListOfActiveFormattingElements(formattingEltListPos); 1.4647 + return true; 1.4648 + } 1.4649 + StackNode<T> commonAncestor = stack[formattingEltStackPos - 1]; // weak ref 1.4650 + StackNode<T> furthestBlock = stack[furthestBlockPos]; // weak ref 1.4651 + // detachFromParent(furthestBlock.node); XXX AAA CHANGE 1.4652 + int bookmark = formattingEltListPos; 1.4653 + int nodePos = furthestBlockPos; 1.4654 + StackNode<T> lastNode = furthestBlock; // weak ref 1.4655 + int j = 0; 1.4656 + for (;;) { 1.4657 + ++j; 1.4658 + nodePos--; 1.4659 + if (nodePos == formattingEltStackPos) { 1.4660 + break; 1.4661 + } 1.4662 + StackNode<T> node = stack[nodePos]; // weak ref 1.4663 + int nodeListPos = findInListOfActiveFormattingElements(node); 1.4664 + 1.4665 + if (j > 3 && nodeListPos != -1) { 1.4666 + removeFromListOfActiveFormattingElements(nodeListPos); 1.4667 + 1.4668 + // Adjust the indices into the list to account 1.4669 + // for the removal of nodeListPos. 1.4670 + if (nodeListPos <= formattingEltListPos) { 1.4671 + formattingEltListPos--; 1.4672 + } 1.4673 + if (nodeListPos <= bookmark) { 1.4674 + bookmark--; 1.4675 + } 1.4676 + 1.4677 + // Update position to reflect removal from list. 1.4678 + nodeListPos = -1; 1.4679 + } 1.4680 + 1.4681 + if (nodeListPos == -1) { 1.4682 + assert formattingEltStackPos < nodePos; 1.4683 + assert bookmark < nodePos; 1.4684 + assert furthestBlockPos > nodePos; 1.4685 + removeFromStack(nodePos); // node is now a bad pointer in C++ 1.4686 + furthestBlockPos--; 1.4687 + continue; 1.4688 + } 1.4689 + // now node is both on stack and in the list 1.4690 + if (nodePos == furthestBlockPos) { 1.4691 + bookmark = nodeListPos + 1; 1.4692 + } 1.4693 + // if (hasChildren(node.node)) { XXX AAA CHANGE 1.4694 + assert node == listOfActiveFormattingElements[nodeListPos]; 1.4695 + assert node == stack[nodePos]; 1.4696 + T clone = createElement("http://www.w3.org/1999/xhtml", 1.4697 + node.name, node.attributes.cloneAttributes(null)); 1.4698 + StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns, 1.4699 + node.name, clone, node.popName, node.attributes 1.4700 + // [NOCPP[ 1.4701 + , node.getLocator() 1.4702 + // ]NOCPP] 1.4703 + ); // creation ownership goes to stack 1.4704 + node.dropAttributes(); // adopt ownership to newNode 1.4705 + stack[nodePos] = newNode; 1.4706 + newNode.retain(); // retain for list 1.4707 + listOfActiveFormattingElements[nodeListPos] = newNode; 1.4708 + node.release(); // release from stack 1.4709 + node.release(); // release from list 1.4710 + node = newNode; 1.4711 + // } XXX AAA CHANGE 1.4712 + detachFromParent(lastNode.node); 1.4713 + appendElement(lastNode.node, node.node); 1.4714 + lastNode = node; 1.4715 + } 1.4716 + if (commonAncestor.isFosterParenting()) { 1.4717 + fatal(); 1.4718 + detachFromParent(lastNode.node); 1.4719 + insertIntoFosterParent(lastNode.node); 1.4720 + } else { 1.4721 + detachFromParent(lastNode.node); 1.4722 + appendElement(lastNode.node, commonAncestor.node); 1.4723 + } 1.4724 + T clone = createElement("http://www.w3.org/1999/xhtml", 1.4725 + formattingElt.name, 1.4726 + formattingElt.attributes.cloneAttributes(null)); 1.4727 + StackNode<T> formattingClone = new StackNode<T>( 1.4728 + formattingElt.getFlags(), formattingElt.ns, 1.4729 + formattingElt.name, clone, formattingElt.popName, 1.4730 + formattingElt.attributes 1.4731 + // [NOCPP[ 1.4732 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.4733 + // ]NOCPP] 1.4734 + ); // Ownership transfers to stack below 1.4735 + formattingElt.dropAttributes(); // transfer ownership to 1.4736 + // formattingClone 1.4737 + appendChildrenToNewParent(furthestBlock.node, clone); 1.4738 + appendElement(clone, furthestBlock.node); 1.4739 + removeFromListOfActiveFormattingElements(formattingEltListPos); 1.4740 + insertIntoListOfActiveFormattingElements(formattingClone, bookmark); 1.4741 + assert formattingEltStackPos < furthestBlockPos; 1.4742 + removeFromStack(formattingEltStackPos); 1.4743 + // furthestBlockPos is now off by one and points to the slot after 1.4744 + // it 1.4745 + insertIntoStack(formattingClone, furthestBlockPos); 1.4746 + } 1.4747 + return true; 1.4748 + } 1.4749 + 1.4750 + private void insertIntoStack(StackNode<T> node, int position) 1.4751 + throws SAXException { 1.4752 + assert currentPtr + 1 < stack.length; 1.4753 + assert position <= currentPtr + 1; 1.4754 + if (position == currentPtr + 1) { 1.4755 + push(node); 1.4756 + } else { 1.4757 + System.arraycopy(stack, position, stack, position + 1, 1.4758 + (currentPtr - position) + 1); 1.4759 + currentPtr++; 1.4760 + stack[position] = node; 1.4761 + } 1.4762 + } 1.4763 + 1.4764 + private void insertIntoListOfActiveFormattingElements( 1.4765 + StackNode<T> formattingClone, int bookmark) { 1.4766 + formattingClone.retain(); 1.4767 + assert listPtr + 1 < listOfActiveFormattingElements.length; 1.4768 + if (bookmark <= listPtr) { 1.4769 + System.arraycopy(listOfActiveFormattingElements, bookmark, 1.4770 + listOfActiveFormattingElements, bookmark + 1, 1.4771 + (listPtr - bookmark) + 1); 1.4772 + } 1.4773 + listPtr++; 1.4774 + listOfActiveFormattingElements[bookmark] = formattingClone; 1.4775 + } 1.4776 + 1.4777 + private int findInListOfActiveFormattingElements(StackNode<T> node) { 1.4778 + for (int i = listPtr; i >= 0; i--) { 1.4779 + if (node == listOfActiveFormattingElements[i]) { 1.4780 + return i; 1.4781 + } 1.4782 + } 1.4783 + return -1; 1.4784 + } 1.4785 + 1.4786 + private int findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker( 1.4787 + @Local String name) { 1.4788 + for (int i = listPtr; i >= 0; i--) { 1.4789 + StackNode<T> node = listOfActiveFormattingElements[i]; 1.4790 + if (node == null) { 1.4791 + return -1; 1.4792 + } else if (node.name == name) { 1.4793 + return i; 1.4794 + } 1.4795 + } 1.4796 + return -1; 1.4797 + } 1.4798 + 1.4799 + 1.4800 + private void maybeForgetEarlierDuplicateFormattingElement( 1.4801 + @Local String name, HtmlAttributes attributes) throws SAXException { 1.4802 + int candidate = -1; 1.4803 + int count = 0; 1.4804 + for (int i = listPtr; i >= 0; i--) { 1.4805 + StackNode<T> node = listOfActiveFormattingElements[i]; 1.4806 + if (node == null) { 1.4807 + break; 1.4808 + } 1.4809 + if (node.name == name && node.attributes.equalsAnother(attributes)) { 1.4810 + candidate = i; 1.4811 + ++count; 1.4812 + } 1.4813 + } 1.4814 + if (count >= 3) { 1.4815 + removeFromListOfActiveFormattingElements(candidate); 1.4816 + } 1.4817 + } 1.4818 + 1.4819 + private int findLastOrRoot(@Local String name) { 1.4820 + for (int i = currentPtr; i > 0; i--) { 1.4821 + if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) { 1.4822 + return i; 1.4823 + } 1.4824 + } 1.4825 + return 0; 1.4826 + } 1.4827 + 1.4828 + private int findLastOrRoot(int group) { 1.4829 + for (int i = currentPtr; i > 0; i--) { 1.4830 + if (stack[i].getGroup() == group) { 1.4831 + return i; 1.4832 + } 1.4833 + } 1.4834 + return 0; 1.4835 + } 1.4836 + 1.4837 + /** 1.4838 + * Attempt to add attribute to the body element. 1.4839 + * @param attributes the attributes 1.4840 + * @return <code>true</code> iff the attributes were added 1.4841 + * @throws SAXException 1.4842 + */ 1.4843 + private boolean addAttributesToBody(HtmlAttributes attributes) 1.4844 + throws SAXException { 1.4845 + // [NOCPP[ 1.4846 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.4847 + // ]NOCPP] 1.4848 + if (currentPtr >= 1) { 1.4849 + StackNode<T> body = stack[1]; 1.4850 + if (body.getGroup() == TreeBuilder.BODY) { 1.4851 + addAttributesToElement(body.node, attributes); 1.4852 + return true; 1.4853 + } 1.4854 + } 1.4855 + return false; 1.4856 + } 1.4857 + 1.4858 + private void addAttributesToHtml(HtmlAttributes attributes) 1.4859 + throws SAXException { 1.4860 + // [NOCPP[ 1.4861 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.4862 + // ]NOCPP] 1.4863 + addAttributesToElement(stack[0].node, attributes); 1.4864 + } 1.4865 + 1.4866 + private void pushHeadPointerOntoStack() throws SAXException { 1.4867 + assert headPointer != null; 1.4868 + assert mode == AFTER_HEAD; 1.4869 + fatal(); 1.4870 + silentPush(new StackNode<T>(ElementName.HEAD, headPointer 1.4871 + // [NOCPP[ 1.4872 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.4873 + // ]NOCPP] 1.4874 + )); 1.4875 + } 1.4876 + 1.4877 + /** 1.4878 + * @throws SAXException 1.4879 + * 1.4880 + */ 1.4881 + private void reconstructTheActiveFormattingElements() throws SAXException { 1.4882 + if (listPtr == -1) { 1.4883 + return; 1.4884 + } 1.4885 + StackNode<T> mostRecent = listOfActiveFormattingElements[listPtr]; 1.4886 + if (mostRecent == null || isInStack(mostRecent)) { 1.4887 + return; 1.4888 + } 1.4889 + int entryPos = listPtr; 1.4890 + for (;;) { 1.4891 + entryPos--; 1.4892 + if (entryPos == -1) { 1.4893 + break; 1.4894 + } 1.4895 + if (listOfActiveFormattingElements[entryPos] == null) { 1.4896 + break; 1.4897 + } 1.4898 + if (isInStack(listOfActiveFormattingElements[entryPos])) { 1.4899 + break; 1.4900 + } 1.4901 + } 1.4902 + while (entryPos < listPtr) { 1.4903 + entryPos++; 1.4904 + StackNode<T> entry = listOfActiveFormattingElements[entryPos]; 1.4905 + T clone = createElement("http://www.w3.org/1999/xhtml", entry.name, 1.4906 + entry.attributes.cloneAttributes(null)); 1.4907 + StackNode<T> entryClone = new StackNode<T>(entry.getFlags(), 1.4908 + entry.ns, entry.name, clone, entry.popName, 1.4909 + entry.attributes 1.4910 + // [NOCPP[ 1.4911 + , entry.getLocator() 1.4912 + // ]NOCPP] 1.4913 + ); 1.4914 + entry.dropAttributes(); // transfer ownership to entryClone 1.4915 + StackNode<T> currentNode = stack[currentPtr]; 1.4916 + if (currentNode.isFosterParenting()) { 1.4917 + insertIntoFosterParent(clone); 1.4918 + } else { 1.4919 + appendElement(clone, currentNode.node); 1.4920 + } 1.4921 + push(entryClone); 1.4922 + // stack takes ownership of the local variable 1.4923 + listOfActiveFormattingElements[entryPos] = entryClone; 1.4924 + // overwriting the old entry on the list, so release & retain 1.4925 + entry.release(); 1.4926 + entryClone.retain(); 1.4927 + } 1.4928 + } 1.4929 + 1.4930 + private void insertIntoFosterParent(T child) throws SAXException { 1.4931 + int tablePos = findLastOrRoot(TreeBuilder.TABLE); 1.4932 + int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE); 1.4933 + 1.4934 + if (templatePos >= tablePos) { 1.4935 + appendElement(child, stack[templatePos].node); 1.4936 + return; 1.4937 + } 1.4938 + 1.4939 + StackNode<T> node = stack[tablePos]; 1.4940 + insertFosterParentedChild(child, node.node, stack[tablePos - 1].node); 1.4941 + } 1.4942 + 1.4943 + private boolean isInStack(StackNode<T> node) { 1.4944 + for (int i = currentPtr; i >= 0; i--) { 1.4945 + if (stack[i] == node) { 1.4946 + return true; 1.4947 + } 1.4948 + } 1.4949 + return false; 1.4950 + } 1.4951 + 1.4952 + private void popTemplateMode() { 1.4953 + templateModePtr--; 1.4954 + } 1.4955 + 1.4956 + private void pop() throws SAXException { 1.4957 + StackNode<T> node = stack[currentPtr]; 1.4958 + assert debugOnlyClearLastStackSlot(); 1.4959 + currentPtr--; 1.4960 + elementPopped(node.ns, node.popName, node.node); 1.4961 + node.release(); 1.4962 + } 1.4963 + 1.4964 + private void silentPop() throws SAXException { 1.4965 + StackNode<T> node = stack[currentPtr]; 1.4966 + assert debugOnlyClearLastStackSlot(); 1.4967 + currentPtr--; 1.4968 + node.release(); 1.4969 + } 1.4970 + 1.4971 + private void popOnEof() throws SAXException { 1.4972 + StackNode<T> node = stack[currentPtr]; 1.4973 + assert debugOnlyClearLastStackSlot(); 1.4974 + currentPtr--; 1.4975 + markMalformedIfScript(node.node); 1.4976 + elementPopped(node.ns, node.popName, node.node); 1.4977 + node.release(); 1.4978 + } 1.4979 + 1.4980 + // [NOCPP[ 1.4981 + private void checkAttributes(HtmlAttributes attributes, @NsUri String ns) 1.4982 + throws SAXException { 1.4983 + if (errorHandler != null) { 1.4984 + int len = attributes.getXmlnsLength(); 1.4985 + for (int i = 0; i < len; i++) { 1.4986 + AttributeName name = attributes.getXmlnsAttributeName(i); 1.4987 + if (name == AttributeName.XMLNS) { 1.4988 + if (html4) { 1.4989 + err("Attribute \u201Cxmlns\u201D not allowed here. (HTML4-only error.)"); 1.4990 + } else { 1.4991 + String xmlns = attributes.getXmlnsValue(i); 1.4992 + if (!ns.equals(xmlns)) { 1.4993 + err("Bad value \u201C" 1.4994 + + xmlns 1.4995 + + "\u201D for the attribute \u201Cxmlns\u201D (only \u201C" 1.4996 + + ns + "\u201D permitted here)."); 1.4997 + switch (namePolicy) { 1.4998 + case ALTER_INFOSET: 1.4999 + // fall through 1.5000 + case ALLOW: 1.5001 + warn("Attribute \u201Cxmlns\u201D is not serializable as XML 1.0."); 1.5002 + break; 1.5003 + case FATAL: 1.5004 + fatal("Attribute \u201Cxmlns\u201D is not serializable as XML 1.0."); 1.5005 + break; 1.5006 + } 1.5007 + } 1.5008 + } 1.5009 + } else if (ns != "http://www.w3.org/1999/xhtml" 1.5010 + && name == AttributeName.XMLNS_XLINK) { 1.5011 + String xmlns = attributes.getXmlnsValue(i); 1.5012 + if (!"http://www.w3.org/1999/xlink".equals(xmlns)) { 1.5013 + err("Bad value \u201C" 1.5014 + + xmlns 1.5015 + + "\u201D for the attribute \u201Cxmlns:link\u201D (only \u201Chttp://www.w3.org/1999/xlink\u201D permitted here)."); 1.5016 + switch (namePolicy) { 1.5017 + case ALTER_INFOSET: 1.5018 + // fall through 1.5019 + case ALLOW: 1.5020 + 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."); 1.5021 + break; 1.5022 + case FATAL: 1.5023 + 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."); 1.5024 + break; 1.5025 + } 1.5026 + } 1.5027 + } else { 1.5028 + err("Attribute \u201C" + attributes.getXmlnsLocalName(i) 1.5029 + + "\u201D not allowed here."); 1.5030 + switch (namePolicy) { 1.5031 + case ALTER_INFOSET: 1.5032 + // fall through 1.5033 + case ALLOW: 1.5034 + warn("Attribute with the local name \u201C" 1.5035 + + attributes.getXmlnsLocalName(i) 1.5036 + + "\u201D is not serializable as XML 1.0."); 1.5037 + break; 1.5038 + case FATAL: 1.5039 + fatal("Attribute with the local name \u201C" 1.5040 + + attributes.getXmlnsLocalName(i) 1.5041 + + "\u201D is not serializable as XML 1.0."); 1.5042 + break; 1.5043 + } 1.5044 + } 1.5045 + } 1.5046 + } 1.5047 + attributes.processNonNcNames(this, namePolicy); 1.5048 + } 1.5049 + 1.5050 + private String checkPopName(@Local String name) throws SAXException { 1.5051 + if (NCName.isNCName(name)) { 1.5052 + return name; 1.5053 + } else { 1.5054 + switch (namePolicy) { 1.5055 + case ALLOW: 1.5056 + warn("Element name \u201C" + name 1.5057 + + "\u201D cannot be represented as XML 1.0."); 1.5058 + return name; 1.5059 + case ALTER_INFOSET: 1.5060 + warn("Element name \u201C" + name 1.5061 + + "\u201D cannot be represented as XML 1.0."); 1.5062 + return NCName.escapeName(name); 1.5063 + case FATAL: 1.5064 + fatal("Element name \u201C" + name 1.5065 + + "\u201D cannot be represented as XML 1.0."); 1.5066 + } 1.5067 + } 1.5068 + return null; // keep compiler happy 1.5069 + } 1.5070 + 1.5071 + // ]NOCPP] 1.5072 + 1.5073 + private void appendHtmlElementToDocumentAndPush(HtmlAttributes attributes) 1.5074 + throws SAXException { 1.5075 + // [NOCPP[ 1.5076 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5077 + // ]NOCPP] 1.5078 + T elt = createHtmlElementSetAsRoot(attributes); 1.5079 + StackNode<T> node = new StackNode<T>(ElementName.HTML, 1.5080 + elt 1.5081 + // [NOCPP[ 1.5082 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.5083 + // ]NOCPP] 1.5084 + ); 1.5085 + push(node); 1.5086 + } 1.5087 + 1.5088 + private void appendHtmlElementToDocumentAndPush() throws SAXException { 1.5089 + appendHtmlElementToDocumentAndPush(tokenizer.emptyAttributes()); 1.5090 + } 1.5091 + 1.5092 + private void appendToCurrentNodeAndPushHeadElement(HtmlAttributes attributes) 1.5093 + throws SAXException { 1.5094 + // [NOCPP[ 1.5095 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5096 + // ]NOCPP] 1.5097 + T elt = createElement("http://www.w3.org/1999/xhtml", "head", 1.5098 + attributes); 1.5099 + appendElement(elt, stack[currentPtr].node); 1.5100 + headPointer = elt; 1.5101 + StackNode<T> node = new StackNode<T>(ElementName.HEAD, 1.5102 + elt 1.5103 + // [NOCPP[ 1.5104 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.5105 + // ]NOCPP] 1.5106 + ); 1.5107 + push(node); 1.5108 + } 1.5109 + 1.5110 + private void appendToCurrentNodeAndPushBodyElement(HtmlAttributes attributes) 1.5111 + throws SAXException { 1.5112 + appendToCurrentNodeAndPushElement(ElementName.BODY, 1.5113 + attributes); 1.5114 + } 1.5115 + 1.5116 + private void appendToCurrentNodeAndPushBodyElement() throws SAXException { 1.5117 + appendToCurrentNodeAndPushBodyElement(tokenizer.emptyAttributes()); 1.5118 + } 1.5119 + 1.5120 + private void appendToCurrentNodeAndPushFormElementMayFoster( 1.5121 + HtmlAttributes attributes) throws SAXException { 1.5122 + // [NOCPP[ 1.5123 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5124 + // ]NOCPP] 1.5125 + T elt = createElement("http://www.w3.org/1999/xhtml", "form", 1.5126 + attributes); 1.5127 + 1.5128 + if (!isTemplateContents()) { 1.5129 + formPointer = elt; 1.5130 + } 1.5131 + 1.5132 + StackNode<T> current = stack[currentPtr]; 1.5133 + if (current.isFosterParenting()) { 1.5134 + fatal(); 1.5135 + insertIntoFosterParent(elt); 1.5136 + } else { 1.5137 + appendElement(elt, current.node); 1.5138 + } 1.5139 + StackNode<T> node = new StackNode<T>(ElementName.FORM, 1.5140 + elt 1.5141 + // [NOCPP[ 1.5142 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.5143 + // ]NOCPP] 1.5144 + ); 1.5145 + push(node); 1.5146 + } 1.5147 + 1.5148 + private void appendToCurrentNodeAndPushFormattingElementMayFoster( 1.5149 + ElementName elementName, HtmlAttributes attributes) 1.5150 + throws SAXException { 1.5151 + // [NOCPP[ 1.5152 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5153 + // ]NOCPP] 1.5154 + // This method can't be called for custom elements 1.5155 + HtmlAttributes clone = attributes.cloneAttributes(null); 1.5156 + // Attributes must not be read after calling createElement, because 1.5157 + // createElement may delete attributes in C++. 1.5158 + T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes); 1.5159 + StackNode<T> current = stack[currentPtr]; 1.5160 + if (current.isFosterParenting()) { 1.5161 + fatal(); 1.5162 + insertIntoFosterParent(elt); 1.5163 + } else { 1.5164 + appendElement(elt, current.node); 1.5165 + } 1.5166 + StackNode<T> node = new StackNode<T>(elementName, elt, clone 1.5167 + // [NOCPP[ 1.5168 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.5169 + // ]NOCPP] 1.5170 + ); 1.5171 + push(node); 1.5172 + append(node); 1.5173 + node.retain(); // append doesn't retain itself 1.5174 + } 1.5175 + 1.5176 + private void appendToCurrentNodeAndPushElement(ElementName elementName, 1.5177 + HtmlAttributes attributes) 1.5178 + throws SAXException { 1.5179 + // [NOCPP[ 1.5180 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5181 + // ]NOCPP] 1.5182 + // This method can't be called for custom elements 1.5183 + T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes); 1.5184 + appendElement(elt, stack[currentPtr].node); 1.5185 + if (ElementName.TEMPLATE == elementName) { 1.5186 + elt = getDocumentFragmentForTemplate(elt); 1.5187 + } 1.5188 + StackNode<T> node = new StackNode<T>(elementName, elt 1.5189 + // [NOCPP[ 1.5190 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.5191 + // ]NOCPP] 1.5192 + ); 1.5193 + push(node); 1.5194 + } 1.5195 + 1.5196 + private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName, 1.5197 + HtmlAttributes attributes) 1.5198 + throws SAXException { 1.5199 + @Local String popName = elementName.name; 1.5200 + // [NOCPP[ 1.5201 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5202 + if (elementName.isCustom()) { 1.5203 + popName = checkPopName(popName); 1.5204 + } 1.5205 + // ]NOCPP] 1.5206 + T elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes); 1.5207 + StackNode<T> current = stack[currentPtr]; 1.5208 + if (current.isFosterParenting()) { 1.5209 + fatal(); 1.5210 + insertIntoFosterParent(elt); 1.5211 + } else { 1.5212 + appendElement(elt, current.node); 1.5213 + } 1.5214 + StackNode<T> node = new StackNode<T>(elementName, elt, popName 1.5215 + // [NOCPP[ 1.5216 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.5217 + // ]NOCPP] 1.5218 + ); 1.5219 + push(node); 1.5220 + } 1.5221 + 1.5222 + private void appendToCurrentNodeAndPushElementMayFosterMathML( 1.5223 + ElementName elementName, HtmlAttributes attributes) 1.5224 + throws SAXException { 1.5225 + @Local String popName = elementName.name; 1.5226 + // [NOCPP[ 1.5227 + checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML"); 1.5228 + if (elementName.isCustom()) { 1.5229 + popName = checkPopName(popName); 1.5230 + } 1.5231 + // ]NOCPP] 1.5232 + boolean markAsHtmlIntegrationPoint = false; 1.5233 + if (ElementName.ANNOTATION_XML == elementName 1.5234 + && annotationXmlEncodingPermitsHtml(attributes)) { 1.5235 + markAsHtmlIntegrationPoint = true; 1.5236 + } 1.5237 + // Attributes must not be read after calling createElement(), since 1.5238 + // createElement may delete the object in C++. 1.5239 + T elt = createElement("http://www.w3.org/1998/Math/MathML", popName, 1.5240 + attributes); 1.5241 + StackNode<T> current = stack[currentPtr]; 1.5242 + if (current.isFosterParenting()) { 1.5243 + fatal(); 1.5244 + insertIntoFosterParent(elt); 1.5245 + } else { 1.5246 + appendElement(elt, current.node); 1.5247 + } 1.5248 + StackNode<T> node = new StackNode<T>(elementName, elt, popName, 1.5249 + markAsHtmlIntegrationPoint 1.5250 + // [NOCPP[ 1.5251 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.5252 + // ]NOCPP] 1.5253 + ); 1.5254 + push(node); 1.5255 + } 1.5256 + 1.5257 + // [NOCPP[ 1.5258 + T getDocumentFragmentForTemplate(T template) { 1.5259 + return template; 1.5260 + } 1.5261 + 1.5262 + T getFormPointerForContext(T context) { 1.5263 + return null; 1.5264 + } 1.5265 + // ]NOCPP] 1.5266 + 1.5267 + private boolean annotationXmlEncodingPermitsHtml(HtmlAttributes attributes) { 1.5268 + String encoding = attributes.getValue(AttributeName.ENCODING); 1.5269 + if (encoding == null) { 1.5270 + return false; 1.5271 + } 1.5272 + return Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.5273 + "application/xhtml+xml", encoding) 1.5274 + || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString( 1.5275 + "text/html", encoding); 1.5276 + } 1.5277 + 1.5278 + private void appendToCurrentNodeAndPushElementMayFosterSVG( 1.5279 + ElementName elementName, HtmlAttributes attributes) 1.5280 + throws SAXException { 1.5281 + @Local String popName = elementName.camelCaseName; 1.5282 + // [NOCPP[ 1.5283 + checkAttributes(attributes, "http://www.w3.org/2000/svg"); 1.5284 + if (elementName.isCustom()) { 1.5285 + popName = checkPopName(popName); 1.5286 + } 1.5287 + // ]NOCPP] 1.5288 + T elt = createElement("http://www.w3.org/2000/svg", popName, attributes); 1.5289 + StackNode<T> current = stack[currentPtr]; 1.5290 + if (current.isFosterParenting()) { 1.5291 + fatal(); 1.5292 + insertIntoFosterParent(elt); 1.5293 + } else { 1.5294 + appendElement(elt, current.node); 1.5295 + } 1.5296 + StackNode<T> node = new StackNode<T>(elementName, popName, elt 1.5297 + // [NOCPP[ 1.5298 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.5299 + // ]NOCPP] 1.5300 + ); 1.5301 + push(node); 1.5302 + } 1.5303 + 1.5304 + private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName, 1.5305 + HtmlAttributes attributes, T form) 1.5306 + throws SAXException { 1.5307 + // [NOCPP[ 1.5308 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5309 + // ]NOCPP] 1.5310 + // Can't be called for custom elements 1.5311 + T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, 1.5312 + form == null || fragment || isTemplateContents() ? null : form); 1.5313 + StackNode<T> current = stack[currentPtr]; 1.5314 + if (current.isFosterParenting()) { 1.5315 + fatal(); 1.5316 + insertIntoFosterParent(elt); 1.5317 + } else { 1.5318 + appendElement(elt, current.node); 1.5319 + } 1.5320 + StackNode<T> node = new StackNode<T>(elementName, elt 1.5321 + // [NOCPP[ 1.5322 + , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer) 1.5323 + // ]NOCPP] 1.5324 + ); 1.5325 + push(node); 1.5326 + } 1.5327 + 1.5328 + private void appendVoidElementToCurrentMayFoster( 1.5329 + @Local String name, HtmlAttributes attributes, T form) throws SAXException { 1.5330 + // [NOCPP[ 1.5331 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5332 + // ]NOCPP] 1.5333 + // Can't be called for custom elements 1.5334 + T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes, 1.5335 + form == null || fragment || isTemplateContents() ? null : form); 1.5336 + StackNode<T> current = stack[currentPtr]; 1.5337 + if (current.isFosterParenting()) { 1.5338 + fatal(); 1.5339 + insertIntoFosterParent(elt); 1.5340 + } else { 1.5341 + appendElement(elt, current.node); 1.5342 + } 1.5343 + elementPushed("http://www.w3.org/1999/xhtml", name, elt); 1.5344 + elementPopped("http://www.w3.org/1999/xhtml", name, elt); 1.5345 + } 1.5346 + 1.5347 + private void appendVoidElementToCurrentMayFoster( 1.5348 + ElementName elementName, HtmlAttributes attributes) 1.5349 + throws SAXException { 1.5350 + @Local String popName = elementName.name; 1.5351 + // [NOCPP[ 1.5352 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5353 + if (elementName.isCustom()) { 1.5354 + popName = checkPopName(popName); 1.5355 + } 1.5356 + // ]NOCPP] 1.5357 + T elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes); 1.5358 + StackNode<T> current = stack[currentPtr]; 1.5359 + if (current.isFosterParenting()) { 1.5360 + fatal(); 1.5361 + insertIntoFosterParent(elt); 1.5362 + } else { 1.5363 + appendElement(elt, current.node); 1.5364 + } 1.5365 + elementPushed("http://www.w3.org/1999/xhtml", popName, elt); 1.5366 + elementPopped("http://www.w3.org/1999/xhtml", popName, elt); 1.5367 + } 1.5368 + 1.5369 + private void appendVoidElementToCurrentMayFosterSVG( 1.5370 + ElementName elementName, HtmlAttributes attributes) 1.5371 + throws SAXException { 1.5372 + @Local String popName = elementName.camelCaseName; 1.5373 + // [NOCPP[ 1.5374 + checkAttributes(attributes, "http://www.w3.org/2000/svg"); 1.5375 + if (elementName.isCustom()) { 1.5376 + popName = checkPopName(popName); 1.5377 + } 1.5378 + // ]NOCPP] 1.5379 + T elt = createElement("http://www.w3.org/2000/svg", popName, attributes); 1.5380 + StackNode<T> current = stack[currentPtr]; 1.5381 + if (current.isFosterParenting()) { 1.5382 + fatal(); 1.5383 + insertIntoFosterParent(elt); 1.5384 + } else { 1.5385 + appendElement(elt, current.node); 1.5386 + } 1.5387 + elementPushed("http://www.w3.org/2000/svg", popName, elt); 1.5388 + elementPopped("http://www.w3.org/2000/svg", popName, elt); 1.5389 + } 1.5390 + 1.5391 + private void appendVoidElementToCurrentMayFosterMathML( 1.5392 + ElementName elementName, HtmlAttributes attributes) 1.5393 + throws SAXException { 1.5394 + @Local String popName = elementName.name; 1.5395 + // [NOCPP[ 1.5396 + checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML"); 1.5397 + if (elementName.isCustom()) { 1.5398 + popName = checkPopName(popName); 1.5399 + } 1.5400 + // ]NOCPP] 1.5401 + T elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes); 1.5402 + StackNode<T> current = stack[currentPtr]; 1.5403 + if (current.isFosterParenting()) { 1.5404 + fatal(); 1.5405 + insertIntoFosterParent(elt); 1.5406 + } else { 1.5407 + appendElement(elt, current.node); 1.5408 + } 1.5409 + elementPushed("http://www.w3.org/1998/Math/MathML", popName, elt); 1.5410 + elementPopped("http://www.w3.org/1998/Math/MathML", popName, elt); 1.5411 + } 1.5412 + 1.5413 + private void appendVoidElementToCurrent( 1.5414 + @Local String name, HtmlAttributes attributes, T form) throws SAXException { 1.5415 + // [NOCPP[ 1.5416 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5417 + // ]NOCPP] 1.5418 + // Can't be called for custom elements 1.5419 + T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes, 1.5420 + form == null || fragment || isTemplateContents() ? null : form); 1.5421 + StackNode<T> current = stack[currentPtr]; 1.5422 + appendElement(elt, current.node); 1.5423 + elementPushed("http://www.w3.org/1999/xhtml", name, elt); 1.5424 + elementPopped("http://www.w3.org/1999/xhtml", name, elt); 1.5425 + } 1.5426 + 1.5427 + private void appendVoidFormToCurrent(HtmlAttributes attributes) throws SAXException { 1.5428 + // [NOCPP[ 1.5429 + checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); 1.5430 + // ]NOCPP] 1.5431 + T elt = createElement("http://www.w3.org/1999/xhtml", "form", 1.5432 + attributes); 1.5433 + formPointer = elt; 1.5434 + // ownership transferred to form pointer 1.5435 + StackNode<T> current = stack[currentPtr]; 1.5436 + appendElement(elt, current.node); 1.5437 + elementPushed("http://www.w3.org/1999/xhtml", "form", elt); 1.5438 + elementPopped("http://www.w3.org/1999/xhtml", "form", elt); 1.5439 + } 1.5440 + 1.5441 + // [NOCPP[ 1.5442 + 1.5443 + private final void accumulateCharactersForced(@Const @NoLength char[] buf, 1.5444 + int start, int length) throws SAXException { 1.5445 + int newLen = charBufferLen + length; 1.5446 + if (newLen > charBuffer.length) { 1.5447 + char[] newBuf = new char[newLen]; 1.5448 + System.arraycopy(charBuffer, 0, newBuf, 0, charBufferLen); 1.5449 + charBuffer = newBuf; 1.5450 + } 1.5451 + System.arraycopy(buf, start, charBuffer, charBufferLen, length); 1.5452 + charBufferLen = newLen; 1.5453 + } 1.5454 + 1.5455 + // ]NOCPP] 1.5456 + 1.5457 + protected void accumulateCharacters(@Const @NoLength char[] buf, int start, 1.5458 + int length) throws SAXException { 1.5459 + appendCharacters(stack[currentPtr].node, buf, start, length); 1.5460 + } 1.5461 + 1.5462 + // ------------------------------- // 1.5463 + 1.5464 + protected final void requestSuspension() { 1.5465 + tokenizer.requestSuspension(); 1.5466 + } 1.5467 + 1.5468 + protected abstract T createElement(@NsUri String ns, @Local String name, 1.5469 + HtmlAttributes attributes) throws SAXException; 1.5470 + 1.5471 + protected T createElement(@NsUri String ns, @Local String name, 1.5472 + HtmlAttributes attributes, T form) throws SAXException { 1.5473 + return createElement("http://www.w3.org/1999/xhtml", name, attributes); 1.5474 + } 1.5475 + 1.5476 + protected abstract T createHtmlElementSetAsRoot(HtmlAttributes attributes) 1.5477 + throws SAXException; 1.5478 + 1.5479 + protected abstract void detachFromParent(T element) throws SAXException; 1.5480 + 1.5481 + protected abstract boolean hasChildren(T element) throws SAXException; 1.5482 + 1.5483 + protected abstract void appendElement(T child, T newParent) 1.5484 + throws SAXException; 1.5485 + 1.5486 + protected abstract void appendChildrenToNewParent(T oldParent, T newParent) 1.5487 + throws SAXException; 1.5488 + 1.5489 + protected abstract void insertFosterParentedChild(T child, T table, 1.5490 + T stackParent) throws SAXException; 1.5491 + 1.5492 + protected abstract void insertFosterParentedCharacters( 1.5493 + @NoLength char[] buf, int start, int length, T table, T stackParent) 1.5494 + throws SAXException; 1.5495 + 1.5496 + protected abstract void appendCharacters(T parent, @NoLength char[] buf, 1.5497 + int start, int length) throws SAXException; 1.5498 + 1.5499 + protected abstract void appendIsindexPrompt(T parent) throws SAXException; 1.5500 + 1.5501 + protected abstract void appendComment(T parent, @NoLength char[] buf, 1.5502 + int start, int length) throws SAXException; 1.5503 + 1.5504 + protected abstract void appendCommentToDocument(@NoLength char[] buf, 1.5505 + int start, int length) throws SAXException; 1.5506 + 1.5507 + protected abstract void addAttributesToElement(T element, 1.5508 + HtmlAttributes attributes) throws SAXException; 1.5509 + 1.5510 + protected void markMalformedIfScript(T elt) throws SAXException { 1.5511 + 1.5512 + } 1.5513 + 1.5514 + protected void start(boolean fragmentMode) throws SAXException { 1.5515 + 1.5516 + } 1.5517 + 1.5518 + protected void end() throws SAXException { 1.5519 + 1.5520 + } 1.5521 + 1.5522 + protected void appendDoctypeToDocument(@Local String name, 1.5523 + String publicIdentifier, String systemIdentifier) 1.5524 + throws SAXException { 1.5525 + 1.5526 + } 1.5527 + 1.5528 + protected void elementPushed(@NsUri String ns, @Local String name, T node) 1.5529 + throws SAXException { 1.5530 + 1.5531 + } 1.5532 + 1.5533 + protected void elementPopped(@NsUri String ns, @Local String name, T node) 1.5534 + throws SAXException { 1.5535 + 1.5536 + } 1.5537 + 1.5538 + // [NOCPP[ 1.5539 + 1.5540 + protected void documentMode(DocumentMode m, String publicIdentifier, 1.5541 + String systemIdentifier, boolean html4SpecificAdditionalErrorChecks) 1.5542 + throws SAXException { 1.5543 + 1.5544 + } 1.5545 + 1.5546 + /** 1.5547 + * @see nu.validator.htmlparser.common.TokenHandler#wantsComments() 1.5548 + */ 1.5549 + public boolean wantsComments() { 1.5550 + return wantingComments; 1.5551 + } 1.5552 + 1.5553 + public void setIgnoringComments(boolean ignoreComments) { 1.5554 + wantingComments = !ignoreComments; 1.5555 + } 1.5556 + 1.5557 + /** 1.5558 + * Sets the errorHandler. 1.5559 + * 1.5560 + * @param errorHandler 1.5561 + * the errorHandler to set 1.5562 + */ 1.5563 + public final void setErrorHandler(ErrorHandler errorHandler) { 1.5564 + this.errorHandler = errorHandler; 1.5565 + } 1.5566 + 1.5567 + /** 1.5568 + * Returns the errorHandler. 1.5569 + * 1.5570 + * @return the errorHandler 1.5571 + */ 1.5572 + public ErrorHandler getErrorHandler() { 1.5573 + return errorHandler; 1.5574 + } 1.5575 + 1.5576 + /** 1.5577 + * The argument MUST be an interned string or <code>null</code>. 1.5578 + * 1.5579 + * @param context 1.5580 + */ 1.5581 + public final void setFragmentContext(@Local String context) { 1.5582 + this.contextName = context; 1.5583 + this.contextNamespace = "http://www.w3.org/1999/xhtml"; 1.5584 + this.contextNode = null; 1.5585 + this.fragment = (contextName != null); 1.5586 + this.quirks = false; 1.5587 + } 1.5588 + 1.5589 + // ]NOCPP] 1.5590 + 1.5591 + /** 1.5592 + * @see nu.validator.htmlparser.common.TokenHandler#cdataSectionAllowed() 1.5593 + */ 1.5594 + @Inline public boolean cdataSectionAllowed() throws SAXException { 1.5595 + return isInForeign(); 1.5596 + } 1.5597 + 1.5598 + private boolean isInForeign() { 1.5599 + return currentPtr >= 0 1.5600 + && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml"; 1.5601 + } 1.5602 + 1.5603 + private boolean isInForeignButNotHtmlOrMathTextIntegrationPoint() { 1.5604 + if (currentPtr < 0) { 1.5605 + return false; 1.5606 + } 1.5607 + return !isSpecialParentInForeign(stack[currentPtr]); 1.5608 + } 1.5609 + 1.5610 + /** 1.5611 + * The argument MUST be an interned string or <code>null</code>. 1.5612 + * 1.5613 + * @param context 1.5614 + */ 1.5615 + public final void setFragmentContext(@Local String context, 1.5616 + @NsUri String ns, T node, boolean quirks) { 1.5617 + this.contextName = context; 1.5618 + this.contextNamespace = ns; 1.5619 + this.contextNode = node; 1.5620 + this.fragment = (contextName != null); 1.5621 + this.quirks = quirks; 1.5622 + } 1.5623 + 1.5624 + protected final T currentNode() { 1.5625 + return stack[currentPtr].node; 1.5626 + } 1.5627 + 1.5628 + /** 1.5629 + * Returns the scriptingEnabled. 1.5630 + * 1.5631 + * @return the scriptingEnabled 1.5632 + */ 1.5633 + public boolean isScriptingEnabled() { 1.5634 + return scriptingEnabled; 1.5635 + } 1.5636 + 1.5637 + /** 1.5638 + * Sets the scriptingEnabled. 1.5639 + * 1.5640 + * @param scriptingEnabled 1.5641 + * the scriptingEnabled to set 1.5642 + */ 1.5643 + public void setScriptingEnabled(boolean scriptingEnabled) { 1.5644 + this.scriptingEnabled = scriptingEnabled; 1.5645 + } 1.5646 + 1.5647 + public void setIsSrcdocDocument(boolean isSrcdocDocument) { 1.5648 + this.isSrcdocDocument = isSrcdocDocument; 1.5649 + } 1.5650 + 1.5651 + // [NOCPP[ 1.5652 + 1.5653 + /** 1.5654 + * Sets the doctypeExpectation. 1.5655 + * 1.5656 + * @param doctypeExpectation 1.5657 + * the doctypeExpectation to set 1.5658 + */ 1.5659 + public void setDoctypeExpectation(DoctypeExpectation doctypeExpectation) { 1.5660 + this.doctypeExpectation = doctypeExpectation; 1.5661 + } 1.5662 + 1.5663 + public void setNamePolicy(XmlViolationPolicy namePolicy) { 1.5664 + this.namePolicy = namePolicy; 1.5665 + } 1.5666 + 1.5667 + /** 1.5668 + * Sets the documentModeHandler. 1.5669 + * 1.5670 + * @param documentModeHandler 1.5671 + * the documentModeHandler to set 1.5672 + */ 1.5673 + public void setDocumentModeHandler(DocumentModeHandler documentModeHandler) { 1.5674 + this.documentModeHandler = documentModeHandler; 1.5675 + } 1.5676 + 1.5677 + /** 1.5678 + * Sets the reportingDoctype. 1.5679 + * 1.5680 + * @param reportingDoctype 1.5681 + * the reportingDoctype to set 1.5682 + */ 1.5683 + public void setReportingDoctype(boolean reportingDoctype) { 1.5684 + this.reportingDoctype = reportingDoctype; 1.5685 + } 1.5686 + 1.5687 + // ]NOCPP] 1.5688 + 1.5689 + /** 1.5690 + * Flushes the pending characters. Public for document.write use cases only. 1.5691 + * @throws SAXException 1.5692 + */ 1.5693 + public final void flushCharacters() throws SAXException { 1.5694 + if (charBufferLen > 0) { 1.5695 + if ((mode == IN_TABLE || mode == IN_TABLE_BODY || mode == IN_ROW) 1.5696 + && charBufferContainsNonWhitespace()) { 1.5697 + errNonSpaceInTable(); 1.5698 + reconstructTheActiveFormattingElements(); 1.5699 + if (!stack[currentPtr].isFosterParenting()) { 1.5700 + // reconstructing gave us a new current node 1.5701 + appendCharacters(currentNode(), charBuffer, 0, 1.5702 + charBufferLen); 1.5703 + charBufferLen = 0; 1.5704 + return; 1.5705 + } 1.5706 + 1.5707 + int tablePos = findLastOrRoot(TreeBuilder.TABLE); 1.5708 + int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE); 1.5709 + 1.5710 + if (templatePos >= tablePos) { 1.5711 + appendCharacters(stack[templatePos].node, charBuffer, 0, charBufferLen); 1.5712 + charBufferLen = 0; 1.5713 + return; 1.5714 + } 1.5715 + 1.5716 + StackNode<T> tableElt = stack[tablePos]; 1.5717 + insertFosterParentedCharacters(charBuffer, 0, charBufferLen, 1.5718 + tableElt.node, stack[tablePos - 1].node); 1.5719 + charBufferLen = 0; 1.5720 + return; 1.5721 + } 1.5722 + appendCharacters(currentNode(), charBuffer, 0, charBufferLen); 1.5723 + charBufferLen = 0; 1.5724 + } 1.5725 + } 1.5726 + 1.5727 + private boolean charBufferContainsNonWhitespace() { 1.5728 + for (int i = 0; i < charBufferLen; i++) { 1.5729 + switch (charBuffer[i]) { 1.5730 + case ' ': 1.5731 + case '\t': 1.5732 + case '\n': 1.5733 + case '\r': 1.5734 + case '\u000C': 1.5735 + continue; 1.5736 + default: 1.5737 + return true; 1.5738 + } 1.5739 + } 1.5740 + return false; 1.5741 + } 1.5742 + 1.5743 + /** 1.5744 + * Creates a comparable snapshot of the tree builder state. Snapshot 1.5745 + * creation is only supported immediately after a script end tag has been 1.5746 + * processed. In C++ the caller is responsible for calling 1.5747 + * <code>delete</code> on the returned object. 1.5748 + * 1.5749 + * @return a snapshot. 1.5750 + * @throws SAXException 1.5751 + */ 1.5752 + @SuppressWarnings("unchecked") public TreeBuilderState<T> newSnapshot() 1.5753 + throws SAXException { 1.5754 + StackNode<T>[] listCopy = new StackNode[listPtr + 1]; 1.5755 + for (int i = 0; i < listCopy.length; i++) { 1.5756 + StackNode<T> node = listOfActiveFormattingElements[i]; 1.5757 + if (node != null) { 1.5758 + StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns, 1.5759 + node.name, node.node, node.popName, 1.5760 + node.attributes.cloneAttributes(null) 1.5761 + // [NOCPP[ 1.5762 + , node.getLocator() 1.5763 + // ]NOCPP] 1.5764 + ); 1.5765 + listCopy[i] = newNode; 1.5766 + } else { 1.5767 + listCopy[i] = null; 1.5768 + } 1.5769 + } 1.5770 + StackNode<T>[] stackCopy = new StackNode[currentPtr + 1]; 1.5771 + for (int i = 0; i < stackCopy.length; i++) { 1.5772 + StackNode<T> node = stack[i]; 1.5773 + int listIndex = findInListOfActiveFormattingElements(node); 1.5774 + if (listIndex == -1) { 1.5775 + StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns, 1.5776 + node.name, node.node, node.popName, 1.5777 + null 1.5778 + // [NOCPP[ 1.5779 + , node.getLocator() 1.5780 + // ]NOCPP] 1.5781 + ); 1.5782 + stackCopy[i] = newNode; 1.5783 + } else { 1.5784 + stackCopy[i] = listCopy[listIndex]; 1.5785 + stackCopy[i].retain(); 1.5786 + } 1.5787 + } 1.5788 + int[] templateModeStackCopy = new int[templateModePtr + 1]; 1.5789 + System.arraycopy(templateModeStack, 0, templateModeStackCopy, 0, 1.5790 + templateModeStackCopy.length); 1.5791 + return new StateSnapshot<T>(stackCopy, listCopy, templateModeStackCopy, formPointer, 1.5792 + headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk, 1.5793 + needToDropLF, quirks); 1.5794 + } 1.5795 + 1.5796 + public boolean snapshotMatches(TreeBuilderState<T> snapshot) { 1.5797 + StackNode<T>[] stackCopy = snapshot.getStack(); 1.5798 + int stackLen = snapshot.getStackLength(); 1.5799 + StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements(); 1.5800 + int listLen = snapshot.getListOfActiveFormattingElementsLength(); 1.5801 + int[] templateModeStackCopy = snapshot.getTemplateModeStack(); 1.5802 + int templateModeStackLen = snapshot.getTemplateModeStackLength(); 1.5803 + 1.5804 + if (stackLen != currentPtr + 1 1.5805 + || listLen != listPtr + 1 1.5806 + || templateModeStackLen != templateModePtr + 1 1.5807 + || formPointer != snapshot.getFormPointer() 1.5808 + || headPointer != snapshot.getHeadPointer() 1.5809 + || deepTreeSurrogateParent != snapshot.getDeepTreeSurrogateParent() 1.5810 + || mode != snapshot.getMode() 1.5811 + || originalMode != snapshot.getOriginalMode() 1.5812 + || framesetOk != snapshot.isFramesetOk() 1.5813 + || needToDropLF != snapshot.isNeedToDropLF() 1.5814 + || quirks != snapshot.isQuirks()) { // maybe just assert quirks 1.5815 + return false; 1.5816 + } 1.5817 + for (int i = listLen - 1; i >= 0; i--) { 1.5818 + if (listCopy[i] == null 1.5819 + && listOfActiveFormattingElements[i] == null) { 1.5820 + continue; 1.5821 + } else if (listCopy[i] == null 1.5822 + || listOfActiveFormattingElements[i] == null) { 1.5823 + return false; 1.5824 + } 1.5825 + if (listCopy[i].node != listOfActiveFormattingElements[i].node) { 1.5826 + return false; // it's possible that this condition is overly 1.5827 + // strict 1.5828 + } 1.5829 + } 1.5830 + for (int i = stackLen - 1; i >= 0; i--) { 1.5831 + if (stackCopy[i].node != stack[i].node) { 1.5832 + return false; 1.5833 + } 1.5834 + } 1.5835 + for (int i = templateModeStackLen - 1; i >=0; i--) { 1.5836 + if (templateModeStackCopy[i] != templateModeStack[i]) { 1.5837 + return false; 1.5838 + } 1.5839 + } 1.5840 + return true; 1.5841 + } 1.5842 + 1.5843 + @SuppressWarnings("unchecked") public void loadState( 1.5844 + TreeBuilderState<T> snapshot, Interner interner) 1.5845 + throws SAXException { 1.5846 + StackNode<T>[] stackCopy = snapshot.getStack(); 1.5847 + int stackLen = snapshot.getStackLength(); 1.5848 + StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements(); 1.5849 + int listLen = snapshot.getListOfActiveFormattingElementsLength(); 1.5850 + int[] templateModeStackCopy = snapshot.getTemplateModeStack(); 1.5851 + int templateModeStackLen = snapshot.getTemplateModeStackLength(); 1.5852 + 1.5853 + for (int i = 0; i <= listPtr; i++) { 1.5854 + if (listOfActiveFormattingElements[i] != null) { 1.5855 + listOfActiveFormattingElements[i].release(); 1.5856 + } 1.5857 + } 1.5858 + if (listOfActiveFormattingElements.length < listLen) { 1.5859 + listOfActiveFormattingElements = new StackNode[listLen]; 1.5860 + } 1.5861 + listPtr = listLen - 1; 1.5862 + 1.5863 + for (int i = 0; i <= currentPtr; i++) { 1.5864 + stack[i].release(); 1.5865 + } 1.5866 + if (stack.length < stackLen) { 1.5867 + stack = new StackNode[stackLen]; 1.5868 + } 1.5869 + currentPtr = stackLen - 1; 1.5870 + 1.5871 + if (templateModeStack.length < templateModeStackLen) { 1.5872 + templateModeStack = new int[templateModeStackLen]; 1.5873 + } 1.5874 + templateModePtr = templateModeStackLen - 1; 1.5875 + 1.5876 + for (int i = 0; i < listLen; i++) { 1.5877 + StackNode<T> node = listCopy[i]; 1.5878 + if (node != null) { 1.5879 + StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns, 1.5880 + Portability.newLocalFromLocal(node.name, interner), node.node, 1.5881 + Portability.newLocalFromLocal(node.popName, interner), 1.5882 + node.attributes.cloneAttributes(null) 1.5883 + // [NOCPP[ 1.5884 + , node.getLocator() 1.5885 + // ]NOCPP] 1.5886 + ); 1.5887 + listOfActiveFormattingElements[i] = newNode; 1.5888 + } else { 1.5889 + listOfActiveFormattingElements[i] = null; 1.5890 + } 1.5891 + } 1.5892 + for (int i = 0; i < stackLen; i++) { 1.5893 + StackNode<T> node = stackCopy[i]; 1.5894 + int listIndex = findInArray(node, listCopy); 1.5895 + if (listIndex == -1) { 1.5896 + StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns, 1.5897 + Portability.newLocalFromLocal(node.name, interner), node.node, 1.5898 + Portability.newLocalFromLocal(node.popName, interner), 1.5899 + null 1.5900 + // [NOCPP[ 1.5901 + , node.getLocator() 1.5902 + // ]NOCPP] 1.5903 + ); 1.5904 + stack[i] = newNode; 1.5905 + } else { 1.5906 + stack[i] = listOfActiveFormattingElements[listIndex]; 1.5907 + stack[i].retain(); 1.5908 + } 1.5909 + } 1.5910 + System.arraycopy(templateModeStackCopy, 0, templateModeStack, 0, templateModeStackLen); 1.5911 + formPointer = snapshot.getFormPointer(); 1.5912 + headPointer = snapshot.getHeadPointer(); 1.5913 + deepTreeSurrogateParent = snapshot.getDeepTreeSurrogateParent(); 1.5914 + mode = snapshot.getMode(); 1.5915 + originalMode = snapshot.getOriginalMode(); 1.5916 + framesetOk = snapshot.isFramesetOk(); 1.5917 + needToDropLF = snapshot.isNeedToDropLF(); 1.5918 + quirks = snapshot.isQuirks(); 1.5919 + } 1.5920 + 1.5921 + private int findInArray(StackNode<T> node, StackNode<T>[] arr) { 1.5922 + for (int i = listPtr; i >= 0; i--) { 1.5923 + if (node == arr[i]) { 1.5924 + return i; 1.5925 + } 1.5926 + } 1.5927 + return -1; 1.5928 + } 1.5929 + 1.5930 + /** 1.5931 + * @see nu.validator.htmlparser.impl.TreeBuilderState#getFormPointer() 1.5932 + */ 1.5933 + public T getFormPointer() { 1.5934 + return formPointer; 1.5935 + } 1.5936 + 1.5937 + /** 1.5938 + * Returns the headPointer. 1.5939 + * 1.5940 + * @return the headPointer 1.5941 + */ 1.5942 + public T getHeadPointer() { 1.5943 + return headPointer; 1.5944 + } 1.5945 + 1.5946 + /** 1.5947 + * Returns the deepTreeSurrogateParent. 1.5948 + * 1.5949 + * @return the deepTreeSurrogateParent 1.5950 + */ 1.5951 + public T getDeepTreeSurrogateParent() { 1.5952 + return deepTreeSurrogateParent; 1.5953 + } 1.5954 + 1.5955 + /** 1.5956 + * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElements() 1.5957 + */ 1.5958 + public StackNode<T>[] getListOfActiveFormattingElements() { 1.5959 + return listOfActiveFormattingElements; 1.5960 + } 1.5961 + 1.5962 + /** 1.5963 + * @see nu.validator.htmlparser.impl.TreeBuilderState#getStack() 1.5964 + */ 1.5965 + public StackNode<T>[] getStack() { 1.5966 + return stack; 1.5967 + } 1.5968 + 1.5969 + /** 1.5970 + * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStack() 1.5971 + */ 1.5972 + public int[] getTemplateModeStack() { 1.5973 + return templateModeStack; 1.5974 + } 1.5975 + 1.5976 + /** 1.5977 + * Returns the mode. 1.5978 + * 1.5979 + * @return the mode 1.5980 + */ 1.5981 + public int getMode() { 1.5982 + return mode; 1.5983 + } 1.5984 + 1.5985 + /** 1.5986 + * Returns the originalMode. 1.5987 + * 1.5988 + * @return the originalMode 1.5989 + */ 1.5990 + public int getOriginalMode() { 1.5991 + return originalMode; 1.5992 + } 1.5993 + 1.5994 + /** 1.5995 + * Returns the framesetOk. 1.5996 + * 1.5997 + * @return the framesetOk 1.5998 + */ 1.5999 + public boolean isFramesetOk() { 1.6000 + return framesetOk; 1.6001 + } 1.6002 + 1.6003 + /** 1.6004 + * Returns the needToDropLF. 1.6005 + * 1.6006 + * @return the needToDropLF 1.6007 + */ 1.6008 + public boolean isNeedToDropLF() { 1.6009 + return needToDropLF; 1.6010 + } 1.6011 + 1.6012 + /** 1.6013 + * Returns the quirks. 1.6014 + * 1.6015 + * @return the quirks 1.6016 + */ 1.6017 + public boolean isQuirks() { 1.6018 + return quirks; 1.6019 + } 1.6020 + 1.6021 + /** 1.6022 + * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElementsLength() 1.6023 + */ 1.6024 + public int getListOfActiveFormattingElementsLength() { 1.6025 + return listPtr + 1; 1.6026 + } 1.6027 + 1.6028 + /** 1.6029 + * @see nu.validator.htmlparser.impl.TreeBuilderState#getStackLength() 1.6030 + */ 1.6031 + public int getStackLength() { 1.6032 + return currentPtr + 1; 1.6033 + } 1.6034 + 1.6035 + /** 1.6036 + * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStackLength() 1.6037 + */ 1.6038 + public int getTemplateModeStackLength() { 1.6039 + return templateModePtr + 1; 1.6040 + } 1.6041 + 1.6042 + /** 1.6043 + * Reports a stray start tag. 1.6044 + * @param name the name of the stray tag 1.6045 + * 1.6046 + * @throws SAXException 1.6047 + */ 1.6048 + private void errStrayStartTag(@Local String name) throws SAXException { 1.6049 + err("Stray start tag \u201C" + name + "\u201D."); 1.6050 + } 1.6051 + 1.6052 + /** 1.6053 + * Reports a stray end tag. 1.6054 + * @param name the name of the stray tag 1.6055 + * 1.6056 + * @throws SAXException 1.6057 + */ 1.6058 + private void errStrayEndTag(@Local String name) throws SAXException { 1.6059 + err("Stray end tag \u201C" + name + "\u201D."); 1.6060 + } 1.6061 + 1.6062 + /** 1.6063 + * Reports a state when elements expected to be closed were not. 1.6064 + * 1.6065 + * @param eltPos the position of the start tag on the stack of the element 1.6066 + * being closed. 1.6067 + * @param name the name of the end tag 1.6068 + * 1.6069 + * @throws SAXException 1.6070 + */ 1.6071 + private void errUnclosedElements(int eltPos, @Local String name) throws SAXException { 1.6072 + errNoCheck("End tag \u201C" + name + "\u201D seen, but there were open elements."); 1.6073 + errListUnclosedStartTags(eltPos); 1.6074 + } 1.6075 + 1.6076 + /** 1.6077 + * Reports a state when elements expected to be closed ahead of an implied 1.6078 + * end tag but were not. 1.6079 + * 1.6080 + * @param eltPos the position of the start tag on the stack of the element 1.6081 + * being closed. 1.6082 + * @param name the name of the end tag 1.6083 + * 1.6084 + * @throws SAXException 1.6085 + */ 1.6086 + private void errUnclosedElementsImplied(int eltPos, String name) throws SAXException { 1.6087 + errNoCheck("End tag \u201C" + name + "\u201D implied, but there were open elements."); 1.6088 + errListUnclosedStartTags(eltPos); 1.6089 + } 1.6090 + 1.6091 + /** 1.6092 + * Reports a state when elements expected to be closed ahead of an implied 1.6093 + * table cell close. 1.6094 + * 1.6095 + * @param eltPos the position of the start tag on the stack of the element 1.6096 + * being closed. 1.6097 + * @throws SAXException 1.6098 + */ 1.6099 + private void errUnclosedElementsCell(int eltPos) throws SAXException { 1.6100 + errNoCheck("A table cell was implicitly closed, but there were open elements."); 1.6101 + errListUnclosedStartTags(eltPos); 1.6102 + } 1.6103 + 1.6104 + private void errStrayDoctype() throws SAXException { 1.6105 + err("Stray doctype."); 1.6106 + } 1.6107 + 1.6108 + private void errAlmostStandardsDoctype() throws SAXException { 1.6109 + if (!isSrcdocDocument) { 1.6110 + err("Almost standards mode doctype. Expected \u201C<!DOCTYPE html>\u201D."); 1.6111 + } 1.6112 + } 1.6113 + 1.6114 + private void errQuirkyDoctype() throws SAXException { 1.6115 + if (!isSrcdocDocument) { 1.6116 + err("Quirky doctype. Expected \u201C<!DOCTYPE html>\u201D."); 1.6117 + } 1.6118 + } 1.6119 + 1.6120 + private void errNonSpaceInTrailer() throws SAXException { 1.6121 + err("Non-space character in page trailer."); 1.6122 + } 1.6123 + 1.6124 + private void errNonSpaceAfterFrameset() throws SAXException { 1.6125 + err("Non-space after \u201Cframeset\u201D."); 1.6126 + } 1.6127 + 1.6128 + private void errNonSpaceInFrameset() throws SAXException { 1.6129 + err("Non-space in \u201Cframeset\u201D."); 1.6130 + } 1.6131 + 1.6132 + private void errNonSpaceAfterBody() throws SAXException { 1.6133 + err("Non-space character after body."); 1.6134 + } 1.6135 + 1.6136 + private void errNonSpaceInColgroupInFragment() throws SAXException { 1.6137 + err("Non-space in \u201Ccolgroup\u201D when parsing fragment."); 1.6138 + } 1.6139 + 1.6140 + private void errNonSpaceInNoscriptInHead() throws SAXException { 1.6141 + err("Non-space character inside \u201Cnoscript\u201D inside \u201Chead\u201D."); 1.6142 + } 1.6143 + 1.6144 + private void errFooBetweenHeadAndBody(@Local String name) throws SAXException { 1.6145 + if (errorHandler == null) { 1.6146 + return; 1.6147 + } 1.6148 + errNoCheck("\u201C" + name + "\u201D element between \u201Chead\u201D and \u201Cbody\u201D."); 1.6149 + } 1.6150 + 1.6151 + private void errStartTagWithoutDoctype() throws SAXException { 1.6152 + if (!isSrcdocDocument) { 1.6153 + err("Start tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D."); 1.6154 + } 1.6155 + } 1.6156 + 1.6157 + private void errNoSelectInTableScope() throws SAXException { 1.6158 + err("No \u201Cselect\u201D in table scope."); 1.6159 + } 1.6160 + 1.6161 + private void errStartSelectWhereEndSelectExpected() throws SAXException { 1.6162 + err("\u201Cselect\u201D start tag where end tag expected."); 1.6163 + } 1.6164 + 1.6165 + private void errStartTagWithSelectOpen(@Local String name) 1.6166 + throws SAXException { 1.6167 + if (errorHandler == null) { 1.6168 + return; 1.6169 + } 1.6170 + errNoCheck("\u201C" + name 1.6171 + + "\u201D start tag with \u201Cselect\u201D open."); 1.6172 + } 1.6173 + 1.6174 + private void errBadStartTagInHead(@Local String name) throws SAXException { 1.6175 + if (errorHandler == null) { 1.6176 + return; 1.6177 + } 1.6178 + errNoCheck("Bad start tag in \u201C" + name 1.6179 + + "\u201D in \u201Chead\u201D."); 1.6180 + } 1.6181 + 1.6182 + private void errImage() throws SAXException { 1.6183 + err("Saw a start tag \u201Cimage\u201D."); 1.6184 + } 1.6185 + 1.6186 + private void errIsindex() throws SAXException { 1.6187 + err("\u201Cisindex\u201D seen."); 1.6188 + } 1.6189 + 1.6190 + private void errFooSeenWhenFooOpen(@Local String name) throws SAXException { 1.6191 + if (errorHandler == null) { 1.6192 + return; 1.6193 + } 1.6194 + errNoCheck("An \u201C" + name + "\u201D start tag seen but an element of the same type was already open."); 1.6195 + } 1.6196 + 1.6197 + private void errHeadingWhenHeadingOpen() throws SAXException { 1.6198 + err("Heading cannot be a child of another heading."); 1.6199 + } 1.6200 + 1.6201 + private void errFramesetStart() throws SAXException { 1.6202 + err("\u201Cframeset\u201D start tag seen."); 1.6203 + } 1.6204 + 1.6205 + private void errNoCellToClose() throws SAXException { 1.6206 + err("No cell to close."); 1.6207 + } 1.6208 + 1.6209 + private void errStartTagInTable(@Local String name) throws SAXException { 1.6210 + if (errorHandler == null) { 1.6211 + return; 1.6212 + } 1.6213 + errNoCheck("Start tag \u201C" + name 1.6214 + + "\u201D seen in \u201Ctable\u201D."); 1.6215 + } 1.6216 + 1.6217 + private void errFormWhenFormOpen() throws SAXException { 1.6218 + err("Saw a \u201Cform\u201D start tag, but there was already an active \u201Cform\u201D element. Nested forms are not allowed. Ignoring the tag."); 1.6219 + } 1.6220 + 1.6221 + private void errTableSeenWhileTableOpen() throws SAXException { 1.6222 + err("Start tag for \u201Ctable\u201D seen but the previous \u201Ctable\u201D is still open."); 1.6223 + } 1.6224 + 1.6225 + private void errStartTagInTableBody(@Local String name) throws SAXException { 1.6226 + if (errorHandler == null) { 1.6227 + return; 1.6228 + } 1.6229 + errNoCheck("\u201C" + name + "\u201D start tag in table body."); 1.6230 + } 1.6231 + 1.6232 + private void errEndTagSeenWithoutDoctype() throws SAXException { 1.6233 + if (!isSrcdocDocument) { 1.6234 + err("End tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D."); 1.6235 + } 1.6236 + } 1.6237 + 1.6238 + private void errEndTagAfterBody() throws SAXException { 1.6239 + err("Saw an end tag after \u201Cbody\u201D had been closed."); 1.6240 + } 1.6241 + 1.6242 + private void errEndTagSeenWithSelectOpen(@Local String name) throws SAXException { 1.6243 + if (errorHandler == null) { 1.6244 + return; 1.6245 + } 1.6246 + errNoCheck("\u201C" + name 1.6247 + + "\u201D end tag with \u201Cselect\u201D open."); 1.6248 + } 1.6249 + 1.6250 + private void errGarbageInColgroup() throws SAXException { 1.6251 + err("Garbage in \u201Ccolgroup\u201D fragment."); 1.6252 + } 1.6253 + 1.6254 + private void errEndTagBr() throws SAXException { 1.6255 + err("End tag \u201Cbr\u201D."); 1.6256 + } 1.6257 + 1.6258 + private void errNoElementToCloseButEndTagSeen(@Local String name) 1.6259 + throws SAXException { 1.6260 + if (errorHandler == null) { 1.6261 + return; 1.6262 + } 1.6263 + errNoCheck("No \u201C" + name + "\u201D element in scope but a \u201C" 1.6264 + + name + "\u201D end tag seen."); 1.6265 + } 1.6266 + 1.6267 + private void errHtmlStartTagInForeignContext(@Local String name) 1.6268 + throws SAXException { 1.6269 + if (errorHandler == null) { 1.6270 + return; 1.6271 + } 1.6272 + errNoCheck("HTML start tag \u201C" + name 1.6273 + + "\u201D in a foreign namespace context."); 1.6274 + } 1.6275 + 1.6276 + private void errTableClosedWhileCaptionOpen() throws SAXException { 1.6277 + err("\u201Ctable\u201D closed but \u201Ccaption\u201D was still open."); 1.6278 + } 1.6279 + 1.6280 + private void errNoTableRowToClose() throws SAXException { 1.6281 + err("No table row to close."); 1.6282 + } 1.6283 + 1.6284 + private void errNonSpaceInTable() throws SAXException { 1.6285 + err("Misplaced non-space characters insided a table."); 1.6286 + } 1.6287 + 1.6288 + private void errUnclosedChildrenInRuby() throws SAXException { 1.6289 + if (errorHandler == null) { 1.6290 + return; 1.6291 + } 1.6292 + errNoCheck("Unclosed children in \u201Cruby\u201D."); 1.6293 + } 1.6294 + 1.6295 + private void errStartTagSeenWithoutRuby(@Local String name) throws SAXException { 1.6296 + if (errorHandler == null) { 1.6297 + return; 1.6298 + } 1.6299 + errNoCheck("Start tag \u201C" 1.6300 + + name 1.6301 + + "\u201D seen without a \u201Cruby\u201D element being open."); 1.6302 + } 1.6303 + 1.6304 + private void errSelfClosing() throws SAXException { 1.6305 + if (errorHandler == null) { 1.6306 + return; 1.6307 + } 1.6308 + errNoCheck("Self-closing syntax (\u201C/>\u201D) used on a non-void HTML element. Ignoring the slash and treating as a start tag."); 1.6309 + } 1.6310 + 1.6311 + private void errNoCheckUnclosedElementsOnStack() throws SAXException { 1.6312 + errNoCheck("Unclosed elements on stack."); 1.6313 + } 1.6314 + 1.6315 + private void errEndTagDidNotMatchCurrentOpenElement(@Local String name, 1.6316 + @Local String currOpenName) throws SAXException { 1.6317 + if (errorHandler == null) { 1.6318 + return; 1.6319 + } 1.6320 + errNoCheck("End tag \u201C" 1.6321 + + name 1.6322 + + "\u201D did not match the name of the current open element (\u201C" 1.6323 + + currOpenName + "\u201D)."); 1.6324 + } 1.6325 + 1.6326 + private void errEndTagViolatesNestingRules(@Local String name) throws SAXException { 1.6327 + if (errorHandler == null) { 1.6328 + return; 1.6329 + } 1.6330 + errNoCheck("End tag \u201C" + name + "\u201D violates nesting rules."); 1.6331 + } 1.6332 + 1.6333 + private void errEofWithUnclosedElements() throws SAXException { 1.6334 + if (errorHandler == null) { 1.6335 + return; 1.6336 + } 1.6337 + errNoCheck("End of file seen and there were open elements."); 1.6338 + // just report all remaining unclosed elements 1.6339 + errListUnclosedStartTags(0); 1.6340 + } 1.6341 + 1.6342 + /** 1.6343 + * Reports arriving at/near end of document with unclosed elements remaining. 1.6344 + * 1.6345 + * @param message 1.6346 + * the message 1.6347 + * @throws SAXException 1.6348 + */ 1.6349 + private void errEndWithUnclosedElements(@Local String name) throws SAXException { 1.6350 + if (errorHandler == null) { 1.6351 + return; 1.6352 + } 1.6353 + errNoCheck("End tag for \u201C" 1.6354 + + name 1.6355 + + "\u201D seen, but there were unclosed elements."); 1.6356 + // just report all remaining unclosed elements 1.6357 + errListUnclosedStartTags(0); 1.6358 + } 1.6359 +}