PRBool nsCSSScanner::ParseString(nsresult& aErrorCode, PRInt32 aStop, nsCSSToken& aToken) { aToken.mIdent.SetLength(0); aToken.mType = eCSSToken_String; aToken.mSymbol = PRUnichar(aStop); // remember how it's quoted for (;;) { if (EatNewline(aErrorCode)) { aToken.mType = eCSSToken_Error; #ifdef CSS_REPORT_PARSE_ERRORS ReportUnexpectedToken(aToken, "SEUnterminatedString"); #endif return PR_TRUE; } PRInt32 ch = Read(aErrorCode); if (ch < 0) { return PR_FALSE; } if (ch == aStop) { break; } if (ch == CSS_ESCAPE) { ParseAndAppendEscape(aErrorCode, aToken.mIdent); } else if (0 < ch) { aToken.mIdent.Append(ch); } } return PR_TRUE; }
PRBool nsCSSScanner::ParseEOLComment(nsresult& aErrorCode, nsCSSToken& aToken) { nsString& ident = aToken.mIdent; ident.SetLength(0); for (;;) { if (EatNewline(aErrorCode)) { break; } PRInt32 ch = Read(aErrorCode); if (ch < 0) { break; } #ifdef COLLECT_WHITESPACE ident.Append(PRUnichar(ch)); #endif } aToken.mType = eCSSToken_WhiteSpace; return PR_TRUE; }
void nsCSSScanner::ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput) { PRUint8* lexTable = gLexTable; PRInt32 ch = Peek(aErrorCode); if (ch < 0) { aOutput.Append(CSS_ESCAPE); return; } if ((ch <= 255) && ((lexTable[ch] & IS_HEX_DIGIT) != 0)) { PRInt32 rv = 0; int i; for (i = 0; i < 6; i++) { // up to six digits ch = Read(aErrorCode); if (ch < 0) { // Whoops: error or premature eof break; } if (ch >= 256 || (lexTable[ch] & (IS_HEX_DIGIT | IS_WHITESPACE)) == 0) { Unread(); break; } else if ((lexTable[ch] & IS_HEX_DIGIT) != 0) { if ((lexTable[ch] & IS_DIGIT) != 0) { rv = rv * 16 + (ch - '0'); } else { // Note: c&7 just keeps the low three bits which causes // upper and lower case alphabetics to both yield their // "relative to 10" value for computing the hex value. rv = rv * 16 + ((ch & 0x7) + 9); } } else { NS_ASSERTION((lexTable[ch] & IS_WHITESPACE) != 0, "bad control flow"); // single space ends escape if (ch == '\r' && Peek(aErrorCode) == '\n') { // if CR/LF, eat LF too Read(aErrorCode); } break; } } if (6 == i) { // look for trailing whitespace and eat it ch = Peek(aErrorCode); if ((0 <= ch) && (ch <= 255) && ((lexTable[ch] & IS_WHITESPACE) != 0)) { (void) Read(aErrorCode); // special case: if trailing whitespace is CR/LF, eat both chars. if (ch == '\r' && Peek(aErrorCode) == '\n') { (void) Read(aErrorCode); // if we hit the "\0" special case below, we'll push back // only the '\r', but that's okay, because '\r' by itself // is still a newline. } } } NS_ASSERTION(rv >= 0, "How did rv become negative?"); // "[at most six hexadecimal digits following a backslash] stand // for the ISO 10646 character with that number, which must not be // zero. (It is undefined in CSS 2.1 what happens if a style sheet // does contain a character with Unicode codepoint zero.)" // -- CSS2.1 section 4.1.3 // // Silently deleting \0 opens a content-filtration loophole (see // bug 228856), so what we do instead is pretend the "cancels the // meaning of special characters" rule applied. if (rv > 0) { AppendUCS4ToUTF16(ENSURE_VALID_CHAR(rv), aOutput); } else { while (i--) aOutput.Append('0'); if ((0 <= ch) && (ch <= 255) && ((lexTable[ch] & IS_WHITESPACE) != 0)) Pushback(ch); } return; } else { // "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 (ch > 0) { aOutput.Append(ch); } } return; } }
void nsCSSScanner::ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput) { PRInt32 ch = Peek(aErrorCode); if (ch < 0) { aOutput.Append(CSS_ESCAPE); return; } if (IsHexDigit(ch)) { PRInt32 rv = 0; int i; for (i = 0; i < 6; i++) { // up to six digits ch = Read(aErrorCode); if (ch < 0) { // Whoops: error or premature eof break; } if (!IsHexDigit(ch) && !IsWhitespace(ch)) { Pushback(ch); break; } else if (IsHexDigit(ch)) { if (IsDigit(ch)) { rv = rv * 16 + (ch - '0'); } else { // Note: c&7 just keeps the low three bits which causes // upper and lower case alphabetics to both yield their // "relative to 10" value for computing the hex value. rv = rv * 16 + ((ch & 0x7) + 9); } } else { NS_ASSERTION(IsWhitespace(ch), "bad control flow"); // single space ends escape break; } } if (6 == i) { // look for trailing whitespace and eat it ch = Peek(aErrorCode); if (IsWhitespace(ch)) { (void) Read(aErrorCode); } } NS_ASSERTION(rv >= 0, "How did rv become negative?"); // "[at most six hexadecimal digits following a backslash] stand // for the ISO 10646 character with that number, which must not be // zero. (It is undefined in CSS 2.1 what happens if a style sheet // does contain a character with Unicode codepoint zero.)" // -- CSS2.1 section 4.1.3 // // Silently deleting \0 opens a content-filtration loophole (see // bug 228856), so what we do instead is pretend the "cancels the // meaning of special characters" rule applied. if (rv > 0) { AppendUCS4ToUTF16(ENSURE_VALID_CHAR(rv), aOutput); } else { while (i--) aOutput.Append('0'); if (IsWhitespace(ch)) Pushback(ch); } return; } else { // "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 (ch > 0) { aOutput.Append(ch); } } return; } }