Clan  0.8.0
symbol.c
Go to the documentation of this file.
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 }