mirror of
https://review.haiku-os.org/buildtools
synced 2024-11-23 07:18:49 +01:00
ecc89c9a6a
git-svn-id: file:///srv/svn/repos/haiku/buildtools/trunk@15729 a95241bf-73f2-0310-859d-f6bbb57e9c96
290 lines
4.6 KiB
C
290 lines
4.6 KiB
C
/*
|
|
* Copyright 1993, 1995 Christopher Seiwald.
|
|
*
|
|
* This file is part of Jam - see jam.c for Copyright information.
|
|
*/
|
|
|
|
/*
|
|
* 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
|
|
* 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr()
|
|
* 11/04/02 (seiwald) - const-ing for string literals
|
|
* 12/09/02 (seiwald) - new list_printq() for writing lists to Jambase
|
|
*/
|
|
|
|
# include "jam.h"
|
|
# include "newstr.h"
|
|
# include "lists.h"
|
|
|
|
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,
|
|
const char *string,
|
|
int copy )
|
|
{
|
|
LIST *l;
|
|
|
|
if( DEBUG_LISTS )
|
|
printf( "list > %s <\n", string );
|
|
|
|
/* Copy/newstr as needed */
|
|
|
|
string = copy ? copystr( string ) : newstr( 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 *)malloc( sizeof( *l ) );
|
|
}
|
|
|
|
/* 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, nl->string, 1 );
|
|
|
|
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, l->string, 1 );
|
|
|
|
return nl;
|
|
}
|
|
|
|
/*
|
|
* 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_print() - print a list of strings to stdout
|
|
*/
|
|
|
|
void
|
|
list_print( LIST *l )
|
|
{
|
|
for( ; l; l = list_next( l ) )
|
|
printf( "%s ", l->string );
|
|
}
|
|
|
|
/*
|
|
* list_printq() - print a list of safely quoted strings to a file
|
|
*/
|
|
|
|
void
|
|
list_printq( FILE *out, LIST *l )
|
|
{
|
|
/* Dump each word, enclosed in "s */
|
|
/* Suitable for Jambase use. */
|
|
|
|
for( ; l; l = list_next( l ) )
|
|
{
|
|
const char *p = l->string;
|
|
const char *ep = p + strlen( p );
|
|
const char *op = p;
|
|
|
|
fputc( '\n', out );
|
|
fputc( '\t', out );
|
|
fputc( '"', out );
|
|
|
|
/* Any embedded "'s? Escape them */
|
|
|
|
while( p = (char *)memchr( op, '"', ep - op ) )
|
|
{
|
|
fwrite( op, p - op, 1, out );
|
|
fputc( '\\', out );
|
|
fputc( '"', out );
|
|
op = p + 1;
|
|
}
|
|
|
|
/* Write remainder */
|
|
|
|
fwrite( op, ep - op, 1, out );
|
|
fputc( '"', out );
|
|
fputc( ' ', out );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
|
|
/*
|
|
* 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] );
|
|
}
|
|
}
|