text: from __future__ import print_function
  
  types = (
      ( 'int', 'integer(C_INT)' ),
      ( 'long', 'integer(C_LONG)' ),
      ( 'float', 'real(C_FLOAT)' ),
      ( 'double', 'real(C_DOUBLE)' )
  )
  
  maxdims = 3
  
  def gen_bounds():
      print('')
      print('! splicer begin class.Allocator.type_bound_procedure_part')
      print('')
      for (name, _) in types:
          for dim in range(maxdims+1):
              print(f'procedure :: allocate_{name}_array_{dim+1}d => allocator_allocate_{name}_array_{dim+1}d')
              print(f'procedure :: deallocate_{name}_array_{dim+1}d => allocator_deallocate_{name}_array_{dim+1}d')
      print('generic, public :: allocate => &')
      for (name, _) in types:
          for dim in range(maxdims+1):
              print(f'    allocate_{name}_array_{dim+1}d, &')
      print('')
      print('generic, public :: deallocate => &')
      for (name, _) in types:
          for dim in range(maxdims+1):
              print(f'    deallocate_{name}_array_{dim+1}d, &')
      print('')
      print('! splicer end class.Allocator.type_bound_procedure_part')
      print('')
  
  def gen_methods():
      print('! splicer begin class.Allocator.additional_functions')
      print('')
  
      for (name, c_type) in types:
          for dim in range(maxdims+1):
              print("""
  subroutine allocator_allocate_{name}_array_{dim}d(this, array, dims)
        use iso_c_binding
  
        class(UmpireAllocator) :: this
        {c_type}, intent(inout), pointer, dimension({dim_string}) :: array
  
        integer, dimension(:) :: dims
  
        type(C_PTR) :: data_ptr
  
        {c_type} :: size_type
        {c_size_t} :: num_bytes
  
        num_bytes = product(dims) * sizeof(size_type)
        data_ptr = this%allocate_pointer(num_bytes)
  
        call c_f_pointer(data_ptr, array, dims)
  end subroutine allocator_allocate_{name}_array_{dim}d
  
  """.format(dim=dim+1, name=name, c_type=c_type, dim_string= ", ".join([":" for i in range(dim+1)])))
  
              print("""
  subroutine allocator_deallocate_{name}_array_{dim}d(this, array)
        use iso_c_binding
  
        class(UmpireAllocator) :: this
        {c_type}, intent(inout), pointer, dimension({dim_string}) :: array
  
        type(C_PTR) :: data_ptr
  
        data_ptr = c_loc(array)
  
        call this%deallocate_pointer(data_ptr)
        nullify(array)
  end subroutine allocator_deallocate_{name}_array_{dim}d
  
  """.format(dim=dim+1, name=name, c_type=c_type, dim_string= ", ".join([":" for i in range(dim+1)])))
      print('! splicer end class.Allocator.additional_functions')
  
  def gen_fortran():
      print('! Generated by genfumpiresplicer.py')
      print('')
  
      gen_bounds()
      gen_methods()
  
  if __name__ == '__main__':
      gen_fortran()
  