xref: /trunk/main/rsc/source/rsc/rsc.cxx (revision df59b427)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_rsc.hxx"
26 /****************************************************************/
27 /*                  Include File                                */
28 /****************************************************************/
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <fcntl.h>
33 
34 #ifdef UNX
35 #include <unistd.h>
36 #include <sys/wait.h>
37 #include <sys/stat.h>
38 #else
39 #include <io.h>
40 #include <process.h>
41 #include <direct.h>
42 #endif
43 
44 #include <string.h>
45 #include <ctype.h>
46 #include <errno.h>
47 
48 #if defined( PM2 ) && defined( ZTC )
49 #include <svpm.h>
50 #ifndef unlink
51 #define unlink( p ) DosDelete( (PSZ)(const char*)p )
52 #endif
53 #endif
54 
55 #include <tools/fsys.hxx>
56 #include <tools/stream.hxx>
57 #include <rscerror.h>
58 #include <rsctop.hxx>
59 #include <rscdb.hxx>
60 #include <rscpar.hxx>
61 #include <rscrsc.hxx>
62 #include <rschash.hxx>
63 
64 #include <osl/file.h>
65 #include <osl/file.hxx>
66 #include <osl/process.h>
67 #include <rtl/strbuf.hxx>
68 #include <rtl/tencinfo.h>
69 #include <rtl/textenc.h>
70 
71 #include <vector>
72 #include <algorithm>
73 
74 
75 using namespace rtl;
76 
77 /*************** F o r w a r d s *****************************************/
78 /*************** G l o b a l e   V a r i a b l e n **********************/
79 ByteString*     pStdParType  = NULL;
80 ByteString*     pStdPar1     = NULL;
81 ByteString*     pStdPar2     = NULL;
82 ByteString*     pWinParType  = NULL;
83 ByteString*     pWinPar1     = NULL;
84 ByteString*     pWinPar2     = NULL;
85 sal_uInt32      nRefDeep     = 10;
86 AtomContainer*  pHS          = NULL;
87 
88 
89 /*************** R s c C m d L i n e ************************************/
90 /*************************************************************************
91 |*
92 |*    RscCmdLine::Init()
93 |*
94 |*    Beschreibung      Kommandozeile interpretierten
95 |*    Ersterstellung    MM 03.05.91
96 |*    Letzte Aenderung  MM 03.05.91
97 |*
98 *************************************************************************/
Init()99 void RscCmdLine::Init()
100 {
101     nCommands       = 0;
102     nByteOrder      = RSC_BIGENDIAN;
103 
104     DirEntry aEntry;
105     aPath = ByteString( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US ); //Immer im Aktuellen Pfad suchen
106     m_aOutputFiles.clear();
107     m_aOutputFiles.push_back( OutputFile() );
108 }
109 
110 /*************************************************************************
111 |*
112 |*    RscCmdLine::RscCmdLine()
113 |*
114 |*    Beschreibung      Kommandozeile interpretierten
115 |*    Ersterstellung    MM 13.02.91
116 |*    Letzte Aenderung  MM 13.02.91
117 |*
118 *************************************************************************/
RscCmdLine()119 RscCmdLine::RscCmdLine()
120 {
121     Init();
122 }
123 
124 /*************************************************************************
125 |*
126 |*    RscCmdLine::RscCmdLine()
127 |*
128 |*    Beschreibung      Kommandozeile interpretierten
129 |*    Ersterstellung    MM 13.02.91
130 |*    Letzte Aenderung  MM 13.02.91
131 |*
132 *************************************************************************/
RscCmdLine(int argc,char ** argv,RscError * pEH)133 RscCmdLine::RscCmdLine( int argc, char ** argv, RscError * pEH )
134 {
135     char *          pStr;
136     char **         ppStr;
137     RscPtrPtr       aCmdLine;       // Kommandozeile
138     ByteString      aString;
139     sal_uInt32      i;
140     sal_Bool        bOutputSrsIsSet = sal_False;
141 
142     Init(); // Defaults setzen
143 
144     pStr = ::ResponseFile( &aCmdLine, argv, argc );
145     if( pStr )
146         pEH->FatalError( ERR_OPENFILE, RscId(), pStr );
147 
148     /* check the inputted switches       */
149     ppStr  = (char **)aCmdLine.GetBlock();
150     ppStr++;
151     i = 1;
152     while( ppStr && i < (aCmdLine.GetCount() -1) )
153     {
154 #if OSL_DEBUG_LEVEL > 1
155         fprintf( stderr, "CmdLineArg: \"%s\"\n", *ppStr );
156 #endif
157         if( '-' == **ppStr )
158         {
159             if( !rsc_stricmp( (*ppStr) + 1, "h" )
160               || !strcmp( (*ppStr) + 1, "?" ) )
161             { // Hilfe
162                 nCommands |= HELP_FLAG;
163             }
164             else if( !rsc_stricmp( (*ppStr) + 1, "syntax" ) )
165             { // Hilfe
166                 nCommands |= PRINTSYNTAX_FLAG;
167             }
168             else if( !rsc_strnicmp( (*ppStr) + 1, "RefDeep", 7 ) )
169             { // maximale Aufloesungtiefe fuer Referenzen
170                 nRefDeep = ByteString( (*ppStr) +1 + strlen( "RefDeep" ) ).ToInt32();
171             }
172             else if( !rsc_stricmp( (*ppStr) + 1, "p" ) )
173             { // kein Preprozessor
174                 nCommands |= NOPREPRO_FLAG;
175             }
176             else if( !rsc_stricmp( (*ppStr) + 1, "s" ) )
177             { // nicht linken
178                 nCommands |= NOLINK_FLAG;
179             }
180             else if( !rsc_stricmp( (*ppStr) + 1, "l" ) )
181             { // Linken, keine Syntax und kein Prepro
182                 nCommands |= NOPREPRO_FLAG;
183                 nCommands |= NOSYNTAX_FLAG;
184             }
185             else if( !rsc_stricmp( (*ppStr) + 1, "r" ) )
186             { // erzeugt kein .res-file
187                 nCommands |= NORESFILE_FLAG;
188             }
189             else if( !rsc_strnicmp( (*ppStr) + 1, "sub", 3 ) )
190             {
191                 const char* pEqual;
192                 for( pEqual = (*ppStr)+4; *pEqual && *pEqual != '='; ++pEqual )
193                     ;
194                 if( *pEqual )
195                 {
196                     const ByteString    aSPath( pEqual + 1 );
197                     DirEntry            aSDir( String( aSPath, RTL_TEXTENCODING_ASCII_US ) );
198 
199                     m_aReplacements.push_back( std::pair< OString, OString >( OString( (*ppStr)+4, pEqual - *ppStr - 4 ),
200                                                                               ByteString( aSDir.GetFull(), RTL_TEXTENCODING_ASCII_US ) ) );
201                 }
202             }
203             else if( !rsc_stricmp( (*ppStr) + 1, "PreLoad" ) )
204             { // Alle Ressourcen mit Preload
205                 nCommands |= PRELOAD_FLAG;
206             }
207             else if( !rsc_stricmp( (*ppStr) + 1, "LITTLEENDIAN" ) )
208             { // Byte Ordnung beim Schreiben
209                 nByteOrder = RSC_LITTLEENDIAN;
210             }
211             else if( !rsc_stricmp( (*ppStr) + 1, "BIGENDIAN" ) )
212             { // Byte Ordnung beim Schreiben
213                 nByteOrder = RSC_BIGENDIAN;
214             }
215             else if( !rsc_stricmp( (*ppStr) + 1, "SMART" ) )
216             { // Byte Ordnung beim Schreiben
217                 nCommands |= SMART_FLAG;
218             }
219             else if( !rsc_strnicmp( (*ppStr) + 1, "d", 1 ) )
220             { // Symbole definieren
221                 nCommands |= DEFINE_FLAG;
222                 aSymbolList.Insert( new ByteString( (*ppStr) + 2 ), 0xFFFF );
223             }
224             else if( !rsc_strnicmp( (*ppStr) + 1, "i", 1 ) )
225             { // Include-Pfade definieren
226                 nCommands |= INCLUDE_FLAG;
227                 if( aPath.Len() )
228                     aPath += ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US );
229                 aPath += (*ppStr) + 2;
230             }
231             else if( !rsc_strnicmp( (*ppStr) + 1, "fs=", 3 ) )
232             { // anderer Name fuer .rc-file
233                 if( m_aOutputFiles.back().aOutputRc.Len() )
234                     m_aOutputFiles.push_back( OutputFile() );
235                 m_aOutputFiles.back().aOutputRc = (*ppStr) + 4;
236             }
237             else if( !rsc_strnicmp( (*ppStr) + 1, "lip=", 4 ) )
238             {  // additional language specific include for system dependent files
239                 const ByteString    aSysSearchDir( (*ppStr)+5 );
240                 DirEntry            aSysDir( String( aSysSearchDir, RTL_TEXTENCODING_ASCII_US ) );
241 
242                 m_aOutputFiles.back().aSysSearchDirs.push_back( ByteString( aSysDir.GetFull(), RTL_TEXTENCODING_ASCII_US ) );
243 
244                 if( m_aOutputFiles.back().aLangSearchPath.Len() )
245                     m_aOutputFiles.back().aLangSearchPath.Append( ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US ) );
246 
247                 m_aOutputFiles.back().aLangSearchPath.Append( aSysSearchDir );
248             }
249             else if( !rsc_strnicmp( (*ppStr) + 1, "fp=", 3 ) )
250             { // anderer Name fuer .srs-file
251                 aOutputSrs = (*ppStr) + 4;
252                 bOutputSrsIsSet = sal_True;
253             }
254             else if( !rsc_strnicmp( (*ppStr) + 1, "fl=", 3 ) )
255             { // Name fuer listing-file
256                 aOutputLst = (*ppStr) + 4;
257             }
258             else if( !rsc_strnicmp( (*ppStr) + 1, "fh=", 3 ) )
259             { // Name fuer .hxx-file
260                 aOutputHxx = (*ppStr) + 4;
261             }
262             else if( !rsc_strnicmp( (*ppStr) + 1, "fc=", 3 ) )
263             { // Name fuer .cxx-file
264                 aOutputCxx = (*ppStr) + 4;
265             }
266             else if( !rsc_strnicmp( (*ppStr) + 1, "fr=", 3 ) )
267             { // Name fuer .cxx-file der Ressource Konstruktoren
268                 aOutputRcCtor = (*ppStr) + 4;
269             }
270             else if( !rsc_strnicmp( (*ppStr) + 1, "fx=", 3 ) )
271             { // Name fuer .src-file
272                 aOutputSrc = (*ppStr) + 4;
273             }
274             else if( !rsc_strnicmp( (*ppStr) + 1, "ft=", 3 ) )
275             { // touch file
276                 aTouchFile = (*ppStr) + 4;
277             }
278             else if( !rsc_strnicmp( (*ppStr) + 1, "oil=", 4 ) )
279             {
280                 aILDir = (*ppStr) + 5;
281             }
282             else if( !rsc_stricmp( (*ppStr) + 1, "NoSysResTest" ) )
283             { // Bitmap, Pointers, Icons nicht ueberpruefen
284                 nCommands |= NOSYSRESTEST_FLAG;
285             }
286             else if( !rsc_stricmp( (*ppStr) + 1, "SrsDefault" ) )
287             { // Bitmap, Pointers, Icons nicht ueberpruefen
288                 nCommands |= SRSDEFAULT_FLAG;
289             }
290             else if( !rsc_strnicmp( (*ppStr) + 1, "CHARSET_", 8 ) )
291             {
292                 // ignore (was an option once)
293             }
294             else if( !rsc_stricmp( (*ppStr) + 1, "lg" ) )
295             {
296                 m_aOutputFiles.back().aLangName = ByteString();
297             }
298             else if( !rsc_strnicmp( (*ppStr) + 1, "lg", 2 ) )
299             {
300                 if( m_aOutputFiles.back().aLangName.Len() )
301                     m_aOutputFiles.push_back( OutputFile() );
302                 m_aOutputFiles.back().aLangName = ByteString( (*ppStr)+3 );
303             }
304             else
305                 pEH->FatalError( ERR_UNKNOWNSW, RscId(), *ppStr );
306         }
307         else
308         {
309             // Eingabedatei
310             aInputList.Insert( new ByteString( *ppStr ), 0xFFFF );
311         }
312         ppStr++;
313         i++;
314     }
315 
316     if( nCommands & HELP_FLAG )
317         pEH->FatalError( ERR_USAGE, RscId() );
318     // was an inputted file specified
319     else if( aInputList.Count() )
320     {
321         ::std::list<OutputFile>::iterator it;
322         for( it = m_aOutputFiles.begin(); it != m_aOutputFiles.end(); ++it )
323         {
324             if( ! it->aOutputRc.Len() )
325                 it->aOutputRc  = ::OutputFile( *aInputList.First(), "rc"  );
326         }
327         if( ! bOutputSrsIsSet )
328             aOutputSrs = ::OutputFile( *aInputList.First(), "srs" );
329     }
330     else if( !(nCommands & PRINTSYNTAX_FLAG) )
331         pEH->FatalError( ERR_NOINPUT, RscId() );
332 }
333 
334 /*************************************************************************
335 |*
336 |*    RscCmdLine::~RscCmdLine()
337 |*
338 |*    Beschreibung      dtor
339 |*    Ersterstellung    MM 13.02.91
340 |*    Letzte Aenderung  MM 13.02.91
341 |*
342 *************************************************************************/
~RscCmdLine()343 RscCmdLine::~RscCmdLine()
344 {
345     ByteString  *pString;
346 
347     while( NULL != (pString = aInputList.Remove( (sal_uLong)0 )) )
348         delete pString;
349     while( NULL != (pString = aSymbolList.Remove( (sal_uLong)0 )) )
350         delete pString;
351 }
352 
353 /*************************************************************************
354 |*
355 |*    RscCmdLine::substitutePaths()
356 |*
357 *************************************************************************/
358 
substitutePaths(const OString & rIn)359 OString RscCmdLine::substitutePaths( const OString& rIn )
360 {
361     // prepare return value
362     OStringBuffer aRet( 256 );
363     std::list< std::pair< OString, OString > >::const_iterator last_match = m_aReplacements.end();
364 
365     // search for longest replacement match
366     for( std::list< std::pair< OString, OString > >::const_iterator repl = m_aReplacements.begin(); repl != m_aReplacements.end(); ++repl )
367     {
368         if( rIn.compareTo( repl->second, repl->second.getLength() ) == 0 ) // path matches
369         {
370             if( last_match == m_aReplacements.end() || last_match->second.getLength() < repl->second.getLength() )
371                 last_match = repl;
372         }
373     }
374 
375     // copy replacement found and rest of rIn
376     sal_Int32 nIndex = 0;
377     if( last_match != m_aReplacements.end() )
378     {
379         aRet.append( "%" );
380         aRet.append( last_match->first );
381         aRet.append( "%" );
382         nIndex = last_match->second.getLength();
383     }
384     aRet.append( rIn.copy( nIndex ) );
385 
386     return aRet.makeStringAndClear();
387 }
388 
389 /*************** R s c C o m p i l e r **********************************/
390 /****************************************************************/
391 /*                                                              */
392 /*  RscCompiler :: RscCompiler(int argc, char **argv)           */
393 /*                                                              */
394 /*  Parameters  :   argc - number of parameters on command line */
395 /*                  argv - arry of pointers to input parameters */
396 /*                                                              */
397 /*  Description :   main calling routine. Calls functions to    */
398 /*  check and assign the input parameters. It then builds the   */
399 /*  command line to call the Glockenspiel preprocessor          */
400 /****************************************************************/
401 
RscCompiler(RscCmdLine * pLine,RscTypCont * pTypCont)402 RscCompiler::RscCompiler( RscCmdLine * pLine, RscTypCont * pTypCont )
403 {
404     fListing      = NULL;
405     fExitFile     = NULL;
406 
407     //Kommandozeile setzen, TypContainer setzen
408     pCL = pLine;
409     pTC = pTypCont;
410 
411     if( pCL->aOutputLst.Len() )
412     {
413         if ( NULL == (fListing = fopen( pCL->aOutputLst.GetBuffer(), "w" )) )
414             pTC->pEH->FatalError( ERR_OPENFILE, RscId(), pCL->aOutputLst.GetBuffer() );
415         pTC->pEH->SetListFile( fListing );
416     }
417 }
418 
419 /*************************************************************************
420 |*
421 |*    RscCompiler :: RscCompiler()
422 |*
423 |*    Beschreibung
424 |*    Ersterstellung    MM 07.02.91
425 |*    Letzte Aenderung  MM 07.02.91
426 |*
427 *************************************************************************/
~RscCompiler()428 RscCompiler::~RscCompiler()
429 {
430     ByteString* pString;
431 
432     // Dateien loeschen
433     pString = aTmpFileList.First();
434     while( pString )
435     {
436         unlink( pString->GetBuffer() );
437         delete pString;
438         pString = aTmpFileList.Next();
439     }
440 
441     pTC->pEH->SetListFile( NULL );
442 
443     if( fListing )
444         fclose( fListing );
445 
446     if( fExitFile )
447         fclose( fExitFile );
448     if( aTmpOutputHxx.Len() )
449         unlink( aTmpOutputHxx.GetBuffer() );
450     if( aTmpOutputCxx.Len() )
451         unlink( aTmpOutputCxx.GetBuffer() );
452     if( aTmpOutputRcCtor.Len() )
453         unlink( aTmpOutputRcCtor.GetBuffer() );
454     if( aTmpOutputSrc.Len() )
455         unlink( aTmpOutputSrc.GetBuffer() );
456 }
457 
458 /*************************************************************************
459 |*
460 |*    RscCompiler::Start()
461 |*
462 |*    Beschreibung      Datei in Kommandozeile aendern
463 |*    Ersterstellung    MM 13.02.91
464 |*    Letzte Aenderung  MM 13.02.91
465 |*
466 *************************************************************************/
Start()467 ERRTYPE RscCompiler::Start()
468 {
469     ERRTYPE         aError;
470     ByteString*     pString;
471     RscFile*        pFName;
472 
473 	if( PRINTSYNTAX_FLAG & pCL->nCommands )
474 	{
475 		pTC->WriteSyntax( stdout );
476         printf( "khg\n" );
477 		return ERR_OK;
478 	}
479 
480     // Kein Parameter, dann Hilfe
481     pString = pCL->aInputList.First();
482     if( !pString )
483         pTC->pEH->FatalError( ERR_NOINPUT, RscId() );
484 
485     while( pString )
486     {
487         pTC->aFileTab.NewCodeFile( *pString );
488         pString = pCL->aInputList.Next();
489     }
490 
491     if( !(pCL->nCommands & NOSYNTAX_FLAG) )
492     {
493         if( pCL->nCommands & NOPREPRO_FLAG )
494         {
495 
496             pTC->pEH->SetListFile( NULL );
497 
498             pFName = pTC->aFileTab.First();
499             while( pFName && aError.IsOk() )
500             {
501                 if( !pFName->bScanned && !pFName->IsIncFile() )
502                 {
503                     aError = IncludeParser(
504                                  pTC->aFileTab.GetIndex( pFName )
505                              );
506                     // Currentzeiger richtig setzen
507                     pTC->aFileTab.Seek( pFName );
508                 };
509                 pFName = pTC->aFileTab.Next();
510             };
511 
512             pTC->pEH->SetListFile( fListing );
513         }
514     };
515 
516     if ( pTC->pEH->GetVerbosity() >= RscVerbosityVerbose )
517     {
518         pTC->pEH->StdOut( "Files: " );
519         pFName = pTC->aFileTab.First();
520         while( pFName )
521         {
522             pTC->pEH->StdOut( pFName->aFileName.GetBuffer() );
523             pTC->pEH->StdOut( " " );
524             pFName = pTC->aFileTab.Next();
525         };
526         pTC->pEH->StdOut( "\n" );
527     }
528 
529     if( aError.IsOk() )
530         aError = Link();
531 
532     if( aError.IsOk() )
533         EndCompile();
534 
535     if( aError.IsError() )
536         pTC->pEH->Error( ERR_ERROR, NULL, RscId() );
537 
538     return( aError );
539 }
540 /*************************************************************************
541 |*
542 |*    RscCmdLine::EndCompile()
543 |*
544 |*    Beschreibung      Datei in Kommandozeile aendern
545 |*    Ersterstellung    MM 13.02.91
546 |*    Letzte Aenderung  MM 13.02.91
547 |*
548 *************************************************************************/
EndCompile()549 void RscCompiler::EndCompile()
550 {
551     if( pCL->aOutputSrs.Len() && (pCL->nCommands & NOLINK_FLAG) )
552     {
553         pTC->pEH->StdOut( "Writing file ", RscVerbosityVerbose );
554         pTC->pEH->StdOut( pCL->aOutputSrs.GetBuffer(), RscVerbosityVerbose );
555         pTC->pEH->StdOut( ".\n", RscVerbosityVerbose );
556 
557         // kopiere von TMP auf richtigen Namen
558         unlink( pCL->aOutputSrs.GetBuffer() );   // Zieldatei loeschen
559         if( !(pCL->nCommands & NOSYNTAX_FLAG) )
560         {
561             FILE        * foutput;
562             RscFile     * pFN;
563 
564             if( NULL == (foutput = fopen( pCL->aOutputSrs.GetBuffer(), "w" )) )
565                 pTC->pEH->FatalError( ERR_OPENFILE, RscId(), pCL->aOutputSrs.GetBuffer() );
566             else
567             {
568                 // Schreibe Datei
569                 pFN = pTC->aFileTab.First();
570                 while( pFN )
571                 {
572                     if( !pFN->IsIncFile() )
573                     {
574                         pTC->WriteSrc( foutput, NOFILE_INDEX,
575                                        RTL_TEXTENCODING_UNICODE, sal_False );
576                         break; // ?T 281091MM nur eine Src-Datei
577                     }
578                 };
579 
580                 fclose( foutput );
581             };
582         };
583     }
584 
585     if ( aTmpOutputHxx.Len() )
586     {
587         pTC->pEH->StdOut( "Writing file ", RscVerbosityVerbose );
588         pTC->pEH->StdOut( pCL->aOutputHxx.GetBuffer(), RscVerbosityVerbose );
589         pTC->pEH->StdOut( ".\n", RscVerbosityVerbose );
590 
591         // kopiere von TMP auf richtigen Namen
592         unlink( pCL->aOutputHxx.GetBuffer() );   // Zieldatei loeschen
593         Append( pCL->aOutputHxx, aTmpOutputHxx );
594         unlink( aTmpOutputHxx.GetBuffer() );// TempDatei  loeschen
595         aTmpOutputHxx = ByteString();
596     }
597 
598     if( aTmpOutputCxx.Len() )
599     {
600         pTC->pEH->StdOut( "Writing file ", RscVerbosityVerbose );
601         pTC->pEH->StdOut( pCL->aOutputCxx.GetBuffer(), RscVerbosityVerbose );
602         pTC->pEH->StdOut( ".\n", RscVerbosityVerbose );
603 
604         // kopiere von TMP auf richtigen Namen
605         unlink( pCL->aOutputCxx.GetBuffer() );   // Zieldatei loeschen
606         Append( pCL->aOutputCxx, aTmpOutputCxx );
607         unlink( aTmpOutputCxx.GetBuffer() );// TempDatei  loeschen
608         aTmpOutputCxx = ByteString();
609     }
610 
611     if( aTmpOutputRcCtor.Len() )
612     {
613         pTC->pEH->StdOut( "Writing file ", RscVerbosityVerbose );
614         pTC->pEH->StdOut( pCL->aOutputRcCtor.GetBuffer(), RscVerbosityVerbose );
615         pTC->pEH->StdOut( ".\n", RscVerbosityVerbose );
616 
617         // kopiere von TMP auf richtigen Namen
618         unlink( pCL->aOutputRcCtor.GetBuffer() );   // Zieldatei loeschen
619         Append( pCL->aOutputRcCtor, aTmpOutputRcCtor );
620         unlink( aTmpOutputRcCtor.GetBuffer() );// TempDatei  loeschen
621         aTmpOutputRcCtor = ByteString();
622     }
623 
624     if( aTmpOutputSrc.Len() )
625     {
626         // kopiere von TMP auf richtigen Namen
627         unlink( pCL->aOutputSrc.GetBuffer() );   // Zieldatei loeschen
628         Append( pCL->aOutputSrc, aTmpOutputSrc );
629         unlink( aTmpOutputSrc.GetBuffer() );// TempDatei  loeschen
630         aTmpOutputSrc = ByteString();
631     }
632 
633     if( pCL->aTouchFile.Len() )
634     {
635         FILE* fp = fopen( pCL->aTouchFile.GetBuffer(), "w" );
636         if( fp )
637         {
638             fprintf( fp, "Done\n" );
639             fclose( fp );
640         }
641         else
642             pTC->pEH->FatalError( ERR_OPENFILE, RscId(), pCL->aTouchFile.GetBuffer() );
643     }
644 }
645 
646 /*************************************************************************
647 |*
648 |*    RscCompiler::IncludeParser()
649 |*
650 |*    Beschreibung
651 |*    Ersterstellung    MM 21.06.91
652 |*    Letzte Aenderung  MM 21.06.91
653 |*
654 *************************************************************************/
IncludeParser(sal_uLong lFileKey)655 ERRTYPE RscCompiler :: IncludeParser( sal_uLong lFileKey )
656 {
657     FILE            * finput;
658     RscFile         * pFName;
659     ERRTYPE           aError;
660 
661     pFName = pTC->aFileTab.Get( lFileKey );
662     if( !pFName )
663         aError = ERR_ERROR;
664     else if( !pFName->bScanned )
665     {
666         finput = fopen( pFName->aPathName.GetBuffer(), "r" );
667         if( !finput )
668         {
669             aError = ERR_OPENFILE;
670             pTC->pEH->Error( aError, NULL, RscId(),
671                              pFName->aPathName.GetBuffer() );
672         }
673         else
674         {
675             RscFile         * pFNTmp;
676             ByteString        aPathName;
677             RscDepend       * pDep;
678             RscFileInst       aFileInst( pTC, lFileKey, lFileKey, finput );
679 
680             pFName->bScanned = sal_True;
681             ::IncludeParser( &aFileInst );
682             fclose( finput );
683 
684             // Include-Pfad durchsuchen
685             pDep = pFName->First();
686             while( pDep )
687             {
688                 pFNTmp = pTC->aFileTab.GetFile( pDep->GetFileKey() );
689                 pDep = pFName->Next();
690             }
691 
692             pDep = pFName->First();
693             while( pDep )
694             {
695                 pFNTmp = pTC->aFileTab.GetFile( pDep->GetFileKey() );
696                 // Kein Pfad und Include Datei
697                 if( pFNTmp && !pFNTmp->bLoaded )
698                 {
699                     UniString aUniFileName( pFNTmp->aFileName, RTL_TEXTENCODING_ASCII_US );
700                     DirEntry aFullName( aUniFileName );
701                     if ( aFullName.Find( UniString( pCL->aPath, RTL_TEXTENCODING_ASCII_US ) ) )
702                         pFNTmp->aPathName = ByteString( aFullName.GetFull(), RTL_TEXTENCODING_ASCII_US );
703                     else
704                         aError = ERR_OPENFILE;
705                 }
706                 pDep = pFName->Next();
707             };
708         };
709     };
710 
711     return aError;
712 }
713 
714 /*************************************************************************
715 |*
716 |*    RscCompiler :: ParseOneFile()
717 |*
718 |*    Beschreibung
719 |*    Ersterstellung    MM 26.06.91
720 |*    Letzte Aenderung  MM 26.06.91
721 |*
722 *************************************************************************/
ParseOneFile(sal_uLong lFileKey,const RscCmdLine::OutputFile * pOutputFile,const WriteRcContext * pContext)723 ERRTYPE RscCompiler :: ParseOneFile( sal_uLong lFileKey,
724                                      const RscCmdLine::OutputFile* pOutputFile,
725                                      const WriteRcContext* pContext )
726 {
727     FILE *              finput = NULL;
728     ERRTYPE             aError;
729     RscFile           * pFName;
730 
731     pFName = pTC->aFileTab.Get( lFileKey );
732     if( !pFName )
733         aError = ERR_ERROR;
734     else if( !pFName->bLoaded )
735     {
736         RscDepend  * pDep;
737 
738         //Include-Dateien vorher lesen
739         pFName->bLoaded = sal_True; //Endlos Rekursion vermeiden
740         pDep = pFName->First();
741         while( pDep && aError.IsOk() )
742         {
743             aError = ParseOneFile( pDep->GetFileKey(), pOutputFile, pContext );
744             pFName->Seek( pDep );
745             pDep = pFName->Next();
746         }
747 
748         if( aError.IsError() )
749             pFName->bLoaded = sal_False; //bei Fehler nicht geladenen
750         else
751         {
752             String      aTmpName( ::GetTmpFileName(), RTL_TEXTENCODING_ASCII_US );
753             DirEntry    aTmpPath( aTmpName ), aSrsPath( String( pFName->aPathName.GetBuffer(), RTL_TEXTENCODING_ASCII_US ) );
754 
755             aTmpPath.ToAbs();
756             aSrsPath.ToAbs();
757 
758             if( pContext && pOutputFile )
759                 PreprocessSrsFile( *pOutputFile, *pContext, aSrsPath, aTmpPath );
760             else
761                 aSrsPath.CopyTo( aTmpPath, FSYS_ACTION_COPYFILE );
762 
763             ByteString aParseFile( aTmpPath.GetFull(), RTL_TEXTENCODING_ASCII_US );
764             finput = fopen( aParseFile.GetBuffer(), "r" );
765 
766             if( !finput )
767             {
768                 pTC->pEH->Error( ERR_OPENFILE, NULL, RscId(), pFName->aPathName.GetBuffer() );
769                 aError = ERR_OPENFILE;
770             }
771             else
772             {
773                 RscFileInst aFileInst( pTC, lFileKey, lFileKey, finput );
774 
775                 pTC->pEH->StdOut( "reading file ", RscVerbosityVerbose );
776                 pTC->pEH->StdOut( aParseFile.GetBuffer(), RscVerbosityVerbose );
777                 pTC->pEH->StdOut( " ", RscVerbosityVerbose );
778 
779                 aError = ::parser( &aFileInst );
780                 if( aError.IsError() )
781                     pTC->Delete( lFileKey );//Resourceobjekte loeschen
782                 pTC->pEH->StdOut( "\n", RscVerbosityVerbose );
783                 fclose( finput );
784             };
785 
786             aTmpPath.Kill();
787         };
788     };
789 
790     return( aError );
791 }
792 
793 /*************************************************************************
794 |*
795 |*    RscCompiler :: Link()
796 |*
797 |*    Beschreibung
798 |*    Ersterstellung    MM 07.02.91
799 |*    Letzte Aenderung  MM 07.02.91
800 |*
801 *************************************************************************/
802 
803 namespace
804 {
805     using namespace ::osl;
806     class RscIoError { };
lcl_getAbsoluteUrl(const OUString & i_sBaseUrl,const OString & i_sPath)807     static inline OUString lcl_getAbsoluteUrl(const OUString& i_sBaseUrl, const OString& i_sPath)
808     {
809         OUString sRelUrl, sAbsUrl;
810         if(FileBase::getFileURLFromSystemPath(OStringToOUString(i_sPath, RTL_TEXTENCODING_MS_1252), sRelUrl) != FileBase::E_None)
811             throw RscIoError();
812         if(FileBase::getAbsoluteFileURL(i_sBaseUrl, sRelUrl, sAbsUrl) != FileBase::E_None)
813             throw RscIoError();
814         return sAbsUrl;
815     };
lcl_getSystemPath(const OUString & i_sUrl)816     static inline OString lcl_getSystemPath(const OUString& i_sUrl)
817     {
818         OUString sSys;
819         if(FileBase::getSystemPathFromFileURL(i_sUrl, sSys) != FileBase::E_None)
820             throw RscIoError();
821         OSL_TRACE("temporary file: %s", OUStringToOString(sSys, RTL_TEXTENCODING_UTF8).getStr());
822         return OUStringToOString(sSys, RTL_TEXTENCODING_MS_1252);
823     };
lcl_getTempFile(OUString & sTempDirUrl)824     static inline OString lcl_getTempFile(OUString& sTempDirUrl)
825     {
826         // get a temp file name for the rc file
827         OUString sTempUrl;
828         if(FileBase::createTempFile(&sTempDirUrl, NULL, &sTempUrl) != FileBase::E_None)
829             throw RscIoError();
830         OSL_TRACE("temporary url: %s", OUStringToOString(sTempUrl, RTL_TEXTENCODING_UTF8).getStr());
831         return lcl_getSystemPath(sTempUrl);
832     };
833 }
834 
Link()835 ERRTYPE RscCompiler::Link()
836 {
837     FILE *      foutput;
838     ERRTYPE     aError;
839     RscFile*    pFName;
840 
841     if( !(pCL->nCommands & NOLINK_FLAG) )
842     {
843         ::std::list<RscCmdLine::OutputFile>::const_iterator it;
844 
845         for( it = pCL->m_aOutputFiles.begin(); it != pCL->m_aOutputFiles.end(); ++it )
846         {
847             // cleanup nodes
848             for( pFName = pTC->aFileTab.First(); pFName && aError.IsOk(); pFName = pTC->aFileTab.Next() )
849             {
850                 if( !pFName->IsIncFile() )
851                 {
852                     pTC->Delete( pTC->aFileTab.GetIndex( pFName ) );
853                     pTC->aFileTab.Seek( pFName );
854                     pFName->bLoaded = sal_False;
855                 }
856             }
857 
858             // get two temp file urls
859             OString aRcTmp, aSysListTmp, aSysList;
860             try
861             {
862                 OUString sPwdUrl;
863                 osl_getProcessWorkingDir( &sPwdUrl.pData );
864                 OUString sRcUrl = lcl_getAbsoluteUrl(sPwdUrl, it->aOutputRc);
865                 // TempDir is either the directory where the rc file is located or pwd
866                 OUString sTempDirUrl = sRcUrl.copy(0,sRcUrl.lastIndexOf('/'));
867                 OSL_TRACE("rc directory URL: %s", OUStringToOString(sTempDirUrl, RTL_TEXTENCODING_UTF8).getStr());
868 
869                 aRcTmp = lcl_getTempFile(sTempDirUrl);
870                 OSL_TRACE("temporary rc file: %s", aRcTmp.getStr());
871 
872                 OUString sOilDirUrl;
873                 if(pCL->aILDir.Len())
874                     sOilDirUrl = lcl_getAbsoluteUrl(sPwdUrl, pCL->aILDir);
875                 else
876                     sOilDirUrl = sTempDirUrl;
877                 OSL_TRACE("ilst directory URL: %s", OUStringToOString(sOilDirUrl, RTL_TEXTENCODING_UTF8).getStr());
878 
879                 aSysListTmp = lcl_getTempFile(sOilDirUrl);
880                 OSL_TRACE("temporary ilst file: %s", aSysListTmp.getStr());
881 
882                 OUString sIlstUrl, sIlstSys;
883                 sIlstUrl = sRcUrl.copy(sRcUrl.lastIndexOf('/')+1);
884                 sIlstUrl = sIlstUrl.copy(0,sIlstUrl.lastIndexOf('.'));
885                 sIlstUrl += OUString::createFromAscii(".ilst");
886                 sIlstUrl = lcl_getAbsoluteUrl(sOilDirUrl, OUStringToOString(sIlstUrl, RTL_TEXTENCODING_UTF8));
887 
888                 aSysList = lcl_getSystemPath(sIlstUrl);
889                 OSL_TRACE("ilst file: %s", aSysList.getStr());
890             }
891             catch (RscIoError&)
892             {
893                 OString sMsg("Error with paths:\n");
894                 sMsg += "temporary rc file: " + aRcTmp + "\n";
895                 sMsg += "temporary ilst file: " + aSysListTmp + "\n";
896                 sMsg += "ilst file: " + aSysList + "\n";
897                 pTC->pEH->FatalError(ERR_OPENFILE, RscId(), sMsg);
898             }
899             if ( NULL == (fExitFile = foutput = fopen( aRcTmp.getStr(), "wb" )) )
900                 pTC->pEH->FatalError( ERR_OPENFILE, RscId(), aRcTmp.getStr() );
901 
902             // Schreibe Datei
903             sal_Char cSearchDelim = ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US ).GetChar( 0 );
904             sal_Char cAccessDelim = ByteString( DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US ).GetChar( 0 );
905             pTC->ChangeLanguage( it->aLangName );
906             pTC->SetSourceCharSet( RTL_TEXTENCODING_UTF8 );
907             pTC->ClearSysNames();
908             ByteString aSysSearchPath( it->aLangSearchPath );
909             xub_StrLen nIndex = 0;
910             ByteString aSearchPath = pTC->GetSearchPath();
911             while( nIndex != STRING_NOTFOUND )
912             {
913                 ByteString aToken = aSearchPath.GetToken( 0, cSearchDelim, nIndex );
914                 if( aSysSearchPath.Len() )
915                     aSysSearchPath.Append( cSearchDelim );
916                 aSysSearchPath.Append( aToken );
917                 aSysSearchPath.Append( cAccessDelim );
918                 aSysSearchPath.Append( it->aLangName );
919                 aSysSearchPath.Append( cSearchDelim );
920                 aSysSearchPath.Append( aToken );
921             }
922             OSL_TRACE( "setting search path for language %s: %s\n", it->aLangName.GetBuffer(), aSysSearchPath.GetBuffer() );
923             pTC->SetSysSearchPath( aSysSearchPath );
924 
925             WriteRcContext  aContext;
926 
927             aContext.fOutput = foutput;
928             aContext.aOutputRc = it->aOutputRc;
929             aContext.aOutputSysList = aSysListTmp;
930             aContext.pCmdLine = pCL;
931 
932             // create empty sys list
933             if( aContext.aOutputSysList.getLength() )
934             {
935                 FILE* pSysListFile = fopen( aContext.aOutputSysList.getStr(), "wb" );
936 
937                 if( !pSysListFile )
938                     pTC->pEH->FatalError( ERR_OPENFILE, RscId(), aContext.aOutputSysList.getStr() );
939                 else
940                     fclose( pSysListFile );
941             }
942 
943             // parse files for specific language
944             for( pFName = pTC->aFileTab.First(); pFName && aError.IsOk(); pFName = pTC->aFileTab.Next() )
945             {
946                 if( !pFName->IsIncFile() )
947                 {
948                     aError = ParseOneFile( pTC->aFileTab.GetIndex( pFName ), &*it, &aContext );
949                     pTC->aFileTab.Seek( pFName );
950                 }
951             };
952 
953             aError = pTC->WriteRc( aContext );
954 
955             fclose( foutput );
956             fExitFile = NULL;
957             unlink( it->aOutputRc.GetBuffer() );
958             if( rename( aRcTmp.getStr(), it->aOutputRc.GetBuffer() ) )
959             {
960                 OStringBuffer aBuf;
961                 aBuf.append( aRcTmp );
962                 aBuf.append( " -> " );
963                 aBuf.append( it->aOutputRc );
964                 pTC->pEH->FatalError( ERR_RENAMEFILE, RscId(), aBuf.getStr() );
965             }
966             else
967             {
968 #ifdef UNX
969                 chmod( it->aOutputRc.GetBuffer(), S_IRWXU | S_IRWXG | S_IROTH );
970 #endif
971             }
972 
973             unlink( aSysList.getStr() );
974             if( rename( aSysListTmp.getStr(), aSysList.getStr() ) )
975             {
976                 OStringBuffer aBuf;
977                 aBuf.append( aSysListTmp );
978                 aBuf.append( " -> " );
979                 aBuf.append( aSysList );
980                 pTC->pEH->FatalError( ERR_RENAMEFILE, RscId(), aBuf.getStr() );
981             }
982             else
983             {
984 #ifdef UNX
985                 chmod( aSysList.getStr(), S_IRWXU | S_IRWXG | S_IROTH );
986 #endif
987             }
988         }
989     }
990     else
991     {
992         // parse files
993         for( pFName = pTC->aFileTab.First(); pFName && aError.IsOk(); pFName = pTC->aFileTab.Next() )
994         {
995             if( !pFName->IsIncFile() )
996             {
997                 aError = ParseOneFile( pTC->aFileTab.GetIndex( pFName ), NULL, NULL );
998                 pTC->aFileTab.Seek( pFName );
999             }
1000         };
1001     }
1002 
1003     // hxx-Datei schreiben
1004     if( pCL->aOutputHxx.Len() && aError.IsOk() )
1005     {
1006         aTmpOutputHxx = ::GetTmpFileName();
1007         if ( NULL == (fExitFile = foutput = fopen( aTmpOutputHxx.GetBuffer(), "w" )) )
1008             pTC->pEH->FatalError( ERR_OPENFILE, RscId(), aTmpOutputHxx.GetBuffer() );
1009 
1010         pTC->pEH->StdOut( "Generating .hxx file\n" );
1011 
1012         // Schreibe Datei
1013         aError = pTC->WriteHxx( foutput, NOFILE_INDEX );
1014 
1015         fclose( foutput );
1016         fExitFile = NULL;
1017     }
1018 
1019     // cxx-Datei schreiben
1020     if( pCL->aOutputCxx.Len() && aError.IsOk() )
1021     {
1022         aTmpOutputCxx = ::GetTmpFileName();
1023         if ( NULL == (fExitFile = foutput = fopen( aTmpOutputCxx.GetBuffer(), "w" )) )
1024             pTC->pEH->FatalError( ERR_OPENFILE, RscId(), aTmpOutputCxx.GetBuffer() );
1025 
1026         pTC->pEH->StdOut( "Generating .cxx file\n" );
1027 
1028         ByteString aHxx = pCL->aOutputHxx;
1029         if( !aHxx.Len() )
1030         {
1031             UniString aUniOutputCxx( pCL->aOutputCxx, RTL_TEXTENCODING_ASCII_US );
1032             aHxx = ByteString( DirEntry( aUniOutputCxx ).GetBase(), RTL_TEXTENCODING_ASCII_US );
1033             aHxx += ".hxx";
1034         }
1035 
1036         // Schreibe Datei
1037         aError = pTC->WriteCxx( foutput, NOFILE_INDEX, aHxx );
1038 
1039         fclose( foutput );
1040         fExitFile = NULL;
1041     }
1042 
1043     // RcCtor-Datei schreiben
1044     if( pCL->aOutputRcCtor.Len() && aError.IsOk() )
1045     {
1046         aTmpOutputRcCtor = ::GetTmpFileName();
1047         if ( NULL == (fExitFile = foutput = fopen( aTmpOutputRcCtor.GetBuffer(), "w" )) )
1048             pTC->pEH->FatalError( ERR_OPENFILE, RscId(), aTmpOutputRcCtor.GetBuffer() );
1049 
1050         pTC->pEH->StdOut( "Generating .cxx ressource constructor file\n" );
1051 
1052         // Schreibe Datei
1053         pTC->WriteRcCtor( foutput );
1054 
1055         fclose( foutput );
1056         fExitFile = NULL;
1057     }
1058 
1059     // src-Datei schreiben
1060     if( pCL->aOutputSrc.Len() && aError.IsOk() )
1061     {
1062         aTmpOutputSrc = ::GetTmpFileName();
1063         if ( NULL == (fExitFile = foutput = fopen( aTmpOutputSrc.GetBuffer(), "w" )) )
1064             pTC->pEH->FatalError( ERR_OPENFILE, RscId(), aTmpOutputSrc.GetBuffer() );
1065 
1066         // Schreibe Datei
1067         pTC->WriteSrc( foutput, NOFILE_INDEX, RTL_TEXTENCODING_UNICODE );
1068 
1069         fclose( foutput );
1070         fExitFile = NULL;
1071     };
1072 
1073     return( aError );
1074 }
1075 
1076 /********************************************************************/
1077 /*                                                                  */
1078 /*  Function    :   Append( )                                       */
1079 /*                                                                  */
1080 /*  Parameters  :   psw     - pointer to a preprocessor switch      */
1081 /*                                                                  */
1082 /*  Description :   appends text files                              */
1083 /********************************************************************/
Append(const ByteString & rOutputSrs,const ByteString & rTmpFile)1084 void RscCompiler::Append( const ByteString& rOutputSrs,
1085                           const ByteString& rTmpFile )
1086 {
1087     if( !::Append( rOutputSrs, rTmpFile ) )
1088     {
1089         ByteString aTemp = rOutputSrs;
1090         aTemp += " or ";
1091         aTemp += rTmpFile;
1092         pTC->pEH->FatalError( ERR_OPENFILE, RscId(), aTemp.GetBuffer() );
1093     }
1094 }
1095 
1096 /********************************************************************/
1097 /*                                                                  */
1098 /*  Function    :   GetTmpFileName()                                */
1099 /*                                                                  */
1100 /*  Description :   Packt einen Dateinamen in Tmp-Dateiliste.       */
1101 /*                                                                  */
1102 /********************************************************************/
GetTmpFileName()1103 ByteString RscCompiler::GetTmpFileName()
1104 {
1105     ByteString aFileName;
1106 
1107     aFileName = ::GetTmpFileName();
1108     aTmpFileList.Insert( new ByteString( aFileName ) );
1109     return( aFileName );
1110 }
1111 
1112 /********************************************************************/
1113 /*                                                                  */
1114 /*  Function    :   sal_Bool openinput()                            */
1115 /*                                                                  */
1116 /*  Description :   Check to see if the input file exists and can   */
1117 /*  be opened for reading.                                          */
1118 /********************************************************************/
1119 
OpenInput(const ByteString & rInput)1120 void RscCompiler::OpenInput( const ByteString& rInput )
1121 {
1122     FILE *fp;
1123                         /* try to open the input file               */
1124     if( NULL == (fp = fopen( rInput.GetBuffer(), "r")))
1125         pTC->pEH->FatalError( ERR_OPENFILE, RscId(), rInput.GetBuffer() );
1126 
1127     fclose( fp );
1128 }
1129 
1130 /*************************************************************************
1131 |*
1132 |*    GetImageFilePath()
1133 |*
1134 |*************************************************************************/
1135 
GetImageFilePath(const RscCmdLine::OutputFile & rOutputFile,const WriteRcContext & rContext,const ByteString & rBaseFileName,ByteString & rImagePath,FILE * pSysListFile)1136 bool RscCompiler::GetImageFilePath( const RscCmdLine::OutputFile& rOutputFile,
1137                                     const WriteRcContext& rContext,
1138                                     const ByteString& rBaseFileName,
1139                                     ByteString& rImagePath,
1140                                     FILE* pSysListFile )
1141 {
1142     ::std::list< ByteString >                   aFileNames;
1143     bool                                        bFound = false;
1144 
1145     ByteString  aFileName( rBaseFileName );
1146     aFileNames.push_back( aFileName += ".png" );
1147 
1148     aFileName = rBaseFileName;
1149     aFileNames.push_back( aFileName += ".bmp" );
1150 
1151     ::std::list< ByteString >::iterator aFileIter( aFileNames.begin() );
1152 
1153     while( ( aFileIter != aFileNames.end() ) && !bFound )
1154     {
1155         ::std::list< ByteString >::const_iterator aDirIter( rOutputFile.aSysSearchDirs.begin() );
1156 
1157         while( ( aDirIter != rOutputFile.aSysSearchDirs.end() ) && !bFound )
1158         {
1159             const DirEntry  aPath( String( *aDirIter, RTL_TEXTENCODING_ASCII_US ) );
1160             DirEntry        aRelPath( aPath );
1161             DirEntry        aAbsPath( aRelPath += DirEntry( String( *aFileIter, RTL_TEXTENCODING_ASCII_US ) ) );
1162 
1163             aAbsPath.ToAbs();
1164             const FileStat aFS( aAbsPath.GetFull() );
1165 
1166 #if OSL_DEBUG_LEVEL > 1
1167             fprintf( stderr, "Searching image: %s\n", ByteString( aRelPath.GetFull(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
1168 #endif
1169 
1170             if( aFS.IsKind( FSYS_KIND_FILE ) )
1171             {
1172                 std::list< std::pair< OString, OString > >::const_iterator  aReplIter( rContext.pCmdLine->m_aReplacements.begin() );
1173                 String                                                      aStr( aRelPath.GetFull() );
1174                 OString                                                     aRelPathStr( aStr.GetBuffer(), aStr.Len(), RTL_TEXTENCODING_ASCII_US );
1175 
1176                 while( ( aReplIter != rContext.pCmdLine->m_aReplacements.end() ) && !bFound )
1177                 {
1178                     ByteString aSearch( aReplIter->second );
1179                     aSearch.ToLowerAscii();
1180                     ByteString aSearchIn( aRelPathStr );
1181                     aSearchIn.ToLowerAscii();
1182                     if( aSearchIn.Search( aSearch ) == 0 )
1183                     {
1184                         sal_Int32       nCopyPos = aReplIter->second.getLength(), nLength = aRelPathStr.getLength();
1185                         const sal_Char* pChars = aRelPathStr.getStr();
1186 
1187                         while( ( nCopyPos < nLength ) && ( pChars[ nCopyPos ] == '/' || pChars[ nCopyPos ] == '\\' || pChars[ nCopyPos ] == ':' ) )
1188                         {
1189                             ++nCopyPos;
1190                         }
1191 
1192                         if( nCopyPos < nLength )
1193                             rImagePath = aRelPathStr.copy( nCopyPos ).replace( '\\', '/' );
1194 
1195                         bFound = true;
1196                     }
1197 
1198                     ++aReplIter;
1199                 }
1200 
1201                 if( bFound && pSysListFile )
1202                 {
1203                     DirEntry    aSysPath( String( *aDirIter, RTL_TEXTENCODING_ASCII_US ) );
1204                     String      aSysPathFull( ( aSysPath += DirEntry( String( *aFileIter, RTL_TEXTENCODING_ASCII_US ) ) ).GetFull() );
1205                     OString     aSysPathStr( aSysPathFull.GetBuffer(), aSysPathFull.Len(), RTL_TEXTENCODING_ASCII_US );
1206 
1207                     fprintf( pSysListFile, "%s\n", rContext.pCmdLine->substitutePaths( aSysPathStr ).getStr() );
1208                 }
1209 
1210 #if OSL_DEBUG_LEVEL > 1
1211                 fprintf( stderr, "ImagePath to add: %s\n", rImagePath.GetBuffer() );
1212 #endif
1213             }
1214 
1215             ++aDirIter;
1216         }
1217 
1218         ++aFileIter;
1219     }
1220 
1221     return bFound;
1222 }
1223 
1224 // ------------------------------------------------------------------------------
1225 
PreprocessSrsFile(const RscCmdLine::OutputFile & rOutputFile,const WriteRcContext & rContext,const DirEntry & rSrsInPath,const DirEntry & rSrsOutPath)1226 void RscCompiler::PreprocessSrsFile( const RscCmdLine::OutputFile& rOutputFile,
1227                                      const WriteRcContext& rContext,
1228                                      const DirEntry& rSrsInPath,
1229                                      const DirEntry& rSrsOutPath )
1230 {
1231     SvFileStream                aIStm( rSrsInPath.GetFull(), STREAM_READ );
1232     SvFileStream                aOStm( rSrsOutPath.GetFull(), STREAM_WRITE | STREAM_TRUNC );
1233     ::std::vector< ByteString > aMissingImages;
1234     FILE*                       pSysListFile = rContext.aOutputSysList.getLength() ? fopen( rContext.aOutputSysList.getStr(), "ab" ) : NULL;
1235     bool                        bRet = true;
1236 
1237     if( !aIStm.GetError() && !aOStm.GetError() )
1238     {
1239         ByteString aLine, aFilePath;
1240 
1241         while( aIStm.ReadLine( aLine ) )
1242         {
1243             if( ( aLine.GetTokenCount( '=' ) == 2 ) &&
1244                 ( aLine.GetToken( 0, '=' ).Search( "File" ) != STRING_NOTFOUND ) )
1245             {
1246                 ByteString aBaseFileName( aLine.GetToken( 1, '"' ).GetToken( 0, '.' ) );
1247 
1248                 if( GetImageFilePath( rOutputFile, rContext, aBaseFileName, aFilePath, pSysListFile ) )
1249                     ( ( aLine = "File = \"" ) += aFilePath ) += "\";";
1250                 else
1251                     aMissingImages.push_back( aBaseFileName );
1252 
1253                 aOStm.WriteLine( aLine );
1254             }
1255             else if( aLine.Search( "ImageList" ) != STRING_NOTFOUND )
1256             {
1257                 ::std::vector< ::std::pair< ByteString, sal_Int32 > > aEntryVector;
1258 
1259                 aOStm.WriteLine( aLine );
1260 
1261                 if( aLine.Search( ';' ) == STRING_NOTFOUND )
1262                 {
1263                     const sal_uInt32 nImgListStartPos = aIStm.Tell();
1264 
1265                     do
1266                     {
1267                         if( !aIStm.ReadLine( aLine ) )
1268                             break;
1269                     }
1270                     while( aLine.Search( "Prefix" ) == STRING_NOTFOUND );
1271 
1272                     const ByteString aPrefix( aLine.GetToken( 1, '"' ) );
1273                     aIStm.Seek( nImgListStartPos );
1274 
1275                     do
1276                     {
1277                         if (!aIStm.ReadLine( aLine ) )
1278                             break;
1279                     }
1280                     while( aLine.Search( "IdList" ) == STRING_NOTFOUND );
1281 
1282                     // scan all ids and collect images
1283                     while( aLine.Search( '}' ) == STRING_NOTFOUND )
1284                     {
1285                         if( !aIStm.ReadLine( aLine ) )
1286                             break;
1287 
1288                         aLine.EraseLeadingChars( ' ' );
1289                         aLine.EraseLeadingChars( '\t' );
1290                         aLine.EraseAllChars( ';' );
1291 
1292                         if( aLine.IsNumericAscii() )
1293                         {
1294                             ByteString  aBaseFileName( aPrefix );
1295                             sal_Int32   nNumber = atoi( aLine.GetBuffer() );
1296 
1297                             if( nNumber < 10000 )
1298                                 aBaseFileName += ByteString::CreateFromInt32( 0 );
1299 
1300                             if( GetImageFilePath( rOutputFile, rContext, aBaseFileName += aLine , aFilePath, pSysListFile ) )
1301                                 aEntryVector.push_back( ::std::pair< ByteString, sal_Int32 >( aFilePath, nNumber ) );
1302                             else
1303                                 aMissingImages.push_back( aBaseFileName );
1304                         }
1305                     }
1306 
1307                     const sal_uInt32 nImgListEndPos = aIStm.Tell();
1308                     aIStm.Seek( nImgListStartPos );
1309                     while( aIStm.Tell() < nImgListEndPos )
1310                     {
1311                         aIStm.ReadLine( aLine );
1312 
1313                         if( aLine.Search( "IdList" ) != STRING_NOTFOUND )
1314                         {
1315                             while( aLine.Search( '}' ) == STRING_NOTFOUND )
1316                                 aIStm.ReadLine( aLine );
1317                         }
1318                         else
1319                             aOStm.WriteLine( aLine );
1320                     }
1321 
1322                     aOStm.WriteLine( "FileList = {" );
1323 
1324                     for( sal_uInt32 i = 0; i < aEntryVector.size(); ++i )
1325                     {
1326                         ByteString aEntryString( "< \"" );
1327 
1328                         aEntryString += aEntryVector[ i ].first;
1329                         aEntryString += "\"; ";
1330                         aEntryString += ByteString::CreateFromInt32( aEntryVector[ i ].second );
1331                         aEntryString += "; >;";
1332 
1333                         aOStm.WriteLine( aEntryString );
1334                     }
1335 
1336                     aOStm.WriteLine( "};" );
1337                 }
1338                 else
1339                     aOStm.WriteLine( aLine );
1340             }
1341             else
1342                 aOStm.WriteLine( aLine );
1343         }
1344     }
1345     else
1346         bRet = false;
1347 
1348     if( aMissingImages.size() > 0 )
1349     {
1350         ByteString aImagesStr;
1351 
1352         for( sal_uInt32 i = 0; i < aMissingImages.size(); ++i )
1353         {
1354             if( i )
1355                 aImagesStr += ' ';
1356 
1357             aImagesStr += aMissingImages[ i ];
1358         }
1359 
1360         pTC->pEH->FatalError( ERR_NOIMAGE, RscId(), aImagesStr.GetBuffer() );
1361     }
1362 
1363     if( pSysListFile )
1364         fclose( pSysListFile );
1365 }
1366 
1367