mirror of
https://github.com/boostorg/build.git
synced 2026-02-12 12:02:24 +00:00
370 lines
6.3 KiB
C
370 lines
6.3 KiB
C
/*
|
|
* Copyright 1993, 1995 Christopher Seiwald.
|
|
*
|
|
* This file is part of Jam - see jam.c for Copyright information.
|
|
*/
|
|
|
|
# include "jam.h"
|
|
# include "newstr.h"
|
|
# include "lists.h"
|
|
|
|
/*
|
|
* lists.c - maintain lists of strings
|
|
*
|
|
* This implementation essentially uses a singly linked list, but
|
|
* guarantees that the head element of every list has a valid pointer
|
|
* to the tail of the list, so the new elements can efficiently and
|
|
* properly be appended to the end of a list.
|
|
*
|
|
* To avoid massive allocation, list_free() just tacks the whole freed
|
|
* chain onto freelist and list_new() looks on freelist first for an
|
|
* available list struct. list_free() does not free the strings in the
|
|
* chain: it lazily lets list_new() do so.
|
|
*
|
|
* 08/23/94 (seiwald) - new list_append()
|
|
* 09/07/00 (seiwald) - documented lol_*() functions
|
|
*/
|
|
|
|
static LIST *freelist = 0; /* junkpile for list_free() */
|
|
|
|
/*
|
|
* list_append() - append a list onto another one, returning total
|
|
*/
|
|
|
|
LIST *
|
|
list_append(
|
|
LIST *l,
|
|
LIST *nl )
|
|
{
|
|
if( !nl )
|
|
{
|
|
/* Just return l */
|
|
}
|
|
else if( !l )
|
|
{
|
|
l = nl;
|
|
}
|
|
else
|
|
{
|
|
/* Graft two non-empty lists. */
|
|
l->tail->next = nl;
|
|
l->tail = nl->tail;
|
|
}
|
|
|
|
return l;
|
|
}
|
|
|
|
/*
|
|
* list_new() - tack a string onto the end of a list of strings
|
|
*/
|
|
|
|
LIST *
|
|
list_new(
|
|
LIST *head,
|
|
char *string )
|
|
{
|
|
LIST *l;
|
|
|
|
if( DEBUG_LISTS )
|
|
printf( "list > %s <\n", string );
|
|
|
|
/* Get list struct from freelist, if one available. */
|
|
/* Otherwise allocate. */
|
|
/* If from freelist, must free string first */
|
|
|
|
if( freelist )
|
|
{
|
|
l = freelist;
|
|
freestr( l->string );
|
|
freelist = freelist->next;
|
|
}
|
|
else
|
|
{
|
|
l = (LIST *)BJAM_MALLOC( sizeof( LIST ) );
|
|
}
|
|
|
|
/* If first on chain, head points here. */
|
|
/* If adding to chain, tack us on. */
|
|
/* Tail must point to this new, last element. */
|
|
|
|
if( !head ) head = l;
|
|
else head->tail->next = l;
|
|
head->tail = l;
|
|
l->next = 0;
|
|
|
|
l->string = string;
|
|
|
|
return head;
|
|
}
|
|
|
|
/*
|
|
* list_copy() - copy a whole list of strings (nl) onto end of another (l)
|
|
*/
|
|
|
|
LIST *
|
|
list_copy(
|
|
LIST *l,
|
|
LIST *nl )
|
|
{
|
|
for( ; nl; nl = list_next( nl ) )
|
|
l = list_new( l, copystr( nl->string ) );
|
|
|
|
return l;
|
|
}
|
|
|
|
/*
|
|
* list_sublist() - copy a subset of a list of strings
|
|
*/
|
|
|
|
LIST *
|
|
list_sublist(
|
|
LIST *l,
|
|
int start,
|
|
int count )
|
|
{
|
|
LIST *nl = 0;
|
|
|
|
for( ; l && start--; l = list_next( l ) )
|
|
;
|
|
|
|
for( ; l && count--; l = list_next( l ) )
|
|
nl = list_new( nl, copystr( l->string ) );
|
|
|
|
return nl;
|
|
}
|
|
|
|
LIST *
|
|
list_sort(
|
|
LIST *l)
|
|
{
|
|
|
|
LIST* first = 0;
|
|
LIST* second = 0;
|
|
LIST* merged = l;
|
|
LIST* result;
|
|
|
|
if (!l)
|
|
return L0;
|
|
|
|
for(;;) {
|
|
|
|
/* Split the list in two */
|
|
LIST** dst = &first;
|
|
LIST* src = merged;
|
|
|
|
for(;;) {
|
|
|
|
*dst = list_append(*dst, list_new(0, src->string));
|
|
|
|
if (!src->next)
|
|
break;
|
|
|
|
if (strcmp(src->string, src->next->string) > 0)
|
|
{
|
|
if (dst == &first)
|
|
dst = &second;
|
|
else
|
|
dst = &first;
|
|
}
|
|
|
|
src = src->next;
|
|
}
|
|
|
|
if (merged != l)
|
|
list_free( merged );
|
|
merged = 0;
|
|
|
|
if (second == 0) {
|
|
result = first;
|
|
break;
|
|
}
|
|
|
|
|
|
/* Merge lists 'first' and 'second' into 'merged' and free
|
|
'first'/'second'. */
|
|
{
|
|
LIST* f = first;
|
|
LIST* s = second;
|
|
|
|
while(f && s)
|
|
{
|
|
if (strcmp(f->string, s->string) < 0)
|
|
{
|
|
merged = list_append( merged, list_new(0, f->string ));
|
|
f = f->next;
|
|
}
|
|
else
|
|
{
|
|
merged = list_append( merged, list_new(0, s->string ));
|
|
s = s->next;
|
|
}
|
|
}
|
|
|
|
merged = list_copy( merged, f );
|
|
merged = list_copy( merged, s );
|
|
list_free( first );
|
|
list_free( second );
|
|
first = 0;
|
|
second = 0;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* list_free() - free a list of strings
|
|
*/
|
|
|
|
void
|
|
list_free( LIST *head )
|
|
{
|
|
/* Just tack onto freelist. */
|
|
|
|
if( head )
|
|
{
|
|
head->tail->next = freelist;
|
|
freelist = head;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* list_pop_front() - remove the front element from a list of strings
|
|
*/
|
|
LIST * list_pop_front( LIST *l )
|
|
{
|
|
LIST * result = l->next;
|
|
if( result )
|
|
{
|
|
result->tail = l->tail;
|
|
l->next = L0;
|
|
l->tail = l;
|
|
}
|
|
list_free( l );
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* list_print() - print a list of strings to stdout
|
|
*/
|
|
|
|
void
|
|
list_print( LIST *l )
|
|
{
|
|
LIST *p = 0;
|
|
for( ; l; p = l, l = list_next( l ) )
|
|
if ( p )
|
|
printf( "%s ", p->string );
|
|
if ( p )
|
|
printf( "%s", p->string );
|
|
}
|
|
|
|
/*
|
|
* list_length() - return the number of items in the list
|
|
*/
|
|
|
|
int
|
|
list_length( LIST *l )
|
|
{
|
|
int n = 0;
|
|
|
|
for( ; l; l = list_next( l ), ++n )
|
|
;
|
|
|
|
return n;
|
|
}
|
|
|
|
int
|
|
list_in(LIST* l, char* value)
|
|
{
|
|
for(; l; l = l->next)
|
|
if (strcmp(l->string, value) == 0)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
LIST *
|
|
list_unique( LIST *sorted_list)
|
|
{
|
|
LIST* result = 0;
|
|
LIST* last_added = 0;
|
|
|
|
for(; sorted_list; sorted_list = sorted_list->next)
|
|
{
|
|
if (!last_added || strcmp(sorted_list->string, last_added->string) != 0)
|
|
{
|
|
result = list_new(result, sorted_list->string);
|
|
last_added = sorted_list;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
* lol_init() - initialize a LOL (list of lists)
|
|
*/
|
|
|
|
void
|
|
lol_init( LOL *lol )
|
|
{
|
|
lol->count = 0;
|
|
}
|
|
|
|
/*
|
|
* lol_add() - append a LIST onto an LOL
|
|
*/
|
|
|
|
void
|
|
lol_add(
|
|
LOL *lol,
|
|
LIST *l )
|
|
{
|
|
if( lol->count < LOL_MAX )
|
|
lol->list[ lol->count++ ] = l;
|
|
}
|
|
|
|
/*
|
|
* lol_free() - free the LOL and its LISTs
|
|
*/
|
|
|
|
void
|
|
lol_free( LOL *lol )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < lol->count; i++ )
|
|
list_free( lol->list[i] );
|
|
|
|
lol->count = 0;
|
|
}
|
|
|
|
/*
|
|
* lol_get() - return one of the LISTs in the LOL
|
|
*/
|
|
|
|
LIST *
|
|
lol_get(
|
|
LOL *lol,
|
|
int i )
|
|
{
|
|
return i < lol->count ? lol->list[i] : 0;
|
|
}
|
|
|
|
/*
|
|
* lol_print() - debug print LISTS separated by ":"
|
|
*/
|
|
|
|
void
|
|
lol_print( LOL *lol )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < lol->count; i++ )
|
|
{
|
|
if( i )
|
|
printf( " : " );
|
|
list_print( lol->list[i] );
|
|
}
|
|
}
|