📄 moc.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the tools applications of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "moc.h"#include "generator.h"#include "qdatetime.h"#include "utils.h"#include "outputrevision.h"#include <stdio.h>#include <stdlib.h>// WARNING: a copy of this function is in qmetaobject.cppstatic QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixScope = false, bool adjustConst = true){ int len = e - t; /* Convert 'char const *' into 'const char *'. Start at index 1, not 0, because 'const char *' is already OK. */ QByteArray constbuf; for (int i = 1; i < len; i++) { if ( t[i] == 'c' && strncmp(t + i + 1, "onst", 4) == 0 && (i + 5 >= len || !is_ident_char(t[i + 5])) && !is_ident_char(t[i-1]) ) { constbuf = QByteArray(t, len); if (is_space(t[i-1])) constbuf.remove(i-1, 6); else constbuf.remove(i, 5); constbuf.prepend("const "); t = constbuf.data(); e = constbuf.data() + constbuf.length(); break; } /* We musn't convert 'char * const *' into 'const char **' and we must beware of 'Bar<const Bla>'. */ if (t[i] == '&' || t[i] == '*' ||t[i] == '<') break; } if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) { if (*(e-1) == '&') { // treat const reference as value t += 6; --e; } else if (is_ident_char(*(e-1))) { // treat const value as value t += 6; } } QByteArray result; result.reserve(len); // some type substitutions for 'unsigned x' if (strncmp("unsigned ", t, 9) == 0) { if (strncmp("int", t+9, 3) == 0) { t += 9+3; result += "uint"; } else if (strncmp("long", t+9, 4) == 0 // preserve '[unsigned] long int' && (strlen(t + 9 + 4) < 4 || strncmp(t + 9 + 4, " int", 4) != 0 ) // preserve '[unsigned] long long' && (strlen(t + 9 + 4) < 5 || strncmp(t + 9 + 4, " long", 5) != 0 ) ) { t += 9+4; result += "ulong"; } } while (t != e) { char c = *t++; if (fixScope && c == ':' && *t == ':' ) { ++t; c = *t++; int i = result.size() - 1; while (i >= 0 && is_ident_char(result.at(i))) --i; result.resize(i + 1); } result += c; if (c == '<') { //template recursion const char* tt = t; int templdepth = 1; while (t != e) { c = *t++; if (c == '<') ++templdepth; if (c == '>') --templdepth; if (templdepth == 0) { result += normalizeTypeInternal(tt, t-1, fixScope, false); result += c; if (*t == '>') result += ' '; // avoid >> break; } } } } return result;}// only moc needs this functionQByteArray normalizeType(const char *s, bool fixScope){ int len = qstrlen(s); char stackbuf[64]; char *buf = (len >= 64 ? new char[len + 1] : stackbuf); char *d = buf; char last = 0; while(*s && is_space(*s)) s++; while (*s) { while (*s && !is_space(*s)) last = *d++ = *s++; while (*s && is_space(*s)) s++; if (*s && is_ident_char(*s) && is_ident_char(last)) last = *d++ = ' '; } *d = '\0'; QByteArray result; if (strncmp("void", buf, d - buf) != 0) result = normalizeTypeInternal(buf, d, fixScope); if (buf != stackbuf) delete [] buf; return result;}static const char *error_msg = 0;#ifdef Q_CC_MSVC#define ErrorFormatString "%s(%d): "#else#define ErrorFormatString "%s:%d: "#endifvoid Moc::error(int rollback) { index -= rollback; error();}void Moc::error(const char *msg) { if (msg || error_msg) qWarning(ErrorFormatString "Error: %s", currentFilenames.top().constData(), symbol().lineNum, msg?msg:error_msg); else qWarning(ErrorFormatString "Parse error at \"%s\"", currentFilenames.top().constData(), symbol().lineNum, symbol().lexem().data()); exit(EXIT_FAILURE);}void Moc::warning(const char *msg) { if (displayWarnings && msg) fprintf(stderr, ErrorFormatString "Warning: %s\n", filename.constData(), qMax(0, symbol().lineNum), msg);}bool Moc::until(Token target) { int braceCount = 0; int brackCount = 0; int parenCount = 0; int angleCount = 0; if (index) { switch(symbols.at(index-1).token) { case LBRACE: ++braceCount; break; case LBRACK: ++brackCount; break; case LPAREN: ++parenCount; break; case LANGLE: ++angleCount; break; default: ; } } while (index < symbols.size()) { Token t = symbols.at(index++).token; switch (t) { case LBRACE: ++braceCount; break; case RBRACE: --braceCount; break; case LBRACK: ++brackCount; break; case RBRACK: --brackCount; break; case LPAREN: ++parenCount; break; case RPAREN: --parenCount; break; case LANGLE: ++angleCount; break; case RANGLE: --angleCount; break; default: break; } if (t == target && braceCount <= 0 && brackCount <= 0 && parenCount <= 0 && (target != RANGLE || angleCount <= 0)) return true; if (braceCount < 0 || brackCount < 0 || parenCount < 0 || (target == RANGLE && angleCount < 0)) { --index; break; } } return false;}QByteArray Moc::lexemUntil(Token target){ int from = index; until(target); QByteArray s; while (from <= index) { QByteArray n = symbols.at(from++-1).lexem(); if (s.size() && n.size() && is_ident_char(s.at(s.size()-1)) && is_ident_char(n.at(0))) s += ' '; s += n; } return s;}bool Moc::parseClassHead(ClassDef *def){ // figure out whether this is a class declaration, or only a // forward or variable declaration. int i = 0; Token token; do { token = lookup(i++); if (token == COLON || token == LBRACE) break; if (token == SEMIC || token == RANGLE) return false; } while (token); next(IDENTIFIER); QByteArray name = lexem(); // support "class IDENT name" and "class IDENT(IDENT) name" if (test(LPAREN)) { until(RPAREN); next(IDENTIFIER); name = lexem(); } else if (test(IDENTIFIER)) { name = lexem(); } def->qualified += name; while (test(SCOPE)) { def->qualified += lexem(); if (test(IDENTIFIER)) { name = lexem(); def->qualified += name; } } def->classname = name; if (test(COLON)) { do { test(VIRTUAL); FunctionDef::Access access = FunctionDef::Public; if (test(PRIVATE)) access = FunctionDef::Private; else if (test(PROTECTED)) access = FunctionDef::Protected; else test(PUBLIC); test(VIRTUAL); const QByteArray type = parseType().name; // ignore the 'class Foo : BAR(Baz)' case if (test(LPAREN)) { until(RPAREN); } else { def->superclassList += qMakePair(type, access); } } while (test(COMMA)); } next(LBRACE); def->begin = index - 1; until(RBRACE); def->end = index ; index = def->begin + 1; return true;}Type Moc::parseType(){ Type type; bool hasSignedOrUnsigned = false; bool isVoid = false; for (;;) { switch (next()) { case SIGNED: case UNSIGNED: hasSignedOrUnsigned = true; // fall through case CONST: case VOLATILE: type.name += lexem(); type.name += ' '; if (lookup(0) == VOLATILE) type.isVolatile = true; continue; default: prev(); break; } break; } test(ENUM) || test(CLASS) || test(STRUCT); for(;;) { switch (next()) { case IDENTIFIER: // void mySlot(unsigned myArg) if (hasSignedOrUnsigned) { prev(); break; } case CHAR: case SHORT: case INT: case LONG: type.name += lexem(); // preserve '[unsigned] long long', 'short int', 'long int', 'long double' if (test(LONG) || test(INT) || test(DOUBLE)) { type.name += ' '; prev(); continue; } break; case FLOAT: case DOUBLE: case VOID: case BOOL: type.name += lexem(); isVoid |= (lookup(0) == VOID); break; default: prev(); ; } if (test(LANGLE)) { QByteArray templ = lexemUntil(RANGLE); for (int i = 0; i < templ.size(); ++i) { type.name += templ.at(i); if (templ.at(i) == '>' && i < templ.size()-1 && templ.at(i+1) == '>') type.name += ' '; } } if (test(SCOPE)) { type.name += lexem(); type.isScoped = true; } else { break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -