OpenScop  0.9.1
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  size_t high_water_mark = OSL_MAX_STRING;
336  size_t nb_chars = 0;
337  size_t 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  lenstr = str != NULL ? strlen(*str) : 0;
348  while (((str != NULL) && (nb_chars != lenstr)) ||
349  ((file != NULL) && (!feof(file)))) {
350  res[nb_chars++] = (str != NULL) ? *((*str)++) : (char)fgetc(file);
351 
352  if ((nb_chars >= lenflag) &&
353  (!strncmp(&res[nb_chars - lenflag], flag, lenflag))) {
354  flag_found = 1;
355  break;
356  }
357 
358  if (nb_chars >= high_water_mark) {
359  high_water_mark += high_water_mark;
360  OSL_realloc(res, char *, high_water_mark * sizeof(char));
361  }
362  }
363 
364  if (!flag_found) {
365  OSL_debug("flag was not found, end of input reached");
366  free(res);
367  return NULL;
368  }
369 
370  // - 0-terminate the string.
371  OSL_realloc(res, char *, (nb_chars - strlen(flag) + 1) * sizeof(char));
372  res[nb_chars - strlen(flag)] = '\0';
373 
374  return res;
375 }
376 
377 
391 char * osl_util_read_uptotag(FILE * file, char ** str, char * name) {
392  char tag[strlen(name) + 3];
393 
394  sprintf(tag, "<%s>", name);
395  return osl_util_read_uptoflag(file, str, tag);
396 }
397 
398 
412 char * osl_util_read_uptoendtag(FILE * file, char ** str, char * name) {
413  char endtag[strlen(name) + 4];
414 
415  sprintf(endtag, "</%s>", name);
416  return osl_util_read_uptoflag(file, str, endtag);
417 }
418 
419 
429 char * osl_util_tag_content(char * str, char * name) {
430  int i;
431  char * start;
432  char * stop;
433  char tag[strlen(name) + 3];
434  char endtag[strlen(name) + 4];
435  size_t size = 0;
436  size_t lentag;
437  char * res = NULL;
438 
439  sprintf(tag, "<%s>", name);
440  sprintf(endtag, "</%s>", name);
441 
442  if (str) {
443  start = str;
444  lentag = strlen(tag);
445  for (; start && *start && strncmp(start, tag, lentag); ++start)
446  continue;
447 
448  // The tag 'tag' was not found.
449  if (! *start)
450  return NULL;
451  start += lentag;
452  stop = start;
453  lentag = strlen(endtag);
454  for (size = 0; *stop && strncmp(stop, endtag, lentag); ++stop, ++size)
455  continue;
456 
457  // the tag 'endtag' was not found.
458  if (! *stop)
459  return NULL;
460  OSL_malloc(res, char *, (size + 1) * sizeof(char));
461 
462  // Copy the chain between the two tags.
463  for (++start, i = 0; start != stop; ++start, ++i)
464  res[i] = *start;
465  res[i] = '\0';
466  }
467 
468  return res;
469 }
470 
471 
482 void osl_util_safe_strcat(char ** dst, char * src, size_t * hwm) {
483 
484  while ((strlen(*dst) + strlen(src)) >= *hwm) {
485  *hwm += OSL_MAX_STRING;
486  OSL_realloc(*dst, char *, *hwm * sizeof(char));
487  }
488 
489  strcat(*dst, src);
490 }
491 
492 
503 char * osl_util_strdup(char const * str) {
504  char * dup = NULL;
505  OSL_malloc(dup, char *, (strlen(str) + 1) * sizeof(char));
506  if (dup) { strcpy(dup, str); }
507  return dup;
508 }
509 
510 
518  int precision = OSL_PRECISION_DP;
519  char * precision_env;
520 
521 #ifdef OSL_GMP_IS_HERE
522  precision = OSL_PRECISION_MP;
523 #endif
524 
525  precision_env = getenv(OSL_PRECISION_ENV);
526  if (precision_env != NULL) {
527  if (!strcmp(precision_env, OSL_PRECISION_ENV_SP))
528  precision = OSL_PRECISION_SP;
529  else if (!strcmp(precision_env, OSL_PRECISION_ENV_DP))
530  precision = OSL_PRECISION_DP;
531  else if (!strcmp(precision_env, OSL_PRECISION_ENV_MP)) {
532 #ifndef OSL_GMP_IS_HERE
533  OSL_warning("$OSL_PRECISION says GMP but osl not compiled with "
534  "GMP support, switching to double precision");
535  precision = OSL_PRECISION_DP;
536 #else
537  precision = OSL_PRECISION_MP;
538 #endif
539  }
540  else
541  OSL_warning("bad OSL_PRECISION environment value, see osl's manual");
542  }
543 
544  return precision;
545 }
546 
547 
556 void osl_util_print_provided(FILE * file, int provided, char * title) {
557  if (provided) {
558  fprintf(file, "# %s provided\n", title);
559  fprintf(file, "1\n");
560  }
561  else {
562  fprintf(file, "# %s not provided\n", title);
563  fprintf(file, "0\n\n");
564  }
565 }
566 
567 
577 static
578 int osl_util_identifier_is_here(char * expression, char * identifier,
579  size_t index) {
580  size_t identifier_len = strlen(identifier);
581  size_t expression_len = strlen(expression);
582 
583  // If there is no space enough to find the identifier: no.
584  if (identifier_len + index > expression_len)
585  return 0;
586 
587  // If there is a character before and it is in [A-Za-z0-9_]: no.
588  if ((index > 0) &&
589  (((expression[index - 1] >= 'A') && (expression[index - 1] <= 'Z')) ||
590  ((expression[index - 1] >= 'a') && (expression[index - 1] <= 'z')) ||
591  ((expression[index - 1] >= '0') && (expression[index - 1] <= '9')) ||
592  (expression[index - 1] == '_')))
593  return 0;
594 
595  // If there is a character after and it is in [A-Za-z0-9_]: no.
596  if ((identifier_len + index < expression_len) &&
597  (((expression[identifier_len + index] >= 'A') &&
598  (expression[identifier_len + index] <= 'Z')) ||
599  ((expression[identifier_len + index] >= 'a') &&
600  (expression[identifier_len + index] <= 'z')) ||
601  ((expression[identifier_len + index] >= '0') &&
602  (expression[identifier_len + index] <= '9')) ||
603  ( expression[identifier_len + index] == '_')))
604  return 0;
605 
606  // If the identifier string is not here: no.
607  if (strncmp(expression + index, identifier, identifier_len))
608  return 0;
609 
610  return 1;
611 }
612 
613 
628 static
629 int osl_util_lazy_isolated_identifier(char * expression, char * identifier,
630  size_t index) {
631  size_t look;
632  size_t expression_len = strlen(expression);
633  size_t identifier_len = strlen(identifier);
634 
635  // If the first non-space character before is not in [\[(,\+=]: no.
636  look = index - 1;
637  while (look < index) {
638  if (isspace(expression[look]))
639  look--;
640  else
641  break;
642  }
643 
644  if ((look < index) &&
645  (expression[look] != '[') &&
646  (expression[look] != '(') &&
647  (expression[look] != '+') &&
648  (expression[look] != '=') &&
649  (expression[look] != ','))
650  return 0;
651 
652  // If the first non-space character after is not in [\]),;\+]: no.
653  look = index + identifier_len;
654  while (look < expression_len) {
655  if (isspace(expression[look]))
656  look++;
657  else
658  break;
659  }
660 
661  if ((look < expression_len) &&
662  (expression[look] != ']') &&
663  (expression[look] != ')') &&
664  (expression[look] != '+') &&
665  (expression[look] != ',') &&
666  (expression[look] != ';'))
667  return 0;
668 
669  return 1;
670 }
671 
672 
688 char * osl_util_identifier_substitution(char * expression,
689  char ** identifiers) {
690  size_t index;
691  int j, found;
692  size_t high_water_mark = OSL_MAX_STRING;
693  char buffer[OSL_MAX_STRING];
694  char * string;
695 
696  OSL_malloc(string, char *, high_water_mark * sizeof(char));
697  string[0] = '\0';
698 
699  index = 0;
700  while (index < strlen(expression)) {
701  j = 0;
702  found = 0;
703  while (identifiers[j] != NULL) {
704  if (osl_util_identifier_is_here(expression, identifiers[j], index)) {
705  if (osl_util_lazy_isolated_identifier(expression,identifiers[j],index))
706  sprintf(buffer, "@%d@", j);
707  else
708  sprintf(buffer, "(@%d@)", j);
709  osl_util_safe_strcat(&string, buffer, &high_water_mark);
710  index += strlen(identifiers[j]);
711  found = 1;
712  break;
713  }
714  j++;
715  }
716  if (!found) {
717  sprintf(buffer, "%c", expression[index]);
718  osl_util_safe_strcat(&string, buffer, &high_water_mark);
719  index++;
720  }
721  }
722 
723  return string;
724 }
725 
726 
727 
#define OSL_PRECISION_ENV_DP
Definition: macros.h:76
#define OSL_error(msg)
Definition: macros.h:149
static int osl_util_identifier_is_here(char *expression, char *identifier, size_t index)
Definition: util.c:578
#define OSL_warning(msg)
Definition: macros.h:144
int osl_util_read_int(FILE *file, char **str)
Definition: util.c:140
static int osl_util_lazy_isolated_identifier(char *expression, char *identifier, size_t index)
Definition: util.c:629
char * osl_util_tag_content(char *str, char *name)
Definition: util.c:429
void osl_util_safe_strcat(char **dst, char *src, size_t *hwm)
Definition: util.c:482
#define OSL_debug(msg)
Definition: macros.h:133
#define OSL_PRECISION_ENV_MP
Definition: macros.h:77
#define OSL_PRECISION_ENV_SP
Definition: macros.h:75
char * osl_util_read_string(FILE *file, char **str)
Definition: util.c:181
#define OSL_realloc(ptr, type, size)
Definition: macros.h:163
char * osl_util_strdup(char const *str)
String duplicate.
Definition: util.c:503
#define OSL_PRECISION_SP
Definition: macros.h:78
#define OSL_MAX_STRING
Definition: macros.h:94
char * osl_util_read_tag(FILE *file, char **str)
Definition: util.c:268
char * osl_util_read_uptotag(FILE *file, char **str, char *name)
Definition: util.c:391
void osl_util_sskip_blank_and_comments(char **str)
Definition: util.c:113
#define OSL_PRECISION_ENV
Definition: macros.h:74
#define OSL_PRECISION_MP
Definition: macros.h:80
char * osl_util_read_uptoendtag(FILE *file, char **str, char *name)
Definition: util.c:412
#define OSL_PRECISION_DP
Definition: macros.h:79
int osl_util_get_precision(void)
Definition: util.c:517
void osl_util_print_provided(FILE *file, int provided, char *title)
Definition: util.c:556
char * osl_util_read_uptoflag(FILE *file, char **str, char *flag)
Definition: util.c:334
char * osl_util_skip_blank_and_comments(FILE *file, char *str)
Definition: util.c:91
char * osl_util_identifier_substitution(char *expression, char **identifiers)
Definition: util.c:688
char * osl_util_read_line(FILE *file, char **str)
Definition: util.c:226
#define OSL_malloc(ptr, type, size)
Definition: macros.h:157