int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new)
{
	struct cil_list_item *omatch = NULL;
	struct cil_list_item *ofirst = old->head;
	struct cil_list_item *ocurr = NULL;
	struct cil_list_item *oprev = NULL;
	struct cil_list_item *nmatch = NULL;
	struct cil_list_item *nfirst = new->head;
	struct cil_list_item *ncurr = NULL;
	int rc = SEPOL_ERR;

	if (nfirst == NULL) {
		return SEPOL_OK;
	}

	if (ofirst == NULL) {
		/* First list added */
		rc = __cil_ordered_list_insert(old, NULL, nfirst, NULL);
		return rc;
	}

	/* Find a match between the new list and the old one */
	for (nmatch = nfirst; nmatch; nmatch = nmatch->next) {
		omatch = __cil_ordered_find_match(nmatch, ofirst);
		if (omatch) {
			break;
		}
	}

	if (!nmatch) {
		/* List cannot be merged yet */
		return SEPOL_ERR;
	}

	if (nmatch != nfirst && omatch != ofirst) {
		/* Potential ordering conflict--try again later */
		return SEPOL_ERR;
	}

	if (nmatch != nfirst) {
		/* Prepend the beginning of the new list up to the first match to the old list */
		rc = __cil_ordered_list_insert(old, NULL, nfirst, nmatch);
		if (rc != SEPOL_OK) {
			return rc;
		}
	}

	/* In the overlapping protion, add items from the new list not in the old list */
	ncurr = nmatch->next;
	ocurr = omatch->next;
	oprev = omatch;
	while (ncurr && ocurr) {
		if (ncurr->data == ocurr->data) {
			oprev = ocurr;
			ocurr = ocurr->next;
			ncurr = ncurr->next;
		} else {
			/* Handle gap in old: old = (A C)  new = (A B C) */
			nmatch = __cil_ordered_find_match(ocurr, ncurr->next);
			if (nmatch) {
				rc = __cil_ordered_list_insert(old, oprev, ncurr, nmatch);
				if (rc != SEPOL_OK) {
					return rc;
				}
				oprev = ocurr;
				ocurr = ocurr->next;
				ncurr = nmatch->next;
				continue;
			}
			/* Handle gap in new: old = (A B C)  new = (A C) */
			omatch = __cil_ordered_find_match(ncurr, ocurr->next);
			if (omatch) {
				/* Nothing to insert, just skip */
				oprev = omatch;
				ocurr = omatch->next;
				ncurr = ncurr->next;
				continue;
			} else {
				return SEPOL_ERR;
			}
		}
	}

	if (ncurr) {
		/* Add the rest of the items from the new list */
		rc = __cil_ordered_list_insert(old, old->tail, ncurr, NULL);
		if (rc != SEPOL_OK) {
			return rc;
		}
	}

	return SEPOL_OK;
}
int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new)
{
	struct cil_list_item *omatch = NULL;
	struct cil_list_item *ofirst = old->head;
	struct cil_list_item *ocurr = NULL;
	struct cil_list_item *oprev = NULL;
	struct cil_list_item *nmatch = NULL;
	struct cil_list_item *nfirst = new->head;
	struct cil_list_item *ncurr = NULL;
	int rc = SEPOL_ERR;

	if (nfirst == NULL) {
		return SEPOL_OK;
	}

	if (ofirst == NULL) {
		 
		rc = __cil_ordered_list_insert(old, NULL, nfirst, NULL);
		return rc;
	}

	 
	for (nmatch = nfirst; nmatch; nmatch = nmatch->next) {
		omatch = __cil_ordered_find_match(nmatch, ofirst);
		if (omatch) {
			break;
		}
	}

	if (!nmatch) {
		 
		return SEPOL_ERR;
	}

	if (nmatch != nfirst && omatch != ofirst) {
		 
		return SEPOL_ERR;
	}

	if (nmatch != nfirst) {
		 
		rc = __cil_ordered_list_insert(old, NULL, nfirst, nmatch);
		if (rc != SEPOL_OK) {
			return rc;
		}
	}

	 
	ncurr = nmatch->next;
	ocurr = omatch->next;
	oprev = omatch;
	while (ncurr && ocurr) {
		if (ncurr->data == ocurr->data) {
			oprev = ocurr;
			ocurr = ocurr->next;
			ncurr = ncurr->next;
		} else {
			 
			nmatch = __cil_ordered_find_match(ocurr, ncurr->next);
			if (nmatch) {
				rc = __cil_ordered_list_insert(old, oprev, ncurr, nmatch);
				if (rc != SEPOL_OK) {
					return rc;
				}
				oprev = ocurr;
				ocurr = ocurr->next;
				ncurr = nmatch->next;
				continue;
			}
			 
			omatch = __cil_ordered_find_match(ncurr, ocurr->next);
			if (omatch) {
				 
				oprev = omatch;
				ocurr = omatch->next;
				ncurr = ncurr->next;
				continue;
			} else {
				return SEPOL_ERR;
			}
		}
	}

	if (ncurr) {
		 
		rc = __cil_ordered_list_insert(old, old->tail, ncurr, NULL);
		if (rc != SEPOL_OK) {
			return rc;
		}
	}

	return SEPOL_OK;
}