diff --git a/htmlparser/src/CNavDTD.cpp b/htmlparser/src/CNavDTD.cpp
index a20c8c59367..3400ef36e19 100644
--- a/htmlparser/src/CNavDTD.cpp
+++ b/htmlparser/src/CNavDTD.cpp
@@ -91,6 +91,115 @@ static char gWhitespaceTags[]={
0};
+/************************************************************************
+ CTagStack class implementation.
+ The reason we use this class is so that we can view the stack state
+ in the usual way via the debugger.
+ ************************************************************************/
+
+
+CTagStack::CTagStack(int aDefaultSize) {
+#ifdef _dynstack
+ mSize=aDefaultSize;
+ mTags =new eHTMLTags[mSize];
+ mBits =new PRBool[mSize];
+#else
+ mSize=eStackSize;
+#endif
+ mCount=0;
+ nsCRT::zero(mTags,mSize*sizeof(eHTMLTag_html));
+ nsCRT::zero(mBits,mSize*sizeof(PRBool));
+}
+
+/**
+ * Default constructor
+ * @update gess7/9/98
+ * @param aDefaultsize tells the stack what size to start out.
+ * however, we'll autosize as needed.
+ */
+CTagStack::~CTagStack() {
+#ifdef _dynstack
+ delete mTags;
+ delete mBits;
+ mTags=0;
+ mBits=0;
+#endif
+ mSize=mCount=0;
+ }
+
+/**
+ *
+ * @update gess7/9/98
+ * @param
+ * @return
+ */
+void CTagStack::Push(eHTMLTags aTag) {
+
+ if(mCount>=mSize) {
+
+#ifdef _dynstack
+ eHTMLTags* tmp=new eHTMLTags[2*mSize];
+ nsCRT::zero(tmp,2*mSize*sizeof(eHTMLTag_html));
+ nsCRT::memcpy(tmp,mTags,mSize*sizeof(eHTMLTag_html));
+ delete mTags;
+ mTags=tmp;
+
+ PRBool* tmp2=new PRBool[2*mSize];
+ nsCRT::zero(tmp2,2*mSize*sizeof(PRBool));
+ nsCRT::memcpy(tmp2,mBits,mSize*sizeof(PRBool));
+ delete mBits;
+ mBits=tmp2;
+ mSize*=2;
+#endif
+ }
+ mTags[mCount++]=aTag;
+}
+
+/**
+ *
+ * @update gess7/9/98
+ * @param
+ * @return
+ */
+eHTMLTags CTagStack::Pop() {
+ eHTMLTags result=eHTMLTag_unknown;
+ if(mCount>0) {
+ result=mTags[--mCount];
+ mTags[mCount]=eHTMLTag_unknown;
+ mBits[mCount]=PR_FALSE;
+ }
+ return result;
+}
+
+/**
+ *
+ * @update gess7/9/98
+ * @param
+ * @return
+ */
+eHTMLTags CTagStack::First() const {
+ if(mCount>0)
+ return mTags[0];
+ return eHTMLTag_unknown;
+}
+
+/**
+ *
+ * @update gess7/9/98
+ * @param
+ * @return
+ */
+eHTMLTags CTagStack::Last() const {
+ if(mCount>0)
+ return mTags[mCount-1];
+ return eHTMLTag_unknown;
+}
+
+
+/************************************************************************
+ And now for the main class -- CNavDTD...
+ ************************************************************************/
+
/**
* This method gets called as part of our COM-like interfaces.
* Its purpose is to create an interface to parser object
@@ -124,6 +233,7 @@ nsresult CNavDTD::QueryInterface(const nsIID& aIID, void** aInstancePtr)
return NS_OK;
}
+
/**
* This method is defined in nsIParser. It is used to
* cause the COM-like construction of an nsParser.
@@ -234,15 +344,13 @@ static CNavTokenDeallocator gTokenKiller;
* @param
* @return
*/
-CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller) {
+CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller),
+ mContextStack(), mStyleStack() {
NS_INIT_REFCNT();
mParser=0;
- mFilename=0;
mSink = nsnull;
mDTDDebug=0;
nsCRT::zero(mTokenHandlers,sizeof(mTokenHandlers));
- mContextStackPos=0;
- mStyleStackPos=0;
mHasOpenForm=PR_FALSE;
mHasOpenMap=PR_FALSE;
InitializeDefaultTokenHandlers();
@@ -257,8 +365,6 @@ CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller) {
*/
CNavDTD::~CNavDTD(){
DeleteTokenHandlers();
- if (mFilename)
- PL_strfree(mFilename);
if (mDTDDebug)
NS_RELEASE(mDTDDebug);
@@ -281,6 +387,7 @@ void CNavDTD::SetDTDDebug(nsIDTDDebug * aDTDDebug)
NS_ADDREF(mDTDDebug);
}
+
/**
* This method is called to determine if the given DTD can parse
* a document in a given source-type.
@@ -308,24 +415,16 @@ eAutoDetectResult CNavDTD::AutoDetectContentType(nsString& aBuffer,nsString& aTy
return result;
}
-
-
/**
*
* @update gess5/18/98
* @param
* @return
*/
-PRInt32 CNavDTD::WillBuildModel(const char* aFilename){
+PRInt32 CNavDTD::WillBuildModel(nsString& aFilename){
PRInt32 result=0;
- if (mFilename) {
- PL_strfree(mFilename);
- mFilename=0;
- }
- if(aFilename) {
- mFilename = PL_strdup(aFilename);
- }
+ mFilename=aFilename;
if(mSink)
mSink->WillBuildModel();
@@ -342,7 +441,7 @@ PRInt32 CNavDTD::WillBuildModel(const char* aFilename){
PRInt32 CNavDTD::DidBuildModel(PRInt32 anErrorCode){
PRInt32 result=0;
- if((kNoError==anErrorCode) && (mContextStackPos>0)) {
+ if((kNoError==anErrorCode) && (mContextStack.mCount>0)) {
CloseContainersTo(0,eHTMLTag_unknown,PR_FALSE);
}
if(mSink) {
@@ -375,7 +474,7 @@ PRInt32 CNavDTD::HandleToken(CToken* aToken){
if(theHandler) {
result=(*theHandler)(theToken,this);
if (mDTDDebug)
- mDTDDebug->Verify(this, mParser, mContextStackPos, mContextStack, mFilename);
+ mDTDDebug->Verify(this, mParser, mContextStack.mCount, mContextStack.mTags, mFilename);
}
}//if
@@ -420,13 +519,13 @@ PRInt32 CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIP
}
if(IsContainer(aChildTag)){
- if(PR_TRUE==(PRBool)mLeafBits[mContextStackPos-1]) {
+ if(PR_TRUE==mContextStack.mBits[mContextStack.mCount-1]) {
CloseTransientStyles(aChildTag);
}
result=OpenContainer(aNode,PR_TRUE);
}
else {
- if(PR_FALSE==(PRBool)mLeafBits[mContextStackPos-1]) {
+ if(PR_FALSE==mContextStack.mBits[mContextStack.mCount-1]) {
OpenTransientStyles(aChildTag);
}
result=AddLeaf(aNode);
@@ -576,16 +675,8 @@ PRInt32 CNavDTD::HandleEndToken(CToken* aToken) {
// we have to handle explicit styles the way it does. That means
// that we keep an internal style stack.When an EndToken occurs,
// we should see if it is an explicit style tag. If so, we can
- // close AND explicit style tag (goofy, huh?)
+ // close the explicit style tag (goofy, huh?)
-/*
- if(0!=strchr(gStyleTags,tokenTagType)){
- eHTMLTags topTag=GetTopNode();
- if(0!=strchr(gStyleTags,topTag)){
- tokenTagType=topTag;
- }
- }
-*/
//now check to see if this token should be omitted...
if(PR_TRUE==CanOmitEndTag(GetTopNode(),tokenTagType)) {
@@ -622,7 +713,7 @@ PRInt32 CNavDTD::HandleEndToken(CToken* aToken) {
// Empty the transient style stack (we just closed any extra
// ones off so it's safe to do it now) because they don't carry
// forward across table cell boundaries.
- mStyleStackPos = 0;
+ mStyleStack.mCount=0;
break;
default:
@@ -1148,8 +1239,8 @@ PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) {
break; //singletons can't contain anything...
case eHTMLTag_li:
- if ((eHTMLTag_li == aChild) ||
- (eHTMLTag_ul == aChild) || // XXX this is temporary!!!
+ if ((eHTMLTag_li == aChild) || //XXX this is temporary!!!
+ (eHTMLTag_ul == aChild) ||
(eHTMLTag_ol == aChild) ||
(eHTMLTag_menu == aChild) ||
(eHTMLTag_dir == aChild)) {
@@ -1620,29 +1711,6 @@ PRBool CNavDTD::BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTa
return PRBool(aParentTag==theParentTag);
}
-/**
- *
- * @update gess6/4/98
- * @param aTag is the id of the html container being opened
- * @return 0 if all is well.
- */
-PRInt32 CNavDTD::DidOpenContainer(eHTMLTags aTag,PRBool /*anExplicitOpen*/){
- PRInt32 result=0;
- return result;
-}
-
-/**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
-PRInt32 CNavDTD::DidCloseContainer(eHTMLTags aTag,PRBool/*anExplicitClosure*/){
- PRInt32 result=0;
- return result;
-}
-
-
/**
* This method allows the caller to determine if a form
* element is currently open.
@@ -1672,9 +1740,7 @@ PRBool CNavDTD::HasOpenContainer(eHTMLTags aContainer) const {
* @return tag id of topmost node in contextstack
*/
eHTMLTags CNavDTD::GetTopNode() const {
- if(mContextStackPos)
- return (eHTMLTags)(int)mContextStack[mContextStackPos-1];
- return eHTMLTag_unknown;
+ return mContextStack.Last();
}
@@ -1688,8 +1754,8 @@ eHTMLTags CNavDTD::GetTopNode() const {
*/
PRInt32 CNavDTD::GetTopmostIndexOf(eHTMLTags aTag) const {
int i=0;
- for(i=mContextStackPos-1;i>=0;i--){
- if((eHTMLTags)(int)mContextStack[i]==aTag)
+ for(i=mContextStack.mCount-1;i>=0;i--){
+ if(mContextStack.mTags[i]==aTag)
return i;
}
return kNotFound;
@@ -1720,8 +1786,8 @@ PRInt32 CNavDTD::OpenTransientStyles(eHTMLTags aTag){
eHTMLTags parentTag=GetTopNode();
if(CanContainStyles(parentTag)) {
- for(pos=0;pos0) && (mLeafBits[mContextStackPos-1])) {
+ if((mStyleStack.mCount>0) && (mContextStack.mBits[mContextStack.mCount-1])) {
if(0==strchr(gWhitespaceTags,aTag)){
- result=CloseContainersTo((eHTMLTags)(int)mStyleStack[0],PR_FALSE);
- mLeafBits.ReplaceElementAt((void*)PR_FALSE,mContextStackPos-1);
+ result=CloseContainersTo(mStyleStack.mTags[0],PR_FALSE);
+ mContextStack.mBits[mContextStack.mCount-1]=PR_FALSE;
}//if
}//if
@@ -1782,10 +1848,10 @@ PRInt32 CNavDTD::CloseTransientStyles(eHTMLTags aTag){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenHTML(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos);
PRInt32 result=mSink->OpenHTML(aNode);
- mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++);
+ mContextStack.Push((eHTMLTags)aNode.GetNodeType());
return result;
}
@@ -1799,9 +1865,9 @@ PRInt32 CNavDTD::OpenHTML(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseHTML(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=mSink->CloseHTML(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
return result;
}
@@ -1815,7 +1881,7 @@ PRInt32 CNavDTD::CloseHTML(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenHead(const nsIParserNode& aNode){
- mContextStack.ReplaceElementAt((void*)eHTMLTag_head,++mContextStackPos);
+ mContextStack.Push(eHTMLTag_head);
PRInt32 result=mSink->OpenHead(aNode);
return result;
}
@@ -1830,7 +1896,7 @@ PRInt32 CNavDTD::OpenHead(const nsIParserNode& aNode){
*/
PRInt32 CNavDTD::CloseHead(const nsIParserNode& aNode){
PRInt32 result=mSink->CloseHead(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
return result;
}
@@ -1843,7 +1909,7 @@ PRInt32 CNavDTD::CloseHead(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos);
PRInt32 result=kNoError;
eHTMLTags topTag=GetTopNode();
@@ -1875,7 +1941,7 @@ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){
if(kNoError==result) {
result=mSink->OpenBody(aNode);
- mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++);
+ mContextStack.Push((eHTMLTags)aNode.GetNodeType());
}
return result;
}
@@ -1889,9 +1955,9 @@ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseBody(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos);
PRInt32 result=mSink->CloseBody(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
return result;
}
@@ -1980,9 +2046,9 @@ PRInt32 CNavDTD::CloseMap(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenFrameset(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos);
PRInt32 result=mSink->OpenFrameset(aNode);
- mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++);
+ mContextStack.Push((eHTMLTags)aNode.GetNodeType());
return result;
}
@@ -1995,9 +2061,9 @@ PRInt32 CNavDTD::OpenFrameset(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseFrameset(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=mSink->CloseFrameset(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
return result;
}
@@ -2011,7 +2077,7 @@ PRInt32 CNavDTD::CloseFrameset(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleStack){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=kNoError;
eHTMLTags nodeType=(eHTMLTags)aNode.GetNodeType();
@@ -2037,7 +2103,7 @@ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleSta
default:
result=mSink->OpenContainer(aNode);
- mContextStack.ReplaceElementAt((void*)nodeType,mContextStackPos++);
+ mContextStack.Push((eHTMLTags)aNode.GetNodeType());
break;
}
@@ -2057,7 +2123,7 @@ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleSta
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool aUpdateStyles){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=kNoError; //was false
eHTMLTags nodeType=(eHTMLTags)aNode.GetNodeType();
@@ -2085,11 +2151,11 @@ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool
case eHTMLTag_title:
default:
result=mSink->CloseContainer(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
break;
}
- mLeafBits.ReplaceElementAt((void*)PR_FALSE, mContextStackPos);
+ mContextStack.mBits[mContextStack.mCount]=PR_FALSE;
if((kNoError==result) && (PR_TRUE==aUpdateStyles)){
UpdateStyleStackForCloseTag(nodeType,aTag);
}
@@ -2106,15 +2172,15 @@ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdateStyles){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=kNoError;
CEndToken aToken(gEmpty);
nsCParserNode theNode(&aToken);
- if((anIndex=0)) {
- while(mContextStackPos>anIndex) {
- eHTMLTags theTag=(eHTMLTags)(int)mContextStack[mContextStackPos-1];
+ if((anIndex=0)) {
+ while(mContextStack.mCount>anIndex) {
+ eHTMLTags theTag=mContextStack.Last();
aToken.SetTypeID(theTag);
result=CloseContainer(theNode,aTag,aUpdateStyles);
}
@@ -2131,7 +2197,7 @@ PRInt32 CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdate
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 pos=GetTopmostIndexOf(aTag);
@@ -2172,10 +2238,10 @@ PRInt32 CNavDTD::CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseTopmostContainer(){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
CEndToken aToken(gEmpty);
- eHTMLTags theTag=(eHTMLTags)(int)mContextStack[mContextStackPos-1];
+ eHTMLTags theTag=mContextStack.Last();
aToken.SetTypeID(theTag);
nsCParserNode theNode(&aToken);
return CloseContainer(theNode,theTag,PR_TRUE);
@@ -2217,7 +2283,7 @@ PRInt32 CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){
//add code here to build up context stack based on forward propagated context vector...
pos=0;
cnt=theVector.Length()-1;
- if(mContextStack[mContextStackPos-1]==(void*)theVector[cnt])
+ if(mContextStack.Last()==(eHTMLTags)theVector[cnt])
result=kNoError;
else result=kContextMismatch;
}
@@ -2236,8 +2302,8 @@ PRInt32 CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){
pos=0;
cnt=theVector.Length();
result=kNoError;
- while(pos0) {
+ if(mStyleStack.mCount>0) {
switch (aTag) {
case eHTMLTag_a:
@@ -2369,7 +2435,7 @@ PRInt32 CNavDTD::UpdateStyleStackForCloseTag(eHTMLTags aTag,eHTMLTags anActualTa
case eHTMLTag_u:
case eHTMLTag_var:
if(aTag==anActualTag)
- mStyleStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mStyleStackPos);
+ mStyleStack.Pop();
break;
case eHTMLTag_h1: case eHTMLTag_h2:
@@ -2716,8 +2782,8 @@ PRInt32 CNavDTD::ConsumeToken(CToken*& aToken){
CScanner* theScanner=mParser->GetScanner();
if(kNoError==result){
- PRUnichar aChar;
- result=theScanner->GetChar(aChar);
+ PRUnichar theChar;
+ result=theScanner->GetChar(theChar);
switch(result) {
case kEOF:
break;
@@ -2728,25 +2794,25 @@ PRInt32 CNavDTD::ConsumeToken(CToken*& aToken){
case kNoError:
default:
- switch(aChar) {
+ switch(theChar) {
case kLessThan:
- return ConsumeTag(aChar,*theScanner,aToken);
+ return ConsumeTag(theChar,*theScanner,aToken);
case kAmpersand:
- return ConsumeEntity(aChar,*theScanner,aToken);
+ return ConsumeEntity(theChar,*theScanner,aToken);
case kCR: case kLF:
- return ConsumeNewline(aChar,*theScanner,aToken);
+ return ConsumeNewline(theChar,*theScanner,aToken);
case kNotFound:
break;
default:
- if(!nsString::IsSpace(aChar)) {
- nsAutoString temp(aChar);
+ if(!nsString::IsSpace(theChar)) {
+ nsAutoString temp(theChar);
return ConsumeText(temp,*theScanner,aToken);
}
- return ConsumeWhitespace(aChar,*theScanner,aToken);
+ return ConsumeWhitespace(theChar,*theScanner,aToken);
} //switch
break;
} //switch
diff --git a/htmlparser/src/CNavDTD.h b/htmlparser/src/CNavDTD.h
index 2ea700f9ec7..063874781d3 100644
--- a/htmlparser/src/CNavDTD.h
+++ b/htmlparser/src/CNavDTD.h
@@ -45,6 +45,54 @@ class nsIParserNode;
class CITokenHandler;
class nsParser;
+
+
+/***************************************************************
+ First define a helper class called CTagStack.
+
+ Simple, we've built ourselves a little data structure that
+ serves as a stack for htmltags (and associated bits).
+ What's special is that if you #define _dynstack 1, the stack
+ size can grow dynamically (like you'ld want in a release build.)
+ If you don't #define _dynstack 1, then the stack is a fixed size,
+ equal to the eStackSize enum. This makes debugging easier, because
+ you can see the htmltags on the stack if its not dynamic.
+ ***************************************************************/
+
+//#define _dynstack 1
+class CTagStack {
+ enum {eStackSize=200};
+
+public:
+
+ CTagStack(int aDefaultSize=50);
+ ~CTagStack();
+ void Push(eHTMLTags aTag);
+ eHTMLTags Pop();
+ eHTMLTags First() const;
+ eHTMLTags Last() const;
+
+ int mSize;
+ int mCount;
+
+#ifdef _dynstack
+ eHTMLTags* mTags;
+ PRBool* mBits;
+#else
+ eHTMLTags mTags[200];
+ PRBool mBits[200];
+#endif
+};
+
+/***************************************************************
+ 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.
+ ***************************************************************/
+
+
class CNavDTD : public nsIDTD {
public:
@@ -103,7 +151,7 @@ class CNavDTD : public nsIDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aFilename);
/**
*
@@ -251,14 +299,6 @@ class CNavDTD : public nsIDTD {
*/
virtual PRBool BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTags aChildTag) const;
- /**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
- virtual PRInt32 DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen);
-
/**
* Ask parser if a given container is open ANYWHERE on stack
* @update gess5/11/98
@@ -283,129 +323,36 @@ class CNavDTD : public nsIDTD {
*/
virtual PRInt32 GetTopmostIndexOf(eHTMLTags aTag) const;
- /**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
- virtual PRInt32 DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure);
/**
- * This method gets called when a start token has been consumed and needs
- * to be handled (possibly added to content model via sink).
+ * The following set of methods are used to partially construct
+ * the content model (via the sink) according to the type of token.
* @update gess5/11/98
* @param aToken is the start token to be handled
* @return TRUE if the token was handled.
*/
PRInt32 HandleStartToken(CToken* aToken);
-
- /**
- * This method gets called when a start token has been consumed, and
- * we want to use default start token handling behavior.
- * This method gets called automatically by handleStartToken.
- *
- * @update gess5/11/98
- * @param aToken is the start token to be handled
- * @param aChildTag is the tag-type of given token
- * @param aNode is a node be updated with info from given token
- * @return TRUE if the token was handled.
- */
PRInt32 HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode);
-
- /**
- * This method gets called when an end token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the end token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleEndToken(CToken* aToken);
-
- /**
- * This method gets called when an entity token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the entity token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleEntityToken(CToken* aToken);
-
- /**
- * This method gets called when a comment token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the comment token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleCommentToken(CToken* aToken);
-
- /**
- * This method gets called when a skipped-content token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the skipped-content token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleSkippedContentToken(CToken* aToken);
-
- /**
- * This method gets called when an attribute token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the attribute token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleAttributeToken(CToken* aToken);
-
- /**
- * This method gets called when a script token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the script token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleScriptToken(CToken* aToken);
-
- /**
- * This method gets called when a style token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the style token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleStyleToken(CToken* aToken);
-
protected:
/**
- * Causes token handlers to be registered for this parser.
- * DO NOT CALL THIS! IT'S DEPRECATED!
- * @update gess5/11/98
- */
- void InitializeDefaultTokenHandlers();
-
-
- /**
- * DEPRECATED
+ * The following methods are use to create and manage
+ * the dynamic set of token handlers.
* @update gess5/11/98
*/
+ void InitializeDefaultTokenHandlers();
CITokenHandler* GetTokenHandler(eHTMLTokenTypes aType) const;
-
- /**
- * DEPRECATED
- * @update gess5/11/98
- */
CITokenHandler* AddTokenHandler(CITokenHandler* aHandler);
-
- /**
- * DEPRECATED
- * @update gess5/11/98
- */
- void DeleteTokenHandlers(void);
-
+ void DeleteTokenHandlers(void);
//*************************************************
@@ -414,145 +361,43 @@ protected:
//*************************************************
/**
- * This cover method opens the given node as a HTML item in
- * content sink.
+ * The next set of method open given HTML element.
+ *
* @update gess5/11/98
* @param HTML (node) to be opened in content sink.
* @return TRUE if all went well.
*/
PRInt32 OpenHTML(const nsIParserNode& aNode);
-
- /**
- *
- * @update gess5/11/98
- * @param
- * @return
- */
- PRInt32 CloseHTML(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a head item in
- * content sink.
- * @update gess5/11/98
- * @param HEAD (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenHead(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink head to be closed
- * @update gess5/11/98
- * @param aNode is the node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseHead(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a body item in
- * content sink.
- * @update gess5/11/98
- * @param BODY (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenBody(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink body to be closed
- * @update gess5/11/98
- * @param aNode is the body node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseBody(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a form item in
- * content sink.
- * @update gess5/11/98
- * @param FORM (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenForm(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink form to be closed
- * @update gess5/11/98
- * @param aNode is the form node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseForm(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a form item in
- * content sink.
- * @update gess5/11/98
- * @param FORM (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenMap(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink form to be closed
- * @update gess5/11/98
- * @param aNode is the form node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseMap(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a frameset item in
- * content sink.
- * @update gess5/11/98
- * @param FRAMESET (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenFrameset(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink frameset to be closed
- * @update gess5/11/98
- * @param aNode is the frameeset node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseFrameset(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a generic container in
- * content sink.
- * @update gess5/11/98
- * @param generic container (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleStack);
/**
- * This cover method causes a generic containre in the content-sink to be closed
+ * The next set of methods close the given HTML element.
+ *
* @update gess5/11/98
- * @param aNode is the node to be closed in sink (usually ignored)
+ * @param HTML (node) to be opened in content sink.
* @return TRUE if all went well.
*/
+ PRInt32 CloseHTML(const nsIParserNode& aNode);
+ PRInt32 CloseHead(const nsIParserNode& aNode);
+ PRInt32 CloseBody(const nsIParserNode& aNode);
+ PRInt32 CloseForm(const nsIParserNode& aNode);
+ PRInt32 CloseMap(const nsIParserNode& aNode);
+ PRInt32 CloseFrameset(const nsIParserNode& aNode);
PRInt32 CloseContainer(const nsIParserNode& aNode,eHTMLTags anActualTag,PRBool aUpdateStyles);
/**
- * This cover method causes the topmost container to be closed in sink
+ * The special purpose methods automatically close
+ * one or more open containers.
* @update gess5/11/98
* @return TRUE if all went well.
*/
PRInt32 CloseTopmostContainer();
-
- /**
- * Cause all containers down to topmost given tag to be closed
- * @update gess5/11/98
- * @param aTag is the tag at which auto-closure should stop (inclusive)
- * @return TRUE if all went well -- otherwise FALSE
- */
PRInt32 CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles);
-
- /**
- * Cause all containers down to given position to be closed
- * @update gess5/11/98
- * @param anIndex is the stack pos at which auto-closure should stop (inclusive)
- * @return TRUE if all went well -- otherwise FALSE
- */
PRInt32 CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdateStyles);
/**
@@ -603,81 +448,22 @@ protected:
CToken* CreateTokenOfType(eHTMLTokenTypes aType);
/**
- * Retrieve the next TAG from the given scanner.
+ * The following methods consume a particular type
+ * of HTML token.
+ *
* @update gess 5/11/98
* @param aScanner is the input source
* @param aToken is the next token (or null)
* @return error code
*/
PRInt32 ConsumeTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve next START tag from given scanner.
- * @update gess 5/11/98
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeStartTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve collection of HTML/XML attributes from given scanner
- * @update gess 5/11/98
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeAttributes(PRUnichar aChar,CScanner& aScanner,CStartToken* aToken);
-
- /**
- * Retrieve a sequence of text from given scanner.
- * @update gess 5/11/98
- * @param aString will contain retrieved text.
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
- PRInt32 ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve an entity from given scanner
- * @update gess 5/11/98
- * @param aChar last char read from scanner
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeEntity(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve a whitespace sequence from the given scanner
- * @update gess 5/11/98
- * @param aChar last char read from scanner
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeWhitespace(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve a comment from the given scanner
- * @update gess 5/11/98
- * @param aChar last char read from scanner
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeComment(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve newlines from given scanner
- * @update gess 5/11/98
- * @param aChar last char read from scanner
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeNewline(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
+ PRInt32 ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken);
/**
* Causes content to be skipped up to sequence contained in aString.
@@ -700,16 +486,13 @@ protected:
CITokenHandler* mTokenHandlers[eToken_last];
- nsVoidArray mLeafBits;
- nsVoidArray mContextStack;
- PRInt32 mContextStackPos;
- nsVoidArray mStyleStack;
- PRInt32 mStyleStackPos;
+ CTagStack mContextStack;
+ CTagStack mStyleStack;
PRBool mHasOpenForm;
PRBool mHasOpenMap;
nsDeque mTokenDeque;
- char* mFilename;
+ nsString mFilename;
nsIDTDDebug* mDTDDebug;
};
diff --git a/htmlparser/src/COtherDTD.cpp b/htmlparser/src/COtherDTD.cpp
index 886dc88c047..a3b2b0cd572 100644
--- a/htmlparser/src/COtherDTD.cpp
+++ b/htmlparser/src/COtherDTD.cpp
@@ -178,7 +178,7 @@ eAutoDetectResult COtherDTD::AutoDetectContentType(nsString& aBuffer,nsString& a
* @param
* @return
*/
-PRInt32 COtherDTD::WillBuildModel(const char* aFilename) {
+PRInt32 COtherDTD::WillBuildModel(nsString& aFilename) {
return CNavDTD::WillBuildModel(aFilename);
}
@@ -464,25 +464,6 @@ PRBool COtherDTD::BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTML
return CNavDTD::BackwardPropagate(aVector,aParentTag,aChildTag);
}
-/**
- *
- * @update gess6/4/98
- * @param aTag is the id of the html container being opened
- * @return 0 if all is well.
- */
-PRInt32 COtherDTD::DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen){
- return CNavDTD::DidOpenContainer(aTag,anExplicitOpen);
-}
-
-/**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
-PRInt32 COtherDTD::DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure){
- return CNavDTD::DidOpenContainer(aTag,anExplicitClosure);
-}
/*********************************************
Here comes code that handles the interface
diff --git a/htmlparser/src/COtherDTD.h b/htmlparser/src/COtherDTD.h
index 10813045aba..488b2f26886 100644
--- a/htmlparser/src/COtherDTD.h
+++ b/htmlparser/src/COtherDTD.h
@@ -87,7 +87,7 @@ class COtherDTD : public CNavDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aString);
/**
*
@@ -218,22 +218,6 @@ class COtherDTD : public CNavDTD {
*/
virtual PRBool BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTags aChildTag) const;
- /**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
- virtual PRInt32 DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen);
-
- /**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
- virtual PRInt32 DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure);
-
/**
* This method gets called when a start token has been consumed and needs
* to be handled (possibly added to content model via sink).
diff --git a/htmlparser/src/CParserContext.cpp b/htmlparser/src/CParserContext.cpp
new file mode 100644
index 00000000000..fae66a3d063
--- /dev/null
+++ b/htmlparser/src/CParserContext.cpp
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/**
+ * MODULE NOTES:
+ * @update gess 4/1/98
+ *
+ */
+
+
+#include "CParserContext.h"
+#include "nsToken.h"
+
+
+class CTokenDeallocator: public nsDequeFunctor{
+public:
+ virtual void* operator()(void* anObject) {
+ CToken* aToken = (CToken*)anObject;
+ delete aToken;
+ return 0;
+ }
+};
+
+CTokenDeallocator gTokenDeallocator;
+
+
+CParserContext::CParserContext(CScanner* aScanner,
+ CParserContext* aPreviousContext,
+ nsIStreamObserver* aListener) :
+ mTokenDeque(gTokenDeallocator),
+ mSourceType()
+{
+ mScanner=aScanner;
+ mPrevContext=aPreviousContext;
+ mListener=aListener;
+ NS_IF_ADDREF(mListener);
+ mMajorIteration=mMinorIteration=-1;
+ mParseMode=eParseMode_unknown;
+ mAutoDetectStatus=eUnknownDetect;
+ mTransferBuffer=new char[eTransferBufferSize+1];
+ mCurrentPos=0;
+ mMarkPos=0;
+ mDTD=0;
+}
+
+
+/**
+ * Destructor for parser context
+ * NOTE: DO NOT destroy the dtd here.
+ * @update gess7/11/98
+ */
+CParserContext::~CParserContext(){
+
+ if(mCurrentPos)
+ delete mCurrentPos;
+ if(mMarkPos)
+ delete mMarkPos;
+
+ if(mScanner)
+ delete mScanner;
+
+ if(mTransferBuffer)
+ delete [] mTransferBuffer;
+
+ //Remember that it's ok to simply
+ //ignore the DTD and the prevcontext.
+
+}
+
+
diff --git a/htmlparser/src/CParserContext.h b/htmlparser/src/CParserContext.h
new file mode 100644
index 00000000000..41da84f49f9
--- /dev/null
+++ b/htmlparser/src/CParserContext.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/**
+ * MODULE NOTES:
+ * @update gess 4/1/98
+ *
+ */
+
+#ifndef __CParserContext
+#define __CParserContext
+
+#include "nsIParser.h"
+#include "nsDeque.h"
+#include "nsParserTypes.h"
+#include "nsIURL.h"
+#include "nsIDTD.h"
+#include "nsScanner.h"
+#include "nsIStreamListener.h"
+
+
+/**
+ * Note that the parser is given FULL access to all
+ * data in a parsercontext. Hey, that what it's for!
+ */
+
+class CParserContext {
+
+public:
+
+ enum {eTransferBufferSize=4096};
+
+ CParserContext( CScanner* aScanner,
+ CParserContext* aPreviousContext=0,
+ nsIStreamObserver* aListener=0);
+
+
+ ~CParserContext();
+
+
+ PRInt32 mMajorIteration;
+ PRInt32 mMinorIteration;
+
+ nsString mSourceType;
+ eAutoDetectResult mAutoDetectStatus;
+
+ nsDequeIterator* mCurrentPos;
+ nsDequeIterator* mMarkPos;
+ nsDeque mTokenDeque;
+ CScanner* mScanner;
+ nsIDTD* mDTD;
+
+ eParseMode mParseMode;
+ char* mTransferBuffer;
+ nsIStreamObserver* mListener;
+
+ CParserContext* mPrevContext;
+
+};
+
+
+
+#endif
+
+
diff --git a/htmlparser/src/CRtfDTD.cpp b/htmlparser/src/CRtfDTD.cpp
index 51add7383a1..8bc844274e8 100644
--- a/htmlparser/src/CRtfDTD.cpp
+++ b/htmlparser/src/CRtfDTD.cpp
@@ -251,7 +251,7 @@ eAutoDetectResult CRtfDTD::AutoDetectContentType(nsString& aBuffer,nsString& aTy
* @param
* @return
*/
-PRInt32 CRtfDTD::WillBuildModel(const char* aFilename){
+PRInt32 CRtfDTD::WillBuildModel(nsString& aFilename){
PRInt32 result=0;
return result;
}
diff --git a/htmlparser/src/CRtfDTD.h b/htmlparser/src/CRtfDTD.h
index dff562561a7..4f40b2f2eba 100644
--- a/htmlparser/src/CRtfDTD.h
+++ b/htmlparser/src/CRtfDTD.h
@@ -190,7 +190,7 @@ class CRtfDTD : public nsIDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aFilename);
/**
*
diff --git a/htmlparser/src/Makefile b/htmlparser/src/Makefile
index 8a09a69ba9d..616e7f6f6b1 100644
--- a/htmlparser/src/Makefile
+++ b/htmlparser/src/Makefile
@@ -34,6 +34,7 @@ CPPSRCS = \
nsValidDTD.cpp \
nsWellFormedDTD.cpp \
nsParser.cpp \
+ CParserContext.cpp \
nsHTMLTokens.cpp \
nsHTMLTags.cpp \
prstrm.cpp \
diff --git a/htmlparser/src/makefile.win b/htmlparser/src/makefile.win
index 68b1598facb..0b786802cb6 100644
--- a/htmlparser/src/makefile.win
+++ b/htmlparser/src/makefile.win
@@ -34,6 +34,7 @@ CPPSRCS= \
nsHTMLTags.obj \
nsHTMLTokens.obj \
nsParser.obj \
+ CParserContext.obj \
nsParserNode.obj \
nsScanner.obj \
nsToken.obj \
@@ -53,6 +54,7 @@ CPP_OBJS= \
.\$(OBJDIR)\nsHTMLTags.obj \
.\$(OBJDIR)\nsHTMLTokens.obj \
.\$(OBJDIR)\nsParser.obj \
+ .\$(OBJDIR)\CParserContext.obj \
.\$(OBJDIR)\nsParserNode.obj \
.\$(OBJDIR)\nsScanner.obj \
.\$(OBJDIR)\nsToken.obj \
diff --git a/htmlparser/src/nsDTDDebug.cpp b/htmlparser/src/nsDTDDebug.cpp
index a67ad7ac475..17166904c7f 100644
--- a/htmlparser/src/nsDTDDebug.cpp
+++ b/htmlparser/src/nsDTDDebug.cpp
@@ -67,7 +67,7 @@ public:
void SetVerificationDirectory(char * verify_dir);
void SetRecordStatistics(PRBool bval);
- PRBool Verify(nsIDTD * aDTD, nsParser * aParser, int ContextStackPos, nsVoidArray &aContextStack, char * aURLRef);
+ PRBool Verify(nsIDTD * aDTD, nsParser * aParser, int ContextStackPos, eHTMLTags aContextStack[], nsString& aURLRef);
void DumpVectorRecord(void);
// global table for storing vector statistics and the size
@@ -78,8 +78,8 @@ private:
char * mVerificationDir;
PRBool mRecordingStatistics;
- PRBool DebugRecord(char * path, char * pURLRef, char * filename);
- void NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector);
+ PRBool DebugRecord(char * path, nsString& pURLRef, char * filename);
+ void NoteVector(eHTMLTags aTags[],PRInt32 count, PRBool good_vector);
void MakeVectorString(char * vector_string, VectorInfo * pInfo);
};
@@ -188,7 +188,7 @@ void CDTDDebug::SetRecordStatistics(PRBool bval)
* @return TRUE if it is already record (dont rerecord)
*/
-PRBool CDTDDebug::DebugRecord(char * path, char * pURLRef, char * filename)
+PRBool CDTDDebug::DebugRecord(char * path, nsString& aURLRef, char * filename)
{
char recordPath[2048];
PRIntn oflags = 0;
@@ -215,7 +215,9 @@ PRBool CDTDDebug::DebugRecord(char * path, char * pURLRef, char * filename)
// vectors are stored on the format iof "URL vector filename"
// where the vector contains the verification path and
// the filename contains the debug source dump
- sprintf(string,"%s %s %s\r\n", pURLRef, path, filename);
+ char buffer[513];
+ aURLRef.ToCString(buffer,sizeof(buffer)-1);
+ sprintf(string,"%s %s %s\r\n", buffer, path, filename);
// get the file size, read in the file and parse it line at
// a time to check to see if we have already recorded this
@@ -310,7 +312,7 @@ static int compare( const void *arg1, const void *arg2 )
* @return
*/
-void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector)
+void CDTDDebug::NoteVector(eHTMLTags aTags[],PRInt32 count, PRBool good_vector)
{
// if the table doesn't exist, create it
if (!mVectorInfoArray) {
@@ -327,7 +329,7 @@ void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector
PRBool match = PR_TRUE;
for (PRInt32 j = 0; j < count; j++)
- if (mVectorInfoArray[i]->vector[j] != (eHTMLTags)(int)aTags[j]) {
+ if (mVectorInfoArray[i]->vector[j] != aTags[j]) {
match = PR_FALSE;
break;
}
@@ -348,7 +350,7 @@ void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector
pVectorInfo->good_vector = good_vector;
pVectorInfo->vector = (eHTMLTags*)PR_Malloc(count*sizeof(eHTMLTags));
for (PRInt32 i = 0; i < count; i++)
- pVectorInfo->vector[i] = (eHTMLTags)(int)aTags[i];
+ pVectorInfo->vector[i] = aTags[i];
mVectorInfoArray[mVectorCount++] = pVectorInfo;
// have we maxed out the table? grow it.. sort it.. love it.
@@ -467,7 +469,7 @@ void CDTDDebug::DumpVectorRecord(void)
* @return TRUE if we know how to handle it, else false
*/
-PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPos, nsVoidArray &aContextStack, char * aURLRef)
+PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPos, eHTMLTags aContextStack[], nsString& aURLRef)
{
PRBool result=PR_TRUE;
@@ -477,7 +479,7 @@ PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPo
if(aDTD && aContextStackPos>1) {
for (int i = 0; i < aContextStackPos-1; i++)
- if (!aDTD->CanContain((eHTMLTags)(int)aContextStack[i],(eHTMLTags)(int)aContextStack[i+1])) {
+ if (!aDTD->CanContain(aContextStack[i],aContextStack[i+1])) {
result = PR_FALSE;
break;
}
@@ -495,7 +497,7 @@ PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPo
int i=0;
for(i=0;i
-#include "nsString.h"
+#include "nsstring.h"
#include "nsParserTypes.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
@@ -89,8 +89,8 @@ NS_IMPL_RELEASE(CHTMLContentSinkStream)
* @param nsIParser** ptr to newly instantiated parser
* @return NS_xxx error result
*/
-NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aInstancePtrResult) {
- CHTMLContentSinkStream* it = new CHTMLContentSinkStream();
+NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aInstancePtrResult,ostream* aStream) {
+ CHTMLContentSinkStream* it = new CHTMLContentSinkStream(aStream);
if (it == 0) {
return NS_ERROR_OUT_OF_MEMORY;
@@ -99,25 +99,14 @@ NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aIns
return it->QueryInterface(kClassIID, (void **) aInstancePtrResult);
}
-
/**
* Construct a content sink stream.
* @update gess7/7/98
* @param
* @return
*/
-CHTMLContentSinkStream::CHTMLContentSinkStream() {
- mOutput=&cout;
-}
-
-/**
- * Construct a content sink stream.
- * @update gess7/7/98
- * @param
- * @return
- */
-CHTMLContentSinkStream::CHTMLContentSinkStream(ostream& aStream) {
- mOutput=&aStream;
+CHTMLContentSinkStream::CHTMLContentSinkStream(ostream* aStream) {
+ mOutput=(0==aStream) ? &cout : aStream;
}
@@ -132,17 +121,6 @@ CHTMLContentSinkStream::~CHTMLContentSinkStream() {
}
-/**
- *
- * @update gess7/7/98
- * @param
- * @return
- */
-void CHTMLContentSinkStream::SetOutputStream(ostream& aStream) {
- mOutput=&aStream;
-}
-
-
/**
*
* @update gess7/7/98
@@ -171,7 +149,7 @@ void WriteAttributes(const nsIParserNode& aNode,ostream& aStream) {
* @param
* @return
*/
-void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,PRBool aNewline) {
+void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,bool aNewline) {
int i=0;
for(i=0;i
-#include "nsIInputStream.h"
#include "nsIParserFilter.h"
#include "nsIDTDDebug.h"
#include "nshtmlpars.h"
@@ -47,13 +46,10 @@ static const char* kNullURL = "Error: Null URL given";
static const char* kNullFilename= "Error: Null filename given";
static const char* kNullTokenizer = "Error: Unable to construct tokenizer";
static const char* kHTMLTextContentType = "text/html";
+static nsString kUnknownFilename("unknown");
static const int gTransferBufferSize=4096; //size of the buffer used in moving data from iistream
-#define DEBUG_SAVE_SOURCE_DOC 1
-#ifdef DEBUG_SAVE_SOURCE_DOC
-fstream* gTempStream=0;
-#endif
/**
@@ -84,7 +80,7 @@ public:
}
};
-CTokenDeallocator gTokenDeallocator;
+CTokenDeallocator gTokenDeallocator2;
class CDTDDeallocator: public nsDequeFunctor{
public:
@@ -114,6 +110,7 @@ public:
CSharedParserObjects() : mDeallocator(), mDTDDeque(mDeallocator) {
}
+
~CSharedParserObjects() {
}
@@ -141,25 +138,13 @@ CSharedParserObjects gSharedParserObjects;
* @param
* @return
*/
-nsParser::nsParser() :
- mTokenDeque(gTokenDeallocator),
- mSourceType(),
- mTargetType()
-{
+nsParser::nsParser() {
NS_INIT_REFCNT();
mDTDDebug = 0;
mParserFilter = 0;
mObserver = 0;
- mTransferBuffer=0;
mSink=0;
- mCurrentPos=0;
- mMarkPos=0;
- mParseMode=eParseMode_unknown;
- mURL=0;
- mDTD=0;
- mScanner=0;
- mTransferBuffer=new char[gTransferBufferSize+1];
- mAutoDetectStatus=eUnknownDetect;
+ mParserContext=0;
}
@@ -172,20 +157,12 @@ nsParser::nsParser() :
*/
nsParser::~nsParser() {
NS_IF_RELEASE(mObserver);
- NS_IF_RELEASE(mDTDDebug);
- if(mTransferBuffer)
- delete [] mTransferBuffer;
- mTransferBuffer=0;
+// NS_IF_RELEASE(mDTDDebug);
NS_RELEASE(mSink);
- if(mCurrentPos)
- delete mCurrentPos;
- mCurrentPos=0;
- if(mScanner)
- delete mScanner;
- mScanner=0;
-
- NS_IF_RELEASE(mURL);
+ //don't forget to add code here to delete
+ //what may be several contexts...
+ delete mParserContext;
}
@@ -298,7 +275,9 @@ void nsParser::RegisterDTD(nsIDTD* aDTD){
* @return
*/
CScanner* nsParser::GetScanner(void){
- return mScanner;
+ if(mParserContext)
+ return mParserContext->mScanner;
+ return 0;
}
/**
@@ -311,6 +290,7 @@ CScanner* nsParser::GetScanner(void){
eParseMode DetermineParseMode() {
const char* theModeStr= PR_GetEnv("PARSE_MODE");
const char* other="other";
+
eParseMode result=eParseMode_navigator;
if(theModeStr)
@@ -326,25 +306,23 @@ eParseMode DetermineParseMode() {
* @param
* @return
*/
-PRBool FindSuitableDTD( eParseMode aMode,
- nsString& aSourceType,
- nsString& aTargetType,
- nsIDTD*& aDefaultDTD) {
+PRBool FindSuitableDTD( CParserContext& aParserContext) {
//Let's start by tring the defaultDTD, if one exists...
- if(aDefaultDTD && (aDefaultDTD->CanParse(aSourceType,0)))
+ if(aParserContext.mDTD && (aParserContext.mDTD->CanParse(aParserContext.mSourceType,0)))
return PR_TRUE;
PRBool result=PR_FALSE;
+
nsDequeIterator b=gSharedParserObjects.mDTDDeque.Begin();
nsDequeIterator e=gSharedParserObjects.mDTDDeque.End();
while(bCanParse(aSourceType,0);
+ result=theDTD->CanParse(aParserContext.mSourceType,0);
if(result){
- aDefaultDTD=theDTD;
+ aParserContext.mDTD=theDTD;
break;
}
}
@@ -371,22 +349,22 @@ eAutoDetectResult nsParser::AutoDetectContentType(nsString& aBuffer,nsString& aT
// recognize the content in the scanner.
// Somebody should say yes, or we can't continue.
- //This method may change mSourceType and mDTD.
- //It absolutely changes mAutoDetectStatus
+ //This method may change mSourceType and mParserContext->mDTD.
+ //It absolutely changes mParserContext->mAutoDetectStatus
nsDequeIterator b=gSharedParserObjects.mDTDDeque.Begin();
nsDequeIterator e=gSharedParserObjects.mDTDDeque.End();
- mAutoDetectStatus=eUnknownDetect;
- while((bmAutoDetectStatus=eUnknownDetect;
+ while((bmAutoDetectStatus)){
nsIDTD* theDTD=(nsIDTD*)b.GetCurrent();
if(theDTD) {
- mAutoDetectStatus=theDTD->AutoDetectContentType(aBuffer,aType);
+ mParserContext->mAutoDetectStatus=theDTD->AutoDetectContentType(aBuffer,aType);
}
b++;
}
- return mAutoDetectStatus;
+ return mParserContext->mAutoDetectStatus;
}
@@ -401,27 +379,18 @@ eAutoDetectResult nsParser::AutoDetectContentType(nsString& aBuffer,nsString& aT
* @param
* @return
*/
-PRInt32 nsParser::WillBuildModel(const char* aFilename){
+PRInt32 nsParser::WillBuildModel(nsString& aFilename){
- mMajorIteration=-1;
- mMinorIteration=-1;
+ mParserContext->mMajorIteration=-1;
+ mParserContext->mMinorIteration=-1;
- mParseMode=DetermineParseMode();
- if(PR_TRUE==FindSuitableDTD(mParseMode,mSourceType,mTargetType,mDTD)) {
- mDTD->SetParser(this);
- mDTD->SetContentSink(mSink);
- mDTD->WillBuildModel(aFilename);
+ mParserContext->mParseMode=DetermineParseMode();
+ if(PR_TRUE==FindSuitableDTD(*mParserContext)) {
+ mParserContext->mDTD->SetParser(this);
+ mParserContext->mDTD->SetContentSink(mSink);
+ mParserContext->mDTD->WillBuildModel(aFilename);
}
-#ifdef DEBUG_SAVE_SOURCE_DOC
-#if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX))
- /* XXX: IRIX does not support ios::binary */
- gTempStream =new fstream("/tmp/out.html",ios::out);
-#else
- gTempStream = new fstream("c:/temp/out.html",ios::out|ios::binary);
-#endif
-#endif
-
return kNoError;
}
@@ -434,18 +403,10 @@ PRInt32 nsParser::WillBuildModel(const char* aFilename){
PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) {
//One last thing...close any open containers.
PRInt32 result=anErrorCode;
- if(mDTD) {
- result=mDTD->DidBuildModel(anErrorCode);
+ if(mParserContext->mDTD) {
+ result=mParserContext->mDTD->DidBuildModel(anErrorCode);
}
-#ifdef DEBUG_SAVE_SOURCE_DOC
- if(gTempStream) {
- gTempStream->close();
- delete gTempStream;
- gTempStream=0;
- }
-#endif
-
return result;
}
@@ -460,22 +421,21 @@ PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) {
* @param aFilename -- const char* containing file to be parsed.
* @return PR_TRUE if parse succeeded, PR_FALSE otherwise.
*/
-PRBool nsParser::Parse(const char* aFilename){
- NS_PRECONDITION(0!=aFilename,kNullFilename);
+PRInt32 nsParser::Parse(nsString& aFilename){
PRInt32 status=kBadFilename;
if(aFilename) {
//ok, time to create our tokenizer and begin the process
- mTargetType=kHTMLTextContentType;
- mScanner=new CScanner(aFilename,mParseMode);
- if(mScanner) {
- mScanner->Eof();
- if(eValidDetect==AutoDetectContentType(mScanner->GetBuffer(),mSourceType)) {
- WillBuildModel(aFilename);
- status=ResumeParse();
- DidBuildModel(status);
- }
+
+ mParserContext = new CParserContext(new CScanner(aFilename),mParserContext);
+ mParserContext->mScanner->Eof();
+ if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(),
+ mParserContext->mSourceType))
+ {
+ WillBuildModel(aFilename);
+ status=ResumeParse();
+ DidBuildModel(status);
} //if
}
return status;
@@ -488,11 +448,35 @@ PRBool nsParser::Parse(const char* aFilename){
* @return TRUE if all went well -- FALSE otherwise
*/
PRInt32 nsParser::Parse(fstream& aStream){
- PRInt32 result=0;
- return result;
+
+ PRInt32 status=kNoError;
+
+ //ok, time to create our tokenizer and begin the process
+ mParserContext = new CParserContext(new CScanner(kUnknownFilename,aStream,PR_FALSE),mParserContext);
+
+ mParserContext->mScanner->Eof();
+ if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(),
+ mParserContext->mSourceType)) {
+ WillBuildModel(mParserContext->mScanner->GetFilename());
+ status=ResumeParse();
+ DidBuildModel(status);
+ } //if
+
+ return status;
}
+/**
+ *
+ * @update gess7/13/98
+ * @param
+ * @return
+ */
+PRInt32 nsParser::Parse(nsIInputStream* pIStream,nsIStreamObserver* aListener,nsIDTDDebug* aDTDDebug){
+ PRInt32 result=kNoError;
+ return result;
+}
+
/**
* This is the main controlling routine in the parsing process.
* Note that it may get called multiple times for the same scanner,
@@ -512,19 +496,14 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug *
PRInt32 status=kBadURL;
+/* Disable DTD Debug for now...
mDTDDebug = aDTDDebug;
NS_IF_ADDREF(mDTDDebug);
-
- NS_IF_RELEASE(mURL);
- mURL = aURL;
- NS_IF_ADDREF(mURL);
-
- NS_IF_RELEASE(mObserver);
- mObserver = aListener;
- NS_IF_ADDREF(mObserver);
+*/
- if(mURL) {
- mScanner=new CScanner(mParseMode);
+ if(aURL) {
+ nsAutoString theName(aURL->GetSpec());
+ mParserContext=new CParserContext(new CScanner(theName,PR_FALSE),mParserContext,aListener);
status=NS_OK;
}
return status;
@@ -533,6 +512,8 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug *
/**
* Call this method if all you want to do is parse 1 string full of HTML text.
+ * In particular, this method should be called by the DOM when it has an HTML
+ * string to feed to the parser in real-time.
*
* @update gess5/11/98
* @param anHTMLString contains a string-full of real HTML
@@ -542,11 +523,10 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug *
PRInt32 nsParser::Parse(nsString& aSourceBuffer,PRBool appendTokens){
PRInt32 result=kNoError;
- mTargetType=kHTMLTextContentType;
- mScanner=new CScanner();
- mScanner->Append(aSourceBuffer);
- if(eValidDetect==AutoDetectContentType(aSourceBuffer,mSourceType)) {
- WillBuildModel("");
+ mParserContext = new CParserContext(new CScanner(kUnknownFilename),mParserContext,0);
+ mParserContext->mScanner->Append(aSourceBuffer);
+ if(eValidDetect==AutoDetectContentType(aSourceBuffer,mParserContext->mSourceType)) {
+ WillBuildModel(mParserContext->mScanner->GetFilename());
result=ResumeParse();
DidBuildModel(result);
}
@@ -567,12 +547,12 @@ PRInt32 nsParser::Parse(nsString& aSourceBuffer,PRBool appendTokens){
PRInt32 nsParser::ResumeParse() {
PRInt32 result=kNoError;
- mDTD->WillResumeParse();
+ mParserContext->mDTD->WillResumeParse();
if(kNoError==result) {
result=Tokenize();
if(kInterrupted==result)
- mDTD->WillInterruptParse();
- IterateTokens();
+ mParserContext->mDTD->WillInterruptParse();
+ BuildModel();
}
return result;
}
@@ -585,26 +565,28 @@ PRInt32 nsParser::ResumeParse() {
* @param
* @return PR_TRUE if parse succeeded, PR_FALSE otherwise.
*/
-PRInt32 nsParser::IterateTokens() {
- nsDequeIterator e=mTokenDeque.End();
+PRInt32 nsParser::BuildModel() {
+
+ nsDequeIterator e=mParserContext->mTokenDeque.End();
nsDequeIterator theMarkPos(e);
- mMajorIteration++;
- if(!mCurrentPos)
- mCurrentPos=new nsDequeIterator(mTokenDeque.Begin());
+// mParserContext->mMajorIteration++;
+
+ if(!mParserContext->mCurrentPos)
+ mParserContext->mCurrentPos=new nsDequeIterator(mParserContext->mTokenDeque.Begin());
PRInt32 result=kNoError;
- while((kNoError==result) && ((*mCurrentPosGetCurrent();
+ while((kNoError==result) && ((*mParserContext->mCurrentPosmMinorIteration++;
+ CToken* theToken=(CToken*)mParserContext->mCurrentPos->GetCurrent();
- theMarkPos=*mCurrentPos;
- result=mDTD->HandleToken(theToken);
- ++(*mCurrentPos);
+ theMarkPos=*mParserContext->mCurrentPos;
+ result=mParserContext->mDTD->HandleToken(theToken);
+ ++(*mParserContext->mCurrentPos);
}
if(kInterrupted==result)
- *mCurrentPos=theMarkPos;
+ *mParserContext->mCurrentPos=theMarkPos;
return result;
}
@@ -619,17 +601,17 @@ PRInt32 nsParser::IterateTokens() {
* @return error code (should be 0)
*/
PRInt32 nsParser::CollectAttributes(nsCParserNode& aNode,PRInt32 aCount){
- nsDequeIterator end=mTokenDeque.End();
+ nsDequeIterator end=mParserContext->mTokenDeque.End();
int attr=0;
for(attr=0;attrmCurrentPosmCurrentPos));
if(tkn){
if(eToken_attribute==eHTMLTokenTypes(tkn->GetTokenType())){
aNode.AddAttribute(tkn);
}
- else (*mCurrentPos)--;
+ else (*mParserContext->mCurrentPos)--;
}
else return kInterrupted;
}
@@ -649,18 +631,18 @@ PRInt32 nsParser::CollectAttributes(nsCParserNode& aNode,PRInt32 aCount){
*/
PRInt32 nsParser::CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount) {
eHTMLTokenTypes subtype=eToken_attribute;
- nsDequeIterator end=mTokenDeque.End();
+ nsDequeIterator end=mParserContext->mTokenDeque.End();
PRInt32 result=kNoError;
aCount=0;
- while((*mCurrentPos!=end) && (eToken_attribute==subtype)) {
- CToken* tkn=(CToken*)(++(*mCurrentPos));
+ while((*mParserContext->mCurrentPos!=end) && (eToken_attribute==subtype)) {
+ CToken* tkn=(CToken*)(++(*mParserContext->mCurrentPos));
subtype=eHTMLTokenTypes(tkn->GetTokenType());
if(eToken_skippedcontent==subtype) {
aNode.SetSkippedContent(tkn);
aCount++;
}
- else (*mCurrentPos)--;
+ else (*mParserContext->mCurrentPos)--;
}
return result;
}
@@ -710,10 +692,9 @@ nsresult nsParser::OnStartBinding(const char *aSourceType){
if (nsnull != mObserver) {
mObserver->OnStartBinding(aSourceType);
}
- mAutoDetectStatus=eUnknownDetect;
- mDTD=0;
-
- mSourceType=aSourceType;
+ mParserContext->mAutoDetectStatus=eUnknownDetect;
+ mParserContext->mDTD=0;
+ mParserContext->mSourceType=aSourceType;
return kNoError;
}
@@ -732,37 +713,33 @@ nsresult nsParser::OnDataAvailable(nsIInputStream *pIStream, PRInt32 length){
mListener->OnDataAvailable(pIStream, length);
}
*/
- int len=0;
- int offset=0;
- if(eInvalidDetect==mAutoDetectStatus) {
- if(mScanner) {
- mScanner->GetBuffer().Truncate();
+ if(eInvalidDetect==mParserContext->mAutoDetectStatus) {
+ if(mParserContext->mScanner) {
+ mParserContext->mScanner->GetBuffer().Truncate();
}
}
- do {
- PRInt32 err;
- len = pIStream->Read(&err, mTransferBuffer, 0, gTransferBufferSize);
- if(len>0) {
+ int len=1; //init to a non-zero value
+ int err;
+ int offset=0;
- #ifdef DEBUG_SAVE_SOURCE_DOC
- if(gTempStream) {
- gTempStream->write(mTransferBuffer,len);
- }
- #endif
+ while (len > 0) {
+ len = pIStream->Read(&err, mParserContext->mTransferBuffer, 0, mParserContext->eTransferBufferSize);
+ if(len>0) {
- if (mParserFilter)
- mParserFilter->RawBuffer(mTransferBuffer, &len);
- mScanner->Append(mTransferBuffer,len);
+ if(mParserFilter)
+ mParserFilter->RawBuffer(mParserContext->mTransferBuffer, &len);
- if(eUnknownDetect==mAutoDetectStatus) {
- if(eValidDetect==AutoDetectContentType(mScanner->GetBuffer(),mSourceType)) {
- nsresult result=WillBuildModel(mURL->GetSpec());
- } //if
- }
- } //if
- } while (len > 0);
+ mParserContext->mScanner->Append(mParserContext->mTransferBuffer,len);
+
+ if(eUnknownDetect==mParserContext->mAutoDetectStatus) {
+ if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(),mParserContext->mSourceType)) {
+ nsresult result=WillBuildModel(mParserContext->mScanner->GetFilename());
+ } //if
+ }
+ } //if
+ }
nsresult result=ResumeParse();
return result;
@@ -797,7 +774,7 @@ nsresult nsParser::OnStopBinding(PRInt32 status, const nsString& aMsg){
* @return new token or null
*/
PRInt32 nsParser::ConsumeToken(CToken*& aToken) {
- PRInt32 result=mDTD->ConsumeToken(aToken);
+ PRInt32 result=mParserContext->mDTD->ConsumeToken(aToken);
return result;
}
@@ -811,39 +788,11 @@ PRInt32 nsParser::ConsumeToken(CToken*& aToken) {
* @param
* @return TRUE if it's ok to proceed
*/
-PRBool nsParser::WillTokenize(void){
+PRBool nsParser::WillTokenize(){
PRBool result=PR_TRUE;
return result;
}
-/**
- *
- * @update gess 3/25/98
- * @return TRUE if it's ok to proceed
- */
-PRInt32 nsParser::Tokenize(nsString& aSourceBuffer,PRBool appendTokens){
- CToken* theToken=0;
- PRInt32 result=kNoError;
- PRInt32 debugCounter=0; //this can be removed. It's only for debugging...
-
- WillTokenize();
-
- while(kNoError==result) {
- debugCounter++;
- result=ConsumeToken(theToken);
- if(theToken && (kNoError==result)) {
-
-#ifdef VERBOSE_DEBUG
- theToken->DebugDumpToken(cout);
-#endif
- mTokenDeque.Push(theToken);
- }
- }
- if(kEOF==result)
- result=kNoError;
- DidTokenize();
- return result;
-}
/**
* This is the primary control routine. It iteratively
@@ -853,14 +802,14 @@ PRInt32 nsParser::Tokenize(nsString& aSourceBuffer,PRBool appendTokens){
* @update gess 3/25/98
* @return error code
*/
-PRInt32 nsParser::Tokenize(void) {
+PRInt32 nsParser::Tokenize(){
CToken* theToken=0;
PRInt32 result=kNoError;
- PRBool done=(0==mMajorIteration) ? (!WillTokenize()) : PR_FALSE;
+ PRBool done=(0==++mParserContext->mMajorIteration) ? (!WillTokenize()) : PR_FALSE;
while((PR_FALSE==done) && (kNoError==result)) {
- mScanner->Mark();
+ mParserContext->mScanner->Mark();
result=ConsumeToken(theToken);
if(kNoError==result) {
if(theToken) {
@@ -868,14 +817,14 @@ PRInt32 nsParser::Tokenize(void) {
#ifdef VERBOSE_DEBUG
theToken->DebugDumpToken(cout);
#endif
- mTokenDeque.Push(theToken);
+ mParserContext->mTokenDeque.Push(theToken);
}
}
else {
if(theToken)
delete theToken;
- mScanner->RewindToMark();
+ mParserContext->mScanner->RewindToMark();
}
}
if((PR_TRUE==done) && (kInterrupted!=result))
@@ -892,7 +841,7 @@ PRInt32 nsParser::Tokenize(void) {
* @param
* @return TRUE if all went well
*/
-PRBool nsParser::DidTokenize(void) {
+PRBool nsParser::DidTokenize(){
PRBool result=PR_TRUE;
#ifdef VERBOSE_DEBUG
@@ -912,8 +861,8 @@ PRBool nsParser::DidTokenize(void) {
* @return
*/
void nsParser::DebugDumpTokens(ostream& out) {
- nsDequeIterator b=mTokenDeque.Begin();
- nsDequeIterator e=mTokenDeque.End();
+ nsDequeIterator b=mParserContext->mTokenDeque.Begin();
+ nsDequeIterator e=mParserContext->mTokenDeque.End();
CToken* theToken;
while(b!=e) {
@@ -933,8 +882,8 @@ void nsParser::DebugDumpTokens(ostream& out) {
* @return
*/
void nsParser::DebugDumpSource(ostream& out) {
- nsDequeIterator b=mTokenDeque.Begin();
- nsDequeIterator e=mTokenDeque.End();
+ nsDequeIterator b=mParserContext->mTokenDeque.Begin();
+ nsDequeIterator e=mParserContext->mTokenDeque.End();
CToken* theToken;
while(b!=e) {
diff --git a/htmlparser/src/nsParser.h b/htmlparser/src/nsParser.h
index 8fdf384dba1..2f59c0b3abc 100644
--- a/htmlparser/src/nsParser.h
+++ b/htmlparser/src/nsParser.h
@@ -60,7 +60,7 @@
#include "nsParserNode.h"
#include "nsParserTypes.h"
#include "nsIURL.h"
-
+#include "CParserContext.h"
#define NS_PARSER_IID \
{0x2ce606b0, 0xbee6, 0x11d1, \
@@ -69,7 +69,6 @@
class IContentSink;
class nsIHTMLContentSink;
-class nsIURL;
class nsIDTD;
class nsIDTDDebug;
class CScanner;
@@ -119,14 +118,26 @@ friend class CTokenHandler;
virtual CScanner* GetScanner(void);
/**
- * Cause parser to parse input from given URL in given mode
+ * Cause parser to parse input from given URL
* @update gess5/11/98
* @param aURL is a descriptor for source document
* @param aListener is a listener to forward notifications to
* @return TRUE if all went well -- FALSE otherwise
*/
virtual PRInt32 Parse(nsIURL* aURL,
- nsIStreamObserver* aListener, nsIDTDDebug * aDTDDebug = 0);
+ nsIStreamObserver* aListener,
+ nsIDTDDebug* aDTDDebug = 0);
+
+ /**
+ * Cause parser to parse input from given nsIInputStream
+ * @update gess5/11/98
+ * @param pIStream is an nsIInputStream
+ * @param aListener is a listener to forward notifications to
+ * @return TRUE if all went well -- FALSE otherwise
+ */
+ virtual PRInt32 Parse(nsIInputStream* pIStream,
+ nsIStreamObserver* aListener,
+ nsIDTDDebug* aDTDDebug = 0);
/**
* Cause parser to parse input from given file in given mode
@@ -134,7 +145,7 @@ friend class CTokenHandler;
* @param aFilename is a path for file document
* @return TRUE if all went well -- FALSE otherwise
*/
- virtual PRInt32 Parse(const char* aFilename);
+ virtual PRInt32 Parse(nsString& aFilename);
/**
* Cause parser to parse input from given stream
@@ -157,7 +168,7 @@ friend class CTokenHandler;
* @update gess5/11/98
* @return TRUE if all went well, otherwise FALSE
*/
- virtual PRInt32 ResumeParse(void);
+ virtual PRInt32 ResumeParse();
/**
* Causes the parser to scan foward, collecting nearby (sequential)
@@ -208,7 +219,7 @@ protected:
* @param
* @return
*/
- PRInt32 WillBuildModel(const char* aFilename=0);
+ PRInt32 WillBuildModel(nsString& aFilename);
/**
*
@@ -224,7 +235,7 @@ protected:
* @update gess5/11/98
* @return YES if model building went well -- NO otherwise.
*/
- virtual PRInt32 IterateTokens(void);
+ virtual PRInt32 BuildModel(void);
private:
@@ -251,15 +262,9 @@ private:
* @param
* @return TRUE if it's ok to proceed
*/
- PRBool WillTokenize(void);
-
- /**
- *
- * @update gess 3/25/98
- * @return TRUE if it's ok to proceed
- */
- PRInt32 Tokenize(nsString& aSourceBuffer,PRBool appendTokens);
+ PRBool WillTokenize();
+
/**
* This is the primary control routine. It iteratively
* consumes tokens until an error occurs or you run out
@@ -268,7 +273,7 @@ private:
* @update gess 3/25/98
* @return error code
*/
- PRInt32 Tokenize(void);
+ PRInt32 Tokenize();
/**
* This is the tail-end of the code sandwich for the
@@ -279,7 +284,7 @@ private:
* @param
* @return TRUE if all went well
*/
- PRBool DidTokenize(void);
+ PRBool DidTokenize();
/**
* This debug routine is used to cause the tokenizer to
@@ -311,27 +316,42 @@ protected:
// And now, some data members...
//*********************************************
- nsIStreamObserver* mObserver;
- nsIContentSink* mSink;
- nsIParserFilter* mParserFilter;
-
- nsDequeIterator* mCurrentPos;
- nsDequeIterator* mMarkPos;
-
- nsIDTD* mDTD;
- eParseMode mParseMode;
- char* mTransferBuffer;
+ /*****************************************************
+ All of these moved into the parse-context object:
PRInt32 mMajorIteration;
PRInt32 mMinorIteration;
- nsDeque mTokenDeque;
- CScanner* mScanner;
nsIURL* mURL;
- nsIDTDDebug* mDTDDebug;
nsString mSourceType;
nsString mTargetType;
eAutoDetectResult mAutoDetectStatus;
+
+ nsDequeIterator* mCurrentPos;
+ nsDequeIterator* mMarkPos;
+ nsDeque mTokenDeque;
+ CScanner* mScanner;
+ nsIDTD* mDTD;
+
+ eParseMode mParseMode;
+ char* mTransferBuffer;
+ *****************************************************/
+
+ CParserContext* mParserContext;
+
+ /*****************************************************
+ The above fields are moving into parse-context
+ *****************************************************/
+
+
+ nsIStreamObserver* mObserver;
+ nsIContentSink* mSink;
+ nsIParserFilter* mParserFilter;
+
+
+ nsIDTDDebug* mDTDDebug;
+
+
};
diff --git a/htmlparser/src/nsScanner.cpp b/htmlparser/src/nsScanner.cpp
index 6e38c26f645..7a9118a1fbc 100644
--- a/htmlparser/src/nsScanner.cpp
+++ b/htmlparser/src/nsScanner.cpp
@@ -19,10 +19,8 @@
//#define __INCREMENTAL 1
#include "nsScanner.h"
-#include "nsIURL.h"
#include "nsDebug.h"
-const char* gURLRef=0;
const char* kBadHTMLText="Oops...
You just tried to read a non-existent document:
";
#ifdef __INCREMENTAL
@@ -31,89 +29,55 @@ const int kBufsize=1;
const int kBufsize=64;
#endif
+
/**
- * Use this constructor if you want an incremental (callback)
- * based input stream.
+ * Use this constructor if you want i/o to be based on an
+ * incremental netstream. If you pass a null filename, you
+ * can still provide data to the scanner via append.
*
* @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
+ * @param aFilename --
* @return
*/
-CScanner::CScanner(eParseMode aMode) : mBuffer("") {
+CScanner::CScanner(nsString& aFilename,PRBool aCreateStream) :
+ mBuffer(""), mFilename(aFilename)
+{
mOffset=0;
mMarkPos=-1;
mTotalRead=0;
- mParseMode=aMode;
- mNetStream=0;
+ mOwnsStream=aCreateStream;
mFileStream=0;
- mIncremental=PR_TRUE;
- mOwnsStream=PR_TRUE;
+ if(aCreateStream) {
+ char buffer[513];
+ aFilename.ToCString(buffer,sizeof(buffer)-1);
+ #if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX))
+ /* XXX: IRIX does not support ios::binary */
+ mFileStream=new fstream(buffer,ios::in);
+ #else
+ mFileStream=new fstream(buffer,ios::in|ios::binary);
+ #endif
+ } //if
}
/**
- * Use this constructor if you want i/o to be file based.
+ * Use this constructor if you want i/o to be stream based.
*
* @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
+ * @param aStream --
+ * @param assumeOwnership --
+ * @param aFilename --
* @return
*/
-CScanner::CScanner(const char* aFilename,eParseMode aMode) : mBuffer("") {
- NS_ASSERTION(0!=aFilename,"Error: Null filename!");
+CScanner::CScanner(nsString& aFilename,fstream& aStream,PRBool assumeOwnership) :
+ mBuffer(""), mFilename(aFilename)
+{
mOffset=0;
mMarkPos=-1;
mTotalRead=0;
- mParseMode=aMode;
- mNetStream=0;
- mIncremental=PR_FALSE;
- mOwnsStream=PR_TRUE;
-#if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX))
- /* XXX: IRIX does not support ios::binary */
- mFileStream=new fstream(aFilename,ios::in);
-#else
- mFileStream=new fstream(aFilename,ios::in|ios::binary);
-#endif
-}
-
-/**
- * Use this constructor if you want i/o to be file based.
- *
- * @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
- * @return
- */
-CScanner::CScanner(fstream& aStream,eParseMode aMode) : mBuffer("") {
- mOffset=0;
- mMarkPos=-1;
- mTotalRead=0;
- mParseMode=aMode;
- mNetStream=0;
- mIncremental=PR_FALSE;
- mOwnsStream=PR_FALSE;
+ mOwnsStream=assumeOwnership;
mFileStream=&aStream;
}
-/**
- * Use this constructor if you want i/o to be based on a
- * non-incremental netstream.
- *
- * @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
- * @return
- */
-CScanner::CScanner(nsIURL* aURL,eParseMode aMode) : mBuffer("") {
- NS_ASSERTION(0!=aURL,"Error: Null URL!");
- mOffset=0;
- mMarkPos=-1;
- mTotalRead=0;
- mParseMode=aMode;
- mFileStream=0;
- PRInt32 error=0;
- mIncremental=PR_FALSE;
- mNetStream=aURL->Open(&error);
- gURLRef=aURL->GetSpec();
- mOwnsStream=PR_FALSE;
-}
-
/**
* default destructor
@@ -128,13 +92,7 @@ CScanner::~CScanner() {
if(mOwnsStream)
delete mFileStream;
}
- else if(mNetStream) {
- mNetStream->Close();
- mNetStream->Release();
- }
mFileStream=0;
- mNetStream=0;
- gURLRef=0;
}
/**
@@ -200,34 +158,9 @@ void _PreCompressBuffer(nsString& aBuffer,PRInt32& anOffset,PRInt32& aMarkPos){
}
-/**
- * This method should only be called by the parser when
- * we're doing incremental i/o over the net.
- *
- * @update gess 5/12/98
- * @param aBuffer contains next blob of i/o data
- * @param aSize contains size of buffer
- * @return 0 if all went well, otherwise error code.
- */
-PRInt32 CScanner::IncrementalAppend(const char* aBuffer,PRInt32 aSize){
- NS_ASSERTION(((!mFileStream) && (!mNetStream)),"Error: Should only be called during incremental net i/o!");
-
- PRInt32 result=0;
- if((!mFileStream) && (!mNetStream)) {
-
- _PreCompressBuffer(mBuffer,mOffset,mMarkPos);
-
- //now that the buffer is (possibly) shortened, let's append the new data.
- if(0read(buf,kBufsize);
numread=mFileStream->gcount();
}
- else if(mNetStream) {
- numread=mNetStream->Read(&anError,buf,0,kBufsize);
- if(1==anError)
- anError=kEOF;
- }
mOffset=mBuffer.Length();
if((0=mBuffer.Length()) {
- if(!mIncremental)
- theError=FillBuffer();
- else return kInterrupted;
+ theError=FillBuffer();
}
if(0==theError)
@@ -451,21 +378,21 @@ PRInt32 CScanner::SkipPast(nsString& aValidSet){
* @return error code
*/
PRInt32 CScanner::ReadWhile(nsString& aString,nsString& aValidSet,PRBool addTerminal){
- PRUnichar ch=0;
+ PRUnichar theChar=0;
PRInt32 result=kNoError;
PRInt32 wrPos=0;
while(kNoError==result) {
- result=GetChar(ch);
+ result=GetChar(theChar);
if(kNoError==result) {
- PRInt32 pos=aValidSet.Find(ch);
+ PRInt32 pos=aValidSet.Find(theChar);
if(kNotFound==pos) {
if(addTerminal)
- aString+=ch;
- else PutBack(ch);
+ aString+=theChar;
+ else PutBack(theChar);
break;
}
- else aString+=ch;
+ else aString+=theChar;
}
}
return result;
@@ -535,6 +462,18 @@ nsString& CScanner::GetBuffer(void) {
return mBuffer;
}
+/**
+ * Retrieve the name of the file that the scanner is reading from.
+ * In some cases, it's just a given name, because the scanner isn't
+ * really reading from a file.
+ *
+ * @update gess 5/12/98
+ * @return
+ */
+nsString& CScanner::GetFilename(void) {
+ return mFilename;
+}
+
/**
* Conduct self test. Actually, selftesting for this class
* occurs in the parser selftest.
diff --git a/htmlparser/src/nsScanner.h b/htmlparser/src/nsScanner.h
index d03b9bfb2f8..627a7f27fe1 100644
--- a/htmlparser/src/nsScanner.h
+++ b/htmlparser/src/nsScanner.h
@@ -35,43 +35,21 @@
#include "nsString.h"
#include "nsParserTypes.h"
#include "prtypes.h"
-#include "nsIInputStream.h"
#include
-class nsIURL;
-//class ifstream;
class CScanner {
public:
/**
- * Use this constructor if you want an incremental (callback)
- * based input stream.
+ * Use this constructor if you want i/o to be based on
+ * a file (therefore a stream) or just data you provide via Append().
*
* @update gess 5/12/98
* @param aMode represents the parser mode (nav, other)
* @return
*/
- CScanner(eParseMode aMode=eParseMode_navigator);
-
- /**
- * Use this constructor if you want i/o to be based on a
- * non-incremental netstream.
- *
- * @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
- * @return
- */
- CScanner(nsIURL* aURL,eParseMode aMode=eParseMode_navigator);
-
- /**
- * Use this constructor if you want i/o to be file based.
- *
- * @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
- * @return
- */
- CScanner(const char* aFilename,eParseMode aMode=eParseMode_navigator);
+ CScanner(nsString& aFilename,PRBool aCreateStream=PR_TRUE);
/**
* Use this constructor if you want i/o to be stream based.
@@ -80,7 +58,7 @@ class CScanner {
* @param aMode represents the parser mode (nav, other)
* @return
*/
- CScanner(fstream& aStream,eParseMode aMode=eParseMode_navigator);
+ CScanner(nsString& aFilename,fstream& aStream,PRBool assumeOwnership=PR_TRUE);
~CScanner();
@@ -241,16 +219,17 @@ class CScanner {
* @param
* @return
*/
- PRInt32 IncrementalAppend(const char* aBuffer,PRInt32 aSize);
+ nsString& GetBuffer(void);
/**
- *
+ * Retrieve the name of the file that the scanner is reading from.
+ * In some cases, it's just a given name, because the scanner isn't
+ * really reading from a file.
*
* @update gess 5/12/98
- * @param
* @return
*/
- nsString& GetBuffer(void);
+ nsString& GetFilename(void);
static void SelfTest();
@@ -268,13 +247,11 @@ class CScanner {
fstream* mFileStream;
- nsIInputStream* mNetStream;
nsString mBuffer;
+ nsString mFilename;
PRInt32 mOffset;
PRInt32 mMarkPos;
PRInt32 mTotalRead;
- eParseMode mParseMode;
- PRBool mIncremental;
PRBool mOwnsStream;
};
diff --git a/htmlparser/src/nsValidDTD.cpp b/htmlparser/src/nsValidDTD.cpp
index 979a78bd12b..95874180e58 100644
--- a/htmlparser/src/nsValidDTD.cpp
+++ b/htmlparser/src/nsValidDTD.cpp
@@ -190,7 +190,7 @@ eAutoDetectResult CValidDTD::AutoDetectContentType(nsString& aBuffer,nsString& a
* @param
* @return
*/
-PRInt32 CValidDTD::WillBuildModel(const char* aFilename){
+PRInt32 CValidDTD::WillBuildModel(nsString& aFilename){
PRInt32 result=0;
return result;
}
diff --git a/htmlparser/src/nsValidDTD.h b/htmlparser/src/nsValidDTD.h
index c0798370091..24bfc89a38a 100644
--- a/htmlparser/src/nsValidDTD.h
+++ b/htmlparser/src/nsValidDTD.h
@@ -108,7 +108,7 @@ class CValidDTD : public nsIDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aFilename);
/**
*
diff --git a/htmlparser/src/nsWellFormedDTD.cpp b/htmlparser/src/nsWellFormedDTD.cpp
index d092ed0e9ec..8137c3299b9 100644
--- a/htmlparser/src/nsWellFormedDTD.cpp
+++ b/htmlparser/src/nsWellFormedDTD.cpp
@@ -177,7 +177,7 @@ eAutoDetectResult CWellFormedDTD::AutoDetectContentType(nsString& aBuffer,nsStri
* @param
* @return
*/
-PRInt32 CWellFormedDTD::WillBuildModel(const char* aFilename){
+PRInt32 CWellFormedDTD::WillBuildModel(nsString& aFilename){
PRInt32 result=0;
return result;
}
diff --git a/htmlparser/src/nsWellFormedDTD.h b/htmlparser/src/nsWellFormedDTD.h
index 6add8b9a5b5..47155413f68 100644
--- a/htmlparser/src/nsWellFormedDTD.h
+++ b/htmlparser/src/nsWellFormedDTD.h
@@ -97,7 +97,7 @@ class CWellFormedDTD : public nsIDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aFilename);
/**
*
diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp
index a20c8c59367..3400ef36e19 100644
--- a/parser/htmlparser/src/CNavDTD.cpp
+++ b/parser/htmlparser/src/CNavDTD.cpp
@@ -91,6 +91,115 @@ static char gWhitespaceTags[]={
0};
+/************************************************************************
+ CTagStack class implementation.
+ The reason we use this class is so that we can view the stack state
+ in the usual way via the debugger.
+ ************************************************************************/
+
+
+CTagStack::CTagStack(int aDefaultSize) {
+#ifdef _dynstack
+ mSize=aDefaultSize;
+ mTags =new eHTMLTags[mSize];
+ mBits =new PRBool[mSize];
+#else
+ mSize=eStackSize;
+#endif
+ mCount=0;
+ nsCRT::zero(mTags,mSize*sizeof(eHTMLTag_html));
+ nsCRT::zero(mBits,mSize*sizeof(PRBool));
+}
+
+/**
+ * Default constructor
+ * @update gess7/9/98
+ * @param aDefaultsize tells the stack what size to start out.
+ * however, we'll autosize as needed.
+ */
+CTagStack::~CTagStack() {
+#ifdef _dynstack
+ delete mTags;
+ delete mBits;
+ mTags=0;
+ mBits=0;
+#endif
+ mSize=mCount=0;
+ }
+
+/**
+ *
+ * @update gess7/9/98
+ * @param
+ * @return
+ */
+void CTagStack::Push(eHTMLTags aTag) {
+
+ if(mCount>=mSize) {
+
+#ifdef _dynstack
+ eHTMLTags* tmp=new eHTMLTags[2*mSize];
+ nsCRT::zero(tmp,2*mSize*sizeof(eHTMLTag_html));
+ nsCRT::memcpy(tmp,mTags,mSize*sizeof(eHTMLTag_html));
+ delete mTags;
+ mTags=tmp;
+
+ PRBool* tmp2=new PRBool[2*mSize];
+ nsCRT::zero(tmp2,2*mSize*sizeof(PRBool));
+ nsCRT::memcpy(tmp2,mBits,mSize*sizeof(PRBool));
+ delete mBits;
+ mBits=tmp2;
+ mSize*=2;
+#endif
+ }
+ mTags[mCount++]=aTag;
+}
+
+/**
+ *
+ * @update gess7/9/98
+ * @param
+ * @return
+ */
+eHTMLTags CTagStack::Pop() {
+ eHTMLTags result=eHTMLTag_unknown;
+ if(mCount>0) {
+ result=mTags[--mCount];
+ mTags[mCount]=eHTMLTag_unknown;
+ mBits[mCount]=PR_FALSE;
+ }
+ return result;
+}
+
+/**
+ *
+ * @update gess7/9/98
+ * @param
+ * @return
+ */
+eHTMLTags CTagStack::First() const {
+ if(mCount>0)
+ return mTags[0];
+ return eHTMLTag_unknown;
+}
+
+/**
+ *
+ * @update gess7/9/98
+ * @param
+ * @return
+ */
+eHTMLTags CTagStack::Last() const {
+ if(mCount>0)
+ return mTags[mCount-1];
+ return eHTMLTag_unknown;
+}
+
+
+/************************************************************************
+ And now for the main class -- CNavDTD...
+ ************************************************************************/
+
/**
* This method gets called as part of our COM-like interfaces.
* Its purpose is to create an interface to parser object
@@ -124,6 +233,7 @@ nsresult CNavDTD::QueryInterface(const nsIID& aIID, void** aInstancePtr)
return NS_OK;
}
+
/**
* This method is defined in nsIParser. It is used to
* cause the COM-like construction of an nsParser.
@@ -234,15 +344,13 @@ static CNavTokenDeallocator gTokenKiller;
* @param
* @return
*/
-CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller) {
+CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller),
+ mContextStack(), mStyleStack() {
NS_INIT_REFCNT();
mParser=0;
- mFilename=0;
mSink = nsnull;
mDTDDebug=0;
nsCRT::zero(mTokenHandlers,sizeof(mTokenHandlers));
- mContextStackPos=0;
- mStyleStackPos=0;
mHasOpenForm=PR_FALSE;
mHasOpenMap=PR_FALSE;
InitializeDefaultTokenHandlers();
@@ -257,8 +365,6 @@ CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller) {
*/
CNavDTD::~CNavDTD(){
DeleteTokenHandlers();
- if (mFilename)
- PL_strfree(mFilename);
if (mDTDDebug)
NS_RELEASE(mDTDDebug);
@@ -281,6 +387,7 @@ void CNavDTD::SetDTDDebug(nsIDTDDebug * aDTDDebug)
NS_ADDREF(mDTDDebug);
}
+
/**
* This method is called to determine if the given DTD can parse
* a document in a given source-type.
@@ -308,24 +415,16 @@ eAutoDetectResult CNavDTD::AutoDetectContentType(nsString& aBuffer,nsString& aTy
return result;
}
-
-
/**
*
* @update gess5/18/98
* @param
* @return
*/
-PRInt32 CNavDTD::WillBuildModel(const char* aFilename){
+PRInt32 CNavDTD::WillBuildModel(nsString& aFilename){
PRInt32 result=0;
- if (mFilename) {
- PL_strfree(mFilename);
- mFilename=0;
- }
- if(aFilename) {
- mFilename = PL_strdup(aFilename);
- }
+ mFilename=aFilename;
if(mSink)
mSink->WillBuildModel();
@@ -342,7 +441,7 @@ PRInt32 CNavDTD::WillBuildModel(const char* aFilename){
PRInt32 CNavDTD::DidBuildModel(PRInt32 anErrorCode){
PRInt32 result=0;
- if((kNoError==anErrorCode) && (mContextStackPos>0)) {
+ if((kNoError==anErrorCode) && (mContextStack.mCount>0)) {
CloseContainersTo(0,eHTMLTag_unknown,PR_FALSE);
}
if(mSink) {
@@ -375,7 +474,7 @@ PRInt32 CNavDTD::HandleToken(CToken* aToken){
if(theHandler) {
result=(*theHandler)(theToken,this);
if (mDTDDebug)
- mDTDDebug->Verify(this, mParser, mContextStackPos, mContextStack, mFilename);
+ mDTDDebug->Verify(this, mParser, mContextStack.mCount, mContextStack.mTags, mFilename);
}
}//if
@@ -420,13 +519,13 @@ PRInt32 CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIP
}
if(IsContainer(aChildTag)){
- if(PR_TRUE==(PRBool)mLeafBits[mContextStackPos-1]) {
+ if(PR_TRUE==mContextStack.mBits[mContextStack.mCount-1]) {
CloseTransientStyles(aChildTag);
}
result=OpenContainer(aNode,PR_TRUE);
}
else {
- if(PR_FALSE==(PRBool)mLeafBits[mContextStackPos-1]) {
+ if(PR_FALSE==mContextStack.mBits[mContextStack.mCount-1]) {
OpenTransientStyles(aChildTag);
}
result=AddLeaf(aNode);
@@ -576,16 +675,8 @@ PRInt32 CNavDTD::HandleEndToken(CToken* aToken) {
// we have to handle explicit styles the way it does. That means
// that we keep an internal style stack.When an EndToken occurs,
// we should see if it is an explicit style tag. If so, we can
- // close AND explicit style tag (goofy, huh?)
+ // close the explicit style tag (goofy, huh?)
-/*
- if(0!=strchr(gStyleTags,tokenTagType)){
- eHTMLTags topTag=GetTopNode();
- if(0!=strchr(gStyleTags,topTag)){
- tokenTagType=topTag;
- }
- }
-*/
//now check to see if this token should be omitted...
if(PR_TRUE==CanOmitEndTag(GetTopNode(),tokenTagType)) {
@@ -622,7 +713,7 @@ PRInt32 CNavDTD::HandleEndToken(CToken* aToken) {
// Empty the transient style stack (we just closed any extra
// ones off so it's safe to do it now) because they don't carry
// forward across table cell boundaries.
- mStyleStackPos = 0;
+ mStyleStack.mCount=0;
break;
default:
@@ -1148,8 +1239,8 @@ PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) {
break; //singletons can't contain anything...
case eHTMLTag_li:
- if ((eHTMLTag_li == aChild) ||
- (eHTMLTag_ul == aChild) || // XXX this is temporary!!!
+ if ((eHTMLTag_li == aChild) || //XXX this is temporary!!!
+ (eHTMLTag_ul == aChild) ||
(eHTMLTag_ol == aChild) ||
(eHTMLTag_menu == aChild) ||
(eHTMLTag_dir == aChild)) {
@@ -1620,29 +1711,6 @@ PRBool CNavDTD::BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTa
return PRBool(aParentTag==theParentTag);
}
-/**
- *
- * @update gess6/4/98
- * @param aTag is the id of the html container being opened
- * @return 0 if all is well.
- */
-PRInt32 CNavDTD::DidOpenContainer(eHTMLTags aTag,PRBool /*anExplicitOpen*/){
- PRInt32 result=0;
- return result;
-}
-
-/**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
-PRInt32 CNavDTD::DidCloseContainer(eHTMLTags aTag,PRBool/*anExplicitClosure*/){
- PRInt32 result=0;
- return result;
-}
-
-
/**
* This method allows the caller to determine if a form
* element is currently open.
@@ -1672,9 +1740,7 @@ PRBool CNavDTD::HasOpenContainer(eHTMLTags aContainer) const {
* @return tag id of topmost node in contextstack
*/
eHTMLTags CNavDTD::GetTopNode() const {
- if(mContextStackPos)
- return (eHTMLTags)(int)mContextStack[mContextStackPos-1];
- return eHTMLTag_unknown;
+ return mContextStack.Last();
}
@@ -1688,8 +1754,8 @@ eHTMLTags CNavDTD::GetTopNode() const {
*/
PRInt32 CNavDTD::GetTopmostIndexOf(eHTMLTags aTag) const {
int i=0;
- for(i=mContextStackPos-1;i>=0;i--){
- if((eHTMLTags)(int)mContextStack[i]==aTag)
+ for(i=mContextStack.mCount-1;i>=0;i--){
+ if(mContextStack.mTags[i]==aTag)
return i;
}
return kNotFound;
@@ -1720,8 +1786,8 @@ PRInt32 CNavDTD::OpenTransientStyles(eHTMLTags aTag){
eHTMLTags parentTag=GetTopNode();
if(CanContainStyles(parentTag)) {
- for(pos=0;pos0) && (mLeafBits[mContextStackPos-1])) {
+ if((mStyleStack.mCount>0) && (mContextStack.mBits[mContextStack.mCount-1])) {
if(0==strchr(gWhitespaceTags,aTag)){
- result=CloseContainersTo((eHTMLTags)(int)mStyleStack[0],PR_FALSE);
- mLeafBits.ReplaceElementAt((void*)PR_FALSE,mContextStackPos-1);
+ result=CloseContainersTo(mStyleStack.mTags[0],PR_FALSE);
+ mContextStack.mBits[mContextStack.mCount-1]=PR_FALSE;
}//if
}//if
@@ -1782,10 +1848,10 @@ PRInt32 CNavDTD::CloseTransientStyles(eHTMLTags aTag){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenHTML(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos);
PRInt32 result=mSink->OpenHTML(aNode);
- mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++);
+ mContextStack.Push((eHTMLTags)aNode.GetNodeType());
return result;
}
@@ -1799,9 +1865,9 @@ PRInt32 CNavDTD::OpenHTML(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseHTML(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=mSink->CloseHTML(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
return result;
}
@@ -1815,7 +1881,7 @@ PRInt32 CNavDTD::CloseHTML(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenHead(const nsIParserNode& aNode){
- mContextStack.ReplaceElementAt((void*)eHTMLTag_head,++mContextStackPos);
+ mContextStack.Push(eHTMLTag_head);
PRInt32 result=mSink->OpenHead(aNode);
return result;
}
@@ -1830,7 +1896,7 @@ PRInt32 CNavDTD::OpenHead(const nsIParserNode& aNode){
*/
PRInt32 CNavDTD::CloseHead(const nsIParserNode& aNode){
PRInt32 result=mSink->CloseHead(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
return result;
}
@@ -1843,7 +1909,7 @@ PRInt32 CNavDTD::CloseHead(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos);
PRInt32 result=kNoError;
eHTMLTags topTag=GetTopNode();
@@ -1875,7 +1941,7 @@ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){
if(kNoError==result) {
result=mSink->OpenBody(aNode);
- mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++);
+ mContextStack.Push((eHTMLTags)aNode.GetNodeType());
}
return result;
}
@@ -1889,9 +1955,9 @@ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseBody(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos);
PRInt32 result=mSink->CloseBody(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
return result;
}
@@ -1980,9 +2046,9 @@ PRInt32 CNavDTD::CloseMap(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenFrameset(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos);
PRInt32 result=mSink->OpenFrameset(aNode);
- mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++);
+ mContextStack.Push((eHTMLTags)aNode.GetNodeType());
return result;
}
@@ -1995,9 +2061,9 @@ PRInt32 CNavDTD::OpenFrameset(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseFrameset(const nsIParserNode& aNode){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=mSink->CloseFrameset(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
return result;
}
@@ -2011,7 +2077,7 @@ PRInt32 CNavDTD::CloseFrameset(const nsIParserNode& aNode){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleStack){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=kNoError;
eHTMLTags nodeType=(eHTMLTags)aNode.GetNodeType();
@@ -2037,7 +2103,7 @@ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleSta
default:
result=mSink->OpenContainer(aNode);
- mContextStack.ReplaceElementAt((void*)nodeType,mContextStackPos++);
+ mContextStack.Push((eHTMLTags)aNode.GetNodeType());
break;
}
@@ -2057,7 +2123,7 @@ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleSta
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool aUpdateStyles){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=kNoError; //was false
eHTMLTags nodeType=(eHTMLTags)aNode.GetNodeType();
@@ -2085,11 +2151,11 @@ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool
case eHTMLTag_title:
default:
result=mSink->CloseContainer(aNode);
- mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos);
+ mContextStack.Pop();
break;
}
- mLeafBits.ReplaceElementAt((void*)PR_FALSE, mContextStackPos);
+ mContextStack.mBits[mContextStack.mCount]=PR_FALSE;
if((kNoError==result) && (PR_TRUE==aUpdateStyles)){
UpdateStyleStackForCloseTag(nodeType,aTag);
}
@@ -2106,15 +2172,15 @@ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdateStyles){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 result=kNoError;
CEndToken aToken(gEmpty);
nsCParserNode theNode(&aToken);
- if((anIndex=0)) {
- while(mContextStackPos>anIndex) {
- eHTMLTags theTag=(eHTMLTags)(int)mContextStack[mContextStackPos-1];
+ if((anIndex=0)) {
+ while(mContextStack.mCount>anIndex) {
+ eHTMLTags theTag=mContextStack.Last();
aToken.SetTypeID(theTag);
result=CloseContainer(theNode,aTag,aUpdateStyles);
}
@@ -2131,7 +2197,7 @@ PRInt32 CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdate
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
PRInt32 pos=GetTopmostIndexOf(aTag);
@@ -2172,10 +2238,10 @@ PRInt32 CNavDTD::CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles){
* @return TRUE if ok, FALSE if error
*/
PRInt32 CNavDTD::CloseTopmostContainer(){
- NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos);
+ NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos);
CEndToken aToken(gEmpty);
- eHTMLTags theTag=(eHTMLTags)(int)mContextStack[mContextStackPos-1];
+ eHTMLTags theTag=mContextStack.Last();
aToken.SetTypeID(theTag);
nsCParserNode theNode(&aToken);
return CloseContainer(theNode,theTag,PR_TRUE);
@@ -2217,7 +2283,7 @@ PRInt32 CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){
//add code here to build up context stack based on forward propagated context vector...
pos=0;
cnt=theVector.Length()-1;
- if(mContextStack[mContextStackPos-1]==(void*)theVector[cnt])
+ if(mContextStack.Last()==(eHTMLTags)theVector[cnt])
result=kNoError;
else result=kContextMismatch;
}
@@ -2236,8 +2302,8 @@ PRInt32 CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){
pos=0;
cnt=theVector.Length();
result=kNoError;
- while(pos0) {
+ if(mStyleStack.mCount>0) {
switch (aTag) {
case eHTMLTag_a:
@@ -2369,7 +2435,7 @@ PRInt32 CNavDTD::UpdateStyleStackForCloseTag(eHTMLTags aTag,eHTMLTags anActualTa
case eHTMLTag_u:
case eHTMLTag_var:
if(aTag==anActualTag)
- mStyleStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mStyleStackPos);
+ mStyleStack.Pop();
break;
case eHTMLTag_h1: case eHTMLTag_h2:
@@ -2716,8 +2782,8 @@ PRInt32 CNavDTD::ConsumeToken(CToken*& aToken){
CScanner* theScanner=mParser->GetScanner();
if(kNoError==result){
- PRUnichar aChar;
- result=theScanner->GetChar(aChar);
+ PRUnichar theChar;
+ result=theScanner->GetChar(theChar);
switch(result) {
case kEOF:
break;
@@ -2728,25 +2794,25 @@ PRInt32 CNavDTD::ConsumeToken(CToken*& aToken){
case kNoError:
default:
- switch(aChar) {
+ switch(theChar) {
case kLessThan:
- return ConsumeTag(aChar,*theScanner,aToken);
+ return ConsumeTag(theChar,*theScanner,aToken);
case kAmpersand:
- return ConsumeEntity(aChar,*theScanner,aToken);
+ return ConsumeEntity(theChar,*theScanner,aToken);
case kCR: case kLF:
- return ConsumeNewline(aChar,*theScanner,aToken);
+ return ConsumeNewline(theChar,*theScanner,aToken);
case kNotFound:
break;
default:
- if(!nsString::IsSpace(aChar)) {
- nsAutoString temp(aChar);
+ if(!nsString::IsSpace(theChar)) {
+ nsAutoString temp(theChar);
return ConsumeText(temp,*theScanner,aToken);
}
- return ConsumeWhitespace(aChar,*theScanner,aToken);
+ return ConsumeWhitespace(theChar,*theScanner,aToken);
} //switch
break;
} //switch
diff --git a/parser/htmlparser/src/CNavDTD.h b/parser/htmlparser/src/CNavDTD.h
index 2ea700f9ec7..063874781d3 100644
--- a/parser/htmlparser/src/CNavDTD.h
+++ b/parser/htmlparser/src/CNavDTD.h
@@ -45,6 +45,54 @@ class nsIParserNode;
class CITokenHandler;
class nsParser;
+
+
+/***************************************************************
+ First define a helper class called CTagStack.
+
+ Simple, we've built ourselves a little data structure that
+ serves as a stack for htmltags (and associated bits).
+ What's special is that if you #define _dynstack 1, the stack
+ size can grow dynamically (like you'ld want in a release build.)
+ If you don't #define _dynstack 1, then the stack is a fixed size,
+ equal to the eStackSize enum. This makes debugging easier, because
+ you can see the htmltags on the stack if its not dynamic.
+ ***************************************************************/
+
+//#define _dynstack 1
+class CTagStack {
+ enum {eStackSize=200};
+
+public:
+
+ CTagStack(int aDefaultSize=50);
+ ~CTagStack();
+ void Push(eHTMLTags aTag);
+ eHTMLTags Pop();
+ eHTMLTags First() const;
+ eHTMLTags Last() const;
+
+ int mSize;
+ int mCount;
+
+#ifdef _dynstack
+ eHTMLTags* mTags;
+ PRBool* mBits;
+#else
+ eHTMLTags mTags[200];
+ PRBool mBits[200];
+#endif
+};
+
+/***************************************************************
+ 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.
+ ***************************************************************/
+
+
class CNavDTD : public nsIDTD {
public:
@@ -103,7 +151,7 @@ class CNavDTD : public nsIDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aFilename);
/**
*
@@ -251,14 +299,6 @@ class CNavDTD : public nsIDTD {
*/
virtual PRBool BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTags aChildTag) const;
- /**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
- virtual PRInt32 DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen);
-
/**
* Ask parser if a given container is open ANYWHERE on stack
* @update gess5/11/98
@@ -283,129 +323,36 @@ class CNavDTD : public nsIDTD {
*/
virtual PRInt32 GetTopmostIndexOf(eHTMLTags aTag) const;
- /**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
- virtual PRInt32 DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure);
/**
- * This method gets called when a start token has been consumed and needs
- * to be handled (possibly added to content model via sink).
+ * The following set of methods are used to partially construct
+ * the content model (via the sink) according to the type of token.
* @update gess5/11/98
* @param aToken is the start token to be handled
* @return TRUE if the token was handled.
*/
PRInt32 HandleStartToken(CToken* aToken);
-
- /**
- * This method gets called when a start token has been consumed, and
- * we want to use default start token handling behavior.
- * This method gets called automatically by handleStartToken.
- *
- * @update gess5/11/98
- * @param aToken is the start token to be handled
- * @param aChildTag is the tag-type of given token
- * @param aNode is a node be updated with info from given token
- * @return TRUE if the token was handled.
- */
PRInt32 HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode);
-
- /**
- * This method gets called when an end token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the end token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleEndToken(CToken* aToken);
-
- /**
- * This method gets called when an entity token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the entity token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleEntityToken(CToken* aToken);
-
- /**
- * This method gets called when a comment token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the comment token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleCommentToken(CToken* aToken);
-
- /**
- * This method gets called when a skipped-content token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the skipped-content token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleSkippedContentToken(CToken* aToken);
-
- /**
- * This method gets called when an attribute token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the attribute token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleAttributeToken(CToken* aToken);
-
- /**
- * This method gets called when a script token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the script token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleScriptToken(CToken* aToken);
-
- /**
- * This method gets called when a style token has been consumed and needs
- * to be handled (possibly added to content model via sink).
- * @update gess5/11/98
- * @param aToken is the style token to be handled
- * @return TRUE if the token was handled.
- */
PRInt32 HandleStyleToken(CToken* aToken);
-
protected:
/**
- * Causes token handlers to be registered for this parser.
- * DO NOT CALL THIS! IT'S DEPRECATED!
- * @update gess5/11/98
- */
- void InitializeDefaultTokenHandlers();
-
-
- /**
- * DEPRECATED
+ * The following methods are use to create and manage
+ * the dynamic set of token handlers.
* @update gess5/11/98
*/
+ void InitializeDefaultTokenHandlers();
CITokenHandler* GetTokenHandler(eHTMLTokenTypes aType) const;
-
- /**
- * DEPRECATED
- * @update gess5/11/98
- */
CITokenHandler* AddTokenHandler(CITokenHandler* aHandler);
-
- /**
- * DEPRECATED
- * @update gess5/11/98
- */
- void DeleteTokenHandlers(void);
-
+ void DeleteTokenHandlers(void);
//*************************************************
@@ -414,145 +361,43 @@ protected:
//*************************************************
/**
- * This cover method opens the given node as a HTML item in
- * content sink.
+ * The next set of method open given HTML element.
+ *
* @update gess5/11/98
* @param HTML (node) to be opened in content sink.
* @return TRUE if all went well.
*/
PRInt32 OpenHTML(const nsIParserNode& aNode);
-
- /**
- *
- * @update gess5/11/98
- * @param
- * @return
- */
- PRInt32 CloseHTML(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a head item in
- * content sink.
- * @update gess5/11/98
- * @param HEAD (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenHead(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink head to be closed
- * @update gess5/11/98
- * @param aNode is the node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseHead(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a body item in
- * content sink.
- * @update gess5/11/98
- * @param BODY (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenBody(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink body to be closed
- * @update gess5/11/98
- * @param aNode is the body node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseBody(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a form item in
- * content sink.
- * @update gess5/11/98
- * @param FORM (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenForm(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink form to be closed
- * @update gess5/11/98
- * @param aNode is the form node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseForm(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a form item in
- * content sink.
- * @update gess5/11/98
- * @param FORM (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenMap(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink form to be closed
- * @update gess5/11/98
- * @param aNode is the form node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseMap(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a frameset item in
- * content sink.
- * @update gess5/11/98
- * @param FRAMESET (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenFrameset(const nsIParserNode& aNode);
-
- /**
- * This cover method causes the content-sink frameset to be closed
- * @update gess5/11/98
- * @param aNode is the frameeset node to be closed in sink (usually ignored)
- * @return TRUE if all went well.
- */
- PRInt32 CloseFrameset(const nsIParserNode& aNode);
-
- /**
- * This cover method opens the given node as a generic container in
- * content sink.
- * @update gess5/11/98
- * @param generic container (node) to be opened in content sink.
- * @return TRUE if all went well.
- */
PRInt32 OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleStack);
/**
- * This cover method causes a generic containre in the content-sink to be closed
+ * The next set of methods close the given HTML element.
+ *
* @update gess5/11/98
- * @param aNode is the node to be closed in sink (usually ignored)
+ * @param HTML (node) to be opened in content sink.
* @return TRUE if all went well.
*/
+ PRInt32 CloseHTML(const nsIParserNode& aNode);
+ PRInt32 CloseHead(const nsIParserNode& aNode);
+ PRInt32 CloseBody(const nsIParserNode& aNode);
+ PRInt32 CloseForm(const nsIParserNode& aNode);
+ PRInt32 CloseMap(const nsIParserNode& aNode);
+ PRInt32 CloseFrameset(const nsIParserNode& aNode);
PRInt32 CloseContainer(const nsIParserNode& aNode,eHTMLTags anActualTag,PRBool aUpdateStyles);
/**
- * This cover method causes the topmost container to be closed in sink
+ * The special purpose methods automatically close
+ * one or more open containers.
* @update gess5/11/98
* @return TRUE if all went well.
*/
PRInt32 CloseTopmostContainer();
-
- /**
- * Cause all containers down to topmost given tag to be closed
- * @update gess5/11/98
- * @param aTag is the tag at which auto-closure should stop (inclusive)
- * @return TRUE if all went well -- otherwise FALSE
- */
PRInt32 CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles);
-
- /**
- * Cause all containers down to given position to be closed
- * @update gess5/11/98
- * @param anIndex is the stack pos at which auto-closure should stop (inclusive)
- * @return TRUE if all went well -- otherwise FALSE
- */
PRInt32 CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdateStyles);
/**
@@ -603,81 +448,22 @@ protected:
CToken* CreateTokenOfType(eHTMLTokenTypes aType);
/**
- * Retrieve the next TAG from the given scanner.
+ * The following methods consume a particular type
+ * of HTML token.
+ *
* @update gess 5/11/98
* @param aScanner is the input source
* @param aToken is the next token (or null)
* @return error code
*/
PRInt32 ConsumeTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve next START tag from given scanner.
- * @update gess 5/11/98
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeStartTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve collection of HTML/XML attributes from given scanner
- * @update gess 5/11/98
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeAttributes(PRUnichar aChar,CScanner& aScanner,CStartToken* aToken);
-
- /**
- * Retrieve a sequence of text from given scanner.
- * @update gess 5/11/98
- * @param aString will contain retrieved text.
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
- PRInt32 ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve an entity from given scanner
- * @update gess 5/11/98
- * @param aChar last char read from scanner
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeEntity(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve a whitespace sequence from the given scanner
- * @update gess 5/11/98
- * @param aChar last char read from scanner
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeWhitespace(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve a comment from the given scanner
- * @update gess 5/11/98
- * @param aChar last char read from scanner
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeComment(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
-
- /**
- * Retrieve newlines from given scanner
- * @update gess 5/11/98
- * @param aChar last char read from scanner
- * @param aScanner is the input source
- * @param aToken is the next token (or null)
- * @return error code
- */
PRInt32 ConsumeNewline(PRUnichar aChar,CScanner& aScanner,CToken*& aToken);
+ PRInt32 ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken);
/**
* Causes content to be skipped up to sequence contained in aString.
@@ -700,16 +486,13 @@ protected:
CITokenHandler* mTokenHandlers[eToken_last];
- nsVoidArray mLeafBits;
- nsVoidArray mContextStack;
- PRInt32 mContextStackPos;
- nsVoidArray mStyleStack;
- PRInt32 mStyleStackPos;
+ CTagStack mContextStack;
+ CTagStack mStyleStack;
PRBool mHasOpenForm;
PRBool mHasOpenMap;
nsDeque mTokenDeque;
- char* mFilename;
+ nsString mFilename;
nsIDTDDebug* mDTDDebug;
};
diff --git a/parser/htmlparser/src/COtherDTD.cpp b/parser/htmlparser/src/COtherDTD.cpp
index 886dc88c047..a3b2b0cd572 100644
--- a/parser/htmlparser/src/COtherDTD.cpp
+++ b/parser/htmlparser/src/COtherDTD.cpp
@@ -178,7 +178,7 @@ eAutoDetectResult COtherDTD::AutoDetectContentType(nsString& aBuffer,nsString& a
* @param
* @return
*/
-PRInt32 COtherDTD::WillBuildModel(const char* aFilename) {
+PRInt32 COtherDTD::WillBuildModel(nsString& aFilename) {
return CNavDTD::WillBuildModel(aFilename);
}
@@ -464,25 +464,6 @@ PRBool COtherDTD::BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTML
return CNavDTD::BackwardPropagate(aVector,aParentTag,aChildTag);
}
-/**
- *
- * @update gess6/4/98
- * @param aTag is the id of the html container being opened
- * @return 0 if all is well.
- */
-PRInt32 COtherDTD::DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen){
- return CNavDTD::DidOpenContainer(aTag,anExplicitOpen);
-}
-
-/**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
-PRInt32 COtherDTD::DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure){
- return CNavDTD::DidOpenContainer(aTag,anExplicitClosure);
-}
/*********************************************
Here comes code that handles the interface
diff --git a/parser/htmlparser/src/COtherDTD.h b/parser/htmlparser/src/COtherDTD.h
index 10813045aba..488b2f26886 100644
--- a/parser/htmlparser/src/COtherDTD.h
+++ b/parser/htmlparser/src/COtherDTD.h
@@ -87,7 +87,7 @@ class COtherDTD : public CNavDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aString);
/**
*
@@ -218,22 +218,6 @@ class COtherDTD : public CNavDTD {
*/
virtual PRBool BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTags aChildTag) const;
- /**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
- virtual PRInt32 DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen);
-
- /**
- *
- * @update gess6/4/98
- * @param
- * @return
- */
- virtual PRInt32 DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure);
-
/**
* This method gets called when a start token has been consumed and needs
* to be handled (possibly added to content model via sink).
diff --git a/parser/htmlparser/src/CParserContext.cpp b/parser/htmlparser/src/CParserContext.cpp
new file mode 100644
index 00000000000..fae66a3d063
--- /dev/null
+++ b/parser/htmlparser/src/CParserContext.cpp
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/**
+ * MODULE NOTES:
+ * @update gess 4/1/98
+ *
+ */
+
+
+#include "CParserContext.h"
+#include "nsToken.h"
+
+
+class CTokenDeallocator: public nsDequeFunctor{
+public:
+ virtual void* operator()(void* anObject) {
+ CToken* aToken = (CToken*)anObject;
+ delete aToken;
+ return 0;
+ }
+};
+
+CTokenDeallocator gTokenDeallocator;
+
+
+CParserContext::CParserContext(CScanner* aScanner,
+ CParserContext* aPreviousContext,
+ nsIStreamObserver* aListener) :
+ mTokenDeque(gTokenDeallocator),
+ mSourceType()
+{
+ mScanner=aScanner;
+ mPrevContext=aPreviousContext;
+ mListener=aListener;
+ NS_IF_ADDREF(mListener);
+ mMajorIteration=mMinorIteration=-1;
+ mParseMode=eParseMode_unknown;
+ mAutoDetectStatus=eUnknownDetect;
+ mTransferBuffer=new char[eTransferBufferSize+1];
+ mCurrentPos=0;
+ mMarkPos=0;
+ mDTD=0;
+}
+
+
+/**
+ * Destructor for parser context
+ * NOTE: DO NOT destroy the dtd here.
+ * @update gess7/11/98
+ */
+CParserContext::~CParserContext(){
+
+ if(mCurrentPos)
+ delete mCurrentPos;
+ if(mMarkPos)
+ delete mMarkPos;
+
+ if(mScanner)
+ delete mScanner;
+
+ if(mTransferBuffer)
+ delete [] mTransferBuffer;
+
+ //Remember that it's ok to simply
+ //ignore the DTD and the prevcontext.
+
+}
+
+
diff --git a/parser/htmlparser/src/CParserContext.h b/parser/htmlparser/src/CParserContext.h
new file mode 100644
index 00000000000..41da84f49f9
--- /dev/null
+++ b/parser/htmlparser/src/CParserContext.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/**
+ * MODULE NOTES:
+ * @update gess 4/1/98
+ *
+ */
+
+#ifndef __CParserContext
+#define __CParserContext
+
+#include "nsIParser.h"
+#include "nsDeque.h"
+#include "nsParserTypes.h"
+#include "nsIURL.h"
+#include "nsIDTD.h"
+#include "nsScanner.h"
+#include "nsIStreamListener.h"
+
+
+/**
+ * Note that the parser is given FULL access to all
+ * data in a parsercontext. Hey, that what it's for!
+ */
+
+class CParserContext {
+
+public:
+
+ enum {eTransferBufferSize=4096};
+
+ CParserContext( CScanner* aScanner,
+ CParserContext* aPreviousContext=0,
+ nsIStreamObserver* aListener=0);
+
+
+ ~CParserContext();
+
+
+ PRInt32 mMajorIteration;
+ PRInt32 mMinorIteration;
+
+ nsString mSourceType;
+ eAutoDetectResult mAutoDetectStatus;
+
+ nsDequeIterator* mCurrentPos;
+ nsDequeIterator* mMarkPos;
+ nsDeque mTokenDeque;
+ CScanner* mScanner;
+ nsIDTD* mDTD;
+
+ eParseMode mParseMode;
+ char* mTransferBuffer;
+ nsIStreamObserver* mListener;
+
+ CParserContext* mPrevContext;
+
+};
+
+
+
+#endif
+
+
diff --git a/parser/htmlparser/src/CRtfDTD.cpp b/parser/htmlparser/src/CRtfDTD.cpp
index 51add7383a1..8bc844274e8 100644
--- a/parser/htmlparser/src/CRtfDTD.cpp
+++ b/parser/htmlparser/src/CRtfDTD.cpp
@@ -251,7 +251,7 @@ eAutoDetectResult CRtfDTD::AutoDetectContentType(nsString& aBuffer,nsString& aTy
* @param
* @return
*/
-PRInt32 CRtfDTD::WillBuildModel(const char* aFilename){
+PRInt32 CRtfDTD::WillBuildModel(nsString& aFilename){
PRInt32 result=0;
return result;
}
diff --git a/parser/htmlparser/src/CRtfDTD.h b/parser/htmlparser/src/CRtfDTD.h
index dff562561a7..4f40b2f2eba 100644
--- a/parser/htmlparser/src/CRtfDTD.h
+++ b/parser/htmlparser/src/CRtfDTD.h
@@ -190,7 +190,7 @@ class CRtfDTD : public nsIDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aFilename);
/**
*
diff --git a/parser/htmlparser/src/Makefile b/parser/htmlparser/src/Makefile
index 8a09a69ba9d..616e7f6f6b1 100644
--- a/parser/htmlparser/src/Makefile
+++ b/parser/htmlparser/src/Makefile
@@ -34,6 +34,7 @@ CPPSRCS = \
nsValidDTD.cpp \
nsWellFormedDTD.cpp \
nsParser.cpp \
+ CParserContext.cpp \
nsHTMLTokens.cpp \
nsHTMLTags.cpp \
prstrm.cpp \
diff --git a/parser/htmlparser/src/makefile.win b/parser/htmlparser/src/makefile.win
index 68b1598facb..0b786802cb6 100644
--- a/parser/htmlparser/src/makefile.win
+++ b/parser/htmlparser/src/makefile.win
@@ -34,6 +34,7 @@ CPPSRCS= \
nsHTMLTags.obj \
nsHTMLTokens.obj \
nsParser.obj \
+ CParserContext.obj \
nsParserNode.obj \
nsScanner.obj \
nsToken.obj \
@@ -53,6 +54,7 @@ CPP_OBJS= \
.\$(OBJDIR)\nsHTMLTags.obj \
.\$(OBJDIR)\nsHTMLTokens.obj \
.\$(OBJDIR)\nsParser.obj \
+ .\$(OBJDIR)\CParserContext.obj \
.\$(OBJDIR)\nsParserNode.obj \
.\$(OBJDIR)\nsScanner.obj \
.\$(OBJDIR)\nsToken.obj \
diff --git a/parser/htmlparser/src/nsDTDDebug.cpp b/parser/htmlparser/src/nsDTDDebug.cpp
index a67ad7ac475..17166904c7f 100644
--- a/parser/htmlparser/src/nsDTDDebug.cpp
+++ b/parser/htmlparser/src/nsDTDDebug.cpp
@@ -67,7 +67,7 @@ public:
void SetVerificationDirectory(char * verify_dir);
void SetRecordStatistics(PRBool bval);
- PRBool Verify(nsIDTD * aDTD, nsParser * aParser, int ContextStackPos, nsVoidArray &aContextStack, char * aURLRef);
+ PRBool Verify(nsIDTD * aDTD, nsParser * aParser, int ContextStackPos, eHTMLTags aContextStack[], nsString& aURLRef);
void DumpVectorRecord(void);
// global table for storing vector statistics and the size
@@ -78,8 +78,8 @@ private:
char * mVerificationDir;
PRBool mRecordingStatistics;
- PRBool DebugRecord(char * path, char * pURLRef, char * filename);
- void NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector);
+ PRBool DebugRecord(char * path, nsString& pURLRef, char * filename);
+ void NoteVector(eHTMLTags aTags[],PRInt32 count, PRBool good_vector);
void MakeVectorString(char * vector_string, VectorInfo * pInfo);
};
@@ -188,7 +188,7 @@ void CDTDDebug::SetRecordStatistics(PRBool bval)
* @return TRUE if it is already record (dont rerecord)
*/
-PRBool CDTDDebug::DebugRecord(char * path, char * pURLRef, char * filename)
+PRBool CDTDDebug::DebugRecord(char * path, nsString& aURLRef, char * filename)
{
char recordPath[2048];
PRIntn oflags = 0;
@@ -215,7 +215,9 @@ PRBool CDTDDebug::DebugRecord(char * path, char * pURLRef, char * filename)
// vectors are stored on the format iof "URL vector filename"
// where the vector contains the verification path and
// the filename contains the debug source dump
- sprintf(string,"%s %s %s\r\n", pURLRef, path, filename);
+ char buffer[513];
+ aURLRef.ToCString(buffer,sizeof(buffer)-1);
+ sprintf(string,"%s %s %s\r\n", buffer, path, filename);
// get the file size, read in the file and parse it line at
// a time to check to see if we have already recorded this
@@ -310,7 +312,7 @@ static int compare( const void *arg1, const void *arg2 )
* @return
*/
-void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector)
+void CDTDDebug::NoteVector(eHTMLTags aTags[],PRInt32 count, PRBool good_vector)
{
// if the table doesn't exist, create it
if (!mVectorInfoArray) {
@@ -327,7 +329,7 @@ void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector
PRBool match = PR_TRUE;
for (PRInt32 j = 0; j < count; j++)
- if (mVectorInfoArray[i]->vector[j] != (eHTMLTags)(int)aTags[j]) {
+ if (mVectorInfoArray[i]->vector[j] != aTags[j]) {
match = PR_FALSE;
break;
}
@@ -348,7 +350,7 @@ void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector
pVectorInfo->good_vector = good_vector;
pVectorInfo->vector = (eHTMLTags*)PR_Malloc(count*sizeof(eHTMLTags));
for (PRInt32 i = 0; i < count; i++)
- pVectorInfo->vector[i] = (eHTMLTags)(int)aTags[i];
+ pVectorInfo->vector[i] = aTags[i];
mVectorInfoArray[mVectorCount++] = pVectorInfo;
// have we maxed out the table? grow it.. sort it.. love it.
@@ -467,7 +469,7 @@ void CDTDDebug::DumpVectorRecord(void)
* @return TRUE if we know how to handle it, else false
*/
-PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPos, nsVoidArray &aContextStack, char * aURLRef)
+PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPos, eHTMLTags aContextStack[], nsString& aURLRef)
{
PRBool result=PR_TRUE;
@@ -477,7 +479,7 @@ PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPo
if(aDTD && aContextStackPos>1) {
for (int i = 0; i < aContextStackPos-1; i++)
- if (!aDTD->CanContain((eHTMLTags)(int)aContextStack[i],(eHTMLTags)(int)aContextStack[i+1])) {
+ if (!aDTD->CanContain(aContextStack[i],aContextStack[i+1])) {
result = PR_FALSE;
break;
}
@@ -495,7 +497,7 @@ PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPo
int i=0;
for(i=0;i
-#include "nsString.h"
+#include "nsstring.h"
#include "nsParserTypes.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
@@ -89,8 +89,8 @@ NS_IMPL_RELEASE(CHTMLContentSinkStream)
* @param nsIParser** ptr to newly instantiated parser
* @return NS_xxx error result
*/
-NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aInstancePtrResult) {
- CHTMLContentSinkStream* it = new CHTMLContentSinkStream();
+NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aInstancePtrResult,ostream* aStream) {
+ CHTMLContentSinkStream* it = new CHTMLContentSinkStream(aStream);
if (it == 0) {
return NS_ERROR_OUT_OF_MEMORY;
@@ -99,25 +99,14 @@ NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aIns
return it->QueryInterface(kClassIID, (void **) aInstancePtrResult);
}
-
/**
* Construct a content sink stream.
* @update gess7/7/98
* @param
* @return
*/
-CHTMLContentSinkStream::CHTMLContentSinkStream() {
- mOutput=&cout;
-}
-
-/**
- * Construct a content sink stream.
- * @update gess7/7/98
- * @param
- * @return
- */
-CHTMLContentSinkStream::CHTMLContentSinkStream(ostream& aStream) {
- mOutput=&aStream;
+CHTMLContentSinkStream::CHTMLContentSinkStream(ostream* aStream) {
+ mOutput=(0==aStream) ? &cout : aStream;
}
@@ -132,17 +121,6 @@ CHTMLContentSinkStream::~CHTMLContentSinkStream() {
}
-/**
- *
- * @update gess7/7/98
- * @param
- * @return
- */
-void CHTMLContentSinkStream::SetOutputStream(ostream& aStream) {
- mOutput=&aStream;
-}
-
-
/**
*
* @update gess7/7/98
@@ -171,7 +149,7 @@ void WriteAttributes(const nsIParserNode& aNode,ostream& aStream) {
* @param
* @return
*/
-void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,PRBool aNewline) {
+void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,bool aNewline) {
int i=0;
for(i=0;i
-#include "nsIInputStream.h"
#include "nsIParserFilter.h"
#include "nsIDTDDebug.h"
#include "nshtmlpars.h"
@@ -47,13 +46,10 @@ static const char* kNullURL = "Error: Null URL given";
static const char* kNullFilename= "Error: Null filename given";
static const char* kNullTokenizer = "Error: Unable to construct tokenizer";
static const char* kHTMLTextContentType = "text/html";
+static nsString kUnknownFilename("unknown");
static const int gTransferBufferSize=4096; //size of the buffer used in moving data from iistream
-#define DEBUG_SAVE_SOURCE_DOC 1
-#ifdef DEBUG_SAVE_SOURCE_DOC
-fstream* gTempStream=0;
-#endif
/**
@@ -84,7 +80,7 @@ public:
}
};
-CTokenDeallocator gTokenDeallocator;
+CTokenDeallocator gTokenDeallocator2;
class CDTDDeallocator: public nsDequeFunctor{
public:
@@ -114,6 +110,7 @@ public:
CSharedParserObjects() : mDeallocator(), mDTDDeque(mDeallocator) {
}
+
~CSharedParserObjects() {
}
@@ -141,25 +138,13 @@ CSharedParserObjects gSharedParserObjects;
* @param
* @return
*/
-nsParser::nsParser() :
- mTokenDeque(gTokenDeallocator),
- mSourceType(),
- mTargetType()
-{
+nsParser::nsParser() {
NS_INIT_REFCNT();
mDTDDebug = 0;
mParserFilter = 0;
mObserver = 0;
- mTransferBuffer=0;
mSink=0;
- mCurrentPos=0;
- mMarkPos=0;
- mParseMode=eParseMode_unknown;
- mURL=0;
- mDTD=0;
- mScanner=0;
- mTransferBuffer=new char[gTransferBufferSize+1];
- mAutoDetectStatus=eUnknownDetect;
+ mParserContext=0;
}
@@ -172,20 +157,12 @@ nsParser::nsParser() :
*/
nsParser::~nsParser() {
NS_IF_RELEASE(mObserver);
- NS_IF_RELEASE(mDTDDebug);
- if(mTransferBuffer)
- delete [] mTransferBuffer;
- mTransferBuffer=0;
+// NS_IF_RELEASE(mDTDDebug);
NS_RELEASE(mSink);
- if(mCurrentPos)
- delete mCurrentPos;
- mCurrentPos=0;
- if(mScanner)
- delete mScanner;
- mScanner=0;
-
- NS_IF_RELEASE(mURL);
+ //don't forget to add code here to delete
+ //what may be several contexts...
+ delete mParserContext;
}
@@ -298,7 +275,9 @@ void nsParser::RegisterDTD(nsIDTD* aDTD){
* @return
*/
CScanner* nsParser::GetScanner(void){
- return mScanner;
+ if(mParserContext)
+ return mParserContext->mScanner;
+ return 0;
}
/**
@@ -311,6 +290,7 @@ CScanner* nsParser::GetScanner(void){
eParseMode DetermineParseMode() {
const char* theModeStr= PR_GetEnv("PARSE_MODE");
const char* other="other";
+
eParseMode result=eParseMode_navigator;
if(theModeStr)
@@ -326,25 +306,23 @@ eParseMode DetermineParseMode() {
* @param
* @return
*/
-PRBool FindSuitableDTD( eParseMode aMode,
- nsString& aSourceType,
- nsString& aTargetType,
- nsIDTD*& aDefaultDTD) {
+PRBool FindSuitableDTD( CParserContext& aParserContext) {
//Let's start by tring the defaultDTD, if one exists...
- if(aDefaultDTD && (aDefaultDTD->CanParse(aSourceType,0)))
+ if(aParserContext.mDTD && (aParserContext.mDTD->CanParse(aParserContext.mSourceType,0)))
return PR_TRUE;
PRBool result=PR_FALSE;
+
nsDequeIterator b=gSharedParserObjects.mDTDDeque.Begin();
nsDequeIterator e=gSharedParserObjects.mDTDDeque.End();
while(bCanParse(aSourceType,0);
+ result=theDTD->CanParse(aParserContext.mSourceType,0);
if(result){
- aDefaultDTD=theDTD;
+ aParserContext.mDTD=theDTD;
break;
}
}
@@ -371,22 +349,22 @@ eAutoDetectResult nsParser::AutoDetectContentType(nsString& aBuffer,nsString& aT
// recognize the content in the scanner.
// Somebody should say yes, or we can't continue.
- //This method may change mSourceType and mDTD.
- //It absolutely changes mAutoDetectStatus
+ //This method may change mSourceType and mParserContext->mDTD.
+ //It absolutely changes mParserContext->mAutoDetectStatus
nsDequeIterator b=gSharedParserObjects.mDTDDeque.Begin();
nsDequeIterator e=gSharedParserObjects.mDTDDeque.End();
- mAutoDetectStatus=eUnknownDetect;
- while((bmAutoDetectStatus=eUnknownDetect;
+ while((bmAutoDetectStatus)){
nsIDTD* theDTD=(nsIDTD*)b.GetCurrent();
if(theDTD) {
- mAutoDetectStatus=theDTD->AutoDetectContentType(aBuffer,aType);
+ mParserContext->mAutoDetectStatus=theDTD->AutoDetectContentType(aBuffer,aType);
}
b++;
}
- return mAutoDetectStatus;
+ return mParserContext->mAutoDetectStatus;
}
@@ -401,27 +379,18 @@ eAutoDetectResult nsParser::AutoDetectContentType(nsString& aBuffer,nsString& aT
* @param
* @return
*/
-PRInt32 nsParser::WillBuildModel(const char* aFilename){
+PRInt32 nsParser::WillBuildModel(nsString& aFilename){
- mMajorIteration=-1;
- mMinorIteration=-1;
+ mParserContext->mMajorIteration=-1;
+ mParserContext->mMinorIteration=-1;
- mParseMode=DetermineParseMode();
- if(PR_TRUE==FindSuitableDTD(mParseMode,mSourceType,mTargetType,mDTD)) {
- mDTD->SetParser(this);
- mDTD->SetContentSink(mSink);
- mDTD->WillBuildModel(aFilename);
+ mParserContext->mParseMode=DetermineParseMode();
+ if(PR_TRUE==FindSuitableDTD(*mParserContext)) {
+ mParserContext->mDTD->SetParser(this);
+ mParserContext->mDTD->SetContentSink(mSink);
+ mParserContext->mDTD->WillBuildModel(aFilename);
}
-#ifdef DEBUG_SAVE_SOURCE_DOC
-#if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX))
- /* XXX: IRIX does not support ios::binary */
- gTempStream =new fstream("/tmp/out.html",ios::out);
-#else
- gTempStream = new fstream("c:/temp/out.html",ios::out|ios::binary);
-#endif
-#endif
-
return kNoError;
}
@@ -434,18 +403,10 @@ PRInt32 nsParser::WillBuildModel(const char* aFilename){
PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) {
//One last thing...close any open containers.
PRInt32 result=anErrorCode;
- if(mDTD) {
- result=mDTD->DidBuildModel(anErrorCode);
+ if(mParserContext->mDTD) {
+ result=mParserContext->mDTD->DidBuildModel(anErrorCode);
}
-#ifdef DEBUG_SAVE_SOURCE_DOC
- if(gTempStream) {
- gTempStream->close();
- delete gTempStream;
- gTempStream=0;
- }
-#endif
-
return result;
}
@@ -460,22 +421,21 @@ PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) {
* @param aFilename -- const char* containing file to be parsed.
* @return PR_TRUE if parse succeeded, PR_FALSE otherwise.
*/
-PRBool nsParser::Parse(const char* aFilename){
- NS_PRECONDITION(0!=aFilename,kNullFilename);
+PRInt32 nsParser::Parse(nsString& aFilename){
PRInt32 status=kBadFilename;
if(aFilename) {
//ok, time to create our tokenizer and begin the process
- mTargetType=kHTMLTextContentType;
- mScanner=new CScanner(aFilename,mParseMode);
- if(mScanner) {
- mScanner->Eof();
- if(eValidDetect==AutoDetectContentType(mScanner->GetBuffer(),mSourceType)) {
- WillBuildModel(aFilename);
- status=ResumeParse();
- DidBuildModel(status);
- }
+
+ mParserContext = new CParserContext(new CScanner(aFilename),mParserContext);
+ mParserContext->mScanner->Eof();
+ if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(),
+ mParserContext->mSourceType))
+ {
+ WillBuildModel(aFilename);
+ status=ResumeParse();
+ DidBuildModel(status);
} //if
}
return status;
@@ -488,11 +448,35 @@ PRBool nsParser::Parse(const char* aFilename){
* @return TRUE if all went well -- FALSE otherwise
*/
PRInt32 nsParser::Parse(fstream& aStream){
- PRInt32 result=0;
- return result;
+
+ PRInt32 status=kNoError;
+
+ //ok, time to create our tokenizer and begin the process
+ mParserContext = new CParserContext(new CScanner(kUnknownFilename,aStream,PR_FALSE),mParserContext);
+
+ mParserContext->mScanner->Eof();
+ if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(),
+ mParserContext->mSourceType)) {
+ WillBuildModel(mParserContext->mScanner->GetFilename());
+ status=ResumeParse();
+ DidBuildModel(status);
+ } //if
+
+ return status;
}
+/**
+ *
+ * @update gess7/13/98
+ * @param
+ * @return
+ */
+PRInt32 nsParser::Parse(nsIInputStream* pIStream,nsIStreamObserver* aListener,nsIDTDDebug* aDTDDebug){
+ PRInt32 result=kNoError;
+ return result;
+}
+
/**
* This is the main controlling routine in the parsing process.
* Note that it may get called multiple times for the same scanner,
@@ -512,19 +496,14 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug *
PRInt32 status=kBadURL;
+/* Disable DTD Debug for now...
mDTDDebug = aDTDDebug;
NS_IF_ADDREF(mDTDDebug);
-
- NS_IF_RELEASE(mURL);
- mURL = aURL;
- NS_IF_ADDREF(mURL);
-
- NS_IF_RELEASE(mObserver);
- mObserver = aListener;
- NS_IF_ADDREF(mObserver);
+*/
- if(mURL) {
- mScanner=new CScanner(mParseMode);
+ if(aURL) {
+ nsAutoString theName(aURL->GetSpec());
+ mParserContext=new CParserContext(new CScanner(theName,PR_FALSE),mParserContext,aListener);
status=NS_OK;
}
return status;
@@ -533,6 +512,8 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug *
/**
* Call this method if all you want to do is parse 1 string full of HTML text.
+ * In particular, this method should be called by the DOM when it has an HTML
+ * string to feed to the parser in real-time.
*
* @update gess5/11/98
* @param anHTMLString contains a string-full of real HTML
@@ -542,11 +523,10 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug *
PRInt32 nsParser::Parse(nsString& aSourceBuffer,PRBool appendTokens){
PRInt32 result=kNoError;
- mTargetType=kHTMLTextContentType;
- mScanner=new CScanner();
- mScanner->Append(aSourceBuffer);
- if(eValidDetect==AutoDetectContentType(aSourceBuffer,mSourceType)) {
- WillBuildModel("");
+ mParserContext = new CParserContext(new CScanner(kUnknownFilename),mParserContext,0);
+ mParserContext->mScanner->Append(aSourceBuffer);
+ if(eValidDetect==AutoDetectContentType(aSourceBuffer,mParserContext->mSourceType)) {
+ WillBuildModel(mParserContext->mScanner->GetFilename());
result=ResumeParse();
DidBuildModel(result);
}
@@ -567,12 +547,12 @@ PRInt32 nsParser::Parse(nsString& aSourceBuffer,PRBool appendTokens){
PRInt32 nsParser::ResumeParse() {
PRInt32 result=kNoError;
- mDTD->WillResumeParse();
+ mParserContext->mDTD->WillResumeParse();
if(kNoError==result) {
result=Tokenize();
if(kInterrupted==result)
- mDTD->WillInterruptParse();
- IterateTokens();
+ mParserContext->mDTD->WillInterruptParse();
+ BuildModel();
}
return result;
}
@@ -585,26 +565,28 @@ PRInt32 nsParser::ResumeParse() {
* @param
* @return PR_TRUE if parse succeeded, PR_FALSE otherwise.
*/
-PRInt32 nsParser::IterateTokens() {
- nsDequeIterator e=mTokenDeque.End();
+PRInt32 nsParser::BuildModel() {
+
+ nsDequeIterator e=mParserContext->mTokenDeque.End();
nsDequeIterator theMarkPos(e);
- mMajorIteration++;
- if(!mCurrentPos)
- mCurrentPos=new nsDequeIterator(mTokenDeque.Begin());
+// mParserContext->mMajorIteration++;
+
+ if(!mParserContext->mCurrentPos)
+ mParserContext->mCurrentPos=new nsDequeIterator(mParserContext->mTokenDeque.Begin());
PRInt32 result=kNoError;
- while((kNoError==result) && ((*mCurrentPosGetCurrent();
+ while((kNoError==result) && ((*mParserContext->mCurrentPosmMinorIteration++;
+ CToken* theToken=(CToken*)mParserContext->mCurrentPos->GetCurrent();
- theMarkPos=*mCurrentPos;
- result=mDTD->HandleToken(theToken);
- ++(*mCurrentPos);
+ theMarkPos=*mParserContext->mCurrentPos;
+ result=mParserContext->mDTD->HandleToken(theToken);
+ ++(*mParserContext->mCurrentPos);
}
if(kInterrupted==result)
- *mCurrentPos=theMarkPos;
+ *mParserContext->mCurrentPos=theMarkPos;
return result;
}
@@ -619,17 +601,17 @@ PRInt32 nsParser::IterateTokens() {
* @return error code (should be 0)
*/
PRInt32 nsParser::CollectAttributes(nsCParserNode& aNode,PRInt32 aCount){
- nsDequeIterator end=mTokenDeque.End();
+ nsDequeIterator end=mParserContext->mTokenDeque.End();
int attr=0;
for(attr=0;attrmCurrentPosmCurrentPos));
if(tkn){
if(eToken_attribute==eHTMLTokenTypes(tkn->GetTokenType())){
aNode.AddAttribute(tkn);
}
- else (*mCurrentPos)--;
+ else (*mParserContext->mCurrentPos)--;
}
else return kInterrupted;
}
@@ -649,18 +631,18 @@ PRInt32 nsParser::CollectAttributes(nsCParserNode& aNode,PRInt32 aCount){
*/
PRInt32 nsParser::CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount) {
eHTMLTokenTypes subtype=eToken_attribute;
- nsDequeIterator end=mTokenDeque.End();
+ nsDequeIterator end=mParserContext->mTokenDeque.End();
PRInt32 result=kNoError;
aCount=0;
- while((*mCurrentPos!=end) && (eToken_attribute==subtype)) {
- CToken* tkn=(CToken*)(++(*mCurrentPos));
+ while((*mParserContext->mCurrentPos!=end) && (eToken_attribute==subtype)) {
+ CToken* tkn=(CToken*)(++(*mParserContext->mCurrentPos));
subtype=eHTMLTokenTypes(tkn->GetTokenType());
if(eToken_skippedcontent==subtype) {
aNode.SetSkippedContent(tkn);
aCount++;
}
- else (*mCurrentPos)--;
+ else (*mParserContext->mCurrentPos)--;
}
return result;
}
@@ -710,10 +692,9 @@ nsresult nsParser::OnStartBinding(const char *aSourceType){
if (nsnull != mObserver) {
mObserver->OnStartBinding(aSourceType);
}
- mAutoDetectStatus=eUnknownDetect;
- mDTD=0;
-
- mSourceType=aSourceType;
+ mParserContext->mAutoDetectStatus=eUnknownDetect;
+ mParserContext->mDTD=0;
+ mParserContext->mSourceType=aSourceType;
return kNoError;
}
@@ -732,37 +713,33 @@ nsresult nsParser::OnDataAvailable(nsIInputStream *pIStream, PRInt32 length){
mListener->OnDataAvailable(pIStream, length);
}
*/
- int len=0;
- int offset=0;
- if(eInvalidDetect==mAutoDetectStatus) {
- if(mScanner) {
- mScanner->GetBuffer().Truncate();
+ if(eInvalidDetect==mParserContext->mAutoDetectStatus) {
+ if(mParserContext->mScanner) {
+ mParserContext->mScanner->GetBuffer().Truncate();
}
}
- do {
- PRInt32 err;
- len = pIStream->Read(&err, mTransferBuffer, 0, gTransferBufferSize);
- if(len>0) {
+ int len=1; //init to a non-zero value
+ int err;
+ int offset=0;
- #ifdef DEBUG_SAVE_SOURCE_DOC
- if(gTempStream) {
- gTempStream->write(mTransferBuffer,len);
- }
- #endif
+ while (len > 0) {
+ len = pIStream->Read(&err, mParserContext->mTransferBuffer, 0, mParserContext->eTransferBufferSize);
+ if(len>0) {
- if (mParserFilter)
- mParserFilter->RawBuffer(mTransferBuffer, &len);
- mScanner->Append(mTransferBuffer,len);
+ if(mParserFilter)
+ mParserFilter->RawBuffer(mParserContext->mTransferBuffer, &len);
- if(eUnknownDetect==mAutoDetectStatus) {
- if(eValidDetect==AutoDetectContentType(mScanner->GetBuffer(),mSourceType)) {
- nsresult result=WillBuildModel(mURL->GetSpec());
- } //if
- }
- } //if
- } while (len > 0);
+ mParserContext->mScanner->Append(mParserContext->mTransferBuffer,len);
+
+ if(eUnknownDetect==mParserContext->mAutoDetectStatus) {
+ if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(),mParserContext->mSourceType)) {
+ nsresult result=WillBuildModel(mParserContext->mScanner->GetFilename());
+ } //if
+ }
+ } //if
+ }
nsresult result=ResumeParse();
return result;
@@ -797,7 +774,7 @@ nsresult nsParser::OnStopBinding(PRInt32 status, const nsString& aMsg){
* @return new token or null
*/
PRInt32 nsParser::ConsumeToken(CToken*& aToken) {
- PRInt32 result=mDTD->ConsumeToken(aToken);
+ PRInt32 result=mParserContext->mDTD->ConsumeToken(aToken);
return result;
}
@@ -811,39 +788,11 @@ PRInt32 nsParser::ConsumeToken(CToken*& aToken) {
* @param
* @return TRUE if it's ok to proceed
*/
-PRBool nsParser::WillTokenize(void){
+PRBool nsParser::WillTokenize(){
PRBool result=PR_TRUE;
return result;
}
-/**
- *
- * @update gess 3/25/98
- * @return TRUE if it's ok to proceed
- */
-PRInt32 nsParser::Tokenize(nsString& aSourceBuffer,PRBool appendTokens){
- CToken* theToken=0;
- PRInt32 result=kNoError;
- PRInt32 debugCounter=0; //this can be removed. It's only for debugging...
-
- WillTokenize();
-
- while(kNoError==result) {
- debugCounter++;
- result=ConsumeToken(theToken);
- if(theToken && (kNoError==result)) {
-
-#ifdef VERBOSE_DEBUG
- theToken->DebugDumpToken(cout);
-#endif
- mTokenDeque.Push(theToken);
- }
- }
- if(kEOF==result)
- result=kNoError;
- DidTokenize();
- return result;
-}
/**
* This is the primary control routine. It iteratively
@@ -853,14 +802,14 @@ PRInt32 nsParser::Tokenize(nsString& aSourceBuffer,PRBool appendTokens){
* @update gess 3/25/98
* @return error code
*/
-PRInt32 nsParser::Tokenize(void) {
+PRInt32 nsParser::Tokenize(){
CToken* theToken=0;
PRInt32 result=kNoError;
- PRBool done=(0==mMajorIteration) ? (!WillTokenize()) : PR_FALSE;
+ PRBool done=(0==++mParserContext->mMajorIteration) ? (!WillTokenize()) : PR_FALSE;
while((PR_FALSE==done) && (kNoError==result)) {
- mScanner->Mark();
+ mParserContext->mScanner->Mark();
result=ConsumeToken(theToken);
if(kNoError==result) {
if(theToken) {
@@ -868,14 +817,14 @@ PRInt32 nsParser::Tokenize(void) {
#ifdef VERBOSE_DEBUG
theToken->DebugDumpToken(cout);
#endif
- mTokenDeque.Push(theToken);
+ mParserContext->mTokenDeque.Push(theToken);
}
}
else {
if(theToken)
delete theToken;
- mScanner->RewindToMark();
+ mParserContext->mScanner->RewindToMark();
}
}
if((PR_TRUE==done) && (kInterrupted!=result))
@@ -892,7 +841,7 @@ PRInt32 nsParser::Tokenize(void) {
* @param
* @return TRUE if all went well
*/
-PRBool nsParser::DidTokenize(void) {
+PRBool nsParser::DidTokenize(){
PRBool result=PR_TRUE;
#ifdef VERBOSE_DEBUG
@@ -912,8 +861,8 @@ PRBool nsParser::DidTokenize(void) {
* @return
*/
void nsParser::DebugDumpTokens(ostream& out) {
- nsDequeIterator b=mTokenDeque.Begin();
- nsDequeIterator e=mTokenDeque.End();
+ nsDequeIterator b=mParserContext->mTokenDeque.Begin();
+ nsDequeIterator e=mParserContext->mTokenDeque.End();
CToken* theToken;
while(b!=e) {
@@ -933,8 +882,8 @@ void nsParser::DebugDumpTokens(ostream& out) {
* @return
*/
void nsParser::DebugDumpSource(ostream& out) {
- nsDequeIterator b=mTokenDeque.Begin();
- nsDequeIterator e=mTokenDeque.End();
+ nsDequeIterator b=mParserContext->mTokenDeque.Begin();
+ nsDequeIterator e=mParserContext->mTokenDeque.End();
CToken* theToken;
while(b!=e) {
diff --git a/parser/htmlparser/src/nsParser.h b/parser/htmlparser/src/nsParser.h
index 8fdf384dba1..2f59c0b3abc 100644
--- a/parser/htmlparser/src/nsParser.h
+++ b/parser/htmlparser/src/nsParser.h
@@ -60,7 +60,7 @@
#include "nsParserNode.h"
#include "nsParserTypes.h"
#include "nsIURL.h"
-
+#include "CParserContext.h"
#define NS_PARSER_IID \
{0x2ce606b0, 0xbee6, 0x11d1, \
@@ -69,7 +69,6 @@
class IContentSink;
class nsIHTMLContentSink;
-class nsIURL;
class nsIDTD;
class nsIDTDDebug;
class CScanner;
@@ -119,14 +118,26 @@ friend class CTokenHandler;
virtual CScanner* GetScanner(void);
/**
- * Cause parser to parse input from given URL in given mode
+ * Cause parser to parse input from given URL
* @update gess5/11/98
* @param aURL is a descriptor for source document
* @param aListener is a listener to forward notifications to
* @return TRUE if all went well -- FALSE otherwise
*/
virtual PRInt32 Parse(nsIURL* aURL,
- nsIStreamObserver* aListener, nsIDTDDebug * aDTDDebug = 0);
+ nsIStreamObserver* aListener,
+ nsIDTDDebug* aDTDDebug = 0);
+
+ /**
+ * Cause parser to parse input from given nsIInputStream
+ * @update gess5/11/98
+ * @param pIStream is an nsIInputStream
+ * @param aListener is a listener to forward notifications to
+ * @return TRUE if all went well -- FALSE otherwise
+ */
+ virtual PRInt32 Parse(nsIInputStream* pIStream,
+ nsIStreamObserver* aListener,
+ nsIDTDDebug* aDTDDebug = 0);
/**
* Cause parser to parse input from given file in given mode
@@ -134,7 +145,7 @@ friend class CTokenHandler;
* @param aFilename is a path for file document
* @return TRUE if all went well -- FALSE otherwise
*/
- virtual PRInt32 Parse(const char* aFilename);
+ virtual PRInt32 Parse(nsString& aFilename);
/**
* Cause parser to parse input from given stream
@@ -157,7 +168,7 @@ friend class CTokenHandler;
* @update gess5/11/98
* @return TRUE if all went well, otherwise FALSE
*/
- virtual PRInt32 ResumeParse(void);
+ virtual PRInt32 ResumeParse();
/**
* Causes the parser to scan foward, collecting nearby (sequential)
@@ -208,7 +219,7 @@ protected:
* @param
* @return
*/
- PRInt32 WillBuildModel(const char* aFilename=0);
+ PRInt32 WillBuildModel(nsString& aFilename);
/**
*
@@ -224,7 +235,7 @@ protected:
* @update gess5/11/98
* @return YES if model building went well -- NO otherwise.
*/
- virtual PRInt32 IterateTokens(void);
+ virtual PRInt32 BuildModel(void);
private:
@@ -251,15 +262,9 @@ private:
* @param
* @return TRUE if it's ok to proceed
*/
- PRBool WillTokenize(void);
-
- /**
- *
- * @update gess 3/25/98
- * @return TRUE if it's ok to proceed
- */
- PRInt32 Tokenize(nsString& aSourceBuffer,PRBool appendTokens);
+ PRBool WillTokenize();
+
/**
* This is the primary control routine. It iteratively
* consumes tokens until an error occurs or you run out
@@ -268,7 +273,7 @@ private:
* @update gess 3/25/98
* @return error code
*/
- PRInt32 Tokenize(void);
+ PRInt32 Tokenize();
/**
* This is the tail-end of the code sandwich for the
@@ -279,7 +284,7 @@ private:
* @param
* @return TRUE if all went well
*/
- PRBool DidTokenize(void);
+ PRBool DidTokenize();
/**
* This debug routine is used to cause the tokenizer to
@@ -311,27 +316,42 @@ protected:
// And now, some data members...
//*********************************************
- nsIStreamObserver* mObserver;
- nsIContentSink* mSink;
- nsIParserFilter* mParserFilter;
-
- nsDequeIterator* mCurrentPos;
- nsDequeIterator* mMarkPos;
-
- nsIDTD* mDTD;
- eParseMode mParseMode;
- char* mTransferBuffer;
+ /*****************************************************
+ All of these moved into the parse-context object:
PRInt32 mMajorIteration;
PRInt32 mMinorIteration;
- nsDeque mTokenDeque;
- CScanner* mScanner;
nsIURL* mURL;
- nsIDTDDebug* mDTDDebug;
nsString mSourceType;
nsString mTargetType;
eAutoDetectResult mAutoDetectStatus;
+
+ nsDequeIterator* mCurrentPos;
+ nsDequeIterator* mMarkPos;
+ nsDeque mTokenDeque;
+ CScanner* mScanner;
+ nsIDTD* mDTD;
+
+ eParseMode mParseMode;
+ char* mTransferBuffer;
+ *****************************************************/
+
+ CParserContext* mParserContext;
+
+ /*****************************************************
+ The above fields are moving into parse-context
+ *****************************************************/
+
+
+ nsIStreamObserver* mObserver;
+ nsIContentSink* mSink;
+ nsIParserFilter* mParserFilter;
+
+
+ nsIDTDDebug* mDTDDebug;
+
+
};
diff --git a/parser/htmlparser/src/nsScanner.cpp b/parser/htmlparser/src/nsScanner.cpp
index 6e38c26f645..7a9118a1fbc 100644
--- a/parser/htmlparser/src/nsScanner.cpp
+++ b/parser/htmlparser/src/nsScanner.cpp
@@ -19,10 +19,8 @@
//#define __INCREMENTAL 1
#include "nsScanner.h"
-#include "nsIURL.h"
#include "nsDebug.h"
-const char* gURLRef=0;
const char* kBadHTMLText="Oops...
You just tried to read a non-existent document:
";
#ifdef __INCREMENTAL
@@ -31,89 +29,55 @@ const int kBufsize=1;
const int kBufsize=64;
#endif
+
/**
- * Use this constructor if you want an incremental (callback)
- * based input stream.
+ * Use this constructor if you want i/o to be based on an
+ * incremental netstream. If you pass a null filename, you
+ * can still provide data to the scanner via append.
*
* @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
+ * @param aFilename --
* @return
*/
-CScanner::CScanner(eParseMode aMode) : mBuffer("") {
+CScanner::CScanner(nsString& aFilename,PRBool aCreateStream) :
+ mBuffer(""), mFilename(aFilename)
+{
mOffset=0;
mMarkPos=-1;
mTotalRead=0;
- mParseMode=aMode;
- mNetStream=0;
+ mOwnsStream=aCreateStream;
mFileStream=0;
- mIncremental=PR_TRUE;
- mOwnsStream=PR_TRUE;
+ if(aCreateStream) {
+ char buffer[513];
+ aFilename.ToCString(buffer,sizeof(buffer)-1);
+ #if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX))
+ /* XXX: IRIX does not support ios::binary */
+ mFileStream=new fstream(buffer,ios::in);
+ #else
+ mFileStream=new fstream(buffer,ios::in|ios::binary);
+ #endif
+ } //if
}
/**
- * Use this constructor if you want i/o to be file based.
+ * Use this constructor if you want i/o to be stream based.
*
* @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
+ * @param aStream --
+ * @param assumeOwnership --
+ * @param aFilename --
* @return
*/
-CScanner::CScanner(const char* aFilename,eParseMode aMode) : mBuffer("") {
- NS_ASSERTION(0!=aFilename,"Error: Null filename!");
+CScanner::CScanner(nsString& aFilename,fstream& aStream,PRBool assumeOwnership) :
+ mBuffer(""), mFilename(aFilename)
+{
mOffset=0;
mMarkPos=-1;
mTotalRead=0;
- mParseMode=aMode;
- mNetStream=0;
- mIncremental=PR_FALSE;
- mOwnsStream=PR_TRUE;
-#if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX))
- /* XXX: IRIX does not support ios::binary */
- mFileStream=new fstream(aFilename,ios::in);
-#else
- mFileStream=new fstream(aFilename,ios::in|ios::binary);
-#endif
-}
-
-/**
- * Use this constructor if you want i/o to be file based.
- *
- * @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
- * @return
- */
-CScanner::CScanner(fstream& aStream,eParseMode aMode) : mBuffer("") {
- mOffset=0;
- mMarkPos=-1;
- mTotalRead=0;
- mParseMode=aMode;
- mNetStream=0;
- mIncremental=PR_FALSE;
- mOwnsStream=PR_FALSE;
+ mOwnsStream=assumeOwnership;
mFileStream=&aStream;
}
-/**
- * Use this constructor if you want i/o to be based on a
- * non-incremental netstream.
- *
- * @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
- * @return
- */
-CScanner::CScanner(nsIURL* aURL,eParseMode aMode) : mBuffer("") {
- NS_ASSERTION(0!=aURL,"Error: Null URL!");
- mOffset=0;
- mMarkPos=-1;
- mTotalRead=0;
- mParseMode=aMode;
- mFileStream=0;
- PRInt32 error=0;
- mIncremental=PR_FALSE;
- mNetStream=aURL->Open(&error);
- gURLRef=aURL->GetSpec();
- mOwnsStream=PR_FALSE;
-}
-
/**
* default destructor
@@ -128,13 +92,7 @@ CScanner::~CScanner() {
if(mOwnsStream)
delete mFileStream;
}
- else if(mNetStream) {
- mNetStream->Close();
- mNetStream->Release();
- }
mFileStream=0;
- mNetStream=0;
- gURLRef=0;
}
/**
@@ -200,34 +158,9 @@ void _PreCompressBuffer(nsString& aBuffer,PRInt32& anOffset,PRInt32& aMarkPos){
}
-/**
- * This method should only be called by the parser when
- * we're doing incremental i/o over the net.
- *
- * @update gess 5/12/98
- * @param aBuffer contains next blob of i/o data
- * @param aSize contains size of buffer
- * @return 0 if all went well, otherwise error code.
- */
-PRInt32 CScanner::IncrementalAppend(const char* aBuffer,PRInt32 aSize){
- NS_ASSERTION(((!mFileStream) && (!mNetStream)),"Error: Should only be called during incremental net i/o!");
-
- PRInt32 result=0;
- if((!mFileStream) && (!mNetStream)) {
-
- _PreCompressBuffer(mBuffer,mOffset,mMarkPos);
-
- //now that the buffer is (possibly) shortened, let's append the new data.
- if(0read(buf,kBufsize);
numread=mFileStream->gcount();
}
- else if(mNetStream) {
- numread=mNetStream->Read(&anError,buf,0,kBufsize);
- if(1==anError)
- anError=kEOF;
- }
mOffset=mBuffer.Length();
if((0=mBuffer.Length()) {
- if(!mIncremental)
- theError=FillBuffer();
- else return kInterrupted;
+ theError=FillBuffer();
}
if(0==theError)
@@ -451,21 +378,21 @@ PRInt32 CScanner::SkipPast(nsString& aValidSet){
* @return error code
*/
PRInt32 CScanner::ReadWhile(nsString& aString,nsString& aValidSet,PRBool addTerminal){
- PRUnichar ch=0;
+ PRUnichar theChar=0;
PRInt32 result=kNoError;
PRInt32 wrPos=0;
while(kNoError==result) {
- result=GetChar(ch);
+ result=GetChar(theChar);
if(kNoError==result) {
- PRInt32 pos=aValidSet.Find(ch);
+ PRInt32 pos=aValidSet.Find(theChar);
if(kNotFound==pos) {
if(addTerminal)
- aString+=ch;
- else PutBack(ch);
+ aString+=theChar;
+ else PutBack(theChar);
break;
}
- else aString+=ch;
+ else aString+=theChar;
}
}
return result;
@@ -535,6 +462,18 @@ nsString& CScanner::GetBuffer(void) {
return mBuffer;
}
+/**
+ * Retrieve the name of the file that the scanner is reading from.
+ * In some cases, it's just a given name, because the scanner isn't
+ * really reading from a file.
+ *
+ * @update gess 5/12/98
+ * @return
+ */
+nsString& CScanner::GetFilename(void) {
+ return mFilename;
+}
+
/**
* Conduct self test. Actually, selftesting for this class
* occurs in the parser selftest.
diff --git a/parser/htmlparser/src/nsScanner.h b/parser/htmlparser/src/nsScanner.h
index d03b9bfb2f8..627a7f27fe1 100644
--- a/parser/htmlparser/src/nsScanner.h
+++ b/parser/htmlparser/src/nsScanner.h
@@ -35,43 +35,21 @@
#include "nsString.h"
#include "nsParserTypes.h"
#include "prtypes.h"
-#include "nsIInputStream.h"
#include
-class nsIURL;
-//class ifstream;
class CScanner {
public:
/**
- * Use this constructor if you want an incremental (callback)
- * based input stream.
+ * Use this constructor if you want i/o to be based on
+ * a file (therefore a stream) or just data you provide via Append().
*
* @update gess 5/12/98
* @param aMode represents the parser mode (nav, other)
* @return
*/
- CScanner(eParseMode aMode=eParseMode_navigator);
-
- /**
- * Use this constructor if you want i/o to be based on a
- * non-incremental netstream.
- *
- * @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
- * @return
- */
- CScanner(nsIURL* aURL,eParseMode aMode=eParseMode_navigator);
-
- /**
- * Use this constructor if you want i/o to be file based.
- *
- * @update gess 5/12/98
- * @param aMode represents the parser mode (nav, other)
- * @return
- */
- CScanner(const char* aFilename,eParseMode aMode=eParseMode_navigator);
+ CScanner(nsString& aFilename,PRBool aCreateStream=PR_TRUE);
/**
* Use this constructor if you want i/o to be stream based.
@@ -80,7 +58,7 @@ class CScanner {
* @param aMode represents the parser mode (nav, other)
* @return
*/
- CScanner(fstream& aStream,eParseMode aMode=eParseMode_navigator);
+ CScanner(nsString& aFilename,fstream& aStream,PRBool assumeOwnership=PR_TRUE);
~CScanner();
@@ -241,16 +219,17 @@ class CScanner {
* @param
* @return
*/
- PRInt32 IncrementalAppend(const char* aBuffer,PRInt32 aSize);
+ nsString& GetBuffer(void);
/**
- *
+ * Retrieve the name of the file that the scanner is reading from.
+ * In some cases, it's just a given name, because the scanner isn't
+ * really reading from a file.
*
* @update gess 5/12/98
- * @param
* @return
*/
- nsString& GetBuffer(void);
+ nsString& GetFilename(void);
static void SelfTest();
@@ -268,13 +247,11 @@ class CScanner {
fstream* mFileStream;
- nsIInputStream* mNetStream;
nsString mBuffer;
+ nsString mFilename;
PRInt32 mOffset;
PRInt32 mMarkPos;
PRInt32 mTotalRead;
- eParseMode mParseMode;
- PRBool mIncremental;
PRBool mOwnsStream;
};
diff --git a/parser/htmlparser/src/nsValidDTD.cpp b/parser/htmlparser/src/nsValidDTD.cpp
index 979a78bd12b..95874180e58 100644
--- a/parser/htmlparser/src/nsValidDTD.cpp
+++ b/parser/htmlparser/src/nsValidDTD.cpp
@@ -190,7 +190,7 @@ eAutoDetectResult CValidDTD::AutoDetectContentType(nsString& aBuffer,nsString& a
* @param
* @return
*/
-PRInt32 CValidDTD::WillBuildModel(const char* aFilename){
+PRInt32 CValidDTD::WillBuildModel(nsString& aFilename){
PRInt32 result=0;
return result;
}
diff --git a/parser/htmlparser/src/nsValidDTD.h b/parser/htmlparser/src/nsValidDTD.h
index c0798370091..24bfc89a38a 100644
--- a/parser/htmlparser/src/nsValidDTD.h
+++ b/parser/htmlparser/src/nsValidDTD.h
@@ -108,7 +108,7 @@ class CValidDTD : public nsIDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aFilename);
/**
*
diff --git a/parser/htmlparser/src/nsWellFormedDTD.cpp b/parser/htmlparser/src/nsWellFormedDTD.cpp
index d092ed0e9ec..8137c3299b9 100644
--- a/parser/htmlparser/src/nsWellFormedDTD.cpp
+++ b/parser/htmlparser/src/nsWellFormedDTD.cpp
@@ -177,7 +177,7 @@ eAutoDetectResult CWellFormedDTD::AutoDetectContentType(nsString& aBuffer,nsStri
* @param
* @return
*/
-PRInt32 CWellFormedDTD::WillBuildModel(const char* aFilename){
+PRInt32 CWellFormedDTD::WillBuildModel(nsString& aFilename){
PRInt32 result=0;
return result;
}
diff --git a/parser/htmlparser/src/nsWellFormedDTD.h b/parser/htmlparser/src/nsWellFormedDTD.h
index 6add8b9a5b5..47155413f68 100644
--- a/parser/htmlparser/src/nsWellFormedDTD.h
+++ b/parser/htmlparser/src/nsWellFormedDTD.h
@@ -97,7 +97,7 @@ class CWellFormedDTD : public nsIDTD {
* @param
* @return
*/
- virtual PRInt32 WillBuildModel(const char* aFilename=0);
+ virtual PRInt32 WillBuildModel(nsString& aFilename);
/**
*