2 /*+-----------------------------------------------------------------**
4 **-----------------------------------------------------------------**
6 **-----------------------------------------------------------------**
7 ** First version: 08/10/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 * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
30 * Copyright (C) 2008 University Paris-Sud 11 and INRIA *
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 *
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. *
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. *
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> *
61 *****************************************************************************/
67 # include <openscop/util.h>
71 * openscop_util_copy_strings internal function.
72 * This function builds and return a "hard copy" (not a pointer copy) of an
74 * \param strings The array of strings to copy.
75 * \param nb_strings The number of strings in the array to copy.
76 * \return A pointer to the copy of the array of strings.
79 openscop_util_copy_strings(char ** strings
, int nb_strings
)
84 if ((strings
== NULL
) || (nb_strings
== 0))
87 copy
= (char **)malloc(nb_strings
* sizeof(char *));
89 for (i
= 0; i
< nb_strings
; i
++)
90 copy
[i
] = strdup(strings
[i
]);
97 * openscop_util_skip_blank_and_comments internal function.
98 * This function reads the open file 'file' line by line and skips
99 * blank/comment lines and spaces. The first line where there is some
100 * useful information is stored at the address 'str' (the memory to
101 * store the line must be allocated before the call to this function
102 * and must be at least OPENSCOP_MAX_STRING*sizeof(char)). The pointer
103 * to the first useful information in this line is returned by the
105 * \param file The (opened) file to read.
106 * \param str Address of an allocated space to store the first line
107 * that contains useful information.
108 * \return The address of the the first useful digit in str.
110 char * openscop_util_skip_blank_and_comments(FILE * file
, char * str
)
116 start
= fgets(str
, OPENSCOP_MAX_STRING
, file
);
117 while ((start
!= NULL
) && isspace(*start
) && (*start
!= '\n'))
120 while (start
!= NULL
&& (*start
== '#' || *start
== '\n'));
127 * openscop_util_read_strings internal function.
128 * Read a line in the input 'file' and extract the first 'nb_strings' strings
129 * from it. nb_strings is a maximum number (the special value -1 corresponds
130 * to infinity). If *max is not NULL, it is updated with the maximum number
131 * of strings that could have been read. It returns the NULL-terminated array
132 * of strings that have been read.
133 * \param file The file where to read some strings.
134 * \param nb_strings Maximum number of strings to read (-1: infinity).
135 * \param max Address to store the maximum number of strings that could
136 * have been read (stored if the address is not NULL).
137 * \return An array of strings.
140 openscop_util_read_strings(FILE * file
, int nb_strings
, int * max
)
142 char str
[OPENSCOP_MAX_STRING
];
143 char tmp
[OPENSCOP_MAX_STRING
];
146 int i
, count
, actual_nb_strings
= 0;
148 // Skip blank/commented lines and spaces.
149 start
= openscop_util_skip_blank_and_comments(file
, str
);
151 // Count the actual number of strings.
155 for (count
= 0; *s
&& ! isspace(*s
) && *s
!= '#'; ++count
)
161 if ((*s
== '#') || (*s
== '\n'))
167 // Update the number of strings if necessary.
168 if ((nb_strings
== -1) || (actual_nb_strings
< nb_strings
))
169 nb_strings
= actual_nb_strings
;
172 *max
= actual_nb_strings
;
174 // Allocate the array of strings. Make it NULL-terminated.
175 res
= (char **) malloc(sizeof(char *) * (nb_strings
+ 1));
176 res
[nb_strings
] = NULL
;
178 // Read the desired number of strings.
180 for (i
= 0; i
< nb_strings
; ++i
)
182 for (count
= 0; *s
&& ! isspace(*s
) && *s
!= '#'; ++count
)
185 res
[i
] = strdup(tmp
);
195 * openscop_util_read_int internal function.
196 * Read an int on the input 'file' or the input string 'str' depending on
197 * which one is not NULL.
198 * \param file The file where to read an int (if not NULL).
199 * \param str The string where to read an int (if not NULL). This pointer
200 * is updated to reflect the read and points after the int.
201 * \return The int that have been read.
204 openscop_util_read_int(FILE * file
, char ** str
)
206 char s
[OPENSCOP_MAX_STRING
], * start
;
211 if ((file
!= NULL
&& str
!= NULL
) || (file
== NULL
&& str
== NULL
))
213 fprintf(stderr
, "[OpenScop] Error: one and only one of the two parameters"
214 " of util_read_int can be non-NULL\n");
220 // Parse from a file.
221 start
= openscop_util_skip_blank_and_comments(file
, s
);
222 sscanf(start
, " %d", &res
);
226 // Parse from a string.
227 // Skip blank/commented lines.
230 while (*str
&& **str
&& isspace(**str
))
234 while (**str
&& **str
!= '\n')
239 // Build the chain to analyze.
240 while (**str
&& !isspace(**str
) && **str
!= '\n')
241 s
[i
++] = *((*str
)++);
243 sscanf(s
, "%d", &res
);
255 openscop_util_free_name_array(char ** name_array
, int nb_names
)
259 for (i
= 0; i
< nb_names
; i
++)
266 * openscop_util_generate_names internal function:
267 * This function generates an array of size 'nb' of chars of the form
268 * "seedXX" where XX goes from 1 to nb.
269 * \param seed The prefix for the created names.
270 * \param nb The number of names to generate.
271 * \return An array of 'nb' generated strings.
274 openscop_util_generate_names(char * seed
, int nb
)
277 char buff
[strlen(seed
) + 16];
282 res
= (char **)malloc(sizeof(char *) * nb
);
285 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
288 for (i
= 0; i
< nb
; ++i
)
290 sprintf(buff
, "%s%d", seed
, i
+ 1);
291 res
[i
] = strdup(buff
);
300 * openscop_util_tag_content function:
301 * This function returns a freshly allocated string containing the
302 * content, in the given string 'str', between the tag 'tag' and
303 * the tag 'endtag'. If the tag 'tag' is not found, returns NULL.
304 * \param str The string where to find a given content.
305 * \param tag The string that marks the beginning of the content.
306 * \param endtag The string that marks the end of the content.
307 * \return The string between 'tag' and 'endtag' in 'str'.
310 openscop_util_tag_content(char * str
, char * tag
, char * endtag
)
322 lentag
= strlen(tag
);
323 for (; start
&& *start
&& strncmp(start
, tag
, lentag
); ++start
)
325 // The tag 'tag' was not found.
330 lentag
= strlen(endtag
);
331 for (size
= 0; *stop
&& strncmp(stop
, endtag
, lentag
); ++stop
, ++size
)
333 // the tag 'endtag' was not found.
336 res
= (char *)malloc((size
+ 1) * sizeof(char));
339 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
342 // Copy the chain between the two tags.
343 for (++start
, i
= 0; start
!= stop
; ++start
, ++i
)
353 openscop_util_read_tag_arrays(char * str
, int * nb_arrays
)
355 int i
, k
, nb_names
, array_index
, max_index
= 0;
356 int high_water_mark
= OPENSCOP_MAX_ARRAYS
;
359 char * content
, * content_backup
;
360 char buff
[OPENSCOP_MAX_STRING
];
362 content
= openscop_util_tag_content(str
, OPENSCOP_TAG_ARRAY_START
,
363 OPENSCOP_TAG_ARRAY_STOP
);
367 fprintf(stderr
, "[OpenScop] Info: no array optional tag.\n");
371 content_backup
= content
;
373 // Allocate the array of names.
374 arrays
= (char **)malloc(high_water_mark
* sizeof(char *));
375 for (i
= 0; i
< high_water_mark
; i
++)
378 // Find the number of names provided.
379 nb_names
= openscop_util_read_int(NULL
, &content
);
381 // Get each array name.
382 for (k
= 0; k
< nb_names
; k
++)
384 // Skip blank or commented lines.
385 while (*content
== '#' || *content
== '\n')
387 for (; *content
!= '\n'; ++content
)
392 // Get the array name index.
393 for (i
= 0; *content
&& ! isspace(*content
); ++i
, ++content
)
396 sscanf(buff
, "%d", &array_index
);
397 max_index
= (max_index
> array_index
) ? max_index
: array_index
;
398 if (array_index
> high_water_mark
)
400 fprintf(stderr
, "[OpenScop] Info: array name indices sound high.\n");
401 high_water_mark
+= OPENSCOP_MAX_ARRAYS
;
402 arrays
= (char **)realloc(arrays
, high_water_mark
* sizeof(char *));
405 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
408 for (i
= high_water_mark
- OPENSCOP_MAX_ARRAYS
; i
< high_water_mark
; i
++)
411 if (array_index
<= 0)
413 fprintf(stderr
, "[OpenScop] Error: array index must be > 0.\n");
417 // Get the array name in buff.
418 while (*content
&& isspace(*content
))
420 for (i
= 0; *content
&& ! isspace(*content
); ++i
, ++content
)
424 // Array index is in 0-basis.
425 if (arrays
[array_index
- 1] != NULL
)
427 fprintf(stderr
, "[OpenScop] Warning: two array names have the "
429 free(arrays
[array_index
- 1]);
431 arrays
[array_index
- 1] = strdup(buff
);
433 // Go to the end of line.
434 while (*content
&& *content
!= '\n')
437 free(content_backup
);
439 // Free unused memory.
440 arrays
= (char **)realloc(arrays
, max_index
* sizeof(char *));
442 // Fill the missing names (and let's hope there is no need for higher index).
443 tmpnames
= openscop_util_generate_names("var", max_index
);
444 for (i
= 0; i
< max_index
; i
++)
446 if (arrays
[i
] == NULL
|| arrays
[i
][0] == '\0')
447 arrays
[i
] = tmpnames
[i
]; // Use a generated name.
449 free(tmpnames
[i
]); // Use a read name.
453 if (OPENSCOP_DEBUG
== 1)
455 printf("max_index: %d\n", max_index
);
456 for (i
= 0; i
< max_index
; i
++)
457 printf("%s ", arrays
[i
]);
461 *nb_arrays
= max_index
;