1
2    /*+-----------------------------------------------------------------**
3     **                       OpenScop Library                          **
4     **-----------------------------------------------------------------**
5     **                      extensions/arrays.c                        **
6     **-----------------------------------------------------------------**
7     **                   First version: 07/12/2010                     **
8     **-----------------------------------------------------------------**
9
10
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 *****************************************************************************/
62
63#include <stdlib.h>
64#include <stdio.h>
65#include <string.h>
66#include <ctype.h>
67
68#include <osl/macros.h>
69#include <osl/util.h>
70#include <osl/strings.h>
71#include <osl/interface.h>
72#include <osl/extensions/arrays.h>
73
74
75/*+***************************************************************************
76 *                          Structure display function                       *
77 *****************************************************************************/
78
79
80/**
81 * osl_arrays_idump function:
82 * this function displays an osl_arrays_t structure (*arrays) into a file
83 * (file, possibly stdout) in a way that trends to be understandable. It
84 * includes an indentation level (level) in order to work with others
85 * idump functions.
86 * \param[in] file   The file where the information has to be printed.
87 * \param[in] arrays The arrays structure to print.
88 * \param[in] level  Number of spaces before printing, for each line.
89 */
90void osl_arrays_idump(FILE * file, osl_arrays_p arrays, int level) {
91  int i, j;
92
93  // Go to the right level.
94  for (j = 0; j < level; j++)
95    fprintf(file, "|\t");
96
97  if (arrays != NULL)
98    fprintf(file, "+-- osl_arrays_t\n");
99  else
100    fprintf(file, "+-- NULL arrays\n");
101
102  if (arrays != NULL) {
103    // Go to the right level.
104    for(j = 0; j <= level; j++)
105      fprintf(file, "|\t");
106
107    // Display the number of names.
108    fprintf(file, "nb_names: %d\n", arrays->nb_names);
109
110    // Display the id/name.
111    for(i = 0; i < arrays->nb_names; i++) {
112      // Go to the right level.
113      for(j = 0; j <= level; j++)
114        fprintf(file, "|\t");
115
116      fprintf(file, "id: %2d, name: %s\n", arrays->id[i], arrays->names[i]);
117    }
118  }
119
120  // The last line.
121  for (j = 0; j <= level; j++)
122    fprintf(file, "|\t");
123  fprintf(file, "\n");
124}
125
126
127/**
128 * osl_arrays_dump function:
129 * this function prints the content of an osl_arrays_t structure
130 * (*arrays) into a file (file, possibly stdout).
131 * \param[in] file   The file where the information has to be printed.
132 * \param[in] arrays The arrays structure to print.
133 */
134void osl_arrays_dump(FILE * file, osl_arrays_p arrays) {
135  osl_arrays_idump(file, arrays, 0);
136}
137
138
139/**
140 * osl_arrays_sprint function:
141 * this function prints the content of an osl_arrays_t structure
142 * (*arrays) into a string (returned) in the OpenScop textual format.
143 * \param[in] arrays The arrays structure to print.
144 * \return A string containing the OpenScop dump of the arrays structure.
145 */
146char * osl_arrays_sprint(osl_arrays_p arrays) {
147  int i;
148  int high_water_mark = OSL_MAX_STRING;
149  char * string = NULL;
150  char buffer[OSL_MAX_STRING];
151
152  if (arrays != NULL) {
153    OSL_malloc(string, char *, high_water_mark * sizeof(char));
154    string[0] = '\0';
155
156    sprintf(buffer, "# Number of arrays\n");
157    osl_util_safe_strcat(&string, buffer, &high_water_mark);
158
159    sprintf(buffer, "%d\n", arrays->nb_names);
160    osl_util_safe_strcat(&string, buffer, &high_water_mark);
161
162    if (arrays->nb_names) {
163      sprintf(buffer, "# Mapping array-identifiers/array-names\n");
164      osl_util_safe_strcat(&string, buffer, &high_water_mark);
165    }
166    for (i = 0; i < arrays->nb_names; i++) {
167      sprintf(buffer, "%d %s\n", arrays->id[i], arrays->names[i]);
168      osl_util_safe_strcat(&string, buffer, &high_water_mark);
169    }
170
171    OSL_realloc(string, char *, (strlen(string) + 1) * sizeof(char));
172  }
173
174  return string;
175}
176
177
178/*****************************************************************************
179 *                               Reading function                            *
180 *****************************************************************************/
181
182
183/**
184 * osl_arrays_sread function:
185 * this function reads an arrays structure from a string complying to the
186 * OpenScop textual format and returns a pointer to this arrays structure.
187 * The string should contain only one textual format of an arrays structure.
188 * The input parameter is updated to the position in the input string this
189 * function reach right after reading the comment structure.
190 * \param[in,out] input The input string where to find an arrays structure.
191 *                      Updated to the position after what has been read.
192 * \return A pointer to the arrays structure that has been read.
193 */
194osl_arrays_p osl_arrays_sread(char ** input) {
195  int i, k;
196  int nb_names;
197  osl_arrays_p arrays;
198
199  if (input == NULL) {
200    OSL_debug("no arrays optional tag");
201    return NULL;
202  }
203
204  // Find the number of names provided.
205  nb_names = osl_util_read_int(NULL, input);
206
207  // Allocate the array of id and names.
208  arrays = osl_arrays_malloc();
209  OSL_malloc(arrays->id, int *, nb_names * sizeof(int));
210  OSL_malloc(arrays->names, char **, nb_names * sizeof(char *));
211  arrays->nb_names = nb_names;
212  for (i = 0; i < nb_names; i++)
213    arrays->names[i] = NULL;
214
215  // Get each array id/name.
216  for (k = 0; k < nb_names; k++) {
217    // Get the array name id.
218    arrays->id[k] = osl_util_read_int(NULL, input);
219
220    // Get the array name string.
221    arrays->names[k] = osl_util_read_string(NULL, input);
222  }
223
224  return arrays;
225}
226
227
228/*+***************************************************************************
229 *                    Memory allocation/deallocation function                *
230 *****************************************************************************/
231
232
233/**
234 * osl_arrays_malloc function:
235 * this function allocates the memory space for an osl_arrays_t
236 * structure and sets its fields with default values. Then it returns a
237 * pointer to the allocated space.
238 * \return A pointer to an empty arrays structure with fields set to
239 *         default values.
240 */
241osl_arrays_p osl_arrays_malloc() {
242  osl_arrays_p arrays;
243
244  OSL_malloc(arrays, osl_arrays_p, sizeof(osl_arrays_t));
245  arrays->nb_names = 0;
246  arrays->id       = NULL;
247  arrays->names    = NULL;
248
249  return arrays;
250}
251
252
253/**
254 * osl_arrays_free function:
255 * this function frees the allocated memory for an arrays structure.
256 * \param[in,out] arrays The pointer to the arrays structure we want to free.
257 */
258void osl_arrays_free(osl_arrays_p arrays) {
259  int i;
260
261  if (arrays != NULL) {
262    free(arrays->id);
263    for (i = 0; i < arrays->nb_names; i++)
264      free(arrays->names[i]);
265    free(arrays->names);
266    free(arrays);
267  }
268}
269
270
271/*+***************************************************************************
272 *                            Processing functions                           *
273 *****************************************************************************/
274
275
276/**
277 * osl_arrays_clone function:
278 * this function builds and returns a "hard copy" (not a pointer copy) of an
279 * osl_arrays_t data structure.
280 * \param[in] arrays The pointer to the arrays structure to clone.
281 * \return A pointer to the clone of the arrays structure.
282 */
283osl_arrays_p osl_arrays_clone(osl_arrays_p arrays) {
284  int i;
285  osl_arrays_p clone;
286
287  if (arrays == NULL)
288    return NULL;
289
290  clone = osl_arrays_malloc();
291  clone->nb_names = arrays->nb_names;
292  OSL_malloc(clone->id, int *, arrays->nb_names * sizeof(int));
293  OSL_malloc(clone->names, char **, arrays->nb_names * sizeof(char*));
294
295  for (i = 0; i < arrays->nb_names; i++) {
296    clone->id[i] = arrays->id[i];
297    OSL_strdup(clone->names[i], arrays->names[i]);
298  }
299
300  return clone;
301}
302
303
304/**
305 * osl_arrays_equal function:
306 * this function returns true if the two arrays structures are the same
307 * (content-wise), false otherwise. This functions considers two arrays
308 * structures as equal if the order of the array names differ, however the
309 * identifiers and names must be the same.
310 * \param[in] a1 The first arrays structure.
311 * \param[in] a2 The second arrays structure.
312 * \return 1 if a1 and a2 are the same (content-wise), 0 otherwise.
313 */
314int osl_arrays_equal(osl_arrays_p a1, osl_arrays_p a2) {
315  int i, j, found;
316
317  if (a1 == a2)
318    return 1;
319
320  if (((a1 == NULL) && (a2 != NULL)) || ((a1 != NULL) && (a2 == NULL)))
321    return 0;
322
323  // Check whether the number of names is the same.
324  if (a1->nb_names != a2->nb_names)
325    return 0;
326
327  // We accept a different order of the names, as long as the identifiers
328  // are the same.
329  for (i = 0; i < a1->nb_names; i++) {
330    found = 0;
331    for (j = 0; j < a2->nb_names; j++) {
332      if ((a1->id[i] == a2->id[j]) && (!strcmp(a1->names[i], a2->names[j]))) {
333        found = 1;
334        break;
335      }
336    }
337    if (found != 1)
338      return 0;
339  }
340
341  return 1;
342}
343
344
345/**
346 * osl_arrays_to_strings function:
347 * this function creates a strings structure containing the textual names
348 * contained in a names structure. Each name is placed according to its
349 * id in the strings array. The "empty" strings cells are filled with
350 * dummy names.
351 * \param[in] arrays The arrays structure to convert to a strings.
352 * \return A strings structure containing all the array names.
353 */
354osl_strings_p osl_arrays_to_strings(osl_arrays_p arrays) {
355  int i, max_id = 0;
356  osl_strings_p strings = NULL;
357
358  if (arrays == NULL)
359    return NULL;
360
361  // Find the maximum array id.
362  if (arrays->nb_names >= 1) {
363    max_id = arrays->id[0];
364    for (i = 1; i < arrays->nb_names; i++)
365      if (arrays->id[i] > max_id)
366        max_id = arrays->id[i];
367  }
368
369  // Build a strings structure for this number of ids.
370  strings = osl_strings_generate("Dummy", max_id);
371  for (i = 0; i < arrays->nb_names; i++) {
372    free(strings->string[arrays->id[i] - 1]);
373    OSL_strdup(strings->string[arrays->id[i] - 1], arrays->names[i]);
374  }
375
376  return strings;
377}
378
379
380/**
381 * osl_arrays_interface function:
382 * this function creates an interface structure corresponding to the arrays
383 * extension and returns it).
384 * \return An interface structure for the arrays extension.
385 */
386osl_interface_p osl_arrays_interface() {
387  osl_interface_p interface = osl_interface_malloc();
388
389  interface->URI    = strdup(OSL_URI_ARRAYS);
390  interface->idump  = (osl_idump_f)osl_arrays_idump;
391  interface->sprint = (osl_sprint_f)osl_arrays_sprint;
392  interface->sread  = (osl_sread_f)osl_arrays_sread;
393  interface->malloc = (osl_malloc_f)osl_arrays_malloc;
394  interface->free   = (osl_free_f)osl_arrays_free;
395  interface->clone  = (osl_clone_f)osl_arrays_clone;
396  interface->equal  = (osl_equal_f)osl_arrays_equal;
397
398  return interface;
399}
400
401
402