Any suggestions? 
Author Message
 Any suggestions?

fortran command for c command strcopy(infile, argv[1])


Sat, 08 May 2010 00:45:51 GMT  
 Any suggestions?
Here's some stuff that works with gfortran... don't know how standard
it is.  

        character(32):: s
        integer:: nRows, nCols
        ...

        if (command_argument_count() .ne. 4) then
        ...

        call getarg(1, s)
         open(unit = 10, file = s)
         call getarg(2, s)
         read (s, *)nCols
         call getarg(3, s)
         read (s, *)nRows

Quote:

> fortran command for c command strcopy(infile, argv[1])



Sat, 08 May 2010 02:20:55 GMT  
 Any suggestions?

Quote:
> fortran command for c command strcopy(infile, argv[1])

C:\gfortran\clf\command>type command.f90
program command
   implicit none
   integer ca_len
   integer iunit
   integer iostat
   character(80) message
   integer m_size

   if(command_argument_count() < 1) then
      call get_command_argument(0,length=ca_len)
      call no_args(ca_len)
      stop
   end if
   call get_command_argument(1,length=ca_len)
   iunit = 10
   call file_open(ca_len, iunit, iostat)
   if(iostat /= 0) stop
   read(10,'(a)',advance='no',size=m_size,iostat=iostat) message
   write(*,'(2a)') 'Message = ',message(1:m_size)
end program command

subroutine no_args(ca_len)
   implicit none
   integer, intent(in) :: ca_len
   character(ca_len) ca

   call get_command_argument(0,value=ca)
   write(*,'(3a)') 'Syntax: ', ca, ' filename'
end subroutine no_args

subroutine file_open(ca_len, iunit, iostat)
   implicit none
   integer, intent(in) :: ca_len
   integer, intent(in) :: iunit
   integer, intent(out) :: iostat
   character(ca_len) ca

   call get_command_argument(1,value=ca)
   open(iunit,file=ca,iostat=iostat,action='read',pad='yes')
! Problem: iostat == 0 for missing file.  Is this correct?
   if(iostat /= 0) then
      write(*,'(2a)') 'Problems opening file ', ca
   end if
end subroutine file_open
C:\gfortran\clf\command>type testfile.txt
This is the message.

C:\gfortran\clf\command>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran
command
.f90 -ocommand

C:\gfortran\clf\command>command testfile.txt
Message = This is the message.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end



Sat, 08 May 2010 03:06:14 GMT  
 Any suggestions?

Quote:

> Here's some stuff that works with gfortran... don't know how standard
> it is.

A bit of a mix, standard-wise

Quote:
>       character(32):: s
>       integer:: nRows, nCols
>       ...
>       if (command_argument_count() .ne. 4) then

Command_argument_count is an f2003 feature, adopted in several f95
compilers. As an aside, I'd not generally test for exact equality to 4.
That could make sense in specific situations, but not as a general
practice without special reason. It would make more sense to test that
the count was at least 4 (or perhaps at least 3, as that is all your
example uses.)

Quote:
>       ...

>       call getarg(1, s)

Getarg is a nonstandard form. While it is a fairy common form, it seems
a bit of a mix to pair it with command_argument_count. No reason it
wouldn't work; just a disparity in style to pair the standard f2003
command_argument_count with the nonstandard getarg. I'd normally expect
to see either the f2003 command_argument_count paired with
command_argument or the nonstandard iargc paired with getarg.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain



Sat, 08 May 2010 03:08:03 GMT  
 Any suggestions?

Quote:

> I'd normally expect
> to see either the f2003 command_argument_count paired with
> command_argument...

Correcting myself... Make that "paired with get_command_argument", as
James correctly shows in his posting.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain



Sat, 08 May 2010 03:12:53 GMT  
 Any suggestions?

Quote:
> fortran command for c command strcopy(infile, argv[1])

    I don't know if you are asking only about how to copy character strings from
one variable to another or also want to know about how to get command line
arguments in Fortran.  I will assume that you want to know about both.

    The very first principle about doing anything with character data in Fortran
is that character strings are a **FIRST CLASS** data type, just like INTEGER,
REAL, COMPLEX, and LOGICAL.  You don't have to muck around with pointers or
treat them like arrays of individual characters.

    Character variables in Fortran are fixed-length strings, prior to Fortran
