summaryrefslogtreecommitdiff
path: root/development
authorzecke <zecke>2003-08-31 19:06:45 (UTC)
committer zecke <zecke>2003-08-31 19:06:45 (UTC)
commit2696413e75a401899764f244c8c24026999fdb9d (patch) (unidiff)
tree630522a33052ea7d337bc76f624be0d7e142ff04 /development
parentce4a99860d28e003871994cca88a82133c1921a7 (diff)
downloadopie-2696413e75a401899764f244c8c24026999fdb9d.zip
opie-2696413e75a401899764f244c8c24026999fdb9d.tar.gz
opie-2696413e75a401899764f244c8c24026999fdb9d.tar.bz2
recognize i18n as well
Diffstat (limited to 'development') (more/less context) (ignore whitespace changes)
-rw-r--r--development/translation/opie-lupdate/fetchtr.cpp3
1 files changed, 3 insertions, 0 deletions
diff --git a/development/translation/opie-lupdate/fetchtr.cpp b/development/translation/opie-lupdate/fetchtr.cpp
index eb25555..d1f5881 100644
--- a/development/translation/opie-lupdate/fetchtr.cpp
+++ b/development/translation/opie-lupdate/fetchtr.cpp
@@ -1,562 +1,565 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qt Linguist. 4** This file is part of Qt Linguist.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#include <metatranslator.h> 21#include <metatranslator.h>
22 22
23#include <qfile.h> 23#include <qfile.h>
24#include <qregexp.h> 24#include <qregexp.h>
25#include <qstring.h> 25#include <qstring.h>
26#include <qtextstream.h> 26#include <qtextstream.h>
27#include <qvaluestack.h> 27#include <qvaluestack.h>
28#include <qxml.h> 28#include <qxml.h>
29 29
30#include <ctype.h> 30#include <ctype.h>
31#include <errno.h> 31#include <errno.h>
32#include <stdio.h> 32#include <stdio.h>
33#include <string.h> 33#include <string.h>
34 34
35/* qmake ignore Q_OBJECT */ 35/* qmake ignore Q_OBJECT */
36 36
37static const char MagicComment[] = "TRANSLATOR "; 37static const char MagicComment[] = "TRANSLATOR ";
38 38
39static QMap<QCString, int> needs_Q_OBJECT; 39static QMap<QCString, int> needs_Q_OBJECT;
40static QMap<QCString, int> lacks_Q_OBJECT; 40static QMap<QCString, int> lacks_Q_OBJECT;
41 41
42/* 42/*
43 The first part of this source file is the C++ tokenizer. We skip 43 The first part of this source file is the C++ tokenizer. We skip
44 most of C++; the only tokens that interest us are defined here. 44 most of C++; the only tokens that interest us are defined here.
45 Thus, the code fragment 45 Thus, the code fragment
46 46
47 int main() 47 int main()
48 { 48 {
49 printf( "Hello, world!\n" ); 49 printf( "Hello, world!\n" );
50 return 0; 50 return 0;
51 } 51 }
52 52
53 is broken down into the following tokens (Tok_ omitted): 53 is broken down into the following tokens (Tok_ omitted):
54 54
55 Ident Ident LeftParen RightParen 55 Ident Ident LeftParen RightParen
56 LeftBrace 56 LeftBrace
57 Ident LeftParen String RightParen Semicolon 57 Ident LeftParen String RightParen Semicolon
58 return Semicolon 58 return Semicolon
59 RightBrace. 59 RightBrace.
60 60
61 The 0 doesn't produce any token. 61 The 0 doesn't produce any token.
62*/ 62*/
63 63
64enum { Tok_Eof, Tok_class, Tok_namespace, Tok_return, Tok_tr, 64enum { Tok_Eof, Tok_class, Tok_namespace, Tok_return, Tok_tr,
65 Tok_trUtf8, Tok_translate, Tok_Q_OBJECT, Tok_Ident, 65 Tok_trUtf8, Tok_translate, Tok_Q_OBJECT, Tok_Ident,
66 Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon, 66 Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon,
67 Tok_Gulbrandsen, Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen, 67 Tok_Gulbrandsen, Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen,
68 Tok_RightParen, Tok_Comma, Tok_Semicolon }; 68 Tok_RightParen, Tok_Comma, Tok_Semicolon };
69 69
70/* 70/*
71 The tokenizer maintains the following global variables. The names 71 The tokenizer maintains the following global variables. The names
72 should be self-explanatory. 72 should be self-explanatory.
73*/ 73*/
74static QCString yyFileName; 74static QCString yyFileName;
75static int yyCh; 75static int yyCh;
76static char yyIdent[128]; 76static char yyIdent[128];
77static size_t yyIdentLen; 77static size_t yyIdentLen;
78static char yyComment[65536]; 78static char yyComment[65536];
79static size_t yyCommentLen; 79static size_t yyCommentLen;
80static char yyString[16384]; 80static char yyString[16384];
81static size_t yyStringLen; 81static size_t yyStringLen;
82static QValueStack<int> yySavedBraceDepth; 82static QValueStack<int> yySavedBraceDepth;
83static int yyBraceDepth; 83static int yyBraceDepth;
84static int yyParenDepth; 84static int yyParenDepth;
85static int yyLineNo; 85static int yyLineNo;
86static int yyCurLineNo; 86static int yyCurLineNo;
87 87
88// the file to read from (if reading from a file) 88// the file to read from (if reading from a file)
89static FILE *yyInFile; 89static FILE *yyInFile;
90 90
91// the string to read from and current position in the string (otherwise) 91// the string to read from and current position in the string (otherwise)
92static QString yyInStr; 92static QString yyInStr;
93static int yyInPos; 93static int yyInPos;
94 94
95static int (*getChar)(); 95static int (*getChar)();
96 96
97static int getCharFromFile() 97static int getCharFromFile()
98{ 98{
99 int c = getc( yyInFile ); 99 int c = getc( yyInFile );
100 if ( c == '\n' ) 100 if ( c == '\n' )
101 yyCurLineNo++; 101 yyCurLineNo++;
102 return c; 102 return c;
103} 103}
104 104
105static int getCharFromString() 105static int getCharFromString()
106{ 106{
107 if ( yyInPos == (int) yyInStr.length() ) { 107 if ( yyInPos == (int) yyInStr.length() ) {
108 return EOF; 108 return EOF;
109 } else { 109 } else {
110 return yyInStr[yyInPos++].latin1(); 110 return yyInStr[yyInPos++].latin1();
111 } 111 }
112} 112}
113 113
114static void startTokenizer( const char *fileName, int (*getCharFunc)() ) 114static void startTokenizer( const char *fileName, int (*getCharFunc)() )
115{ 115{
116 yyInPos = 0; 116 yyInPos = 0;
117 getChar = getCharFunc; 117 getChar = getCharFunc;
118 118
119 yyFileName = fileName; 119 yyFileName = fileName;
120 yyCh = getChar(); 120 yyCh = getChar();
121 yySavedBraceDepth.clear(); 121 yySavedBraceDepth.clear();
122 yyBraceDepth = 0; 122 yyBraceDepth = 0;
123 yyParenDepth = 0; 123 yyParenDepth = 0;
124 yyCurLineNo = 1; 124 yyCurLineNo = 1;
125} 125}
126 126
127static int getToken() 127static int getToken()
128{ 128{
129 const char tab[] = "abfnrtv"; 129 const char tab[] = "abfnrtv";
130 const char backTab[] = "\a\b\f\n\r\t\v"; 130 const char backTab[] = "\a\b\f\n\r\t\v";
131 uint n; 131 uint n;
132 132
133 yyIdentLen = 0; 133 yyIdentLen = 0;
134 yyCommentLen = 0; 134 yyCommentLen = 0;
135 yyStringLen = 0; 135 yyStringLen = 0;
136 136
137 while ( yyCh != EOF ) { 137 while ( yyCh != EOF ) {
138 yyLineNo = yyCurLineNo; 138 yyLineNo = yyCurLineNo;
139 139
140 if ( isalpha(yyCh) || yyCh == '_' ) { 140 if ( isalpha(yyCh) || yyCh == '_' ) {
141 do { 141 do {
142 if ( yyIdentLen < sizeof(yyIdent) - 1 ) 142 if ( yyIdentLen < sizeof(yyIdent) - 1 )
143 yyIdent[yyIdentLen++] = (char) yyCh; 143 yyIdent[yyIdentLen++] = (char) yyCh;
144 yyCh = getChar(); 144 yyCh = getChar();
145 } while ( isalnum(yyCh) || yyCh == '_' ); 145 } while ( isalnum(yyCh) || yyCh == '_' );
146 yyIdent[yyIdentLen] = '\0'; 146 yyIdent[yyIdentLen] = '\0';
147 147
148 switch ( yyIdent[0] ) { 148 switch ( yyIdent[0] ) {
149 case 'Q': 149 case 'Q':
150 if ( strcmp(yyIdent + 1, "_OBJECT") == 0 ) { 150 if ( strcmp(yyIdent + 1, "_OBJECT") == 0 ) {
151 return Tok_Q_OBJECT; 151 return Tok_Q_OBJECT;
152 } else if ( strcmp(yyIdent + 1, "T_TR_NOOP") == 0 ) { 152 } else if ( strcmp(yyIdent + 1, "T_TR_NOOP") == 0 ) {
153 return Tok_tr; 153 return Tok_tr;
154 } else if ( strcmp(yyIdent + 1, "T_TRANSLATE_NOOP") == 0 ) { 154 } else if ( strcmp(yyIdent + 1, "T_TRANSLATE_NOOP") == 0 ) {
155 return Tok_translate; 155 return Tok_translate;
156 } 156 }
157 break; 157 break;
158 case 'T': 158 case 'T':
159 // TR() for when all else fails 159 // TR() for when all else fails
160 if ( qstricmp(yyIdent + 1, "R") == 0 ) 160 if ( qstricmp(yyIdent + 1, "R") == 0 )
161 return Tok_tr; 161 return Tok_tr;
162 break; 162 break;
163 case 'c': 163 case 'c':
164 if ( strcmp(yyIdent + 1, "lass") == 0 ) 164 if ( strcmp(yyIdent + 1, "lass") == 0 )
165 return Tok_class; 165 return Tok_class;
166 break; 166 break;
167 case 'n': 167 case 'n':
168 if ( strcmp(yyIdent + 1, "amespace") == 0 ) 168 if ( strcmp(yyIdent + 1, "amespace") == 0 )
169 return Tok_namespace; 169 return Tok_namespace;
170 break; 170 break;
171 case 'r': 171 case 'r':
172 if ( strcmp(yyIdent + 1, "eturn") == 0 ) 172 if ( strcmp(yyIdent + 1, "eturn") == 0 )
173 return Tok_return; 173 return Tok_return;
174 break; 174 break;
175 case 's': 175 case 's':
176 if ( strcmp(yyIdent + 1, "truct") == 0 ) 176 if ( strcmp(yyIdent + 1, "truct") == 0 )
177 return Tok_class; 177 return Tok_class;
178 break; 178 break;
179 case 'i':
180 if( strcmp(yyIdent + 1, "18n") == 0 )
181 return Tok_tr;
179 case 't': 182 case 't':
180 if ( strcmp(yyIdent + 1, "r") == 0 ) { 183 if ( strcmp(yyIdent + 1, "r") == 0 ) {
181 return Tok_tr; 184 return Tok_tr;
182 } else if ( qstrcmp(yyIdent + 1, "rUtf8") == 0 ) { 185 } else if ( qstrcmp(yyIdent + 1, "rUtf8") == 0 ) {
183 return Tok_trUtf8; 186 return Tok_trUtf8;
184 } else if ( qstrcmp(yyIdent + 1, "ranslate") == 0 ) { 187 } else if ( qstrcmp(yyIdent + 1, "ranslate") == 0 ) {
185 return Tok_translate; 188 return Tok_translate;
186 } 189 }
187 } 190 }
188 return Tok_Ident; 191 return Tok_Ident;
189 } else { 192 } else {
190 switch ( yyCh ) { 193 switch ( yyCh ) {
191 case '#': 194 case '#':
192 /* 195 /*
193 Early versions of lupdate complained about 196 Early versions of lupdate complained about
194 unbalanced braces in the following code: 197 unbalanced braces in the following code:
195 198
196 #ifdef ALPHA 199 #ifdef ALPHA
197 while ( beta ) { 200 while ( beta ) {
198 #else 201 #else
199 while ( gamma ) { 202 while ( gamma ) {
200 #endif 203 #endif
201 delta; 204 delta;
202 } 205 }
203 206
204 The code contains, indeed, two opening braces for 207 The code contains, indeed, two opening braces for
205 one closing brace; yet there's no reason to panic. 208 one closing brace; yet there's no reason to panic.
206 209
207 The solution is to remember yyBraceDepth as it was 210 The solution is to remember yyBraceDepth as it was
208 when #if, #ifdef or #ifndef was met, and to set 211 when #if, #ifdef or #ifndef was met, and to set
209 yyBraceDepth to that value when meeting #elif or 212 yyBraceDepth to that value when meeting #elif or
210 #else. 213 #else.
211 */ 214 */
212 do { 215 do {
213 yyCh = getChar(); 216 yyCh = getChar();
214 } while ( isspace(yyCh) && yyCh != '\n' ); 217 } while ( isspace(yyCh) && yyCh != '\n' );
215 218
216 switch ( yyCh ) { 219 switch ( yyCh ) {
217 case 'i': 220 case 'i':
218 yyCh = getChar(); 221 yyCh = getChar();
219 if ( yyCh == 'f' ) { 222 if ( yyCh == 'f' ) {
220 // if, ifdef, ifndef 223 // if, ifdef, ifndef
221 yySavedBraceDepth.push( yyBraceDepth ); 224 yySavedBraceDepth.push( yyBraceDepth );
222 } 225 }
223 break; 226 break;
224 case 'e': 227 case 'e':
225 yyCh = getChar(); 228 yyCh = getChar();
226 if ( yyCh == 'l' ) { 229 if ( yyCh == 'l' ) {
227 // elif, else 230 // elif, else
228 if ( !yySavedBraceDepth.isEmpty() ) 231 if ( !yySavedBraceDepth.isEmpty() )
229 yyBraceDepth = yySavedBraceDepth.top(); 232 yyBraceDepth = yySavedBraceDepth.top();
230 } else if ( yyCh == 'n' ) { 233 } else if ( yyCh == 'n' ) {
231 // endif 234 // endif
232 if ( !yySavedBraceDepth.isEmpty() ) 235 if ( !yySavedBraceDepth.isEmpty() )
233 yySavedBraceDepth.pop(); 236 yySavedBraceDepth.pop();
234 } 237 }
235 } 238 }
236 while ( isalnum(yyCh) || yyCh == '_' ) 239 while ( isalnum(yyCh) || yyCh == '_' )
237 yyCh = getChar(); 240 yyCh = getChar();
238 break; 241 break;
239 case '/': 242 case '/':
240 yyCh = getChar(); 243 yyCh = getChar();
241 if ( yyCh == '/' ) { 244 if ( yyCh == '/' ) {
242 do { 245 do {
243 yyCh = getChar(); 246 yyCh = getChar();
244 } while ( yyCh != EOF && yyCh != '\n' ); 247 } while ( yyCh != EOF && yyCh != '\n' );
245 } else if ( yyCh == '*' ) { 248 } else if ( yyCh == '*' ) {
246 bool metAster = FALSE; 249 bool metAster = FALSE;
247 bool metAsterSlash = FALSE; 250 bool metAsterSlash = FALSE;
248 251
249 while ( !metAsterSlash ) { 252 while ( !metAsterSlash ) {
250 yyCh = getChar(); 253 yyCh = getChar();
251 if ( yyCh == EOF ) { 254 if ( yyCh == EOF ) {
252 fprintf( stderr, 255 fprintf( stderr,
253 "%s: Unterminated C++ comment starting at" 256 "%s: Unterminated C++ comment starting at"
254 " line %d\n", 257 " line %d\n",
255 (const char *) yyFileName, yyLineNo ); 258 (const char *) yyFileName, yyLineNo );
256 yyComment[yyCommentLen] = '\0'; 259 yyComment[yyCommentLen] = '\0';
257 return Tok_Comment; 260 return Tok_Comment;
258 } 261 }
259 if ( yyCommentLen < sizeof(yyComment) - 1 ) 262 if ( yyCommentLen < sizeof(yyComment) - 1 )
260 yyComment[yyCommentLen++] = (char) yyCh; 263 yyComment[yyCommentLen++] = (char) yyCh;
261 264
262 if ( yyCh == '*' ) 265 if ( yyCh == '*' )
263 metAster = TRUE; 266 metAster = TRUE;
264 else if ( metAster && yyCh == '/' ) 267 else if ( metAster && yyCh == '/' )
265 metAsterSlash = TRUE; 268 metAsterSlash = TRUE;
266 else 269 else
267 metAster = FALSE; 270 metAster = FALSE;
268 } 271 }
269 yyCh = getChar(); 272 yyCh = getChar();
270 yyCommentLen -= 2; 273 yyCommentLen -= 2;
271 yyComment[yyCommentLen] = '\0'; 274 yyComment[yyCommentLen] = '\0';
272 return Tok_Comment; 275 return Tok_Comment;
273 } 276 }
274 break; 277 break;
275 case '"': 278 case '"':
276 yyCh = getChar(); 279 yyCh = getChar();
277 280
278 while ( yyCh != EOF && yyCh != '\n' && yyCh != '"' ) { 281 while ( yyCh != EOF && yyCh != '\n' && yyCh != '"' ) {
279 if ( yyCh == '\\' ) { 282 if ( yyCh == '\\' ) {
280 yyCh = getChar(); 283 yyCh = getChar();
281 284
282 if ( yyCh == '\n' ) { 285 if ( yyCh == '\n' ) {
283 yyCh = getChar(); 286 yyCh = getChar();
284 } else if ( yyCh == 'x' ) { 287 } else if ( yyCh == 'x' ) {
285 QCString hex = "0"; 288 QCString hex = "0";
286 289
287 yyCh = getChar(); 290 yyCh = getChar();
288 while ( isxdigit(yyCh) ) { 291 while ( isxdigit(yyCh) ) {
289 hex += (char) yyCh; 292 hex += (char) yyCh;
290 yyCh = getChar(); 293 yyCh = getChar();
291 } 294 }
292 sscanf( hex, "%x", &n ); 295 sscanf( hex, "%x", &n );
293 if ( yyStringLen < sizeof(yyString) - 1 ) 296 if ( yyStringLen < sizeof(yyString) - 1 )
294 yyString[yyStringLen++] = (char) n; 297 yyString[yyStringLen++] = (char) n;
295 } else if ( yyCh >= '0' && yyCh < '8' ) { 298 } else if ( yyCh >= '0' && yyCh < '8' ) {
296 QCString oct = ""; 299 QCString oct = "";
297 300
298 do { 301 do {
299 oct += (char) yyCh; 302 oct += (char) yyCh;
300 yyCh = getChar(); 303 yyCh = getChar();
301 } while ( yyCh >= '0' && yyCh < '8' ); 304 } while ( yyCh >= '0' && yyCh < '8' );
302 sscanf( oct, "%o", &n ); 305 sscanf( oct, "%o", &n );
303 if ( yyStringLen < sizeof(yyString) - 1 ) 306 if ( yyStringLen < sizeof(yyString) - 1 )
304 yyString[yyStringLen++] = (char) n; 307 yyString[yyStringLen++] = (char) n;
305 } else { 308 } else {
306 const char *p = strchr( tab, yyCh ); 309 const char *p = strchr( tab, yyCh );
307 if ( yyStringLen < sizeof(yyString) - 1 ) 310 if ( yyStringLen < sizeof(yyString) - 1 )
308 yyString[yyStringLen++] = ( p == 0 ) ? 311 yyString[yyStringLen++] = ( p == 0 ) ?
309 (char) yyCh : backTab[p - tab]; 312 (char) yyCh : backTab[p - tab];
310 yyCh = getChar(); 313 yyCh = getChar();
311 } 314 }
312 } else { 315 } else {
313 if ( yyStringLen < sizeof(yyString) - 1 ) 316 if ( yyStringLen < sizeof(yyString) - 1 )
314 yyString[yyStringLen++] = (char) yyCh; 317 yyString[yyStringLen++] = (char) yyCh;
315 yyCh = getChar(); 318 yyCh = getChar();
316 } 319 }
317 } 320 }
318 yyString[yyStringLen] = '\0'; 321 yyString[yyStringLen] = '\0';
319 322
320 if ( yyCh != '"' ) 323 if ( yyCh != '"' )
321 qWarning( "%s:%d: Unterminated C++ string", 324 qWarning( "%s:%d: Unterminated C++ string",
322 (const char *) yyFileName, yyLineNo ); 325 (const char *) yyFileName, yyLineNo );
323 326
324 if ( yyCh == EOF ) { 327 if ( yyCh == EOF ) {
325 return Tok_Eof; 328 return Tok_Eof;
326 } else { 329 } else {
327 yyCh = getChar(); 330 yyCh = getChar();
328 return Tok_String; 331 return Tok_String;
329 } 332 }
330 break; 333 break;
331 case '-': 334 case '-':
332 yyCh = getChar(); 335 yyCh = getChar();
333 if ( yyCh == '>' ) { 336 if ( yyCh == '>' ) {
334 yyCh = getChar(); 337 yyCh = getChar();
335 return Tok_Arrow; 338 return Tok_Arrow;
336 } 339 }
337 break; 340 break;
338 case ':': 341 case ':':
339 yyCh = getChar(); 342 yyCh = getChar();
340 if ( yyCh == ':' ) { 343 if ( yyCh == ':' ) {
341 yyCh = getChar(); 344 yyCh = getChar();
342 return Tok_Gulbrandsen; 345 return Tok_Gulbrandsen;
343 } 346 }
344 return Tok_Colon; 347 return Tok_Colon;
345 case '\'': 348 case '\'':
346 yyCh = getChar(); 349 yyCh = getChar();
347 if ( yyCh == '\\' ) 350 if ( yyCh == '\\' )
348 yyCh = getChar(); 351 yyCh = getChar();
349 352
350 do { 353 do {
351 yyCh = getChar(); 354 yyCh = getChar();
352 } while ( yyCh != EOF && yyCh != '\'' ); 355 } while ( yyCh != EOF && yyCh != '\'' );
353 yyCh = getChar(); 356 yyCh = getChar();
354 break; 357 break;
355 case '{': 358 case '{':
356 yyBraceDepth++; 359 yyBraceDepth++;
357 yyCh = getChar(); 360 yyCh = getChar();
358 return Tok_LeftBrace; 361 return Tok_LeftBrace;
359 case '}': 362 case '}':
360 yyBraceDepth--; 363 yyBraceDepth--;
361 yyCh = getChar(); 364 yyCh = getChar();
362 return Tok_RightBrace; 365 return Tok_RightBrace;
363 case '(': 366 case '(':
364 yyParenDepth++; 367 yyParenDepth++;
365 yyCh = getChar(); 368 yyCh = getChar();
366 return Tok_LeftParen; 369 return Tok_LeftParen;
367 case ')': 370 case ')':
368 yyParenDepth--; 371 yyParenDepth--;
369 yyCh = getChar(); 372 yyCh = getChar();
370 return Tok_RightParen; 373 return Tok_RightParen;
371 case ',': 374 case ',':
372 yyCh = getChar(); 375 yyCh = getChar();
373 return Tok_Comma; 376 return Tok_Comma;
374 case ';': 377 case ';':
375 yyCh = getChar(); 378 yyCh = getChar();
376 return Tok_Semicolon; 379 return Tok_Semicolon;
377 default: 380 default:
378 yyCh = getChar(); 381 yyCh = getChar();
379 } 382 }
380 } 383 }
381 } 384 }
382 return Tok_Eof; 385 return Tok_Eof;
383} 386}
384 387
385/* 388/*
386 The second part of this source file is the parser. It accomplishes 389 The second part of this source file is the parser. It accomplishes
387 a very easy task: It finds all strings inside a tr() or translate() 390 a very easy task: It finds all strings inside a tr() or translate()
388 call, and possibly finds out the context of the call. It supports 391 call, and possibly finds out the context of the call. It supports
389 three cases: (1) the context is specified, as in 392 three cases: (1) the context is specified, as in
390 FunnyDialog::tr("Hello") or translate("FunnyDialog", "Hello"); 393 FunnyDialog::tr("Hello") or translate("FunnyDialog", "Hello");
391 (2) the call appears within an inlined function; (3) the call 394 (2) the call appears within an inlined function; (3) the call
392 appears within a function defined outside the class definition. 395 appears within a function defined outside the class definition.
393*/ 396*/
394 397
395static int yyTok; 398static int yyTok;
396 399
397static bool match( int t ) 400static bool match( int t )
398{ 401{
399 bool matches = ( yyTok == t ); 402 bool matches = ( yyTok == t );
400 if ( matches ) 403 if ( matches )
401 yyTok = getToken(); 404 yyTok = getToken();
402 return matches; 405 return matches;
403} 406}
404 407
405static bool matchString( QCString *s ) 408static bool matchString( QCString *s )
406{ 409{
407 bool matches = ( yyTok == Tok_String ); 410 bool matches = ( yyTok == Tok_String );
408 *s = ""; 411 *s = "";
409 while ( yyTok == Tok_String ) { 412 while ( yyTok == Tok_String ) {
410 *s += yyString; 413 *s += yyString;
411 yyTok = getToken(); 414 yyTok = getToken();
412 } 415 }
413 return matches; 416 return matches;
414} 417}
415 418
416static bool matchEncoding( bool *utf8 ) 419static bool matchEncoding( bool *utf8 )
417{ 420{
418 if ( yyTok == Tok_Ident ) { 421 if ( yyTok == Tok_Ident ) {
419 if ( strcmp(yyIdent, "QApplication") == 0 ) { 422 if ( strcmp(yyIdent, "QApplication") == 0 ) {
420 yyTok = getToken(); 423 yyTok = getToken();
421 if ( yyTok == Tok_Gulbrandsen ) 424 if ( yyTok == Tok_Gulbrandsen )
422 yyTok = getToken(); 425 yyTok = getToken();
423 } 426 }
424 *utf8 = QString( yyIdent ).endsWith( QString("UTF8") ); 427 *utf8 = QString( yyIdent ).endsWith( QString("UTF8") );
425 yyTok = getToken(); 428 yyTok = getToken();
426 return TRUE; 429 return TRUE;
427 } else { 430 } else {
428 return FALSE; 431 return FALSE;
429 } 432 }
430} 433}
431 434
432static void parse( MetaTranslator *tor, const char *initialContext, 435static void parse( MetaTranslator *tor, const char *initialContext,
433 const char *defaultContext ) 436 const char *defaultContext )
434{ 437{
435 QMap<QCString, QCString> qualifiedContexts; 438 QMap<QCString, QCString> qualifiedContexts;
436 QStringList namespaces; 439 QStringList namespaces;
437 QCString context; 440 QCString context;
438 QCString text; 441 QCString text;
439 QCString com; 442 QCString com;
440 QCString functionContext = initialContext; 443 QCString functionContext = initialContext;
441 QCString prefix; 444 QCString prefix;
442 bool utf8 = FALSE; 445 bool utf8 = FALSE;
443 bool missing_Q_OBJECT = FALSE; 446 bool missing_Q_OBJECT = FALSE;
444 447
445 yyTok = getToken(); 448 yyTok = getToken();
446 while ( yyTok != Tok_Eof ) { 449 while ( yyTok != Tok_Eof ) {
447 switch ( yyTok ) { 450 switch ( yyTok ) {
448 case Tok_class: 451 case Tok_class:
449 /* 452 /*
450 Partial support for inlined functions. 453 Partial support for inlined functions.
451 */ 454 */
452 yyTok = getToken(); 455 yyTok = getToken();
453 if ( yyBraceDepth == (int) namespaces.count() && 456 if ( yyBraceDepth == (int) namespaces.count() &&
454 yyParenDepth == 0 ) { 457 yyParenDepth == 0 ) {
455 do { 458 do {
456 /* 459 /*
457 This code should execute only once, but we play 460 This code should execute only once, but we play
458 safe with impure definitions such as 461 safe with impure definitions such as
459 'class Q_EXPORT QMessageBox', in which case 462 'class Q_EXPORT QMessageBox', in which case
460 'QMessageBox' is the class name, not 'Q_EXPORT'. 463 'QMessageBox' is the class name, not 'Q_EXPORT'.
461 */ 464 */
462 functionContext = yyIdent; 465 functionContext = yyIdent;
463 yyTok = getToken(); 466 yyTok = getToken();
464 } while ( yyTok == Tok_Ident ); 467 } while ( yyTok == Tok_Ident );
465 468
466 while ( yyTok == Tok_Gulbrandsen ) { 469 while ( yyTok == Tok_Gulbrandsen ) {
467 yyTok = getToken(); 470 yyTok = getToken();
468 functionContext += "::"; 471 functionContext += "::";
469 functionContext += yyIdent; 472 functionContext += yyIdent;
470 yyTok = getToken(); 473 yyTok = getToken();
471 } 474 }
472 475
473 if ( yyTok == Tok_Colon ) { 476 if ( yyTok == Tok_Colon ) {
474 missing_Q_OBJECT = TRUE; 477 missing_Q_OBJECT = TRUE;
475 } else { 478 } else {
476 functionContext = defaultContext; 479 functionContext = defaultContext;
477 } 480 }
478 } 481 }
479 break; 482 break;
480 case Tok_namespace: 483 case Tok_namespace:
481 yyTok = getToken(); 484 yyTok = getToken();
482 if ( yyTok == Tok_Ident ) { 485 if ( yyTok == Tok_Ident ) {
483 QCString ns = yyIdent; 486 QCString ns = yyIdent;
484 yyTok = getToken(); 487 yyTok = getToken();
485 if ( yyTok == Tok_LeftBrace && 488 if ( yyTok == Tok_LeftBrace &&
486 yyBraceDepth == (int) namespaces.count() + 1 ) 489 yyBraceDepth == (int) namespaces.count() + 1 )
487 namespaces.append( QString(ns) ); 490 namespaces.append( QString(ns) );
488 } 491 }
489 break; 492 break;
490 case Tok_tr: 493 case Tok_tr:
491 case Tok_trUtf8: 494 case Tok_trUtf8:
492 utf8 = ( yyTok == Tok_trUtf8 ); 495 utf8 = ( yyTok == Tok_trUtf8 );
493 yyTok = getToken(); 496 yyTok = getToken();
494 if ( match(Tok_LeftParen) && matchString(&text) ) { 497 if ( match(Tok_LeftParen) && matchString(&text) ) {
495 com = ""; 498 com = "";
496 if ( match(Tok_RightParen) || (match(Tok_Comma) && 499 if ( match(Tok_RightParen) || (match(Tok_Comma) &&
497 matchString(&com) && match(Tok_RightParen)) ) { 500 matchString(&com) && match(Tok_RightParen)) ) {
498 if ( prefix.isNull() ) { 501 if ( prefix.isNull() ) {
499 context = functionContext; 502 context = functionContext;
500 if ( !namespaces.isEmpty() ) 503 if ( !namespaces.isEmpty() )
501 context.prepend( (namespaces.join(QString("::")) + 504 context.prepend( (namespaces.join(QString("::")) +
502 QString("::")).latin1() ); 505 QString("::")).latin1() );
503 } else { 506 } else {
504 context = prefix; 507 context = prefix;
505 } 508 }
506 prefix = (const char *) 0; 509 prefix = (const char *) 0;
507 510
508 if ( qualifiedContexts.contains(context) ) 511 if ( qualifiedContexts.contains(context) )
509 context = qualifiedContexts[context]; 512 context = qualifiedContexts[context];
510 tor->insert( MetaTranslatorMessage(context, text, com, 513 tor->insert( MetaTranslatorMessage(context, text, com,
511 QString::null, utf8) ); 514 QString::null, utf8) );
512 515
513 if ( lacks_Q_OBJECT.contains(context) ) { 516 if ( lacks_Q_OBJECT.contains(context) ) {
514 qWarning( "%s:%d: Class '%s' lacks Q_OBJECT macro", 517 qWarning( "%s:%d: Class '%s' lacks Q_OBJECT macro",
515 (const char *) yyFileName, yyLineNo, 518 (const char *) yyFileName, yyLineNo,
516 (const char *) context ); 519 (const char *) context );
517 lacks_Q_OBJECT.remove( context ); 520 lacks_Q_OBJECT.remove( context );
518 } else { 521 } else {
519 needs_Q_OBJECT.insert( context, 0 ); 522 needs_Q_OBJECT.insert( context, 0 );
520 } 523 }
521 } 524 }
522 } 525 }
523 break; 526 break;
524 case Tok_translate: 527 case Tok_translate:
525 utf8 = FALSE; 528 utf8 = FALSE;
526 yyTok = getToken(); 529 yyTok = getToken();
527 if ( match(Tok_LeftParen) && 530 if ( match(Tok_LeftParen) &&
528 matchString(&context) && 531 matchString(&context) &&
529 match(Tok_Comma) && 532 match(Tok_Comma) &&
530 matchString(&text) ) { 533 matchString(&text) ) {
531 com = ""; 534 com = "";
532 if ( match(Tok_RightParen) || 535 if ( match(Tok_RightParen) ||
533 (match(Tok_Comma) && 536 (match(Tok_Comma) &&
534 matchString(&com) && 537 matchString(&com) &&
535 (match(Tok_RightParen) || 538 (match(Tok_RightParen) ||
536 match(Tok_Comma) && 539 match(Tok_Comma) &&
537 matchEncoding(&utf8) && 540 matchEncoding(&utf8) &&
538 match(Tok_RightParen))) ) 541 match(Tok_RightParen))) )
539 tor->insert( MetaTranslatorMessage(context, text, com, 542 tor->insert( MetaTranslatorMessage(context, text, com,
540 QString::null, utf8) ); 543 QString::null, utf8) );
541 } 544 }
542 break; 545 break;
543 case Tok_Q_OBJECT: 546 case Tok_Q_OBJECT:
544 missing_Q_OBJECT = FALSE; 547 missing_Q_OBJECT = FALSE;
545 yyTok = getToken(); 548 yyTok = getToken();
546 break; 549 break;
547 case Tok_Ident: 550 case Tok_Ident:
548 if ( !prefix.isNull() ) 551 if ( !prefix.isNull() )
549 prefix += "::"; 552 prefix += "::";
550 prefix += yyIdent; 553 prefix += yyIdent;
551 yyTok = getToken(); 554 yyTok = getToken();
552 if ( yyTok != Tok_Gulbrandsen ) 555 if ( yyTok != Tok_Gulbrandsen )
553 prefix = (const char *) 0; 556 prefix = (const char *) 0;
554 break; 557 break;
555 case Tok_Comment: 558 case Tok_Comment:
556 com = yyComment; 559 com = yyComment;
557 com = com.simplifyWhiteSpace(); 560 com = com.simplifyWhiteSpace();
558 if ( com.left(sizeof(MagicComment) - 1) == MagicComment ) { 561 if ( com.left(sizeof(MagicComment) - 1) == MagicComment ) {
559 com.remove( 0, sizeof(MagicComment) - 1 ); 562 com.remove( 0, sizeof(MagicComment) - 1 );
560 int k = com.find( ' ' ); 563 int k = com.find( ' ' );
561 if ( k == -1 ) { 564 if ( k == -1 ) {
562 context = com; 565 context = com;