! rawread.exe - raw array to gtool4 convertor
! Copyright (C) TOYODA Eizi, 2000.  All rights reserved.
! vi: set sw=4:

module rawread_file
    use dc_string
    use varying_strings
    implicit none
    private
    public:: file_status, file_read, file_open, file_name
    public:: file_direct, file_formatted, file_skip, file_recl

    integer, save:: unit = 0
    type(VSTRING):: file
    character(len = 11):: form = 'UNFORMATTED'
    character(len = 10):: access = 'SEQUENTIAL'
    logical, save:: exist = .FALSE.
    logical, save:: opened = .FALSE.
    integer, save:: recl = 1
    integer, save:: iostat = 0
    integer, save:: skip_file = 0
    integer, save:: skip_record = 0
    
contains

    subroutine file_formatted(formatted)
	logical, intent(in):: formatted
    continue
	if (formatted) then
	    form = 'FORMATTED'
	else
	    form = 'UNFORMATTED'
	endif
    end subroutine

    subroutine file_direct(direct)
	logical, intent(in):: direct
    continue
	if (direct) then
	    access = 'DIRECT'
	else
	    access = 'SEQUENTIAL'
	endif
    end subroutine

    subroutine file_status(tokens)
	use dcl
	type(STRINGS), intent(in):: tokens
    continue
	if (unit == 0) then
	    unit = DclGetUnitNum()
	    file = ""
	endif
	inquire(file=file, recl=recl, opened=opened, exist=exist)
	print "('--- file module status ---')"
	print "(' unit=',i3,' iostat=',i3,' &
	    & open=',L1,' exist=',L1,' file=',a20)", &
	    & unit, iostat, opened, exist, char(file)
	print "(' access=',a10,' form=',a11,' recl=',i8)", access, form, recl
    end subroutine

    subroutine file_open
	if (access == 'DIRECT') then
	    open(unit=unit, file=char(file), access=access, form=form, &
		& recl=recl, iostat=iostat)
	else
	    open(unit=unit, file=char(file), access=access, form=form, &
		& iostat=iostat)
	endif
    end subroutine

    subroutine file_name(tokens)
	type(STRINGS), intent(inout):: tokens
	character(len=3) fmt, unf, seq, drc
	integer:: f_unit
    continue
	file = pop(tokens)
	inquire(file=file, formatted=fmt, unformatted=unf, sequential=seq, &
	    & direct=drc, opened=f_unit, exist=exist)
	if (f_unit > 0) unit = f_unit
	if (fmt == 'YES' .and. unf == 'YES') then
	    form = '(both ok)'
	else if (fmt == 'YES') then
	    form = 'FORMATTED'
	else if (unf == 'YES') then
	    form = 'UNFORMATTED'
	endif
	if (seq == 'YES' .and. drc == 'YES') then
	    access = '(both ok)'
	else if (seq == 'YES') then
	    access = 'SEQUENTIAL'
	else if (drc == 'YES') then
	    access = 'DIRECT'
	else
	    access = '(both bad)'
	endif
    end subroutine

    subroutine file_skip(tokens)
	type(STRINGS), intent(inout):: tokens
    continue
	if (len(tokens) <= 0) then
	    print *, 'skip (file, record): ', skip_file, skip_record
	else
	    skip_file = stoi(shift(tokens))
	    skip_record = stoi(shift(tokens))
	endif
    end subroutine

    subroutine file_recl(tokens)
	type(STRINGS), intent(inout):: tokens
    continue
	if (len(tokens) <= 0) then
	    print *, 'recl = ', recl
	else
	    recl = stoi(shift(tokens))
	endif
    end subroutine

    subroutine file_read(tokens)
	type(STRINGS), intent(in):: tokens
    end subroutine

end module rawread_file


module rawread_array

    use dc_string
    use varying_strings
    implicit none
    private
    public:: array_size, array_type

