summaryrefslogtreecommitdiffstats
path: root/l10ntools/source/xrmmerge.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'l10ntools/source/xrmmerge.cxx')
-rw-r--r--l10ntools/source/xrmmerge.cxx489
1 files changed, 489 insertions, 0 deletions
diff --git a/l10ntools/source/xrmmerge.cxx b/l10ntools/source/xrmmerge.cxx
new file mode 100644
index 000000000..b7a7e0042
--- /dev/null
+++ b/l10ntools/source/xrmmerge.cxx
@@ -0,0 +1,489 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <stdio.h>
+
+#include <common.hxx>
+#include <export.hxx>
+#include <po.hxx>
+#include <xrmlex.hxx>
+#include <xrmmerge.hxx>
+#include <tokens.h>
+#include <helper.hxx>
+#include <iostream>
+#include <vector>
+#include <memory>
+
+// set of global variables
+static bool bMergeMode;
+static bool bDisplayName;
+static bool bExtensionDescription;
+static OString sLanguage;
+static OString sInputFileName;
+static OString sOutputFile;
+static OString sMergeSrc;
+static OString sLangAttribute;
+static OString sResourceType;
+static XRMResParser *pParser = nullptr;
+
+extern "C" {
+// the whole interface to lexer is in this extern "C" section
+
+extern bool GetOutputFile( int argc, char* argv[])
+{
+ bDisplayName = false;
+ bExtensionDescription = false;
+
+ common::HandledArgs aArgs;
+ if ( common::handleArguments(argc, argv, aArgs) )
+ {
+ bMergeMode = aArgs.m_bMergeMode;
+ sLanguage = aArgs.m_sLanguage;
+ sInputFileName = aArgs.m_sInputFile;
+ sOutputFile = aArgs.m_sOutputFile;
+ sMergeSrc = aArgs.m_sMergeSrc;
+ return true;
+ }
+ else
+ {
+ // command line is not valid
+ common::writeUsage("xrmex","*.xrm/*.xml");
+ return false;
+ }
+}
+
+int InitXrmExport( const char* pFilename)
+{
+ // instantiate Export
+ OString sFilename( pFilename );
+
+ if ( bMergeMode )
+ pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
+ else if (!sOutputFile.isEmpty())
+ pParser = new XRMResExport( sOutputFile, sInputFileName );
+
+ return 1;
+}
+
+int EndXrmExport()
+{
+ delete pParser;
+ return 1;
+}
+extern const char* getFilename()
+{
+ return sInputFileName.getStr();
+}
+
+extern FILE *GetXrmFile()
+{
+ // look for valid filename
+ if (!sInputFileName.isEmpty()) {
+ //TODO: explicit BOM handling?
+ FILE * pFile = fopen(sInputFileName.getStr(), "r");
+ if ( !pFile ){
+ fprintf( stderr, "Error: Could not open file %s\n",
+ sInputFileName.getStr());
+ }
+ else {
+ return pFile;
+ }
+ }
+ // this means the file could not be opened
+ return nullptr;
+}
+
+int WorkOnTokenSet( int nTyp, char *pTokenText )
+{
+ //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
+ pParser->Execute( nTyp, pTokenText );
+
+ return 1;
+}
+
+int SetError()
+{
+ pParser->SetError();
+ return 1;
+}
+}
+
+extern "C" {
+
+int GetError()
+{
+ return pParser->GetError();
+}
+}
+
+
+
+
+XRMResParser::XRMResParser()
+ : bError( false ),
+ bText( false )
+{
+}
+
+XRMResParser::~XRMResParser()
+{
+}
+
+void XRMResParser::Execute( int nToken, char * pToken )
+{
+ OString rToken( pToken );
+
+ switch ( nToken ) {
+ case XRM_TEXT_START:{
+ OString sNewGID = GetAttribute( rToken, "id" );
+ if ( sNewGID != sGID ) {
+ sGID = sNewGID;
+ }
+ bText = true;
+ sCurrentText = OString();
+ sCurrentOpenTag = rToken;
+ Output( rToken );
+ }
+ break;
+
+ case XRM_TEXT_END: {
+ sCurrentCloseTag = rToken;
+ sResourceType = OString ( "readmeitem" );
+ sLangAttribute = OString ( "xml:lang" );
+ WorkOnText( sCurrentOpenTag, sCurrentText );
+ Output( sCurrentText );
+ EndOfText( sCurrentOpenTag, sCurrentCloseTag );
+ bText = false;
+ rToken = OString();
+ sCurrentText = OString();
+ }
+ break;
+
+ case DESC_DISPLAY_NAME_START:{
+ bDisplayName = true;
+ }
+ break;
+
+ case DESC_DISPLAY_NAME_END:{
+ bDisplayName = false;
+ }
+ break;
+
+ case DESC_TEXT_START:{
+ if (bDisplayName) {
+ sGID = OString("dispname");
+ bText = true;
+ sCurrentText = OString();
+ sCurrentOpenTag = rToken;
+ Output( rToken );
+ }
+ }
+ break;
+
+ case DESC_TEXT_END: {
+ if (bDisplayName) {
+ sCurrentCloseTag = rToken;
+ sResourceType = OString ( "description" );
+ sLangAttribute = OString ( "lang" );
+ WorkOnText( sCurrentOpenTag, sCurrentText );
+ Output( sCurrentText );
+ EndOfText( sCurrentOpenTag, sCurrentCloseTag );
+ bText = false;
+ rToken = OString();
+ sCurrentText = OString();
+ }
+ }
+ break;
+
+ case DESC_EXTENSION_DESCRIPTION_START: {
+ bExtensionDescription = true;
+ }
+ break;
+
+ case DESC_EXTENSION_DESCRIPTION_END: {
+ bExtensionDescription = false;
+ }
+ break;
+
+ case DESC_EXTENSION_DESCRIPTION_SRC: {
+ if (bExtensionDescription) {
+ sGID = OString("extdesc");
+ sResourceType = OString ( "description" );
+ sLangAttribute = OString ( "lang" );
+ sCurrentOpenTag = rToken;
+ sCurrentText = OString();
+ Output( rToken );
+ WorkOnDesc( sCurrentOpenTag, sCurrentText );
+ sCurrentCloseTag = rToken;
+ Output( sCurrentText );
+ rToken = OString();
+ sCurrentText = OString();
+ }
+ }
+ break;
+
+ default:
+ if ( bText ) {
+ sCurrentText += rToken;
+ }
+ break;
+ }
+
+ if ( !bText )
+ {
+ Output( rToken );
+ }
+}
+
+OString XRMResParser::GetAttribute( const OString &rToken, std::string_view rAttribute )
+{
+ const OString sSearch{ OString::Concat(" ") + rAttribute + "=" };
+ OString sTmp{ rToken.replace('\t', ' ') };
+ sal_Int32 nPos = sTmp.indexOf( sSearch );
+
+ if ( nPos<0 )
+ return OString();
+
+ return sTmp.getToken(1, '"', nPos);
+}
+
+
+void XRMResParser::Error( const OString &rError )
+{
+ yyerror(rError.getStr());
+}
+
+
+
+
+XRMResExport::XRMResExport(
+ const OString &rOutputFile, const OString &rFilePath )
+ : sPath( rFilePath )
+{
+ pOutputStream.open( rOutputFile, PoOfstream::APP );
+ if (!pOutputStream.isOpen())
+ {
+ Error( "Unable to open output file: " + rOutputFile );
+ }
+}
+
+XRMResExport::~XRMResExport()
+{
+ pOutputStream.close();
+}
+
+void XRMResExport::Output( const OString& ) {}
+
+void XRMResExport::WorkOnDesc(
+ const OString &rOpenTag,
+ OString &rText )
+{
+ const OString sDescFileName{ sInputFileName.replaceAll("description.xml", OString())
+ + GetAttribute( rOpenTag, "xlink:href" ) };
+ std::ifstream file (sDescFileName.getStr(), std::ios::in|std::ios::binary|std::ios::ate);
+ if (file.is_open()) {
+ int size = static_cast<int>(file.tellg());
+ std::unique_ptr<char[]> memblock(new char [size+1]);
+ file.seekg (0, std::ios::beg);
+ file.read (memblock.get(), size);
+ file.close();
+ memblock[size] = '\0';
+ rText = OString(memblock.get());
+ }
+ WorkOnText( rOpenTag, rText );
+ EndOfText( rOpenTag, rOpenTag );
+}
+
+void XRMResExport::WorkOnText(
+ const OString &rOpenTag,
+ OString &rText )
+{
+ OString sLang( GetAttribute( rOpenTag, sLangAttribute ));
+
+ if ( !pResData )
+ {
+ pResData.reset( new ResData( GetGID() ) );
+ }
+ pResData->sText[sLang] = rText;
+}
+
+void XRMResExport::EndOfText(
+ const OString &,
+ const OString & )
+{
+ if ( pResData )
+ {
+ OString sAct = pResData->sText["en-US"];
+
+ if( !sAct.isEmpty() )
+ common::writePoEntry(
+ "Xrmex", pOutputStream, sPath, sResourceType,
+ pResData->sGId, OString(), OString(), sAct );
+ }
+ pResData.reset();
+}
+
+
+
+
+XRMResMerge::XRMResMerge(
+ const OString &rMergeSource, const OString &rOutputFile,
+ const OString &rFilename )
+ : sFilename( rFilename )
+{
+ if (!rMergeSource.isEmpty() && sLanguage.equalsIgnoreAsciiCase("ALL"))
+ {
+ pMergeDataFile.reset(new MergeDataFile(
+ rMergeSource, sInputFileName, false));
+ aLanguages = pMergeDataFile->GetLanguages();
+ }
+ else
+ aLanguages.push_back( sLanguage );
+ pOutputStream.open(
+ rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
+ if (!pOutputStream.is_open()) {
+ Error( "Unable to open output file: " + rOutputFile );
+ }
+}
+
+XRMResMerge::~XRMResMerge()
+{
+ pOutputStream.close();
+}
+
+void XRMResMerge::WorkOnDesc(
+ const OString &rOpenTag,
+ OString &rText )
+{
+ WorkOnText( rOpenTag, rText);
+ if ( pMergeDataFile && pResData ) {
+ MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData.get() );
+ if ( pEntrys ) {
+ OString sCur;
+ OString sDescFilename = GetAttribute ( rOpenTag, "xlink:href" );
+ for( size_t n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ OString sText;
+ if ( !sCur.equalsIgnoreAsciiCase("en-US") &&
+ ( pEntrys->GetText( sText, sCur, true )) &&
+ !sText.isEmpty())
+ {
+ OString sAdditionalLine{ "\n " + rOpenTag };
+ OString sSearch{ sLangAttribute + "=\"" };
+ OString sReplace( sSearch );
+
+ sSearch += GetAttribute( rOpenTag, sLangAttribute );
+ sReplace += sCur;
+ sAdditionalLine = sAdditionalLine.replaceFirst(
+ sSearch, sReplace);
+
+ sSearch = OString("xlink:href=\"");
+ sReplace = sSearch;
+
+ const OString sLocDescFilename = sDescFilename.replaceFirst( "en-US", sCur);
+
+ sSearch += sDescFilename;
+ sReplace += sLocDescFilename;
+ sAdditionalLine = sAdditionalLine.replaceFirst(
+ sSearch, sReplace);
+
+ Output( sAdditionalLine );
+
+ sal_Int32 i = sOutputFile.lastIndexOf('/');
+ if (i == -1) {
+ std::cerr
+ << "Error: output file " << sOutputFile
+ << " does not contain any /\n";
+ throw false; //TODO
+ }
+ OString sOutputDescFile(
+ sOutputFile.subView(0, i + 1) + sLocDescFilename);
+ std::ofstream file(sOutputDescFile.getStr());
+ if (file.is_open()) {
+ file << sText;
+ file.close();
+ } else {
+ std::cerr
+ << "Error: cannot write "
+ << sOutputDescFile << '\n';
+ throw false; //TODO
+ }
+ }
+ }
+ }
+ }
+ pResData.reset();
+}
+
+void XRMResMerge::WorkOnText(
+ const OString &,
+ OString & )
+{
+ if ( pMergeDataFile && !pResData ) {
+ pResData.reset( new ResData( GetGID(), sFilename ) );
+ pResData->sResTyp = sResourceType;
+ }
+}
+
+void XRMResMerge::Output( const OString& rOutput )
+{
+ if (!rOutput.isEmpty())
+ pOutputStream << rOutput;
+}
+
+void XRMResMerge::EndOfText(
+ const OString &rOpenTag,
+ const OString &rCloseTag )
+{
+
+ Output( rCloseTag );
+ if ( pMergeDataFile && pResData ) {
+ MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData.get() );
+ if ( pEntrys ) {
+ OString sCur;
+ for( size_t n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ OString sContent;
+ if (!sCur.equalsIgnoreAsciiCase("en-US") &&
+ ( pEntrys->GetText( sContent, sCur, true )) &&
+ !sContent.isEmpty() &&
+ helper::isWellFormedXML( sContent ))
+ {
+ const OString& sText( sContent );
+ OString sAdditionalLine{ "\n " + rOpenTag };
+ OString sSearch{ sLangAttribute + "=\"" };
+ OString sReplace( sSearch );
+
+ sSearch += GetAttribute( rOpenTag, sLangAttribute );
+ sReplace += sCur;
+
+ sAdditionalLine = sAdditionalLine.replaceFirst(
+ sSearch, sReplace) + sText + rCloseTag;
+
+ Output( sAdditionalLine );
+ }
+ }
+ }
+ }
+ pResData.reset();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */