OpenScop
0.9.0
|
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' && **str != '#') 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 00181 char * osl_util_read_string(FILE * file, char ** str) { 00182 char s[OSL_MAX_STRING], * start; 00183 char * res; 00184 int i = 0; 00185 00186 if ((file != NULL && str != NULL) || (file == NULL && str == NULL)) 00187 OSL_error("one and only one of the two parameters can be non-NULL"); 00188 00189 OSL_malloc(res, char *, OSL_MAX_STRING * sizeof(char)); 00190 if (file != NULL) { 00191 // Parse from a file. 00192 start = osl_util_skip_blank_and_comments(file, s); 00193 if (sscanf(start, " %s", res) != 1) 00194 OSL_error("a string was expected"); 00195 } 00196 else { 00197 // Parse from a string. 00198 // Skip blank/commented lines. 00199 osl_util_sskip_blank_and_comments(str); 00200 00201 // Build the chain to analyze. 00202 while (**str && !isspace(**str) && **str != '\n' && **str != '#') 00203 s[i++] = *((*str)++); 00204 s[i] = '\0'; 00205 if (sscanf(s, "%s", res) != 1) 00206 OSL_error("a string was expected"); 00207 } 00208 00209 OSL_realloc(res, char *, strlen(res) + 1); 00210 return res; 00211 } 00212 00213 00226 char * osl_util_read_line(FILE * file, char ** str) { 00227 char s[OSL_MAX_STRING], * start; 00228 char * res; 00229 int i = 0; 00230 00231 if ((file != NULL && str != NULL) || (file == NULL && str == NULL)) 00232 OSL_error("one and only one of the two parameters can be non-NULL"); 00233 00234 OSL_malloc(res, char *, OSL_MAX_STRING * sizeof(char)); 00235 if (file != NULL) { 00236 // Parse from a file. 00237 start = osl_util_skip_blank_and_comments(file, s); 00238 while (*start && *start != '\n' && *start != '#' && i < OSL_MAX_STRING) 00239 res[i++] = *start++; 00240 } 00241 else { 00242 // Parse from a string. 00243 osl_util_sskip_blank_and_comments(str); 00244 while (**str && **str != '\n' && **str != '#' && i < OSL_MAX_STRING) 00245 res[i++] = *((*str)++); 00246 } 00247 00248 res[i] = '\0'; 00249 OSL_realloc(res, char *, strlen(res) + 1); 00250 return res; 00251 } 00252 00253 00268 char * osl_util_read_tag(FILE * file, char ** str) { 00269 char s[OSL_MAX_STRING], * start; 00270 char * res; 00271 int i = 0; 00272 00273 if ((file != NULL && str != NULL) || (file == NULL && str == NULL)) 00274 OSL_error("one and only one of the two parameters can be non-NULL"); 00275 00276 // Skip blank/commented lines. 00277 if (file != NULL) { 00278 start = osl_util_skip_blank_and_comments(file, s); 00279 str = &start; 00280 } 00281 else { 00282 osl_util_sskip_blank_and_comments(str); 00283 } 00284 00285 // If the end of the input has been reached, return NULL. 00286 if (((file != NULL) && (feof(file))) || 00287 ((str != NULL) && (**str == '\0'))) 00288 return NULL; 00289 00290 // Pass the starting '<'. 00291 if (**str != '<') 00292 OSL_error("a \"<\" to start a tag was expected"); 00293 (*str)++; 00294 00295 // Read the tag. 00296 OSL_malloc(res, char *, (OSL_MAX_STRING + 1) * sizeof(char)); 00297 res[OSL_MAX_STRING] = '\0'; 00298 00299 while (**str && **str != '>') { 00300 if (((**str >= 'A') && (**str <= 'Z')) || 00301 ((**str >= 'a') && (**str <= 'z')) || 00302 ((**str == '/') && (i == 0)) || 00303 (**str == '_')) { 00304 res[i++] = *((*str)++); 00305 res[i] = '\0'; 00306 } 00307 else { 00308 OSL_error("illegal character in the tag name"); 00309 } 00310 } 00311 00312 // Check we actually end up with a '>' and pass it. 00313 if (**str != '>') 00314 OSL_error("a \">\" to end a tag was expected"); 00315 (*str)++; 00316 00317 return res; 00318 } 00319 00320 00334 char * osl_util_read_uptoflag(FILE * file, char ** str, char * flag) { 00335 int high_water_mark = OSL_MAX_STRING; 00336 int nb_chars = 0; 00337 int lenflag = strlen(flag), lenstr; 00338 int flag_found = 0; 00339 char * res; 00340 00341 if ((file != NULL && str != NULL) || (file == NULL && str == NULL)) 00342 OSL_error("one and only one of the two parameters can be non-NULL"); 00343 00344 OSL_malloc(res, char *, high_water_mark * sizeof(char)); 00345 00346 // Copy everything to the res string. 00347 if (str != NULL) 00348 lenstr = strlen(*str); 00349 while (((str != NULL) && (nb_chars != lenstr)) || 00350 ((file != NULL) && (!feof(file)))) { 00351 res[nb_chars++] = (str != NULL) ? *((*str)++) : fgetc(file); 00352 00353 if ((nb_chars >= lenflag) && 00354 (!strncmp(&res[nb_chars - lenflag], flag, lenflag))) { 00355 flag_found = 1; 00356 break; 00357 } 00358 00359 if (nb_chars >= high_water_mark) { 00360 high_water_mark += high_water_mark; 00361 OSL_realloc(res, char *, high_water_mark * sizeof(char)); 00362 } 00363 } 00364 00365 if (!flag_found) { 00366 OSL_debug("flag was not found, end of input reached"); 00367 free(res); 00368 return NULL; 00369 } 00370 00371 // - 0-terminate the string. 00372 OSL_realloc(res, char *, (nb_chars - strlen(flag) + 1) * sizeof(char)); 00373 res[nb_chars - strlen(flag)] = '\0'; 00374 00375 return res; 00376 } 00377 00378 00392 char * osl_util_read_uptotag(FILE * file, char ** str, char * name) { 00393 char tag[strlen(name) + 3]; 00394 00395 sprintf(tag, "<%s>", name); 00396 return osl_util_read_uptoflag(file, str, tag); 00397 } 00398 00399 00413 char * osl_util_read_uptoendtag(FILE * file, char ** str, char * name) { 00414 char endtag[strlen(name) + 4]; 00415 00416 sprintf(endtag, "</%s>", name); 00417 return osl_util_read_uptoflag(file, str, endtag); 00418 } 00419 00420 00430 char * osl_util_tag_content(char * str, char * name) { 00431 int i; 00432 char * start; 00433 char * stop; 00434 char tag[strlen(name) + 3]; 00435 char endtag[strlen(name) + 4]; 00436 int size = 0; 00437 size_t lentag; 00438 char * res = NULL; 00439 00440 sprintf(tag, "<%s>", name); 00441 sprintf(endtag, "</%s>", name); 00442 00443 if (str) { 00444 start = str; 00445 lentag = strlen(tag); 00446 for (; start && *start && strncmp(start, tag, lentag); ++start) 00447 continue; 00448 00449 // The tag 'tag' was not found. 00450 if (! *start) 00451 return NULL; 00452 start += lentag; 00453 stop = start; 00454 lentag = strlen(endtag); 00455 for (size = 0; *stop && strncmp(stop, endtag, lentag); ++stop, ++size) 00456 continue; 00457 00458 // the tag 'endtag' was not found. 00459 if (! *stop) 00460 return NULL; 00461 OSL_malloc(res, char *, (size + 1) * sizeof(char)); 00462 00463 // Copy the chain between the two tags. 00464 for (++start, i = 0; start != stop; ++start, ++i) 00465 res[i] = *start; 00466 res[i] = '\0'; 00467 } 00468 00469 return res; 00470 } 00471 00472 00483 void osl_util_safe_strcat(char ** dst, char * src, int * hwm) { 00484 00485 while ((int)(strlen(*dst) + strlen(src)) >= *hwm) { 00486 *hwm += OSL_MAX_STRING; 00487 OSL_realloc(*dst, char *, *hwm * sizeof(char)); 00488 } 00489 00490 strcat(*dst, src); 00491 } 00492 00493 00504 char * osl_util_strdup(char const * str) { 00505 char * dup = NULL; 00506 OSL_malloc(dup, char *, (strlen(str) + 1) * sizeof(char)); 00507 if (dup) { strcpy(dup, str); } 00508 return dup; 00509 } 00510 00511 00518 int osl_util_get_precision() { 00519 int precision = OSL_PRECISION_DP; 00520 char * precision_env; 00521 00522 #ifdef OSL_GMP_IS_HERE 00523 precision = OSL_PRECISION_MP; 00524 #endif 00525 00526 precision_env = getenv(OSL_PRECISION_ENV); 00527 if (precision_env != NULL) { 00528 if (!strcmp(precision_env, OSL_PRECISION_ENV_SP)) 00529 precision = OSL_PRECISION_SP; 00530 else if (!strcmp(precision_env, OSL_PRECISION_ENV_DP)) 00531 precision = OSL_PRECISION_DP; 00532 else if (!strcmp(precision_env, OSL_PRECISION_ENV_MP)) { 00533 #ifndef OSL_GMP_IS_HERE 00534 OSL_warning("$OSL_PRECISION says GMP but osl not compiled with " 00535 "GMP support, switching to double precision"); 00536 precision = OSL_PRECISION_DP; 00537 #else 00538 precision = OSL_PRECISION_MP; 00539 #endif 00540 } 00541 else 00542 OSL_warning("bad OSL_PRECISION environment value, see osl's manual"); 00543 } 00544 00545 return precision; 00546 } 00547 00548 00557 void osl_util_print_provided(FILE * file, int provided, char * title) { 00558 if (provided) { 00559 fprintf(file, "# %s provided\n", title); 00560 fprintf(file, "1\n"); 00561 } 00562 else { 00563 fprintf(file, "# %s not provided\n", title); 00564 fprintf(file, "0\n\n"); 00565 } 00566 } 00567 00568 00578 static 00579 int osl_util_identifier_is_here(char * expression, char * identifier, 00580 int index) { 00581 // If there is no space enough to find the identifier: no. 00582 if (strlen(identifier) + index > strlen(expression)) 00583 return 0; 00584 00585 // If there is a character before and it is in [A-Za-z0-9]: no. 00586 if ((index > 0) && 00587 (((expression[index - 1] >= 'A') && (expression[index - 1] <= 'Z')) || 00588 ((expression[index - 1] >= 'a') && (expression[index - 1] <= 'z')) || 00589 ((expression[index - 1] >= '0') && (expression[index - 1] <= '9')))) 00590 return 0; 00591 00592 // If there is a character after and it is in [A-Za-z0-9]: no. 00593 if ((strlen(identifier) + index < strlen(expression)) && 00594 (((expression[strlen(identifier) + index] >= 'A') && 00595 (expression[strlen(identifier) + index] <= 'Z')) || 00596 ((expression[strlen(identifier) + index] >= 'a') && 00597 (expression[strlen(identifier) + index] <= 'z')) || 00598 ((expression[strlen(identifier) + index] >= '0') && 00599 (expression[strlen(identifier) + index] <= '9')))) 00600 return 0; 00601 00602 // If the identifier string is not here: no. 00603 if (strncmp(expression + index, identifier, strlen(identifier))) 00604 return 0; 00605 00606 return 1; 00607 } 00608 00609 00624 static 00625 int osl_util_lazy_isolated_identifier(char * expression, char * identifier, 00626 int index) { 00627 int look; 00628 00629 // If the first non-space character before is not in [\[(,\+=]: no. 00630 look = index - 1; 00631 while (look >= 0) { 00632 if (isspace(expression[look])) 00633 look--; 00634 else 00635 break; 00636 } 00637 00638 if ((look >= 0) && 00639 (expression[look] != '[') && 00640 (expression[look] != '(') && 00641 (expression[look] != '+') && 00642 (expression[look] != '=') && 00643 (expression[look] != ',')) 00644 return 0; 00645 00646 // If the first non-space character after is not in [\]),;\+]: no. 00647 look = index + strlen(identifier); 00648 while (look < (int)strlen(expression)) { 00649 if (isspace(expression[look])) 00650 look++; 00651 else 00652 break; 00653 } 00654 00655 if ((look < (int)strlen(expression)) && 00656 (expression[look] != ']') && 00657 (expression[look] != ')') && 00658 (expression[look] != '+') && 00659 (expression[look] != ',') && 00660 (expression[look] != ';')) 00661 return 0; 00662 00663 return 1; 00664 } 00665 00666 00682 char * osl_util_identifier_substitution(char * expression, 00683 char ** identifiers) { 00684 size_t index; 00685 int j, found; 00686 int high_water_mark = OSL_MAX_STRING; 00687 char buffer[OSL_MAX_STRING]; 00688 char * string; 00689 00690 OSL_malloc(string, char *, high_water_mark * sizeof(char)); 00691 string[0] = '\0'; 00692 00693 index = 0; 00694 while (index < strlen(expression)) { 00695 j = 0; 00696 found = 0; 00697 while (identifiers[j] != NULL) { 00698 if (osl_util_identifier_is_here(expression, identifiers[j], index)) { 00699 if (osl_util_lazy_isolated_identifier(expression,identifiers[j],index)) 00700 sprintf(buffer, "@%d@", j); 00701 else 00702 sprintf(buffer, "(@%d@)", j); 00703 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00704 index += strlen(identifiers[j]); 00705 found = 1; 00706 break; 00707 } 00708 j++; 00709 } 00710 if (!found) { 00711 sprintf(buffer, "%c", expression[index]); 00712 osl_util_safe_strcat(&string, buffer, &high_water_mark); 00713 index++; 00714 } 00715 } 00716 00717 return string; 00718 } 00719 00720 00721