Checking in the first stab at error propagation from the expat parser to the content sink. The flow of control is as follows. The tokenizer creates an error token (CErrorToken) when an error occurs in expat and pushes it onto the token dequeue. The DTD forwards the contents of the token to the content sink, which creates content objects to show the error.
This commit is contained in:
Родитель
e8e368f977
Коммит
c2cc5de10d
|
@ -369,19 +369,20 @@ CToken* CTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag)
|
|||
else {
|
||||
//mTotals[aType-1]++;
|
||||
switch(aType){
|
||||
case eToken_start: result=new CStartToken(aTag); break;
|
||||
case eToken_end: result=new CEndToken(aTag); break;
|
||||
case eToken_comment: result=new CCommentToken(); break;
|
||||
case eToken_attribute: result=new CAttributeToken(); break;
|
||||
case eToken_entity: result=new CEntityToken(); break;
|
||||
case eToken_whitespace: result=new CWhitespaceToken(); break;
|
||||
case eToken_newline: result=new CNewlineToken(); break;
|
||||
case eToken_text: result=new CTextToken(theEmpty); break;
|
||||
case eToken_script: result=new CScriptToken(); break;
|
||||
case eToken_style: result=new CStyleToken(); break;
|
||||
case eToken_skippedcontent: result=new CSkippedContentToken(theEmpty); break;
|
||||
case eToken_instruction:result=new CInstructionToken(); break;
|
||||
case eToken_cdatasection:result=new CCDATASectionToken(); break;
|
||||
case eToken_start: result=new CStartToken(aTag); break;
|
||||
case eToken_end: result=new CEndToken(aTag); break;
|
||||
case eToken_comment: result=new CCommentToken(); break;
|
||||
case eToken_attribute: result=new CAttributeToken(); break;
|
||||
case eToken_entity: result=new CEntityToken(); break;
|
||||
case eToken_whitespace: result=new CWhitespaceToken(); break;
|
||||
case eToken_newline: result=new CNewlineToken(); break;
|
||||
case eToken_text: result=new CTextToken(theEmpty); break;
|
||||
case eToken_script: result=new CScriptToken(); break;
|
||||
case eToken_style: result=new CStyleToken(); break;
|
||||
case eToken_skippedcontent: result=new CSkippedContentToken(theEmpty); break;
|
||||
case eToken_instruction: result=new CInstructionToken(); break;
|
||||
case eToken_cdatasection: result=new CCDATASectionToken(); break;
|
||||
case eToken_error: result=new CErrorToken(); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -24,13 +24,14 @@
|
|||
*/
|
||||
|
||||
#include "nsExpatTokenizer.h"
|
||||
//#include "nsParser.h"
|
||||
#include "nsScanner.h"
|
||||
#include "nsDTDUtils.h"
|
||||
#include "nsParser.h"
|
||||
#include "nsParserError.h"
|
||||
// #include "nsParser.h"
|
||||
#include "nsIParser.h"
|
||||
|
||||
/************************************************************************
|
||||
|
||||
/************************************************************************
|
||||
And now for the main class -- nsExpatTokenizer...
|
||||
************************************************************************/
|
||||
|
||||
|
@ -39,6 +40,9 @@ static NS_DEFINE_IID(kITokenizerIID, NS_ITOKENIZER_IID);
|
|||
static NS_DEFINE_IID(kHTMLTokenizerIID, NS_HTMLTOKENIZER_IID);
|
||||
static NS_DEFINE_IID(kClassIID, NS_EXPATTOKENIZER_IID);
|
||||
|
||||
static CTokenRecycler* gTokenRecycler=0;
|
||||
static nsDeque* gTokenDeque=0;
|
||||
|
||||
/**
|
||||
* This method gets called as part of our COM-like interfaces.
|
||||
* Its purpose is to create an interface to parser object
|
||||
|
@ -148,14 +152,38 @@ nsExpatTokenizer::~nsExpatTokenizer(){
|
|||
Here begins the real working methods for the tokenizer.
|
||||
*******************************************************************/
|
||||
|
||||
/* Called immediately after an error has occurred in expat. Creates
|
||||
an error token and pushes it onto the token queue. The DTD
|
||||
will process this token and either try to correct the error or
|
||||
propagate the error to the content sink.
|
||||
|
||||
Creates an nsParserError o
|
||||
*/
|
||||
void nsExpatTokenizer::PushXMLErrorToken(void)
|
||||
{
|
||||
CErrorToken* token= (CErrorToken *) gTokenRecycler->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
|
||||
nsParserError *error = new nsParserError;
|
||||
|
||||
error->code = XML_GetErrorCode(mExpatParser);
|
||||
error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
|
||||
error->colNumber = XML_GetCurrentColumnNumber(mExpatParser);
|
||||
// XXX Does the copy constructor of nsString free the passed in char *?
|
||||
error->description = XML_ErrorString(error->code);
|
||||
// XXX Not setting a source buffer and error offset for now
|
||||
error->offset = 0;
|
||||
error->sourceBuffer = "";
|
||||
|
||||
token->SetError(error);
|
||||
|
||||
CToken* theToken = (CToken* )token;
|
||||
AddToken(theToken, NS_OK, *gTokenDeque);
|
||||
}
|
||||
|
||||
nsresult nsExpatTokenizer::ParseXMLBuffer(const char *buffer){
|
||||
nsresult result=NS_OK;
|
||||
if (mExpatParser) {
|
||||
if (!XML_Parse(mExpatParser, buffer, strlen(buffer), PR_FALSE)) {
|
||||
// XXX Add code here to implement error propagation to the
|
||||
// content sink.
|
||||
NS_NOTYETIMPLEMENTED("Error: nsExpatTokenizer::ParseXMLBuffer(): Error propogation from expat not yet implemented.");
|
||||
result = NS_ERROR_FAILURE;
|
||||
if (!XML_Parse(mExpatParser, buffer, strlen(buffer), PR_FALSE)) {
|
||||
PushXMLErrorToken();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -164,8 +192,6 @@ nsresult nsExpatTokenizer::ParseXMLBuffer(const char *buffer){
|
|||
return result;
|
||||
}
|
||||
|
||||
static CTokenRecycler* gTokenRecycler=0;
|
||||
static nsDeque* gTokenDeque=0;
|
||||
|
||||
/**
|
||||
* This method repeatedly called by the tokenizer.
|
||||
|
|
|
@ -70,6 +70,8 @@ protected:
|
|||
*/
|
||||
void SetupExpatCallbacks(void);
|
||||
|
||||
void PushXMLErrorToken(void);
|
||||
|
||||
/* The callback handlers that get called from the expat parser */
|
||||
static void HandleStartElement(void *userData, const XML_Char *name, const XML_Char **atts);
|
||||
static void HandleEndElement(void *userData, const XML_Char *name);
|
||||
|
|
|
@ -1656,3 +1656,30 @@ PRInt32 CInstructionToken::GetTokenType(void){
|
|||
return eToken_instruction;
|
||||
}
|
||||
|
||||
|
||||
CErrorToken::CErrorToken(nsParserError *aError) : CHTMLToken(eHTMLTag_unknown)
|
||||
{
|
||||
mError = aError;
|
||||
}
|
||||
|
||||
CErrorToken::~CErrorToken()
|
||||
{
|
||||
delete mError;
|
||||
}
|
||||
|
||||
PRInt32 CErrorToken::GetTokenType(void){
|
||||
return eToken_error;
|
||||
}
|
||||
|
||||
const char* CErrorToken::GetClassName(void){
|
||||
return "error";
|
||||
}
|
||||
|
||||
void CErrorToken::SetError(nsParserError *aError) {
|
||||
mError = aError;
|
||||
}
|
||||
|
||||
const nsParserError * CErrorToken::GetError(void)
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "nsToken.h"
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsParserError.h"
|
||||
#include <iostream.h>
|
||||
|
||||
class nsScanner;
|
||||
|
@ -51,10 +52,10 @@ class nsScanner;
|
|||
|
||||
enum eHTMLTokenTypes {
|
||||
eToken_unknown=0,
|
||||
eToken_start=1, eToken_end, eToken_comment, eToken_entity,
|
||||
eToken_whitespace, eToken_newline, eToken_text, eToken_attribute,
|
||||
eToken_script, eToken_style, eToken_skippedcontent, eToken_instruction,
|
||||
eToken_cdatasection,
|
||||
eToken_start=1, eToken_end, eToken_comment, eToken_entity,
|
||||
eToken_whitespace, eToken_newline, eToken_text, eToken_attribute,
|
||||
eToken_script, eToken_style, eToken_skippedcontent, eToken_instruction,
|
||||
eToken_cdatasection, eToken_error,
|
||||
eToken_last //make sure this stays the last token...
|
||||
};
|
||||
|
||||
|
@ -359,6 +360,23 @@ class CInstructionToken: public CHTMLToken {
|
|||
virtual PRInt32 GetTokenType(void);
|
||||
};
|
||||
|
||||
class CErrorToken : public CHTMLToken {
|
||||
public:
|
||||
CErrorToken(nsParserError* aError=0);
|
||||
~CErrorToken();
|
||||
virtual const char* GetClassName(void);
|
||||
virtual PRInt32 GetTokenType(void);
|
||||
|
||||
void SetError(nsParserError* aError); // CErrorToken takes ownership of aError
|
||||
|
||||
// The nsParserError object returned by GetError is still owned by CErrorToken.
|
||||
// DO NOT use the delete operator on it. Should we change this so that a copy
|
||||
// of nsParserError is returned which needs to be destroyed by the consumer?
|
||||
const nsParserError* GetError(void);
|
||||
|
||||
protected:
|
||||
nsParserError* mError;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -493,6 +493,13 @@ NS_IMETHODIMP CWellFormedDTD::HandleToken(CToken* aToken,nsIParser* aParser) {
|
|||
result=mSink->CloseContainer(theNode);
|
||||
break;
|
||||
|
||||
case eToken_error:
|
||||
{
|
||||
// Propagate the error onto the content sink.
|
||||
CErrorToken *errTok = (CErrorToken *)aToken;
|
||||
result = mSink->NotifyError(errTok->GetError());
|
||||
}
|
||||
break;
|
||||
case eToken_style:
|
||||
case eToken_skippedcontent:
|
||||
default:
|
||||
|
|
|
@ -369,19 +369,20 @@ CToken* CTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag)
|
|||
else {
|
||||
//mTotals[aType-1]++;
|
||||
switch(aType){
|
||||
case eToken_start: result=new CStartToken(aTag); break;
|
||||
case eToken_end: result=new CEndToken(aTag); break;
|
||||
case eToken_comment: result=new CCommentToken(); break;
|
||||
case eToken_attribute: result=new CAttributeToken(); break;
|
||||
case eToken_entity: result=new CEntityToken(); break;
|
||||
case eToken_whitespace: result=new CWhitespaceToken(); break;
|
||||
case eToken_newline: result=new CNewlineToken(); break;
|
||||
case eToken_text: result=new CTextToken(theEmpty); break;
|
||||
case eToken_script: result=new CScriptToken(); break;
|
||||
case eToken_style: result=new CStyleToken(); break;
|
||||
case eToken_skippedcontent: result=new CSkippedContentToken(theEmpty); break;
|
||||
case eToken_instruction:result=new CInstructionToken(); break;
|
||||
case eToken_cdatasection:result=new CCDATASectionToken(); break;
|
||||
case eToken_start: result=new CStartToken(aTag); break;
|
||||
case eToken_end: result=new CEndToken(aTag); break;
|
||||
case eToken_comment: result=new CCommentToken(); break;
|
||||
case eToken_attribute: result=new CAttributeToken(); break;
|
||||
case eToken_entity: result=new CEntityToken(); break;
|
||||
case eToken_whitespace: result=new CWhitespaceToken(); break;
|
||||
case eToken_newline: result=new CNewlineToken(); break;
|
||||
case eToken_text: result=new CTextToken(theEmpty); break;
|
||||
case eToken_script: result=new CScriptToken(); break;
|
||||
case eToken_style: result=new CStyleToken(); break;
|
||||
case eToken_skippedcontent: result=new CSkippedContentToken(theEmpty); break;
|
||||
case eToken_instruction: result=new CInstructionToken(); break;
|
||||
case eToken_cdatasection: result=new CCDATASectionToken(); break;
|
||||
case eToken_error: result=new CErrorToken(); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -24,13 +24,14 @@
|
|||
*/
|
||||
|
||||
#include "nsExpatTokenizer.h"
|
||||
//#include "nsParser.h"
|
||||
#include "nsScanner.h"
|
||||
#include "nsDTDUtils.h"
|
||||
#include "nsParser.h"
|
||||
#include "nsParserError.h"
|
||||
// #include "nsParser.h"
|
||||
#include "nsIParser.h"
|
||||
|
||||
/************************************************************************
|
||||
|
||||
/************************************************************************
|
||||
And now for the main class -- nsExpatTokenizer...
|
||||
************************************************************************/
|
||||
|
||||
|
@ -39,6 +40,9 @@ static NS_DEFINE_IID(kITokenizerIID, NS_ITOKENIZER_IID);
|
|||
static NS_DEFINE_IID(kHTMLTokenizerIID, NS_HTMLTOKENIZER_IID);
|
||||
static NS_DEFINE_IID(kClassIID, NS_EXPATTOKENIZER_IID);
|
||||
|
||||
static CTokenRecycler* gTokenRecycler=0;
|
||||
static nsDeque* gTokenDeque=0;
|
||||
|
||||
/**
|
||||
* This method gets called as part of our COM-like interfaces.
|
||||
* Its purpose is to create an interface to parser object
|
||||
|
@ -148,14 +152,38 @@ nsExpatTokenizer::~nsExpatTokenizer(){
|
|||
Here begins the real working methods for the tokenizer.
|
||||
*******************************************************************/
|
||||
|
||||
/* Called immediately after an error has occurred in expat. Creates
|
||||
an error token and pushes it onto the token queue. The DTD
|
||||
will process this token and either try to correct the error or
|
||||
propagate the error to the content sink.
|
||||
|
||||
Creates an nsParserError o
|
||||
*/
|
||||
void nsExpatTokenizer::PushXMLErrorToken(void)
|
||||
{
|
||||
CErrorToken* token= (CErrorToken *) gTokenRecycler->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
|
||||
nsParserError *error = new nsParserError;
|
||||
|
||||
error->code = XML_GetErrorCode(mExpatParser);
|
||||
error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
|
||||
error->colNumber = XML_GetCurrentColumnNumber(mExpatParser);
|
||||
// XXX Does the copy constructor of nsString free the passed in char *?
|
||||
error->description = XML_ErrorString(error->code);
|
||||
// XXX Not setting a source buffer and error offset for now
|
||||
error->offset = 0;
|
||||
error->sourceBuffer = "";
|
||||
|
||||
token->SetError(error);
|
||||
|
||||
CToken* theToken = (CToken* )token;
|
||||
AddToken(theToken, NS_OK, *gTokenDeque);
|
||||
}
|
||||
|
||||
nsresult nsExpatTokenizer::ParseXMLBuffer(const char *buffer){
|
||||
nsresult result=NS_OK;
|
||||
if (mExpatParser) {
|
||||
if (!XML_Parse(mExpatParser, buffer, strlen(buffer), PR_FALSE)) {
|
||||
// XXX Add code here to implement error propagation to the
|
||||
// content sink.
|
||||
NS_NOTYETIMPLEMENTED("Error: nsExpatTokenizer::ParseXMLBuffer(): Error propogation from expat not yet implemented.");
|
||||
result = NS_ERROR_FAILURE;
|
||||
if (!XML_Parse(mExpatParser, buffer, strlen(buffer), PR_FALSE)) {
|
||||
PushXMLErrorToken();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -164,8 +192,6 @@ nsresult nsExpatTokenizer::ParseXMLBuffer(const char *buffer){
|
|||
return result;
|
||||
}
|
||||
|
||||
static CTokenRecycler* gTokenRecycler=0;
|
||||
static nsDeque* gTokenDeque=0;
|
||||
|
||||
/**
|
||||
* This method repeatedly called by the tokenizer.
|
||||
|
|
|
@ -70,6 +70,8 @@ protected:
|
|||
*/
|
||||
void SetupExpatCallbacks(void);
|
||||
|
||||
void PushXMLErrorToken(void);
|
||||
|
||||
/* The callback handlers that get called from the expat parser */
|
||||
static void HandleStartElement(void *userData, const XML_Char *name, const XML_Char **atts);
|
||||
static void HandleEndElement(void *userData, const XML_Char *name);
|
||||
|
|
|
@ -1656,3 +1656,30 @@ PRInt32 CInstructionToken::GetTokenType(void){
|
|||
return eToken_instruction;
|
||||
}
|
||||
|
||||
|
||||
CErrorToken::CErrorToken(nsParserError *aError) : CHTMLToken(eHTMLTag_unknown)
|
||||
{
|
||||
mError = aError;
|
||||
}
|
||||
|
||||
CErrorToken::~CErrorToken()
|
||||
{
|
||||
delete mError;
|
||||
}
|
||||
|
||||
PRInt32 CErrorToken::GetTokenType(void){
|
||||
return eToken_error;
|
||||
}
|
||||
|
||||
const char* CErrorToken::GetClassName(void){
|
||||
return "error";
|
||||
}
|
||||
|
||||
void CErrorToken::SetError(nsParserError *aError) {
|
||||
mError = aError;
|
||||
}
|
||||
|
||||
const nsParserError * CErrorToken::GetError(void)
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "nsToken.h"
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsParserError.h"
|
||||
#include <iostream.h>
|
||||
|
||||
class nsScanner;
|
||||
|
@ -51,10 +52,10 @@ class nsScanner;
|
|||
|
||||
enum eHTMLTokenTypes {
|
||||
eToken_unknown=0,
|
||||
eToken_start=1, eToken_end, eToken_comment, eToken_entity,
|
||||
eToken_whitespace, eToken_newline, eToken_text, eToken_attribute,
|
||||
eToken_script, eToken_style, eToken_skippedcontent, eToken_instruction,
|
||||
eToken_cdatasection,
|
||||
eToken_start=1, eToken_end, eToken_comment, eToken_entity,
|
||||
eToken_whitespace, eToken_newline, eToken_text, eToken_attribute,
|
||||
eToken_script, eToken_style, eToken_skippedcontent, eToken_instruction,
|
||||
eToken_cdatasection, eToken_error,
|
||||
eToken_last //make sure this stays the last token...
|
||||
};
|
||||
|
||||
|
@ -359,6 +360,23 @@ class CInstructionToken: public CHTMLToken {
|
|||
virtual PRInt32 GetTokenType(void);
|
||||
};
|
||||
|
||||
class CErrorToken : public CHTMLToken {
|
||||
public:
|
||||
CErrorToken(nsParserError* aError=0);
|
||||
~CErrorToken();
|
||||
virtual const char* GetClassName(void);
|
||||
virtual PRInt32 GetTokenType(void);
|
||||
|
||||
void SetError(nsParserError* aError); // CErrorToken takes ownership of aError
|
||||
|
||||
// The nsParserError object returned by GetError is still owned by CErrorToken.
|
||||
// DO NOT use the delete operator on it. Should we change this so that a copy
|
||||
// of nsParserError is returned which needs to be destroyed by the consumer?
|
||||
const nsParserError* GetError(void);
|
||||
|
||||
protected:
|
||||
nsParserError* mError;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -493,6 +493,13 @@ NS_IMETHODIMP CWellFormedDTD::HandleToken(CToken* aToken,nsIParser* aParser) {
|
|||
result=mSink->CloseContainer(theNode);
|
||||
break;
|
||||
|
||||
case eToken_error:
|
||||
{
|
||||
// Propagate the error onto the content sink.
|
||||
CErrorToken *errTok = (CErrorToken *)aToken;
|
||||
result = mSink->NotifyError(errTok->GetError());
|
||||
}
|
||||
break;
|
||||
case eToken_style:
|
||||
case eToken_skippedcontent:
|
||||
default:
|
||||
|
|
Загрузка…
Ссылка в новой задаче