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>
29 #include <xrmmerge.hxx>
36 // set of global variables
37 static bool bMergeMode
;
38 static bool bDisplayName
;
39 static bool bExtensionDescription
;
40 static OString sLanguage
;
41 static OString sInputFileName
;
42 static OString sOutputFile
;
43 static OString sMergeSrc
;
44 static OString sLangAttribute
;
45 static OString sResourceType
;
46 static XRMResParser
*pParser
= nullptr;
49 // the whole interface to lexer is in this extern "C" section
51 extern bool GetOutputFile( int argc
, char* argv
[])
54 bExtensionDescription
= false;
56 common::HandledArgs aArgs
;
57 if ( common::handleArguments(argc
, argv
, aArgs
) )
59 bMergeMode
= aArgs
.m_bMergeMode
;
60 sLanguage
= aArgs
.m_sLanguage
;
61 sInputFileName
= aArgs
.m_sInputFile
;
62 sOutputFile
= aArgs
.m_sOutputFile
;
63 sMergeSrc
= aArgs
.m_sMergeSrc
;
68 // command line is not valid
69 common::writeUsage("xrmex"_ostr
,"*.xrm/*.xml"_ostr
);
74 int InitXrmExport( const char* pFilename
)
77 OString
sFilename( pFilename
);
80 pParser
= new XRMResMerge( sMergeSrc
, sOutputFile
, sFilename
);
81 else if (!sOutputFile
.isEmpty())
82 pParser
= new XRMResExport( sOutputFile
, sInputFileName
);
92 extern const char* getFilename()
94 return sInputFileName
.getStr();
97 extern FILE *GetXrmFile()
99 // look for valid filename
100 if (!sInputFileName
.isEmpty()) {
101 //TODO: explicit BOM handling?
102 FILE * pFile
= fopen(sInputFileName
.getStr(), "r");
104 fprintf( stderr
, "Error: Could not open file %s\n",
105 sInputFileName
.getStr());
111 // this means the file could not be opened
115 int WorkOnTokenSet( int nTyp
, char *pTokenText
)
117 //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
118 pParser
->Execute( nTyp
, pTokenText
);
134 return pParser
->GetError();
141 XRMResParser::XRMResParser()
147 XRMResParser::~XRMResParser()
151 void XRMResParser::Execute( int nToken
, char * pToken
)
153 OString
rToken( pToken
);
156 case XRM_TEXT_START
:{
157 OString sNewGID
= GetAttribute( rToken
, "id" );
158 if ( sNewGID
!= sGID
) {
162 sCurrentText
= OString();
163 sCurrentOpenTag
= rToken
;
169 sCurrentCloseTag
= rToken
;
170 sResourceType
= "readmeitem"_ostr
;
171 sLangAttribute
= "xml:lang"_ostr
;
172 WorkOnText( sCurrentOpenTag
, sCurrentText
);
173 Output( sCurrentText
);
174 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
177 sCurrentText
= OString();
181 case DESC_DISPLAY_NAME_START
:{
186 case DESC_DISPLAY_NAME_END
:{
187 bDisplayName
= false;
191 case DESC_TEXT_START
:{
193 sGID
= "dispname"_ostr
;
195 sCurrentText
= OString();
196 sCurrentOpenTag
= rToken
;
202 case DESC_TEXT_END
: {
204 sCurrentCloseTag
= rToken
;
205 sResourceType
= "description"_ostr
;
206 sLangAttribute
= "lang"_ostr
;
207 WorkOnText( sCurrentOpenTag
, sCurrentText
);
208 Output( sCurrentText
);
209 EndOfText( sCurrentOpenTag
, sCurrentCloseTag
);
212 sCurrentText
= OString();
217 case DESC_EXTENSION_DESCRIPTION_START
: {
218 bExtensionDescription
= true;
222 case DESC_EXTENSION_DESCRIPTION_END
: {
223 bExtensionDescription
= false;
227 case DESC_EXTENSION_DESCRIPTION_SRC
: {
228 if (bExtensionDescription
) {
229 sGID
= "extdesc"_ostr
;
230 sResourceType
= "description"_ostr
;
231 sLangAttribute
= "lang"_ostr
;
232 sCurrentOpenTag
= rToken
;
233 sCurrentText
= OString();
235 WorkOnDesc( sCurrentOpenTag
, sCurrentText
);
236 sCurrentCloseTag
= rToken
;
237 Output( sCurrentText
);
239 sCurrentText
= OString();
246 sCurrentText
+= rToken
;
257 OString
XRMResParser::GetAttribute( const OString
&rToken
, std::string_view rAttribute
)
259 const OString sSearch
{ OString::Concat(" ") + rAttribute
+ "=" };
260 OString sTmp
{ rToken
.replace('\t', ' ') };
261 sal_Int32 nPos
= sTmp
.indexOf( sSearch
);
266 return sTmp
.getToken(1, '"', nPos
);
270 void XRMResParser::Error( const OString
&rError
)
272 yyerror(rError
.getStr());
278 XRMResExport::XRMResExport(
279 const OString
&rOutputFile
, OString _sFilePath
)
280 : sPath(std::move( _sFilePath
))
282 pOutputStream
.open( rOutputFile
, PoOfstream::APP
);
283 if (!pOutputStream
.isOpen())
285 Error( "Unable to open output file: " + rOutputFile
);
289 XRMResExport::~XRMResExport()
291 pOutputStream
.close();
294 void XRMResExport::Output( const OString
& ) {}
296 void XRMResExport::WorkOnDesc(
297 const OString
&rOpenTag
,
300 const OString sDescFileName
{ sInputFileName
.replaceAll("description.xml"_ostr
, OString())
301 + GetAttribute( rOpenTag
, "xlink:href" ) };
302 std::ifstream
file (sDescFileName
.getStr(), std::ios::in
|std::ios::binary
|std::ios::ate
);
303 if (file
.is_open()) {
304 int size
= static_cast<int>(file
.tellg());
305 std::unique_ptr
<char[]> memblock(new char [size
+1]);
306 file
.seekg (0, std::ios::beg
);
307 file
.read (memblock
.get(), size
);
309 memblock
[size
] = '\0';
310 rText
= OString(memblock
.get());
312 WorkOnText( rOpenTag
, rText
);
313 EndOfText( rOpenTag
, rOpenTag
);
316 void XRMResExport::WorkOnText(
317 const OString
&rOpenTag
,
320 OString
sLang( GetAttribute( rOpenTag
, sLangAttribute
));
324 pResData
.reset( new ResData( GetGID() ) );
326 pResData
->sText
[sLang
] = rText
;
329 void XRMResExport::EndOfText(
335 OString sAct
= pResData
->sText
["en-US"_ostr
];
337 if( !sAct
.isEmpty() )
338 common::writePoEntry(
339 "Xrmex"_ostr
, pOutputStream
, sPath
, sResourceType
,
340 pResData
->sGId
, OString(), OString(), sAct
);
348 XRMResMerge::XRMResMerge(
349 const OString
&rMergeSource
, const OString
&rOutputFile
,
351 : sFilename(std::move( _sFilename
))
353 if (!rMergeSource
.isEmpty() && sLanguage
.equalsIgnoreAsciiCase("ALL"))
355 pMergeDataFile
.reset(new MergeDataFile(
356 rMergeSource
, sInputFileName
, false));
357 aLanguages
= pMergeDataFile
->GetLanguages();
360 aLanguages
.push_back( sLanguage
);
362 rOutputFile
.getStr(), std::ios_base::out
| std::ios_base::trunc
);
363 if (!pOutputStream
.is_open()) {
364 Error( "Unable to open output file: " + rOutputFile
);
368 XRMResMerge::~XRMResMerge()
370 pOutputStream
.close();
373 void XRMResMerge::WorkOnDesc(
374 const OString
&rOpenTag
,
377 WorkOnText( rOpenTag
, rText
);
378 if ( pMergeDataFile
&& pResData
) {
379 MergeEntrys
*pEntrys
= pMergeDataFile
->GetMergeEntrys( pResData
.get() );
382 OString sDescFilename
= GetAttribute ( rOpenTag
, "xlink:href" );
383 for( size_t n
= 0; n
< aLanguages
.size(); n
++ ){
384 sCur
= aLanguages
[ n
];
386 if ( !sCur
.equalsIgnoreAsciiCase("en-US") &&
387 ( pEntrys
->GetText( sText
, sCur
, true )) &&
390 OString sAdditionalLine
{ "\n " + rOpenTag
};
391 OString sSearch
{ sLangAttribute
+ "=\"" };
392 OString
sReplace( sSearch
);
394 sSearch
+= GetAttribute( rOpenTag
, sLangAttribute
);
396 sAdditionalLine
= sAdditionalLine
.replaceFirst(
399 sSearch
= "xlink:href=\""_ostr
;
402 const OString sLocDescFilename
= sDescFilename
.replaceFirst( "en-US"_ostr
, sCur
);
404 sSearch
+= sDescFilename
;
405 sReplace
+= sLocDescFilename
;
406 sAdditionalLine
= sAdditionalLine
.replaceFirst(
409 Output( sAdditionalLine
);
411 sal_Int32 i
= sOutputFile
.lastIndexOf('/');
414 << "Error: output file " << sOutputFile
415 << " does not contain any /\n";
418 OString
sOutputDescFile(
419 sOutputFile
.subView(0, i
+ 1) + sLocDescFilename
);
420 std::ofstream
file(sOutputDescFile
.getStr());
421 if (file
.is_open()) {
426 << "Error: cannot write "
427 << sOutputDescFile
<< '\n';
437 void XRMResMerge::WorkOnText(
441 if ( pMergeDataFile
&& !pResData
) {
442 pResData
.reset( new ResData( GetGID(), sFilename
) );
443 pResData
->sResTyp
= sResourceType
;
447 void XRMResMerge::Output( const OString
& rOutput
)
449 if (!rOutput
.isEmpty())
450 pOutputStream
<< rOutput
;
453 void XRMResMerge::EndOfText(
454 const OString
&rOpenTag
,
455 const OString
&rCloseTag
)
459 if ( pMergeDataFile
&& pResData
) {
460 MergeEntrys
*pEntrys
= pMergeDataFile
->GetMergeEntrys( pResData
.get() );
463 for( size_t n
= 0; n
< aLanguages
.size(); n
++ ){
464 sCur
= aLanguages
[ n
];
466 if (!sCur
.equalsIgnoreAsciiCase("en-US") &&
467 ( pEntrys
->GetText( sContent
, sCur
, true )) &&
468 !sContent
.isEmpty() &&
469 helper::isWellFormedXML( sContent
))
471 const OString
& sText( sContent
);
472 OString sAdditionalLine
{ "\n " + rOpenTag
};
473 OString sSearch
{ sLangAttribute
+ "=\"" };
474 OString
sReplace( sSearch
);
476 sSearch
+= GetAttribute( rOpenTag
, sLangAttribute
);
479 sAdditionalLine
= sAdditionalLine
.replaceFirst(
480 sSearch
, sReplace
) + sText
+ rCloseTag
;
482 Output( sAdditionalLine
);
490 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */