Merge three changesets from Zack Weinberg <zweinberg@mozilla.com>.

This commit is contained in:
L. David Baron 2008-09-10 07:20:57 -07:00
commit 36fa7ce69d
3 changed files with 1392 additions and 1394 deletions

File diff suppressed because it is too large Load Diff

View File

@ -61,14 +61,14 @@
#undef COLLECT_WHITESPACE
static const PRUnichar CSS_ESCAPE = PRUnichar('\\');
const PRUint8 nsCSSScanner::IS_DIGIT = 0x01;
const PRUint8 nsCSSScanner::IS_HEX_DIGIT = 0x02;
const PRUint8 nsCSSScanner::START_IDENT = 0x04;
const PRUint8 nsCSSScanner::IS_IDENT = 0x08;
const PRUint8 nsCSSScanner::IS_WHITESPACE = 0x10;
static const PRUint8 IS_DIGIT = 0x01;
static const PRUint8 IS_HEX_DIGIT = 0x02;
static const PRUint8 START_IDENT = 0x04;
static const PRUint8 IS_IDENT = 0x08;
static const PRUint8 IS_WHITESPACE = 0x10;
static PRBool gLexTableSetup = PR_FALSE;
PRUint8 nsCSSScanner::gLexTable[256];
static PRUint8 gLexTable[256];
#ifdef CSS_REPORT_PARSE_ERRORS
static PRBool gReportErrors = PR_TRUE;
@ -77,9 +77,8 @@ static nsIFactory *gScriptErrorFactory;
static nsIStringBundle *gStringBundle;
#endif
/* static */
void
nsCSSScanner::BuildLexTable()
static void
BuildLexTable()
{
gLexTableSetup = PR_TRUE;
@ -109,6 +108,40 @@ nsCSSScanner::BuildLexTable()
}
}
static inline PRBool
IsIdentStart(PRInt32 aChar)
{
return aChar >= 0 &&
(aChar >= 256 || (gLexTable[aChar] & START_IDENT) != 0);
}
static inline PRBool
StartsIdent(PRInt32 aFirstChar, PRInt32 aSecondChar)
{
return IsIdentStart(aFirstChar) ||
(aFirstChar == '-' && IsIdentStart(aSecondChar));
}
static inline PRBool
IsWhitespace(PRInt32 ch) {
return PRUint32(ch) < 256 && (gLexTable[ch] & IS_WHITESPACE) != 0;
}
static inline PRBool
IsDigit(PRInt32 ch) {
return PRUint32(ch) < 256 && (gLexTable[ch] & IS_DIGIT) != 0;
}
static inline PRBool
IsHexDigit(PRInt32 ch) {
return PRUint32(ch) < 256 && (gLexTable[ch] & IS_HEX_DIGIT) != 0;
}
static inline PRBool
IsIdent(PRInt32 ch) {
return ch >= 0 && (ch >= 256 || (gLexTable[ch] & IS_IDENT) != 0);
}
nsCSSToken::nsCSSToken()
{
mType = eCSSToken_Symbol;
@ -189,6 +222,7 @@ nsCSSToken::AppendToString(nsString& aBuffer)
nsCSSScanner::nsCSSScanner()
: mInputStream(nsnull)
, mReadPointer(nsnull)
, mLowLevelError(NS_OK)
#ifdef MOZ_SVG
, mSVGMode(PR_FALSE)
#endif
@ -217,17 +251,33 @@ nsCSSScanner::~nsCSSScanner()
}
}
nsresult
nsCSSScanner::GetLowLevelError()
{
return mLowLevelError;
}
void
nsCSSScanner::SetLowLevelError(nsresult aErrorCode)
{
NS_ASSERTION(aErrorCode != NS_OK, "SetLowLevelError() used to clear error");
NS_ASSERTION(mLowLevelError == NS_OK, "there is already a low-level error");
mLowLevelError = aErrorCode;
}
#ifdef CSS_REPORT_PARSE_ERRORS
#define CSS_ERRORS_PREF "layout.css.report_errors"
PR_STATIC_CALLBACK(int) CSSErrorsPrefChanged(const char *aPref, void *aClosure)
PR_STATIC_CALLBACK(int)
CSSErrorsPrefChanged(const char *aPref, void *aClosure)
{
gReportErrors = nsContentUtils::GetBoolPref(CSS_ERRORS_PREF, PR_TRUE);
return NS_OK;
}
#endif
/* static */ PRBool nsCSSScanner::InitGlobals()
/* static */ PRBool
nsCSSScanner::InitGlobals()
{
#ifdef CSS_REPORT_PARSE_ERRORS
if (gConsoleService && gScriptErrorFactory)
@ -247,7 +297,8 @@ PR_STATIC_CALLBACK(int) CSSErrorsPrefChanged(const char *aPref, void *aClosure)
return PR_TRUE;
}
/* static */ void nsCSSScanner::ReleaseGlobals()
/* static */ void
nsCSSScanner::ReleaseGlobals()
{
#ifdef CSS_REPORT_PARSE_ERRORS
nsContentUtils::UnregisterPrefCallback(CSS_ERRORS_PREF, CSSErrorsPrefChanged, nsnull);
@ -257,9 +308,10 @@ PR_STATIC_CALLBACK(int) CSSErrorsPrefChanged(const char *aPref, void *aClosure)
#endif
}
void nsCSSScanner::Init(nsIUnicharInputStream* aInput,
const PRUnichar * aBuffer, PRUint32 aCount,
nsIURI* aURI, PRUint32 aLineNumber)
void
nsCSSScanner::Init(nsIUnicharInputStream* aInput,
const PRUnichar * aBuffer, PRUint32 aCount,
nsIURI* aURI, PRUint32 aLineNumber)
{
NS_PRECONDITION(!mInputStream, "Should not have an existing input stream!");
NS_PRECONDITION(!mReadPointer, "Should not have an existing input buffer!");
@ -296,6 +348,7 @@ void nsCSSScanner::Init(nsIUnicharInputStream* aInput,
// Reset variables that we use to keep track of our progress through the input
mOffset = 0;
mPushbackCount = 0;
mLowLevelError = NS_OK;
#ifdef CSS_REPORT_PARSE_ERRORS
mColNumber = 0;
@ -308,7 +361,8 @@ void nsCSSScanner::Init(nsIUnicharInputStream* aInput,
#define REPORT_UNEXPECTED_EOF(lf_) \
ReportUnexpectedEOF(#lf_)
void nsCSSScanner::AddToError(const nsSubstring& aErrorText)
void
nsCSSScanner::AddToError(const nsSubstring& aErrorText)
{
if (mError.IsEmpty()) {
mErrorLineNumber = mLineNumber;
@ -319,12 +373,14 @@ void nsCSSScanner::AddToError(const nsSubstring& aErrorText)
}
}
void nsCSSScanner::ClearError()
void
nsCSSScanner::ClearError()
{
mError.Truncate();
}
void nsCSSScanner::OutputError()
void
nsCSSScanner::OutputError()
{
if (mError.IsEmpty()) return;
@ -349,7 +405,8 @@ void nsCSSScanner::OutputError()
ClearError();
}
static PRBool InitStringBundle()
static PRBool
InitStringBundle()
{
if (gStringBundle)
return PR_TRUE;
@ -383,9 +440,10 @@ void nsCSSScanner::ReportUnexpected(const char* aMessage)
AddToError(str);
}
void nsCSSScanner::ReportUnexpectedParams(const char* aMessage,
const PRUnichar **aParams,
PRUint32 aParamsLength)
void
nsCSSScanner::ReportUnexpectedParams(const char* aMessage,
const PRUnichar **aParams,
PRUint32 aParamsLength)
{
NS_PRECONDITION(aParamsLength > 0, "use the non-params version");
ENSURE_STRINGBUNDLE;
@ -398,7 +456,8 @@ void nsCSSScanner::ReportUnexpectedParams(const char* aMessage,
}
// aLookingFor is a plain string, not a format string
void nsCSSScanner::ReportUnexpectedEOF(const char* aLookingFor)
void
nsCSSScanner::ReportUnexpectedEOF(const char* aLookingFor)
{
ENSURE_STRINGBUNDLE;
@ -417,7 +476,8 @@ void nsCSSScanner::ReportUnexpectedEOF(const char* aLookingFor)
}
// aLookingFor is a single character
void nsCSSScanner::ReportUnexpectedEOF(PRUnichar aLookingFor)
void
nsCSSScanner::ReportUnexpectedEOF(PRUnichar aLookingFor)
{
ENSURE_STRINGBUNDLE;
@ -434,8 +494,9 @@ void nsCSSScanner::ReportUnexpectedEOF(PRUnichar aLookingFor)
// aMessage must take 1 parameter (for the string representation of the
// unexpected token)
void nsCSSScanner::ReportUnexpectedToken(nsCSSToken& tok,
const char *aMessage)
void
nsCSSScanner::ReportUnexpectedToken(nsCSSToken& tok,
const char *aMessage)
{
ENSURE_STRINGBUNDLE;
@ -450,10 +511,11 @@ void nsCSSScanner::ReportUnexpectedToken(nsCSSToken& tok,
}
// aParams's first entry must be null, and we'll fill in the token
void nsCSSScanner::ReportUnexpectedTokenParams(nsCSSToken& tok,
const char* aMessage,
const PRUnichar **aParams,
PRUint32 aParamsLength)
void
nsCSSScanner::ReportUnexpectedTokenParams(nsCSSToken& tok,
const char* aMessage,
const PRUnichar **aParams,
PRUint32 aParamsLength)
{
NS_PRECONDITION(aParamsLength > 1, "use the non-params version");
NS_PRECONDITION(aParams[0] == nsnull, "first param should be empty");
@ -473,7 +535,8 @@ void nsCSSScanner::ReportUnexpectedTokenParams(nsCSSToken& tok,
#endif // CSS_REPORT_PARSE_ERRORS
void nsCSSScanner::Close()
void
nsCSSScanner::Close()
{
mInputStream = nsnull;
mReadPointer = nsnull;
@ -495,39 +558,43 @@ void nsCSSScanner::Close()
#define TAB_STOP_WIDTH 8
#endif
PRBool nsCSSScanner::EnsureData(nsresult& aErrorCode)
PRBool
nsCSSScanner::EnsureData()
{
if (mOffset < mCount)
return PR_TRUE;
if (mInputStream) {
mOffset = 0;
aErrorCode = mInputStream->Read(mBuffer, CSS_BUFFER_SIZE, &mCount);
if (NS_FAILED(aErrorCode) || mCount == 0) {
mCount = 0;
return PR_FALSE;
}
return PR_TRUE;
if (!mInputStream)
return PR_FALSE;
mOffset = 0;
nsresult rv = mInputStream->Read(mBuffer, CSS_BUFFER_SIZE, &mCount);
if (NS_FAILED(rv)) {
mCount = 0;
SetLowLevelError(rv);
return PR_FALSE;
}
return PR_FALSE;
return mCount > 0;
}
// Returns -1 on error or eof
PRInt32 nsCSSScanner::Read(nsresult& aErrorCode)
PRInt32
nsCSSScanner::Read()
{
PRInt32 rv;
if (0 < mPushbackCount) {
rv = PRInt32(mPushback[--mPushbackCount]);
} else {
if (mOffset == mCount && !EnsureData(aErrorCode)) {
if (mOffset == mCount && !EnsureData()) {
return -1;
}
rv = PRInt32(mReadPointer[mOffset++]);
// There are four types of newlines in CSS: "\r", "\n", "\r\n", and "\f".
// To simplify dealing with newlines, they are all normalized to "\n" here
if (rv == '\r') {
if (EnsureData(aErrorCode) && mReadPointer[mOffset] == '\n') {
if (EnsureData() && mReadPointer[mOffset] == '\n') {
mOffset++;
}
rv = '\n';
@ -555,10 +622,11 @@ PRInt32 nsCSSScanner::Read(nsresult& aErrorCode)
return rv;
}
PRInt32 nsCSSScanner::Peek(nsresult& aErrorCode)
PRInt32
nsCSSScanner::Peek()
{
if (0 == mPushbackCount) {
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) {
return -1;
}
@ -569,7 +637,8 @@ PRInt32 nsCSSScanner::Peek(nsresult& aErrorCode)
return PRInt32(mPushback[mPushbackCount - 1]);
}
void nsCSSScanner::Pushback(PRUnichar aChar)
void
nsCSSScanner::Pushback(PRUnichar aChar)
{
if (mPushbackCount == mPushbackSize) { // grow buffer
PRUnichar* newPushback = new PRUnichar[mPushbackSize + 4];
@ -586,9 +655,10 @@ void nsCSSScanner::Pushback(PRUnichar aChar)
mPushback[mPushbackCount++] = aChar;
}
PRBool nsCSSScanner::LookAhead(nsresult& aErrorCode, PRUnichar aChar)
PRBool
nsCSSScanner::LookAhead(PRUnichar aChar)
{
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) {
return PR_FALSE;
}
@ -599,11 +669,12 @@ PRBool nsCSSScanner::LookAhead(nsresult& aErrorCode, PRUnichar aChar)
return PR_FALSE;
}
PRBool nsCSSScanner::EatWhiteSpace(nsresult& aErrorCode)
PRBool
nsCSSScanner::EatWhiteSpace()
{
PRBool eaten = PR_FALSE;
for (;;) {
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) {
break;
}
@ -617,9 +688,10 @@ PRBool nsCSSScanner::EatWhiteSpace(nsresult& aErrorCode)
return eaten;
}
PRBool nsCSSScanner::EatNewline(nsresult& aErrorCode)
PRBool
nsCSSScanner::EatNewline()
{
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) {
return PR_FALSE;
}
@ -632,67 +704,68 @@ PRBool nsCSSScanner::EatNewline(nsresult& aErrorCode)
return eaten;
}
PRBool nsCSSScanner::Next(nsresult& aErrorCode, nsCSSToken& aToken)
PRBool
nsCSSScanner::Next(nsCSSToken& aToken)
{
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) {
return PR_FALSE;
}
// IDENT
if (StartsIdent(ch, Peek(aErrorCode)))
return ParseIdent(aErrorCode, ch, aToken);
if (StartsIdent(ch, Peek()))
return ParseIdent(ch, aToken);
// AT_KEYWORD
if (ch == '@') {
PRInt32 nextChar = Read(aErrorCode);
PRInt32 nextChar = Read();
if (nextChar >= 0) {
PRInt32 followingChar = Peek(aErrorCode);
PRInt32 followingChar = Peek();
Pushback(nextChar);
if (StartsIdent(nextChar, followingChar))
return ParseAtKeyword(aErrorCode, ch, aToken);
return ParseAtKeyword(ch, aToken);
}
}
// NUMBER or DIM
if ((ch == '.') || (ch == '+') || (ch == '-')) {
PRInt32 nextChar = Peek(aErrorCode);
PRInt32 nextChar = Peek();
if (IsDigit(nextChar)) {
return ParseNumber(aErrorCode, ch, aToken);
return ParseNumber(ch, aToken);
}
else if (('.' == nextChar) && ('.' != ch)) {
nextChar = Read(aErrorCode);
PRInt32 followingChar = Peek(aErrorCode);
nextChar = Read();
PRInt32 followingChar = Peek();
Pushback(nextChar);
if (IsDigit(followingChar))
return ParseNumber(aErrorCode, ch, aToken);
return ParseNumber(ch, aToken);
}
}
if (IsDigit(ch)) {
return ParseNumber(aErrorCode, ch, aToken);
return ParseNumber(ch, aToken);
}
// ID
if (ch == '#') {
return ParseRef(aErrorCode, ch, aToken);
return ParseRef(ch, aToken);
}
// STRING
if ((ch == '"') || (ch == '\'')) {
return ParseString(aErrorCode, ch, aToken);
return ParseString(ch, aToken);
}
// WS
if (IsWhitespace(ch)) {
aToken.mType = eCSSToken_WhiteSpace;
aToken.mIdent.Assign(PRUnichar(ch));
(void) EatWhiteSpace(aErrorCode);
(void) EatWhiteSpace();
return PR_TRUE;
}
if (ch == '/') {
PRInt32 nextChar = Peek(aErrorCode);
PRInt32 nextChar = Peek();
if (nextChar == '*') {
(void) Read(aErrorCode);
(void) Read();
#if 0
// If we change our storage data structures such that comments are
// stored (for Editor), we should reenable this code, condition it
@ -701,15 +774,15 @@ PRBool nsCSSScanner::Next(nsresult& aErrorCode, nsCSSToken& aToken)
aToken.mIdent.SetCapacity(2);
aToken.mIdent.Assign(PRUnichar(ch));
aToken.mIdent.Append(PRUnichar(nextChar));
return ParseCComment(aErrorCode, aToken);
return ParseCComment(aToken);
#endif
return SkipCComment(aErrorCode) && Next(aErrorCode, aToken);
return SkipCComment() && Next(aToken);
}
}
if (ch == '<') { // consume HTML comment tags
if (LookAhead(aErrorCode, '!')) {
if (LookAhead(aErrorCode, '-')) {
if (LookAhead(aErrorCode, '-')) {
if (LookAhead('!')) {
if (LookAhead('-')) {
if (LookAhead('-')) {
aToken.mType = eCSSToken_HTMLComment;
aToken.mIdent.AssignLiteral("<!--");
return PR_TRUE;
@ -720,8 +793,8 @@ PRBool nsCSSScanner::Next(nsresult& aErrorCode, nsCSSToken& aToken)
}
}
if (ch == '-') { // check for HTML comment end
if (LookAhead(aErrorCode, '-')) {
if (LookAhead(aErrorCode, '>')) {
if (LookAhead('-')) {
if (LookAhead('>')) {
aToken.mType = eCSSToken_HTMLComment;
aToken.mIdent.AssignLiteral("-->");
return PR_TRUE;
@ -733,7 +806,7 @@ PRBool nsCSSScanner::Next(nsresult& aErrorCode, nsCSSToken& aToken)
// INCLUDES ("~=") and DASHMATCH ("|=")
if (( ch == '|' ) || ( ch == '~' ) || ( ch == '^' ) ||
( ch == '$' ) || ( ch == '*' )) {
PRInt32 nextChar = Read(aErrorCode);
PRInt32 nextChar = Read();
if ( nextChar == '=' ) {
if (ch == '~') {
aToken.mType = eCSSToken_Includes;
@ -760,29 +833,30 @@ PRBool nsCSSScanner::Next(nsresult& aErrorCode, nsCSSToken& aToken)
return PR_TRUE;
}
PRBool nsCSSScanner::NextURL(nsresult& aErrorCode, nsCSSToken& aToken)
PRBool
nsCSSScanner::NextURL(nsCSSToken& aToken)
{
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) {
return PR_FALSE;
}
// STRING
if ((ch == '"') || (ch == '\'')) {
return ParseString(aErrorCode, ch, aToken);
return ParseString(ch, aToken);
}
// WS
if (IsWhitespace(ch)) {
aToken.mType = eCSSToken_WhiteSpace;
aToken.mIdent.Assign(PRUnichar(ch));
(void) EatWhiteSpace(aErrorCode);
(void) EatWhiteSpace();
return PR_TRUE;
}
if (ch == '/') {
PRInt32 nextChar = Peek(aErrorCode);
PRInt32 nextChar = Peek();
if (nextChar == '*') {
(void) Read(aErrorCode);
(void) Read();
#if 0
// If we change our storage data structures such that comments are
// stored (for Editor), we should reenable this code, condition it
@ -791,9 +865,9 @@ PRBool nsCSSScanner::NextURL(nsresult& aErrorCode, nsCSSToken& aToken)
aToken.mIdent.SetCapacity(2);
aToken.mIdent.Assign(PRUnichar(ch));
aToken.mIdent.Append(PRUnichar(nextChar));
return ParseCComment(aErrorCode, aToken);
return ParseCComment(aToken);
#endif
return SkipCComment(aErrorCode) && Next(aErrorCode, aToken);
return SkipCComment() && Next(aToken);
}
}
@ -819,17 +893,17 @@ PRBool nsCSSScanner::NextURL(nsresult& aErrorCode, nsCSSToken& aToken)
Pushback(ch);
PRBool ok = PR_TRUE;
for (;;) {
ch = Read(aErrorCode);
ch = Read();
if (ch < 0) break;
if (ch == CSS_ESCAPE) {
ParseAndAppendEscape(aErrorCode, ident);
ParseAndAppendEscape(ident);
} else if ((ch == '"') || (ch == '\'') || (ch == '(')) {
// This is an invalid URL spec
ok = PR_FALSE;
} else if (IsWhitespace(ch)) {
// Whitespace is allowed at the end of the URL
(void) EatWhiteSpace(aErrorCode);
if (LookAhead(aErrorCode, ')')) {
(void) EatWhiteSpace();
if (LookAhead(')')) {
Pushback(')'); // leave the closing symbol
// done!
break;
@ -858,9 +932,9 @@ PRBool nsCSSScanner::NextURL(nsresult& aErrorCode, nsCSSToken& aToken)
void
nsCSSScanner::ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput)
nsCSSScanner::ParseAndAppendEscape(nsString& aOutput)
{
PRInt32 ch = Peek(aErrorCode);
PRInt32 ch = Peek();
if (ch < 0) {
aOutput.Append(CSS_ESCAPE);
return;
@ -869,7 +943,7 @@ nsCSSScanner::ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput)
PRInt32 rv = 0;
int i;
for (i = 0; i < 6; i++) { // up to six digits
ch = Read(aErrorCode);
ch = Read();
if (ch < 0) {
// Whoops: error or premature eof
break;
@ -893,9 +967,9 @@ nsCSSScanner::ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput)
}
}
if (6 == i) { // look for trailing whitespace and eat it
ch = Peek(aErrorCode);
ch = Peek();
if (IsWhitespace(ch)) {
ch = Read(aErrorCode);
ch = Read();
}
}
NS_ASSERTION(rv >= 0, "How did rv become negative?");
@ -907,8 +981,8 @@ nsCSSScanner::ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput)
// "Any character except a hexidecimal digit can be escaped to
// remove its special meaning by putting a backslash in front"
// -- CSS1 spec section 7.1
if (!EatNewline(aErrorCode)) { // skip escaped newline
(void) Read(aErrorCode);
if (!EatNewline()) { // skip escaped newline
(void) Read();
if (ch > 0) {
aOutput.Append(ch);
}
@ -924,18 +998,18 @@ nsCSSScanner::ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput)
* until the first non-identifier character is seen. The termination
* character is unread for the future re-reading.
*/
PRBool nsCSSScanner::GatherIdent(nsresult& aErrorCode, PRInt32 aChar,
nsString& aIdent)
PRBool
nsCSSScanner::GatherIdent(PRInt32 aChar, nsString& aIdent)
{
if (aChar == CSS_ESCAPE) {
ParseAndAppendEscape(aErrorCode, aIdent);
ParseAndAppendEscape(aIdent);
}
else if (0 < aChar) {
aIdent.Append(aChar);
}
for (;;) {
// If nothing in pushback, first try to get as much as possible in one go
if (!mPushbackCount && EnsureData(aErrorCode)) {
if (!mPushbackCount && EnsureData()) {
// See how much we can consume and append in one go
PRUint32 n = mOffset;
// Count number of Ident characters that can be processed
@ -952,10 +1026,10 @@ PRBool nsCSSScanner::GatherIdent(nsresult& aErrorCode, PRInt32 aChar,
}
}
aChar = Read(aErrorCode);
aChar = Read();
if (aChar < 0) break;
if (aChar == CSS_ESCAPE) {
ParseAndAppendEscape(aErrorCode, aIdent);
ParseAndAppendEscape(aIdent);
} else if (IsIdent(aChar)) {
aIdent.Append(PRUnichar(aChar));
} else {
@ -966,23 +1040,22 @@ PRBool nsCSSScanner::GatherIdent(nsresult& aErrorCode, PRInt32 aChar,
return PR_TRUE;
}
PRBool nsCSSScanner::ParseRef(nsresult& aErrorCode,
PRInt32 aChar,
nsCSSToken& aToken)
PRBool
nsCSSScanner::ParseRef(PRInt32 aChar, nsCSSToken& aToken)
{
aToken.mIdent.SetLength(0);
aToken.mType = eCSSToken_Ref;
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) {
return PR_FALSE;
}
if (IsIdent(ch) || ch == CSS_ESCAPE) {
// First char after the '#' is a valid ident char (or an escape),
// so it makes sense to keep going
if (StartsIdent(ch, Peek(aErrorCode))) {
if (StartsIdent(ch, Peek())) {
aToken.mType = eCSSToken_ID;
}
return GatherIdent(aErrorCode, ch, aToken.mIdent);
return GatherIdent(ch, aToken.mIdent);
}
// No ident chars after the '#'. Just unread |ch| and get out of here.
@ -990,19 +1063,18 @@ PRBool nsCSSScanner::ParseRef(nsresult& aErrorCode,
return PR_TRUE;
}
PRBool nsCSSScanner::ParseIdent(nsresult& aErrorCode,
PRInt32 aChar,
nsCSSToken& aToken)
PRBool
nsCSSScanner::ParseIdent(PRInt32 aChar, nsCSSToken& aToken)
{
nsString& ident = aToken.mIdent;
ident.SetLength(0);
if (!GatherIdent(aErrorCode, aChar, ident)) {
if (!GatherIdent(aChar, ident)) {
return PR_FALSE;
}
nsCSSTokenType tokenType = eCSSToken_Ident;
// look for functions (ie: "ident(")
if (PRUnichar('(') == PRUnichar(Peek(aErrorCode))) { // this is a function definition
if (PRUnichar('(') == PRUnichar(Peek())) { // this is a function definition
tokenType = eCSSToken_Function;
}
@ -1010,16 +1082,16 @@ PRBool nsCSSScanner::ParseIdent(nsresult& aErrorCode,
return PR_TRUE;
}
PRBool nsCSSScanner::ParseAtKeyword(nsresult& aErrorCode, PRInt32 aChar,
nsCSSToken& aToken)
PRBool
nsCSSScanner::ParseAtKeyword(PRInt32 aChar, nsCSSToken& aToken)
{
aToken.mIdent.SetLength(0);
aToken.mType = eCSSToken_AtKeyword;
return GatherIdent(aErrorCode, 0, aToken.mIdent);
return GatherIdent(0, aToken.mIdent);
}
PRBool nsCSSScanner::ParseNumber(nsresult& aErrorCode, PRInt32 c,
nsCSSToken& aToken)
PRBool
nsCSSScanner::ParseNumber(PRInt32 c, nsCSSToken& aToken)
{
nsString& ident = aToken.mIdent;
ident.SetLength(0);
@ -1032,21 +1104,21 @@ PRBool nsCSSScanner::ParseNumber(nsresult& aErrorCode, PRInt32 c,
// Gather up characters that make up the number
PRBool gotE = PR_FALSE;
for (;;) {
c = Read(aErrorCode);
c = Read();
if (c < 0) break;
if (!gotDot && !gotE && (c == '.') &&
IsDigit(Peek(aErrorCode))) {
IsDigit(Peek())) {
gotDot = PR_TRUE;
#ifdef MOZ_SVG
} else if (!gotE && (c == 'e' || c == 'E')) {
if (!IsSVGMode()) {
break;
}
PRInt32 nextChar = Peek(aErrorCode);
PRInt32 nextChar = Peek();
PRInt32 sign = 0;
if (nextChar == '-' || nextChar == '+') {
sign = Read(aErrorCode);
nextChar = Peek(aErrorCode);
sign = Read();
nextChar = Peek();
}
if (IsDigit(nextChar)) {
gotE = PR_TRUE;
@ -1083,8 +1155,8 @@ PRBool nsCSSScanner::ParseNumber(nsresult& aErrorCode, PRInt32 c,
// Look at character that terminated the number
if (c >= 0) {
if (StartsIdent(c, Peek(aErrorCode))) {
if (!GatherIdent(aErrorCode, c, ident)) {
if (StartsIdent(c, Peek())) {
if (!GatherIdent(c, ident)) {
return PR_FALSE;
}
type = eCSSToken_Dimension;
@ -1102,13 +1174,14 @@ PRBool nsCSSScanner::ParseNumber(nsresult& aErrorCode, PRInt32 c,
return PR_TRUE;
}
PRBool nsCSSScanner::SkipCComment(nsresult& aErrorCode)
PRBool
nsCSSScanner::SkipCComment()
{
for (;;) {
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) break;
if (ch == '*') {
if (LookAhead(aErrorCode, '/')) {
if (LookAhead('/')) {
return PR_TRUE;
}
}
@ -1119,14 +1192,15 @@ PRBool nsCSSScanner::SkipCComment(nsresult& aErrorCode)
}
#if 0
PRBool nsCSSScanner::ParseCComment(nsresult& aErrorCode, nsCSSToken& aToken)
PRBool
nsCSSScanner::ParseCComment(nsCSSToken& aToken)
{
nsString& ident = aToken.mIdent;
for (;;) {
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) break;
if (ch == '*') {
if (LookAhead(aErrorCode, '/')) {
if (LookAhead('/')) {
ident.Append(PRUnichar(ch));
ident.Append(PRUnichar('/'));
break;
@ -1142,15 +1216,16 @@ PRBool nsCSSScanner::ParseCComment(nsresult& aErrorCode, nsCSSToken& aToken)
#endif
#if 0
PRBool nsCSSScanner::ParseEOLComment(nsresult& aErrorCode, nsCSSToken& aToken)
PRBool
nsCSSScanner::ParseEOLComment(nsCSSToken& aToken)
{
nsString& ident = aToken.mIdent;
ident.SetLength(0);
for (;;) {
if (EatNewline(aErrorCode)) {
if (EatNewline()) {
break;
}
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0) {
break;
}
@ -1163,15 +1238,15 @@ PRBool nsCSSScanner::ParseEOLComment(nsresult& aErrorCode, nsCSSToken& aToken)
}
#endif // 0
PRBool nsCSSScanner::ParseString(nsresult& aErrorCode, PRInt32 aStop,
nsCSSToken& aToken)
PRBool
nsCSSScanner::ParseString(PRInt32 aStop, nsCSSToken& aToken)
{
aToken.mIdent.SetLength(0);
aToken.mType = eCSSToken_String;
aToken.mSymbol = PRUnichar(aStop); // remember how it's quoted
for (;;) {
// If nothing in pushback, first try to get as much as possible in one go
if (!mPushbackCount && EnsureData(aErrorCode)) {
if (!mPushbackCount && EnsureData()) {
// See how much we can consume and append in one go
PRUint32 n = mOffset;
// Count number of characters that can be processed
@ -1196,7 +1271,7 @@ PRBool nsCSSScanner::ParseString(nsresult& aErrorCode, PRInt32 aStop,
mOffset = n;
}
}
PRInt32 ch = Read(aErrorCode);
PRInt32 ch = Read();
if (ch < 0 || ch == aStop) {
break;
}
@ -1208,7 +1283,7 @@ PRBool nsCSSScanner::ParseString(nsresult& aErrorCode, PRInt32 aStop,
break;
}
if (ch == CSS_ESCAPE) {
ParseAndAppendEscape(aErrorCode, aToken.mIdent);
ParseAndAppendEscape(aToken.mIdent);
} else {
aToken.mIdent.Append(ch);
}

View File

@ -188,10 +188,10 @@ class nsCSSScanner {
// Get the next token. Return PR_FALSE on EOF. aTokenResult
// is filled in with the data for the token.
PRBool Next(nsresult& aErrorCode, nsCSSToken& aTokenResult);
PRBool Next(nsCSSToken& aTokenResult);
// Get the next token that may be a string or unquoted URL or whitespace
PRBool NextURL(nsresult& aErrorCode, nsCSSToken& aTokenResult);
PRBool NextURL(nsCSSToken& aTokenResult);
// It's really ugly that we have to expose this, but it's the easiest
// way to do :nth-child() parsing sanely. (In particular, in
@ -199,58 +199,34 @@ class nsCSSScanner {
// "-1" back so we can read it again as a number.)
void Pushback(PRUnichar aChar);
static inline PRBool
IsIdentStart(PRInt32 aChar)
{
return aChar >= 0 &&
(aChar >= 256 || (gLexTable[aChar] & START_IDENT) != 0);
}
// Reports operating-system level errors, e.g. read failures and
// out of memory.
nsresult GetLowLevelError();
static inline PRBool
StartsIdent(PRInt32 aFirstChar, PRInt32 aSecondChar)
{
return IsIdentStart(aFirstChar) ||
(aFirstChar == '-' && IsIdentStart(aSecondChar));
}
static PRBool IsWhitespace(PRInt32 ch) {
return PRUint32(ch) < 256 && (gLexTable[ch] & IS_WHITESPACE) != 0;
}
static PRBool IsDigit(PRInt32 ch) {
return PRUint32(ch) < 256 && (gLexTable[ch] & IS_DIGIT) != 0;
}
static PRBool IsHexDigit(PRInt32 ch) {
return PRUint32(ch) < 256 && (gLexTable[ch] & IS_HEX_DIGIT) != 0;
}
static PRBool IsIdent(PRInt32 ch) {
return ch >= 0 && (ch >= 256 || (gLexTable[ch] & IS_IDENT) != 0);
}
// sometimes the parser wants to make note of a low-level error
void SetLowLevelError(nsresult aErrorCode);
protected:
PRBool EnsureData(nsresult& aErrorCode);
PRInt32 Read(nsresult& aErrorCode);
PRInt32 Peek(nsresult& aErrorCode);
PRBool LookAhead(nsresult& aErrorCode, PRUnichar aChar);
PRBool EatWhiteSpace(nsresult& aErrorCode);
PRBool EatNewline(nsresult& aErrorCode);
PRBool EnsureData();
PRInt32 Read();
PRInt32 Peek();
PRBool LookAhead(PRUnichar aChar);
PRBool EatWhiteSpace();
PRBool EatNewline();
void ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput);
PRBool ParseIdent(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aResult);
PRBool ParseAtKeyword(nsresult& aErrorCode, PRInt32 aChar,
nsCSSToken& aResult);
PRBool ParseNumber(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aResult);
PRBool ParseRef(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aResult);
PRBool ParseString(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aResult);
void ParseAndAppendEscape(nsString& aOutput);
PRBool ParseIdent(PRInt32 aChar, nsCSSToken& aResult);
PRBool ParseAtKeyword(PRInt32 aChar, nsCSSToken& aResult);
PRBool ParseNumber(PRInt32 aChar, nsCSSToken& aResult);
PRBool ParseRef(PRInt32 aChar, nsCSSToken& aResult);
PRBool ParseString(PRInt32 aChar, nsCSSToken& aResult);
#if 0
PRBool ParseEOLComment(nsresult& aErrorCode, nsCSSToken& aResult);
PRBool ParseCComment(nsresult& aErrorCode, nsCSSToken& aResult);
PRBool ParseCComment(nsCSSToken& aResult);
PRBool ParseEOLComment(nsCSSToken& aResult);
#endif
PRBool SkipCComment(nsresult& aErrorCode);
PRBool SkipCComment();
PRBool GatherIdent(nsresult& aErrorCode, PRInt32 aChar, nsString& aIdent);
PRBool GatherIdent(PRInt32 aChar, nsString& aIdent);
// Only used when input is a stream
nsCOMPtr<nsIUnicharInputStream> mInputStream;
@ -263,6 +239,7 @@ protected:
PRInt32 mPushbackCount;
PRInt32 mPushbackSize;
PRUnichar mLocalPushback[4];
nsresult mLowLevelError;
PRUint32 mLineNumber;
#ifdef MOZ_SVG
@ -276,15 +253,6 @@ protected:
nsFixedString mError;
PRUnichar mErrorBuf[200];
#endif
static const PRUint8 IS_DIGIT;
static const PRUint8 IS_HEX_DIGIT;
static const PRUint8 START_IDENT;
static const PRUint8 IS_IDENT;
static const PRUint8 IS_WHITESPACE;
static PRUint8 gLexTable[256];
static void BuildLexTable();
};
#endif /* nsCSSScanner_h___ */