1 /* Id: strlist.c,v 1.3 2014/12/24 09:55:32 plunky Exp */ 2 /* $NetBSD: strlist.c,v 1.1.1.2 2016/02/09 20:28:56 plunky Exp $ */ 3 4 /*- 5 * Copyright (c) 2011 Joerg Sonnenberger <joerg (at) NetBSD.org>. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <stdlib.h> 34 #include "strlist.h" 35 #include "xalloc.h" 36 37 void 38 strlist_init(struct strlist *l) 39 { 40 l->first = l->last = NULL; 41 } 42 43 void 44 strlist_free(struct strlist *l) 45 { 46 struct string *s1, *s2; 47 48 STRLIST_FOREACH_MUTABLE(s1, l, s2) { 49 free(s1->value); 50 free(s1); 51 } 52 l->first = l->last = NULL; 53 } 54 55 void 56 strlist_make_array(const struct strlist *l, char ***a, size_t *len) 57 { 58 const struct string *s; 59 char **i; 60 61 *len = 0; 62 63 STRLIST_FOREACH(s, l) 64 ++*len; 65 66 *a = xcalloc(*len + 1, sizeof(*i)); 67 i = *a; 68 69 STRLIST_FOREACH(s, l) 70 *i++ = xstrdup(s->value); 71 *i = NULL; 72 } 73 74 void 75 strlist_print(const struct strlist *l, FILE *f, int esc) 76 { 77 const struct string *s; 78 int quote, first = 1; 79 const char *p; 80 81 STRLIST_FOREACH(s, l) { 82 if (!first) 83 putc(' ', f); 84 quote = 0; 85 if (esc) { 86 for (p = s->value; *p; p++) { 87 if ((*p >= '0' && *p <= '9') 88 || (*p >= 'a' && *p <= 'z') 89 || (*p >= 'A' && *p <= 'Z') 90 || *p == '.' || *p == '/' 91 || *p == '-' || *p == '_') 92 continue; 93 quote = 1; 94 break; 95 } 96 } 97 if (quote) 98 putc('"', f); 99 for (p = s->value; *p; p++) { 100 if (quote && (*p == '"' || *p == '$' 101 || *p == '\\' || *p == '`')) 102 putc('\\', f); 103 putc(*p, f); 104 } 105 if (quote) 106 putc('"', f); 107 first = 0; 108 } 109 } 110 111 void 112 strlist_append_nocopy(struct strlist *l, char *val) 113 { 114 struct string *s; 115 116 s = xmalloc(sizeof(*s)); 117 s->next = NULL; 118 s->value = val; 119 if (l->last != NULL) { 120 l->last->next = s; 121 l->last = s; 122 } else { 123 l->last = s; 124 l->first = s; 125 } 126 } 127 128 void 129 strlist_append(struct strlist *l, const char *val) 130 { 131 strlist_append_nocopy(l, xstrdup(val)); 132 } 133 134 void 135 strlist_append_list(struct strlist *l, const struct strlist *l2) 136 { 137 struct string *s; 138 139 STRLIST_FOREACH(s, l2) 140 strlist_append(l, s->value); 141 } 142 143 void 144 strlist_append_array(struct strlist *l, const char * const *strings) 145 { 146 for (; *strings != NULL; ++strings) 147 strlist_append(l, *strings); 148 } 149 150 void 151 strlist_prepend_nocopy(struct strlist *l, char *val) 152 { 153 struct string *s; 154 155 s = xmalloc(sizeof(*s)); 156 s->next = l->first; 157 s->value = val; 158 l->first = s; 159 if (l->last == NULL) { 160 l->last = s; 161 } 162 } 163 164 void 165 strlist_prepend(struct strlist *l, const char *val) 166 { 167 strlist_prepend_nocopy(l, xstrdup(val)); 168 } 169 170 void 171 strlist_prepend_list(struct strlist *l, const struct strlist *l2) 172 { 173 struct string *s, *s2, *s3, *s4; 174 175 if (STRLIST_EMPTY(l2)) 176 return; 177 178 if (STRLIST_EMPTY(l)) { 179 strlist_append_list(l, l2); 180 return; 181 } 182 183 s2 = NULL; 184 s4 = l->first; 185 STRLIST_FOREACH(s, l2) { 186 s3 = xmalloc(sizeof(*s3)); 187 s3->value = xstrdup(s->value); 188 s3->next = s4; 189 if (s2 == NULL) 190 l->first = s3; 191 else 192 s2->next = s3; 193 } 194 } 195