fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / idl / source / prj / database.cxx
blob8cdf10d34213a3af36922939d9fc6a352f31c4c6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <tools/debug.hxx>
25 #include <database.hxx>
26 #include <globals.hxx>
27 #include <rtl/strbuf.hxx>
28 #include <osl/file.hxx>
30 SvIdlDataBase::SvIdlDataBase( const SvCommand& rCmd )
31 : bExport( false )
32 , nUniqueId( 0 )
33 , nVerbosity( rCmd.nVerbosity )
34 , pIdTable( NULL )
36 sSlotMapFile = rCmd.aSlotMapFile;
39 SvIdlDataBase::~SvIdlDataBase()
41 aIdFileList.clear();
43 delete pIdTable;
46 #define ADD_TYPE( Name, OdlName, ParserChar, CName, BasName, BasPost ) \
47 aTypeList.push_back( new SvMetaType( SvHash_##Name()->GetName(), \
48 BasName, OdlName, ParserChar, CName, BasName, BasPost ) );
50 SvMetaTypeMemberList & SvIdlDataBase::GetTypeList()
52 if( aTypeList.empty() )
53 { // fill initially
54 aTypeList.push_back( new SvMetaTypeString() );
55 aTypeList.push_back( new SvMetaTypevoid() );
57 // MI: IDispatch::Invoke can not unsigned
58 ADD_TYPE( UINT16, "long", 'h', "unsigned short", "Long", "&" );
59 ADD_TYPE( INT16, "short", 'h', "short", "Integer", "%" );
60 ADD_TYPE( UINT32, "long", 'l', "unsigned long", "Long", "&" );
61 ADD_TYPE( INT32, "long", 'l', "long", "Long", "&" );
62 ADD_TYPE( int, "int", 'i', "int", "Integer", "%" );
63 ADD_TYPE( BOOL, "boolean", 'b', "unsigned char", "Boolean", "" );
64 ADD_TYPE( char, "char", 'c', "char", "Integer", "%" );
65 ADD_TYPE( BYTE, "char", 'c', "unsigned char", "Integer", "%" );
66 ADD_TYPE( float, "float", 'f', "float", "Single", "!" );
67 ADD_TYPE( double, "double", 'F', "double", "Double", "#" );
68 ADD_TYPE( SbxObject, "VARIANT", 'o', "C_Object", "Object", "" );
70 // Attention! When adding types all binary data bases get incompatible
73 return aTypeList;
76 SvMetaModule * SvIdlDataBase::GetModule( const OString& rName )
78 for( sal_uLong n = 0; n < aModuleList.size(); n++ )
79 if( aModuleList[n]->GetName().getString().equals(rName) )
80 return aModuleList[n];
81 return NULL;
84 void SvIdlDataBase::SetError( const OString& rError, SvToken * pTok )
86 if( pTok->GetLine() > 10000 )
87 aError.SetText( "line count overflow" );
89 if( aError.nLine < pTok->GetLine()
90 || (aError.nLine == pTok->GetLine() && aError.nColumn < pTok->GetColumn()) )
92 aError = SvIdlError( pTok->GetLine(), pTok->GetColumn() );
93 aError.SetText( rError );
97 void SvIdlDataBase::Push( SvMetaObject * pObj )
99 GetStack().Push( pObj );
102 bool SvIdlDataBase::FindId( const OString& rIdName, sal_uLong * pVal )
104 if( pIdTable )
106 sal_uInt32 nHash;
107 if( pIdTable->Test( rIdName, &nHash ) )
109 *pVal = pIdTable->Get( nHash )->GetValue();
110 return true;
113 return false;
116 bool SvIdlDataBase::InsertId( const OString& rIdName, sal_uLong nVal )
118 if( !pIdTable )
119 pIdTable = new SvStringHashTable( 20003 );
121 sal_uInt32 nHash;
122 if( pIdTable->Insert( rIdName, &nHash ) )
124 pIdTable->Get( nHash )->SetValue( nVal );
125 return true;
127 return false;
130 bool SvIdlDataBase::ReadIdFile( const OUString & rFileName )
132 OUString aFullName;
133 osl::File::searchFileURL( rFileName, GetPath(), aFullName);
134 osl::FileBase::getSystemPathFromFileURL( aFullName, aFullName );
136 for ( size_t i = 0, n = aIdFileList.size(); i < n; ++i )
137 if ( aIdFileList[ i ] == rFileName )
138 return true;
140 aIdFileList.push_back( rFileName );
141 this->AddDepFile( aFullName );
142 SvTokenStream aTokStm( aFullName );
143 if( aTokStm.GetStream().GetError() == SVSTREAM_OK )
145 SvToken * pTok = aTokStm.GetToken_Next();
147 while( !pTok->IsEof() )
149 if( pTok->IsChar() && pTok->GetChar() == '#' )
151 pTok = aTokStm.GetToken_Next();
152 if( pTok->Is( SvHash_define() ) )
154 pTok = aTokStm.GetToken_Next();
155 OString aDefName;
156 if( pTok->IsIdentifier() )
157 aDefName = pTok->GetString();
158 else
160 OString aStr("unexpected token after define");
161 // set error
162 SetError( aStr, pTok );
163 WriteError( aTokStm );
164 return false;
167 sal_uLong nVal = 0;
168 bool bOk = true;
169 while( bOk )
171 pTok = aTokStm.GetToken_Next();
172 if( pTok->IsIdentifier() )
174 sal_uLong n;
175 if( FindId( pTok->GetString(), &n ) )
176 nVal += n;
177 else
178 bOk = false;
180 else if( pTok->IsChar() )
182 if( pTok->GetChar() == '-'
183 || pTok->GetChar() == '/'
184 || pTok->GetChar() == '*'
185 || pTok->GetChar() == '&'
186 || pTok->GetChar() == '|'
187 || pTok->GetChar() == '^'
188 || pTok->GetChar() == '~' )
190 OStringBuffer aStr("unknown operator '");
191 aStr.append(pTok->GetChar());
192 aStr.append("'in define");
193 // set error
194 SetError( aStr.makeStringAndClear(), pTok );
195 WriteError( aTokStm );
196 return false;
198 if( pTok->GetChar() != '+'
199 && pTok->GetChar() != '('
200 && pTok->GetChar() != ')' )
201 // only + is allowed, parentheses are immaterial
202 // because + is commutative
203 break;
205 else if( pTok->IsInteger() )
207 nVal += pTok->GetNumber();
209 else
210 break;
212 if( bOk )
214 if( !InsertId( aDefName, nVal ) )
216 OString aStr("hash table overflow: ");
217 SetError( aStr, pTok );
218 WriteError( aTokStm );
219 return false;
223 else if( pTok->Is( SvHash_include() ) )
225 pTok = aTokStm.GetToken_Next();
226 OStringBuffer aName;
227 if( pTok->IsString() )
228 aName.append(pTok->GetString());
229 else if( pTok->IsChar() && pTok->GetChar() == '<' )
231 pTok = aTokStm.GetToken_Next();
232 while( !pTok->IsEof()
233 && !(pTok->IsChar() && pTok->GetChar() == '>') )
235 aName.append(pTok->GetTokenAsString());
236 pTok = aTokStm.GetToken_Next();
238 if( pTok->IsEof() )
240 OString aStr("unexpected eof in #include");
241 // set error
242 SetError(aStr, pTok);
243 WriteError( aTokStm );
244 return false;
247 if (!ReadIdFile(OStringToOUString(aName.toString(),
248 RTL_TEXTENCODING_ASCII_US)))
250 OStringBuffer aStr("cannot read file: ");
251 aStr.append(aName.makeStringAndClear());
252 SetError(aStr.makeStringAndClear(), pTok);
253 WriteError( aTokStm );
254 return false;
258 else
259 pTok = aTokStm.GetToken_Next();
262 else
263 return false;
264 return true;
267 SvMetaType * SvIdlDataBase::FindType( const SvMetaType * pPType,
268 SvMetaTypeMemberList & rList )
270 for( SvMetaTypeMemberList::const_iterator it = rList.begin(); it != rList.end(); ++it )
271 if( *it == pPType )
272 return *it;
273 return NULL;
276 SvMetaType * SvIdlDataBase::FindType( const OString& rName )
278 for( SvMetaTypeMemberList::const_iterator it = aTypeList.begin(); it != aTypeList.end(); ++it )
279 if( rName.equals((*it)->GetName().getString()) )
280 return *it;
281 return NULL;
284 SvMetaType * SvIdlDataBase::ReadKnownType( SvTokenStream & rInStm )
286 bool bIn = false;
287 bool bOut = false;
288 int nCall0 = CALL_VALUE;
289 int nCall1 = CALL_VALUE;
290 bool bSet = false; // any attribute set
292 sal_uInt32 nTokPos = rInStm.Tell();
293 SvToken * pTok = rInStm.GetToken_Next();
295 if( pTok->HasHash() )
297 sal_uInt32 nBeginPos = 0; // can not happen with Tell
298 while( nBeginPos != rInStm.Tell() )
300 nBeginPos = rInStm.Tell();
301 if( pTok->Is( SvHash_in() ) )
303 bIn = true;
304 pTok = rInStm.GetToken_Next();
305 bSet = true;
307 if( pTok->Is( SvHash_out() ) )
309 bOut = true;
310 pTok = rInStm.GetToken_Next();
311 bSet = true;
313 if( pTok->Is( SvHash_inout() ) )
315 bIn = true;
316 bOut = true;
317 pTok = rInStm.GetToken_Next();
318 bSet = true;
323 if( pTok->IsIdentifier() )
325 OString aName = pTok->GetString();
326 SvMetaTypeMemberList & rList = GetTypeList();
327 SvMetaTypeMemberList::const_iterator it = rList.begin();
328 SvMetaType * pType = NULL;
329 while( it != rList.end() )
331 if( (*it)->GetName().getString().equals(aName) )
333 pType = *it;
334 break;
336 ++it;
338 if( pType )
340 pTok = rInStm.GetToken();
341 if( pTok->IsChar() )
343 if( pTok->GetChar() == '&' || pTok->GetChar() == '*' )
345 nCall0 = (pTok->GetChar() == '&') ? CALL_REFERENCE :
346 CALL_POINTER;
347 rInStm.GetToken_Next();
348 pTok = rInStm.GetToken();
349 if( pTok->GetChar() == '&' || pTok->GetChar() == '*' )
351 nCall1 = (pTok->GetChar() == '&') ? CALL_REFERENCE :
352 CALL_POINTER;
353 rInStm.GetToken_Next();
355 bSet = true;
359 if( !bSet )
360 // is exactly this type
361 return pType;
363 DBG_ASSERT( aTmpTypeList.front(), "mindestens ein Element" );
364 SvMetaTypeRef xType = new SvMetaType( pType->GetName().getString(), 'h', "dummy" );
365 xType->SetRef( pType );
366 xType->SetIn( bIn );
367 xType->SetOut( bOut );
368 xType->SetCall0( nCall0 );
369 xType->SetCall1( nCall1 );
371 aTmpTypeList.push_back( xType );
372 return xType;
375 rInStm.Seek( nTokPos );
376 return NULL;
379 SvMetaAttribute * SvIdlDataBase::ReadKnownAttr
381 SvTokenStream & rInStm,
382 SvMetaType * pType /* If pType == NULL, then the type has
383 still to be read. */
386 sal_uInt32 nTokPos = rInStm.Tell();
388 if( !pType )
389 pType = ReadKnownType( rInStm );
391 if( !pType )
393 // otherwise SlotId?
394 SvToken * pTok = rInStm.GetToken_Next();
395 if( pTok->IsIdentifier() )
397 sal_uLong n;
398 if( FindId( pTok->GetString(), &n ) )
400 for( sal_uLong i = 0; i < aAttrList.size(); i++ )
402 SvMetaAttribute * pAttr = aAttrList[i];
403 if( pAttr->GetSlotId().getString().equals(pTok->GetString()) )
404 return pAttr;
408 OStringBuffer aStr("Nicht gefunden : ");
409 aStr.append(pTok->GetString());
410 OSL_FAIL(aStr.getStr());
414 rInStm.Seek( nTokPos );
415 return NULL;
418 SvMetaAttribute* SvIdlDataBase::SearchKnownAttr
420 const SvNumberIdentifier& rId
423 sal_uLong n;
424 if( FindId( rId.getString(), &n ) )
426 for( sal_uLong i = 0; i < aAttrList.size(); i++ )
428 SvMetaAttribute * pAttr = aAttrList[i];
429 if( pAttr->GetSlotId().getString() == rId.getString() )
430 return pAttr;
434 return NULL;
437 SvMetaClass * SvIdlDataBase::ReadKnownClass( SvTokenStream & rInStm )
439 sal_uInt32 nTokPos = rInStm.Tell();
440 SvToken * pTok = rInStm.GetToken_Next();
442 if( pTok->IsIdentifier() )
443 for( sal_uLong n = 0; n < aClassList.size(); n++ )
445 SvMetaClass * pClass = aClassList[n];
446 if( pClass->GetName().getString().equals(pTok->GetString()) )
447 return pClass;
450 rInStm.Seek( nTokPos );
451 return NULL;
454 void SvIdlDataBase::Write(const OString& rText)
456 if( nVerbosity != 0 )
457 fprintf( stdout, "%s", rText.getStr() );
460 void SvIdlDataBase::WriteError( const OString& rErrWrn,
461 const OString& rFileName,
462 const OString& rErrorText,
463 sal_uLong nRow, sal_uLong nColumn )
465 // error treatment
466 fprintf( stderr, "\n%s --- %s: ( %ld, %ld )\n",
467 rFileName.getStr(), rErrWrn.getStr(), nRow, nColumn );
469 if( !rErrorText.isEmpty() )
470 { // error set
471 fprintf( stderr, "\t%s\n", rErrorText.getStr() );
475 void SvIdlDataBase::WriteError( SvTokenStream & rInStm )
477 // error treatment
478 OUString aFileName( rInStm.GetFileName() );
479 OStringBuffer aErrorText;
480 sal_uLong nRow = 0, nColumn = 0;
482 rInStm.SeekEnd();
483 SvToken *pTok = rInStm.GetToken();
485 // error position
486 nRow = pTok->GetLine();
487 nColumn = pTok->GetColumn();
489 if( aError.IsError() )
490 { // error set
491 // search error token
492 // error text
493 if( !aError.GetText().isEmpty() )
495 aErrorText.append("may be <");
496 aErrorText.append(aError.GetText());
498 SvToken * pPrevTok = NULL;
499 while( pTok != pPrevTok )
501 pPrevTok = pTok;
502 if( pTok->GetLine() == aError.nLine
503 && pTok->GetColumn() == aError.nColumn )
504 break;
505 pTok = rInStm.GetToken_PrevAll();
508 // error position
509 aErrorText.append("> at ( ");
510 aErrorText.append(static_cast<sal_Int64>(aError.nLine));
511 aErrorText.append(", ");
512 aErrorText.append(static_cast<sal_Int64>(aError.nColumn));
513 aErrorText.append(" )");
515 // reset error
516 aError = SvIdlError();
519 WriteError("error", OUStringToOString(aFileName,
520 RTL_TEXTENCODING_UTF8), aErrorText.makeStringAndClear(), nRow, nColumn);
522 DBG_ASSERT( pTok, "token must be found" );
523 if( !pTok )
524 return;
526 // look for identifier close by
527 if( !pTok->IsIdentifier() )
529 rInStm.GetToken_PrevAll();
530 pTok = rInStm.GetToken();
532 if( pTok && pTok->IsIdentifier() )
534 OString aN = IDLAPP->pHashTable->GetNearString( pTok->GetString() );
535 if( !aN.isEmpty() )
536 fprintf( stderr, "%s versus %s\n", pTok->GetString().getStr(), aN.getStr() );
540 SvIdlWorkingBase::SvIdlWorkingBase(const SvCommand& rCmd) : SvIdlDataBase(rCmd)
544 bool SvIdlWorkingBase::ReadSvIdl( SvTokenStream & rInStm, bool bImported, const OUString & rPath )
546 aPath = rPath; // only valid for this iteration
547 bool bOk = true;
548 SvToken * pTok = rInStm.GetToken();
549 // only one import at the very beginning
550 if( pTok->Is( SvHash_import() ) )
552 rInStm.GetToken_Next();
553 bOk = rInStm.Read( '(' ); // optional
554 pTok = bOk ? rInStm.GetToken_Next() : NULL;
555 if( pTok && pTok->IsString() )
557 OUString aFullName;
558 if( osl::FileBase::E_None == osl::File::searchFileURL(
559 OStringToOUString(pTok->GetString(), RTL_TEXTENCODING_ASCII_US),
560 rPath,
561 aFullName) )
563 osl::FileBase::getSystemPathFromFileURL( aFullName, aFullName );
564 this->AddDepFile(aFullName);
565 SvFileStream aStm( aFullName, STREAM_STD_READ | StreamMode::NOCREATE );
566 SvTokenStream aTokStm( aStm, aFullName );
567 bOk = ReadSvIdl( aTokStm, true, rPath );
569 else
570 bOk = false;
572 else
573 bOk = false;
576 sal_uInt32 nBeginPos = 0xFFFFFFFF; // can not happen with Tell
578 while( bOk && nBeginPos != rInStm.Tell() )
580 nBeginPos = rInStm.Tell();
581 pTok = rInStm.GetToken();
582 if( pTok->IsEof() )
583 return true;
584 if( pTok->IsEmpty() )
585 bOk = false;
587 // only one import at the very beginning
588 if( pTok->Is( SvHash_module() ) )
590 SvMetaModuleRef aModule = new SvMetaModule( rInStm.GetFileName(), bImported );
591 if( aModule->ReadSvIdl( *this, rInStm ) )
592 GetModuleList().push_back( aModule );
593 else
594 bOk = false;
596 else
597 bOk = false;
599 if( !bOk || !pTok->IsEof() )
601 // error treatment
602 WriteError( rInStm );
603 return false;
605 return true;
608 bool SvIdlWorkingBase::WriteSfx( SvStream & rOutStm )
610 if( rOutStm.GetError() != SVSTREAM_OK )
611 return false;
613 // reset all tmp variables for writing
614 WriteReset();
615 SvMemoryStream aTmpStm( 256000, 256000 );
616 sal_uLong n;
617 for( n = 0; n < GetModuleList().size(); n++ )
619 SvMetaModule * pModule = GetModuleList()[n];
620 if( !pModule->IsImported() )
621 pModule->WriteSfx( *this, aTmpStm );
622 aTmpStm.Seek( 0 );
624 for( n = 0; n < aUsedTypes.size(); n++ )
626 SvMetaType * pType = aUsedTypes[n];
627 pType->WriteSfx( *this, rOutStm );
629 aUsedTypes.clear();
630 rOutStm.WriteStream( aTmpStm );
631 return true;
634 void SvIdlDataBase::StartNewFile( const OUString& rName )
636 bExport = ( aExportFile.equalsIgnoreAsciiCase( rName ) );
639 void SvIdlDataBase::AppendAttr( SvMetaAttribute *pAttr )
641 aAttrList.push_back( pAttr );
642 if ( bExport )
643 pAttr->SetNewAttribute( true );
646 void SvIdlDataBase::AddDepFile(OUString const& rFileName)
648 m_DepFiles.insert(rFileName);
651 struct WriteDep
653 SvFileStream & m_rStream;
654 explicit WriteDep(SvFileStream & rStream) : m_rStream(rStream) { }
655 void operator() (OUString const& rItem)
657 m_rStream.WriteCharPtr( " \\\n " );
658 m_rStream.WriteCharPtr( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8).getStr() );
662 // write a dummy target for one included file, so the incremental build does
663 // not break with "No rule to make target" if the included file is removed
664 struct WriteDummy
666 SvFileStream & m_rStream;
667 explicit WriteDummy(SvFileStream & rStream) : m_rStream(rStream) { }
668 void operator() (OUString const& rItem)
670 m_rStream.WriteCharPtr( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8).getStr() );
671 m_rStream.WriteCharPtr( " :\n\n" );
675 bool SvIdlDataBase::WriteDepFile(
676 SvFileStream & rStream, OUString const& rTarget)
678 rStream.WriteCharPtr( OUStringToOString(rTarget, RTL_TEXTENCODING_UTF8).getStr() );
679 rStream.WriteCharPtr( " :" );
680 ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDep(rStream));
681 rStream.WriteCharPtr( "\n\n" );
682 ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDummy(rStream));
683 return rStream.GetError() == SVSTREAM_OK;
686 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */