source: trunk/src/gcc/gcc/sbitmap.c@ 1392

Last change on this file since 1392 was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 16.4 KB
Line 
1/* Simple bitmaps.
2 Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 2, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING. If not, write to the Free
18Software Foundation, 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include "config.h"
22#include "system.h"
23#include "rtl.h"
24#include "flags.h"
25#include "hard-reg-set.h"
26#include "basic-block.h"
27
28/* Bitmap manipulation routines. */
29
30/* Allocate a simple bitmap of N_ELMS bits. */
31
32sbitmap
33sbitmap_alloc (n_elms)
34 unsigned int n_elms;
35{
36 unsigned int bytes, size, amt;
37 sbitmap bmap;
38
39 size = SBITMAP_SET_SIZE (n_elms);
40 bytes = size * sizeof (SBITMAP_ELT_TYPE);
41 amt = (sizeof (struct simple_bitmap_def)
42 + bytes - sizeof (SBITMAP_ELT_TYPE));
43 bmap = (sbitmap) xmalloc (amt);
44 bmap->n_bits = n_elms;
45 bmap->size = size;
46 bmap->bytes = bytes;
47 return bmap;
48}
49
50/* Resize a simple bitmap BMAP to N_ELMS bits. If increasing the
51 size of BMAP, clear the new bits to zero if the DEF argument
52 is zero, and set them to one otherwise. */
53
54sbitmap
55sbitmap_resize (bmap, n_elms, def)
56 sbitmap bmap;
57 unsigned int n_elms;
58 int def;
59{
60 unsigned int bytes, size, amt;
61 unsigned int last_bit;
62
63 size = SBITMAP_SET_SIZE (n_elms);
64 bytes = size * sizeof (SBITMAP_ELT_TYPE);
65 if (bytes > bmap->bytes)
66 {
67 amt = (sizeof (struct simple_bitmap_def)
68 + bytes - sizeof (SBITMAP_ELT_TYPE));
69 bmap = (sbitmap) xrealloc ((PTR) bmap, amt);
70 }
71
72 if (n_elms > bmap->n_bits)
73 {
74 if (def)
75 {
76 memset ((PTR) (bmap->elms + bmap->size), -1, bytes - bmap->bytes);
77
78 /* Set the new bits if the original last element. */
79 last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
80 if (last_bit)
81 bmap->elms[bmap->size - 1]
82 |= ~((SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit));
83
84 /* Clear the unused bit in the new last element. */
85 last_bit = n_elms % SBITMAP_ELT_BITS;
86 if (last_bit)
87 bmap->elms[size - 1]
88 &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
89 }
90 else
91 memset ((PTR) (bmap->elms + bmap->size), 0, bytes - bmap->bytes);
92 }
93 else if (n_elms < bmap->n_bits)
94 {
95 /* Clear the surplus bits in the last word. */
96 last_bit = n_elms % SBITMAP_ELT_BITS;
97 if (last_bit)
98 bmap->elms[size - 1]
99 &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
100 }
101
102 bmap->n_bits = n_elms;
103 bmap->size = size;
104 bmap->bytes = bytes;
105 return bmap;
106}
107
108/* Allocate a vector of N_VECS bitmaps of N_ELMS bits. */
109
110sbitmap *
111sbitmap_vector_alloc (n_vecs, n_elms)
112 unsigned int n_vecs, n_elms;
113{
114 unsigned int i, bytes, offset, elm_bytes, size, amt, vector_bytes;
115 sbitmap *bitmap_vector;
116
117 size = SBITMAP_SET_SIZE (n_elms);
118 bytes = size * sizeof (SBITMAP_ELT_TYPE);
119 elm_bytes = (sizeof (struct simple_bitmap_def)
120 + bytes - sizeof (SBITMAP_ELT_TYPE));
121 vector_bytes = n_vecs * sizeof (sbitmap *);
122
123 /* Round up `vector_bytes' to account for the alignment requirements
124 of an sbitmap. One could allocate the vector-table and set of sbitmaps
125 separately, but that requires maintaining two pointers or creating
126 a cover struct to hold both pointers (so our result is still just
127 one pointer). Neither is a bad idea, but this is simpler for now. */
128 {
129 /* Based on DEFAULT_ALIGNMENT computation in obstack.c. */
130 struct { char x; SBITMAP_ELT_TYPE y; } align;
131 int alignment = (char *) & align.y - & align.x;
132 vector_bytes = (vector_bytes + alignment - 1) & ~ (alignment - 1);
133 }
134
135 amt = vector_bytes + (n_vecs * elm_bytes);
136 bitmap_vector = (sbitmap *) xmalloc (amt);
137
138 for (i = 0, offset = vector_bytes; i < n_vecs; i++, offset += elm_bytes)
139 {
140 sbitmap b = (sbitmap) ((char *) bitmap_vector + offset);
141
142 bitmap_vector[i] = b;
143 b->n_bits = n_elms;
144 b->size = size;
145 b->bytes = bytes;
146 }
147
148 return bitmap_vector;
149}
150
151/* Copy sbitmap SRC to DST. */
152
153void
154sbitmap_copy (dst, src)
155 sbitmap dst, src;
156{
157 memcpy (dst->elms, src->elms, sizeof (SBITMAP_ELT_TYPE) * dst->size);
158}
159
160/* Determine if a == b. */
161int
162sbitmap_equal (a, b)
163 sbitmap a, b;
164{
165 return !memcmp (a->elms, b->elms, sizeof (SBITMAP_ELT_TYPE) * a->size);
166}
167
168/* Zero all elements in a bitmap. */
169
170void
171sbitmap_zero (bmap)
172 sbitmap bmap;
173{
174 memset ((PTR) bmap->elms, 0, bmap->bytes);
175}
176
177/* Set all elements in a bitmap to ones. */
178
179void
180sbitmap_ones (bmap)
181 sbitmap bmap;
182{
183 unsigned int last_bit;
184
185 memset ((PTR) bmap->elms, -1, bmap->bytes);
186
187 last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
188 if (last_bit)
189 bmap->elms[bmap->size - 1]
190 = (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
191}
192
193/* Zero a vector of N_VECS bitmaps. */
194
195void
196sbitmap_vector_zero (bmap, n_vecs)
197 sbitmap *bmap;
198 unsigned int n_vecs;
199{
200 unsigned int i;
201
202 for (i = 0; i < n_vecs; i++)
203 sbitmap_zero (bmap[i]);
204}
205
206/* Set a vector of N_VECS bitmaps to ones. */
207
208void
209sbitmap_vector_ones (bmap, n_vecs)
210 sbitmap *bmap;
211 unsigned int n_vecs;
212{
213 unsigned int i;
214
215 for (i = 0; i < n_vecs; i++)
216 sbitmap_ones (bmap[i]);
217}
218
219/* Set DST to be A union (B - C).
220 DST = A | (B & ~C).
221 Returns true if any change is made. */
222
223bool
224sbitmap_union_of_diff_cg (dst, a, b, c)
225 sbitmap dst, a, b, c;
226{
227 unsigned int i, n = dst->size;
228 sbitmap_ptr dstp = dst->elms;
229 sbitmap_ptr ap = a->elms;
230 sbitmap_ptr bp = b->elms;
231 sbitmap_ptr cp = c->elms;
232 SBITMAP_ELT_TYPE changed = 0;
233
234 for (i = 0; i < n; i++)
235 {
236 SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & ~*cp++);
237 changed |= *dstp ^ tmp;
238 *dstp++ = tmp;
239 }
240
241 return changed != 0;
242}
243
244void
245sbitmap_union_of_diff (dst, a, b, c)
246 sbitmap dst, a, b, c;
247{
248 unsigned int i, n = dst->size;
249 sbitmap_ptr dstp = dst->elms;
250 sbitmap_ptr ap = a->elms;
251 sbitmap_ptr bp = b->elms;
252 sbitmap_ptr cp = c->elms;
253
254 for (i = 0; i < n; i++)
255 *dstp++ = *ap++ | (*bp++ & ~*cp++);
256}
257
258/* Set bitmap DST to the bitwise negation of the bitmap SRC. */
259
260void
261sbitmap_not (dst, src)
262 sbitmap dst, src;
263{
264 unsigned int i, n = dst->size;
265 sbitmap_ptr dstp = dst->elms;
266 sbitmap_ptr srcp = src->elms;
267
268 for (i = 0; i < n; i++)
269 *dstp++ = ~*srcp++;
270}
271
272/* Set the bits in DST to be the difference between the bits
273 in A and the bits in B. i.e. dst = a & (~b). */
274
275void
276sbitmap_difference (dst, a, b)
277 sbitmap dst, a, b;
278{
279 unsigned int i, dst_size = dst->size;
280 unsigned int min_size = dst->size;
281 sbitmap_ptr dstp = dst->elms;
282 sbitmap_ptr ap = a->elms;
283 sbitmap_ptr bp = b->elms;
284
285 /* A should be at least as large as DEST, to have a defined source. */
286 if (a->size < dst_size)
287 abort ();
288 /* If minuend is smaller, we simply pretend it to be zero bits, i.e.
289 only copy the subtrahend into dest. */
290 if (b->size < min_size)
291 min_size = b->size;
292 for (i = 0; i < min_size; i++)
293 *dstp++ = *ap++ & (~*bp++);
294 /* Now fill the rest of dest from A, if B was too short.
295 This makes sense only when destination and A differ. */
296 if (dst != a && i != dst_size)
297 for (; i < dst_size; i++)
298 *dstp++ = *ap++;
299}
300
301/* Set DST to be (A and B).
302 Return nonzero if any change is made. */
303
304bool
305sbitmap_a_and_b_cg (dst, a, b)
306 sbitmap dst, a, b;
307{
308 unsigned int i, n = dst->size;
309 sbitmap_ptr dstp = dst->elms;
310 sbitmap_ptr ap = a->elms;
311 sbitmap_ptr bp = b->elms;
312 SBITMAP_ELT_TYPE changed = 0;
313
314 for (i = 0; i < n; i++)
315 {
316 SBITMAP_ELT_TYPE tmp = *ap++ & *bp++;
317 changed = *dstp ^ tmp;
318 *dstp++ = tmp;
319 }
320
321 return changed != 0;
322}
323
324void
325sbitmap_a_and_b (dst, a, b)
326 sbitmap dst, a, b;
327{
328 unsigned int i, n = dst->size;
329 sbitmap_ptr dstp = dst->elms;
330 sbitmap_ptr ap = a->elms;
331 sbitmap_ptr bp = b->elms;
332
333 for (i = 0; i < n; i++)
334 *dstp++ = *ap++ & *bp++;
335}
336
337/* Set DST to be (A xor B)).
338 Return nonzero if any change is made. */
339
340bool
341sbitmap_a_xor_b_cg (dst, a, b)
342 sbitmap dst, a, b;
343{
344 unsigned int i, n = dst->size;
345 sbitmap_ptr dstp = dst->elms;
346 sbitmap_ptr ap = a->elms;
347 sbitmap_ptr bp = b->elms;
348 SBITMAP_ELT_TYPE changed = 0;
349
350 for (i = 0; i < n; i++)
351 {
352 SBITMAP_ELT_TYPE tmp = *ap++ ^ *bp++;
353 changed = *dstp ^ tmp;
354 *dstp++ = tmp;
355 }
356
357 return changed != 0;
358}
359
360void
361sbitmap_a_xor_b (dst, a, b)
362 sbitmap dst, a, b;
363{
364 unsigned int i, n = dst->size;
365 sbitmap_ptr dstp = dst->elms;
366 sbitmap_ptr ap = a->elms;
367 sbitmap_ptr bp = b->elms;
368
369 for (i = 0; i < n; i++)
370 *dstp++ = *ap++ ^ *bp++;
371}
372
373/* Set DST to be (A or B)).
374 Return nonzero if any change is made. */
375
376bool
377sbitmap_a_or_b_cg (dst, a, b)
378 sbitmap dst, a, b;
379{
380 unsigned int i, n = dst->size;
381 sbitmap_ptr dstp = dst->elms;
382 sbitmap_ptr ap = a->elms;
383 sbitmap_ptr bp = b->elms;
384 SBITMAP_ELT_TYPE changed = 0;
385
386 for (i = 0; i < n; i++)
387 {
388 SBITMAP_ELT_TYPE tmp = *ap++ | *bp++;
389 changed = *dstp ^ tmp;
390 *dstp++ = tmp;
391 }
392
393 return changed != 0;
394}
395
396void
397sbitmap_a_or_b (dst, a, b)
398 sbitmap dst, a, b;
399{
400 unsigned int i, n = dst->size;
401 sbitmap_ptr dstp = dst->elms;
402 sbitmap_ptr ap = a->elms;
403 sbitmap_ptr bp = b->elms;
404
405 for (i = 0; i < n; i++)
406 *dstp++ = *ap++ | *bp++;
407}
408
409/* Return nonzero if A is a subset of B. */
410
411bool
412sbitmap_a_subset_b_p (a, b)
413 sbitmap a, b;
414{
415 unsigned int i, n = a->size;
416 sbitmap_ptr ap, bp;
417
418 for (ap = a->elms, bp = b->elms, i = 0; i < n; i++, ap++, bp++)
419 if ((*ap | *bp) != *bp)
420 return false;
421
422 return true;
423}
424
425/* Set DST to be (A or (B and C)).
426 Return nonzero if any change is made. */
427
428bool
429sbitmap_a_or_b_and_c_cg (dst, a, b, c)
430 sbitmap dst, a, b, c;
431{
432 unsigned int i, n = dst->size;
433 sbitmap_ptr dstp = dst->elms;
434 sbitmap_ptr ap = a->elms;
435 sbitmap_ptr bp = b->elms;
436 sbitmap_ptr cp = c->elms;
437 SBITMAP_ELT_TYPE changed = 0;
438
439 for (i = 0; i < n; i++)
440 {
441 SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & *cp++);
442 changed |= *dstp ^ tmp;
443 *dstp++ = tmp;
444 }
445
446 return changed != 0;
447}
448
449void
450sbitmap_a_or_b_and_c (dst, a, b, c)
451 sbitmap dst, a, b, c;
452{
453 unsigned int i, n = dst->size;
454 sbitmap_ptr dstp = dst->elms;
455 sbitmap_ptr ap = a->elms;
456 sbitmap_ptr bp = b->elms;
457 sbitmap_ptr cp = c->elms;
458
459 for (i = 0; i < n; i++)
460 *dstp++ = *ap++ | (*bp++ & *cp++);
461}
462
463/* Set DST to be (A and (B or C)).
464 Return nonzero if any change is made. */
465
466bool
467sbitmap_a_and_b_or_c_cg (dst, a, b, c)
468 sbitmap dst, a, b, c;
469{
470 unsigned int i, n = dst->size;
471 sbitmap_ptr dstp = dst->elms;
472 sbitmap_ptr ap = a->elms;
473 sbitmap_ptr bp = b->elms;
474 sbitmap_ptr cp = c->elms;
475 SBITMAP_ELT_TYPE changed = 0;
476
477 for (i = 0; i < n; i++)
478 {
479 SBITMAP_ELT_TYPE tmp = *ap++ & (*bp++ | *cp++);
480 changed |= *dstp ^ tmp;
481 *dstp++ = tmp;
482 }
483
484 return changed != 0;
485}
486
487void
488sbitmap_a_and_b_or_c (dst, a, b, c)
489 sbitmap dst, a, b, c;
490{
491 unsigned int i, n = dst->size;
492 sbitmap_ptr dstp = dst->elms;
493 sbitmap_ptr ap = a->elms;
494 sbitmap_ptr bp = b->elms;
495 sbitmap_ptr cp = c->elms;
496
497 for (i = 0; i < n; i++)
498 *dstp++ = *ap++ & (*bp++ | *cp++);
499}
500
501#ifdef IN_GCC
502/* Set the bitmap DST to the intersection of SRC of successors of
503 block number BB, using the new flow graph structures. */
504
505void
506sbitmap_intersection_of_succs (dst, src, bb)
507 sbitmap dst;
508 sbitmap *src;
509 int bb;
510{
511 basic_block b = BASIC_BLOCK (bb);
512 unsigned int set_size = dst->size;
513 edge e;
514
515 for (e = b->succ; e != 0; e = e->succ_next)
516 {
517 if (e->dest == EXIT_BLOCK_PTR)
518 continue;
519
520 sbitmap_copy (dst, src[e->dest->index]);
521 break;
522 }
523
524 if (e == 0)
525 sbitmap_ones (dst);
526 else
527 for (e = e->succ_next; e != 0; e = e->succ_next)
528 {
529 unsigned int i;
530 sbitmap_ptr p, r;
531
532 if (e->dest == EXIT_BLOCK_PTR)
533 continue;
534
535 p = src[e->dest->index]->elms;
536 r = dst->elms;
537 for (i = 0; i < set_size; i++)
538 *r++ &= *p++;
539 }
540}
541
542/* Set the bitmap DST to the intersection of SRC of predecessors of
543 block number BB, using the new flow graph structures. */
544
545void
546sbitmap_intersection_of_preds (dst, src, bb)
547 sbitmap dst;
548 sbitmap *src;
549 int bb;
550{
551 basic_block b = BASIC_BLOCK (bb);
552 unsigned int set_size = dst->size;
553 edge e;
554
555 for (e = b->pred; e != 0; e = e->pred_next)
556 {
557 if (e->src == ENTRY_BLOCK_PTR)
558 continue;
559
560 sbitmap_copy (dst, src[e->src->index]);
561 break;
562 }
563
564 if (e == 0)
565 sbitmap_ones (dst);
566 else
567 for (e = e->pred_next; e != 0; e = e->pred_next)
568 {
569 unsigned int i;
570 sbitmap_ptr p, r;
571
572 if (e->src == ENTRY_BLOCK_PTR)
573 continue;
574
575 p = src[e->src->index]->elms;
576 r = dst->elms;
577 for (i = 0; i < set_size; i++)
578 *r++ &= *p++;
579 }
580}
581
582/* Set the bitmap DST to the union of SRC of successors of
583 block number BB, using the new flow graph structures. */
584
585void
586sbitmap_union_of_succs (dst, src, bb)
587 sbitmap dst;
588 sbitmap *src;
589 int bb;
590{
591 basic_block b = BASIC_BLOCK (bb);
592 unsigned int set_size = dst->size;
593 edge e;
594
595 for (e = b->succ; e != 0; e = e->succ_next)
596 {
597 if (e->dest == EXIT_BLOCK_PTR)
598 continue;
599
600 sbitmap_copy (dst, src[e->dest->index]);
601 break;
602 }
603
604 if (e == 0)
605 sbitmap_zero (dst);
606 else
607 for (e = e->succ_next; e != 0; e = e->succ_next)
608 {
609 unsigned int i;
610 sbitmap_ptr p, r;
611
612 if (e->dest == EXIT_BLOCK_PTR)
613 continue;
614
615 p = src[e->dest->index]->elms;
616 r = dst->elms;
617 for (i = 0; i < set_size; i++)
618 *r++ |= *p++;
619 }
620}
621
622/* Set the bitmap DST to the union of SRC of predecessors of
623 block number BB, using the new flow graph structures. */
624
625void
626sbitmap_union_of_preds (dst, src, bb)
627 sbitmap dst;
628 sbitmap *src;
629 int bb;
630{
631 basic_block b = BASIC_BLOCK (bb);
632 unsigned int set_size = dst->size;
633 edge e;
634
635 for (e = b->pred; e != 0; e = e->pred_next)
636 {
637 if (e->src== ENTRY_BLOCK_PTR)
638 continue;
639
640 sbitmap_copy (dst, src[e->src->index]);
641 break;
642 }
643
644 if (e == 0)
645 sbitmap_zero (dst);
646 else
647 for (e = e->pred_next; e != 0; e = e->pred_next)
648 {
649 unsigned int i;
650 sbitmap_ptr p, r;
651
652 if (e->src == ENTRY_BLOCK_PTR)
653 continue;
654
655 p = src[e->src->index]->elms;
656 r = dst->elms;
657 for (i = 0; i < set_size; i++)
658 *r++ |= *p++;
659 }
660}
661#endif
662
663/* Return number of first bit set in the bitmap, -1 if none. */
664
665int
666sbitmap_first_set_bit (bmap)
667 sbitmap bmap;
668{
669 unsigned int n;
670
671 EXECUTE_IF_SET_IN_SBITMAP (bmap, 0, n, { return n; });
672 return -1;
673}
674
675/* Return number of last bit set in the bitmap, -1 if none. */
676
677int
678sbitmap_last_set_bit (bmap)
679 sbitmap bmap;
680{
681 int i;
682 SBITMAP_ELT_TYPE *ptr = bmap->elms;
683
684 for (i = bmap->size - 1; i >= 0; i--)
685 {
686 SBITMAP_ELT_TYPE word = ptr[i];
687
688 if (word != 0)
689 {
690 unsigned int index = (i + 1) * SBITMAP_ELT_BITS - 1;
691 SBITMAP_ELT_TYPE mask
692 = (SBITMAP_ELT_TYPE) 1 << (SBITMAP_ELT_BITS - 1);
693
694 while (1)
695 {
696 if ((word & mask) != 0)
697 return index;
698
699 mask >>= 1;
700 index--;
701 }
702 }
703 }
704
705 return -1;
706}
707
708void
709dump_sbitmap (file, bmap)
710 FILE *file;
711 sbitmap bmap;
712{
713 unsigned int i, n, j;
714 unsigned int set_size = bmap->size;
715 unsigned int total_bits = bmap->n_bits;
716
717 fprintf (file, " ");
718 for (i = n = 0; i < set_size && n < total_bits; i++)
719 for (j = 0; j < SBITMAP_ELT_BITS && n < total_bits; j++, n++)
720 {
721 if (n != 0 && n % 10 == 0)
722 fprintf (file, " ");
723
724 fprintf (file, "%d",
725 (bmap->elms[i] & ((SBITMAP_ELT_TYPE) 1 << j)) != 0);
726 }
727
728 fprintf (file, "\n");
729}
730
731void
732dump_sbitmap_file (file, bmap)
733 FILE *file;
734 sbitmap bmap;
735{
736 unsigned int i, pos;
737
738 fprintf (file, "n_bits = %d, set = {", bmap->n_bits);
739
740 for (pos = 30, i = 0; i < bmap->n_bits; i++)
741 if (TEST_BIT (bmap, i))
742 {
743 if (pos > 70)
744 {
745 fprintf (file, "\n ");
746 pos = 0;
747 }
748
749 fprintf (file, "%d ", i);
750 pos += 2 + (i >= 10) + (i >= 100) + (i >= 1000);
751 }
752
753 fprintf (file, "}\n");
754}
755
756void
757debug_sbitmap (bmap)
758 sbitmap bmap;
759{
760 dump_sbitmap_file (stderr, bmap);
761}
762
763void
764dump_sbitmap_vector (file, title, subtitle, bmaps, n_maps)
765 FILE *file;
766 const char *title, *subtitle;
767 sbitmap *bmaps;
768 int n_maps;
769{
770 int bb;
771
772 fprintf (file, "%s\n", title);
773 for (bb = 0; bb < n_maps; bb++)
774 {
775 fprintf (file, "%s %d\n", subtitle, bb);
776 dump_sbitmap (file, bmaps[bb]);
777 }
778
779 fprintf (file, "\n");
780}
Note: See TracBrowser for help on using the repository browser.