1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
25 #include <database.hxx>
26 #include <globals.hxx>
27 #include <osl/file.hxx>
29 void SvIdlParser::ReadSvIdl( const OUString
& rPath
)
31 rBase
.SetPath(rPath
); // only valid for this iteration
32 SvToken
& rTok
= rInStm
.GetToken();
36 rTok
= rInStm
.GetToken();
40 Read( SvHash_module() );
41 tools::SvRef
<SvMetaModule
> aModule
= new SvMetaModule
;
42 ReadModuleHeader(*aModule
);
43 rBase
.GetModuleList().push_back( aModule
.get() );
47 void SvIdlParser::ReadModuleHeader(SvMetaModule
& rModule
)
49 OString aName
= ReadIdentifier();
50 rModule
.SetName( aName
);
51 rBase
.Push( &rModule
); // onto the context stack
52 ReadModuleBody(rModule
);
53 rBase
.GetStack().pop_back(); // remove from stack
56 void SvIdlParser::ReadModuleBody(SvMetaModule
& rModule
)
63 if( !ReadStringSvIdl( SvHash_SlotIdFile(), rInStm
, aSlotIdFile
) )
65 if( !rBase
.ReadIdFile( aSlotIdFile
) )
67 throw SvParseException( rInStm
, "cannot read file: " + aSlotIdFile
);
77 sal_uInt32 nBeginPos
= 0;
78 while( nBeginPos
!= rInStm
.Tell() )
80 nBeginPos
= rInStm
.Tell();
81 ReadModuleElement( rModule
);
87 void SvIdlParser::ReadModuleElement( SvMetaModule
& rModule
)
89 if( ReadIf( SvHash_interface() ) )
91 ReadInterfaceOrShell(rModule
, MetaTypeType::Interface
);
93 else if( ReadIf( SvHash_shell() ) )
95 ReadInterfaceOrShell(rModule
, MetaTypeType::Shell
);
97 else if( ReadIf( SvHash_enum() ) )
101 else if( ReadIf( SvHash_item() ) )
105 else if( ReadIf( SvHash_struct() ) )
109 else if( ReadIf( SvHash_include() ) )
111 ReadInclude(rModule
);
115 tools::SvRef
<SvMetaSlot
> xSlot( new SvMetaSlot() );
117 if (ReadSlot(*xSlot
))
119 if( xSlot
->Test( rInStm
) )
122 rBase
.AppendSlot( xSlot
.get() );
128 void SvIdlParser::ReadInclude( SvMetaModule
& rModule
)
130 sal_uInt32 nTokPos
= rInStm
.Tell();
132 OUString
aFullName(OStringToOUString(ReadString(), RTL_TEXTENCODING_ASCII_US
));
133 rBase
.StartNewFile( aFullName
);
134 osl::FileBase::RC searchError
= osl::File::searchFileURL(aFullName
, rBase
.GetPath(), aFullName
);
135 if( osl::FileBase::E_None
!= searchError
)
137 OString aStr
= "cannot find file:" +
138 OUStringToOString(aFullName
, RTL_TEXTENCODING_UTF8
);
139 throw SvParseException(aStr
, rInStm
.GetToken());
141 osl::FileBase::getSystemPathFromFileURL( aFullName
, aFullName
);
142 rBase
.AddDepFile( aFullName
);
143 SvTokenStream
aTokStm( aFullName
);
144 if( ERRCODE_NONE
!= aTokStm
.GetStream().GetError() )
146 OString aStr
= "cannot open file: " +
147 OUStringToOString(aFullName
, RTL_TEXTENCODING_UTF8
);
148 throw SvParseException(aStr
, rInStm
.GetToken());
150 // rescue error from old file
151 SvIdlError aOldErr
= rBase
.GetError();
153 rBase
.SetError( SvIdlError() );
156 SvIdlParser
aIncludeParser( rBase
, aTokStm
);
157 sal_uInt32 nBeginPos
= 0xFFFFFFFF; // can not happen with Tell
158 while( nBeginPos
!= aTokStm
.Tell() )
160 nBeginPos
= aTokStm
.Tell();
161 aIncludeParser
.ReadModuleElement(rModule
);
162 aTokStm
.ReadIfDelimiter();
164 } catch (const SvParseException
& ex
) {
165 rBase
.SetError(ex
.aError
);
166 rBase
.WriteError(aTokStm
);
168 bOk
= aTokStm
.GetToken().IsEof();
171 rBase
.WriteError( aTokStm
);
173 // recover error from old file
174 rBase
.SetError( aOldErr
);
176 rInStm
.Seek( nTokPos
);
179 void SvIdlParser::ReadStruct()
181 tools::SvRef
<SvMetaType
> xStruct(new SvMetaType() );
182 xStruct
->SetType( MetaTypeType::Struct
);
183 xStruct
->SetName( ReadIdentifier() );
187 tools::SvRef
<SvMetaAttribute
> xAttr( new SvMetaAttribute() );
188 xAttr
->aType
= ReadKnownType();
189 xAttr
->SetName(ReadIdentifier());
190 xAttr
->aSlotId
.setString(ReadIdentifier());
192 if( !rBase
.FindId( xAttr
->aSlotId
.getString(), &n
) )
193 throw SvParseException( rInStm
, "no value for identifier <" + xAttr
->aSlotId
.getString() + "> " );
194 xAttr
->aSlotId
.SetValue(n
);
195 xStruct
->GetAttrList().push_back( xAttr
.get() );
196 if( !ReadIfDelimiter() )
198 if( rInStm
.GetToken().IsChar() && rInStm
.GetToken().GetChar() == '}')
204 rBase
.GetTypeList().push_back( xStruct
.get() );
207 void SvIdlParser::ReadItem()
209 tools::SvRef
<SvMetaType
> xItem(new SvMetaType() );
210 xItem
->SetItem(true);
211 xItem
->SetRef( ReadKnownType() );
212 xItem
->SetName( ReadIdentifier() );
214 rBase
.GetTypeList().push_back( xItem
.get() );
217 void SvIdlParser::ReadEnum()
219 tools::SvRef
<SvMetaTypeEnum
> xEnum( new SvMetaTypeEnum() );
220 xEnum
->SetType( MetaTypeType::Enum
);
221 xEnum
->SetName( ReadIdentifier() );
226 ReadEnumValue( *xEnum
);
227 if( !ReadIfDelimiter() )
232 rBase
.GetTypeList().push_back( xEnum
.get() );
235 static OString
getCommonSubPrefix(const OString
&rA
, const OString
&rB
)
237 sal_Int32 nMax
= std::min(rA
.getLength(), rB
.getLength());
241 if (rA
[nI
] != rB
[nI
])
245 return rA
.copy(0, nI
);
248 void SvIdlParser::ReadEnumValue( SvMetaTypeEnum
& rEnum
)
250 tools::SvRef
<SvMetaEnumValue
> aEnumVal
= new SvMetaEnumValue();
251 aEnumVal
->SetName( ReadIdentifier() );
252 if( rEnum
.aEnumValueList
.empty() )
255 rEnum
.aPrefix
= aEnumVal
->GetName();
259 rEnum
.aPrefix
= getCommonSubPrefix(rEnum
.aPrefix
, aEnumVal
->GetName());
261 rEnum
.aEnumValueList
.push_back( aEnumVal
.get() );
264 void SvIdlParser::ReadInterfaceOrShell( SvMetaModule
& rModule
, MetaTypeType aMetaTypeType
)
266 tools::SvRef
<SvMetaClass
> aClass( new SvMetaClass() );
268 aClass
->SetType( aMetaTypeType
);
270 aClass
->SetName( ReadIdentifier() );
274 aClass
->aSuperClass
= ReadKnownClass();
278 sal_uInt32 nBeginPos
= 0; // can not happen with Tell
279 while( nBeginPos
!= rInStm
.Tell() )
281 nBeginPos
= rInStm
.Tell();
282 ReadInterfaceOrShellEntry(*aClass
);
287 rModule
.aClassList
.push_back( aClass
.get() );
289 rBase
.GetClassList().push_back( aClass
.get() );
292 void SvIdlParser::ReadInterfaceOrShellEntry(SvMetaClass
& rClass
)
294 if( ReadIf( SvHash_import() ) )
296 SvMetaClass
* pClass
= ReadKnownClass();
297 SvClassElement
aEle(pClass
);
298 SvToken
& rTok
= rInStm
.GetToken();
299 if( rTok
.IsString() )
301 aEle
.SetPrefix( rTok
.GetString() );
302 rInStm
.GetToken_Next();
304 rClass
.aClassElementList
.push_back( aEle
);
308 SvMetaType
* pType
= rBase
.ReadKnownType( rInStm
);
309 tools::SvRef
<SvMetaAttribute
> xAttr
;
311 if( !pType
|| pType
->IsItem() )
313 xAttr
= new SvMetaSlot( pType
);
314 bOk
= ReadSlot(static_cast<SvMetaSlot
&>(*xAttr
));
318 xAttr
= new SvMetaAttribute( pType
);
319 ReadInterfaceOrShellMethod(*xAttr
);
323 bOk
= xAttr
->Test( rInStm
);
325 bOk
= rClass
.TestAttribute( rBase
, rInStm
, *xAttr
);
328 if( !xAttr
->GetSlotId().IsSet() )
329 xAttr
->SetSlotId( SvIdentifier(rBase
.GetUniqueId()) );
330 rClass
.aAttrList
.push_back( xAttr
.get() );
335 bool SvIdlParser::ReadSlot(SvMetaSlot
& rSlot
)
337 sal_uInt32 nTokPos
= rInStm
.Tell();
340 SvMetaAttribute
* pAttr
= rBase
.ReadKnownAttr( rInStm
, rSlot
.GetType() );
343 SvMetaSlot
* pKnownSlot
= dynamic_cast<SvMetaSlot
*>( pAttr
);
345 throw SvParseException( rInStm
, "attribute " + pAttr
->GetName() + " is method or variable but not a slot" );
346 rSlot
.SetRef( pKnownSlot
);
347 rSlot
.SetName( pKnownSlot
->GetName() );
350 sal_uInt32 nBeginPos
= 0; // can not happen with Tell
351 while( nBeginPos
!= rInStm
.Tell() )
353 nBeginPos
= rInStm
.Tell();
354 ReadSlotAttribute(rSlot
);
362 bOk
= rSlot
.SvMetaAttribute::ReadSvIdl( rBase
, rInStm
);
363 SvMetaAttribute
*pAttr2
= rBase
.FindKnownAttr( rSlot
.GetSlotId() );
366 SvMetaSlot
* pKnownSlot
= dynamic_cast<SvMetaSlot
*>( pAttr2
);
368 throw SvParseException( rInStm
, "attribute " + pAttr2
->GetName() + " is method or variable but not a slot" );
369 rSlot
.SetRef( pKnownSlot
);
370 // names may differ, because explicitly given
371 if ( pKnownSlot
->GetName() != rSlot
.GetName() )
372 throw SvParseException( rInStm
, "Illegal definition!" );
377 rInStm
.Seek( nTokPos
);
382 void SvIdlParser::ReadSlotAttribute( SvMetaSlot
& rSlot
)
384 ReadIfIdAttribute(rSlot
.aGroupId
, SvHash_GroupId() );
385 ReadIfIdAttribute(rSlot
.aExecMethod
, SvHash_ExecMethod() );
386 ReadIfIdAttribute(rSlot
.aStateMethod
, SvHash_StateMethod() );
387 ReadStringSvIdl( SvHash_DisableFlags(), rInStm
, rSlot
.aDisableFlags
);
388 ReadIfBoolAttribute(rSlot
.aReadOnlyDoc
, SvHash_ReadOnlyDoc() );
389 ReadIfBoolAttribute(rSlot
.aExport
, SvHash_Export() );
391 ReadIfBoolAttribute(rSlot
.aToggle
, SvHash_Toggle() );
392 ReadIfBoolAttribute(rSlot
.aAutoUpdate
, SvHash_AutoUpdate() );
393 ReadIfBoolAttribute(rSlot
.aAsynchron
, SvHash_Asynchron() );
394 ReadIfBoolAttribute(rSlot
.aRecordAbsolute
, SvHash_RecordAbsolute() );
396 if( ReadIfBoolAttribute(rSlot
.aRecordPerItem
, SvHash_RecordPerItem()) )
398 if (rSlot
.aRecordPerSet
.IsSet() || rSlot
.aNoRecord
.IsSet())
399 throw SvParseException(rInStm
, "conflicting attributes");
400 rSlot
.SetRecordPerItem( rSlot
.aRecordPerItem
);
402 if( ReadIfBoolAttribute(rSlot
.aRecordPerSet
, SvHash_RecordPerSet() ) )
404 if (rSlot
.aRecordPerItem
.IsSet() || rSlot
.aNoRecord
.IsSet())
405 throw SvParseException(rInStm
, "conflicting attributes");
406 rSlot
.SetRecordPerSet( rSlot
.aRecordPerSet
);
408 if( ReadIfBoolAttribute(rSlot
.aNoRecord
, SvHash_NoRecord() ) )
410 if (rSlot
.aRecordPerItem
.IsSet() || rSlot
.aRecordPerSet
.IsSet())
411 throw SvParseException(rInStm
, "conflicting attributes");
412 rSlot
.SetNoRecord( rSlot
.aNoRecord
);
415 ReadIfBoolAttribute(rSlot
.aMenuConfig
, SvHash_MenuConfig() );
416 ReadIfBoolAttribute(rSlot
.aToolBoxConfig
, SvHash_ToolBoxConfig() );
417 ReadIfBoolAttribute(rSlot
.aAccelConfig
, SvHash_AccelConfig() );
419 ReadIfBoolAttribute(rSlot
.aFastCall
, SvHash_FastCall() );
420 ReadIfBoolAttribute(rSlot
.aContainer
, SvHash_Container() );
423 void SvIdlParser::ReadInterfaceOrShellMethod( SvMetaAttribute
& rAttr
)
425 rAttr
.SetName( ReadIdentifier() );
426 ReadSlotId( rAttr
.aSlotId
);
428 // read method arguments
430 tools::SvRef
<SvMetaType
> xT(new SvMetaType() );
431 xT
->SetRef(rAttr
.GetType() );
433 rAttr
.aType
->SetType( MetaTypeType::Method
);
438 tools::SvRef
<SvMetaAttribute
> xParamAttr( new SvMetaAttribute() );
439 xParamAttr
->aType
= ReadKnownType();
440 xParamAttr
->SetName( ReadIdentifier() );
441 ReadSlotId(xParamAttr
->aSlotId
);
442 rAttr
.aType
->GetAttrList().push_back( xParamAttr
.get() );
443 if (!ReadIfDelimiter())
450 void SvIdlParser::ReadSlotId(SvIdentifier
& rSlotId
)
452 rSlotId
.setString( ReadIdentifier() );
454 if( !rBase
.FindId( rSlotId
.getString(), &n
) )
455 throw SvParseException( rInStm
, "no value for identifier <" + rSlotId
.getString() + "> " );
459 SvMetaClass
* SvIdlParser::ReadKnownClass()
461 OString
aName(ReadIdentifier());
462 SvMetaClass
* pClass
= rBase
.FindKnownClass( aName
);
464 throw SvParseException( rInStm
, "unknown class" );
468 SvMetaType
* SvIdlParser::ReadKnownType()
470 OString aName
= ReadIdentifier();
471 for( const auto& aType
: rBase
.GetTypeList() )
473 if( aType
->GetName() == aName
)
476 throw SvParseException( rInStm
, "wrong typedef: ");
479 bool SvIdlParser::ReadIfBoolAttribute( SvBOOL
& rBool
, SvStringHashEntry
const * pName
)
481 sal_uInt32 nTokPos
= rInStm
.Tell();
482 SvToken
& rTok
= rInStm
.GetToken_Next();
484 if( rTok
.Is( pName
) )
486 if( rInStm
.ReadIf( '=' ) )
488 rTok
= rInStm
.GetToken();
490 throw SvParseException(rInStm
, "xxx");
491 rBool
= rTok
.GetBool();
492 rInStm
.GetToken_Next();
495 rBool
= true; //default action set to TRUE
498 rInStm
.Seek( nTokPos
);
502 void SvIdlParser::ReadIfIdAttribute( SvIdentifier
& rIdentifier
, SvStringHashEntry
const * pName
)
504 sal_uInt32 nTokPos
= rInStm
.Tell();
505 SvToken
& rTok
= rInStm
.GetToken_Next();
507 if( rTok
.Is( pName
) )
509 if( rInStm
.ReadIf( '=' ) )
511 rTok
= rInStm
.GetToken();
512 if( !rTok
.IsIdentifier() )
513 throw SvParseException(rInStm
, "expected identifier");
514 rIdentifier
.setString(rTok
.GetString());
515 rInStm
.GetToken_Next();
519 rInStm
.Seek( nTokPos
);
522 void SvIdlParser::ReadDelimiter()
524 if( !ReadIfDelimiter() )
525 throw SvParseException(rInStm
, "expected delimiter");
528 bool SvIdlParser::ReadIfDelimiter()
530 if( rInStm
.GetToken().IsChar()
531 && (';' == rInStm
.GetToken().GetChar()
532 || ',' == rInStm
.GetToken().GetChar()) )
534 rInStm
.GetToken_Next();
540 OString
SvIdlParser::ReadIdentifier()
542 SvToken
& rTok
= rInStm
.GetToken();
543 if( !rTok
.IsIdentifier() )
544 throw SvParseException("expected identifier", rTok
);
545 rInStm
.GetToken_Next();
546 return rTok
.GetString();
549 OString
SvIdlParser::ReadString()
551 SvToken
& rTok
= rInStm
.GetToken();
552 if( !rTok
.IsString() )
553 throw SvParseException("expected string", rTok
);
554 rInStm
.GetToken_Next();
555 return rTok
.GetString();
558 void SvIdlParser::Read(char cChar
)
561 throw SvParseException(rInStm
, "expected char '" + OStringChar(cChar
) + "'");
564 bool SvIdlParser::ReadIf(char cChar
)
566 if( rInStm
.GetToken().IsChar() && rInStm
.GetToken().GetChar() == cChar
)
568 rInStm
.GetToken_Next();
574 void SvIdlParser::Read(SvStringHashEntry
const * entry
)
576 if( !rInStm
.GetToken().Is(entry
) )
577 throw SvParseException("expected " + entry
->GetName(), rInStm
.GetToken());
578 rInStm
.GetToken_Next();
581 bool SvIdlParser::ReadIf(SvStringHashEntry
const * entry
)
583 if( rInStm
.GetToken().Is(entry
) )
585 rInStm
.GetToken_Next();
590 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */