# Defining commandline parameters

**URL:** <https://fortran-lang.discourse.group/t/defining-commandline-parameters/2017>\
**Category:** Uncategorized\
**Created:** [October 6, 2021, 9:56am UTC](https://fortran-lang.discourse.group/t/defining-commandline-parameters/2017 "2021-10-06T09:56:04Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![garynewport](https://avatars.discourse-cdn.com/v4/letter/g/898d66/32.png) [@garynewport](https://fortran-lang.discourse.group/u/garynewport)\
**Post date:** [October 6, 2021, 9:56am UTC](https://fortran-lang.discourse.group/t/defining-commandline-parameters/2017/1 "2021-10-06T09:56:04Z")

</div>

How might I go about defining the commandline arguments, such that I don’t have to do all or nothing?

I have (at least) 2 parameters I wish to parse to the main routine; accmethod and massonly; both being values. I also currently define the output file as `> dummymain.lst` but wonder if I might be better served by turning this into a commandline option with a default setting.

I’m wondering if I should be considering something along this line…

```auto
dummymain accmethod=2 massonly=1 outfile='dummymain.lst'

```

How would I be able to identify which is which or is this simply by reading in the parameters as usual (all as strings, which is the default action of Fortran, I believe) and simply interrogating each parameter given (so, look for `accmethod=` within the argument itself)?

---

<div class="post-metadata">

**Author:** ![mecej4](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/mecej4/32/855_2.png) [@mecej4](https://fortran-lang.discourse.group/u/mecej4)\
**Post date:** [October 6, 2021, 10:27am UTC](https://fortran-lang.discourse.group/t/defining-commandline-parameters/2017/2 "2021-10-06T10:27:25Z")

</div>

It seems to me that you expect the user to run your program from the command line. A Windows user may prefer to run with no arguments, but have a small SETTINGS windows to pop up, showing default values and clickable buttons, etc., to change those values.

In the command line version, you expect the arguments to appear in arbitrary order, and each argument has the form

```
 KeyWord = value

```

You can maintain a table containing a “dictionary”. For each keyword string, there will be a corresponding variable in the program, possibly with a default value.

At the beginning of your program, you process the command line arguments; for each, you look up the variable (or its index, if all the variables are in an array, or the relevant component of a derived type) in the dictionary, and set the corresponding variable entity to the value after the ‘=’.

---

<div class="post-metadata">

**Author:** ![garynewport](https://avatars.discourse-cdn.com/v4/letter/g/898d66/32.png) [@garynewport](https://fortran-lang.discourse.group/u/garynewport)\
**Post date:** [October 6, 2021, 10:38am UTC](https://fortran-lang.discourse.group/t/defining-commandline-parameters/2017/3 "2021-10-06T10:38:48Z")

</div>

Thank you. We’re running this under commandline in Windows, OsX and Linux; since the servers I will eventually run this on are Linux units.

I will explore this further and get this set up. I did think this was probably the methodology used but appreciate the direction - it helps build my confidence. 🙂

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [October 6, 2021, 11:36am UTC](https://fortran-lang.discourse.group/t/defining-commandline-parameters/2017/4 "2021-10-06T11:36:48Z")

</div>

> [@garynewport](#):
>
> How might I go about defining the commandline arguments, such that I don’t have to do all or nothing?
> 
> I have (at least) 2 parameters I wish to parse to the main routine; accmethod and massonly; both being values. I also currently define the output file as `> dummymain.lst` but wonder if I might be better served by turning this into a commandline option with a default setting.
> 
> I’m wondering if I should be considering something along this line…
> 
> ```auto
> dummymain accmethod=2 massonly=1 outfile='dummymain.lst'
> 
> ```
> 
> How would I be able to identify which is which or is this simply by reading in the parameters as usual (all as strings, which is the default action of Fortran, I believe) and simply interrogating each parameter given (so, look for `accmethod=` within the argument itself)?

There are tools to parse command lines in a Fortran program:

[M\_CLI2](https://github.com/urbanjost/M_CLI2): cracks the command line when given a prototype string that looks very much like an invocation of the program, by urbanjost. A call to get\_args(3f) or one of its variants is then made for each parameter name to set the variables appropriately in the program.

[fArgParse](https://github.com/Goddard-Fortran-Ecosystem/fArgParse): command line argument parsing for Fortran, from Goddard-Fortran-Ecosystem

[FLAP](https://github.com/szaghi/FLAP): command Line Arguments Parser for poor people, by szaghi et al. A KISS pure Fortran Library for building powerful, easy-to-use, elegant command line interfaces

A [namelist](https://cyber.dabamos.de/programming/modernfortran/namelists.html) input file can also be considered.

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [October 7, 2021, 1:47am UTC](https://fortran-lang.discourse.group/t/defining-commandline-parameters/2017/5 "2021-10-07T01:47:52Z")

</div>

I strongly support using one of the many command line parsing libraries available, as mentioned. However, in your particular case a simple program would do exactly what you asked for except that with some compiler and shell combinations quoting a filename can require double-quoting. For example:

```fortran
program dummymain
implicit none
! define arguments and their default values
integer :: accmethod=2 ;namelist /args/ accmethod
integer :: massonly=1 ;namelist /args/ massonly
character(len=80) :: outfile='dummymain.lst' ;namelist /args/ outfile

character(len=256) :: input(3)=[character(len=256) :: '&args','','/']
character(len=256) :: message
integer :: i, ios
! read arguments from command line
do i=1,command_argument_count()
   call get_command_argument(i,input(2))
   read(input,nml=args,iostat=ios,iomsg=message)
   if(ios.ne.0)then
      write(*,*)'ERROR:'//trim(message)
      stop 2
   endif
enddo
write(*,nml=args)
end program dummymain

```

```nohighlight
dummymain accmethod=10

```

technically you need to pass quotes or apostrophes around a string value  
and shells often strip those characters from the command line values so  
to conform to standard NAMELIST usage you need to do something like

```nohighlight
dummymain outfile='"myfile.out"'

```

but most if not all compilers will work with an unquoted string as long  
as it does not contain spaces or special characters, so it is an  
extension but this will commonly work:

```nohighlight
dummymain outfile=file.txt

```

numbers work great, even arrays and user-defined types but special  
characters often need quoted to protect them from shell expansion.

Your request is unusual in that most requests are for something like ULS (Unix-Like Systems) syntax or MSWIndows DOS syntax:

```auto
dummymain --outfile 'myfile.out' --accmethod=10
dummymain /outfile myfile.out /accmethod 10

```

but you have asked for something very much like NAMELIST or bash or CDC NOS syntax (sans the commas).

Another method appropriate for bash/sh/fish and tcsh/csh users is to read environment variables and to call the program as part of an env(1) statement:

```bash
env outfile='file.txt' accmethod=20 dummymain

```

both methods work and are quite simple; but in the case of the environment variables you also have to convert the numeric values from strings to numerics; whereas with the first method using a NAMELIST group you do not.

PS;

Why I say this is “bash-like” is because it is, users just rarely use the built-in bash keyword-name syntax. If might surprise quite a few people that given the bash shell

```bash
#!/bin/bash
echo A is $A
echo B is $B

```

```bash
$ A=100 >out.txt B=200 ./a

```

is a completely standard way to run the script and place the output in the file “out.txt” with  
contents like so:

```auto
A is 100
B is 200

```

the world just rarely sees it used that way, and if you start your bash shell with the -k switch  
the script can be called as

```bash
a A=11 B=20

```

supporting exactly the syntax style in the original OP request. So it is VERY bash-like, but for some reason few users use bash that way.

---

<div class="post-metadata">

**Author:** ![garynewport](https://avatars.discourse-cdn.com/v4/letter/g/898d66/32.png) [@garynewport](https://fortran-lang.discourse.group/u/garynewport)\
**Post date:** [October 11, 2021, 1:51pm UTC](https://fortran-lang.discourse.group/t/defining-commandline-parameters/2017/6 "2021-10-11T13:51:04Z")

</div>

I hadn’t replied to this as of yet because I am still piecing this all together. However, I just HAD to say a HUGE thank you!  
Though the libraries seem like such a nice idea, if ever possible I do like to code it myself and love the idea of the NAMELIST concept. My example did, indeed, give a BASH feel but I am not wedded to this. So, I am going to explore your solution a little more; before then considering my options in relation to using a library. The number of people likely to use my code when finished is low (currently 2, and I am one of them! Hahahaha!), so I’m quite free on implementation (especially since I am only doing this to simplify execution and it is not an essential part of the project).

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [October 11, 2021, 2:31pm UTC](https://fortran-lang.discourse.group/t/defining-commandline-parameters/2017/7 "2021-10-11T14:31:08Z")

</div>

Just what I use NAMELIST from the command line for. It is great for numbers including arrays and it is then trivial to read options from a config file (the more typical use of NAMELIST) by just having a filename option on the command line as well. No type conversions are needed and to add a new parameter you just add it to the namelist. So it is a handy way to go.

Now if Fortran just had an extension to allow a NAMELIST to have other syntax like “unix-style” and "dos-styl it would be one of the few languages with built-in command line parsing out of the box.

I have added an option in my own routines to “requote” a name so it is more portable when a string. It works as-is with numeric values but if you want to add something like

```nohighlight
mytitle="this is the plot of the stuff"

```

most shells turn that into this by the time your program sees it

```nohighlight
mytitle=this is the plot of the stuff

```

unless you double-quote the string on the command line. To avoid that you need to make  
a little function that changes the first = to =" and adds a " at the end, and turns a " into “” and then this works very nicely with strings too.

So for anyone looking at this later, it is also a good way to experiment with NAMELIST. Do  
you know what the output will be if you call the following program with

```nohighlight
   dummymain title=' this is my title ' arr='4*10' arr=,,3

```

and that allocatable variables (if allocated at the time of reading) work with NAMELIST, and …?

```fortran
program dummymain
implicit none
! define arguments and their default values
integer :: accmethod=2 ; namelist /args/ accmethod
integer :: massonly=1 ; namelist /args/ massonly
character(len=:),allocatable :: outfile ; namelist /args/ outfile
character(len=:),allocatable :: title ; namelist /args/ title  
real,allocatable :: arr(:) ; namelist /args/ arr
character(len=256) :: input(3)=[character(len=256) :: '&args','','/']
character(len=256) :: message1, message2
integer :: i, ios, equal_pos
! allocate allocatable variables
outfile='input.txt'//repeat(' ',1024)
title=repeat(' ',1024)
arr=[(huge(1.0),i=1,4)]
! read arguments from command line
do i=1,command_argument_count()
   call get_command_argument(i,input(2))
   read(input,nml=args,iostat=ios,iomsg=message1)
   ! assume first failure might be because of missing quotes
   if(ios.ne.0)then
      equal_pos=index(input(2),'=')
      if(equal_pos.ne.0)then
         ! requote and try again
         input(2)=input(2)(:equal_pos)//'"'//input(2)(equal_pos+1:len_trim(input(2)))//'"'
         read(input,nml=args,iostat=ios,iomsg=message2)
         if(ios.ne.0)then
            write(*,*)'ERROR UNQUOTED:'//trim(message1)//': when reading '//trim(input(2))
            write(*,*)'ERROR QUOTED :'//trim(message2)//': when reading '//trim(input(2))
            stop 2
         endif
      else
         write(*,*)'ERROR:'//trim(message1)//': when reading '//trim(input(2))
         stop 4
      endif
   endif
enddo
outfile=trim(outfile)
title=trim(title)
write(*,nml=args,delim='quote')
end program dummymain

```