2003.  There is an optional VARYING_STRING feature that can be implemented as a
module, but it is not widely implemented.  Fortran 2003 includes the ability to
specify a varying length through the LEN=(:) specifier, but this will likely be
one of the last Fortrean 2003 features to be implemented.

    You declare character strings with the CHARACTER statement, using a LEN=n
specifier, where n is either a literal integer constant or a named integer
constant.  E.g., to declare a character variable for the input file name, you
could write:

    Character (LEN=255) :: Input_File_Name

This statement will create a character variable named Input_File_Name 255
characters in length.

    BTW, syntax elements and names in Fortran are case insensitive, unlike in C.

    Character variables behave in a way that is parallel to integer and real
variables, as much as possible.  Thus, the relational operators (>, >=, <. <=.
==, and /=) work on character strings just like they do with integers or reals.
Fortran compares according to the collating sequence for the character set used,
starting at the beginning of the string.  Earlier in the collating sequence
compares less than (<) later in the collating sequence, e.g., "A" < "Z".
Shorter strings are blank filled to the length of longer strings.

    Similarly, you use the usual assignment operator (=) to copy characters from
one string to another.  Thus, in order to copy from argv(1) to Input_File_Name,
you would write:

    Input_File_Name = argv(1)

Don't worry about mismatches in length.  By rule, Fortran truncates the source
string or blank pads the destination string on the right in order to make the
assignment fit into the destination string.  Thus, if argv(1) was 300 characters
in length, the last 45 characters would be lost.  Similarly, if argv(1) was only
55 chracters in length, it would  be appended with 200 blanks on the right.

    Fortran 2003 specifies three procedures you can use in order to get command
line arguments.  They are:
        Command_Argument_Count
        Get_Command
        Get_Command_Argument
Some Fortran 95 compilers already implement them as intrinsic subroutines, but I
know that one, gfortran, does not do it properly.  Fortunately, Winteracter has
implemented a free module, called F2KCLI, that provides a standard-comforming
capability for nearly every Fortran compiler that there is.  You can find F2KCLI
at:
        http://www.winteracter.com/f2kcli/index.htm
The comments to the source code include complete copies of the specifications
from the Fortran 2003 standard.

    To get the first command argument from the command line, you would write:

        Call Get_Command_Argument ( Number=1, Value=argv(1), Length=Arg_Length,
Status=Arg_Status)

Of course, you can use whatever variable names you want for the arguments to
this subroutine.

    Hope this helps.

--
Craig Dedo
17130 W. Burleigh Place
P. O. Box 423
Brookfield, WI   53008-0423
Voice:  (262) 783-5869
Fax:    (262) 783-5928
Mobile: (414) 412-5869



Sat, 08 May 2010 03:30:59 GMT  
 Any suggestions?

Quote:


> > fortran command for c command strcopy(infile, argv[1])

> C:\gfortran\clf\command>type command.f90
> program command
>    implicit none
>    integer ca_len
>    integer iunit
>    integer iostat
>    character(80) message
>    integer m_size

>    if(command_argument_count() < 1) then
>       call get_command_argument(0,length=ca_len)
>       call no_args(ca_len)
>       stop
>    end if
>    call get_command_argument(1,length=ca_len)
>    iunit = 10
>    call file_open(ca_len, iunit, iostat)
>    if(iostat /= 0) stop
>    read(10,'(a)',advance='no',size=m_size,iostat=iostat) message
>    write(*,'(2a)') 'Message = ',message(1:m_size)
> end program command

> subroutine no_args(ca_len)
>    implicit none
>    integer, intent(in) :: ca_len
>    character(ca_len) ca

>    call get_command_argument(0,value=ca)
>    write(*,'(3a)') 'Syntax: ', ca, ' filename'
> end subroutine no_args

> subroutine file_open(ca_len, iunit, iostat)
>    implicit none
>    integer, intent(in) :: ca_len
>    integer, intent(in) :: iunit
>    integer, intent(out) :: iostat
>    character(ca_len) ca

>    call get_command_argument(1,value=ca)
>    open(iunit,file=ca,iostat=iostat,action='read',pad='yes')
> ! Problem: iostat == 0 for missing file.  Is this correct?
>    if(iostat /= 0) then
>       write(*,'(2a)') 'Problems opening file ', ca
>    end if
> end subroutine file_open
> C:\gfortran\clf\command>type testfile.txt
> This is the message.

> C:\gfortran\clf\command>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran
> command
> .f90 -ocommand

> C:\gfortran\clf\command>command testfile.txt
> Message = This is the message.

