COMMAND LINE CRACKING WITH GET_COMMAND()
AND WHY THE PROCEDURE NEEDS CLARIFIED OR CHANGED:
John S. Urban Dec,2008
Well, the good news is starting with Fortran 2003 there is a standard
way to get the command line with the GET_COMMAND() procedure. It
is already very widely available in f90+ compilers (g95, gfortran,
ifort, ...). Or, you can use the F2KCLI package to add it if your
compiler does not have it; or you can make something very much like
it using the often-available GETARGS() and IARG() procedures or their
equivalent (I don't know of a Fortran /FORTRAN compiler that doesn't
have one anymore).
The GET_COMMAND() routine is clarified in the most recent Fortran
2008 proposal; but there's still a flaw in making what GET_COMMAND()
returns determinant; and different compilers seem to have solved the
"problem" differently. G95 seems to do the most reasonable thing --
leave the command "verb" out of the "complete command string" and let
you get the verb with GET_COMMAND_ARGUMENT(0) if you can. But the
standard seems to imply the verb should be returned by GET_COMMAND()
(and gfortran, ifort, and IBM include it). Yet the description of
GET_COMMAND_ARGUMENT() clearly states that GET_COMMAND_ARGUMENT(0)
may not exist or be accessable, while other arguments (ie. 1, 2, 3,
...) may be.
SIMPLE EXAMPLE OF WHERE THIS LEADS TO PROBLEMS:
Lets say the verb should be part of what GET_COMMAND() returns:
A related procedure (GET_COMMAND_ARGUMENT()) makes it clear the command
verb may legally not be defined. And so if you use GET_COMMAND() you
don't know if the returned value includes the pathname to the command
or not; and some systems allow filenames with blank characters (or
backslashes,etc.); and you are going to have to make sure the returned
value is big enough for any pathname plus the actual arguments.
Lets say the verb is not part of what GET_COMMAND() returns:
You can still get it with GET_COMMAND_ARGUMENT(0,VERB,STATUS) as one
string, so things like blanks in the filename are not confusing.
So I say that the G95 interpretation ends up with a better routine. In
fact, GET_COMMAND() is better off replaced with a routine that
concatenates the strings returned by GET_COMMAND_ARGUMENT() if
interpretation (A) is used.
AGAIN WITH EXAMPLES AND DOCUMENTATION EXTRACTS:
! ------------------------------------------------------------------
! TEST PROGRAM:
! -------------
! ISSUE:
! ifort(1) and gfortran(1) return get_command_argument(0) at beginning of
! string returned by get_command(3f). g95(1) return string that begins
! with get_command_argument(1)
-------------------------------------------------------------------
! pros and cons:
! get_command_argument implies there may not be a meaningful
! get_command_argument(0); so you can't know if the "verb" is there or not.
! Could resolve that by letting you control if
! get_command_argument(0) is present in COMMAND or not;
! or less desirably STATUS could have values assigned that mean
! returned-OK-with-arg(0) and returned-OK-without-arg(0).
! That is, STATUS=0 means OK with; STATUS=1 means OK without.
! Using STATUS means the current command does not change, but this
! means you would have to conditionally parse arg(0) if present.
! But is get_command_argument(0) "exactly as typed" or the
! full path or ! the path leaf?
! What about spaces and non-alphameric characters like \ in the command?
!
! Something else that is not clear to me -- is the only delimiter for
! get_command_argument(3F) a space? What about tab, comma, colon, and so on?
!
! the other problem is that the length of the COMMAND variable would have
! to be able to hold all the parameters plus the longest possible arg(0)
! option; which is typically a system pathname.
Program echo
integer :: i
integer :: ierr
character :: command*256
call get_command_argument(0,command,i,ier)
write (*,*) "get_command_argument(0) is "//command(:len_trim(command))
call get_command(command,i,ier)
write (*,*) "get_command is " //command(:len_trim(command))
do i10=1,command_argument_count()
call get_command_argument(i10,command)
write (*,*) i10, "th argument="//command(:len_trim(command))
enddo
end program echo
-------------------------------------------------------------------
!GFORTRAN RUN:
------------
!
!gfortran-4 --version
! GNU Fortran (GCC) 4.3.2 20080827 (alpha-testing) 1
! Copyright (C) 2008 Free Software Foundation, Inc.
! :
!
!gfortran-4 bug1.f90
!./a
! get_command_argument(0) is ./a
! get_command is ./a <--- arg(0) is in COMMAND
!
-------------------------------------------------------------------
!G95 RUN:
-------
!
!g95 --version
!G95 (GCC 4.0.3 (g95 0.92!) Aug 21 2008)
!Copyright (C) 2002-2005 Free Software Foundation, Inc.
! :
!
!g95 bug1.f90
!./a
! get_command_argument(0) is ./a
! get_command is <--- arg(0) is not in COMMAND
-------------------------------------------------------------------
So, what should GET_COMMAND(3f) and GET_COMMAND_ARGUMENT(3f) return from
a Unix platform (for example) if the command executed is:
/bin/"parsed command" -header hello
Is there any system where the following should execute?
what would they return if run with the program above?
program.exe,a=10,b=20,c,d
.\program.exe/a=10/b=20
RESULTS FROM GFORTRAN COMPILER:
Microsoft Windows [Version 6.0.6001]
Copyright (c) 2006 Microsoft Corporation. All rights reserved.
# program called "gf"
gf;a;b;c
get_command_argument(0) is gf
get_command is gf ;a;b;c <-- notice the space
1 th argument=;a;b;c
# program called "g f.exe"
"g f"/a=10/b=20
get_command_argument(0) is gf
get_command is g f /a=10/b=20
1 th argument=/a=10/b=20
# two ways on MSW to execute the same program. Results varied a lot
# with each compiler. Some showed "g f.exe" in GET_COMMAND(), but "g f" in
# GET_COMMAND_ARGUMENT(), for example.
"g f" hello
"g f.exe" hello
#############################################################################
REFERENCES:
--------------------------------------------------------------------------------------------------------------------
! DESCRIPTIONS FROM J3'S RECENT PROPOSAL FOR FORTRAN 2008:
--------------------------------------------------------------------------------------------------------------------
! Page 348 Intrinsic procedures and modules 13.7.62
! 08-007r2:2008/03/11 CD 1539-1 ISO/IEC SC22/WG5/N1723
!
!
! 13.7.65 GET_COMMAND ([COMMAND, LENGTH, STATUS])
!1 Description. Get the entire command by which the program was invoked.
!
!2 Class. Subroutine.
!
!3 Arguments.
! COMMAND (optional) shall be a default character scalar. It is an INTENT (OUT) argument. It is assigned
! the entire command by which the program was invoked. If the command cannot be determined,
! COMMAND is assigned all blanks.
! LENGTH (optional) shall be a default integer scalar. It is an INTENT (OUT) argument. It is assigned the
! significant length of the command by which the program was invoked. The significant length may
! include trailing blanks if the processor allows commands with significant trailing blanks. This length
! does not consider any possible truncation or padding in assigning the command to the COMMAND
! argument; in fact the COMMAND argument need not even be present. If the command length
! cannot be determined, a length of 0 is assigned.
! STATUS (optional) shall be a default integer scalar. It is an INTENT (OUT) argument. It is assigned the
! value -1 if the COMMAND argument is present and has a length less than the significant length
! of the command. It is assigned a processor-dependent positive value if the command retrieval fails.
! Otherwise it is assigned the value 0.
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
! 13.7.66 GET_COMMAND_ARGUMENT (NUMBER [, VALUE, LENGTH,
! STATUS])
!1 Description. Get an argument from the command by which the program was invoked.
!
!2 Class. Subroutine.
!
!3 Arguments.
! NUMBER shall be a default integer scalar. It is an INTENT (IN) argument.
! It specifies the number of the command argument that the other arguments give information about.
! Useful values of NUMBER are those between 0 and the argument count returned by the intrinsic
! function COMMAND_ARGUMENT_COUNT. Other values are allowed, but will result in error
! status return (see below).
! Command argument 0 is defined to be the command name by which the program was invoked if
! the processor has such a concept. NUMBER is allowed to be zero even if the processor does not
! define command names or other command arguments.
! The remaining command arguments are numbered consecutively from 1 to the argument count in
! an order determined by the processor.
! VALUE (optional) shall be a default character scalar. It is an INTENT (OUT) argument. It is assigned the
! value of the command argument specified by NUMBER. If the command argument value cannot be
! determined, VALUE is assigned all blanks.
! LENGTH (optional) shall be a default integer scalar. It is an INTENT (OUT) argument. It is assigned the
! significant length of the command argument specified by NUMBER. The significant length may
! include trailing blanks if the processor allows command arguments with significant trailing blanks.
! This length does not consider any possible truncation or padding in assigning the command argument
! value to the VALUE argument; in fact the VALUE argument need not even be present. If the
! command argument length cannot be determined, a length of 0 is assigned.
! STATUS (optional) shall be a default integer scalar. It is an INTENT (OUT) argument. It is assigned the
! value -1 if the VALUE argument is present and has a length less than the significant length of the
! command argument specified by NUMBER. It is assigned a processor-dependent positive value if
! the argument retrieval fails. Otherwise it is assigned the value 0.
--------------------------------------------------------------------------------------------------------------------