Use o3tl::convert in Math
[LibreOffice.git] / l10ntools / source / xrmmerge.cxx
blobd1dc5bb4dcd294d3cade3e48225777c4c7b077e3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <cstring>
24 #include <stdio.h>
26 #include <common.hxx>
27 #include <export.hxx>
28 #include <po.hxx>
29 #include <xrmlex.hxx>
30 #include <xrmmerge.hxx>
31 #include <tokens.h>
32 #include <helper.hxx>
33 #include <iostream>
34 #include <fstream>
35 #include <vector>
36 #include <memory>
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;
50 extern "C" {
51 // the whole interface to lexer is in this extern "C" section
53 extern bool GetOutputFile( int argc, char* argv[])
55 bDisplayName = false;
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;
66 return true;
68 else
70 // command line is not valid
71 common::writeUsage("xrmex","*.xrm/*.xml");
72 return false;
76 int InitXrmExport( const char* pFilename)
78 // instantiate Export
79 OString sFilename( pFilename );
81 if ( bMergeMode )
82 pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
83 else if (!sOutputFile.isEmpty())
84 pParser = new XRMResExport( sOutputFile, sInputFileName );
86 return 1;
89 int EndXrmExport()
91 delete pParser;
92 return 1;
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");
105 if ( !pFile ){
106 fprintf( stderr, "Error: Could not open file %s\n",
107 sInputFileName.getStr());
109 else {
110 return pFile;
113 // this means the file could not be opened
114 return nullptr;
117 int WorkOnTokenSet( int nTyp, char *pTokenText )
119 //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
120 pParser->Execute( nTyp, pTokenText );
122 return 1;
125 int SetError()
127 pParser->SetError();
128 return 1;
132 extern "C" {
134 int GetError()
136 return pParser->GetError();
143 XRMResParser::XRMResParser()
144 : bError( false ),
145 bText( false )
149 XRMResParser::~XRMResParser()
153 void XRMResParser::Execute( int nToken, char * pToken )
155 OString rToken( pToken );
157 switch ( nToken ) {
158 case XRM_TEXT_START:{
159 OString sNewGID = GetAttribute( rToken, "id" );
160 if ( sNewGID != sGID ) {
161 sGID = sNewGID;
163 bText = true;
164 sCurrentText = OString();
165 sCurrentOpenTag = rToken;
166 Output( rToken );
168 break;
170 case XRM_TEXT_END: {
171 sCurrentCloseTag = rToken;
172 sResourceType = OString ( "readmeitem" );
173 sLangAttribute = OString ( "xml:lang" );
174 WorkOnText( sCurrentOpenTag, sCurrentText );
175 Output( sCurrentText );
176 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
177 bText = false;
178 rToken = OString();
179 sCurrentText = OString();
181 break;
183 case DESC_DISPLAY_NAME_START:{
184 bDisplayName = true;
186 break;
188 case DESC_DISPLAY_NAME_END:{
189 bDisplayName = false;
191 break;
193 case DESC_TEXT_START:{
194 if (bDisplayName) {
195 sGID = OString("dispname");
196 bText = true;
197 sCurrentText = OString();
198 sCurrentOpenTag = rToken;
199 Output( rToken );
202 break;
204 case DESC_TEXT_END: {
205 if (bDisplayName) {
206 sCurrentCloseTag = rToken;
207 sResourceType = OString ( "description" );
208 sLangAttribute = OString ( "lang" );
209 WorkOnText( sCurrentOpenTag, sCurrentText );
210 Output( sCurrentText );
211 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
212 bText = false;
213 rToken = OString();
214 sCurrentText = OString();
217 break;
219 case DESC_EXTENSION_DESCRIPTION_START: {
220 bExtensionDescription = true;
222 break;
224 case DESC_EXTENSION_DESCRIPTION_END: {
225 bExtensionDescription = false;
227 break;
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();
236 Output( rToken );
237 WorkOnDesc( sCurrentOpenTag, sCurrentText );
238 sCurrentCloseTag = rToken;
239 Output( sCurrentText );
240 rToken = OString();
241 sCurrentText = OString();
244 break;
246 default:
247 if ( bText ) {
248 sCurrentText += rToken;
250 break;
253 if ( !bText )
255 Output( 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 );
265 if ( nPos<0 )
266 return OString();
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 )
282 : sPath( 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,
300 OString &rText )
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);
310 file.close();
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,
320 OString &rText )
322 OString sLang( GetAttribute( rOpenTag, sLangAttribute ));
324 if ( !pResData )
326 pResData.reset( new ResData( GetGID() ) );
328 pResData->sText[sLang] = rText;
331 void XRMResExport::EndOfText(
332 const OString &,
333 const OString & )
335 if ( pResData )
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 );
344 pResData.reset();
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();
361 else
362 aLanguages.push_back( sLanguage );
363 pOutputStream.open(
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,
377 OString &rText )
379 WorkOnText( rOpenTag, rText);
380 if ( pMergeDataFile && pResData ) {
381 MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData.get() );
382 if ( pEntrys ) {
383 OString sCur;
384 OString sDescFilename = GetAttribute ( rOpenTag, "xlink:href" );
385 for( size_t n = 0; n < aLanguages.size(); n++ ){
386 sCur = aLanguages[ n ];
387 OString sText;
388 if ( !sCur.equalsIgnoreAsciiCase("en-US") &&
389 ( pEntrys->GetText( sText, sCur, true )) &&
390 !sText.isEmpty())
392 OString sAdditionalLine{ "\n " + rOpenTag };
393 OString sSearch{ sLangAttribute + "=\"" };
394 OString sReplace( sSearch );
396 sSearch += GetAttribute( rOpenTag, sLangAttribute );
397 sReplace += sCur;
398 sAdditionalLine = sAdditionalLine.replaceFirst(
399 sSearch, sReplace);
401 sSearch = OString("xlink:href=\"");
402 sReplace = sSearch;
404 const OString sLocDescFilename = sDescFilename.replaceFirst( "en-US", sCur);
406 sSearch += sDescFilename;
407 sReplace += sLocDescFilename;
408 sAdditionalLine = sAdditionalLine.replaceFirst(
409 sSearch, sReplace);
411 Output( sAdditionalLine );
413 sal_Int32 i = sOutputFile.lastIndexOf('/');
414 if (i == -1) {
415 std::cerr
416 << "Error: output file " << sOutputFile
417 << " does not contain any /\n";
418 throw false; //TODO
420 OString sOutputDescFile(
421 sOutputFile.subView(0, i + 1) + sLocDescFilename);
422 std::ofstream file(sOutputDescFile.getStr());
423 if (file.is_open()) {
424 file << sText;
425 file.close();
426 } else {
427 std::cerr
428 << "Error: cannot write "
429 << sOutputDescFile << '\n';
430 throw false; //TODO
436 pResData.reset();
439 void XRMResMerge::WorkOnText(
440 const OString &,
441 OString & )
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 )
460 Output( rCloseTag );
461 if ( pMergeDataFile && pResData ) {
462 MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData.get() );
463 if ( pEntrys ) {
464 OString sCur;
465 for( size_t n = 0; n < aLanguages.size(); n++ ){
466 sCur = aLanguages[ n ];
467 OString sContent;
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 );
479 sReplace += sCur;
481 sAdditionalLine = sAdditionalLine.replaceFirst(
482 sSearch, sReplace) + sText + rCloseTag;
484 Output( sAdditionalLine );
489 pResData.reset();
492 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */