1ea6ae205Smrg/*
2ea6ae205Smrg  Copyright (c) 2002-2003 by Juliusz Chroboczek
3ea6ae205Smrg
4ea6ae205Smrg  Permission is hereby granted, free of charge, to any person obtaining a copy
5ea6ae205Smrg  of this software and associated documentation files (the "Software"), to deal
6ea6ae205Smrg  in the Software without restriction, including without limitation the rights
7ea6ae205Smrg  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8ea6ae205Smrg  copies of the Software, and to permit persons to whom the Software is
9ea6ae205Smrg  furnished to do so, subject to the following conditions:
10ea6ae205Smrg
11ea6ae205Smrg  The above copyright notice and this permission notice shall be included in
12ea6ae205Smrg  all copies or substantial portions of the Software.
13ea6ae205Smrg
14ea6ae205Smrg  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15ea6ae205Smrg  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16ea6ae205Smrg  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17ea6ae205Smrg  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18ea6ae205Smrg  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19ea6ae205Smrg  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20ea6ae205Smrg  THE SOFTWARE.
21ea6ae205Smrg*/
22ea6ae205Smrg
238b165ca7Smrg#ifdef HAVE_CONFIG_H
2412458b28Smrg#include "config.h"
258b165ca7Smrg#endif
2612458b28Smrg
27ea6ae205Smrg#include <stdlib.h>
28ea6ae205Smrg#include <stdio.h>
29ea6ae205Smrg#include <stdarg.h>
30ea6ae205Smrg#include <string.h>
31ea6ae205Smrg#include "list.h"
32ea6ae205Smrg
33ea6ae205Smrgint
34663cdc11SmrglistMember(const char *elt, ListPtr list)
35ea6ae205Smrg{
366ae2c069Smrg    while (list != NULL) {
376ae2c069Smrg        if (strcmp(elt, list->value) == 0)
38ea6ae205Smrg            return 1;
39ea6ae205Smrg        list = list->next;
40ea6ae205Smrg    }
41ea6ae205Smrg    return 0;
42ea6ae205Smrg}
43ea6ae205Smrg
44ea6ae205SmrgListPtr
45ea6ae205SmrglistCons(char *car, ListPtr cdr)
46ea6ae205Smrg{
47ea6ae205Smrg    ListPtr lcar = malloc(sizeof(ListRec));
486ae2c069Smrg
496ae2c069Smrg    if (!lcar)
50ea6ae205Smrg        return NULL;
516ae2c069Smrg    lcar->value = car;
526ae2c069Smrg    lcar->next = cdr;
53ea6ae205Smrg    return lcar;
54ea6ae205Smrg}
55ea6ae205Smrg
56ea6ae205SmrgListPtr
57ea6ae205SmrglistAdjoin(char *car, ListPtr cdr)
58ea6ae205Smrg{
596ae2c069Smrg    if (listMember(car, cdr)) {
60ea6ae205Smrg        free(car);
61ea6ae205Smrg        return cdr;
62ea6ae205Smrg    }
63ea6ae205Smrg    return listCons(car, cdr);
64ea6ae205Smrg}
65ea6ae205Smrg
66ea6ae205Smrgchar *
67663cdc11Smrgdsprintf(const char *f, ...)
68ea6ae205Smrg{
69ea6ae205Smrg    va_list args;
70ea6ae205Smrg    char *string;
716ae2c069Smrg
7212458b28Smrg#ifdef HAVE_VASPRINTF
7312458b28Smrg    va_start(args, f);
7412458b28Smrg    if (vasprintf(&string, f, args) == -1)
7512458b28Smrg        string = NULL;
7612458b28Smrg    va_end(args);
7712458b28Smrg    return string;
7812458b28Smrg#else
79ea6ae205Smrg    {
806ae2c069Smrg        int n, size = 20;
816ae2c069Smrg
826ae2c069Smrg        while (1) {
836ae2c069Smrg            if (size > 4096)
846ae2c069Smrg                return NULL;
856ae2c069Smrg            string = malloc(size);
866ae2c069Smrg            if (!string)
876ae2c069Smrg                return NULL;
886ae2c069Smrg            va_start(args, f);
896ae2c069Smrg            n = vsnprintf(string, size, f, args);
906ae2c069Smrg            va_end(args);
916ae2c069Smrg            if (n >= 0 && n < size)
92ea6ae205Smrg                return string;
936ae2c069Smrg            else if (n >= size)
946ae2c069Smrg                size = n + 1;
956ae2c069Smrg            else
966ae2c069Smrg                size = size * 3 / 2 + 1;
976ae2c069Smrg            free(string);
986ae2c069Smrg        }
99ea6ae205Smrg    }
10012458b28Smrg#endif
101ea6ae205Smrg}
102663cdc11Smrg
103ea6ae205SmrgListPtr
104663cdc11SmrglistConsF(ListPtr cdr, const char *f, ...)
105ea6ae205Smrg{
106ea6ae205Smrg    va_list args;
107ea6ae205Smrg    char *string;
1086ae2c069Smrg
109ea6ae205Smrg    {
1106ae2c069Smrg        int n, size = 20;
1116ae2c069Smrg
1126ae2c069Smrg        while (1) {
1136ae2c069Smrg            if (size > 4096)
1146ae2c069Smrg                return NULL;
1156ae2c069Smrg            string = malloc(size);
1166ae2c069Smrg            if (!string)
1176ae2c069Smrg                return NULL;
1186ae2c069Smrg            va_start(args, f);
1196ae2c069Smrg            n = vsnprintf(string, size, f, args);
1206ae2c069Smrg            va_end(args);
1216ae2c069Smrg            if (n >= 0 && n < size)
1226ae2c069Smrg                return listCons(string, cdr);
1236ae2c069Smrg            else if (n >= size)
1246ae2c069Smrg                size = n + 1;
1256ae2c069Smrg            else
1266ae2c069Smrg                size = size * 3 / 2 + 1;
1276ae2c069Smrg            free(string);
1286ae2c069Smrg        }
129ea6ae205Smrg    }
130ea6ae205Smrg}
131ea6ae205Smrg
132ea6ae205SmrgListPtr
133663cdc11SmrglistAdjoinF(ListPtr cdr, const char *f, ...)
134ea6ae205Smrg{
135ea6ae205Smrg    va_list args;
136ea6ae205Smrg    char *string;
1376ae2c069Smrg
138ea6ae205Smrg    {
1396ae2c069Smrg        int n, size = 20;
1406ae2c069Smrg
1416ae2c069Smrg        while (1) {
1426ae2c069Smrg            if (size > 4096)
1436ae2c069Smrg                return NULL;
1446ae2c069Smrg            string = malloc(size);
1456ae2c069Smrg            if (!string)
1466ae2c069Smrg                return NULL;
1476ae2c069Smrg            va_start(args, f);
1486ae2c069Smrg            n = vsnprintf(string, size, f, args);
1496ae2c069Smrg            va_end(args);
1506ae2c069Smrg            if (n >= 0 && n < size)
1516ae2c069Smrg                return listAdjoin(string, cdr);
1526ae2c069Smrg            else if (n >= size)
1536ae2c069Smrg                size = n + 1;
1546ae2c069Smrg            else
1556ae2c069Smrg                size = size * 3 / 2 + 1;
1566ae2c069Smrg            free(string);
1576ae2c069Smrg        }
158ea6ae205Smrg    }
159ea6ae205Smrg}
160ea6ae205Smrg
161ea6ae205Smrgint
162ea6ae205SmrglistLength(ListPtr list)
163ea6ae205Smrg{
164ea6ae205Smrg    int n = 0;
1656ae2c069Smrg
1666ae2c069Smrg    while (list) {
167ea6ae205Smrg        n++;
168ea6ae205Smrg        list = list->next;
169ea6ae205Smrg    }
170ea6ae205Smrg    return n;
171ea6ae205Smrg}
172ea6ae205Smrg
173663cdc11SmrgListPtr
174ea6ae205SmrgappendList(ListPtr first, ListPtr second)
175ea6ae205Smrg{
176ea6ae205Smrg    ListPtr current;
177ea6ae205Smrg
1786ae2c069Smrg    if (second == NULL)
179ea6ae205Smrg        return first;
180ea6ae205Smrg
1816ae2c069Smrg    if (first == NULL)
182ea6ae205Smrg        return second;
183ea6ae205Smrg
1846ae2c069Smrg    for (current = first; current->next; current = current->next);
185ea6ae205Smrg
186ea6ae205Smrg    current->next = second;
187ea6ae205Smrg    return first;
188ea6ae205Smrg}
189ea6ae205Smrg
190ea6ae205SmrgListPtr
191ea6ae205SmrgmakeList(char **a, int n, ListPtr old, int begin)
192ea6ae205Smrg{
193ea6ae205Smrg    ListPtr first, current, next;
194ea6ae205Smrg    int i;
195ea6ae205Smrg
1966ae2c069Smrg    if (n == 0)
197ea6ae205Smrg        return old;
198ea6ae205Smrg
199ea6ae205Smrg    first = malloc(sizeof(ListRec));
2006ae2c069Smrg    if (!first)
201ea6ae205Smrg        return NULL;
202ea6ae205Smrg
203ea6ae205Smrg    first->value = a[0];
204ea6ae205Smrg    first->next = NULL;
205ea6ae205Smrg
206ea6ae205Smrg    current = first;
2076ae2c069Smrg    for (i = 1; i < n; i++) {
208ea6ae205Smrg        next = malloc(sizeof(ListRec));
2096ae2c069Smrg        if (!next) {
210245f6787Smrg            destroyList(first);
211ea6ae205Smrg            return NULL;
212245f6787Smrg        }
213ea6ae205Smrg        next->value = a[i];
214ea6ae205Smrg        next->next = NULL;
215ea6ae205Smrg
216ea6ae205Smrg        current->next = next;
217ea6ae205Smrg        current = next;
218ea6ae205Smrg    }
2196ae2c069Smrg    if (begin) {
220ea6ae205Smrg        current->next = old;
221ea6ae205Smrg        return first;
2226ae2c069Smrg    }
2236ae2c069Smrg    else {
224ea6ae205Smrg        return appendList(old, first);
225ea6ae205Smrg    }
226ea6ae205Smrg}
227ea6ae205Smrg
228ea6ae205SmrgListPtr
229ea6ae205SmrgreverseList(ListPtr old)
230ea6ae205Smrg{
231ea6ae205Smrg    ListPtr new = NULL, current;
2326ae2c069Smrg
2336ae2c069Smrg    while (old) {
234ea6ae205Smrg        current = old;
235ea6ae205Smrg        old = old->next;
236ea6ae205Smrg        current->next = new;
237ea6ae205Smrg        new = current;
238ea6ae205Smrg    }
239ea6ae205Smrg    return new;
240ea6ae205Smrg}
241ea6ae205Smrg
242245f6787Smrg/* qsort helper for sorting list entries */
243245f6787Smrgstatic int
244245f6787SmrgcompareListEntries(const void *a, const void *b)
245245f6787Smrg{
246245f6787Smrg    const ListPtr lista = *(const ListPtr *) a;
247245f6787Smrg    const ListPtr listb = *(const ListPtr *) b;
248245f6787Smrg
249245f6787Smrg    return strcmp(lista->value, listb->value);
250245f6787Smrg}
251245f6787Smrg
252245f6787SmrgListPtr
253245f6787SmrgsortList(ListPtr old)
254245f6787Smrg{
255245f6787Smrg    int i;
256245f6787Smrg    int l = listLength(old);
257245f6787Smrg    ListPtr n;
25848f45e26Smrg    ListPtr *sorted;
25948f45e26Smrg
26048f45e26Smrg    if (l <= 0)
26148f45e26Smrg        return old;
26248f45e26Smrg
26348f45e26Smrg    sorted = malloc(l * sizeof(ListPtr));
264245f6787Smrg
265245f6787Smrg    if (sorted == NULL)
266245f6787Smrg        return old;
267245f6787Smrg
268245f6787Smrg    for (n = old, i = 0; n != NULL; n = n->next) {
269245f6787Smrg        sorted[i++] = n;
270245f6787Smrg    }
271245f6787Smrg    qsort(sorted, i, sizeof(ListPtr), compareListEntries);
272245f6787Smrg    n = sorted[0];
273245f6787Smrg    for (i = 0; i < (l - 1); i++) {
2746ae2c069Smrg        sorted[i]->next = sorted[i + 1];
275245f6787Smrg    }
276245f6787Smrg    sorted[i]->next = NULL;
277245f6787Smrg    free(sorted);
278245f6787Smrg    return n;
279245f6787Smrg}
280245f6787Smrg
281ea6ae205Smrgvoid
282ea6ae205SmrgdestroyList(ListPtr old)
283ea6ae205Smrg{
284ea6ae205Smrg    ListPtr next;
2856ae2c069Smrg
2866ae2c069Smrg    if (!old)
287ea6ae205Smrg        return;
2886ae2c069Smrg    while (old) {
289ea6ae205Smrg        next = old->next;
290ea6ae205Smrg        free(old);
291ea6ae205Smrg        old = next;
292ea6ae205Smrg    }
293ea6ae205Smrg}
294ea6ae205Smrg
295ea6ae205Smrgvoid
296ea6ae205SmrgdeepDestroyList(ListPtr old)
297ea6ae205Smrg{
298ea6ae205Smrg    ListPtr next;
2996ae2c069Smrg
3006ae2c069Smrg    if (!old)
301ea6ae205Smrg        return;
3026ae2c069Smrg    while (old) {
303ea6ae205Smrg        next = old->next;
304ea6ae205Smrg        free(old->value);
305ea6ae205Smrg        free(old);
306ea6ae205Smrg        old = next;
307ea6ae205Smrg    }
308ea6ae205Smrg}
309