int classad_evaluate_boolean_expr(const char *s_in, const classad_expr_tree t_ex, int *result) { ClassAd *ad; ClassAdParser parser; if (s_in == NULL || t_ex == NULL || result == NULL) return C_CLASSAD_INVALID_ARG; ExprTree *et = (ExprTree *)t_ex; ad = parser.ParseClassAd(s_in); if (ad == NULL) return C_CLASSAD_PARSE_ERROR; int retcod = C_CLASSAD_NO_ERROR; Value v; et->SetParentScope(ad); ad->EvaluateExpr(et, v); et->SetParentScope(NULL); bool tmp_res; if (v.IsBooleanValue( tmp_res )) { if (tmp_res) *result = 1; else *result = 0; retcod = C_CLASSAD_NO_ERROR; } else retcod = C_CLASSAD_INVALID_VALUE; delete ad; return retcod; }
bool Metric::evaluate(char const *attr_name,classad::Value &result,classad::ClassAd &metric_ad,classad::ClassAd const &daemon_ad,MetricTypeEnum type,ExtArray<MyString> *regex_groups,char const *regex_attr) { bool retval = true; ExprTree *expr = NULL; if( !(expr=metric_ad.Lookup(attr_name)) ) { return true; } classad::ClassAd const *ad = &daemon_ad; ClassAd daemon_ad_copy; if( regex_attr ) { // make a modifiable copy of daemon_ad and insert regex_attr = regex_attr, so the user-defined expression can refer to it daemon_ad_copy = daemon_ad; ad = &daemon_ad_copy; daemon_ad_copy.AssignExpr(ATTR_REGEX,regex_attr); } expr->SetParentScope(ad); if( !ad->EvaluateExpr(expr,result) || (type == STRING && !result.IsStringValue()) || (type == DOUBLE && !result.IsNumber()) || (type == FLOAT && !result.IsNumber()) || (type == INT8 && !result.IsIntegerValue()) || (type == UINT8 && !result.IsIntegerValue()) || (type == INT16 && !result.IsIntegerValue()) || (type == UINT16 && !result.IsIntegerValue()) || (type == INT32 && !result.IsIntegerValue()) || (type == UINT32 && !result.IsIntegerValue()) || (type == BOOLEAN && !result.IsBooleanValue()) ) { retval = false; classad::ClassAdUnParser unparser; std::string expr_str; unparser.Unparse(expr_str,expr); dprintf(D_FULLDEBUG,"Failed to evaluate the following%s%s: %s=%s\n", name.empty() ? "" : " attribute of metric ", name.c_str(), attr_name, expr_str.c_str()); } expr->SetParentScope(&metric_ad); // do regex macro substitutions if( regex_groups && regex_groups->length() > 0 ) { std::string str_value; if( result.IsStringValue(str_value) && str_value.find("\\")!=std::string::npos ) { std::string new_str_value; const char *ch = str_value.c_str(); while( *ch ) { if( *ch == '\\' ) { ch++; if( !isdigit(*ch) ) { new_str_value += *(ch++); } else { char *endptr = NULL; long index = strtol(ch,&endptr,10); ch = endptr; if( index < regex_groups->length() ) { new_str_value += (*regex_groups)[index]; } } } else { new_str_value += *(ch++); } } result.SetStringValue(new_str_value); } } return retval; }
/********************************************************************* * * Function: process_evaluate * Purpose: Given a line that begins with "evaluate", parse the rest * of the line and perform the evaluation. * *********************************************************************/ static void process_evaluate(const string &line, int token_start, int line_number, const Parameters ¶meters, ErrorCount *errors) { string classad_name, expression_string; ExprTree *expr; ClassAdParser parser; classad_name = extract_token(&token_start, line); expr = NULL; if ((unsigned) token_start < line.size()) { expression_string = line.substr(token_start, line.size() - token_start); } else { expression_string = ""; } if (!classad_name.compare("") || !expression_string.compare("")) { cout << "Error: Missing evaluate information on line " << line_number << "." << endl; cout << " Format: evaluate <classad> <expression>" << endl; errors->IncrementErrors(); } else { if (!parser.ParseExpression(expression_string, expr)) { cout << "Error: Can't parse expression (" << expression_string << ") on line " << line_number << "." << endl; errors->IncrementErrors(); } else { ClassAd *classad = classads[classad_name]; if (classad == NULL) { cout << "Error: Unknown ClassAd: \"" << classad_name << "\" on line " << line_number << "." << endl; errors->IncrementErrors(); } else { Value value; expr->SetParentScope(classad); if (!classad->EvaluateExpr(expr, value)) { cout << "Error: Can't evaluate expression (" << expression_string << ") on line " <<line_number << "." << endl; errors->IncrementErrors(); } else { PrettyPrint unparser; string value_string; unparser.Unparse(value_string, value); cout << "OK: Evaluating \"" << expression_string << "\" in " << classad_name << " evaluates to " << value_string << " on line " << line_number << endl; } } } } if (expr != NULL) { delete expr; } return; }