1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** Contact: Qt Software Information ([email protected])
|
---|
5 | **
|
---|
6 | ** This file is part of the Qt Linguist of the Qt Toolkit.
|
---|
7 | **
|
---|
8 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
9 | ** Commercial Usage
|
---|
10 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
11 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
12 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
13 | ** a written agreement between you and Nokia.
|
---|
14 | **
|
---|
15 | ** GNU Lesser General Public License Usage
|
---|
16 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
17 | ** General Public License version 2.1 as published by the Free Software
|
---|
18 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
19 | ** packaging of this file. Please review the following information to
|
---|
20 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
21 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
22 | **
|
---|
23 | ** In addition, as a special exception, Nokia gives you certain
|
---|
24 | ** additional rights. These rights are described in the Nokia Qt LGPL
|
---|
25 | ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
---|
26 | ** package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you are unsure which license is appropriate for your use, please
|
---|
37 | ** contact the sales department at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "translator.h"
|
---|
43 |
|
---|
44 | #include <QtCore/QDebug>
|
---|
45 | #include <QtCore/QFile>
|
---|
46 | #include <QtCore/QRegExp>
|
---|
47 | #include <QtCore/QStack>
|
---|
48 | #include <QtCore/QStack>
|
---|
49 | #include <QtCore/QString>
|
---|
50 | #include <QtCore/QTextCodec>
|
---|
51 |
|
---|
52 | #include <ctype.h>
|
---|
53 |
|
---|
54 | QT_BEGIN_NAMESPACE
|
---|
55 |
|
---|
56 | enum { Tok_Eof, Tok_class, Tok_return, Tok_tr,
|
---|
57 | Tok_translate, Tok_Ident, Tok_Package,
|
---|
58 | Tok_Comment, Tok_String, Tok_Colon, Tok_Dot,
|
---|
59 | Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen,
|
---|
60 | Tok_RightParen, Tok_Comma, Tok_Semicolon,
|
---|
61 | Tok_Integer, Tok_Plus, Tok_PlusPlus, Tok_PlusEq };
|
---|
62 |
|
---|
63 | class Scope
|
---|
64 | {
|
---|
65 | public:
|
---|
66 | QString name;
|
---|
67 | enum Type {Clazz, Function, Other} type;
|
---|
68 | int line;
|
---|
69 |
|
---|
70 | Scope(const QString & name, Type type, int line) :
|
---|
71 | name(name),
|
---|
72 | type(type),
|
---|
73 | line(line)
|
---|
74 | {}
|
---|
75 |
|
---|
76 | ~Scope()
|
---|
77 | {}
|
---|
78 | };
|
---|
79 |
|
---|
80 | /*
|
---|
81 | The tokenizer maintains the following global variables. The names
|
---|
82 | should be self-explanatory.
|
---|
83 | */
|
---|
84 |
|
---|
85 | static QString yyFileName;
|
---|
86 | static QChar yyCh;
|
---|
87 | static QString yyIdent;
|
---|
88 | static QString yyComment;
|
---|
89 | static QString yyString;
|
---|
90 |
|
---|
91 |
|
---|
92 | static qlonglong yyInteger;
|
---|
93 | static int yyParenDepth;
|
---|
94 | static int yyLineNo;
|
---|
95 | static int yyCurLineNo;
|
---|
96 | static int yyParenLineNo;
|
---|
97 | static int yyTok;
|
---|
98 |
|
---|
99 | // the string to read from and current position in the string
|
---|
100 | static QString yyInStr;
|
---|
101 | static int yyInPos;
|
---|
102 |
|
---|
103 | // The parser maintains the following global variables.
|
---|
104 | static QString yyPackage;
|
---|
105 | static QStack<Scope*> yyScope;
|
---|
106 | static QString yyDefaultContext;
|
---|
107 |
|
---|
108 | static QChar getChar()
|
---|
109 | {
|
---|
110 | if (yyInPos >= yyInStr.size())
|
---|
111 | return EOF;
|
---|
112 | QChar c = yyInStr[yyInPos++];
|
---|
113 | if (c.unicode() == '\n')
|
---|
114 | ++yyCurLineNo;
|
---|
115 | return c.unicode();
|
---|
116 | }
|
---|
117 |
|
---|
118 | static int getToken()
|
---|
119 | {
|
---|
120 | const char tab[] = "bfnrt\"\'\\";
|
---|
121 | const char backTab[] = "\b\f\n\r\t\"\'\\";
|
---|
122 |
|
---|
123 | yyIdent.clear();
|
---|
124 | yyComment.clear();
|
---|
125 | yyString.clear();
|
---|
126 |
|
---|
127 | while ( yyCh != EOF ) {
|
---|
128 | yyLineNo = yyCurLineNo;
|
---|
129 |
|
---|
130 | if ( yyCh.isLetter() || yyCh.toLatin1() == '_' ) {
|
---|
131 | do {
|
---|
132 | yyIdent.append(yyCh);
|
---|
133 | yyCh = getChar();
|
---|
134 | } while ( yyCh.isLetterOrNumber() || yyCh.toLatin1() == '_' );
|
---|
135 |
|
---|
136 | if (yyTok != Tok_Dot) {
|
---|
137 | switch ( yyIdent.at(0).toLatin1() ) {
|
---|
138 | case 'r':
|
---|
139 | if ( yyIdent == QLatin1String("return") )
|
---|
140 | return Tok_return;
|
---|
141 | break;
|
---|
142 | case 'c':
|
---|
143 | if ( yyIdent == QLatin1String("class") )
|
---|
144 | return Tok_class;
|
---|
145 | break;
|
---|
146 | }
|
---|
147 | }
|
---|
148 | switch ( yyIdent.at(0).toLatin1() ) {
|
---|
149 | case 'T':
|
---|
150 | // TR() for when all else fails
|
---|
151 | if ( yyIdent == QLatin1String("TR") )
|
---|
152 | return Tok_tr;
|
---|
153 | break;
|
---|
154 | case 'p':
|
---|
155 | if( yyIdent == QLatin1String("package") )
|
---|
156 | return Tok_Package;
|
---|
157 | break;
|
---|
158 | case 't':
|
---|
159 | if ( yyIdent == QLatin1String("tr") )
|
---|
160 | return Tok_tr;
|
---|
161 | if ( yyIdent == QLatin1String("translate") )
|
---|
162 | return Tok_translate;
|
---|
163 | }
|
---|
164 | return Tok_Ident;
|
---|
165 | } else {
|
---|
166 | switch ( yyCh.toLatin1() ) {
|
---|
167 |
|
---|
168 | case '/':
|
---|
169 | yyCh = getChar();
|
---|
170 | if ( yyCh == QLatin1Char('/') ) {
|
---|
171 | do {
|
---|
172 | yyCh = getChar();
|
---|
173 | if (yyCh == EOF)
|
---|
174 | break;
|
---|
175 | yyComment.append(yyCh);
|
---|
176 | } while (yyCh != QLatin1Char('\n'));
|
---|
177 | return Tok_Comment;
|
---|
178 |
|
---|
179 | } else if ( yyCh == QLatin1Char('*') ) {
|
---|
180 | bool metAster = false;
|
---|
181 | bool metAsterSlash = false;
|
---|
182 |
|
---|
183 | while ( !metAsterSlash ) {
|
---|
184 | yyCh = getChar();
|
---|
185 | if ( yyCh == EOF ) {
|
---|
186 | qFatal( "%s: Unterminated Java comment starting at"
|
---|
187 | " line %d\n",
|
---|
188 | qPrintable(yyFileName), yyLineNo );
|
---|
189 |
|
---|
190 | return Tok_Comment;
|
---|
191 | }
|
---|
192 |
|
---|
193 | yyComment.append( yyCh );
|
---|
194 |
|
---|
195 | if ( yyCh == QLatin1Char('*') )
|
---|
196 | metAster = true;
|
---|
197 | else if ( metAster && yyCh == QLatin1Char('/') )
|
---|
198 | metAsterSlash = true;
|
---|
199 | else
|
---|
200 | metAster = false;
|
---|
201 | }
|
---|
202 | yyComment.chop(2);
|
---|
203 | yyCh = getChar();
|
---|
204 |
|
---|
205 | return Tok_Comment;
|
---|
206 | }
|
---|
207 | break;
|
---|
208 | case '"':
|
---|
209 | yyCh = getChar();
|
---|
210 |
|
---|
211 | while ( yyCh != EOF && yyCh != QLatin1Char('\n') && yyCh != QLatin1Char('"') ) {
|
---|
212 | if ( yyCh == QLatin1Char('\\') ) {
|
---|
213 | yyCh = getChar();
|
---|
214 | if ( yyCh == QLatin1Char('u') ) {
|
---|
215 | yyCh = getChar();
|
---|
216 | uint unicode(0);
|
---|
217 | for (int i = 4; i > 0; --i) {
|
---|
218 | unicode = unicode << 4;
|
---|
219 | if( yyCh.isDigit() ) {
|
---|
220 | unicode += yyCh.digitValue();
|
---|
221 | }
|
---|
222 | else {
|
---|
223 | int sub(yyCh.toLower().toAscii() - 87);
|
---|
224 | if( sub > 15 || sub < 10) {
|
---|
225 | qFatal( "%s:%d: Invalid Unicode",
|
---|
226 | qPrintable(yyFileName), yyLineNo );
|
---|
227 | }
|
---|
228 | unicode += sub;
|
---|
229 | }
|
---|
230 | yyCh = getChar();
|
---|
231 | }
|
---|
232 | yyString.append(QChar(unicode));
|
---|
233 | }
|
---|
234 | else if ( yyCh == QLatin1Char('\n') ) {
|
---|
235 | yyCh = getChar();
|
---|
236 | }
|
---|
237 | else {
|
---|
238 | yyString.append( QLatin1Char(backTab[strchr( tab, yyCh.toAscii() ) - tab]) );
|
---|
239 | yyCh = getChar();
|
---|
240 | }
|
---|
241 | } else {
|
---|
242 | yyString.append(yyCh);
|
---|
243 | yyCh = getChar();
|
---|
244 | }
|
---|
245 | }
|
---|
246 |
|
---|
247 | if ( yyCh != QLatin1Char('"') )
|
---|
248 | qFatal( "%s:%d: Unterminated string",
|
---|
249 | qPrintable(yyFileName), yyLineNo );
|
---|
250 |
|
---|
251 | yyCh = getChar();
|
---|
252 |
|
---|
253 | return Tok_String;
|
---|
254 |
|
---|
255 | case ':':
|
---|
256 | yyCh = getChar();
|
---|
257 | return Tok_Colon;
|
---|
258 | case '\'':
|
---|
259 | yyCh = getChar();
|
---|
260 |
|
---|
261 | if ( yyCh == QLatin1Char('\\') )
|
---|
262 | yyCh = getChar();
|
---|
263 | do {
|
---|
264 | yyCh = getChar();
|
---|
265 | } while ( yyCh != EOF && yyCh != QLatin1Char('\'') );
|
---|
266 | yyCh = getChar();
|
---|
267 | break;
|
---|
268 | case '{':
|
---|
269 | yyCh = getChar();
|
---|
270 | return Tok_LeftBrace;
|
---|
271 | case '}':
|
---|
272 | yyCh = getChar();
|
---|
273 | return Tok_RightBrace;
|
---|
274 | case '(':
|
---|
275 | if (yyParenDepth == 0)
|
---|
276 | yyParenLineNo = yyCurLineNo;
|
---|
277 | yyParenDepth++;
|
---|
278 | yyCh = getChar();
|
---|
279 | return Tok_LeftParen;
|
---|
280 | case ')':
|
---|
281 | if (yyParenDepth == 0)
|
---|
282 | yyParenLineNo = yyCurLineNo;
|
---|
283 | yyParenDepth--;
|
---|
284 | yyCh = getChar();
|
---|
285 | return Tok_RightParen;
|
---|
286 | case ',':
|
---|
287 | yyCh = getChar();
|
---|
288 | return Tok_Comma;
|
---|
289 | case '.':
|
---|
290 | yyCh = getChar();
|
---|
291 | return Tok_Dot;
|
---|
292 | case ';':
|
---|
293 | yyCh = getChar();
|
---|
294 | return Tok_Semicolon;
|
---|
295 | case '+':
|
---|
296 | yyCh = getChar();
|
---|
297 | if (yyCh == QLatin1Char('+')) {
|
---|
298 | yyCh = getChar();
|
---|
299 | return Tok_PlusPlus;
|
---|
300 | }
|
---|
301 | if( yyCh == QLatin1Char('=') ){
|
---|
302 | yyCh = getChar();
|
---|
303 | return Tok_PlusEq;
|
---|
304 | }
|
---|
305 | return Tok_Plus;
|
---|
306 | case '0':
|
---|
307 | case '1':
|
---|
308 | case '2':
|
---|
309 | case '3':
|
---|
310 | case '4':
|
---|
311 | case '5':
|
---|
312 | case '6':
|
---|
313 | case '7':
|
---|
314 | case '8':
|
---|
315 | case '9':
|
---|
316 | {
|
---|
317 | QByteArray ba;
|
---|
318 | ba += yyCh.toLatin1();
|
---|
319 | yyCh = getChar();
|
---|
320 | bool hex = yyCh == QLatin1Char('x');
|
---|
321 | if ( hex ) {
|
---|
322 | ba += yyCh.toLatin1();
|
---|
323 | yyCh = getChar();
|
---|
324 | }
|
---|
325 | while ( hex ? isxdigit(yyCh.toLatin1()) : yyCh.isDigit() ) {
|
---|
326 | ba += yyCh.toLatin1();
|
---|
327 | yyCh = getChar();
|
---|
328 | }
|
---|
329 | bool ok;
|
---|
330 | yyInteger = ba.toLongLong(&ok);
|
---|
331 | if (ok) return Tok_Integer;
|
---|
332 | break;
|
---|
333 | }
|
---|
334 | default:
|
---|
335 | yyCh = getChar();
|
---|
336 | }
|
---|
337 | }
|
---|
338 | }
|
---|
339 | return Tok_Eof;
|
---|
340 | }
|
---|
341 |
|
---|
342 | static bool match( int t )
|
---|
343 | {
|
---|
344 | bool matches = ( yyTok == t );
|
---|
345 | if ( matches )
|
---|
346 | yyTok = getToken();
|
---|
347 | return matches;
|
---|
348 | }
|
---|
349 |
|
---|
350 | static bool matchString( QString &s )
|
---|
351 | {
|
---|
352 | if ( yyTok != Tok_String )
|
---|
353 | return false;
|
---|
354 |
|
---|
355 | s = yyString;
|
---|
356 | yyTok = getToken();
|
---|
357 | while ( yyTok == Tok_Plus ) {
|
---|
358 | yyTok = getToken();
|
---|
359 | if (yyTok == Tok_String)
|
---|
360 | s += yyString;
|
---|
361 | else {
|
---|
362 | qWarning( "%s:%d: String used in translation can only contain strings"
|
---|
363 | " concatenated with other strings, not expressions or numbers.",
|
---|
364 | qPrintable(yyFileName), yyLineNo );
|
---|
365 | return false;
|
---|
366 | }
|
---|
367 | yyTok = getToken();
|
---|
368 | }
|
---|
369 | return true;
|
---|
370 | }
|
---|
371 |
|
---|
372 | static bool matchInteger( qlonglong *number)
|
---|
373 | {
|
---|
374 | bool matches = (yyTok == Tok_Integer);
|
---|
375 | if (matches) {
|
---|
376 | yyTok = getToken();
|
---|
377 | *number = yyInteger;
|
---|
378 | }
|
---|
379 | return matches;
|
---|
380 | }
|
---|
381 |
|
---|
382 | static bool matchStringOrNull(QString &s)
|
---|
383 | {
|
---|
384 | bool matches = matchString(s);
|
---|
385 | qlonglong num = 0;
|
---|
386 | if (!matches) matches = matchInteger(&num);
|
---|
387 | return matches && num == 0;
|
---|
388 | }
|
---|
389 |
|
---|
390 | /*
|
---|
391 | * match any expression that can return a number, which can be
|
---|
392 | * 1. Literal number (e.g. '11')
|
---|
393 | * 2. simple identifier (e.g. 'm_count')
|
---|
394 | * 3. simple function call (e.g. 'size()' )
|
---|
395 | * 4. function call on an object (e.g. 'list.size()')
|
---|
396 | * 5. function call on an object (e.g. 'list->size()')
|
---|
397 | *
|
---|
398 | * Other cases:
|
---|
399 | * size(2,4)
|
---|
400 | * list().size()
|
---|
401 | * list(a,b).size(2,4)
|
---|
402 | * etc...
|
---|
403 | */
|
---|
404 | static bool matchExpression()
|
---|
405 | {
|
---|
406 | if (match(Tok_Integer)) {
|
---|
407 | return true;
|
---|
408 | }
|
---|
409 |
|
---|
410 | int parenlevel = 0;
|
---|
411 | while (match(Tok_Ident) || parenlevel > 0) {
|
---|
412 | if (yyTok == Tok_RightParen) {
|
---|
413 | if (parenlevel == 0) break;
|
---|
414 | --parenlevel;
|
---|
415 | yyTok = getToken();
|
---|
416 | } else if (yyTok == Tok_LeftParen) {
|
---|
417 | yyTok = getToken();
|
---|
418 | if (yyTok == Tok_RightParen) {
|
---|
419 | yyTok = getToken();
|
---|
420 | } else {
|
---|
421 | ++parenlevel;
|
---|
422 | }
|
---|
423 | } else if (yyTok == Tok_Ident) {
|
---|
424 | continue;
|
---|
425 | } else if (parenlevel == 0) {
|
---|
426 | return false;
|
---|
427 | }
|
---|
428 | }
|
---|
429 | return true;
|
---|
430 | }
|
---|
431 |
|
---|
432 | static const QString context()
|
---|
433 | {
|
---|
434 | QString context(yyPackage);
|
---|
435 | bool innerClass = false;
|
---|
436 | for (int i = 0; i < yyScope.size(); ++i) {
|
---|
437 | if (yyScope.at(i)->type == Scope::Clazz) {
|
---|
438 | if (innerClass)
|
---|
439 | context.append(QLatin1String("$"));
|
---|
440 | else
|
---|
441 | context.append(QLatin1String("."));
|
---|
442 |
|
---|
443 | context.append(yyScope.at(i)->name);
|
---|
444 | innerClass = true;
|
---|
445 | }
|
---|
446 | }
|
---|
447 | return context.isEmpty() ? yyDefaultContext : context;
|
---|
448 | }
|
---|
449 |
|
---|
450 | static void recordMessage(
|
---|
451 | Translator *tor, const QString &context, const QString &text, const QString &comment,
|
---|
452 | const QString &extracomment, bool plural)
|
---|
453 | {
|
---|
454 | TranslatorMessage msg(
|
---|
455 | context, text, comment, QString(),
|
---|
456 | yyFileName, yyLineNo, QStringList(),
|
---|
457 | TranslatorMessage::Unfinished, plural);
|
---|
458 | msg.setExtraComment(extracomment.simplified());
|
---|
459 | tor->extend(msg);
|
---|
460 | }
|
---|
461 |
|
---|
462 | static void parse( Translator *tor )
|
---|
463 | {
|
---|
464 | QString text;
|
---|
465 | QString com;
|
---|
466 | QString extracomment;
|
---|
467 |
|
---|
468 | yyCh = getChar();
|
---|
469 |
|
---|
470 | yyTok = getToken();
|
---|
471 | while ( yyTok != Tok_Eof ) {
|
---|
472 | switch ( yyTok ) {
|
---|
473 | case Tok_class:
|
---|
474 | yyTok = getToken();
|
---|
475 | if(yyTok == Tok_Ident) {
|
---|
476 | yyScope.push(new Scope(yyIdent, Scope::Clazz, yyLineNo));
|
---|
477 | }
|
---|
478 | else {
|
---|
479 | qFatal( "%s:%d: Class must be followed by a classname",
|
---|
480 | qPrintable(yyFileName), yyLineNo );
|
---|
481 | }
|
---|
482 | while (!match(Tok_LeftBrace)) {
|
---|
483 | yyTok = getToken();
|
---|
484 | }
|
---|
485 | break;
|
---|
486 |
|
---|
487 | case Tok_tr:
|
---|
488 | yyTok = getToken();
|
---|
489 | if ( match(Tok_LeftParen) && matchString(text) ) {
|
---|
490 | com.clear();
|
---|
491 | bool plural = false;
|
---|
492 |
|
---|
493 | if ( match(Tok_RightParen) ) {
|
---|
494 | // no comment
|
---|
495 | } else if (match(Tok_Comma) && matchStringOrNull(com)) { //comment
|
---|
496 | if ( match(Tok_RightParen)) {
|
---|
497 | // ok,
|
---|
498 | } else if (match(Tok_Comma)) {
|
---|
499 | plural = true;
|
---|
500 | }
|
---|
501 | }
|
---|
502 | if (!text.isEmpty())
|
---|
503 | recordMessage(tor, context(), text, com, extracomment, plural);
|
---|
504 | }
|
---|
505 | break;
|
---|
506 | case Tok_translate:
|
---|
507 | {
|
---|
508 | QString contextOverride;
|
---|
509 | yyTok = getToken();
|
---|
510 | if ( match(Tok_LeftParen) &&
|
---|
511 | matchString(contextOverride) &&
|
---|
512 | match(Tok_Comma) &&
|
---|
513 | matchString(text) ) {
|
---|
514 |
|
---|
515 | com.clear();
|
---|
516 | bool plural = false;
|
---|
517 | if (!match(Tok_RightParen)) {
|
---|
518 | // look for comment
|
---|
519 | if ( match(Tok_Comma) && matchStringOrNull(com)) {
|
---|
520 | if (!match(Tok_RightParen)) {
|
---|
521 | if (match(Tok_Comma) && matchExpression() && match(Tok_RightParen)) {
|
---|
522 | plural = true;
|
---|
523 | } else {
|
---|
524 | break;
|
---|
525 | }
|
---|
526 | }
|
---|
527 | } else {
|
---|
528 | break;
|
---|
529 | }
|
---|
530 | }
|
---|
531 | if (!text.isEmpty())
|
---|
532 | recordMessage(tor, contextOverride, text, com, extracomment, plural);
|
---|
533 | }
|
---|
534 | }
|
---|
535 | break;
|
---|
536 |
|
---|
537 | case Tok_Ident:
|
---|
538 | yyTok = getToken();
|
---|
539 | break;
|
---|
540 |
|
---|
541 | case Tok_Comment:
|
---|
542 | if (yyComment.startsWith(QLatin1Char(':'))) {
|
---|
543 | yyComment.remove(0, 1);
|
---|
544 | extracomment.append(yyComment);
|
---|
545 | }
|
---|
546 | yyTok = getToken();
|
---|
547 | break;
|
---|
548 |
|
---|
549 | case Tok_RightBrace:
|
---|
550 | if ( yyScope.isEmpty() ) {
|
---|
551 | qFatal( "%s:%d: Unbalanced right brace in Java code\n",
|
---|
552 | qPrintable(yyFileName), yyLineNo );
|
---|
553 | }
|
---|
554 | else
|
---|
555 | delete (yyScope.pop());
|
---|
556 | extracomment.clear();
|
---|
557 | yyTok = getToken();
|
---|
558 | break;
|
---|
559 |
|
---|
560 | case Tok_LeftBrace:
|
---|
561 | yyScope.push(new Scope(QString(), Scope::Other, yyLineNo));
|
---|
562 | yyTok = getToken();
|
---|
563 | break;
|
---|
564 |
|
---|
565 | case Tok_Semicolon:
|
---|
566 | extracomment.clear();
|
---|
567 | yyTok = getToken();
|
---|
568 | break;
|
---|
569 |
|
---|
570 | case Tok_Package:
|
---|
571 | yyTok = getToken();
|
---|
572 | while(!match(Tok_Semicolon)) {
|
---|
573 | switch(yyTok) {
|
---|
574 | case Tok_Ident:
|
---|
575 | yyPackage.append(yyIdent);
|
---|
576 | break;
|
---|
577 | case Tok_Dot:
|
---|
578 | yyPackage.append(QLatin1String("."));
|
---|
579 | break;
|
---|
580 | default:
|
---|
581 | qFatal( "%s:%d: Package keyword should be followed by com.package.name;",
|
---|
582 | qPrintable(yyFileName), yyLineNo );
|
---|
583 | break;
|
---|
584 | }
|
---|
585 | yyTok = getToken();
|
---|
586 | }
|
---|
587 | break;
|
---|
588 |
|
---|
589 | default:
|
---|
590 | yyTok = getToken();
|
---|
591 | }
|
---|
592 | }
|
---|
593 |
|
---|
594 | if ( !yyScope.isEmpty() )
|
---|
595 | qFatal( "%s:%d: Unbalanced braces in Java code\n",
|
---|
596 | qPrintable(yyFileName), yyScope.top()->line );
|
---|
597 | else if ( yyParenDepth != 0 )
|
---|
598 | qFatal( "%s:%d: Unbalanced parentheses in Java code\n",
|
---|
599 | qPrintable(yyFileName), yyParenLineNo );
|
---|
600 | }
|
---|
601 |
|
---|
602 |
|
---|
603 | bool loadJava(Translator &translator, QIODevice &dev, ConversionData &cd)
|
---|
604 | {
|
---|
605 | //void LupdateApplication::fetchtr_java( const QString &fileName, Translator *tor,
|
---|
606 | //const QString &defaultContext, bool mustExist, const QByteArray &codecForSource )
|
---|
607 |
|
---|
608 | yyDefaultContext = cd.m_defaultContext;
|
---|
609 | yyInPos = -1;
|
---|
610 | yyFileName = cd.m_sourceFileName;
|
---|
611 | yyPackage.clear();
|
---|
612 | yyScope.clear();
|
---|
613 | yyTok = -1;
|
---|
614 | yyParenDepth = 0;
|
---|
615 | yyCurLineNo = 0;
|
---|
616 | yyParenLineNo = 1;
|
---|
617 |
|
---|
618 | QTextStream ts(&dev);
|
---|
619 | QByteArray codecName;
|
---|
620 | if (!cd.m_codecForSource.isEmpty())
|
---|
621 | codecName = cd.m_codecForSource;
|
---|
622 | else
|
---|
623 | codecName = translator.codecName(); // Just because it should be latin1 already
|
---|
624 | ts.setCodec(QTextCodec::codecForName(codecName));
|
---|
625 | ts.setAutoDetectUnicode(true);
|
---|
626 | yyInStr = ts.readAll();
|
---|
627 | yyInPos = 0;
|
---|
628 | yyFileName = cd.m_sourceFileName;
|
---|
629 | yyCurLineNo = 1;
|
---|
630 | yyParenLineNo = 1;
|
---|
631 | yyCh = getChar();
|
---|
632 |
|
---|
633 | parse(&translator);
|
---|
634 |
|
---|
635 | // Java uses UTF-16 internally and Jambi makes UTF-8 for tr() purposes of it.
|
---|
636 | translator.setCodecName("UTF-8");
|
---|
637 | return true;
|
---|
638 | }
|
---|
639 |
|
---|
640 | int initJava()
|
---|
641 | {
|
---|
642 | Translator::FileFormat format;
|
---|
643 | format.extension = QLatin1String("java");
|
---|
644 | format.fileType = Translator::FileFormat::SourceCode;
|
---|
645 | format.priority = 0;
|
---|
646 | format.description = QObject::tr("Java source files");
|
---|
647 | format.loader = &loadJava;
|
---|
648 | format.saver = 0;
|
---|
649 | Translator::registerFileFormat(format);
|
---|
650 | return 1;
|
---|
651 | }
|
---|
652 |
|
---|
653 | Q_CONSTRUCTOR_FUNCTION(initJava)
|
---|
654 |
|
---|
655 | QT_END_NAMESPACE
|
---|