LibreOffice Module idl (master) 1
database.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <algorithm>
23#include <stdio.h>
24#include <string_view>
25
26#include <command.hxx>
27#include <database.hxx>
28#include <globals.hxx>
29#include <slot.hxx>
30#include <rtl/strbuf.hxx>
31#include <osl/file.hxx>
32
33
34SvParseException::SvParseException( SvTokenStream const & rInStm, const OString& rError )
35{
36 SvToken& rTok = rInStm.GetToken();
37 aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
38 aError.SetText( rError );
39};
40
41SvParseException::SvParseException( const OString& rError, SvToken const & rTok )
42{
43 aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
44 aError.SetText( rError );
45};
46
47
49 : bExport( false )
50 , nUniqueId( 0 )
51 , nVerbosity( rCmd.nVerbosity )
52{
53 sSlotMapFile = rCmd.aSlotMapFile;
54}
55
57{
58 aIdFileList.clear();
59}
60
61#define ADD_TYPE( Name ) \
62 aTypeList.push_back( new SvMetaType( SvHash_##Name()->GetName() ) );
63
65{
66 if( aTypeList.empty() )
67 { // fill initially
70
71 // MI: IDispatch::Invoke can not unsigned
72 ADD_TYPE( UINT16 );
73 ADD_TYPE( INT16 );
74 ADD_TYPE( UINT32 );
75 ADD_TYPE( INT32 );
76 ADD_TYPE( BOOL );
77 ADD_TYPE( BYTE );
78 ADD_TYPE( float );
79 ADD_TYPE( double );
81
82 // Attention! When adding types all binary data bases get incompatible
83
84 }
85 return aTypeList;
86}
87
88void SvIdlDataBase::SetError( const OString& rError, SvToken const & rTok )
89{
90 if( rTok.GetLine() > 10000 )
91 aError.SetText( "line count overflow" );
92
93 if( aError.nLine < rTok.GetLine()
94 || (aError.nLine == rTok.GetLine() && aError.nColumn < rTok.GetColumn()) )
95 {
96 aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
97 aError.SetText( rError );
98 }
99}
100
101void SvIdlDataBase::SetAndWriteError( SvTokenStream & rInStm, const OString& rError )
102{
103 SetError( rError, rInStm.GetToken() );
104 WriteError( rInStm );
105}
106
108{
109 GetStack().push_back( pObj );
110}
111
112bool SvIdlDataBase::FindId( const OString& rIdName, sal_uInt32 * pVal )
113{
114 if( pIdTable )
115 {
116 sal_uInt32 nHash;
117 if( pIdTable->Test( rIdName, &nHash ) )
118 {
119 *pVal = pIdTable->Get( nHash )->GetValue();
120 return true;
121 }
122 }
123 return false;
124}
125
126void SvIdlDataBase::InsertId( const OString& rIdName, sal_uInt32 nVal )
127{
128 if( !pIdTable )
129 pIdTable.reset( new SvStringHashTable );
130
131 sal_uInt32 nHash;
132 pIdTable->Insert( rIdName, &nHash )->SetValue( nVal );
133}
134
135bool SvIdlDataBase::ReadIdFile( std::string_view rOFileName )
136{
137 OUString rFileName = OStringToOUString(rOFileName, RTL_TEXTENCODING_ASCII_US);
138 OUString aFullName;
139 osl::File::searchFileURL( rFileName, GetPath(), aFullName);
140 osl::FileBase::getSystemPathFromFileURL( aFullName, aFullName );
141
142 for ( size_t i = 0, n = aIdFileList.size(); i < n; ++i )
143 if ( aIdFileList[ i ] == rFileName )
144 return true;
145
146 aIdFileList.push_back( rFileName );
147 AddDepFile( aFullName );
148 SvTokenStream aTokStm( aFullName );
149 if( aTokStm.GetStream().GetError() != ERRCODE_NONE )
150 return false;
151
152 SvToken& rTok = aTokStm.GetToken_Next();
153
154 while( !rTok.IsEof() )
155 {
156 if( rTok.IsChar() && rTok.GetChar() == '#' )
157 {
158 rTok = aTokStm.GetToken_Next();
159 if( rTok.Is( SvHash_define() ) )
160 {
161 rTok = aTokStm.GetToken_Next();
162 OString aDefName;
163 if( !rTok.IsIdentifier() )
164 throw SvParseException( "unexpected token after define", rTok );
165 aDefName = rTok.GetString();
166
167 sal_uInt32 nVal = 0;
168 bool bOk = true;
169 while( bOk )
170 {
171 rTok = aTokStm.GetToken_Next();
172 if (rTok.GetTokenAsString().startsWith("TypedWhichId"))
173 {
174 rTok = aTokStm.GetToken_Next();
175 if( !rTok.IsChar() || rTok.GetChar() != '<')
176 throw SvParseException( "expected '<'", rTok );
177 rTok = aTokStm.GetToken_Next();
178 if (rTok.IsChar() && rTok.GetChar() == ':')
179 {
180 // add support for "::avmedia::MediaItem" namespaced identifier
181 rTok = aTokStm.GetToken_Next();
182 if( !rTok.IsChar() || rTok.GetChar() != ':')
183 throw SvParseException( "expected ':'", rTok );
184 // the lexer reads "avmedia::MediaItem" as an identifier
185 rTok = aTokStm.GetToken_Next();
186 if( !rTok.IsIdentifier() )
187 throw SvParseException( "expected identifier", rTok );
188 }
189 else if( !rTok.IsIdentifier() )
190 throw SvParseException( "expected identifier", rTok );
191 rTok = aTokStm.GetToken_Next();
192 if( !rTok.IsChar() || rTok.GetChar() != '>')
193 throw SvParseException( "expected '<'", rTok );
194 rTok = aTokStm.GetToken_Next();
195 }
196 else if( rTok.IsIdentifier() )
197 {
198 sal_uInt32 n;
199 if( FindId( rTok.GetString(), &n ) )
200 nVal += n;
201 else
202 bOk = false;
203 }
204 else if( rTok.IsChar() )
205 {
206 if( rTok.GetChar() == '-'
207 || rTok.GetChar() == '/'
208 || rTok.GetChar() == '*'
209 || rTok.GetChar() == '&'
210 || rTok.GetChar() == '|'
211 || rTok.GetChar() == '^'
212 || rTok.GetChar() == '~' )
213 {
214 throw SvParseException( "unknown operator '" + OStringChar(rTok.GetChar()) + "'in define", rTok );
215 }
216 if( rTok.GetChar() != '+'
217 && rTok.GetChar() != '('
218 && rTok.GetChar() != ')' )
219 // only + is allowed, parentheses are immaterial
220 // because + is commutative
221 break;
222 }
223 else if( rTok.IsInteger() )
224 {
225 nVal += rTok.GetNumber();
226 }
227 else
228 break;
229 }
230 if( bOk )
231 {
232 InsertId( aDefName, nVal );
233 }
234 }
235 else if( rTok.Is( SvHash_include() ) )
236 {
237 rTok = aTokStm.GetToken_Next();
238 OStringBuffer aNameBuf(128);
239 if( rTok.IsString() )
240 aNameBuf.append(rTok.GetString());
241 else if( rTok.IsChar() && rTok.GetChar() == '<' )
242 {
243 rTok = aTokStm.GetToken_Next();
244 while( !rTok.IsEof()
245 && !(rTok.IsChar() && rTok.GetChar() == '>') )
246 {
247 aNameBuf.append(rTok.GetTokenAsString());
248 rTok = aTokStm.GetToken_Next();
249 }
250 if( rTok.IsEof() )
251 {
252 throw SvParseException("unexpected eof in #include", rTok);
253 }
254 }
255 OString aName(aNameBuf.makeStringAndClear());
256 if (aName == "sfx2/groupid.hxx")
257 {
258 // contains C++ code which we cannot parse
259 // we special-case this by defining a macro internally in...
260 }
261 else if (aName == "svl/typedwhich.hxx")
262 {
263 // contains C++ code which we cannot parse
264 }
265 else if (!ReadIdFile(aName))
266 {
267 throw SvParseException("cannot read file: " + aName, rTok);
268 }
269 }
270 }
271 else
272 rTok = aTokStm.GetToken_Next();
273 }
274 return true;
275}
276
279{
280 for (auto const& elem : rList)
281 if( elem == pPType )
282 return elem;
283 return nullptr;
284}
285
286SvMetaType * SvIdlDataBase::FindType( std::string_view rName )
287{
288 for (auto const& elem : aTypeList)
289 if( rName == elem->GetName() )
290 return elem;
291 return nullptr;
292}
293
295{
296 sal_uInt32 nTokPos = rInStm.Tell();
297 SvToken& rTok = rInStm.GetToken_Next();
298
299 if( rTok.IsIdentifier() )
300 {
301 const OString& aName = rTok.GetString();
302 for( const auto& aType : GetTypeList() )
303 {
304 if( aType->GetName() == aName )
305 {
306 return aType;
307 }
308 }
309 }
310 rInStm.Seek( nTokPos );
311 return nullptr;
312}
313
315(
316 SvTokenStream & rInStm,
317 SvMetaType * pType /* If pType == NULL, then the type has
318 still to be read. */
319)
320{
321 sal_uInt32 nTokPos = rInStm.Tell();
322
323 if( !pType )
324 pType = ReadKnownType( rInStm );
325
326 if( !pType )
327 {
328 // otherwise SlotId?
329 SvToken& rTok = rInStm.GetToken_Next();
330 if( rTok.IsIdentifier() )
331 {
332 sal_uInt32 n;
333 if( FindId( rTok.GetString(), &n ) )
334 {
335 for( size_t i = 0; i < aSlotList.size(); i++ )
336 {
337 SvMetaSlot * pSlot = aSlotList[i];
338 if( pSlot->GetSlotId().getString() == rTok.GetString() )
339 return pSlot;
340 }
341 }
342
343 OSL_FAIL(OString("Not found : " + rTok.GetString()).getStr());
344 }
345 }
346
347 rInStm.Seek( nTokPos );
348 return nullptr;
349}
350
352{
353 sal_uInt32 n;
354 if( FindId( rId.getString(), &n ) )
355 {
356 for( size_t i = 0; i < aSlotList.size(); i++ )
357 {
358 SvMetaSlot * pSlot = aSlotList[i];
359 if( pSlot->GetSlotId().getString() == rId.getString() )
360 return pSlot;
361 }
362 }
363
364 return nullptr;
365}
366
368{
369 sal_uInt32 nTokPos = rInStm.Tell();
370 SvToken& rTok = rInStm.GetToken_Next();
371
372 if( rTok.IsIdentifier() )
373 {
375 if (p)
376 return p;
377 }
378
379 rInStm.Seek( nTokPos );
380 return nullptr;
381}
382
384{
385 for( size_t n = 0; n < aClassList.size(); n++ )
386 {
387 SvMetaClass * pClass = aClassList[n];
388 if( pClass->GetName() == aName )
389 return pClass;
390 }
391 return nullptr;
392}
393
394void SvIdlDataBase::Write(const OString& rText) const
395{
396 if( nVerbosity != 0 )
397 fprintf( stdout, "%s", rText.getStr() );
398}
399
401{
402 // error treatment
403 OUString aFileName( rInStm.GetFileName() );
404 OStringBuffer aErrorText;
405 sal_uInt64 nRow = 0, nColumn = 0;
406
407 rInStm.SeekToMax();
408 SvToken& rTok = rInStm.GetToken();
409
410 // error position
411 nRow = rTok.GetLine();
412 nColumn = rTok.GetColumn();
413
414 if( aError.IsError() )
415 { // error set
416 // search error token
417 // error text
418 if( !aError.GetText().isEmpty() )
419 {
420 aErrorText.append("may be <" + aError.GetText());
421 }
422 SvToken * pPrevTok = nullptr;
423 while( &rTok != pPrevTok )
424 {
425 pPrevTok = &rTok;
426 if( rTok.GetLine() == aError.nLine
427 && rTok.GetColumn() == aError.nColumn )
428 break;
429 rTok = rInStm.GetToken_PrevAll();
430 }
431
432 // error position
433 aErrorText.append("> at ( "
434 + OString::number(static_cast<sal_Int64>(aError.nLine))
435 + ", "
436 + OString::number(static_cast<sal_Int64>(aError.nColumn))
437 + " )");
438
439 // reset error
440 aError = SvIdlError();
441 }
442
443 // error treatment
444 fprintf( stderr, "\n%s --- %s: ( %" SAL_PRIuUINT64 ", %" SAL_PRIuUINT64 " )\n",
445 OUStringToOString(aFileName, RTL_TEXTENCODING_UTF8).getStr(),
446 "error", nRow, nColumn );
447
448 if( !aErrorText.isEmpty() )
449 { // error set
450 fprintf( stderr, "\t%s\n", aErrorText.getStr() );
451 }
452
453 // look for identifier close by
454 if( !rTok.IsIdentifier() )
455 {
456 rInStm.GetToken_PrevAll();
457 rTok = rInStm.GetToken();
458 }
459 if( rTok.IsIdentifier() )
460 {
461 OString aN = GetIdlApp().pHashTable->GetNearString( rTok.GetString() );
462 if( !aN.isEmpty() )
463 fprintf( stderr, "%s versus %s\n", rTok.GetString().getStr(), aN.getStr() );
464 }
465}
466
468{
469}
470
471
473{
474 if( rOutStm.GetError() != ERRCODE_NONE )
475 return false;
476
477 // reset all tmp variables for writing
478 WriteReset();
479 SvMemoryStream aTmpStm( 256000, 256000 );
480 size_t n;
481 for( n = 0; n < GetModuleList().size(); n++ )
482 {
483 SvMetaModule * pModule = GetModuleList()[n];
484 pModule->WriteSfx( *this, aTmpStm );
485 aTmpStm.Seek( 0 );
486 }
487 for( n = 0; n < aUsedTypes.size(); n++ )
488 {
489 SvMetaType * pType = aUsedTypes[n];
490 pType->WriteSfx( *this, rOutStm );
491 }
493 rOutStm.WriteStream( aTmpStm );
494 return true;
495}
496
497void SvIdlDataBase::StartNewFile( std::u16string_view rName )
498{
499 bExport = aExportFile.equalsIgnoreAsciiCase( rName );
500 assert ( !bExport );
501}
502
504{
505 aSlotList.push_back( pSlot );
506 assert ( !bExport );
507}
508
509void SvIdlDataBase::AddDepFile(OUString const& rFileName)
510{
511 m_DepFiles.insert(rFileName);
512}
513
514namespace {
515
516struct WriteDep
517{
518 SvFileStream & m_rStream;
519 explicit WriteDep(SvFileStream & rStream) : m_rStream(rStream) { }
520 void operator() (std::u16string_view rItem)
521 {
522 m_rStream.WriteOString( " \\\n " );
523 m_rStream.WriteOString( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8) );
524 }
525};
526
527// write a dummy target for one included file, so the incremental build does
528// not break with "No rule to make target" if the included file is removed
529struct WriteDummy
530{
531 SvFileStream & m_rStream;
532 explicit WriteDummy(SvFileStream & rStream) : m_rStream(rStream) { }
533 void operator() (std::u16string_view rItem)
534 {
535 m_rStream.WriteOString( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8) );
536 m_rStream.WriteOString( " :\n\n" );
537 }
538};
539
540}
541
543 SvFileStream & rStream, std::u16string_view rTarget)
544{
545 rStream.WriteOString( OUStringToOString(rTarget, RTL_TEXTENCODING_UTF8) );
546 rStream.WriteOString( " :" );
547 ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDep(rStream));
548 rStream.WriteOString( "\n\n" );
549 ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDummy(rStream));
550}
551
552/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< SvStringHashTable > pHashTable
Definition: globals.hxx:71
const OString & getString() const
Definition: bastype.hxx:57
std::unique_ptr< SvStringHashTable > pIdTable
Definition: database.hxx:67
SvRefMemberList< SvMetaObject * > & GetStack()
Definition: database.hxx:106
SvMetaAttribute * FindKnownAttr(const SvIdentifier &)
Definition: database.cxx:351
void SetAndWriteError(SvTokenStream &rInStm, const OString &rError)
Definition: database.cxx:101
SvMetaClass * ReadKnownClass(SvTokenStream &rInStm)
Definition: database.cxx:367
void AppendSlot(SvMetaSlot *pSlot)
Definition: database.cxx:503
SvRefMemberList< SvMetaModule * > & GetModuleList()
Definition: database.hxx:91
void Push(SvMetaObject *pObj)
Definition: database.cxx:107
const OUString & GetPath() const
Definition: database.hxx:104
sal_uInt32 nVerbosity
Definition: database.hxx:65
SvIdlDataBase(const SvCommand &rCmd)
Definition: database.cxx:48
SvIdlError aError
Definition: database.hxx:78
void WriteDepFile(SvFileStream &rStream, std::u16string_view rTarget)
Definition: database.cxx:542
SvMetaAttribute * ReadKnownAttr(SvTokenStream &rInStm, SvMetaType *pType)
Definition: database.cxx:315
std::vector< OUString > aIdFileList
Definition: database.hxx:66
SvRefMemberList< SvMetaType * > & GetTypeList()
Definition: database.cxx:64
SvRefMemberList< SvMetaType * > aUsedTypes
Definition: database.hxx:94
OUString sSlotMapFile
Definition: database.hxx:84
void SetError(const SvIdlError &r)
Definition: database.hxx:101
void StartNewFile(std::u16string_view rName)
Definition: database.cxx:497
void WriteError(SvTokenStream &rInStm)
Definition: database.cxx:400
SvRefMemberList< SvMetaSlot * > aSlotList
Definition: database.hxx:72
void WriteReset()
Definition: database.hxx:79
OUString aExportFile
Definition: database.hxx:63
void Write(const OString &rText) const
Definition: database.cxx:394
SvMetaType * FindType(std::string_view rName)
Definition: database.cxx:286
void AddDepFile(OUString const &rFileName)
Definition: database.cxx:509
SvRefMemberList< SvMetaClass * > aClassList
Definition: database.hxx:70
bool FindId(const OString &rIdName, sal_uInt32 *pVal)
Definition: database.cxx:112
SvMetaType * ReadKnownType(SvTokenStream &rInStm)
Definition: database.cxx:294
SvRefMemberList< SvMetaType * > aTypeList
Definition: database.hxx:69
void InsertId(const OString &rIdName, sal_uInt32 nVal)
Definition: database.cxx:126
SvMetaClass * FindKnownClass(std::string_view aName)
Definition: database.cxx:383
bool ReadIdFile(std::string_view rFileName)
Definition: database.cxx:135
::std::set< OUString > m_DepFiles
Definition: database.hxx:76
const OString & GetText() const
Definition: database.hxx:45
sal_uInt32 nColumn
Definition: database.hxx:39
sal_uInt32 nLine
Definition: database.hxx:39
bool IsError() const
Definition: database.hxx:47
void SetText(const OString &rT)
Definition: database.hxx:46
SvIdlWorkingBase(const SvCommand &rCmd)
Definition: database.cxx:467
bool WriteSfx(SvStream &)
Definition: database.cxx:472
const SvIdentifier & GetSlotId() const
Definition: types.cxx:45
void WriteSfx(SvIdlDataBase &rBase, SvStream &rOutStm)
Definition: module.cxx:25
const OString & GetName() const override
Definition: basobj.hxx:112
virtual void WriteSfx(SvIdlDataBase &rBase, SvStream &rOutStm)
Definition: types.cxx:274
SvIdlError aError
Definition: database.hxx:53
SvParseException(SvTokenStream const &rInStm, const OString &rError)
Definition: database.cxx:34
void clear()
Definition: basobj.hxx:51
void push_back(T p)
Definition: basobj.hxx:62
SvStream & WriteOString(std::string_view rStr)
sal_uInt64 Seek(sal_uInt64 nPos)
ErrCode GetError() const
SvStream & WriteStream(SvStream &rStream)
SvStream & GetStream()
Definition: lex.hxx:152
void Seek(sal_uInt32 nPos)
Definition: lex.hxx:202
SvToken & GetToken() const
Definition: lex.hxx:177
SvToken & GetToken_PrevAll()
Definition: lex.hxx:154
SvToken & GetToken_Next()
Definition: lex.hxx:165
void SeekToMax()
Definition: lex.hxx:208
const OUString & GetFileName() const
Definition: lex.hxx:151
sal_uInt32 Tell() const
Definition: lex.hxx:200
Definition: lex.hxx:36
sal_uInt64 GetColumn() const
Definition: lex.hxx:60
sal_uInt64 GetLine() const
Definition: lex.hxx:57
bool IsChar() const
Definition: lex.hxx:73
OString GetTokenAsString() const
Definition: lex.cxx:27
bool IsString() const
Definition: lex.hxx:64
sal_uInt64 GetNumber() const
Definition: lex.hxx:82
bool Is(SvStringHashEntry const *pEntry) const
Definition: lex.hxx:88
bool IsEof() const
Definition: lex.hxx:74
char GetChar() const
Definition: lex.hxx:84
bool IsIdentifier() const
Definition: lex.hxx:68
bool IsInteger() const
Definition: lex.hxx:63
const OString & GetString() const
Definition: lex.hxx:76
#define ADD_TYPE(Name)
Definition: database.cxx:61
#define ERRCODE_NONE
FilterGroup & rTarget
IdlDll & GetIdlApp()
Definition: globals.cxx:24
OUString aName
void * p
sal_Int64 n
int i
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
const wchar_t *typedef BOOL
unsigned char BYTE