static void parse( MetaTranslator *tor, const char *initialContext, const char *defaultContext ) { QMap<QCString, QCString> qualifiedContexts; QStringList namespaces; QCString context; QCString text; QCString com; QCString functionContext = initialContext; QCString prefix; bool utf8 = FALSE; bool missing_Q_OBJECT = FALSE; yyTok = getToken(); while ( yyTok != Tok_Eof ) { switch ( yyTok ) { case Tok_class: /* Partial support for inlined functions. */ yyTok = getToken(); if ( yyBraceDepth == (int) namespaces.count() && yyParenDepth == 0 ) { do { /* This code should execute only once, but we play safe with impure definitions such as 'class Q_EXPORT QMessageBox', in which case 'QMessageBox' is the class name, not 'Q_EXPORT'. */ functionContext = yyIdent; yyTok = getToken(); } while ( yyTok == Tok_Ident ); while ( yyTok == Tok_Gulbrandsen ) { yyTok = getToken(); functionContext += "::"; functionContext += yyIdent; yyTok = getToken(); } if ( yyTok == Tok_Colon ) { missing_Q_OBJECT = TRUE; } else { functionContext = defaultContext; } } break; case Tok_namespace: yyTok = getToken(); if ( yyTok == Tok_Ident ) { QCString ns = yyIdent; yyTok = getToken(); if ( yyTok == Tok_LeftBrace && yyBraceDepth == (int) namespaces.count() + 1 ) namespaces.append( QString(ns) ); } 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 = functionContext; if ( !namespaces.isEmpty() ) context.prepend( (namespaces.join(QString("::")) + QString("::")).latin1() ); } else { context = prefix; } prefix = (const char *) 0; if ( qualifiedContexts.contains(context) ) context = qualifiedContexts[context]; tor->insert( MetaTranslatorMessage(context, text, com, QString::null, utf8) ); if ( lacks_Q_OBJECT.contains(context) ) { qWarning( "%s:%d: Class '%s' lacks Q_OBJECT macro", (const char *) yyFileName, yyLineNo, (const char *) context ); lacks_Q_OBJECT.remove( context ); } else { needs_Q_OBJECT.insert( context, 0 ); } } } 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_Q_OBJECT: missing_Q_OBJECT = FALSE; yyTok = getToken(); break; case Tok_Ident: if ( !prefix.isNull() ) prefix += "::"; prefix += yyIdent; yyTok = getToken(); if ( yyTok != Tok_Gulbrandsen ) 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) ); } /* Provide a backdoor for people using "using namespace". See the manual for details. */ k = 0; while ( (k = context.find("::", k)) != -1 ) { qualifiedContexts.insert( context.mid(k + 2), context ); k++; } } yyTok = getToken(); break; case Tok_Arrow: yyTok = getToken(); if ( yyTok == Tok_tr || yyTok == Tok_trUtf8 ) qWarning( "%s:%d: Cannot invoke tr() like this", (const char *) yyFileName, yyLineNo ); break; case Tok_Gulbrandsen: // at top level? if ( yyBraceDepth == (int) namespaces.count() && yyParenDepth == 0 ) functionContext = prefix; yyTok = getToken(); break; case Tok_RightBrace: case Tok_Semicolon: if ( yyBraceDepth >= 0 && yyBraceDepth + 1 == (int) namespaces.count() ) namespaces.remove( namespaces.fromLast() ); if ( yyBraceDepth == (int) namespaces.count() ) { if ( missing_Q_OBJECT ) { if ( needs_Q_OBJECT.contains(functionContext) ) { qWarning( "%s:%d: Class '%s' lacks Q_OBJECT macro", (const char *) yyFileName, yyLineNo, (const char *) functionContext ); } else { lacks_Q_OBJECT.insert( functionContext, 0 ); } } functionContext = defaultContext; missing_Q_OBJECT = FALSE; } yyTok = getToken(); break; default: yyTok = getToken(); } } if ( yyBraceDepth != 0 ) fprintf( stderr, "%s:%d: Unbalanced braces in C++ code (or abuse of the C++" " preprocessor)\n", (const char *)yyFileName, yyBraceLineNo ); else if ( yyParenDepth != 0 ) fprintf( stderr, "%s:%d: Unbalanced parentheses in C++ code (or abuse of the C++" " preprocessor)\n", (const char *)yyFileName, yyParenLineNo ); }
static void parse( MetaTranslator *tor, const char *initialContext, const char *defaultContext ) { QMap<QByteArray, QByteArray> qualifiedContexts; QByteArray context; QByteArray text; QByteArray com; QByteArray functionContext = initialContext; QByteArray 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 || (yyCodecForTr && strcmp(yyCodecForTr->name(), "UTF-8") == 0)); yyTok = getToken(); if (match(Tok_LeftParen) && matchString(&text)) { com = ""; bool plural = false; if (match(Tok_RightParen)) { // There is no comment or plural arguments. } else if (match(Tok_Comma) && matchStringOrNone(&com)) { // There is a comment argument. if (match(Tok_RightParen)) { // There is no plural argument. } else if (match(Tok_Comma)) { // There is a plural argument. plural = true; } } 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]; if (!text.isEmpty()) { tor->insert(MetaTranslatorMessage(context, text, com, yyFileName, yyParenLineNo, QStringList(), utf8, MetaTranslatorMessage::Unfinished, plural)); } } break; case Tok_translate: utf8 = false; yyTok = getToken(); if ( match(Tok_LeftParen) && matchString(&context) && match(Tok_Comma) && matchString(&text) ) { com = ""; bool plural = false; if (!match(Tok_RightParen)) { // look for comment if ( match(Tok_Comma) && matchStringOrNone(&com)) { if (!match(Tok_RightParen)) { // look for encoding if (match(Tok_Comma)) { if (matchEncoding(&utf8)) { if (!match(Tok_RightParen)) { // look for the plural quantifier, // this can be a number, an identifier or a function call, // so for simplicity we mark it as plural if we know we have a comma instead of an // right parentheses. plural = match(Tok_Comma); } } else { // This can be a QTranslator::translate("context", "source", "comment", n) plural translation if (matchExpression() && match(Tok_RightParen)) { plural = true; } else { break; } } } else { break; } } } else { break; } } if (!text.isEmpty()) { tor->insert( MetaTranslatorMessage(context, text, com, yyFileName, yyParenLineNo, QStringList(), utf8, MetaTranslatorMessage::Unfinished, plural) ); } } 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.simplified(); if ( com.left(sizeof(MagicComment) - 1) == MagicComment ) { com.remove( 0, sizeof(MagicComment) - 1 ); int k = com.indexOf( ' ' ); if ( k == -1 ) { context = com; } else { context = com.left( k ); com.remove( 0, k + 1 ); tor->insert( MetaTranslatorMessage(context, "", com, yyFileName, yyParenLineNo, QStringList(), false) ); } } yyTok = getToken(); break; default: yyTok = getToken(); } } if ( yyParenDepth != 0 ) qWarning( "%s: Unbalanced parentheses in Python code", (const char *) yyFileName ); }