! Copyright (C) GFD Dennou Club, 2000.  All rights reserved

recursive subroutine ANVarOpen(var, url, writable, err)
    use dc_string, only: VSTRING, operator(/=), vchar, len, &
        & assignment(=), operator(==)
    use an_types
    use an_file
    use dc_url
    use dc_error
    use netcdf_f77
    use an_generic, only: Slice
    implicit none
    type(AN_VARIABLE), intent(inout):: var
    type(VSTRING), intent(in):: url
    logical, intent(in), optional:: writable
    logical, intent(out), optional:: err
    type(VSTRING):: filename, varname, iorange
    type(VSTRING):: limitdim, iorange_remainder
    type(VSTRING):: range(3)
    character(len = NF_MAX_NAME):: dimname
    integer:: stat, nvars, ndims, i, growable_dim_id
continue
    call UrlSplit(url, file=filename, var=varname, iorange=iorange)
    if (filename == "") filename = "gtool.nc"
    call ANFileOpen(var%fileid, filename, stat=stat, writable=writable)
    if (stat /= 0) goto 999
    !
    ! 名前から変数を探し出す
    !
    if (varname /= '') then
        var%varid = 0
        stat = nf_inq_varid(var%fileid, vchar(varname, len(varname)), var%varid)
        if (stat == NF_ENOTVAR) then
            var%varid = 0
            goto 100
        endif
    else
        ! 名前が空ならできれば次元変数でない最初の変数をとりだす
        stat = nf_inq_nvars(var%fileid, nvars)
        if (stat /= 0) goto 999
        var%varid = 1
        do, i = 1, nvars
            stat = nf_inq_varname(var%fileid, i, dimname)
            if (stat /= NF_NOERR) goto 999
            stat = nf_inq_dimid(var%fileid, dimname, var%dimid)
            if (stat == NF_NOERR) cycle
            if (stat /= NF_EBADDIM) goto 999
            var%varid = i
            stat = NF_NOERR
            exit
        enddo
    endif
    if (stat /= NF_NOERR) goto 999
    !
    ! 次元id を調べる
    !
100 continue
    stat = nf_inq_dimid(var%fileid, vchar(varname, len(varname)), var%dimid)
    if (stat /= NF_NOERR) then
        if (var%varid <= 0) goto 999
        var%dimid = 0
    endif
    !
    ! 次元数を調べて必要な配列を割り付ける
    !
    if (var%varid > 0) then
        stat = nf_inq_varndims(var%fileid, var%varid, ndims)
        if (stat /= NF_NOERR) goto 999
        if (ndims == 0) then
            nullify(var%dimids, var%allcount)
        else
            allocate(var%dimids(ndims))
            allocate(var%allcount(ndims))
            stat = nf_inq_vardimid(var%fileid, var%varid, var%dimids)
            if (stat /= NF_NOERR) goto 999
        endif
    else
        ndims = 1
        allocate(var%dimids(1))
        allocate(var%allcount(1))
        var%dimids(1) = var%dimid
    endif
    ! Even if no unlimited dimension exists, stat will be NF_NOERR.
    stat = nf_inq_unlimdim(var%fileid, growable_dim_id)
    if (stat /= NF_NOERR) goto 999
    var%growable = 0
    do, i = 1, ndims
        stat = nf_inq_dimlen(var%fileid, var%dimids(i), var%allcount(i))
        if (stat /= NF_NOERR) goto 999
        if (var%dimids(i) == growable_dim_id) var%growable = i
    enddo
    if (ndims == 0) then
        nullify(var%start, var%count, var%stride)
    else
        allocate(var%start(ndims))
        allocate(var%count(ndims))
        allocate(var%stride(ndims))
        var%start(:) = 1
        var%count(:) = var%allcount(:)
        var%stride(:) = 1
    endif
    var%attrid = 0
    !
    ! 入出力範囲限定処理
    !
    do
        call IORangeParse(iorange, limitdim, range, iorange_remainder)
        if (limitdim == "") exit
        call Slice(var, limitdim, &
            lower=range(1), upper=range(2), interval=range(3))
        iorange = iorange_remainder
    enddo
    !
    ! エラー処理 (正常完了時も呼ぶ)
    !
999 continue
    call StoreError(stat, 'ANVarOpen', err)
end subroutine