contains

    subroutine array_size(tokens)
	type(STRINGS), intent(in):: tokens
    end subroutine

    subroutine array_type(type)
	type(VSTRING), intent(in):: type
    end subroutine

end module


program rawread
    use dc_string
    use varying_strings
    use getline
    use rawread_array
    use rawread_file
    type(VSTRING):: command
    type(STRINGS):: tokens
    integer:: iostat
continue
    call init(tokens)
    call set_prompt('rawread> ')
    do
	call ask_tokens(tokens, iostat=iostat)
	if (iostat /= 0) exit
	command = shift(tokens)
	if (command == "") cycle
	if (command == 'exit' .or. command == 'quit' .or. command == 'q') exit
	if (command == 'sta') command = 'status'
	if (command == 'seq') command = 'sequential'
	if (command == 'help') then 
	    call help
	else if (command == 'cd') then
	    call cd(pop(tokens)) 
	else if (command == 'ascii') then
	    call file_formatted(.TRUE.)
	else if (command == 'binary') then
	    call file_formatted(.FALSE.)
	else if (command == 'endian') then
	    print *, 'unsupported command'
	else if (command == 'exec' .or. command == '!') then
	    call exec(tokens)
	else if (command == 'direct') then
	    call file_direct(.TRUE.) 
	else if (command == 'file') then
	    call file_name(tokens)
	else if (command == 'format') then
	    print *, 'unsupported command'
	    ! call file_format(tokens)
	else if (command == 'integer') then
	    call array_type(command)
	else if (command == 'list') then
	    print *, 'unsupported command'
	    ! call listmode
	else if (command == 'ls') then 
	    call exec(tokens, insert='ls')
	else if (command == 'open') then
	    call file_open()
	else if (command == 'read') then
	    call file_read(tokens)
	else if (command == 'real') then
	    call array_type(command)
	else if (command == 'recl') then
	    call file_recl(tokens)
	else if (command == 'save') then
	    print *, 'unsupported command'
	    ! call savemode(tokens)
	else if (command == 'size') then
	    call array_size(tokens)
	else if (command == 'sequential') then
	    call file_direct(.FALSE.)
	else if (command == 'show') then
	    print *, 'unsupported command'
	    ! call showmode
	else if (command == 'skip') then
	    call file_skip(tokens)
	else if (command == 'status') then
	    call file_status(tokens)
	else if (command == 'unformatted') then
	    call file_formatted(.FALSE.)
	else
	    call put_line("unknown command: " // command);
	endif
    enddo
    ! プロセスが続くなら call dispose(tokens) すべきところ
    stop
contains

    subroutine help
	print *, "rawread by TOYODA Eizi <toyoda@gfd-dennou.org>, 2000."
	print *, "commands:"
	print *, "    ascii binary endian exit direct format help integer list"
	print *, "    read real recl save size sequential show skip status unformatted"
    end subroutine

    subroutine exec(tokens, insert)
	use dcl
	type(STRINGS), intent(in):: tokens
	type(STRINGS):: list
	character(len = *), intent(in), optional:: insert
	type(VSTRING):: command, word
    continue
	call init(list)
	list = tokens
	if (present(insert)) call unshift(list, var_str(insert))
	command = ''
	do
	    if (len(list) == 0) exit
	    word = shift(list)
	    if (index(word, ' ') > 0) word = '"' // word // '"'
	    command = command // ' ' // word
	enddo
	call put_line('> ' // command)
	call osexec(char(command))
	call dispose(list)
    end subroutine

    subroutine cd(dir)
	use dfport
	type(VSTRING), intent(in):: dir
	integer:: errno
    continue
	errno = chdir(char(dir))
	if (errno == 0) return
	if (errno == ENOENT) then
	    call put_line('cd: ' // dir // ' not exists.')
	else if (errno == ENOTDIR) then
	    call put_line('cd: ' // dir // ' is not a directory.')
	else
	    call put_line('cd: unknown error')
	endif
    end subroutine

end program
