bool KviKvsTreeNodeSpecialCommandWhile::execute(KviKvsRunTimeContext * c)
{
	for(;;)
	{
		KviKvsVariant v;
		if(!m_pExpression->evaluateReadOnly(c, &v))
			return false;

		if(!v.asBoolean())
			break;

		if(m_pInstruction)
		{
			if(!m_pInstruction->execute(c))
			{
				if(c->error())
					return false;

				if(c->breakPending())
				{
					c->handleBreak();
					return true;
				}

				if(c->continuePending())
				{
					c->handleContinue();
					continue;
				}
				return false;
			}
		}
	}
	return true;
}
bool KviKvsTreeNodeSpecialCommandFor::execute(KviKvsRunTimeContext * c)
{
	if(m_pInitialization)
	{
		if(!m_pInitialization->execute(c))
		{
			// break allowed also here
			if(c->error())
				return false;

			if(c->breakPending())
			{
				c->handleBreak();
				return true;
			}

			return false; // propagate false ret value
		}
	}

	for(;;)
	{
		if(m_pCondition)
		{
			KviKvsVariant v;
			if(!m_pCondition->evaluateReadOnly(c, &v))
				return false;
			if(!v.asBoolean())
				return true;
		}

		if(m_pLoop)
		{
			if(!m_pLoop->execute(c))
			{
				if(c->error())
					return false;

				if(c->breakPending())
				{
					c->handleBreak();
					return true;
				}

				if(c->continuePending())
					c->handleContinue();
				else
					return false; // propagate false ret value
			}
		}

		if(m_pUpdate)
		{
			if(!m_pUpdate->execute(c))
			{
				// break allowed also here
				if(c->error())
					return false;

				if(c->breakPending())
				{
					c->handleBreak();
					return true;
				}

				if(c->continuePending())
					c->handleContinue();

				return false; // propagate false ret value
			}
		}
	}
	// not reached
	return false;
}
	bool process(KviKvsVariantList * pVariantList, KviKvsRunTimeContext * pContext, KviKvsParameterProcessor::ParameterFormat * pFmtArray)
	{
		KviKvsVariant * v = pVariantList->first();

		while(pFmtArray->szName)
		{
			if(!v)
			{
				// parameter not present
				// it MUST be optional
				if(!(pFmtArray->uFlags & KVS_PF_OPTIONAL))
				{
					// bad luck
					QString szError = QString(__tr2qs_ctx("Missing non-optional parameter \"%1\"", "kvs")).arg(pFmtArray->szName);
					pContext->error(szError);
					return false;
				}
				// ok, missing but optional (all the following are implicitly optional too)
				// set to default values
				do
				{
					setDefaultValue(pFmtArray);
					pFmtArray++;
				} while(pFmtArray->szName);
				return true;
			}
			// here we do only "light" casts: hard ones must be done explicitly by the user
			switch(pFmtArray->uType)
			{
				case KVS_PT_STRING:
					v->asString(*((QString *)(pFmtArray->pContainer)));
					if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
					{
						v = pVariantList->next();
						while(v)
						{
							*((QString *)(pFmtArray->pContainer)) += QChar(' ');
							v->appendAsString(*((QString *)(pFmtArray->pContainer)));
							v = pVariantList->next();
						}
						return true;
					}
					break;
				case KVS_PT_STRINGLIST:
				{
					((QStringList *)(pFmtArray->pContainer))->clear();
					QString pSz;
					v->asString(pSz);
					((QStringList *)(pFmtArray->pContainer))->append(pSz);
					v = pVariantList->next();
					while(v)
					{
						v->asString(pSz);
						((QStringList *)(pFmtArray->pContainer))->append(pSz);
						v = pVariantList->next();
					}
					return true;
				}
				break;
				case KVS_PT_VARIANTLIST:
				{
					((KviKvsVariantList *)(pFmtArray->pContainer))->clear();
					((KviKvsVariantList *)(pFmtArray->pContainer))->setAutoDelete(false);
					((KviKvsVariantList *)(pFmtArray->pContainer))->append(v);
					v = pVariantList->next();
					while(v)
					{
						((KviKvsVariantList *)(pFmtArray->pContainer))->append(v);
						v = pVariantList->next();
					}
					return true;
				}
				break;
				case KVS_PT_NONEMPTYSTRING:
				{
					v->asString(*((QString *)(pFmtArray->pContainer)));
					bool bDoReturn = false;
					if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
					{
						v = pVariantList->next();
						while(v)
						{
							*((QString *)(pFmtArray->pContainer)) += QChar(' ');
							v->appendAsString(*((QString *)(pFmtArray->pContainer)));
							v = pVariantList->next();
						}
						bDoReturn = true;
					}
					if(((QString *)(pFmtArray->pContainer))->isEmpty())
					{
						QString szError = QString(__tr2qs_ctx("Invalid data type for parameter \"%1\": found empty string while a non empty one was expected", "kvs")).arg(pFmtArray->szName);
						pContext->error(szError);
						return false;
					}
					if(bDoReturn)
						return true;
				}
				break;
				case KVS_PT_CSTRING:
				{
					QString tmp;
					v->asString(tmp);
					if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
					{
						v = pVariantList->next();
						while(v)
						{
							*((QByteArray *)(pFmtArray->pContainer)) += ' ';
							v->appendAsString(tmp);
							v = pVariantList->next();
						}
						*((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8();
						return true;
					}
					*((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8();
				}
				break;
				case KVS_PT_NONEMPTYCSTRING:
				{
					QString tmp;
					v->asString(tmp);
					bool bDoReturn = false;
					if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
					{
						v = pVariantList->next();
						while(v)
						{
							*((QByteArray *)(pFmtArray->pContainer)) += ' ';
							v->appendAsString(tmp);
							v = pVariantList->next();
						}
						*((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8();
						bDoReturn = true;
					}
					*((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8();
					if(((QByteArray *)(pFmtArray->pContainer))->isEmpty())
					{
						QString szError = QString(__tr2qs_ctx("Invalid data type for parameter \"%1\": found empty string while a non empty one was expected", "kvs")).arg(pFmtArray->szName);
						pContext->error(szError);
						return false;
					}
					if(bDoReturn)
						return true;
				}
				break;
				case KVS_PT_INT:
					if(!v->asInteger(*((kvs_int_t *)(pFmtArray->pContainer))))
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "integer"))
							return false;
					}
					break;
				case KVS_PT_UINT:
				{
					kvs_int_t iTmp;
					if(!v->asInteger(iTmp))
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "unsigned integer"))
							return false;
					}
					if(iTmp < 0)
					{
						QString szError = QString(__tr2qs_ctx("Invalid data type for parameter \"%1\": found signed integer \"%2\" where type 'unsigned integer' was expected", "kvs")).arg(pFmtArray->szName).arg(iTmp);
						pContext->error(szError);
						return false;
					}
					*((kvs_uint_t *)(pFmtArray->pContainer)) = (kvs_uint_t)iTmp;
				}
				break;
				case KVS_PT_DOUBLE:
					if(!v->asReal(*((kvs_real_t *)(pFmtArray->pContainer))))
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "real"))
							return false;
					}
					break;
				case KVS_PT_HASH:
					if(!v->isHash())
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "hash"))
							return false;
					}
					else
					{
						*((KviKvsHash **)(pFmtArray->pContainer)) = v->hash();
					}
					break;
				case KVS_PT_ARRAYCAST:
					v->castToArray((KviKvsArrayCast *)(pFmtArray->pContainer));
					break;
				case KVS_PT_ARRAY:
					if(!v->isArray())
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "array"))
							return false;
					}
					else
					{
						*((KviKvsArray **)(pFmtArray->pContainer)) = v->array();
					}
					break;
				case KVS_PT_BOOL:
					// this never fails: anything is converted to a boolean
					*((bool *)(pFmtArray->pContainer)) = v->asBoolean();
					break;
				case KVS_PT_VARIANT:
					*((KviKvsVariant **)(pFmtArray->pContainer)) = v;
					break;
				case KVS_PT_HOBJECT:
					if(!v->asHObject(*((kvs_hobject_t *)(pFmtArray->pContainer))))
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "hobject"))
							return false;
					}
					break;
				case KVS_PT_IGNORE:
					// ignore
					break;
				default:
					qDebug("Internal error in KviKvsParameterProcessor::processAsParameters(): unknown parameter type %d", pFmtArray->uType);
					return false;
					break;
			}
			pFmtArray++;
			v = pVariantList->next();
		}
		return true;
	}