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"
39 #include <rtl/strbuf.hxx>
42 #include "tagtest.hxx"
43 #include "gsicheck.hxx"
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
;
106 if ( (*(argv
[ i
]+2)) == 'e' )
108 if ( (*(argv
[ i
]+3)) == 'f' )
111 aErrorFilename
= argv
[i
+ 1];
112 bWriteError
= sal_True
;
117 fprintf( stderr
, "\nERROR: Switch %s requires parameter!\n\n", argv
[ i
] );
121 bWriteError
= sal_True
;
123 else if ( (*(argv
[ i
]+2)) == 'c' )
124 if ( (*(argv
[ i
]+3)) == 'f' )
127 aCorrectFilename
= argv
[i
+ 1];
128 bWriteCorrect
= sal_True
;
133 fprintf( stderr
, "\nERROR: Switch %s requires parameter!\n\n", argv
[ i
] );
137 bWriteCorrect
= sal_True
;
138 else if ( (*(argv
[ i
]+2)) == 'f' )
139 if ( (*(argv
[ i
]+3)) == 'f' )
142 aFixedFilename
= argv
[i
+ 1];
143 bWriteFixed
= sal_True
;
149 fprintf( stderr
, "\nERROR: Switch %s requires parameter!\n\n", argv
[ i
] );
154 bWriteFixed
= sal_True
;
159 fprintf( stderr
, "\nERROR: Unknown Switch %s!\n\n", argv
[ i
] );
164 case 's':bCheckSourceLang
= sal_True
;
166 case 't':bCheckTranslationLang
= sal_True
;
172 aSourceLang
= argv
[ i
+1 ];
173 if ( aSourceLang
.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("none")) )
174 aSourceLang
= rtl::OString();
179 fprintf( stderr
, "\nERROR: Switch %s requires parameter!\n\n", argv
[ i
] );
188 aReferenceFilename
= argv
[ i
+1 ];
189 bReferenceFile
= sal_True
;
194 fprintf( stderr
, "\nERROR: Switch %s requires parameter!\n\n", argv
[ i
] );
206 bAllowSuspicious
= sal_True
;
210 fprintf( stderr
, "\nERROR: Unknown Switch %s!\n\n", argv
[ i
] );
216 if (aFilename
.isEmpty())
220 fprintf( stderr
, "\nERROR: Only one filename may be specified!\n\n");
227 if (aFilename
.isEmpty() || bError
)
233 if ( !aSourceLang
.isEmpty() && !LanguageOK( aSourceLang
) )
235 fprintf( stderr
, "\nERROR: The Language '%s' is invalid!\n\n", aSourceLang
.getStr() );
240 if ( bCheckSourceLang
&& bCheckTranslationLang
)
242 fprintf( stderr
, "\nERROR: The Options -s and -t are mutually exclusive.\nUse only one of them.\n\n" );
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() );
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() );
268 if (aCorrectFilename
.isEmpty())
270 aCorrectFilename
= addSuffix(
271 aFilename
, rtl::OString(RTL_CONSTASCII_STRINGPARAM("_ok")));
273 aOkOut
.SetFileName(aCorrectFilename
);
279 if (aErrorFilename
.isEmpty())
281 aErrorFilename
= addSuffix(
282 aFilename
, rtl::OString(RTL_CONSTASCII_STRINGPARAM("_err")));
284 aErrOut
.SetFileName(aErrorFilename
);
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;
310 std::getline(aGSI
, s
);
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() );
324 bFileHasError
= sal_True
;
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
334 aOkOut
<< pGSILine
->data_
.getStr() << '\n';
339 rtl::OString aId
= pGSILine
->GetUniqId();
344 bFileHasError
|= pBlock
->CheckSyntax( nLine
, !aSourceLang
.isEmpty(), bFixTags
);
347 pBlock
->WriteError( aErrOut
, !aSourceLang
.isEmpty() );
349 pBlock
->WriteCorrect( aOkOut
, !aSourceLang
.isEmpty() );
351 pBlock
->WriteFixed( aFixOut
);
355 pBlock
= new GSIBlock( bPrintContext
, bCheckSourceLang
, bCheckTranslationLang
, bReferenceFile
, bAllowSuspicious
);
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
)
368 std::getline(aReferenceGSI
, s2
);
370 pReferenceLine
= new GSILine(
371 rtl::OString(s2
.data(), s2
.length()),
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
;
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
;
395 delete pReferenceLine
;
396 pReferenceLine
= NULL
;
403 pBlock
->InsertLine( pGSILine
, aSourceLang
);
412 bFileHasError
|= pBlock
->CheckSyntax( nLine
, !aSourceLang
.isEmpty(), bFixTags
);
415 pBlock
->WriteError( aErrOut
, !aSourceLang
.isEmpty() );
417 pBlock
->WriteCorrect( aOkOut
, !aSourceLang
.isEmpty() );
419 pBlock
->WriteFixed( aFixOut
);
437 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */