1 /* Binary relations. 2 3 Copyright (C) 2002, 2004-2005, 2009-2012 Free Software Foundation, 4 Inc. 5 6 This file is part of Bison, the GNU Compiler Compiler. 7 8 This program is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 #include <config.h> 22 #include "system.h" 23 24 #include <bitsetv.h> 25 26 #include "getargs.h" 27 #include "relation.h" 28 29 void 30 relation_print (relation r, relation_node size, FILE *out) 31 { 32 relation_node i; 33 relation_node j; 34 35 for (i = 0; i < size; ++i) 36 { 37 fprintf (out, "%3lu: ", (unsigned long int) i); 38 if (r[i]) 39 for (j = 0; r[i][j] != END_NODE; ++j) 40 fprintf (out, "%3lu ", (unsigned long int) r[i][j]); 41 fputc ('\n', out); 42 } 43 fputc ('\n', out); 44 } 45 46 47 /*---------------------------------------------------------------. 48 | digraph & traverse. | 49 | | 50 | The following variables are used as common storage between the | 51 | two. | 52 `---------------------------------------------------------------*/ 53 54 static relation R; 55 static relation_nodes INDEX; 56 static relation_nodes VERTICES; 57 static relation_node top; 58 static relation_node infinity; 59 static bitsetv F; 60 61 static void 62 traverse (relation_node i) 63 { 64 relation_node j; 65 relation_node height; 66 67 VERTICES[++top] = i; 68 INDEX[i] = height = top; 69 70 if (R[i]) 71 for (j = 0; R[i][j] != END_NODE; ++j) 72 { 73 if (INDEX[R[i][j]] == 0) 74 traverse (R[i][j]); 75 76 if (INDEX[i] > INDEX[R[i][j]]) 77 INDEX[i] = INDEX[R[i][j]]; 78 79 bitset_or (F[i], F[i], F[R[i][j]]); 80 } 81 82 if (INDEX[i] == height) 83 for (;;) 84 { 85 j = VERTICES[top--]; 86 INDEX[j] = infinity; 87 88 if (i == j) 89 break; 90 91 bitset_copy (F[j], F[i]); 92 } 93 } 94 95 96 void 97 relation_digraph (relation r, relation_node size, bitsetv *function) 98 { 99 relation_node i; 100 101 infinity = size + 2; 102 INDEX = xcalloc (size + 1, sizeof *INDEX); 103 VERTICES = xnmalloc (size + 1, sizeof *VERTICES); 104 top = 0; 105 106 R = r; 107 F = *function; 108 109 for (i = 0; i < size; i++) 110 if (INDEX[i] == 0 && R[i]) 111 traverse (i); 112 113 free (INDEX); 114 free (VERTICES); 115 116 *function = F; 117 } 118 119 120 /*-------------------------------------------. 121 | Destructively transpose R_ARG, of size N. | 122 `-------------------------------------------*/ 123 124 void 125 relation_transpose (relation *R_arg, relation_node n) 126 { 127 relation r = *R_arg; 128 /* The result. */ 129 relation new_R = xnmalloc (n, sizeof *new_R); 130 /* END_R[I] -- next entry of NEW_R[I]. */ 131 relation end_R = xnmalloc (n, sizeof *end_R); 132 /* NEDGES[I] -- total size of NEW_R[I]. */ 133 size_t *nedges = xcalloc (n, sizeof *nedges); 134 relation_node i; 135 relation_node j; 136 137 if (trace_flag & trace_sets) 138 { 139 fputs ("relation_transpose: input\n", stderr); 140 relation_print (r, n, stderr); 141 } 142 143 /* Count. */ 144 for (i = 0; i < n; i++) 145 if (r[i]) 146 for (j = 0; r[i][j] != END_NODE; ++j) 147 ++nedges[r[i][j]]; 148 149 /* Allocate. */ 150 for (i = 0; i < n; i++) 151 { 152 relation_node *sp = NULL; 153 if (nedges[i] > 0) 154 { 155 sp = xnmalloc (nedges[i] + 1, sizeof *sp); 156 sp[nedges[i]] = END_NODE; 157 } 158 new_R[i] = sp; 159 end_R[i] = sp; 160 } 161 162 /* Store. */ 163 for (i = 0; i < n; i++) 164 if (r[i]) 165 for (j = 0; r[i][j] != END_NODE; ++j) 166 *end_R[r[i][j]]++ = i; 167 168 free (nedges); 169 free (end_R); 170 171 /* Free the input: it is replaced with the result. */ 172 for (i = 0; i < n; i++) 173 free (r[i]); 174 free (r); 175 176 if (trace_flag & trace_sets) 177 { 178 fputs ("relation_transpose: output\n", stderr); 179 relation_print (new_R, n, stderr); 180 } 181 182 *R_arg = new_R; 183 } 184