office-gobmx/l10ntools/source/xrmmerge.cxx
Gabor Kelemen 67478f9d63 Recheck modules [i-l]* with IWYU
See tdf#42949 for motivation

Change-Id: I758bb27e93779e3df21c463714e49354748f446f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128715
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
2022-01-27 18:52:16 +01:00

489 lines
13 KiB
C++

/* -*- 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: */