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