1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
32 #include <boost/unordered_map.hpp>
37 typedef sal_Int32 TokenId
;
39 #define TOK_INVALIDPOS (-1)
42 typedef ::std::vector
< ParserMessage
* > Impl_ParserMessageList
;
44 class ParserMessageList
;
46 typedef boost::unordered_map
<rtl::OString
, rtl::OUString
, rtl::OStringHash
> StringHashMap
;
51 void SplitTag( ParserMessageList
&rErrorList
);
53 rtl::OUString aTagName
;
54 StringHashMap aProperties
;
55 sal_Bool bClosed
; // tag is closed <sdnf/>
56 sal_Bool bCloseTag
; // tag is close Tag </sdnf>
60 sal_Bool bHasBeenFixed
;
65 rtl::OUString aTokenString
;
67 sal_Int32 nPos
; // Position in String
69 TokenInfo():bClosed(sal_False
),bCloseTag(sal_False
),bIsBroken(sal_False
),bHasBeenFixed(sal_False
),bDone(sal_False
),nId( 0 ){;}
70 explicit TokenInfo( TokenId pnId
, sal_Int32 nP
):bClosed(sal_False
),bCloseTag(sal_False
),bIsBroken(sal_False
),bHasBeenFixed(sal_False
),bDone(sal_False
),nId( pnId
),nPos(nP
){;}
71 explicit TokenInfo( TokenId pnId
, sal_Int32 nP
, rtl::OUString
const & paStr
):bClosed(sal_False
),bCloseTag(sal_False
),bIsBroken(sal_False
),bHasBeenFixed(sal_False
),bDone(sal_False
),aTokenString( paStr
),nId( pnId
),nPos(nP
) {;}
72 explicit TokenInfo( TokenId pnId
, sal_Int32 nP
, rtl::OUString
const & paStr
, ParserMessageList
&rErrorList
);
74 rtl::OUString
GetTagName() const;
76 rtl::OUString
MakeTag() const;
79 Is the property to be ignored or does it have the default value anyways
81 sal_Bool
IsPropertyRelevant( const rtl::OString
&rName
, const rtl::OUString
&rValue
) const;
82 sal_Bool
IsPropertyValueValid( const rtl::OString
&rName
, const rtl::OUString
&rValue
) const;
84 Does the property contain the same value for all languages
85 e.g.: the href in a link tag
87 sal_Bool
IsPropertyInvariant( const rtl::OString
&rName
, const rtl::OUString
&rValue
) const;
89 a subset of IsPropertyInvariant but containing only those that are fixable
90 we dont wat to fix e.g.: ahelp :: visibility
92 sal_Bool
IsPropertyFixable( const rtl::OString
&rName
) const;
93 sal_Bool
MatchesTranslation( TokenInfo
& rInfo
, sal_Bool bGenErrors
, ParserMessageList
&rErrorList
, sal_Bool bFixTags
= sal_False
) const;
95 sal_Bool
IsDone() const { return bDone
; }
96 void SetDone( sal_Bool bNew
= sal_True
) { bDone
= bNew
; }
98 sal_Bool
HasBeenFixed() const { return bHasBeenFixed
; }
99 void SetHasBeenFixed( sal_Bool bNew
= sal_True
) { bHasBeenFixed
= bNew
; }
103 class ParserMessageList
106 Impl_ParserMessageList maList
;
109 ~ParserMessageList() { clear(); }
110 void AddError( sal_Int32 nErrorNr
, const rtl::OString
& rErrorText
, const TokenInfo
&rTag
);
111 void AddWarning( sal_Int32 nErrorNr
, const rtl::OString
& rErrorText
, const TokenInfo
&rTag
);
113 sal_Bool
HasErrors();
114 bool empty() const { return maList
.empty(); }
115 size_t size() const { return maList
.size(); }
116 ParserMessage
* operator [] ( size_t i
) { return ( i
< maList
.size() ) ? maList
[ i
] : NULL
; }
121 #define TAG_GROUPMASK 0xF000
122 #define TAG_GROUPSHIFT 12
124 #define TAG_GROUP( nTag ) (( nTag & TAG_GROUPMASK ) >> TAG_GROUPSHIFT )
125 #define TAG_NOGROUP( nTag ) ( nTag & ~TAG_GROUPMASK ) // ~ = Bitweises NOT
127 #define TAG_NOMORETAGS 0x0
129 #define TAG_GROUP_FORMAT 0x1
131 #define TAG_BOLDON ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x001 )
132 #define TAG_BOLDOFF ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | 0x001 )
133 #define TAG_ITALICON ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x002 )
134 #define TAG_ITALICOFF ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | 0x002 )
135 #define TAG_UNDERLINEON ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x004 )
136 #define TAG_UNDERLINEOFF ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | 0x004 )
138 #define TAG_GROUP_NOTALLOWED 0x2
139 #define TAG_HELPID ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x001 )
140 #define TAG_MODIFY ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x002 )
141 #define TAG_REFNR ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x004 )
143 #define TAG_GROUP_STRUCTURE 0x3
144 #define TAG_NAME ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x001 )
145 #define TAG_HREF ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x002 )
146 #define TAG_AVIS ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x004 )
147 #define TAG_AHID ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x008 )
149 #define TAG_TITEL ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x020 )
150 #define TAG_KEY ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x040 )
151 #define TAG_INDEX ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x080 )
153 #define TAG_REFSTART ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x100 )
155 #define TAG_GRAPHIC ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x200 )
156 #define TAG_NEXTVERSION ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x400 )
158 #define TAG_GROUP_SYSSWITCH 0x4
159 #define TAG_WIN ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x001 )
160 #define TAG_UNIX ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x002 )
161 #define TAG_MAC ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x004 )
162 #define TAG_OS2 ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x008 )
164 #define TAG_GROUP_PROGSWITCH 0x5
165 #define TAG_WRITER ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x001 )
166 #define TAG_CALC ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x002 )
167 #define TAG_DRAW ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x004 )
168 #define TAG_IMPRESS ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x008 )
169 #define TAG_SCHEDULE ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x010 )
170 #define TAG_IMAGE ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x020 )
171 #define TAG_MATH ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x040 )
172 #define TAG_CHART ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x080 )
173 #define TAG_OFFICE ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x100 )
176 #define TAG_GROUP_META 0x6
177 #define TAG_OFFICEFULLNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x001 )
178 #define TAG_OFFICENAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x002 )
179 #define TAG_OFFICEPATH ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x004 )
180 #define TAG_OFFICEVERSION ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x008 )
181 #define TAG_PORTALNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x010 )
182 #define TAG_PORTALFULLNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x020 )
183 #define TAG_PORTALPATH ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x040 )
184 #define TAG_PORTALVERSION ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x080 )
185 #define TAG_PORTALSHORTNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x100 )
188 #define TAG_GROUP_SINGLE 0x7
189 #define TAG_REFINSERT ( TAG_GROUP_SINGLE << TAG_GROUPSHIFT | 0x001 )
192 #define TAG_GROUP_MULTI 0x8
193 #define TAG_END ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x010 )
194 #define TAG_ELSE ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x020 )
195 #define TAG_AEND ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x040 )
196 #define TAG_VERSIONEND ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x080 )
197 #define TAG_ENDGRAPHIC ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x100 )
199 #define TAG_GROUP_MISC 0x9
200 #define TAG_COMMONSTART ( TAG_GROUP_MISC << TAG_GROUPSHIFT | 0x001 )
201 #define TAG_COMMONEND ( TAG_GROUP_MISC << TAG_GROUPSHIFT | 0x002 )
203 #define TAG_UNKNOWN_TAG ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x800 )
205 typedef ::std::vector
< TokenInfo
* > TokenListImpl
;
210 TokenListImpl maList
;
211 TokenList
& operator =( const TokenList
& rList
);
215 ~TokenList(){ clear(); }
217 size_t size() const { return maList
.size(); }
220 for ( size_t i
= 0 ; i
< maList
.size() ; i
++ )
225 void insert( TokenInfo p
, size_t nIndex
= size_t(-1) )
227 if ( nIndex
< maList
.size() ) {
228 TokenListImpl::iterator it
= maList
.begin();
229 ::std::advance( it
, nIndex
);
230 maList
.insert( it
, new TokenInfo(p
) );
232 maList
.push_back( new TokenInfo(p
) );
235 TokenInfo
& operator [] ( size_t nIndex
) const
237 return *maList
[ nIndex
];
240 TokenList( const TokenList
& rList
);
246 rtl::OString aErrorText
;
247 sal_Int32 nTagBegin
,nTagLength
;
250 ParserMessage( sal_Int32 PnErrorNr
, const rtl::OString
&rPaErrorText
, const TokenInfo
&rTag
);
253 sal_Int32
GetErrorNr() { return nErrorNr
; }
254 rtl::OString
GetErrorText() { return aErrorText
; }
256 sal_Int32
GetTagBegin() { return nTagBegin
; }
257 sal_Int32
GetTagLength() { return nTagLength
; }
259 virtual ~ParserMessage() {}
260 virtual sal_Bool
IsError() =0;
261 virtual rtl::OString
Prefix() =0;
264 class ParserError
: public ParserMessage
267 ParserError( sal_Int32 PnErrorNr
, const rtl::OString
&rPaErrorText
, const TokenInfo
&rTag
);
269 virtual sal_Bool
IsError() {return sal_True
;}
270 virtual rtl::OString
Prefix() {return rtl::OString(RTL_CONSTASCII_STRINGPARAM("Error:")); }
273 class ParserWarning
: public ParserMessage
276 ParserWarning( sal_Int32 PnErrorNr
, const rtl::OString
&rPaErrorText
, const TokenInfo
&rTag
);
278 virtual sal_Bool
IsError() {return sal_False
;}
279 virtual rtl::OString
Prefix() {return rtl::OString(RTL_CONSTASCII_STRINGPARAM("Warning:")); }
286 rtl::OUString aSource
;
287 rtl::OUString aLastToken
;
288 TokenList aTokenList
;
290 TokenInfo aNextTag
; // to store closetag in case of combined tags like <br/>
292 rtl::OUString
GetNextTokenString( ParserMessageList
&rErrorList
, sal_Int32
&rTokeStartPos
);
296 void Parse( rtl::OUString
const & PaSource
);
297 TokenInfo
GetNextToken( ParserMessageList
&rErrorList
);
298 static rtl::OUString
GetLexem( TokenInfo
const &aToken
);
299 TokenList
& GetTokenList(){ return aTokenList
; }
304 sal_Bool
match( const TokenInfo
&aCurrentToken
, const TokenId
&aExpectedToken
);
305 sal_Bool
match( const TokenInfo
&aCurrentToken
, const TokenInfo
&aExpectedToken
);
306 void ParseError( sal_Int32 nErrNr
, const rtl::OString
&rErrMsg
, const TokenInfo
&rTag
);
317 SimpleParser aParser
;
320 TokenId nPfCaseOptions
;
321 TokenId nAppCaseOptions
;
322 sal_Bool bPfCaseActive
,bAppCaseActive
;
324 TokenId nActiveRefTypes
;
326 ParserMessageList
*pErrorList
;
330 void Parse( const rtl::OUString
&aCode
, ParserMessageList
* pList
);
331 TokenList
& GetTokenList(){ return aParser
.GetTokenList(); }
337 TokenParser aReferenceParser
;
338 TokenParser aTesteeParser
;
339 ParserMessageList aCompareWarningList
;
340 void CheckTags( TokenList
&aReference
, TokenList
&aTestee
, sal_Bool bFixTags
);
341 sal_Bool
IsTagMandatory( TokenInfo
const &aToken
, TokenId
&aMetaTokens
);
342 rtl::OUString aFixedTestee
;
344 void CheckReference( GSILine
*aReference
);
345 void CheckTestee( GSILine
*aTestee
, sal_Bool bHasSourceLine
, sal_Bool bFixTags
);
347 ParserMessageList
& GetCompareWarnings(){ return aCompareWarningList
; }
348 sal_Bool
HasCompareWarnings(){ return ( !aCompareWarningList
.empty() ); }
350 rtl::OUString
GetFixedTestee(){ return aFixedTestee
; }
355 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */