static bool perl_kvs_cmd_begin(KviKvsModuleCommandCall * c) { // This command is somewhat special in the fact that has a dedicated // parsing routine in the KVS core parser. // The parser sets the perl code as the first parameter of our call, // the remaining params are the context name and the arguments QString szCode,szContext; KviKvsVariantList vList; KVSM_PARAMETERS_BEGIN(c) KVSM_PARAMETER("code",KVS_PT_STRING,0,szCode) KVSM_PARAMETER("context",KVS_PT_STRING,KVS_PF_OPTIONAL,szContext) KVSM_PARAMETER("args",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,vList) KVSM_PARAMETERS_END(c) KVS_CHECK_MODULE_STATE(m,c) #ifdef COMPILE_PERL_SUPPORT KviPerlCoreCtrlCommand_execute ex; ex.uSize = sizeof(KviPerlCoreCtrlCommand_execute); ex.pKvsContext = c->context(); ex.szContext = szContext; ex.szCode = szCode; for(KviKvsVariant * v = vList.first();v;v = vList.next()) { QString tmp; v->asString(tmp); ex.lArgs.append(tmp); } ex.bQuiet = c->switches()->find('q',"quiet"); if(!g_pPerlCoreModule->ctrl(KVI_PERLCORECTRLCOMMAND_EXECUTE,&ex)) { if(!c->switches()->find('q',"quiet")) c->warning(__tr2qs_ctx("The perlcore module failed to execute the code: something is wrong with the perl support","perl")); return true; } if(!ex.lWarnings.isEmpty()) { for(QStringList::Iterator it = ex.lWarnings.begin();it != ex.lWarnings.end();++it) c->warning(*it); } if(!ex.bExitOk) { if(!c->switches()->find('q',"quiet")) { if(c->switches()->find('f',"fail-on-error")) { c->warning(__tr2qs_ctx("Perl execution error:","perl")); c->warning(ex.szError); return false; } else { c->warning(__tr2qs_ctx("Perl execution error:","perl")); c->error(ex.szError); } } } if(!c->switches()->find('n',"no-return")) c->context()->returnValue()->setString(ex.szRetVal); #endif //COMPILE_PERL_SUPPORT return true; }
bool KviKvsTreeNodeSpecialCommandForeach::execute(KviKvsRunTimeContext * c) { KviKvsVariantList l; l.setAutoDelete(true); if(!m_pIterationData->evaluate(c,&l)) return false; KviKvsSwitchList swl; if(m_pSwitches) { if(!(m_pSwitches->evaluate(c,&swl))) return false; } bool bIncludeEmptyScalars = swl.find('a',"all") != 0; for(KviKvsVariant * pArg = l.first(); pArg; pArg = l.next()) { switch(pArg->type()) { case KviKvsVariantData::Array: { unsigned int uCnt = pArg->array()->size(); unsigned int idx = 0; while(idx < uCnt) { // we evaluate this each time (as it may actually be killed at each iteration) // FIXME: maybe some kind of reference counting or a observer pattern might be a bit more efficient here // (but might be far less efficient everywhere else...) KviKvsRWEvaluationResult * v = m_pIterationVariable->evaluateReadWrite(c); if(!v) return false; KviKvsVariant * pOne = pArg->array()->at(idx); if(pOne) { if(bIncludeEmptyScalars || (!pOne->isEmpty())) { v->result()->copyFrom(*pOne); } else { delete v; // we're done with it for this iteration idx++; continue; } } else { if(bIncludeEmptyScalars) { v->result()->setNothing(); } else { delete v; // we're done with it for this iteration idx++; continue; } } delete v; // we're done with it for this iteration if(!m_pLoop->execute(c)) { if(c->error()) return false; // break allowed! if(c->breakPending()) { c->handleBreak(); return true; } if(c->continuePending()) { c->handleContinue(); idx++; continue; } return false; // propagate the false return value } idx++; } } break; case KviKvsVariantData::Hash: { KviKvsHashIterator it(*(pArg->hash()->dict())); while(KviKvsVariant * pOne = it.current()) { // we evaluate this each time (as it may actually be killed at each iteration) // FIXME: maybe some kind of reference counting or a observer pattern might be a bit more efficient here // (but might be far less efficient everywhere else...) KviKvsRWEvaluationResult * v = m_pIterationVariable->evaluateReadWrite(c); if(!v) return false; if(bIncludeEmptyScalars || (!pOne->isEmpty())) { v->result()->copyFrom(*pOne); } else { delete v; // we're done with it for this iteration ++it; continue; } delete v; // we're done with it for this iteration if(!m_pLoop->execute(c)) { if(c->error()) return false; // break allowed! if(c->breakPending()) { c->handleBreak(); return true; } if(c->continuePending()) { c->handleContinue(); ++it; continue; } return false; // propagate the false return value } ++it; } } break; default: if(bIncludeEmptyScalars || (!pArg->isEqualToNothing())) { // we evaluate this each time (as it may actually be killed at each iteration) // FIXME: maybe some kind of reference counting or a observer pattern might be a bit more efficient here // (but might be far less efficient everywhere else...) KviKvsRWEvaluationResult * v = m_pIterationVariable->evaluateReadWrite(c); if(!v) return false; v->result()->copyFrom(*pArg); delete v; // we're done with it for this iteration if(!m_pLoop->execute(c)) { if(c->error()) return false; // break allowed! if(c->breakPending()) { c->handleBreak(); return true; } if(c->continuePending()) { c->handleContinue(); continue; } return false; // propagate the false return value } } break; } } return true; }
bool KviKvsTreeNodeSpecialCommandClass::execute(KviKvsRunTimeContext * c) { KviKvsVariantList l; if(!m_pParams->evaluate(c,&l))return false; KviKvsVariant * pClassName = l.first(); if(!pClassName) { c->error(this,__tr2qs_ctx("Missing class name","kvs")); return false; } KviKvsVariant * pBaseClassName = l.next(); QString szClassName; QString szBaseClassName; pClassName->asString(szClassName); QRegExp re("[\\w:]+"); if(!re.exactMatch(szClassName)) { c->error(this,__tr2qs_ctx("Class names can contain only letters, digits, underscores and '::' namespace separators","kvs")); return false; } if(pBaseClassName) pBaseClassName->asString(szBaseClassName); if(szClassName.isEmpty()) { c->error(this,__tr2qs_ctx("Missing class name","kvs")); return false; } if(szBaseClassName.isEmpty())szBaseClassName = "object"; // avoid infinite recursion in loading the base class if(KviQString::equalCI(szBaseClassName,szClassName)) { c->error(__tr2qs_ctx("A class can't be a subclass of itself","kvs")); return false; } KviKvsObjectClass * pBaseClass = KviKvsKernel::instance()->objectController()->lookupClass(szBaseClassName); if(!pBaseClass) { c->error(this,__tr2qs_ctx("Couln't find base class named '%Q'","kvs"),&szBaseClassName); return false; } // walk the inheritance tree of the base class in order to detect loops KviKvsObjectClass * pClass = pBaseClass; while(pClass) { if(KviQString::equalCI(pClass->name(),szClassName)) { c->error(this,__tr2qs_ctx("Detected a loop in the inheritance tree of the base class '%Q': redefine that class first","kvs"),&szBaseClassName); return false; } pClass = pClass->parentClass(); } KviKvsObjectClass * pActualClass = KviKvsKernel::instance()->objectController()->lookupClass(szClassName,true); if(pActualClass) { c->error(this,__tr2qs_ctx("Can't override the builtin class '%Q'","kvs"),&szClassName); return false; } pActualClass = new KviKvsObjectClass(pBaseClass,szClassName,0,false); for(KviKvsTreeNodeSpecialCommandClassFunctionDefinition * d = m_pFunctions->first();d;d = m_pFunctions->next()) { pActualClass->registerFunctionHandler(d->name(),d->buffer(),d->reminder(),d->handlerFlags()); } return true; }