1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "sal/config.h"
37 #include "xrmmerge.hxx"
45 void yyerror( const char * );
46 void YYWarning( const char * );
48 // defines to parse command line
49 #define STATE_NON 0x0001
50 #define STATE_INPUT 0x0002
51 #define STATE_OUTPUT 0x0003
52 #define STATE_PRJ 0x0004
53 #define STATE_ROOT 0x0005
54 #define STATE_MERGESRC 0x0006
55 #define STATE_ERRORLOG 0x0007
56 #define STATE_LANGUAGES 0x000C
58 // set of global variables
59 sal_Bool bEnableExport
;
63 sal_Bool bDisplayName
;
64 sal_Bool bExtensionDescription
;
66 rtl::OString sPrjRoot
;
67 rtl::OString sInputFileName
;
68 rtl::OString sActFileName
;
69 rtl::OString sOutputFile
;
70 rtl::OString sMergeSrc
;
71 rtl::OString sLangAttribute
;
72 rtl::OString sResourceType
;
73 XRMResParser
*pParser
= NULL
;
76 // the whole interface to lexer is in this extern "C" section
78 /*****************************************************************************/
79 extern char *GetOutputFile( int argc
, char* argv
[])
80 /*****************************************************************************/
82 bEnableExport
= sal_False
;
83 bMergeMode
= sal_False
;
86 bDisplayName
= sal_False
;
87 bExtensionDescription
= sal_False
;
92 Export::sLanguages
= "";
93 sal_uInt16 nState
= STATE_NON
;
94 sal_Bool bInput
= sal_False
;
97 for( int i
= 1; i
< argc
; i
++ ) {
98 if ( rtl::OString( argv
[ i
] ).toAsciiUpperCase() == "-I" ) {
99 nState
= STATE_INPUT
; // next token specifies source file
101 else if ( rtl::OString( argv
[ i
] ).toAsciiUpperCase() == "-O" ) {
102 nState
= STATE_OUTPUT
; // next token specifies the dest file
104 else if ( rtl::OString( argv
[ i
] ).toAsciiUpperCase() == "-P" ) {
105 nState
= STATE_PRJ
; // next token specifies the cur. project
107 else if ( rtl::OString( argv
[ i
] ).toAsciiUpperCase() == "-R" ) {
108 nState
= STATE_ROOT
; // next token specifies path to project root
110 else if ( rtl::OString( argv
[ i
] ).toAsciiUpperCase() == "-M" ) {
111 nState
= STATE_MERGESRC
; // next token specifies the merge database
113 else if ( rtl::OString( argv
[ i
] ).toAsciiUpperCase() == "-E" ) {
114 nState
= STATE_ERRORLOG
;
115 bErrorLog
= sal_False
;
117 else if ( rtl::OString( argv
[ i
] ).toAsciiUpperCase() == "-L" ) {
118 nState
= STATE_LANGUAGES
;
123 return NULL
; // no valid command line
126 sInputFileName
= argv
[ i
];
127 bInput
= sal_True
; // source file found
131 sOutputFile
= argv
[ i
]; // the dest. file
135 sPrj
= rtl::OString( argv
[ i
]);
139 sPrjRoot
= rtl::OString( argv
[ i
]); // path to project root
142 case STATE_MERGESRC
: {
143 sMergeSrc
= rtl::OString( argv
[ i
]);
144 bMergeMode
= sal_True
; // activate merge mode, cause merge database found
147 case STATE_LANGUAGES
: {
148 Export::sLanguages
= rtl::OString( argv
[ i
]);
156 // command line is valid
157 bEnableExport
= sal_True
;
158 char *pReturn
= new char[ sOutputFile
.getLength() + 1 ];
159 std::strcpy( pReturn
, sOutputFile
.getStr()); // #100211# - checked
163 // command line is not valid
167 /*****************************************************************************/
168 int InitXrmExport( char *pOutput
, char* pFilename
)
169 /*****************************************************************************/
171 // instanciate Export
172 rtl::OString
sOutput( pOutput
);
173 rtl::OString
sFilename( pFilename
);
174 Export::InitLanguages( false );
177 pParser
= new XRMResMerge( sMergeSrc
, sOutputFile
, sFilename
);
178 else if (!sOutputFile
.isEmpty()) {
179 pParser
= new XRMResExport( sOutputFile
, sPrj
, sActFileName
);
185 /*****************************************************************************/
187 /*****************************************************************************/
192 extern const char* getFilename()
194 return sInputFileName
.getStr();
196 /*****************************************************************************/
197 extern FILE *GetXrmFile()
198 /*****************************************************************************/
200 // look for valid filename
201 if (!sInputFileName
.isEmpty()) {
202 //TODO: explicit BOM handling?
203 FILE * pFile
= fopen(sInputFileName
.getStr(), "r");
205 fprintf( stderr
, "Error: Could not open file %s\n",
206 sInputFileName
.getStr());
210 sActFileName
= common::pathnameToken(
211 sInputFileName
.getStr(), sPrjRoot
.getStr());
216 // this means the file could not be opened
220 /*****************************************************************************/
221 int WorkOnTokenSet( int nTyp
, char *pTokenText
)
222 /*****************************************************************************/
224 //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
225 pParser
->Execute( nTyp
, pTokenText
);
230 /*****************************************************************************/
232 /*****************************************************************************/
240 /*****************************************************************************/
242 /*****************************************************************************/
244 return pParser
->GetError();
249 // class XRMResParser
253 /*****************************************************************************/
254 XRMResParser::XRMResParser()
255 /*****************************************************************************/
256 : bError( sal_False
),
259 aLanguages
= Export::GetLanguages();
262 /*****************************************************************************/
263 XRMResParser::~XRMResParser()
264 /*****************************************************************************/
268 /*****************************************************************************/
269 int XRMResParser::Execute( int nToken
, char * pToken
)
270 /*****************************************************************************/
272 rtl::OString
rToken( pToken
);
275 case XRM_TEXT_START
:{
276 rtl::OString sNewLID
= GetAttribute( rToken
, "id" );
277 if ( sNewLID
!= sLID
) {
282 sCurrentOpenTag
= rToken
;
288 sCurrentCloseTag
= rToken
;
289 sResourceType
= rtl::OString ( "readmeitem" );
290 sLangAttribute
= rtl::OString ( "xml:lang" );
291 WorkOnText( sCurrentOpenTag
, sCurrentText
);
292 Output( sCurrentText
);
293 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
295 rToken
= rtl::OString("");
296 sCurrentText
= rtl::OString("");
300 case DESC_DISPLAY_NAME_START
:{
301 bDisplayName
= sal_True
;
305 case DESC_DISPLAY_NAME_END
:{
306 bDisplayName
= sal_False
;
310 case DESC_TEXT_START
:{
312 sLID
= rtl::OString("dispname");
315 sCurrentOpenTag
= rToken
;
321 case DESC_TEXT_END
: {
323 sCurrentCloseTag
= rToken
;
324 sResourceType
= rtl::OString ( "description" );
325 sLangAttribute
= rtl::OString ( "lang" );
326 WorkOnText( sCurrentOpenTag
, sCurrentText
);
327 Output( sCurrentText
);
328 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
330 rToken
= rtl::OString("");
331 sCurrentText
= rtl::OString("");
336 case DESC_EXTENSION_DESCRIPTION_START
: {
337 bExtensionDescription
= sal_True
;
341 case DESC_EXTENSION_DESCRIPTION_END
: {
342 bExtensionDescription
= sal_False
;
346 case DESC_EXTENSION_DESCRIPTION_SRC
: {
347 if (bExtensionDescription
) {
348 sLID
= rtl::OString("extdesc");
349 sResourceType
= rtl::OString ( "description" );
350 sLangAttribute
= rtl::OString ( "lang" );
351 sCurrentOpenTag
= rToken
;
352 sCurrentText
= rtl::OString("");
354 WorkOnDesc( sCurrentOpenTag
, sCurrentText
);
355 sCurrentCloseTag
= rToken
;
356 Output( sCurrentText
);
357 rToken
= rtl::OString("");
358 sCurrentText
= rtl::OString("");
365 sCurrentText
+= rToken
;
377 /*****************************************************************************/
378 rtl::OString
XRMResParser::GetAttribute( const rtl::OString
&rToken
, const rtl::OString
&rAttribute
)
379 /*****************************************************************************/
381 rtl::OString
sTmp( rToken
);
382 sTmp
= sTmp
.replace('\t', ' ');
384 rtl::OString
sSearch( " " );
385 sSearch
+= rAttribute
;
387 sal_Int32 nPos
= sTmp
.indexOf( sSearch
);
391 sTmp
= sTmp
.copy( nPos
);
392 rtl::OString sId
= sTmp
.getToken(1, '"');
395 return rtl::OString();
399 /*****************************************************************************/
400 void XRMResParser::Error( const rtl::OString
&rError
)
401 /*****************************************************************************/
403 yyerror(( char * ) rError
.getStr());
406 /*****************************************************************************/
407 void XRMResParser::ConvertStringToDBFormat( rtl::OString
&rString
)
408 /*****************************************************************************/
410 rString
= rString
.trim().replaceAll("\t", "\\t");
413 /*****************************************************************************/
414 void XRMResParser::ConvertStringToXMLFormat( rtl::OString
&rString
)
415 /*****************************************************************************/
417 rString
= rString
.replaceAll("\\t", "\t");
423 // class XRMResOutputParser
426 /*****************************************************************************/
427 XRMResOutputParser::XRMResOutputParser ( const rtl::OString
&rOutputFile
)
428 /*****************************************************************************/
430 aLanguages
= Export::GetLanguages();
432 rOutputFile
.getStr(), std::ios_base::out
| std::ios_base::trunc
);
433 if (!pOutputStream
.is_open()) {
434 rtl::OString
sError( "Unable to open output file: " );
435 sError
+= rOutputFile
;
440 /*****************************************************************************/
441 XRMResOutputParser::~XRMResOutputParser()
442 /*****************************************************************************/
444 pOutputStream
.close();
448 // class XMLResExport
451 /*****************************************************************************/
452 XRMResExport::XRMResExport(
453 const rtl::OString
&rOutputFile
, const rtl::OString
&rProject
,
454 const rtl::OString
&rFilePath
)
455 /*****************************************************************************/
456 : XRMResOutputParser( rOutputFile
),
461 aLanguages
= Export::GetLanguages();
464 /*****************************************************************************/
465 XRMResExport::~XRMResExport()
466 /*****************************************************************************/
471 void XRMResExport::Output( const rtl::OString
& ) {}
473 /*****************************************************************************/
474 void XRMResExport::WorkOnDesc(
475 const rtl::OString
&rOpenTag
,
478 /*****************************************************************************/
480 rtl::OString
sDescFileName(
481 sInputFileName
.replaceAll("description.xml", rtl::OString()));
482 sDescFileName
+= GetAttribute( rOpenTag
, "xlink:href" );
485 ifstream
file (sDescFileName
.getStr(), ios::in
|ios::binary
|ios::ate
);
486 if (file
.is_open()) {
487 size
= static_cast<int>(file
.tellg());
488 memblock
= new char [size
+1];
489 file
.seekg (0, ios::beg
);
490 file
.read (memblock
, size
);
492 memblock
[size
] = '\0';
493 rText
= rtl::OString(memblock
).replaceAll("\n", "\\n");
496 WorkOnText( rOpenTag
, rText
);
497 EndOfText( rOpenTag
, rOpenTag
);
500 //*****************************************************************************/
501 void XRMResExport::WorkOnText(
502 const rtl::OString
&rOpenTag
,
505 /*****************************************************************************/
507 rtl::OString
sLang( GetAttribute( rOpenTag
, sLangAttribute
));
511 rtl::OString
sPlatform( "" );
512 pResData
= new ResData( sPlatform
, GetGID() );
513 pResData
->sId
= GetLID();
516 rtl::OString
sText(rText
);
517 ConvertStringToDBFormat(sText
);
518 pResData
->sText
[sLang
] = sText
;
521 /*****************************************************************************/
522 void XRMResExport::EndOfText(
523 const rtl::OString
&,
526 /*****************************************************************************/
531 for( unsigned int n
= 0; n
< aLanguages
.size(); n
++ )
533 sCur
= aLanguages
[ n
];
536 pResData
->sText
[sCur
].replaceAll("\x0A", rtl::OString()));
538 rtl::OString
sOutput( sPrj
); sOutput
+= "\t";
541 sOutput
+= sResourceType
;
543 sOutput
+= pResData
->sId
;
544 // USE LID AS GID OR MERGE DON'T WORK
545 //sOutput += pResData->sGId;
547 sOutput
+= pResData
->sId
;
548 sOutput
+= "\t\t\t0\t";
553 sOutput
+= "\t\t\t\t";
555 sOutput
= sOutput
.replace('\0', '_');
556 if( sAct
.getLength() > 1 )
557 pOutputStream
<< sOutput
.getStr() << '\n';
568 /*****************************************************************************/
569 XRMResMerge::XRMResMerge(
570 const rtl::OString
&rMergeSource
, const rtl::OString
&rOutputFile
,
571 const rtl::OString
&rFilename
)
572 /*****************************************************************************/
573 : XRMResOutputParser( rOutputFile
),
574 pMergeDataFile( NULL
),
575 sFilename( rFilename
) ,
578 if (!rMergeSource
.isEmpty())
579 pMergeDataFile
= new MergeDataFile(
580 rMergeSource
, sInputFileName
, bErrorLog
);
581 if( Export::sLanguages
.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("ALL")))
583 Export::SetLanguages( pMergeDataFile
->GetLanguages() );
584 aLanguages
= pMergeDataFile
->GetLanguages();
587 aLanguages
= Export::GetLanguages();
590 /*****************************************************************************/
591 XRMResMerge::~XRMResMerge()
592 /*****************************************************************************/
594 delete pMergeDataFile
;
598 /*****************************************************************************/
599 void XRMResMerge::WorkOnDesc(
600 const rtl::OString
&rOpenTag
,
603 /*****************************************************************************/
605 WorkOnText( rOpenTag
, rText
);
606 if ( pMergeDataFile
&& pResData
) {
607 PFormEntrys
*pEntrys
= pMergeDataFile
->GetPFormEntrys( pResData
);
610 rtl::OString sDescFilename
= GetAttribute ( rOpenTag
, "xlink:href" );
611 for( unsigned int n
= 0; n
< aLanguages
.size(); n
++ ){
612 sCur
= aLanguages
[ n
];
613 rtl::OString sContent
;
614 if ( !sCur
.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("en-US")) &&
616 sContent
, STRING_TYP_TEXT
, sCur
, sal_True
)) &&
617 ( sContent
!= "-" ) && !sContent
.isEmpty())
619 rtl::OString
sText( sContent
);
620 rtl::OString
sAdditionalLine( "\n " );
621 sAdditionalLine
+= rOpenTag
;
622 rtl::OString sSearch
= sLangAttribute
;
624 rtl::OString
sReplace( sSearch
);
626 sSearch
+= GetAttribute( rOpenTag
, sLangAttribute
);
628 sAdditionalLine
= sAdditionalLine
.replaceFirst(
631 sSearch
= rtl::OString("xlink:href=\"");
634 rtl::OString sLocDescFilename
= sDescFilename
;
635 sLocDescFilename
= sLocDescFilename
.replaceFirst(
638 sSearch
+= sDescFilename
;
639 sReplace
+= sLocDescFilename
;
640 sAdditionalLine
= sAdditionalLine
.replaceFirst(
643 Output( sAdditionalLine
);
645 sal_Int32 i
= sOutputFile
.lastIndexOf('/');
648 << "Error: output file " << sOutputFile
.getStr()
649 << " does not contain any /\n";
652 rtl::OString
sOutputDescFile(
653 sOutputFile
.copy(0, i
+ 1) + sLocDescFilename
);
654 sText
= sText
.replaceAll("\\n", "\n");
655 ofstream
file(sOutputDescFile
.getStr());
656 if (file
.is_open()) {
657 file
<< sText
.getStr();
661 << "Error: cannot write "
662 << sOutputDescFile
.getStr() << '\n';
673 /*****************************************************************************/
674 void XRMResMerge::WorkOnText(
675 const rtl::OString
&rOpenTag
,
678 /*****************************************************************************/
680 rtl::OString
sLang( GetAttribute( rOpenTag
, sLangAttribute
));
682 if ( pMergeDataFile
) {
684 rtl::OString
sPlatform( "" );
685 pResData
= new ResData( sPlatform
, GetLID() , sFilename
);
686 pResData
->sId
= GetLID();
687 pResData
->sResTyp
= sResourceType
;
690 PFormEntrys
*pEntrys
= pMergeDataFile
->GetPFormEntrys( pResData
);
692 rtl::OString sContent
;
693 if ( Export::isAllowed( sLang
) &&
695 sContent
, STRING_TYP_TEXT
, sLang
)) &&
696 ( sContent
!= "-" ) && !sContent
.isEmpty())
700 ConvertStringToXMLFormat( rText
);
706 /*****************************************************************************/
707 void XRMResMerge::Output( const rtl::OString
& rOutput
)
708 /*****************************************************************************/
710 if (!rOutput
.isEmpty())
711 pOutputStream
<< rOutput
.getStr();
714 /*****************************************************************************/
715 void XRMResMerge::EndOfText(
716 const rtl::OString
&rOpenTag
,
717 const rtl::OString
&rCloseTag
719 /*****************************************************************************/
723 if ( pMergeDataFile
&& pResData
) {
724 PFormEntrys
*pEntrys
= pMergeDataFile
->GetPFormEntrys( pResData
);
727 for( unsigned int n
= 0; n
< aLanguages
.size(); n
++ ){
728 sCur
= aLanguages
[ n
];
729 rtl::OString sContent
;
730 if (!sCur
.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("en-US")) &&
732 sContent
, STRING_TYP_TEXT
, sCur
, sal_True
)) &&
733 ( sContent
!= "-" ) && !sContent
.isEmpty())
735 rtl::OString
sText( sContent
);
736 rtl::OString
sAdditionalLine( "\n " );
737 sAdditionalLine
+= rOpenTag
;
738 rtl::OString sSearch
= sLangAttribute
;
740 rtl::OString
sReplace( sSearch
);
742 sSearch
+= GetAttribute( rOpenTag
, sLangAttribute
);
745 sAdditionalLine
= sAdditionalLine
.replaceFirst(
748 sAdditionalLine
+= sText
;
749 sAdditionalLine
+= rCloseTag
;
751 Output( sAdditionalLine
);
760 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */