CRM_ASSERT(cl_is_allocated(new_obj) == 1);
CRM_DEV_ASSERT(cl_is_allocated(new_obj) == 1);
parse_xml(const char *input, int *offset){	int len = 0, lpc = 0;	char ch = 0;	char *tag_name = NULL;	char *attr_name = NULL;	char *attr_value = NULL;	gboolean more = TRUE;	const char *error = NULL;	const char *our_input = input;	crm_data_t *new_obj = NULL;	if(offset != NULL) {		our_input = input + (*offset);	}	len = strlen(our_input);	while(lpc < len) {		if(our_input[lpc] != '<') {		} else if(our_input[lpc+1] == '!') {			crm_err("XML Comments are not supported");			crm_insane("Skipping char %c", our_input[lpc]);			lpc++;					} else if(our_input[lpc+1] == '?') {			crm_insane("Skipping char %c", our_input[lpc]);			lpc++;		} else {			lpc++;			our_input += lpc;			break;		}		crm_insane("Skipping char %c", our_input[lpc]);		lpc++;	}		len = get_tag_name(our_input);	if(len < 0) {		return NULL;	}	crm_malloc(tag_name, len+1);	strncpy(tag_name, our_input, len+1);	tag_name[len] = EOS;	crm_debug("Processing tag %s", tag_name);		new_obj = ha_msg_new(1);	CRM_ASSERT(cl_is_allocated(new_obj) == 1);		ha_msg_add(new_obj, XML_ATTR_TAGNAME, tag_name);	lpc = len;	for(; more && error == NULL && lpc < strlen(input); lpc++) {			ch = our_input[lpc];			crm_insane("Processing char %c[%d]", ch, lpc);			switch(ch) {				case EOF: 				case 0:					error = "unexpected EOS";					break;				case '/':					if(our_input[lpc+1] == '>') {						more = FALSE;					}					break;				case '<':					if(our_input[lpc+1] != '/') {						crm_data_t *child = NULL;						crm_debug("Start parsing child...");						child = parse_xml(our_input, &lpc);						if(child == NULL) {							error = "error parsing child";						} else {							CRM_ASSERT(cl_is_allocated(child) == 1);							ha_msg_addstruct(								new_obj, crm_element_name(child), child);							crm_debug("Finished parsing child: %s",								  crm_element_name(child));/* 							lpc++; /\* > *\/ */						}					} else {						lpc += 2; /* </ */						len = get_tag_name(our_input+lpc);						if(len < 0) {							error = "couldnt find tag";						} else if(strncmp(our_input+lpc, tag_name, len) == 0) {							more = FALSE;							lpc += len;/* 							lpc++; /\* > *\/ */							if(our_input[lpc] != '>') {								error = "clase tag cannot contain attrs";							}							crm_debug("Finished parsing ourselves: %s",								  crm_element_name(new_obj));													} else {							error = "Mismatching close tag";							crm_err("Expected: %s", tag_name);						}					}					break;				case '=':					lpc++; /* = */				case '"':					lpc++; /* " */					len = get_attr_value(our_input+lpc);					if(len < 0) {						error = "couldnt find attr_value";					} else {						crm_malloc(attr_value, len+1);						strncpy(attr_value, our_input+lpc, len+1);						attr_value[len] = EOS;						lpc += len;/* 						lpc++; /\* " *\/ */						crm_debug("creating nvpair: <%s %s=\"%s\"...",							  tag_name, attr_name, attr_value);												ha_msg_add(new_obj, attr_name, attr_value);						crm_free(attr_name);						crm_free(attr_value);					}					break;				case '>':				case ' ':				case '\t':				case '\n':					break;				default:					len = get_attr_name(our_input+lpc);					if(len < 0) {						error = "couldnt find attr_name";					} else {						crm_malloc(attr_name, len+1);						strncpy(attr_name, our_input+lpc, len+1);						attr_name[len] = EOS;						lpc += len;						crm_trace("found attr name: %s", attr_name);						lpc--; /* make sure the '=' is seen next time around */					}					break;			}	}		if(error) {		crm_err("Error parsing token: %s", error);		crm_err("Error at or before: %s", our_input+lpc-3);		return NULL;	}		crm_debug("Finished processing %s tag", tag_name);	crm_free(tag_name);	if(offset != NULL) {		(*offset) += lpc;	}		CRM_ASSERT(cl_is_allocated(new_obj) == 1);	return new_obj;}