OpenScop  0.9.0
util.c
Go to the documentation of this file.
1 
2  /*+-----------------------------------------------------------------**
3  ** OpenScop Library **
4  **-----------------------------------------------------------------**
5  ** util.c **
6  **-----------------------------------------------------------------**
7  ** First version: 08/10/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 <ctype.h>
66 #include <string.h>
67 
68 #include <osl/macros.h>
69 #include <osl/util.h>
70 
71 
72 /*+***************************************************************************
73  * Utility functions *
74  *****************************************************************************/
75 
76 
91 char * osl_util_skip_blank_and_comments(FILE * file, char * str) {
92  char * start;
93 
94  do {
95  start = fgets(str, OSL_MAX_STRING, file);
96  while ((start != NULL) && isspace(*start) && (*start != '\n'))
97  start++;
98  }
99  while (start != NULL && (*start == '#' || *start == '\n'));
100 
101  return start;
102 }
103 
104 
114  do {
115  // Skip spaces/blanc lines.
116  while (*str && **str && isspace(**str))
117  (*str)++;
118 
119  // Skip the comment if any.
120  if (*str && **str && **str == '#') {
121  while (**str && **str != '\n') {
122  (*str)++;
123  }
124  }
125  }
126  while (*str && **str && **str == '\n');
127 }
128 
129 
140 int osl_util_read_int(FILE * file, char ** str) {
141  char s[OSL_MAX_STRING], * start;
142  int res;
143  int i = 0;
144 
145  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
146  OSL_error("one and only one of the two parameters can be non-NULL");
147 
148  if (file != NULL) {
149  // Parse from a file.
150  start = osl_util_skip_blank_and_comments(file, s);
151  if (sscanf(start, " %d", &res) != 1)
152  OSL_error("an int was expected");
153  }
154  else {
155  // Parse from a string.
156  // Skip blank/commented lines.
158 
159  // Build the chain to analyze.
160  while (**str && !isspace(**str) && **str != '\n' && **str != '#')
161  s[i++] = *((*str)++);
162  s[i] = '\0';
163  if (sscanf(s, "%d", &res) != 1)
164  OSL_error("an int was expected");
165  }
166 
167  return res;
168 }
169 
170 
181 char * osl_util_read_string(FILE * file, char ** str) {
182  char s[OSL_MAX_STRING], * start;
183  char * res;
184  int i = 0;
185 
186  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
187  OSL_error("one and only one of the two parameters can be non-NULL");
188 
189  OSL_malloc(res, char *, OSL_MAX_STRING * sizeof(char));
190  if (file != NULL) {
191  // Parse from a file.
192  start = osl_util_skip_blank_and_comments(file, s);
193  if (sscanf(start, " %s", res) != 1)
194  OSL_error("a string was expected");
195  }
196  else {
197  // Parse from a string.
198  // Skip blank/commented lines.
200 
201  // Build the chain to analyze.
202  while (**str && !isspace(**str) && **str != '\n' && **str != '#')
203  s[i++] = *((*str)++);
204  s[i] = '\0';
205  if (sscanf(s, "%s", res) != 1)
206  OSL_error("a string was expected");
207  }
208 
209  OSL_realloc(res, char *, strlen(res) + 1);
210  return res;
211 }
212 
213 
226 char * osl_util_read_line(FILE * file, char ** str) {
227  char s[OSL_MAX_STRING], * start;
228  char * res;
229  int i = 0;
230 
231  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
232  OSL_error("one and only one of the two parameters can be non-NULL");
233 
234  OSL_malloc(res, char *, OSL_MAX_STRING * sizeof(char));
235  if (file != NULL) {
236  // Parse from a file.
237  start = osl_util_skip_blank_and_comments(file, s);
238  while (*start && *start != '\n' && *start != '#' && i < OSL_MAX_STRING)
239  res[i++] = *start++;
240  }
241  else {
242  // Parse from a string.
244  while (**str && **str != '\n' && **str != '#' && i < OSL_MAX_STRING)
245  res[i++] = *((*str)++);
246  }
247 
248  res[i] = '\0';
249  OSL_realloc(res, char *, strlen(res) + 1);
250  return res;
251 }
252 
253 
268 char * osl_util_read_tag(FILE * file, char ** str) {
269  char s[OSL_MAX_STRING], * start;
270  char * res;
271  int i = 0;
272 
273  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
274  OSL_error("one and only one of the two parameters can be non-NULL");
275 
276  // Skip blank/commented lines.
277  if (file != NULL) {
278  start = osl_util_skip_blank_and_comments(file, s);
279  str = &start;
280  }
281  else {
283  }
284 
285  // If the end of the input has been reached, return NULL.
286  if (((file != NULL) && (feof(file))) ||
287  ((str != NULL) && (**str == '\0')))
288  return NULL;
289 
290  // Pass the starting '<'.
291  if (**str != '<')
292  OSL_error("a \"<\" to start a tag was expected");
293  (*str)++;
294 
295  // Read the tag.
296  OSL_malloc(res, char *, (OSL_MAX_STRING + 1) * sizeof(char));
297  res[OSL_MAX_STRING] = '\0';
298 
299  while (**str && **str != '>') {
300  if (((**str >= 'A') && (**str <= 'Z')) ||
301  ((**str >= 'a') && (**str <= 'z')) ||
302  ((**str == '/') && (i == 0)) ||
303  (**str == '_')) {
304  res[i++] = *((*str)++);
305  res[i] = '\0';
306  }
307  else {
308  OSL_error("illegal character in the tag name");
309  }
310  }
311 
312  // Check we actually end up with a '>' and pass it.
313  if (**str != '>')
314  OSL_error("a \">\" to end a tag was expected");
315  (*str)++;
316 
317  return res;
318 }
319 
320 
334 char * osl_util_read_uptoflag(FILE * file, char ** str, char * flag) {
335  int high_water_mark = OSL_MAX_STRING;
336  int nb_chars = 0;
337  int lenflag = strlen(flag), lenstr;
338  int flag_found = 0;
339  char * res;
340 
341  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
342  OSL_error("one and only one of the two parameters can be non-NULL");
343 
344  OSL_malloc(res, char *, high_water_mark * sizeof(char));
345 
346  // Copy everything to the res string.
347  if (str != NULL)
348  lenstr = strlen(*str);
349  while (((str != NULL) && (nb_chars != lenstr)) ||
350  ((file != NULL) && (!feof(file)))) {
351  res[nb_chars++] = (str != NULL) ? *((*str)++) : fgetc(file);
352 
353  if ((nb_chars >= lenflag) &&
354  (!strncmp(&res[nb_chars - lenflag], flag, lenflag))) {
355  flag_found = 1;
356  break;
357  }
358 
359  if (nb_chars >= high_water_mark) {
360  high_water_mark += high_water_mark;
361  OSL_realloc(res, char *, high_water_mark * sizeof(char));
362  }
363  }
364 
365  if (!flag_found) {
366  OSL_debug("flag was not found, end of input reached");
367  free(res);
368  return NULL;
369  }
370 
371  // - 0-terminate the string.
372  OSL_realloc(res, char *, (nb_chars - strlen(flag) + 1) * sizeof(char));
373  res[nb_chars - strlen(flag)] = '\0';
374 
375  return res;
376 }
377 
378 
392 char * osl_util_read_uptotag(FILE * file, char ** str, char * name) {
393  char tag[strlen(name) + 3];
394 
395  sprintf(tag, "<%s>", name);
396  return osl_util_read_uptoflag(file, str, tag);
397 }
398 
399 
413 char * osl_util_read_uptoendtag(FILE * file, char ** str, char * name) {
414  char endtag[strlen(name) + 4];
415 
416  sprintf(endtag, "</%s>", name);
417  return osl_util_read_uptoflag(file, str, endtag);
418 }
419 
420 
430 char * osl_util_tag_content(char * str, char * name) {
431  int i;
432  char * start;
433  char * stop;
434  char tag[strlen(name) + 3];
435  char endtag[strlen(name) + 4];
436  int size = 0;
437  size_t lentag;
438  char * res = NULL;
439 
440  sprintf(tag, "<%s>", name);
441  sprintf(endtag, "</%s>", name);
442 
443  if (str) {
444  start = str;
445  lentag = strlen(tag);
446  for (; start && *start && strncmp(start, tag, lentag); ++start)
447  continue;
448 
449  // The tag 'tag' was not found.
450  if (! *start)
451  return NULL;
452  start += lentag;
453  stop = start;
454  lentag = strlen(endtag);
455  for (size = 0; *stop && strncmp(stop, endtag, lentag); ++stop, ++size)
456  continue;
457 
458  // the tag 'endtag' was not found.
459  if (! *stop)
460  return NULL;
461  OSL_malloc(res, char *, (size + 1) * sizeof(char));
462 
463  // Copy the chain between the two tags.
464  for (++start, i = 0; start != stop; ++start, ++i)
465  res[i] = *start;
466  res[i] = '\0';
467  }
468 
469  return res;
470 }
471 
472 
483 void osl_util_safe_strcat(char ** dst, char * src, int * hwm) {
484 
485  while ((int)(strlen(*dst) + strlen(src)) >= *hwm) {
486  *hwm += OSL_MAX_STRING;
487  OSL_realloc(*dst, char *, *hwm * sizeof(char));
488  }
489 
490  strcat(*dst, src);
491 }
492 
493 
504 char * osl_util_strdup(char const * str) {
505  char * dup = NULL;
506  OSL_malloc(dup, char *, (strlen(str) + 1) * sizeof(char));
507  if (dup) { strcpy(dup, str); }
508  return dup;
509 }
510 
511 
519  int precision = OSL_PRECISION_DP;
520  char * precision_env;
521 
522 #ifdef OSL_GMP_IS_HERE
523  precision = OSL_PRECISION_MP;
524 #endif
525 
526  precision_env = getenv(OSL_PRECISION_ENV);
527  if (precision_env != NULL) {
528  if (!strcmp(precision_env, OSL_PRECISION_ENV_SP))
529  precision = OSL_PRECISION_SP;
530  else if (!strcmp(precision_env, OSL_PRECISION_ENV_DP))
531  precision = OSL_PRECISION_DP;
532  else if (!strcmp(precision_env, OSL_PRECISION_ENV_MP)) {
533 #ifndef OSL_GMP_IS_HERE
534  OSL_warning("$OSL_PRECISION says GMP but osl not compiled with "
535  "GMP support, switching to double precision");
536  precision = OSL_PRECISION_DP;
537 #else
538  precision = OSL_PRECISION_MP;
539 #endif
540  }
541  else
542  OSL_warning("bad OSL_PRECISION environment value, see osl's manual");
543  }
544 
545  return precision;
546 }
547 
548 
557 void osl_util_print_provided(FILE * file, int provided, char * title) {
558  if (provided) {
559  fprintf(file, "# %s provided\n", title);
560  fprintf(file, "1\n");
561  }
562  else {
563  fprintf(file, "# %s not provided\n", title);
564  fprintf(file, "0\n\n");
565  }
566 }
567 
568 
578 static
579 int osl_util_identifier_is_here(char * expression, char * identifier,
580  int index) {
581  // If there is no space enough to find the identifier: no.
582  if (strlen(identifier) + index > strlen(expression))
583  return 0;
584 
585  // If there is a character before and it is in [A-Za-z0-9]: no.
586  if ((index > 0) &&
587  (((expression[index - 1] >= 'A') && (expression[index - 1] <= 'Z')) ||
588  ((expression[index - 1] >= 'a') && (expression[index - 1] <= 'z')) ||
589  ((expression[index - 1] >= '0') && (expression[index - 1] <= '9'))))
590  return 0;
591 
592  // If there is a character after and it is in [A-Za-z0-9]: no.
593  if ((strlen(identifier) + index < strlen(expression)) &&
594  (((expression[strlen(identifier) + index] >= 'A') &&
595  (expression[strlen(identifier) + index] <= 'Z')) ||
596  ((expression[strlen(identifier) + index] >= 'a') &&
597  (expression[strlen(identifier) + index] <= 'z')) ||
598  ((expression[strlen(identifier) + index] >= '0') &&
599  (expression[strlen(identifier) + index] <= '9'))))
600  return 0;
601 
602  // If the identifier string is not here: no.
603  if (strncmp(expression + index, identifier, strlen(identifier)))
604  return 0;
605 
606  return 1;
607 }
608 
609 
624 static
625 int osl_util_lazy_isolated_identifier(char * expression, char * identifier,
626  int index) {
627  int look;
628 
629  // If the first non-space character before is not in [\[(,\+=]: no.
630  look = index - 1;
631  while (look >= 0) {
632  if (isspace(expression[look]))
633  look--;
634  else
635  break;
636  }
637 
638  if ((look >= 0) &&
639  (expression[look] != '[') &&
640  (expression[look] != '(') &&
641  (expression[look] != '+') &&
642  (expression[look] != '=') &&
643  (expression[look] != ','))
644  return 0;
645 
646  // If the first non-space character after is not in [\]),;\+]: no.
647  look = index + strlen(identifier);
648  while (look < (int)strlen(expression)) {
649  if (isspace(expression[look]))
650  look++;
651  else
652  break;
653  }
654 
655  if ((look < (int)strlen(expression)) &&
656  (expression[look] != ']') &&
657  (expression[look] != ')') &&
658  (expression[look] != '+') &&
659  (expression[look] != ',') &&
660  (expression[look] != ';'))
661  return 0;
662 
663  return 1;
664 }
665 
666 
682 char * osl_util_identifier_substitution(char * expression,
683  char ** identifiers) {
684  size_t index;
685  int j, found;
686  int high_water_mark = OSL_MAX_STRING;
687  char buffer[OSL_MAX_STRING];
688  char * string;
689 
690  OSL_malloc(string, char *, high_water_mark * sizeof(char));
691  string[0] = '\0';
692 
693  index = 0;
694  while (index < strlen(expression)) {
695  j = 0;
696  found = 0;
697  while (identifiers[j] != NULL) {
698  if (osl_util_identifier_is_here(expression, identifiers[j], index)) {
699  if (osl_util_lazy_isolated_identifier(expression,identifiers[j],index))
700  sprintf(buffer, "@%d@", j);
701  else
702  sprintf(buffer, "(@%d@)", j);
703  osl_util_safe_strcat(&string, buffer, &high_water_mark);
704  index += strlen(identifiers[j]);
705  found = 1;
706  break;
707  }
708  j++;
709  }
710  if (!found) {
711  sprintf(buffer, "%c", expression[index]);
712  osl_util_safe_strcat(&string, buffer, &high_water_mark);
713  index++;
714  }
715  }
716 
717  return string;
718 }
719 
720 
721 
char * osl_util_read_uptoendtag(FILE *file, char **str, char *name)
Definition: util.c:413
char * osl_util_identifier_substitution(char *expression, char **identifiers)
Definition: util.c:682
static int osl_util_lazy_isolated_identifier(char *expression, char *identifier, int index)
Definition: util.c:625
char * osl_util_strdup(char const *str)
String duplicate.
Definition: util.c:504
void osl_util_safe_strcat(char **dst, char *src, int *hwm)
Definition: util.c:483
char * osl_util_read_uptoflag(FILE *file, char **str, char *flag)
Definition: util.c:334
int osl_util_get_precision()
Definition: util.c:518
void osl_util_sskip_blank_and_comments(char **str)
Definition: util.c:113
static int osl_util_identifier_is_here(char *expression, char *identifier, int index)
Definition: util.c:579
int osl_util_read_int(FILE *file, char **str)
Definition: util.c:140
char * osl_util_skip_blank_and_comments(FILE *file, char *str)
Definition: util.c:91
char * osl_util_read_string(FILE *file, char **str)
Definition: util.c:181
void osl_util_print_provided(FILE *file, int provided, char *title)
Definition: util.c:557
char * osl_util_read_tag(FILE *file, char **str)
Definition: util.c:268
char * osl_util_read_line(FILE *file, char **str)
Definition: util.c:226
char * osl_util_read_uptotag(FILE *file, char **str, char *name)
Definition: util.c:392
char * osl_util_tag_content(char *str, char *name)
Definition: util.c:430