xref: /netbsd-src/external/gpl3/gdb/dist/libiberty/partition.c (revision 5173eb0a33e5d83890ba976253e703be4c92557c)
198b9484cSchristos /* List implementation of a partition of consecutive integers.
2*5173eb0aSchristos    Copyright (C) 2000-2024 Free Software Foundation, Inc.
398b9484cSchristos    Contributed by CodeSourcery, LLC.
498b9484cSchristos 
598b9484cSchristos    This file is part of GNU CC.
698b9484cSchristos 
798b9484cSchristos    GNU CC is free software; you can redistribute it and/or modify
898b9484cSchristos    it under the terms of the GNU General Public License as published by
998b9484cSchristos    the Free Software Foundation; either version 2, or (at your option)
1098b9484cSchristos    any later version.
1198b9484cSchristos 
1298b9484cSchristos    GNU CC is distributed in the hope that it will be useful,
1398b9484cSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1498b9484cSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598b9484cSchristos    GNU General Public License for more details.
1698b9484cSchristos 
1798b9484cSchristos    You should have received a copy of the GNU General Public License
1898b9484cSchristos    along with GNU CC; see the file COPYING.  If not, write to
1998b9484cSchristos    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
2098b9484cSchristos    Boston, MA 02110-1301, USA.  */
2198b9484cSchristos 
2298b9484cSchristos #ifdef HAVE_CONFIG_H
2398b9484cSchristos #include "config.h"
2498b9484cSchristos #endif
2598b9484cSchristos 
2698b9484cSchristos #ifdef HAVE_STDLIB_H
2798b9484cSchristos #include <stdlib.h>
2898b9484cSchristos #endif
2998b9484cSchristos 
3098b9484cSchristos #ifdef HAVE_STRING_H
3198b9484cSchristos #include <string.h>
3298b9484cSchristos #endif
3398b9484cSchristos 
3498b9484cSchristos #include "libiberty.h"
3598b9484cSchristos #include "partition.h"
3698b9484cSchristos 
3798b9484cSchristos static int elem_compare (const void *, const void *);
3898b9484cSchristos 
3998b9484cSchristos /* Creates a partition of NUM_ELEMENTS elements.  Initially each
4098b9484cSchristos    element is in a class by itself.  */
4198b9484cSchristos 
4298b9484cSchristos partition
4398b9484cSchristos partition_new (int num_elements)
4498b9484cSchristos {
4598b9484cSchristos   int e;
4698b9484cSchristos 
4798b9484cSchristos   partition part = (partition)
4898b9484cSchristos     xmalloc (sizeof (struct partition_def) +
4998b9484cSchristos 	     (num_elements - 1) * sizeof (struct partition_elem));
5098b9484cSchristos   part->num_elements = num_elements;
5198b9484cSchristos   for (e = 0; e < num_elements; ++e)
5298b9484cSchristos     {
5398b9484cSchristos       part->elements[e].class_element = e;
5498b9484cSchristos       part->elements[e].next = &(part->elements[e]);
5598b9484cSchristos       part->elements[e].class_count = 1;
5698b9484cSchristos     }
5798b9484cSchristos 
5898b9484cSchristos   return part;
5998b9484cSchristos }
6098b9484cSchristos 
6198b9484cSchristos /* Freeds a partition.  */
6298b9484cSchristos 
6398b9484cSchristos void
6498b9484cSchristos partition_delete (partition part)
6598b9484cSchristos {
6698b9484cSchristos   free (part);
6798b9484cSchristos }
6898b9484cSchristos 
6998b9484cSchristos /* Unites the classes containing ELEM1 and ELEM2 into a single class
7098b9484cSchristos    of partition PART.  If ELEM1 and ELEM2 are already in the same
7198b9484cSchristos    class, does nothing.  Returns the canonical element of the
7298b9484cSchristos    resulting union class.  */
7398b9484cSchristos 
7498b9484cSchristos int
7598b9484cSchristos partition_union (partition part, int elem1, int elem2)
7698b9484cSchristos {
7798b9484cSchristos   struct partition_elem *elements = part->elements;
7898b9484cSchristos   struct partition_elem *e1;
7998b9484cSchristos   struct partition_elem *e2;
8098b9484cSchristos   struct partition_elem *p;
8198b9484cSchristos   struct partition_elem *old_next;
8298b9484cSchristos   /* The canonical element of the resulting union class.  */
8398b9484cSchristos   int class_element = elements[elem1].class_element;
8498b9484cSchristos 
8598b9484cSchristos   /* If they're already in the same class, do nothing.  */
8698b9484cSchristos   if (class_element == elements[elem2].class_element)
8798b9484cSchristos     return class_element;
8898b9484cSchristos 
8998b9484cSchristos   /* Make sure ELEM1 is in the larger class of the two.  If not, swap
9098b9484cSchristos      them.  This way we always scan the shorter list.  */
9198b9484cSchristos   if (elements[elem1].class_count < elements[elem2].class_count)
9298b9484cSchristos     {
9398b9484cSchristos       int temp = elem1;
9498b9484cSchristos       elem1 = elem2;
9598b9484cSchristos       elem2 = temp;
9698b9484cSchristos       class_element = elements[elem1].class_element;
9798b9484cSchristos     }
9898b9484cSchristos 
9998b9484cSchristos   e1 = &(elements[elem1]);
10098b9484cSchristos   e2 = &(elements[elem2]);
10198b9484cSchristos 
10298b9484cSchristos   /* Keep a count of the number of elements in the list.  */
10398b9484cSchristos   elements[class_element].class_count
10498b9484cSchristos     += elements[e2->class_element].class_count;
10598b9484cSchristos 
10698b9484cSchristos   /* Update the class fields in elem2's class list.  */
10798b9484cSchristos   e2->class_element = class_element;
10898b9484cSchristos   for (p = e2->next; p != e2; p = p->next)
10998b9484cSchristos     p->class_element = class_element;
11098b9484cSchristos 
11198b9484cSchristos   /* Splice ELEM2's class list into ELEM1's.  These are circular
11298b9484cSchristos      lists.  */
11398b9484cSchristos   old_next = e1->next;
11498b9484cSchristos   e1->next = e2->next;
11598b9484cSchristos   e2->next = old_next;
11698b9484cSchristos 
11798b9484cSchristos   return class_element;
11898b9484cSchristos }
11998b9484cSchristos 
12098b9484cSchristos /* Compare elements ELEM1 and ELEM2 from array of integers, given a
12198b9484cSchristos    pointer to each.  Used to qsort such an array.  */
12298b9484cSchristos 
12398b9484cSchristos static int
12498b9484cSchristos elem_compare (const void *elem1, const void *elem2)
12598b9484cSchristos {
12698b9484cSchristos   int e1 = * (const int *) elem1;
12798b9484cSchristos   int e2 = * (const int *) elem2;
12898b9484cSchristos   if (e1 < e2)
12998b9484cSchristos     return -1;
13098b9484cSchristos   else if (e1 > e2)
13198b9484cSchristos     return 1;
13298b9484cSchristos   else
13398b9484cSchristos     return 0;
13498b9484cSchristos }
13598b9484cSchristos 
13698b9484cSchristos /* Prints PART to the file pointer FP.  The elements of each
13798b9484cSchristos    class are sorted.  */
13898b9484cSchristos 
13998b9484cSchristos void
14098b9484cSchristos partition_print (partition part, FILE *fp)
14198b9484cSchristos {
14298b9484cSchristos   char *done;
14398b9484cSchristos   int num_elements = part->num_elements;
14498b9484cSchristos   struct partition_elem *elements = part->elements;
14598b9484cSchristos   int *class_elements;
14698b9484cSchristos   int e;
14798b9484cSchristos 
14898b9484cSchristos   /* Flag the elements we've already printed.  */
14998b9484cSchristos   done = (char *) xmalloc (num_elements);
15098b9484cSchristos   memset (done, 0, num_elements);
15198b9484cSchristos 
15298b9484cSchristos   /* A buffer used to sort elements in a class.  */
15398b9484cSchristos   class_elements = (int *) xmalloc (num_elements * sizeof (int));
15498b9484cSchristos 
15598b9484cSchristos   fputc ('[', fp);
15698b9484cSchristos   for (e = 0; e < num_elements; ++e)
15798b9484cSchristos     /* If we haven't printed this element, print its entire class.  */
15898b9484cSchristos     if (! done[e])
15998b9484cSchristos       {
16098b9484cSchristos 	int c = e;
16198b9484cSchristos 	int count = elements[elements[e].class_element].class_count;
16298b9484cSchristos 	int i;
16398b9484cSchristos 
16498b9484cSchristos       /* Collect the elements in this class.  */
16598b9484cSchristos 	for (i = 0; i < count; ++i) {
16698b9484cSchristos 	  class_elements[i] = c;
16798b9484cSchristos 	  done[c] = 1;
16898b9484cSchristos 	  c = elements[c].next - elements;
16998b9484cSchristos 	}
17098b9484cSchristos 	/* Sort them.  */
17198b9484cSchristos 	qsort ((void *) class_elements, count, sizeof (int), elem_compare);
17298b9484cSchristos 	/* Print them.  */
17398b9484cSchristos 	fputc ('(', fp);
17498b9484cSchristos 	for (i = 0; i < count; ++i)
17598b9484cSchristos 	  fprintf (fp, i == 0 ? "%d" : " %d", class_elements[i]);
17698b9484cSchristos 	fputc (')', fp);
17798b9484cSchristos       }
17898b9484cSchristos   fputc (']', fp);
17998b9484cSchristos 
18098b9484cSchristos   free (class_elements);
18198b9484cSchristos   free (done);
18298b9484cSchristos }
18398b9484cSchristos 
184