> --
> write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
> 6.0134700243160014d-154/),(/'x'/)); end

I treid compiling on a HP Unix compiler and got these error msgs!
f90 test.f90
test.f90
   program COMMAND
       call get_command_argument(0,length=ca_len)
                                   ^
Error 240 at (10:test.f90) : The dummy arguments for
GET_COMMAND_ARGUMENT have not been specified in an interface block
    call get_command_argument(1,length=ca_len)
                                ^
Error 240 at (14:test.f90) : The dummy arguments for
GET_COMMAND_ARGUMENT have not been specified in an interface block
   external subroutine NO_ARGS
    call get_command_argument(0,value=ca)
                                ^
Error 240 at (27:test.f90) : The dummy arguments for
GET_COMMAND_ARGUMENT have not been specified in an interface block
   external subroutine FILE_OPEN
    call get_command_argument(1,value=ca)
                                ^
Error 240 at (38:test.f90) : The dummy arguments for
GET_COMMAND_ARGUMENT have not been specified in an interface block

4 Errors
f90: Errors detected, no link.



Sat, 08 May 2010 04:05:31 GMT  
 Any suggestions?

Quote:
> Error 240 at (10:test.f90) : The dummy arguments for
> GET_COMMAND_ARGUMENT have not been specified in an interface block
>    call get_command_argument(1,length=ca_len)

Yes, my method is the f03 way, and not yet supported on all compilers.
My understanding is that F2KCLI, as mentioned in Craig Dedo's post,
is an implementation that works on just about all Fortran 95
compilers.  Looking at http://www.winteracter.com/f2kcli/compat.htm
I see that HP f90 on HP/UX is supported, so I suggest you check it
out.  I have only ever seen positive comments about F2KCLI, although
in truth I have never used it myself.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end



Sat, 08 May 2010 04:45:23 GMT  
 Any suggestions?

Quote:

> I treid compiling on a HP Unix compiler and got these error msgs!
> f90 test.f90
> test.f90
>   program COMMAND
>       call get_command_argument(0,length=ca_len)
>                                   ^
> Error 240 at (10:test.f90) : The dummy arguments for
> GET_COMMAND_ARGUMENT have not been specified in an interface block
>    call get_command_argument(1,length=ca_len)
>                                ^
> Error 240 at (14:test.f90) : The dummy arguments for
> GET_COMMAND_ARGUMENT have not been specified in an interface block
>   external subroutine NO_ARGS
>    call get_command_argument(0,value=ca)
>                                ^
> Error 240 at (27:test.f90) : The dummy arguments for
> GET_COMMAND_ARGUMENT have not been specified in an interface block
>   external subroutine FILE_OPEN
>    call get_command_argument(1,value=ca)
>                                ^
> Error 240 at (38:test.f90) : The dummy arguments for
> GET_COMMAND_ARGUMENT have not been specified in an interface block

> 4 Errors
> f90: Errors detected, no link.

    The Fortran standard **REQUIRES** that any procedures that use the keyword
form of argument reference **MUST** have what is called an explicit interface.
there are two ways to provide an explicit interface.
    1.  Use interface blocks.
    2.  Place the source code for the procedures that you are calling into one
or more modules.

    Interface blocks and modules are both Fortran 90 features.

    It looks like the F90 compiler on your HP-UX system does not have a native
implementation of the Fortran 2003 command line procedures as intrinsic
procedures.  Most likely, your best course of action is to download F2KCLI from
the Winteracter web site and compile it into the F2KCLI module on your system.

--
Craig Dedo
17130 W. Burleigh Place
P. O. Box 423
Brookfield, WI   53008-0423
Voice:  (262) 783-5869
Fax:    (262) 783-5928
Mobile: (414) 412-5869



Sat, 08 May 2010 04:49:39 GMT  
 Any suggestions?

Quote:


> > I treid compiling on a HP Unix compiler and got these error msgs!
> > f90 test.f90
> > test.f90
> >   program COMMAND
> >       call get_command_argument(0,length=ca_len)
> >                                   ^
> > Error 240 at (10:test.f90) : The dummy arguments for
> > GET_COMMAND_ARGUMENT have not been specified in an interface block
> >    call get_command_argument(1,length=ca_len)
> >                                ^
> > Error 240 at (14:test.f90) : The dummy arguments for
> > GET_COMMAND_ARGUMENT have not been specified in an interface block
> >   external subroutine NO_ARGS
> >    call get_command_argument(0,value=ca)
> >                                ^
> > Error 240 at (27:test.f90) : The dummy arguments for
> > GET_COMMAND_ARGUMENT have not been specified in an interface block
> >   external subroutine FILE_OPEN
> >    call get_command_argument(1,value=ca)
> >                                ^
> > Error 240 at (38:test.f90) : The dummy arguments for
> > GET_COMMAND_ARGUMENT have not been specified in an interface block

