bool ExprTree:: Flatten( Value& val, ExprTree *&tree ) const { EvalState state; state.SetScopes( parentScope ); return( Flatten( state, val, tree ) ); }
bool ExprTree:: Evaluate( Value& val, ExprTree*& sig ) const { EvalState state; state.SetScopes( parentScope ); return( Evaluate( state, val, sig ) ); }
int classad_get_string_list_attribute (classad_context cad, const char *attribute_name, char ***result) { if (cad == NULL) return C_CLASSAD_INVALID_CONTEXT; int n_results = 0; (*result) = (char **)malloc(sizeof(char **)); if ((*result) == NULL) return C_CLASSAD_OUT_OF_MEMORY; (*result)[0] = NULL; ClassAd *ad = (ClassAd *)cad; Value vl; ad->EvaluateAttr(attribute_name, vl); const ExprList *et_result; if (vl.IsListValue(et_result)) { std::vector<ExprTree*> ads; et_result->GetComponents(ads); // Get string values. for(std::vector<ExprTree*>::const_iterator it = ads.begin(); it != ads.end(); ++it) { if ((*it)->GetKind() == ExprTree::LITERAL_NODE) { Value v; EvalState state; state.SetScopes( ad ); (*it)->Evaluate(state,v); std::string res_str; if (v.IsStringValue( res_str )) { // add string value to result, which is a NULL-terminated // string array. n_results++; (*result) = (char **)realloc(*result, (n_results+1)*sizeof(char *)); if ((*result) == NULL) return C_CLASSAD_OUT_OF_MEMORY; (*result)[n_results-1] = strdup(res_str.c_str()); (*result)[n_results] = NULL; } } } return C_CLASSAD_NO_ERROR; } // The result list needs to be freed on success only. classad_free_string_list(*result); (*result) = NULL; return C_CLASSAD_VALUE_NOT_FOUND; }
bool ExprTree:: Evaluate( Value& val ) const { EvalState state; if (parentScope == NULL) { val.SetErrorValue(); return false; } else { state.SetScopes( parentScope ); return( Evaluate( state, val ) ); } }
int unwind_attributes(classad_context cad, char *attribute_name, char ***results) { if (cad == NULL) return C_CLASSAD_INVALID_CONTEXT; if ((results == NULL) || (attribute_name == NULL)) return C_CLASSAD_INVALID_ARG; ClassAd *ad = (ClassAd *)cad; ExprTree *et; bool need_to_delete_et = false; et = ad->Lookup(attribute_name); if (et == NULL) { return C_CLASSAD_VALUE_NOT_FOUND; } if (et->GetKind() == ExprTree::LITERAL_NODE) { // The attribute was probably stringified. Try to parse it. Value v; EvalState state; state.SetScopes( ad ); et->Evaluate(state,v); std::string strres; if (v.IsStringValue( strres )) { ClassAdParser parser; et=NULL; parser.ParseExpression(strres,et); need_to_delete_et = true; } } BinaryOpUnwind res_unp; std::string result; res_unp.Unparse(result, et); int n_results; if (*results == NULL) { n_results = 0; (*results) = (char **)malloc(sizeof(char **)); if ((*results) == NULL) return C_CLASSAD_OUT_OF_MEMORY; (*results)[0] = NULL; } else { for (n_results = 0; (*results)[n_results] != NULL; n_results++) /*NOP*/ ; } std::vector<std::string>::const_iterator it; for (it = res_unp.m_unwind_output.begin(); it != res_unp.m_unwind_output.end(); ++it) { n_results++; char **new_results; new_results = (char **)realloc(*results, (n_results+1)*sizeof(char *)); if (new_results == NULL) { if (need_to_delete_et) delete et; return C_CLASSAD_OUT_OF_MEMORY; } (*results) = new_results; (*results)[n_results] = NULL; (*results)[n_results-1] = strdup(it->c_str()); if (((*results)[n_results-1]) == NULL) { if (need_to_delete_et) delete et; return C_CLASSAD_OUT_OF_MEMORY; } } if (need_to_delete_et) delete et; return C_CLASSAD_NO_ERROR; }
int AttributeReference:: FindExpr(EvalState &state, ExprTree *&tree, ExprTree *&sig, bool wantSig) const { const ClassAd *current=NULL; const ExprList *adList = NULL; Value val; bool rval; sig = NULL; // establish starting point for search if( expr == NULL ) { // "attr" and ".attr" current = absolute ? state.rootAd : state.curAd; if( absolute && ( current == NULL ) ) { // NAC - circularity so no root return EVAL_FAIL; // NAC } // NAC } else { // "expr.attr" rval=wantSig?expr->Evaluate(state,val,sig):expr->Evaluate(state,val); if( !rval ) { return( EVAL_FAIL ); } if( val.IsUndefinedValue( ) ) { return( EVAL_UNDEF ); } else if( val.IsErrorValue( ) ) { return( EVAL_ERROR ); } if( !val.IsClassAdValue( current ) && !val.IsListValue( adList ) ) { return( EVAL_ERROR ); } } if( val.IsListValue( ) ) { vector< ExprTree *> eVector; const ExprTree *currExpr; // iterate through exprList and apply attribute reference // to each exprTree for(ExprListIterator itr(adList);!itr.IsAfterLast( );itr.NextExpr( )){ currExpr = itr.CurrentExpr( ); if( currExpr == NULL ) { return( EVAL_FAIL ); } else { AttributeReference *attrRef = NULL; attrRef = MakeAttributeReference( currExpr->Copy( ), attributeStr, false ); val.Clear( ); // Create new EvalState, within this scope, because // attrRef is only temporary, so we do not want to // cache the evaluated result in the outer state object. EvalState tstate; tstate.SetScopes(state.curAd); rval = wantSig ? attrRef->Evaluate( tstate, val, sig ) : attrRef->Evaluate( tstate, val ); delete attrRef; if( !rval ) { return( EVAL_FAIL ); } ClassAd *evaledAd = NULL; const ExprList *evaledList = NULL; if( val.IsClassAdValue( evaledAd ) ) { eVector.push_back( evaledAd ); continue; } else if( val.IsListValue( evaledList ) ) { eVector.push_back( evaledList->Copy( ) ); continue; } else { eVector.push_back( Literal::MakeLiteral( val ) ); } } } tree = ExprList::MakeExprList( eVector ); ClassAd *newRoot = new ClassAd( ); ((ExprList*)tree)->SetParentScope( newRoot ); return EVAL_OK; } // lookup with scope; this may side-affect state /* ClassAd::alternateScope is intended for transitioning Condor from * old to new ClassAds. It allows unscoped attribute references * in expressions that can't be found in the local scope to be * looked for in an alternate scope. In Condor, the alternate * scope is the Target ad in matchmaking. * Expect alternateScope to be removed from a future release. */ if (!current) { return EVAL_UNDEF; } int rc = current->LookupInScope( attributeStr, tree, state ); if ( !expr && !absolute && rc == EVAL_UNDEF && current->alternateScope ) { rc = current->alternateScope->LookupInScope( attributeStr, tree, state ); } return rc; }