summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (show 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,434 +1,437 @@
/**********************************************************************
** Copyright (C) 2000 Trolltech AS. All rights reserved.
**
** This file is part of Qt Linguist.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include <metatranslator.h>
#include <qfile.h>
#include <qregexp.h>
#include <qstring.h>
#include <qtextstream.h>
#include <qvaluestack.h>
#include <qxml.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
/* qmake ignore Q_OBJECT */
static const char MagicComment[] = "TRANSLATOR ";
static QMap<QCString, int> needs_Q_OBJECT;
static QMap<QCString, int> lacks_Q_OBJECT;
/*
The first part of this source file is the C++ tokenizer. We skip
most of C++; the only tokens that interest us are defined here.
Thus, the code fragment
int main()
{
printf( "Hello, world!\n" );
return 0;
}
is broken down into the following tokens (Tok_ omitted):
Ident Ident LeftParen RightParen
LeftBrace
Ident LeftParen String RightParen Semicolon
return Semicolon
RightBrace.
The 0 doesn't produce any token.
*/
enum { Tok_Eof, Tok_class, Tok_namespace, Tok_return, Tok_tr,
Tok_trUtf8, Tok_translate, Tok_Q_OBJECT, Tok_Ident,
Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon,
Tok_Gulbrandsen, Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen,
Tok_RightParen, Tok_Comma, Tok_Semicolon };
/*
The tokenizer maintains the following global variables. The names
should be self-explanatory.
*/
static QCString yyFileName;
static int yyCh;
static char yyIdent[128];
static size_t yyIdentLen;
static char yyComment[65536];
static size_t yyCommentLen;
static char yyString[16384];
static size_t yyStringLen;
static QValueStack<int> yySavedBraceDepth;
static int yyBraceDepth;
static int yyParenDepth;
static int yyLineNo;
static int yyCurLineNo;
// the file to read from (if reading from a file)
static FILE *yyInFile;
// the string to read from and current position in the string (otherwise)
static QString yyInStr;
static int yyInPos;
static int (*getChar)();
static int getCharFromFile()
{
int c = getc( yyInFile );
if ( c == '\n' )
yyCurLineNo++;
return c;
}
static int getCharFromString()
{
if ( yyInPos == (int) yyInStr.length() ) {
return EOF;
} else {
return yyInStr[yyInPos++].latin1();
}
}
static void startTokenizer( const char *fileName, int (*getCharFunc)() )
{
yyInPos = 0;
getChar = getCharFunc;
yyFileName = fileName;
yyCh = getChar();
yySavedBraceDepth.clear();
yyBraceDepth = 0;
yyParenDepth = 0;
yyCurLineNo = 1;
}
static int getToken()
{
const char tab[] = "abfnrtv";
const char backTab[] = "\a\b\f\n\r\t\v";
uint n;
yyIdentLen = 0;
yyCommentLen = 0;
yyStringLen = 0;
while ( yyCh != EOF ) {
yyLineNo = yyCurLineNo;
if ( isalpha(yyCh) || yyCh == '_' ) {
do {
if ( yyIdentLen < sizeof(yyIdent) - 1 )
yyIdent[yyIdentLen++] = (char) yyCh;
yyCh = getChar();
} while ( isalnum(yyCh) || yyCh == '_' );
yyIdent[yyIdentLen] = '\0';
switch ( yyIdent[0] ) {
case 'Q':
if ( strcmp(yyIdent + 1, "_OBJECT") == 0 ) {
return Tok_Q_OBJECT;
} else if ( strcmp(yyIdent + 1, "T_TR_NOOP") == 0 ) {
return Tok_tr;
} else if ( strcmp(yyIdent + 1, "T_TRANSLATE_NOOP") == 0 ) {
return Tok_translate;
}
break;
case 'T':
// TR() for when all else fails
if ( qstricmp(yyIdent + 1, "R") == 0 )
return Tok_tr;
break;
case 'c':
if ( strcmp(yyIdent + 1, "lass") == 0 )
return Tok_class;
break;
case 'n':
if ( strcmp(yyIdent + 1, "amespace") == 0 )
return Tok_namespace;
break;
case 'r':
if ( strcmp(yyIdent + 1, "eturn") == 0 )
return Tok_return;
break;
case 's':
if ( strcmp(yyIdent + 1, "truct") == 0 )
return Tok_class;
break;
+ case 'i':
+ if( strcmp(yyIdent + 1, "18n") == 0 )
+ return Tok_tr;
case 't':
if ( strcmp(yyIdent + 1, "r") == 0 ) {
return Tok_tr;
} else if ( qstrcmp(yyIdent + 1, "rUtf8") == 0 ) {
return Tok_trUtf8;
} else if ( qstrcmp(yyIdent + 1, "ranslate") == 0 ) {
return Tok_translate;
}
}
return Tok_Ident;
} else {
switch ( yyCh ) {
case '#':
/*
Early versions of lupdate complained about
unbalanced braces in the following code:
#ifdef ALPHA
while ( beta ) {
#else
while ( gamma ) {
#endif
delta;
}
The code contains, indeed, two opening braces for
one closing brace; yet there's no reason to panic.
The solution is to remember yyBraceDepth as it was
when #if, #ifdef or #ifndef was met, and to set
yyBraceDepth to that value when meeting #elif or
#else.
*/
do {
yyCh = getChar();
} while ( isspace(yyCh) && yyCh != '\n' );
switch ( yyCh ) {
case 'i':
yyCh = getChar();
if ( yyCh == 'f' ) {
// if, ifdef, ifndef
yySavedBraceDepth.push( yyBraceDepth );
}
break;
case 'e':
yyCh = getChar();
if ( yyCh == 'l' ) {
// elif, else
if ( !yySavedBraceDepth.isEmpty() )
yyBraceDepth = yySavedBraceDepth.top();
} else if ( yyCh == 'n' ) {
// endif
if ( !yySavedBraceDepth.isEmpty() )
yySavedBraceDepth.pop();
}
}
while ( isalnum(yyCh) || yyCh == '_' )
yyCh = getChar();
break;
case '/':
yyCh = getChar();
if ( yyCh == '/' ) {
do {
yyCh = getChar();
} while ( yyCh != EOF && yyCh != '\n' );
} else if ( yyCh == '*' ) {
bool metAster = FALSE;
bool metAsterSlash = FALSE;
while ( !metAsterSlash ) {
yyCh = getChar();
if ( yyCh == EOF ) {
fprintf( stderr,
"%s: Unterminated C++ comment starting at"
" line %d\n",
(const char *) yyFileName, yyLineNo );
yyComment[yyCommentLen] = '\0';
return Tok_Comment;
}
if ( yyCommentLen < sizeof(yyComment) - 1 )
yyComment[yyCommentLen++] = (char) yyCh;
if ( yyCh == '*' )
metAster = TRUE;
else if ( metAster && yyCh == '/' )
metAsterSlash = TRUE;
else
metAster = FALSE;
}
yyCh = getChar();
yyCommentLen -= 2;
yyComment[yyCommentLen] = '\0';
return Tok_Comment;
}
break;
case '"':
yyCh = getChar();
while ( yyCh != EOF && yyCh != '\n' && yyCh != '"' ) {
if ( yyCh == '\\' ) {
yyCh = getChar();
if ( yyCh == '\n' ) {
yyCh = getChar();
} else if ( yyCh == 'x' ) {
QCString hex = "0";
yyCh = getChar();
while ( isxdigit(yyCh) ) {
hex += (char) yyCh;
yyCh = getChar();
}
sscanf( hex, "%x", &n );
if ( yyStringLen < sizeof(yyString) - 1 )
yyString[yyStringLen++] = (char) n;
} else if ( yyCh >= '0' && yyCh < '8' ) {
QCString oct = "";
do {
oct += (char) yyCh;
yyCh = getChar();
} while ( yyCh >= '0' && yyCh < '8' );
sscanf( oct, "%o", &n );
if ( yyStringLen < sizeof(yyString) - 1 )
yyString[yyStringLen++] = (char) n;
} else {
const char *p = strchr( tab, yyCh );
if ( yyStringLen < sizeof(yyString) - 1 )
yyString[yyStringLen++] = ( p == 0 ) ?
(char) yyCh : backTab[p - tab];
yyCh = getChar();
}
} else {
if ( yyStringLen < sizeof(yyString) - 1 )
yyString[yyStringLen++] = (char) yyCh;
yyCh = getChar();
}
}
yyString[yyStringLen] = '\0';
if ( yyCh != '"' )
qWarning( "%s:%d: Unterminated C++ string",
(const char *) yyFileName, yyLineNo );
if ( yyCh == EOF ) {
return Tok_Eof;
} else {
yyCh = getChar();
return Tok_String;
}
break;
case '-':
yyCh = getChar();
if ( yyCh == '>' ) {
yyCh = getChar();
return Tok_Arrow;
}
break;
case ':':
yyCh = getChar();
if ( yyCh == ':' ) {
yyCh = getChar();
return Tok_Gulbrandsen;
}
return Tok_Colon;
case '\'':
yyCh = getChar();
if ( yyCh == '\\' )
yyCh = getChar();
do {
yyCh = getChar();
} while ( yyCh != EOF && yyCh != '\'' );
yyCh = getChar();
break;
case '{':
yyBraceDepth++;
yyCh = getChar();
return Tok_LeftBrace;
case '}':
yyBraceDepth--;
yyCh = getChar();
return Tok_RightBrace;
case '(':
yyParenDepth++;
yyCh = getChar();
return Tok_LeftParen;
case ')':
yyParenDepth--;
yyCh = getChar();
return Tok_RightParen;
case ',':
yyCh = getChar();
return Tok_Comma;
case ';':
yyCh = getChar();
return Tok_Semicolon;
default:
yyCh = getChar();
}
}
}
return Tok_Eof;
}
/*
The second part of this source file is the parser. It accomplishes
a very easy task: It finds all strings inside a tr() or translate()
call, and possibly finds out the context of the call. It supports
three cases: (1) the context is specified, as in
FunnyDialog::tr("Hello") or translate("FunnyDialog", "Hello");
(2) the call appears within an inlined function; (3) the call
appears within a function defined outside the class definition.
*/
static int yyTok;
static bool match( int t )
{
bool matches = ( yyTok == t );
if ( matches )
yyTok = getToken();
return matches;
}
static bool matchString( QCString *s )
{
bool matches = ( yyTok == Tok_String );
*s = "";
while ( yyTok == Tok_String ) {
*s += yyString;
yyTok = getToken();
}
return matches;
}
static bool matchEncoding( bool *utf8 )
{
if ( yyTok == Tok_Ident ) {
if ( strcmp(yyIdent, "QApplication") == 0 ) {
yyTok = getToken();
if ( yyTok == Tok_Gulbrandsen )
yyTok = getToken();
}
*utf8 = QString( yyIdent ).endsWith( QString("UTF8") );
yyTok = getToken();
return TRUE;
} else {
return FALSE;
}
}
static void parse( MetaTranslator *tor, const char *initialContext,
const char *defaultContext )
{