xref: /netbsd/external/bsd/pcc/dist/pcc/driver/list.c (revision 6935091c)
1 /*	Id	*/
2 /*	$NetBSD: list.c,v 1.1.1.1 2016/02/09 20:29:12 plunky Exp $	*/
3 
4 /*-
5  * Copyright (c) 2014 Iain Hibbert.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 
30 #include "driver.h"
31 
32 /*
33  * A list is an opaque collection of strings. We can add strings, another
34  * list or an array of strings to the list. We can get a pointer to the
35  * array of strings in the list and the number of strings in it, and we
36  * can free the entire list when we are done.
37  */
38 
39 #define COUNT	64		/* element count increments */
40 #define BLOCK	4096		/* buffer size increments */
41 
42 struct list {
43 	const char **	array;
44 	size_t		arraylen;
45 	size_t		arrayused;
46 	void *		buf;
47 	size_t		buflen;
48 	size_t		bufused;
49 };
50 
51 /*
52  * return array pointer
53  */
54 const char **
list_array(const struct list * l)55 list_array(const struct list *l)
56 {
57 
58 	return l->array;
59 }
60 
61 /*
62  * return array count
63  */
64 size_t
list_count(const struct list * l)65 list_count(const struct list *l)
66 {
67 
68 	return l->arrayused;
69 }
70 
71 /*
72  * allocate a new list header
73  */
74 struct list *
list_alloc(void)75 list_alloc(void)
76 {
77 	struct list *l;
78 
79 	l = xmalloc(sizeof(struct list));
80 	l->array = xmalloc(COUNT * sizeof(char *));
81 	l->array[0] = NULL;
82 	l->arraylen = COUNT;
83 	l->arrayused = 0;
84 	l->buf = NULL;
85 	l->buflen = 0;
86 	l->bufused = 0;
87 
88 	return l;
89 }
90 
91 /*
92  * release a list header and associated storage
93  */
94 void
list_free(struct list * l)95 list_free(struct list *l)
96 {
97 
98 	free(l->array);
99 	free(l->buf);
100 	free(l);
101 }
102 
103 /*
104  * print out a list
105  */
106 void
list_print(const struct list * l)107 list_print(const struct list *l)
108 {
109 	size_t i;
110 
111 	for (i = 0; i < l->arrayused; i++)
112 		fprintf(stderr, "%s%s\n", (i == 0 ? "" : " "), l->array[i]);
113 }
114 
115 /*
116  * add const string to list
117  */
118 void
list_add_nocopy(struct list * l,const char * str)119 list_add_nocopy(struct list *l, const char *str)
120 {
121 
122 	l->array[l->arrayused++] = str;
123 
124 	if (l->arrayused == l->arraylen) {
125 		l->arraylen += COUNT;
126 		l->array = xrealloc(l->array, l->arraylen * sizeof(char *));
127 	}
128 
129 	l->array[l->arrayused] = NULL;
130 }
131 
132 /*
133  * add formatted string to list, storing in list buffer
134  */
135 void
list_add(struct list * l,const char * str,...)136 list_add(struct list *l, const char *str, ...)
137 {
138 	va_list ap;
139 	void *p;
140 	size_t s;
141 	int n;
142 
143 	for (;;) {
144 		p = l->buf + l->bufused;
145 		s = l->buflen - l->bufused;
146 
147 		va_start(ap, str);
148 		n = vsnprintf(p, s, str, ap);
149 		va_end(ap);
150 
151 		if (n < 0)
152 			error("vsnprintf");
153 
154 		if ((unsigned int)n < s)
155 			break;
156 
157 		l->buflen += BLOCK;
158 		l->buf = xrealloc(l->buf, l->buflen);
159 	}
160 
161 	list_add_nocopy(l, p);
162 	l->bufused += n;
163 }
164 
165 /*
166  * add a NULL terminated array of const data to list
167  */
168 void
list_add_array(struct list * l,const char ** a)169 list_add_array(struct list *l, const char **a)
170 {
171 
172 	while (*a)
173 		list_add_nocopy(l, *a++);
174 }
175 
176 /*
177  * add another list to list (with copy)
178  */
179 void
list_add_list(struct list * l1,const struct list * l2)180 list_add_list(struct list *l1, const struct list *l2)
181 {
182 	size_t i;
183 
184 	for (i = 0; i < l2->arrayused; i++)
185 		list_add(l1, l2->array[i]);
186 }
187