1 /* *** This file was borrowed from jam 2.5. The copyright statement from
2 * *** jam.c appears below.
3 */
4 /*
5 * /+\
6 * +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
7 * \+/
8 *
9 * This file is part of jam.
10 *
11 * License is hereby granted to use this software and distribute it
12 * freely, as long as this copyright notice is retained and modifications
13 * are clearly marked.
14 *
15 * ALL WARRANTIES ARE HEREBY DISCLAIMED.
16 */
17
18 /*
19 * Copyright 1993, 1995 Christopher Seiwald.
20 *
21 * This file is part of Jam - see jam.c for Copyright information.
22 */
23
24 /*
25 * lists.c - maintain lists of strings
26 *
27 * This implementation essentially uses a singly linked list, but
28 * guarantees that the head element of every list has a valid pointer
29 * to the tail of the list, so the new elements can efficiently and
30 * properly be appended to the end of a list.
31 *
32 * To avoid massive allocation, list_free() just tacks the whole freed
33 * chain onto freelist and list_new() looks on freelist first for an
34 * available list struct. list_free() does not free the strings in the
35 * chain: it lazily lets list_new() do so.
36 *
37 * 08/23/94 (seiwald) - new list_append()
38 * 09/07/00 (seiwald) - documented lol_*() functions
39 * 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr()
40 * 11/04/02 (seiwald) - const-ing for string literals
41 * 12/09/02 (seiwald) - new list_printq() for writing lists to Jambase
42 */
43
44 # include "jam.h"
45 # include "newstr.h"
46 # include "lists.h"
47
48 #if 1 /* TNB */
49 #include "alloc.h"
50 static ALLOC *listalloc = 0;
51 #endif
52
53 static LIST *freelist = 0; /* junkpile for list_free() */
54
55 /*
56 * list_append() - append a list onto another one, returning total
57 */
58
59 LIST *
list_append(LIST * l,LIST * nl)60 list_append(
61 LIST *l,
62 LIST *nl )
63 {
64 if( !nl )
65 {
66 /* Just return l */
67 }
68 else if( !l )
69 {
70 l = nl;
71 }
72 else
73 {
74 /* Graft two non-empty lists. */
75 l->tail->next = nl;
76 l->tail = nl->tail;
77 }
78
79 return l;
80 }
81
82 /*
83 * list_new() - tack a string onto the end of a list of strings
84 */
85
86 LIST *
list_new(LIST * head,const char * string,int copy)87 list_new(
88 LIST *head,
89 const char *string,
90 int copy )
91 {
92 LIST *l;
93
94 if( DEBUG_LISTS )
95 printf( "list > %s <\n", string );
96
97 /* Copy/newstr as needed */
98
99 string = copy ? copystr( string ) : newstr( string );
100
101 /* Get list struct from freelist, if one available. */
102 /* Otherwise allocate. */
103 /* If from freelist, must free string first */
104
105 if( freelist )
106 {
107 l = freelist;
108 freestr( l->string );
109 freelist = freelist->next;
110 }
111 else
112 {
113 #if 1 /* TNB */
114 if (!listalloc)
115 listalloc = alloc_init(sizeof(LIST), 64);
116 l = (LIST *) alloc_enter(listalloc);
117 #else
118 l = (LIST *)malloc( sizeof( *l ) );
119 #endif
120 }
121
122 /* If first on chain, head points here. */
123 /* If adding to chain, tack us on. */
124 /* Tail must point to this new, last element. */
125
126 if( !head ) head = l;
127 else head->tail->next = l;
128 head->tail = l;
129 l->next = 0;
130
131 l->string = string;
132
133 return head;
134 }
135
136 /*
137 * list_copy() - copy a whole list of strings (nl) onto end of another (l)
138 */
139
140 LIST *
list_copy(LIST * l,LIST * nl)141 list_copy(
142 LIST *l,
143 LIST *nl )
144 {
145 for( ; nl; nl = list_next( nl ) )
146 l = list_new( l, nl->string, 1 );
147
148 return l;
149 }
150
151 /*
152 * list_sublist() - copy a subset of a list of strings
153 */
154
155 LIST *
list_sublist(LIST * l,int start,int count)156 list_sublist(
157 LIST *l,
158 int start,
159 int count )
160 {
161 LIST *nl = 0;
162
163 for( ; l && start--; l = list_next( l ) )
164 ;
165
166 for( ; l && count--; l = list_next( l ) )
167 nl = list_new( nl, l->string, 1 );
168
169 return nl;
170 }
171
172 /*
173 * list_free() - free a list of strings
174 */
175
176 void
list_free(LIST * head)177 list_free( LIST *head )
178 {
179 /* Just tack onto freelist. */
180
181 if( head )
182 {
183 head->tail->next = freelist;
184 freelist = head;
185 }
186 }
187
188 /*
189 * list_print() - print a list of strings to stdout
190 */
191
192 void
list_print(LIST * l)193 list_print( LIST *l )
194 {
195 for( ; l; l = list_next( l ) )
196 printf( "%s ", l->string );
197 }
198
199 /*
200 * list_printq() - print a list of safely quoted strings to a file
201 */
202
203 void
list_printq(FILE * out,LIST * l)204 list_printq( FILE *out, LIST *l )
205 {
206 /* Dump each word, enclosed in "s */
207 /* Suitable for Jambase use. */
208
209 for( ; l; l = list_next( l ) )
210 {
211 const char *p = l->string;
212 const char *ep = p + strlen( p );
213 const char *op = p;
214
215 fputc( '\n', out );
216 fputc( '\t', out );
217 fputc( '"', out );
218
219 /* Any embedded "'s? Escape them */
220
221 while( ( p = (char *)memchr( op, '"', ep - op ) ) ) /* TNB */
222 {
223 fwrite( op, p - op, 1, out );
224 fputc( '\\', out );
225 fputc( '"', out );
226 op = p + 1;
227 }
228
229 /* Write remainder */
230
231 fwrite( op, ep - op, 1, out );
232 fputc( '"', out );
233 fputc( ' ', out );
234 }
235 }
236
237 /*
238 * list_length() - return the number of items in the list
239 */
240
241 int
list_length(LIST * l)242 list_length( LIST *l )
243 {
244 int n = 0;
245
246 for( ; l; l = list_next( l ), ++n )
247 ;
248
249 return n;
250 }
251
252 /*
253 * lol_init() - initialize a LOL (list of lists)
254 */
255
256 void
lol_init(LOL * lol)257 lol_init( LOL *lol )
258 {
259 lol->count = 0;
260 }
261
262 /*
263 * lol_add() - append a LIST onto an LOL
264 */
265
266 void
lol_add(LOL * lol,LIST * l)267 lol_add(
268 LOL *lol,
269 LIST *l )
270 {
271 if( lol->count < LOL_MAX )
272 lol->list[ lol->count++ ] = l;
273 }
274
275 /*
276 * lol_free() - free the LOL and its LISTs
277 */
278
279 void
lol_free(LOL * lol)280 lol_free( LOL *lol )
281 {
282 int i;
283
284 for( i = 0; i < lol->count; i++ )
285 list_free( lol->list[i] );
286
287 lol->count = 0;
288 }
289
290 /*
291 * lol_get() - return one of the LISTs in the LOL
292 */
293
294 LIST *
lol_get(LOL * lol,int i)295 lol_get(
296 LOL *lol,
297 int i )
298 {
299 return i < lol->count ? lol->list[i] : 0;
300 }
301
302 /*
303 * lol_print() - debug print LISTS separated by ":"
304 */
305
306 void
lol_print(LOL * lol)307 lol_print( LOL *lol )
308 {
309 int i;
310
311 for( i = 0; i < lol->count; i++ )
312 {
313 if( i )
314 printf( " : " );
315 list_print( lol->list[i] );
316 }
317 }
318
donelist(void)319 void donelist(void) /* TNB */
320 {
321 freelist = 0;
322 alloc_free(listalloc);
323 listalloc = 0;
324 }
325