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