Add minor functionalities on relations
[openscop.git] / source / generic.c
blob57fd4098c227f215f4ebc416486369ad6dc31972
2 /*+-----------------------------------------------------------------**
3 ** OpenScop Library **
4 **-----------------------------------------------------------------**
5 ** generic.c **
6 **-----------------------------------------------------------------**
7 ** First version: 26/11/2010 **
8 **-----------------------------------------------------------------**
11 *****************************************************************************
12 * OpenScop: Structures and formats for polyhedral tools to talk together *
13 *****************************************************************************
14 * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, *
15 * / / / // // // // / / / // // / / // / /|,_, *
16 * / / / // // // // / / / // // / / // / / / /\ *
17 * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ *
18 * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ *
19 * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ *
20 * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ *
21 * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ *
22 * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ *
23 * | I | | | | e | | | | | | | | | | | | | \ \ \ *
24 * | T | | | | | | | | | | | | | | | | | \ \ \ *
25 * | E | | | | | | | | | | | | | | | | | \ \ \ *
26 * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ *
27 * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / *
28 * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
29 * *
30 * Copyright (C) 2008 University Paris-Sud 11 and INRIA *
31 * *
32 * (3-clause BSD license) *
33 * Redistribution and use in source and binary forms, with or without *
34 * modification, are permitted provided that the following conditions *
35 * are met: *
36 * *
37 * 1. Redistributions of source code must retain the above copyright notice, *
38 * this list of conditions and the following disclaimer. *
39 * 2. Redistributions in binary form must reproduce the above copyright *
40 * notice, this list of conditions and the following disclaimer in the *
41 * documentation and/or other materials provided with the distribution. *
42 * 3. The name of the author may not be used to endorse or promote products *
43 * derived from this software without specific prior written permission. *
44 * *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
55 * *
56 * OpenScop Library, a library to manipulate OpenScop formats and data *
57 * structures. Written by: *
58 * Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and *
59 * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> *
60 * *
61 *****************************************************************************/
63 # include <stdlib.h>
64 # include <stdio.h>
65 # include <string.h>
66 # include <osl/generic.h>
69 /*+***************************************************************************
70 * Structure display function *
71 *****************************************************************************/
74 /**
75 * osl_generic_idump function:
76 * this function displays an osl_generic_t structure (*generic) into
77 * a file (file, possibly stdout) in a way that trends to be understandable.
78 * It includes an indentation level (level) in order to work with others
79 * print_structure functions.
80 * \param[in] file File where informations are printed.
81 * \param[in] generic The generic whose information has to be printed.
82 * \param[in] level Number of spaces before printing, for each line.
84 void osl_generic_idump(FILE * file, osl_generic_p generic, int level) {
85 int j, first = 1;
87 // Go to the right level.
88 for (j = 0; j < level; j++)
89 fprintf(file,"|\t");
91 if (generic != NULL)
92 fprintf(file, "+-- osl_generic_t\n");
93 else
94 fprintf(file, "+-- NULL generic\n");
96 while (generic != NULL) {
97 if (!first) {
98 // Go to the right level.
99 for (j = 0; j < level; j++)
100 fprintf(file, "|\t");
101 fprintf(file, "| osl_generic_t\n");
103 else
104 first = 0;
106 // A blank line
107 for(j = 0; j <= level + 1; j++)
108 fprintf(file, "|\t");
109 fprintf(file, "\n");
111 osl_interface_idump(file, generic->interface, level + 1);
113 if (generic->interface != NULL)
114 generic->interface->idump(file, generic->data, level + 1);
116 generic = generic->next;
118 // Next line.
119 if (generic != NULL) {
120 for (j = 0; j <= level; j++)
121 fprintf(file, "|\t");
122 fprintf(file, "V\n");
126 // The last line.
127 for (j = 0; j <= level; j++)
128 fprintf(file, "|\t");
129 fprintf(file, "\n");
134 * osl_generic_dump function:
135 * this function prints the content of an osl_generic_t structure
136 * (*generic) into a file (file, possibly stdout).
137 * \param[in] file File where the information has to be printed.
138 * \param[in] generic The generic structure to print.
140 void osl_generic_dump(FILE * file, osl_generic_p generic) {
141 osl_generic_idump(file, generic, 0);
146 * osl_generic_print function:
147 * this function prints the content of an osl_generic_t structure
148 * (*generic) into a string (returned) in the OpenScop format.
149 * \param[in] file File where the information has to be printed.
150 * \param[in] generic The generic structure to print.
152 void osl_generic_print(FILE * file, osl_generic_p generic) {
153 char * string;
155 if (generic == NULL)
156 return;
158 while (generic != NULL) {
159 if (generic->interface != NULL) {
160 string = generic->interface->sprint(generic->data);
161 if (string != NULL) {
162 fprintf(file, "%s", string);
163 free(string);
166 generic = generic->next;
171 /*****************************************************************************
172 * Reading function *
173 *****************************************************************************/
177 * osl_generic_sread function:
178 * this function reads a list of generics from a string complying to the
179 * OpenScop textual format and a list of known interfaces. It returns a
180 * pointer to the corresponding list of generic structures.
181 * \param[in] string The string where to read a list of data.
182 * \param[in] registry The list of known interfaces (others are ignored).
183 * \return A pointer to the generic information list that has been read.
185 osl_generic_p osl_generic_sread(char * string, osl_interface_p registry) {
186 osl_generic_p generic = NULL, new;
187 osl_interface_p interface;
188 void * x;
190 while (registry != NULL) {
191 x = registry->sread(string);
192 if (x != NULL) {
193 interface = osl_interface_nclone(registry, 1);
194 new = osl_generic_malloc();
195 new->interface = interface;
196 new->data = x;
197 osl_generic_add(&generic, new);
199 registry = registry->next;
202 return generic;
207 * osl_generic_read function:
208 * this function reads a list of generics from a file (possibly stdin)
209 * complying to the OpenScop textual format and a list of known interfaces.
210 * It returns a pointer to the list of corresponding generic structures.
211 * \param[in] file The input file where to read a list of data.
212 * \param[in] registry The list of known interfaces (others are ignored).
213 * \return A pointer to the generic information list that has been read.
215 osl_generic_p osl_generic_read(FILE * file, osl_interface_p registry) {
216 char * generic_string;
217 void * generic_list;
219 generic_string = osl_util_read_uptotag(file, OSL_TAG_END_SCOP);
220 generic_list = osl_generic_sread(generic_string, registry);
221 free(generic_string);
222 return generic_list;
226 /*+***************************************************************************
227 * Memory allocation/deallocation function *
228 *****************************************************************************/
232 * osl_generic_add function:
233 * this function adds a generic node (it may be a list as well) to a list
234 * of generics provided as parameter (list). The new node is inserted at
235 * the end of the list.
236 * \param[in] list The list of generics to add a node (NULL if empty).
237 * \param[in] generic The generic list to add to the initial list.
239 void osl_generic_add(osl_generic_p * list, osl_generic_p generic) {
240 osl_generic_p tmp = *list, check;
242 if (generic != NULL) {
243 // First, check that the generic list is OK.
244 check = generic;
245 while (check != NULL) {
246 if ((check->interface == NULL) || (check->interface->URI == NULL))
247 OSL_error("no interface or URI in a generic to add to a list");
249 // TODO: move this to the integrity check.
250 if (osl_generic_lookup(*list, check->interface->URI) != NULL)
251 OSL_error("only one generic with a given URI is allowed");
252 check = check->next;
255 if (*list != NULL) {
256 while (tmp->next != NULL)
257 tmp = tmp->next;
258 tmp->next = generic;
260 else {
261 *list = generic;
268 * osl_generic_malloc function:
269 * This function allocates the memory space for an osl_generic_t
270 * structure and sets its fields with default values. Then it returns a
271 * pointer to the allocated space.
272 * \return A pointer to an empty generic structure with fields set to
273 * default values.
275 osl_generic_p osl_generic_malloc() {
276 osl_generic_p generic;
278 OSL_malloc(generic, osl_generic_p, sizeof(osl_generic_t));
279 generic->interface = NULL;
280 generic->data = NULL;
281 generic->next = NULL;
283 return generic;
288 * osl_generic_free function:
289 * This function frees the allocated memory for a generic structure.
290 * \param[in] generic The pointer to the generic structure we want to free.
292 void osl_generic_free(osl_generic_p generic) {
293 osl_generic_p next;
295 while (generic != NULL) {
296 next = generic->next;
297 if (generic->interface != NULL) {
298 generic->interface->free(generic->data);
299 osl_interface_free(generic->interface);
301 else {
302 if (generic->data != NULL) {
303 OSL_warning("unregistered interface, memory leaks are possible");
304 free(generic->data);
307 free(generic);
308 generic = next;
313 /*+***************************************************************************
314 * Processing functions *
315 *****************************************************************************/
319 * osl_generic_clone function:
320 * This function builds and returns a "hard copy" (not a pointer copy) of an
321 * osl_generic_t data structure.
322 * \param[in] generic The pointer to the generic structure we want to clone.
323 * \return A pointer to the clone of the input generic structure.
325 osl_generic_p osl_generic_clone(osl_generic_p generic) {
326 osl_generic_p clone = NULL, new;
327 osl_interface_p interface;
328 void * x;
330 while (generic != NULL) {
331 if (generic->interface != NULL) {
332 x = generic->interface->clone(generic->data);
333 interface = osl_interface_clone(generic->interface);
334 new = osl_generic_malloc();
335 new->interface = interface;
336 new->data = x;
337 osl_generic_add(&clone, new);
339 else {
340 OSL_warning("unregistered interface, cloning ignored");
342 generic = generic->next;
345 return clone;
350 * osl_generic_count function:
351 * this function counts the number of elements in the generic list provided
352 * as parameter (x) and returns this number.
353 * \param[in] x The list of generics.
354 * \return The number of elements in the list.
356 int osl_generic_count(osl_generic_p x) {
357 int generic_number = 0;
359 while (x != NULL) {
360 generic_number++;
361 x = x->next;
364 return generic_number;
369 * osl_generic_equal function:
370 * this function returns true if the two generic structures are the same,
371 * false otherwise. This functions considers two generic structures as equal
372 * independently of the order of the nodes. TODO: make it dependent on the
373 * order.
374 * \param x1 The first generic structure.
375 * \param x2 The second generic structure.
376 * \return 1 if x1 and x2 are the same (content-wise), 0 otherwise.
378 int osl_generic_equal(osl_generic_p x1, osl_generic_p x2) {
379 int x1_generic_number, x2_generic_number;
380 int found, equal;
381 osl_generic_p backup_x2 = x2;
383 if (x1 == x2)
384 return 1;
386 // Check whether the number of generics is the same or not.
387 x1_generic_number = osl_generic_count(x1);
388 x2_generic_number = osl_generic_count(x2);
389 if (x1_generic_number != x2_generic_number)
390 return 0;
392 // Check that for each generic in x1 a similar generic is in x2.
393 while (x1 != NULL) {
394 x2 = backup_x2;
395 found = 0;
396 while ((x2 != NULL) && (found != 1)) {
397 if (osl_interface_equal(x1->interface, x2->interface)) {
398 if (x1->interface != NULL) {
399 equal = x1->interface->equal(x1->data, x2->data);
401 else {
402 OSL_warning("unregistered generic, "
403 "cannot state generic equality");
404 equal = 0;
407 if (equal == 0)
408 return 0;
409 else
410 found = 1;
413 x2 = x2->next;
416 if (found != 1)
417 return 0;
419 x1 = x1->next;
422 return 1;
427 * osl_generic_has_URI function:
428 * this function returns 1 if the generic provided as parameter has
429 * a given URI, 0 other wise.
430 * \param x The generic structure to test.
431 * \param URI The URI value to test.
432 * \return 1 if x has the provided URI, 0 otherwise.
434 int osl_generic_has_URI(osl_generic_p x, char * URI) {
436 if ((x == NULL) ||
437 (x->interface == NULL) ||
438 (x->interface->URI == NULL) ||
439 (strcmp(x->interface->URI, URI)))
440 return 0;
442 return 1;
447 * osl_generic_lookup function:
448 * this function returns the first generic with a given URI in the
449 * generic list provided as parameter and NULL if it doesn't find such
450 * a generic.
451 * \param x The generic list where to search a given generic URI.
452 * \param URI The URI of the generic we are looking for.
453 * \return The first generic of the requested URI in the list.
455 void * osl_generic_lookup(osl_generic_p x, char * URI) {
456 while (x != NULL) {
457 if (osl_generic_has_URI(x, URI))
458 return x->data;
460 x = x->next;
463 return NULL;