> > 4 Errors
> > f90: Errors detected, no link.

>     The Fortran standard **REQUIRES** that any procedures that use the keyword
> form of argument reference **MUST** have what is called an explicit interface.
> there are two ways to provide an explicit interface.
>     1.  Use interface blocks.
>     2.  Place the source code for the procedures that you are calling into one
> or more modules.

>     Interface blocks and modules are both Fortran 90 features.

>     It looks like the F90 compiler on your HP-UX system does not have a native
> implementation of the Fortran 2003 command line procedures as intrinsic
> procedures.  Most likely, your best course of action is to download F2KCLI from
> the Winteracter web site and compile it into the F2KCLI module on your system.

> --
> Craig Dedo
> 17130 W. Burleigh Place
> P. O. Box 423
> Brookfield, WI   53008-0423
> Voice:  (262) 783-5869
> Fax:    (262) 783-5928
> Mobile: (414) 412-5869


Thanks for  the help! Appears to be lot simpler in C, to insert a
subroutine call to use strcpy(fn,argv[1]) etc


Sat, 08 May 2010 04:56:13 GMT  
 Any suggestions?


Quote:
>   open(iunit,file=ca,iostat=iostat,action='read',pad='yes')
> ! Problem: iostat == 0 for missing file.  Is this correct?

The above is a bug.  Looking at n3661.pdf, section 9.4.5.15:

"If UNKNOWN is specified, the status is processor dependent.  If
this specifier is omitted, the default value is UNKNOWN."

Thus the status should pretty much always be specified when
opening (not reopening) a named file so as to avoid the highly
undesirable UNKNOWN status.  Fixing this:

open(iunit,file=ca,iostat=iostat,action='read',pad='yes',status='old')

The program detects when the file is not found.  Sorry for the
mistake in my original example.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end



Sat, 08 May 2010 04:57:52 GMT  
 Any suggestions?

Quote:

>>     The Fortran standard **REQUIRES** that any procedures that use the
>> keyword
>> form of argument reference **MUST** have what is called an explicit
>> interface.
>> there are two ways to provide an explicit interface.
>>     1.  Use interface blocks.
>>     2.  Place the source code for the procedures that you are calling into
>> one
>> or more modules.

>>     Interface blocks and modules are both Fortran 90 features.

>>     It looks like the F90 compiler on your HP-UX system does not have a
>> native
>> implementation of the Fortran 2003 command line procedures as intrinsic
>> procedures.  Most likely, your best course of action is to download F2KCLI
>> from
>> the Winteracter web site and compile it into the F2KCLI module on your
>> system.

> Thanks for  the help! Appears to be lot simpler in C, to insert a
> subroutine call to use strcpy(fn,argv[1]) etc

    I strongly disagree.  The C approach may appear to be easier for you, for a
number of reasons.
    1.  Apparently, you are very familiar with C and are only starting to learn
Fortran.
    2.  The C command line functionality has been around since C first got
started, i.e., for over 20 years.
    3.  In contrast, the Fortran 2003 command line functionality is very recent.
Not all Fortran compilers support it yet as part of the Fortran compiler.
    4.  Some of the more advanced features of procedure calls, e.g.,
keyword-style arguments, require explicit interfaces.  There is no corresponding
feature in C.
    5.  There are substantial cultural differences between Fortran and C.

    FYI, two years ago I downloaded and compiled the F2KCLI module on an OpenVMS
system and then used the module in a production program.  Building and using it
was a very clean and simple process.

    Here is how to do what you want very simply and straightforwardly in
Fortran.
[Begin example]
    Use F2KCLI                ! Use the F2KCLI module from Winteracter in order
to provide the Fortran 2003 command line capabilities.  This statement is not
necessary if the compiler already has this functionality.
    Character (Len=255)    :: Input_File_Name
    Character (Len=50)      :: Command_Arg_1
    Call Get_Command_Argument (Number=1, Value=Command_Arg_1)
    Input_File_Name = Command_Arg_1
[End of example]

    Hope this helps.

