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