Still supported by several compilers. ifort/ifx has the extension, called the “VFE” extension.
For compilers that do not, you can convert it to an internal write relatively easily. Looks like
@Beliavsky got to that already. A little example is
program extension
! use Variable Format Expression (VFE) extension
implicit none
integer :: int1, int2, iostat
character(len=256) :: iomsg
character(len=256) :: fmt
int1=3
int2=1
! USE EXTENSION
write(*,101,iostat=iostat,iomsg=iomsg)10,20,30
! <int2> is replaced by it's value, same for <int1>
101 format(<int2>(:"[",i0,"]"),<int1>(:"[",i0,"]"))
if(iostat.ne.0)write(*,*)trim(iomsg)
! USE STANDARD INTERNAL WRITE TO CREATE FORMAT
write(fmt,'(*(g0))')'(',int2,'(:"[",i0,"]")',int1,'(:"[",i0,"]")',')'
! so you can see what that did
write(*,*)'CREATED FORMAT STATEMENT:',trim(fmt)
write(*,fmt,iostat=iostat,iomsg=iomsg)10,20,30
if(iostat.ne.0)write(*,*)trim(iomsg)
end program extension
So for complicated formats where you actually need to generate the format the VFE would; use
internal writes to build a normal format and use that as a standard way to do the equivalent. For a lot of simple statements any of the above suggestions can help. For the simple one you posted an “exact” equivalent would be
VFE: block
character(len=256) :: fmt
! this would build the format
write(fmt,'(*(g0))')'(', mypar%l, 'f12.4)'
! show the format for fun
write(*,*)'fmt=',trim(fmt)
! use the format
write(ch,fmt) (mypar%mu(ii,jj,tt), jj=1,mypar%l)
endblock VFE