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