Line data Source code
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 <stdlib.h>
21 : #include <stdio.h>
22 : #include <fcntl.h>
23 :
24 : #ifdef UNX
25 : #include <unistd.h>
26 : #include <sys/wait.h>
27 : #include <sys/stat.h>
28 : #else
29 : #include <io.h>
30 : #include <process.h>
31 : #include <direct.h>
32 : #endif
33 :
34 : #include <string.h>
35 : #include <ctype.h>
36 : #include <errno.h>
37 :
38 : #include <tools/stream.hxx>
39 : #include <rscerror.h>
40 : #include <rsctop.hxx>
41 : #include <rscdb.hxx>
42 : #include <rscpar.hxx>
43 : #include <rscrsc.hxx>
44 : #include <rschash.hxx>
45 :
46 : #include <osl/file.h>
47 : #include <osl/file.hxx>
48 : #include <osl/process.h>
49 : #include <rtl/strbuf.hxx>
50 : #include <rtl/tencinfo.h>
51 : #include <rtl/textenc.h>
52 : #include <comphelper/string.hxx>
53 :
54 : #include <vector>
55 : #include <algorithm>
56 :
57 : using comphelper::string::getToken;
58 : using comphelper::string::getTokenCount;
59 :
60 : OString* pStdParType = NULL;
61 : OString* pStdPar1 = NULL;
62 : OString* pStdPar2 = NULL;
63 : OString* pWinParType = NULL;
64 : OString* pWinPar1 = NULL;
65 : OString* pWinPar2 = NULL;
66 : sal_uInt32 nRefDeep = 10;
67 : AtomContainer* pHS = NULL;
68 :
69 :
70 419 : void RscCmdLine::Init()
71 : {
72 419 : nCommands = 0;
73 419 : nByteOrder = RSC_BIGENDIAN;
74 :
75 419 : aPath = OString(".");
76 419 : m_aOutputFiles.clear();
77 419 : m_aOutputFiles.push_back( OutputFile() );
78 419 : }
79 :
80 419 : RscCmdLine::RscCmdLine( int argc, char ** argv, RscError * pEH )
81 : {
82 : char * pStr;
83 : char ** ppStr;
84 419 : RscPtrPtr aCmdLine;
85 : sal_uInt32 i;
86 419 : bool bOutputSrsIsSet = false;
87 :
88 419 : Init();
89 :
90 419 : pStr = ::ResponseFile( &aCmdLine, argv, argc );
91 419 : if( pStr )
92 0 : pEH->FatalError( ERR_OPENFILE, RscId(), pStr );
93 :
94 : /* check the inputted switches */
95 419 : ppStr = (char **)aCmdLine.GetBlock();
96 419 : ppStr++;
97 419 : i = 1;
98 11140 : while( ppStr && i < (aCmdLine.GetCount() -1) )
99 : {
100 : #if OSL_DEBUG_LEVEL > 1
101 : fprintf( stderr, "CmdLineArg: \"%s\"\n", *ppStr );
102 : #endif
103 10302 : if (strcmp(*ppStr, "-isystem") == 0)
104 : {
105 : // ignore "-isystem" and following arg
106 0 : if (i < aCmdLine.GetCount() - 1)
107 : {
108 0 : ++ppStr;
109 0 : ++i;
110 : }
111 : }
112 10302 : else if (strncmp(*ppStr, "-isystem", strlen("-isystem")) == 0)
113 : {
114 : // ignore args starting with "-isystem"
115 : }
116 10302 : else if( '-' == **ppStr )
117 : {
118 19766 : if( !rsc_stricmp( (*ppStr) + 1, "h" )
119 9883 : || !strcmp( (*ppStr) + 1, "?" ) )
120 : { // Write help to standard output
121 0 : nCommands |= HELP_FLAG;
122 : }
123 9883 : else if( !rsc_stricmp( (*ppStr) + 1, "p" ) )
124 : { // No preprocessor
125 56 : nCommands |= NOPREPRO_FLAG;
126 : }
127 9827 : else if( !rsc_stricmp( (*ppStr) + 1, "s" ) )
128 : { // Syntax analysis, creates .srs file
129 363 : nCommands |= NOLINK_FLAG;
130 : }
131 9464 : else if( !rsc_stricmp( (*ppStr) + 1, "l" ) )
132 : { // Linken, keine Syntax und kein Prepro
133 0 : nCommands |= NOPREPRO_FLAG;
134 0 : nCommands |= NOSYNTAX_FLAG;
135 : }
136 9464 : else if( !rsc_stricmp( (*ppStr) + 1, "r" ) )
137 : { // erzeugt kein .res-file
138 0 : nCommands |= NORESFILE_FLAG;
139 : }
140 9464 : else if( !rsc_strnicmp( (*ppStr) + 1, "sub", 3 ) )
141 : {
142 : const char* pEqual;
143 112 : for( pEqual = (*ppStr)+4; *pEqual && *pEqual != '='; ++pEqual )
144 : ;
145 112 : if( *pEqual )
146 : {
147 112 : m_aReplacements.push_back( std::pair< OString, OString >( OString( (*ppStr)+4, pEqual - *ppStr - 4 ),
148 224 : OString( pEqual + 1 ) ) );
149 : }
150 : }
151 9352 : else if( !rsc_stricmp( (*ppStr) + 1, "PreLoad" ) )
152 : { // Alle Resourcen mit Preload
153 0 : nCommands |= PRELOAD_FLAG;
154 : }
155 9352 : else if( !rsc_stricmp( (*ppStr) + 1, "LITTLEENDIAN" ) )
156 : { // Byte Ordnung beim Schreiben
157 0 : nByteOrder = RSC_LITTLEENDIAN;
158 : }
159 9352 : else if( !rsc_stricmp( (*ppStr) + 1, "BIGENDIAN" ) )
160 : { // Byte Ordnung beim Schreiben
161 0 : nByteOrder = RSC_BIGENDIAN;
162 : }
163 9352 : else if( !rsc_strnicmp( (*ppStr) + 1, "d", 1 ) )
164 : { // Symbole definieren
165 3993 : nCommands |= DEFINE_FLAG;
166 : }
167 5359 : else if( !rsc_strnicmp( (*ppStr) + 1, "i", 1 ) )
168 : { // define include path
169 4324 : nCommands |= INCLUDE_FLAG;
170 4324 : OStringBuffer aBuffer(aPath);
171 4324 : if (!aBuffer.isEmpty())
172 4324 : aBuffer.append(SAL_PATHSEPARATOR);
173 4324 : aBuffer.append((*ppStr) + 2);
174 4324 : aPath = aBuffer.makeStringAndClear();
175 : }
176 1035 : else if( !rsc_strnicmp( (*ppStr) + 1, "fs=", 3 ) )
177 : { // define name of .res file
178 56 : if( m_aOutputFiles.back().aOutputRc.getLength() )
179 0 : m_aOutputFiles.push_back( OutputFile() );
180 56 : m_aOutputFiles.back().aOutputRc = (*ppStr) + 4;
181 : }
182 979 : else if( !rsc_strnicmp( (*ppStr) + 1, "lip=", 4 ) )
183 : { // additional language specific include for system dependent files
184 448 : const OString aSysSearchDir( (*ppStr)+5 );
185 :
186 : // ignore empty -lip= arguments that we get lots of these days
187 448 : if (!aSysSearchDir.isEmpty())
188 : {
189 448 : m_aOutputFiles.back().aSysSearchDirs.push_back(aSysSearchDir);
190 448 : OString aLangSearchPath = m_aOutputFiles.back().aLangSearchPath;
191 448 : if( !aLangSearchPath.isEmpty() )
192 : {
193 392 : aLangSearchPath = aLangSearchPath + OString( SAL_PATHSEPARATOR );
194 : }
195 448 : aLangSearchPath = aLangSearchPath + aSysSearchDir;
196 :
197 448 : m_aOutputFiles.back().aLangSearchPath = aLangSearchPath;
198 448 : }
199 : }
200 531 : else if( !rsc_strnicmp( (*ppStr) + 1, "fp=", 3 ) )
201 : { // define name of .srs file
202 419 : aOutputSrs = (*ppStr) + 4;
203 419 : bOutputSrsIsSet = true;
204 : }
205 112 : else if( !rsc_strnicmp( (*ppStr) + 1, "oil=", 4 ) )
206 : {
207 56 : aILDir = (*ppStr) + 5;
208 : }
209 56 : else if( !rsc_stricmp( (*ppStr) + 1, "NoSysResTest" ) )
210 : { // Bitmap, Pointers, Icons nicht ueberpruefen
211 0 : nCommands |= NOSYSRESTEST_FLAG;
212 : }
213 56 : else if( !rsc_stricmp( (*ppStr) + 1, "SrsDefault" ) )
214 : { // Only write one language to srs file
215 0 : nCommands |= SRSDEFAULT_FLAG;
216 : }
217 56 : else if( !rsc_stricmp( (*ppStr) + 1, "lg" ) )
218 : {
219 0 : m_aOutputFiles.back().aLangName = OString();
220 : }
221 56 : else if( !rsc_strnicmp( (*ppStr) + 1, "lg", 2 ) )
222 : {
223 56 : if( !m_aOutputFiles.back().aLangName.isEmpty() )
224 0 : m_aOutputFiles.push_back( OutputFile() );
225 56 : m_aOutputFiles.back().aLangName = OString((*ppStr)+3);
226 : }
227 : else
228 0 : pEH->FatalError( ERR_UNKNOWNSW, RscId(), *ppStr );
229 : }
230 : else
231 : {
232 : // Eingabedatei
233 419 : aInputList.push_back( new OString(*ppStr) );
234 : }
235 10302 : ppStr++;
236 10302 : i++;
237 : }
238 :
239 419 : if( nCommands & HELP_FLAG )
240 0 : pEH->FatalError( ERR_USAGE, RscId() );
241 : // was an inputted file specified
242 419 : else if( !aInputList.empty() )
243 : {
244 419 : ::std::list<OutputFile>::iterator it;
245 838 : for( it = m_aOutputFiles.begin(); it != m_aOutputFiles.end(); ++it )
246 : {
247 419 : if( it->aOutputRc.isEmpty() )
248 363 : it->aOutputRc = ::OutputFile( *aInputList.front(), "rc" );
249 : }
250 419 : if( ! bOutputSrsIsSet )
251 0 : aOutputSrs = ::OutputFile( *aInputList.front(), "srs" );
252 : }
253 : else
254 0 : pEH->FatalError( ERR_NOINPUT, RscId() );
255 419 : }
256 :
257 838 : RscCmdLine::~RscCmdLine()
258 : {
259 838 : for ( size_t i = 0, n = aInputList.size(); i < n; ++i )
260 419 : delete aInputList[ i ];
261 419 : aInputList.clear();
262 419 : }
263 :
264 1672 : OString RscCmdLine::substitutePaths( const OString& rIn )
265 : {
266 : // prepare return value
267 1672 : OStringBuffer aRet( 256 );
268 1672 : std::list< std::pair< OString, OString > >::const_iterator last_match = m_aReplacements.end();
269 :
270 : // search for longest replacement match
271 5016 : for( std::list< std::pair< OString, OString > >::const_iterator repl = m_aReplacements.begin(); repl != m_aReplacements.end(); ++repl )
272 : {
273 3344 : if( rIn.startsWith( repl->second ) ) // path matches
274 : {
275 2059 : if( last_match == m_aReplacements.end() || last_match->second.getLength() < repl->second.getLength() )
276 2059 : last_match = repl;
277 : }
278 : }
279 :
280 : // copy replacement found and rest of rIn
281 1672 : sal_Int32 nIndex = 0;
282 1672 : if( last_match != m_aReplacements.end() )
283 : {
284 1672 : aRet.append( "%" );
285 1672 : aRet.append( last_match->first );
286 1672 : aRet.append( "%" );
287 1672 : nIndex = last_match->second.getLength();
288 : }
289 :
290 1672 : if( rIn.match( "/", nIndex ) )
291 387 : aRet.append( rIn.copy( nIndex ) );
292 : else
293 1285 : aRet.append( rIn.copy( nIndex - 1 ) );
294 :
295 1672 : return aRet.makeStringAndClear();
296 : }
297 :
298 419 : RscCompiler::RscCompiler( RscCmdLine * pLine, RscTypCont * pTypCont )
299 : {
300 419 : fListing = NULL;
301 419 : fExitFile = NULL;
302 :
303 : //Set Command Line, set Type Container
304 419 : pCL = pLine;
305 419 : pTC = pTypCont;
306 419 : }
307 :
308 419 : RscCompiler::~RscCompiler()
309 : {
310 419 : pTC->pEH->SetListFile( NULL );
311 :
312 419 : if( fListing )
313 0 : fclose( fListing );
314 :
315 419 : if( fExitFile )
316 0 : fclose( fExitFile );
317 419 : }
318 :
319 419 : ERRTYPE RscCompiler::Start()
320 : {
321 419 : ERRTYPE aError;
322 : RscFile* pFName;
323 :
324 419 : if( pCL->aInputList.empty() )
325 0 : pTC->pEH->FatalError( ERR_NOINPUT, RscId() );
326 :
327 838 : for( size_t i = 0, n = pCL->aInputList.size(); i < n; ++i )
328 419 : pTC->aFileTab.NewCodeFile( *pCL->aInputList[ i ] );
329 :
330 419 : if( !(pCL->nCommands & NOSYNTAX_FLAG) )
331 : {
332 419 : if( pCL->nCommands & NOPREPRO_FLAG )
333 : {
334 :
335 56 : pTC->pEH->SetListFile( NULL );
336 :
337 56 : sal_uIntPtr aIndex = pTC->aFileTab.FirstIndex();
338 168 : while( aIndex != UNIQUEINDEX_ENTRY_NOTFOUND && aError.IsOk() )
339 : {
340 56 : pFName = pTC->aFileTab.Get( aIndex );
341 56 : if( !pFName->bScanned && !pFName->IsIncFile() )
342 : {
343 56 : aError = IncludeParser( aIndex );
344 : // Currentzeiger richtig setzen
345 56 : aIndex = pTC->aFileTab.GetIndexOf( pFName );
346 : }
347 56 : aIndex = pTC->aFileTab.NextIndex( aIndex );
348 : }
349 :
350 56 : pTC->pEH->SetListFile( fListing );
351 : }
352 : }
353 :
354 419 : if ( pTC->pEH->GetVerbosity() >= RscVerbosityVerbose )
355 : {
356 0 : pTC->pEH->StdOut( "Files: " );
357 0 : sal_uIntPtr aIndex = pTC->aFileTab.FirstIndex();
358 0 : while( aIndex != UNIQUEINDEX_ENTRY_NOTFOUND )
359 : {
360 0 : pFName = pTC->aFileTab.Get( aIndex );
361 0 : pTC->pEH->StdOut( pFName->aFileName.getStr() );
362 0 : pTC->pEH->StdOut( " " );
363 0 : aIndex = pTC->aFileTab.NextIndex( aIndex );
364 : }
365 0 : pTC->pEH->StdOut( "\n" );
366 : }
367 :
368 419 : if( aError.IsOk() )
369 419 : aError = Link();
370 :
371 419 : if( aError.IsOk() )
372 419 : EndCompile();
373 :
374 419 : if( aError.IsError() )
375 0 : pTC->pEH->Error( ERR_ERROR, NULL, RscId() );
376 :
377 419 : return aError;
378 : }
379 :
380 419 : void RscCompiler::EndCompile()
381 : {
382 419 : if( !pCL->aOutputSrs.isEmpty() && (pCL->nCommands & NOLINK_FLAG) )
383 : {
384 363 : pTC->pEH->StdOut( "Writing file ", RscVerbosityVerbose );
385 363 : pTC->pEH->StdOut( pCL->aOutputSrs.getStr(), RscVerbosityVerbose );
386 363 : pTC->pEH->StdOut( ".\n", RscVerbosityVerbose );
387 :
388 : // kopiere von TMP auf richtigen Namen
389 363 : unlink( pCL->aOutputSrs.getStr() ); // Zieldatei loeschen
390 363 : if( !(pCL->nCommands & NOSYNTAX_FLAG) )
391 : {
392 : FILE * foutput;
393 : RscFile * pFN;
394 :
395 363 : if( NULL == (foutput = fopen( pCL->aOutputSrs.getStr(), "w" )) )
396 0 : pTC->pEH->FatalError( ERR_OPENFILE, RscId(), pCL->aOutputSrs.getStr() );
397 : else
398 : {
399 : // Schreibe Datei
400 363 : sal_uIntPtr aIndex = pTC->aFileTab.FirstIndex();
401 726 : while( aIndex != UNIQUEINDEX_ENTRY_NOTFOUND )
402 : {
403 363 : pFN = pTC->aFileTab.Get( aIndex );
404 363 : if( !pFN->IsIncFile() )
405 : {
406 363 : pTC->WriteSrc( foutput, NOFILE_INDEX, false );
407 363 : break; // ?T 281091MM nur eine Src-Datei
408 : }
409 : }
410 :
411 363 : fclose( foutput );
412 : }
413 : }
414 : }
415 419 : }
416 :
417 56 : ERRTYPE RscCompiler :: IncludeParser( sal_uLong lFileKey )
418 : {
419 : FILE * finput;
420 : RscFile * pFName;
421 56 : ERRTYPE aError;
422 :
423 56 : pFName = pTC->aFileTab.Get( lFileKey );
424 56 : if( !pFName )
425 0 : aError = ERR_ERROR;
426 56 : else if( !pFName->bScanned )
427 : {
428 56 : finput = fopen( pFName->aPathName.getStr(), "r" );
429 56 : if( !finput )
430 : {
431 0 : aError = ERR_OPENFILE;
432 : pTC->pEH->Error( aError, NULL, RscId(),
433 0 : pFName->aPathName.getStr() );
434 : }
435 : else
436 : {
437 56 : RscFileInst aFileInst( pTC, lFileKey, lFileKey, finput );
438 :
439 56 : pFName->bScanned = true;
440 56 : ::IncludeParser( &aFileInst );
441 56 : fclose( finput );
442 :
443 : // Include-Pfad durchsuchen
444 112 : for ( size_t i = 0, n = pFName->aDepLst.size(); i < n; ++i )
445 : {
446 56 : RscDepend * pDep = pFName->aDepLst[ i ];
447 56 : pTC->aFileTab.GetFile( pDep->GetFileKey() );
448 : }
449 :
450 112 : for ( size_t i = 0, n = pFName->aDepLst.size(); i < n; ++i )
451 : {
452 56 : RscDepend * pDep = pFName->aDepLst[ i ];
453 56 : RscFile * pFNTmp = pTC->aFileTab.GetFile( pDep->GetFileKey() );
454 : // Kein Pfad und Include Datei
455 56 : if( pFNTmp && !pFNTmp->bLoaded )
456 : {
457 56 : pFNTmp->aPathName = pFNTmp->aFileName;
458 : }
459 56 : };
460 : };
461 : };
462 :
463 56 : return aError;
464 : }
465 :
466 1202 : ERRTYPE RscCompiler :: ParseOneFile( sal_uLong lFileKey,
467 : const RscCmdLine::OutputFile* pOutputFile,
468 : const WriteRcContext* pContext )
469 : {
470 1202 : FILE * finput = NULL;
471 1202 : ERRTYPE aError;
472 : RscFile * pFName;
473 :
474 1202 : pFName = pTC->aFileTab.Get( lFileKey );
475 1202 : if( !pFName )
476 0 : aError = ERR_ERROR;
477 1202 : else if( !pFName->bLoaded )
478 : {
479 : RscDepend * pDep;
480 :
481 : //Include-Dateien vorher lesen
482 419 : pFName->bLoaded = true; //Endlos Rekursion vermeiden
483 :
484 838 : for ( size_t i = 0; i < pFName->aDepLst.size() && aError.IsOk(); ++i )
485 : {
486 419 : pDep = pFName->aDepLst[ i ];
487 419 : aError = ParseOneFile( pDep->GetFileKey(), pOutputFile, pContext );
488 : }
489 :
490 419 : if( aError.IsError() )
491 0 : pFName->bLoaded = false; //bei Fehler nicht geladenen
492 : else
493 : {
494 419 : OUString aTmpPath;
495 838 : OUString aSrsPath = OStringToOUString( pFName->aPathName, RTL_TEXTENCODING_ASCII_US );
496 :
497 419 : osl::FileBase::createTempFile( 0, 0, &aTmpPath );
498 419 : osl::FileBase::getFileURLFromSystemPath( aSrsPath, aSrsPath );
499 :
500 419 : if( pContext && pOutputFile )
501 56 : PreprocessSrsFile( *pOutputFile, *pContext, aSrsPath, aTmpPath );
502 : else
503 363 : osl::File::copy( aSrsPath, aTmpPath );
504 :
505 838 : OUString aParseFile;
506 419 : osl::FileBase::getSystemPathFromFileURL( aTmpPath, aParseFile );
507 419 : finput = fopen(OUStringToOString(aParseFile, RTL_TEXTENCODING_ASCII_US).getStr(), "r");
508 :
509 419 : if( !finput )
510 : {
511 0 : pTC->pEH->Error( ERR_OPENFILE, NULL, RscId(), pFName->aPathName.getStr() );
512 0 : aError = ERR_OPENFILE;
513 : }
514 : else
515 : {
516 419 : RscFileInst aFileInst( pTC, lFileKey, lFileKey, finput );
517 :
518 419 : pTC->pEH->StdOut( "reading file ", RscVerbosityVerbose );
519 419 : pTC->pEH->StdOut( OUStringToOString(aParseFile, RTL_TEXTENCODING_ASCII_US).getStr(), RscVerbosityVerbose );
520 419 : pTC->pEH->StdOut( " ", RscVerbosityVerbose );
521 :
522 419 : aError = ::parser( &aFileInst );
523 419 : if( aError.IsError() )
524 0 : pTC->Delete( lFileKey );//Resourceobjekte loeschen
525 419 : pTC->pEH->StdOut( "\n", RscVerbosityVerbose );
526 419 : fclose( finput );
527 : };
528 :
529 838 : osl::File::remove( aTmpPath );
530 : };
531 : };
532 :
533 1202 : return aError;
534 : }
535 :
536 : namespace
537 : {
538 : using namespace ::osl;
539 : class RscIoError { };
540 :
541 168 : static inline OUString lcl_getAbsoluteUrl(const OUString& i_sBaseUrl, const OString& i_sPath)
542 : {
543 168 : OUString sRelUrl, sAbsUrl;
544 168 : if(FileBase::getFileURLFromSystemPath(OStringToOUString(i_sPath, RTL_TEXTENCODING_MS_1252), sRelUrl) != FileBase::E_None)
545 0 : throw RscIoError();
546 168 : if(FileBase::getAbsoluteFileURL(i_sBaseUrl, sRelUrl, sAbsUrl) != FileBase::E_None)
547 0 : throw RscIoError();
548 168 : return sAbsUrl;
549 : };
550 :
551 168 : static inline OString lcl_getSystemPath(const OUString& i_sUrl)
552 : {
553 168 : OUString sSys;
554 168 : if(FileBase::getSystemPathFromFileURL(i_sUrl, sSys) != FileBase::E_None)
555 0 : throw RscIoError();
556 : OSL_TRACE("temporary file: %s", OUStringToOString(sSys, RTL_TEXTENCODING_UTF8).getStr());
557 168 : return OUStringToOString(sSys, RTL_TEXTENCODING_MS_1252);
558 : };
559 :
560 112 : static inline OString lcl_getTempFile(OUString& sTempDirUrl)
561 : {
562 : // get a temp file name for the rc file
563 112 : OUString sTempUrl;
564 112 : if(FileBase::createTempFile(&sTempDirUrl, NULL, &sTempUrl) != FileBase::E_None)
565 0 : throw RscIoError();
566 : OSL_TRACE("temporary url: %s", OUStringToOString(sTempUrl, RTL_TEXTENCODING_UTF8).getStr());
567 112 : return lcl_getSystemPath(sTempUrl);
568 : };
569 : }
570 :
571 419 : ERRTYPE RscCompiler::Link()
572 : {
573 : FILE * foutput;
574 419 : ERRTYPE aError;
575 : RscFile* pFName;
576 :
577 419 : if( !(pCL->nCommands & NOLINK_FLAG) )
578 : {
579 56 : ::std::list<RscCmdLine::OutputFile>::const_iterator it;
580 :
581 112 : for( it = pCL->m_aOutputFiles.begin(); it != pCL->m_aOutputFiles.end(); ++it )
582 : {
583 : // cleanup nodes
584 224 : for( sal_uIntPtr aIndex = pTC->aFileTab.FirstIndex();
585 112 : aIndex != UNIQUEINDEX_ENTRY_NOTFOUND && aError.IsOk();
586 56 : aIndex = pTC->aFileTab.NextIndex( aIndex ) )
587 : {
588 56 : pFName = pTC->aFileTab.Get( aIndex );
589 56 : if( !pFName->IsIncFile() )
590 : {
591 56 : pTC->Delete( aIndex );
592 56 : aIndex = pTC->aFileTab.GetIndexOf( pFName );
593 56 : pFName->bLoaded = false;
594 : }
595 : }
596 :
597 :
598 : // get two temp file urls
599 112 : OString aRcTmp, aSysListTmp, aSysList;
600 : try
601 : {
602 56 : OUString sPwdUrl;
603 56 : osl_getProcessWorkingDir( &sPwdUrl.pData );
604 112 : OUString sRcUrl = lcl_getAbsoluteUrl(sPwdUrl, it->aOutputRc);
605 : // TempDir is either the directory where the rc file is located or pwd
606 112 : OUString sTempDirUrl = sRcUrl.copy(0,sRcUrl.lastIndexOf('/'));
607 : OSL_TRACE("rc directory URL: %s", OUStringToOString(sTempDirUrl, RTL_TEXTENCODING_UTF8).getStr());
608 :
609 56 : aRcTmp = lcl_getTempFile(sTempDirUrl);
610 : OSL_TRACE("temporary rc file: %s", aRcTmp.getStr());
611 :
612 112 : OUString sOilDirUrl;
613 56 : if(!pCL->aILDir.isEmpty())
614 56 : sOilDirUrl = lcl_getAbsoluteUrl(sPwdUrl, pCL->aILDir);
615 : else
616 0 : sOilDirUrl = sTempDirUrl;
617 : OSL_TRACE("ilst directory URL: %s", OUStringToOString(sOilDirUrl, RTL_TEXTENCODING_UTF8).getStr());
618 :
619 56 : aSysListTmp = lcl_getTempFile(sOilDirUrl);
620 : OSL_TRACE("temporary ilst file: %s", aSysListTmp.getStr());
621 :
622 112 : OUString sIlstUrl;
623 56 : sIlstUrl = sRcUrl.copy(sRcUrl.lastIndexOf('/')+1);
624 56 : sIlstUrl = sIlstUrl.copy(0,sIlstUrl.lastIndexOf('.'));
625 56 : sIlstUrl += ".ilst";
626 56 : sIlstUrl = lcl_getAbsoluteUrl(sOilDirUrl, OUStringToOString(sIlstUrl, RTL_TEXTENCODING_UTF8));
627 :
628 56 : aSysList = lcl_getSystemPath(sIlstUrl);
629 56 : OSL_TRACE("ilst file: %s", aSysList.getStr());
630 : }
631 0 : catch (RscIoError&)
632 : {
633 0 : OString sMsg("Error with paths:\n");
634 0 : sMsg += "temporary rc file: " + aRcTmp + "\n";
635 0 : sMsg += "temporary ilst file: " + aSysListTmp + "\n";
636 0 : sMsg += "ilst file: " + aSysList + "\n";
637 0 : pTC->pEH->FatalError(ERR_OPENFILE, RscId(), sMsg.getStr());
638 : }
639 56 : if ( NULL == (fExitFile = foutput = fopen( aRcTmp.getStr(), "wb" )) )
640 0 : pTC->pEH->FatalError( ERR_OPENFILE, RscId(), aRcTmp.getStr() );
641 :
642 : // Schreibe Datei
643 56 : sal_Char cSearchDelim = SAL_PATHSEPARATOR;
644 56 : sal_Char cAccessDelim = SAL_PATHDELIMITER;
645 56 : pTC->ChangeLanguage( it->aLangName );
646 56 : pTC->SetSourceCharSet( RTL_TEXTENCODING_UTF8 );
647 56 : pTC->ClearSysNames();
648 112 : OStringBuffer aSysSearchPath(it->aLangSearchPath);
649 56 : sal_Int32 nIndex = 0;
650 112 : OString aSearchPath = pTC->GetSearchPath();
651 56 : do
652 : {
653 56 : OString aToken = aSearchPath.getToken( 0, cSearchDelim, nIndex );
654 56 : if (!aSysSearchPath.isEmpty())
655 56 : aSysSearchPath.append(cSearchDelim);
656 56 : aSysSearchPath.append(aToken);
657 56 : aSysSearchPath.append(cAccessDelim);
658 56 : aSysSearchPath.append(it->aLangName);
659 56 : aSysSearchPath.append(cSearchDelim);
660 56 : aSysSearchPath.append(aToken);
661 : }
662 56 : while ( nIndex >= 0 );
663 : OSL_TRACE( "setting search path for language %s: %s", it->aLangName.getStr(), aSysSearchPath.getStr() );
664 56 : pTC->SetSysSearchPath(aSysSearchPath.makeStringAndClear());
665 :
666 112 : WriteRcContext aContext;
667 :
668 56 : aContext.fOutput = foutput;
669 56 : aContext.aOutputRc = it->aOutputRc;
670 56 : aContext.aOutputSysList = aSysListTmp;
671 56 : aContext.pCmdLine = pCL;
672 :
673 : // create empty sys list
674 56 : if( !aContext.aOutputSysList.isEmpty() )
675 : {
676 56 : FILE* pSysListFile = fopen( aContext.aOutputSysList.getStr(), "wb" );
677 :
678 56 : if( !pSysListFile )
679 0 : pTC->pEH->FatalError( ERR_OPENFILE, RscId(), aContext.aOutputSysList.getStr() );
680 : else
681 56 : fclose( pSysListFile );
682 : }
683 :
684 : // parse files for specific language
685 224 : for( sal_uIntPtr aIndex = pTC->aFileTab.FirstIndex();
686 112 : aIndex != UNIQUEINDEX_ENTRY_NOTFOUND && aError.IsOk();
687 56 : aIndex = pTC->aFileTab.NextIndex( aIndex ) )
688 : {
689 56 : pFName = pTC->aFileTab.Get( aIndex );
690 56 : if( !pFName->IsIncFile() )
691 : {
692 56 : aError = ParseOneFile( aIndex, &*it, &aContext );
693 56 : aIndex = pTC->aFileTab.GetIndexOf( pFName );
694 : }
695 : };
696 :
697 56 : aError = pTC->WriteRc( aContext );
698 :
699 56 : fclose( foutput );
700 56 : fExitFile = NULL;
701 56 : unlink( it->aOutputRc.getStr() );
702 56 : if( rename( aRcTmp.getStr(), it->aOutputRc.getStr() ) )
703 : {
704 0 : OStringBuffer aBuf;
705 0 : aBuf.append( aRcTmp );
706 0 : aBuf.append( " -> " );
707 0 : aBuf.append( it->aOutputRc );
708 0 : pTC->pEH->FatalError( ERR_RENAMEFILE, RscId(), aBuf.getStr() );
709 : }
710 : else
711 : {
712 : #ifdef UNX
713 56 : (void)chmod( it->aOutputRc.getStr(), S_IRWXU | S_IRWXG | S_IROTH );
714 : #endif
715 : }
716 :
717 56 : unlink( aSysList.getStr() );
718 56 : if( rename( aSysListTmp.getStr(), aSysList.getStr() ) )
719 : {
720 0 : OStringBuffer aBuf;
721 0 : aBuf.append( aSysListTmp );
722 0 : aBuf.append( " -> " );
723 0 : aBuf.append( aSysList );
724 0 : pTC->pEH->FatalError( ERR_RENAMEFILE, RscId(), aBuf.getStr() );
725 : }
726 : else
727 : {
728 : #ifdef UNX
729 56 : (void)chmod( aSysList.getStr(), S_IRWXU | S_IRWXG | S_IROTH );
730 : #endif
731 : }
732 56 : }
733 : }
734 : else
735 : {
736 : // parse files
737 2180 : for( sal_uIntPtr aIndex = pTC->aFileTab.FirstIndex();
738 1090 : aIndex != UNIQUEINDEX_ENTRY_NOTFOUND && aError.IsOk();
739 727 : aIndex = pTC->aFileTab.NextIndex( aIndex ) )
740 : {
741 727 : pFName = pTC->aFileTab.Get( aIndex );
742 727 : if( !pFName->IsIncFile() )
743 : {
744 727 : aError = ParseOneFile( aIndex, NULL, NULL );
745 727 : aIndex = pTC->aFileTab.GetIndexOf( pFName );
746 : }
747 : };
748 : }
749 :
750 419 : return aError;
751 : }
752 :
753 1672 : bool RscCompiler::GetImageFilePath( const RscCmdLine::OutputFile& rOutputFile,
754 : const WriteRcContext& rContext,
755 : const OString& rBaseFileName,
756 : OString& rImagePath,
757 : FILE* pSysListFile )
758 : {
759 1672 : ::std::list< OString > aFileNames;
760 1672 : bool bFound = false;
761 :
762 1672 : aFileNames.push_back( rBaseFileName + OString(".png") );
763 1672 : aFileNames.push_back( rBaseFileName + OString(".bmp") );
764 :
765 1672 : ::std::list< OString >::iterator aFileIter( aFileNames.begin() );
766 :
767 5022 : while( ( aFileIter != aFileNames.end() ) && !bFound )
768 : {
769 1678 : ::std::list< OString >::const_iterator aDirIter( rOutputFile.aSysSearchDirs.begin() );
770 :
771 12680 : while( ( aDirIter != rOutputFile.aSysSearchDirs.end() ) && !bFound )
772 : {
773 9324 : const OString aSysPath = *aDirIter + "/" + *aFileIter;
774 18648 : OUString aAbsPath = OStringToOUString( aSysPath, RTL_TEXTENCODING_ASCII_US );
775 :
776 :
777 9324 : osl::FileBase::getFileURLFromSystemPath( aAbsPath, aAbsPath );
778 18648 : osl::DirectoryItem aDirectoryItem;
779 9324 : bool bFile = false;
780 9324 : if (osl::DirectoryItem::E_None == osl::DirectoryItem::get( aAbsPath, aDirectoryItem ))
781 : {
782 1672 : osl::FileStatus aFS(osl_FileStatus_Mask_Type);
783 1672 : if (osl::DirectoryItem::E_None == aDirectoryItem.getFileStatus( aFS ))
784 1672 : bFile = aFS.isRegular();
785 : }
786 :
787 : #if OSL_DEBUG_LEVEL > 1
788 : fprintf( stderr, "Searching image: %s\n", aSysPath.getStr() );
789 : #endif
790 :
791 9324 : if( bFile )
792 : {
793 1672 : std::list< std::pair< OString, OString > >::const_iterator aReplIter( rContext.pCmdLine->m_aReplacements.begin() );
794 1672 : OString aRelPathStr( aSysPath );
795 :
796 5016 : while( ( aReplIter != rContext.pCmdLine->m_aReplacements.end() ) && !bFound )
797 : {
798 1672 : OString aSearch(aReplIter->second.toAsciiLowerCase());
799 3344 : OString aSearchIn(aRelPathStr.toAsciiLowerCase());
800 1672 : if( aSearchIn.startsWith(aSearch) )
801 : {
802 1672 : sal_Int32 nCopyPos = aReplIter->second.getLength(), nLength = aRelPathStr.getLength();
803 1672 : const sal_Char* pChars = aRelPathStr.getStr();
804 :
805 3344 : while( ( nCopyPos < nLength ) && ( pChars[ nCopyPos ] == '/' || pChars[ nCopyPos ] == '\\' || pChars[ nCopyPos ] == ':' ) )
806 : {
807 0 : ++nCopyPos;
808 : }
809 :
810 1672 : if( nCopyPos < nLength )
811 1672 : rImagePath = aRelPathStr.copy( nCopyPos ).replace( '\\', '/' );
812 :
813 1672 : bFound = true;
814 : }
815 :
816 1672 : ++aReplIter;
817 1672 : }
818 :
819 1672 : if( bFound && pSysListFile )
820 : {
821 1672 : fprintf( pSysListFile, "%s\n", rContext.pCmdLine->substitutePaths( aSysPath ).getStr() );
822 1672 : }
823 :
824 : #if OSL_DEBUG_LEVEL > 1
825 : fprintf( stderr, "ImagePath to add: %s\n", rImagePath.getStr() );
826 : #endif
827 : }
828 :
829 9324 : ++aDirIter;
830 9324 : }
831 :
832 1678 : ++aFileIter;
833 : }
834 :
835 1672 : return bFound;
836 : }
837 :
838 56 : void RscCompiler::PreprocessSrsFile( const RscCmdLine::OutputFile& rOutputFile,
839 : const WriteRcContext& rContext,
840 : const OUString& rSrsInPath,
841 : const OUString& rSrsOutPath )
842 : {
843 56 : SvFileStream aIStm( rSrsInPath, STREAM_READ );
844 112 : SvFileStream aOStm( rSrsOutPath, STREAM_WRITE | STREAM_TRUNC );
845 112 : ::std::vector< OString > aMissingImages;
846 56 : FILE* pSysListFile = rContext.aOutputSysList.isEmpty() ? NULL : fopen( rContext.aOutputSysList.getStr(), "ab" );
847 :
848 56 : if( !aIStm.GetError() && !aOStm.GetError() )
849 : {
850 56 : OString aLine;
851 112 : OString aFilePath;
852 :
853 118223 : while( aIStm.ReadLine( aLine ) )
854 : {
855 400933 : if( ( getTokenCount(aLine, '=') == 2 ) &&
856 257911 : ( getToken(aLine, 0, '=').indexOf("File") != -1 ) )
857 : {
858 1007 : OString aBaseFileName( getToken(getToken(aLine, 1, '"'), 0, '.') );
859 :
860 1007 : if( GetImageFilePath( rOutputFile, rContext, aBaseFileName, aFilePath, pSysListFile ) )
861 : {
862 2014 : aLine = OStringBuffer("File = \"").
863 2014 : append(aFilePath).append("\";").
864 1007 : makeStringAndClear();
865 : }
866 : else
867 0 : aMissingImages.push_back( aBaseFileName );
868 :
869 1007 : aOStm.WriteLine(aLine);
870 : }
871 117104 : else if (aLine.indexOf("ImageList") != -1)
872 : {
873 57 : ::std::vector< ::std::pair< OString, sal_Int32 > > aEntryVector;
874 :
875 57 : aOStm.WriteLine(aLine);
876 :
877 57 : if (aLine.indexOf(';') == -1)
878 : {
879 56 : const sal_Size nImgListStartPos = aIStm.Tell();
880 :
881 140 : do
882 : {
883 140 : if( !aIStm.ReadLine(aLine) )
884 0 : break;
885 : }
886 140 : while (aLine.indexOf("Prefix") == -1);
887 :
888 56 : const OString aPrefix( getToken(aLine, 1, '"') );
889 56 : aIStm.Seek( nImgListStartPos );
890 :
891 476 : do
892 : {
893 476 : if (!aIStm.ReadLine(aLine) )
894 0 : break;
895 : }
896 476 : while (aLine.indexOf("IdList") == -1);
897 :
898 : // scan all ids and collect images
899 889 : while (aLine.indexOf('}') == -1)
900 : {
901 777 : if( !aIStm.ReadLine(aLine) )
902 0 : break;
903 :
904 777 : aLine = comphelper::string::stripStart(aLine, ' ');
905 777 : aLine = comphelper::string::stripStart(aLine, '\t');
906 777 : aLine = comphelper::string::remove(aLine, ';');
907 :
908 777 : if (comphelper::string::isdigitAsciiString(aLine))
909 : {
910 665 : sal_Int32 nNumber = atoi(aLine.getStr());
911 :
912 665 : OStringBuffer aBuf(aPrefix);
913 665 : if( nNumber < 10000 )
914 309 : aBuf.append('0');
915 665 : aBuf.append(aLine);
916 1330 : OString aBaseFileName = aBuf.makeStringAndClear();
917 :
918 665 : if( GetImageFilePath( rOutputFile, rContext, aBaseFileName, aFilePath, pSysListFile ) )
919 665 : aEntryVector.push_back( ::std::pair< OString, sal_Int32 >( aFilePath, nNumber ) );
920 : else
921 665 : aMissingImages.push_back( aBaseFileName );
922 : }
923 : }
924 :
925 56 : const sal_Size nImgListEndPos = aIStm.Tell();
926 56 : aIStm.Seek( nImgListStartPos );
927 588 : while( aIStm.Tell() < nImgListEndPos )
928 : {
929 476 : aIStm.ReadLine( aLine );
930 :
931 476 : if (aLine.indexOf("IdList") != -1)
932 : {
933 889 : while (aLine.indexOf('}') == -1)
934 777 : aIStm.ReadLine(aLine);
935 : }
936 : else
937 420 : aOStm.WriteLine(aLine);
938 : }
939 :
940 56 : aOStm.WriteLine(OString("FileList = {"));
941 :
942 721 : for( sal_uInt32 i = 0; i < aEntryVector.size(); ++i )
943 : {
944 665 : OStringBuffer aEntryString("< \"");
945 :
946 665 : aEntryString.append(aEntryVector[i].first);
947 665 : aEntryString.append("\"; ");
948 665 : aEntryString.append(static_cast<sal_Int32>(aEntryVector[ i ].second));
949 665 : aEntryString.append("; >;");
950 :
951 665 : aOStm.WriteLine(aEntryString.makeStringAndClear());
952 665 : }
953 :
954 56 : aOStm.WriteLine(OString("};"));
955 : }
956 : else
957 1 : aOStm.WriteLine(aLine);
958 : }
959 : else
960 117047 : aOStm.WriteLine(aLine);
961 56 : }
962 : }
963 :
964 56 : if( aMissingImages.size() > 0 )
965 : {
966 0 : OStringBuffer aImagesStr;
967 :
968 0 : for( sal_uInt32 i = 0; i < aMissingImages.size(); ++i )
969 : {
970 0 : if( i )
971 0 : aImagesStr.append(' ');
972 :
973 0 : aImagesStr.append(aMissingImages[i]);
974 : }
975 :
976 0 : pTC->pEH->FatalError( ERR_NOIMAGE, RscId(), aImagesStr.getStr() );
977 : }
978 :
979 56 : if( pSysListFile )
980 112 : fclose( pSysListFile );
981 56 : }
982 :
983 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|