diff --git a/mozilla/htmlparser/src/nsExpatTokenizer.cpp b/mozilla/htmlparser/src/nsExpatTokenizer.cpp index 973c98d87f4..bf303f40da8 100644 --- a/mozilla/htmlparser/src/nsExpatTokenizer.cpp +++ b/mozilla/htmlparser/src/nsExpatTokenizer.cpp @@ -30,6 +30,7 @@ // #include "nsParser.h" #include "nsIParser.h" #include "prlog.h" +#include /************************************************************************ @@ -154,22 +155,69 @@ 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. -*/ -void nsExpatTokenizer::PushXMLErrorToken(void) + +static void SetErrorContextInfo(nsParserError* aError, PRUint32 aByteIndex, + const char* aSourceBuffer, PRUint32 aLength) +{ + /* Figure out the substring inside aSourceBuffer that contains the line on which the error + occurred. Copy the line into error->sourceLine */ + PR_ASSERT(aByteIndex > 0 && aByteIndex < aLength); + char* start = (char* ) &aSourceBuffer[aByteIndex]; /* Will try to find the start of the line */ + char* end = (char* ) &aSourceBuffer[aByteIndex]; /* Will try to find the end of the line */ + PRUint32 startIndex = aByteIndex; /* Track the position of the 'start' pointer into the buffer */ + PRUint32 endIndex = aByteIndex; /* Track the position of the 'end' pointer into the buffer */ + PRBool reachedStart; + PRBool reachedEnd; + + /* Use start to find the first new line before the error position and + end to find the first new line after the error position */ + reachedStart = ('\n' == *start || '\r' == *start || startIndex <= 0); + reachedEnd = ('\n' == *end || '\r' == *end || endIndex >= aLength); + while (!reachedStart || !reachedEnd) { + if (!reachedStart) { + start--; + startIndex--; + } + if (!reachedEnd) { + end++; + endIndex++; + } + reachedStart = ('\n' == *start || '\r' == *start || startIndex <= 0); + reachedEnd = ('\n' == *end || '\r' == *end || endIndex >= aLength); + } + + if (startIndex == endIndex) { + /* Special case if the error is on a line where the only character is a newline */ + aError->sourceLine.Append(""); + } + else { + PR_ASSERT(endIndex - startIndex >= 2); + + /* At this point, the substring starting at (startIndex + 1) and ending at (endIndex - 1), + is the line on which the error occurred. Copy that substring into the error structure. */ + char* tempLine = new char[endIndex - startIndex]; + strncpy(tempLine, &aSourceBuffer[startIndex + 1], (endIndex - 1) - startIndex); + tempLine[endIndex - startIndex - 1] = '\0'; + aError->sourceLine.Append(tempLine); + delete [] tempLine; + } +} + +/* + * Called immediately after an error has occurred in expat. Creates + * an error token and pushes it onto the token queue. + * + */ +void nsExpatTokenizer::PushXMLErrorToken(const char *aBuffer, PRUint32 aLength) { 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 = ""; + error->colNumber = XML_GetCurrentColumnNumber(mExpatParser); + error->description = XML_ErrorString(error->code); + SetErrorContextInfo(error, (PRUint32) XML_GetCurrentByteIndex(mExpatParser), aBuffer, aLength); token->SetError(error); @@ -182,7 +230,7 @@ nsresult nsExpatTokenizer::ParseXMLBuffer(const char *aBuffer, PRUint32 aLength) if (mExpatParser) { PR_ASSERT(aLength == strlen(aBuffer)); if (!XML_Parse(mExpatParser, aBuffer, aLength, PR_FALSE)) { - PushXMLErrorToken(); + PushXMLErrorToken(aBuffer, aLength); } } else { diff --git a/mozilla/htmlparser/src/nsExpatTokenizer.h b/mozilla/htmlparser/src/nsExpatTokenizer.h index 428b6026468..e9d8d67b8a3 100644 --- a/mozilla/htmlparser/src/nsExpatTokenizer.h +++ b/mozilla/htmlparser/src/nsExpatTokenizer.h @@ -70,7 +70,7 @@ protected: */ void SetupExpatCallbacks(void); - void PushXMLErrorToken(void); + void PushXMLErrorToken(const char *aBuffer, PRUint32 aLength); /* The callback handlers that get called from the expat parser */ static void HandleStartElement(void *userData, const XML_Char *name, const XML_Char **atts); diff --git a/mozilla/htmlparser/src/nsHTMLTags.cpp b/mozilla/htmlparser/src/nsHTMLTags.cpp index bfb9ab3b219..504bbe0ca53 100644 --- a/mozilla/htmlparser/src/nsHTMLTags.cpp +++ b/mozilla/htmlparser/src/nsHTMLTags.cpp @@ -31,10 +31,10 @@ static char* tagTable[] = { "kbd", "keygen", "label", "layer", "legend", "li", "link", "listing", "map", "menu", "meta", "multicol", "nobr", "noembed", "noframes", "nolayer", "noscript", "object", "ol", "optgroup", "option", "p", "param", - "plaintext", "pre", "q", "s", "samp", "script", "select", "server", - "small", "sound", "spacer", "span", "strike", "strong", "style", "sub", - "sup", "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "title", - "tr", "tt", "u", "ul", "var", "wbr", "xmp" + "parsererror", "plaintext", "pre", "q", "s", "samp", "script", "select", + "server", "small", "sound", "sourcetext", "spacer", "span", "strike", + "strong", "style", "sub", "sup", "table", "tbody", "td", "textarea", + "tfoot", "th", "thead", "title", "tr", "tt", "u", "ul", "var", "wbr", "xmp" }; nsHTMLTag NS_TagToEnum(const char* aTagName) { diff --git a/mozilla/htmlparser/src/nsHTMLTags.h b/mozilla/htmlparser/src/nsHTMLTags.h index a2209558c97..6e5e4195b44 100644 --- a/mozilla/htmlparser/src/nsHTMLTags.h +++ b/mozilla/htmlparser/src/nsHTMLTags.h @@ -46,24 +46,25 @@ enum nsHTMLTag { eHTMLTag_nobr=66, eHTMLTag_noembed=67, eHTMLTag_noframes=68, eHTMLTag_nolayer=69, eHTMLTag_noscript=70, eHTMLTag_object=71, eHTMLTag_ol=72, eHTMLTag_optgroup=73, eHTMLTag_option=74, eHTMLTag_p=75, - eHTMLTag_param=76, eHTMLTag_plaintext=77, eHTMLTag_pre=78, eHTMLTag_q=79, - eHTMLTag_s=80, eHTMLTag_samp=81, eHTMLTag_script=82, eHTMLTag_select=83, - eHTMLTag_server=84, eHTMLTag_small=85, eHTMLTag_sound=86, - eHTMLTag_spacer=87, eHTMLTag_span=88, eHTMLTag_strike=89, - eHTMLTag_strong=90, eHTMLTag_style=91, eHTMLTag_sub=92, eHTMLTag_sup=93, - eHTMLTag_table=94, eHTMLTag_tbody=95, eHTMLTag_td=96, eHTMLTag_textarea=97, - eHTMLTag_tfoot=98, eHTMLTag_th=99, eHTMLTag_thead=100, eHTMLTag_title=101, - eHTMLTag_tr=102, eHTMLTag_tt=103, eHTMLTag_u=104, eHTMLTag_ul=105, - eHTMLTag_var=106, eHTMLTag_wbr=107, eHTMLTag_xmp=108, + eHTMLTag_param=76, eHTMLTag_parsererror=77, eHTMLTag_plaintext=78, + eHTMLTag_pre=79, eHTMLTag_q=80, eHTMLTag_s=81, eHTMLTag_samp=82, + eHTMLTag_script=83, eHTMLTag_select=84, eHTMLTag_server=85, + eHTMLTag_small=86, eHTMLTag_sound=87, eHTMLTag_sourcetext=88, + eHTMLTag_spacer=89, eHTMLTag_span=90, eHTMLTag_strike=91, + eHTMLTag_strong=92, eHTMLTag_style=93, eHTMLTag_sub=94, eHTMLTag_sup=95, + eHTMLTag_table=96, eHTMLTag_tbody=97, eHTMLTag_td=98, eHTMLTag_textarea=99, + eHTMLTag_tfoot=100, eHTMLTag_th=101, eHTMLTag_thead=102, + eHTMLTag_title=103, eHTMLTag_tr=104, eHTMLTag_tt=105, eHTMLTag_u=106, + eHTMLTag_ul=107, eHTMLTag_var=108, eHTMLTag_wbr=109, eHTMLTag_xmp=110, /* The remaining enums are not for tags */ - eHTMLTag_text=109, eHTMLTag_whitespace=110, eHTMLTag_newline=111, - eHTMLTag_comment=112, eHTMLTag_entity=113, eHTMLTag_userdefined=114, - eHTMLTag_secret_h1style=115, eHTMLTag_secret_h2style=116, - eHTMLTag_secret_h3style=117, eHTMLTag_secret_h4style=118, - eHTMLTag_secret_h5style=119, eHTMLTag_secret_h6style=120 + eHTMLTag_text=111, eHTMLTag_whitespace=112, eHTMLTag_newline=113, + eHTMLTag_comment=114, eHTMLTag_entity=115, eHTMLTag_userdefined=116, + eHTMLTag_secret_h1style=117, eHTMLTag_secret_h2style=118, + eHTMLTag_secret_h3style=119, eHTMLTag_secret_h4style=120, + eHTMLTag_secret_h5style=121, eHTMLTag_secret_h6style=122 }; -#define NS_HTML_TAG_MAX 108 +#define NS_HTML_TAG_MAX 110 extern NS_HTMLPARS nsHTMLTag NS_TagToEnum(const char* aTag); extern NS_HTMLPARS const char* NS_EnumToTag(nsHTMLTag aEnum); diff --git a/mozilla/htmlparser/src/nsParserError.h b/mozilla/htmlparser/src/nsParserError.h index f2cab09e790..7925f0dd623 100644 --- a/mozilla/htmlparser/src/nsParserError.h +++ b/mozilla/htmlparser/src/nsParserError.h @@ -35,9 +35,8 @@ typedef struct _nsParserError { PRInt32 code; PRInt32 lineNumber; PRInt32 colNumber; - nsString description; - PRInt32 offset; - nsString sourceBuffer; + nsString description; + nsString sourceLine; } nsParserError; #endif diff --git a/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp b/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp index 973c98d87f4..bf303f40da8 100644 --- a/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp +++ b/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp @@ -30,6 +30,7 @@ // #include "nsParser.h" #include "nsIParser.h" #include "prlog.h" +#include /************************************************************************ @@ -154,22 +155,69 @@ 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. -*/ -void nsExpatTokenizer::PushXMLErrorToken(void) + +static void SetErrorContextInfo(nsParserError* aError, PRUint32 aByteIndex, + const char* aSourceBuffer, PRUint32 aLength) +{ + /* Figure out the substring inside aSourceBuffer that contains the line on which the error + occurred. Copy the line into error->sourceLine */ + PR_ASSERT(aByteIndex > 0 && aByteIndex < aLength); + char* start = (char* ) &aSourceBuffer[aByteIndex]; /* Will try to find the start of the line */ + char* end = (char* ) &aSourceBuffer[aByteIndex]; /* Will try to find the end of the line */ + PRUint32 startIndex = aByteIndex; /* Track the position of the 'start' pointer into the buffer */ + PRUint32 endIndex = aByteIndex; /* Track the position of the 'end' pointer into the buffer */ + PRBool reachedStart; + PRBool reachedEnd; + + /* Use start to find the first new line before the error position and + end to find the first new line after the error position */ + reachedStart = ('\n' == *start || '\r' == *start || startIndex <= 0); + reachedEnd = ('\n' == *end || '\r' == *end || endIndex >= aLength); + while (!reachedStart || !reachedEnd) { + if (!reachedStart) { + start--; + startIndex--; + } + if (!reachedEnd) { + end++; + endIndex++; + } + reachedStart = ('\n' == *start || '\r' == *start || startIndex <= 0); + reachedEnd = ('\n' == *end || '\r' == *end || endIndex >= aLength); + } + + if (startIndex == endIndex) { + /* Special case if the error is on a line where the only character is a newline */ + aError->sourceLine.Append(""); + } + else { + PR_ASSERT(endIndex - startIndex >= 2); + + /* At this point, the substring starting at (startIndex + 1) and ending at (endIndex - 1), + is the line on which the error occurred. Copy that substring into the error structure. */ + char* tempLine = new char[endIndex - startIndex]; + strncpy(tempLine, &aSourceBuffer[startIndex + 1], (endIndex - 1) - startIndex); + tempLine[endIndex - startIndex - 1] = '\0'; + aError->sourceLine.Append(tempLine); + delete [] tempLine; + } +} + +/* + * Called immediately after an error has occurred in expat. Creates + * an error token and pushes it onto the token queue. + * + */ +void nsExpatTokenizer::PushXMLErrorToken(const char *aBuffer, PRUint32 aLength) { 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 = ""; + error->colNumber = XML_GetCurrentColumnNumber(mExpatParser); + error->description = XML_ErrorString(error->code); + SetErrorContextInfo(error, (PRUint32) XML_GetCurrentByteIndex(mExpatParser), aBuffer, aLength); token->SetError(error); @@ -182,7 +230,7 @@ nsresult nsExpatTokenizer::ParseXMLBuffer(const char *aBuffer, PRUint32 aLength) if (mExpatParser) { PR_ASSERT(aLength == strlen(aBuffer)); if (!XML_Parse(mExpatParser, aBuffer, aLength, PR_FALSE)) { - PushXMLErrorToken(); + PushXMLErrorToken(aBuffer, aLength); } } else { diff --git a/mozilla/parser/htmlparser/src/nsExpatTokenizer.h b/mozilla/parser/htmlparser/src/nsExpatTokenizer.h index 428b6026468..e9d8d67b8a3 100644 --- a/mozilla/parser/htmlparser/src/nsExpatTokenizer.h +++ b/mozilla/parser/htmlparser/src/nsExpatTokenizer.h @@ -70,7 +70,7 @@ protected: */ void SetupExpatCallbacks(void); - void PushXMLErrorToken(void); + void PushXMLErrorToken(const char *aBuffer, PRUint32 aLength); /* The callback handlers that get called from the expat parser */ static void HandleStartElement(void *userData, const XML_Char *name, const XML_Char **atts); diff --git a/mozilla/parser/htmlparser/src/nsHTMLTags.cpp b/mozilla/parser/htmlparser/src/nsHTMLTags.cpp index bfb9ab3b219..504bbe0ca53 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLTags.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLTags.cpp @@ -31,10 +31,10 @@ static char* tagTable[] = { "kbd", "keygen", "label", "layer", "legend", "li", "link", "listing", "map", "menu", "meta", "multicol", "nobr", "noembed", "noframes", "nolayer", "noscript", "object", "ol", "optgroup", "option", "p", "param", - "plaintext", "pre", "q", "s", "samp", "script", "select", "server", - "small", "sound", "spacer", "span", "strike", "strong", "style", "sub", - "sup", "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "title", - "tr", "tt", "u", "ul", "var", "wbr", "xmp" + "parsererror", "plaintext", "pre", "q", "s", "samp", "script", "select", + "server", "small", "sound", "sourcetext", "spacer", "span", "strike", + "strong", "style", "sub", "sup", "table", "tbody", "td", "textarea", + "tfoot", "th", "thead", "title", "tr", "tt", "u", "ul", "var", "wbr", "xmp" }; nsHTMLTag NS_TagToEnum(const char* aTagName) { diff --git a/mozilla/parser/htmlparser/src/nsHTMLTags.h b/mozilla/parser/htmlparser/src/nsHTMLTags.h index a2209558c97..6e5e4195b44 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLTags.h +++ b/mozilla/parser/htmlparser/src/nsHTMLTags.h @@ -46,24 +46,25 @@ enum nsHTMLTag { eHTMLTag_nobr=66, eHTMLTag_noembed=67, eHTMLTag_noframes=68, eHTMLTag_nolayer=69, eHTMLTag_noscript=70, eHTMLTag_object=71, eHTMLTag_ol=72, eHTMLTag_optgroup=73, eHTMLTag_option=74, eHTMLTag_p=75, - eHTMLTag_param=76, eHTMLTag_plaintext=77, eHTMLTag_pre=78, eHTMLTag_q=79, - eHTMLTag_s=80, eHTMLTag_samp=81, eHTMLTag_script=82, eHTMLTag_select=83, - eHTMLTag_server=84, eHTMLTag_small=85, eHTMLTag_sound=86, - eHTMLTag_spacer=87, eHTMLTag_span=88, eHTMLTag_strike=89, - eHTMLTag_strong=90, eHTMLTag_style=91, eHTMLTag_sub=92, eHTMLTag_sup=93, - eHTMLTag_table=94, eHTMLTag_tbody=95, eHTMLTag_td=96, eHTMLTag_textarea=97, - eHTMLTag_tfoot=98, eHTMLTag_th=99, eHTMLTag_thead=100, eHTMLTag_title=101, - eHTMLTag_tr=102, eHTMLTag_tt=103, eHTMLTag_u=104, eHTMLTag_ul=105, - eHTMLTag_var=106, eHTMLTag_wbr=107, eHTMLTag_xmp=108, + eHTMLTag_param=76, eHTMLTag_parsererror=77, eHTMLTag_plaintext=78, + eHTMLTag_pre=79, eHTMLTag_q=80, eHTMLTag_s=81, eHTMLTag_samp=82, + eHTMLTag_script=83, eHTMLTag_select=84, eHTMLTag_server=85, + eHTMLTag_small=86, eHTMLTag_sound=87, eHTMLTag_sourcetext=88, + eHTMLTag_spacer=89, eHTMLTag_span=90, eHTMLTag_strike=91, + eHTMLTag_strong=92, eHTMLTag_style=93, eHTMLTag_sub=94, eHTMLTag_sup=95, + eHTMLTag_table=96, eHTMLTag_tbody=97, eHTMLTag_td=98, eHTMLTag_textarea=99, + eHTMLTag_tfoot=100, eHTMLTag_th=101, eHTMLTag_thead=102, + eHTMLTag_title=103, eHTMLTag_tr=104, eHTMLTag_tt=105, eHTMLTag_u=106, + eHTMLTag_ul=107, eHTMLTag_var=108, eHTMLTag_wbr=109, eHTMLTag_xmp=110, /* The remaining enums are not for tags */ - eHTMLTag_text=109, eHTMLTag_whitespace=110, eHTMLTag_newline=111, - eHTMLTag_comment=112, eHTMLTag_entity=113, eHTMLTag_userdefined=114, - eHTMLTag_secret_h1style=115, eHTMLTag_secret_h2style=116, - eHTMLTag_secret_h3style=117, eHTMLTag_secret_h4style=118, - eHTMLTag_secret_h5style=119, eHTMLTag_secret_h6style=120 + eHTMLTag_text=111, eHTMLTag_whitespace=112, eHTMLTag_newline=113, + eHTMLTag_comment=114, eHTMLTag_entity=115, eHTMLTag_userdefined=116, + eHTMLTag_secret_h1style=117, eHTMLTag_secret_h2style=118, + eHTMLTag_secret_h3style=119, eHTMLTag_secret_h4style=120, + eHTMLTag_secret_h5style=121, eHTMLTag_secret_h6style=122 }; -#define NS_HTML_TAG_MAX 108 +#define NS_HTML_TAG_MAX 110 extern NS_HTMLPARS nsHTMLTag NS_TagToEnum(const char* aTag); extern NS_HTMLPARS const char* NS_EnumToTag(nsHTMLTag aEnum); diff --git a/mozilla/parser/htmlparser/src/nsParserError.h b/mozilla/parser/htmlparser/src/nsParserError.h index f2cab09e790..7925f0dd623 100644 --- a/mozilla/parser/htmlparser/src/nsParserError.h +++ b/mozilla/parser/htmlparser/src/nsParserError.h @@ -35,9 +35,8 @@ typedef struct _nsParserError { PRInt32 code; PRInt32 lineNumber; PRInt32 colNumber; - nsString description; - PRInt32 offset; - nsString sourceBuffer; + nsString description; + nsString sourceLine; } nsParserError; #endif