author | zecke <zecke> | 2003-08-31 19:06:45 (UTC) |
---|---|---|
committer | zecke <zecke> | 2003-08-31 19:06:45 (UTC) |
commit | 2696413e75a401899764f244c8c24026999fdb9d (patch) (unidiff) | |
tree | 630522a33052ea7d337bc76f624be0d7e142ff04 /development | |
parent | ce4a99860d28e003871994cca88a82133c1921a7 (diff) | |
download | opie-2696413e75a401899764f244c8c24026999fdb9d.zip opie-2696413e75a401899764f244c8c24026999fdb9d.tar.gz opie-2696413e75a401899764f244c8c24026999fdb9d.tar.bz2 |
recognize i18n as well
-rw-r--r-- | development/translation/opie-lupdate/fetchtr.cpp | 3 |
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 | ||
37 | static const char MagicComment[] = "TRANSLATOR "; | 37 | static const char MagicComment[] = "TRANSLATOR "; |
38 | 38 | ||
39 | static QMap<QCString, int> needs_Q_OBJECT; | 39 | static QMap<QCString, int> needs_Q_OBJECT; |
40 | static QMap<QCString, int> lacks_Q_OBJECT; | 40 | static 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 | ||
64 | enum { Tok_Eof, Tok_class, Tok_namespace, Tok_return, Tok_tr, | 64 | enum { 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 | */ |
74 | static QCString yyFileName; | 74 | static QCString yyFileName; |
75 | static int yyCh; | 75 | static int yyCh; |
76 | static char yyIdent[128]; | 76 | static char yyIdent[128]; |
77 | static size_t yyIdentLen; | 77 | static size_t yyIdentLen; |
78 | static char yyComment[65536]; | 78 | static char yyComment[65536]; |
79 | static size_t yyCommentLen; | 79 | static size_t yyCommentLen; |
80 | static char yyString[16384]; | 80 | static char yyString[16384]; |
81 | static size_t yyStringLen; | 81 | static size_t yyStringLen; |
82 | static QValueStack<int> yySavedBraceDepth; | 82 | static QValueStack<int> yySavedBraceDepth; |
83 | static int yyBraceDepth; | 83 | static int yyBraceDepth; |
84 | static int yyParenDepth; | 84 | static int yyParenDepth; |
85 | static int yyLineNo; | 85 | static int yyLineNo; |
86 | static int yyCurLineNo; | 86 | static 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) |
89 | static FILE *yyInFile; | 89 | static 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) |
92 | static QString yyInStr; | 92 | static QString yyInStr; |
93 | static int yyInPos; | 93 | static int yyInPos; |
94 | 94 | ||
95 | static int (*getChar)(); | 95 | static int (*getChar)(); |
96 | 96 | ||
97 | static int getCharFromFile() | 97 | static 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 | ||
105 | static int getCharFromString() | 105 | static 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 | ||
114 | static void startTokenizer( const char *fileName, int (*getCharFunc)() ) | 114 | static 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 | ||
127 | static int getToken() | 127 | static 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 | ||
395 | static int yyTok; | 398 | static int yyTok; |
396 | 399 | ||
397 | static bool match( int t ) | 400 | static 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 | ||
405 | static bool matchString( QCString *s ) | 408 | static 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 | ||
416 | static bool matchEncoding( bool *utf8 ) | 419 | static 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 | ||
432 | static void parse( MetaTranslator *tor, const char *initialContext, | 435 | static 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; |