summaryrefslogtreecommitdiffstats
path: root/python/pyqt/pylupdate3/fetchtr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'python/pyqt/pylupdate3/fetchtr.cpp')
-rw-r--r--python/pyqt/pylupdate3/fetchtr.cpp455
1 files changed, 455 insertions, 0 deletions
diff --git a/python/pyqt/pylupdate3/fetchtr.cpp b/python/pyqt/pylupdate3/fetchtr.cpp
new file mode 100644
index 00000000..609dbc18
--- /dev/null
+++ b/python/pyqt/pylupdate3/fetchtr.cpp
@@ -0,0 +1,455 @@
+/**********************************************************************
+** Copyright (C) 2002 Detlev Offenbach <detlev@die-offenbachs.de>
+**
+** This is a modified version of lupdate. The original is part of Qt-Linguist.
+** The copyright of the original file can be found below.
+**
+** This version is modified to handle python sources.
+**
+** The file is provided AS IS with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE.
+**
+**********************************************************************/
+
+
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** fetchtr.cpp
+**
+** This file is part of Qt Linguist.
+**
+** See the file LICENSE included in the distribution for the usage
+** and distribution terms.
+**
+** The file is provided AS IS with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE.
+**
+**********************************************************************/
+
+#include <qfile.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qtextstream.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <metatranslator.h>
+#include <stdio.h>
+#include <string.h>
+/*#include <qxml.h>*/
+
+
+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 python tokenizer. We skip
+ most of python; the only tokens that interest us are defined here.
+*/
+
+enum { Tok_Eof, Tok_class, Tok_return, Tok_tr,
+ Tok_trUtf8, Tok_translate, Tok_Ident,
+ Tok_Comment, Tok_Dot, Tok_String,
+ Tok_LeftParen, Tok_RightParen,
+ Tok_Comma};
+
+/*
+ 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 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 buf;
+
+static int (*getChar)();
+static int (*peekChar)();
+
+static int getCharFromFile()
+{
+ int c;
+
+ if ( buf < 0 )
+ c = getc( yyInFile );
+ else {
+ c = buf;
+ buf = -1;
+ }
+ if ( c == '\n' )
+ yyCurLineNo++;
+ return c;
+}
+
+static int peekCharFromFile()
+{
+ int c = getc( yyInFile );
+ buf = c;
+ return c;
+}
+
+static void startTokenizer( const char *fileName, int (*getCharFunc)(),
+ int (*peekCharFunc)() )
+{
+ yyInPos = 0;
+ buf = -1;
+ getChar = getCharFunc;
+ peekChar = peekCharFunc;
+
+ yyFileName = fileName;
+ yyCh = getChar();
+ 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, "T_TR_NOOP") == 0 ) {
+ return Tok_tr;
+ } else if ( strcmp(yyIdent + 1, "T_TRANSLATE_NOOP") == 0 ) {
+ return Tok_translate;
+ }
+ break;
+ case 'c':
+ if ( strcmp(yyIdent + 1, "lass") == 0 )
+ return Tok_class;
+ break;
+ case 'r':
+ if ( strcmp(yyIdent + 1, "eturn") == 0 )
+ return Tok_return;
+ break;
+ case 't':
+ if ( strcmp(yyIdent + 1, "r") == 0 )
+ return Tok_tr;
+ else if ( strcmp(yyIdent + 1, "rUtf8") == 0 )
+ return Tok_trUtf8;
+ else if ( strcmp(yyIdent + 1, "ranslate") == 0 )
+ return Tok_translate;
+ case '_':
+ if ( strcmp(yyIdent + 1, "_tr") == 0 )
+ return Tok_tr;
+ else if ( strcmp(yyIdent + 1, "_trUtf8") == 0 )
+ return Tok_trUtf8;
+ }
+ return Tok_Ident;
+ } else {
+ switch ( yyCh ) {
+ case '#':
+ yyCh = getChar();
+ do {
+ yyCh = getChar();
+ } while ( yyCh != EOF && yyCh != '\n' );
+ break;
+ case '"':
+ case '\'':
+ int quoteChar;
+ int trippelQuote, singleQuote;
+ int in;
+
+ quoteChar = yyCh;
+ trippelQuote = 0;
+ singleQuote = 1;
+ in = 0;
+ yyCh = getChar();
+
+ while ( yyCh != EOF ) {
+ if ( singleQuote && (yyCh == '\n' || (in && yyCh == quoteChar)) )
+ break;
+
+ if ( yyCh == quoteChar ) {
+ if (peekChar() == quoteChar) {
+ yyCh = getChar();
+ if (!trippelQuote) {
+ trippelQuote = 1;
+ singleQuote = 0;
+ in = 1;
+ yyCh = getChar();
+ } else {
+ yyCh = getChar();
+ if (yyCh == quoteChar) {
+ trippelQuote = 0;
+ break;
+ }
+ }
+ } else if (trippelQuote) {
+ if ( yyStringLen < sizeof(yyString) - 1 )
+ yyString[yyStringLen++] = (char) yyCh;
+ yyCh = getChar();
+ continue;
+ } else
+ break;
+ } else
+ in = 1;
+
+ if ( yyCh == '\\' ) {
+ yyCh = getChar();
+
+ 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 != quoteChar ) {
+ printf("%c\n", yyCh);
+ qWarning( "%s:%d: Unterminated string",
+ (const char *) yyFileName, yyLineNo );
+ }
+
+ if ( yyCh == EOF ) {
+ return Tok_Eof;
+ } else {
+ yyCh = getChar();
+ return Tok_String;
+ }
+ break;
+ 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_Dot;
+ 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();
+ }
+ *utf8 = QString( yyIdent ).endsWith( QString("UTF8") );
+ yyTok = getToken();
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static void parse( MetaTranslator *tor, const char *initialContext,
+ const char *defaultContext )
+{
+ QMap<QCString, QCString> qualifiedContexts;
+ QCString context;
+ QCString text;
+ QCString com;
+ QCString functionContext = initialContext;
+ QCString prefix;
+ bool utf8 = FALSE;
+
+ yyTok = getToken();
+ while ( yyTok != Tok_Eof ) {
+ switch ( yyTok ) {
+ case Tok_class:
+ yyTok = getToken();
+ functionContext = yyIdent;
+ yyTok = getToken();
+ break;
+ case Tok_tr:
+ case Tok_trUtf8:
+ utf8 = ( yyTok == Tok_trUtf8 );
+ yyTok = getToken();
+ if ( match(Tok_LeftParen) && matchString(&text) ) {
+ com = "";
+ if ( match(Tok_RightParen) || (match(Tok_Comma) &&
+ matchString(&com) && match(Tok_RightParen)) ) {
+ if ( prefix.isNull() ) {
+ context = defaultContext;
+ } else if ( qstrcmp(prefix, "self") == 0 ) {
+ context = functionContext;
+ } else {
+ context = prefix;
+ }
+ prefix = (const char *) 0;
+
+ if ( qualifiedContexts.contains(context) )
+ context = qualifiedContexts[context];
+ tor->insert( MetaTranslatorMessage(context, text, com,
+ QString::null, utf8) );
+ }
+ }
+ break;
+ case Tok_translate:
+ utf8 = FALSE;
+ yyTok = getToken();
+ if ( match(Tok_LeftParen) &&
+ matchString(&context) &&
+ match(Tok_Comma) &&
+ matchString(&text) ) {
+ com = "";
+ if ( match(Tok_RightParen) ||
+ (match(Tok_Comma) &&
+ matchString(&com) &&
+ (match(Tok_RightParen) ||
+ match(Tok_Comma) &&
+ matchEncoding(&utf8) &&
+ match(Tok_RightParen))) )
+ tor->insert( MetaTranslatorMessage(context, text, com,
+ QString::null, utf8) );
+ }
+ break;
+ case Tok_Ident:
+ if ( !prefix.isNull() )
+ prefix += ".";
+ prefix += yyIdent;
+ yyTok = getToken();
+ if ( yyTok != Tok_Dot )
+ prefix = (const char *) 0;
+ break;
+ case Tok_Comment:
+ com = yyComment;
+ com = com.simplifyWhiteSpace();
+ if ( com.left(sizeof(MagicComment) - 1) == MagicComment ) {
+ com.remove( 0, sizeof(MagicComment) - 1 );
+ int k = com.find( ' ' );
+ if ( k == -1 ) {
+ context = com;
+ } else {
+ context = com.left( k );
+ com.remove( 0, k + 1 );
+ tor->insert( MetaTranslatorMessage(context, "", com,
+ QString::null, FALSE) );
+ }
+ }
+ yyTok = getToken();
+ break;
+ default:
+ yyTok = getToken();
+ }
+ }
+
+ if ( yyParenDepth != 0 )
+ qWarning( "%s: Unbalanced parentheses in Python code",
+ (const char *) yyFileName );
+}
+
+void fetchtr_py( const char *fileName, MetaTranslator *tor,
+ const char *defaultContext, bool mustExist )
+{
+ yyInFile = fopen( fileName, "r" );
+ if ( yyInFile == 0 ) {
+ if ( mustExist )
+ qWarning( "pylupdate error: cannot open Python source file '%s': %s",
+ fileName, strerror(errno) );
+ return;
+ }
+
+ startTokenizer( fileName, getCharFromFile, peekCharFromFile );
+ parse( tor, 0, defaultContext );
+ fclose( yyInFile );
+}