OpenScop 0.8.1

util.c

Go to the documentation of this file.
00001 
00002     /*+-----------------------------------------------------------------**
00003      **                       OpenScop Library                          **
00004      **-----------------------------------------------------------------**
00005      **                            util.c                               **
00006      **-----------------------------------------------------------------**
00007      **                   First version: 08/10/2010                     **
00008      **-----------------------------------------------------------------**
00009 
00010  
00011  *****************************************************************************
00012  * OpenScop: Structures and formats for polyhedral tools to talk together    *
00013  *****************************************************************************
00014  *    ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__,                *
00015  *    /   / /  //  //  //  // /   / /  //  //   / /  // /  /|,_,             *
00016  *   /   / /  //  //  //  // /   / /  //  //   / /  // /  / / /\             *
00017  *  |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/  \            *
00018  *  | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\  \ /\           *
00019  *  | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\          *
00020  *  | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \  \         *
00021  *  | P |n| l | = | s | t |=| = |d| = | = | = | |   |=| o | | \# \  \        *
00022  *  | H | | y |   | e | o | | = |l|   |   | = | |   | | G | |  \  \  \       *
00023  *  | I | |   |   | e |   | |   | |   |   |   | |   | |   | |   \  \  \      *
00024  *  | T | |   |   |   |   | |   | |   |   |   | |   | |   | |    \  \  \     *
00025  *  | E | |   |   |   |   | |   | |   |   |   | |   | |   | |     \  \  \    *
00026  *  | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | /      \* \  \   *
00027  *  | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/        \  \ /   *
00028  *  '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---'          '--'    *
00029  *                                                                           *
00030  * Copyright (C) 2008 University Paris-Sud 11 and INRIA                      *
00031  *                                                                           *
00032  * (3-clause BSD license)                                                    *
00033  * Redistribution and use in source  and binary forms, with or without       *
00034  * modification, are permitted provided that the following conditions        *
00035  * are met:                                                                  *
00036  *                                                                           *
00037  * 1. Redistributions of source code must retain the above copyright notice, *
00038  *    this list of conditions and the following disclaimer.                  *
00039  * 2. Redistributions in binary form must reproduce the above copyright      *
00040  *    notice, this list of conditions and the following disclaimer in the    *
00041  *    documentation and/or other materials provided with the distribution.   *
00042  * 3. The name of the author may not be used to endorse or promote products  *
00043  *    derived from this software without specific prior written permission.  *
00044  *                                                                           *
00045  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      *
00046  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
00047  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   *
00048  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          *
00049  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  *
00050  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
00051  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     *
00052  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       *
00053  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  *
00054  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         *
00055  *                                                                           *
00056  * OpenScop Library, a library to manipulate OpenScop formats and data       *
00057  * structures. Written by:                                                   *
00058  * Cedric Bastoul     <Cedric.Bastoul@u-psud.fr> and                         *
00059  * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr>                          *
00060  *                                                                           *
00061  *****************************************************************************/
00062 
00063 #include <stdlib.h>
00064 #include <stdio.h>
00065 #include <ctype.h>
00066 #include <string.h>
00067 
00068 #include <osl/macros.h>
00069 #include <osl/util.h>
00070 
00071 
00072 /*+***************************************************************************
00073  *                             Utility functions                             *
00074  *****************************************************************************/
00075 
00076 
00091 char * osl_util_skip_blank_and_comments(FILE * file, char * str) {
00092   char * start;
00093 
00094   do {
00095     start = fgets(str, OSL_MAX_STRING, file);
00096     while ((start != NULL) && isspace(*start) && (*start != '\n'))
00097       start++;
00098   }
00099   while (start != NULL && (*start == '#' || *start == '\n'));
00100 
00101   return start;
00102 }
00103 
00104 
00113 void osl_util_sskip_blank_and_comments(char ** str) {
00114   do {
00115     // Skip spaces/blanc lines.
00116     while (*str && **str && isspace(**str))
00117       (*str)++;
00118 
00119     // Skip the comment if any.
00120     if (*str && **str && **str == '#') {
00121       while (**str && **str != '\n') {
00122         (*str)++;
00123       }
00124     }
00125   }
00126   while (*str && **str && **str == '\n');
00127 }
00128 
00129 
00140 int osl_util_read_int(FILE * file, char ** str) {
00141   char s[OSL_MAX_STRING], * start;
00142   int res;
00143   int i = 0;
00144 
00145   if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
00146     OSL_error("one and only one of the two parameters can be non-NULL");
00147 
00148   if (file != NULL) {
00149     // Parse from a file.
00150     start = osl_util_skip_blank_and_comments(file, s);
00151     if (sscanf(start, " %d", &res) != 1)
00152       OSL_error("an int was expected");
00153   }
00154   else {
00155     // Parse from a string.
00156     // Skip blank/commented lines.
00157     osl_util_sskip_blank_and_comments(str);
00158     
00159     // Build the chain to analyze.
00160     while (**str && !isspace(**str) && **str != '\n')
00161       s[i++] = *((*str)++);
00162     s[i] = '\0';
00163     if (sscanf(s, "%d", &res) != 1)
00164       OSL_error("an int was expected");
00165   }
00166 
00167   return res;
00168 }
00169 
00170 
00184 char * osl_util_read_tag(FILE * file, char ** str) {
00185   char s[OSL_MAX_STRING], * start;
00186   char * res;
00187   int i = 0;
00188 
00189   if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
00190     OSL_error("one and only one of the two parameters can be non-NULL");
00191 
00192   // Skip blank/commented lines.
00193   if (file != NULL) {
00194     start = osl_util_skip_blank_and_comments(file, s);
00195     str = &start;
00196   }
00197   else {
00198     osl_util_sskip_blank_and_comments(str);
00199   }
00200 
00201   // Pass the starting '<'.
00202   if (**str != '<')
00203     OSL_error("a \"<\" to start a tag was expected");
00204   (*str)++;
00205 
00206   // Read the tag.
00207   OSL_malloc(res, char *, (OSL_MAX_STRING + 1) * sizeof(char));
00208   res[OSL_MAX_STRING] = '\0';
00209   
00210   while (**str && **str != '>') {
00211     if (((**str >= 'A') && (**str <= 'Z')) ||
00212         ((**str >= 'a') && (**str <= 'z')) ||
00213         ((**str == '/') && (i == 0))       ||
00214         (**str == '_')) {
00215       res[i++] = *((*str)++);
00216       res[i] = '\0';
00217     }
00218     else {
00219       OSL_error("illegal character in the tag name");
00220     }
00221   }
00222 
00223   // Check we actually end up with a '>' and pass it.
00224   if (**str != '>')
00225     OSL_error("a \">\" to end a tag was expected");
00226   (*str)++;
00227 
00228   return res;
00229 }
00230 
00231 
00241 char * osl_util_read_uptotag(FILE * file, char * tag) {
00242   int high_water_mark = OSL_MAX_STRING;
00243   int nb_chars = 0;
00244   int lentag = strlen(tag);
00245   int tag_found = 0;
00246   char * res;
00247 
00248   OSL_malloc(res, char *, high_water_mark * sizeof(char));
00249 
00250   // - Copy everything to the res string.
00251   while (!feof(file)) {
00252     res[nb_chars] = fgetc(file); 
00253     nb_chars++;
00254 
00255     if ((nb_chars >= lentag) &&
00256         (!strncmp(&res[nb_chars - lentag], tag, lentag))) {
00257       tag_found = 1;
00258       break;
00259     }
00260 
00261     if (nb_chars >= high_water_mark) {
00262       high_water_mark += high_water_mark;
00263       OSL_realloc(res, char *, high_water_mark * sizeof(char));
00264     }
00265   }
00266 
00267   if (!tag_found) {
00268     OSL_debug("tag was not found, end of file reached");
00269     free(res);
00270     return NULL;
00271   }
00272 
00273   // - 0-terminate the string.
00274   OSL_realloc(res, char *, (nb_chars - strlen(tag) + 1) * sizeof(char));
00275   res[nb_chars - strlen(tag)] = '\0';
00276 
00277   return res;
00278 }
00279 
00280 
00291 char * osl_util_read_uptoendtag(FILE * file, char * name) {
00292   char tag[strlen(name) + 4];
00293   
00294   sprintf(tag, "</%s>", name);
00295   return osl_util_read_uptotag(file, tag);
00296 }
00297 
00298 
00308 char * osl_util_tag_content(char * str, char * name) {
00309   int i;
00310   char * start;
00311   char * stop;
00312   char tag[strlen(name) + 3];
00313   char endtag[strlen(name) + 4];
00314   int size = 0;
00315   int lentag;
00316   char * res = NULL;
00317 
00318   sprintf(tag, "<%s>", name);
00319   sprintf(endtag, "</%s>", name);
00320   
00321   if (str) {
00322     start = str;
00323     lentag = strlen(tag);
00324     for (; start && *start && strncmp(start, tag, lentag); ++start)
00325       continue;
00326     
00327     // The tag 'tag' was not found.
00328     if (! *start)
00329       return NULL;
00330     start += lentag;
00331     stop = start;
00332     lentag = strlen(endtag);
00333     for (size = 0; *stop && strncmp(stop, endtag, lentag); ++stop, ++size)
00334       continue;
00335     
00336     // the tag 'endtag' was not found.
00337     if (! *stop)
00338       return NULL;
00339     OSL_malloc(res, char *, (size + 1) * sizeof(char));
00340     
00341     // Copy the chain between the two tags.
00342     for (++start, i = 0; start != stop; ++start, ++i)
00343       res[i] = *start;
00344     res[i] = '\0';
00345   }
00346 
00347   return res;
00348 }
00349 
00350 
00361 void osl_util_safe_strcat(char ** dst, char * src, int * hwm) {
00362 
00363   while (strlen(*dst) + strlen(src) >= *hwm) {
00364     *hwm += OSL_MAX_STRING;
00365     OSL_realloc(*dst, char *, *hwm * sizeof(char));
00366   }
00367 
00368   strcat(*dst, src);
00369 }
00370 
00371 
00378 int osl_util_get_precision() {
00379   int precision = OSL_PRECISION_DP;
00380   char * precision_env;
00381 
00382 #ifdef OSL_GMP_IS_HERE
00383   precision = OSL_PRECISION_MP;
00384 #endif
00385 
00386   precision_env = getenv(OSL_PRECISION_ENV);
00387   if (precision_env != NULL) {
00388     if (!strcmp(precision_env, OSL_PRECISION_ENV_SP))
00389       precision = OSL_PRECISION_SP;
00390     else if (!strcmp(precision_env, OSL_PRECISION_ENV_DP))
00391       precision = OSL_PRECISION_DP;
00392     else if (!strcmp(precision_env, OSL_PRECISION_ENV_MP))
00393       precision = OSL_PRECISION_MP;
00394     else
00395       OSL_warning("bad precision environment value");
00396   }
00397 
00398   return precision;
00399 }
00400 
00401 
00410 void osl_util_print_provided(FILE * file, int provided, char * title) {
00411   if (provided) {
00412     fprintf(file, "# %s provided\n", title);
00413     fprintf(file, "1\n");
00414   }
00415   else {
00416     fprintf(file, "# %s not provided\n", title);
00417     fprintf(file, "0\n\n");
00418   }
00419 }
00420 
00421 
00431 static
00432 int osl_util_identifier_is_here(char * expression, char * identifier,
00433                                 int index) {
00434   // If there is no space enough to find the identifier: no.
00435   if (strlen(identifier) + index > strlen(expression))
00436     return 0;
00437   
00438   // If there is a character before and it is in [A-Za-z0-9]: no.
00439   if ((index > 0) &&
00440       (((expression[index - 1] >= 'A') && (expression[index - 1] <= 'Z')) || 
00441        ((expression[index - 1] >= 'a') && (expression[index - 1] <= 'z')) || 
00442        ((expression[index - 1] >= '0') && (expression[index - 1] <= '9'))))
00443     return 0;
00444 
00445   // If there is a character after and it is in [A-Za-z0-9]: no.
00446   if ((strlen(identifier) + index < strlen(expression)) &&
00447       (((expression[strlen(identifier) + index] >= 'A') &&
00448         (expression[strlen(identifier) + index] <= 'Z'))   || 
00449        ((expression[strlen(identifier) + index] >= 'a') &&
00450         (expression[strlen(identifier) + index] <= 'z'))   || 
00451        ((expression[strlen(identifier) + index] >= '0') &&
00452         (expression[strlen(identifier) + index] <= '9'))))
00453     return 0;
00454 
00455   // If the identifier string is not here: no.
00456   if (strncmp(expression + index, identifier, strlen(identifier)))
00457     return 0;
00458 
00459   return 1;
00460 }
00461 
00462 
00477 static
00478 int osl_util_lazy_isolated_identifier(char * expression, char * identifier,
00479                                       int index) {
00480   int look;
00481 
00482   // If the first non-space character before is not in [\[(,\+=]: no. 
00483   look = index - 1;
00484   while (look >= 0) {
00485     if (isspace(expression[look]))
00486       look--;
00487     else
00488       break;
00489   }
00490 
00491   if ((look >= 0) &&
00492       (expression[look] != '[') &&
00493       (expression[look] != '(') &&
00494       (expression[look] != '+') &&
00495       (expression[look] != '=') &&
00496       (expression[look] != ','))
00497     return 0;
00498         
00499   // If the first non-space character after is not in [\]),;\+]: no. 
00500   look = index + strlen(identifier);
00501   while (look < strlen(expression)) {
00502     if (isspace(expression[look]))
00503       look++;
00504     else
00505       break;
00506   }
00507 
00508   if ((look < strlen(expression)) &&
00509       (expression[look] != ']')   &&
00510       (expression[look] != ')')   &&
00511       (expression[look] != '+')   &&
00512       (expression[look] != ',')   &&
00513       (expression[look] != ';'))
00514     return 0;
00515 
00516   return 1;
00517 }
00518 
00519 
00535 char * osl_util_identifier_substitution(char * expression,
00536                                         char ** identifiers) {
00537   int index, j, found;
00538   int high_water_mark = OSL_MAX_STRING;
00539   char buffer[OSL_MAX_STRING];
00540   char * string;
00541  
00542   OSL_malloc(string, char *, high_water_mark * sizeof(char));
00543   string[0] = '\0';
00544 
00545   index = 0;
00546   while (index < strlen(expression)) {
00547     j = 0;
00548     found = 0;
00549     while (identifiers[j] != NULL) {
00550       if (osl_util_identifier_is_here(expression, identifiers[j], index)) {
00551         if (osl_util_lazy_isolated_identifier(expression,identifiers[j],index))
00552           sprintf(buffer, "@%d@", j);
00553         else
00554           sprintf(buffer, "(@%d@)", j);
00555         osl_util_safe_strcat(&string, buffer, &high_water_mark);
00556         index += strlen(identifiers[j]);
00557         found = 1;
00558         break;
00559       }
00560       j++;
00561     }
00562     if (!found) {
00563       sprintf(buffer, "%c", expression[index]);
00564       osl_util_safe_strcat(&string, buffer, &high_water_mark);
00565       index++;
00566     }
00567   }
00568 
00569   return string;
00570 }
00571 
00572 
00573