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 <rtl/strbuf.hxx>
28 #include <osl/file.hxx>
31 SvParseException::SvParseException( SvTokenStream
const & rInStm
, const OString
& rError
)
33 SvToken
& rTok
= rInStm
.GetToken();
34 aError
= SvIdlError( rTok
.GetLine(), rTok
.GetColumn() );
35 aError
.SetText( rError
);
38 SvParseException::SvParseException( const OString
& rError
, SvToken
const & rTok
)
40 aError
= SvIdlError( rTok
.GetLine(), rTok
.GetColumn() );
41 aError
.SetText( rError
);
45 SvIdlDataBase::SvIdlDataBase( const SvCommand
& rCmd
)
48 , nVerbosity( rCmd
.nVerbosity
)
50 sSlotMapFile
= rCmd
.aSlotMapFile
;
53 SvIdlDataBase::~SvIdlDataBase()
58 #define ADD_TYPE( Name ) \
59 aTypeList.push_back( new SvMetaType( SvHash_##Name()->GetName() ) );
61 SvRefMemberList
<SvMetaType
*>& SvIdlDataBase::GetTypeList()
63 if( aTypeList
.empty() )
65 aTypeList
.push_back( new SvMetaTypeString() );
66 aTypeList
.push_back( new SvMetaTypevoid() );
68 // MI: IDispatch::Invoke can not unsigned
77 ADD_TYPE( SbxObject
);
79 // Attention! When adding types all binary data bases get incompatible
85 void SvIdlDataBase::SetError( const OString
& rError
, SvToken
const & rTok
)
87 if( rTok
.GetLine() > 10000 )
88 aError
.SetText( "line count overflow" );
90 if( aError
.nLine
< rTok
.GetLine()
91 || (aError
.nLine
== rTok
.GetLine() && aError
.nColumn
< rTok
.GetColumn()) )
93 aError
= SvIdlError( rTok
.GetLine(), rTok
.GetColumn() );
94 aError
.SetText( rError
);
98 void SvIdlDataBase::SetAndWriteError( SvTokenStream
& rInStm
, const OString
& rError
)
100 SetError( rError
, rInStm
.GetToken() );
101 WriteError( rInStm
);
104 void SvIdlDataBase::Push( SvMetaObject
* pObj
)
106 GetStack().push_back( pObj
);
109 bool SvIdlDataBase::FindId( const OString
& rIdName
, sal_uLong
* pVal
)
114 if( pIdTable
->Test( rIdName
, &nHash
) )
116 *pVal
= pIdTable
->Get( nHash
)->GetValue();
123 void SvIdlDataBase::InsertId( const OString
& rIdName
, sal_uLong nVal
)
126 pIdTable
.reset( new SvStringHashTable
);
129 pIdTable
->Insert( rIdName
, &nHash
)->SetValue( nVal
);
132 bool SvIdlDataBase::ReadIdFile( const OString
& rOFileName
)
134 OUString rFileName
= OStringToOUString(rOFileName
, RTL_TEXTENCODING_ASCII_US
);
136 osl::File::searchFileURL( rFileName
, GetPath(), aFullName
);
137 osl::FileBase::getSystemPathFromFileURL( aFullName
, aFullName
);
139 for ( size_t i
= 0, n
= aIdFileList
.size(); i
< n
; ++i
)
140 if ( aIdFileList
[ i
] == rFileName
)
143 aIdFileList
.push_back( rFileName
);
144 AddDepFile( aFullName
);
145 SvTokenStream
aTokStm( aFullName
);
146 if( aTokStm
.GetStream().GetError() != ERRCODE_NONE
)
149 SvToken
& rTok
= aTokStm
.GetToken_Next();
151 while( !rTok
.IsEof() )
153 if( rTok
.IsChar() && rTok
.GetChar() == '#' )
155 rTok
= aTokStm
.GetToken_Next();
156 if( rTok
.Is( SvHash_define() ) )
158 rTok
= aTokStm
.GetToken_Next();
160 if( !rTok
.IsIdentifier() )
161 throw SvParseException( "unexpected token after define", rTok
);
162 aDefName
= rTok
.GetString();
168 rTok
= aTokStm
.GetToken_Next();
169 if (rTok
.GetTokenAsString().startsWith("TypedWhichId"))
171 rTok
= aTokStm
.GetToken_Next();
172 if( !rTok
.IsChar() || rTok
.GetChar() != '<')
173 throw SvParseException( "expected '<'", rTok
);
174 rTok
= aTokStm
.GetToken_Next();
175 if( !rTok
.IsIdentifier() )
176 throw SvParseException( "expected identifier", rTok
);
177 rTok
= aTokStm
.GetToken_Next();
178 if( !rTok
.IsChar() || rTok
.GetChar() != '>')
179 throw SvParseException( "expected '<'", rTok
);
180 rTok
= aTokStm
.GetToken_Next();
182 else if( rTok
.IsIdentifier() )
185 if( FindId( rTok
.GetString(), &n
) )
190 else if( rTok
.IsChar() )
192 if( rTok
.GetChar() == '-'
193 || rTok
.GetChar() == '/'
194 || rTok
.GetChar() == '*'
195 || rTok
.GetChar() == '&'
196 || rTok
.GetChar() == '|'
197 || rTok
.GetChar() == '^'
198 || rTok
.GetChar() == '~' )
200 throw SvParseException( "unknown operator '" + OStringChar(rTok
.GetChar()) + "'in define", rTok
);
202 if( rTok
.GetChar() != '+'
203 && rTok
.GetChar() != '('
204 && rTok
.GetChar() != ')' )
205 // only + is allowed, parentheses are immaterial
206 // because + is commutative
209 else if( rTok
.IsInteger() )
211 nVal
+= rTok
.GetNumber();
218 InsertId( aDefName
, nVal
);
221 else if( rTok
.Is( SvHash_include() ) )
223 rTok
= aTokStm
.GetToken_Next();
224 OStringBuffer
aNameBuf(128);
225 if( rTok
.IsString() )
226 aNameBuf
.append(rTok
.GetString());
227 else if( rTok
.IsChar() && rTok
.GetChar() == '<' )
229 rTok
= aTokStm
.GetToken_Next();
231 && !(rTok
.IsChar() && rTok
.GetChar() == '>') )
233 aNameBuf
.append(rTok
.GetTokenAsString());
234 rTok
= aTokStm
.GetToken_Next();
238 throw SvParseException("unexpected eof in #include", rTok
);
241 OString
aName(aNameBuf
.makeStringAndClear());
242 if (aName
== "sfx2/groupid.hxx")
244 // contains C++ code which we cannot parse
245 // we special-case this by defining a macro internally in...
247 else if (aName
== "svl/typedwhich.hxx")
249 // contains C++ code which we cannot parse
251 else if (!ReadIdFile(aName
))
253 throw SvParseException("cannot read file: " + aName
, rTok
);
258 rTok
= aTokStm
.GetToken_Next();
263 SvMetaType
* SvIdlDataBase::FindType( const SvMetaType
* pPType
,
264 SvRefMemberList
<SvMetaType
*>& rList
)
266 for (auto const& elem
: rList
)
272 SvMetaType
* SvIdlDataBase::FindType( const OString
& rName
)
274 for (auto const& elem
: aTypeList
)
275 if( rName
== elem
->GetName() )
280 SvMetaType
* SvIdlDataBase::ReadKnownType( SvTokenStream
& rInStm
)
282 sal_uInt32 nTokPos
= rInStm
.Tell();
283 SvToken
& rTok
= rInStm
.GetToken_Next();
285 if( rTok
.IsIdentifier() )
287 const OString
& aName
= rTok
.GetString();
288 for( const auto& aType
: GetTypeList() )
290 if( aType
->GetName() == aName
)
296 rInStm
.Seek( nTokPos
);
300 SvMetaAttribute
* SvIdlDataBase::ReadKnownAttr
302 SvTokenStream
& rInStm
,
303 SvMetaType
* pType
/* If pType == NULL, then the type has
307 sal_uInt32 nTokPos
= rInStm
.Tell();
310 pType
= ReadKnownType( rInStm
);
315 SvToken
& rTok
= rInStm
.GetToken_Next();
316 if( rTok
.IsIdentifier() )
319 if( FindId( rTok
.GetString(), &n
) )
321 for( sal_uLong i
= 0; i
< aSlotList
.size(); i
++ )
323 SvMetaSlot
* pSlot
= aSlotList
[i
];
324 if( pSlot
->GetSlotId().getString() == rTok
.GetString() )
329 OStringBuffer
aStr("Not found : ");
330 aStr
.append(rTok
.GetString());
331 OSL_FAIL(aStr
.getStr());
335 rInStm
.Seek( nTokPos
);
339 SvMetaAttribute
* SvIdlDataBase::FindKnownAttr( const SvIdentifier
& rId
)
342 if( FindId( rId
.getString(), &n
) )
344 for( sal_uLong i
= 0; i
< aSlotList
.size(); i
++ )
346 SvMetaSlot
* pSlot
= aSlotList
[i
];
347 if( pSlot
->GetSlotId().getString() == rId
.getString() )
355 SvMetaClass
* SvIdlDataBase::ReadKnownClass( SvTokenStream
& rInStm
)
357 sal_uInt32 nTokPos
= rInStm
.Tell();
358 SvToken
& rTok
= rInStm
.GetToken_Next();
360 if( rTok
.IsIdentifier() )
362 SvMetaClass
* p
= FindKnownClass(rTok
.GetString());
367 rInStm
.Seek( nTokPos
);
371 SvMetaClass
* SvIdlDataBase::FindKnownClass( const OString
& aName
)
373 for( sal_uLong n
= 0; n
< aClassList
.size(); n
++ )
375 SvMetaClass
* pClass
= aClassList
[n
];
376 if( pClass
->GetName() == aName
)
382 void SvIdlDataBase::Write(const OString
& rText
) const
384 if( nVerbosity
!= 0 )
385 fprintf( stdout
, "%s", rText
.getStr() );
388 void SvIdlDataBase::WriteError( SvTokenStream
& rInStm
)
391 OUString
aFileName( rInStm
.GetFileName() );
392 OStringBuffer aErrorText
;
393 sal_uLong nRow
= 0, nColumn
= 0;
396 SvToken
& rTok
= rInStm
.GetToken();
399 nRow
= rTok
.GetLine();
400 nColumn
= rTok
.GetColumn();
402 if( aError
.IsError() )
404 // search error token
406 if( !aError
.GetText().isEmpty() )
408 aErrorText
.append("may be <");
409 aErrorText
.append(aError
.GetText());
411 SvToken
* pPrevTok
= nullptr;
412 while( &rTok
!= pPrevTok
)
415 if( rTok
.GetLine() == aError
.nLine
416 && rTok
.GetColumn() == aError
.nColumn
)
418 rTok
= rInStm
.GetToken_PrevAll();
422 aErrorText
.append("> at ( ");
423 aErrorText
.append(static_cast<sal_Int64
>(aError
.nLine
));
424 aErrorText
.append(", ");
425 aErrorText
.append(static_cast<sal_Int64
>(aError
.nColumn
));
426 aErrorText
.append(" )");
429 aError
= SvIdlError();
433 fprintf( stderr
, "\n%s --- %s: ( %" SAL_PRIuUINTPTR
", %" SAL_PRIuUINTPTR
" )\n",
434 OUStringToOString(aFileName
, RTL_TEXTENCODING_UTF8
).getStr(),
435 "error", nRow
, nColumn
);
437 if( !aErrorText
.isEmpty() )
439 fprintf( stderr
, "\t%s\n", aErrorText
.getStr() );
442 // look for identifier close by
443 if( !rTok
.IsIdentifier() )
445 rInStm
.GetToken_PrevAll();
446 rTok
= rInStm
.GetToken();
448 if( rTok
.IsIdentifier() )
450 OString aN
= GetIdlApp().pHashTable
->GetNearString( rTok
.GetString() );
452 fprintf( stderr
, "%s versus %s\n", rTok
.GetString().getStr(), aN
.getStr() );
456 SvIdlWorkingBase::SvIdlWorkingBase(const SvCommand
& rCmd
) : SvIdlDataBase(rCmd
)
461 bool SvIdlWorkingBase::WriteSfx( SvStream
& rOutStm
)
463 if( rOutStm
.GetError() != ERRCODE_NONE
)
466 // reset all tmp variables for writing
468 SvMemoryStream
aTmpStm( 256000, 256000 );
470 for( n
= 0; n
< GetModuleList().size(); n
++ )
472 SvMetaModule
* pModule
= GetModuleList()[n
];
473 pModule
->WriteSfx( *this, aTmpStm
);
476 for( n
= 0; n
< aUsedTypes
.size(); n
++ )
478 SvMetaType
* pType
= aUsedTypes
[n
];
479 pType
->WriteSfx( *this, rOutStm
);
482 rOutStm
.WriteStream( aTmpStm
);
486 void SvIdlDataBase::StartNewFile( const OUString
& rName
)
488 bExport
= aExportFile
.equalsIgnoreAsciiCase( rName
);
492 void SvIdlDataBase::AppendSlot( SvMetaSlot
*pSlot
)
494 aSlotList
.push_back( pSlot
);
498 void SvIdlDataBase::AddDepFile(OUString
const& rFileName
)
500 m_DepFiles
.insert(rFileName
);
505 SvFileStream
& m_rStream
;
506 explicit WriteDep(SvFileStream
& rStream
) : m_rStream(rStream
) { }
507 void operator() (OUString
const& rItem
)
509 m_rStream
.WriteCharPtr( " \\\n " );
510 m_rStream
.WriteOString( OUStringToOString(rItem
, RTL_TEXTENCODING_UTF8
) );
514 // write a dummy target for one included file, so the incremental build does
515 // not break with "No rule to make target" if the included file is removed
518 SvFileStream
& m_rStream
;
519 explicit WriteDummy(SvFileStream
& rStream
) : m_rStream(rStream
) { }
520 void operator() (OUString
const& rItem
)
522 m_rStream
.WriteOString( OUStringToOString(rItem
, RTL_TEXTENCODING_UTF8
) );
523 m_rStream
.WriteCharPtr( " :\n\n" );
527 void SvIdlDataBase::WriteDepFile(
528 SvFileStream
& rStream
, OUString
const& rTarget
)
530 rStream
.WriteOString( OUStringToOString(rTarget
, RTL_TEXTENCODING_UTF8
) );
531 rStream
.WriteCharPtr( " :" );
532 ::std::for_each(m_DepFiles
.begin(), m_DepFiles
.end(), WriteDep(rStream
));
533 rStream
.WriteCharPtr( "\n\n" );
534 ::std::for_each(m_DepFiles
.begin(), m_DepFiles
.end(), WriteDummy(rStream
));
537 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */