1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * L. David Baron <dbaron@dbaron.org>
24 : * Daniel Glazman <glazman@netscape.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : /* tokenization of CSS style sheets */
41 :
42 : #ifndef nsCSSScanner_h___
43 : #define nsCSSScanner_h___
44 :
45 : #include "nsString.h"
46 : #include "nsCOMPtr.h"
47 : #include "mozilla/css/Loader.h"
48 : #include "nsCSSStyleSheet.h"
49 :
50 : // XXX turn this off for minimo builds
51 : #define CSS_REPORT_PARSE_ERRORS
52 :
53 : // for #ifdef CSS_REPORT_PARSE_ERRORS
54 : #include "nsXPIDLString.h"
55 : class nsIURI;
56 :
57 : // Token types
58 : enum nsCSSTokenType {
59 : // A css identifier (e.g. foo)
60 : eCSSToken_Ident, // mIdent
61 :
62 : // A css at keyword (e.g. @foo)
63 : eCSSToken_AtKeyword, // mIdent
64 :
65 : // A css number without a percentage or dimension; with percentage;
66 : // without percentage but with a dimension
67 : eCSSToken_Number, // mNumber
68 : eCSSToken_Percentage, // mNumber
69 : eCSSToken_Dimension, // mNumber + mIdent
70 :
71 : // A css string (e.g. "foo" or 'foo')
72 : eCSSToken_String, // mSymbol + mIdent + mSymbol
73 :
74 : // Whitespace (e.g. " " or "/* abc */")
75 : eCSSToken_WhiteSpace, // mIdent
76 :
77 : // A css symbol (e.g. ':', ';', '+', etc.)
78 : eCSSToken_Symbol, // mSymbol
79 :
80 : // A css1 id (e.g. #foo3)
81 : eCSSToken_ID, // mIdent
82 : // Just like eCSSToken_ID, except the part following the '#' is not
83 : // a valid CSS identifier (eg. starts with a digit, is the empty
84 : // string, etc).
85 : eCSSToken_Ref, // mIdent
86 :
87 : eCSSToken_Function, // mIdent
88 :
89 : eCSSToken_URL, // mIdent + mSymbol
90 : eCSSToken_Bad_URL, // mIdent + mSymbol
91 :
92 : eCSSToken_HTMLComment, // "<!--" or "-->"
93 :
94 : eCSSToken_Includes, // "~="
95 : eCSSToken_Dashmatch, // "|="
96 : eCSSToken_Beginsmatch, // "^="
97 : eCSSToken_Endsmatch, // "$="
98 : eCSSToken_Containsmatch, // "*="
99 :
100 : eCSSToken_URange, // Low in mInteger, high in mInteger2;
101 : // mIntegerValid is true if the token is a
102 : // valid range; mIdent preserves the textual
103 : // form of the token for error reporting
104 :
105 : // An unterminated string, which is always an error.
106 : eCSSToken_Bad_String // mSymbol + mIdent
107 : };
108 :
109 12 : struct nsCSSToken {
110 : nsAutoString mIdent NS_OKONHEAP;
111 : float mNumber;
112 : PRInt32 mInteger;
113 : PRInt32 mInteger2;
114 : nsCSSTokenType mType;
115 : PRUnichar mSymbol;
116 : bool mIntegerValid; // for number, dimension, urange
117 : bool mHasSign; // for number, percentage, and dimension
118 :
119 : nsCSSToken();
120 :
121 660 : bool IsSymbol(PRUnichar aSymbol) {
122 660 : return bool((eCSSToken_Symbol == mType) && (mSymbol == aSymbol));
123 : }
124 :
125 : void AppendToString(nsString& aBuffer);
126 : };
127 :
128 : // CSS Scanner API. Used to tokenize an input stream using the CSS
129 : // forward compatible tokenization rules. This implementation is
130 : // private to this package and is only used internally by the css
131 : // parser.
132 : class nsCSSScanner {
133 : public:
134 : nsCSSScanner();
135 : ~nsCSSScanner();
136 :
137 : // Init the scanner.
138 : // |aLineNumber == 1| is the beginning of a file, use |aLineNumber == 0|
139 : // when the line number is unknown.
140 : void Init(const nsAString& aBuffer,
141 : nsIURI* aURI, PRUint32 aLineNumber,
142 : nsCSSStyleSheet* aSheet, mozilla::css::Loader* aLoader);
143 : void Close();
144 :
145 : static bool InitGlobals();
146 : static void ReleaseGlobals();
147 :
148 : // Set whether or not we are processing SVG
149 110 : void SetSVGMode(bool aSVGMode) {
150 110 : mSVGMode = aSVGMode;
151 110 : }
152 0 : bool IsSVGMode() const {
153 0 : return mSVGMode;
154 : }
155 :
156 : #ifdef CSS_REPORT_PARSE_ERRORS
157 : void AddToError(const nsSubstring& aErrorText);
158 : void OutputError();
159 : void ClearError();
160 :
161 : // aMessage must take no parameters
162 : void ReportUnexpected(const char* aMessage);
163 :
164 : private:
165 : void ReportUnexpectedParams(const char* aMessage,
166 : const PRUnichar** aParams,
167 : PRUint32 aParamsLength);
168 :
169 : public:
170 : template<PRUint32 N>
171 0 : void ReportUnexpectedParams(const char* aMessage,
172 : const PRUnichar* (&aParams)[N])
173 : {
174 0 : return ReportUnexpectedParams(aMessage, aParams, N);
175 : }
176 : // aLookingFor is a plain string, not a format string
177 : void ReportUnexpectedEOF(const char* aLookingFor);
178 : // aLookingFor is a single character
179 : void ReportUnexpectedEOF(PRUnichar aLookingFor);
180 : // aMessage must take 1 parameter (for the string representation of the
181 : // unexpected token)
182 : void ReportUnexpectedToken(nsCSSToken& tok, const char *aMessage);
183 : // aParams's first entry must be null, and we'll fill in the token
184 : void ReportUnexpectedTokenParams(nsCSSToken& tok,
185 : const char* aMessage,
186 : const PRUnichar **aParams,
187 : PRUint32 aParamsLength);
188 : #endif
189 :
190 0 : PRUint32 GetLineNumber() { return mLineNumber; }
191 :
192 : // Get the next token. Return false on EOF. aTokenResult
193 : // is filled in with the data for the token.
194 : bool Next(nsCSSToken& aTokenResult);
195 :
196 : // Get the next token that may be a string or unquoted URL
197 : bool NextURL(nsCSSToken& aTokenResult);
198 :
199 : // It's really ugly that we have to expose this, but it's the easiest
200 : // way to do :nth-child() parsing sanely. (In particular, in
201 : // :nth-child(2n-1), "2n-1" is a dimension, and we need to push the
202 : // "-1" back so we can read it again as a number.)
203 : void Pushback(PRUnichar aChar);
204 :
205 : protected:
206 : PRInt32 Read();
207 : PRInt32 Peek();
208 : bool LookAhead(PRUnichar aChar);
209 : bool LookAheadOrEOF(PRUnichar aChar); // expect either aChar or EOF
210 : void EatWhiteSpace();
211 :
212 : bool ParseAndAppendEscape(nsString& aOutput, bool aInString);
213 : bool ParseIdent(PRInt32 aChar, nsCSSToken& aResult);
214 : bool ParseAtKeyword(PRInt32 aChar, nsCSSToken& aResult);
215 : bool ParseNumber(PRInt32 aChar, nsCSSToken& aResult);
216 : bool ParseRef(PRInt32 aChar, nsCSSToken& aResult);
217 : bool ParseString(PRInt32 aChar, nsCSSToken& aResult);
218 : bool ParseURange(PRInt32 aChar, nsCSSToken& aResult);
219 : bool SkipCComment();
220 :
221 : bool GatherIdent(PRInt32 aChar, nsString& aIdent);
222 :
223 : const PRUnichar *mReadPointer;
224 : PRUint32 mOffset;
225 : PRUint32 mCount;
226 : PRUnichar* mPushback;
227 : PRInt32 mPushbackCount;
228 : PRInt32 mPushbackSize;
229 : PRUnichar mLocalPushback[4];
230 :
231 : PRUint32 mLineNumber;
232 : // True if we are in SVG mode; false in "normal" CSS
233 : bool mSVGMode;
234 : #ifdef CSS_REPORT_PARSE_ERRORS
235 : nsXPIDLCString mFileName;
236 : nsCOMPtr<nsIURI> mURI; // Cached so we know to not refetch mFileName
237 : PRUint32 mErrorLineNumber, mColNumber, mErrorColNumber;
238 : nsFixedString mError;
239 : PRUnichar mErrorBuf[200];
240 : PRUint64 mInnerWindowID;
241 : bool mWindowIDCached;
242 : nsCSSStyleSheet* mSheet;
243 : mozilla::css::Loader* mLoader;
244 : #endif
245 : };
246 :
247 : #endif /* nsCSSScanner_h___ */
|