nss: upgrade to release 3.73
[LibreOffice.git] / l10ntools / source / xrmmerge.cxx
blob62734f04ddd9ab8df543dd0d20d98a705fe77557
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 using namespace std;
40 // set of global variables
41 static bool bMergeMode;
42 static bool bDisplayName;
43 static bool bExtensionDescription;
44 static OString sLanguage;
45 static OString sInputFileName;
46 static OString sOutputFile;
47 static OString sMergeSrc;
48 static OString sLangAttribute;
49 static OString sResourceType;
50 static XRMResParser *pParser = nullptr;
52 extern "C" {
53 // the whole interface to lexer is in this extern "C" section
55 extern bool GetOutputFile( int argc, char* argv[])
57 bDisplayName = false;
58 bExtensionDescription = false;
60 common::HandledArgs aArgs;
61 if ( common::handleArguments(argc, argv, aArgs) )
63 bMergeMode = aArgs.m_bMergeMode;
64 sLanguage = aArgs.m_sLanguage;
65 sInputFileName = aArgs.m_sInputFile;
66 sOutputFile = aArgs.m_sOutputFile;
67 sMergeSrc = aArgs.m_sMergeSrc;
68 return true;
70 else
72 // command line is not valid
73 common::writeUsage("xrmex","*.xrm/*.xml");
74 return false;
78 int InitXrmExport( const char* pFilename)
80 // instantiate Export
81 OString sFilename( pFilename );
83 if ( bMergeMode )
84 pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
85 else if (!sOutputFile.isEmpty())
86 pParser = new XRMResExport( sOutputFile, sInputFileName );
88 return 1;
91 int EndXrmExport()
93 delete pParser;
94 return 1;
96 extern const char* getFilename()
98 return sInputFileName.getStr();
101 extern FILE *GetXrmFile()
103 // look for valid filename
104 if (!sInputFileName.isEmpty()) {
105 //TODO: explicit BOM handling?
106 FILE * pFile = fopen(sInputFileName.getStr(), "r");
107 if ( !pFile ){
108 fprintf( stderr, "Error: Could not open file %s\n",
109 sInputFileName.getStr());
111 else {
112 return pFile;
115 // this means the file could not be opened
116 return nullptr;
119 int WorkOnTokenSet( int nTyp, char *pTokenText )
121 //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
122 pParser->Execute( nTyp, pTokenText );
124 return 1;
127 int SetError()
129 pParser->SetError();
130 return 1;
134 extern "C" {
136 int GetError()
138 return pParser->GetError();
145 XRMResParser::XRMResParser()
146 : bError( false ),
147 bText( false )
151 XRMResParser::~XRMResParser()
155 void XRMResParser::Execute( int nToken, char * pToken )
157 OString rToken( pToken );
159 switch ( nToken ) {
160 case XRM_TEXT_START:{
161 OString sNewGID = GetAttribute( rToken, "id" );
162 if ( sNewGID != sGID ) {
163 sGID = sNewGID;
165 bText = true;
166 sCurrentText = OString();
167 sCurrentOpenTag = rToken;
168 Output( rToken );
170 break;
172 case XRM_TEXT_END: {
173 sCurrentCloseTag = rToken;
174 sResourceType = OString ( "readmeitem" );
175 sLangAttribute = OString ( "xml:lang" );
176 WorkOnText( sCurrentOpenTag, sCurrentText );
177 Output( sCurrentText );
178 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
179 bText = false;
180 rToken = OString();
181 sCurrentText = OString();
183 break;
185 case DESC_DISPLAY_NAME_START:{
186 bDisplayName = true;
188 break;
190 case DESC_DISPLAY_NAME_END:{
191 bDisplayName = false;
193 break;
195 case DESC_TEXT_START:{
196 if (bDisplayName) {
197 sGID = OString("dispname");
198 bText = true;
199 sCurrentText = OString();
200 sCurrentOpenTag = rToken;
201 Output( rToken );
204 break;
206 case DESC_TEXT_END: {
207 if (bDisplayName) {
208 sCurrentCloseTag = rToken;
209 sResourceType = OString ( "description" );
210 sLangAttribute = OString ( "lang" );
211 WorkOnText( sCurrentOpenTag, sCurrentText );
212 Output( sCurrentText );
213 EndOfText( sCurrentOpenTag, sCurrentCloseTag );
214 bText = false;
215 rToken = OString();
216 sCurrentText = OString();
219 break;
221 case DESC_EXTENSION_DESCRIPTION_START: {
222 bExtensionDescription = true;
224 break;
226 case DESC_EXTENSION_DESCRIPTION_END: {
227 bExtensionDescription = false;
229 break;
231 case DESC_EXTENSION_DESCRIPTION_SRC: {
232 if (bExtensionDescription) {
233 sGID = OString("extdesc");
234 sResourceType = OString ( "description" );
235 sLangAttribute = OString ( "lang" );
236 sCurrentOpenTag = rToken;
237 sCurrentText = OString();
238 Output( rToken );
239 WorkOnDesc( sCurrentOpenTag, sCurrentText );
240 sCurrentCloseTag = rToken;
241 Output( sCurrentText );
242 rToken = OString();
243 sCurrentText = OString();
246 break;
248 default:
249 if ( bText ) {
250 sCurrentText += rToken;
252 break;
255 if ( !bText )
257 Output( rToken );
261 OString XRMResParser::GetAttribute( const OString &rToken, const OString &rAttribute )
263 const OString sSearch{ " " + rAttribute + "=" };
264 OString sTmp{ rToken.replace('\t', ' ') };
265 sal_Int32 nPos = sTmp.indexOf( sSearch );
267 if ( nPos<0 )
268 return OString();
270 return sTmp.getToken(1, '"', nPos);
274 void XRMResParser::Error( const OString &rError )
276 yyerror(rError.getStr());
282 XRMResExport::XRMResExport(
283 const OString &rOutputFile, const OString &rFilePath )
284 : XRMResParser(),
285 sPath( rFilePath )
287 pOutputStream.open( rOutputFile, PoOfstream::APP );
288 if (!pOutputStream.isOpen())
290 Error( "Unable to open output file: " + rOutputFile );
294 XRMResExport::~XRMResExport()
296 pOutputStream.close();
299 void XRMResExport::Output( const OString& ) {}
301 void XRMResExport::WorkOnDesc(
302 const OString &rOpenTag,
303 OString &rText )
305 const OString sDescFileName{ sInputFileName.replaceAll("description.xml", OString())
306 + GetAttribute( rOpenTag, "xlink:href" ) };
307 ifstream file (sDescFileName.getStr(), ios::in|ios::binary|ios::ate);
308 if (file.is_open()) {
309 int size = static_cast<int>(file.tellg());
310 std::unique_ptr<char[]> memblock(new char [size+1]);
311 file.seekg (0, ios::beg);
312 file.read (memblock.get(), size);
313 file.close();
314 memblock[size] = '\0';
315 rText = OString(memblock.get());
317 WorkOnText( rOpenTag, rText );
318 EndOfText( rOpenTag, rOpenTag );
321 void XRMResExport::WorkOnText(
322 const OString &rOpenTag,
323 OString &rText )
325 OString sLang( GetAttribute( rOpenTag, sLangAttribute ));
327 if ( !pResData )
329 pResData.reset( new ResData( GetGID() ) );
331 pResData->sText[sLang] = rText;
334 void XRMResExport::EndOfText(
335 const OString &,
336 const OString & )
338 if ( pResData )
340 OString sAct = pResData->sText["en-US"];
342 if( !sAct.isEmpty() )
343 common::writePoEntry(
344 "Xrmex", pOutputStream, sPath, sResourceType,
345 pResData->sGId, OString(), OString(), sAct );
347 pResData.reset();
353 XRMResMerge::XRMResMerge(
354 const OString &rMergeSource, const OString &rOutputFile,
355 const OString &rFilename )
356 : XRMResParser(),
357 sFilename( rFilename )
359 if (!rMergeSource.isEmpty() && sLanguage.equalsIgnoreAsciiCase("ALL"))
361 pMergeDataFile.reset(new MergeDataFile(
362 rMergeSource, sInputFileName, false));
363 aLanguages = pMergeDataFile->GetLanguages();
365 else
366 aLanguages.push_back( sLanguage );
367 pOutputStream.open(
368 rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
369 if (!pOutputStream.is_open()) {
370 Error( "Unable to open output file: " + rOutputFile );
374 XRMResMerge::~XRMResMerge()
376 pOutputStream.close();
379 void XRMResMerge::WorkOnDesc(
380 const OString &rOpenTag,
381 OString &rText )
383 WorkOnText( rOpenTag, rText);
384 if ( pMergeDataFile && pResData ) {
385 MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData.get() );
386 if ( pEntrys ) {
387 OString sCur;
388 OString sDescFilename = GetAttribute ( rOpenTag, "xlink:href" );
389 for( size_t n = 0; n < aLanguages.size(); n++ ){
390 sCur = aLanguages[ n ];
391 OString sText;
392 if ( !sCur.equalsIgnoreAsciiCase("en-US") &&
393 ( pEntrys->GetText( sText, sCur, true )) &&
394 !sText.isEmpty())
396 OString sAdditionalLine{ "\n " + rOpenTag };
397 OString sSearch{ sLangAttribute + "=\"" };
398 OString sReplace( sSearch );
400 sSearch += GetAttribute( rOpenTag, sLangAttribute );
401 sReplace += sCur;
402 sAdditionalLine = sAdditionalLine.replaceFirst(
403 sSearch, sReplace);
405 sSearch = OString("xlink:href=\"");
406 sReplace = sSearch;
408 const OString sLocDescFilename = sDescFilename.replaceFirst( "en-US", sCur);
410 sSearch += sDescFilename;
411 sReplace += sLocDescFilename;
412 sAdditionalLine = sAdditionalLine.replaceFirst(
413 sSearch, sReplace);
415 Output( sAdditionalLine );
417 sal_Int32 i = sOutputFile.lastIndexOf('/');
418 if (i == -1) {
419 std::cerr
420 << "Error: output file " << sOutputFile
421 << " does not contain any /\n";
422 throw false; //TODO
424 OString sOutputDescFile(
425 sOutputFile.subView(0, i + 1) + sLocDescFilename);
426 ofstream file(sOutputDescFile.getStr());
427 if (file.is_open()) {
428 file << sText;
429 file.close();
430 } else {
431 std::cerr
432 << "Error: cannot write "
433 << sOutputDescFile << '\n';
434 throw false; //TODO
440 pResData.reset();
443 void XRMResMerge::WorkOnText(
444 const OString &,
445 OString & )
447 if ( pMergeDataFile && !pResData ) {
448 pResData.reset( new ResData( GetGID(), sFilename ) );
449 pResData->sResTyp = sResourceType;
453 void XRMResMerge::Output( const OString& rOutput )
455 if (!rOutput.isEmpty())
456 pOutputStream << rOutput;
459 void XRMResMerge::EndOfText(
460 const OString &rOpenTag,
461 const OString &rCloseTag )
464 Output( rCloseTag );
465 if ( pMergeDataFile && pResData ) {
466 MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData.get() );
467 if ( pEntrys ) {
468 OString sCur;
469 for( size_t n = 0; n < aLanguages.size(); n++ ){
470 sCur = aLanguages[ n ];
471 OString sContent;
472 if (!sCur.equalsIgnoreAsciiCase("en-US") &&
473 ( pEntrys->GetText( sContent, sCur, true )) &&
474 !sContent.isEmpty() &&
475 helper::isWellFormedXML( sContent ))
477 const OString& sText( sContent );
478 OString sAdditionalLine{ "\n " + rOpenTag };
479 OString sSearch{ sLangAttribute + "=\"" };
480 OString sReplace( sSearch );
482 sSearch += GetAttribute( rOpenTag, sLangAttribute );
483 sReplace += sCur;
485 sAdditionalLine = sAdditionalLine.replaceFirst(
486 sSearch, sReplace) + sText + rCloseTag;
488 Output( sAdditionalLine );
493 pResData.reset();
496 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */