Annotation of embedaddon/strongswan/src/include/sys/queue.h, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1991, 1993
3: * The Regents of the University of California. All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the University nor the names of its contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: *
29: * @(#)queue.h 8.5 (Berkeley) 8/20/94
30: */
31:
32: #ifndef _SYS_QUEUE_H_
33: #define _SYS_QUEUE_H_
34:
35: /*
36: * This file defines five types of data structures: singly-linked lists,
37: * lists, simple queues, tail queues, and circular queues.
38: *
39: * A singly-linked list is headed by a single forward pointer. The
40: * elements are singly linked for minimum space and pointer manipulation
41: * overhead at the expense of O(n) removal for arbitrary elements. New
42: * elements can be added to the list after an existing element or at the
43: * head of the list. Elements being removed from the head of the list
44: * should use the explicit macro for this purpose for optimum
45: * efficiency. A singly-linked list may only be traversed in the forward
46: * direction. Singly-linked lists are ideal for applications with large
47: * datasets and few or no removals or for implementing a LIFO queue.
48: *
49: * A list is headed by a single forward pointer (or an array of forward
50: * pointers for a hash table header). The elements are doubly linked
51: * so that an arbitrary element can be removed without a need to
52: * traverse the list. New elements can be added to the list before
53: * or after an existing element or at the head of the list. A list
54: * may only be traversed in the forward direction.
55: *
56: * A simple queue is headed by a pair of pointers, one the head of the
57: * list and the other to the tail of the list. The elements are singly
58: * linked to save space, so elements can only be removed from the
59: * head of the list. New elements can be added to the list after
60: * an existing element, at the head of the list, or at the end of the
61: * list. A simple queue may only be traversed in the forward direction.
62: *
63: * A tail queue is headed by a pair of pointers, one to the head of the
64: * list and the other to the tail of the list. The elements are doubly
65: * linked so that an arbitrary element can be removed without a need to
66: * traverse the list. New elements can be added to the list before or
67: * after an existing element, at the head of the list, or at the end of
68: * the list. A tail queue may be traversed in either direction.
69: *
70: * A circle queue is headed by a pair of pointers, one to the head of the
71: * list and the other to the tail of the list. The elements are doubly
72: * linked so that an arbitrary element can be removed without a need to
73: * traverse the list. New elements can be added to the list before or after
74: * an existing element, at the head of the list, or at the end of the list.
75: * A circle queue may be traversed in either direction, but has a more
76: * complex end of list detection.
77: *
78: * For details on the use of these macros, see the queue(3) manual page.
79: */
80:
81: /*
82: * List definitions.
83: */
84: #define LIST_HEAD(name, type) \
85: struct name { \
86: struct type *lh_first; /* first element */ \
87: }
88:
89: #define LIST_HEAD_INITIALIZER(head) \
90: { NULL }
91:
92: #define LIST_ENTRY(type) \
93: struct { \
94: struct type *le_next; /* next element */ \
95: struct type **le_prev; /* address of previous next element */ \
96: }
97:
98: /*
99: * List functions.
100: */
101: #define LIST_INIT(head) do { \
102: (head)->lh_first = NULL; \
103: } while (/*CONSTCOND*/0)
104:
105: #define LIST_INSERT_AFTER(listelm, elm, field) do { \
106: if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
107: (listelm)->field.le_next->field.le_prev = \
108: &(elm)->field.le_next; \
109: (listelm)->field.le_next = (elm); \
110: (elm)->field.le_prev = &(listelm)->field.le_next; \
111: } while (/*CONSTCOND*/0)
112:
113: #define LIST_INSERT_BEFORE(listelm, elm, field) do { \
114: (elm)->field.le_prev = (listelm)->field.le_prev; \
115: (elm)->field.le_next = (listelm); \
116: *(listelm)->field.le_prev = (elm); \
117: (listelm)->field.le_prev = &(elm)->field.le_next; \
118: } while (/*CONSTCOND*/0)
119:
120: #define LIST_INSERT_HEAD(head, elm, field) do { \
121: if (((elm)->field.le_next = (head)->lh_first) != NULL) \
122: (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
123: (head)->lh_first = (elm); \
124: (elm)->field.le_prev = &(head)->lh_first; \
125: } while (/*CONSTCOND*/0)
126:
127: #define LIST_REMOVE(elm, field) do { \
128: if ((elm)->field.le_next != NULL) \
129: (elm)->field.le_next->field.le_prev = \
130: (elm)->field.le_prev; \
131: *(elm)->field.le_prev = (elm)->field.le_next; \
132: } while (/*CONSTCOND*/0)
133:
134: #define LIST_FOREACH(var, head, field) \
135: for ((var) = ((head)->lh_first); \
136: (var); \
137: (var) = ((var)->field.le_next))
138:
139: /*
140: * List access methods.
141: */
142: #define LIST_EMPTY(head) ((head)->lh_first == NULL)
143: #define LIST_FIRST(head) ((head)->lh_first)
144: #define LIST_NEXT(elm, field) ((elm)->field.le_next)
145:
146:
147: /*
148: * Singly-linked List definitions.
149: */
150: #define SLIST_HEAD(name, type) \
151: struct name { \
152: struct type *slh_first; /* first element */ \
153: }
154:
155: #define SLIST_HEAD_INITIALIZER(head) \
156: { NULL }
157:
158: #define SLIST_ENTRY(type) \
159: struct { \
160: struct type *sle_next; /* next element */ \
161: }
162:
163: /*
164: * Singly-linked List functions.
165: */
166: #define SLIST_INIT(head) do { \
167: (head)->slh_first = NULL; \
168: } while (/*CONSTCOND*/0)
169:
170: #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
171: (elm)->field.sle_next = (slistelm)->field.sle_next; \
172: (slistelm)->field.sle_next = (elm); \
173: } while (/*CONSTCOND*/0)
174:
175: #define SLIST_INSERT_HEAD(head, elm, field) do { \
176: (elm)->field.sle_next = (head)->slh_first; \
177: (head)->slh_first = (elm); \
178: } while (/*CONSTCOND*/0)
179:
180: #define SLIST_REMOVE_HEAD(head, field) do { \
181: (head)->slh_first = (head)->slh_first->field.sle_next; \
182: } while (/*CONSTCOND*/0)
183:
184: #define SLIST_REMOVE(head, elm, type, field) do { \
185: if ((head)->slh_first == (elm)) { \
186: SLIST_REMOVE_HEAD((head), field); \
187: } \
188: else { \
189: struct type *curelm = (head)->slh_first; \
190: while(curelm->field.sle_next != (elm)) \
191: curelm = curelm->field.sle_next; \
192: curelm->field.sle_next = \
193: curelm->field.sle_next->field.sle_next; \
194: } \
195: } while (/*CONSTCOND*/0)
196:
197: #define SLIST_FOREACH(var, head, field) \
198: for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
199:
200: /*
201: * Singly-linked List access methods.
202: */
203: #define SLIST_EMPTY(head) ((head)->slh_first == NULL)
204: #define SLIST_FIRST(head) ((head)->slh_first)
205: #define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
206:
207:
208: /*
209: * Singly-linked Tail queue declarations.
210: */
211: #define STAILQ_HEAD(name, type) \
212: struct name { \
213: struct type *stqh_first; /* first element */ \
214: struct type **stqh_last; /* addr of last next element */ \
215: }
216:
217: #define STAILQ_HEAD_INITIALIZER(head) \
218: { NULL, &(head).stqh_first }
219:
220: #define STAILQ_ENTRY(type) \
221: struct { \
222: struct type *stqe_next; /* next element */ \
223: }
224:
225: /*
226: * Singly-linked Tail queue functions.
227: */
228: #define STAILQ_INIT(head) do { \
229: (head)->stqh_first = NULL; \
230: (head)->stqh_last = &(head)->stqh_first; \
231: } while (/*CONSTCOND*/0)
232:
233: #define STAILQ_INSERT_HEAD(head, elm, field) do { \
234: if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
235: (head)->stqh_last = &(elm)->field.stqe_next; \
236: (head)->stqh_first = (elm); \
237: } while (/*CONSTCOND*/0)
238:
239: #define STAILQ_INSERT_TAIL(head, elm, field) do { \
240: (elm)->field.stqe_next = NULL; \
241: *(head)->stqh_last = (elm); \
242: (head)->stqh_last = &(elm)->field.stqe_next; \
243: } while (/*CONSTCOND*/0)
244:
245: #define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
246: if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
247: (head)->stqh_last = &(elm)->field.stqe_next; \
248: (listelm)->field.stqe_next = (elm); \
249: } while (/*CONSTCOND*/0)
250:
251: #define STAILQ_REMOVE_HEAD(head, field) do { \
252: if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
253: (head)->stqh_last = &(head)->stqh_first; \
254: } while (/*CONSTCOND*/0)
255:
256: #define STAILQ_REMOVE(head, elm, type, field) do { \
257: if ((head)->stqh_first == (elm)) { \
258: STAILQ_REMOVE_HEAD((head), field); \
259: } else { \
260: struct type *curelm = (head)->stqh_first; \
261: while (curelm->field.stqe_next != (elm)) \
262: curelm = curelm->field.stqe_next; \
263: if ((curelm->field.stqe_next = \
264: curelm->field.stqe_next->field.stqe_next) == NULL) \
265: (head)->stqh_last = &(curelm)->field.stqe_next; \
266: } \
267: } while (/*CONSTCOND*/0)
268:
269: #define STAILQ_FOREACH(var, head, field) \
270: for ((var) = ((head)->stqh_first); \
271: (var); \
272: (var) = ((var)->field.stqe_next))
273:
274: /*
275: * Singly-linked Tail queue access methods.
276: */
277: #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
278: #define STAILQ_FIRST(head) ((head)->stqh_first)
279: #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
280:
281:
282: /*
283: * Simple queue definitions.
284: */
285: #define SIMPLEQ_HEAD(name, type) \
286: struct name { \
287: struct type *sqh_first; /* first element */ \
288: struct type **sqh_last; /* addr of last next element */ \
289: }
290:
291: #define SIMPLEQ_HEAD_INITIALIZER(head) \
292: { NULL, &(head).sqh_first }
293:
294: #define SIMPLEQ_ENTRY(type) \
295: struct { \
296: struct type *sqe_next; /* next element */ \
297: }
298:
299: /*
300: * Simple queue functions.
301: */
302: #define SIMPLEQ_INIT(head) do { \
303: (head)->sqh_first = NULL; \
304: (head)->sqh_last = &(head)->sqh_first; \
305: } while (/*CONSTCOND*/0)
306:
307: #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
308: if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
309: (head)->sqh_last = &(elm)->field.sqe_next; \
310: (head)->sqh_first = (elm); \
311: } while (/*CONSTCOND*/0)
312:
313: #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
314: (elm)->field.sqe_next = NULL; \
315: *(head)->sqh_last = (elm); \
316: (head)->sqh_last = &(elm)->field.sqe_next; \
317: } while (/*CONSTCOND*/0)
318:
319: #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
320: if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
321: (head)->sqh_last = &(elm)->field.sqe_next; \
322: (listelm)->field.sqe_next = (elm); \
323: } while (/*CONSTCOND*/0)
324:
325: #define SIMPLEQ_REMOVE_HEAD(head, field) do { \
326: if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
327: (head)->sqh_last = &(head)->sqh_first; \
328: } while (/*CONSTCOND*/0)
329:
330: #define SIMPLEQ_REMOVE(head, elm, type, field) do { \
331: if ((head)->sqh_first == (elm)) { \
332: SIMPLEQ_REMOVE_HEAD((head), field); \
333: } else { \
334: struct type *curelm = (head)->sqh_first; \
335: while (curelm->field.sqe_next != (elm)) \
336: curelm = curelm->field.sqe_next; \
337: if ((curelm->field.sqe_next = \
338: curelm->field.sqe_next->field.sqe_next) == NULL) \
339: (head)->sqh_last = &(curelm)->field.sqe_next; \
340: } \
341: } while (/*CONSTCOND*/0)
342:
343: #define SIMPLEQ_FOREACH(var, head, field) \
344: for ((var) = ((head)->sqh_first); \
345: (var); \
346: (var) = ((var)->field.sqe_next))
347:
348: /*
349: * Simple queue access methods.
350: */
351: #define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
352: #define SIMPLEQ_FIRST(head) ((head)->sqh_first)
353: #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
354:
355:
356: /*
357: * Tail queue definitions.
358: */
359: #define _TAILQ_HEAD(name, type, qual) \
360: struct name { \
361: qual type *tqh_first; /* first element */ \
362: qual type *qual *tqh_last; /* addr of last next element */ \
363: }
364: #define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
365:
366: #define TAILQ_HEAD_INITIALIZER(head) \
367: { NULL, &(head).tqh_first }
368:
369: #define _TAILQ_ENTRY(type, qual) \
370: struct { \
371: qual type *tqe_next; /* next element */ \
372: qual type *qual *tqe_prev; /* address of previous next element */\
373: }
374: #define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
375:
376: /*
377: * Tail queue functions.
378: */
379: #define TAILQ_INIT(head) do { \
380: (head)->tqh_first = NULL; \
381: (head)->tqh_last = &(head)->tqh_first; \
382: } while (/*CONSTCOND*/0)
383:
384: #define TAILQ_INSERT_HEAD(head, elm, field) do { \
385: if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
386: (head)->tqh_first->field.tqe_prev = \
387: &(elm)->field.tqe_next; \
388: else \
389: (head)->tqh_last = &(elm)->field.tqe_next; \
390: (head)->tqh_first = (elm); \
391: (elm)->field.tqe_prev = &(head)->tqh_first; \
392: } while (/*CONSTCOND*/0)
393:
394: #define TAILQ_INSERT_TAIL(head, elm, field) do { \
395: (elm)->field.tqe_next = NULL; \
396: (elm)->field.tqe_prev = (head)->tqh_last; \
397: *(head)->tqh_last = (elm); \
398: (head)->tqh_last = &(elm)->field.tqe_next; \
399: } while (/*CONSTCOND*/0)
400:
401: #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
402: if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
403: (elm)->field.tqe_next->field.tqe_prev = \
404: &(elm)->field.tqe_next; \
405: else \
406: (head)->tqh_last = &(elm)->field.tqe_next; \
407: (listelm)->field.tqe_next = (elm); \
408: (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
409: } while (/*CONSTCOND*/0)
410:
411: #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
412: (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
413: (elm)->field.tqe_next = (listelm); \
414: *(listelm)->field.tqe_prev = (elm); \
415: (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
416: } while (/*CONSTCOND*/0)
417:
418: #define TAILQ_REMOVE(head, elm, field) do { \
419: if (((elm)->field.tqe_next) != NULL) \
420: (elm)->field.tqe_next->field.tqe_prev = \
421: (elm)->field.tqe_prev; \
422: else \
423: (head)->tqh_last = (elm)->field.tqe_prev; \
424: *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
425: } while (/*CONSTCOND*/0)
426:
427: #define TAILQ_FOREACH(var, head, field) \
428: for ((var) = ((head)->tqh_first); \
429: (var); \
430: (var) = ((var)->field.tqe_next))
431:
432: #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
433: for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
434: (var); \
435: (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
436:
437: /*
438: * Tail queue access methods.
439: */
440: #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
441: #define TAILQ_FIRST(head) ((head)->tqh_first)
442: #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
443:
444: #define TAILQ_LAST(head, headname) \
445: (*(((struct headname *)((head)->tqh_last))->tqh_last))
446: #define TAILQ_PREV(elm, headname, field) \
447: (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
448:
449:
450: /*
451: * Circular queue definitions.
452: */
453: #define CIRCLEQ_HEAD(name, type) \
454: struct name { \
455: struct type *cqh_first; /* first element */ \
456: struct type *cqh_last; /* last element */ \
457: }
458:
459: #define CIRCLEQ_HEAD_INITIALIZER(head) \
460: { (void *)&head, (void *)&head }
461:
462: #define CIRCLEQ_ENTRY(type) \
463: struct { \
464: struct type *cqe_next; /* next element */ \
465: struct type *cqe_prev; /* previous element */ \
466: }
467:
468: /*
469: * Circular queue functions.
470: */
471: #define CIRCLEQ_INIT(head) do { \
472: (head)->cqh_first = (void *)(head); \
473: (head)->cqh_last = (void *)(head); \
474: } while (/*CONSTCOND*/0)
475:
476: #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
477: (elm)->field.cqe_next = (listelm)->field.cqe_next; \
478: (elm)->field.cqe_prev = (listelm); \
479: if ((listelm)->field.cqe_next == (void *)(head)) \
480: (head)->cqh_last = (elm); \
481: else \
482: (listelm)->field.cqe_next->field.cqe_prev = (elm); \
483: (listelm)->field.cqe_next = (elm); \
484: } while (/*CONSTCOND*/0)
485:
486: #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
487: (elm)->field.cqe_next = (listelm); \
488: (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
489: if ((listelm)->field.cqe_prev == (void *)(head)) \
490: (head)->cqh_first = (elm); \
491: else \
492: (listelm)->field.cqe_prev->field.cqe_next = (elm); \
493: (listelm)->field.cqe_prev = (elm); \
494: } while (/*CONSTCOND*/0)
495:
496: #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
497: (elm)->field.cqe_next = (head)->cqh_first; \
498: (elm)->field.cqe_prev = (void *)(head); \
499: if ((head)->cqh_last == (void *)(head)) \
500: (head)->cqh_last = (elm); \
501: else \
502: (head)->cqh_first->field.cqe_prev = (elm); \
503: (head)->cqh_first = (elm); \
504: } while (/*CONSTCOND*/0)
505:
506: #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
507: (elm)->field.cqe_next = (void *)(head); \
508: (elm)->field.cqe_prev = (head)->cqh_last; \
509: if ((head)->cqh_first == (void *)(head)) \
510: (head)->cqh_first = (elm); \
511: else \
512: (head)->cqh_last->field.cqe_next = (elm); \
513: (head)->cqh_last = (elm); \
514: } while (/*CONSTCOND*/0)
515:
516: #define CIRCLEQ_REMOVE(head, elm, field) do { \
517: if ((elm)->field.cqe_next == (void *)(head)) \
518: (head)->cqh_last = (elm)->field.cqe_prev; \
519: else \
520: (elm)->field.cqe_next->field.cqe_prev = \
521: (elm)->field.cqe_prev; \
522: if ((elm)->field.cqe_prev == (void *)(head)) \
523: (head)->cqh_first = (elm)->field.cqe_next; \
524: else \
525: (elm)->field.cqe_prev->field.cqe_next = \
526: (elm)->field.cqe_next; \
527: } while (/*CONSTCOND*/0)
528:
529: #define CIRCLEQ_FOREACH(var, head, field) \
530: for ((var) = ((head)->cqh_first); \
531: (var) != (const void *)(head); \
532: (var) = ((var)->field.cqe_next))
533:
534: #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
535: for ((var) = ((head)->cqh_last); \
536: (var) != (const void *)(head); \
537: (var) = ((var)->field.cqe_prev))
538:
539: /*
540: * Circular queue access methods.
541: */
542: #define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
543: #define CIRCLEQ_FIRST(head) ((head)->cqh_first)
544: #define CIRCLEQ_LAST(head) ((head)->cqh_last)
545: #define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
546: #define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
547:
548: #define CIRCLEQ_LOOP_NEXT(head, elm, field) \
549: (((elm)->field.cqe_next == (void *)(head)) \
550: ? ((head)->cqh_first) \
551: : (elm->field.cqe_next))
552: #define CIRCLEQ_LOOP_PREV(head, elm, field) \
553: (((elm)->field.cqe_prev == (void *)(head)) \
554: ? ((head)->cqh_last) \
555: : (elm->field.cqe_prev))
556:
557: #endif /* sys/queue.h */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>