fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / l10ntools / source / cfgmerge.cxx
blobd68327d29e7046806a120b9ce23eabeeb8193026
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 "cfglex.hxx"
23 #include "common.hxx"
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstring>
29 #include "boost/scoped_ptr.hpp"
30 #include "rtl/strbuf.hxx"
32 #include "helper.hxx"
33 #include "export.hxx"
34 #include "cfgmerge.hxx"
35 #include "tokens.h"
37 void yyerror(char const *);
39 namespace {
41 namespace global {
43 OString inputPathname;
44 boost::scoped_ptr< CfgParser > parser;
49 extern "C" {
51 FILE * init(int argc, char ** argv) {
53 common::HandledArgs aArgs;
54 if ( !common::handleArguments(argc, argv, aArgs) )
56 common::writeUsage("cfgex","*.xcu");
57 std::exit(EXIT_FAILURE);
59 global::inputPathname = aArgs.m_sInputFile;
61 FILE * pFile = std::fopen(global::inputPathname.getStr(), "r");
62 if (pFile == 0) {
63 std::fprintf(
64 stderr, "Error: Cannot open file \"%s\"\n",
65 global::inputPathname.getStr() );
66 std::exit(EXIT_FAILURE);
69 if (aArgs.m_bMergeMode) {
70 global::parser.reset(
71 new CfgMerge(
72 aArgs.m_sMergeSrc, aArgs.m_sOutputFile,
73 global::inputPathname, aArgs.m_sLanguage ));
74 } else {
75 global::parser.reset(
76 new CfgExport(
77 aArgs.m_sOutputFile, global::inputPathname ));
80 return pFile;
83 void workOnTokenSet(int nTyp, char * pTokenText) {
84 global::parser->Execute( nTyp, pTokenText );
90 // class CfgStackData
93 CfgStackData* CfgStack::Push(const OString &rTag, const OString &rId)
95 CfgStackData *pD = new CfgStackData( rTag, rId );
96 maList.push_back( pD );
97 return pD;
101 // class CfgStack
104 CfgStack::~CfgStack()
106 for ( size_t i = 0, n = maList.size(); i < n; i++ )
107 delete maList[ i ];
108 maList.clear();
111 OString CfgStack::GetAccessPath( size_t nPos )
113 OStringBuffer sReturn;
114 for (size_t i = 0; i <= nPos; ++i)
116 if (i)
117 sReturn.append('.');
118 sReturn.append(maList[i]->GetIdentifier());
121 return sReturn.makeStringAndClear();
124 CfgStackData *CfgStack::GetStackData()
126 if (!maList.empty())
127 return maList[maList.size() - 1];
128 else
129 return 0;
133 // class CfgParser
136 CfgParser::CfgParser()
137 : pStackData( NULL ),
138 bLocalize( false )
142 CfgParser::~CfgParser()
146 bool CfgParser::IsTokenClosed(const OString &rToken)
148 return rToken[rToken.getLength() - 2] == '/';
151 void CfgParser::AddText(
152 OString &rText,
153 const OString &rIsoLang,
154 const OString &rResTyp )
156 rText = rText.replaceAll(OString('\n'), OString()).
157 replaceAll(OString('\r'), OString()).
158 replaceAll(OString('\t'), OString());
159 pStackData->sResTyp = rResTyp;
160 WorkOnText( rText, rIsoLang );
161 pStackData->sText[ rIsoLang ] = rText;
164 int CfgParser::ExecuteAnalyzedToken( int nToken, char *pToken )
166 OString sToken( pToken );
168 if ( sToken == " " || sToken == "\t" )
169 sLastWhitespace += sToken;
171 OString sTokenName;
172 OString sTokenId;
174 bool bOutput = true;
176 switch ( nToken ) {
177 case CFG_TOKEN_PACKAGE:
178 case CFG_TOKEN_COMPONENT:
179 case CFG_TOKEN_TEMPLATE:
180 case CFG_TOKEN_CONFIGNAME:
181 case CFG_TOKEN_OORNAME:
182 case CFG_TOKEN_OORVALUE:
183 case CFG_TAG:
184 case ANYTOKEN:
185 case CFG_TEXT_START:
187 sTokenName = sToken.getToken(1, '<').getToken(0, '>').
188 getToken(0, ' ');
190 if ( !IsTokenClosed( sToken )) {
191 OString sSearch;
192 switch ( nToken ) {
193 case CFG_TOKEN_PACKAGE:
194 sSearch = "package-id=";
195 break;
196 case CFG_TOKEN_COMPONENT:
197 sSearch = "component-id=";
198 break;
199 case CFG_TOKEN_TEMPLATE:
200 sSearch = "template-id=";
201 break;
202 case CFG_TOKEN_CONFIGNAME:
203 sSearch = "cfg:name=";
204 break;
205 case CFG_TOKEN_OORNAME:
206 sSearch = "oor:name=";
207 bLocalize = true;
208 break;
209 case CFG_TOKEN_OORVALUE:
210 sSearch = "oor:value=";
211 break;
212 case CFG_TEXT_START: {
213 if ( sCurrentResTyp != sTokenName ) {
214 WorkOnResourceEnd();
216 sCurrentResTyp = sTokenName;
218 OString sTemp = sToken.copy( sToken.indexOf( "xml:lang=" ));
219 sCurrentIsoLang = sTemp.getToken(1, '"');
221 if ( sCurrentIsoLang == NO_TRANSLATE_ISO )
222 bLocalize = false;
224 pStackData->sTextTag = sToken;
226 sCurrentText = "";
228 break;
230 if ( !sSearch.isEmpty())
232 OString sTemp = sToken.copy( sToken.indexOf( sSearch ));
233 sTokenId = sTemp.getToken(1, '"');
235 pStackData = aStack.Push( sTokenName, sTokenId );
237 if ( sSearch == "cfg:name=" ) {
238 OString sTemp( sToken.toAsciiUpperCase() );
239 bLocalize = (( sTemp.indexOf( "CFG:TYPE=\"STRING\"" ) != -1 ) &&
240 ( sTemp.indexOf( "CFG:LOCALIZED=\"sal_True\"" ) != -1 ));
243 else if ( sTokenName == "label" ) {
244 if ( sCurrentResTyp != sTokenName ) {
245 WorkOnResourceEnd();
247 sCurrentResTyp = sTokenName;
250 break;
251 case CFG_CLOSETAG:
253 sTokenName = sToken.getToken(1, '/').getToken(0, '>').
254 getToken(0, ' ');
255 if ( aStack.GetStackData() && ( aStack.GetStackData()->GetTagType() == sTokenName ))
257 if (sCurrentText.isEmpty())
258 WorkOnResourceEnd();
259 aStack.Pop();
260 pStackData = aStack.GetStackData();
262 else
264 OString sError( "Misplaced close tag: " );
265 OString sInFile(" in file ");
266 sError += sToken;
267 sError += sInFile;
268 sError += global::inputPathname;
269 Error( sError );
270 std::exit(EXIT_FAILURE);
273 break;
275 case CFG_TEXTCHAR:
276 sCurrentText += sToken;
277 bOutput = false;
278 break;
280 case CFG_TOKEN_NO_TRANSLATE:
281 bLocalize = false;
282 break;
285 if ( !sCurrentText.isEmpty() && nToken != CFG_TEXTCHAR )
287 AddText( sCurrentText, sCurrentIsoLang, sCurrentResTyp );
288 Output( sCurrentText );
289 sCurrentText.clear();
290 pStackData->sEndTextTag = sToken;
293 if ( bOutput )
294 Output( sToken );
296 if ( sToken != " " && sToken != "\t" )
297 sLastWhitespace = "";
299 return 1;
302 void CfgExport::Output(const OString&)
306 int CfgParser::Execute( int nToken, char * pToken )
308 OString sToken( pToken );
310 switch ( nToken ) {
311 case CFG_TAG:
312 if ( sToken.indexOf( "package-id=" ) != -1 )
313 return ExecuteAnalyzedToken( CFG_TOKEN_PACKAGE, pToken );
314 else if ( sToken.indexOf( "component-id=" ) != -1 )
315 return ExecuteAnalyzedToken( CFG_TOKEN_COMPONENT, pToken );
316 else if ( sToken.indexOf( "template-id=" ) != -1 )
317 return ExecuteAnalyzedToken( CFG_TOKEN_TEMPLATE, pToken );
318 else if ( sToken.indexOf( "cfg:name=" ) != -1 )
319 return ExecuteAnalyzedToken( CFG_TOKEN_OORNAME, pToken );
320 else if ( sToken.indexOf( "oor:name=" ) != -1 )
321 return ExecuteAnalyzedToken( CFG_TOKEN_OORNAME, pToken );
322 else if ( sToken.indexOf( "oor:value=" ) != -1 )
323 return ExecuteAnalyzedToken( CFG_TOKEN_OORVALUE, pToken );
324 break;
326 return ExecuteAnalyzedToken( nToken, pToken );
329 void CfgParser::Error(const OString& rError)
331 yyerror(rError.getStr());
335 // class CfgExport
338 CfgExport::CfgExport(
339 const OString &rOutputFile,
340 const OString &rFilePath )
342 : sPath( rFilePath )
344 pOutputStream.open( rOutputFile, PoOfstream::APP );
345 if (!pOutputStream.isOpen())
347 std::cerr << "ERROR: Unable to open output file: " << rOutputFile << "\n";
348 std::exit(EXIT_FAILURE);
352 CfgExport::~CfgExport()
354 pOutputStream.close();
358 void CfgExport::WorkOnResourceEnd()
360 if ( bLocalize ) {
361 if ( !pStackData->sText["en-US"].isEmpty() )
363 OString sXComment = pStackData->sText[OString("x-comment")];
364 OString sLocalId = pStackData->sIdentifier;
365 OString sGroupId;
366 if ( aStack.size() == 1 ) {
367 sGroupId = sLocalId;
368 sLocalId = "";
370 else {
371 sGroupId = aStack.GetAccessPath( aStack.size() - 2 );
375 OString sText = pStackData->sText[ "en-US" ];
376 sText = helper::UnQuotHTML( sText );
378 common::writePoEntry(
379 "Cfgex", pOutputStream, sPath, pStackData->sResTyp,
380 sGroupId, sLocalId, sXComment, sText);
385 void CfgExport::WorkOnText(
386 OString &rText,
387 const OString &rIsoLang
390 if( !rIsoLang.isEmpty() ) rText = helper::UnQuotHTML( rText );
395 // class CfgMerge
398 CfgMerge::CfgMerge(
399 const OString &rMergeSource, const OString &rOutputFile,
400 const OString &rFilename, const OString &rLanguage )
401 : pMergeDataFile( NULL ),
402 pResData( NULL ),
403 sFilename( rFilename ),
404 bEnglish( false )
406 pOutputStream.open(
407 rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
408 if (!pOutputStream.is_open())
410 std::cerr << "ERROR: Unable to open output file: " << rOutputFile << "\n";
411 std::exit(EXIT_FAILURE);
414 if (!rMergeSource.isEmpty())
416 pMergeDataFile = new MergeDataFile(
417 rMergeSource, global::inputPathname, true );
418 if (rLanguage.equalsIgnoreAsciiCase("ALL") )
420 aLanguages = pMergeDataFile->GetLanguages();
422 else aLanguages.push_back(rLanguage);
424 else
425 aLanguages.push_back(rLanguage);
428 CfgMerge::~CfgMerge()
430 pOutputStream.close();
431 delete pMergeDataFile;
432 delete pResData;
435 void CfgMerge::WorkOnText(OString &, const OString& rLangIndex)
438 if ( pMergeDataFile && bLocalize ) {
439 if ( !pResData ) {
440 OString sLocalId = pStackData->sIdentifier;
441 OString sGroupId;
442 if ( aStack.size() == 1 ) {
443 sGroupId = sLocalId;
444 sLocalId.clear();
446 else {
447 sGroupId = aStack.GetAccessPath( aStack.size() - 2 );
450 pResData = new ResData( sGroupId, sFilename );
451 pResData->sId = sLocalId;
452 pResData->sResTyp = pStackData->sResTyp;
455 if (rLangIndex.equalsIgnoreAsciiCase("en-US"))
456 bEnglish = true;
460 void CfgMerge::Output(const OString& rOutput)
462 pOutputStream << rOutput.getStr();
465 void CfgMerge::WorkOnResourceEnd()
468 if ( pMergeDataFile && pResData && bLocalize && bEnglish ) {
469 MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrysCaseSensitive( pResData );
470 if ( pEntrys ) {
471 OString sCur;
473 for( unsigned int i = 0; i < aLanguages.size(); ++i ){
474 sCur = aLanguages[ i ];
476 OString sContent;
477 pEntrys->GetText( sContent, STRING_TYP_TEXT, sCur , true );
478 if (
479 ( !sCur.equalsIgnoreAsciiCase("en-US") ) && !sContent.isEmpty())
482 OString sText = helper::QuotHTML( sContent);
484 OString sAdditionalLine( "\t" );
486 OString sTextTag = pStackData->sTextTag;
487 OString sTemp = sTextTag.copy( sTextTag.indexOf( "xml:lang=" ));
489 sal_Int32 n = 0;
490 OString sSearch = sTemp.getToken(0, '"', n);
491 sSearch += "\"";
492 sSearch += sTemp.getToken(0, '"', n);
493 sSearch += "\"";
495 OString sReplace = sTemp.getToken(0, '"');
496 sReplace += "\"";
497 sReplace += sCur;
498 sReplace += "\"";
500 sTextTag = sTextTag.replaceFirst(sSearch, sReplace);
502 sAdditionalLine += sTextTag;
503 sAdditionalLine += sText;
504 sAdditionalLine += pStackData->sEndTextTag;
506 sAdditionalLine += "\n";
507 sAdditionalLine += sLastWhitespace;
509 Output( sAdditionalLine );
514 delete pResData;
515 pResData = NULL;
516 bEnglish = false;
519 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */