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