}
);
unpack_rsc_location(xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr node_list,		    GListPtr *node_constraints){/*  <constraints>     <rsc_location rsc="Filesystem-whatever-1" timestamp="..." lifetime="...">     	<rule score="+50.0" result="can"><!ATTLIST node_expression	  id         CDATA #REQUIRED	  attribute  CDATA #REQUIRED	  operation  (lt|gt|lte|gte|eq|ne|exists|notexists)	  value      CDATA #IMPLIED	  type	     (integer|string|version)    'string'>	</rule>     	<rule score="+500.0">       		<node_expression match="cpu:50GHz" />	</rule>     	<rule result="cannot">       		<node_expression not_match="san"/>	</rule>...   Translation:   Further translation:       */	xmlNodePtr rules    = xml_obj->children;	const char *id_lh   = xmlGetProp(xml_obj, "rsc");	const char *id      = xmlGetProp(xml_obj, XML_ATTR_ID);	resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh);	if(rsc_lh == NULL) {		crm_err("No resource (con=%s, rsc=%s)",		       id, id_lh);		return FALSE;	}				if(rules == NULL) {		crm_err("no rules for constraint %s", id);	}		while(rules != NULL) {		gboolean first_expr = TRUE;		gboolean   can_run  = FALSE;		gboolean   do_and   = TRUE;		xmlNodePtr rule     = rules;		xmlNodePtr expr     = rule->children;		const char *rule_id = xmlGetProp(rule, XML_ATTR_ID);		const char *score   = xmlGetProp(rule, "score");		const char *result  = xmlGetProp(rule, "result");		const char *boolean = xmlGetProp(rule, "boolean_op");		GListPtr match_L    = NULL;		GListPtr old_list   = NULL;		float score_f       = atof(score?score:"0.0");		rsc_to_node_t *new_con = NULL;		if(safe_str_eq(boolean, "or")) {			do_and = FALSE;		}		rules = rules->next;		if(result == NULL || (safe_str_eq(result, "can"))) {			can_run = TRUE;		}		new_con = rsc2node_new(rule_id, rsc_lh, score_f,				       can_run, NULL, node_constraints);		if(new_con == NULL) {			crm_err("couldnt create constraint %s", rule_id);			continue;		}				/* feels like a hack */		if(expr == NULL && can_run) {			new_con->node_list_rh = node_list_dup(node_list,FALSE);		}				while(expr != NULL) {			const char *attr  = xmlGetProp(expr, "attribute");			const char *op    = xmlGetProp(expr, "operation");			const char *value = xmlGetProp(expr, "value");			const char *type  = xmlGetProp(expr, "type");			crm_trace("processing expression: %s", xmlGetProp(expr, "id"));			expr = expr->next;			match_L = match_attrs(				attr, op, value, type, node_list);						if(first_expr) {				new_con->node_list_rh =	node_list_dup(					match_L, FALSE);				first_expr = FALSE;				continue;			}			old_list = new_con->node_list_rh;			if(do_and) {				crm_trace("do_and");								new_con->node_list_rh = node_list_and(					old_list, match_L, FALSE);			} else {				crm_trace("do_or");								new_con->node_list_rh = node_list_or(					old_list, match_L, FALSE);			}			pe_free_shallow_adv(match_L,  FALSE);			pe_free_shallow_adv(old_list, TRUE);		}				if(new_con->node_list_rh == NULL) {			crm_warn("No matching nodes for constraint/rule %s/%s",				 id, xmlGetProp(rule, "id"));		}		crm_debug_action(print_rsc_to_node("Added", new_con, FALSE));	}	return TRUE;}