/*	SearchCrossCallEntry (nr,entry) returns the first CrossCallEntry
	following/including entry that either:
		matches nr, or
		is the entry after which a new entry with nr should be added, or
		NULL in case nr should be placed before entry.
*/
static CrossCallEntry SearchCrossCallEntry (int nr,CrossCallEntry entry)
{
	if (nr == entry->cce_code)
		return entry;				// entry found
	if (nr < entry->cce_code)
		return NULL;				// no entry found
	if (entry->cce_next == NULL)
		return entry;				// last entry; should insert new entry after this one
	if (nr < entry->cce_next->cce_code)
		return entry;				// next entry exceeds nr; should insert new entry after this one
	return SearchCrossCallEntry (nr,entry->cce_next);
}
//	FindCrossCallEntry returns the found CrossCallProcedure or NULL if not found.
CrossCallProcedure FindCrossCallEntry (CrossCallProcedureTable ccpt, int cce_code)
{
	if (ccpt->ccpt_size == 0)	// table is empty, return NULL
		return NULL;
	else
	{
		CrossCallEntry searchCCE;
		searchCCE = SearchCrossCallEntry (cce_code,ccpt->ccpt_first);
		if (searchCCE && searchCCE->cce_code == cce_code)
			return searchCCE->cce_proc;
		else
			return NULL;
	}
}
/*
 * FindCrossCallEntry returns the found CrossCallProcedure or NULL if not found.
 */
CrossCallProcedure FindCrossCallEntry (CrossCallProcedureTable ccpt, int cce_code)
{
    /* printf("FindCrossCallEntry\n"); */
    if (ccpt->ccpt_size == 0)
    {   /* table is empty, return NULL */
        return NULL;
    }
    else
    {
        CrossCallEntry searchCCE;
        searchCCE = SearchCrossCallEntry (cce_code,ccpt->ccpt_first);
        if (searchCCE && searchCCE->cce_code == cce_code)
            return searchCCE->cce_proc;
        else
            return NULL;
    }
}
/*
 * AddCrossCallEntry (table,nr,proc) adds a new entry (nr,proc) if an entry
 * with nr is not already present.
 */
void AddCrossCallEntry (CrossCallProcedureTable ccpt, int cce_code,
                CrossCallProcedure cce_proc)
{
    CrossCallEntry entry;
    /* printf("AddCrossCallEntry\n"); */
    entry = NewCrossCallEntry (cce_code,cce_proc);

    if (ccpt->ccpt_size == 0)
    {	/* table is empty; create entry and add it */
        ccpt->ccpt_size  = 1;
        ccpt->ccpt_first = entry;
        ccpt->ccpt_last  = entry;
    }
    else if (cce_code < ccpt->ccpt_first->cce_code)
    {	/* entry should be inserted before first entry */
        ccpt->ccpt_size += 1;
        entry->cce_next = ccpt->ccpt_first;
        ccpt->ccpt_first= entry;
    }
    else if (cce_code > ccpt->ccpt_first->cce_code)
    {	/* entry could be in table; look for it and add it if not present */
        CrossCallEntry searchCCE;
        searchCCE = SearchCrossCallEntry (cce_code,ccpt->ccpt_first);

        if (searchCCE == NULL)
        {
            /* printf("\'AddCrossCallEntry\' SearchCrossCallEntry returned NULL CrossCallEntry"); */
            exit(1);
        }
        if (searchCCE->cce_code != cce_code)
        {	/* entry not in table but should be linked after searchCCE */
            gboolean appendLast = (ccpt->ccpt_last == searchCCE);
            ccpt->ccpt_size     += 1;
            entry->cce_next     = searchCCE->cce_next;
            searchCCE->cce_next = entry;

            if (appendLast)
                ccpt->ccpt_last  = entry;	// adjust last if entry is appended at end
        }
    }
}