1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
30 #include <xrmmerge.hxx>
38 // set of global variables
39 static bool bMergeMode
;
40 static bool bDisplayName
;
41 static bool bExtensionDescription
;
42 static OString sLanguage
;
43 static OString sInputFileName
;
44 static OString sOutputFile
;
45 static OString sMergeSrc
;
46 static OString sLangAttribute
;
47 static OString sResourceType
;
48 static XRMResParser
*pParser
= nullptr;
51 // the whole interface to lexer is in this extern "C" section
53 extern bool GetOutputFile( int argc
, char* argv
[])
56 bExtensionDescription
= false;
58 common::HandledArgs aArgs
;
59 if ( common::handleArguments(argc
, argv
, aArgs
) )
61 bMergeMode
= aArgs
.m_bMergeMode
;
62 sLanguage
= aArgs
.m_sLanguage
;
63 sInputFileName
= aArgs
.m_sInputFile
;
64 sOutputFile
= aArgs
.m_sOutputFile
;
65 sMergeSrc
= aArgs
.m_sMergeSrc
;
70 // command line is not valid
71 common::writeUsage("xrmex","*.xrm/*.xml");
76 int InitXrmExport( const char* pFilename
)
79 OString
sFilename( pFilename
);
82 pParser
= new XRMResMerge( sMergeSrc
, sOutputFile
, sFilename
);
83 else if (!sOutputFile
.isEmpty())
84 pParser
= new XRMResExport( sOutputFile
, sInputFileName
);
94 extern const char* getFilename()
96 return sInputFileName
.getStr();
99 extern FILE *GetXrmFile()
101 // look for valid filename
102 if (!sInputFileName
.isEmpty()) {
103 //TODO: explicit BOM handling?
104 FILE * pFile
= fopen(sInputFileName
.getStr(), "r");
106 fprintf( stderr
, "Error: Could not open file %s\n",
107 sInputFileName
.getStr());
113 // this means the file could not be opened
117 int WorkOnTokenSet( int nTyp
, char *pTokenText
)
119 //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
120 pParser
->Execute( nTyp
, pTokenText
);
136 return pParser
->GetError();
143 XRMResParser::XRMResParser()
149 XRMResParser::~XRMResParser()
153 void XRMResParser::Execute( int nToken
, char * pToken
)
155 OString
rToken( pToken
);
158 case XRM_TEXT_START
:{
159 OString sNewGID
= GetAttribute( rToken
, "id" );
160 if ( sNewGID
!= sGID
) {
164 sCurrentText
= OString();
165 sCurrentOpenTag
= rToken
;
171 sCurrentCloseTag
= rToken
;
172 sResourceType
= OString ( "readmeitem" );
173 sLangAttribute
= OString ( "xml:lang" );
174 WorkOnText( sCurrentOpenTag
, sCurrentText
);
175 Output( sCurrentText
);
176 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
179 sCurrentText
= OString();
183 case DESC_DISPLAY_NAME_START
:{
188 case DESC_DISPLAY_NAME_END
:{
189 bDisplayName
= false;
193 case DESC_TEXT_START
:{
195 sGID
= OString("dispname");
197 sCurrentText
= OString();
198 sCurrentOpenTag
= rToken
;
204 case DESC_TEXT_END
: {
206 sCurrentCloseTag
= rToken
;
207 sResourceType
= OString ( "description" );
208 sLangAttribute
= OString ( "lang" );
209 WorkOnText( sCurrentOpenTag
, sCurrentText
);
210 Output( sCurrentText
);
211 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
214 sCurrentText
= OString();
219 case DESC_EXTENSION_DESCRIPTION_START
: {
220 bExtensionDescription
= true;
224 case DESC_EXTENSION_DESCRIPTION_END
: {
225 bExtensionDescription
= false;
229 case DESC_EXTENSION_DESCRIPTION_SRC
: {
230 if (bExtensionDescription
) {
231 sGID
= OString("extdesc");
232 sResourceType
= OString ( "description" );
233 sLangAttribute
= OString ( "lang" );
234 sCurrentOpenTag
= rToken
;
235 sCurrentText
= OString();
237 WorkOnDesc( sCurrentOpenTag
, sCurrentText
);
238 sCurrentCloseTag
= rToken
;
239 Output( sCurrentText
);
241 sCurrentText
= OString();
248 sCurrentText
+= rToken
;
259 OString
XRMResParser::GetAttribute( const OString
&rToken
, std::string_view rAttribute
)
261 const OString sSearch
{ OString::Concat(" ") + rAttribute
+ "=" };
262 OString sTmp
{ rToken
.replace('\t', ' ') };
263 sal_Int32 nPos
= sTmp
.indexOf( sSearch
);
268 return sTmp
.getToken(1, '"', nPos
);
272 void XRMResParser::Error( const OString
&rError
)
274 yyerror(rError
.getStr());
280 XRMResExport::XRMResExport(
281 const OString
&rOutputFile
, const OString
&rFilePath
)
284 pOutputStream
.open( rOutputFile
, PoOfstream::APP
);
285 if (!pOutputStream
.isOpen())
287 Error( "Unable to open output file: " + rOutputFile
);
291 XRMResExport::~XRMResExport()
293 pOutputStream
.close();
296 void XRMResExport::Output( const OString
& ) {}
298 void XRMResExport::WorkOnDesc(
299 const OString
&rOpenTag
,
302 const OString sDescFileName
{ sInputFileName
.replaceAll("description.xml", OString())
303 + GetAttribute( rOpenTag
, "xlink:href" ) };
304 std::ifstream
file (sDescFileName
.getStr(), std::ios::in
|std::ios::binary
|std::ios::ate
);
305 if (file
.is_open()) {
306 int size
= static_cast<int>(file
.tellg());
307 std::unique_ptr
<char[]> memblock(new char [size
+1]);
308 file
.seekg (0, std::ios::beg
);
309 file
.read (memblock
.get(), size
);
311 memblock
[size
] = '\0';
312 rText
= OString(memblock
.get());
314 WorkOnText( rOpenTag
, rText
);
315 EndOfText( rOpenTag
, rOpenTag
);
318 void XRMResExport::WorkOnText(
319 const OString
&rOpenTag
,
322 OString
sLang( GetAttribute( rOpenTag
, sLangAttribute
));
326 pResData
.reset( new ResData( GetGID() ) );
328 pResData
->sText
[sLang
] = rText
;
331 void XRMResExport::EndOfText(
337 OString sAct
= pResData
->sText
["en-US"];
339 if( !sAct
.isEmpty() )
340 common::writePoEntry(
341 "Xrmex", pOutputStream
, sPath
, sResourceType
,
342 pResData
->sGId
, OString(), OString(), sAct
);
350 XRMResMerge::XRMResMerge(
351 const OString
&rMergeSource
, const OString
&rOutputFile
,
352 const OString
&rFilename
)
353 : sFilename( rFilename
)
355 if (!rMergeSource
.isEmpty() && sLanguage
.equalsIgnoreAsciiCase("ALL"))
357 pMergeDataFile
.reset(new MergeDataFile(
358 rMergeSource
, sInputFileName
, false));
359 aLanguages
= pMergeDataFile
->GetLanguages();
362 aLanguages
.push_back( sLanguage
);
364 rOutputFile
.getStr(), std::ios_base::out
| std::ios_base::trunc
);
365 if (!pOutputStream
.is_open()) {
366 Error( "Unable to open output file: " + rOutputFile
);
370 XRMResMerge::~XRMResMerge()
372 pOutputStream
.close();
375 void XRMResMerge::WorkOnDesc(
376 const OString
&rOpenTag
,
379 WorkOnText( rOpenTag
, rText
);
380 if ( pMergeDataFile
&& pResData
) {
381 MergeEntrys
*pEntrys
= pMergeDataFile
->GetMergeEntrys( pResData
.get() );
384 OString sDescFilename
= GetAttribute ( rOpenTag
, "xlink:href" );
385 for( size_t n
= 0; n
< aLanguages
.size(); n
++ ){
386 sCur
= aLanguages
[ n
];
388 if ( !sCur
.equalsIgnoreAsciiCase("en-US") &&
389 ( pEntrys
->GetText( sText
, sCur
, true )) &&
392 OString sAdditionalLine
{ "\n " + rOpenTag
};
393 OString sSearch
{ sLangAttribute
+ "=\"" };
394 OString
sReplace( sSearch
);
396 sSearch
+= GetAttribute( rOpenTag
, sLangAttribute
);
398 sAdditionalLine
= sAdditionalLine
.replaceFirst(
401 sSearch
= OString("xlink:href=\"");
404 const OString sLocDescFilename
= sDescFilename
.replaceFirst( "en-US", sCur
);
406 sSearch
+= sDescFilename
;
407 sReplace
+= sLocDescFilename
;
408 sAdditionalLine
= sAdditionalLine
.replaceFirst(
411 Output( sAdditionalLine
);
413 sal_Int32 i
= sOutputFile
.lastIndexOf('/');
416 << "Error: output file " << sOutputFile
417 << " does not contain any /\n";
420 OString
sOutputDescFile(
421 sOutputFile
.subView(0, i
+ 1) + sLocDescFilename
);
422 std::ofstream
file(sOutputDescFile
.getStr());
423 if (file
.is_open()) {
428 << "Error: cannot write "
429 << sOutputDescFile
<< '\n';
439 void XRMResMerge::WorkOnText(
443 if ( pMergeDataFile
&& !pResData
) {
444 pResData
.reset( new ResData( GetGID(), sFilename
) );
445 pResData
->sResTyp
= sResourceType
;
449 void XRMResMerge::Output( const OString
& rOutput
)
451 if (!rOutput
.isEmpty())
452 pOutputStream
<< rOutput
;
455 void XRMResMerge::EndOfText(
456 const OString
&rOpenTag
,
457 const OString
&rCloseTag
)
461 if ( pMergeDataFile
&& pResData
) {
462 MergeEntrys
*pEntrys
= pMergeDataFile
->GetMergeEntrys( pResData
.get() );
465 for( size_t n
= 0; n
< aLanguages
.size(); n
++ ){
466 sCur
= aLanguages
[ n
];
468 if (!sCur
.equalsIgnoreAsciiCase("en-US") &&
469 ( pEntrys
->GetText( sContent
, sCur
, true )) &&
470 !sContent
.isEmpty() &&
471 helper::isWellFormedXML( sContent
))
473 const OString
& sText( sContent
);
474 OString sAdditionalLine
{ "\n " + rOpenTag
};
475 OString sSearch
{ sLangAttribute
+ "=\"" };
476 OString
sReplace( sSearch
);
478 sSearch
+= GetAttribute( rOpenTag
, sLangAttribute
);
481 sAdditionalLine
= sAdditionalLine
.replaceFirst(
482 sSearch
, sReplace
) + sText
+ rCloseTag
;
484 Output( sAdditionalLine
);
492 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */