moc: Move the property access code to the qt_static_metacall
That way we will be able to access property of objects that are not QObject (Q_GADGET) Change-Id: Ib8ef6e52fc621e0b0d6530f82b1aa205f1ed5fd9 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
d49e7acc2b
commit
4ed39bed4e
|
|
@ -1,6 +1,7 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
|
|
@ -2837,8 +2838,13 @@ QVariant QMetaProperty::read(const QObject *object) const
|
|||
// Try to register the type and try again before reporting an error.
|
||||
int registerResult = -1;
|
||||
void *argv[] = { ®isterResult };
|
||||
QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::RegisterPropertyMetaType,
|
||||
idx + mobj->propertyOffset(), argv);
|
||||
if ((priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall) && mobj->d.static_metacall) {
|
||||
mobj->d.static_metacall(const_cast<QObject*>(object), QMetaObject::RegisterPropertyMetaType,
|
||||
idx, argv);
|
||||
} else {
|
||||
QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::RegisterPropertyMetaType,
|
||||
idx + mobj->propertyOffset(), argv);
|
||||
}
|
||||
if (registerResult == -1) {
|
||||
qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name());
|
||||
return QVariant();
|
||||
|
|
@ -2861,8 +2867,12 @@ QVariant QMetaProperty::read(const QObject *object) const
|
|||
value = QVariant(t, (void*)0);
|
||||
argv[0] = value.data();
|
||||
}
|
||||
QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty,
|
||||
idx + mobj->propertyOffset(), argv);
|
||||
if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall) {
|
||||
mobj->d.static_metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty, idx, argv);
|
||||
} else {
|
||||
QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty,
|
||||
idx + mobj->propertyOffset(), argv);
|
||||
}
|
||||
|
||||
if (status != -1)
|
||||
return value;
|
||||
|
|
@ -2932,7 +2942,11 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const
|
|||
argv[0] = &v;
|
||||
else
|
||||
argv[0] = v.data();
|
||||
QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
|
||||
if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall)
|
||||
mobj->d.static_metacall(object, QMetaObject::WriteProperty, idx, argv);
|
||||
else
|
||||
QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -2949,7 +2963,10 @@ bool QMetaProperty::reset(QObject *object) const
|
|||
if (!object || !mobj || !isResettable())
|
||||
return false;
|
||||
void *argv[] = { 0 };
|
||||
QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
|
||||
if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall)
|
||||
mobj->d.static_metacall(object, QMetaObject::ResetProperty, idx, argv);
|
||||
else
|
||||
QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
|
|
@ -98,7 +99,8 @@ enum MethodFlags {
|
|||
|
||||
enum MetaObjectFlags {
|
||||
DynamicMetaObject = 0x01,
|
||||
RequiresVariantMetaObject = 0x02
|
||||
RequiresVariantMetaObject = 0x02,
|
||||
PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall
|
||||
};
|
||||
|
||||
enum MetaDataFlags {
|
||||
|
|
|
|||
|
|
@ -359,7 +359,13 @@ void Generator::generateCode()
|
|||
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
|
||||
isConstructible ? index : 0);
|
||||
|
||||
fprintf(out, " %4d, // flags\n", 0);
|
||||
int flags = 0;
|
||||
if (cdef->hasQGadget) {
|
||||
// Ideally, all the classes could have that flag. But this broke classes generated
|
||||
// by qdbusxml2cpp which generate code that require that we call qt_metacall for properties
|
||||
flags |= PropertyAccessInStaticMetaCall;
|
||||
}
|
||||
fprintf(out, " %4d, // flags\n", flags);
|
||||
fprintf(out, " %4d, // signalCount\n", cdef->signalList.count());
|
||||
|
||||
|
||||
|
|
@ -425,7 +431,8 @@ void Generator::generateCode()
|
|||
//
|
||||
// Generate internal qt_static_metacall() function
|
||||
//
|
||||
const bool hasStaticMetaCall = (cdef->hasQObject || !cdef->methodList.isEmpty()) && !isQt;
|
||||
const bool hasStaticMetaCall = !isQt &&
|
||||
(cdef->hasQObject || !cdef->methodList.isEmpty() || !cdef->propertyList.isEmpty());
|
||||
if (hasStaticMetaCall)
|
||||
generateStaticMetacall();
|
||||
|
||||
|
|
@ -920,10 +927,6 @@ void Generator::generateMetacall()
|
|||
}
|
||||
|
||||
if (cdef->propertyList.size()) {
|
||||
bool needGet = false;
|
||||
bool needTempVarForGet = false;
|
||||
bool needSet = false;
|
||||
bool needReset = false;
|
||||
bool needDesignable = false;
|
||||
bool needScriptable = false;
|
||||
bool needStored = false;
|
||||
|
|
@ -931,132 +934,21 @@ void Generator::generateMetacall()
|
|||
bool needUser = false;
|
||||
for (int i = 0; i < cdef->propertyList.size(); ++i) {
|
||||
const PropertyDef &p = cdef->propertyList.at(i);
|
||||
needGet |= !p.read.isEmpty() || !p.member.isEmpty();
|
||||
if (!p.read.isEmpty() || !p.member.isEmpty())
|
||||
needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec
|
||||
&& p.gspec != PropertyDef::ReferenceSpec);
|
||||
|
||||
needSet |= !p.write.isEmpty() || (!p.member.isEmpty() && !p.constant);
|
||||
needReset |= !p.reset.isEmpty();
|
||||
needDesignable |= p.designable.endsWith(')');
|
||||
needScriptable |= p.scriptable.endsWith(')');
|
||||
needStored |= p.stored.endsWith(')');
|
||||
needEditable |= p.editable.endsWith(')');
|
||||
needUser |= p.user.endsWith(')');
|
||||
}
|
||||
fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
|
||||
|
||||
fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
|
||||
if (needElse)
|
||||
fprintf(out, " else ");
|
||||
fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
|
||||
if (needGet) {
|
||||
if (needTempVarForGet)
|
||||
fprintf(out, " void *_v = _a[0];\n");
|
||||
fprintf(out, " switch (_id) {\n");
|
||||
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
|
||||
const PropertyDef &p = cdef->propertyList.at(propindex);
|
||||
if (p.read.isEmpty() && p.member.isEmpty())
|
||||
continue;
|
||||
QByteArray prefix;
|
||||
if (p.inPrivateClass.size()) {
|
||||
prefix = p.inPrivateClass;
|
||||
prefix.append("->");
|
||||
}
|
||||
if (p.gspec == PropertyDef::PointerSpec)
|
||||
fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s%s())); break;\n",
|
||||
propindex, prefix.constData(), p.read.constData());
|
||||
else if (p.gspec == PropertyDef::ReferenceSpec)
|
||||
fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s%s())); break;\n",
|
||||
propindex, prefix.constData(), p.read.constData());
|
||||
else if (cdef->enumDeclarations.value(p.type, false))
|
||||
fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
|
||||
propindex, prefix.constData(), p.read.constData());
|
||||
else if (!p.read.isEmpty())
|
||||
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
|
||||
propindex, p.type.constData(), prefix.constData(), p.read.constData());
|
||||
else
|
||||
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n",
|
||||
propindex, p.type.constData(), prefix.constData(), p.member.constData());
|
||||
}
|
||||
fprintf(out, " default: break;\n");
|
||||
fprintf(out, " }\n");
|
||||
}
|
||||
|
||||
fprintf(out, "else ");
|
||||
fprintf(out,
|
||||
" _id -= %d;\n"
|
||||
" }", cdef->propertyList.count());
|
||||
|
||||
fprintf(out, " else ");
|
||||
fprintf(out, "if (_c == QMetaObject::WriteProperty) {\n");
|
||||
|
||||
if (needSet) {
|
||||
fprintf(out, " void *_v = _a[0];\n");
|
||||
fprintf(out, " switch (_id) {\n");
|
||||
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
|
||||
const PropertyDef &p = cdef->propertyList.at(propindex);
|
||||
if (p.constant)
|
||||
continue;
|
||||
if (p.write.isEmpty() && p.member.isEmpty())
|
||||
continue;
|
||||
QByteArray prefix;
|
||||
if (p.inPrivateClass.size()) {
|
||||
prefix = p.inPrivateClass;
|
||||
prefix.append("->");
|
||||
}
|
||||
if (cdef->enumDeclarations.value(p.type, false)) {
|
||||
fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
|
||||
propindex, prefix.constData(), p.write.constData());
|
||||
} else if (!p.write.isEmpty()) {
|
||||
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
|
||||
propindex, prefix.constData(), p.write.constData(), p.type.constData());
|
||||
} else {
|
||||
fprintf(out, " case %d:\n", propindex);
|
||||
fprintf(out, " if (%s%s != *reinterpret_cast< %s*>(_v)) {\n",
|
||||
prefix.constData(), p.member.constData(), p.type.constData());
|
||||
fprintf(out, " %s%s = *reinterpret_cast< %s*>(_v);\n",
|
||||
prefix.constData(), p.member.constData(), p.type.constData());
|
||||
if (!p.notify.isEmpty() && p.notifyId != -1) {
|
||||
const FunctionDef &f = cdef->signalList.at(p.notifyId);
|
||||
if (f.arguments.size() == 0)
|
||||
fprintf(out, " Q_EMIT %s();\n", p.notify.constData());
|
||||
else if (f.arguments.size() == 1 && f.arguments.at(0).normalizedType == p.type)
|
||||
fprintf(out, " Q_EMIT %s(%s%s);\n",
|
||||
p.notify.constData(), prefix.constData(), p.member.constData());
|
||||
}
|
||||
fprintf(out, " }\n");
|
||||
fprintf(out, " break;\n");
|
||||
}
|
||||
}
|
||||
fprintf(out, " default: break;\n");
|
||||
fprintf(out, " }\n");
|
||||
}
|
||||
|
||||
fprintf(out,
|
||||
" _id -= %d;\n"
|
||||
" }", cdef->propertyList.count());
|
||||
|
||||
fprintf(out, " else ");
|
||||
fprintf(out, "if (_c == QMetaObject::ResetProperty) {\n");
|
||||
if (needReset) {
|
||||
fprintf(out, " switch (_id) {\n");
|
||||
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
|
||||
const PropertyDef &p = cdef->propertyList.at(propindex);
|
||||
if (!p.reset.endsWith(')'))
|
||||
continue;
|
||||
QByteArray prefix;
|
||||
if (p.inPrivateClass.size()) {
|
||||
prefix = p.inPrivateClass;
|
||||
prefix.append("->");
|
||||
}
|
||||
fprintf(out, " case %d: %s%s; break;\n",
|
||||
propindex, prefix.constData(), p.reset.constData());
|
||||
}
|
||||
fprintf(out, " default: break;\n");
|
||||
fprintf(out, " }\n");
|
||||
}
|
||||
fprintf(out,
|
||||
" _id -= %d;\n"
|
||||
" }", cdef->propertyList.count());
|
||||
"if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty\n"
|
||||
" || _c == QMetaObject::ResetProperty || _c == QMetaObject::RegisterPropertyMetaType) {\n"
|
||||
" qt_static_metacall(this, _c, _id, _a);\n"
|
||||
" _id -= %d;\n }", cdef->propertyList.count());
|
||||
|
||||
fprintf(out, " else ");
|
||||
fprintf(out, "if (_c == QMetaObject::QueryPropertyDesignable) {\n");
|
||||
|
|
@ -1154,16 +1046,6 @@ void Generator::generateMetacall()
|
|||
" _id -= %d;\n"
|
||||
" }", cdef->propertyList.count());
|
||||
|
||||
fprintf(out, " else ");
|
||||
fprintf(out, "if (_c == QMetaObject::RegisterPropertyMetaType) {\n");
|
||||
fprintf(out, " if (_id < %d)\n", cdef->propertyList.size());
|
||||
|
||||
if (automaticPropertyMetaTypesHelper().isEmpty())
|
||||
fprintf(out, " *reinterpret_cast<int*>(_a[0]) = -1;\n");
|
||||
else
|
||||
fprintf(out, " qt_static_metacall(this, _c, _id, _a);\n");
|
||||
fprintf(out, " _id -= %d;\n }", cdef->propertyList.size());
|
||||
|
||||
fprintf(out, "\n#endif // QT_NO_PROPERTIES");
|
||||
}
|
||||
if (methodList.size() || cdef->signalList.size() || cdef->propertyList.size())
|
||||
|
|
@ -1382,6 +1264,153 @@ void Generator::generateStaticMetacall()
|
|||
needElse = true;
|
||||
}
|
||||
|
||||
if (!cdef->propertyList.empty()) {
|
||||
bool needGet = false;
|
||||
bool needTempVarForGet = false;
|
||||
bool needSet = false;
|
||||
bool needReset = false;
|
||||
for (int i = 0; i < cdef->propertyList.size(); ++i) {
|
||||
const PropertyDef &p = cdef->propertyList.at(i);
|
||||
needGet |= !p.read.isEmpty() || !p.member.isEmpty();
|
||||
if (!p.read.isEmpty() || !p.member.isEmpty())
|
||||
needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec
|
||||
&& p.gspec != PropertyDef::ReferenceSpec);
|
||||
|
||||
needSet |= !p.write.isEmpty() || (!p.member.isEmpty() && !p.constant);
|
||||
needReset |= !p.reset.isEmpty();
|
||||
}
|
||||
fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
|
||||
|
||||
if (needElse)
|
||||
fprintf(out, "else ");
|
||||
fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
|
||||
if (needGet) {
|
||||
if (cdef->hasQObject) {
|
||||
#ifndef QT_NO_DEBUG
|
||||
fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
|
||||
#endif
|
||||
fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
|
||||
} else {
|
||||
fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
|
||||
}
|
||||
if (needTempVarForGet)
|
||||
fprintf(out, " void *_v = _a[0];\n");
|
||||
fprintf(out, " switch (_id) {\n");
|
||||
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
|
||||
const PropertyDef &p = cdef->propertyList.at(propindex);
|
||||
if (p.read.isEmpty() && p.member.isEmpty())
|
||||
continue;
|
||||
QByteArray prefix = "_t->";
|
||||
if (p.inPrivateClass.size()) {
|
||||
prefix += p.inPrivateClass + "->";
|
||||
}
|
||||
if (p.gspec == PropertyDef::PointerSpec)
|
||||
fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s%s())); break;\n",
|
||||
propindex, prefix.constData(), p.read.constData());
|
||||
else if (p.gspec == PropertyDef::ReferenceSpec)
|
||||
fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s%s())); break;\n",
|
||||
propindex, prefix.constData(), p.read.constData());
|
||||
else if (cdef->enumDeclarations.value(p.type, false))
|
||||
fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
|
||||
propindex, prefix.constData(), p.read.constData());
|
||||
else if (!p.read.isEmpty())
|
||||
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
|
||||
propindex, p.type.constData(), prefix.constData(), p.read.constData());
|
||||
else
|
||||
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n",
|
||||
propindex, p.type.constData(), prefix.constData(), p.member.constData());
|
||||
}
|
||||
fprintf(out, " default: break;\n");
|
||||
fprintf(out, " }\n");
|
||||
}
|
||||
|
||||
fprintf(out, " }");
|
||||
|
||||
fprintf(out, " else ");
|
||||
fprintf(out, "if (_c == QMetaObject::WriteProperty) {\n");
|
||||
|
||||
if (needSet) {
|
||||
if (cdef->hasQObject) {
|
||||
#ifndef QT_NO_DEBUG
|
||||
fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
|
||||
#endif
|
||||
fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
|
||||
} else {
|
||||
fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
|
||||
}
|
||||
fprintf(out, " void *_v = _a[0];\n");
|
||||
fprintf(out, " switch (_id) {\n");
|
||||
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
|
||||
const PropertyDef &p = cdef->propertyList.at(propindex);
|
||||
if (p.constant)
|
||||
continue;
|
||||
if (p.write.isEmpty() && p.member.isEmpty())
|
||||
continue;
|
||||
QByteArray prefix = "_t->";
|
||||
if (p.inPrivateClass.size()) {
|
||||
prefix += p.inPrivateClass + "->";
|
||||
}
|
||||
if (cdef->enumDeclarations.value(p.type, false)) {
|
||||
fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
|
||||
propindex, prefix.constData(), p.write.constData());
|
||||
} else if (!p.write.isEmpty()) {
|
||||
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
|
||||
propindex, prefix.constData(), p.write.constData(), p.type.constData());
|
||||
} else {
|
||||
fprintf(out, " case %d:\n", propindex);
|
||||
fprintf(out, " if (%s%s != *reinterpret_cast< %s*>(_v)) {\n",
|
||||
prefix.constData(), p.member.constData(), p.type.constData());
|
||||
fprintf(out, " %s%s = *reinterpret_cast< %s*>(_v);\n",
|
||||
prefix.constData(), p.member.constData(), p.type.constData());
|
||||
if (!p.notify.isEmpty() && p.notifyId != -1) {
|
||||
const FunctionDef &f = cdef->signalList.at(p.notifyId);
|
||||
if (f.arguments.size() == 0)
|
||||
fprintf(out, " Q_EMIT _t->%s();\n", p.notify.constData());
|
||||
else if (f.arguments.size() == 1 && f.arguments.at(0).normalizedType == p.type)
|
||||
fprintf(out, " Q_EMIT _t->%s(%s%s);\n",
|
||||
p.notify.constData(), prefix.constData(), p.member.constData());
|
||||
}
|
||||
fprintf(out, " }\n");
|
||||
fprintf(out, " break;\n");
|
||||
}
|
||||
}
|
||||
fprintf(out, " default: break;\n");
|
||||
fprintf(out, " }\n");
|
||||
}
|
||||
|
||||
fprintf(out, " }");
|
||||
|
||||
fprintf(out, " else ");
|
||||
fprintf(out, "if (_c == QMetaObject::ResetProperty) {\n");
|
||||
if (needReset) {
|
||||
if (cdef->hasQObject) {
|
||||
#ifndef QT_NO_DEBUG
|
||||
fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
|
||||
#endif
|
||||
fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
|
||||
} else {
|
||||
fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
|
||||
}
|
||||
fprintf(out, " switch (_id) {\n");
|
||||
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
|
||||
const PropertyDef &p = cdef->propertyList.at(propindex);
|
||||
if (!p.reset.endsWith(')'))
|
||||
continue;
|
||||
QByteArray prefix = "_t->";
|
||||
if (p.inPrivateClass.size()) {
|
||||
prefix += p.inPrivateClass + "->";
|
||||
}
|
||||
fprintf(out, " case %d: %s%s; break;\n",
|
||||
propindex, prefix.constData(), p.reset.constData());
|
||||
}
|
||||
fprintf(out, " default: break;\n");
|
||||
fprintf(out, " }\n");
|
||||
}
|
||||
fprintf(out, " }");
|
||||
fprintf(out, "\n#endif // QT_NO_PROPERTIES");
|
||||
needElse = true;
|
||||
}
|
||||
|
||||
if (needElse)
|
||||
fprintf(out, "\n");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue