Bump for 3.6-28
[LibreOffice.git] / l10ntools / source / gsimain.cxx
blob4ed9d69f3aa70f53aa9a670279121bd9ae9cdd5e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "sal/config.h"
31 #include <algorithm>
32 #include <cassert>
33 #include <cstddef>
34 #include <fstream>
35 #include <string>
37 #include <stdio.h>
39 #include <rtl/strbuf.hxx>
40 #include "sal/main.h"
41 #include "helper.hxx"
42 #include "tagtest.hxx"
43 #include "gsicheck.hxx"
45 void Help()
47 fprintf( stdout, "\n" );
48 fprintf( stdout, "gsicheck checks the syntax of tags in SDF-Files\n" );
49 fprintf( stdout, " checks for inconsistencies and malicious UTF8 encoding\n" );
50 fprintf( stdout, " checks tags in Online Help\n" );
51 fprintf( stdout, " relax GID/LID length to %s\n",
52 rtl::OString::valueOf(static_cast<sal_Int32>(MAX_GID_LID_LEN)).getStr() );
53 fprintf( stdout, "\n" );
54 fprintf( stdout, "Syntax: gsicheck [ -c ] [-f] [ -we ] [ -wef ErrorFilename ] [ -wc ]\n" );
55 fprintf( stdout, " [ -wcf CorrectFilename ] [ -s | -t ] [ -l LanguageID ]\n" );
56 fprintf( stdout, " [ -r ReferenceFile ] filename\n" );
57 fprintf( stdout, "\n" );
58 fprintf( stdout, "-c Add context to error message (Print the line containing the error)\n" );
59 fprintf( stdout, "-f try to fix errors. See also -wf -wff \n" );
60 fprintf( stdout, "-wf Write File containing all fixed parts\n" );
61 fprintf( stdout, "-wff Same as above but give own filename\n" );
62 fprintf( stdout, "-we Write File containing all errors\n" );
63 fprintf( stdout, "-wef Same as above but give own filename\n" );
64 fprintf( stdout, "-wc Write File containing all correct parts\n" );
65 fprintf( stdout, "-wcf Same as above but give own filename\n" );
66 fprintf( stdout, "-s Check only source language. Should be used before handing out to vendor.\n" );
67 fprintf( stdout, "-t Check only Translation language(s). Should be used before merging.\n" );
68 fprintf( stdout, "-e disable encoding checks. E.g.: double questionmark \'??\' which may be the\n" );
69 fprintf( stdout, " result of false conversions\n" );
70 fprintf( stdout, "-l ISO language code of the source language.\n" );
71 fprintf( stdout, " Default is en-US. Use \"\" (empty string) or 'none'\n" );
72 fprintf( stdout, " to disable source language dependent checks\n" );
73 fprintf( stdout, "-r Reference filename to check that source language entries\n" );
74 fprintf( stdout, " have not been changed\n" );
75 fprintf( stdout, "\n" );
78 SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
79 sal_Bool bError = sal_False;
80 sal_Bool bPrintContext = sal_False;
81 sal_Bool bCheckSourceLang = sal_False;
82 sal_Bool bCheckTranslationLang = sal_False;
83 sal_Bool bWriteError = sal_False;
84 sal_Bool bWriteCorrect = sal_False;
85 sal_Bool bWriteFixed = sal_False;
86 sal_Bool bFixTags = sal_False;
87 sal_Bool bAllowSuspicious = sal_False;
88 rtl::OString aErrorFilename;
89 rtl::OString aCorrectFilename;
90 rtl::OString aFixedFilename;
91 sal_Bool bFileHasError = sal_False;
92 rtl::OString aSourceLang( "en-US" ); // English is default
93 rtl::OString aFilename;
94 rtl::OString aReferenceFilename;
95 sal_Bool bReferenceFile = sal_False;
96 for ( int i = 1 ; i < argc ; i++ )
98 if ( *argv[ i ] == '-' )
100 switch (*(argv[ i ]+1))
102 case 'c':bPrintContext = sal_True;
103 break;
104 case 'w':
106 if ( (*(argv[ i ]+2)) == 'e' )
108 if ( (*(argv[ i ]+3)) == 'f' )
109 if ( (i+1) < argc )
111 aErrorFilename = argv[i + 1];
112 bWriteError = sal_True;
113 i++;
115 else
117 fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
118 bError = sal_True;
120 else
121 bWriteError = sal_True;
123 else if ( (*(argv[ i ]+2)) == 'c' )
124 if ( (*(argv[ i ]+3)) == 'f' )
125 if ( (i+1) < argc )
127 aCorrectFilename = argv[i + 1];
128 bWriteCorrect = sal_True;
129 i++;
131 else
133 fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
134 bError = sal_True;
136 else
137 bWriteCorrect = sal_True;
138 else if ( (*(argv[ i ]+2)) == 'f' )
139 if ( (*(argv[ i ]+3)) == 'f' )
140 if ( (i+1) < argc )
142 aFixedFilename = argv[i + 1];
143 bWriteFixed = sal_True;
144 bFixTags = sal_True;
145 i++;
147 else
149 fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
150 bError = sal_True;
152 else
154 bWriteFixed = sal_True;
155 bFixTags = sal_True;
157 else
159 fprintf( stderr, "\nERROR: Unknown Switch %s!\n\n", argv[ i ] );
160 bError = sal_True;
163 break;
164 case 's':bCheckSourceLang = sal_True;
165 break;
166 case 't':bCheckTranslationLang = sal_True;
167 break;
168 case 'l':
170 if ( (i+1) < argc )
172 aSourceLang = argv[ i+1 ];
173 if ( aSourceLang.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("none")) )
174 aSourceLang = rtl::OString();
175 i++;
177 else
179 fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
180 bError = sal_True;
183 break;
184 case 'r':
186 if ( (i+1) < argc )
188 aReferenceFilename = argv[ i+1 ];
189 bReferenceFile = sal_True;
190 i++;
192 else
194 fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
195 bError = sal_True;
198 break;
199 case 'f':
201 bFixTags = sal_True;
203 break;
204 case 'e':
206 bAllowSuspicious = sal_True;
208 break;
209 default:
210 fprintf( stderr, "\nERROR: Unknown Switch %s!\n\n", argv[ i ] );
211 bError = sal_True;
214 else
216 if (aFilename.isEmpty())
217 aFilename = argv[i];
218 else
220 fprintf( stderr, "\nERROR: Only one filename may be specified!\n\n");
221 bError = sal_True;
227 if (aFilename.isEmpty() || bError)
229 Help();
230 exit ( 0 );
233 if ( !aSourceLang.isEmpty() && !LanguageOK( aSourceLang ) )
235 fprintf( stderr, "\nERROR: The Language '%s' is invalid!\n\n", aSourceLang.getStr() );
236 Help();
237 exit ( 1 );
240 if ( bCheckSourceLang && bCheckTranslationLang )
242 fprintf( stderr, "\nERROR: The Options -s and -t are mutually exclusive.\nUse only one of them.\n\n" );
243 Help();
244 exit ( 1 );
249 std::ifstream aGSI(aFilename.getStr());
250 if (!aGSI.is_open()) {
251 fprintf( stderr, "\nERROR: Could not open GSI-File %s!\n\n", aFilename.getStr() );
252 exit ( 3 );
255 std::ifstream aReferenceGSI;
256 if ( bReferenceFile )
258 aReferenceGSI.open(aReferenceFilename.getStr());
259 if (!aReferenceGSI.is_open()) {
260 fprintf( stderr, "\nERROR: Could not open Input-File %s!\n\n", aFilename.getStr() );
261 exit ( 3 );
265 LazyStream aOkOut;
266 if ( bWriteCorrect )
268 if (aCorrectFilename.isEmpty())
270 aCorrectFilename = addSuffix(
271 aFilename, rtl::OString(RTL_CONSTASCII_STRINGPARAM("_ok")));
273 aOkOut.SetFileName(aCorrectFilename);
276 LazyStream aErrOut;
277 if ( bWriteError )
279 if (aErrorFilename.isEmpty())
281 aErrorFilename = addSuffix(
282 aFilename, rtl::OString(RTL_CONSTASCII_STRINGPARAM("_err")));
284 aErrOut.SetFileName(aErrorFilename);
287 LazyStream aFixOut;
288 if ( bWriteFixed )
290 if (aFixedFilename.isEmpty())
292 aFixedFilename = addSuffix(
293 aFilename, rtl::OString(RTL_CONSTASCII_STRINGPARAM("_fix")));
295 aFixOut.SetFileName(aFixedFilename);
299 GSILine* pReferenceLine = NULL;
300 std::size_t nReferenceLine = 0;
302 GSILine* pGSILine = NULL;
303 rtl::OString aOldId("No Valid ID"); // just set to something which can never be an ID
304 GSIBlock *pBlock = NULL;
305 std::size_t nLine = 0;
307 while (!aGSI.eof())
309 std::string s;
310 std::getline(aGSI, s);
311 nLine++;
313 pGSILine = new GSILine(rtl::OString(s.data(), s.length()), nLine );
314 sal_Bool bDelete = sal_True;
316 if ( !pGSILine->data_.isEmpty() )
318 if ( FORMAT_UNKNOWN == pGSILine->GetLineFormat() )
320 PrintError( "Format of line is unknown. Ignoring!", "Line format", pGSILine->data_.copy( 0,40 ), bPrintContext, pGSILine->GetLineNumber() );
321 pGSILine->NotOK();
322 if ( bWriteError )
324 bFileHasError = sal_True;
325 aErrOut.LazyOpen();
326 aErrOut << pGSILine->data_.getStr();
329 else if ( pGSILine->GetLineType().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("res-comment")) )
330 { // ignore comment lines, but write them to Correct Items File
331 if ( bWriteCorrect )
333 aOkOut.LazyOpen();
334 aOkOut << pGSILine->data_.getStr() << '\n';
337 else
339 rtl::OString aId = pGSILine->GetUniqId();
340 if ( aId != aOldId )
342 if ( pBlock )
344 bFileHasError |= pBlock->CheckSyntax( nLine, !aSourceLang.isEmpty(), bFixTags );
346 if ( bWriteError )
347 pBlock->WriteError( aErrOut, !aSourceLang.isEmpty() );
348 if ( bWriteCorrect )
349 pBlock->WriteCorrect( aOkOut, !aSourceLang.isEmpty() );
350 if ( bWriteFixed )
351 pBlock->WriteFixed( aFixOut );
353 delete pBlock;
355 pBlock = new GSIBlock( bPrintContext, bCheckSourceLang, bCheckTranslationLang, bReferenceFile, bAllowSuspicious );
357 aOldId = aId;
359 // find corresponding line in reference file
360 if ( bReferenceFile )
362 sal_Bool bContinueSearching = sal_True;
363 while ( ( !aReferenceGSI.eof() || pReferenceLine ) && bContinueSearching )
365 if ( !pReferenceLine )
367 std::string s2;
368 std::getline(aReferenceGSI, s2);
369 nReferenceLine++;
370 pReferenceLine = new GSILine(
371 rtl::OString(s2.data(), s2.length()),
372 nReferenceLine);
374 if ( pReferenceLine->GetLineFormat() != FORMAT_UNKNOWN )
376 if ( pReferenceLine->GetUniqId() == aId && pReferenceLine->GetLanguageId() == aSourceLang )
378 pBlock->SetReferenceLine( pReferenceLine );
379 pReferenceLine = NULL;
381 else if ( pReferenceLine->GetUniqId() > aId )
383 bContinueSearching = sal_False;
385 else
387 if ( pReferenceLine->GetUniqId() < aId && pReferenceLine->GetLanguageId() == aSourceLang )
388 PrintError( "No Entry in source file found. Entry has been removed from source file", "File format", "", bPrintContext, pGSILine->GetLineNumber(), pReferenceLine->GetUniqId() );
389 delete pReferenceLine;
390 pReferenceLine = NULL;
393 else
395 delete pReferenceLine;
396 pReferenceLine = NULL;
403 pBlock->InsertLine( pGSILine, aSourceLang );
404 bDelete = sal_False;
407 if ( bDelete )
408 delete pGSILine;
410 if ( pBlock )
412 bFileHasError |= pBlock->CheckSyntax( nLine, !aSourceLang.isEmpty(), bFixTags );
414 if ( bWriteError )
415 pBlock->WriteError( aErrOut, !aSourceLang.isEmpty() );
416 if ( bWriteCorrect )
417 pBlock->WriteCorrect( aOkOut, !aSourceLang.isEmpty() );
418 if ( bWriteFixed )
419 pBlock->WriteFixed( aFixOut );
421 delete pBlock;
423 aGSI.close();
425 if ( bWriteError )
426 aErrOut.close();
427 if ( bWriteCorrect )
428 aOkOut.close();
429 if ( bWriteFixed )
430 aFixOut.close();
431 if ( bFileHasError )
432 return 55;
433 else
434 return 0;
437 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */