Bug 903912 - Remove the internals of the old parser since it's only used for about:blank. r=hsivonen
authorBlake Kaplan <mrbkap@gmail.com>
Mon, 12 Aug 2013 11:28:41 -0400
changeset 142331 0bcfd14b61e81ef3bb389e9196109b7ba6b6b534
parent 142330 8c2d7f586811baf315b0685b30311e00f3a1765a
child 142332 f64b25b245022165eb5cc122560200ce3a2a5b53
push id25093
push usercbook@mozilla.com
push dateTue, 13 Aug 2013 10:34:53 +0000
treeherdermozilla-central@a0e613b4f4d8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsivonen
bugs903912
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 903912 - Remove the internals of the old parser since it's only used for about:blank. r=hsivonen
content/html/document/src/nsHTMLContentSink.cpp
content/xbl/src/nsXBLContentSink.cpp
parser/htmlparser/public/moz.build
parser/htmlparser/public/nsHTMLTokens.h
parser/htmlparser/public/nsIDTD.h
parser/htmlparser/public/nsIParserNode.h
parser/htmlparser/public/nsITokenizer.h
parser/htmlparser/public/nsToken.h
parser/htmlparser/src/CNavDTD.cpp
parser/htmlparser/src/CNavDTD.h
parser/htmlparser/src/CParserContext.cpp
parser/htmlparser/src/moz.build
parser/htmlparser/src/nsDTDUtils.cpp
parser/htmlparser/src/nsDTDUtils.h
parser/htmlparser/src/nsElementTable.cpp
parser/htmlparser/src/nsElementTable.h
parser/htmlparser/src/nsExpatDriver.cpp
parser/htmlparser/src/nsExpatDriver.h
parser/htmlparser/src/nsHTMLTokenizer.cpp
parser/htmlparser/src/nsHTMLTokenizer.h
parser/htmlparser/src/nsHTMLTokens.cpp
parser/htmlparser/src/nsParser.cpp
parser/htmlparser/src/nsParser.h
parser/htmlparser/src/nsParserModule.cpp
parser/htmlparser/src/nsParserNode.cpp
parser/htmlparser/src/nsParserNode.h
parser/htmlparser/src/nsParserService.h
parser/htmlparser/src/nsToken.cpp
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -20,17 +20,17 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsScriptLoader.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsIContentViewer.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsINodeInfo.h"
-#include "nsHTMLTokens.h"
+#include "nsToken.h"
 #include "nsIAppShell.h"
 #include "nsCRT.h"
 #include "prtime.h"
 #include "prlog.h"
 #include "nsNodeUtils.h"
 #include "nsIContent.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Preferences.h"
@@ -425,24 +425,18 @@ HTMLContentSink::AddAttributes(const nsI
 already_AddRefed<nsGenericHTMLElement>
 HTMLContentSink::CreateContentObject(const nsIParserNode& aNode,
                                      nsHTMLTag aNodeType)
 {
   // Find/create atom for the tag name
 
   nsCOMPtr<nsINodeInfo> nodeInfo;
 
-  if (aNodeType == eHTMLTag_userdefined) {
-    nsAutoString lower;
-    nsContentUtils::ASCIIToLower(aNode.GetText(), lower);
-    nsCOMPtr<nsIAtom> name = do_GetAtom(lower);
-    nodeInfo = mNodeInfoManager->GetNodeInfo(name, nullptr, kNameSpaceID_XHTML,
-                                             nsIDOMNode::ELEMENT_NODE);
-  }
-  else if (mNodeInfoCache[aNodeType]) {
+  MOZ_ASSERT(aNodeType != eHTMLTag_userdefined);
+  if (mNodeInfoCache[aNodeType]) {
     nodeInfo = mNodeInfoCache[aNodeType];
   }
   else {
     nsIParserService *parserService = nsContentUtils::GetParserService();
     if (!parserService)
       return nullptr;
 
     nsIAtom *name = parserService->HTMLIdToAtomTag(aNodeType);
@@ -859,35 +853,21 @@ SinkContext::AddLeaf(const nsIParserNode
         break;
       }
     }
     break;
 
   case eToken_text:
   case eToken_whitespace:
   case eToken_newline:
-    rv = AddText(aNode.GetText());
+    MOZ_CRASH();
 
     break;
   case eToken_entity:
-    {
-      nsAutoString tmp;
-      int32_t unicode = aNode.TranslateToUnicodeStr(tmp);
-      if (unicode < 0) {
-        rv = AddText(aNode.GetText());
-      } else {
-        // Map carriage returns to newlines
-        if (!tmp.IsEmpty()) {
-          if (tmp.CharAt(0) == '\r') {
-            tmp.Assign((PRUnichar)'\n');
-          }
-          rv = AddText(tmp);
-        }
-      }
-    }
+    MOZ_CRASH();
 
     break;
   default:
     break;
   }
 
   return rv;
 }
--- a/content/xbl/src/nsXBLContentSink.cpp
+++ b/content/xbl/src/nsXBLContentSink.cpp
@@ -6,17 +6,16 @@
 #include "mozilla/Util.h"
 
 #include "nsXBLContentSink.h"
 #include "nsIDocument.h"
 #include "nsBindingManager.h"
 #include "nsIDOMNode.h"
 #include "nsGkAtoms.h"
 #include "nsINameSpaceManager.h"
-#include "nsHTMLTokens.h"
 #include "nsIURI.h"
 #include "nsTextFragment.h"
 #ifdef MOZ_XUL
 #include "nsXULElement.h"
 #endif
 #include "nsXBLProtoImplProperty.h"
 #include "nsXBLProtoImplMethod.h"
 #include "nsXBLProtoImplField.h"
--- a/parser/htmlparser/public/moz.build
+++ b/parser/htmlparser/public/moz.build
@@ -9,17 +9,16 @@ XPIDL_SOURCES += [
     'nsIExtendedExpatSink.idl',
 ]
 
 MODULE = 'htmlparser'
 
 EXPORTS += [
     'nsHTMLTagList.h',
     'nsHTMLTags.h',
-    'nsHTMLTokens.h',
     'nsIContentSink.h',
     'nsIDTD.h',
     'nsIElementObserver.h',
     'nsIFragmentContentSink.h',
     'nsIHTMLContentSink.h',
     'nsIParser.h',
     'nsIParserNode.h',
     'nsIParserService.h',
deleted file mode 100644
--- a/parser/htmlparser/public/nsHTMLTokens.h
+++ /dev/null
@@ -1,376 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * MODULE NOTES:
- * @update  gess 4/1/98
- *
- * This file contains the declarations for all the HTML specific token types that
- * our DTD's understand. In fact, the same set of token types are used for XML.
- * Currently we have tokens for text, comments, start and end tags, entities,
- * attributes, style, script and skipped content. Whitespace and newlines also
- * have their own token types, but don't count on them to stay forever.
- *
- * If you're looking for the html tags, they're in a file called nsHTMLTag.h/cpp.
- *
- * Most of the token types have a similar API. They have methods to get the type
- * of token (GetTokenType); those that represent HTML tags also have a method to
- * get type tag type (GetTypeID). In addition, most have a method that causes the
- * token to help in the parsing process called (Consume). We've also thrown in a
- * few standard debugging methods as well.
- */
-
-#ifndef HTMLTOKENS_H
-#define HTMLTOKENS_H
-
-#include "nsToken.h"
-#include "nsHTMLTags.h"
-#include "nsString.h"
-#include "nsScannerString.h"
-
-class nsScanner;
-
-  /*******************************************************************
-   * This enum defines the set of token types that we currently support.
-   *******************************************************************/
-
-enum eHTMLTokenTypes {
-  eToken_unknown=0,
-  eToken_start=1,      eToken_end,          eToken_comment,         eToken_entity,
-  eToken_whitespace,   eToken_newline,      eToken_text,            eToken_attribute,
-  eToken_instruction,  eToken_cdatasection, eToken_doctypeDecl,     eToken_markupDecl,
-  eToken_last //make sure this stays the last token...
-};
-
-nsresult      ConsumeQuotedString(PRUnichar aChar,nsString& aString,nsScanner& aScanner);
-nsresult      ConsumeAttributeText(PRUnichar aChar,nsString& aString,nsScanner& aScanner);
-const PRUnichar* GetTagName(int32_t aTag);
-//int32_t     FindEntityIndex(nsString& aString,int32_t aCount=-1);
-
-
-
-/**
- *  This declares the basic token type used in the HTML DTD's.
- *  @update  gess 3/25/98
- */
-class CHTMLToken : public CToken {
-public:
-  virtual ~CHTMLToken();
-  CHTMLToken(eHTMLTags aTag);
-
-  virtual eContainerInfo GetContainerInfo(void) const {return eFormUnknown;}
-  virtual void SetContainerInfo(eContainerInfo aInfo) { }
-
-protected:
-};
-
-/**
- *  This declares start tokens, which always take the form <xxxx>.
- *  This class also knows how to consume related attributes.
- *
- *  @update  gess 3/25/98
- */
-class CStartToken: public CHTMLToken {
-public:
-  CStartToken(eHTMLTags aTag=eHTMLTag_unknown);
-  CStartToken(const nsAString& aString);
-  CStartToken(const nsAString& aName,eHTMLTags aTag);
-
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTypeID(void);
-  virtual int32_t GetTokenType(void);
-
-  virtual bool IsEmpty(void);
-  virtual void SetEmpty(bool aValue);
-
-  virtual const nsSubstring& GetStringValue();
-  virtual void GetSource(nsString& anOutputString);
-  virtual void AppendSourceTo(nsAString& anOutputString);
-
-  // the following info is used to set well-formedness state on start tags...
-  virtual eContainerInfo GetContainerInfo(void) const {return mContainerInfo;}
-  virtual void SetContainerInfo(eContainerInfo aContainerInfo) {
-    if (eFormUnknown==mContainerInfo) {
-      mContainerInfo=aContainerInfo;
-    }
-  }
-  virtual bool IsWellFormed(void) const {
-    return eWellFormed == mContainerInfo;
-  }
-
-  nsString mTextValue;
-protected:
-  eContainerInfo mContainerInfo;
-  bool mEmpty;
-#ifdef DEBUG
-  bool mAttributed;
-#endif
-};
-
-
-/**
- *  This declares end tokens, which always take the
- *  form </xxxx>. This class also knows how to consume
- *  related attributes.
- *
- *  @update  gess 3/25/98
- */
-class CEndToken: public CHTMLToken {
-public:
-  CEndToken(eHTMLTags aTag);
-  CEndToken(const nsAString& aString);
-  CEndToken(const nsAString& aName,eHTMLTags aTag);
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTypeID(void);
-  virtual int32_t GetTokenType(void);
-
-  virtual const nsSubstring& GetStringValue();
-  virtual void GetSource(nsString& anOutputString);
-  virtual void AppendSourceTo(nsAString& anOutputString);
-
-protected:
-  nsString mTextValue;
-};
-
-
-/**
- *  This declares comment tokens. Comments are usually
- *  thought of as tokens, but we treat them that way
- *  here so that the parser can have a consistent view
- *  of all tokens.
- *
- *  @update  gess 3/25/98
- */
-class CCommentToken: public CHTMLToken {
-public:
-  CCommentToken();
-  CCommentToken(const nsAString& aString);
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTokenType(void);
-  virtual const nsSubstring& GetStringValue(void);
-  virtual void AppendSourceTo(nsAString& anOutputString);
-
-  nsresult ConsumeStrictComment(nsScanner& aScanner);
-  nsresult ConsumeQuirksComment(nsScanner& aScanner);
-
-protected:
-  nsScannerSubstring mComment; // does not include MDO & MDC
-  nsScannerSubstring mCommentDecl; // includes MDO & MDC
-};
-
-
-/**
- *  This class declares entity tokens, which always take
- *  the form &xxxx;. This class also offers a few utility
- *  methods that allow you to easily reduce entities.
- *
- *  @update  gess 3/25/98
- */
-class CEntityToken : public CHTMLToken {
-public:
-  CEntityToken();
-  CEntityToken(const nsAString& aString);
-  virtual int32_t GetTokenType(void);
-  int32_t TranslateToUnicodeStr(nsString& aString);
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  static nsresult ConsumeEntity(PRUnichar aChar, nsString& aString,
-                                nsScanner& aScanner);
-  static int32_t TranslateToUnicodeStr(int32_t aValue,nsString& aString);
-
-  virtual const nsSubstring& GetStringValue(void);
-  virtual void GetSource(nsString& anOutputString);
-  virtual void AppendSourceTo(nsAString& anOutputString);
-
-protected:
-  nsString mTextValue;
-};
-
-
-/**
- *  Whitespace tokens are used where whitespace can be
- *  detected as distinct from text. This allows us to
- *  easily skip leading/trailing whitespace when desired.
- *
- *  @update  gess 3/25/98
- */
-class CWhitespaceToken: public CHTMLToken {
-public:
-  CWhitespaceToken();
-  CWhitespaceToken(const nsAString& aString);
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTokenType(void);
-  virtual const nsSubstring& GetStringValue(void);
-
-protected:
-  nsScannerSharedSubstring mTextValue;
-};
-
-/**
- *  Text tokens contain the normalized form of html text.
- *  These tokens are guaranteed not to contain entities,
- *  start or end tags, or newlines.
- *
- *  @update  gess 3/25/98
- */
-class CTextToken: public CHTMLToken {
-public:
-  CTextToken();
-  CTextToken(const nsAString& aString);
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTokenType(void);
-  virtual int32_t GetTextLength(void);
-  virtual void CopyTo(nsAString& aStr);
-  virtual const nsSubstring& GetStringValue(void);
-  virtual void Bind(nsScanner* aScanner, nsScannerIterator& aStart,
-                    nsScannerIterator& aEnd);
-  virtual void Bind(const nsAString& aStr);
-
-  nsresult ConsumeCharacterData(bool aIgnoreComments,
-                                nsScanner& aScanner,
-                                const nsAString& aEndTagName,
-                                int32_t aFlag,
-                                bool& aFlushTokens);
-
-  nsresult ConsumeParsedCharacterData(bool aDiscardFirstNewline,
-                                      bool aConservativeConsume,
-                                      nsScanner& aScanner,
-                                      const nsAString& aEndTagName,
-                                      int32_t aFlag,
-                                      bool& aFound);
-
-protected:
-  nsScannerSubstring mTextValue;
-};
-
-
-/**
- *  CDATASection tokens contain raw unescaped text content delimited by
- *  a ![CDATA[ and ]].
- *  XXX Not really a HTML construct - maybe we need a separation
- *
- *  @update  vidur 11/12/98
- */
-class CCDATASectionToken : public CHTMLToken {
-public:
-  CCDATASectionToken(eHTMLTags aTag = eHTMLTag_unknown);
-  CCDATASectionToken(const nsAString& aString);
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTokenType(void);
-  virtual const nsSubstring& GetStringValue(void);
-
-protected:
-  nsString mTextValue;
-};
-
-
-/**
- *  Declaration tokens contain raw unescaped text content (not really, but
- *  right now we use this only for view source).
- *  XXX Not really a HTML construct - maybe we need a separation
- *
- */
-class CMarkupDeclToken : public CHTMLToken {
-public:
-  CMarkupDeclToken();
-  CMarkupDeclToken(const nsAString& aString);
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTokenType(void);
-  virtual const nsSubstring& GetStringValue(void);
-
-protected:
-  nsScannerSubstring  mTextValue;
-};
-
-
-/**
- *  Attribute tokens are used to contain attribute key/value
- *  pairs whereever they may occur. Typically, they should
- *  occur only in start tokens. However, we may expand that
- *  ability when XML tokens become commonplace.
- *
- *  @update  gess 3/25/98
- */
-class CAttributeToken: public CHTMLToken {
-public:
-  CAttributeToken();
-  CAttributeToken(const nsAString& aString);
-  CAttributeToken(const nsAString& aKey, const nsAString& aString);
-  ~CAttributeToken() {}
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTokenType(void);
-  const nsSubstring&     GetKey(void) { return mTextKey.AsString(); }
-  virtual void SetKey(const nsAString& aKey);
-  virtual void BindKey(nsScanner* aScanner, nsScannerIterator& aStart,
-                       nsScannerIterator& aEnd);
-  const nsSubstring& GetValue(void) {return mTextValue.str();}
-  virtual const nsSubstring& GetStringValue(void);
-  virtual void GetSource(nsString& anOutputString);
-  virtual void AppendSourceTo(nsAString& anOutputString);
-
-  bool mHasEqualWithoutValue;
-protected:
-  nsScannerSharedSubstring mTextValue;
-  nsScannerSubstring mTextKey;
-};
-
-
-/**
- *  Newline tokens contain, you guessed it, newlines.
- *  They consume newline (CR/LF) either alone or in pairs.
- *
- *  @update  gess 3/25/98
- */
-class CNewlineToken: public CHTMLToken {
-public:
-  CNewlineToken();
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTokenType(void);
-  virtual const nsSubstring& GetStringValue(void);
-
-  static void AllocNewline();
-  static void FreeNewline();
-};
-
-
-/**
- *  Whitespace tokens are used where whitespace can be
- *  detected as distinct from text. This allows us to
- *  easily skip leading/trailing whitespace when desired.
- *
- *  @update  gess 3/25/98
- */
-class CInstructionToken: public CHTMLToken {
-public:
-  CInstructionToken();
-  CInstructionToken(const nsAString& aString);
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTokenType(void);
-  virtual const nsSubstring& GetStringValue(void);
-
-protected:
-  nsString mTextValue;
-};
-
-
-/**
- * This token is generated by the HTML and Expat tokenizers
- * when they see the doctype declaration ("<!DOCTYPE ... >")
- *
- */
-
-class CDoctypeDeclToken: public CHTMLToken {
-public:
-  CDoctypeDeclToken(eHTMLTags aTag=eHTMLTag_unknown);
-  CDoctypeDeclToken(const nsAString& aString,eHTMLTags aTag=eHTMLTag_unknown);
-  virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-  virtual int32_t GetTokenType(void);
-  virtual const nsSubstring& GetStringValue(void);
-  virtual void SetStringValue(const nsAString& aStr);
-
-protected:
-  nsString mTextValue;
-};
-
-#endif
--- a/parser/htmlparser/public/nsIDTD.h
+++ b/parser/htmlparser/public/nsIDTD.h
@@ -42,17 +42,16 @@ enum nsDTDMode {
     eDTDMode_almost_standards,
     eDTDMode_full_standards,
     eDTDMode_autodetect,
     eDTDMode_fragment
 };
 
 
 class nsIParser;
-class CToken;
 class nsIURI;
 class nsIContentSink;
 class CParserContext;
 
 class nsIDTD : public nsISupports
 {
 public:
 
@@ -76,19 +75,17 @@ public:
      *
      * @param   aTokenizer - tokenizer providing the token stream to be parsed
      * @param   aCountLines - informs the DTD whether to count newlines
      *                        (not wanted, e.g., when handling document.write)
      * @param   aCharsetPtr - address of an nsCString containing the charset
      *                        that the DTD should use (pointer in case the DTD
      *                        opts to ignore this parameter)
      */
-    NS_IMETHOD BuildModel(nsITokenizer* aTokenizer,
-                          bool aCountLines,
-                          const nsCString* aCharsetPtr) = 0;
+    NS_IMETHOD BuildModel(nsITokenizer* aTokenizer, nsIContentSink* aSink) = 0;
 
     /**
      * This method is called to determine whether or not a tag of one
      * type can contain a tag of another type.
      *
      * @update  gess 3/25/98
      * @param   aParent -- int tag of parent container
      * @param   aChild -- int tag of child container
@@ -127,15 +124,15 @@ public:
     NS_IMETHOD_(nsDTDMode) GetMode() const = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIDTD, NS_IDTD_IID)
 
 #define NS_DECL_NSIDTD \
     NS_IMETHOD WillBuildModel(  const CParserContext& aParserContext, nsITokenizer* aTokenizer, nsIContentSink* aSink);\
     NS_IMETHOD DidBuildModel(nsresult anErrorCode);\
-    NS_IMETHOD BuildModel(nsITokenizer* aTokenizer, bool aCountLines, const nsCString* aCharsetPtr);\
+    NS_IMETHOD BuildModel(nsITokenizer* aTokenizer, nsIContentSink* aSink);\
     NS_IMETHOD_(bool) CanContain(int32_t aParent,int32_t aChild) const;\
     NS_IMETHOD_(bool) IsContainer(int32_t aTag) const;\
     NS_IMETHOD_(void)  Terminate();\
     NS_IMETHOD_(int32_t) GetType();\
     NS_IMETHOD_(nsDTDMode) GetMode() const;
 #endif /* nsIDTD_h___ */
--- a/parser/htmlparser/public/nsIParserNode.h
+++ b/parser/htmlparser/public/nsIParserNode.h
@@ -18,58 +18,30 @@
  * If you want to hang onto one of these, you should
  * make your own copy.
  *
  */
 
 #ifndef NS_IPARSERNODE__
 #define NS_IPARSERNODE__
 
-#include "nsISupports.h"
 #include "nsStringGlue.h"
-#include "nsDebug.h"
-
-//#define HEAP_ALLOCATED_NODES 
-//#define DEBUG_TRACK_NODES
 
 class nsIAtom;
-class CToken;
-
-// 6e59f160-2717-11d2-9246-00805f8a7ab6
-#define NS_IPARSER_NODE_IID      \
-  {0x6e59f160, 0x2717,  0x11d1,  \
-  {0x92, 0x46, 0x00,    0x80, 0x5f, 0x8a, 0x7a, 0xb6}}
 
 /**
  *  Parser nodes are the unit of exchange between the 
  *  parser and the content sink. Nodes offer access to
  *  the current token, its attributes, and its skipped-
  *  content if applicable.
  *  
  *  @update  gess 3/25/98
  */
-class nsIParserNode { // XXX Should be nsAParserNode
-            
+class nsIParserNode {
   public:
-
-
-    /**
-     * Retrieve the name of the node
-     * @update	gess5/11/98
-     * @return  string containing node name
-     */
-    virtual const nsAString& GetTagName() const = 0;  //to get name of tag
-
-    /**
-     * Retrieve the text from the given node
-     * @update	gess5/11/98
-     * @return  string containing node text
-     */
-    virtual const nsAString& GetText() const = 0;  //get plain text if available
-
     /**
      * Retrieve the type of the parser node.
      * @update	gess5/11/98
      * @return  node type.
      */
     virtual int32_t GetNodeType()  const =0;
 
     /**
@@ -79,68 +51,28 @@ class nsIParserNode { // XXX Should be n
      */
     virtual int32_t GetTokenType()  const =0;
 
     /**
      * Retrieve the number of attributes in this node.
      * @update	gess5/11/98
      * @return  count of attributes (may be 0)
      */
-    virtual int32_t GetAttributeCount(bool askToken=false) const =0;
+    virtual int32_t GetAttributeCount() const =0;
 
     /**
      * Retrieve the key (of key/value pair) at given index
      * @update	gess5/11/98
      * @param   anIndex is the index of the key you want
      * @return  string containing key.
      */
     virtual const nsAString& GetKeyAt(uint32_t anIndex) const = 0;
 
     /**
      * Retrieve the value (of key/value pair) at given index
      * @update	gess5/11/98
      * @param   anIndex is the index of the value you want
      * @return  string containing value.
      */
     virtual const nsAString& GetValueAt(uint32_t anIndex) const = 0;
-
-    /**
-     * NOTE: When the node is an entity, this will translate the entity
-     *       to it's unicode value, and store it in aString.
-     * @update	gess5/11/98
-     * @param   aString will contain the resulting unicode string value
-     * @return  int (unicode char or unicode index from table)
-     */
-    virtual int32_t TranslateToUnicodeStr(nsString& aString) const = 0;
-
-
-    virtual void AddAttribute(CToken* aToken)=0;
-
-    /**
-     * This getter retrieves the line number from the input source where
-     * the token occurred. Lines are interpreted as occurring between \n characters.
-     * @update	gess7/24/98
-     * @return  int containing the line number the token was found on
-     */
-    virtual int32_t GetSourceLineNumber(void) const =0;
-
-    /**
-     * This pair of methods allows us to set a generic bit (for arbitrary use)
-     * on each node stored in the context.
-     * @update	gess 11May2000
-     */
-    virtual bool    GetGenericState(void) const =0;
-    virtual void    SetGenericState(bool aState) =0;
-
-    /** Retrieve a string containing the tag and its attributes in "source" form
-     * @update	rickg 06June2000
-     * @return  void
-     */
-    virtual void GetSource(nsString& aString) const = 0;
-
-    /** Release all the objects you're holding
-     * @update	harishd 08/02/00
-     * @return  void
-     */
-    virtual nsresult ReleaseAll()=0;
 };
 
 #endif
--- a/parser/htmlparser/public/nsITokenizer.h
+++ b/parser/htmlparser/public/nsITokenizer.h
@@ -10,60 +10,35 @@
  * 
  */
 
 #ifndef __NSITOKENIZER__
 #define __NSITOKENIZER__
 
 #include "nsISupports.h"
 
-class CToken;
 class nsScanner;
-class nsDeque;
-class nsTokenAllocator;
 
 #define NS_ITOKENIZER_IID      \
-  {0xe4238ddc, 0x9eb6,  0x11d2, {0xba, 0xa5, 0x0,     0x10, 0x4b, 0x98, 0x3f, 0xd4 }}
-
+{ 0Xae98a348, 0X5e91, 0X41a8, \
+  { 0Xa5, 0Xb4, 0Xd2, 0X20, 0Xf3, 0X1f, 0Xc4, 0Xab } }
 
 /***************************************************************
   Notes: 
  ***************************************************************/
 
 
 class nsITokenizer : public nsISupports {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITOKENIZER_IID)
 
-  NS_IMETHOD                     WillTokenize(bool aIsFinalChunk,nsTokenAllocator* aTokenAllocator)=0;
+  NS_IMETHOD                     WillTokenize(bool aIsFinalChunk)=0;
   NS_IMETHOD                     ConsumeToken(nsScanner& aScanner,bool& aFlushTokens)=0;
-  NS_IMETHOD                     DidTokenize(bool aIsFinalChunk)=0;
-  
-  NS_IMETHOD_(CToken*)           PushTokenFront(CToken* aToken)=0;
-  NS_IMETHOD_(CToken*)           PushToken(CToken* aToken)=0;
-  NS_IMETHOD_(CToken*)           PopToken(void)=0;
-  NS_IMETHOD_(CToken*)           PeekToken(void)=0;
-  NS_IMETHOD_(CToken*)           GetTokenAt(int32_t anIndex)=0;
-  NS_IMETHOD_(int32_t)           GetCount(void)=0;
-  NS_IMETHOD_(nsTokenAllocator*) GetTokenAllocator(void)=0;
-  NS_IMETHOD_(void)              PrependTokens(nsDeque& aDeque)=0;
-  NS_IMETHOD                     CopyState(nsITokenizer* aTokenizer)=0;
-  
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsITokenizer, NS_ITOKENIZER_IID)
 
 #define NS_DECL_NSITOKENIZER \
-  NS_IMETHOD                     WillTokenize(bool aIsFinalChunk,nsTokenAllocator* aTokenAllocator);\
+  NS_IMETHOD                     WillTokenize(bool aIsFinalChunk);\
   NS_IMETHOD                     ConsumeToken(nsScanner& aScanner,bool& aFlushTokens);\
-  NS_IMETHOD                     DidTokenize(bool aIsFinalChunk);\
-  NS_IMETHOD_(CToken*)           PushTokenFront(CToken* aToken);\
-  NS_IMETHOD_(CToken*)           PushToken(CToken* aToken);\
-  NS_IMETHOD_(CToken*)           PopToken(void);\
-  NS_IMETHOD_(CToken*)           PeekToken(void);\
-  NS_IMETHOD_(CToken*)           GetTokenAt(int32_t anIndex);\
-  NS_IMETHOD_(int32_t)           GetCount(void);\
-  NS_IMETHOD_(nsTokenAllocator*) GetTokenAllocator(void);\
-  NS_IMETHOD_(void)              PrependTokens(nsDeque& aDeque);\
-  NS_IMETHOD                     CopyState(nsITokenizer* aTokenizer);
 
 
 #endif
--- a/parser/htmlparser/public/nsToken.h
+++ b/parser/htmlparser/public/nsToken.h
@@ -1,263 +1,26 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-
-/**
- * MODULE NOTES:
- * @update  gess 4/1/98
- * 
- * This class is defines the basic notion of a token
- * within our system. All other tokens are derived from
- * this one. It offers a few basic interfaces, but the
- * most important is consume(). The consume() method gets
- * called during the tokenization process when an instance
- * of that particular token type gets detected in the 
- * input stream.
- *
- * CToken objects that are allocated from the heap are allocated
- * using the nsTokenAllocator object.  nsTokenAllocator used to use
- * an arena-style allocator, but that is no longer necessary or helpful;
- * it now uses a trivial drop-in replacement for the arena-style
- * allocator called nsDummyAllocator, which just wraps malloc/free.
- */
-
-
 #ifndef CTOKEN__
 #define CTOKEN__
 
 #include "prtypes.h"
 #include "nsString.h"
 #include "nsError.h"
 
 class nsScanner;
 class nsTokenAllocator;
 
-/**
- * A trivial allocator.  See the comment at the top of this file.
- */
-class nsDummyAllocator {
-public:
-  void* Alloc(size_t aSize) { return malloc(aSize); }
-  void Free(void* aPtr) { free(aPtr); }
-};
-
-enum eContainerInfo {
-  eWellFormed,
-  eMalformed,
-  eFormUnknown
+enum eHTMLTokenTypes {
+  eToken_unknown=0,
+  eToken_start=1,      eToken_end,          eToken_comment,         eToken_entity,
+  eToken_whitespace,   eToken_newline,      eToken_text,            eToken_attribute,
+  eToken_instruction,  eToken_cdatasection, eToken_doctypeDecl,     eToken_markupDecl,
+  eToken_last //make sure this stays the last token...
 };
 
-/**
- *  Token objects represent sequences of characters as they
- *  are consumed from the input stream (URL). While they're
- *  pretty general in nature, we use subclasses (found in
- *  nsHTMLTokens.h) to define <start>, </end>, <text>,
- *  <comment>, <&entity>, <newline>, and <whitespace> tokens.
- *  
- *  @update  gess 3/25/98
- */
-class CToken {
-  public:
-
-    enum  eTokenOrigin {eSource,eResidualStyle};
-
-  protected:
-
-    // nsTokenAllocator should be the only class that tries to
-    // allocate tokens from the heap.
-    friend class nsTokenAllocator;
-
-    /**
-     * 
-     * @update	harishd 08/01/00
-     * @param   aSize    - 
-     * @param   aArena   - Allocate memory from this pool.
-     */
-    static void * operator new (size_t aSize, nsDummyAllocator& anArena) CPP_THROW_NEW
-    {
-      return anArena.Alloc(aSize);
-    }
-
-    /**
-     * Hide operator delete; clients should use Destroy() instead.
-     */
-    static void operator delete (void*,size_t) {}
-
-  protected:
-    /**
-     * destructor
-     * @update	gess5/11/98
-     */
-    virtual ~CToken();
-
-  private:
-    /**
-     * Destroy a token.
-     */
-    static void Destroy(CToken* aToken, nsDummyAllocator& aArenaPool)
-    {
-      aToken->~CToken();
-      aArenaPool.Free(aToken);
-    }
-
-  public:
-    /**
-     * Make a note on number of times you have been referenced
-     * @update	harishd 08/02/00
-     */
-    void AddRef() {
-      ++mUseCount;
-      NS_LOG_ADDREF(this, mUseCount, "CToken", sizeof(*this));
-    }
-    
-    /**
-     * Free yourself if no one is holding you.
-     * @update	harishd 08/02/00
-     */
-    void Release(nsDummyAllocator& aArenaPool) {
-      --mUseCount;
-      NS_LOG_RELEASE(this, mUseCount, "CToken");
-      if (mUseCount==0)
-        Destroy(this, aArenaPool);
-    }
-
-    /**
-     * Default constructor
-     * @update	gess7/21/98
-     */
-    CToken(int32_t aTag=0);
-
-    /**
-     * Retrieve string value of the token
-     * @update	gess5/11/98
-     * @return  reference to string containing string value
-     */
-    virtual const nsSubstring& GetStringValue(void) = 0;
-
-    /**
-     * Get string of full contents, suitable for debug dump.
-     * It should look exactly like the input source.
-     * @update	gess5/11/98
-     * @return  reference to string containing string value
-     */
-    virtual void GetSource(nsString& anOutputString);
-
-    /** @update	harishd 03/23/00
-     *  @return  reference to string containing string value
-     */
-    virtual void AppendSourceTo(nsAString& anOutputString);
-
-    /**
-     * Sets the ordinal value of this token (not currently used)
-     * @update	gess5/11/98
-     * @param   value is the new ord value for this token
-     */
-    void SetTypeID(int32_t aValue) {
-      mTypeID = aValue;
-    }
-    
-    /**
-     * Getter which retrieves the current ordinal value for this token
-     * @update	gess5/11/98
-     * @return  current ordinal value 
-     */
-    virtual int32_t GetTypeID(void);
-
-    /**
-     * Getter which retrieves the current attribute count for this token
-     * @update	gess5/11/98
-     * @return  current attribute count 
-     */
-    virtual int16_t GetAttributeCount(void);
-
-    /**
-     * Causes token to consume data from given scanner.
-     * Note that behavior varies wildly between CToken subclasses.
-     * @update	gess5/11/98
-     * @param   aChar -- most recent char consumed
-     * @param   aScanner -- input source where token should get data
-     * @return  error code (0 means ok)
-     */
-    virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,int32_t aMode);
-
-    /**
-     * Getter which retrieves type of token
-     * @update	gess5/11/98
-     * @return  int containing token type
-     */
-    virtual int32_t GetTokenType(void);
-
-    /**
-     * For tokens who care, this can tell us whether the token is 
-     * well formed or not.
-     *
-     * @update	gess 8/30/00
-     * @return  false; subclasses MUST override if they care.
-     */
-    virtual bool IsWellFormed(void) const {return false;}
-
-    virtual bool IsEmpty(void) { return false; }
-    
-    /**
-     * If aValue is TRUE then the token represents a short-hand tag
-     */
-    virtual void SetEmpty(bool aValue) { return ; }
-
-    int32_t GetNewlineCount() 
-    { 
-      return mNewlineCount; 
-    }
-
-    void SetNewlineCount(int32_t aCount)
-    {
-      mNewlineCount = aCount;
-    }
-
-    int32_t GetLineNumber() 
-    { 
-      return mLineNumber;
-    }
-
-    void SetLineNumber(int32_t aLineNumber) 
-    { 
-      mLineNumber = mLineNumber == 0 ? aLineNumber : mLineNumber;
-    }
-
-    void SetInError(bool aInError)
-    {
-      mInError = aInError;
-    }
-
-    bool IsInError()
-    {
-      return mInError;
-    }
-
-    void SetAttributeCount(int16_t aValue) {  mAttrCount = aValue; }
-
-    /**
-     * perform self test.
-     * @update	gess5/11/98
-     */
-    virtual void SelfTest(void);
-
-    static int GetTokenCount();
-
-    
-
-protected:
-    int32_t mTypeID;
-    int32_t mUseCount;
-    int32_t mNewlineCount;
-    uint32_t mLineNumber : 31;
-    uint32_t mInError : 1;
-    int16_t mAttrCount;
-};
-
-
-
 #endif
 
 
--- a/parser/htmlparser/src/CNavDTD.cpp
+++ b/parser/htmlparser/src/CNavDTD.cpp
@@ -1,2907 +1,97 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=2 et tw=78: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Util.h"
 
-#include "nsDebug.h"
-#include "nsIAtom.h"
+#include "nsISupports.h"
+#include "nsISupportsImpl.h"
+#include "nsIParser.h"
 #include "CNavDTD.h"
-#include "nsHTMLTokens.h"
-#include "nsCRT.h"
-#include "nsParser.h"
 #include "nsIHTMLContentSink.h"
-#include "nsScanner.h"
-#include "prenv.h"
-#include "prtypes.h"
-#include "prio.h"
-#include "plstr.h"
-#include "nsDTDUtils.h"
-#include "nsHTMLTokenizer.h"
 #include "nsParserNode.h"
-#include "nsHTMLEntities.h"
-#include "nsLinebreakConverter.h"
-#include "nsIFormProcessor.h"
-#include "nsTArray.h"
-#include "nsReadableUtils.h"
-#include "nsUnicharUtils.h"
-#include "nsIServiceManager.h"
-#include "nsParserConstants.h"
-#include <algorithm>
-
-using namespace mozilla;
-
-/*
- * Ignore kFontStyle and kPhrase tags when the stack is deep, bug 58917.
- */
-#define FONTSTYLE_IGNORE_DEPTH (MAX_REFLOW_DEPTH * 80 / 100)
-#define PHRASE_IGNORE_DEPTH    (MAX_REFLOW_DEPTH * 90 / 100)
 
-static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID);
-
-#ifdef DEBUG
-static const  char kNullToken[] = "Error: Null token given";
-static const  char kInvalidTagStackPos[] = "Error: invalid tag stack position";
-#endif
-
-#include "nsElementTable.h"
-
-// Some flags for use by the DTD.
-#define NS_DTD_FLAG_NONE                   0x00000000
-#define NS_DTD_FLAG_HAS_OPEN_HEAD          0x00000001
-#define NS_DTD_FLAG_HAS_OPEN_BODY          0x00000002
-#define NS_DTD_FLAG_HAS_OPEN_FORM          0x00000004
-#define NS_DTD_FLAG_HAS_EXPLICIT_HEAD      0x00000008
-#define NS_DTD_FLAG_HAD_BODY               0x00000010
-#define NS_DTD_FLAG_HAD_FRAMESET           0x00000020
-#define NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE  0x00000040
-#define NS_DTD_FLAG_ALTERNATE_CONTENT      0x00000080 // NOFRAMES, NOSCRIPT
-#define NS_DTD_FLAG_MISPLACED_CONTENT      0x00000100
-#define NS_DTD_FLAG_IN_MISPLACED_CONTENT   0x00000200
-#define NS_DTD_FLAG_STOP_PARSING           0x00000400
-
-#define NS_DTD_FLAG_HAS_MAIN_CONTAINER     (NS_DTD_FLAG_HAD_BODY |            \
-                                            NS_DTD_FLAG_HAD_FRAMESET)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CNavDTD)
-  NS_INTERFACE_MAP_ENTRY(nsIDTD)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDTD)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(CNavDTD)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(CNavDTD)
-
-NS_IMPL_CYCLE_COLLECTION_1(CNavDTD, mSink)
+NS_IMPL_ISUPPORTS1(CNavDTD, nsIDTD);
 
 CNavDTD::CNavDTD()
-  : mMisplacedContent(0),
-    mTokenAllocator(0),
-    mBodyContext(new nsDTDContext()),
-    mTempContext(0),
-    mCountLines(true),
-    mTokenizer(0),
-    mDTDMode(eDTDMode_quirks),
-    mDocType(eHTML_Quirks),
-    mParserCommand(eViewNormal),
-    mLineNumber(1),
-    mOpenMapCount(0),
-    mHeadContainerPosition(-1),
-    mFlags(NS_DTD_FLAG_NONE)
 {
 }
 
 CNavDTD::~CNavDTD()
 {
-  delete mBodyContext;
-  delete mTempContext;
 }
 
 NS_IMETHODIMP
 CNavDTD::WillBuildModel(const CParserContext& aParserContext,
                         nsITokenizer* aTokenizer,
                         nsIContentSink* aSink)
 {
-  nsresult result = NS_OK;
-
-  mFilename = aParserContext.mScanner->GetFilename();
-  mFlags = NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE;
-  mLineNumber = 1;
-  mDTDMode = aParserContext.mDTDMode;
-  mParserCommand = aParserContext.mParserCommand;
-  mMimeType = aParserContext.mMimeType;
-  mDocType = aParserContext.mDocType;
-  mTokenizer = aTokenizer;
-  mBodyContext->SetNodeAllocator(&mNodeAllocator);
-
-  if (!aParserContext.mPrevContext && aSink) {
-
-    if (!mSink) {
-      mSink = do_QueryInterface(aSink, &result);
-      if (NS_FAILED(result)) {
-        mFlags |= NS_DTD_FLAG_STOP_PARSING;
-        return result;
-      }
-    }
-
-    mFlags |= nsHTMLTokenizer::GetFlags(aSink);
-
-  }
-
-  return result;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 CNavDTD::BuildModel(nsITokenizer* aTokenizer,
-                    bool aCountLines,
-                    const nsCString*)
+                    nsIContentSink* aSink)
 {
-  NS_PRECONDITION(mBodyContext != nullptr,
-                  "Create a context before calling build model");
-
-  nsresult result = NS_OK;
-
-  if (!aTokenizer) {
-    return NS_OK;
-  }
-
-  nsITokenizer* const oldTokenizer = mTokenizer;
-
-  mCountLines     = aCountLines;
-  mTokenizer      = aTokenizer;
-  mTokenAllocator = mTokenizer->GetTokenAllocator();
-  
-  if (!mSink) {
-    return (mFlags & NS_DTD_FLAG_STOP_PARSING)
-           ? NS_ERROR_HTMLPARSER_STOPPARSING
-           : result;
+  // NB: It is important to throw STOPPARSING if the sink is the wrong type in
+  // order to make sure nsParser cleans up properly after itself.
+  nsCOMPtr<nsIHTMLContentSink> sink = do_QueryInterface(aSink);
+  if (!sink) {
+    return NS_ERROR_HTMLPARSER_STOPPARSING;
   }
 
-  if (mBodyContext->GetCount() == 0) {
-    CToken* tempToken;
-    if (ePlainText == mDocType) {
-      tempToken =
-        mTokenAllocator->CreateTokenOfType(eToken_start, eHTMLTag_pre);
-      if (tempToken) {
-        mTokenizer->PushTokenFront(tempToken);
-      }
-    }
-
-    // Always open a body if frames are disabled.
-    if (!(mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED)) {
-      tempToken =
-        mTokenAllocator->CreateTokenOfType(eToken_start,
-                                           eHTMLTag_body,
-                                           NS_LITERAL_STRING("body"));
-      if (tempToken) {
-        mTokenizer->PushTokenFront(tempToken);
-      }
-    }
+  nsParserNode html(eHTMLTag_html);
+  nsParserNode body(eHTMLTag_body);
 
-    // If the content model is empty, then begin by opening <html>.
-    CStartToken* theToken = (CStartToken*)mTokenizer->GetTokenAt(0);
-    if (theToken) {
-      eHTMLTags theTag = (eHTMLTags)theToken->GetTypeID();
-      eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType());
-      if (theTag != eHTMLTag_html || theType != eToken_start) {
-        tempToken =
-          mTokenAllocator->CreateTokenOfType(eToken_start,
-                                             eHTMLTag_html,
-                                             NS_LITERAL_STRING("html"));
-        if (tempToken) {
-          mTokenizer->PushTokenFront(tempToken);
-        }
-      }
-    } else {
-      tempToken =
-        mTokenAllocator->CreateTokenOfType(eToken_start,
-                                           eHTMLTag_html,
-                                           NS_LITERAL_STRING("html"));
-      if (tempToken) {
-        mTokenizer->PushTokenFront(tempToken);
-      }
-    }
-  }
+  nsresult rv = sink->OpenContainer(html);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = sink->OpenContainer(body);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  while (NS_SUCCEEDED(result)) {
-    if (!(mFlags & NS_DTD_FLAG_STOP_PARSING)) {
-      CToken* theToken = mTokenizer->PopToken();
-      if (!theToken) {
-        break;
-      }
-      result = HandleToken(theToken);
-    } else {
-      result = NS_ERROR_HTMLPARSER_STOPPARSING;
-      break;
-    }
+  rv = sink->CloseContainer(eHTMLTag_body);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  rv = sink->CloseContainer(eHTMLTag_html);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
 
-    if (NS_ERROR_HTMLPARSER_INTERRUPTED == mSink->DidProcessAToken()) {
-      // The content sink has requested that DTD interrupt processing tokens
-      // We need to make sure that an interruption does not override
-      // a request to block the parser.
-      if (NS_SUCCEEDED(result)) {
-        result = NS_ERROR_HTMLPARSER_INTERRUPTED;
-        break;
-      }
-    }
-  }
-
-  mTokenizer = oldTokenizer;
-  return result;
-}
-
-nsresult
-CNavDTD::BuildNeglectedTarget(eHTMLTags aTarget,
-                              eHTMLTokenTypes aType)
-{ 
-  NS_ASSERTION(mTokenizer, "tokenizer is null! unable to build target.");
-  NS_ASSERTION(mTokenAllocator, "unable to create tokens without an allocator.");
-  if (!mTokenizer || !mTokenAllocator) {
-    return NS_OK;
-  }
-
-  CToken* target = mTokenAllocator->CreateTokenOfType(aType, aTarget);
-  NS_ENSURE_TRUE(target, NS_ERROR_OUT_OF_MEMORY);
-  mTokenizer->PushTokenFront(target);
-  // Also, BuildModel
-  // doesn't seem to care about the charset, and at this point we have no idea
-  // what the charset was, so 0 can and must suffice.
-  return BuildModel(mTokenizer, mCountLines, 0);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 CNavDTD::DidBuildModel(nsresult anErrorCode)
 {
-  nsresult result = NS_OK;
-
-  if (mSink) {
-    if (NS_OK == anErrorCode) {
-      if (!(mFlags & NS_DTD_FLAG_HAS_MAIN_CONTAINER)) {
-        // This document is not a frameset document, however, it did not contain
-        // a body tag either. So, make one!. Note: Body tag is optional per spec..
-        // Also note: We ignore the return value of BuildNeglectedTarget, we
-        // can't reasonably respond to errors (or requests to block) at this
-        // point in the parsing process.
-        BuildNeglectedTarget(eHTMLTag_body, eToken_start);
-      }
-      if (mFlags & NS_DTD_FLAG_MISPLACED_CONTENT) {
-        // Looks like the misplaced contents are not processed yet.
-        // Here is our last chance to handle the misplaced content.
-
-        // Keep track of the top index.
-        int32_t topIndex = mBodyContext->mContextTopIndex;
-        
-        // Loop until we've really consumed all of our misplaced content.
-        do {
-          mFlags &= ~NS_DTD_FLAG_MISPLACED_CONTENT; 
-
-          // mContextTopIndex refers to the misplaced content's legal parent index.
-          result = HandleSavedTokens(mBodyContext->mContextTopIndex);
-          if (NS_FAILED(result)) {
-            NS_ERROR("Bug in the DTD");
-            break;
-          }
-
-          // If we start handling misplaced content while handling misplaced
-          // content, mContextTopIndex gets modified. However, this new index
-          // necessarily points to the middle of a closed tag (since we close
-          // new tags after handling the misplaced content). So we restore the
-          // insertion point after every iteration.
-          mBodyContext->mContextTopIndex = topIndex;
-        } while (mFlags & NS_DTD_FLAG_MISPLACED_CONTENT);
-
-        mBodyContext->mContextTopIndex = -1; 
-      }
-
-      // Now let's disable style handling to save time when closing remaining
-      // stack members.
-      mFlags &= ~NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE;
-      while (mBodyContext->GetCount() > 0) { 
-        result = CloseContainersTo(mBodyContext->Last(), false);
-        NS_ENSURE_SUCCESS(result, result);
-      } 
-    } else {
-      // If you're here, then an error occurred, but we still have nodes on the stack.
-      // At a minimum, we should grab the nodes and recycle them.
-      // Just to be correct, we'll also recycle the nodes.
-      while (mBodyContext->GetCount() > 0) { 
-        nsEntryStack* theChildStyles = 0;
-        nsCParserNode* theNode = mBodyContext->Pop(theChildStyles);
-        IF_DELETE(theChildStyles, &mNodeAllocator);
-        IF_FREE(theNode, &mNodeAllocator);
-      } 
-    }
-
-    // Now make sure the misplaced content list is empty,
-    // by forcefully recycling any tokens we might find there.
-    CToken* theToken = 0;
-    while ((theToken = (CToken*)mMisplacedContent.Pop())) {
-      IF_FREE(theToken, mTokenAllocator);
-    }
-  }
-
-  return result;
+  return NS_OK;
 }
 
-NS_IMETHODIMP_(void) 
-CNavDTD::Terminate() 
-{ 
-  mFlags |= NS_DTD_FLAG_STOP_PARSING; 
+NS_IMETHODIMP_(void)
+CNavDTD::Terminate()
+{
 }
 
 
 NS_IMETHODIMP_(int32_t) 
 CNavDTD::GetType() 
 { 
   return NS_IPARSER_FLAG_HTML; 
 }
 
 NS_IMETHODIMP_(nsDTDMode)
 CNavDTD::GetMode() const
 {
-  return mDTDMode;
-}
-
-/**
- * Text and some tags require a body when they're added, this function returns
- * true for those tags.
- *
- * @param aToken The current token that we care about.
- * @param aTokenizer A tokenizer that we can get the tags attributes off of.
- * @return true if aToken does indeed force the body to open.
- */
-static bool
-DoesRequireBody(CToken* aToken, nsITokenizer* aTokenizer)
-{
-  bool result = false;
-
-  if (aToken) {
-    eHTMLTags theTag = (eHTMLTags)aToken->GetTypeID();
-    if (gHTMLElements[theTag].HasSpecialProperty(kRequiresBody)) {
-      if (theTag == eHTMLTag_input) {
-        // IE & Nav4x opens up a body for type=text - Bug 66985
-        // XXXbz but we don't want to open one for <input> with no
-        // type attribute?  That's pretty whack.
-        int32_t ac = aToken->GetAttributeCount();
-        for(int32_t i = 0; i < ac; ++i) {
-          CAttributeToken* attr = static_cast<CAttributeToken*>
-                                             (aTokenizer->GetTokenAt(i));
-          const nsSubstring& name = attr->GetKey();
-          const nsAString& value = attr->GetValue();
-          // XXXbz note that this stupid case-sensitive comparison is
-          // actually depended on by sites...
-          if ((name.EqualsLiteral("type") || 
-               name.EqualsLiteral("TYPE"))    
-              && 
-              !(value.EqualsLiteral("hidden") || 
-              value.EqualsLiteral("HIDDEN"))) {
-            result = true; 
-            break;
-          }
-        }
-      } else {
-        result = true;
-      }
-    }
-  }
- 
-  return result;
+  return eDTDMode_quirks;
 }
 
-static bool
-ValueIsHidden(const nsAString& aValue)
-{
-  // Having to deal with whitespace here sucks, but we have to match
-  // what the content sink does.
-  nsAutoString str(aValue);
-  str.Trim("\n\r\t\b");
-  return str.LowerCaseEqualsLiteral("hidden");
-}
-
-// Check whether aToken corresponds to a <input type="hidden"> tag.  The token
-// must be a start tag token for an <input>.  This must be called at a point
-// when all the attributes for the input are still in the tokenizer.
-static bool
-IsHiddenInput(CToken* aToken, nsITokenizer* aTokenizer)
+NS_IMETHODIMP_(bool)
+CNavDTD::CanContain(int32_t aParent,int32_t aChild) const
 {
-  NS_PRECONDITION(eHTMLTokenTypes(aToken->GetTokenType()) == eToken_start,
-                  "Must be start token");
-  NS_PRECONDITION(eHTMLTags(aToken->GetTypeID()) == eHTMLTag_input,
-                  "Must be <input> tag");
-  
-  int32_t ac = aToken->GetAttributeCount();
-  NS_ASSERTION(ac <= aTokenizer->GetCount(),
-               "Not enough tokens in the tokenizer");
-  // But we don't really trust ourselves to get that right
-  ac = std::min(ac, aTokenizer->GetCount());
-  
-  for (int32_t i = 0; i < ac; ++i) {
-    NS_ASSERTION(eHTMLTokenTypes(aTokenizer->GetTokenAt(i)->GetTokenType()) ==
-                   eToken_attribute, "Unexpected token type");
-    // Again, we're not sure we actually manage to guarantee that
-    if (eHTMLTokenTypes(aTokenizer->GetTokenAt(i)->GetTokenType()) !=
-        eToken_attribute) {
-      break;
-    }
-    
-    CAttributeToken* attrToken =
-      static_cast<CAttributeToken*>(aTokenizer->GetTokenAt(i));
-    if (!attrToken->GetKey().LowerCaseEqualsLiteral("type")) {
-      continue;
-    }
-
-    return ValueIsHidden(attrToken->GetValue());
-  }
-
-  return false;    
-}
-
-/**
- * Returns whether or not there is a tag of type aType open on aContext.
- */
-static bool
-HasOpenTagOfType(int32_t aType, const nsDTDContext& aContext)
-{
-  int32_t count = aContext.GetCount();
-
-  while (--count >= 0) {
-    if (gHTMLElements[aContext.TagAt(count)].IsMemberOf(aType)) {
-      return true;
-    }
-  }
-
+  MOZ_CRASH("nobody calls this");
   return false;
 }
 
-nsresult
-CNavDTD::HandleToken(CToken* aToken)
-{
-  if (!aToken) {
-    return NS_OK;
-  }
-
-  nsresult        result   = NS_OK;
-  CHTMLToken*     theToken = static_cast<CHTMLToken*>(aToken);
-  eHTMLTokenTypes theType  = eHTMLTokenTypes(theToken->GetTokenType());
-  eHTMLTags       theTag   = (eHTMLTags)theToken->GetTypeID();
-
-  aToken->SetLineNumber(mLineNumber);
-
-  if (mCountLines) {
-    mLineNumber += aToken->GetNewlineCount();
-  }
-
-  if (mFlags & NS_DTD_FLAG_MISPLACED_CONTENT) {
-    // Included TD & TH to fix Bug# 20797
-    static eHTMLTags gLegalElements[] = {
-      eHTMLTag_table, eHTMLTag_thead, eHTMLTag_tbody,
-      eHTMLTag_tr, eHTMLTag_td, eHTMLTag_th, eHTMLTag_tfoot
-    };
-    // Don't even try processing misplaced tokens if we're already
-    // handling misplaced content. See bug 269095
-    if (mFlags & NS_DTD_FLAG_IN_MISPLACED_CONTENT) {
-      PushIntoMisplacedStack(theToken);
-      return NS_OK;
-    }
-
-    eHTMLTags theParentTag = mBodyContext->Last();
-    if (FindTagInSet(theTag, gLegalElements,
-                     ArrayLength(gLegalElements)) ||
-        (gHTMLElements[theParentTag].CanContain(theTag, mDTDMode) &&
-         // Here's a problem.  If theTag is legal in here, we don't move it
-         // out.  So if we're moving stuff out of here, the parent of theTag
-         // gets closed at this point.  But some things are legal
-         // _everywhere_ and hence would effectively close out misplaced
-         // content in tables.  This is undesirable, so treat them as
-         // illegal here so they'll be shipped out with their parents and
-         // siblings.  See bug 40855 for an explanation (that bug was for
-         // comments, but the same issues arise with whitespace, newlines,
-         // noscript, etc).  Script is special, though.  Shipping it out
-         // breaks document.write stuff.  See bug 243064.
-         (!gHTMLElements[theTag].HasSpecialProperty(kLegalOpen) ||
-          theTag == eHTMLTag_script)) ||
-        (theTag == eHTMLTag_input && theType == eToken_start &&
-         FindTagInSet(theParentTag, gLegalElements,
-                      ArrayLength(gLegalElements)) &&
-         IsHiddenInput(theToken, mTokenizer))) {
-      // Reset the state since all the misplaced tokens are about to get
-      // handled.
-      mFlags &= ~NS_DTD_FLAG_MISPLACED_CONTENT;
-
-      result = HandleSavedTokens(mBodyContext->mContextTopIndex);
-      NS_ENSURE_SUCCESS(result, result);
-
-      mBodyContext->mContextTopIndex = -1;
-    } else {
-      PushIntoMisplacedStack(theToken);
-      return result;
-    }
-  }
-
-  /*
-   * This section of code is used to "move" misplaced content from one location
-   * in our document model to another. (Consider what would happen if we found a
-   * <P> tag in the head.) To move content, we throw it onto the
-   * misplacedcontent deque until we can deal with it.
-   */
-  switch(theTag) {
-    case eHTMLTag_html:
-    case eHTMLTag_noframes:
-    case eHTMLTag_script:
-    case eHTMLTag_doctypeDecl:
-    case eHTMLTag_instruction:
-      break;
-
-    default:
-      if (!gHTMLElements[eHTMLTag_html].SectionContains(theTag, false)) {
-        if (!(mFlags & (NS_DTD_FLAG_HAS_MAIN_CONTAINER |
-                        NS_DTD_FLAG_ALTERNATE_CONTENT))) {
-          // For bug examples from this code, see bugs: 18928, 20989.
-          // At this point we know the body/frameset aren't open.
-          // If the child belongs in the head, then handle it (which may open
-          // the head); otherwise, push it onto the misplaced stack.
-
-          bool isExclusive = false;
-          bool theChildBelongsInHead =
-            gHTMLElements[eHTMLTag_head].IsChildOfHead(theTag, isExclusive);
-          if (theChildBelongsInHead &&
-              !isExclusive &&
-              !gHTMLElements[theTag].HasSpecialProperty(kPreferHead)) {
-            if (mMisplacedContent.GetSize() == 0 &&
-                (!gHTMLElements[theTag].HasSpecialProperty(kPreferBody) ||
-                 (mFlags & NS_DTD_FLAG_HAS_EXPLICIT_HEAD))) {
-              // This tag can either be in the body or the head. Since
-              // there is no indication that the body should be open,
-              // put this token in the head.
-              break;
-            }
-
-            // Otherwise, we have received some indication that the body is
-            // "open", so push this token onto the misplaced content stack.
-            theChildBelongsInHead = false;
-          }
-
-          if (!theChildBelongsInHead) {
-            eHTMLTags top = mBodyContext->Last();
-            NS_ASSERTION(top != eHTMLTag_userdefined,
-                         "Userdefined tags should act as leaves in the head");
-            if (top != eHTMLTag_html && top != eHTMLTag_head &&
-                gHTMLElements[top].CanContain(theTag, mDTDMode)) {
-              // Some tags (such as <object> and <script>) are opened in the
-              // head and allow other non-head content to be children.
-              // Note: Userdefined tags in the head act like leaves.
-              break;
-            }
-
-            // If you're here then we found a child of the body that was out of
-            // place.  We're going to move it to the body by storing it
-            // temporarily on the misplaced stack.  However, in quirks mode, a
-            // few tags request, ambiguosly, for a BODY. - Bugs 18928, 24204.-
-            PushIntoMisplacedStack(aToken);
-
-            if (IsAlternateTag(theTag)) {
-              // These tags' contents are consumed as CDATA. If we simply
-              // pushed them on the misplaced content stack, the CDATA
-              // contents would force us to open a body, which could be
-              // wrong. So we collect the whole tag as misplaced in one
-              // gulp. Note that the tokenizer guarantees that there will
-              // be an end tag.
-              CToken *current = aToken;
-              while (current->GetTokenType() != eToken_end ||
-                     current->GetTypeID() != theTag) {
-                current = static_cast<CToken *>(mTokenizer->PopToken());
-                NS_ASSERTION(current, "The tokenizer is not creating good "
-                                      "alternate tags");
-                PushIntoMisplacedStack(current);
-              }
-
-              // XXX Add code to also collect incorrect attributes on the
-              // end tag.
-            }
-
-            if (DoesRequireBody(aToken, mTokenizer)) {
-              CToken* theBodyToken =
-                mTokenAllocator->CreateTokenOfType(eToken_start,
-                                                   eHTMLTag_body,
-                                                   NS_LITERAL_STRING("body"));
-              result = HandleToken(theBodyToken);
-            }
-            return result;
-          }
-        }
-      }
-  }
-
-  if (theToken) {
-    switch (theType) {
-      case eToken_text:
-      case eToken_start:
-      case eToken_whitespace:
-      case eToken_newline:
-        result = HandleStartToken(theToken);
-        break;
-
-      case eToken_end:
-        result = HandleEndToken(theToken);
-        break;
-
-      case eToken_cdatasection:
-      case eToken_comment:
-      case eToken_markupDecl:
-        result = HandleCommentToken(theToken);
-        break;
-
-      case eToken_entity:
-        result = HandleEntityToken(theToken);
-        break;
-
-      case eToken_attribute:
-        result = HandleAttributeToken(theToken);
-        break;
-
-      case eToken_instruction:
-        result = HandleProcessingInstructionToken(theToken);
-        break;
-
-      case eToken_doctypeDecl:
-        result = HandleDocTypeDeclToken(theToken);
-        break;
-
-      default:
-        break;
-    }
-
-    IF_FREE(theToken, mTokenAllocator);
-    if (result == NS_ERROR_HTMLPARSER_STOPPARSING) {
-      mFlags |= NS_DTD_FLAG_STOP_PARSING;
-    } else if (NS_FAILED(result) && result != NS_ERROR_HTMLPARSER_BLOCK) {
-      result = NS_OK;
-    }
-  }
-
-  return result;
-}
-
-nsresult
-CNavDTD::DidHandleStartTag(nsIParserNode& aNode, eHTMLTags aChildTag)
-{
-  nsresult result = NS_OK;
-
-  switch (aChildTag) {
-    case eHTMLTag_pre:
-    case eHTMLTag_listing:
-      {
-        // Skip the 1st newline inside PRE and LISTING unless this is a
-        // plain text doc (for which we pushed a PRE in CNavDTD::BuildModel).
-
-        // XXX This code is incorrect in the face of misplaced <pre> and
-        // <listing> tags (as direct children of <table>).
-        CToken* theNextToken = mTokenizer->PeekToken();
-        if (ePlainText != mDocType && theNextToken) {
-          eHTMLTokenTypes theType = eHTMLTokenTypes(theNextToken->GetTokenType());
-          if (eToken_newline == theType) {
-            if (mCountLines) {
-              mLineNumber += theNextToken->GetNewlineCount();
-            }
-            theNextToken = mTokenizer->PopToken();
-            IF_FREE(theNextToken, mTokenAllocator); // fix for Bug 29379
-          }
-        }
-      }
-      break;
-
-    default:
-      break;
-  }
-
-  return result;
-}
-
-int32_t
-CNavDTD::LastOf(eHTMLTags aTagSet[], int32_t aCount) const
-{
-  for (int32_t theIndex = mBodyContext->GetCount() - 1; theIndex >= 0;
-       --theIndex) {
-    if (FindTagInSet((*mBodyContext)[theIndex], aTagSet, aCount)) {
-      return theIndex;
-    }
-  }
-
-  return kNotFound;
-}
-
-static bool
-CanBeContained(eHTMLTags aChildTag, nsDTDContext& aContext)
-{
-  /* #    Interesting test cases:       Result:
-   * 1.   <UL><LI>..<B>..<LI>           inner <LI> closes outer <LI>
-   * 2.   <CENTER><DL><DT><A><CENTER>   allow nested <CENTER>
-   * 3.   <TABLE><TR><TD><TABLE>...     allow nested <TABLE>
-   * 4.   <FRAMESET> ... <FRAMESET>
-   */
-  bool    result = true;
-  int32_t theCount = aContext.GetCount();
-
-  if (0 < theCount) {
-    const TagList* theRootTags = gHTMLElements[aChildTag].GetRootTags();
-    const TagList* theSpecialParents =
-      gHTMLElements[aChildTag].GetSpecialParents();
-
-    if (theRootTags) {
-      int32_t theRootIndex = LastOf(aContext, *theRootTags);
-      int32_t theSPIndex = theSpecialParents
-                           ? LastOf(aContext, *theSpecialParents)
-                           : kNotFound;
-      int32_t theChildIndex =
-        nsHTMLElement::GetIndexOfChildOrSynonym(aContext, aChildTag);
-      int32_t theTargetIndex = (theRootIndex > theSPIndex)
-                               ? theRootIndex
-                               : theSPIndex;
-
-      if (theTargetIndex == theCount-1 ||
-          (theTargetIndex == theChildIndex &&
-           gHTMLElements[aChildTag].CanContainSelf())) {
-        result = true;
-      } else {
-        result = false;
-
-        static eHTMLTags gTableElements[] = { eHTMLTag_td, eHTMLTag_th };
-
-        int32_t theIndex = theCount - 1;
-        while (theChildIndex < theIndex) {
-          eHTMLTags theParentTag = aContext.TagAt(theIndex--);
-          if (gHTMLElements[theParentTag].IsMemberOf(kBlockEntity)  ||
-              gHTMLElements[theParentTag].IsMemberOf(kHeading)      ||
-              gHTMLElements[theParentTag].IsMemberOf(kPreformatted) ||
-              gHTMLElements[theParentTag].IsMemberOf(kFormControl)  ||  //fixes bug 44479
-              gHTMLElements[theParentTag].IsMemberOf(kList)) {
-            if (!HasOptionalEndTag(theParentTag)) {
-              result = true;
-              break;
-            }
-          } else if (FindTagInSet(theParentTag, gTableElements,
-                                  ArrayLength(gTableElements))) {
-            // Added this to catch a case we missed; bug 57173.
-            result = true;
-            break;
-          }
-        }
-      }
-    }
-  }
-
-  return result;
-}
-
-enum eProcessRule { eNormalOp, eLetInlineContainBlock };
-
-nsresult
-CNavDTD::HandleDefaultStartToken(CToken* aToken, eHTMLTags aChildTag,
-                                 nsCParserNode *aNode)
-{
-  NS_PRECONDITION(nullptr != aToken, kNullToken);
-
-  nsresult  result = NS_OK;
-  bool    theChildIsContainer = nsHTMLElement::IsContainer(aChildTag);
-
-  // Client of parser is spefically trying to parse a fragment that
-  // may lack required context.  Suspend containment rules if so.
-  if (mParserCommand != eViewFragment) {
-    bool    theChildAgrees = true;
-    int32_t theIndex = mBodyContext->GetCount();
-    int32_t theParentContains = 0;
-
-    do {
-      eHTMLTags theParentTag = mBodyContext->TagAt(--theIndex);
-      if (theParentTag == eHTMLTag_userdefined) {
-        continue;
-      }
-
-      // Figure out whether this is a hidden input inside a
-      // table/tbody/thead/tfoot/tr
-      static eHTMLTags sTableElements[] = {
-        eHTMLTag_table, eHTMLTag_thead, eHTMLTag_tbody,
-        eHTMLTag_tr, eHTMLTag_tfoot
-      };
-
-      bool isHiddenInputInsideTableElement = false;
-      if (aChildTag == eHTMLTag_input &&
-          FindTagInSet(theParentTag, sTableElements,
-                       ArrayLength(sTableElements))) {
-        int32_t attrCount = aNode->GetAttributeCount();
-        for (int32_t attrIndex = 0; attrIndex < attrCount; ++attrIndex) {
-          const nsAString& key = aNode->GetKeyAt(attrIndex);
-          if (key.LowerCaseEqualsLiteral("type")) {
-            isHiddenInputInsideTableElement =
-              ValueIsHidden(aNode->GetValueAt(attrIndex));
-            break;
-          }
-        }
-      }
-      
-      // Precompute containment, and pass it to CanOmit()...
-      theParentContains =
-        isHiddenInputInsideTableElement || CanContain(theParentTag, aChildTag);
-      if (!isHiddenInputInsideTableElement &&
-          CanOmit(theParentTag, aChildTag, theParentContains)) {
-        HandleOmittedTag(aToken, aChildTag, theParentTag, aNode);
-        return NS_OK;
-      }
-
-      eProcessRule theRule = eNormalOp;
-
-      if (!theParentContains &&
-          (IsBlockElement(aChildTag, theParentTag) &&
-           IsInlineElement(theParentTag, theParentTag))) {
-        // Don't test for table to fix 57554.
-        if (eHTMLTag_li != aChildTag) {
-          nsCParserNode* theParentNode = mBodyContext->PeekNode();
-          if (theParentNode && theParentNode->mToken->IsWellFormed()) {
-            theRule = eLetInlineContainBlock;
-          }
-        }
-      }
-
-      switch (theRule) {
-        case eNormalOp:
-          theChildAgrees = true;
-          if (theParentContains) {
-            eHTMLTags theAncestor = gHTMLElements[aChildTag].mRequiredAncestor;
-            if (eHTMLTag_unknown != theAncestor) {
-              theChildAgrees = HasOpenContainer(theAncestor);
-            }
-
-            if (theChildAgrees && theChildIsContainer) {
-              if (theParentTag != aChildTag) {
-                // Double check the power structure
-                // Note: The bit is currently set on tags such as <A> and <LI>.
-                if (gHTMLElements[aChildTag].ShouldVerifyHierarchy()) {
-                  int32_t theChildIndex =
-                    nsHTMLElement::GetIndexOfChildOrSynonym(*mBodyContext,
-                                                            aChildTag);
-
-                  if (kNotFound < theChildIndex && theChildIndex < theIndex) {
-                    /*
-                     * 1  Here's a tricky case from bug 22596:  <h5><li><h5>
-                     *    How do we know that the 2nd <h5> should close the <LI>
-                     *    rather than nest inside the <LI>? (Afterall, the <h5>
-                     *    is a legal child of the <LI>).
-                     *
-                     *    The way you know is that there is no root between the
-                     *    two, so the <h5> binds more tightly to the 1st <h5>
-                     *    than to the <LI>.
-                     *
-                     * 2  Also, bug 6148 shows this case: <SPAN><DIV><SPAN>
-                     *    From this case we learned not to execute this logic if
-                     *    the parent is a block.
-                     *
-                     * 3  Fix for 26583:
-                     *    <A href=foo.html><B>foo<A href-bar.html>bar</A></B></A>
-                     *    In the above example clicking on "foo" or "bar" should
-                     *    link to foo.html or bar.html respectively. That is,
-                     *    the inner <A> should be informed about the presence of
-                     *    an open <A> above <B>..so that the inner <A> can close
-                     *    out the outer <A>. The following code does it for us.
-                     *
-                     * 4  Fix for 27865 [ similer to 22596 ]. Ex:
-                     *    <DL><DD><LI>one<DD><LI>two
-                     */
-                    theChildAgrees = CanBeContained(aChildTag, *mBodyContext);
-                  }
-                }
-              }
-            }
-          }
-
-          if (!(theParentContains && theChildAgrees)) {
-            if (!CanPropagate(theParentTag, aChildTag, theParentContains)) {
-              if (theChildIsContainer || !theParentContains) {
-                if (!theChildAgrees &&
-                    !gHTMLElements[aChildTag].CanAutoCloseTag(*mBodyContext,
-                                                              theIndex,
-                                                              aChildTag)) {
-                  // Closing the tags above might cause non-compatible results.
-                  // Ex. <TABLE><TR><TD><TBODY>Text</TD></TR></TABLE>.
-                  // In the example above <TBODY> is badly misplaced, but
-                  // we should not attempt to close the tags above it,
-                  // The safest thing to do is to discard this tag.
-                  // XXX We get the above example wrong anyway because of
-                  // CanBeContained.
-                  return result;
-                } else if (mBodyContext->mContextTopIndex > 0 &&
-                           theIndex <= mBodyContext->mContextTopIndex) {
-                  // Looks like the parent tag does not want to contain the
-                  // current tag ( aChildTag ).  However, we have to force the
-                  // containment, when handling misplaced content, to avoid data
-                  // loss.  Ref. bug 138577.
-                  theParentContains = true;
-                } else {
-                  CloseContainersTo(theIndex, aChildTag, true);
-                }
-              } else {
-                break;
-              }
-            } else {
-              CreateContextStackFor(theParentTag, aChildTag);
-              theIndex = mBodyContext->GetCount();
-            }
-          }
-          break;
-
-        case eLetInlineContainBlock:
-          // Break out of this loop and open the block.
-          theParentContains = theChildAgrees = true;
-          break;
-
-        default:
-          NS_NOTREACHED("Invalid rule detected");
-      }
-    } while (!(theParentContains && theChildAgrees));
-  }
-
-  if (theChildIsContainer) {
-    result = OpenContainer(aNode, aChildTag);
-  } else {
-    result = AddLeaf(aNode);
-  }
-
-  return result;
-}
-
-nsresult
-CNavDTD::WillHandleStartTag(CToken* aToken, eHTMLTags aTag,
-                            nsIParserNode& aNode)
-{
-  nsresult result = NS_OK;
-
-  int32_t stackDepth = mBodyContext->GetCount();
-  if (stackDepth >= FONTSTYLE_IGNORE_DEPTH &&
-      gHTMLElements[aTag].IsMemberOf(kFontStyle)) {
-    // Prevent bug 58917 by tossing the new kFontStyle start tag
-    return kHierarchyTooDeep;
-  }
-
-  if (stackDepth >= PHRASE_IGNORE_DEPTH &&
-      gHTMLElements[aTag].IsMemberOf(kPhrase)) {
-    // Prevent bug 58917 by tossing the new kPhrase start tag
-    return kHierarchyTooDeep;
-  }
-
-  /*
-   * Now a little code to deal with bug #49687 (crash when layout stack gets
-   * too deep) I've also opened this up to any container (not just inlines):
-   * re bug 55095 Improved to handle bug 55980 (infinite loop caused when
-   * DEPTH is exceeded and </P> is encountered by itself (<P>) is continuously
-   * produced.
-   */
-  if (stackDepth > MAX_REFLOW_DEPTH) {
-    if (nsHTMLElement::IsContainer(aTag) &&
-        !gHTMLElements[aTag].HasSpecialProperty(kHandleStrayTag)) {
-      // Ref. bug 98261,49678,55095,55980
-      // Instead of throwing away the current tag close it's parent
-      // such that the stack level does not go beyond the max_reflow_depth.
-      // This would allow leaf tags, that follow the current tag, to find
-      // the correct node.
-      while (stackDepth != MAX_REFLOW_DEPTH && NS_SUCCEEDED(result)) {
-        result = CloseContainersTo(mBodyContext->Last(), false);
-        --stackDepth;
-      }
-    }
-  }
-
-  return result;
-}
-
-static void
-PushMisplacedAttributes(nsIParserNode& aNode, nsDeque& aDeque)
-{
-  nsCParserNode& theAttrNode = static_cast<nsCParserNode &>(aNode);
-
-  for (int32_t count = aNode.GetAttributeCount(); count > 0; --count) {
-    CToken* theAttrToken = theAttrNode.PopAttributeTokenFront();
-    if (theAttrToken) {
-      theAttrToken->SetNewlineCount(0);
-      aDeque.Push(theAttrToken);
-    }
-  }
-}
-
-void
-CNavDTD::HandleOmittedTag(CToken* aToken, eHTMLTags aChildTag,
-                          eHTMLTags aParent, nsIParserNode* aNode)
-{
-  NS_PRECONDITION(mBodyContext != nullptr, "need a context to work with");
-
-  // The trick here is to see if the parent can contain the child, but prefers
-  // not to. Only if the parent CANNOT contain the child should we look to see
-  // if it's potentially a child of another section. If it is, the cache it for
-  // later.
-  int32_t theTagCount = mBodyContext->GetCount();
-  bool pushToken = false;
-
-  if (gHTMLElements[aParent].HasSpecialProperty(kBadContentWatch) &&
-      !nsHTMLElement::IsWhitespaceTag(aChildTag)) {
-    eHTMLTags theTag = eHTMLTag_unknown;
-
-    // Don't bother saving misplaced stuff in the head. This can happen in
-    // cases like |<head><noscript><table>foo|. See bug 401169.
-    if (mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD) {
-      NS_ASSERTION(!(mFlags & NS_DTD_FLAG_HAS_MAIN_CONTAINER),
-                   "Bad state");
-      return;
-    }
-
-    // Determine the insertion point
-    while (theTagCount > 0) {
-      theTag = mBodyContext->TagAt(--theTagCount);
-      if (!gHTMLElements[theTag].HasSpecialProperty(kBadContentWatch)) {
-        // This is our insertion point.
-        mBodyContext->mContextTopIndex = theTagCount;
-        break;
-      }
-    }
-
-    if (mBodyContext->mContextTopIndex > -1) {
-      pushToken = true;
-
-      // Remember that we've stashed some misplaced content.
-      mFlags |= NS_DTD_FLAG_MISPLACED_CONTENT;
-    }
-  }
-
-  if (aChildTag != aParent &&
-      gHTMLElements[aParent].HasSpecialProperty(kSaveMisplaced)) {
-    NS_ASSERTION(!pushToken, "A strange element has both kBadContentWatch "
-                             "and kSaveMisplaced");
-    pushToken = true;
-  }
-
-  if (pushToken) {
-    // Hold on to this token for later use. Ref Bug. 53695
-    IF_HOLD(aToken);
-    PushIntoMisplacedStack(aToken);
-
-    // If the token is attributed then save those attributes too.
-    PushMisplacedAttributes(*aNode, mMisplacedContent);
-  }
-}
-
-/**
- *  This method gets called when a kegen token is found.
- *   
- *  @update  harishd 05/02/00
- *  @param   aNode -- CParserNode representing keygen
- *  @return  NS_OK if all went well; ERROR if error occurred
- */
-nsresult
-CNavDTD::HandleKeyGen(nsIParserNode* aNode)
-{
-  nsresult result = NS_OK;
-
-  nsCOMPtr<nsIFormProcessor> theFormProcessor =
-           do_GetService(kFormProcessorCID, &result);
-  if (NS_FAILED(result)) {
-    return result;
-  }
-
-  int32_t      theAttrCount = aNode->GetAttributeCount();
-  nsTArray<nsString> theContent;
-  nsAutoString theAttribute;
-  nsAutoString theFormType;
-  CToken*      theToken = nullptr;
-
-  theFormType.AssignLiteral("select");
-
-  result = theFormProcessor->ProvideContent(theFormType, theContent,
-                                            theAttribute);
-  if (NS_FAILED(result)) {
-    return result;
-  }
-  int32_t   theIndex = 0;
-
-  // Populate the tokenizer with the fabricated elements in the reverse
-  // order such that <SELECT> is on the top fo the tokenizer followed by
-  // <OPTION>s and </SELECT>.
-  theToken = mTokenAllocator->CreateTokenOfType(eToken_end,
-                                                eHTMLTag_select);
-  NS_ENSURE_TRUE(theToken, NS_ERROR_OUT_OF_MEMORY);
-  mTokenizer->PushTokenFront(theToken);
-
-  for (theIndex = theContent.Length()-1; theIndex > -1; --theIndex) {
-    theToken = mTokenAllocator->CreateTokenOfType(eToken_text,
-                                                  eHTMLTag_text,
-                                                  theContent[theIndex]);
-    NS_ENSURE_TRUE(theToken, NS_ERROR_OUT_OF_MEMORY);
-    mTokenizer->PushTokenFront(theToken);
-
-    theToken = mTokenAllocator->CreateTokenOfType(eToken_start,
-                                                  eHTMLTag_option);
-    NS_ENSURE_TRUE(theToken, NS_ERROR_OUT_OF_MEMORY);
-    mTokenizer->PushTokenFront(theToken);
-  }
-
-  // The attribute ( provided by the form processor ) should be a part
-  // of the SELECT.  Placing the attribute token on the tokenizer to get
-  // picked up by the SELECT.
-  theToken = mTokenAllocator->CreateTokenOfType(eToken_attribute,
-                                                eHTMLTag_unknown,
-                                                theAttribute);
-  NS_ENSURE_TRUE(theToken, NS_ERROR_OUT_OF_MEMORY);
-
-  ((CAttributeToken*)theToken)->SetKey(NS_LITERAL_STRING("_moz-type"));
-  mTokenizer->PushTokenFront(theToken);
-
-  // Pop out NAME and CHALLENGE attributes ( from the keygen NODE ) and
-  // place it in the tokenizer such that the attribtues get sucked into
-  // SELECT node.
-  for (theIndex = theAttrCount; theIndex > 0; --theIndex) {
-    mTokenizer->PushTokenFront(((nsCParserNode*)aNode)->PopAttributeToken());
-  }
-
-  theToken = mTokenAllocator->CreateTokenOfType(eToken_start,
-                                                eHTMLTag_select);
-  NS_ENSURE_TRUE(theToken, NS_ERROR_OUT_OF_MEMORY);
-
-  // Increment the count because of the additional attribute from the form processor.
-  theToken->SetAttributeCount(theAttrCount + 1);
-  mTokenizer->PushTokenFront(theToken);
-
-  return result;
-}
-
-bool
-CNavDTD::IsAlternateTag(eHTMLTags aTag)
-{
-  switch (aTag) {
-    case eHTMLTag_noembed:
-      return true;
-
-    case eHTMLTag_noscript:
-      return (mFlags & NS_IPARSER_FLAG_SCRIPT_ENABLED) != 0;
-
-    case eHTMLTag_iframe:
-    case eHTMLTag_noframes:
-      return (mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED) != 0;
-
-    default:
-      return false;
-  }
-}
-
-nsresult
-CNavDTD::HandleStartToken(CToken* aToken)
-{
-  NS_PRECONDITION(nullptr != aToken, kNullToken);
-
-  nsCParserNode* theNode = mNodeAllocator.CreateNode(aToken, mTokenAllocator);
-  NS_ENSURE_TRUE(theNode, NS_ERROR_OUT_OF_MEMORY);
-
-  eHTMLTags     theChildTag = (eHTMLTags)aToken->GetTypeID();
-  int16_t       attrCount   = aToken->GetAttributeCount();
-  eHTMLTags     theParent   = mBodyContext->Last();
-  nsresult      result      = NS_OK;
-
-  if (attrCount > 0) {
-    result = CollectAttributes(theNode, theChildTag, attrCount);
-  }
-
-  if (NS_OK == result) {
-    result = WillHandleStartTag(aToken, theChildTag, *theNode);
-    if (NS_OK == result) {
-      bool isTokenHandled = false;
-      bool theHeadIsParent = false;
-
-      if (nsHTMLElement::IsSectionTag(theChildTag)) {
-        switch (theChildTag) {
-          case eHTMLTag_html:
-            if (mBodyContext->GetCount() > 0) {
-              result = OpenContainer(theNode, theChildTag);
-              isTokenHandled = true;
-            }
-            break;
-
-          case eHTMLTag_body:
-            if (mFlags & NS_DTD_FLAG_HAS_OPEN_BODY) {
-              result = OpenContainer(theNode, theChildTag);
-              isTokenHandled=true;
-            }
-            break;
-
-          case eHTMLTag_head:
-            mFlags |= NS_DTD_FLAG_HAS_EXPLICIT_HEAD;
-
-            if (mFlags & NS_DTD_FLAG_HAS_MAIN_CONTAINER) {
-              HandleOmittedTag(aToken, theChildTag, theParent, theNode);
-              isTokenHandled = true;
-            }
-            break;
-
-          default:
-            break;
-        }
-      }
-
-      bool isExclusive = false;
-      theHeadIsParent = nsHTMLElement::IsChildOfHead(theChildTag, isExclusive);
-
-      switch (theChildTag) {
-        case eHTMLTag_area:
-          if (!mOpenMapCount) {
-            isTokenHandled = true;
-          }
-
-          if (mOpenMapCount > 0 && mSink) {
-            result = mSink->AddLeaf(*theNode);
-            isTokenHandled = true;
-          }
-	  
-          break;
-
-        case eHTMLTag_image:
-          aToken->SetTypeID(theChildTag = eHTMLTag_img);
-          break;
-
-        case eHTMLTag_keygen:
-          result = HandleKeyGen(theNode);
-          isTokenHandled = true;
-          break;
-
-        case eHTMLTag_script:
-          // Script isn't really exclusively in the head. However, we treat it
-          // as such to make sure that we don't pull scripts outside the head
-          // into the body.
-          // XXX Where does the script go in a frameset document?
-          isExclusive = !(mFlags & NS_DTD_FLAG_HAD_BODY);
-          break;
-
-        default:;
-      }
-
-      if (!isTokenHandled) {
-        bool prefersBody =
-          gHTMLElements[theChildTag].HasSpecialProperty(kPreferBody);
-
-        // If this tag prefers to be in the head (when neither the head nor the
-        // body have been explicitly opened) then check that we haven't seen the
-        // body (true until the <body> tag has really been seen). Otherwise,
-        // check if the head has been explicitly opened. See bug 307122.
-        theHeadIsParent = theHeadIsParent &&
-          (isExclusive ||
-           (prefersBody
-            ? (mFlags & NS_DTD_FLAG_HAS_EXPLICIT_HEAD) &&
-              (mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD)
-            : !(mFlags & NS_DTD_FLAG_HAS_MAIN_CONTAINER)));
-
-        if (theHeadIsParent) {
-          // These tokens prefer to be in the head.
-          result = AddHeadContent(theNode);
-        } else {
-          result = HandleDefaultStartToken(aToken, theChildTag, theNode);
-        }
-      }
-
-      // Now do any post processing necessary on the tag...
-      if (NS_OK == result) {
-        DidHandleStartTag(*theNode, theChildTag);
-      }
-    }
-  }
-
-  if (kHierarchyTooDeep == result) {
-    // Reset this error to ok; all that happens here is that given inline tag
-    // gets dropped because the stack is too deep. Don't terminate parsing.
-    result = NS_OK;
-  }
-
-  IF_FREE(theNode, &mNodeAllocator);
-  return result;
-}
-
-/**
- *  Call this to see if you have a closeable peer on the stack that
- *  is ABOVE one of its root tags.
- *
- *  @update  gess 4/11/99
- *  @param   aRootTagList -- list of root tags for aTag
- *  @param   aTag -- tag to test for containership
- *  @return  true if given tag can contain other tags
- */
-static bool
-HasCloseablePeerAboveRoot(const TagList& aRootTagList, nsDTDContext& aContext,
-                          eHTMLTags aTag, bool anEndTag)
-{
-  int32_t  theRootIndex = LastOf(aContext, aRootTagList);
-  const TagList* theCloseTags = anEndTag
-                                ? gHTMLElements[aTag].GetAutoCloseEndTags()
-                                : gHTMLElements[aTag].GetAutoCloseStartTags();
-  int32_t theChildIndex = -1;
-
-  if (theCloseTags) {
-    theChildIndex=LastOf(aContext, *theCloseTags);
-  } else if (anEndTag || !gHTMLElements[aTag].CanContainSelf()) {
-    theChildIndex = aContext.LastOf(aTag);
-  }
-
-  // I changed this to theRootIndex<=theChildIndex so to handle this case:
-  //  <SELECT><OPTGROUP>...</OPTGROUP>
-  return theRootIndex<=theChildIndex;
-}
-
-
-/**
- *  This method is called to determine whether or not an END tag
- *  can be autoclosed. This means that based on the current
- *  context, the stack should be closed to the nearest matching
- *  tag.
- *
- *  @param   aTag -- tag enum of child to be tested
- *  @return  true if autoclosure should occur
- */
-static eHTMLTags
-FindAutoCloseTargetForEndTag(eHTMLTags aCurrentTag, nsDTDContext& aContext,
-                             nsDTDMode aMode)
-{
-  int theTopIndex = aContext.GetCount();
-  eHTMLTags thePrevTag = aContext.Last();
-
-  if (nsHTMLElement::IsContainer(aCurrentTag)) {
-    int32_t theChildIndex =
-      nsHTMLElement::GetIndexOfChildOrSynonym(aContext, aCurrentTag);
-
-    if (kNotFound < theChildIndex) {
-      if (thePrevTag == aContext[theChildIndex]) {
-        return aContext[theChildIndex];
-      }
-
-      if (nsHTMLElement::IsBlockCloser(aCurrentTag)) {
-        /*
-         * Here's the algorithm:
-         * Our here is sitting at aChildIndex. There are other tags above it
-         * on the stack. We have to try to close them out, but we may encounter
-         * one that can block us. The way to tell is by comparing each tag on
-         * the stack against our closeTag and rootTag list.
-         *
-         * For each tag above our hero on the stack, ask 3 questions:
-         * 1. Is it in the closeTag list? If so, the we can skip over it
-         * 2. Is it in the rootTag list? If so, then we're gated by it
-         * 3. Otherwise its non-specified and we simply presume we can close it.
-         */
-        const TagList* theCloseTags =
-          gHTMLElements[aCurrentTag].GetAutoCloseEndTags();
-        const TagList* theRootTags =
-          gHTMLElements[aCurrentTag].GetEndRootTags();
-
-        if (theCloseTags) {
-          // At a mininimum, this code is needed for H1..H6
-          while (theChildIndex < --theTopIndex) {
-            eHTMLTags theNextTag = aContext[theTopIndex];
-            if (!FindTagInSet(theNextTag, theCloseTags->mTags,
-                              theCloseTags->mCount) &&
-                FindTagInSet(theNextTag, theRootTags->mTags,
-                             theRootTags->mCount)) {
-              // We encountered a tag in root list so fail (we're gated).
-              return eHTMLTag_unknown;
-            }
-
-            // Otherwise, presume it's something we can simply ignore and
-            // continue searching.
-          }
-
-          eHTMLTags theTarget = aContext.TagAt(theChildIndex);
-          if (aCurrentTag != theTarget) {
-            aCurrentTag = theTarget;
-          }
-          // If you make it here, we're ungated and found a target!
-          return aCurrentTag;
-        } else if (theRootTags) {
-          // Since we didn't find any close tags, see if there is an instance of
-          // aCurrentTag above the stack from the roottag.
-          if (HasCloseablePeerAboveRoot(*theRootTags, aContext, aCurrentTag,
-                                        true)) {
-            return aCurrentTag;
-          } else {
-            return eHTMLTag_unknown;
-          }
-        }
-      } else {
-        // Ok, a much more sensible approach for non-block closers; use the tag
-        // group to determine closure: For example: %phrasal closes %phrasal,
-        // %fontstyle and %special
-        return gHTMLElements[aCurrentTag].GetCloseTargetForEndTag(aContext,
-                                                                  theChildIndex,
-                                                                  aMode);
-      }
-    }
-  }
-
-  return eHTMLTag_unknown;
-}
-
-static void
-StripWSFollowingTag(eHTMLTags aChildTag, nsITokenizer* aTokenizer,
-                    nsTokenAllocator* aTokenAllocator, int32_t* aNewlineCount)
-{
-  if (!aTokenizer || !aTokenAllocator) {
-    return;
-  }
-
-  CToken* theToken = aTokenizer->PeekToken();
-
-  int32_t newlineCount = 0;
-  while (theToken) {
-    eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType());
-
-    switch(theType) {
-      case eToken_newline:
-      case eToken_whitespace:
-        theToken = aTokenizer->PopToken();
-        newlineCount += theToken->GetNewlineCount();
-        IF_FREE(theToken, aTokenAllocator);
-
-        theToken = aTokenizer->PeekToken();
-        break;
-
-      default:
-        theToken = nullptr;
-        break;
-    }
-  }
-
-  if (aNewlineCount) {
-    *aNewlineCount += newlineCount;
-  }
-}
-
-/**
- *  This method gets called when an end token has been 
- *  encountered in the parse process. If the end tag matches
- *  the start tag on the stack, then simply close it. Otherwise,
- *  we have a erroneous state condition. This can be because we
- *  have a close tag with no prior open tag (user error) or because
- *  we screwed something up in the parse process. I'm not sure
- *  yet how to tell the difference.
- *  
- *  @param   aToken -- next (start) token to be handled
- *  @return  true if all went well; false if error occurred
- */
-nsresult
-CNavDTD::HandleEndToken(CToken* aToken)
-{
-  NS_PRECONDITION(nullptr != aToken, kNullToken);
-
-  nsresult    result = NS_OK;
-  eHTMLTags   theChildTag = (eHTMLTags)aToken->GetTypeID();
-
-  // Begin by dumping any attributes (bug 143512)
-  CollectAttributes(nullptr, theChildTag, aToken->GetAttributeCount());
-
-  switch (theChildTag) {
-    case eHTMLTag_link:
-    case eHTMLTag_meta:
-      break;
-
-    case eHTMLTag_head:
-      StripWSFollowingTag(theChildTag, mTokenizer, mTokenAllocator,
-                          !mCountLines ? nullptr : &mLineNumber);
-      if (mBodyContext->LastOf(eHTMLTag_head) != kNotFound) {
-        result = CloseContainersTo(eHTMLTag_head, false);
-      }
-      mFlags &= ~NS_DTD_FLAG_HAS_EXPLICIT_HEAD;
-      break;
-
-    case eHTMLTag_form:
-      result = CloseContainer(eHTMLTag_form, false);
-      break;
-
-    case eHTMLTag_br:
-      {
-        // This is special NAV-QUIRKS code that allows users to use </BR>, even
-        // though that isn't a legitimate tag.
-        if (eDTDMode_quirks == mDTDMode) {
-          // Use recycler and pass the token thro' HandleToken() to fix bugs
-          // like 32782.
-          CToken* theToken = mTokenAllocator->CreateTokenOfType(eToken_start,
-                                                                theChildTag);
-          result = HandleToken(theToken);
-        }
-      }
-      break;
-
-    case eHTMLTag_body:
-    case eHTMLTag_html:
-      StripWSFollowingTag(theChildTag, mTokenizer, mTokenAllocator,
-                          !mCountLines ? nullptr : &mLineNumber);
-      break;
-
-    case eHTMLTag_script:
-      // Note: we don't fall through to the default case because
-      // CloseContainersTo() has the bad habit of closing tags that are opened
-      // by document.write(). Fortunately, the tokenizer guarantees that no
-      // actual tags appear between <script> and </script> so we won't be
-      // closing the wrong tag.
-      if (mBodyContext->Last() != eHTMLTag_script) {
-        // Except if we're here, then there's probably a stray script tag.
-        NS_ASSERTION(mBodyContext->LastOf(eHTMLTag_script) == kNotFound,
-                     "Mishandling scripts in CNavDTD");
-        break;
-      }
-
-      mBodyContext->Pop();
-      result = CloseContainer(eHTMLTag_script, aToken->IsInError());
-      break;
-
-    default:
-     {
-        // Now check to see if this token should be omitted, or
-        // if it's gated from closing by the presence of another tag.
-        if (gHTMLElements[theChildTag].CanOmitEndTag()) {
-          PopStyle(theChildTag);
-        } else {
-          eHTMLTags theParentTag = mBodyContext->Last();
-
-          // First open transient styles, so that we see any autoclosed style
-          // tags.
-          if (nsHTMLElement::IsResidualStyleTag(theChildTag)) {
-            result = OpenTransientStyles(theChildTag);
-            if (NS_FAILED(result)) {
-              return result;
-            }
-          }
-
-          if (kNotFound ==
-                nsHTMLElement::GetIndexOfChildOrSynonym(*mBodyContext,
-                                                        theChildTag)) {
-            // Ref: bug 30487
-            // Make sure that we don't cross boundaries, of certain elements,
-            // to close stylistic information.
-            // <font face="helvetica"><table><tr><td></font></td></tr></table> some text...
-            // In the above ex. the orphaned FONT tag, inside TD, should cross
-            // TD boundary to close the FONT tag above TABLE.
-            static eHTMLTags gBarriers[] = {
-              eHTMLTag_thead, eHTMLTag_tbody, eHTMLTag_tfoot, eHTMLTag_table
-            };
-
-            if (!FindTagInSet(theParentTag, gBarriers,
-                              ArrayLength(gBarriers)) &&
-                nsHTMLElement::IsResidualStyleTag(theChildTag)) {
-              // Fix bug 77746
-              mBodyContext->RemoveStyle(theChildTag);
-            }
-
-            // If the bit kHandleStrayTag is set then we automatically open up a
-            // matching start tag (compatibility).  Currently this bit is set on
-            // P tag.  This also fixes Bug: 22623
-            if (gHTMLElements[theChildTag].HasSpecialProperty(kHandleStrayTag) &&
-                mDTDMode != eDTDMode_full_standards &&
-                mDTDMode != eDTDMode_almost_standards) {
-              // Oh boy!! we found a "stray" tag. Nav4.x and IE introduce line
-              // break in such cases. So, let's simulate that effect for
-              // compatibility.
-              // Ex. <html><body>Hello</P>There</body></html>
-              int32_t theParentContains = -1;
-              if (!CanOmit(theParentTag, theChildTag, theParentContains)) {
-                CToken* theStartToken =
-                  mTokenAllocator->CreateTokenOfType(eToken_start, theChildTag);
-                NS_ENSURE_TRUE(theStartToken, NS_ERROR_OUT_OF_MEMORY);
-
-                // This check for NS_DTD_FLAG_IN_MISPLACED_CONTENT was added
-                // to fix bug 142965.
-                if (!(mFlags & NS_DTD_FLAG_IN_MISPLACED_CONTENT)) {
-                  // We're not handling misplaced content right now, just push
-                  // these new tokens back on the stack and handle them in the
-                  // regular flow of HandleToken.
-                  IF_HOLD(aToken);
-                  mTokenizer->PushTokenFront(aToken);
-                  mTokenizer->PushTokenFront(theStartToken);
-                } else {
-                  // Oops, we're in misplaced content. Handle these tokens
-                  // directly instead of trying to push them onto the tokenizer
-                  // stack.
-                  result = HandleToken(theStartToken);
-                  NS_ENSURE_SUCCESS(result, result);
-
-                  IF_HOLD(aToken);
-                  result = HandleToken(aToken);
-                }
-              }
-            }
-            return result;
-          }
-          if (result == NS_OK) {
-            eHTMLTags theTarget =
-              FindAutoCloseTargetForEndTag(theChildTag, *mBodyContext,
-                                           mDTDMode);
-            if (eHTMLTag_unknown != theTarget) {
-              result = CloseContainersTo(theTarget, false);
-            }
-          }
-        }
-      }
-      break;
-  }
-
-  return result;
-}
-
-/**
- * This method will be triggered when the end of a table is
- * encountered.  Its primary purpose is to process all the
- * bad-contents pertaining a particular table. The position
- * of the table is the token bank ID.
- *
- * @update harishd 03/24/99
- * @param  aTag - This ought to be a table tag
- *
- */
-nsresult
-CNavDTD::HandleSavedTokens(int32_t anIndex)
-{
-  NS_PRECONDITION(mBodyContext != nullptr && mBodyContext->GetCount() > 0, "invalid context");
-
-  nsresult  result = NS_OK;
-
-  if (mSink && (anIndex > kNotFound)) {
-    int32_t theBadTokenCount = mMisplacedContent.GetSize();
-
-    if (theBadTokenCount > 0) {
-      mFlags |= NS_DTD_FLAG_IN_MISPLACED_CONTENT;
-
-      if (!mTempContext && !(mTempContext = new nsDTDContext())) {
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-
-      CToken*   theToken;
-      eHTMLTags theTag;
-      int32_t   attrCount;
-      int32_t   theTopIndex = anIndex + 1;
-      int32_t   theTagCount = mBodyContext->GetCount();
-
-      // Pause the main context and switch to the new context.
-      result = mSink->BeginContext(anIndex);
-      
-      NS_ENSURE_SUCCESS(result, result);
-
-      // The body context should contain contents only upto the marked position.
-      mBodyContext->MoveEntries(*mTempContext, theTagCount - theTopIndex);
-
-      // Now flush out all the bad contents.
-      while (theBadTokenCount-- > 0){
-        theToken = (CToken*)mMisplacedContent.PopFront();
-        if (theToken) {
-          theTag       = (eHTMLTags)theToken->GetTypeID();
-          attrCount    = theToken->GetAttributeCount();
-          // Put back attributes, which once got popped out, into the
-          // tokenizer.  Make sure we preserve their ordering, however!
-          // XXXbz would it be faster to get the tokens out with ObjectAt and
-          // put them in the tokenizer and then PopFront them all from
-          // mMisplacedContent?
-          nsDeque temp;
-          for (int32_t j = 0; j < attrCount; ++j) {
-            CToken* theAttrToken = (CToken*)mMisplacedContent.PopFront();
-            if (theAttrToken) {
-              temp.Push(theAttrToken);
-            }
-            theBadTokenCount--;
-          }
-          mTokenizer->PrependTokens(temp);
-
-          if (eToken_end == theToken->GetTokenType()) {
-            // Ref: Bug 25202
-            // Make sure that the BeginContext() is ended only by the call to
-            // EndContext(). Ex: <center><table><a></center>.
-            // In the Ex. above </center> should not close <center> above table.
-            // Doing so will cause the current context to get closed prematurely.
-            eHTMLTags closed = FindAutoCloseTargetForEndTag(theTag, *mBodyContext,
-                                                            mDTDMode);
-            int32_t theIndex = closed != eHTMLTag_unknown
-                               ? mBodyContext->LastOf(closed)
-                               : kNotFound;
-
-            if (theIndex != kNotFound &&
-                theIndex <= mBodyContext->mContextTopIndex) {
-              IF_FREE(theToken, mTokenAllocator);
-              continue;
-            }
-          }
-
-          // XXX This should go away, with this call, it becomes extremely
-          // difficult to handle misplaced style and link tags, since it's hard
-          // to propagate the block return all the way up and then re-enter this
-          // method.
-          result = HandleToken(theToken);
-        }
-      }
-
-      if (theTopIndex != mBodyContext->GetCount()) {
-        // CloseContainersTo does not close any forms we might have opened while
-        // handling saved tokens, because the parser does not track forms on its
-        // mBodyContext stack.
-        CloseContainersTo(theTopIndex, mBodyContext->TagAt(theTopIndex),
-                          true);
-      }      
-
-      // Bad-contents were successfully processed. Now, itz time to get
-      // back to the original body context state.
-      mTempContext->MoveEntries(*mBodyContext, theTagCount - theTopIndex);
-
-      // Terminate the new context and switch back to the main context
-      mSink->EndContext(anIndex);
-
-      mFlags &= ~NS_DTD_FLAG_IN_MISPLACED_CONTENT;
-    }
-  }
-  return result;
-}
-
-
-/**
- *  This method gets called when an entity token has been 
- *  encountered in the parse process. 
- *  
- *  @update  gess 3/25/98
- *  @param   aToken -- next (start) token to be handled
- *  @return  true if all went well; false if error occurred
- */
-nsresult
-CNavDTD::HandleEntityToken(CToken* aToken)
-{
-  NS_PRECONDITION(nullptr != aToken, kNullToken);
-
-  nsresult  result = NS_OK;
-
-  const nsSubstring& theStr = aToken->GetStringValue();
-
-  if (kHashsign != theStr.First() &&
-      -1 == nsHTMLEntities::EntityToUnicode(theStr)) {
-    // If you're here we have a bogus entity.
-    // Convert it into a text token.
-    CToken *theToken;
-
-    nsAutoString entityName;
-    entityName.AssignLiteral("&");
-    entityName.Append(theStr);
-    theToken = mTokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_text,
-                                                  entityName);
-    NS_ENSURE_TRUE(theToken, NS_ERROR_OUT_OF_MEMORY);
-
-    // theToken should get recycled automagically...
-    return HandleToken(theToken);
-  }
-
-  eHTMLTags theParentTag = mBodyContext->Last();
-  nsCParserNode* theNode = mNodeAllocator.CreateNode(aToken, mTokenAllocator);
-  NS_ENSURE_TRUE(theNode, NS_ERROR_OUT_OF_MEMORY);
-
-  int32_t theParentContains = -1;
-  if (CanOmit(theParentTag, eHTMLTag_entity, theParentContains)) {
-    eHTMLTags theCurrTag = (eHTMLTags)aToken->GetTypeID();
-    HandleOmittedTag(aToken, theCurrTag, theParentTag, theNode);
-  } else {
-    result = AddLeaf(theNode);
-  }
-  IF_FREE(theNode, &mNodeAllocator);
-  return result;
-}
-
-/**
- *  This method gets called when a comment token has been 
- *  encountered in the parse process. After making sure
- *  we're somewhere in the body, we handle the comment
- *  in the same code that we use for text.
- *  
- *  @update  gess 3/25/98
- *  @param   aToken -- next (start) token to be handled
- *  @return  true if all went well; false if error occurred
- */
-nsresult
-CNavDTD::HandleCommentToken(CToken* aToken)
-{
-  NS_PRECONDITION(nullptr != aToken, kNullToken);
-  return NS_OK;
-}
-
-
-/**
- *  This method gets called when an attribute token has been
- *  encountered in the parse process. This is an error, since
- *  all attributes should have been accounted for in the prior
- *  start or end tokens
- *
- *  @update  gess 3/25/98
- *  @param   aToken -- next (start) token to be handled
- *  @return  true if all went well; false if error occurred
- */
-nsresult
-CNavDTD::HandleAttributeToken(CToken* aToken)
-{
-  NS_ERROR("attribute encountered -- this shouldn't happen.");
-  return NS_OK;
-}
-
-/**
- *  This method gets called when an "instruction" token has been 
- *  encountered in the parse process. 
- *  
- *  @update  gess 3/25/98
- *  @param   aToken -- next (start) token to be handled
- *  @return  true if all went well; false if error occurred
- */
-nsresult
-CNavDTD::HandleProcessingInstructionToken(CToken* aToken)
-{
-  NS_PRECONDITION(nullptr != aToken, kNullToken);
-  return NS_OK;
-}
-
-/**
- *  This method gets called when a DOCTYPE token has been 
- *  encountered in the parse process. 
- *  
- *  @update  harishd 09/02/99
- *  @param   aToken -- The very first token to be handled
- *  @return  true if all went well; false if error occurred
- */
-nsresult
-CNavDTD::HandleDocTypeDeclToken(CToken* aToken)
-{
-  NS_PRECONDITION(nullptr != aToken, kNullToken);
-
-  CDoctypeDeclToken* theToken = static_cast<CDoctypeDeclToken*>(aToken);
-  nsAutoString docTypeStr(theToken->GetStringValue());
-  // XXX Doesn't this count the newlines twice?
-  if (mCountLines) {
-    mLineNumber += docTypeStr.CountChar(kNewLine);
-  }
-
-  int32_t len = docTypeStr.Length();
-  int32_t pos = docTypeStr.RFindChar(kGreaterThan);
-  if (pos != kNotFound) {
-    // First remove '>' from the end.
-    docTypeStr.Cut(pos, len - pos);
-  }
-
-  // Now remove "<!" from the begining
-  docTypeStr.Cut(0, 2);
-  theToken->SetStringValue(docTypeStr);
-  return NS_OK;
-}
-
-/**
- * Retrieve the attributes for this node, and add then into
- * the node.
- *
- * @update  gess4/22/98
- * @param   aNode is the node you want to collect attributes for
- * @param   aCount is the # of attributes you're expecting
- * @return error code (should be 0)
- */
-nsresult
-CNavDTD::CollectAttributes(nsIParserNode *aNode, eHTMLTags aTag, int32_t aCount)
-{
-  int attr = 0;
-  nsresult result = NS_OK;
-  int theAvailTokenCount = mTokenizer->GetCount();
-
-  if (aCount <= theAvailTokenCount) {
-    CToken* theToken;
-    for (attr = 0; attr < aCount; ++attr) {
-      theToken = mTokenizer->PopToken();
-      if (theToken) {
-        eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType());
-        if (theType != eToken_attribute) {
-          // If you're here then it means that the token does not
-          // belong to this node. Put the token back into the tokenizer
-          // and let it go thro' the regular path. Bug: 59189.
-          mTokenizer->PushTokenFront(theToken);
-          break;
-        }
-
-        if (mCountLines) {
-          mLineNumber += theToken->GetNewlineCount();
-        }
-
-        if (aNode) {
-          // If the key is empty, the attribute is unusable, so we should not
-          // add it to the node.
-          if (!((CAttributeToken*)theToken)->GetKey().IsEmpty()) {
-            aNode->AddAttribute(theToken);
-          } else {
-            IF_FREE(theToken, mTokenAllocator);
-          }
-        } else {
-          IF_FREE(theToken, mTokenAllocator);
-        }
-      }
-    }
-  } else {
-    result = kEOF;
-  }
-  return result;
-}
-
-/** 
- *  This method is called to determine whether or not a tag
- *  of one type can contain a tag of another type.
- *  
- *  @update  gess 4/8/98
- *  @param   aParent -- tag enum of parent container
- *  @param   aChild -- tag enum of child container
- *  @return  true if parent can contain child
- */
-NS_IMETHODIMP_(bool)
-CNavDTD::CanContain(int32_t aParent, int32_t aChild) const
-{
-  bool result = gHTMLElements[aParent].CanContain((eHTMLTags)aChild, mDTDMode);
-
-  if (eHTMLTag_nobr == aChild &&
-      IsInlineElement(aParent, aParent) &&
-      HasOpenContainer(eHTMLTag_nobr)) {
-    return false;
-  }
-
-  return result;
-}
-
-/**
- *  This method is called to determine whether or not
- *  the given childtag is a block element.
- *
- *  @update  gess 6June2000
- *  @param   aChildID -- tag id of child 
- *  @param   aParentID -- tag id of parent (or eHTMLTag_unknown)
- *  @return  true if this tag is a block tag
- */
-bool
-CNavDTD::IsBlockElement(int32_t aTagID, int32_t aParentID) const
-{
-  eHTMLTags theTag = (eHTMLTags)aTagID;
-
-  return (theTag > eHTMLTag_unknown && theTag < eHTMLTag_userdefined) &&
-          (gHTMLElements[theTag].IsMemberOf(kBlock)        ||
-           gHTMLElements[theTag].IsMemberOf(kBlockEntity)  ||
-           gHTMLElements[theTag].IsMemberOf(kHeading)      ||
-           gHTMLElements[theTag].IsMemberOf(kPreformatted) ||
-           gHTMLElements[theTag].IsMemberOf(kList));
-}
-
-/**
- *  This method is called to determine whether or not
- *  the given childtag is an inline element.
- *
- *  @update  gess 6June2000
- *  @param   aChildID -- tag id of child 
- *  @param   aParentID -- tag id of parent (or eHTMLTag_unknown)
- *  @return  true if this tag is an inline tag
- */
-bool
-CNavDTD::IsInlineElement(int32_t aTagID, int32_t aParentID) const
-{
-  eHTMLTags theTag = (eHTMLTags)aTagID;
-
-  return (theTag > eHTMLTag_unknown && theTag < eHTMLTag_userdefined) &&
-          (gHTMLElements[theTag].IsMemberOf(kInlineEntity) ||
-           gHTMLElements[theTag].IsMemberOf(kFontStyle)    ||
-           gHTMLElements[theTag].IsMemberOf(kPhrase)       ||
-           gHTMLElements[theTag].IsMemberOf(kSpecial)      ||
-           gHTMLElements[theTag].IsMemberOf(kFormControl));
-}
-
-/**
- *  This method is called to determine whether or not
- *  the necessary intermediate tags should be propagated
- *  between the given parent and given child.
- *
- *  @update  gess 4/8/98
- *  @param   aParent -- tag enum of parent container
- *  @param   aChild -- tag enum of child container
- *  @return  true if propagation should occur
- */
-bool
-CNavDTD::CanPropagate(eHTMLTags aParent, eHTMLTags aChild,
-                      int32_t aParentContains)
-{
-  bool result = false;
-  if (aParentContains == -1) {
-    aParentContains = CanContain(aParent, aChild);
-  }
-
-  if (aParent == aChild) {
-    return result;
-  }
-
-  if (nsHTMLElement::IsContainer(aChild)) {
-    mScratch.Truncate();
-    if (!gHTMLElements[aChild].HasSpecialProperty(kNoPropagate)) {
-      if (nsHTMLElement::IsBlockParent(aParent) ||
-          gHTMLElements[aParent].GetSpecialChildren()) {
-        result = ForwardPropagate(mScratch, aParent, aChild);
-        if (!result) {
-          if (eHTMLTag_unknown != aParent) {
-            result = BackwardPropagate(mScratch, aParent, aChild);
-          } else {
-            result = BackwardPropagate(mScratch, eHTMLTag_html, aChild);
-          }
-        }
-      }
-    }
-    if (mScratch.Length() - 1 > gHTMLElements[aParent].mPropagateRange) {
-      result = false;
-    }
-  } else {
-    result = !!aParentContains;
-  }
-
-
-  return result;
-}
-
-
-/**
- *  This method gets called to determine whether a given 
- *  tag can be omitted from opening. Most cannot.
- *  
- *  @param   aParent
- *  @param   aChild
- *  @param   aParentContains
- *  @return  true if given tag can contain other tags
- */
-bool
-CNavDTD::CanOmit(eHTMLTags aParent, eHTMLTags aChild, int32_t& aParentContains)
-{
-  eHTMLTags theAncestor = gHTMLElements[aChild].mExcludingAncestor;
-  if (eHTMLTag_unknown != theAncestor && HasOpenContainer(theAncestor)) {
-    return true;
-  }
-
-  theAncestor = gHTMLElements[aChild].mRequiredAncestor;
-  if (eHTMLTag_unknown != theAncestor) {
-    // If there's a required ancestor, we only omit if it isn't open and we
-    // can't get to it through propagation.
-    return !HasOpenContainer(theAncestor) &&
-           !CanPropagate(aParent, aChild, aParentContains);
-  }
-
-  if (gHTMLElements[aParent].CanExclude(aChild)) {
-    return true;
-  }
-
-  // Now the obvious test: if the parent can contain the child, don't omit.
-  if (-1 == aParentContains) {
-    aParentContains = CanContain(aParent, aChild);
-  }
-
-  if (aParentContains || aChild == aParent) {
-    return false;
-  }
-
-  if (gHTMLElements[aParent].IsBlockEntity() &&
-      nsHTMLElement::IsInlineEntity(aChild)) {
-    // Feel free to drop inlines that a block doesn't contain.
-    return true;
-  }
-
-  if (gHTMLElements[aParent].HasSpecialProperty(kBadContentWatch)) {
-    // We can only omit this child if it does not have the kBadContentWatch
-    // special property.
-    return !gHTMLElements[aChild].HasSpecialProperty(kBadContentWatch);
-  }
-
-  if (gHTMLElements[aParent].HasSpecialProperty(kSaveMisplaced)) {
-    return true;
-  }
-
-  if (aParent == eHTMLTag_body) {
-    // There are very few tags that the body does not contain. If we get here
-    // the best thing to do is just drop them.
-    return true;
-  }
-
-  return false;
-}
-
-/**
- *  This method gets called to determine whether a given 
- *  tag is itself a container
- *  
- *  @update  gess 4/8/98
- *  @param   aTag -- tag to test as a container
- *  @return  true if given tag can contain other tags
- */
 NS_IMETHODIMP_(bool)
 CNavDTD::IsContainer(int32_t aTag) const
 {
-  return nsHTMLElement::IsContainer((eHTMLTags)aTag);
-}
-
-
-bool
-CNavDTD::ForwardPropagate(nsString& aSequence, eHTMLTags aParent,
-                          eHTMLTags aChild)
-{
-  bool result = false;
-
-  switch(aParent) {
-    case eHTMLTag_table:
-      if (eHTMLTag_tr == aChild || eHTMLTag_td == aChild) {
-        return BackwardPropagate(aSequence, aParent, aChild);
-      }
-      // Otherwise, intentionally fall through...
-
-    case eHTMLTag_tr:
-      if (CanContain(eHTMLTag_td, aChild)) {
-        aSequence.Append((PRUnichar)eHTMLTag_td);
-        result = BackwardPropagate(aSequence, aParent, eHTMLTag_td);
-      }
-      break;
-
-    default:
-      break;
-  }
-
-  return result;
-}
-
-bool
-CNavDTD::BackwardPropagate(nsString& aSequence, eHTMLTags aParent,
-                           eHTMLTags aChild) const
-{
-  eHTMLTags theParent = aParent;
-
-  do {
-    const TagList* theRootTags = gHTMLElements[aChild].GetRootTags();
-    if (!theRootTags) {
-      break;
-    }
-
-    theParent = theRootTags->mTags[0];
-    NS_ASSERTION(CanContain(theParent, aChild),
-                 "Children must be contained by their root tags");
-
-    aChild = theParent;
-    aSequence.Append((PRUnichar)theParent);
-  } while (theParent != eHTMLTag_unknown && theParent != aParent);
-
-  return aParent == theParent;
-}
-
-bool CNavDTD::HasOpenContainer(eHTMLTags aContainer) const
-{
-  switch (aContainer) {
-    case eHTMLTag_form:
-      return !(~mFlags & NS_DTD_FLAG_HAS_OPEN_FORM);
-    case eHTMLTag_map:
-      return mOpenMapCount > 0;
-    default:
-      return mBodyContext->HasOpenContainer(aContainer);
-  }
-}
-
-bool
-CNavDTD::HasOpenContainer(const eHTMLTags aTagSet[], int32_t aCount) const
-{
-  int theIndex;
-  int theTopIndex = mBodyContext->GetCount() - 1;
-
-  for (theIndex = theTopIndex; theIndex > 0; --theIndex) {
-    if (FindTagInSet((*mBodyContext)[theIndex], aTagSet, aCount)) {
-      return true;
-    }
-  }
-
+  MOZ_CRASH("nobody calls this");
   return false;
 }
-
-eHTMLTags
-CNavDTD::GetTopNode() const
-{
-  return mBodyContext->Last();
-}
-
-/**
- * It is with great trepidation that I offer this method (privately of course).
- * The gets called whenever a container gets opened. This methods job is to 
- * take a look at the (transient) style stack, and open any style containers that
- * are there. Of course, we shouldn't bother to open styles that are incompatible
- * with our parent container.
- *
- * @update  gess6/4/98
- * @param   tag of the container just opened
- * @return  0 (for now)
- */
-nsresult
-CNavDTD::OpenTransientStyles(eHTMLTags aChildTag, bool aCloseInvalid)
-{
-  nsresult result = NS_OK;
-
-  // No need to open transient styles in head context - Fix for 41427
-  if ((mFlags & NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE) &&
-      eHTMLTag_newline != aChildTag &&
-      !(mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD)) {
-    if (CanContain(eHTMLTag_font, aChildTag)) {
-      uint32_t theCount = mBodyContext->GetCount();
-      uint32_t theLevel = theCount;
-
-      // This first loop is used to determine how far up the containment
-      // hierarchy we go looking for residual styles.
-      while (1 < theLevel) {
-        eHTMLTags theParentTag = mBodyContext->TagAt(--theLevel);
-        if (gHTMLElements[theParentTag].HasSpecialProperty(kNoStyleLeaksIn)) {
-          break;
-        }
-      }
-
-      mFlags &= ~NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE;
-      for (; theLevel < theCount; ++theLevel) {
-        nsEntryStack* theStack = mBodyContext->GetStylesAt(theLevel);
-        if (theStack) {
-          // Don't open transient styles if it makes the stack deep, bug 58917.
-          if (theCount + theStack->mCount >= FONTSTYLE_IGNORE_DEPTH) {
-            break;
-          }
-
-          int32_t sindex = 0;
-
-          nsTagEntry *theEntry = theStack->mEntries;
-          bool isHeadingOpen = HasOpenTagOfType(kHeading, *mBodyContext);
-          for (sindex = 0; sindex < theStack->mCount; ++sindex) {
-            nsCParserNode* theNode = (nsCParserNode*)theEntry->mNode;
-            if (1 == theNode->mUseCount) {
-              eHTMLTags theNodeTag = (eHTMLTags)theNode->GetNodeType();
-              if (gHTMLElements[theNodeTag].CanContain(aChildTag, mDTDMode)) {
-                // XXX The following comment is entirely incoherent.
-                // We do this too, because this entry differs from the new one
-                // we're pushing.
-                theEntry->mParent = theStack;
-                if (isHeadingOpen) {
-                  // Bug 77352
-                  // The style system needs to identify residual style tags
-                  // within heading tags so that heading tags' size can take
-                  // precedence over the residual style tags' size info..
-                  // *Note: Make sure that this attribute is transient since it
-                  // should not get carried over to cases other than heading.
-                  CAttributeToken theAttrToken(NS_LITERAL_STRING("_moz-rs-heading"),
-                                               EmptyString());
-                  theNode->AddAttribute(&theAttrToken);
-                  result = OpenContainer(theNode, theNodeTag, theStack);
-                  theNode->PopAttributeToken();
-                } else {
-                  result = OpenContainer(theNode, theNodeTag, theStack);
-                }
-              } else if (aCloseInvalid) {
-                // If the node tag can't contain the child tag, then remove the
-                // child tag from the style stack
-                nsCParserNode* node = theStack->Remove(sindex, theNodeTag);
-                IF_FREE(node, &mNodeAllocator);
-                --theEntry;
-              }
-            }
-            ++theEntry;
-          }
-        }
-      }
-      mFlags |= NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE;
-    }
-  }
-
-  return result;
-}
-
-/**
- * This method gets called when an explicit style close-tag is encountered.
- * It results in the style tag id being popped from our internal style stack.
- *
- * @update  gess6/4/98
- * @param 
- * @return  0 if all went well (which it always does)
- */
-void
-CNavDTD::PopStyle(eHTMLTags aTag)
-{
-  if ((mFlags & NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE) &&
-      nsHTMLElement::IsResidualStyleTag(aTag)) {
-    nsCParserNode* node = mBodyContext->PopStyle(aTag);
-    IF_FREE(node, &mNodeAllocator);  
-  }
-}
-
-
-/**
- * This method does two things: 1st, help construct
- * our own internal model of the content-stack; and
- * 2nd, pass this message on to the sink.
- * 
- * @update  gess4/22/98
- * @param   aNode -- next node to be added to model
- */
-nsresult
-CNavDTD::OpenHTML(const nsCParserNode *aNode)
-{
-  NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
-
-  nsresult result = mSink ? mSink->OpenContainer(*aNode) : NS_OK; 
-
-  // Don't push more than one HTML tag into the stack.
-  if (mBodyContext->GetCount() == 0)  {
-    mBodyContext->Push(const_cast<nsCParserNode*>(aNode), 0, false); 
-  }
-
-  return result;
-}
-
-/**
- * This method does two things: 1st, help construct
- * our own internal model of the content-stack; and
- * 2nd, pass this message on to the sink.
- * @update  gess4/6/98
- * @param   aNode -- next node to be added to model
- * @return  TRUE if ok, FALSE if error
- */
-nsresult
-CNavDTD::OpenBody(const nsCParserNode *aNode)
-{
-  NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
-
-  nsresult result = NS_OK;
-  
-  if (!(mFlags & NS_DTD_FLAG_HAD_FRAMESET)) {
-    mFlags |= NS_DTD_FLAG_HAD_BODY;
-
-    // Make sure the head is closed by the time the body is opened.
-    CloseContainer(eHTMLTag_head, false);
-
-    // Now we can open the body.
-    result = mSink ? mSink->OpenContainer(*aNode) : NS_OK; 
-
-    if (!HasOpenContainer(eHTMLTag_body)) {
-      mBodyContext->Push(const_cast<nsCParserNode*>(aNode), 0, false);
-      mTokenizer->PrependTokens(mMisplacedContent);
-    }
-  }
-
-  return result;
-}
-
-/**
- * This method does two things: 1st, help construct
- * our own internal model of the content-stack; and
- * 2nd, pass this message on to the sink.
- * @update  gess4/6/98
- * @param   aNode -- next node to be added to model
- * @param   aClosedByStartTag -- ONLY TRUE if the container is being closed by opening of another container.
- * @return  TRUE if ok, FALSE if error
- */
-nsresult
-CNavDTD::OpenContainer(const nsCParserNode *aNode,
-                       eHTMLTags aTag,
-                       nsEntryStack* aStyleStack)
-{
-  NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
-
-  nsresult   result = NS_OK;
-  bool       done   = true;
-  bool       rs_tag = nsHTMLElement::IsResidualStyleTag(aTag);
-  // We need to open transient styles to encompass the <li> so that the bullets
-  // inherit the proper colors.
-  bool       li_tag = aTag == eHTMLTag_li;
-
-  if (rs_tag || li_tag) {
-    /*
-     * Here's an interesting problem:
-     *
-     * If there's an <a> on the RS-stack, and you're trying to open
-     * another <a>, the one on the RS-stack should be discarded.
-     *
-     * I'm updating OpenTransientStyles to throw old <a>'s away.
-     */
-    OpenTransientStyles(aTag, !li_tag);
-  }
-
-  switch (aTag) {
-    case eHTMLTag_html:
-      result = OpenHTML(aNode);
-      break;
-
-    case eHTMLTag_head:
-      if (!(mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD)) {
-        mFlags |= NS_DTD_FLAG_HAS_OPEN_HEAD;
-        done = false;
-      }
-      break;
-
-    case eHTMLTag_body:
-      {
-        eHTMLTags theParent = mBodyContext->Last();
-        if (!gHTMLElements[aTag].IsSpecialParent(theParent)) {
-          mFlags |= NS_DTD_FLAG_HAS_OPEN_BODY;
-          result = OpenBody(aNode);
-        } else {
-          done = false;
-        }
-      }
-      break;
-
-    case eHTMLTag_map:
-      ++mOpenMapCount;
-      done = false;
-      break;
-
-    case eHTMLTag_form:
-      // Discard nested forms - bug 72639
-      if (!(mFlags & NS_DTD_FLAG_HAS_OPEN_FORM)) {
-        mFlags |= NS_DTD_FLAG_HAS_OPEN_FORM;
-        result = mSink ? mSink->OpenContainer(*aNode) : NS_OK;
-      }
-      break;
-
-    case eHTMLTag_frameset:
-      // Make sure that the head is closed before we try to open this frameset.
-      CloseContainer(eHTMLTag_head, false);
-
-      // Now that the head is closed, continue on with opening this frameset.
-      mFlags |= NS_DTD_FLAG_HAD_FRAMESET;
-      done = false;
-      break;
-
-    case eHTMLTag_noembed:
-      // <noembed> is unconditionally alternate content.
-      done = false;
-      mFlags |= NS_DTD_FLAG_ALTERNATE_CONTENT;
-      break;
-
-    case eHTMLTag_noscript:
-      // We want to make sure that OpenContainer gets called below since we're
-      // not doing it here
-      done = false;
-
-      if (mFlags & NS_IPARSER_FLAG_SCRIPT_ENABLED) {
-        // XXX This flag doesn't currently do anything (and would be
-        // insufficient if it did).
-        mFlags |= NS_DTD_FLAG_ALTERNATE_CONTENT;
-      }
-      break;
-
-    case eHTMLTag_iframe: // Bug 84491
-    case eHTMLTag_noframes:
-      done = false;
-      if (mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED) {
-        mFlags |= NS_DTD_FLAG_ALTERNATE_CONTENT;
-      }
-      break;
-
-    default:
-      done = false;
-      break;
-  }
-
-  if (!done) {
-
-    result = mSink ? mSink->OpenContainer(*aNode) : NS_OK;
-
-    // For residual style tags rs_tag will be true and hence
-    // the body context will hold an extra reference to the node.
-    mBodyContext->Push(const_cast<nsCParserNode*>(aNode), aStyleStack, rs_tag); 
-  }
-
-  return result;
-}
-
-nsresult
-CNavDTD::CloseResidualStyleTags(const eHTMLTags aTag,
-                                bool aClosedByStartTag)
-{
-  const int32_t count = mBodyContext->GetCount();
-  int32_t pos = count;
-  while (nsHTMLElement::IsResidualStyleTag(mBodyContext->TagAt(pos - 1)))
-    --pos;
-  if (pos < count)
-    return CloseContainersTo(pos, aTag, aClosedByStartTag);
-  return NS_OK;
-}
-
-/**
- * This method does two things: 1st, help construct
- * our own internal model of the content-stack; and
- * 2nd, pass this message on to the sink.
- * @update  gess4/6/98
- * @param   aTag  -- id of tag to be closed
- * @return  TRUE if ok, FALSE if error
- */
-nsresult
-CNavDTD::CloseContainer(const eHTMLTags aTag, bool aMalformed)
-{
-  nsresult   result = NS_OK;
-  bool       done   = true;
-
-  switch (aTag) {
-    case eHTMLTag_head:
-      if (mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD) {
-        mFlags &= ~NS_DTD_FLAG_HAS_OPEN_HEAD;
-        if (mBodyContext->Last() == eHTMLTag_head) {
-          mBodyContext->Pop();
-        } else {
-          // This else can happen because CloseContainer is called both directly
-          // and from CloseContainersTo. CloseContainersTo pops the current tag
-          // off of the stack before calling CloseContainer.
-          NS_ASSERTION(mBodyContext->LastOf(eHTMLTag_head) == kNotFound,
-                       "Closing the wrong tag");
-        }
-        done = false;
-      }
-      break;
-
-    case eHTMLTag_map:
-      if (mOpenMapCount) {
-        mOpenMapCount--;
-        done = false;
-      }
-      break;
-
-    case eHTMLTag_form:
-      if (mFlags & NS_DTD_FLAG_HAS_OPEN_FORM) {
-        mFlags &= ~NS_DTD_FLAG_HAS_OPEN_FORM;
-        done = false;
-        // If we neglect to close these tags, the sink will refuse to close the
-        // form because the form will not be on the top of the SinkContext stack.
-        // See HTMLContentSink::CloseForm.  (XXX do this in other cases?)
-        CloseResidualStyleTags(eHTMLTag_form, false);
-      }
-      break;
-
-    case eHTMLTag_iframe:
-    case eHTMLTag_noembed:
-    case eHTMLTag_noscript:
-    case eHTMLTag_noframes:
-      // Switch from alternate content state to regular state.
-      mFlags &= ~NS_DTD_FLAG_ALTERNATE_CONTENT;
-
-      // falling thro' intentionally....
-    default:
-      done = false;
-  }
-
-  if (!done) {
-
-    if (mSink) {
-      result = !aMalformed
-               ? mSink->CloseContainer(aTag)
-               : mSink->CloseMalformedContainer(aTag);
-    }
-
-    // If we were dealing with a head container in the body, make sure to
-    // close the head context now, so that body content doesn't get sucked
-    // into the head.
-    if (mBodyContext->GetCount() == mHeadContainerPosition) {
-      mHeadContainerPosition = -1;
-      nsresult headresult = CloseContainer(eHTMLTag_head, false);
-
-      // Note: we could be assigning NS_OK into NS_OK here, but that's ok.
-      // This test is to avoid a successful CloseHead result stomping over a
-      // request to block the parser.
-      if (NS_SUCCEEDED(result)) {
-        result = headresult;
-      }
-    }
-  }
-
-  return result;
-}
-
-/**
- * This method does two things: 1st, help construct
- * our own internal model of the content-stack; and
- * 2nd, pass this message on to the sink.
- * @update  gess4/6/98
- * @param   anIndex
- * @param   aTag
- * @param   aClosedByStartTag -- if TRUE, then we're closing something because a start tag caused it
- * @return  TRUE if ok, FALSE if error
- */
-nsresult
-CNavDTD::CloseContainersTo(int32_t anIndex, eHTMLTags aTarget,
-                           bool aClosedByStartTag)
-{
-  NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos);
-  nsresult result = NS_OK;
-
-  if (anIndex < mBodyContext->GetCount() && anIndex >= 0) {
-    int32_t count = 0;
-    while ((count = mBodyContext->GetCount()) > anIndex) {
-      nsEntryStack* theChildStyleStack = 0;
-      eHTMLTags theTag = mBodyContext->Last();
-      nsCParserNode* theNode = mBodyContext->Pop(theChildStyleStack);
-      result = CloseContainer(theTag, false);
-
-      bool theTagIsStyle = nsHTMLElement::IsResidualStyleTag(theTag);
-      // If the current tag cannot leak out then we shouldn't leak out of the target - Fix 40713
-      bool theStyleDoesntLeakOut = gHTMLElements[theTag].HasSpecialProperty(kNoStyleLeaksOut);
-      if (!theStyleDoesntLeakOut) {
-        theStyleDoesntLeakOut = gHTMLElements[aTarget].HasSpecialProperty(kNoStyleLeaksOut);
-      }
-
-      // Do not invoke residual style handling when dealing with
-      // alternate content. This fixed bug 25214.
-      if (theTagIsStyle && !(mFlags & NS_DTD_FLAG_ALTERNATE_CONTENT)) {
-        NS_ASSERTION(theNode, "residual style node should not be null");
-        if (!theNode) {
-          if (theChildStyleStack) {
-            mBodyContext->PushStyles(theChildStyleStack);
-          }
-          return NS_OK;
-        }
-
-        bool theTargetTagIsStyle = nsHTMLElement::IsResidualStyleTag(aTarget);
-        if (aClosedByStartTag) {
-          // Handle closure due to new start tag.
-          // The cases we're handing here:
-          // 1. <body><b><DIV>       //<b> gets pushed onto <body>.mStyles.
-          // 2. <body><a>text<a>     //in this case, the target matches, so don't push style
-          if (theNode->mUseCount == 0) {
-            if (theTag != aTarget) {
-              if (theChildStyleStack) {
-                theChildStyleStack->PushFront(theNode);
-              } else {
-                mBodyContext->PushStyle(theNode);
-              }
-            }
-          } else if (theTag == aTarget && !gHTMLElements[aTarget].CanContainSelf()) {
-            //here's a case we missed:  <a><div>text<a>text</a></div>
-            //The <div> pushes the 1st <a> onto the rs-stack, then the 2nd <a>
-            //pops the 1st <a> from the rs-stack altogether.
-            nsCParserNode* node = mBodyContext->PopStyle(theTag);
-            IF_FREE(node, &mNodeAllocator);
-          }
-
-          if (theChildStyleStack) {
-            mBodyContext->PushStyles(theChildStyleStack);
-          }
-        } else {
-          /*
-           * if you're here, then we're dealing with the closure of tags
-           * caused by a close tag (as opposed to an open tag).
-           * At a minimum, we should consider pushing residual styles up
-           * up the stack or popping and recycling displaced nodes.
-           *
-           * Known cases:
-           * 1. <body><b><div>text</DIV>
-           * Here the <b> will leak into <div> (see case given above), and
-           * when <div> closes the <b> is dropped since it's already residual.
-           *
-           * 2. <body><div><b>text</div>
-           * Here the <b> will leak out of the <div> and get pushed onto
-           * the RS stack for the <body>, since it originated in the <div>.
-           *
-           * 3. <body><span><b>text</span>
-           * In this case, the the <b> get's pushed onto the style stack.
-           * Later we deal with RS styles stored on the <span>
-           *
-           * 4. <body><span><b>text</i>
-           * Here we the <b>is closed by a (synonymous) style tag.
-           * In this case, the <b> is simply closed.
-           */
-          if (theChildStyleStack) {
-            if (!theStyleDoesntLeakOut) {
-              if (theTag != aTarget) {
-                if (theNode->mUseCount == 0) {
-                  theChildStyleStack->PushFront(theNode);
-                }
-              } else if (theNode->mUseCount == 1) {
-                // This fixes bug 30885,29626.
-                // Make sure that the node, which is about to
-                // get released does not stay on the style stack...
-                // Also be sure to remove the correct style off the
-                // style stack. -  Ref. bug 94208.
-                // Ex <FONT><B><I></FONT><FONT></B></I></FONT>
-                // Make sure that </B> removes B off the style stack.
-                mBodyContext->RemoveStyle(theTag);
-              }
-              mBodyContext->PushStyles(theChildStyleStack);
-            } else{
-              IF_DELETE(theChildStyleStack, &mNodeAllocator);
-            }
-          } else if (theNode->mUseCount == 0) {
-            // The old version of this only pushed if the targettag wasn't
-            // style.  But that misses this case: <font><b>text</font>, where
-            // the b should leak.
-            if (aTarget != theTag) {
-              mBodyContext->PushStyle(theNode);
-            }
-          } else {
-            // Ah, at last, the final case. If you're here, then we just popped
-            // a style tag that got onto that tag stack from a stylestack
-            // somewhere.  Pop it from the stylestack if the target is also a
-            // style tag.  Make sure to remove the matching style. In the
-            // following example:
-            // <FONT><B><I></FONT><FONT color=red></B></I></FONT>
-            // make sure that </I> does not remove
-            // <FONT color=red> off the style stack. - bug 94208
-            if (theTargetTagIsStyle && theTag == aTarget) {
-              mBodyContext->RemoveStyle(theTag);
-            }
-          }
-        }
-      } else {
-        // The tag is not a style tag.
-        if (theChildStyleStack) {
-          if (theStyleDoesntLeakOut) {
-            IF_DELETE(theChildStyleStack, &mNodeAllocator);
-          } else {
-            mBodyContext->PushStyles(theChildStyleStack);
-          }
-        }
-      }
-      IF_FREE(theNode, &mNodeAllocator);
-    }
-  }
-  return result;
-}
-
-/**
- * This method does two things: 1st, help construct
- * our own internal model of the content-stack; and
- * 2nd, pass this message on to the sink.
- * @update  gess4/6/98
- * @param   aTag --
- * @param   aClosedByStartTag -- ONLY TRUE if the container is being closed by opening of another container.
- * @return  TRUE if ok, FALSE if error
- */
-nsresult
-CNavDTD::CloseContainersTo(eHTMLTags aTag, bool aClosedByStartTag)
-{
-  NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos);
-
-  int32_t pos = mBodyContext->LastOf(aTag);
-
-  if (kNotFound != pos) {
-    // The tag is indeed open, so close it.
-    return CloseContainersTo(pos, aTag, aClosedByStartTag);
-  }
-
-  eHTMLTags theTopTag = mBodyContext->Last();
-
-  bool theTagIsSynonymous = (nsHTMLElement::IsResidualStyleTag(aTag) &&
-                               nsHTMLElement::IsResidualStyleTag(theTopTag)) ||
-                              (gHTMLElements[aTag].IsMemberOf(kHeading) &&
-                               gHTMLElements[theTopTag].IsMemberOf(kHeading));
-
-  if (theTagIsSynonymous) {
-    // If you're here, it's because we're trying to close one tag,
-    // but a different (synonymous) one is actually open. Because this is NAV4x
-    // compatibililty mode, we must close the one that's really open.
-    aTag = theTopTag;
-    pos = mBodyContext->LastOf(aTag);
-    if (kNotFound != pos) {
-      // The tag is indeed open, so close it.
-      return CloseContainersTo(pos, aTag, aClosedByStartTag);
-    }
-  }
-
-  nsresult result = NS_OK;
-  const TagList* theRootTags = gHTMLElements[aTag].GetRootTags();
-  // XXX Can we just bail if !theRootTags? Does that ever happen?
-  eHTMLTags theParentTag = theRootTags ? theRootTags->mTags[0] : eHTMLTag_unknown;
-  pos = mBodyContext->LastOf(theParentTag);
-  if (kNotFound != pos) {
-    // The parent container is open, so close it instead
-    result = CloseContainersTo(pos + 1, aTag, aClosedByStartTag);
-  }
-  return result;
-}
-
-/**
- * This method does two things: 1st, help construct
- * our own internal model of the content-stack; and
- * 2nd, pass this message on to the sink.
- * @update  gess4/6/98
- * @param   aNode -- next node to be added to model
- * @return  error code; 0 means OK
- */
-nsresult
-CNavDTD::AddLeaf(const nsIParserNode *aNode)
-{
-  nsresult result = NS_OK;
-
-  if (mSink) {
-    eHTMLTags theTag = (eHTMLTags)aNode->GetNodeType();
-    OpenTransientStyles(theTag);
-
-    result = mSink->AddLeaf(*aNode);
-  }
-
-  return result;
-}
-
-/**
- * Call this method ONLY when you want to write a leaf
- * into the head container.
- * 
- * @update  gess 03/14/99
- * @param   aNode -- next node to be added to model
- * @return  error code; 0 means OK
- */
-nsresult
-CNavDTD::AddHeadContent(nsIParserNode *aNode)
-{
-  nsresult result = NS_OK;
-
-  static eHTMLTags gNoXTags[] = { eHTMLTag_noembed, eHTMLTag_noframes };
-
-  eHTMLTags theTag = (eHTMLTags)aNode->GetNodeType();
-
-  // XXX - SCRIPT inside NOTAGS should not get executed unless the pref.
-  // says so.  Since we don't have this support yet..lets ignore the
-  // SCRIPT inside NOTAGS.  Ref Bug 25880.
-  if (eHTMLTag_meta == theTag || eHTMLTag_script == theTag) {
-    if (HasOpenContainer(gNoXTags, ArrayLength(gNoXTags))) {
-      return result;
-    }
-  }
-
-  if (mSink) {
-    // Make sure the head is opened.
-    if (!(mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD)) {
-      result = mSink->OpenHead();
-      mBodyContext->PushTag(eHTMLTag_head);
-      mFlags |= NS_DTD_FLAG_HAS_OPEN_HEAD;
-    }
-
-    // Note: userdefined tags in the head are treated as leaves.
-    if (!nsHTMLElement::IsContainer(theTag) || theTag == eHTMLTag_userdefined) {
-      result = mSink->AddLeaf(*aNode);
-
-      if (mFlags & NS_DTD_FLAG_HAS_MAIN_CONTAINER) {
-        // Close the head now so that body content doesn't get sucked into it.
-        CloseContainer(eHTMLTag_head, false);
-      }
-    } else {
-      if ((mFlags & NS_DTD_FLAG_HAS_MAIN_CONTAINER) &&
-          mHeadContainerPosition == -1) {
-        // Keep track of this so that we know when to close the head, when
-        // this tag is done with.
-        mHeadContainerPosition = mBodyContext->GetCount();
-      }
-
-      // Note: The head context is already opened.
-      result = mSink->OpenContainer(*aNode);
-
-      mBodyContext->Push(static_cast<nsCParserNode*>(aNode), nullptr,
-                         false);
-    }
-  }
-
-  return result;
-}
-
-void
-CNavDTD::CreateContextStackFor(eHTMLTags aParent, eHTMLTags aChild)
-{
-  mScratch.Truncate();
-
-  bool      result = ForwardPropagate(mScratch, aParent, aChild);
-
-  if (!result) {
-    if (eHTMLTag_unknown == aParent) {
-      result = BackwardPropagate(mScratch, eHTMLTag_html, aChild);
-    } else if (aParent != aChild) {
-      // Don't even bother if we're already inside a similar element...
-      result = BackwardPropagate(mScratch, aParent, aChild);
-    }
-  }
-
-  if (!result) {
-    return;
-  }
-
-  int32_t   theLen = mScratch.Length();
-  eHTMLTags theTag = (eHTMLTags)mScratch[--theLen];
-
-  // Now, build up the stack according to the tags.
-  while (theLen) {
-    theTag = (eHTMLTags)mScratch[--theLen];
-
-    // Note: These tokens should all wind up on contextstack, so don't recycle
-    // them.
-    CToken *theToken = mTokenAllocator->CreateTokenOfType(eToken_start, theTag);
-    HandleToken(theToken);
-  }
-}
--- a/parser/htmlparser/src/CNavDTD.h
+++ b/parser/htmlparser/src/CNavDTD.h
@@ -1,373 +1,38 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim: set sw=2 ts=2 et tw=78: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/**
- * MODULE NOTES:
- *
- * NavDTD is an implementation of the nsIDTD interface.
- * In particular, this class captures the behaviors of the original 
- * Navigator parser productions.
- *
- * This DTD, like any other in NGLayout, provides a few basic services:
- *  - First, the DTD collaborates with the Parser class to convert plain 
- *    text into a sequence of HTMLTokens. 
- *  - Second, the DTD describes containment rules for known elements. 
- *  - Third the DTD controls and coordinates the interaction between the
- *    parsing system and content sink. (The content sink is the interface
- *    that serves as a proxy for content model).
- *  - Fourth the DTD maintains an internal style-stack to handle residual (leaky)
- *    style tags.
- *
- * You're most likely working in this class file because
- * you want to add or change a behavior inherent in this DTD. The remainder
- * of this section will describe what you need to do to affect the kind of
- * change you want in this DTD.
- *
- * RESIDUAL-STYLE HANDLNG:
- *   There are a number of ways to represent style in an HTML document.
- *    1) explicit style tags (<B>, <I> etc)
- *    2) implicit styles (like those implicit in <Hn>)
- *    3) CSS based styles
- *
- *   Residual style handling results from explicit style tags that are
- *   not closed. Consider this example: <p>text <b>bold </p>
- *   When the <p> tag closes, the <b> tag is NOT automatically closed.
- *   Unclosed style tags are handled by the process we call residual-style 
- *   tag handling. 
- *
- *   There are two aspects to residual style tag handling. The first is the 
- *   construction and managing of a stack of residual style tags. The 
- *   second is the automatic emission of residual style tags onto leaf content
- *   in subsequent portions of the document.This step is necessary to propagate
- *   the expected style behavior to subsequent portions of the document.
- *
- *   Construction and managing the residual style stack is an inline process that
- *   occurs during the model building phase of the parse process. During the model-
- *   building phase of the parse process, a content stack is maintained which tracks
- *   the open container hierarchy. If a style tag(s) fails to be closed when a normal
- *   container is closed, that style tag is placed onto the residual style stack. If
- *   that style tag is subsequently closed (in most contexts), it is popped off the
- *   residual style stack -- and are of no further concern.
- *
- *   Residual style tag emission occurs when the style stack is not empty, and leaf
- *   content occurs. In our earlier example, the <b> tag "leaked" out of the <p> 
- *   container. Just before the next leaf is emitted (in this or another container) the 
- *   style tags that are on the stack are emitted in succession. These same residual
- *   style tags get closed automatically when the leaf's container closes, or if a
- *   child container is opened.
- * 
- *         
- */
 #ifndef NS_NAVHTMLDTD__
 #define NS_NAVHTMLDTD__
 
 #include "nsIDTD.h"
 #include "nsISupports.h"
-#include "nsHTMLTags.h"
-#include "nsDeque.h"
-#include "nsParserCIID.h"
-#include "nsDTDUtils.h"
-#include "nsParser.h"
-#include "nsCycleCollectionParticipant.h"
+#include "nsCOMPtr.h"
 
+// This class is no longer useful.
 class nsIHTMLContentSink;
-class nsIParserNode;
-class nsDTDContext;
-class nsEntryStack;
-class nsITokenizer;
-class nsCParserNode;
-class nsTokenAllocator;
-
-/***************************************************************
-  Now the main event: CNavDTD.
-
-  This not so simple class performs all the duties of token 
-  construction and model building. It works in conjunction with
-  an nsParser.
- ***************************************************************/
 
 #ifdef _MSC_VER
 #pragma warning( disable : 4275 )
 #endif
 
 class CNavDTD : public nsIDTD
 {
 #ifdef _MSC_VER
 #pragma warning( default : 4275 )
 #endif
 
 public:
-    /**
-     *  Common constructor for navdtd. You probably want to call
-     *  NS_NewNavHTMLDTD().
-     */
     CNavDTD();
     virtual ~CNavDTD();
 
-    /**
-     * This method is offered publically for the sole use from
-     * nsParser::ParseFragment. In general, you should prefer to use methods
-     * that are directly on nsIDTD, since those will be guaranteed to do the
-     * right thing.
-     *
-     * @param aNode The parser node that contains the token information for
-     *              this tag.
-     * @param aTag The actual tag that is being opened (should correspond to
-     *             aNode.
-     * @param aStyleStack The style stack that aNode might be a member of
-     *                    (usually null).
-     */
-    nsresult OpenContainer(const nsCParserNode *aNode,
-                           eHTMLTags aTag,
-                           nsEntryStack* aStyleStack = nullptr);
-
-    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_ISUPPORTS
     NS_DECL_NSIDTD
-    NS_DECL_CYCLE_COLLECTION_CLASS(CNavDTD)
-
-private:
-    /**
-     *  This method is called to determine whether or not a tag
-     *  of one type can contain a tag of another type.
-     *  
-     *  @param   aParent Tag of parent container
-     *  @param   aChild Tag of child container
-     *  @return  true if parent can contain child
-     */
-    bool CanPropagate(eHTMLTags aParent,
-                        eHTMLTags aChild,
-                        int32_t aParentContains);
-
-    /**
-     *  This method gets called to determine whether a given 
-     *  child tag can be omitted by the given parent.
-     *  
-     *  @param   aParent Parent tag being asked about omitting given child
-     *  @param   aChild Child tag being tested for omittability by parent
-     *  @param   aParentContains Can be 0,1,-1 (false,true, unknown)
-     *                           XXX should be int32_t, not bool
-     *  @return  true if given tag can be omitted
-     */
-    bool CanOmit(eHTMLTags aParent, 
-                   eHTMLTags aChild,
-                   int32_t& aParentContains);
-
-    /**
-     * Looking at aParent, try to see if we can propagate from aChild to
-     * aParent. If aParent is a TR tag, then see if we can start at TD instead
-     * of at aChild.
-     *
-     * @param   aParent Tag type of parent
-     * @param   aChild Tag type of child
-     * @return  true if closure was achieved -- otherwise false
-     */
-    bool ForwardPropagate(nsString& aSequence,
-                            eHTMLTags aParent,
-                            eHTMLTags aChild);
-
-    /**
-     * Given aParent that does not contain aChild, starting with aChild's
-     * first root tag, try to find aParent. If we can reach aParent simply by
-     * going up each first root tag, then return true. Otherwise, we could not
-     * propagate from aChild up to aParent, so return false.
-     *
-     * @param   aParent Tag type of parent
-     * @param   aChild Tag type of child
-     * @return  true if closure was achieved -- other false
-     */
-    bool BackwardPropagate(nsString& aSequence,
-                             eHTMLTags aParent,
-                             eHTMLTags aChild) const;
-
-    /**
-     * Attempt forward and/or backward propagation for the given child within
-     * the current context vector stack. And actually open the required tags.
-     *
-     * @param   aParent The tag we're trying to open this element inside of.
-     * @param   aChild Type of child to be propagated.
-     */
-    void CreateContextStackFor(eHTMLTags aParent, eHTMLTags aChild);
-
-    /**
-     * Ask if a given container is open anywhere on its stack
-     *
-     * @param   id of container you want to test for
-     * @return  TRUE if the given container type is open -- otherwise FALSE
-     */
-    bool HasOpenContainer(eHTMLTags aContainer) const;
-
-    /**
-     * This method allows the caller to determine if a any member
-     * in a set of tags is currently open.
-     *
-     * @param   aTagSet A set of tags you care about.
-     * @return  true if any of the members of aTagSet are currently open.
-     */
-    bool HasOpenContainer(const eHTMLTags aTagSet[], int32_t aCount) const;
-
-    /**
-     * Accessor that retrieves the tag type of the topmost item on the DTD's
-     * tag stack.
-     *
-     * @return The tag type (may be unknown)
-     */
-    eHTMLTags GetTopNode() const;
-
-    /**
-     * Finds the topmost occurrence of given tag within context vector stack.
-     *
-     * @param   tag to be found
-     * @return  index of topmost tag occurrence -- may be -1 (kNotFound).
-     */
-    int32_t LastOf(eHTMLTags aTagSet[], int32_t aCount) const;
-
-    nsresult HandleToken(CToken* aToken);
-
-    /**
-     *  This method gets called when a start token has been
-     *  encountered in the parse process. If the current container
-     *  can contain this tag, then add it. Otherwise, you have
-     *  two choices: 1) create an implicit container for this tag
-     *                  to be stored in
-     *               2) close the top container, and add this to
-     *                  whatever container ends up on top.
-     *
-     *  @param   aToken -- next (start) token to be handled
-     *  @return  Whether or not we should block the parser.
-     */
-    nsresult    HandleStartToken(CToken* aToken);
-
-    /** 
-     *  This method gets called when a start token has been 
-     *  encountered in the parse process. If the current container
-     *  can contain this tag, then add it. Otherwise, you have
-     *  two choices: 1) create an implicit container for this tag
-     *                  to be stored in
-     *               2) close the top container, and add this to
-     *                  whatever container ends up on top.
-     *   
-     *  @param   aToken Next (start) token to be handled.
-     *  @param   aChildTag The tag corresponding to aToken.
-     *  @param   aNode CParserNode representing this start token
-     *  @return  A potential request to block the parser.
-     */
-    nsresult    HandleDefaultStartToken(CToken* aToken, eHTMLTags aChildTag,
-                                        nsCParserNode *aNode);
-    nsresult    HandleEndToken(CToken* aToken);
-    nsresult    HandleEntityToken(CToken* aToken);
-    nsresult    HandleCommentToken(CToken* aToken);
-    nsresult    HandleAttributeToken(CToken* aToken);
-    nsresult    HandleProcessingInstructionToken(CToken* aToken);
-    nsresult    HandleDocTypeDeclToken(CToken* aToken);
-    nsresult    BuildNeglectedTarget(eHTMLTags aTarget, eHTMLTokenTypes aType);
-
-    nsresult OpenHTML(const nsCParserNode *aNode);
-    nsresult OpenBody(const nsCParserNode *aNode);
-
-    /**
-     * The special purpose methods automatically close
-     * one or more open containers.
-     * @return  error code - 0 if all went well.
-     */
-    nsresult CloseContainer(const eHTMLTags aTag, bool aMalformed);
-    nsresult CloseContainersTo(eHTMLTags aTag, bool aClosedByStartTag);
-    nsresult CloseContainersTo(int32_t anIndex, eHTMLTags aTag,
-                               bool aClosedByStartTag);
-    nsresult CloseResidualStyleTags(const eHTMLTags aTag,
-                                    bool aClosedByStartTag);
-
-    /**
-     * Causes leaf to be added to sink at current vector pos.
-     * @param   aNode is leaf node to be added.
-     * @return  error code - 0 if all went well.
-     */
-    nsresult AddLeaf(const nsIParserNode *aNode);
-    nsresult AddHeadContent(nsIParserNode *aNode);
-
-    /**
-     * This set of methods is used to create and manage the set of
-     * transient styles that occur as a result of poorly formed HTML
-     * or bugs in the original navigator.
-     *
-     * @param   aTag -- represents the transient style tag to be handled.
-     * @return  error code -- usually 0
-     */
-    nsresult  OpenTransientStyles(eHTMLTags aChildTag,
-                                  bool aCloseInvalid = true);
-    void      PopStyle(eHTMLTags aTag);
-
-    nsresult  PushIntoMisplacedStack(CToken* aToken)
-    {
-      NS_ENSURE_ARG_POINTER(aToken);
-      aToken->SetNewlineCount(0); // Note: We have already counted the newlines for these tokens
-
-      mMisplacedContent.Push(aToken);
-      return NS_OK;
-    }
-
-protected:
-
-    nsresult        CollectAttributes(nsIParserNode* aNode,eHTMLTags aTag,int32_t aCount);
-
-    /**
-     * This gets called before we've handled a given start tag.
-     * It's a generic hook to let us do pre processing.
-     *
-     * @param   aToken contains the tag in question
-     * @param   aTag is the tag itself.
-     * @param   aNode is the node (tag) with associated attributes.
-     * @return  NS_OK if we should continue, a failure code otherwise.
-     */
-    nsresult        WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode);
-    nsresult        DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag);
-
-    /**
-     *  This method gets called when a start token has been encountered that
-     *  the parent wants to omit. It stashes it in the current element if that
-     *  element accepts such misplaced tokens.
-     *
-     *  @param   aToken Next (start) token to be handled
-     *  @param   aChildTag id of the child in question
-     *  @param   aParent id of the parent in question
-     *  @param   aNode CParserNode representing this start token
-     */
-    void            HandleOmittedTag(CToken* aToken, eHTMLTags aChildTag,
-                                     eHTMLTags aParent, nsIParserNode *aNode);
-    nsresult        HandleSavedTokens(int32_t anIndex);
-    nsresult        HandleKeyGen(nsIParserNode *aNode);
-    bool            IsAlternateTag(eHTMLTags aTag);
-    bool            IsBlockElement(int32_t aTagID, int32_t aParentID) const;
-    bool            IsInlineElement(int32_t aTagID, int32_t aParentID) const;
-
-    nsDeque             mMisplacedContent;
-    
-    nsCOMPtr<nsIHTMLContentSink> mSink;
-    nsTokenAllocator*   mTokenAllocator;
-    nsDTDContext*       mBodyContext;
-    nsDTDContext*       mTempContext;
-    bool                mCountLines;
-    nsITokenizer*       mTokenizer; // weak
-   
-    nsString            mFilename; 
-    nsString            mScratch;  //used for various purposes; non-persistent
-    nsCString           mMimeType;
-
-    nsNodeAllocator     mNodeAllocator;
-    nsDTDMode           mDTDMode;
-    eParserDocType      mDocType;
-    eParserCommands     mParserCommand;   //tells us to viewcontent/viewsource/viewerrors...
-
-    int32_t             mLineNumber;
-    int32_t             mOpenMapCount;
-    int32_t             mHeadContainerPosition;
-
-    uint16_t            mFlags;
 };
 
-#endif 
+#endif
 
 
 
--- a/parser/htmlparser/src/CParserContext.cpp
+++ b/parser/htmlparser/src/CParserContext.cpp
@@ -7,16 +7,17 @@
 
 #include "nsIAtom.h"
 #include "CParserContext.h"
 #include "nsToken.h"
 #include "prenv.h"  
 #include "nsIHTMLContentSink.h"
 #include "nsHTMLTokenizer.h"
 #include "nsMimeTypes.h"
+#include "nsHTMLTokenizer.h"
 
 CParserContext::CParserContext(CParserContext* aPrevContext,
                                nsScanner* aScanner, 
                                void *aKey, 
                                eParserCommands aCommand,
                                nsIRequestObserver* aListener, 
                                eAutoDetectResult aStatus, 
                                bool aCopyUnused)
@@ -73,22 +74,16 @@ CParserContext::GetTokenizer(nsIDTD* aDT
   if (!mTokenizer) {
     if (type == NS_IPARSER_FLAG_HTML || mParserCommand == eViewSource) {
       nsCOMPtr<nsIHTMLContentSink> theSink = do_QueryInterface(aSink);
       mTokenizer = new nsHTMLTokenizer(mDTDMode, mDocType, mParserCommand,
                                        nsHTMLTokenizer::GetFlags(aSink));
       if (!mTokenizer) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
-
-      // Make sure the new tokenizer has all of the necessary information.
-      // XXX this might not be necessary.
-      if (mPrevContext) {
-        mTokenizer->CopyState(mPrevContext->mTokenizer);
-      }
     }
     else if (type == NS_IPARSER_FLAG_XML) {
       mTokenizer = do_QueryInterface(aDTD, &result);
     }
   }
 
   aTokenizer = mTokenizer;
 
--- a/parser/htmlparser/src/moz.build
+++ b/parser/htmlparser/src/moz.build
@@ -4,27 +4,24 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MODULE = 'htmlparser'
 
 CPP_SOURCES += [
     'CNavDTD.cpp',
     'CParserContext.cpp',
-    'nsDTDUtils.cpp',
     'nsElementTable.cpp',
     'nsExpatDriver.cpp',
     'nsHTMLEntities.cpp',
     'nsHTMLTags.cpp',
     'nsHTMLTokenizer.cpp',
-    'nsHTMLTokens.cpp',
     'nsParser.cpp',
     'nsParserModule.cpp',
     'nsParserMsgUtils.cpp',
     'nsParserNode.cpp',
     'nsParserService.cpp',
     'nsScanner.cpp',
     'nsScannerString.cpp',
-    'nsToken.cpp',
 ]
 
 LIBRARY_NAME = 'htmlpars'
 
deleted file mode 100644
--- a/parser/htmlparser/src/nsDTDUtils.cpp
+++ /dev/null
@@ -1,985 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sw=2 et tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-       
-  
-#include "nsIAtom.h"
-#include "nsDTDUtils.h" 
-#include "CNavDTD.h" 
-#include "nsIParserNode.h"
-#include "nsParserNode.h" 
-#include "nsIChannel.h"
-#include "nsIServiceManager.h"
-#include "nsUnicharUtils.h"
-
-/**************************************************************************************
-  A few notes about how residual style handling is performed:
-   
-    1. The style stack contains nsTagEntry elements. 
-    2. Every tag on the containment stack can have it's own residual style stack.
-    3. When a style leaks, it's mParent member is set to the level on the stack where 
-       it originated. A node with an mParent of 0 is not opened on tag stack, 
-       but is open on stylestack.
-    4. An easy way to tell that a container on the element stack is a residual style tag
-       is that it's use count is >1.
-
- **************************************************************************************/
-
-
-/**
- * Default constructor
- * @update	harishd 04/04/99
- * @update  gess 04/22/99
- */
-nsEntryStack::nsEntryStack()  {
-
-  MOZ_COUNT_CTOR(nsEntryStack);
-  
-  mCapacity=0;
-  mCount=0;
-  mEntries=0;
-}
-
-/**
- * Default destructor
- * @update  harishd 04/04/99
- * @update  gess 04/22/99
- */
-nsEntryStack::~nsEntryStack() {
-
-  MOZ_COUNT_DTOR(nsEntryStack);
-
-  if(mEntries) {
-    //add code here to recycle the node if you have one...  
-    delete [] mEntries;
-    mEntries=0;
-  }
-
-  mCount=mCapacity=0;
-}
-
-/**
- * Release all objects in the entry stack
- */
-void 
-nsEntryStack::ReleaseAll(nsNodeAllocator* aNodeAllocator)
-{
-  NS_ASSERTION(aNodeAllocator,"no allocator? - potential leak!");
-
-  if(aNodeAllocator) {
-    NS_ASSERTION(mCount >= 0,"count should not be negative");
-    while(mCount > 0) {
-      nsCParserNode* node=this->Pop();
-      IF_FREE(node,aNodeAllocator);
-    }
-  }
-}
-
-/**
- * Resets state of stack to be empty.
- * @update harishd 04/04/99
- */
-void nsEntryStack::Empty(void) {
-  mCount=0;
-}
-
-
-/**
- * 
- * @update  gess 04/22/99
- */
-void nsEntryStack::EnsureCapacityFor(int32_t aNewMax,int32_t aShiftOffset) {
-  if(mCapacity<aNewMax){ 
-
-    const int kDelta=16;
-
-    int32_t theSize = kDelta * ((aNewMax / kDelta) + 1);
-    nsTagEntry* temp=new nsTagEntry[theSize]; 
-    mCapacity=theSize;
-
-    if(temp){ 
-      int32_t index=0; 
-      for(index=0;index<mCount;++index) {
-        temp[aShiftOffset+index]=mEntries[index];
-      }
-      if(mEntries) delete [] mEntries;
-      mEntries=temp;
-    }
-    else{
-      //XXX HACK! This is very bad! We failed to get memory.
-    }
-  } //if
-}
-
-/**
- * 
- * @update  gess 04/22/99
- */
-void nsEntryStack::Push(nsCParserNode* aNode,
-                        nsEntryStack* aStyleStack, 
-                        bool aRefCntNode) 
-{
-  if(aNode) {
-    EnsureCapacityFor(mCount+1);
-    mEntries[mCount].mTag = (eHTMLTags)aNode->GetNodeType();
-    if (aRefCntNode) {
-      aNode->mUseCount++;
-      mEntries[mCount].mNode = const_cast<nsCParserNode*>(aNode);
-      IF_HOLD(mEntries[mCount].mNode);
-    }
-    mEntries[mCount].mParent=aStyleStack;
-    mEntries[mCount++].mStyles=0;
-  }
-}
-
-void nsEntryStack::PushTag(eHTMLTags aTag)
-{
-  EnsureCapacityFor(mCount + 1);
-  mEntries[mCount].mTag = aTag;
-  mEntries[mCount].mParent = nullptr;
-  mEntries[mCount].mStyles = nullptr;
-  ++mCount;
-}
-
-
-/**
- * This method inserts the given node onto the front of this stack
- *
- * @update  gess 11/10/99
- */
-void nsEntryStack::PushFront(nsCParserNode* aNode,
-                             nsEntryStack* aStyleStack, 
-                             bool aRefCntNode) 
-{
-  if(aNode) {
-    if(mCount<mCapacity) {
-      int32_t index=0; 
-      for(index=mCount;index>0;index--) {
-        mEntries[index]=mEntries[index-1];
-      }
-    }
-    else {
-      EnsureCapacityFor(mCount+1,1);
-    }
-    mEntries[0].mTag = (eHTMLTags)aNode->GetNodeType();
-    if (aRefCntNode) {
-      aNode->mUseCount++;
-      mEntries[0].mNode = const_cast<nsCParserNode*>(aNode);
-      IF_HOLD(mEntries[0].mNode);
-    }
-    mEntries[0].mParent=aStyleStack;
-    mEntries[0].mStyles=0;
-    ++mCount;
-  }
-}
-
-/**
- * 
- * @update  gess 11/10/99
- */
-void nsEntryStack::Append(nsEntryStack *aStack) {
-  if(aStack) {
-
-    int32_t theCount=aStack->mCount;
-
-    EnsureCapacityFor(mCount+aStack->mCount,0);
-
-    int32_t theIndex=0;
-    for(theIndex=0;theIndex<theCount;++theIndex){
-      mEntries[mCount]=aStack->mEntries[theIndex];
-      mEntries[mCount++].mParent=0;
-    }
-  }
-} 
- 
-/**
- * This method removes the node for the given tag
- * from anywhere within this entry stack, and shifts
- * other entries down.
- * 
- * NOTE: It's odd to be removing an element from the middle
- *       of a stack, but it's necessary because of how MALFORMED
- *       html can be. 
- * 
- * anIndex: the index within the stack of the tag to be removed
- * aTag: the id of the tag to be removed
- * @update  gess 02/25/00
- */
-nsCParserNode* nsEntryStack::Remove(int32_t anIndex,
-                                    eHTMLTags aTag) 
-{
-  nsCParserNode* result = 0;
-  if (0 < mCount && anIndex < mCount){
-    result = mEntries[anIndex].mNode;
-    if (result)
-      result->mUseCount--;
-    int32_t theIndex = 0;
-    mCount -= 1;
-    for( theIndex = anIndex; theIndex < mCount; ++theIndex){
-      mEntries[theIndex] = mEntries[theIndex+1];
-    }
-    mEntries[mCount].mNode = 0;
-    mEntries[mCount].mStyles = 0;
-    nsEntryStack* theStyleStack = mEntries[anIndex].mParent;
-    if (theStyleStack) {
-      //now we have to tell the residual style stack where this tag
-      //originated that it's no longer in use.
-      uint32_t scount = theStyleStack->mCount;
-#ifdef DEBUG_mrbkap
-      NS_ASSERTION(scount != 0, "RemoveStyles has a bad style stack");
-#endif
-      nsTagEntry *theStyleEntry = theStyleStack->mEntries;
-      for (uint32_t sindex = scount-1;; --sindex) {            
-        if (theStyleEntry->mTag == aTag) {
-          // This tells us that the style is not open at any level.
-          theStyleEntry->mParent = nullptr;
-          break;
-        }
-        if (sindex == 0) {
-#ifdef DEBUG_mrbkap
-          NS_ERROR("Couldn't find the removed style on its parent stack");
-#endif
-          break;
-        }
-        ++theStyleEntry;
-      }
-    }
-  }
-  return result;
-}
-
-/**
- * Pops an entry from this style stack. If the entry has a parent stack, it
- * updates the entry so that we know not to try to remove it from the parent
- * stack since it's no longer open.
- */
-nsCParserNode* nsEntryStack::Pop(void)
-{
-  nsCParserNode* result = 0;
-  if (0 < mCount) {
-    result = mEntries[--mCount].mNode;
-    if (result)
-      result->mUseCount--;
-    mEntries[mCount].mNode = 0;
-    mEntries[mCount].mStyles = 0;
-    nsEntryStack* theStyleStack = mEntries[mCount].mParent;
-    if (theStyleStack) {
-      //now we have to tell the residual style stack where this tag
-      //originated that it's no longer in use.
-      uint32_t scount = theStyleStack->mCount;
-
-      // XXX If this NS_ENSURE_TRUE fails, it means that the style stack was
-      //     empty before we were removed.
-#ifdef DEBUG_mrbkap
-      NS_ASSERTION(scount != 0, "preventing a potential crash.");
-#endif
-      NS_ENSURE_TRUE(scount != 0, result);
-
-      nsTagEntry *theStyleEntry = theStyleStack->mEntries;
-      for (uint32_t sindex = scount - 1;; --sindex) {
-        if (theStyleEntry->mTag == mEntries[mCount].mTag) {
-          // This tells us that the style is not open at any level
-          theStyleEntry->mParent = nullptr;
-          break;
-        }
-        if (sindex == 0) {
-#ifdef DEBUG_mrbkap
-          NS_ERROR("Couldn't find the removed style on its parent stack");
-#endif
-          break;
-        }
-        ++theStyleEntry;
-      }
-    }
-  }
-  return result;
-} 
-
-/**
- * 
- * @update  harishd 04/04/99
- * @update  gess 04/21/99
- */
-eHTMLTags nsEntryStack::First() const 
-{
-  eHTMLTags result=eHTMLTag_unknown;
-  if(0<mCount){
-    result=mEntries[0].mTag;
-  }
-  return result;
-}
-
-/**
- * 
- * @update  harishd 04/04/99
- * @update  gess 04/21/99
- */
-nsCParserNode* nsEntryStack::NodeAt(int32_t anIndex) const 
-{
-  nsCParserNode* result=0;
-  if((0<mCount) && (anIndex<mCount)) {
-    result=mEntries[anIndex].mNode;
-  }
-  return result;
-}
-
-/**
- * 
- * @update  harishd 04/04/99
- * @update  gess 04/21/99
- */
-eHTMLTags nsEntryStack::TagAt(int32_t anIndex) const 
-{
-  eHTMLTags result=eHTMLTag_unknown;
-  if((0<mCount) && (anIndex<mCount)) {
-    result=mEntries[anIndex].mTag;
-  }
-  return result;
-}
-
-/**
- * 
- * @update  gess 04/21/99
- */
-nsTagEntry* nsEntryStack::EntryAt(int32_t anIndex) const 
-{
-  nsTagEntry *result=0;
-  if((0<mCount) && (anIndex<mCount)) {
-    result=&mEntries[anIndex];
-  }
-  return result;
-}
-
-
-/**
- * 
- * @update  harishd 04/04/99
- * @update  gess 04/21/99
- */
-eHTMLTags nsEntryStack::operator[](int32_t anIndex) const 
-{
-  eHTMLTags result=eHTMLTag_unknown;
-  if((0<mCount) && (anIndex<mCount)) {
-    result=mEntries[anIndex].mTag;
-  }
-  return result;
-}
-
-
-/**
- * 
- * @update  harishd 04/04/99
- * @update  gess 04/21/99
- */
-eHTMLTags nsEntryStack::Last(void) const 
-{
-  eHTMLTags result=eHTMLTag_unknown;
-  if(0<mCount) {
-    result=mEntries[mCount-1].mTag;
-  }
-  return result;
-}
-
-nsTagEntry*
-nsEntryStack::PopEntry() 
-{
-  nsTagEntry* entry = EntryAt(mCount-1);
-  this->Pop();
-  return entry;
-}
-
-void nsEntryStack::PushEntry(nsTagEntry* aEntry, 
-                             bool aRefCntNode) 
-{
-  if (aEntry) {
-    EnsureCapacityFor(mCount+1);
-    mEntries[mCount].mNode   = aEntry->mNode;
-    mEntries[mCount].mTag    = aEntry->mTag;
-    mEntries[mCount].mParent = aEntry->mParent;
-    mEntries[mCount].mStyles = aEntry->mStyles;
-    if (aRefCntNode && mEntries[mCount].mNode) {
-      mEntries[mCount].mNode->mUseCount++;
-      IF_HOLD(mEntries[mCount].mNode);
-    }
-    mCount++;
-  }
-}
-
-/***************************************************************
-  Now define the dtdcontext class
- ***************************************************************/
-
-
-/**
- * 
- * @update	gess 04.21.2000
- */
-nsDTDContext::nsDTDContext() : mStack()
-{
-  MOZ_COUNT_CTOR(nsDTDContext);
-  mResidualStyleCount=0;
-  mContextTopIndex=-1;
-  mTokenAllocator=0;
-  mNodeAllocator=0;
-
-#ifdef DEBUG
-  memset(mXTags,0,sizeof(mXTags));
-#endif
-} 
- 
-/**
- * 
- * @update	gess9/10/98
- */
-nsDTDContext::~nsDTDContext()
-{
-  MOZ_COUNT_DTOR(nsDTDContext);
-}
-
-
-/**
- * 
- * @update  gess7/9/98
- */
-bool nsDTDContext::HasOpenContainer(eHTMLTags aTag) const {
-  int32_t theIndex=mStack.LastOf(aTag);
-  return bool(-1<theIndex);
-}
-
-/**
- * 
- * @update  gess7/9/98
- */
-void nsDTDContext::Push(nsCParserNode* aNode,
-                        nsEntryStack* aStyleStack, 
-                        bool aRefCntNode) {
-  if(aNode) {
-#ifdef  DEBUG
-    eHTMLTags theTag = (eHTMLTags)aNode->GetNodeType();
-    int size = mStack.mCount;
-    if (size < eMaxTags)
-      mXTags[size] = theTag;
-#endif
-    mStack.Push(aNode, aStyleStack, aRefCntNode);
-  }
-}
-
-void nsDTDContext::PushTag(eHTMLTags aTag)
-{
-#ifdef DEBUG
-  if (mStack.mCount < eMaxTags) {
-    mXTags[mStack.mCount] = aTag;
-  }
-#endif
-
-  mStack.PushTag(aTag);
-}
-
-nsTagEntry*
-nsDTDContext::PopEntry()
-{
-  int32_t theSize = mStack.mCount;
-  if(0<theSize) {
-#ifdef  DEBUG
-    if (theSize <= eMaxTags)
-      mXTags[theSize-1]=eHTMLTag_unknown;
-#endif
-    return mStack.PopEntry();
-  }
-  return 0;
-}
-
-void nsDTDContext::PushEntry(nsTagEntry* aEntry, 
-                             bool aRefCntNode)
-{
-#ifdef  DEBUG
-    int size=mStack.mCount;
-    if(size< eMaxTags && aEntry)
-      mXTags[size]=aEntry->mTag;
-#endif
-    mStack.PushEntry(aEntry, aRefCntNode);
-}
-
-/* This method will move the top entries, in the entry-stack, into dest context.
- * @param aDest  - Destination context for the entries.
- * @param aCount - Number of entries, on top of the entry-stack, to be moved.
- */
-void 
-nsDTDContext::MoveEntries(nsDTDContext& aDest,
-                          int32_t aCount)
-{
-  NS_ASSERTION(aCount > 0 && mStack.mCount >= aCount, "cannot move entries");
-  if (aCount > 0 && mStack.mCount >= aCount) {
-    while (aCount) {
-      aDest.PushEntry(&mStack.mEntries[--mStack.mCount], false);
-#ifdef  DEBUG
-      if (mStack.mCount < eMaxTags) {
-        mXTags[mStack.mCount] = eHTMLTag_unknown;
-      }
-#endif
-      --aCount;
-    }
-  }
-}
-
-/** 
- * @update  gess 11/11/99, 
- *          harishd 04/04/99
- */
-nsCParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
-
-  int32_t         theSize=mStack.mCount;
-  nsCParserNode*  result=0;
-
-  if(0<theSize) {
-
-#ifdef  DEBUG
-    if ((theSize>0) && (theSize <= eMaxTags))
-      mXTags[theSize-1]=eHTMLTag_unknown;
-#endif
-
-
-    nsTagEntry* theEntry=mStack.EntryAt(mStack.mCount-1);
-    aChildStyleStack=theEntry->mStyles;
-
-    result=mStack.Pop();
-    theEntry->mParent=0;
-  }
-
-  return result;
-}
- 
-/**
- * 
- * @update  harishd 04/07/00
- */
-
-nsCParserNode* nsDTDContext::Pop() {
-  nsEntryStack   *theTempStyleStack=0; // This has no use here...
-  return Pop(theTempStyleStack);
-}
-
-/**
- * 
- * @update  gess7/9/98
- */
-eHTMLTags nsDTDContext::First(void) const {
-  return mStack.First();
-}
-
-/**
- * 
- * @update  gess7/9/98
- */
-eHTMLTags nsDTDContext::TagAt(int32_t anIndex) const {
-  return mStack.TagAt(anIndex);
-}
-
-/**
- * 
- * @update  gess7/9/98
- */
-nsTagEntry* nsDTDContext::LastEntry(void) const {
-  return mStack.EntryAt(mStack.mCount-1);
-}
-
-/**
- *  
- * @update  gess7/9/98
- */
-eHTMLTags nsDTDContext::Last() const {
-  return mStack.Last();
-}
-
-
-/**
- * 
- * @update  gess7/9/98
- */
-nsEntryStack* nsDTDContext::GetStylesAt(int32_t anIndex) const {
-  nsEntryStack* result=0;
-
-  if(anIndex<mStack.mCount){
-    nsTagEntry* theEntry=mStack.EntryAt(anIndex);
-    if(theEntry) {
-      result=theEntry->mStyles;
-    }
-  }
-  return result;
-}
-
-
-/**
- * 
- * @update  gess 04/28/99
- */
-void nsDTDContext::PushStyle(nsCParserNode* aNode){
-
-  nsTagEntry* theEntry=mStack.EntryAt(mStack.mCount-1);
-  if(theEntry ) {
-    nsEntryStack* theStack=theEntry->mStyles;
-    if(!theStack) {
-      theStack=theEntry->mStyles=new nsEntryStack();
-    }
-    if(theStack) {
-      theStack->Push(aNode);
-      ++mResidualStyleCount;
-    }
-  } //if
-}
-
-
-/**
- * Call this when you have an EntryStack full of styles
- * that you want to push at this level.
- * 
- * @update  gess 04/28/99
- */
-void nsDTDContext::PushStyles(nsEntryStack *aStyles){
-
-  if(aStyles) {
-    nsTagEntry* theEntry=mStack.EntryAt(mStack.mCount-1);
-    if(theEntry ) {
-      nsEntryStack* theStyles=theEntry->mStyles;
-      if(!theStyles) {
-        theEntry->mStyles=aStyles;
-
-        uint32_t scount=aStyles->mCount;
-        uint32_t sindex=0;
-
-        theEntry=aStyles->mEntries;
-        for(sindex=0;sindex<scount;++sindex){            
-          theEntry->mParent=0;  //this tells us that the style is not open at any level
-          ++theEntry;
-          ++mResidualStyleCount;
-        } //for
-
-      }
-      else {
-        theStyles->Append(aStyles);
-        //  Delete aStyles since it has been copied to theStyles...
-        delete aStyles;
-        aStyles=0;
-      }
-    } //if(theEntry )
-    else if(mStack.mCount==0) {
-      // If you're here it means that we have hit the rock bottom
-      // ,of the stack, and there's no need to handle anymore styles.
-      // Fix for bug 29048
-      IF_DELETE(aStyles,mNodeAllocator);
-    }
-  }//if(aStyles)
-}
-
-
-/** 
- * 
- * @update  gess 04/28/99
- */
-nsCParserNode* nsDTDContext::PopStyle(void){
-  nsCParserNode *result=0;
-
-  nsTagEntry *theEntry=mStack.EntryAt(mStack.mCount-1);
-  if(theEntry && (theEntry->mNode)) {
-    nsEntryStack* theStyleStack=theEntry->mParent;
-    if(theStyleStack){
-      result=theStyleStack->Pop();
-      mResidualStyleCount--;
-    }
-  } //if
-  return result;
-}
-
-/** 
- * 
- * @update  gess 04/28/99
- */
-nsCParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
-
-  int32_t theLevel=0;
-  nsCParserNode* result=0;
-
-  for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
-    nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
-    if(theStack) {
-      if(aTag==theStack->Last()) {
-        result=theStack->Pop();
-        mResidualStyleCount--;
-        break; // Fix bug 50710 - Stop after finding a style.
-      } else {
-        // NS_ERROR("bad residual style entry");
-      }
-    } 
-  }
-
-  return result;
-}
-
-/** 
- * 
- * This is similar to popstyle, except that it removes the
- * style tag given from anywhere in the style stack, and
- * not just at the top.
- *
- * @update  gess 01/26/00
- */
-void nsDTDContext::RemoveStyle(eHTMLTags aTag){
-  
-  int32_t theLevel=mStack.mCount;
-  
-  while (theLevel) {
-    nsEntryStack *theStack=GetStylesAt(--theLevel);
-    if (theStack) {
-      int32_t index=theStack->mCount;
-      while (index){
-        nsTagEntry *theEntry=theStack->EntryAt(--index);
-        if (aTag==(eHTMLTags)theEntry->mNode->GetNodeType()) {
-          mResidualStyleCount--;
-          nsCParserNode* result=theStack->Remove(index,aTag);
-          IF_FREE(result, mNodeAllocator);  
-          return;
-        } 
-      }
-    } 
-  }
-}
-
-/**
- * This gets called when the parser module is getting unloaded
- * 
- * @return  nada
- */
-void nsDTDContext::ReleaseGlobalObjects(void){
-}
-
-
-/**************************************************************
-  Now define the nsTokenAllocator class...
- **************************************************************/
-
-/**
- * 
- * @update  gess7/25/98
- * @param 
- */
-nsTokenAllocator::nsTokenAllocator() {
-
-  MOZ_COUNT_CTOR(nsTokenAllocator);
-
-#ifdef DEBUG
-  int i=0;
-  for(i=0;i<eToken_last-1;++i) {
-    mTotals[i]=0;
-  }
-#endif
-
-}
-
-/**
- * Destructor for the token factory
- * @update  gess7/25/98
- */
-nsTokenAllocator::~nsTokenAllocator() {
-
-  MOZ_COUNT_DTOR(nsTokenAllocator);
-
-}
-
-class CTokenFinder: public nsDequeFunctor{
-public:
-  CTokenFinder(CToken* aToken) {mToken=aToken;}
-  virtual void* operator()(void* anObject) {
-    if(anObject==mToken) {
-      return anObject;
-    }
-    return 0;
-  }
-  CToken* mToken;
-};
-
-/**
- * Let's get this code ready to be reused by all the contexts.
- * 
- * @update	rickg 12June2000
- * @param   aType -- tells you the type of token to create
- * @param   aTag  -- tells you the type of tag to init with this token
- * @param   aString -- gives a default string value for the token
- *
- * @return  ptr to new token (or 0).
- */
-CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsAString& aString) {
-
-  CToken* result=0;
-
-#ifdef  DEBUG
-    mTotals[aType-1]++;
-#endif
-  switch(aType){
-    case eToken_start:            result=new(mArenaPool) CStartToken(aString, aTag); break;
-    case eToken_end:              result=new(mArenaPool) CEndToken(aString, aTag); break;
-    case eToken_comment:          result=new(mArenaPool) CCommentToken(aString); break;
-    case eToken_entity:           result=new(mArenaPool) CEntityToken(aString); break;
-    case eToken_whitespace:       result=new(mArenaPool) CWhitespaceToken(aString); break;
-    case eToken_newline:          result=new(mArenaPool) CNewlineToken(); break;
-    case eToken_text:             result=new(mArenaPool) CTextToken(aString); break;
-    case eToken_attribute:        result=new(mArenaPool) CAttributeToken(aString); break;
-    case eToken_instruction:      result=new(mArenaPool) CInstructionToken(aString); break;
-    case eToken_cdatasection:     result=new(mArenaPool) CCDATASectionToken(aString); break;
-    case eToken_doctypeDecl:      result=new(mArenaPool) CDoctypeDeclToken(aString); break;
-    case eToken_markupDecl:       result=new(mArenaPool) CMarkupDeclToken(aString); break;
-      default:
-        NS_ASSERTION(false, "nsDTDUtils::CreateTokenOfType: illegal token type"); 
-        break;
-  }
-
-  return result;
-}
-
-/**
- * Let's get this code ready to be reused by all the contexts.
- * 
- * @update	rickg 12June2000
- * @param   aType -- tells you the type of token to create
- * @param   aTag  -- tells you the type of tag to init with this token
- *
- * @return  ptr to new token (or 0).
- */
-CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag) {
-
-  CToken* result=0;
-
-#ifdef  DEBUG
-    mTotals[aType-1]++;
-#endif
-  switch(aType){
-    case eToken_start:            result=new(mArenaPool) CStartToken(aTag); break;
-    case eToken_end:              result=new(mArenaPool) CEndToken(aTag); break;
-    case eToken_comment:          result=new(mArenaPool) CCommentToken(); break;
-    case eToken_attribute:        result=new(mArenaPool) CAttributeToken(); break;
-    case eToken_entity:           result=new(mArenaPool) CEntityToken(); break;
-    case eToken_whitespace:       result=new(mArenaPool) CWhitespaceToken(); break;
-    case eToken_newline:          result=new(mArenaPool) CNewlineToken(); break;
-    case eToken_text:             result=new(mArenaPool) CTextToken(); break;
-    case eToken_instruction:      result=new(mArenaPool) CInstructionToken(); break;
-    case eToken_cdatasection:     result=new(mArenaPool) CCDATASectionToken(aTag); break;
-    case eToken_doctypeDecl:      result=new(mArenaPool) CDoctypeDeclToken(aTag); break;
-    case eToken_markupDecl:       result=new(mArenaPool) CMarkupDeclToken(); break;
-    default:
-      NS_ASSERTION(false, "nsDTDUtils::CreateTokenOfType: illegal token type"); 
-      break;
-   }
-
-  return result;
-}
-
-#ifdef DEBUG_TRACK_NODES 
-
-static nsCParserNode* gAllNodes[100];
-static int gAllNodeCount=0;
-
-int FindNode(nsCParserNode *aNode) {
-  int theIndex=0;
-  for(theIndex=0;theIndex<gAllNodeCount;++theIndex) {
-    if(gAllNodes[theIndex]==aNode) {
-      return theIndex;
-    }
-  }
-  return -1;
-}
-
-void AddNode(nsCParserNode *aNode) {
-  if(-1==FindNode(aNode)) {
-    gAllNodes[gAllNodeCount++]=aNode;
-  }
-  else {
-    //you tried to recycle a node twice!
-  }
-}
-
-void RemoveNode(nsCParserNode *aNode) {
-  int theIndex=FindNode(aNode);
-  if(-1<theIndex) {
-    gAllNodes[theIndex]=gAllNodes[--gAllNodeCount];
-  }
-}
-
-#endif 
-
-
-#ifdef HEAP_ALLOCATED_NODES
-nsNodeAllocator::nsNodeAllocator():mSharedNodes(0){
-#ifdef DEBUG_TRACK_NODES
-  mCount=0;
-#endif
-#else 
-nsNodeAllocator::nsNodeAllocator() {
-#endif
-  MOZ_COUNT_CTOR(nsNodeAllocator);
-}
-
-nsNodeAllocator::~nsNodeAllocator() {
-  MOZ_COUNT_DTOR(nsNodeAllocator);
-
-#ifdef HEAP_ALLOCATED_NODES
-  nsCParserNode* theNode = 0;
-
-  while((theNode=(nsCParserNode*)mSharedNodes.Pop())){
-#ifdef DEBUG_TRACK_NODES
-    RemoveNode(theNode);
-#endif
-    ::operator delete(theNode); 
-    theNode=nullptr;
-  }
-#ifdef DEBUG_TRACK_NODES
-  if(mCount) {
-    printf("**************************\n");
-    printf("%i out of %i nodes leaked!\n",gAllNodeCount,mCount);
-    printf("**************************\n");
-  }
-#endif
-#endif
-}
-  
-nsCParserNode* nsNodeAllocator::CreateNode(CToken* aToken,  
-                                           nsTokenAllocator* aTokenAllocator) 
-{
-  nsCParserNode* result = 0;
-#ifdef HEAP_ALLOCATED_NODES
-#if 0
-  if(gAllNodeCount!=mSharedNodes.GetSize()) {
-    int x=10; //this is very BAD!
-  }
-#endif
-  result = static_cast<nsCParserNode*>(mSharedNodes.Pop());
-  if (result) {
-    result->Init(aToken, aTokenAllocator,this);
-  }
-  else{
-    result = nsCParserNode::Create(aToken, aTokenAllocator,this);
-#ifdef DEBUG_TRACK_NODES
-    ++mCount;
-    AddNode(static_cast<nsCParserNode*>(result));
-#endif
-    IF_HOLD(result);
-  }
-#else
-  eHTMLTokenTypes type = aToken ? eHTMLTokenTypes(aToken->GetTokenType()) : eToken_unknown;
-  switch (type) {
-    case eToken_start:
-      result = nsCParserStartNode::Create(aToken, aTokenAllocator,this); 
-      break;
-    default :
-      result = nsCParserNode::Create(aToken, aTokenAllocator,this); 
-      break;
-  }
-  IF_HOLD(result);
-#endif
-  return result;
-}
-
-#ifdef DEBUG
-void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle) {
-}
-#endif
deleted file mode 100644
--- a/parser/htmlparser/src/nsDTDUtils.h
+++ /dev/null
@@ -1,453 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sw=2 et tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-/**
- * MODULE NOTES:
- * @update  gess 4/1/98
- * 
- */
-
-
-
-#ifndef DTDUTILS_
-#define DTDUTILS_
-
-#include "nsHTMLTags.h"
-#include "nsHTMLTokens.h"
-#include "nsIParser.h"
-#include "nsCRT.h"
-#include "nsDeque.h"
-#include "nsIDTD.h"
-#include "nsITokenizer.h"
-#include "nsString.h"
-#include "nsIParserNode.h"
-#include "nsCOMArray.h"
-#include "nsIParserService.h"
-#include "nsReadableUtils.h"
-#include "nsIHTMLContentSink.h"
-#include "nsIFrame.h"
-
-#define IF_HOLD(_ptr) \
- PR_BEGIN_MACRO       \
- if(_ptr) {           \
-   _ptr->AddRef();    \
- }                    \
- PR_END_MACRO
-
-// recycles _ptr
-#define IF_FREE(_ptr, _allocator)                \
-  PR_BEGIN_MACRO                                 \
-  if(_ptr && _allocator) {                       \
-    _ptr->Release((_allocator)->GetArenaPool()); \
-    _ptr=0;                                      \
-  }                                              \
-  PR_END_MACRO   
-
-// release objects and destroy _ptr
-#define IF_DELETE(_ptr, _allocator) \
-  PR_BEGIN_MACRO                    \
-  if(_ptr) {                        \
-    _ptr->ReleaseAll(_allocator);   \
-    delete(_ptr);                   \
-    _ptr=0;                         \
-  }                                 \
-  PR_END_MACRO
-
-class nsIParserNode;
-class nsCParserNode;
-class nsNodeAllocator;
-
-
-#ifdef DEBUG
-void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle);
-void DebugDumpContainmentRules2(nsIDTD& theDTD,const char* aFilename,const char* aTitle);
-#endif
-
-/***************************************************************
-  First, define the tagstack class
- ***************************************************************/
-
-class nsEntryStack;  //forware declare to make compilers happy.
-
-struct nsTagEntry {
-  nsTagEntry ()
-    : mTag(eHTMLTag_unknown), mNode(0), mParent(0), mStyles(0){}
-  eHTMLTags       mTag;  //for speedier access to tag id
-  nsCParserNode*  mNode;
-  nsEntryStack*   mParent;
-  nsEntryStack*   mStyles;
-};
-
-class nsEntryStack {
-
-public:
-                  nsEntryStack();
-                  ~nsEntryStack();
-
-  nsTagEntry*     PopEntry();
-  void            PushEntry(nsTagEntry* aEntry, bool aRefCntNode = true);
-  void            EnsureCapacityFor(int32_t aNewMax, int32_t aShiftOffset=0);
-  void            Push(nsCParserNode* aNode,nsEntryStack* aStyleStack=0, bool aRefCntNode = true);
-  void            PushTag(eHTMLTags aTag);
-  void            PushFront(nsCParserNode* aNode,nsEntryStack* aStyleStack=0, bool aRefCntNode = true);
-  void            Append(nsEntryStack *aStack);
-  nsCParserNode*  Pop(void);
-  nsCParserNode*  Remove(int32_t anIndex,eHTMLTags aTag);
-  nsCParserNode*  NodeAt(int32_t anIndex) const;
-  eHTMLTags       First() const;
-  eHTMLTags       TagAt(int32_t anIndex) const;
-  nsTagEntry*     EntryAt(int32_t anIndex) const;
-  eHTMLTags       operator[](int32_t anIndex) const;
-  eHTMLTags       Last() const;
-  void            Empty(void); 
-
-  /*
-   * Release all objects in the entry stack
-   */
-  void ReleaseAll(nsNodeAllocator* aNodeAllocator);
-  
-  /**
-   * Find the first instance of given tag on the stack.
-   * @update	gess 12/14/99
-   * @param   aTag
-   * @return  index of tag, or kNotFound if not found
-   */
-  inline int32_t FirstOf(eHTMLTags aTag) const {
-    int32_t index=-1;
-    
-    if(0<mCount) {
-      while(++index<mCount) {
-        if(aTag==mEntries[index].mTag) {
-          return index;
-        }
-      } //while
-    }
-    return kNotFound;
-  }
-
-
-  /**
-   * Find the last instance of given tag on the stack.
-   * @update	gess 12/14/99
-   * @param   aTag
-   * @return  index of tag, or kNotFound if not found
-   */
-  inline int32_t LastOf(eHTMLTags aTag) const {
-    int32_t index=mCount;
-    while(--index>=0) {
-        if(aTag==mEntries[index].mTag) {
-          return index; 
-        }
-    }
-    return kNotFound;
-  }
-
-  nsTagEntry* mEntries;
-  int32_t    mCount;
-  int32_t    mCapacity;
-};
-
-
-/**********************************************************
-  The table state class is used to store info about each
-  table that is opened on the stack. As tables open and
-  close on the context, we update these objects to track 
-  what has/hasn't been seen on a per table basis. 
- **********************************************************/
-class CTableState {
-public:
-  CTableState(CTableState *aPreviousState=0) {
-    mHasCaption=false;
-    mHasCols=false;
-    mHasTHead=false;
-    mHasTFoot=false;
-    mHasTBody=false;    
-    mPrevious=aPreviousState;
-  }
-
-  bool    CanOpenCaption() {
-    bool result=!(mHasCaption || mHasCols || mHasTHead || mHasTFoot || mHasTBody);
-    return result;
-  }
-
-  bool    CanOpenCols() {
-    bool result=!(mHasCols || mHasTHead || mHasTFoot || mHasTBody);
-    return result;
-  }
-
-  bool    CanOpenTBody() {
-    bool result=!(mHasTBody);
-    return result;
-  }
-
-  bool    CanOpenTHead() {
-    bool result=!(mHasTHead || mHasTFoot || mHasTBody);
-    return result;
-  }
-
-  bool    CanOpenTFoot() {
-    bool result=!(mHasTFoot || mHasTBody);
-    return result;
-  }
-
-  bool          mHasCaption;
-  bool          mHasCols;
-  bool          mHasTHead;
-  bool          mHasTFoot;
-  bool          mHasTBody;
-  CTableState   *mPrevious;
-};
-
-/************************************************************************
-  nsTokenAllocator class implementation.
-  This class is used to recycle tokens. 
-  By using this simple class, we cut WAY down on the number of tokens
-  that get created during the run of the system.
-
-  Note: The allocator is created per document. It's been shared 
-        ( but not ref. counted ) by objects, tokenizer,dtd,and dtd context,
-        that cease to exist when the document is destroyed.
- ************************************************************************/
-class nsTokenAllocator
-{
-public: 
-
-  nsTokenAllocator();
-  ~nsTokenAllocator();
-  CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsAString& aString);
-  CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag);
-
-  nsDummyAllocator& GetArenaPool() { return mArenaPool; }
-
-protected:
-  nsDummyAllocator mArenaPool;
-#ifdef  DEBUG
-  int mTotals[eToken_last-1];
-#endif
-};
-
-/************************************************************************
-  CNodeRecycler class implementation.
-  This class is used to recycle nodes. 
-  By using this simple class, we cut down on the number of nodes
-  that get created during the run of the system.
- ************************************************************************/
-
-#ifndef HEAP_ALLOCATED_NODES
-class nsCParserNode;
-#endif
-
-class nsNodeAllocator
-{
-public:
-  
-  nsNodeAllocator();
-  ~nsNodeAllocator();
-  nsCParserNode* CreateNode(CToken* aToken=nullptr, nsTokenAllocator* aTokenAllocator=0);
-
-  nsDummyAllocator&  GetArenaPool() { return mNodePool; }
-
-#ifdef HEAP_ALLOCATED_NODES
-  void Recycle(nsCParserNode* aNode) { mSharedNodes.Push(static_cast<void*>(aNode)); }
-protected:
-  nsDeque mSharedNodes;
-#ifdef DEBUG_TRACK_NODES
-  int32_t mCount;
-#endif
-#endif
-
-protected:
-  nsDummyAllocator mNodePool;
-};
-
-/************************************************************************
-  The dtdcontext class defines an ordered list of tags (a context).
- ************************************************************************/
-
-class nsDTDContext
-{
-public:
-                  nsDTDContext();
-                  ~nsDTDContext();
-
-  nsTagEntry*     PopEntry();
-  void            PushEntry(nsTagEntry* aEntry, bool aRefCntNode = true);
-  void            MoveEntries(nsDTDContext& aDest, int32_t aCount);
-  void            Push(nsCParserNode* aNode,nsEntryStack* aStyleStack=0, bool aRefCntNode = true);
-  void            PushTag(eHTMLTags aTag);
-  nsCParserNode*  Pop(nsEntryStack*& aChildStack);
-  nsCParserNode*  Pop();
-  nsCParserNode*  PeekNode() { return mStack.NodeAt(mStack.mCount-1); }
-  eHTMLTags       First(void) const;
-  eHTMLTags       Last(void) const;
-  nsTagEntry*     LastEntry(void) const;
-  eHTMLTags       TagAt(int32_t anIndex) const;
-  eHTMLTags       operator[](int32_t anIndex) const {return TagAt(anIndex);}
-  bool            HasOpenContainer(eHTMLTags aTag) const;
-  int32_t         FirstOf(eHTMLTags aTag) const {return mStack.FirstOf(aTag);}
-  int32_t         LastOf(eHTMLTags aTag) const {return mStack.LastOf(aTag);}
-
-  void            Empty(void); 
-  int32_t         GetCount(void) const {return mStack.mCount;}
-  int32_t         GetResidualStyleCount(void) {return mResidualStyleCount;}
-  nsEntryStack*   GetStylesAt(int32_t anIndex) const;
-  void            PushStyle(nsCParserNode* aNode);
-  void            PushStyles(nsEntryStack *aStyles);
-  nsCParserNode*  PopStyle(void);
-  nsCParserNode*  PopStyle(eHTMLTags aTag);
-  void            RemoveStyle(eHTMLTags aTag);
-
-  static  void    ReleaseGlobalObjects(void);
-
-  void            SetTokenAllocator(nsTokenAllocator* aTokenAllocator) { mTokenAllocator=aTokenAllocator; }
-  void            SetNodeAllocator(nsNodeAllocator* aNodeAllocator) { mNodeAllocator=aNodeAllocator; }
-
-  nsEntryStack    mStack; //this will hold a list of tagentries...
-  int32_t         mResidualStyleCount;
-  int32_t         mContextTopIndex;
-
-  nsTokenAllocator  *mTokenAllocator;
-  nsNodeAllocator   *mNodeAllocator;
-
-#ifdef  DEBUG
-  enum { eMaxTags = MAX_REFLOW_DEPTH };
-  eHTMLTags       mXTags[eMaxTags];
-#endif
-};
-
-/**************************************************************
-  Now define the token deallocator class...
- **************************************************************/
-class CTokenDeallocator: public nsDequeFunctor{
-protected:
-  nsDummyAllocator& mArenaPool;
-
-public:
-  CTokenDeallocator(nsDummyAllocator& aArenaPool)
-    : mArenaPool(aArenaPool) {}
-
-  virtual void* operator()(void* anObject) {
-    CToken* aToken = (CToken*)anObject;
-    aToken->Release(mArenaPool);
-    return 0;
-  }
-};
-
-
-/************************************************************************
-  ITagHandler class offers an API for taking care of specific tokens.
- ************************************************************************/
-class nsITagHandler {
-public:
-  
-  virtual void          SetString(const nsString &aTheString)=0;
-  virtual nsString*     GetString()=0;
-  virtual bool          HandleToken(CToken* aToken,nsIDTD* aDTD)=0;
-  virtual bool          HandleCapturedTokens(CToken* aToken,nsIDTD* aDTD)=0;
-};
-
-/************************************************************************
-  Here are a few useful utility methods...
- ************************************************************************/
-
-/**
- * This method quickly scans the given set of tags,
- * looking for the given tag.
- * @update	gess8/27/98
- * @param   aTag -- tag to be search for in set
- * @param   aTagSet -- set of tags to be searched
- * @return
- */
-inline int32_t IndexOfTagInSet(int32_t aTag,const eHTMLTags* aTagSet,int32_t aCount)  {
-
-  const eHTMLTags* theEnd=aTagSet+aCount;
-  const eHTMLTags* theTag=aTagSet;
-
-  while(theTag<theEnd) {
-    if(aTag==*theTag) {
-      return theTag-aTagSet;
-    }
-    ++theTag;
-  }
-
-  return kNotFound;
-}
-
-/**
- * This method quickly scans the given set of tags,
- * looking for the given tag.
- * @update	gess8/27/98
- * @param   aTag -- tag to be search for in set
- * @param   aTagSet -- set of tags to be searched
- * @return
- */
-inline bool FindTagInSet(int32_t aTag,const eHTMLTags *aTagSet,int32_t aCount)  {
-  return bool(-1<IndexOfTagInSet(aTag,aTagSet,aCount));
-}
-
-/*********************************************************************************************/
-
-struct TagList {
-  size_t mCount;
-  const eHTMLTags *mTags;
-};
-
-/**
- * Find the last member of given taglist on the given context
- * @update	gess 12/14/99
- * @param   aContext
- * @param   aTagList
- * @return  index of tag, or kNotFound if not found
- */
-inline int32_t LastOf(nsDTDContext& aContext, const TagList& aTagList){
-  int max = aContext.GetCount();
-  int index;
-  for(index=max-1;index>=0;index--){
-    bool result=FindTagInSet(aContext[index],aTagList.mTags,aTagList.mCount);
-    if(result) {
-      return index;
-    }
-  }
-  return kNotFound;
-}
- 
-/**
- * Find the first member of given taglist on the given context
- * @update	gess 12/14/99
- * @param   aContext
- * @param   aStartOffset
- * @param   aTagList
- * @return  index of tag, or kNotFound if not found
- */
-inline int32_t FirstOf(nsDTDContext& aContext,int32_t aStartOffset,TagList& aTagList){
-  int max = aContext.GetCount();
-  int index;
-  for(index=aStartOffset;index<max;++index){
-    bool result=FindTagInSet(aContext[index],aTagList.mTags,aTagList.mCount);
-    if(result) {
-      return index;
-    }
-  }
-  return kNotFound;
-}
-
-
-/**
- * Call this to find out whether the DTD thinks the tag requires an END tag </xxx>
- * @update	gess 01/04/99
- * @param   id of tag
- * @return  TRUE of the element's end tag is optional
- */
-inline bool HasOptionalEndTag(eHTMLTags aTag) {
-  static eHTMLTags gHasOptionalEndTags[]={eHTMLTag_body,eHTMLTag_colgroup,eHTMLTag_dd,eHTMLTag_dt,
-                                                    eHTMLTag_head,eHTMLTag_li,eHTMLTag_option,
-                                                    eHTMLTag_p,eHTMLTag_tbody,eHTMLTag_td,eHTMLTag_tfoot,
-                                                    eHTMLTag_th,eHTMLTag_thead,eHTMLTag_tr,
-                                                    eHTMLTag_userdefined,eHTMLTag_unknown};
-  return FindTagInSet(aTag,gHasOptionalEndTags,sizeof(gHasOptionalEndTags)/sizeof(eHTMLTag_body));
-}
-#endif
--- a/parser/htmlparser/src/nsElementTable.cpp
+++ b/parser/htmlparser/src/nsElementTable.cpp
@@ -7,2225 +7,577 @@
 
 #include "nsIAtom.h"
 #include "nsElementTable.h"
 
 /***************************************************************************** 
   Now it's time to list all the html elements all with their capabilities...
 ******************************************************************************/
 
-#define DECL_TAG_LIST(name_, list_)                                           \
-  static const eHTMLTags name_##list[] = list_;                               \
-  static const TagList name_ = { NS_ARRAY_LENGTH(name_##list), name_##list };
-
-#define COMMA ,
-
-//First, define the set of taglists for tags with special parents...
-DECL_TAG_LIST(gAParents,{eHTMLTag_map})
-DECL_TAG_LIST(gInAddress,{eHTMLTag_address})
-DECL_TAG_LIST(gInHead,{eHTMLTag_head})
-DECL_TAG_LIST(gInTable,{eHTMLTag_table})
-DECL_TAG_LIST(gInHTML,{eHTMLTag_html})
-DECL_TAG_LIST(gInBody,{eHTMLTag_body})
-DECL_TAG_LIST(gInForm,{eHTMLTag_form})
-DECL_TAG_LIST(gInFieldset,{eHTMLTag_fieldset})
-DECL_TAG_LIST(gInTR,{eHTMLTag_tr})
-DECL_TAG_LIST(gInDL,{eHTMLTag_dl COMMA eHTMLTag_body})
-DECL_TAG_LIST(gInFrameset,{eHTMLTag_frameset})
-DECL_TAG_LIST(gInNoframes,{eHTMLTag_noframes})
-//Removed ADDRESS to solve 24885
-// gInP: nsHTMLElement::CanContain() also allows table in Quirks mode for bug 43678, removed FORM bug 94269
-DECL_TAG_LIST(gInP,{eHTMLTag_span})
-DECL_TAG_LIST(gOptgroupParents,{eHTMLTag_select COMMA eHTMLTag_optgroup})
-DECL_TAG_LIST(gBodyParents,{eHTMLTag_html COMMA eHTMLTag_noframes})
-DECL_TAG_LIST(gColParents,{eHTMLTag_table COMMA eHTMLTag_colgroup})
-DECL_TAG_LIST(gFramesetParents,{eHTMLTag_html COMMA eHTMLTag_frameset})
-DECL_TAG_LIST(gLegendParents,{eHTMLTag_fieldset})
-DECL_TAG_LIST(gAreaParent,{eHTMLTag_map})
-DECL_TAG_LIST(gParamParents,{eHTMLTag_applet COMMA eHTMLTag_object})
-DECL_TAG_LIST(gTRParents,{eHTMLTag_tbody COMMA eHTMLTag_tfoot COMMA eHTMLTag_thead COMMA eHTMLTag_table})
-DECL_TAG_LIST(gTREndParents,{eHTMLTag_tbody COMMA eHTMLTag_tfoot COMMA eHTMLTag_thead COMMA eHTMLTag_table COMMA eHTMLTag_applet})
-DECL_TAG_LIST(gSourceParents,{eHTMLTag_video COMMA eHTMLTag_audio})
-DECL_TAG_LIST(gTrackParents,{eHTMLTag_video COMMA eHTMLTag_audio})
-
-//*********************************************************************************************
-//  Next, define the set of taglists for tags with special kids...
-//*********************************************************************************************
-
-DECL_TAG_LIST(gContainsText,{eHTMLTag_text COMMA eHTMLTag_newline COMMA eHTMLTag_whitespace COMMA eHTMLTag_entity})
-DECL_TAG_LIST(gUnknownKids,{eHTMLTag_html COMMA eHTMLTag_frameset})
-
-// The presence of <input>, <select>, and <textarea> in gContainsOpts is due to
-// the exclgroup that <select> sets...  If I don't include those here, they
-// just get dropped automatically, since they are not allowed to open inside
-// <select>.  Note that we are NOT allowing them to actually open without
-// closing the select -- see gInputAutoClose.  Further note that I'm not
-// including <button> in the list because in IE it doesn't autoclose <select>!
-DECL_TAG_LIST(gContainsOpts,{eHTMLTag_option COMMA eHTMLTag_optgroup COMMA eHTMLTag_script COMMA eHTMLTag_input COMMA eHTMLTag_select COMMA eHTMLTag_textarea })
-// Similar deal for <option> except it allows all of gContainsText _and_ the things that should autoclose selects.
-DECL_TAG_LIST(gContainedInOpt,{eHTMLTag_text COMMA eHTMLTag_newline COMMA eHTMLTag_whitespace COMMA eHTMLTag_entity COMMA eHTMLTag_input COMMA eHTMLTag_select COMMA eHTMLTag_textarea})
-DECL_TAG_LIST(gContainsParam,{eHTMLTag_param})
-DECL_TAG_LIST(gColgroupKids,{eHTMLTag_col}) 
-DECL_TAG_LIST(gAddressKids,{eHTMLTag_p})
-DECL_TAG_LIST(gBodyKids,{eHTMLTag_dd COMMA eHTMLTag_del COMMA eHTMLTag_dt COMMA eHTMLTag_ins COMMA  eHTMLTag_noscript COMMA eHTMLTag_script COMMA eHTMLTag_li COMMA eHTMLTag_param}) // Added PARAM for bug 54448
-DECL_TAG_LIST(gButtonKids,{eHTMLTag_caption COMMA eHTMLTag_legend})
-
-DECL_TAG_LIST(gDLRootTags,{eHTMLTag_body COMMA eHTMLTag_td COMMA eHTMLTag_table COMMA eHTMLTag_applet COMMA eHTMLTag_dd})
-DECL_TAG_LIST(gDLKids,{eHTMLTag_dd COMMA eHTMLTag_dt})
-DECL_TAG_LIST(gDTKids,{eHTMLTag_dt})
-DECL_TAG_LIST(gFieldsetKids,{eHTMLTag_legend COMMA eHTMLTag_text})
-DECL_TAG_LIST(gFontKids,{eHTMLTag_legend COMMA eHTMLTag_table COMMA eHTMLTag_text COMMA eHTMLTag_li}) // Added table to fix bug 93365, li to fix bug 96031
-DECL_TAG_LIST(gFormKids,{eHTMLTag_keygen})
-DECL_TAG_LIST(gFramesetKids,{eHTMLTag_frame COMMA eHTMLTag_frameset COMMA eHTMLTag_noframes})
-
-DECL_TAG_LIST(gHtmlKids,{eHTMLTag_body COMMA eHTMLTag_frameset COMMA eHTMLTag_head COMMA eHTMLTag_noscript COMMA eHTMLTag_noframes COMMA eHTMLTag_script COMMA eHTMLTag_newline COMMA eHTMLTag_whitespace})
-
-DECL_TAG_LIST(gLabelKids,{eHTMLTag_span})
-DECL_TAG_LIST(gLIKids,{eHTMLTag_ol COMMA eHTMLTag_ul})
-DECL_TAG_LIST(gMapKids,{eHTMLTag_area})
-DECL_TAG_LIST(gPreKids,{eHTMLTag_hr COMMA eHTMLTag_center})  //note that CENTER is here for backward compatibility; it's not 4.0 spec.
-
-DECL_TAG_LIST(gTableKids,{eHTMLTag_caption COMMA eHTMLTag_col COMMA eHTMLTag_colgroup COMMA eHTMLTag_form COMMA  eHTMLTag_thead COMMA eHTMLTag_tbody COMMA eHTMLTag_tfoot COMMA eHTMLTag_script})// Removed INPUT - Ref. Bug 20087, 25382
-  
-DECL_TAG_LIST(gTableElemKids,{eHTMLTag_form COMMA eHTMLTag_noscript COMMA eHTMLTag_script COMMA eHTMLTag_td COMMA eHTMLTag_th COMMA eHTMLTag_tr})
-DECL_TAG_LIST(gTRKids,{eHTMLTag_td COMMA eHTMLTag_th COMMA eHTMLTag_form COMMA eHTMLTag_script})// Removed INPUT - Ref. Bug 20087, 25382 |  Removed MAP to fix 58942
-DECL_TAG_LIST(gTBodyKids,{eHTMLTag_tr COMMA eHTMLTag_form}) // Removed INPUT - Ref. Bug 20087, 25382
-DECL_TAG_LIST(gULKids,{eHTMLTag_li COMMA eHTMLTag_p})
-DECL_TAG_LIST(gVideoKids,{eHTMLTag_source COMMA eHTMLTag_track})
-DECL_TAG_LIST(gAudioKids,{eHTMLTag_source COMMA eHTMLTag_track})
-
-//*********************************************************************************************
-// The following tag lists are used to define common set of root notes for the HTML elements...
-//*********************************************************************************************
-
-DECL_TAG_LIST(gRootTags,{eHTMLTag_body COMMA eHTMLTag_td COMMA eHTMLTag_table COMMA eHTMLTag_applet COMMA eHTMLTag_select}) // Added SELECT to fix bug 98645
-DECL_TAG_LIST(gTableRootTags,{eHTMLTag_applet COMMA eHTMLTag_body COMMA eHTMLTag_dl COMMA eHTMLTag_ol COMMA eHTMLTag_td COMMA eHTMLTag_th})
-DECL_TAG_LIST(gHTMLRootTags,{eHTMLTag_unknown})
- 
-DECL_TAG_LIST(gLIRootTags,{eHTMLTag_ul COMMA eHTMLTag_ol COMMA eHTMLTag_dir COMMA eHTMLTag_menu COMMA eHTMLTag_p COMMA eHTMLTag_body COMMA eHTMLTag_td COMMA eHTMLTag_th})
-
-DECL_TAG_LIST(gOLRootTags,{eHTMLTag_body COMMA eHTMLTag_li COMMA eHTMLTag_td COMMA eHTMLTag_th COMMA eHTMLTag_select})
-DECL_TAG_LIST(gTDRootTags,{eHTMLTag_tr COMMA eHTMLTag_tbody COMMA eHTMLTag_thead COMMA eHTMLTag_tfoot COMMA eHTMLTag_table COMMA eHTMLTag_applet})
-DECL_TAG_LIST(gNoframeRoot,{eHTMLTag_body COMMA eHTMLTag_frameset})
-
-//*********************************************************************************************
-// The following tag lists are used to define the autoclose properties of the html elements...
-//*********************************************************************************************
-
-DECL_TAG_LIST(gBodyAutoClose,{eHTMLTag_head})
-DECL_TAG_LIST(gTBodyAutoClose,{eHTMLTag_thead COMMA eHTMLTag_tfoot COMMA eHTMLTag_tbody COMMA eHTMLTag_td COMMA eHTMLTag_th})  // TD|TH inclusion - Bug# 24112
-DECL_TAG_LIST(gCaptionAutoClose,{eHTMLTag_tbody})
-DECL_TAG_LIST(gLIAutoClose,{eHTMLTag_p COMMA eHTMLTag_li})
-DECL_TAG_LIST(gPAutoClose,{eHTMLTag_p COMMA eHTMLTag_li})
-DECL_TAG_LIST(gHRAutoClose,{eHTMLTag_p})
-DECL_TAG_LIST(gOLAutoClose,{eHTMLTag_p COMMA eHTMLTag_ol})
-DECL_TAG_LIST(gDivAutoClose,{eHTMLTag_p})
-// Form controls that autoclose <select> use this
-DECL_TAG_LIST(gInputAutoClose,{eHTMLTag_select COMMA eHTMLTag_optgroup COMMA eHTMLTag_option})
-
-DECL_TAG_LIST(gHeadingTags,{eHTMLTag_h1 COMMA eHTMLTag_h2 COMMA eHTMLTag_h3 COMMA eHTMLTag_h4 COMMA eHTMLTag_h5 COMMA eHTMLTag_h6})
-
-DECL_TAG_LIST(gTableCloseTags,{eHTMLTag_td COMMA eHTMLTag_tr COMMA eHTMLTag_th COMMA eHTMLTag_tbody COMMA eHTMLTag_thead COMMA eHTMLTag_tfoot})
-DECL_TAG_LIST(gTRCloseTags,{eHTMLTag_tr COMMA eHTMLTag_td COMMA eHTMLTag_th})
-DECL_TAG_LIST(gTDCloseTags,{eHTMLTag_td COMMA eHTMLTag_th})
-DECL_TAG_LIST(gDTCloseTags,{eHTMLTag_p COMMA eHTMLTag_dd COMMA eHTMLTag_dt})
-DECL_TAG_LIST(gULCloseTags,{eHTMLTag_li})
-DECL_TAG_LIST(gULAutoClose,{eHTMLTag_p COMMA eHTMLTag_ul}) //fix bug 50261..
-
-DECL_TAG_LIST(gExcludableParents,{eHTMLTag_pre}) // Ref Bug 22913
-DECL_TAG_LIST(gCaptionExcludableParents,{eHTMLTag_td}) //Ref Bug 26488
-
-//*********************************************************************************************
-//Lastly, bind tags with their rules, their special parents and special kids.
-//*********************************************************************************************
-
-
-const int kNoPropRange=0;
-const int kDefaultPropRange=1;
-const int kBodyPropRange=2;
-
-//*********************************************************************************************
-//
-//        Now let's declare the element table...
-//
-//*********************************************************************************************
-
+// The Element Table (sung to the tune of Modern Major General)
 
 const nsHTMLElement gHTMLElements[] = {
   {
-    /*tag*/                             eHTMLTag_unknown,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,  
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer, 10,
-    /*special parents,kids*/            0,&gUnknownKids,
+    /*tag*/         eHTMLTag_unknown,
+    /*parent,leaf*/ kNone, true
   },
   {
-    /*tag*/                             eHTMLTag_a,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kInlineEntity, kNone,  
-    /*special props, prop-range*/       kVerifyHierarchy, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_a,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_abbr,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_abbr,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_acronym,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_acronym,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_address,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, kInlineEntity, kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,&gAddressKids,
+    /*tag*/         eHTMLTag_address,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_applet,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kSelf|kInlineEntity|kFlowEntity), kNone,
-    /*special props, prop-range*/       kRequiresBody,kDefaultPropRange,
-    /*special parents,kids*/            0,&gContainsParam,
+    /*tag*/         eHTMLTag_applet,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_area,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gAreaParent,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kInlineEntity, kSelf,
-    /*special props, prop-range*/       kNonContainer,kDefaultPropRange,
-    /*special parents,kids*/            &gAreaParent,0,
+    /*tag*/         eHTMLTag_area,
+    /*parent,leaf*/ kNone, true
   },
   {
-    /*tag*/                             eHTMLTag_article,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_article,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_aside,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_aside,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_audio,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0, 0, 0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kFlowEntity|kSelf), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,&gAudioKids,
+    /*tag*/         eHTMLTag_audio,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_b,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFontStyle, (kInlineEntity|kSelf), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_b,
+    /*parent,leaf*/ kFontStyle, false
   },
   {
-    /*tag*/                             eHTMLTag_base,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInHead,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kHeadContent, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer, kNoPropRange,
-    /*special parents,kids*/            &gInHead,0,
+    /*tag*/         eHTMLTag_base,
+    /*parent,leaf*/ kHeadContent, true
   },
   {
-    /*tag*/                             eHTMLTag_basefont,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kInlineEntity, kNone,
-    /*special props, prop-range*/       kNonContainer, kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_basefont,
+    /*parent,leaf*/ kSpecial, true
   },
   {
-    /*tag*/                             eHTMLTag_bdo,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_bdo,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_bgsound,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          (kFlowEntity|kHeadMisc), kNone, kNone,
-    /*special props, prop-range*/       kNonContainer,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_bgsound,
+    /*parent,leaf*/ (kFlowEntity|kHeadMisc), true
   },
   {
-    /*tag*/                             eHTMLTag_big,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFontStyle, (kInlineEntity|kSelf), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_big,
+    /*parent,leaf*/ kFontStyle, false
   },
   {
-    /*tag*/                             eHTMLTag_blockquote,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,  //remove excludeable parents to fix bug 53473
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_blockquote,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_body,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_frameset,
-    /*rootnodes,endrootnodes*/          &gInHTML,&gInHTML,
-    /*autoclose starttags and endtags*/ &gBodyAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kHTMLContent,(kFlowEntity|kSelf), kNone,
-    /*special props, prop-range*/       kOmitEndTag, kBodyPropRange,
-    /*special parents,kids*/            0,&gBodyKids,
+    /*tag*/         eHTMLTag_body,
+    /*parent,leaf*/ kHTMLContent, false
   },
   {
-    /*tag*/                             eHTMLTag_br,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,
-    /*special props, prop-range*/       kRequiresBody|kNonContainer, kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_br,
+    /*parent,leaf*/ kSpecial, true
   },
   {
-    /*tag*/                             eHTMLTag_button,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFormControl, kFlowEntity, kFormControl,
-    /*special props, prop-range*/       kRequiresBody,kDefaultPropRange,
-    /*special parents,kids*/            0,&gButtonKids,
+    /*tag*/         eHTMLTag_button,
+    /*parent,leaf*/ kFormControl, false
   },
   {
-    /*tag*/                             eHTMLTag_canvas,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kFlowEntity|kSelf), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_canvas,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_caption,
-    /*req-parent excl-parent*/          eHTMLTag_table,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInTable,&gInTable,
-    /*autoclose starttags and endtags*/ &gCaptionAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kFlowEntity, kSelf,
-    /*special props, prop-range*/       (kNoPropagate|kNoStyleLeaksOut),kDefaultPropRange,
-    /*special parents,kids*/            &gInTable,0,
+    /*tag*/         eHTMLTag_caption,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_center,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_center,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_cite,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_cite,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_code,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_code,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_col,
-    /*req-parent excl-parent*/          eHTMLTag_table,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gColParents,&gColParents,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, kNone,
-    /*special props, prop-range*/       kNoPropagate|kNonContainer,kDefaultPropRange,
-    /*special parents,kids*/            &gColParents,0,
+    /*tag*/         eHTMLTag_col,
+    /*parent,leaf*/ kNone, true
   },
   {
-    /*tag*/                             eHTMLTag_colgroup,
-    /*req-parent excl-parent*/          eHTMLTag_table,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInTable,&gInTable,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, kNone,
-    /*special props, prop-range*/       kNoPropagate,kDefaultPropRange,
-    /*special parents,kids*/            &gInTable,&gColgroupKids,
+    /*tag*/         eHTMLTag_colgroup,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_data,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_data,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_datalist,
-    /*requiredAncestor*/                eHTMLTag_unknown, eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kInlineEntity|kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_datalist,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_dd,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gDTCloseTags,0,&gDLKids,0,
-    /*parent,incl,exclgroups*/          kInlineEntity, kFlowEntity, kNone,
-    /*special props, prop-range*/       kNoPropagate|kMustCloseSelf|kVerifyHierarchy|kRequiresBody,kDefaultPropRange,
-    /*special parents,kids*/            &gInDL,0,
+    /*tag*/         eHTMLTag_dd,
+    /*parent,leaf*/ kInlineEntity, false
   },
   {
-    /*tag*/                             eHTMLTag_del,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            &gInBody,0,
+    /*tag*/         eHTMLTag_del,
+    /*parent,leaf*/ kFlowEntity, false
   },
   {
-    /*tag*/                             eHTMLTag_dfn,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_dfn,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_dir,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gOLRootTags,&gOLRootTags,
-    /*autoclose starttags and endtags*/ &gOLAutoClose, &gULCloseTags, 0,0,
-    /*parent,incl,exclgroups*/          kList, (kFlowEntity|kSelf), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,&gULKids,
+    /*tag*/         eHTMLTag_dir,
+    /*parent,leaf*/ kList, false
   },
   {
-    /*tag*/                             eHTMLTag_div,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gDivAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_div,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_dl,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gDLRootTags,&gRootTags,  //fix bug 57634
-    /*autoclose starttags and endtags*/ 0,0,0,&gDTKids,           // DT should not contain DL - bug 100466
-    /*parent,incl,exclgroups*/          kBlock, kSelf|kFlowEntity, kNone,
-    /*special props, prop-range*/       0, kNoPropRange,
-    /*special parents,kids*/            0,&gDLKids,
+    /*tag*/         eHTMLTag_dl,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_dt,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gDTCloseTags,0,&gDLKids,0,
-    /*parent,incl,exclgroups*/          kInlineEntity, (kFlowEntity-kHeading), kNone,  // dt's parent group is inline - bug 65467
-    /*special props, prop-range*/       (kNoPropagate|kMustCloseSelf|kVerifyHierarchy|kRequiresBody),kDefaultPropRange,
-    /*special parents,kids*/            &gInDL,0,
+    /*tag*/         eHTMLTag_dt,
+    /*parent,leaf*/ kInlineEntity, false
   },
   {
-    /*tag*/                             eHTMLTag_em,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_em,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_embed,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer|kRequiresBody,kDefaultPropRange,
-    /*special parents,kids*/            0,&gContainsParam,
+    /*tag*/         eHTMLTag_embed,
+    /*parent,leaf*/ kSpecial, true
   },
   {
-    /*tag*/                             eHTMLTag_fieldset,
-    /*requiredAncestor*/                eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       kNoPropagate,kDefaultPropRange,
-    /*special parents,kids*/            0,&gFieldsetKids,
+    /*tag*/         eHTMLTag_fieldset,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_figcaption,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_figcaption,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_figure,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_figure,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_font,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,&gFontKids,
+    /*tag*/         eHTMLTag_font,
+    /*parent,leaf*/ kFontStyle, false
   },
   {
-    /*tag*/                             eHTMLTag_footer,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_footer,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_form,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, kFlowEntity, kNone,
-    /*special props, prop-range*/       kNoStyleLeaksIn, kNoPropRange,
-    /*special parents,kids*/            0,&gFormKids,
+    /*tag*/         eHTMLTag_form,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_frame, 
-    /*req-parent excl-parent*/          eHTMLTag_frameset,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInFrameset,&gInFrameset,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, kNone,
-    /*special props, prop-range*/       kNoPropagate|kNoStyleLeaksIn|kNonContainer, kNoPropRange,
-    /*special parents,kids*/            &gInFrameset,0,
+    /*tag*/         eHTMLTag_frame,
+    /*parent,leaf*/ kNone, true
+  },
+  {
+    /*tag*/         eHTMLTag_frameset,
+    /*parent,leaf*/ kHTMLContent, false
   },
   {
-    /*tag*/                             eHTMLTag_frameset,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_body,
-    /*rootnodes,endrootnodes*/          &gFramesetParents,&gInHTML,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kHTMLContent, kSelf, kAllTags,
-    /*special props, prop-range*/       kNoPropagate|kNoStyleLeaksIn, kNoPropRange,
-    /*special parents,kids*/            &gInHTML,&gFramesetKids,
+    /*tag*/         eHTMLTag_h1,
+    /*parent,leaf*/ kHeading, false
   },
-
   {
-    /*tag*/                             eHTMLTag_h1,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gHeadingTags,  &gHeadingTags, &gHeadingTags,0,
-    /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,
-    /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_h2,
+    /*parent,leaf*/ kHeading, false
   },
   {
-    /*tag*/                             eHTMLTag_h2,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gHeadingTags,  &gHeadingTags, &gHeadingTags,0,
-    /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,
-    /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_h3,
+    /*parent,leaf*/ kHeading, false
   },
   {
-    /*tag*/                             eHTMLTag_h3,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gHeadingTags,  &gHeadingTags, &gHeadingTags,0,
-    /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,
-    /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_h4,
+    /*parent,leaf*/ kHeading, false
   },
   {
-    /*tag*/                             eHTMLTag_h4,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gHeadingTags,  &gHeadingTags, &gHeadingTags,0,
-    /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,
-    /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
-  },
-  {
-    /*tag*/                             eHTMLTag_h5,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gHeadingTags,  &gHeadingTags, &gHeadingTags,0,
-    /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,
-    /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_h5,
+    /*parent,leaf*/ kHeading, false
   },
   {
-    /*tag*/                             eHTMLTag_h6,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gHeadingTags,  &gHeadingTags, &gHeadingTags,0,
-    /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,
-    /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_h6,
+    /*parent,leaf*/ kHeading, false
   },
   {
-    /*tag*/                             eHTMLTag_head,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInHTML,&gInHTML,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kHTMLContent, (kHeadContent|kHeadMisc), kNone,
-    /*special props, prop-range*/       kNoStyleLeaksIn, kDefaultPropRange,
-    /*special parents,kids*/            &gInHTML,0,
+    /*tag*/         eHTMLTag_head,
+    /*parent,leaf*/ kHTMLContent, false
   },
   {
-    /*tag*/                             eHTMLTag_header,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_header,
+    /*parent,leaf*/ kBlock, false
+  },
+  {
+    /*tag*/         eHTMLTag_hgroup,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_hgroup,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_hr,
+    /*parent,leaf*/ kBlock, true
   },
   {
-    /*tag*/                             eHTMLTag_hr,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gHRAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer|kRequiresBody,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_html,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_html,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_html,
-    /*rootnodes,endrootnodes*/          &gHTMLRootTags,&gHTMLRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kHTMLContent, kNone,
-    /*special props, prop-range*/       kSaveMisplaced|kOmitEndTag|kNoStyleLeaksIn, kDefaultPropRange,
-    /*special parents,kids*/            0,&gHtmlKids,
+    /*tag*/         eHTMLTag_i,
+    /*parent,leaf*/ kFontStyle, false
   },
   {
-    /*tag*/                             eHTMLTag_i,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_iframe,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_iframe,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       kNoStyleLeaksIn, kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_image,
+    /*parent,leaf*/ kSpecial, true
   },
   {
-    /*tag*/                             eHTMLTag_image,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_img,
+    /*parent,leaf*/ kSpecial, true
   },
   {
-    /*tag*/                             eHTMLTag_img,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer|kRequiresBody,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_input,
+    /*parent,leaf*/ kFormControl, true
   },
   {
-    /*tag*/                             eHTMLTag_input,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gInputAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kFormControl, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer|kRequiresBody,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_ins,
+    /*parent,leaf*/ kFlowEntity, false
   },
   {
-    /*tag*/                             eHTMLTag_ins,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_kbd,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_kbd,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_keygen,
+    /*parent,leaf*/ kFlowEntity, true
   },
   {
-    /*tag*/                             eHTMLTag_keygen,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_label,
+    /*parent,leaf*/ kFormControl, false
   },
   {
-    /*tag*/                             eHTMLTag_label,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFormControl, kInlineEntity, kSelf,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,&gLabelKids,
+    /*tag*/         eHTMLTag_legend,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_legend,
-    /*requiredAncestor*/                eHTMLTag_fieldset,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInFieldset,&gInFieldset,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kInlineEntity, kNone,
-    /*special props, prop-range*/       kRequiresBody,kDefaultPropRange,
-    /*special parents,kids*/            &gInFieldset,0,
+    /*tag*/         eHTMLTag_li,
+    /*parent,leaf*/ kBlockEntity, false
   },
   {
-    /*tag*/                             eHTMLTag_li,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gLIRootTags,&gLIRootTags,
-    /*autoclose starttags and endtags*/ &gLIAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kBlockEntity, kFlowEntity, kSelf, // changed this back to kBlockEntity so we enable RS handling for phrasals. ref bug 181697
-    /*special props, prop-range*/       kNoPropagate|kVerifyHierarchy|kRequiresBody, kDefaultPropRange,
-    /*special parents,kids*/            0,&gLIKids,
+    /*tag*/         eHTMLTag_link,
+    /*parent,leaf*/ kAllTags - kHeadContent, true
   },
   {
-    /*tag*/                             eHTMLTag_link,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInHead,&gInHead,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kAllTags - kHeadContent, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer|kPreferHead|kLegalOpen,kDefaultPropRange,
-    /*special parents,kids*/            &gInHead,0,
+    /*tag*/         eHTMLTag_listing,
+    /*parent,leaf*/ kPreformatted, false
   },
   {
-    /*tag*/                             eHTMLTag_listing,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPreformatted, (kSelf|kFlowEntity), kNone,  //add flowentity to fix 54993
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_main,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_main,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_map,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_map,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kInlineEntity|kBlockEntity, kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,&gMapKids,
+    /*tag*/         eHTMLTag_mark,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_mark,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kInlineEntity|kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_marquee,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_marquee,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       kRequiresBody, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_menu,
+    /*parent,leaf*/ kList, false
   },
   {
-    /*tag*/                             eHTMLTag_menu,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kList, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,&gULKids,
+    /*tag*/         eHTMLTag_menuitem,
+    /*parent,leaf*/ kFlowEntity, false
   },
   {
-    /*tag*/                             eHTMLTag_menuitem,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_meta,
+    /*parent,leaf*/ kHeadContent, true
   },
   {
-    /*tag*/                             eHTMLTag_meta,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInHead,&gInHead,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kHeadContent, kNone, kNone,
-    /*special props, prop-range*/       kNoStyleLeaksIn|kNonContainer, kDefaultPropRange,
-    /*special parents,kids*/            &gInHead,0,
+    /*tag*/         eHTMLTag_meter,
+    /*parent,leaf*/ kFormControl, false
   },
   {
-    /*tag*/                             eHTMLTag_meter,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFormControl, kFlowEntity, kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_multicol,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_multicol,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, kFlowEntity, kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_nav,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_nav,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_nobr,
+    /*parent,leaf*/ kExtensions, false
   },
   {
-    /*tag*/                             eHTMLTag_nobr,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kExtensions, kFlowEntity, kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_noembed,
+    /*parent,leaf*/ kFlowEntity, false
   },
   {
-    /*tag*/                             eHTMLTag_noembed, 
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, kFlowEntity, kNone,
-    /*special props, prop-range*/       0, kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_noframes,
+    /*parent,leaf*/ kFlowEntity, false
   },
   {
-    /*tag*/                             eHTMLTag_noframes,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gNoframeRoot,&gNoframeRoot,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, kFlowEntity, kNone,
-    /*special props, prop-range*/       0, kNoPropRange,
-    /*special parents,kids*/            &gNoframeRoot,0,
+    /*tag*/         eHTMLTag_noscript,
+    /*parent,leaf*/ kFlowEntity|kHeadMisc, false
   },
   {
-    /*tag*/                             eHTMLTag_noscript,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity|kHeadMisc, kFlowEntity|kSelf, kNone,
-    /*special props, prop-range*/       0, kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_object,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_object,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kFlowEntity|kSelf), kNone,
-    /*special props, prop-range*/       kNoStyleLeaksOut|kPreferBody,kDefaultPropRange,
-    /*special parents,kids*/            0,&gContainsParam,
+    /*tag*/         eHTMLTag_ol,
+    /*parent,leaf*/ kList, false
   },
   {
-    /*tag*/                             eHTMLTag_ol,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gOLRootTags,&gOLRootTags,
-    /*autoclose starttags and endtags*/ &gOLAutoClose, &gULCloseTags, 0,0,
-    /*parent,incl,exclgroups*/          kList, (kFlowEntity|kSelf), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,   
-    /*special parents,kids*/            0,&gULKids,
+    /*tag*/         eHTMLTag_optgroup,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_optgroup,
-    /*requiredAncestor*/                eHTMLTag_select,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gOptgroupParents,&gOptgroupParents,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            &gOptgroupParents,&gContainsOpts,
+    /*tag*/         eHTMLTag_option,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_option,
-    /*requiredAncestor*/                eHTMLTag_select,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gOptgroupParents,&gOptgroupParents, 
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kPCDATA, kFlowEntity|kHeadMisc,
-    /*special props, prop-range*/       kNoStyleLeaksIn|kNoPropagate, kDefaultPropRange,
-    /*special parents,kids*/            &gOptgroupParents,&gContainedInOpt,
+    /*tag*/         eHTMLTag_output,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_output,
-    /*requiredAncestor*/                eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kInlineEntity|kSelf), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_p,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_p,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, kInlineEntity, kNone,      //this used to contain FLOW. But it's really an inline container.
-    /*special props, prop-range*/       kHandleStrayTag,kDefaultPropRange, //otherwise it tries to contain things like H1..H6
-    /*special parents,kids*/            0,&gInP,
+    /*tag*/         eHTMLTag_param,
+    /*parent,leaf*/ kSpecial, true
   },
   {
-    /*tag*/                             eHTMLTag_param,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gParamParents,&gParamParents,
-    /*autoclose starttags and endtags*/ &gPAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer, kNoPropRange,
-    /*special parents,kids*/            &gParamParents,0,
+    /*tag*/         eHTMLTag_plaintext,
+    /*parent,leaf*/ kExtensions, false
   },
   {
-    /*tag*/                             eHTMLTag_plaintext,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kExtensions, kCDATA, kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_pre,
+    /*parent,leaf*/ kBlock|kPreformatted, false
   },
   {
-    /*tag*/                             eHTMLTag_pre,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock|kPreformatted, (kSelf|kFlowEntity), kNone,  // Note: PRE is a block level element - bug 80009
-    /*special props, prop-range*/       kRequiresBody, kDefaultPropRange,
-    /*special parents,kids*/            0,&gPreKids,
+    /*tag*/         eHTMLTag_progress,
+    /*parent,leaf*/ kFormControl, false
   },
   {
-    /*tag*/                             eHTMLTag_progress,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFormControl, kFlowEntity, kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_q,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_q,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_s,
+    /*parent,leaf*/ kFontStyle, false
   },
   {
-    /*tag*/                             eHTMLTag_s,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_samp,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_samp,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_script,
+    /*parent,leaf*/ (kSpecial|kHeadContent), false
   },
   {
-    /*tag*/                             eHTMLTag_script,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          (kSpecial|kHeadContent), kCDATA, kNone,   // note: this is kHeadContent since shipping this breaks things.
-    /*special props, prop-range*/       kNoStyleLeaksIn|kLegalOpen, kNoPropRange,
-    /*special parents,kids*/            0,&gContainsText,
+    /*tag*/         eHTMLTag_section,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    /*tag*/                             eHTMLTag_section,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_select,
+    /*parent,leaf*/ kFormControl, false
   },
   {
-    /*tag*/                             eHTMLTag_select,
-    /*requiredAncestor*/                eHTMLTag_unknown, eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInForm,&gInForm,
-    /*autoclose starttags and endtags*/ &gInputAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kFormControl, kNone, kFlowEntity|kDLChild|kHeadMisc, // Added kHeadMisc to fix bug 287349
-    /*special props, prop-range*/       kNoPropagate|kNoStyleLeaksIn|kRequiresBody, kDefaultPropRange,
-    /*special parents,kids*/            &gInForm,&gContainsOpts,
+    /*tag*/         eHTMLTag_small,
+    /*parent,leaf*/ kFontStyle, false
   },
   {
-    /*tag*/                             eHTMLTag_small,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_source,
+    /*parent,leaf*/ kSpecial, true
   },
   {
-    /*tag*/                             eHTMLTag_source,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gSourceParents,&gSourceParents,
-    /*autoclose starttags and endtags*/ &gPAutoClose, 0, 0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer,kNoPropRange,
-    /*special parents,kids*/            &gSourceParents,0,
+    /*tag*/         eHTMLTag_span,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    
-          // I made span a special% tag again, (instead of inline).
-          // This fixes the case:  <font color="blue"><p><span>text</span>
-
-    /*tag*/                             eHTMLTag_span,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kInlineEntity|kSelf|kFlowEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_strike,
+    /*parent,leaf*/ kFontStyle, false
+  },
+  {
+    /*tag*/         eHTMLTag_strong,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    
-    /*tag*/                             eHTMLTag_strike,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_style,
+    /*parent,leaf*/ kAllTags - kHeadContent, false
   },
   {
-    
-    /*tag*/                             eHTMLTag_strong,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,  //changed this to inline per spec; fix bug 44584.
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,&gContainsText,
+    /*tag*/         eHTMLTag_sub,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    
-    /*tag*/                             eHTMLTag_style,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kAllTags - kHeadContent, kCDATA, kNone,
-    /*special props, prop-range*/       kNoStyleLeaksIn|kPreferHead|kLegalOpen, kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_sup,
+    /*parent,leaf*/ kSpecial, false
   },
   {
-    /*tag*/                             eHTMLTag_sub,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_table,
+    /*parent,leaf*/ kBlock, false
   },
   {
-    
-    /*tag*/                             eHTMLTag_sup,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_tbody,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_table,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gTableRootTags,&gTableRootTags,
-    /*autoclose starttags and endtags*/ 0,&gTableCloseTags,0,0,
-    /*parent,incl,exclgroups*/          kBlock, kNone, (kSelf|kInlineEntity),
-    /*special props, prop-range*/       (kBadContentWatch|kNoStyleLeaksIn|kRequiresBody), 2,
-    /*special parents,kids*/            0,&gTableKids,
+    /*tag*/         eHTMLTag_td,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_tbody,
-    /*requiredAncestor*/                eHTMLTag_table, eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInTable,&gInTable,
-    /*autoclose starttags and endtags*/ &gTBodyAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, (kSelf|kInlineEntity),
-    /*special props, prop-range*/       (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kDefaultPropRange,
-    /*special parents,kids*/            &gInTable,&gTBodyKids,
+    /*tag*/         eHTMLTag_textarea,
+    /*parent,leaf*/ kFormControl, false
   },
   {
-    /*tag*/                             eHTMLTag_td,
-    /*requiredAncestor*/                eHTMLTag_table, eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gTDRootTags,&gTDRootTags,
-    /*autoclose starttags and endtags*/ &gTDCloseTags,&gTDCloseTags,0,&gExcludableParents,
-    /*parent,incl,exclgroups*/          kNone, kFlowEntity, kSelf,
-    /*special props, prop-range*/       kNoStyleLeaksIn|kNoStyleLeaksOut, kDefaultPropRange,
-    /*special parents,kids*/            &gTDRootTags,&gBodyKids,
+    /*tag*/         eHTMLTag_tfoot,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_textarea,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInForm,&gInForm,
-    /*autoclose starttags and endtags*/ &gInputAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kFormControl, kPCDATA, kNone,
-    /*special props, prop-range*/       kRequiresBody|kNoStyleLeaksIn,kDefaultPropRange,
-    /*special parents,kids*/            &gInForm,&gContainsText,
+    /*tag*/         eHTMLTag_th,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_tfoot,
-    /*requiredAncestor*/                eHTMLTag_table, eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInTable,&gInTable,
-    /*autoclose starttags and endtags*/ &gTBodyAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, kSelf,
-    /*special props, prop-range*/       (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kNoPropRange,
-    /*special parents,kids*/            &gInTable,&gTableElemKids,
+    /*tag*/         eHTMLTag_thead,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_th, 
-    /*requiredAncestor*/                eHTMLTag_table, eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gTDRootTags,&gTDRootTags,
-    /*autoclose starttags and endtags*/ &gTDCloseTags,&gTDCloseTags,0,0,
-    /*parent,incl,exclgroups*/          kNone, kFlowEntity, kSelf,
-    /*special props, prop-range*/       (kNoStyleLeaksIn|kNoStyleLeaksOut), kDefaultPropRange,
-    /*special parents,kids*/            &gTDRootTags,&gBodyKids,
+    /*tag*/         eHTMLTag_template,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_thead,
-    /*req-parent excl-parent*/          eHTMLTag_table,eHTMLTag_unknown,  //fix bug 54840...
-    /*rootnodes,endrootnodes*/          &gInTable,&gInTable,  
-    /*autoclose starttags and endtags*/ &gTBodyAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, kSelf,
-    /*special props, prop-range*/       (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kNoPropRange,
-    /*special parents,kids*/            &gInTable,&gTableElemKids,
+    /*tag*/         eHTMLTag_time,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_template,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_title,
+    /*parent,leaf*/ kHeadContent, false
   },
   {
-    /*tag*/                             eHTMLTag_time,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_tr,
+    /*parent,leaf*/ kNone, false
   },
   {
-    /*tag*/                             eHTMLTag_title,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInHead,&gInHead,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kHeadContent,kPCDATA, kNone,
-    /*special props, prop-range*/       kNoStyleLeaksIn, kNoPropRange,
-    /*special parents,kids*/            &gInHead,&gContainsText,
+    /*tag*/         eHTMLTag_track,
+    /*parent,leaf*/ kSpecial, true
   },
   {
-    /*tag*/                             eHTMLTag_tr,
-    /*requiredAncestor*/                eHTMLTag_table, eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gTRParents,&gTREndParents,
-    /*autoclose starttags and endtags*/ &gTRCloseTags,0,0,0,
-    /*parent,incl,exclgroups*/          kNone, kNone, kInlineEntity,
-    /*special props, prop-range*/       (kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kNoPropRange,
-    /*special parents,kids*/            &gTRParents,&gTRKids,
+    /*tag*/         eHTMLTag_tt,
+    /*parent,leaf*/ kFontStyle, false
   },
   {
-    /*tag*/                             eHTMLTag_track,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gTrackParents,&gTrackParents,
-    /*autoclose starttags and endtags*/ &gPAutoClose, 0, 0,0,
-    /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer,kNoPropRange,
-    /*special parents,kids*/            &gTrackParents,0,
+    /*tag*/         eHTMLTag_u,
+    /*parent,leaf*/ kFontStyle, false
   },
   {
-    /*tag*/                             eHTMLTag_tt,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_ul,
+    /*parent,leaf*/ kList, false
   },
   {
-    /*tag*/                             eHTMLTag_u,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0, kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_var,
+    /*parent,leaf*/ kPhrase, false
   },
   {
-    /*tag*/                             eHTMLTag_ul,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gOLRootTags,&gOLRootTags,
-    /*autoclose starttags and endtags*/ &gULAutoClose,&gULCloseTags,0,0,
-    /*parent,incl,exclgroups*/          kList, (kFlowEntity|kSelf), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,&gULKids,
+    /*tag*/         eHTMLTag_video,
+    /*parent,leaf*/ kSpecial, false
+  },
+  {
+    /*tag*/         eHTMLTag_wbr,
+    /*parent,leaf*/ kExtensions, true
   },
   {
-    /*tag*/                             eHTMLTag_var,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_xmp,
+    /*parent,leaf*/ kInlineEntity|kPreformatted, false
   },
   {
-    /*tag*/                             eHTMLTag_video,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0, 0, 0,0,
-    /*parent,incl,exclgroups*/          kSpecial, (kFlowEntity|kSelf), kNone,
-    /*special props, prop-range*/       0,kDefaultPropRange,
-    /*special parents,kids*/            0,&gVideoKids,
+    /*tag*/         eHTMLTag_text,
+    /*parent,leaf*/ kFlowEntity, true
   },
   {
-    /*tag*/                             eHTMLTag_wbr,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kExtensions, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer|kRequiresBody,kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_whitespace,
+    /*parent,leaf*/ kFlowEntity|kHeadMisc, true
   },
   {
-    /*tag*/                             eHTMLTag_xmp,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kInlineEntity|kPreformatted, kCDATA, kNone,
-    /*special props, prop-range*/       kNone,kDefaultPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_newline,
+    /*parent,leaf*/ kFlowEntity|kHeadMisc, true
   },
   {
-    /*tag*/                             eHTMLTag_text,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInBody,&gInBody,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer|kRequiresBody,kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_comment,
+    /*parent,leaf*/ kFlowEntity|kHeadMisc, false
   },
   {
-          // Whitespace must have a parent model of kHeadMisc to ensure that we
-          // do the right thing for whitespace in the head section of a document.
-          // (i.e., it must be non-exclusively a child of the head).
-
-    /*tag*/                             eHTMLTag_whitespace, 
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInBody,&gInBody,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity|kHeadMisc, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer|kLegalOpen,kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_entity,
+    /*parent,leaf*/ kFlowEntity, false
   },
   {
-          // Newlines must have a parent model of kHeadMisc to ensure that we
-          // do the right thing for whitespace in the head section of a document.
-          // (i.e., it must be non-exclusively a child of the head).
-
-    /*tag*/                             eHTMLTag_newline,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInBody,&gInBody,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity|kHeadMisc, kNone, kNone,
-    /*special props, prop-range*/       kNonContainer|kLegalOpen, kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_doctypeDecl,
+    /*parent,leaf*/ kFlowEntity, false
   },
   {
-          // Comments must have a parent model of kHeadMisc to ensure that we
-          // do the right thing for whitespace in the head section of a document
-          // (i.e., it must be non-exclusively a child of the head).
-
-    /*tag*/                             eHTMLTag_comment,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity|kHeadMisc, kNone, kNone,
-    /*special props, prop-range*/       kOmitEndTag|kLegalOpen,kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_markupDecl,
+    /*parent,leaf*/ kFlowEntity, false
+  },
+  {
+    /*tag*/         eHTMLTag_instruction,
+    /*parent,leaf*/ kFlowEntity, false
   },
   {
-    /*tag*/                             eHTMLTag_entity,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gInBody,&gInBody,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,
-    /*special props, prop-range*/       0, kNoPropRange,
-    /*special parents,kids*/            0,0,
-  },
-  {
-    /*tag*/                             eHTMLTag_doctypeDecl,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,
-    /*special props, prop-range*/       kOmitEndTag,kNoPropRange,
-    /*special parents,kids*/            0,0,
+    /*tag*/         eHTMLTag_userdefined,
+    /*parent,leaf*/ (kFlowEntity|kHeadMisc), false
   },
-  {
-    /*tag*/                             eHTMLTag_markupDecl,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,
-    /*special props, prop-range*/       kOmitEndTag,kNoPropRange,
-    /*special parents,kids*/            0,0,
-  },
-  {
-    /*tag*/                             eHTMLTag_instruction,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,
-    /*rootnodes,endrootnodes*/          0,0,
-    /*autoclose starttags and endtags*/ 0,0,0,0,
-    /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,
-    /*special props, prop-range*/       kOmitEndTag,kNoPropRange,
-    /*special parents,kids*/            0,0,
-  },
-  {
-          // Userdefined tags must have a parent model of kHeadMisc to ensure that
-          // we do the right thing for whitespace in the head section of a document.
-          // (i.e., it must be non-exclusively a child of the head).
-
-    /*tag*/                             eHTMLTag_userdefined,
-    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_frameset,
-    /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,
-    /*autoclose starttags and endtags*/ &gBodyAutoClose,0,0,0,
-    /*parent,incl,exclgroups*/          (kFlowEntity|kHeadMisc), (kInlineEntity|kSelf), kNone,  // Treat userdefined as inline element - Ref bug 56245,66772
-    /*special props, prop-range*/       kPreferBody, kBodyPropRange,
-    /*special parents,kids*/            &gInNoframes,&gBodyKids,
-  }
 };
 
-#ifdef DEBUG  
-void CheckElementTable() {
+/*********************************************************************************************/
+
+bool nsHTMLElement::IsContainer(eHTMLTags aChild)
+{
+  return !gHTMLElements[aChild].mLeaf;
+}
+
+bool nsHTMLElement::IsMemberOf(int32_t aSet) const
+{
+  return TestBits(aSet,mParentBits);
+}
+
+#ifdef DEBUG
+void CheckElementTable()
+{
   for (eHTMLTags t = eHTMLTag_unknown; t <= eHTMLTag_userdefined; t = eHTMLTags(t + 1)) {
     NS_ASSERTION(gHTMLElements[t].mTagID == t, "gHTMLElements entries does match tag list.");
   }
 }
 #endif
-
-/**
- *  Call this to find the index of a given child, or (if not found)
- *  the index of its nearest synonym.
- *   
- *  @update  gess 3/25/98
- *  @param   aTagStack -- list of open tags
- *  @param   aTag -- tag to test for containership
- *  @return  index of kNotFound
- */
-int32_t nsHTMLElement::GetIndexOfChildOrSynonym(nsDTDContext& aContext,eHTMLTags aChildTag) {
-  int32_t theChildIndex=aContext.LastOf(aChildTag);
-  if(kNotFound==theChildIndex) {
-    const TagList* theSynTags=gHTMLElements[aChildTag].GetSynonymousTags(); //get the list of tags that THIS tag can close
-    if(theSynTags) {
-      theChildIndex=LastOf(aContext,*theSynTags);
-    } 
-  }
-  return theChildIndex;
-}
-
-/**
- * 
- * @update	gess1/21/99
- * @param 
- * @return
- */
-bool nsHTMLElement::HasSpecialProperty(int32_t aProperty) const{
-  bool result=TestBits(mSpecialProperties,aProperty);
-  return result;
-}
-
-/**
- * 
- * @update	gess12/13/98
- * @param 
- * @return
- */ 
-bool nsHTMLElement::IsContainer(eHTMLTags aChild) {
-  bool result=(eHTMLTag_unknown==aChild);
-
-  if(!result){
-    result=!TestBits(gHTMLElements[aChild].mSpecialProperties,kNonContainer);
-  }
-  return result;
-}
-
-/**
- * This tests whether all the bits in the parentbits
- * are included in the given set. It may be too 
- * broad a question for most cases.
- *
- * @update	gess12/13/98
- * @param 
- * @return
- */
-bool nsHTMLElement::IsMemberOf(int32_t aSet) const{
-  return TestBits(aSet,mParentBits);
-}
-
-/**
- * This tests whether all the bits in the parentbits
- * are included in the given set. It may be too 
- * broad a question for most cases.
- *
- * @update	gess12/13/98
- * @param 
- * @return
- */
-bool nsHTMLElement::ContainsSet(int32_t aSet) const{
-  return TestBits(mParentBits,aSet);
-}
-
-/** 
- * This method determines whether the given tag closes other blocks.
- * 
- * @update	gess 12/20/99 -- added H1..H6 to this list.
- * @param 
- * @return
- */
-bool nsHTMLElement::IsBlockCloser(eHTMLTags aTag){
-  bool result=false;
-    
-  if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
-
-    result=(gHTMLElements[aTag].IsBlock() || 
-            gHTMLElements[aTag].IsBlockEntity() ||
-            (kHeading==gHTMLElements[aTag].mParentBits));
-    if(!result) {
-      // NOBR is a block closure   - Ref. Bug# 24462
-      // DIR is a block closure    - Ref. Bug# 25845
-      // TD is a block closure     - Ref. Bug# 27490
-      // TR is a block closure     - Ref. Bug# 26488
-      // OBJECT is a block closure - Ref. Bug# 88992
-
-      static eHTMLTags gClosers[]={ eHTMLTag_table,eHTMLTag_tbody,
-                                    eHTMLTag_td,eHTMLTag_th,
-                                    eHTMLTag_tr,eHTMLTag_caption,
-                                    eHTMLTag_object,eHTMLTag_applet,
-                                    eHTMLTag_ol, eHTMLTag_ul,
-                                    eHTMLTag_optgroup,
-                                    eHTMLTag_nobr,eHTMLTag_dir};
-
-      result=FindTagInSet(aTag,gClosers,sizeof(gClosers)/sizeof(eHTMLTag_body));
-    }
-  }
-  return result;
-}
-
-
-/**
- * 
- * @update	gess 01/04/99
- * @param 
- * @return
- */
-bool nsHTMLElement::IsInlineEntity(eHTMLTags aTag){
-  bool result=false;
-  if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
-    result=TestBits(gHTMLElements[aTag].mParentBits,kInlineEntity);
-  } 
-  return result;
-}
-
-/**
- * 
- * @update	gess 01/04/99
- * @param 
- * @return
- */
-bool nsHTMLElement::IsFlowEntity(eHTMLTags aTag){
-  bool result=false;
-
-  if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
-    result=TestBits(gHTMLElements[aTag].mParentBits,kFlowEntity);
-  } 
-  return result;
-}
-
-/**
- * 
- * @update	gess 01/04/99
- * @param 
- * @return
- */
-bool nsHTMLElement::IsBlockParent(eHTMLTags aTag){
-  bool result=false;
-  if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
-    result=TestBits(gHTMLElements[aTag].mInclusionBits,kBlockEntity);
-  } 
-  return result;
-}
-
-/**
- * 
- * @update	gess 01/04/99
- * @param 
- * @return
- */
-bool nsHTMLElement::IsInlineParent(eHTMLTags aTag){
-  bool result=false;
-  if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
-    result=TestBits(gHTMLElements[aTag].mInclusionBits,kInlineEntity);
-  } 
-  return result;
-}
-
-
-/**
- * 
- * @update	gess 01/04/99
- * @param 
- * @return
- */
-bool nsHTMLElement::IsFlowParent(eHTMLTags aTag){
-  bool result=false;
-  if((aTag>=eHTMLTag_unknown) & (aTag<=eHTMLTag_xmp)){
-    result=TestBits(gHTMLElements[aTag].mInclusionBits,kFlowEntity);
-  } 
-  return result;
-}
-
-/**
- * 
- * @update	harishd 11/19/99
- * @param 
- * @return
- */
-bool nsHTMLElement::IsSpecialParent(eHTMLTags aTag) const{
-  bool result=false;
-  if(mSpecialParents) {
-    if(FindTagInSet(aTag,mSpecialParents->mTags,mSpecialParents->mCount))
-        result=true;
-  }
-  return result;
-}
-
-/**
- * Tells us whether the given tag opens a section
- * @update	gess 01/04/99
- * @param   id of tag
- * @return  TRUE if opens section
- */
-bool nsHTMLElement::IsSectionTag(eHTMLTags aTag){
-  bool result=false;
-  switch(aTag){
-    case eHTMLTag_html:
-    case eHTMLTag_frameset:
-    case eHTMLTag_body:
-    case eHTMLTag_head:
-      result=true;
-      break;
-    default:
-      result=false;
-  }
-  return result;
-}
-
-
-/**
- * 
- * @update	gess 01/04/99
- * @param 
- * @return
- */
-bool nsHTMLElement::CanContain(eHTMLTags aParent,eHTMLTags aChild,nsDTDMode aMode){
-  bool result=false;
-  if((aParent>=eHTMLTag_unknown) && (aParent<=eHTMLTag_userdefined)){
-    result=gHTMLElements[aParent].CanContain(aChild,aMode);
-  } 
-  return result;
-}
-
-/**
- * 
- * @update	gess 01/04/99
- * @param 
- * @return
- */
-bool nsHTMLElement::CanExclude(eHTMLTags aChild) const{
-  bool result=false;
-
-  if(gHTMLElements[aChild].HasSpecialProperty(kLegalOpen)) {
-    // Some tags could be opened anywhere, in the document, as they please.
-    return false;
-  }
-
-  //Note that special kids takes precedence over exclusions...
-  if(mSpecialKids) {
-    if(FindTagInSet(aChild,mSpecialKids->mTags,mSpecialKids->mCount)) {
-      return false;
-    }
-  }
-
-  if(mExclusionBits){
-    if(gHTMLElements[aChild].IsMemberOf(mExclusionBits)) {
-      result=true;
-    }
-  }
-  return result;
-}
-
-/**
- * 
- * @update	harishd 03/01/00
- * @param 
- * @return
- */
-bool nsHTMLElement::IsExcludableParent(eHTMLTags aParent) const{
-  bool result=false;
-
-  if(!IsTextTag(mTagID)) {
-    if(mExcludableParents) {
-      const TagList* theParents=mExcludableParents;
-      if(FindTagInSet(aParent,theParents->mTags,theParents->mCount))
-        result=true;
-    }
-    if(!result) {
-      // If you're a block parent make sure that you're not the
-      // parent of a TABLE element. ex. <table><tr><td><div><td></tr></table>
-      // IE & Nav. render this as table with two cells ( which I think is correct ).
-      // NOTE: If need arise we could use the root node to solve this problem
-      if(nsHTMLElement::IsBlockParent(aParent)){
-        switch(mTagID) {
-          case eHTMLTag_caption:
-          case eHTMLTag_thead:
-          case eHTMLTag_tbody:
-          case eHTMLTag_tfoot:
-          case eHTMLTag_td:
-          case eHTMLTag_th:
-          case eHTMLTag_tr:
-            result=true;
-          default:
-            break;
-        }
-      }
-    }
-  }
-  return result;
-}
-
-/**
- * 
- * @update	gess 01/04/99
- * @param 
- * @return
- */
-bool nsHTMLElement::CanOmitEndTag(void) const{
-  bool result=!IsContainer(mTagID);
-  if(!result)
-    result=TestBits(mSpecialProperties,kOmitEndTag);
-  return result;
-}
-
-/**
- * Returns whether a given tag can be a direct child of the <head> node of
- * an HTML document.
- *
- * @param aChild The tag in question.
- * @param aExclusively [out]Whether or not this tag can *only* appear in the
- *                     head (as opposed to things like <object> which can be
-                       either in the body or the head).
- * @return Whether this tag can appear in the head.
- */
-bool nsHTMLElement::IsChildOfHead(eHTMLTags aChild,bool& aExclusively) {
-  aExclusively = true;
-
-  // Is this a head-only tag?
-  if (gHTMLElements[aChild].mParentBits & kHeadContent) {
-    return true;
-  }
-
-
-  // If not, check if it can appear in the head.
-  if (gHTMLElements[aChild].mParentBits & kHeadMisc) {
-    aExclusively = false;
-    return true;
-  }
-
-  return false;
-}
-
-
-
-/**
- * 
- * @update	gess12/13/98
- * @param 
- * @return
- */
-bool nsHTMLElement::SectionContains(eHTMLTags aChild,bool allowDepthSearch) const {
-  bool result=false;
-  const TagList* theRootTags=gHTMLElements[aChild].GetRootTags();
-
-  if(theRootTags){
-    if(!FindTagInSet(mTagID,theRootTags->mTags,theRootTags->mCount)){
-      eHTMLTags theRootBase=theRootTags->mTags[0];
-      if((eHTMLTag_unknown!=theRootBase) && (allowDepthSearch))
-        result=SectionContains(theRootBase,allowDepthSearch);
-    }
-    else result=true;
-  }
-  return result;
-}
-
-/**
- * This method should be called to determine if the a tags
- * hierarchy needs to be validated.
- * 
- * @update	harishd 04/19/00
- * @param 
- * @return
- */
-
-bool nsHTMLElement::ShouldVerifyHierarchy() const {
-  bool result=false;
-  
-  // If the tag cannot contain itself then we need to make sure that
-  // anywhere in the hierarchy we don't nest accidently.
-  // Ex: <H1><LI><H1><LI>. Inner LI has the potential of getting nested
-  // inside outer LI.If the tag can contain self, Ex: <A><B><A>,
-  // ( B can contain self )then ask the child (<A>) if it requires a containment check.
-  if(mTagID!=eHTMLTag_userdefined) {
-    result=HasSpecialProperty(kVerifyHierarchy);
-  }
-  return result;
-}
-  
-/**
- * 
- * @update	gess12/13/98
- * @param 
- * @return
- */
-bool nsHTMLElement::IsResidualStyleTag(eHTMLTags aChild) {
-  bool result=false;
-  switch(aChild) {
-    case eHTMLTag_a:       
-    case eHTMLTag_b:
-    case eHTMLTag_bdo:     
-    case eHTMLTag_big:       
-    case eHTMLTag_del:
-    case eHTMLTag_em:
-    case eHTMLTag_font:    
-    case eHTMLTag_i:         
-    case eHTMLTag_ins:
-    case eHTMLTag_q:
-    case eHTMLTag_s:       
-    case eHTMLTag_small:
-    case eHTMLTag_strong:
-    case eHTMLTag_strike:    
-    case eHTMLTag_sub:     
-    case eHTMLTag_sup:       
-    case eHTMLTag_tt:
-    case eHTMLTag_u:       
-      result=true;
-      break;
-
-    case eHTMLTag_abbr:
-    case eHTMLTag_acronym:   
-    case eHTMLTag_center:  
-    case eHTMLTag_cite:      
-    case eHTMLTag_code:
-    case eHTMLTag_dfn:       
-    case eHTMLTag_kbd:     
-    case eHTMLTag_samp:      
-    case eHTMLTag_span:    
-    case eHTMLTag_var:
-      result=false;
-    default:
-      break;
-  };
-  return result;
-}
-
-/**
- * 
- * @update	gess12/13/98
- * @param 
- * @return
- */
-bool nsHTMLElement::CanContainType(int32_t aType) const{
-  int32_t answer=mInclusionBits & aType;
-  bool    result=bool(0!=answer);
-  return result;
-}
-
-/**
- * 
- * @update	gess12/13/98
- * @param 
- * @return
- */
-bool nsHTMLElement::IsWhitespaceTag(eHTMLTags aChild) {
-  bool result=false;
-
-  switch(aChild) {
-    case eHTMLTag_newline:
-    case eHTMLTag_whitespace:
-      result=true;
-      break;
-    default:
-      break;
-  }
-  return result;
-}
-
-/**
- * 
- * @update	gess12/13/98
- * @param 
- * @return
- */
-bool nsHTMLElement::IsTextTag(eHTMLTags aChild) {
-  bool result=false;
-
-  switch(aChild) {
-    case eHTMLTag_text:
-    case eHTMLTag_entity:
-    case eHTMLTag_newline:
-    case eHTMLTag_whitespace:
-      result=true;
-      break;
-    default:
-      break;
-  }
-  return result;
-}
-
-/**
- * 
- * @update	gess12/13/98
- * @param 
- * @return
- */
-bool nsHTMLElement::CanContainSelf(void) const {
-  bool result=bool(TestBits(mInclusionBits,kSelf)!=0);
-  return result;
-}
-
-/**
- * This method is called to determine (once and for all) whether a start tag
- * can close another tag on the stack. This method will return
- * false if something prevents aParentTag from closing.
- *
- * @update	gess 12/20/99
- * @param   aContext is the tag stack we're testing against
- * @param   aIndex is the index of the tag we want to close
- * @param   aChildTag is the child we're trying to close
- * @return  TRUE if we can autoclose the start tag; FALSE otherwise
- */
-bool nsHTMLElement::CanAutoCloseTag(nsDTDContext& aContext,int32_t aIndex,
-                                      eHTMLTags aChildTag) const{
-
-  int32_t thePos;
-  bool    result = true;
-  eHTMLTags thePrevTag;
-
-  for(thePos = aContext.GetCount() - 1; thePos >= aIndex; thePos--) {
-    thePrevTag = aContext.TagAt(thePos);
-
-    if (thePrevTag == eHTMLTag_applet ||
-        thePrevTag == eHTMLTag_td) {
-          result = false;
-          break;
-    }
-  }
-  
-  return result;
-}
-
-/**
- * 
- * @update	gess 10.17.2000
- * @param 
- * @return  
- */
-eHTMLTags nsHTMLElement::GetCloseTargetForEndTag(nsDTDContext& aContext,int32_t anIndex,nsDTDMode aMode) const{
-  eHTMLTags result=eHTMLTag_unknown;
-
-  int theCount=aContext.GetCount();
-  int theIndex=theCount;
-
-  if(IsMemberOf(kPhrase)){
-
-    while((--theIndex>=anIndex) && (eHTMLTag_unknown==result)){
-      eHTMLTags theTag = aContext.TagAt(theIndex);
-      if(theTag != mTagID) {
-        // Allow phrasals to close userdefined tags. bug 256731
-        if(eHTMLTag_userdefined == theTag) {
-          continue; // We can close this.
-        }
-
-        // Fixes a derivative of bug 22842...
-        if(CanContainType(kBlock)) { // INS/DEL can contain blocks.
-          if(gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kBlockEntity) || 
-             gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kFlowEntity)) {
-            if(HasOptionalEndTag(theTag)) {
-              continue; // Then I can close it.
-            }
-          }
-        }
-
-        // Phrasal elements can close other phrasals, along with fontstyle,
-        // extensions, and special tags...
-        if(!gHTMLElements[theTag].IsMemberOf(kSpecial | 
-                                             kFontStyle |
-                                             kPhrase |
-                                             kExtensions)) {  //fix bug 56665
-          break; // It's not something I can close
-        }
-      }
-      else {
-        result=theTag; // Stop because you just found yourself on the stack
-        break;
-      }
-    }
-  }
-  
-  else if(IsMemberOf(kSpecial)){
-
-    while((--theIndex>=anIndex) && (eHTMLTag_unknown==result)){
-      eHTMLTags theTag=aContext.TagAt(theIndex);
-      if(theTag!=mTagID) {
-        // Special elements can close other specials, along with fontstyle 
-        // extensions, and phrasal tags...
-
-        // Added Phrasal to fix bug 26347
-        if((eHTMLTag_userdefined==theTag) ||
-            gHTMLElements[theTag].IsSpecialEntity()  || 
-            gHTMLElements[theTag].IsFontStyleEntity()||
-            gHTMLElements[theTag].IsPhraseEntity()   ||
-            gHTMLElements[theTag].IsMemberOf(kExtensions)) {
-          continue;
-        }
-        else {
-
-          // Fixes bug 22842...
-          if(CanContainType(kBlock)) {
-            if(gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kBlockEntity) || 
-               gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kFlowEntity)) {
-              if(HasOptionalEndTag(theTag)) {
-                continue; // Then I can close it.
-              }
-            }
-          }
-          break; // It's not something I can close
-        }
-      }
-      else {
-        result=theTag; // Stop because you just found yourself on the stack
-        break;
-      }
-    }
-  }
-
-  else if(ContainsSet(kPreformatted) ||  
-          IsMemberOf(kFormControl|kExtensions|kPreformatted)){  //bug54834...
-
-    while((--theIndex>=anIndex) && (eHTMLTag_unknown==result)){
-      eHTMLTags theTag=aContext.TagAt(theIndex);
-      if(theTag!=mTagID) {
-        if(!CanContain(theTag,aMode)) {
-          break; //it's not something I can close
-        }
-      }
-      else {
-        result=theTag; //stop because you just found yourself on the stack
-        break; 
-      }
-    }
-  }
-
-  else if(IsMemberOf(kList)){
-
-    while((--theIndex>=anIndex) && (eHTMLTag_unknown==result)){
-      eHTMLTags theTag=aContext.TagAt(theIndex);
-      if(theTag!=mTagID) {
-        if(!CanContain(theTag,aMode)) {
-          break; //it's not something I can close
-        }
-      }
-      else {
-        result=theTag; //stop because you just found yourself on the stack
-        break; 
-      }
-    }
-  }
-
-  else if(IsResidualStyleTag(mTagID)){
-    
-    // Before finding a close target, for the current tag, make sure
-    // that the tag above does not gate.
-    // Note: we intentionally make 2 passes: 
-    // The first pass tries to exactly match, the 2nd pass matches the group.
-
-    const TagList* theRootTags=gHTMLElements[mTagID].GetEndRootTags();
-    int32_t theIndexCopy=theIndex;
-    while(--theIndex>=anIndex){
-      eHTMLTags theTag=aContext.TagAt(theIndex);
-      if(theTag == mTagID) {
-        return theTag; // we found our target.
-      }
-      else if (!CanContain(theTag,aMode) || 
-               (theRootTags && FindTagInSet(theTag,theRootTags->mTags,theRootTags->mCount))) {
-        // If you cannot contain this tag then
-        // you cannot close it either. It looks like
-        // the tag trying to close is misplaced.
-        // In the following Exs. notice the misplaced /font:
-        // Ex. <font><table><tr><td></font></td></tr></table. -- Ref. bug 56245
-        // Ex. <font><select><option></font></select> -- Ref. bug 37618
-        // Ex. <font><select></font><option></select> -- Ref. bug 98187
-        return eHTMLTag_unknown;
-      }
-    }
-
-    theIndex=theIndexCopy;
-    while(--theIndex>=anIndex){
-      eHTMLTags theTag=aContext.TagAt(theIndex);
-      if(gHTMLElements[theTag].IsMemberOf(mParentBits)) {
-        return theTag;
-      }
-    }    
-  }
-
-  else if(gHTMLElements[mTagID].IsTableElement()) {
-    
-      //This fixes 57378...
-      //example: <TABLE><THEAD><TR><TH></THEAD> which didn't close the <THEAD>
-
-    int32_t theLastTable=aContext.LastOf(eHTMLTag_table);
-    int32_t theLastOfMe=aContext.LastOf(mTagID);
-    if(theLastTable<theLastOfMe) {
-      return mTagID;
-    }
-        
-  }
-
-  else if(mTagID == eHTMLTag_legend)  {
-    while((--theIndex>=anIndex) && (eHTMLTag_unknown==result)){
-      eHTMLTags theTag = aContext.TagAt(theIndex);
-      if (theTag == mTagID) {
-        result = theTag;
-        break;
-      }
-
-      if (!CanContain(theTag, aMode)) {
-        break;
-      }
-    }
-  }
-
-  else if (mTagID == eHTMLTag_head) {
-    while (--theIndex >= anIndex) {
-      eHTMLTags tag = aContext.TagAt(theIndex);
-      if (tag == eHTMLTag_html) {
-        // HTML gates head closing, but the head should never be the parent of
-        // an html tag.
-        break;
-      }
-
-      if (tag == eHTMLTag_head) {
-        result = eHTMLTag_head;
-        break;
-      }
-    }
-  }
-
-  return result;
-}
-
-
-/**
- * See whether this tag can DIRECTLY contain the given child.
- * @update	gess12/13/98
- * @param 
- * @return
- */
-bool nsHTMLElement::CanContain(eHTMLTags aChild,nsDTDMode aMode) const{
-
-
-  if(IsContainer(mTagID)){
-
-    if(gHTMLElements[aChild].HasSpecialProperty(kLegalOpen)) {
-      // Some tags could be opened anywhere, in the document, as they please.
-      return true;
-    }
-
-    if(mTagID==aChild) {
-      return CanContainSelf();  //not many tags can contain themselves...
-    }
-
-    const TagList* theCloseTags=gHTMLElements[aChild].GetAutoCloseStartTags();
-    if(theCloseTags){
-      if(FindTagInSet(mTagID,theCloseTags->mTags,theCloseTags->mCount))
-        return false;
-    }
-
-    if(gHTMLElements[aChild].mExcludableParents) {
-      const TagList* theParents=gHTMLElements[aChild].mExcludableParents;
-      if(FindTagInSet(mTagID,theParents->mTags,theParents->mCount))
-        return false;
-    }
-    
-    if(gHTMLElements[aChild].IsExcludableParent(mTagID))
-      return false;
-
-    if(gHTMLElements[aChild].IsBlockCloser(aChild)){
-      if(nsHTMLElement::IsBlockParent(mTagID)){
-        return true;
-      }
-    }
-
-    if(nsHTMLElement::IsInlineEntity(aChild)){
-      if(nsHTMLElement::IsInlineParent(mTagID)){
-        return true;
-      }
-    }
-
-    if(nsHTMLElement::IsFlowEntity(aChild)) {
-      if(nsHTMLElement::IsFlowParent(mTagID)){
-        return true;
-      }
-    }
-
-    if(nsHTMLElement::IsTextTag(aChild)) {
-      // Allow <xmp> to contain text.
-      if(nsHTMLElement::IsInlineParent(mTagID) || CanContainType(kCDATA)){
-        return true;
-      }
-    }
-
-    if(CanContainType(gHTMLElements[aChild].mParentBits)) {
-      return true;
-    }
- 
-    if(mSpecialKids) {
-      if(FindTagInSet(aChild,mSpecialKids->mTags,mSpecialKids->mCount)) {
-        return true;
-      }
-    }
-
-    // Allow <p> to contain <table> only in Quirks mode, bug 43678 and bug 91927
-    if (aChild == eHTMLTag_table && mTagID == eHTMLTag_p && aMode == eDTDMode_quirks) {
-      return true;
-    }
-  }
-  
-  return false;
-}
-
-#ifdef DEBUG
-void nsHTMLElement::DebugDumpContainment(const char* aFilename,const char* aTitle){
-}
-
-void nsHTMLElement::DebugDumpMembership(const char* aFilename){
-}
-
-void nsHTMLElement::DebugDumpContainType(const char* aFilename){
-}
-#endif
--- a/parser/htmlparser/src/nsElementTable.h
+++ b/parser/htmlparser/src/nsElementTable.h
@@ -10,19 +10,18 @@
  * 
  */
 
 
 
 #ifndef _NSELEMENTABLE
 #define _NSELEMENTABLE
 
-#include "nsHTMLTokens.h"
-#include "nsDTDUtils.h"
-
+#include "nsHTMLTags.h"
+#include "nsIDTD.h"
 
 //*********************************************************************************************
 // The following ints define the standard groups of HTML elements...
 //*********************************************************************************************
 
 static const int kNone= 0x0;
 
 static const int kHTMLContent   = 0x0001; //  HEAD, (FRAMESET | BODY)
@@ -54,184 +53,40 @@ static const int kBlockEntity   = (kHead
 static const int kFlowEntity    = (kBlockEntity|kInlineEntity); //  %blockentity, %inlineentity
 static const int kAllTags       = 0xffffff;
 
 
 //*********************************************************************************************
 // The following ints define the standard groups of HTML elements...
 //*********************************************************************************************
 
-
 #ifdef DEBUG
 extern void CheckElementTable();
 #endif
 
 
 /**
  * We're asking the question: is aTest a member of bitset. 
  *
- * @update	gess 01/04/99
  * @param 
  * @return TRUE or FALSE
  */
 inline bool TestBits(int aBitset,int aTest) {
   if(aTest) {
     int32_t result=(aBitset & aTest);
     return bool(result==aTest);
   }
   return false;
 }
 
-
-/**
- * 
- * @update	gess 01/04/99
- * @param 
- * @return
- */
 struct nsHTMLElement {
-
-#ifdef DEBUG
-  static  void    DebugDumpMembership(const char* aFilename);
-  static  void    DebugDumpContainment(const char* aFilename,const char* aTitle);
-  static  void    DebugDumpContainType(const char* aFilename);
-#endif
-
-  static  bool    IsInlineEntity(eHTMLTags aTag);
-  static  bool    IsFlowEntity(eHTMLTags aTag);
-  static  bool    IsBlockCloser(eHTMLTags aTag);
-
-  inline  bool    IsBlock(void) const { 
-                    if((mTagID>=eHTMLTag_unknown) & (mTagID<=eHTMLTag_xmp)){
-                      return TestBits(mParentBits,kBlock);
-                    } 
-                    return false;
-                  }
-
-  inline  bool    IsBlockEntity(void) const { 
-                    if((mTagID>=eHTMLTag_unknown) & (mTagID<=eHTMLTag_xmp)){
-                      return TestBits(mParentBits,kBlockEntity);
-                    } 
-                    return false;
-                  }
-
-  inline  bool    IsSpecialEntity(void) const { 
-                    if((mTagID>=eHTMLTag_unknown) & (mTagID<=eHTMLTag_xmp)){
-                      return TestBits(mParentBits,kSpecial);
-                    } 
-                    return false;
-                  }
-
-  inline  bool    IsPhraseEntity(void) const { 
-                    if((mTagID>=eHTMLTag_unknown) & (mTagID<=eHTMLTag_xmp)){
-                      return TestBits(mParentBits,kPhrase);
-                    } 
-                    return false;
-                  }
-
-  inline  bool    IsFontStyleEntity(void) const { 
-                    if((mTagID>=eHTMLTag_unknown) & (mTagID<=eHTMLTag_xmp)){
-                      return TestBits(mParentBits,kFontStyle);
-                    } 
-                    return false;
-                  }
-  
-  inline  bool    IsTableElement(void) const {  //return yes if it's a table or child of a table...
-                    bool result=false;
-
-                    switch(mTagID) {
-                      case eHTMLTag_table:
-                      case eHTMLTag_thead:
-                      case eHTMLTag_tbody:
-                      case eHTMLTag_tfoot:
-                      case eHTMLTag_caption:
-                      case eHTMLTag_tr:
-                      case eHTMLTag_td:
-                      case eHTMLTag_th:
-                      case eHTMLTag_col:
-                      case eHTMLTag_colgroup:
-                        result=true;
-                        break;
-                      default:
-                        result=false;
-                    }
-                    return result;
-                  }
-
-
-  static  int32_t GetIndexOfChildOrSynonym(nsDTDContext& aContext,eHTMLTags aChildTag);
-
-  const TagList*  GetSynonymousTags(void) const {return mSynonymousTags;}
-  const TagList*  GetRootTags(void) const {return mRootNodes;}
-  const TagList*  GetEndRootTags(void) const {return mEndRootNodes;}
-  const TagList*  GetAutoCloseStartTags(void) const {return mAutocloseStart;}
-  const TagList*  GetAutoCloseEndTags(void) const {return mAutocloseEnd;}
-  eHTMLTags       GetCloseTargetForEndTag(nsDTDContext& aContext,int32_t anIndex,nsDTDMode aMode) const;
-
-  const TagList*        GetSpecialChildren(void) const {return mSpecialKids;}
-  const TagList*        GetSpecialParents(void) const {return mSpecialParents;}
-
   bool            IsMemberOf(int32_t aType) const;
-  bool            ContainsSet(int32_t aType) const;
-  bool            CanContainType(int32_t aType) const;
-
-  bool            CanContain(eHTMLTags aChild,nsDTDMode aMode) const;
-  bool            CanExclude(eHTMLTags aChild) const;
-  bool            CanOmitEndTag(void) const;
-  bool            CanContainSelf(void) const;
-  bool            CanAutoCloseTag(nsDTDContext& aContext,int32_t aIndex,eHTMLTags aTag) const;
-  bool            HasSpecialProperty(int32_t aProperty) const;
-  bool            IsSpecialParent(eHTMLTags aTag) const;
-  bool            IsExcludableParent(eHTMLTags aParent) const;
-  bool            SectionContains(eHTMLTags aTag,bool allowDepthSearch) const;
-  bool            ShouldVerifyHierarchy() const;
-
-  static  bool    CanContain(eHTMLTags aParent,eHTMLTags aChild,nsDTDMode aMode);
-  static  bool    IsContainer(eHTMLTags aTag) ;
-  static  bool    IsResidualStyleTag(eHTMLTags aTag) ;
-  static  bool    IsTextTag(eHTMLTags aTag);
-  static  bool    IsWhitespaceTag(eHTMLTags aTag);
-
-  static  bool    IsBlockParent(eHTMLTags aTag);
-  static  bool    IsInlineParent(eHTMLTags aTag); 
-  static  bool    IsFlowParent(eHTMLTags aTag);
-  static  bool    IsSectionTag(eHTMLTags aTag);
-  static  bool    IsChildOfHead(eHTMLTags aTag,bool& aExclusively) ;
 
   eHTMLTags       mTagID;
-  eHTMLTags       mRequiredAncestor;
-  eHTMLTags       mExcludingAncestor; //If set, the presence of the excl-ancestor prevents this from opening.
-  const TagList*  mRootNodes;         //These are the tags above which you many not autoclose a START tag
-  const TagList*        mEndRootNodes;      //These are the tags above which you many not autoclose an END tag
-  const TagList*        mAutocloseStart;    //these are the start tags that you can automatically close with this START tag
-  const TagList*        mAutocloseEnd;      //these are the start tags that you can automatically close with this END tag
-  const TagList*        mSynonymousTags;    //These are morally equivalent; an end tag for one can close a start tag for another (like <Hn>)
-  const TagList*        mExcludableParents; //These are the TAGS that cannot contain you
   int             mParentBits;        //defines groups that can contain this element
-  int             mInclusionBits;     //defines parental and containment rules
-  int             mExclusionBits;     //defines things you CANNOT contain
-  int             mSpecialProperties; //used for various special purposes...
-  uint32_t        mPropagateRange;    //tells us how far a parent is willing to prop. badly formed children
-  const TagList*  mSpecialParents;    //These are the special tags that contain this tag (directly)
-  const TagList*  mSpecialKids;       //These are the extra things you can contain
+  bool            mLeaf;
+
+  static  bool    IsContainer(eHTMLTags aTag);
 }; 
 
 extern const nsHTMLElement gHTMLElements[];
 
-//special property bits...
-static const int kPreferBody       = 0x0001; //this kHeadMisc tag prefers to be in the body if there isn't an explicit <head>
-static const int kOmitEndTag       = 0x0002; //safely ignore end tag
-static const int kLegalOpen        = 0x0004; //Lets BODY, TITLE, SCRIPT to reopen
-static const int kNoPropagate      = 0x0008; //If set, this tag won't propagate as a child
-static const int kBadContentWatch  = 0x0010; 
-
-static const int kNoStyleLeaksIn   = 0x0020; 
-static const int kNoStyleLeaksOut  = 0x0040; 
-
-static const int kMustCloseSelf    = 0x0080; 
-static const int kSaveMisplaced    = 0x0100; //If set, then children this tag can't contain are pushed onto the misplaced stack
-static const int kNonContainer     = 0x0200; //If set, then this tag is not a container.
-static const int kHandleStrayTag   = 0x0400; //If set, we automatically open a start tag
-static const int kRequiresBody     = 0x0800; //If set, then in case of no BODY one will be opened up immediately.
-static const int kVerifyHierarchy  = 0x1000; //If set, check to see if the tag is a child or a sibling..
-static const int kPreferHead       = 0x2000; //This kHeadMisc tag prefers to be in the head if there isn't an explicit <body>
-
 #endif
--- a/parser/htmlparser/src/nsExpatDriver.cpp
+++ b/parser/htmlparser/src/nsExpatDriver.cpp
@@ -1284,46 +1284,37 @@ nsExpatDriver::WillBuildModel(const CPar
 
   // XML must detect invalid character convertion
   aParserContext.mScanner->OverrideReplacementCharacter(0xffff);
 
   return mInternalState;
 }
 
 NS_IMETHODIMP
-nsExpatDriver::BuildModel(nsITokenizer* aTokenizer,
-                          bool,// aCountLines,
-                          const nsCString*)// aCharsetPtr)
+nsExpatDriver::BuildModel(nsITokenizer* aTokenizer, nsIContentSink* aSink)
 {
   return mInternalState;
 }
 
 NS_IMETHODIMP
 nsExpatDriver::DidBuildModel(nsresult anErrorCode)
 {
   mOriginalSink = nullptr;
   mSink = nullptr;
   mExtendedSink = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsExpatDriver::WillTokenize(bool aIsFinalChunk,
-                            nsTokenAllocator* aTokenAllocator)
+nsExpatDriver::WillTokenize(bool aIsFinalChunk)
 {
   mIsFinalChunk = aIsFinalChunk;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsExpatDriver::DidTokenize(bool aIsFinalChunk)
-{
-  return NS_OK;
-}
-
 NS_IMETHODIMP_(void)
 nsExpatDriver::Terminate()
 {
   // XXX - not sure what happens to the unparsed data.
   if (mExpatParser) {
     XML_StopParser(mExpatParser, XML_FALSE);
   }
   mInternalState = NS_ERROR_HTMLPARSER_STOPPARSING;
@@ -1338,75 +1329,16 @@ nsExpatDriver::GetType()
 NS_IMETHODIMP_(nsDTDMode)
 nsExpatDriver::GetMode() const
 {
   return eDTDMode_full_standards;
 }
 
 /*************************** Unused methods **********************************/
 
-NS_IMETHODIMP_(CToken*)
-nsExpatDriver::PushTokenFront(CToken* aToken)
-{
-  return 0;
-}
-
-NS_IMETHODIMP_(CToken*)
-nsExpatDriver::PushToken(CToken* aToken)
-{
-  return 0;
-}
-
-NS_IMETHODIMP_(CToken*)
-nsExpatDriver::PopToken(void)
-{
-  return 0;
-}
-
-NS_IMETHODIMP_(CToken*)
-nsExpatDriver::PeekToken(void)
-{
-  return 0;
-}
-
-NS_IMETHODIMP_(CToken*)
-nsExpatDriver::GetTokenAt(int32_t anIndex)
-{
-  return 0;
-}
-
-NS_IMETHODIMP_(int32_t)
-nsExpatDriver::GetCount(void)
-{
-  return 0;
-}
-
-NS_IMETHODIMP_(nsTokenAllocator*)
-nsExpatDriver::GetTokenAllocator(void)
-{
-  return 0;
-}
-
-NS_IMETHODIMP_(void)
-nsExpatDriver::PrependTokens(nsDeque& aDeque)
-{
-}
-
-NS_IMETHODIMP
-nsExpatDriver::CopyState(nsITokenizer* aTokenizer)
-{
-  return NS_OK;
-}
-
-nsresult
-nsExpatDriver::HandleToken(CToken* aToken)
-{
-  return NS_OK;
-}
-
 NS_IMETHODIMP_(bool)
 nsExpatDriver::IsContainer(int32_t aTag) const
 {
   return true;
 }
 
 NS_IMETHODIMP_(bool)
 nsExpatDriver::CanContain(int32_t aParent,int32_t aChild) const
--- a/parser/htmlparser/src/nsExpatDriver.h
+++ b/parser/htmlparser/src/nsExpatDriver.h
@@ -62,18 +62,16 @@ public:
                               const PRUnichar* aPubid);
   nsresult HandleUnparsedEntityDecl(const PRUnichar* aEntityName,
                                     const PRUnichar* aBase,
                                     const PRUnichar* aSysid,
                                     const PRUnichar* aPubid,
                                     const PRUnichar* aNotationName);
 
 private:
-  nsresult HandleToken(CToken* aToken);
-
   // Load up an external stream to get external entity information
   nsresult OpenInputStreamFromExternalDTD(const PRUnichar* aFPIStr,
                                           const PRUnichar* aURLStr,
                                           const PRUnichar* aBaseURL,
                                           nsIInputStream** aStream,
                                           nsAString& aAbsURL);
 
   /**
--- a/parser/htmlparser/src/nsHTMLTokenizer.cpp
+++ b/parser/htmlparser/src/nsHTMLTokenizer.cpp
@@ -11,22 +11,18 @@
  * This file contains the implementation of a tokenizer to tokenize an HTML
  * document. It attempts to do so, making tradeoffs between compatibility with
  * older parsers and the SGML specification. Note that most of the real
  * "tokenization" takes place in nsHTMLTokens.cpp.
  */
 
 #include "nsIAtom.h"
 #include "nsHTMLTokenizer.h"
-#include "nsScanner.h"
-#include "nsElementTable.h"
-#include "nsReadableUtils.h"
-#include "nsUnicharUtils.h"
 #include "nsParserConstants.h"
-#include "mozilla/Likely.h"
+#include "nsIHTMLContentSink.h"
 
 /************************************************************************
   And now for the main class -- nsHTMLTokenizer...
  ************************************************************************/
 
 /**
  * Satisfy the nsISupports interface.
  */
@@ -38,59 +34,26 @@ NS_IMPL_ISUPPORTS1(nsHTMLTokenizer, nsIT
  * @param  aParseMode The current mode the document is in (quirks, etc.)
  * @param  aDocType The document type of the current document
  * @param  aCommand What we are trying to do (view-source, parse a fragment, etc.)
  */
 nsHTMLTokenizer::nsHTMLTokenizer(nsDTDMode aParseMode,
                                  eParserDocType aDocType,
                                  eParserCommands aCommand,
                                  uint32_t aFlags)
-  : mTokenDeque(0), mFlags(aFlags)
 {
-  if (aParseMode == eDTDMode_full_standards ||
-      aParseMode == eDTDMode_almost_standards) {
-    mFlags |= NS_IPARSER_FLAG_STRICT_MODE;
-  } else if (aParseMode == eDTDMode_quirks)  {
-    mFlags |= NS_IPARSER_FLAG_QUIRKS_MODE;
-  } else if (aParseMode == eDTDMode_autodetect) {
-    mFlags |= NS_IPARSER_FLAG_AUTO_DETECT_MODE;
-  } else {
-    mFlags |= NS_IPARSER_FLAG_UNKNOWN_MODE;
-  }
-
-  if (aDocType == ePlainText) {
-    mFlags |= NS_IPARSER_FLAG_PLAIN_TEXT;
-  } else if (aDocType == eXML) {
-    mFlags |= NS_IPARSER_FLAG_XML;
-  } else if (aDocType == eHTML_Quirks ||
-             aDocType == eHTML_Strict) {
-    mFlags |= NS_IPARSER_FLAG_HTML;
-  }
-  
-  mFlags |= aCommand == eViewSource
-            ? NS_IPARSER_FLAG_VIEW_SOURCE
-            : NS_IPARSER_FLAG_VIEW_NORMAL;
-
-  NS_ASSERTION(!(mFlags & NS_IPARSER_FLAG_XML) || 
-                (mFlags & NS_IPARSER_FLAG_VIEW_SOURCE),
-              "Why isn't this XML document going through our XML parser?");
-
-  mTokenAllocator = nullptr;
-  mTokenScanPos = 0;
+  // TODO Assert about:blank-ness.
+  MOZ_ASSERT(!(aFlags & NS_IPARSER_FLAG_XML));
 }
 
 /**
  * The destructor ensures that we don't leak any left over tokens.
  */
 nsHTMLTokenizer::~nsHTMLTokenizer()
 {
-  if (mTokenDeque.GetSize()) {
-    CTokenDeallocator theDeallocator(mTokenAllocator->GetArenaPool());
-    mTokenDeque.ForEach(theDeallocator);
-  }
 }
 
 /*static*/ uint32_t
 nsHTMLTokenizer::GetFlags(const nsIContentSink* aSink)
 {
   uint32_t flags = 0;
   nsCOMPtr<nsIHTMLContentSink> sink =
     do_QueryInterface(const_cast<nsIContentSink*>(aSink));
@@ -103,1095 +66,31 @@ nsHTMLTokenizer::GetFlags(const nsIConte
     sink->IsEnabled(eHTMLTag_script, &enabled);
     if (enabled) {
       flags |= NS_IPARSER_FLAG_SCRIPT_ENABLED;
     }
   }
   return flags;
 }
 
-/*******************************************************************
-  Here begins the real working methods for the tokenizer.
- *******************************************************************/
-
-/**
- * Adds a token onto the end of the deque if aResult is a successful result.
- * Otherwise, this function frees aToken and sets it to nullptr.
- *
- * @param aToken The token that wants to be added.
- * @param aResult The error code that will be used to determine if we actually
- *                want to push this token.
- * @param aDeque The deque we want to push aToken onto.
- * @param aTokenAllocator The allocator we use to free aToken in case aResult
- *                        is not a success code.
- */
-/* static */
-void
-nsHTMLTokenizer::AddToken(CToken*& aToken,
-                          nsresult aResult,
-                          nsDeque* aDeque,
-                          nsTokenAllocator* aTokenAllocator)
-{
-  if (aToken && aDeque) {
-    if (NS_SUCCEEDED(aResult)) {
-      aDeque->Push(aToken);
-    } else {
-      IF_FREE(aToken, aTokenAllocator);
-    }
-  }
-}
-
-/**
- * Retrieve a pointer to the global token recycler...
- *
- * @return Pointer to recycler (or null)
- */
-nsTokenAllocator*
-nsHTMLTokenizer::GetTokenAllocator()
-{
-  return mTokenAllocator;
-}
-
-/**
- * This method provides access to the topmost token in the tokenDeque.
- * The token is not really removed from the list.
- *
- * @return Pointer to token
- */
-CToken*
-nsHTMLTokenizer::PeekToken()
-{
-  return (CToken*)mTokenDeque.PeekFront();
-}
-
-/**
- * This method provides access to the topmost token in the tokenDeque.
- * The token is really removed from the list; if the list is empty we return 0.
- *
- * @return Pointer to token or nullptr
- */
-CToken*
-nsHTMLTokenizer::PopToken()
-{
-  return (CToken*)mTokenDeque.PopFront();
-}
-
-
-/**
- * Pushes a token onto the front of our deque such that the next call to
- * PopToken() or PeekToken() will return that token.
- * 
- * @param theToken The next token to be processed
- * @return theToken
- */
-CToken*
-nsHTMLTokenizer::PushTokenFront(CToken* theToken)
+nsresult
+nsHTMLTokenizer::WillTokenize(bool aIsFinalChunk)
 {
-  mTokenDeque.PushFront(theToken);
-  return theToken;
-}
-
-/**
- * Pushes a token onto the deque.
- * 
- * @param theToken the new token.
- * @return theToken
- */
-CToken*
-nsHTMLTokenizer::PushToken(CToken* theToken)
-{
-  mTokenDeque.Push(theToken);
-  return theToken;
-}
-
-/**
- * Returns the size of the deque.
- *
- * @return The number of remaining tokens.
- */
-int32_t
-nsHTMLTokenizer::GetCount()
-{
-  return mTokenDeque.GetSize();
-}
-
-/**
- * Allows access to an arbitrary token in the deque. The accessed token is left
- * in the deque.
- *
- * @param anIndex The index of the target token. Token 0 would be the same as
- *                the result of a call to PeekToken()
- * @return The requested token.
- */
-CToken*
-nsHTMLTokenizer::GetTokenAt(int32_t anIndex)
-{
-  return (CToken*)mTokenDeque.ObjectAt(anIndex);
-}
-
-/**
- * This method is part of the "sandwich" that occurs when we want to tokenize
- * a document. This prepares us to be able to tokenize properly.
- *
- * @param aIsFinalChunk Whether this is the last chunk of data that we will
- *                      get to see.
- * @param aTokenAllocator The token allocator to use for this document.
- * @return Our success in setting up.
- */
-nsresult
-nsHTMLTokenizer::WillTokenize(bool aIsFinalChunk,
-                              nsTokenAllocator* aTokenAllocator)
-{
-  mTokenAllocator = aTokenAllocator;
-  mIsFinalChunk = aIsFinalChunk;
-
-  // Cause ScanDocStructure to search from here for new tokens...
-  mTokenScanPos = mTokenDeque.GetSize();
-  return NS_OK;
-}
-
-/**
- * Pushes all of the tokens in aDeque onto the front of our deque so they
- * get processed before any other tokens.
- *
- * @param aDeque The deque with the tokens in it.
- */
-void
-nsHTMLTokenizer::PrependTokens(nsDeque& aDeque)
-{
-  int32_t aCount = aDeque.GetSize();
-  
-  for (int32_t anIndex = 0; anIndex < aCount; ++anIndex) {
-    CToken* theToken = (CToken*)aDeque.Pop();
-    PushTokenFront(theToken);
-  }
-}
-
-/**
- * Copies the state flags from aTokenizer into this tokenizer. This is used
- * to pass information around between the main tokenizer and tokenizers
- * created for document.write() calls.
- *
- * @param aTokenizer The tokenizer with more information in it.
- * @return NS_OK
- */
-nsresult
-nsHTMLTokenizer::CopyState(nsITokenizer* aTokenizer)
-{
-  if (aTokenizer) {
-    mFlags = ((nsHTMLTokenizer*)aTokenizer)->mFlags;
-  }
-
   return NS_OK;
 }
 
 /**
- * This is a utilty method for ScanDocStructure, which finds a given
- * tag in the stack. The return value is meant to be used with
- * nsDeque::ObjectAt() on aTagStack.
- *
- * @param   aTag -- the ID of the tag we're seeking
- * @param   aTagStack -- the stack to be searched
- * @return  index position of tag in stack if found, otherwise kNotFound
- */
-static int32_t
-FindLastIndexOfTag(eHTMLTags aTag, nsDeque &aTagStack)
-{
-  int32_t theCount = aTagStack.GetSize();
-  
-  while (0 < theCount) {
-    CHTMLToken* theToken = (CHTMLToken*)aTagStack.ObjectAt(--theCount);  
-    if (theToken) {
-      eHTMLTags theTag = (eHTMLTags)theToken->GetTypeID();
-      if (theTag == aTag) {
-        return theCount;
-      }
-    }
-  }
-
-  return kNotFound;
-}
-
-/**
- * This method scans the sequence of tokens to determine whether or not the
- * tag structure of the document is well formed. In well formed cases, we can
- * skip doing residual style handling and allow inlines to contain block-level
- * elements.
- *
- * @param aFinalChunk Is unused.
- * @return Success (currently, this function cannot fail).
- */
-nsresult nsHTMLTokenizer::ScanDocStructure(bool aFinalChunk)
-{
-  nsresult result = NS_OK;
-  if (!mTokenDeque.GetSize()) {
-    return result;
-  }
-
-  CHTMLToken* theToken = (CHTMLToken*)mTokenDeque.ObjectAt(mTokenScanPos);
-
-  // Start by finding the first start tag that hasn't been reviewed.
-  while (mTokenScanPos > 0) {
-    if (theToken) {
-      eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType());  
-      if (theType == eToken_start &&
-          theToken->GetContainerInfo() == eFormUnknown) {
-        break;
-      }
-    }
-    theToken = (CHTMLToken*)mTokenDeque.ObjectAt(--mTokenScanPos);
-  }
-
-  // Now that we know where to start, let's walk through the
-  // tokens to see which are well-formed. Stop when you run out
-  // of fresh tokens.
-
-  nsDeque       theStack(0);
-  nsDeque       tempStack(0);
-  int32_t       theStackDepth = 0;
-  // Don't bother if we get ridiculously deep.
-  static  const int32_t theMaxStackDepth = 200;
-
-  while (theToken && theStackDepth < theMaxStackDepth) {
-    eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType());
-    eHTMLTags       theTag  = (eHTMLTags)theToken->GetTypeID();
-
-    if (nsHTMLElement::IsContainer(theTag)) { // Bug 54117
-      bool theTagIsBlock  = gHTMLElements[theTag].IsMemberOf(kBlockEntity);
-      bool theTagIsInline = theTagIsBlock
-                              ? false
-                              : gHTMLElements[theTag].IsMemberOf(kInlineEntity);
-
-      if (theTagIsBlock || theTagIsInline || eHTMLTag_table == theTag) {
-        switch(theType) {
-          case eToken_start:
-            {
-              if (gHTMLElements[theTag].ShouldVerifyHierarchy()) {
-                int32_t earlyPos = FindLastIndexOfTag(theTag, theStack);
-                if (earlyPos != kNotFound) {
-                  // Uh-oh, we've found a tag that is not allowed to nest at
-                  // all. Mark the previous one and all of its children as 
-                  // malformed to increase our chances of doing RS handling
-                  // on all of them. We want to do this for cases such as:
-                  // <a><div><a></a></div></a>.
-                  // Note that we have to iterate through all of the chilren
-                  // of the original malformed tag to protect against:
-                  // <a><font><div><a></a></div></font></a>, so that the <font>
-                  // is allowed to contain the <div>.
-                  // XXX What about <a><span><a>, where the second <a> closes
-                  // the <span>?
-                  nsDequeIterator it(theStack, earlyPos), end(theStack.End());
-                  while (it < end) {
-                    CHTMLToken *theMalformedToken = 
-                        static_cast<CHTMLToken*>(it++);
-                  
-                    theMalformedToken->SetContainerInfo(eMalformed);
-                  }
-                }
-              }
-
-              theStack.Push(theToken);
-              ++theStackDepth;
-            }
-            break;
-          case eToken_end: 
-            {
-              CHTMLToken *theLastToken =
-                static_cast<CHTMLToken*>(theStack.Peek());
-              if (theLastToken) {
-                if (theTag == theLastToken->GetTypeID()) {
-                  theStack.Pop(); // Yank it for real 
-                  theStackDepth--;
-                  theLastToken->SetContainerInfo(eWellFormed);
-                } else {
-                  // This token wasn't what we expected it to be! We need to
-                  // go searching for its real start tag on our stack. Each
-                  // tag in between the end tag and start tag must be malformed
-
-                  if (FindLastIndexOfTag(theTag, theStack) != kNotFound) {
-                    // Find theTarget in the stack, marking each (malformed!)
-                    // tag in our way.
-                    theStack.Pop(); // Pop off theLastToken for real.
-                    do {
-                      theLastToken->SetContainerInfo(eMalformed);
-                      tempStack.Push(theLastToken);
-                      theLastToken = static_cast<CHTMLToken*>(theStack.Pop());
-                    } while (theLastToken && theTag != theLastToken->GetTypeID());
-                    // XXX The above test can confuse two different userdefined 
-                    // tags.
-
-                    NS_ASSERTION(theLastToken,
-                                 "FindLastIndexOfTag lied to us!"
-                                 " We couldn't find theTag on theStack");
-                    theLastToken->SetContainerInfo(eMalformed);
-
-                    // Great, now push all of the other tokens back onto the
-                    // stack to preserve the general structure of the document.
-                    // Note that we don't push the target token back onto the
-                    // the stack (since it was just closed).
-                    while (tempStack.GetSize() != 0) {
-                      theStack.Push(tempStack.Pop());
-                    }
-                  }
-                }
-              }
-            }
-            break;
-          default:
-            break; 
-        }
-      }
-    }
-
-    theToken = (CHTMLToken*)mTokenDeque.ObjectAt(++mTokenScanPos);
-  }
-
-  return result;
-}
-
-/**
- * This method is called after we're done tokenizing a chunk of data.
- *
- * @param aFinalChunk Tells us if this was the last chunk of data.
- * @return Error result.
- */
-nsresult
-nsHTMLTokenizer::DidTokenize(bool aFinalChunk)
-{
-  return ScanDocStructure(aFinalChunk);
-}
-
-/**
  * This method is repeatedly called by the tokenizer. 
  * Each time, we determine the kind of token we're about to 
  * read, and then we call the appropriate method to handle
  * that token type.
  *  
  * @param  aScanner The source of our input.
  * @param  aFlushTokens An OUT parameter to tell the caller whether it should
  *                      process our queued tokens up to now (e.g., when we
  *                      reach a <script>).
  * @return Success or error
  */
 nsresult
 nsHTMLTokenizer::ConsumeToken(nsScanner& aScanner, bool& aFlushTokens)
 {
-  PRUnichar theChar;
-  CToken* theToken = nullptr;
-
-  nsresult result = aScanner.Peek(theChar);
-
-  switch(result) {
-    case kEOF:
-      // Tell our caller that'we finished.
-      return result;
-
-    case NS_OK:
-    default:
-      if (!(mFlags & NS_IPARSER_FLAG_PLAIN_TEXT)) {
-        if (kLessThan == theChar) {
-          return ConsumeTag(theChar, theToken, aScanner, aFlushTokens);
-        } else if (kAmpersand == theChar) {
-          return ConsumeEntity(theChar, theToken, aScanner);
-        }
-      }
-
-      if (kCR == theChar || kLF == theChar) {
-        return ConsumeNewline(theChar, theToken, aScanner);
-      } else {
-        if (!nsCRT::IsAsciiSpace(theChar)) {
-          if (theChar != '\0') {
-            result = ConsumeText(theToken, aScanner);
-          } else {
-            // Skip the embedded null char. Fix bug 64098.
-            aScanner.GetChar(theChar);
-          }
-          break;
-        }
-        result = ConsumeWhitespace(theChar, theToken, aScanner);
-      }
-      break;
-  }
-
-  return result;
-}
-
-/**
- * This method is called just after a "<" has been consumed 
- * and we know we're at the start of some kind of tagged 
- * element. We don't know yet if it's a tag or a comment.
- * 
- * @param   aChar is the last char read
- * @param   aToken is the out arg holding our new token (the function allocates
- *                 the return token using mTokenAllocator).
- * @param   aScanner represents our input source
- * @param   aFlushTokens is an OUT parameter use to tell consumers to flush
- *                       the current tokens after processing the current one.
- * @return  error code.
- */
-nsresult
-nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,
-                            CToken*& aToken,
-                            nsScanner& aScanner,
-                            bool& aFlushTokens)
-{
-  PRUnichar theNextChar, oldChar;
-  nsresult result = aScanner.Peek(aChar, 1);
-
-  if (NS_OK == result) {
-    switch (aChar) {
-      case kForwardSlash:
-        result = aScanner.Peek(theNextChar, 2);
-
-        if (NS_OK == result) {
-          // Get the original "<" (we've already seen it with a Peek)
-          aScanner.GetChar(oldChar);
-
-          // XML allows non ASCII tag names, consume this as an end tag. This
-          // is needed to make XML view source work
-          bool isXML = !!(mFlags & NS_IPARSER_FLAG_XML);
-          if (nsCRT::IsAsciiAlpha(theNextChar) ||
-              kGreaterThan == theNextChar      ||
-              (isXML && !nsCRT::IsAscii(theNextChar))) {
-            result = ConsumeEndTag(aChar, aToken, aScanner);
-          } else {
-            result = ConsumeComment(aChar, aToken, aScanner);
-          }
-        }
-
-        break;
-
-      case kExclamation:
-        result = aScanner.Peek(theNextChar, 2);
-
-        if (NS_OK == result) {
-          // Get the original "<" (we've already seen it with a Peek)
-          aScanner.GetChar(oldChar);
-
-          if (kMinus == theNextChar || kGreaterThan == theNextChar) {
-            result = ConsumeComment(aChar, aToken, aScanner);
-          } else {
-            result = ConsumeSpecialMarkup(aChar, aToken, aScanner);
-          }
-        }
-        break;
-
-      case kQuestionMark:
-        // It must be a processing instruction...
-        // Get the original "<" (we've already seen it with a Peek)
-        aScanner.GetChar(oldChar);
-        result = ConsumeProcessingInstruction(aChar, aToken, aScanner);
-        break;
-
-      default:
-        // XML allows non ASCII tag names, consume this as a start tag.
-        bool isXML = !!(mFlags & NS_IPARSER_FLAG_XML);
-        if (nsCRT::IsAsciiAlpha(aChar) ||
-            (isXML && !nsCRT::IsAscii(aChar))) {
-          // Get the original "<" (we've already seen it with a Peek)
-          aScanner.GetChar(oldChar);
-          result = ConsumeStartTag(aChar, aToken, aScanner, aFlushTokens);
-        } else {
-          // We are not dealing with a tag. So, don't consume the original
-          // char and leave the decision to ConsumeText().
-          result = ConsumeText(aToken, aScanner);
-        }
-    }
-  }
-
-  // Last ditch attempt to make sure we don't lose data.
-  if (kEOF == result && !aScanner.IsIncremental()) {
-    // Whoops, we don't want to lose any data! Consume the rest as text.
-    // This normally happens for either a trailing < or </
-    result = ConsumeText(aToken, aScanner);
-  }
-
-  return result;
-}
-
-/**
- * This method is called just after we've consumed a start or end
- * tag, and we now have to consume its attributes.
- * 
- * @param   aChar is the last char read
- * @param   aToken is the start or end tag that "owns" these attributes.
- * @param   aScanner represents our input source
- * @return  Error result.
- */
-nsresult
-nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,
-                                   CToken* aToken,
-                                   nsScanner& aScanner)
-{
-  bool done = false;
-  nsresult result = NS_OK;
-  int16_t theAttrCount = 0;
-
-  nsTokenAllocator* theAllocator = this->GetTokenAllocator();
-
-  while (!done && result == NS_OK) {
-    CAttributeToken* theToken =
-      static_cast<CAttributeToken*>
-                 (theAllocator->CreateTokenOfType(eToken_attribute,
-                                                     eHTMLTag_unknown));
-    if (MOZ_LIKELY(theToken != nullptr)) {
-      // Tell the new token to finish consuming text...
-      result = theToken->Consume(aChar, aScanner, mFlags);
-
-      if (NS_SUCCEEDED(result)) {
-        ++theAttrCount;
-        AddToken((CToken*&)theToken, result, &mTokenDeque, theAllocator);
-      } else {
-        IF_FREE(theToken, mTokenAllocator);
-        // Bad attribute returns shouldn't propagate out.
-        if (NS_ERROR_HTMLPARSER_BADATTRIBUTE == result) {
-          result = NS_OK;
-        }
-      }
-    }
-    else {
-      result = NS_ERROR_OUT_OF_MEMORY;
-    }
-
-#ifdef DEBUG
-    if (NS_SUCCEEDED(result)) {
-      int32_t newline = 0;
-      aScanner.SkipWhitespace(newline);
-      NS_ASSERTION(newline == 0,
-          "CAttribute::Consume() failed to collect all the newlines!");
-    }
-#endif
-    if (NS_SUCCEEDED(result)) {
-      result = aScanner.Peek(aChar);
-      if (NS_SUCCEEDED(result)) {
-        if (aChar == kGreaterThan) { // You just ate the '>'
-          aScanner.GetChar(aChar); // Skip the '>'
-          done = true;
-        } else if (aChar == kLessThan) {
-          aToken->SetInError(true);
-          done = true;
-        }
-      }
-    }
-  }
-
-  if (NS_FAILED(result)) {
-    aToken->SetInError(true);
-
-    if (!aScanner.IsIncremental()) {
-      result = NS_OK;
-    }
-  }
-
-  aToken->SetAttributeCount(theAttrCount);
-  return result;
+  return kEOF;
 }
-
-/**
- * This method consumes a start tag and all of its attributes.
- *
- * @param aChar The last character read from the scanner.
- * @param aToken The OUT parameter that holds our resulting token. (allocated
- *               by the function using mTokenAllocator
- * @param aScanner Our source of data
- * @param aFlushTokens is an OUT parameter use to tell consumers to flush
- *                     the current tokens after processing the current one.
- * @return Error result.
- */
-nsresult
-nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,
-                                 CToken*& aToken,
-                                 nsScanner& aScanner,
-                                 bool& aFlushTokens)
-{
-  // Remember this for later in case you have to unwind...
-  int32_t theDequeSize = mTokenDeque.GetSize();
-  nsresult result = NS_OK;
-
-  nsTokenAllocator* theAllocator = this->GetTokenAllocator();
-  aToken = theAllocator->CreateTokenOfType(eToken_start, eHTMLTag_unknown);
-  NS_ENSURE_TRUE(aToken, NS_ERROR_OUT_OF_MEMORY);
-
-  // Tell the new token to finish consuming text...
-  result = aToken->Consume(aChar, aScanner, mFlags);
-
-  if (NS_SUCCEEDED(result)) {
-    AddToken(aToken, result, &mTokenDeque, theAllocator);
-
-    eHTMLTags theTag = (eHTMLTags)aToken->GetTypeID();
-
-    // Good. Now, let's see if the next char is ">".
-    // If so, we have a complete tag, otherwise, we have attributes.
-    result = aScanner.Peek(aChar);
-    if (NS_FAILED(result)) {
-      aToken->SetInError(true);
-
-      // Don't return early here so we can create a text and end token for
-      // the special <iframe>, <script> and similar tags down below.
-      result = NS_OK;
-    } else {
-      if (kGreaterThan != aChar) { // Look for a '>'
-        result = ConsumeAttributes(aChar, aToken, aScanner);
-      } else {
-        aScanner.GetChar(aChar);
-      }
-    }
-
-    /*  Now that that's over with, we have one more problem to solve.
-        In the case that we just read a <SCRIPT> or <STYLE> tags, we should go and
-        consume all the content itself.
-        But XML doesn't treat these tags differently, so we shouldn't if the
-        document is XML.
-     */
-    if (NS_SUCCEEDED(result) && !(mFlags & NS_IPARSER_FLAG_XML)) {
-      bool isCDATA = gHTMLElements[theTag].CanContainType(kCDATA);
-      bool isPCDATA = eHTMLTag_textarea == theTag ||
-                        eHTMLTag_title    == theTag;
-
-      // XXX This is an evil hack, we should be able to handle these properly
-      // in the DTD.
-      if ((eHTMLTag_iframe == theTag &&
-            (mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED)) ||
-          (eHTMLTag_noframes == theTag &&
-            (mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED)) ||
-          (eHTMLTag_noscript == theTag &&
-            (mFlags & NS_IPARSER_FLAG_SCRIPT_ENABLED)) ||
-          (eHTMLTag_noembed == theTag)) {
-        isCDATA = true;
-      }
-
-      // Plaintext contains CDATA, but it's special, so we handle it
-      // differently than the other CDATA elements
-      if (eHTMLTag_plaintext == theTag) {
-        isCDATA = false;
-
-        // Note: We check in ConsumeToken() for this flag, and if we see it
-        // we only construct text tokens (which is what we want).
-        mFlags |= NS_IPARSER_FLAG_PLAIN_TEXT;
-      }
-
-
-      if (isCDATA || isPCDATA) {
-        bool done = false;
-        nsDependentString endTagName(nsHTMLTags::GetStringValue(theTag)); 
-
-        CToken* text =
-            theAllocator->CreateTokenOfType(eToken_text, eHTMLTag_text);
-        NS_ENSURE_TRUE(text, NS_ERROR_OUT_OF_MEMORY);
-
-        CTextToken* textToken = static_cast<CTextToken*>(text);
-
-        if (isCDATA) {
-          result = textToken->ConsumeCharacterData(theTag != eHTMLTag_script,
-                                                   aScanner,
-                                                   endTagName,
-                                                   mFlags,
-                                                   done);
-
-          // Only flush tokens for <script>, to give ourselves more of a
-          // chance of allowing inlines to contain blocks.
-          aFlushTokens = done && theTag == eHTMLTag_script;
-        } else if (isPCDATA) {
-          // Title is consumed conservatively in order to not regress
-          // bug 42945
-          result = textToken->ConsumeParsedCharacterData(
-                                                  theTag == eHTMLTag_textarea,
-                                                  theTag == eHTMLTag_title,
-                                                  aScanner,
-                                                  endTagName,
-                                                  mFlags,
-                                                  done);
-
-          // Note: we *don't* set aFlushTokens here.
-        }
-
-        // We want to do this unless result is kEOF, in which case we will
-        // simply unwind our stack and wait for more data anyway.
-        if (kEOF != result) {
-          AddToken(text, NS_OK, &mTokenDeque, theAllocator);
-          CToken* endToken = nullptr;
-
-          if (NS_SUCCEEDED(result) && done) {
-            PRUnichar theChar;
-            // Get the <
-            result = aScanner.GetChar(theChar);
-            NS_ASSERTION(NS_SUCCEEDED(result) && theChar == kLessThan,
-                         "CTextToken::Consume*Data is broken!");
-#ifdef DEBUG
-            // Ensure we have a /
-            PRUnichar tempChar;  // Don't change non-debug vars in debug-only code
-            result = aScanner.Peek(tempChar);
-            NS_ASSERTION(NS_SUCCEEDED(result) && tempChar == kForwardSlash,
-                         "CTextToken::Consume*Data is broken!");
-#endif
-            result = ConsumeEndTag(PRUnichar('/'), endToken, aScanner);
-            if (!(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE) &&
-                NS_SUCCEEDED(result)) {
-              // If ConsumeCharacterData returned a success result (and
-              // we're not in view source), then we want to make sure that
-              // we're going to execute this script (since the result means
-              // that we've found an end tag that satisfies all of the right
-              // conditions).
-              endToken->SetInError(false);
-            }
-          } else if (result == kFakeEndTag &&
-                    !(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE)) {
-            result = NS_OK;
-            endToken = theAllocator->CreateTokenOfType(eToken_end, theTag,
-                                                       endTagName);
-            AddToken(endToken, result, &mTokenDeque, theAllocator);
-            if (MOZ_LIKELY(endToken != nullptr)) {
-              endToken->SetInError(true);
-            }
-            else {
-              result = NS_ERROR_OUT_OF_MEMORY;
-            }
-          } else if (result == kFakeEndTag) {
-            // If we are here, we are both faking having seen the end tag
-            // and are in view-source.
-            result = NS_OK;
-          }
-        } else {
-          IF_FREE(text, mTokenAllocator);
-        }
-      }
-    }
-
-    // This code is confusing, so pay attention.
-    // If you're here, it's because we were in the midst of consuming a start
-    // tag but ran out of data (not in the stream, but in this *part* of the
-    // stream. For simplicity, we have to unwind our input. Therefore, we pop
-    // and discard any new tokens we've queued this round. Later we can get
-    // smarter about this.
-    if (NS_FAILED(result)) {
-      while (mTokenDeque.GetSize()>theDequeSize) {
-        CToken* theToken = (CToken*)mTokenDeque.Pop();
-        IF_FREE(theToken, mTokenAllocator);
-      }
-    }
-  } else {
-    IF_FREE(aToken, mTokenAllocator);
-  }
-
-  return result;
-}
-
-/**
- * This method consumes an end tag and any "attributes" that may come after it.
- *
- * @param aChar The last character read from the scanner.
- * @param aToken The OUT parameter that holds our resulting token.
- * @param aScanner Our source of data
- * @return Error result
- */
-nsresult
-nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,
-                               CToken*& aToken,
-                               nsScanner& aScanner)
-{
-  // Get the "/" (we've already seen it with a Peek)
-  aScanner.GetChar(aChar);
-
-  nsTokenAllocator* theAllocator = this->GetTokenAllocator();
-  aToken = theAllocator->CreateTokenOfType(eToken_end, eHTMLTag_unknown);
-  NS_ENSURE_TRUE(aToken, NS_ERROR_OUT_OF_MEMORY);
-
-  // Remember this for later in case you have to unwind...
-  int32_t theDequeSize = mTokenDeque.GetSize();
-  nsresult result = NS_OK;
-
-  // Tell the new token to finish consuming text...
-  result = aToken->Consume(aChar, aScanner, mFlags);
-  AddToken(aToken, result, &mTokenDeque, theAllocator);
-  if (NS_FAILED(result)) {
-    // Note that this early-return here is safe because we have not yet
-    // added any of our tokens to the queue (AddToken only adds the token if
-    // result is a success), so we don't need to fall through.
-    return result;
-  }
-
-  result = aScanner.Peek(aChar);
-  if (NS_FAILED(result)) {
-    aToken->SetInError(true);
-
-    // Note: We know here that the scanner is not incremental since if
-    // this peek fails, then we've already masked over a kEOF coming from
-    // the Consume() call above.