1
2   /**-------------------------------------------------------------------**
3    **                              CLooG                                **
4    **-------------------------------------------------------------------**
5    **                             names.c                               **
6    **-------------------------------------------------------------------**
7    **                  First version: august 1st 2002                   **
8    **-------------------------------------------------------------------**/
9
10
11/******************************************************************************
12 *               CLooG : the Chunky Loop Generator (experimental)             *
13 ******************************************************************************
14 *                                                                            *
15 * Copyright (C) 2002-2005 Cedric Bastoul                                     *
16 *                                                                            *
17 * This library is free software; you can redistribute it and/or              *
18 * modify it under the terms of the GNU Lesser General Public                 *
19 * License as published by the Free Software Foundation; either               *
20 * version 2.1 of the License, or (at your option) any later version.         *
21 *                                                                            *
22 * This library is distributed in the hope that it will be useful,            *
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU          *
25 * Lesser General Public License for more details.                            *
26 *                                                                            *
27 * You should have received a copy of the GNU Lesser General Public           *
28 * License along with this library; if not, write to the Free Software        *
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor,                         *
30 * Boston, MA  02110-1301  USA                                                *
31 *                                                                            *
32 * CLooG, the Chunky Loop Generator                                           *
33 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr                         *
34 *                                                                            *
35 ******************************************************************************/
36/* CAUTION: the english used for comments is probably the worst you ever read,
37 *          please feel free to correct and improve it !
38 */
39
40
41# include <stdlib.h>
42# include <stdio.h>
43# include <ctype.h>
44# include "../include/cloog/cloog.h"
45
46
47/******************************************************************************
48 *                          Structure display function                        *
49 ******************************************************************************/
50
51
52/**
53 * cloog_names_print function:
54 * this function is a human-friendly way to display the CloogNames data
55 * structure, it shows all the different fields and includes an indentation
56 * level (level) in order to work with others print_structure functions.
57 * - July 1st 2005: first version based on the old cloog_names_print function,
58 *                  it was the first modification in this file since two years !
59 */
60void cloog_names_print_structure(FILE * file, CloogNames * names, int level)
61{ int i ;
62
63  /* Go to the right level. */
64  for (i=0; i<level; i++)
65  fprintf(file,"|\t") ;
66
67  if (names != NULL)
68  { fprintf(file,"+-- CloogNames\n") ;
69
70    /* A blank line. */
71    for (i=0; i<=level+1; i++)
72    fprintf(file,"|\t") ;
73    fprintf(file,"\n") ;
74
75    /* Print the scalar dimension number. */
76    for (i=0; i<=level; i++)
77    fprintf(file,"|\t") ;
78    fprintf(file,"Scalar dimension number ---: %d\n",names->nb_scalars) ;
79
80    /* A blank line. */
81    for (i=0; i<=level+1; i++)
82    fprintf(file,"|\t") ;
83    fprintf(file,"\n") ;
84
85    /* Print the scalar iterators. */
86    for (i=0; i<=level; i++)
87    fprintf(file,"|\t") ;
88    if (names->nb_scalars > 0)
89    { fprintf(file,"+-- Scalar iterator strings:") ;
90      for (i=0;i<names->nb_scalars;i++)
91      fprintf(file," %s",names->scalars[i]) ;
92      fprintf(file,"\n") ;
93    }
94    else
95    fprintf(file,"+-- No scalar string\n") ;
96
97    /* A blank line. */
98    for (i=0; i<=level+1; i++)
99    fprintf(file,"|\t") ;
100    fprintf(file,"\n") ;
101
102    /* Print the scattering dimension number. */
103    for (i=0; i<=level; i++)
104    fprintf(file,"|\t") ;
105    fprintf(file,"Scattering dimension number: %d\n",names->nb_scattering) ;
106
107    /* A blank line. */
108    for (i=0; i<=level+1; i++)
109    fprintf(file,"|\t") ;
110    fprintf(file,"\n") ;
111
112    /* Print the scattering iterators. */
113    for (i=0; i<=level; i++)
114    fprintf(file,"|\t") ;
115    if (names->nb_scattering > 0)
116    { fprintf(file,"+-- Scattering strings ----:") ;
117      for (i=0;i<names->nb_scattering;i++)
118      fprintf(file," %s",names->scattering[i]) ;
119      fprintf(file,"\n") ;
120    }
121    else
122    fprintf(file,"+-- No scattering string\n") ;
123
124    /* A blank line. */
125    for (i=0; i<=level+1; i++)
126    fprintf(file,"|\t") ;
127    fprintf(file,"\n") ;
128
129    /* Print the iterator number. */
130    for (i=0; i<=level; i++)
131    fprintf(file,"|\t") ;
132    fprintf(file,"Iterator number -----------: %d\n",names->nb_iterators) ;
133
134    /* A blank line. */
135    for (i=0; i<=level+1; i++)
136    fprintf(file,"|\t") ;
137    fprintf(file,"\n") ;
138
139    /* Print the iterators. */
140    for (i=0; i<=level; i++)
141    fprintf(file,"|\t") ;
142    if (names->nb_iterators > 0)
143    { fprintf(file,"+-- Iterator strings ------:") ;
144      for (i=0;i<names->nb_iterators;i++)
145      fprintf(file," %s",names->iterators[i]) ;
146      fprintf(file,"\n") ;
147    }
148    else
149    fprintf(file,"+-- No iterators\n") ;
150
151    /* A blank line. */
152    for (i=0; i<=level+1; i++)
153    fprintf(file,"|\t") ;
154    fprintf(file,"\n") ;
155
156    /* Print the parameter number. */
157    for (i=0; i<=level; i++)
158    fprintf(file,"|\t") ;
159    fprintf(file,"Parameter number ----------: %d\n",names->nb_parameters) ;
160
161    /* A blank line. */
162    for (i=0; i<=level+1; i++)
163    fprintf(file,"|\t") ;
164    fprintf(file,"\n") ;
165
166    /* Print the parameters. */
167    for (i=0; i<=level; i++)
168    fprintf(file,"|\t") ;
169    if (names->nb_parameters > 0)
170    { fprintf(file,"+-- Parameter strings -----:") ;
171      for (i=0;i<names->nb_parameters;i++)
172      fprintf(file," %s",names->parameters[i]) ;
173      fprintf(file,"\n") ;
174    }
175    else
176    fprintf(file,"No parameters\n") ;
177
178  }
179  else
180  fprintf(file,"+-- No CloogNames\n") ;
181  fprintf(file, "Number of active references: %d\n", names->references);
182}
183
184
185/**
186 * cloog_names_print function:
187 * This function prints the content of a CloogNames structure (names) into a
188 * file (file, possibly stdout).
189 * - July 1st 2005: Now this function is only a frontend to
190 *                  cloog_program_print_structure, with a quite better
191 *                  human-readable representation.
192 */
193void cloog_names_print(FILE * file, CloogNames * names)
194{ cloog_names_print_structure(file,names,0) ;
195}
196
197
198/******************************************************************************
199 *                         Memory deallocation function                       *
200 ******************************************************************************/
201
202
203/**
204 * cloog_names_free function:
205 * This function decrements the number of active references to
206 * a CloogNames structure and frees the allocated memory for this structure
207 * if the count drops to zero.
208 */
209void cloog_names_free(CloogNames * names)
210{ int i ;
211
212  if (--names->references)
213    return;
214
215  if (names->scalars != NULL)
216  { for (i=0;i<names->nb_scalars;i++)
217    free(names->scalars[i]) ;
218    free(names->scalars) ;
219  }
220
221  if (names->scattering != NULL)
222  { for (i=0;i<names->nb_scattering;i++)
223    free(names->scattering[i]) ;
224    free(names->scattering) ;
225  }
226
227  if (names->iterators != NULL)
228  { for (i=0;i<names->nb_iterators;i++)
229    free(names->iterators[i]) ;
230    free(names->iterators) ;
231  }
232
233  if (names->parameters != NULL)
234  { for (i=0;i<names->nb_parameters;i++)
235    free(names->parameters[i]) ;
236    free(names->parameters) ;
237  }
238  free(names) ;
239}
240
241
242/**
243 * cloog_names_copy function:
244 * As usual in CLooG, "copy" means incrementing the reference count.
245 */
246CloogNames *cloog_names_copy(CloogNames *names)
247{
248  names->references++;
249  return names;
250}
251
252
253/******************************************************************************
254 *                              Reading functions                             *
255 ******************************************************************************/
256
257
258/**
259 * cloog_names_read_strings function:
260 * This function reads names data from a file (file, possibly stdin). It first
261 * reads the naming option to know if whether it can read the names from the
262 * file.  If not, NULL is returned.  Otherwise, the names are stored
263 * into an array of strings, and a pointer to this array is returned.
264 * - nb_items is the number of names the function will have to read if the
265 *   naming option is set to read.
266 */
267char ** cloog_names_read_strings(FILE *file, int nb_items)
268{ int i, option, n ;
269  char s[MAX_STRING], str[MAX_STRING], * c, **names = NULL;
270
271  /* We first read name option. */
272  while (fgets(s,MAX_STRING,file) == 0) ;
273  while ((*s=='#' || *s=='\n') || (sscanf(s," %d",&option)<1))
274  fgets(s,MAX_STRING,file) ;
275
276  /* If there is no item to read, then return NULL. */
277  if (nb_items == 0)
278  return NULL ;
279
280  /* If option is to read them in the file, then we do it and put them into
281   * the array.
282   */
283  if (option)
284  { /* Memory allocation. */
285    names = (char **)malloc(nb_items*sizeof(char *)) ;
286    if (names == NULL)
287      cloog_die("memory overflow.\n");
288    for (i=0;i<nb_items;i++)
289    { names[i] = (char *)malloc(MAX_NAME*sizeof(char)) ;
290      if (names[i] == NULL)
291	cloog_die("memory overflow.\n");
292    }
293
294    do  /* Skip the comments, spaces and empty lines... */
295    { c = fgets(s,MAX_STRING,file) ;
296      while ((c != NULL) && isspace(*c) && (*c != '\n'))
297      c++ ;
298    }
299    while (c != NULL && (*c == '#' || *c == '\n'));
300
301    if (c == NULL)
302      cloog_die("no names in input file.\n");
303    for (i=0;i<nb_items;i++)
304    { /* All names must be on the same line. */
305      while (isspace(*c))
306      c++ ;
307      if (!*c || *c == '#' || *c == '\n')
308        cloog_die("not enough names in input file.\n");
309      /* n is strlen(str). */
310      if (sscanf(c,"%s%n",str,&n) == 0)
311        cloog_die("no names in input file.\n");
312      sscanf(str,"%s",names[i]) ;
313      c += n ;
314    }
315  }
316
317  return names ;
318}
319
320
321/******************************************************************************
322 *                            Processing functions                            *
323 ******************************************************************************/
324
325
326/**
327 * cloog_names_malloc function:
328 * This function allocates the memory space for a CloogNames structure and
329 * sets its fields with default values. Then it returns a pointer to the
330 * allocated space.
331 * - November 21th 2005: first version.
332 */
333CloogNames * cloog_names_malloc()
334{ CloogNames * names ;
335
336  /* Memory allocation for the CloogNames structure. */
337  names = (CloogNames *)malloc(sizeof(CloogNames)) ;
338  if (names == NULL)
339    cloog_die("memory overflow.\n");
340
341  /* We set the various fields with default values. */
342  names->nb_scalars    = 0 ;
343  names->nb_scattering = 0 ;
344  names->nb_iterators  = 0 ;
345  names->nb_parameters = 0 ;
346  names->scalars       = NULL ;
347  names->scattering    = NULL ;
348  names->iterators     = NULL ;
349  names->parameters    = NULL ;
350  names->references    = 1;
351
352  return names ;
353}
354
355
356/**
357 * cloog_names_alloc function:
358 * This function allocates the memory space for a CloogNames structure and
359 * sets its fields with those given as input. Then it returns a pointer to the
360 * allocated space.
361 * - July       7th 2005: first version.
362 * - September 11th 2005: addition of both scalar and scattering informations.
363 * - November  21th 2005: use of cloog_names_malloc.
364 */
365CloogNames * cloog_names_alloc()
366{ CloogNames * names ;
367
368  /* Memory allocation for the CloogNames structure. */
369  names = cloog_names_malloc() ;
370
371  names->nb_scalars    = 0;
372  names->nb_scattering = 0;
373  names->nb_iterators  = 0;
374  names->nb_parameters = 0;
375  names->scalars       = NULL;
376  names->scattering    = NULL;
377  names->iterators     = NULL;
378  names->parameters    = NULL;
379
380  return names ;
381}
382
383
384/**
385 * cloog_names_generate_items function:
386 * This function returns a pointer to an array of strings with entries set
387 * based on the function's parameters.
388 * - nb_items will be the number of entries in the string array.
389 * - prefix is the name prefix of each item or NULL.
390 *   If not NULL, then the remainder of the name will be an integer
391 *   in the range [0, nb_items-1].
392 * - first_item is the name of the first item (if prefix == NULL),
393 *   the nb_items-1 following items will be the nb_items-1
394 *   following letters in ASCII code.
395 **
396 * - September 9th 2002 : first version, extracted from cloog_names_generate.
397 */
398char ** cloog_names_generate_items(int nb_items, char * prefix, char first_item)
399{ int i ;
400  char ** names ;
401
402  if (nb_items == 0)
403  return NULL ;
404
405  names = (char **)malloc(nb_items*sizeof(char *)) ;
406  if (names == NULL)
407    cloog_die("memory overflow.\n");
408  for (i=0;i<nb_items;i++)
409  { names[i] = (char *)malloc(MAX_NAME*sizeof(char)) ;
410    if (names[i] == NULL)
411      cloog_die("memory overflow.\n");
412    if (prefix == NULL)
413    sprintf(names[i],"%c",first_item+i) ;
414    else
415      sprintf(names[i], "%s%d", prefix, 1+i);
416  }
417
418  return names ;
419}
420
421
422/**
423 * cloog_names_generate function:
424 * This function returns a pointer to a CloogNames structure with fields set
425 * thanks to the function's parameters.
426 * - nb_scalars will be the number of scalar dimensions in the structure.
427 * - nb_scattering will be the number of scattering dimensions in the structure.
428 * - nb_iterators will be the number of iterators in the CloogNames structure.
429 * - nb_parameters will be the number of parameters in the CloogNames structure.
430 * - first_s is the name of the first scalar iterator, the nb_scalars-1
431 *   following iterators will be the nb_scalars-1 following letters in ASCII.
432 * - first_t is the name of the first scattering iterator, the nb_scattering-1
433 *   following iterators will be the nb_scattering-1 following letters in ASCII.
434 * - first_i is the name of the first iterator, the nb_iterators-1 following
435 *   iterators will be the nb_iterators-1 following letters in ASCII code.
436 * - first_i is the name of the first iterator, the nb_iterators-1 following
437 *   iterators will be the nb_iterators-1 following letters in ASCII code.
438 * - first_p is the name of the first parameter, the nb_parameters-1 following
439 *   parameters will be the nb_parameters-1 following letters in ASCII code.
440 **
441 * - July       1st 2002 : first version.
442 * - September  9th 2002 : use of cloog_names_generate_items.
443 * - September 11th 2005 : addition of both scalar and scattering informations.
444 */
445CloogNames * cloog_names_generate(
446     int nb_scalars, int nb_scattering, int nb_iterators, int nb_parameters,
447     char first_s,   char first_t,      char first_i,     char first_p)
448{ CloogNames * names ;
449
450  names = (CloogNames *)malloc(sizeof(CloogNames)) ;
451  if (names == NULL)
452    cloog_die("memory overflow.\n");
453
454  names->nb_scalars    = nb_scalars ;
455  names->nb_scattering = nb_scattering ;
456  names->nb_parameters = nb_parameters ;
457  names->nb_iterators  = nb_iterators ;
458  names->scalars       = cloog_names_generate_items(nb_scalars,   NULL,first_s);
459  names->scattering    = cloog_names_generate_items(nb_scattering,NULL,first_t);
460  names->parameters    = cloog_names_generate_items(nb_parameters,NULL,first_p);
461  names->iterators     = cloog_names_generate_items(nb_iterators, NULL,first_i);
462
463  return names ;
464}
465
466
467/* Lastly we update the CLoogNames structure: the iterators corresponding to
468 * scalar dimensions have to be removed since these dimensions have been
469 * erased and do not need to be print. We copy all the iterator names except
470 * the scalar ones in a new string array.
471 * - September 12th 2005: first version.
472 */
473void cloog_names_scalarize(CloogNames * names, int nb_scattdims, int * scaldims)
474{ int  nb_scalars, nb_scattering, i, current_scalar, current_scattering ;
475  char ** scalars, ** scattering ;
476
477  if (!nb_scattdims || (scaldims == NULL))
478  return ;
479
480  nb_scalars = 0 ;
481  for (i=0;i<nb_scattdims;i++)
482  if (scaldims[i])
483  nb_scalars  ++ ;
484
485  if (!nb_scalars)
486  return ;
487
488  nb_scattering = names->nb_scattering - nb_scalars ;
489  scattering = (char **)malloc(nb_scattering * sizeof(char *)) ;
490  if (scattering == NULL)
491    cloog_die("memory overflow.\n");
492  scalars = (char **)malloc(nb_scalars * sizeof(char *)) ;
493  if (scalars == NULL)
494    cloog_die("memory overflow.\n");
495
496  current_scalar = 0 ;
497  current_scattering  = 0 ;
498  for (i=0;i<nb_scattdims;i++)
499  { if (!scaldims[i])
500    { scattering[current_scattering] = names->scattering[i] ;
501      current_scattering ++ ;
502    }
503    else
504    { scalars[current_scalar] = names->scattering[i] ;
505      current_scalar ++ ;
506    }
507  }
508
509  free(names->scattering) ;
510  names->scattering    = scattering ;
511  names->scalars       = scalars ;
512  names->nb_scattering = nb_scattering ;
513  names->nb_scalars    = nb_scalars ;
514}
515
516/**
517 * Return the name at a given level (starting at one).
518 * May be a scattering dimension or an iterator of the original domain.
519 */
520const char *cloog_names_name_at_level(CloogNames *names, int level)
521{
522  if (level <= names->nb_scattering)
523    return names->scattering[level - 1];
524  else
525    return names->iterators[level - names->nb_scattering - 1];
526}
527