Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <cstring>
23 :
24 : #include <stdio.h>
25 :
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 <boost/scoped_array.hpp>
37 :
38 : using namespace std;
39 :
40 : void yyerror( const char * );
41 :
42 : // set of global variables
43 : bool bMergeMode;
44 : bool bDisplayName;
45 : bool bExtensionDescription;
46 0 : OString sLanguage;
47 0 : OString sInputFileName;
48 0 : OString sOutputFile;
49 0 : OString sMergeSrc;
50 0 : OString sLangAttribute;
51 0 : OString sResourceType;
52 : XRMResParser *pParser = NULL;
53 :
54 : extern "C" {
55 : // the whole interface to lexer is in this extern "C" section
56 :
57 0 : extern bool GetOutputFile( int argc, char* argv[])
58 : {
59 0 : bDisplayName = false;
60 0 : bExtensionDescription = false;
61 :
62 0 : common::HandledArgs aArgs;
63 0 : if ( common::handleArguments(argc, argv, aArgs) )
64 : {
65 0 : bMergeMode = aArgs.m_bMergeMode;
66 0 : sLanguage = aArgs.m_sLanguage;
67 0 : sInputFileName = aArgs.m_sInputFile;
68 0 : sOutputFile = aArgs.m_sOutputFile;
69 0 : sMergeSrc = aArgs.m_sMergeSrc;
70 0 : return true;
71 : }
72 : else
73 : {
74 : // command line is not valid
75 0 : common::writeUsage("xrmex","*.xrm/*.xml");
76 0 : return false;
77 0 : }
78 : }
79 :
80 0 : int InitXrmExport( const char* pFilename)
81 : {
82 : // instanciate Export
83 0 : OString sFilename( pFilename );
84 :
85 0 : if ( bMergeMode )
86 0 : pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
87 0 : else if (!sOutputFile.isEmpty()) {
88 0 : pParser = new XRMResExport( sOutputFile, sInputFileName );
89 : }
90 :
91 0 : return 1;
92 : }
93 :
94 0 : int EndXrmExport()
95 : {
96 0 : delete pParser;
97 0 : return 1;
98 : }
99 0 : extern const char* getFilename()
100 : {
101 0 : return sInputFileName.getStr();
102 : }
103 :
104 0 : extern FILE *GetXrmFile()
105 : {
106 : // look for valid filename
107 0 : if (!sInputFileName.isEmpty()) {
108 : //TODO: explicit BOM handling?
109 0 : FILE * pFile = fopen(sInputFileName.getStr(), "r");
110 0 : if ( !pFile ){
111 : fprintf( stderr, "Error: Could not open file %s\n",
112 0 : sInputFileName.getStr());
113 : }
114 : else {
115 0 : return pFile;
116 : }
117 : }
118 : // this means the file could not be opened
119 0 : return NULL;
120 : }
121 :
122 0 : int WorkOnTokenSet( int nTyp, char *pTokenText )
123 : {
124 : //printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
125 0 : pParser->Execute( nTyp, pTokenText );
126 :
127 0 : return 1;
128 : }
129 :
130 0 : int SetError()
131 : {
132 0 : pParser->SetError();
133 0 : return 1;
134 : }
135 : }
136 :
137 : extern "C" {
138 :
139 0 : int GetError()
140 : {
141 0 : return pParser->GetError();
142 : }
143 : }
144 :
145 :
146 : // class XRMResParser
147 :
148 :
149 :
150 0 : XRMResParser::XRMResParser()
151 : : bError( false ),
152 0 : bText( false )
153 : {
154 0 : }
155 :
156 0 : XRMResParser::~XRMResParser()
157 : {
158 0 : }
159 :
160 0 : int XRMResParser::Execute( int nToken, char * pToken )
161 : {
162 0 : OString rToken( pToken );
163 :
164 0 : switch ( nToken ) {
165 : case XRM_TEXT_START:{
166 0 : OString sNewGID = GetAttribute( rToken, "id" );
167 0 : if ( sNewGID != sGID ) {
168 0 : sGID = sNewGID;
169 : }
170 0 : bText = true;
171 0 : sCurrentText = "";
172 0 : sCurrentOpenTag = rToken;
173 0 : Output( rToken );
174 : }
175 0 : break;
176 :
177 : case XRM_TEXT_END: {
178 0 : sCurrentCloseTag = rToken;
179 0 : sResourceType = OString ( "readmeitem" );
180 0 : sLangAttribute = OString ( "xml:lang" );
181 0 : WorkOnText( sCurrentOpenTag, sCurrentText );
182 0 : Output( sCurrentText );
183 0 : EndOfText( sCurrentOpenTag, sCurrentCloseTag );
184 0 : bText = false;
185 0 : rToken = OString("");
186 0 : sCurrentText = OString("");
187 : }
188 0 : break;
189 :
190 : case DESC_DISPLAY_NAME_START:{
191 0 : bDisplayName = true;
192 : }
193 0 : break;
194 :
195 : case DESC_DISPLAY_NAME_END:{
196 0 : bDisplayName = false;
197 : }
198 0 : break;
199 :
200 : case DESC_TEXT_START:{
201 0 : if (bDisplayName) {
202 0 : sGID = OString("dispname");
203 0 : bText = true;
204 0 : sCurrentText = "";
205 0 : sCurrentOpenTag = rToken;
206 0 : Output( rToken );
207 : }
208 : }
209 0 : break;
210 :
211 : case DESC_TEXT_END: {
212 0 : if (bDisplayName) {
213 0 : sCurrentCloseTag = rToken;
214 0 : sResourceType = OString ( "description" );
215 0 : sLangAttribute = OString ( "lang" );
216 0 : WorkOnText( sCurrentOpenTag, sCurrentText );
217 0 : Output( sCurrentText );
218 0 : EndOfText( sCurrentOpenTag, sCurrentCloseTag );
219 0 : bText = false;
220 0 : rToken = OString("");
221 0 : sCurrentText = OString("");
222 : }
223 : }
224 0 : break;
225 :
226 : case DESC_EXTENSION_DESCRIPTION_START: {
227 0 : bExtensionDescription = true;
228 : }
229 0 : break;
230 :
231 : case DESC_EXTENSION_DESCRIPTION_END: {
232 0 : bExtensionDescription = false;
233 : }
234 0 : break;
235 :
236 : case DESC_EXTENSION_DESCRIPTION_SRC: {
237 0 : if (bExtensionDescription) {
238 0 : sGID = OString("extdesc");
239 0 : sResourceType = OString ( "description" );
240 0 : sLangAttribute = OString ( "lang" );
241 0 : sCurrentOpenTag = rToken;
242 0 : sCurrentText = OString("");
243 0 : Output( rToken );
244 0 : WorkOnDesc( sCurrentOpenTag, sCurrentText );
245 0 : sCurrentCloseTag = rToken;
246 0 : Output( sCurrentText );
247 0 : rToken = OString("");
248 0 : sCurrentText = OString("");
249 : }
250 : }
251 0 : break;
252 :
253 : default:
254 0 : if ( bText ) {
255 0 : sCurrentText += rToken;
256 : }
257 0 : break;
258 : }
259 :
260 0 : if ( !bText )
261 : {
262 0 : Output( rToken );
263 : }
264 0 : return 0;
265 : }
266 :
267 0 : OString XRMResParser::GetAttribute( const OString &rToken, const OString &rAttribute )
268 : {
269 0 : OString sTmp( rToken );
270 0 : sTmp = sTmp.replace('\t', ' ');
271 :
272 0 : OString sSearch( " " );
273 0 : sSearch += rAttribute;
274 0 : sSearch += "=";
275 0 : sal_Int32 nPos = sTmp.indexOf( sSearch );
276 :
277 0 : if ( nPos != -1 )
278 : {
279 0 : sTmp = sTmp.copy( nPos );
280 0 : OString sId = sTmp.getToken(1, '"');
281 0 : return sId;
282 : }
283 0 : return OString();
284 : }
285 :
286 :
287 0 : void XRMResParser::Error( const OString &rError )
288 : {
289 0 : yyerror(( char * ) rError.getStr());
290 0 : }
291 :
292 :
293 : // class XMLResExport
294 :
295 :
296 0 : XRMResExport::XRMResExport(
297 : const OString &rOutputFile, const OString &rFilePath )
298 : : XRMResParser(),
299 : pResData( NULL ),
300 0 : sPath( rFilePath )
301 : {
302 0 : pOutputStream.open( rOutputFile, PoOfstream::APP );
303 0 : if (!pOutputStream.isOpen())
304 : {
305 0 : OString sError( "Unable to open output file: " );
306 0 : sError += rOutputFile;
307 0 : Error( sError );
308 : }
309 0 : }
310 :
311 0 : XRMResExport::~XRMResExport()
312 : {
313 0 : pOutputStream.close();
314 0 : delete pResData;
315 0 : }
316 :
317 0 : void XRMResExport::Output( const OString& ) {}
318 :
319 0 : void XRMResExport::WorkOnDesc(
320 : const OString &rOpenTag,
321 : OString &rText )
322 : {
323 : OString sDescFileName(
324 0 : sInputFileName.replaceAll("description.xml", OString()));
325 0 : sDescFileName += GetAttribute( rOpenTag, "xlink:href" );
326 0 : ifstream file (sDescFileName.getStr(), ios::in|ios::binary|ios::ate);
327 0 : if (file.is_open()) {
328 0 : int size = static_cast<int>(file.tellg());
329 0 : boost::scoped_array<char> memblock(new char [size+1]);
330 0 : file.seekg (0, ios::beg);
331 0 : file.read (memblock.get(), size);
332 0 : file.close();
333 0 : memblock[size] = '\0';
334 0 : rText = OString(memblock.get());
335 : }
336 0 : WorkOnText( rOpenTag, rText );
337 0 : EndOfText( rOpenTag, rOpenTag );
338 0 : }
339 :
340 0 : void XRMResExport::WorkOnText(
341 : const OString &rOpenTag,
342 : OString &rText )
343 : {
344 0 : OString sLang( GetAttribute( rOpenTag, sLangAttribute ));
345 :
346 0 : if ( !pResData )
347 : {
348 0 : pResData = new ResData( GetGID() );
349 : }
350 0 : pResData->sText[sLang] = rText;
351 0 : }
352 :
353 0 : void XRMResExport::EndOfText(
354 : const OString &,
355 : const OString & )
356 : {
357 0 : if ( pResData )
358 : {
359 0 : OString sAct = pResData->sText["en-US"];
360 :
361 0 : if( !sAct.isEmpty() )
362 : common::writePoEntry(
363 : "Xrmex", pOutputStream, sPath, sResourceType,
364 0 : pResData->sGId, OString(), OString(), sAct );
365 : }
366 0 : delete pResData;
367 0 : pResData = NULL;
368 0 : }
369 :
370 :
371 : // class XRMResMerge
372 :
373 :
374 0 : XRMResMerge::XRMResMerge(
375 : const OString &rMergeSource, const OString &rOutputFile,
376 : const OString &rFilename )
377 : : XRMResParser(),
378 : pMergeDataFile( NULL ),
379 : sFilename( rFilename ) ,
380 0 : pResData( NULL )
381 : {
382 0 : if (!rMergeSource.isEmpty() && sLanguage.equalsIgnoreAsciiCase("ALL"))
383 : {
384 : pMergeDataFile = new MergeDataFile(
385 0 : rMergeSource, sInputFileName, false);
386 0 : aLanguages = pMergeDataFile->GetLanguages();
387 : }
388 : else
389 0 : aLanguages.push_back( sLanguage );
390 : pOutputStream.open(
391 0 : rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
392 0 : if (!pOutputStream.is_open()) {
393 0 : OString sError( "Unable to open output file: " );
394 0 : sError += rOutputFile;
395 0 : Error( sError );
396 : }
397 0 : }
398 :
399 0 : XRMResMerge::~XRMResMerge()
400 : {
401 0 : pOutputStream.close();
402 0 : delete pMergeDataFile;
403 0 : delete pResData;
404 0 : }
405 :
406 0 : void XRMResMerge::WorkOnDesc(
407 : const OString &rOpenTag,
408 : OString &rText )
409 : {
410 0 : WorkOnText( rOpenTag, rText);
411 0 : if ( pMergeDataFile && pResData ) {
412 0 : MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
413 0 : if ( pEntrys ) {
414 0 : OString sCur;
415 0 : OString sDescFilename = GetAttribute ( rOpenTag, "xlink:href" );
416 0 : for( unsigned int n = 0; n < aLanguages.size(); n++ ){
417 0 : sCur = aLanguages[ n ];
418 0 : OString sContent;
419 0 : if ( !sCur.equalsIgnoreAsciiCase("en-US") &&
420 : ( pEntrys->GetText(
421 0 : sContent, STRING_TYP_TEXT, sCur, true )) &&
422 0 : !sContent.isEmpty())
423 : {
424 0 : OString sText( sContent );
425 0 : OString sAdditionalLine( "\n " );
426 0 : sAdditionalLine += rOpenTag;
427 0 : OString sSearch = sLangAttribute;
428 0 : sSearch += "=\"";
429 0 : OString sReplace( sSearch );
430 :
431 0 : sSearch += GetAttribute( rOpenTag, sLangAttribute );
432 0 : sReplace += sCur;
433 0 : sAdditionalLine = sAdditionalLine.replaceFirst(
434 0 : sSearch, sReplace);
435 :
436 0 : sSearch = OString("xlink:href=\"");
437 0 : sReplace = sSearch;
438 :
439 0 : OString sLocDescFilename = sDescFilename;
440 0 : sLocDescFilename = sLocDescFilename.replaceFirst(
441 0 : "en-US", sCur);
442 :
443 0 : sSearch += sDescFilename;
444 0 : sReplace += sLocDescFilename;
445 0 : sAdditionalLine = sAdditionalLine.replaceFirst(
446 0 : sSearch, sReplace);
447 :
448 0 : Output( sAdditionalLine );
449 :
450 0 : sal_Int32 i = sOutputFile.lastIndexOf('/');
451 0 : if (i == -1) {
452 : std::cerr
453 0 : << "Error: output file " << sOutputFile.getStr()
454 0 : << " does not contain any /\n";
455 0 : throw false; //TODO
456 : }
457 : OString sOutputDescFile(
458 0 : sOutputFile.copy(0, i + 1) + sLocDescFilename);
459 0 : ofstream file(sOutputDescFile.getStr());
460 0 : if (file.is_open()) {
461 0 : file << sText.getStr();
462 0 : file.close();
463 : } else {
464 : std::cerr
465 0 : << "Error: cannot write "
466 0 : << sOutputDescFile.getStr() << '\n';
467 0 : throw false; //TODO
468 0 : }
469 : }
470 0 : }
471 : }
472 : }
473 0 : delete pResData;
474 0 : pResData = NULL;
475 0 : }
476 :
477 0 : void XRMResMerge::WorkOnText(
478 : const OString &,
479 : OString & )
480 : {
481 0 : if ( pMergeDataFile ) {
482 0 : if ( !pResData ) {
483 0 : pResData = new ResData( GetGID(), sFilename );
484 0 : pResData->sResTyp = sResourceType;
485 : }
486 : }
487 0 : }
488 :
489 0 : void XRMResMerge::Output( const OString& rOutput )
490 : {
491 0 : if (!rOutput.isEmpty())
492 0 : pOutputStream << rOutput.getStr();
493 0 : }
494 :
495 0 : void XRMResMerge::EndOfText(
496 : const OString &rOpenTag,
497 : const OString &rCloseTag )
498 : {
499 :
500 0 : Output( rCloseTag );
501 0 : if ( pMergeDataFile && pResData ) {
502 0 : MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
503 0 : if ( pEntrys ) {
504 0 : OString sCur;
505 0 : for( unsigned int n = 0; n < aLanguages.size(); n++ ){
506 0 : sCur = aLanguages[ n ];
507 0 : OString sContent;
508 0 : if (!sCur.equalsIgnoreAsciiCase("en-US") &&
509 : ( pEntrys->GetText(
510 0 : sContent, STRING_TYP_TEXT, sCur, true )) &&
511 0 : !sContent.isEmpty() &&
512 0 : helper::isWellFormedXML( sContent ))
513 : {
514 0 : OString sText( sContent );
515 0 : OString sAdditionalLine( "\n " );
516 0 : sAdditionalLine += rOpenTag;
517 0 : OString sSearch = sLangAttribute;
518 0 : sSearch += "=\"";
519 0 : OString sReplace( sSearch );
520 :
521 0 : sSearch += GetAttribute( rOpenTag, sLangAttribute );
522 0 : sReplace += sCur;
523 :
524 0 : sAdditionalLine = sAdditionalLine.replaceFirst(
525 0 : sSearch, sReplace);
526 :
527 0 : sAdditionalLine += sText;
528 0 : sAdditionalLine += rCloseTag;
529 :
530 0 : Output( sAdditionalLine );
531 : }
532 0 : }
533 : }
534 : }
535 0 : delete pResData;
536 0 : pResData = NULL;
537 0 : }
538 :
539 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|