1
2    /*+-----------------------------------------------------------------**
3     **                       OpenScop Library                          **
4     **-----------------------------------------------------------------**
5     **                            body.c                               **
6     **-----------------------------------------------------------------**
7     **                   First version: 25/06/2011                     **
8     **-----------------------------------------------------------------**
9
10
11 *****************************************************************************
12 * OpenScop: Structures and formats for polyhedral tools to talk together    *
13 *****************************************************************************
14 *    ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__,                *
15 *    /   / /  //  //  //  // /   / /  //  //   / /  // /  /|,_,             *
16 *   /   / /  //  //  //  // /   / /  //  //   / /  // /  / / /\             *
17 *  |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/  \            *
18 *  | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\  \ /\           *
19 *  | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\          *
20 *  | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \  \         *
21 *  | P |n| l | = | s | t |=| = |d| = | = | = | |   |=| o | | \# \  \        *
22 *  | H | | y |   | e | o | | = |l|   |   | = | |   | | G | |  \  \  \       *
23 *  | I | |   |   | e |   | |   | |   |   |   | |   | |   | |   \  \  \      *
24 *  | T | |   |   |   |   | |   | |   |   |   | |   | |   | |    \  \  \     *
25 *  | E | |   |   |   |   | |   | |   |   |   | |   | |   | |     \  \  \    *
26 *  | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | /      \* \  \   *
27 *  | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/        \  \ /   *
28 *  '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---'          '--'    *
29 *                                                                           *
30 * Copyright (C) 2008 University Paris-Sud 11 and INRIA                      *
31 *                                                                           *
32 * (3-clause BSD license)                                                    *
33 * Redistribution and use in source  and binary forms, with or without       *
34 * modification, are permitted provided that the following conditions        *
35 * are met:                                                                  *
36 *                                                                           *
37 * 1. Redistributions of source code must retain the above copyright notice, *
38 *    this list of conditions and the following disclaimer.                  *
39 * 2. Redistributions in binary form must reproduce the above copyright      *
40 *    notice, this list of conditions and the following disclaimer in the    *
41 *    documentation and/or other materials provided with the distribution.   *
42 * 3. The name of the author may not be used to endorse or promote products  *
43 *    derived from this software without specific prior written permission.  *
44 *                                                                           *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      *
46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   *
48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          *
49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  *
50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     *
52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       *
53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  *
54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         *
55 *                                                                           *
56 * OpenScop Library, a library to manipulate OpenScop formats and data       *
57 * structures. Written by:                                                   *
58 * Cedric Bastoul     <Cedric.Bastoul@u-psud.fr> and                         *
59 * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr>                          *
60 *                                                                           *
61 *****************************************************************************/
62
63
64# include <stdlib.h>
65# include <stdio.h>
66# include <string.h>
67# include <ctype.h>
68# include <osl/macros.h>
69# include <osl/util.h>
70# include <osl/strings.h>
71# include <osl/interface.h>
72# include <osl/body.h>
73
74
75/*+***************************************************************************
76 *                         Structure display functions                       *
77 *****************************************************************************/
78
79
80/**
81 * osl_body_idump function:
82 * this function displays an osl_body_t structure (*body) into a
83 * file (file, possibly stdout) in a way that trends to be understandable.
84 * It includes an indentation level (level) in order to work with others
85 * dumping functions.
86 * \param[in] file  File where informations are printed.
87 * \param[in] body  The body whose information has to be printed.
88 * \param[in] level Number of spaces before printing, for each line.
89 */
90void osl_body_idump(FILE * file, osl_body_p body, int level) {
91  int j;
92
93  // Go to the right level.
94  for (j = 0; j < level; j++)
95    fprintf(file, "|\t");
96
97  if (body != NULL) {
98    fprintf(file, "+-- osl_body_t\n");
99
100    // A blank line.
101    for (j = 0; j <= level+1; j++)
102      fprintf(file, "|\t");
103    fprintf(file, "\n");
104
105    // Print the iterators
106    osl_strings_idump(file, body->iterators, level + 1);
107
108    // Print the original body expression.
109    osl_strings_idump(file, body->expression, level + 1);
110  }
111  else {
112    fprintf(file, "+-- NULL body\n");
113  }
114
115  // The last line.
116  for (j = 0; j <= level; j++)
117    fprintf(file, "|\t");
118  fprintf(file, "\n");
119}
120
121
122/**
123 * osl_body_dump function:
124 * this function prints the content of an osl_body_t structure
125 * (*body) into  a file (file, possibly stdout).
126 * \param[in] file File where informations are printed.
127 * \param[in] body The body whose information has to be printed.
128 */
129void osl_body_dump(FILE * file, osl_body_p body) {
130  osl_body_idump(file, body, 0);
131}
132
133
134/**
135 * osl_body_print function:
136 * this function prints the content of an osl_body_t structure
137 * (*body) into a file (file, possibly stdout) in the OpenScop format.
138 * \param[in] file  File where informations are printed.
139 * \param[in] body  The body whose information has to be printed.
140 */
141void osl_body_print(FILE * file, osl_body_p body) {
142  int nb_iterators;
143
144  if (body != NULL) {
145    nb_iterators = osl_strings_size(body->iterators);
146    fprintf(file, "# Number of original iterators\n");
147    fprintf(file, "%d\n", nb_iterators);
148
149    if (nb_iterators > 0) {
150      fprintf(file, "\n# List of original iterators\n");
151      osl_strings_print(file, body->iterators);
152    }
153
154    fprintf(file, "\n# Statement body expression\n");
155    osl_strings_print(file, body->expression);
156  }
157  else {
158    fprintf(file, "# NULL statement body\n");
159  }
160}
161
162
163/**
164 * osl_body_sprint function:
165 * this function prints the content of an osl_body_t structure
166 * (*body) into a string (returned) in the OpenScop textual format.
167 * \param[in] body The body structure which has to be printed.
168 * \return A string containing the OpenScop dump of the body structure.
169 */
170char * osl_body_sprint(osl_body_p body) {
171  int nb_iterators;
172  int high_water_mark = OSL_MAX_STRING;
173  char * string = NULL;
174  char buffer[OSL_MAX_STRING];
175  char * iterators, * expression;
176
177  OSL_malloc(string, char *, high_water_mark * sizeof(char));
178  string[0] = '\0';
179
180  if (body != NULL) {
181    nb_iterators = osl_strings_size(body->iterators);
182    sprintf(buffer, "# Number of original iterators\n%d\n", nb_iterators);
183    osl_util_safe_strcat(&string, buffer, &high_water_mark);
184
185    if (nb_iterators > 0) {
186      sprintf(buffer, "# List of original iterators\n");
187      osl_util_safe_strcat(&string, buffer, &high_water_mark);
188      iterators = osl_strings_sprint(body->iterators);
189      osl_util_safe_strcat(&string, iterators, &high_water_mark);
190      free(iterators);
191    }
192
193    sprintf(buffer, "# Statement body expression\n");
194    osl_util_safe_strcat(&string, buffer, &high_water_mark);
195    expression = osl_strings_sprint(body->expression);
196    osl_util_safe_strcat(&string, expression, &high_water_mark);
197    free(expression);
198  }
199  else {
200    sprintf(buffer, "# NULL body\n");
201    osl_util_safe_strcat(&string, buffer, &high_water_mark);
202  }
203
204  return string;
205}
206
207
208
209/*****************************************************************************
210 *                               Reading function                            *
211 *****************************************************************************/
212
213
214/**
215 * osl_body_read function:
216 * this function reads a body structure from a string complying to the
217 * OpenScop textual format and returns a pointer to this body structure.
218 * The input string should only contain the body this function
219 * has to read (comments at the end of the line are accepted). The input
220 * parameter is updated to the position in the input string this function
221 * reach right after reading the strings structure.
222 * \param[in,out] input The input string where to find a body structure.
223 *                      Updated to the position after what has been read.
224 * \return A pointer to the body structure that has been read.
225 */
226osl_body_p osl_body_sread(char ** input) {
227  osl_body_p body = NULL;
228  char * expression;
229  int nb_iterators;
230
231  if (input) {
232    body = osl_body_malloc();
233
234    // Read the number of iterators.
235    nb_iterators = osl_util_read_int(NULL, input);
236
237    // Read the iterator strings if any.
238    if (nb_iterators > 0) {
239      body->iterators = osl_strings_sread(input);
240    }
241    else {
242      body->iterators = osl_strings_malloc();
243      OSL_malloc(body->iterators->string, char **, sizeof(char *));
244      body->iterators->string[0] = NULL;
245    }
246
247    // Read the body:
248    expression = osl_util_read_line(NULL, input);
249
250    // Insert the body.
251    body->expression = osl_strings_encapsulate(expression);
252  }
253
254  return body;
255}
256
257
258/*+***************************************************************************
259 *                   Memory allocation/deallocation functions                *
260 *****************************************************************************/
261
262
263/**
264 * osl_body_malloc function:
265 * this function allocates the memory space for an osl_body_t
266 * structure and sets its fields with default values. Then it returns a pointer
267 * to the allocated space.
268 * \return A pointer to an empty body with fields set to default values.
269 */
270osl_body_p osl_body_malloc() {
271  osl_body_p body;
272
273  OSL_malloc(body, osl_body_p, sizeof(osl_body_t));
274  body->iterators    = NULL;
275  body->expression   = NULL;
276
277  return body;
278}
279
280
281/**
282 * osl_body_free function:
283 * this function frees the allocated memory for an osl_body_t
284 * structure.
285 * \param[in,out] body The pointer to the body we want to free.
286 */
287void osl_body_free(osl_body_p body) {
288
289  if (body != NULL) {
290    osl_strings_free(body->iterators);
291    osl_strings_free(body->expression);
292    free(body);
293  }
294}
295
296
297/*+***************************************************************************
298 *                            Processing functions                           *
299 *****************************************************************************/
300
301
302/**
303 * osl_body_clone function:
304 * this functions builds and returns a "hard copy" (not a pointer copy) of an
305 * osl_body_t data structure provided as parameter. However, let us
306 * recall here that non-string elements are untouched by the OpenScop Library.
307 * \param[in] body The pointer to the body we want to copy.
308 * \return A pointer to the full copy of the body provided as parameter.
309 */
310osl_body_p osl_body_clone(osl_body_p body) {
311  osl_body_p copy = NULL;
312
313  if (body != NULL) {
314    copy = osl_body_malloc();
315    copy->iterators  = osl_strings_clone(body->iterators);
316    copy->expression = osl_strings_clone(body->expression);
317  }
318
319  return copy;
320}
321
322
323/**
324 * osl_body_equal function:
325 * this function returns true if the two bodies are the same, false
326 * otherwise (the usr field is not tested). However, let us
327 * recall here that non-string elements are untouched by the OpenScop Library.
328 * \param[in] b1 The first body.
329 * \param[in] b2 The second body.
330 * \return 1 if b1 and b2 are the same (content-wise), 0 otherwise.
331 */
332int osl_body_equal(osl_body_p b1, osl_body_p b2) {
333
334  if (b1 == b2)
335    return 1;
336
337  if (((b1 != NULL) && (b2 == NULL)) ||
338      ((b1 == NULL) && (b2 != NULL))) {
339    OSL_info("bodies are not the same");
340    return 0;
341  }
342
343  if (!osl_strings_equal(b1->iterators, b2->iterators)) {
344    OSL_info("body iterators are not the same");
345    return 0;
346  }
347
348  if (!osl_strings_equal(b1->expression, b2->expression)) {
349    OSL_info("body expressions are not the same");
350    return 0;
351  }
352
353  return 1;
354}
355
356
357/**
358 * osl_body_interface function:
359 * this function creates an interface structure corresponding to the body
360 * structure and returns it).
361 * \return An interface structure for the body structure.
362 */
363osl_interface_p osl_body_interface() {
364  osl_interface_p interface = osl_interface_malloc();
365
366  interface->URI    = strdup(OSL_URI_BODY);
367  interface->idump  = (osl_idump_f)osl_body_idump;
368  interface->sprint = (osl_sprint_f)osl_body_sprint;
369  interface->sread  = (osl_sread_f)osl_body_sread;
370  interface->malloc = (osl_malloc_f)osl_body_malloc;
371  interface->free   = (osl_free_f)osl_body_free;
372  interface->clone  = (osl_clone_f)osl_body_clone;
373  interface->equal  = (osl_equal_f)osl_body_equal;
374
375  return interface;
376}
377
378