OpenScop 0.8.1
|
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