PIPS
set.c
Go to the documentation of this file.
1 /*
2 
3  $Id: set.c 1387 2020-07-06 08:36:33Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of NewGen.
8 
9  NewGen is free software: you can redistribute it and/or modify it under the
10  terms of the GNU General Public License as published by the Free Software
11  Foundation, either version 3 of the License, or any later version.
12 
13  NewGen is distributed in the hope that it will be useful, but WITHOUT ANY
14  WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16  License for more details.
17 
18  You should have received a copy of the GNU General Public License along with
19  NewGen. If not, see <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 /*
24  Pierre Jouvelot (3 Avril 1989)
25 
26  Set package for any type of pointer.
27 
28  To avoid sharing problem, all the routines are 3-adress: S1 = S2 op S3.
29  It is up to the user to know what to do (e.g., freeing some temporary
30  memory storage) before S1 is assigned a new value.
31 
32  Shallow copies are used. If set A is assigned to set B, side
33  effects on elements of A are visible in B.
34 
35  Formal parameters are modified in functions which makes the stack
36  misleading when debugging with gdb.
37 
38  The sets are implemented with hash-tables. Each element is stored
39  as key and value.
40 
41  */
42 #ifdef HAVE_CONFIG_H
43  #include "config.h"
44 #endif
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <stdarg.h>
49 
50 #include "genC.h"
51 #include "newgen_set.h"
52 #include "newgen_include.h"
53 
54 /* FI: I do not understand why the type is duplicated at the set
55  level. Is there a potential consistency problem with the hash
56  table type? Is this a consequence of the decision to hide the
57  actual hash_table data structure?
58 */
59 struct _set_chunk {
62 };
63 
64 #define INITIAL_SET_SIZE 10
65 
66 /* return the internal hash table of set s
67  */
69 {
70  return s->table;
71 }
72 
73 /* return the type of set s
74  */
76 {
77  return s->type;
78 }
79 
80 /* Create an empty set of any type */
81 /* discrepancy: size_t sometimes, _uint elsewhere */
82 /* why not use the functional types now defined in newgen_hash.h? */
84  hash_equals_t private_equal_p,
85  hash_rank_t private_rank)
86 {
87  set hp = (set) alloc(sizeof(struct _set_chunk));
88  message_assert("allocated", hp);
89 
91  (hash_key_type) typ,
93  private_equal_p,
94  private_rank);
95 
96  hp->type = typ;
97 
98  return hp;
99 }
100 
101 /* Create an empty set of any type but hash_private */
103 {
104  message_assert("typ is not set_private", typ!=set_private);
105  /* Use default functions for equality check and rank computation. */
106  return set_generic_make(typ, NULL, NULL);
107 }
108 
109 /* create a singleton set of any type but hash_private
110  *
111  * use set_add_element() instead for hash_private
112  */
113 set set_singleton(set_type type, const void * p)
114 {
115  set s = set_make( type ) ;
116  hash_put( s->table, p, p ) ;
117  return s;
118 }
119 
120 /* Assign a set with the content of another set.
121 
122  @param s1 the set to write into
123  @param s2 the set to copy
124 
125  If the same set is given twice, nothing is done.
126 
127  @return the target set.
128 */
129 set set_assign(set s1, const set s2)
130 {
131  if (s1 == s2) {
132  return s1;
133  }
134  else {
135  set_clear(s1);
136  HASH_MAP(k, v, hash_put( s1->table, k, v ), s2->table);
137  return s1;
138  }
139 }
140 
141 /* @return duplicated set
142  */
143 set set_dup(const set s)
144 {
145  set n = set_make(s->type);
146  HASH_MAP(k, v, hash_put(n->table, k, v ), s->table);
147  return n;
148 }
149 
150 /* @return s1 = s2 u { e }.
151  */
152 set set_add_element(set s1, const set s2, const void * e)
153 {
154  if( s1 == s2 ) {
155  if (! set_belong_p(s1, e))
156  hash_put(s1->table, e, e);
157  return( s1 ) ;
158  }
159  else {
160  set_clear( s1 ) ;
161  HASH_MAP( k, v, {hash_put( s1->table, k, v ) ;}, s2->table ) ;
162  if (! set_belong_p(s1, e))
163  hash_put(s1->table, e, e);
164  return( s1 ) ;
165  }
166 }
167 
168 
169 /* @return s1 = s2 u { list of e }.
170  */
171 set set_add_elements(set s1, const set s2, const void * e, ...)
172 {
173  bool first = true;
174  va_list args;
175  /* The statement list */
176  /* Analyze in args the variadic arguments that may be after s2: */
177  va_start(args, e);
178  /* Since a variadic function in C must have at least 1 non variadic
179  argument (here the s), just skew the varargs analysis: */
180  e = va_arg(args, void *);
181  while(e) {
182  // may copy s2 on first time
183  s1 = set_add_element(s1, first? s2: s1, e);
184  first = false;
185  // get next element
186  e = va_arg(args, void *);
187  }
188  /* Release the variadic analyzis: */
189  va_end(args);
190  return s1;
191 }
192 /* @return whether e \in s.
193  */
194 bool set_belong_p(const set s, const void * e)
195 {
196  return hash_get(s->table, e) != HASH_UNDEFINED_VALUE;
197 }
198 
199 /* @return whether all items in l are in s
200  */
201 bool list_in_set_p(const list l, const set s)
202 {
203  FOREACH(chunk, c, l)
204  if (!set_belong_p(s, c))
205  return false;
206  return true;
207 }
208 
209 /* @return s1 = s2 u s3.
210  */
211 set set_union(set s1, const set s2, const set s3)
212 {
213  // do not warn on redefinitions when computing an union.
214  bool warning = hash_warn_on_redefinition_p();
215  if (warning) hash_dont_warn_on_redefinition();
216  if( s1 != s3 ) {
217  set_assign(s1, s2) ;
218  HASH_MAP( k, v, hash_put( s1->table, k, v), s3->table ) ;
219  }
220  else {
221  HASH_MAP( k, v, hash_put( s1->table, k, v), s2->table ) ;
222  }
223  if (warning) hash_warn_on_redefinition();
224  return s1;
225 }
226 
227 /* @return s1 = s2 n s3.
228  */
229 set set_intersection(set s1, const set s2, const set s3)
230 {
231  if( s1 != s2 && s1 != s3 ) {
232  set_clear( s1 ) ;
233  HASH_MAP( k, v, {if( hash_get( s2->table, k )
235  hash_put( s1->table, k, v ) ;},
236  s3->table ) ;
237  return( s1 ) ;
238  }
239  else {
240  set tmp = set_generic_make( s1->type,
242  hash_table_rank_function(s1->table) ) ;
243 
244  HASH_MAP( k, v, {if( hash_get( s1->table, k )
246  hash_put( tmp->table, k, v ) ;},
247  (s1 == s2) ? s3->table : s2->table ) ;
248  set_assign( s1, tmp ) ;
249  set_free( tmp ) ;
250  return( s1 ) ;
251  }
252 }
253 
254 /* @return s1 = s2 - s3.
255  */
256 set set_difference(set s1, const set s2, const set s3)
257 {
258  set_assign(s1, s2);
259  HASH_MAP(k, ignore, hash_del(s1->table, k), s3->table);
260  return s1;
261 }
262 
263 /* @return s1 = s2 - { e }.
264  */
265 set set_del_element(set s1, const set s2, const void * e)
266 {
267  set_assign( s1, s2 ) ;
268  hash_del( s1->table, e );
269  return s1;
270 }
271 
272 /* May be useful for string sets ... NOT TESTED
273  *
274  * FI:Confusing for Newgen users because gen_free() is expected?
275  */
276 set set_delfree_element(set s1, const set s2, const void * e)
277 {
278  void * pe;
279  set_assign(s1, s2);
280  (void) hash_delget(s1->table, e ,&pe);
281  free(pe);
282  return s1;
283 }
284 
285 /* returns whether s1 n s2 <> 0
286  * complexity of the intersection
287  */
288 bool set_intersection_p(const set s1, const set s2)
289 {
290  bool non_empty_intersection;
291  if (set_empty_p(s1) || set_empty_p(s2))
292  non_empty_intersection = false;
293  else
294  {
295  set inter = set_make(set_pointer);
296  set_intersection(inter, s1, s2);
297  non_empty_intersection = !set_empty_p(inter);
298  set_free(inter);
299  }
300  return non_empty_intersection;
301 }
302 
303 /* return whether s1 \included s2
304  */
305 bool set_inclusion_p(const set s1, const set s2)
306 {
307  if (s1==s2) return true;
308  SET_FOREACH(void *, i, s1)
309  if (!set_belong_p(s2, i))
310  return false;
311  return true;
312 }
313 
314 /* returns whether s1 == s2
315  */
316 bool set_equal_p(const set s1, const set s2)
317 {
318  if (s1==s2) return true;
319  return set_size(s1)==set_size(s2) &&
320  set_inclusion_p(s1, s2) && set_inclusion_p(s2, s1);
321 }
322 
323 /* Assign the empty set to s
324  * s := {}
325  */
327 {
329  return s;
330 }
331 
332 void set_free(set s)
333 {
335  gen_free_area((void**) s, sizeof(struct _set_chunk));
336 }
337 
338 /* Free several sets in one call. Useful when many sets are used
339  simultaneously. */
340 void sets_free(set s,...)
341 {
342  va_list args;
343 
344  /* Analyze in args the variadic arguments that may be after t: */
345  va_start(args, s);
346  /* Since a variadic function in C must have at least 1 non variadic
347  argument (here the s), just skew the varargs analysis: */
348  do {
349  set_free(s);
350  /* Get the next argument */
351  s = va_arg(args, set);
352  } while(s!=NULL);
353  /* Release the variadic analysis */
354  va_end(args);
355 }
356 
357 /* returns the number of items in s.
358  */
359 int set_size(const set s)
360 {
361  return hash_table_entry_count(s->table);
362 }
363 
364 /* tell whether set s is empty.
365  * returnn s=={}
366  */
367 bool set_empty_p(const set s)
368 {
369  return set_size(s)==0;
370 }
371 
372 void gen_set_closure_iterate(void (*iterate)(void *, set),
373  set initial,
374  bool dont_iterate_twice)
375 {
376  set curr, next, seen;
377  set_type t = initial->type;
378 
381  hash_table_rank_function(initial->table));
382  curr = set_generic_make(t,
384  hash_table_rank_function(initial->table));
385  next = set_generic_make(t,
387  hash_table_rank_function(initial->table));
388 
389  set_assign(curr, initial);
390 
391  while (!set_empty_p(curr))
392  {
393  SET_FOREACH(void *, x, curr)
394  iterate(x, next);
395 
396  if (dont_iterate_twice)
397  {
398  set_union(seen, seen, curr);
399  set_difference(curr, next, seen);
400  }
401  else
402  {
403  set_assign(curr, next);
404  }
405  set_clear(next);
406  }
407 
408  set_free(curr);
409  set_free(seen);
410  set_free(next);
411 
412 }
413 
414 /* a set-based implementation of gen_closure
415  * that does not go twice in the same object.
416  * FC 27/10/95.
417  */
418 void gen_set_closure(void (*iterate)(void *, set), set initial)
419 {
420  gen_set_closure_iterate(iterate, initial, true);
421 }
422 
424 {
425  return sizeof(struct _set_chunk)+hash_table_own_allocated_memory(s->table);
426 }
427 
428 /**
429  * create a list from a set
430  * the set is not freed
431  * @warning no assumption can be made on the ordering of returned list
432  * @param s set where the data are
433  *
434  * @return an allocated list of elements from s
435  */
437 {
438  list l =NIL;
439  SET_FOREACH(void *, v, s)
440  l = gen_cons(v,l);
441  return l;
442 }
443 
444 /* @return a sorted list from a set.
445  * provide comparison function as gen_sort_list, which calls "qsort".
446  */
448 {
449  list l = set_to_list(s);
450  gen_sort_list(l, cmp);
451  return l;
452 }
453 
454 /**
455  * add list l items to set s, which is returned.
456  *
457  * @param s modified set
458  * @param l provided list
459  */
461 {
462  FOREACH(chunk, i, l)
463  set_add_element(s, s, i);
464  return s;
465 }
466 
467 /**
468  * assigns a list contents to a set
469  * all duplicated elements are lost
470  *
471  * @param s set being assigned to.
472  * @param l list to turn into a set
473  */
475 {
476  set_clear(s);
477  return set_append_list(s, l);
478 }
479 
480 /************************************************** UTILITIES FOR DEBUGGING */
481 
482 #include "newgen_string_buffer.h"
483 
484 /* convert set s to a string_buffer
485  * used internally, but may be exported if needed.
486  */
487 static string_buffer
488 set_to_string_buffer(string name, const set s, gen_string_func_t item_name)
489 {
491  if (name)
492  string_buffer_cat(sb, name, " = (", i2a(set_size(s)), ") { ", NULL);
493  else
494  string_buffer_cat(sb, " (", i2a(set_size(s)), ") { ", NULL);
495 
496  bool first = true;
497  SET_FOREACH(void *, i, s)
498  {
499  if (first) first = false;
500  else string_buffer_append(sb, ", ");
501  string_buffer_append(sb, item_name(i));
502  }
503 
504  string_buffer_append(sb, " }");
505  return sb;
506 }
507 
508 /* return allocated string for set s
509  * @param name set description
510  * @param s the set
511  * @param item_name user function to build a string for each item
512  */
513 string set_to_string(string name, const set s, gen_string_func_t item_name)
514 {
515  string_buffer sb = set_to_string_buffer(name, s, item_name);
516  string res = string_buffer_to_string(sb);
518  return res;
519 }
520 
521 /* print set s to file stream out.
522  */
524  (FILE * out, string name, const set s, gen_string_func_t item_name)
525 {
526  string_buffer sb = set_to_string_buffer(name, s, item_name);
528  putc('\n', out);
530 }
static hash_table seen
static function to store whether a module has been seen during the recursive generation of the daVinc...
Definition: graph.c:85
static FILE * out
Definition: alias_check.c:128
char * alloc(int size)
ALLOC is an "iron-clad" version of malloc(3).
Definition: build.c:501
void free(void *)
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_cons(const void *item, const list next)
Definition: list.c:888
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
void gen_free_area(void **p, int size)
free an area.
Definition: list.c:775
void gen_sort_list(list l, gen_cmp_func_t compare)
Sorts a list of gen_chunks in place, to avoid allocations...
Definition: list.c:796
void hash_dont_warn_on_redefinition(void)
Definition: hash.c:188
hash_equals_t hash_table_equals_function(hash_table h)
Because the hash table data structure is hidden in this source file hash.c and not exported via the n...
Definition: hash.c:934
bool hash_warn_on_redefinition_p(void)
Definition: hash.c:193
int hash_table_own_allocated_memory(hash_table htp)
Definition: hash.c:869
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_warn_on_redefinition(void)
these function set the variable should_i_warn_on_redefinition to the value true or false
Definition: hash.c:183
hash_table hash_table_generic_make(hash_key_type key_type, size_t size, hash_equals_t private_equal_p, hash_rank_t private_rank)
this function makes a hash table of size size.
Definition: hash.c:223
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
hash_rank_t hash_table_rank_function(hash_table h)
Definition: hash.c:939
void * hash_del(hash_table htp, const void *key)
this function removes from the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:439
void * hash_delget(hash_table htp, const void *key, void **pkey)
deletes key from the hash table.
Definition: hash.c:398
int hash_table_entry_count(hash_table htp)
now we define observers in order to hide the hash_table type...
Definition: hash.c:818
void hash_table_clear(hash_table htp)
Clears all entries of a hash table HTP.
Definition: hash.c:305
#define message_assert(msg, ex)
Definition: newgen_assert.h:47
char * i2a(int)
I2A (Integer TO Ascii) yields a string for a given Integer.
Definition: string.c:121
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
hash_key_type
Equality and rank functions are provided for strings, integers, pointers and Newgen chunks.
Definition: newgen_hash.h:31
_uint(* hash_rank_t)(const void *, size_t)
Definition: newgen_hash.h:44
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56
int(* hash_equals_t)(const void *, const void *)
Definition: newgen_hash.h:45
struct _set_chunk * set
Definition: newgen_set.h:38
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
set_type
Note: hash_chunk is not included in set_type.
Definition: newgen_set.h:41
@ set_pointer
Definition: newgen_set.h:44
@ set_private
Definition: newgen_set.h:45
void string_buffer_append(string_buffer, const string)
append string s (if non empty) to string buffer sb, the duplication is done if needed according to th...
string string_buffer_to_string(const string_buffer)
return malloc'ed string from string buffer sb
void string_buffer_to_file(const string_buffer, FILE *)
put string buffer into file.
void string_buffer_free(string_buffer *)
free string buffer structure, also free string contents according to the dup field
Definition: string_buffer.c:82
string_buffer string_buffer_make(bool dup)
allocate a new string buffer
Definition: string_buffer.c:58
void string_buffer_cat(string_buffer, const string,...)
append a NULL terminated list of string to sb.
string(* gen_string_func_t)(const void *)
Definition: newgen_types.h:111
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
set_free(tmp)
set set_intersection(set s1, const set s2, const set s3)
Definition: set.c:229
set set_add_element(set s1, const set s2, const void *e)
Definition: set.c:152
list set_to_sorted_list(const set s, gen_cmp_func_t cmp)
Definition: set.c:447
set set_generic_make(set_type typ, hash_equals_t private_equal_p, hash_rank_t private_rank)
Create an empty set of any type.
Definition: set.c:83
bool set_equal_p(const set s1, const set s2)
returns whether s1 == s2
Definition: set.c:316
set set_difference(set s1, const set s2, const set s3)
Definition: set.c:256
s1
Definition: set.c:247
void gen_set_closure_iterate(void(*iterate)(void *, set), set initial, bool dont_iterate_twice)
Definition: set.c:372
string set_to_string(string name, const set s, gen_string_func_t item_name)
return allocated string for set s
Definition: set.c:513
bool set_intersection_p(const set s1, const set s2)
returns whether s1 n s2 <> 0 complexity of the intersection
Definition: set.c:288
void gen_set_closure(void(*iterate)(void *, set), set initial)
a set-based implementation of gen_closure that does not go twice in the same object.
Definition: set.c:418
set set_append_list(set s, const list l)
add list l items to set s, which is returned.
Definition: set.c:460
set set_clear(set s)
Assign the empty set to s s := {}.
Definition: set.c:326
bool set_belong_p(const set s, const void *e)
Definition: set.c:194
static string_buffer set_to_string_buffer(string name, const set s, gen_string_func_t item_name)
convert set s to a string_buffer used internally, but may be exported if needed.
Definition: set.c:488
bool set_inclusion_p(const set s1, const set s2)
return whether s1 \included s2
Definition: set.c:305
int set_size(const set s)
returns the number of items in s.
Definition: set.c:359
set set_delfree_element(set s1, const set s2, const void *e)
May be useful for string sets ...
Definition: set.c:276
hash_table set_private_get_hash_table(const set s)
return the internal hash table of set s
Definition: set.c:68
list set_to_list(const set s)
create a list from a set the set is not freed
Definition: set.c:436
void sets_free(set s,...)
Free several sets in one call.
Definition: set.c:340
set set_add_elements(set s1, const set s2, const void *e,...)
Definition: set.c:171
void set_fprint(FILE *out, string name, const set s, gen_string_func_t item_name)
print set s to file stream out.
Definition: set.c:524
set set_make(set_type typ)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_singleton(set_type type, const void *p)
create a singleton set of any type but hash_private
Definition: set.c:113
int set_own_allocated_memory(const set s)
Definition: set.c:423
set set_union(set s1, const set s2, const set s3)
Definition: set.c:211
set set_del_element(set s1, const set s2, const void *e)
Definition: set.c:265
set set_assign(set s1, const set s2)
Assign a set with the content of another set.
Definition: set.c:129
bool list_in_set_p(const list l, const set s)
Definition: set.c:201
bool set_empty_p(const set s)
tell whether set s is empty.
Definition: set.c:367
set set_assign_list(set s, const list l)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474
set_type set_get_type(const set s)
return the type of set s
Definition: set.c:75
set set_dup(const set s)
Definition: set.c:143
#define INITIAL_SET_SIZE
Definition: set.c:64
static char * x
Definition: split_file.c:159
internally defined structure.
Definition: string_buffer.c:47
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
hash_table table
Definition: set.c:60
set_type type
Definition: set.c:61
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:4047