Clan
0.8.0
|
00001 00002 /*+------- <| --------------------------------------------------------** 00003 ** A Clan ** 00004 **--- /.\ -----------------------------------------------------** 00005 ** <| [""M# symbol.c ** 00006 **- A | # -----------------------------------------------------** 00007 ** /.\ [""M# First version: 01/05/2008 ** 00008 **- [""M# | # U"U#U -----------------------------------------------** 00009 | # | # \ .:/ 00010 | # | #___| # 00011 ****** | "--' .-" ****************************************************** 00012 * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * 00013 **** | # ## ###### ***************************************************** 00014 * \ .::::'/ * 00015 * \ ::::'/ Copyright (C) 2008 University Paris-Sud 11 * 00016 * :8a| # # ## * 00017 * ::88a ### This is free software; you can redistribute it * 00018 * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * 00019 * ::::::::888a88a[]::: General Public License as published by the Free * 00020 *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * 00021 *::::::::8::::888:Y8888:: License, or (at your option) any later version. * 00022 *::::':::88::::888::Y88a::::::::::::... * 00023 *::'::.. . ..... .. ... . * 00024 * This software is distributed in the hope that it will be useful, but * 00025 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * 00026 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * 00027 * for more details. * 00028 * * 00029 * You should have received a copy of the GNU Lesser General Public License * 00030 * along with software; if not, write to the Free Software Foundation, Inc., * 00031 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 00032 * * 00033 * Clan, the Chunky Loop Analyzer * 00034 * Written by Cedric Bastoul, Cedric.Bastoul@u-psud.fr * 00035 * * 00036 ******************************************************************************/ 00037 00038 00039 #include <stdlib.h> 00040 #include <stdio.h> 00041 #include <ctype.h> 00042 #include <string.h> 00043 00044 #include <osl/macros.h> 00045 #include <osl/strings.h> 00046 #include <osl/generic.h> 00047 #include <osl/relation.h> 00048 #include <osl/relation_list.h> 00049 #include <osl/extensions/arrays.h> 00050 #include <clan/macros.h> 00051 #include <clan/symbol.h> 00052 00053 00054 void yyerror(char*); 00055 00056 00057 /*+**************************************************************************** 00058 * Structure display function * 00059 ******************************************************************************/ 00060 00061 00073 void clan_symbol_print_structure(FILE* file, clan_symbol_p symbol, int level) { 00074 int i, j, first = 1, number = 1; 00075 00076 if (symbol != NULL) { 00077 // Go to the right level. 00078 for(j = 0; j < level; j++) 00079 fprintf(file, "|\t"); 00080 fprintf(file, "+-- clan_symbol_t (node %d)\n", number); 00081 } else { 00082 // Go to the right level. 00083 for(j = 0; j < level; j++) 00084 fprintf(file, "|\t"); 00085 fprintf(file, "+-- NULL symbol\n"); 00086 } 00087 00088 while (symbol != NULL) { 00089 if (!first) { 00090 // Go to the right level. 00091 for (j = 0; j < level; j++) 00092 fprintf(file, "|\t"); 00093 fprintf(file, "| clan_symbol_t (node %d)\n", number); 00094 } else { 00095 first = 0; 00096 } 00097 00098 // A blank line. 00099 for (j = 0; j <= level + 1; j++) 00100 fprintf(file, "|\t"); 00101 fprintf(file, "\n"); 00102 00103 // Go to the right level and print the key. 00104 for (j = 0; j <= level; j++) 00105 fprintf(file, "|\t"); 00106 fprintf(file, "Key: %d\n", symbol->key); 00107 00108 // A blank line. 00109 for (j = 0; j <= level+1; j++) 00110 fprintf(file, "|\t"); 00111 fprintf(file, "\n"); 00112 00113 // Print the identifier. 00114 for (i = 0; i <= level; i++) 00115 fprintf(file, "|\t"); 00116 if (symbol->identifier != NULL) 00117 fprintf(file, "+-- Identifier: %s\n", symbol->identifier); 00118 else 00119 fprintf(file, "+-- No identifier\n"); 00120 00121 // A blank line. 00122 for(j = 0; j <= level + 1; j++) 00123 fprintf(file, "|\t") ; 00124 fprintf(file, "\n") ; 00125 00126 // Go to the right level and print the type. 00127 for (j = 0; j <= level; j++) 00128 fprintf(file, "|\t") ; 00129 fprintf(file, "Type: ") ; 00130 switch (symbol->type) { 00131 case CLAN_TYPE_ITERATOR : fprintf(file, "Iterator\n"); break; 00132 case CLAN_TYPE_PARAMETER: fprintf(file, "Parameter\n"); break; 00133 case CLAN_TYPE_ARRAY : fprintf(file, "Array\n"); break; 00134 case CLAN_TYPE_FUNCTION : fprintf(file, "Function\n"); break; 00135 default : fprintf(file, "Unknown\n") ; 00136 } 00137 00138 // A blank line. 00139 for (j = 0; j <= level + 1; j++) 00140 fprintf(file, "|\t"); 00141 fprintf(file, "\n"); 00142 00143 // Go to the right level and print the rank. 00144 for (j = 0; j <= level; j++) 00145 fprintf(file, "|\t"); 00146 fprintf(file, "Rank: %d\n", symbol->rank); 00147 00148 // A blank line. 00149 for (j = 0; j <= level + 1; j++) 00150 fprintf(file, "|\t"); 00151 fprintf(file, "\n"); 00152 00153 symbol = symbol->next; 00154 number++; 00155 00156 // Next line. 00157 if (symbol != NULL) { 00158 for (j = 0; j <= level; j++) 00159 fprintf(file, "|\t"); 00160 fprintf(file, "V\n"); 00161 } 00162 } 00163 00164 // The last line. 00165 for(j = 0; j <= level; j++) 00166 fprintf(file, "|\t"); 00167 fprintf(file, "\n"); 00168 } 00169 00170 00178 void clan_symbol_print(FILE* file, clan_symbol_p symbol) { 00179 clan_symbol_print_structure(file, symbol, 0); 00180 } 00181 00182 00183 /*+**************************************************************************** 00184 * Memory allocation/deallocation function * 00185 ******************************************************************************/ 00186 00187 00195 clan_symbol_p clan_symbol_malloc() { 00196 clan_symbol_p symbol; 00197 00198 CLAN_malloc(symbol, clan_symbol_p, sizeof(clan_symbol_t)); 00199 symbol->key = CLAN_UNDEFINED; 00200 symbol->identifier = NULL; 00201 symbol->type = CLAN_UNDEFINED; 00202 symbol->rank = CLAN_UNDEFINED; 00203 symbol->next = NULL; 00204 00205 return symbol; 00206 } 00207 00208 00214 void clan_symbol_free(clan_symbol_p symbol) { 00215 clan_symbol_p next; 00216 00217 while (symbol != NULL) { 00218 next = symbol->next; 00219 free(symbol->identifier); 00220 free(symbol); 00221 symbol = next; 00222 } 00223 } 00224 00225 00226 /*+**************************************************************************** 00227 * Processing functions * 00228 ******************************************************************************/ 00229 00230 00240 clan_symbol_p clan_symbol_lookup(clan_symbol_p symbol, char* identifier) { 00241 while (symbol != NULL) { 00242 if (strcmp(symbol->identifier, identifier) == 0) 00243 return symbol; 00244 else 00245 symbol = symbol->next; 00246 } 00247 return NULL; 00248 } 00249 00250 00260 clan_symbol_p clan_symbol_lookup_by_key(clan_symbol_p symbol, int key) { 00261 while (symbol != NULL) { 00262 if (symbol->key == key) 00263 return symbol; 00264 else 00265 symbol = symbol->next; 00266 } 00267 return NULL; 00268 } 00269 00270 00277 static 00278 int clan_symbol_generate_new_key(clan_symbol_p table) { 00279 int key = CLAN_KEY_START; 00280 00281 while (table != NULL) { 00282 if (table->key >= key) 00283 key = table->key + 1; 00284 table = table->next; 00285 } 00286 return key; 00287 } 00288 00289 00301 clan_symbol_p clan_symbol_add(clan_symbol_p* table, char* identifier, 00302 int type) { 00303 clan_symbol_p symbol, tmp = *table; 00304 00305 // If the identifier is already in the table, do nothing. 00306 symbol = clan_symbol_lookup(*table, identifier); 00307 if (symbol != NULL) 00308 return symbol; 00309 00310 // Else, we allocate and fill a new clan_symbol_t node. 00311 symbol = clan_symbol_malloc(); 00312 symbol->key = clan_symbol_generate_new_key(*table); 00313 symbol->identifier = strdup(identifier); 00314 symbol->type = type; 00315 00316 // We put the new symbol at the end of the table. 00317 if (*table == NULL) { 00318 *table = symbol; 00319 } else { 00320 while (tmp->next != NULL) 00321 tmp = tmp->next; 00322 tmp->next = symbol; 00323 } 00324 00325 return symbol; 00326 } 00327 00328 00338 int clan_symbol_get_key(clan_symbol_p symbol, char* identifier) { 00339 while (symbol != NULL) { 00340 if (strcmp(symbol->identifier,identifier) == 0) 00341 return symbol->key; 00342 else 00343 symbol = symbol->next; 00344 } 00345 return CLAN_UNDEFINED; 00346 } 00347 00348 00358 int clan_symbol_get_rank(clan_symbol_p symbol, char* identifier) { 00359 while (symbol != NULL) { 00360 if (strcmp(symbol->identifier,identifier) == 0) 00361 return symbol->rank; 00362 else 00363 symbol = symbol->next; 00364 } 00365 return CLAN_UNDEFINED; 00366 } 00367 00368 00378 int clan_symbol_get_type(clan_symbol_p symbol, char* identifier) { 00379 while (symbol != NULL) { 00380 if (strcmp(symbol->identifier,identifier) == 0) 00381 return symbol->type; 00382 else 00383 symbol = symbol->next; 00384 } 00385 return CLAN_UNDEFINED; 00386 } 00387 00388 00399 osl_strings_p clan_symbol_array_to_strings(clan_symbol_p* sarray, int size) { 00400 int i, length; 00401 char** identifiers = NULL; 00402 osl_strings_p strings; 00403 00404 // Allocate, initialize and NULL-terminate the array of strings. 00405 CLAN_malloc(identifiers, char**, (size + 1) * sizeof(char *)); 00406 for (i = 0; i <= size; i++) 00407 identifiers[i] = NULL; 00408 00409 // Fill the array of strings. 00410 for (i = 0; i < size; i++) { 00411 length = strlen((sarray[i])->identifier) + 1; 00412 CLAN_malloc(identifiers[i], char*, length * sizeof(char)); 00413 strcpy(identifiers[i], (sarray[i])->identifier); 00414 } 00415 00416 // Build the osl_strings_t container. 00417 strings = osl_strings_malloc(); 00418 strings->string = identifiers; 00419 00420 return strings; 00421 } 00422 00423 00432 int clan_symbol_nb_of_type(clan_symbol_p symbol, int type) { 00433 int nb = 0; 00434 00435 while (symbol != NULL) { 00436 if (symbol->type == type) 00437 nb++; 00438 symbol = symbol->next; 00439 } 00440 00441 return nb; 00442 } 00443 00444 00457 osl_generic_p clan_symbol_to_strings(clan_symbol_p symbol, int type) { 00458 int i, length, nb_identifiers = 0; 00459 char** identifiers = NULL; 00460 osl_strings_p strings; 00461 osl_generic_p generic; 00462 00463 nb_identifiers = clan_symbol_nb_of_type(symbol, type); 00464 if (nb_identifiers == 0) 00465 return NULL; 00466 00467 // Allocate, initialize and NULL-terminate the array. 00468 CLAN_malloc(identifiers, char**, (nb_identifiers + 1) * sizeof(char *)); 00469 for (i = 0; i <= nb_identifiers; i++) 00470 identifiers[i] = NULL; 00471 00472 // We scan the table a second time to fill the identifier array 00473 // Not optimal to act this way but overkills are worse! 00474 i = 0; 00475 while (symbol != NULL) { 00476 if (symbol->type == type) { 00477 length = strlen(symbol->identifier) + 1; 00478 CLAN_malloc(identifiers[i], char*, length * sizeof(char)); 00479 strcpy(identifiers[i], symbol->identifier); 00480 i++; 00481 } 00482 symbol = symbol->next; 00483 } 00484 00485 // Build the osl_strings_t container. 00486 strings = osl_strings_malloc(); 00487 strings->string = identifiers; 00488 00489 // Embed the strings in a generic shell. 00490 generic = osl_generic_shell(strings, osl_strings_interface()); 00491 return generic; 00492 } 00493 00494 00502 clan_symbol_p clan_symbol_clone_one(clan_symbol_p symbol) { 00503 clan_symbol_p clone = clan_symbol_malloc(); 00504 00505 if (symbol->identifier != NULL) 00506 clone->identifier = strdup(symbol->identifier); 00507 clone->type = symbol->type; 00508 clone->rank = symbol->rank; 00509 00510 return clone; 00511 } 00512 00513 00522 osl_generic_p clan_symbol_to_arrays(clan_symbol_p symbol) { 00523 int i; 00524 int nb_arrays = 0; 00525 osl_arrays_p arrays = NULL; 00526 osl_generic_p generic = NULL; 00527 clan_symbol_p top = symbol; 00528 00529 // A first scan to know how many arrays there are. 00530 while (symbol != NULL) { 00531 nb_arrays++; 00532 symbol = symbol->next; 00533 } 00534 00535 // Build the arrays extension. 00536 if (nb_arrays > 0) { 00537 arrays = osl_arrays_malloc(); 00538 CLAN_malloc(arrays->id, int*, nb_arrays * sizeof(int)); 00539 CLAN_malloc(arrays->names, char**, nb_arrays * sizeof(char *)); 00540 arrays->nb_names = nb_arrays; 00541 symbol = top; 00542 i = 0; 00543 while (symbol != NULL) { 00544 arrays->id[i] = symbol->key; 00545 CLAN_strdup(arrays->names[i], symbol->identifier); 00546 i++; 00547 symbol = symbol->next; 00548 } 00549 00550 // Embed the arrays in a generic shell. 00551 generic = osl_generic_shell(arrays, osl_arrays_interface()); 00552 } 00553 00554 return generic; 00555 } 00556 00557 00570 int clan_symbol_new_iterator(clan_symbol_p* table, clan_symbol_p* array, 00571 char* id, int depth) { 00572 clan_symbol_p symbol; 00573 symbol = clan_symbol_add(table, id, CLAN_TYPE_ITERATOR); 00574 00575 // Ensure that the returned symbol was either a new one, or of the same type. 00576 if (symbol->type != CLAN_TYPE_ITERATOR) { 00577 yyerror("a loop iterator was previously used for something else"); 00578 return 0; 00579 } 00580 00581 // Update the rank, in case the symbol already exists. 00582 if (symbol->rank != depth + 1) 00583 symbol->rank = depth + 1; 00584 00585 array[depth] = clan_symbol_clone_one(symbol); 00586 return 1; 00587 } 00588 00589 00604 int clan_symbol_update_type(clan_symbol_p table, osl_relation_list_p access, 00605 int type) { 00606 int key; 00607 int relation_type; 00608 clan_symbol_p symbol; 00609 00610 if (table == NULL) 00611 CLAN_error("cannot even try to update type: NULL symbol table"); 00612 if (access == NULL) 00613 CLAN_error("cannot even try to update type: NULL access list"); 00614 00615 // We will only consider the last reference in the list. 00616 while (access->next != NULL) 00617 access = access->next; 00618 00619 // Get the key (with some cheating with the relation type to be able to use 00620 // osl_relation_get_array_id), find the corresponding symbol and update. 00621 relation_type = access->elt->type; 00622 access->elt->type = OSL_TYPE_READ; 00623 key = osl_relation_get_array_id(access->elt); 00624 access->elt->type = relation_type; 00625 symbol = clan_symbol_lookup_by_key(table, key); 00626 if (symbol == NULL) 00627 CLAN_error("no symbol corresponding to the key"); 00628 00629 if ((symbol->type == CLAN_TYPE_ITERATOR) && (type != CLAN_TYPE_ITERATOR)) { 00630 yyerror("illegal use of an iterator (update or reference) in a statement"); 00631 return 0; 00632 } 00633 00634 if ((symbol->type == CLAN_TYPE_PARAMETER) && (type != CLAN_TYPE_PARAMETER)) { 00635 yyerror("illegal use of a parameter (update or reference) in a statement"); 00636 return 0; 00637 } 00638 00639 symbol->type = type; 00640 return 1; 00641 }