change gdium conf to print message out both on uart and lcd
[pmon-gdium.git] / tools / pmoncfg / pack.c
blobfc4a309bfe840337ee6da3df2217756919a24f56
1 /* $OpenBSD: pack.c,v 1.9 1999/01/19 01:11:25 niklas Exp $ */
2 /* $NetBSD: pack.c,v 1.5 1996/08/31 21:15:11 mycroft Exp $ */
4 /*
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
8 * This software was developed by the Computer Systems Engineering group
9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10 * contributed to Berkeley.
12 * All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by the University of
15 * California, Lawrence Berkeley Laboratories.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. All advertising materials mentioning features or use of this software
26 * must display the following acknowledgement:
27 * This product includes software developed by the University of
28 * California, Berkeley and its contributors.
29 * 4. Neither the name of the University nor the names of its contributors
30 * may be used to endorse or promote products derived from this software
31 * without specific prior written permission.
33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
45 * from: @(#)pack.c 8.1 (Berkeley) 6/6/93
48 #include <sys/param.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include "config.h"
54 * Packing. We have three separate kinds of packing here.
56 * First, we pack device instances, to collapse things like
58 * uba0 at sbi0 nexus ?
59 * uba0 at bi0 nexus ?
61 * into a single instance that is "at sbi0 or bi0".
63 * Second, we pack locators. Given something like
65 * hp0 at mba0 drive 0
66 * hp* at mba* drive ?
67 * ht0 at mba0 drive 0
68 * tu0 at ht0 slave 0
69 * ht* at mba* drive ?
70 * tu* at ht* slave ?
72 * (where the default drive and slave numbers are -1), we have three
73 * locators whose value is 0 and three whose value is -1. Rather than
74 * emitting six integers, we emit just two.
76 * Finally, we pack parent vectors. This is very much like packing
77 * locators. Unlike locators, however, parent vectors are always
78 * terminated by -1 (rather like the way C strings always end with
79 * a NUL).
81 * When packing locators, we would like to find sequences such as
82 * {1 2 3} {2 3 4} {3} {4 5}
83 * and turn this into the flat sequence {1 2 3 4 5}, with each subsequence
84 * given by the appropriate offset (here 0, 1, 2, and 3 respectively).
85 * When we pack parent vectors, overlap of this sort is impossible.
86 * Non-overlapping packing is much easier, and so we use that here
87 * and miss out on the chance to squeeze the locator sequence optimally.
88 * (So it goes.)
91 typedef int (*vec_cmp_func) (const void *, int, int);
93 #define TAILHSIZE 128
94 #define PVHASH(i) ((i) & (TAILHSIZE - 1))
95 #define LOCHASH(l) (((long)(l) >> 2) & (TAILHSIZE - 1))
96 struct tails {
97 struct tails *t_next;
98 int t_ends_at;
101 static struct tails *tails[TAILHSIZE];
102 static int locspace;
103 static int pvecspace;
104 static int longest_pvec;
106 static void packdevi(void);
107 static void packlocs(void);
108 static void packpvec(void);
110 static void addparents(struct devi *src, struct devi *dst);
111 static int nparents(struct devi **, struct devbase *, int);
112 static int sameas(struct devi *, struct devi *);
113 static int findvec(const void *, int, int, vec_cmp_func, int);
114 static int samelocs(const void *, int, int);
115 static int addlocs(const char **, int);
116 static int loclencmp(const void *, const void *);
117 static int samepv(const void *, int, int);
118 static int addpv(short *, int);
119 static int pvlencmp(const void *, const void *);
120 static void resettails(void);
122 void
123 pack()
125 register struct devi *i;
126 register int n;
128 /* Pack instances and make parent vectors. */
129 packdevi();
132 * Now that we know what we have, find upper limits on space
133 * needed for the loc[] and pv[] tables, and find the longest
134 * single pvec. The loc and pv table sizes are bounded by
135 * what we would get if no packing occurred.
137 locspace = pvecspace = 0;
138 for (i = alldevi; i != NULL; i = i->i_next) {
139 if (i->i_collapsed)
140 continue;
141 locspace += i->i_atattr->a_loclen;
142 n = i->i_pvlen + 1;
143 if (n > longest_pvec)
144 longest_pvec = n;
145 pvecspace += n;
148 /* Allocate and pack loc[]. */
149 locators.vec = emalloc(locspace * sizeof(*locators.vec));
150 locators.used = 0;
151 packlocs();
153 /* Allocate and pack pv[]. */
154 parents.vec = emalloc(pvecspace * sizeof(*parents.vec));
155 parents.used = 0;
156 packpvec();
160 * Pack instances together wherever possible. When everything is
161 * packed, go back and set up the parents for each. We must do this
162 * on a second pass because during the first one, we do not know which,
163 * if any, of the parents will collapse during packing.
165 void
166 packdevi()
168 register struct devi *i, *l, *p;
169 register struct deva *d;
170 register int j, m, n;
172 packed = emalloc((ndevi + 1) * sizeof *packed);
173 n = 0;
174 for (d = alldevas; d != NULL; d = d->d_next) {
176 * For each instance of each attachment, add or collapse
177 * all its aliases.
179 for (i = d->d_ihead; i != NULL; i = i->i_asame) {
180 m = n;
181 for (l = i; l != NULL; l = l->i_alias) {
182 /* Skip if we already handled this one. */
183 if (l->i_cfindex >= 0)
184 continue;
185 l->i_pvlen = 0;
186 l->i_pvoff = -1;
187 l->i_locoff = -1;
188 /* try to find an equivalent for l */
189 for (j = m; j < n; j++) {
190 p = packed[j];
191 if (sameas(l, p)) {
192 l->i_collapsed = 1;
193 l->i_cfindex = p->i_cfindex;
194 goto nextalias;
197 /* could not find a suitable alias */
198 l->i_collapsed = 0;
199 l->i_cfindex = n;
200 l->i_parents = emalloc(sizeof(*l->i_parents));
201 l->i_parents[0] = NULL;
202 packed[n++] = l;
203 nextalias:;
207 npacked = n;
208 packed[n] = NULL;
209 for (i = alldevi; i != NULL; i = i->i_next)
210 addparents(i, packed[i->i_cfindex]);
214 * Return true if two aliases are "the same". In this case, they need
215 * to attach via the same attribute, have the same config flags, and
216 * have the same locators.
218 static int
219 sameas(i1, i2)
220 register struct devi *i1, *i2;
222 register const char **p1, **p2;
224 if (i1->i_atattr != i2->i_atattr)
225 return (0);
226 if (i1->i_cfflags != i2->i_cfflags)
227 return (0);
228 for (p1 = i1->i_locs, p2 = i2->i_locs; *p1 == *p2; p2++)
229 if (*p1++ == 0)
230 return (1);
231 return 0;
235 * Add the parents associated with "src" to the (presumably uncollapsed)
236 * instance "dst".
238 static void
239 addparents(src, dst)
240 register struct devi *src, *dst;
242 register struct nvlist *nv;
243 register struct devi *i, **p, **q;
244 register int j, n, old, new, ndup;
246 if (dst->i_collapsed)
247 panic("addparents() i_collapsed");
249 /* Collect up list of parents to add. */
250 if (src->i_at == NULL) /* none, 'cuz "at root" */
251 return;
252 if (src->i_atdev != NULL) {
253 n = nparents(NULL, src->i_atdev, src->i_atunit);
254 p = emalloc(n * sizeof *p);
255 if (n == 0)
256 return;
257 (void)nparents(p, src->i_atdev, src->i_atunit);
258 } else {
259 n = 0;
260 for (nv = src->i_atattr->a_refs; nv != NULL; nv = nv->nv_next)
261 n += nparents(NULL, nv->nv_ptr, src->i_atunit);
262 if (n == 0)
263 return;
264 p = emalloc(n * sizeof *p);
265 n = 0;
266 for (nv = src->i_atattr->a_refs; nv != NULL; nv = nv->nv_next)
267 n += nparents(p + n, nv->nv_ptr, src->i_atunit);
269 /* Now elide duplicates. */
270 ndup = 0;
271 for (j = 0; j < n; j++) {
272 i = p[j];
273 for (q = dst->i_parents; *q != NULL; q++) {
274 if (*q == i) {
275 ndup++;
276 p[j] = NULL;
277 break;
281 /* Finally, add all the non-duplicates. */
282 old = dst->i_pvlen;
283 new = old + (n - ndup);
284 if (old > new)
285 panic("addparents() old > new");
286 if (old == new) {
287 free(p);
288 return;
290 dst->i_parents = q = erealloc(dst->i_parents, (new + 1) * sizeof(*q));
291 dst->i_pvlen = new;
292 q[new] = NULL;
293 q += old;
294 for (j = 0; j < n; j++)
295 if (p[j] != NULL)
296 *q++ = p[j];
297 free(p);
301 * Count up parents, and optionally store pointers to each.
303 static int
304 nparents(p, dev, unit)
305 register struct devi **p;
306 register struct devbase *dev;
307 register int unit;
309 register struct devi *i, *l;
310 register int n;
312 n = 0;
313 /* for each instance ... */
314 for (i = dev->d_ihead; i != NULL; i = i->i_bsame) {
315 /* ... take each un-collapsed alias */
316 for (l = i; l != NULL; l = l->i_alias) {
317 if (!l->i_collapsed &&
318 (unit == WILD || unit == l->i_unit)) {
319 if (p != NULL)
320 *p++ = l;
321 n++;
325 return (n);
328 static void
329 packlocs()
331 register struct devi **p, *i;
332 register int l, o;
334 qsort(packed, npacked, sizeof *packed, loclencmp);
335 for (p = packed; (i = *p) != NULL; p++) {
336 if ((l = i->i_atattr->a_loclen) > 0) {
337 o = findvec(i->i_locs, LOCHASH(i->i_locs[l - 1]), l,
338 samelocs, locators.used);
339 i->i_locoff = o < 0 ? addlocs(i->i_locs, l) : o;
340 } else
341 i->i_locoff = -1;
343 resettails();
346 static void
347 packpvec()
349 register struct devi **p, *i, **par;
350 register int l, v, o;
351 register short *vec;
353 vec = emalloc(longest_pvec * sizeof(*vec));
354 qsort(packed, npacked, sizeof *packed, pvlencmp);
355 for (p = packed; (i = *p) != NULL; p++) {
356 l = i->i_pvlen;
357 if (l > longest_pvec) panic("packpvec");
358 par = i->i_parents;
359 for (v = 0; v < l; v++)
360 vec[v] = par[v]->i_cfindex;
361 if (l == 0 ||
362 (o = findvec(vec, PVHASH(vec[l - 1]), l,
363 samepv, parents.used)) < 0)
364 o = addpv(vec, l);
365 i->i_pvoff = o;
367 free(vec);
368 resettails();
372 * Return the index at which the given vector already exists, or -1
373 * if it is not anywhere in the current set. If we return -1, we assume
374 * our caller will add it at the end of the current set, and we make
375 * sure that next time, we will find it there.
377 static int
378 findvec(ptr, hash, len, cmp, nextplace)
379 const void *ptr;
380 int hash, len;
381 vec_cmp_func cmp;
382 int nextplace;
384 register struct tails *t, **hp;
385 register int off;
387 hp = &tails[hash];
388 for (t = *hp; t != NULL; t = t->t_next) {
389 off = t->t_ends_at - len;
390 if (off >= 0 && (*cmp)(ptr, off, len))
391 return (off);
393 t = emalloc(sizeof(*t));
394 t->t_next = *hp;
395 *hp = t;
396 t->t_ends_at = nextplace + len;
397 return (-1);
401 * Comparison function for locators.
403 static int
404 samelocs(ptr, off, len)
405 const void *ptr;
406 int off;
407 register int len;
409 register const char **p, **q;
411 for (p = &locators.vec[off], q = (const char **)ptr; --len >= 0;)
412 if (*p++ != *q++)
413 return (0); /* different */
414 return (1); /* same */
418 * Add the given locators at the end of the global loc[] table.
420 static int
421 addlocs(locs, len)
422 register const char **locs;
423 register int len;
425 register const char **p;
426 register int ret;
428 ret = locators.used;
429 if ((locators.used = ret + len) > locspace)
430 panic("addlocs: overrun");
431 for (p = &locators.vec[ret]; --len >= 0;)
432 *p++ = *locs++;
433 return (ret);
437 * Comparison function for qsort-by-locator-length, longest first.
438 * We rashly assume that subtraction of these lengths does not overflow.
440 static int
441 loclencmp(a, b)
442 const void *a, *b;
444 register int l1, l2;
446 l1 = (*(struct devi **)a)->i_atattr->a_loclen;
447 l2 = (*(struct devi **)b)->i_atattr->a_loclen;
448 return (l2 - l1);
452 * Comparison function for parent vectors.
454 static int
455 samepv(ptr, off, len)
456 const void *ptr;
457 int off;
458 register int len;
460 register short *p, *q;
462 for (p = &parents.vec[off], q = (short *)ptr; --len >= 0;)
463 if (*p++ != *q++)
464 return (0); /* different */
465 return (1); /* same */
469 * Add the given parent vectors at the end of the global pv[] table.
471 static int
472 addpv(pv, len)
473 register short *pv;
474 register int len;
476 register short *p;
477 register int ret;
478 static int firstend = -1;
481 * If the vector is empty, reuse the first -1. It will be
482 * there if there are any nonempty vectors at all, since we
483 * do the longest first. If there are no nonempty vectors,
484 * something is probably wrong, but we will ignore that here.
486 if (len == 0 && firstend >= 0)
487 return (firstend);
488 len++; /* account for trailing -1 */
489 ret = parents.used;
490 if ((parents.used = ret + len) > pvecspace)
491 panic("addpv: overrun");
492 for (p = &parents.vec[ret]; --len > 0;)
493 *p++ = *pv++;
494 *p = -1;
495 if (firstend < 0)
496 firstend = parents.used - 1;
497 return (ret);
501 * Comparison function for qsort-by-parent-vector-length, longest first.
502 * We rashly assume that subtraction of these lengths does not overflow.
504 static int
505 pvlencmp(a, b)
506 const void *a, *b;
508 register int l1, l2;
510 l1 = (*(struct devi **)a)->i_pvlen;
511 l2 = (*(struct devi **)b)->i_pvlen;
512 return (l2 - l1);
515 static void
516 resettails()
518 register struct tails **p, *t, *next;
519 register int i;
521 for (p = tails, i = TAILHSIZE; --i >= 0; p++) {
522 for (t = *p; t != NULL; t = next) {
523 next = t->t_next;
524 free(t);
526 *p = NULL;