--
Craig Dedo
17130 W. Burleigh Place
P. O. Box 423
Brookfield, WI   53008-0423
Voice:  (262) 783-5869
Fax:    (262) 783-5928
Mobile: (414) 412-5869



Sat, 08 May 2010 05:38:17 GMT  
 Any suggestions?

Quote:

> Thanks for  the help! Appears to be lot simpler in C, to insert a
> subroutine call to use strcpy(fn,argv[1]) etc

The complication in the examples was the sort of checking that you
should also be doing in C.  How do you verify that argv[1] is present,
how do you verify that fn is big enough to accept it, etc... a naive
strcpy is a recipe for a buffer overflow error.

As far as having or not having the current standard argument access
features, that's a bit of a pain, granted.  (You would no doubt be
somewhat limited by using an out-of-date C compiler as well, but I'd
expect the limitations to fall in less commonly-used areas.)



Sat, 08 May 2010 05:41:32 GMT  
 Any suggestions?

Quote:

> there are two ways to provide an explicit interface.
>     1.  Use interface blocks.
>     2.  Place the source code for the procedures that you are calling into one
> or more modules.

Make that 4 ways instead of 2.

The 3rd way, not likely to be used in this case, but just for pedantic
completeness, is to make the procedure an internal procedure.

The 4th way, however, is extremely relevant to this case. That's for the
procedure to be an intrinsic one. These procedures are f2003 standard
intrinsic procedures, so for f2003, you do nothing at all to get the
explicit interface. In fact, doing some of the other things would be
counter-productive and probably cause the program to fail. For example,
if you try to use an interface block for an intrinsic procedure, that
won't work.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain



Sat, 08 May 2010 06:07:28 GMT  
 Any suggestions?

Quote:
> "If UNKNOWN is specified, the status is processor dependent.  If
> this specifier is omitted, the default value is UNKNOWN."

> Thus the status should pretty much always be specified when
> opening (not reopening) a named file so as to avoid the highly
> undesirable UNKNOWN status.

I have expressed my disagreement with this position before, but I
suppose I'll do it again, as it doesn't seem to have stuck. Or maybe you
just disagree with me, in which case, I'll at least go on record as
reminding people that another side of the matter exists.

I see nothing at all undesirable about the unknown status if that is an
accurate representation of reality, as is often the case.

If the file is required to be an old one, then certainly specifying
status='old' is better. Likewise, if a status of new or replace is
specifically desired, then specify the appropriate one of them.

But there are plenty of cases where status='unknown' is exactly what is
appropriate. If there is an existing file, you want to open it. If there
is no existing file, you want to create a new one. For example, that
would be the usual cases when opening a log file that you want to either
append to or create.

If that is the situation, then there is nothing at all undesirable about
status='unknown'. To the contrary, it exactly fits that need. I have
seen people here propose Rube Goldberg schemes whereby they achieve this
same effect with an inquire, followed by an open with a status of new or
old, depending on the result of the inquire. I see no sense at all in
such a roundabout aproach. If anything, it is objectively inferior to a
simple open with status='unknown' because the complicated version with
inquire is susceptible to race conditions. (Things can possibly change
between the inquire and the open; and if one doesn't think that can
happen, then one must not have paid much attention to the large number
security hacks based on taking advantage of exactly that kind of race
condition).

As far as I can tell, the only reason that peopel write code like that
is that someone has told them that status='unknown' is undesirable for
some ill-defined reason. It just ain't so. The "processor dependence"
here is a red herring. The reason processor dependence is in whether the
file exists or not. That is inherent to the scenario - not something
particular to this specifier in the OPEN statement.

Yes, it probably is the case that status='old' was appropriate for the
particular code in question. But I vehemently object to the
overgeneralization that status='unknown' is somehow inherently
undesirable. That overgeneralization causes people to go out of their
way to avoid it when it is exactly the right thing.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain



Sat, 08 May 2010 06:31:04 GMT  
 
 [ 25 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Help needed - suggestions about Smalltalk for Windows

2. How to instantiate a class suggestion?

3. Small Package Browser suggestion

4. Console app + networking: a suggestion

5. Suggestion: Patch Directory...

6. Suggestion - #ideModel

7. Suggestions for a way to prove/refute this?

8. Suggestions II

9. Suggestions

10. Small IDE suggestion

11. Code mentor suggestion

12. D6 suggestion

 

 
Powered by phpBB® Forum Software