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>
70 /*+***************************************************************************
71 * Functions on arrays of strings *
72 *****************************************************************************/
76 * openscop_util_strings_idump function:
77 * this function displays an array of strings into a file (file, possibly
78 * stdout) in a way that trends to be understandable. It includes an
79 * indentation level (level) in order to work with others
80 * print_structure functions.
81 * \param file The file where the information has to be printed.
82 * \param strings The array of strings that has to be printed.
83 * \param nb_strings The number of strings in the array of strings.
84 * \param level Number of spaces before printing, for each line.
85 * \param title A string to use as a title for the array of strings.
87 void openscop_util_strings_idump(FILE * file
,
88 char ** strings
, int nb_strings
,
93 // Print the original parameter names.
94 for (i
= 0; i
<= level
; i
++)
96 if ((strings
!= NULL
) && (nb_strings
> 0)) {
97 fprintf(file
, "+-- %s:", title
);
98 for (i
= 0; i
< nb_strings
; i
++)
99 fprintf(file
, " %s", strings
[i
]);
103 fprintf(file
, "+-- No %s\n", title
);
106 for (i
= 0; i
<= level
+1; i
++)
107 fprintf(file
, "|\t");
113 * openscop_util_strings_print function:
114 * this function prints the content of an array of strings
115 * into a file (file, possibly stdout) in the OpenScop textual format.
116 * \param file The file where the information has to be printed.
117 * \param strings The array of strings that has to be printed.
118 * \param nb_strings The number of strings in the array of strings.
119 * \param print Boolean not set to 0 to print the names, 0 otherwise.
120 * \param title A string to use as a title for the array of strings.
122 void openscop_util_strings_print(FILE * file
,
123 char ** strings
, int nb_strings
,
128 if ((print
!= 0) && (strings
!= NULL
) && (nb_strings
> 0)) {
129 fprintf(file
, "# %s are provided\n", title
);
130 fprintf(file
, "1\n");
131 fprintf(file
, "# %s\n", title
);
132 for (i
= 0; i
< nb_strings
; i
++)
133 fprintf(file
, "%s ", strings
[i
]);
134 fprintf(file
, "\n\n");
137 fprintf(file
, "# %s are not provided\n", title
);
138 fprintf(file
, "0\n\n");
144 * openscop_util_strings_read function.
145 * this function reads an array of strings from a file (possibly stdin)
146 * complying to the OpenScop textual format and returns a pointer to this
147 * array as well as the number of elements of this array (through the
148 * parameter nb_strings).
149 * \param file The file where to read the array of strings.
150 * \param nb_strings Pointer to where to store the number of strings (output).
151 * \return The array of strings that has been read.
153 char ** openscop_util_strings_read(FILE * file
, int * nb_strings
) {
154 char str
[OPENSCOP_MAX_STRING
];
155 char tmp
[OPENSCOP_MAX_STRING
];
157 char ** strings
= NULL
;
160 // Skip blank/commented lines and spaces.
161 start
= openscop_util_skip_blank_and_comments(file
, str
);
163 // Count the actual number of strings.
167 for (count
= 0; *s
&& ! isspace(*s
) && *s
!= '#'; ++count
)
173 if ((*s
== '#') || (*s
== '\n'))
179 if (*nb_strings
> 0) {
180 // Allocate the array of strings. Make it NULL-terminated.
181 strings
= (char **) malloc(sizeof(char *) * ((*nb_strings
) + 1));
182 if (strings
== NULL
) {
183 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
186 strings
[*nb_strings
] = NULL
;
188 // Read the desired number of strings.
190 for (i
= 0; i
< *nb_strings
; ++i
) {
191 for (count
= 0; *s
&& ! isspace(*s
) && *s
!= '#'; ++count
)
194 strings
[i
] = strdup(tmp
);
195 if (strings
[i
] == NULL
) {
196 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
209 * openscop_util_strings_generate function:
210 * This function generates an array of size 'nb' of strings of the form
211 * "prefixXX" where XX goes from 1 to nb.
212 * \param prefix The prefix of the generated names.
213 * \param nb_strings The number of strings to generate.
214 * \return An array of 'nb' generated strings.
216 char ** openscop_util_strings_generate(char * prefix
, int nb_strings
) {
217 char ** strings
= NULL
;
218 char buff
[strlen(prefix
) + 16]; // TODO: better (log10(INT_MAX) ?) :-D.
222 strings
= (char **)malloc(sizeof(char *) * nb_strings
);
223 if (strings
== NULL
) {
224 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
227 for (i
= 0; i
< nb_strings
; i
++) {
228 sprintf(buff
, "%s%d", prefix
, i
+ 1);
229 strings
[i
] = strdup(buff
);
230 if (strings
[i
] == NULL
) {
231 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
242 * openscop_util_strings_complete function:
243 * this function completes an array of strings with generated strings.
244 * \param strings Pointer to the initial array of strings (modified).
245 * \param nb_strings Pointer to the initial number of strings (modified).
246 * \param prefix The prefix of the generated names.
247 * \param nb_complete The desired number of strings in the new array.
249 void openscop_util_strings_complete(char *** strings
, int * nb_strings
,
250 char * prefix
, int nb_complete
) {
254 nb_new
= nb_complete
- *nb_strings
;
256 fprintf(stderr
, "[OpenScop] Error: asked to complete the following "
257 "string array but it would be smaller than the original "
258 "(desired length: %d):\n", nb_complete
);
259 openscop_util_strings_idump(stderr
, *strings
, *nb_strings
, -1,
265 *strings
= (char **)realloc(*strings
, nb_complete
* sizeof(char *));
266 completion
= openscop_util_strings_generate(prefix
, nb_new
);
267 for (i
= 0; i
< nb_new
; i
++)
268 (*strings
)[i
+ *nb_strings
] = completion
[i
];
270 *nb_strings
= nb_complete
;
276 * openscop_util_strings_free function:
277 * this function frees the allocated memory for an array of strings.
278 * \param strings The array of strings we want to free.
279 * \param nb_strings The number of strings in the array of strings.
281 void openscop_util_strings_free(char ** strings
, int nb_strings
) {
284 if (strings
!= NULL
) {
285 for (i
= 0; i
< nb_strings
; i
++)
286 if (strings
[i
] != NULL
)
294 * openscop_util_copy_strings internal function.
295 * this function builds and return a "hard copy" (not a pointer copy) of an
296 * array of strings provided as parameter.
297 * \param strings The array of strings to copy.
298 * \param nb_strings The number of strings in the array to copy.
299 * \return The copy of the array of strings.
301 char ** openscop_util_strings_copy(char ** strings
, int nb_strings
) {
305 if ((strings
== NULL
) || (nb_strings
== 0))
308 copy
= (char **)malloc(nb_strings
* sizeof(char *));
310 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
313 for (i
= 0; i
< nb_strings
; i
++) {
314 copy
[i
] = strdup(strings
[i
]);
315 if (copy
[i
] == NULL
) {
316 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
326 * openscop_util_strings_equal function:
327 * this function returns true if the two arrays of strings are the same
328 * (content-wise), false otherwise.
329 * \param s1 The first array of strings.
330 * \param nb_s1 The number of strings in the first array of string.
331 * \param s2 The second array of strings.
332 * \param nb_s2 The number of strings in the second array of string.
333 * \return 1 if s1 and s2 are the same (content-wise), 0 otherwise.
335 int openscop_util_strings_equal(char ** s1
, int nb_s1
, char ** s2
, int nb_s2
) {
341 if (((s1
== NULL
) && (s2
!= NULL
)) ||
342 ((s1
!= NULL
) && (s2
== NULL
)) ||
346 for (i
= 0; i
< nb_s1
; i
++)
347 if (strcmp(s1
[i
], s2
[i
]) != 0)
354 /*+***************************************************************************
355 * Utility functions *
356 *****************************************************************************/
360 * openscop_util_skip_blank_and_comments internal function.
361 * This function reads the open file 'file' line by line and skips
362 * blank/comment lines and spaces. The first line where there is some
363 * useful information is stored at the address 'str' (the memory to
364 * store the line must be allocated before the call to this function
365 * and must be at least OPENSCOP_MAX_STRING*sizeof(char)). The pointer
366 * to the first useful information in this line is returned by the
368 * \param file The (opened) file to read.
369 * \param str Address of an allocated space to store the first line
370 * that contains useful information.
371 * \return The address of the the first useful digit in str.
373 char * openscop_util_skip_blank_and_comments(FILE * file
, char * str
) {
377 start
= fgets(str
, OPENSCOP_MAX_STRING
, file
);
378 while ((start
!= NULL
) && isspace(*start
) && (*start
!= '\n'))
381 while (start
!= NULL
&& (*start
== '#' || *start
== '\n'));
388 * openscop_util_read_int internal function.
389 * Read an int on the input 'file' or the input string 'str' depending on
390 * which one is not NULL (exactly one of them must not be NULL).
391 * \param file The file where to read an int (if not NULL).
392 * \param str The string where to read an int (if not NULL). This pointer
393 * is updated to reflect the read and points after the int.
394 * \return The int that have been read.
396 int openscop_util_read_int(FILE * file
, char ** str
) {
397 char s
[OPENSCOP_MAX_STRING
], * start
;
402 if ((file
!= NULL
&& str
!= NULL
) || (file
== NULL
&& str
== NULL
)) {
403 fprintf(stderr
, "[OpenScop] Error: one and only one of the two parameters"
404 " of util_read_int can be non-NULL\n");
409 // Parse from a file.
410 start
= openscop_util_skip_blank_and_comments(file
, s
);
411 if (sscanf(start
, " %d", &res
) != 1) {
412 fprintf(stderr
, "[OpenScop] Error: an int was expected.\n");
417 // Parse from a string.
418 // Skip blank/commented lines.
420 while (*str
&& **str
&& isspace(**str
))
423 while (**str
&& **str
!= '\n')
427 // Build the chain to analyze.
428 while (**str
&& !isspace(**str
) && **str
!= '\n')
429 s
[i
++] = *((*str
)++);
431 if (sscanf(s
, "%d", &res
) != 1) {
432 fprintf(stderr
, "[OpenScop] Error: an int was expected.\n");
446 * openscop_util_read_tail function:
447 * this function puts the remainder of a file (from the current file pointer to
448 * the end of the file) to a string and returns this string. This excepts the
449 * first blank or commented lines (commented according to the OpenScop textual
451 * \param file The file where to read the tail.
452 * \return The string corresponding to the tail of the input file.
454 char * openscop_util_read_tail(FILE * file
) {
455 int high_water_mark
= OPENSCOP_MAX_STRING
;
457 char buff
[OPENSCOP_MAX_STRING
], *c
;
460 // - Skip blank/commented lines and spaces.
461 c
= openscop_util_skip_blank_and_comments(file
, buff
);
465 extensions
= (char *)malloc(high_water_mark
* sizeof(char));
466 if (extensions
== NULL
) {
467 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
471 strcpy(extensions
, c
);
472 nb_chars
= strlen(c
);
474 // - Copy everything else to the option tags field.
475 while (!feof(file
)) {
476 extensions
[nb_chars
] = fgetc(file
);
479 if (nb_chars
>= high_water_mark
) {
480 high_water_mark
+= high_water_mark
;
481 extensions
= (char *)realloc(extensions
, high_water_mark
* sizeof(char));
482 if (extensions
== NULL
) {
483 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
489 // - 0-terminate the string.
490 extensions
= (char *)realloc(extensions
, nb_chars
* sizeof(char));
491 extensions
[nb_chars
- 1] = '\0';
498 * openscop_util_tag_content function:
499 * This function returns a freshly allocated string containing the
500 * content, in the given string 'str', between the tag 'tag' and
501 * the tag 'endtag'. If the tag 'tag' is not found, returns NULL.
502 * \param str The string where to find a given content.
503 * \param tag The string that marks the beginning of the content.
504 * \param endtag The string that marks the end of the content.
505 * \return The string between 'tag' and 'endtag' in 'str'.
507 char * openscop_util_tag_content(char * str
, char * tag
, char * endtag
) {
517 lentag
= strlen(tag
);
518 for (; start
&& *start
&& strncmp(start
, tag
, lentag
); ++start
)
521 // The tag 'tag' was not found.
526 lentag
= strlen(endtag
);
527 for (size
= 0; *stop
&& strncmp(stop
, endtag
, lentag
); ++stop
, ++size
)
530 // the tag 'endtag' was not found.
533 res
= (char *)malloc((size
+ 1) * sizeof(char));
535 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");
539 // Copy the chain between the two tags.
540 for (++start
, i
= 0; start
!= stop
; ++start
, ++i
)
550 * openscop_util_safe_strcat function:
551 * this function concatenates the string src to the string *dst
552 * and reallocates *dst if necessary. The current size of the
553 * *dst buffer must be *hwm (high water mark), if there is some
554 * reallocation, this value is updated.
555 * \param dst pointer to the destination string (may be reallocated).
556 * \param src string to concatenate to dst.
557 * \param hwm pointer to the size of the *dst buffer (may be updated).
558 * TODO: This function is not that safe, improve it !
560 void openscop_util_safe_strcat(char ** dst
, char * src
, int * hwm
) {
562 if (strlen(src
) >= OPENSCOP_MAX_STRING
) {
563 fprintf(stderr
, "[OpenScop] Error: string to concatenate is too long.\n");
567 if (strlen(*dst
) + strlen(src
) >= *hwm
) {
568 *hwm
+= OPENSCOP_MAX_STRING
;
569 *dst
= (char *)realloc(*dst
, *hwm
* sizeof(char));
571 fprintf(stderr
, "[OpenScop] Error: memory overflow.\n");