Home | History | Annotate | Line # | Download | only in m4
      1      1.1  mrg dnl Support macro file for intrinsic functions.
      2      1.1  mrg dnl Contains the generic sections of the array functions.
      3      1.1  mrg dnl This file is part of the GNU Fortran Runtime Library (libgfortran)
      4      1.1  mrg dnl Distributed under the GNU GPL with exception.  See COPYING for details.
      5      1.1  mrg dnl
      6      1.1  mrg dnl Pass the implementation for a single section as the parameter to
      7      1.1  mrg dnl {MASK_}ARRAY_FUNCTION.
      8      1.1  mrg dnl The variables base, delta, and len describe the input section.
      9      1.1  mrg dnl For masked section the mask is described by mbase and mdelta.
     10      1.1  mrg dnl These should not be modified. The result should be stored in *dest.
     11      1.1  mrg dnl The names count, extent, sstride, dstride, base, dest, rank, dim
     12      1.1  mrg dnl retarray, array, pdim and mstride should not be used.
     13      1.1  mrg dnl The variable n is declared as index_type and may be used.
     14      1.1  mrg dnl Other variable declarations may be placed at the start of the code,
     15      1.1  mrg dnl The types of the array parameter and the return value are
     16      1.1  mrg dnl atype_name and rtype_name respectively.
     17      1.1  mrg dnl Execution should be allowed to continue to the end of the block.
     18      1.1  mrg dnl You should not return or break from the inner loop of the implementation.
     19      1.1  mrg dnl Care should also be taken to avoid using the names defined in iparm.m4
     20      1.1  mrg define(START_ARRAY_FUNCTION,
     21      1.1  mrg `#include <string.h>
     22      1.1  mrg #include <assert.h>
     23      1.1  mrg 
     24      1.1  mrg static inline int
     25      1.1  mrg compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n)
     26      1.1  mrg {
     27      1.1  mrg   if (sizeof ('atype_name`) == 1)
     28      1.1  mrg     return memcmp (a, b, n);
     29      1.1  mrg   else
     30      1.1  mrg     return memcmp_char4 (a, b, n);
     31      1.1  mrg }
     32      1.1  mrg 
     33      1.1  mrg extern void name`'rtype_qual`_'atype_code (rtype * const restrict,
     34      1.1  mrg         gfc_charlen_type, atype * const restrict,
     35      1.1  mrg 	const index_type * const restrict, gfc_charlen_type);
     36      1.1  mrg export_proto(name`'rtype_qual`_'atype_code);
     37      1.1  mrg 
     38      1.1  mrg void
     39      1.1  mrg name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
     40      1.1  mrg 	gfc_charlen_type xlen, atype * const restrict array, 
     41      1.1  mrg 	const index_type * const restrict pdim, gfc_charlen_type string_len)
     42      1.1  mrg {
     43      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
     44      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
     45      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
     46      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
     47      1.1  mrg   const atype_name * restrict base;
     48      1.1  mrg   rtype_name * restrict dest;
     49      1.1  mrg   index_type rank;
     50      1.1  mrg   index_type n;
     51      1.1  mrg   index_type len;
     52      1.1  mrg   index_type delta;
     53      1.1  mrg   index_type dim;
     54      1.1  mrg   int continue_loop;
     55      1.1  mrg 
     56      1.1  mrg   assert (xlen == string_len);
     57      1.1  mrg   /* Make dim zero based to avoid confusion.  */
     58      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
     59      1.1  mrg   dim = (*pdim) - 1;
     60      1.1  mrg 
     61      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
     62      1.1  mrg     {
     63      1.1  mrg       runtime_error ("Dim argument incorrect in u_name intrinsic: "
     64      1.1  mrg  		     "is %ld, should be between 1 and %ld",
     65      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
     66      1.1  mrg     }
     67      1.1  mrg 
     68      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
     69      1.1  mrg   if (len < 0)
     70      1.1  mrg     len = 0;
     71      1.1  mrg 
     72      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
     73      1.1  mrg 
     74      1.1  mrg   for (n = 0; n < dim; n++)
     75      1.1  mrg     {
     76      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
     77      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
     78      1.1  mrg 
     79      1.1  mrg       if (extent[n] < 0)
     80      1.1  mrg 	extent[n] = 0;
     81      1.1  mrg     }
     82      1.1  mrg   for (n = dim; n < rank; n++)
     83      1.1  mrg     {
     84      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
     85      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
     86      1.1  mrg 
     87      1.1  mrg       if (extent[n] < 0)
     88      1.1  mrg 	extent[n] = 0;
     89      1.1  mrg     }
     90      1.1  mrg 
     91      1.1  mrg   if (retarray->base_addr == NULL)
     92      1.1  mrg     {
     93      1.1  mrg       size_t alloc_size, str;
     94      1.1  mrg 
     95      1.1  mrg       for (n = 0; n < rank; n++)
     96      1.1  mrg 	{
     97      1.1  mrg 	  if (n == 0)
     98      1.1  mrg 	    str = 1;
     99      1.1  mrg 	  else
    100      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    101      1.1  mrg 
    102      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    103      1.1  mrg 
    104      1.1  mrg 	}
    105      1.1  mrg 
    106      1.1  mrg       retarray->offset = 0;
    107      1.1  mrg       retarray->dtype.rank = rank;
    108      1.1  mrg 
    109      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
    110      1.1  mrg       		 * string_len;
    111      1.1  mrg 
    112      1.1  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
    113      1.1  mrg       if (alloc_size == 0)
    114  1.1.1.2  mrg 	return;
    115      1.1  mrg     }
    116      1.1  mrg   else
    117      1.1  mrg     {
    118      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    119      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    120      1.1  mrg 		       " u_name intrinsic: is %ld, should be %ld",
    121      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    122      1.1  mrg 		       (long int) rank);
    123      1.1  mrg 
    124      1.1  mrg       if (unlikely (compile_options.bounds_check))
    125      1.1  mrg 	bounds_ifunction_return ((array_t *) retarray, extent,
    126      1.1  mrg 				 "return value", "u_name");
    127      1.1  mrg     }
    128      1.1  mrg 
    129      1.1  mrg   for (n = 0; n < rank; n++)
    130      1.1  mrg     {
    131      1.1  mrg       count[n] = 0;
    132      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
    133      1.1  mrg       if (extent[n] <= 0)
    134      1.1  mrg 	return;
    135      1.1  mrg     }
    136      1.1  mrg 
    137      1.1  mrg   base = array->base_addr;
    138      1.1  mrg   dest = retarray->base_addr;
    139      1.1  mrg 
    140      1.1  mrg   continue_loop = 1;
    141      1.1  mrg   while (continue_loop)
    142      1.1  mrg     {
    143      1.1  mrg       const atype_name * restrict src;
    144      1.1  mrg       src = base;
    145      1.1  mrg       {
    146      1.1  mrg ')dnl
    147      1.1  mrg define(START_ARRAY_BLOCK,
    148      1.1  mrg `	if (len <= 0)
    149      1.1  mrg 	  memset (dest, '$1`, sizeof (*dest) * string_len);
    150      1.1  mrg 	else
    151      1.1  mrg 	  {
    152      1.1  mrg 	    for (n = 0; n < len; n++, src += delta)
    153      1.1  mrg 	      {
    154      1.1  mrg ')dnl
    155      1.1  mrg define(FINISH_ARRAY_FUNCTION,
    156      1.1  mrg `	      }
    157      1.1  mrg 	    '$1`
    158      1.1  mrg 	    memcpy (dest, retval, sizeof (*dest) * string_len);
    159      1.1  mrg 	  }
    160      1.1  mrg       }
    161      1.1  mrg       /* Advance to the next element.  */
    162      1.1  mrg       count[0]++;
    163      1.1  mrg       base += sstride[0];
    164      1.1  mrg       dest += dstride[0];
    165      1.1  mrg       n = 0;
    166      1.1  mrg       while (count[n] == extent[n])
    167      1.1  mrg 	{
    168      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    169      1.1  mrg 	     the next dimension.  */
    170      1.1  mrg 	  count[n] = 0;
    171      1.1  mrg 	  /* We could precalculate these products, but this is a less
    172      1.1  mrg 	     frequently used path so probably not worth it.  */
    173      1.1  mrg 	  base -= sstride[n] * extent[n];
    174      1.1  mrg 	  dest -= dstride[n] * extent[n];
    175      1.1  mrg 	  n++;
    176      1.1  mrg 	  if (n >= rank)
    177      1.1  mrg 	    {
    178      1.1  mrg 	      /* Break out of the loop.  */
    179      1.1  mrg 	      continue_loop = 0;
    180      1.1  mrg 	      break;
    181      1.1  mrg 	    }
    182      1.1  mrg 	  else
    183      1.1  mrg 	    {
    184      1.1  mrg 	      count[n]++;
    185      1.1  mrg 	      base += sstride[n];
    186      1.1  mrg 	      dest += dstride[n];
    187      1.1  mrg 	    }
    188      1.1  mrg 	}
    189      1.1  mrg     }
    190      1.1  mrg }')dnl
    191      1.1  mrg define(START_MASKED_ARRAY_FUNCTION,
    192      1.1  mrg `
    193      1.1  mrg extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
    194      1.1  mrg         gfc_charlen_type, atype * const restrict,
    195      1.1  mrg 	const index_type * const restrict,
    196      1.1  mrg 	gfc_array_l1 * const restrict, gfc_charlen_type);
    197      1.1  mrg export_proto(`m'name`'rtype_qual`_'atype_code);
    198      1.1  mrg 
    199      1.1  mrg void
    200      1.1  mrg `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
    201      1.1  mrg 	gfc_charlen_type xlen, atype * const restrict array, 
    202      1.1  mrg 	const index_type * const restrict pdim,
    203      1.1  mrg 	gfc_array_l1 * const restrict mask,
    204      1.1  mrg 	gfc_charlen_type string_len)
    205      1.1  mrg 
    206      1.1  mrg {
    207      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    208      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    209      1.1  mrg   index_type sstride[GFC_MAX_DIMENSIONS];
    210      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    211      1.1  mrg   index_type mstride[GFC_MAX_DIMENSIONS];
    212      1.1  mrg   rtype_name * restrict dest;
    213      1.1  mrg   const atype_name * restrict base;
    214      1.1  mrg   const GFC_LOGICAL_1 * restrict mbase;
    215      1.1  mrg   index_type rank;
    216      1.1  mrg   index_type dim;
    217      1.1  mrg   index_type n;
    218      1.1  mrg   index_type len;
    219      1.1  mrg   index_type delta;
    220      1.1  mrg   index_type mdelta;
    221      1.1  mrg   int mask_kind;
    222      1.1  mrg 
    223      1.1  mrg   if (mask == NULL)
    224      1.1  mrg     {
    225      1.1  mrg       name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len);
    226      1.1  mrg       return;
    227      1.1  mrg     }
    228      1.1  mrg 
    229      1.1  mrg   assert (xlen == string_len);
    230      1.1  mrg 
    231      1.1  mrg   dim = (*pdim) - 1;
    232      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    233      1.1  mrg 
    234      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    235      1.1  mrg     {
    236      1.1  mrg       runtime_error ("Dim argument incorrect in u_name intrinsic: "
    237      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    238      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    239      1.1  mrg     }
    240      1.1  mrg 
    241      1.1  mrg   len = GFC_DESCRIPTOR_EXTENT(array,dim);
    242  1.1.1.2  mrg   if (len < 0)
    243  1.1.1.2  mrg     len = 0;
    244      1.1  mrg 
    245      1.1  mrg   mbase = mask->base_addr;
    246      1.1  mrg 
    247      1.1  mrg   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
    248      1.1  mrg 
    249      1.1  mrg   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
    250      1.1  mrg #ifdef HAVE_GFC_LOGICAL_16
    251      1.1  mrg       || mask_kind == 16
    252      1.1  mrg #endif
    253      1.1  mrg       )
    254      1.1  mrg     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
    255      1.1  mrg   else
    256      1.1  mrg     runtime_error ("Funny sized logical array");
    257      1.1  mrg 
    258      1.1  mrg   delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
    259      1.1  mrg   mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
    260      1.1  mrg 
    261      1.1  mrg   for (n = 0; n < dim; n++)
    262      1.1  mrg     {
    263      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
    264      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
    265      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    266      1.1  mrg 
    267      1.1  mrg       if (extent[n] < 0)
    268      1.1  mrg 	extent[n] = 0;
    269      1.1  mrg 
    270      1.1  mrg     }
    271      1.1  mrg   for (n = dim; n < rank; n++)
    272      1.1  mrg     {
    273      1.1  mrg       sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
    274      1.1  mrg       mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
    275      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
    276      1.1  mrg 
    277      1.1  mrg       if (extent[n] < 0)
    278      1.1  mrg 	extent[n] = 0;
    279      1.1  mrg     }
    280      1.1  mrg 
    281      1.1  mrg   if (retarray->base_addr == NULL)
    282      1.1  mrg     {
    283      1.1  mrg       size_t alloc_size, str;
    284      1.1  mrg 
    285      1.1  mrg       for (n = 0; n < rank; n++)
    286      1.1  mrg 	{
    287      1.1  mrg 	  if (n == 0)
    288      1.1  mrg 	    str = 1;
    289      1.1  mrg 	  else
    290      1.1  mrg 	    str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    291      1.1  mrg 
    292      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    293      1.1  mrg 
    294      1.1  mrg 	}
    295      1.1  mrg 
    296      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
    297      1.1  mrg       		 * string_len;
    298      1.1  mrg 
    299      1.1  mrg       retarray->offset = 0;
    300      1.1  mrg       retarray->dtype.rank = rank;
    301      1.1  mrg 
    302  1.1.1.2  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
    303      1.1  mrg       if (alloc_size == 0)
    304  1.1.1.2  mrg 	return;
    305      1.1  mrg     }
    306      1.1  mrg   else
    307      1.1  mrg     {
    308      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    309      1.1  mrg 	runtime_error ("rank of return array incorrect in u_name intrinsic");
    310      1.1  mrg 
    311      1.1  mrg       if (unlikely (compile_options.bounds_check))
    312      1.1  mrg 	{
    313      1.1  mrg 	  bounds_ifunction_return ((array_t *) retarray, extent,
    314      1.1  mrg 				   "return value", "u_name");
    315      1.1  mrg 	  bounds_equal_extents ((array_t *) mask, (array_t *) array,
    316      1.1  mrg 	  			"MASK argument", "u_name");
    317      1.1  mrg 	}
    318      1.1  mrg     }
    319      1.1  mrg 
    320      1.1  mrg   for (n = 0; n < rank; n++)
    321      1.1  mrg     {
    322      1.1  mrg       count[n] = 0;
    323      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
    324      1.1  mrg       if (extent[n] <= 0)
    325      1.1  mrg 	return;
    326      1.1  mrg     }
    327      1.1  mrg 
    328      1.1  mrg   dest = retarray->base_addr;
    329      1.1  mrg   base = array->base_addr;
    330      1.1  mrg 
    331      1.1  mrg   while (base)
    332      1.1  mrg     {
    333      1.1  mrg       const atype_name * restrict src;
    334      1.1  mrg       const GFC_LOGICAL_1 * restrict msrc;
    335      1.1  mrg 
    336      1.1  mrg       src = base;
    337      1.1  mrg       msrc = mbase;
    338      1.1  mrg       {
    339      1.1  mrg ')dnl
    340      1.1  mrg define(START_MASKED_ARRAY_BLOCK,
    341      1.1  mrg `	for (n = 0; n < len; n++, src += delta, msrc += mdelta)
    342      1.1  mrg 	  {
    343      1.1  mrg ')dnl
    344      1.1  mrg define(FINISH_MASKED_ARRAY_FUNCTION,
    345      1.1  mrg `	  }
    346      1.1  mrg 	memcpy (dest, retval, sizeof (*dest) * string_len);
    347      1.1  mrg       }
    348      1.1  mrg       /* Advance to the next element.  */
    349      1.1  mrg       count[0]++;
    350      1.1  mrg       base += sstride[0];
    351      1.1  mrg       mbase += mstride[0];
    352      1.1  mrg       dest += dstride[0];
    353      1.1  mrg       n = 0;
    354      1.1  mrg       while (count[n] == extent[n])
    355      1.1  mrg 	{
    356      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    357      1.1  mrg 	     the next dimension.  */
    358      1.1  mrg 	  count[n] = 0;
    359      1.1  mrg 	  /* We could precalculate these products, but this is a less
    360      1.1  mrg 	     frequently used path so probably not worth it.  */
    361      1.1  mrg 	  base -= sstride[n] * extent[n];
    362      1.1  mrg 	  mbase -= mstride[n] * extent[n];
    363      1.1  mrg 	  dest -= dstride[n] * extent[n];
    364      1.1  mrg 	  n++;
    365      1.1  mrg 	  if (n >= rank)
    366      1.1  mrg 	    {
    367      1.1  mrg 	      /* Break out of the loop.  */
    368      1.1  mrg 	      base = NULL;
    369      1.1  mrg 	      break;
    370      1.1  mrg 	    }
    371      1.1  mrg 	  else
    372      1.1  mrg 	    {
    373      1.1  mrg 	      count[n]++;
    374      1.1  mrg 	      base += sstride[n];
    375      1.1  mrg 	      mbase += mstride[n];
    376      1.1  mrg 	      dest += dstride[n];
    377      1.1  mrg 	    }
    378      1.1  mrg 	}
    379      1.1  mrg     }
    380      1.1  mrg }')dnl
    381      1.1  mrg define(SCALAR_ARRAY_FUNCTION,
    382      1.1  mrg `
    383      1.1  mrg void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
    384      1.1  mrg         gfc_charlen_type, atype * const restrict,
    385      1.1  mrg 	const index_type * const restrict,
    386      1.1  mrg 	GFC_LOGICAL_4 *, gfc_charlen_type);
    387      1.1  mrg 
    388      1.1  mrg export_proto(`s'name`'rtype_qual`_'atype_code);
    389      1.1  mrg 
    390      1.1  mrg void
    391      1.1  mrg `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
    392      1.1  mrg 	gfc_charlen_type xlen, atype * const restrict array, 
    393      1.1  mrg 	const index_type * const restrict pdim,
    394      1.1  mrg 	GFC_LOGICAL_4 *mask, gfc_charlen_type string_len)
    395      1.1  mrg 
    396      1.1  mrg {
    397      1.1  mrg   index_type count[GFC_MAX_DIMENSIONS];
    398      1.1  mrg   index_type extent[GFC_MAX_DIMENSIONS];
    399      1.1  mrg   index_type dstride[GFC_MAX_DIMENSIONS];
    400      1.1  mrg   rtype_name * restrict dest;
    401      1.1  mrg   index_type rank;
    402      1.1  mrg   index_type n;
    403      1.1  mrg   index_type dim;
    404      1.1  mrg 
    405      1.1  mrg 
    406      1.1  mrg   if (mask == NULL || *mask)
    407      1.1  mrg     {
    408      1.1  mrg       name`'rtype_qual`_'atype_code (retarray, xlen, array, pdim, string_len);
    409      1.1  mrg       return;
    410      1.1  mrg     }
    411      1.1  mrg   /* Make dim zero based to avoid confusion.  */
    412      1.1  mrg   dim = (*pdim) - 1;
    413      1.1  mrg   rank = GFC_DESCRIPTOR_RANK (array) - 1;
    414      1.1  mrg 
    415      1.1  mrg   if (unlikely (dim < 0 || dim > rank))
    416      1.1  mrg     {
    417      1.1  mrg       runtime_error ("Dim argument incorrect in u_name intrinsic: "
    418      1.1  mrg  		     "is %ld, should be between 1 and %ld",
    419      1.1  mrg 		     (long int) dim + 1, (long int) rank + 1);
    420      1.1  mrg     }
    421      1.1  mrg 
    422      1.1  mrg   for (n = 0; n < dim; n++)
    423      1.1  mrg     {
    424      1.1  mrg       extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
    425      1.1  mrg 
    426      1.1  mrg       if (extent[n] <= 0)
    427      1.1  mrg 	extent[n] = 0;
    428      1.1  mrg     }
    429      1.1  mrg 
    430      1.1  mrg   for (n = dim; n < rank; n++)
    431      1.1  mrg     {
    432      1.1  mrg       extent[n] =
    433      1.1  mrg 	GFC_DESCRIPTOR_EXTENT(array,n + 1);
    434      1.1  mrg 
    435      1.1  mrg       if (extent[n] <= 0)
    436      1.1  mrg 	extent[n] = 0;
    437      1.1  mrg     }
    438      1.1  mrg 
    439      1.1  mrg   if (retarray->base_addr == NULL)
    440      1.1  mrg     {
    441      1.1  mrg       size_t alloc_size, str;
    442      1.1  mrg 
    443      1.1  mrg       for (n = 0; n < rank; n++)
    444      1.1  mrg 	{
    445      1.1  mrg 	  if (n == 0)
    446      1.1  mrg 	    str = 1;
    447      1.1  mrg 	  else
    448      1.1  mrg 	    str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
    449      1.1  mrg 
    450      1.1  mrg 	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
    451      1.1  mrg 
    452      1.1  mrg 	}
    453      1.1  mrg 
    454      1.1  mrg       retarray->offset = 0;
    455      1.1  mrg       retarray->dtype.rank = rank;
    456      1.1  mrg 
    457      1.1  mrg       alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
    458      1.1  mrg       		 * string_len;
    459      1.1  mrg 
    460  1.1.1.2  mrg       retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
    461      1.1  mrg       if (alloc_size == 0)
    462  1.1.1.2  mrg 	return;
    463      1.1  mrg     }
    464      1.1  mrg   else
    465      1.1  mrg     {
    466      1.1  mrg       if (rank != GFC_DESCRIPTOR_RANK (retarray))
    467      1.1  mrg 	runtime_error ("rank of return array incorrect in"
    468      1.1  mrg 		       " u_name intrinsic: is %ld, should be %ld",
    469      1.1  mrg 		       (long int) (GFC_DESCRIPTOR_RANK (retarray)),
    470      1.1  mrg 		       (long int) rank);
    471      1.1  mrg 
    472      1.1  mrg       if (unlikely (compile_options.bounds_check))
    473      1.1  mrg 	{
    474      1.1  mrg 	  for (n=0; n < rank; n++)
    475      1.1  mrg 	    {
    476      1.1  mrg 	      index_type ret_extent;
    477      1.1  mrg 
    478      1.1  mrg 	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
    479      1.1  mrg 	      if (extent[n] != ret_extent)
    480      1.1  mrg 		runtime_error ("Incorrect extent in return value of"
    481      1.1  mrg 			       " u_name intrinsic in dimension %ld:"
    482      1.1  mrg 			       " is %ld, should be %ld", (long int) n + 1,
    483      1.1  mrg 			       (long int) ret_extent, (long int) extent[n]);
    484      1.1  mrg 	    }
    485      1.1  mrg 	}
    486      1.1  mrg     }
    487      1.1  mrg 
    488      1.1  mrg   for (n = 0; n < rank; n++)
    489      1.1  mrg     {
    490      1.1  mrg       count[n] = 0;
    491      1.1  mrg       dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
    492      1.1  mrg     }
    493      1.1  mrg 
    494      1.1  mrg   dest = retarray->base_addr;
    495      1.1  mrg 
    496      1.1  mrg   while(1)
    497      1.1  mrg     {
    498      1.1  mrg       memset (dest, '$1`, sizeof (*dest) * string_len);
    499      1.1  mrg       count[0]++;
    500      1.1  mrg       dest += dstride[0];
    501      1.1  mrg       n = 0;
    502      1.1  mrg       while (count[n] == extent[n])
    503      1.1  mrg 	{
    504      1.1  mrg 	  /* When we get to the end of a dimension, reset it and increment
    505      1.1  mrg 	     the next dimension.  */
    506      1.1  mrg 	  count[n] = 0;
    507      1.1  mrg 	  /* We could precalculate these products, but this is a less
    508      1.1  mrg 	     frequently used path so probably not worth it.  */
    509      1.1  mrg 	  dest -= dstride[n] * extent[n];
    510      1.1  mrg 	  n++;
    511      1.1  mrg 	  if (n >= rank)
    512      1.1  mrg 	    return;
    513      1.1  mrg 	  else
    514      1.1  mrg 	    {
    515      1.1  mrg 	      count[n]++;
    516      1.1  mrg 	      dest += dstride[n];
    517      1.1  mrg 	    }
    518      1.1  mrg       	}
    519      1.1  mrg     }
    520      1.1  mrg }')dnl
    521      1.1  mrg define(ARRAY_FUNCTION,
    522      1.1  mrg `START_ARRAY_FUNCTION($1)
    523      1.1  mrg $2
    524      1.1  mrg START_ARRAY_BLOCK($1)
    525      1.1  mrg $3
    526      1.1  mrg FINISH_ARRAY_FUNCTION($4)')dnl
    527      1.1  mrg define(MASKED_ARRAY_FUNCTION,
    528      1.1  mrg `START_MASKED_ARRAY_FUNCTION
    529      1.1  mrg $2
    530      1.1  mrg START_MASKED_ARRAY_BLOCK
    531      1.1  mrg $3
    532      1.1  mrg FINISH_MASKED_ARRAY_FUNCTION')dnl
    533