OpenScop  0.9.0
statement.c
Go to the documentation of this file.
00001 
00002     /*+-----------------------------------------------------------------**
00003      **                       OpenScop Library                          **
00004      **-----------------------------------------------------------------**
00005      **                          statement.c                            **
00006      **-----------------------------------------------------------------**
00007      **                   First version: 30/04/2008                     **
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 
00064 #include <stdlib.h>
00065 #include <stdio.h>
00066 #include <string.h>
00067 #include <ctype.h>
00068 
00069 #include <osl/macros.h>
00070 #include <osl/util.h>
00071 #include <osl/strings.h>
00072 #include <osl/body.h>
00073 #include <osl/relation.h>
00074 #include <osl/relation_list.h>
00075 #include <osl/names.h>
00076 #include <osl/interface.h>
00077 #include <osl/generic.h>
00078 #include <osl/statement.h>
00079 
00080 
00081 /*+***************************************************************************
00082  *                         Structure display functions                       *
00083  *****************************************************************************/
00084 
00085 
00096 void osl_statement_idump(FILE * file, osl_statement_p statement, int level) {
00097   int j, first = 1, number = 1;
00098 
00099   // Go to the right level.
00100   for (j = 0; j < level; j++)
00101     fprintf(file, "|\t");
00102 
00103   if (statement != NULL)
00104     fprintf(file, "+-- osl_statement_t (S%d)\n", number);
00105   else
00106     fprintf(file, "+-- NULL statement\n");
00107 
00108   while (statement != NULL) {
00109     if (!first) {
00110       // Go to the right level.
00111       for (j = 0; j < level; j++)
00112         fprintf(file, "|\t");
00113       fprintf(file, "|   osl_statement_t (S%d)\n", number);
00114     }
00115     else
00116       first = 0;
00117 
00118     // A blank line.
00119     for (j = 0; j <= level + 1; j++)
00120       fprintf(file, "|\t");
00121     fprintf(file, "\n");
00122 
00123     // Print the domain of the statement.
00124     osl_relation_idump(file, statement->domain, level + 1);
00125 
00126     // Print the scattering of the statement.
00127     osl_relation_idump(file, statement->scattering, level + 1);
00128 
00129     // Print the array access information of the statement.
00130     osl_relation_list_idump(file, statement->access, level + 1);
00131 
00132     // Print the original body expression.
00133     osl_generic_idump(file, statement->extension, level + 1);
00134 
00135     statement = statement->next;
00136     number++;
00137 
00138     // Next line.
00139     if (statement != NULL) {
00140       for (j = 0; j <= level; j++)
00141         fprintf(file, "|\t");
00142       fprintf(file, "V\n");
00143     }
00144   }
00145 
00146   // The last line.
00147   for (j = 0; j <= level; j++)
00148     fprintf(file, "|\t");
00149   fprintf(file, "\n");
00150 }
00151 
00152 
00160 void osl_statement_dump(FILE * file, osl_statement_p statement) {
00161   osl_statement_idump(file, statement, 0);
00162 }
00163 
00164 
00172 static
00173 osl_names_p osl_statement_names(osl_statement_p statement) {
00174   int nb_parameters = OSL_UNDEFINED;
00175   int nb_iterators  = OSL_UNDEFINED;
00176   int nb_scattdims  = OSL_UNDEFINED;
00177   int nb_localdims  = OSL_UNDEFINED;
00178   int array_id      = OSL_UNDEFINED;
00179 
00180   osl_statement_get_attributes(statement, &nb_parameters, &nb_iterators,
00181                                &nb_scattdims,  &nb_localdims, &array_id);
00182   
00183   return osl_names_generate("P", nb_parameters,
00184                             "i", nb_iterators,
00185                             "c", nb_scattdims,
00186                             "l", nb_localdims,
00187                             "A", array_id);
00188 }
00189 
00190 
00199 void osl_statement_pprint(FILE * file, osl_statement_p statement,
00200                           osl_names_p names) {
00201   size_t nb_relations;
00202   int number = 1;
00203   int generated_names = 0;
00204   int iterators_backedup = 0;
00205   int nb_ext = 0;
00206   osl_body_p body = NULL;
00207   osl_strings_p iterators_backup = NULL;
00208 
00209   // Generate the dimension names if necessary and replace iterators with
00210   // statement iterators if possible.
00211   if (names == NULL) {
00212     generated_names = 1;
00213     names = osl_statement_names(statement);
00214   }
00215 
00216   while (statement != NULL) {
00217     // If possible, replace iterator names with statement iterator names.
00218     body = (osl_body_p)osl_generic_lookup(statement->extension, OSL_URI_BODY);
00219     if (body && body->iterators != NULL) {
00220       iterators_backedup = 1;
00221       iterators_backup = names->iterators;
00222       names->iterators = body->iterators;
00223     }
00224 
00225     nb_relations = 0;
00226 
00227     fprintf(file, "# =============================================== ");
00228     fprintf(file, "Statement %d\n", number);
00229 
00230     fprintf(file, "# Number of relations describing the statement:\n");
00231 
00232     if (statement->domain != NULL)
00233       nb_relations ++;
00234     if (statement->scattering != NULL)
00235       nb_relations ++;
00236     nb_relations += osl_relation_list_count(statement->access); 
00237 
00238     fprintf(file, "%lu\n\n", nb_relations);
00239 
00240     fprintf(file, "# ---------------------------------------------- ");
00241     fprintf(file, "%2d.1 Domain\n", number);
00242     osl_relation_pprint(file, statement->domain, names);
00243     fprintf(file, "\n");
00244 
00245     fprintf(file, "# ---------------------------------------------- ");
00246     fprintf(file, "%2d.2 Scattering\n", number);
00247     osl_relation_pprint(file, statement->scattering, names);
00248     fprintf(file, "\n");
00249 
00250     fprintf(file, "# ---------------------------------------------- ");
00251     fprintf(file, "%2d.3 Access\n", number);
00252     osl_relation_list_pprint_elts(file, statement->access, names);
00253     fprintf(file, "\n");
00254 
00255     fprintf(file, "# ---------------------------------------------- ");
00256     fprintf(file, "%2d.4 Statement Extensions\n", number);
00257     fprintf(file, "# Number of Statement Extensions\n");
00258     nb_ext = osl_generic_number(statement->extension);
00259     fprintf(file, "%d\n", nb_ext);
00260     if(nb_ext>0)
00261       osl_generic_print(file, statement->extension);
00262 
00263     fprintf(file, "\n");
00264 
00265     // If necessary, switch back iterator names.
00266     if (iterators_backedup) {
00267       iterators_backedup = 0;
00268       names->iterators = iterators_backup;
00269     }
00270 
00271     statement = statement->next;
00272     number++;
00273   }
00274 
00275   if (generated_names)
00276     osl_names_free(names);
00277 }
00278 
00279 
00288 void osl_statement_pprint_scoplib(FILE * file, osl_statement_p statement,
00289                           osl_names_p names) {
00290   int number = 1;
00291   int generated_names = 0;
00292   int iterators_backedup = 0;
00293   osl_body_p body = NULL;
00294   osl_strings_p iterators_backup = NULL;
00295   int add_fakeiter;
00296 
00297   // Generate the dimension names if necessary and replace iterators with
00298   // statement iterators if possible.
00299   if (names == NULL) {
00300     generated_names = 1;
00301     names = osl_statement_names(statement);
00302   }
00303 
00304   while (statement != NULL) {
00305     // If possible, replace iterator names with statement iterator names.
00306     body = (osl_body_p)osl_generic_lookup(statement->extension, OSL_URI_BODY);
00307     if (body && body->iterators != NULL) {
00308       iterators_backedup = 1;
00309       iterators_backup = names->iterators;
00310       names->iterators = body->iterators;
00311     }
00312     
00313     add_fakeiter = statement->domain->nb_rows == 0 &&
00314                    statement->scattering->nb_rows == 1;
00315     
00316     fprintf(file, "# =============================================== ");
00317     fprintf(file, "Statement %d\n", number);
00318     
00319     fprintf(file, "# ---------------------------------------------- ");
00320     fprintf(file, "%2d.1 Domain\n", number);
00321     fprintf(file, "# Iteration domain\n");
00322     osl_relation_pprint_scoplib(file, statement->domain, names, 1, add_fakeiter);
00323     fprintf(file, "\n");
00324 
00325     fprintf(file, "# ---------------------------------------------- ");
00326     fprintf(file, "%2d.2 Scattering\n", number);
00327     fprintf(file,"# Scattering function is provided\n1\n");
00328     osl_relation_pprint_scoplib(file, statement->scattering, names, 0,
00329                                 add_fakeiter);
00330     fprintf(file, "\n");
00331 
00332     fprintf(file, "# ---------------------------------------------- ");
00333     fprintf(file, "%2d.3 Access\n", number);
00334     fprintf(file,"# Access informations are provided\n1\n");
00335     
00336     osl_relation_list_pprint_access_array_scoplib(file, statement->access,
00337                                                   names, add_fakeiter);
00338     fprintf(file, "\n");
00339 
00340     fprintf(file, "# ---------------------------------------------- ");
00341     fprintf(file, "%2d.4 Body\n", number);
00342     if (body != NULL) {
00343       fprintf(file, "# Statement body is provided\n1\n");
00344       osl_body_print_scoplib(file, body);
00345       body = NULL; //re-initialize for next statement
00346     }
00347     else {
00348       fprintf(file, "# Statement body is not provided\n0\n");
00349     }
00350 
00351     fprintf(file, "\n");
00352 
00353     // If necessary, switch back iterator names.
00354     if (iterators_backedup) {
00355       iterators_backedup = 0;
00356       names->iterators = iterators_backup;
00357     }
00358 
00359     statement = statement->next;
00360     number++;
00361   }
00362 
00363   if (generated_names)
00364     osl_names_free(names);
00365 }
00366 
00367 
00375 void osl_statement_print(FILE * file, osl_statement_p statement) {
00376 
00377   osl_statement_pprint(file, statement, NULL);
00378 }
00379 
00380 
00381 /*****************************************************************************
00382  *                               Reading function                            *
00383  *****************************************************************************/
00384 
00385 
00395 static
00396 void osl_statement_dispatch(osl_statement_p stmt, osl_relation_list_p list) {
00397   osl_relation_list_p domain_list; 
00398   osl_relation_list_p scattering_list; 
00399   size_t nb_domains, nb_scattering, nb_accesses;
00400 
00401   // Domain.
00402   domain_list = osl_relation_list_filter(list, OSL_TYPE_DOMAIN);
00403   nb_domains = osl_relation_list_count(domain_list); 
00404   if (nb_domains > 1)
00405     OSL_error("more than one domain for a statement");
00406   
00407   if (domain_list != NULL) {
00408     stmt->domain = domain_list->elt;
00409     domain_list->elt = NULL;
00410     osl_relation_list_free(domain_list);
00411   }
00412   else {
00413     stmt->domain = NULL;
00414   }
00415 
00416   // Scattering.
00417   scattering_list=osl_relation_list_filter(list,OSL_TYPE_SCATTERING);
00418   nb_scattering = osl_relation_list_count(scattering_list); 
00419   if (nb_scattering > 1)
00420     OSL_error("more than one scattering relation for a statement");
00421   
00422   if (scattering_list != NULL) {
00423     stmt->scattering = scattering_list->elt;
00424     scattering_list->elt = NULL;
00425     osl_relation_list_free(scattering_list);
00426   }
00427   else {
00428     stmt->scattering = NULL;
00429   }
00430 
00431   // Access.
00432   stmt->access = osl_relation_list_filter(list, OSL_TYPE_ACCESS);
00433   nb_accesses = osl_relation_list_count(stmt->access);
00434 
00435   if ((nb_domains + nb_scattering + nb_accesses) !=
00436       (osl_relation_list_count(list)))
00437     OSL_error("unexpected relation type to define a statement");
00438 
00439   osl_relation_list_free(list);
00440 }
00441 
00442 
00452 osl_statement_p osl_statement_pread(FILE * file, osl_interface_p registry,
00453                                     int precision) {
00454   osl_statement_p stmt = osl_statement_malloc();
00455   osl_relation_list_p list;
00456   osl_generic_p new = NULL;
00457   int i, nb_ext = 0;
00458 
00459   if (file) {
00460     // Read all statement relations.
00461     list = osl_relation_list_pread(file, precision);
00462 
00463     // Store relations at the right place according to their type.
00464     osl_statement_dispatch(stmt, list);
00465 
00466     // Read the Extensions
00467     nb_ext = osl_util_read_int(file, NULL);
00468     for (i=0; i<nb_ext; i++) {
00469       new = osl_generic_read_one(file, registry); 
00470       osl_generic_add(&stmt->extension, new);
00471     }
00472   }
00473 
00474   return stmt;
00475 }
00476 
00477 
00486 osl_statement_p osl_statement_read(FILE * foo) {
00487   int precision = osl_util_get_precision();
00488   osl_interface_p registry = osl_interface_get_default_registry();
00489   osl_statement_p statement = osl_statement_pread(foo, registry, precision);
00490 
00491   osl_interface_free(registry);
00492   return statement;
00493 }
00494 
00495 
00496 /*+***************************************************************************
00497  *                   Memory allocation/deallocation functions                *
00498  *****************************************************************************/
00499 
00500 
00508 osl_statement_p osl_statement_malloc() {
00509   osl_statement_p statement;
00510 
00511   OSL_malloc(statement, osl_statement_p, sizeof(osl_statement_t));
00512   statement->domain     = NULL;
00513   statement->scattering = NULL;
00514   statement->access     = NULL;
00515   statement->extension  = NULL;
00516   statement->next       = NULL;
00517 
00518   return statement;
00519 }
00520 
00521 
00528 void osl_statement_free(osl_statement_p statement) {
00529   osl_statement_p next;
00530 
00531   while (statement != NULL) {
00532     next = statement->next;
00533     osl_relation_free(statement->domain);
00534     osl_relation_free(statement->scattering);
00535     osl_relation_list_free(statement->access);
00536     osl_generic_free(statement->extension);
00537 
00538     free(statement);
00539     statement = next;
00540   }
00541 }
00542 
00543 
00544 /*+***************************************************************************
00545  *                            Processing functions                           *
00546  *****************************************************************************/
00547 
00548 
00556 void osl_statement_add(osl_statement_p * location,
00557                        osl_statement_p   statement) {
00558   while (*location != NULL)
00559     location = &((*location)->next);
00560 
00561   *location = statement;
00562 }
00563 
00564 
00572 int osl_statement_number(osl_statement_p statement) {
00573   int number = 0;
00574 
00575   while (statement != NULL) {
00576     number++;
00577     statement = statement->next;
00578   }
00579   return number;
00580 }
00581 
00582 
00591 osl_statement_p osl_statement_nclone(osl_statement_p statement, int n) {
00592   int first = 1, i = 0;
00593   osl_statement_p clone = NULL, node, previous = NULL;
00594 
00595   while ((statement != NULL) && ((n == -1) || (i < n))) {
00596     node             = osl_statement_malloc();
00597     node->domain     = osl_relation_clone(statement->domain);
00598     node->scattering = osl_relation_clone(statement->scattering);
00599     node->access     = osl_relation_list_clone(statement->access);
00600     node->extension  = osl_generic_clone(statement->extension);
00601     node->next       = NULL;
00602 
00603     if (first) {
00604       first = 0;
00605       clone = node;
00606       previous = node;
00607     }
00608     else {
00609       previous->next = node;
00610       previous = previous->next;
00611     }
00612 
00613     i++;
00614     statement = statement->next;
00615   }
00616 
00617   return clone;
00618 }
00619 
00620 
00628 osl_statement_p osl_statement_clone(osl_statement_p statement) {
00629   return osl_statement_nclone(statement, -1);
00630 }
00631 
00632 
00641 int osl_statement_equal(osl_statement_p s1, osl_statement_p s2) {
00642   
00643   if (s1 == s2)
00644     return 1;
00645   
00646   if (((s1->next != NULL) && (s2->next == NULL)) ||
00647       ((s1->next == NULL) && (s2->next != NULL))) {
00648     OSL_info("statements are not the same"); 
00649     return 0;
00650   }
00651 
00652   if ((s1->next != NULL) && (s2->next != NULL)) {
00653     if (!osl_statement_equal(s1->next, s2->next)) {
00654       OSL_info("number of statements is not the same"); 
00655       return 0;
00656     }
00657   }
00658     
00659   if (!osl_relation_equal(s1->domain, s2->domain)) {
00660     OSL_info("statement domains are not the same"); 
00661     return 0;
00662   }
00663 
00664   if (!osl_relation_equal(s1->scattering, s2->scattering)) {
00665     OSL_info("statement scatterings are not the same"); 
00666     return 0;
00667   }
00668 
00669   if (!osl_relation_list_equal(s1->access, s2->access)) {
00670     OSL_info("statement accesses are not the same"); 
00671     return 0;
00672   }
00673 
00674   if (!osl_generic_equal(s1->extension, s2->extension)) {
00675     OSL_info("statement bodies are not the same"); 
00676     return 0;
00677   }
00678 
00679   return 1;
00680 }
00681 
00682 
00693 int osl_statement_integrity_check(osl_statement_p statement,
00694                                   int expected_nb_parameters) {
00695   int expected_nb_iterators;
00696   osl_body_p body = NULL;
00697 
00698   while (statement != NULL) {
00699     // Check the domain.
00700     if (!osl_relation_integrity_check(statement->domain,
00701                                       OSL_TYPE_DOMAIN,
00702                                       OSL_UNDEFINED,
00703                                       0,
00704                                       expected_nb_parameters)) {
00705       return 0;
00706     }
00707 
00708     // Get the number of iterators.
00709     if (statement->domain != NULL)
00710       expected_nb_iterators = statement->domain->nb_output_dims;
00711     else
00712       expected_nb_iterators = OSL_UNDEFINED;
00713 
00714     // Check the scattering relation.
00715     if (!osl_relation_integrity_check(statement->scattering,
00716                                       OSL_TYPE_SCATTERING,
00717                                       OSL_UNDEFINED,
00718                                       expected_nb_iterators,
00719                                       expected_nb_parameters)) {
00720       return 0;
00721     }
00722 
00723     // Check the access relations.
00724     if (!osl_relation_list_integrity_check(statement->access,
00725                                            OSL_TYPE_ACCESS,
00726                                            OSL_UNDEFINED,
00727                                            expected_nb_iterators,
00728                                            expected_nb_parameters)) {
00729       return 0;
00730     }
00731 
00732     // Check the statement body.
00733     body = (osl_body_p)osl_generic_lookup(statement->extension, OSL_URI_BODY);
00734     if ((expected_nb_iterators != OSL_UNDEFINED) &&
00735         body && body->iterators != NULL &&
00736         ((size_t)expected_nb_iterators != osl_strings_size(body->iterators))) {
00737       OSL_warning("unexpected number of original iterators");
00738       return 0;
00739     }
00740 
00741     statement = statement->next;
00742   }
00743 
00744   return 1;
00745 }
00746 
00747 
00755 int osl_statement_get_nb_iterators(osl_statement_p statement) {
00756 
00757   if (statement->domain == NULL) {
00758     OSL_warning("no statement domain, assuming 0 iterators");
00759     return 0;
00760   }
00761   else {
00762     return statement->domain->nb_output_dims;
00763   }
00764 }
00765 
00766 
00785 void osl_statement_get_attributes(osl_statement_p statement,
00786                                   int * nb_parameters,
00787                                   int * nb_iterators,
00788                                   int * nb_scattdims,
00789                                   int * nb_localdims,
00790                                   int * array_id) {
00791   int local_nb_parameters = OSL_UNDEFINED;
00792   int local_nb_iterators  = OSL_UNDEFINED;
00793   int local_nb_scattdims  = OSL_UNDEFINED;
00794   int local_nb_localdims  = OSL_UNDEFINED;
00795   int local_array_id      = OSL_UNDEFINED;
00796 
00797   while (statement != NULL) {
00798     osl_relation_get_attributes(statement->domain,
00799                                 &local_nb_parameters,
00800                                 &local_nb_iterators,
00801                                 &local_nb_scattdims,
00802                                 &local_nb_localdims,
00803                                 &local_array_id);
00804 
00805     osl_relation_get_attributes(statement->scattering,
00806                                 &local_nb_parameters,
00807                                 &local_nb_iterators,
00808                                 &local_nb_scattdims,
00809                                 &local_nb_localdims,
00810                                 &local_array_id);
00811 
00812     osl_relation_list_get_attributes(statement->access,
00813                                 &local_nb_parameters,
00814                                 &local_nb_iterators,
00815                                 &local_nb_scattdims,
00816                                 &local_nb_localdims,
00817                                 &local_array_id);
00818     // Update.
00819     *nb_parameters = OSL_max(*nb_parameters, local_nb_parameters);
00820     *nb_iterators  = OSL_max(*nb_iterators,  local_nb_iterators);
00821     *nb_scattdims  = OSL_max(*nb_scattdims,  local_nb_scattdims);
00822     *nb_localdims  = OSL_max(*nb_localdims,  local_nb_localdims);
00823     *array_id      = OSL_max(*array_id,      local_array_id);
00824     statement = statement->next;
00825   }
00826 }
00827 
00828 
00835 osl_body_p osl_statement_get_body(osl_statement_p statement) {
00836   osl_body_p body;
00837   osl_extbody_p ebody;
00838 
00839   if (statement == NULL || statement->extension == NULL) {
00840     return NULL;
00841   }
00842 
00843   body = (osl_body_p)osl_generic_lookup(statement->extension, OSL_URI_BODY);
00844   if (body != NULL)
00845     return body;
00846   ebody = (osl_extbody_p)osl_generic_lookup(statement->extension,
00847                                                            OSL_URI_EXTBODY);
00848   if (ebody != NULL)
00849     return ebody->body;
00850   return NULL;
00851 }