BraWl
Loading...
Searching...
No Matches
command_line Module Reference

Data Types

type  cmd_arg
 type containing a key-value pair More...
 
interface  get_arg
 read arguments by name or number More...
 
type  str_wrapper
 wrapper to allow array of allocatable strings More...
 

Functions/Subroutines

subroutine parse_args ()
 Parse out command line args.
 
subroutine initial_parse
 helper function - do a parse if it hasn't been done yet
 
integer function, public arg_count ()
 get the number of arguments note: total count may not match command_argument_count due to parsing key=value syntax!
 
logical function get_arg_num_logical (num, val, exists)
 read by number for logical values
 
logical function get_arg_name_logical (name, val, exists)
 Read by name for logical values.
 
logical function get_arg_num_dbl (num, val, exists)
 read by number for double precision values
 
logical function get_arg_name_dbl (name, val, exists)
 read by name for double precision values
 
logical function get_arg_num_float (num, val, exists)
 Read by number for single precision (float) values.
 
logical function get_arg_name_float (name, val, exists)
 read by name for single precision (float) values
 
logical function get_arg_num_int (num, val, exists)
 read by number for integer values
 
logical function get_arg_name_int (name, val, exists)
 read by name for integer values
 
logical function get_arg_num_long (num, val, exists)
 read by number for long integer values
 
logical function get_arg_name_long (name, val, exists)
 read by name for long integer values
 
logical function get_arg_num_str (num, val, exists)
 read by number for string/character values
 
logical function get_arg_name_str (name, val, exists)
 read by name for string values
 
logical function, public arg_present (name, has_value)
 check presence of an argument by name
 
type(str_wrapper) function, dimension(:), allocatable, public dump_names ()
 get all the argument names (by copy) order will probably match input order, but this is not guaranteed
 
character(len=:) function, allocatable, public get_arg_value (name, exists)
 lookup an argument by name and return the value as an (allocatable) string if the name is not present, an empty string is returned
 

Variables

logical initial_parse_done = .false.
 
type(cmd_arg), dimension(:), allocatable, private all_args
 the argument list
 
integer, private num_args = 0
 the number of arguments
 
integer, parameter max_string_len = 200
 

Function/Subroutine Documentation

◆ arg_count()

integer function, public command_line::arg_count

get the number of arguments note: total count may not match command_argument_count due to parsing key=value syntax!

Definition at line 229 of file command_line.f90.

230 integer :: arg_count
231
232 call initial_parse
233 arg_count = num_args
Here is the call graph for this function:
Here is the caller graph for this function:

◆ arg_present()

logical function, public command_line::arg_present ( character(len=*), intent(in) name,
logical, intent(out), optional has_value )

check presence of an argument by name

Author
H. Ratcliffe
Date
2024
Parameters
nameargument name to look up
has_valuewhether this argument has a defined value (also .false. if not present)
Returns
true if present, false if not

Definition at line 727 of file command_line.f90.

728
729 logical :: found
730 character(len=*), intent(in) :: name
731 logical, intent(out), optional :: has_value
732 integer :: i
733
734 call initial_parse
735
736 found = .false.
737 if(present(has_value)) has_value = .false.
738 do i = 1, num_args
739 if(all_args(i)%name == trim(adjustl(name))) then
740 found = .true.
741 if(present(has_value)) has_value = all_args(i)%has_value
742 exit
743 endif
744 end do
745
Here is the call graph for this function:

◆ dump_names()

type(str_wrapper) function, dimension(:), allocatable, public command_line::dump_names

get all the argument names (by copy) order will probably match input order, but this is not guaranteed

Author
H. Ratcliffe
Date
2024
Returns
array of str_wrapper types containing all argument names

Definition at line 756 of file command_line.f90.

757 type(str_wrapper), dimension(:), allocatable :: dump_names
758 integer :: i
759
760 ! do this the long way again to support non implicit allocations
761 allocate(dump_names(num_args))
762 do i = 1, num_args
763 allocate(dump_names(i)%str, source =all_args(i)%name)
764 end do
765
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_arg_name_dbl()

logical function command_line::get_arg_name_dbl ( character(len=*), intent(in) name,
real(kind=real64), intent(inout) val,
logical, intent(out), optional exists )
private

read by name for double precision values

Author
H. Ratcliffe
Date
2024
Parameters
nameargument name to look up
valvalue to read into
existswhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 379 of file command_line.f90.

380
381 logical :: get_arg_name_dbl
382 character(len=*), intent(in) :: name
383 real(kind=real64), intent(inout) :: val
384 integer :: i
385 logical, intent(out), optional :: exists
386 logical :: found
387 integer :: ierr
388
389 call initial_parse
390
391 found = .false.
392 ! our cmd_arg type is already initialised to the sentinel
393 do i = 1, num_args
394 if(all_args(i)%name == trim(adjustl(name))) then
395 found = .true.
396 read(all_args(i)%value, *, iostat=ierr) val
397 exit
398 end if
399 end do
400
401 if(present(exists)) then
402 exists = found
403 end if
404
405 ! return value is whether value is found and correctly parsed
406 get_arg_name_dbl = (found .and. (ierr == 0))
407
Here is the caller graph for this function:

◆ get_arg_name_float()

logical function command_line::get_arg_name_float ( character(len=*), intent(in) name,
real(kind=real32), intent(inout) val,
logical, intent(out), optional exists )
private

read by name for single precision (float) values

Author
H. Ratcliffe
Date
2024
Parameters
nameargument name to look up
valvalue to read into
existswhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 453 of file command_line.f90.

454 logical :: get_arg_name_float
455 character(len=*), intent(in) :: name
456 real(kind=real32), intent(inout) :: val
457 real(kind=real64) :: tmp
458 logical, intent(out), optional :: exists
459
460 get_arg_name_float = get_arg_name_dbl(name, tmp, exists)
461 if( abs(tmp) < huge(val)) then
462 !value in range. convert. note: there may be precision loss
463 val = real(tmp, kind=real32)
464 else
465 !value out of range, can't be parsed
466 get_arg_name_float = .false.
467 end if
468
Here is the caller graph for this function:

◆ get_arg_name_int()

logical function command_line::get_arg_name_int ( character(len=*), intent(in) name,
integer(kind=int32), intent(inout) val,
logical, intent(out), optional exists )
private

read by name for integer values

Author
H. Ratcliffe
Date
2024
Parameters
nameargument name to look up
valvalue to read into
existswhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 521 of file command_line.f90.

522
523 logical :: get_arg_name_int
524 character(len=*), intent(in) :: name
525 integer(kind=int32), intent(inout) :: val
526 integer :: i
527 logical, intent(out), optional :: exists
528 logical :: found
529 integer :: ierr
530
531 call initial_parse
532
533 found = .false.
534 ! our cmd_arg type is already initialised to the sentinel
535 do i = 1, num_args
536 if(all_args(i)%name == trim(adjustl(name))) then
537 found = .true.
538 read(all_args(i)%value, *, iostat=ierr) val
539 exit
540 end if
541 end do
542
543 if(present(exists)) then
544 exists = found
545 end if
546
547 ! return value is whether value is found and correctly parsed
548 get_arg_name_int = (found .and. (ierr == 0))
549
Here is the caller graph for this function:

◆ get_arg_name_logical()

logical function command_line::get_arg_name_logical ( character(len=*), intent(in) name,
logical, intent(inout) val,
logical, intent(out), optional exists )
private

Read by name for logical values.

Note : a flag (name with no '=value' part) will parse as .true. if present, and .false. if not

Author
H. Ratcliffe
Date
2024
Parameters
nameArgument name to look up
valValue to read into
existsWhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 291 of file command_line.f90.

292
293 logical :: get_arg_name_logical
294 character(len=*), intent(in) :: name
295 logical, intent(inout) :: val
296 integer :: i
297 logical, intent(out), optional :: exists
298 logical :: found
299 integer :: ierr
300
301 call initial_parse
302
303 found = .false.
304 val = .false.
305 ierr = 0
306 ! our cmd_arg type is already initialised to the sentinel
307 do i = 1, num_args
308 if(all_args(i)%name == trim(adjustl(name))) then
309 found = .true.
310 if(all_args(i)%has_value) then
311 read(all_args(i)%value, *, iostat=ierr) val
312 else
313 val = .true.
314 end if
315 exit
316 end if
317 end do
318
319 if(present(exists)) then
320 exists = found
321 end if
322
323 ! return value is whether value is found and correctly parsed
324 get_arg_name_logical = (found .and. (ierr == 0))
325
Here is the caller graph for this function:

◆ get_arg_name_long()

logical function command_line::get_arg_name_long ( character(len=*), intent(in) name,
integer(kind=int64), intent(inout) val,
logical, intent(out), optional exists )
private

read by name for long integer values

Author
H. Ratcliffe
Date
2024
Parameters
nameargument name to look up
valvalue to read into
existswhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 601 of file command_line.f90.

602
603 logical :: get_arg_name_long
604 character(len=*), intent(in) :: name
605 integer(kind=int64), intent(inout) :: val
606 integer :: i
607 logical, intent(out), optional :: exists
608 logical :: found
609 integer :: ierr
610
611 call initial_parse
612
613 found = .false.
614 ! our cmd_arg type is already initialised to the sentinel
615 do i = 1, num_args
616 if(all_args(i)%name == trim(adjustl(name))) then
617 found = .true.
618 read(all_args(i)%value, *, iostat=ierr) val
619 exit
620 end if
621 end do
622
623 if(present(exists)) then
624 exists = found
625 end if
626
627 ! return value is whether value is found and correctly parsed
628 get_arg_name_long = (found .and. (ierr == 0))
629
Here is the caller graph for this function:

◆ get_arg_name_str()

logical function command_line::get_arg_name_str ( character(len=*), intent(in) name,
character(len=*), intent(inout) val,
logical, intent(out), optional exists )
private

read by name for string values

Note: if the string passed is shorter than the value, it will be truncated if the length is not known use get_arg_value to get an allocatable string

Author
H. Ratcliffe
Date
2024
Parameters
nameargument name to look up
valvalue to read into
existswhether the name was found - this is already contained in the return value, but is given for consistency with the other members
Returns
true if the name is found and parsed, false otherwise

Definition at line 686 of file command_line.f90.

687
688 logical :: get_arg_name_str
689 character(len=*), intent(in) :: name
690 character(len=*), intent(inout) :: val
691 integer :: i
692 logical, intent(out), optional :: exists
693 logical :: found
694
695 call initial_parse
696
697 found = .false.
698 do i = 1, num_args
699 if(all_args(i)%name == trim(adjustl(name))) then
700 found = .true.
701 val = all_args(i)%value
702 exit
703 end if
704 end do
705
706 if(present(exists)) then
707 exists = found
708 end if
709
710 ! return value is whether value is found and correctly parsed
711 get_arg_name_str = found
712
Here is the caller graph for this function:

◆ get_arg_num_dbl()

logical function command_line::get_arg_num_dbl ( integer, intent(in) num,
real(kind=real64), intent(inout) val,
logical, intent(out), optional exists )
private

read by number for double precision values

Author
H. Ratcliffe
Date
2024
Parameters
numargument number to read
valvalue to read into
existswhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 340 of file command_line.f90.

341
342 logical :: get_arg_num_dbl
343 integer, intent(in) :: num
344 real(kind=real64), intent(inout) :: val
345 logical, intent(out), optional :: exists
346 logical :: found
347 integer :: ierr
348
349 call initial_parse
350
351 found = .false.
352 ! check requested number is in range
353 if(num <= num_args .and. num > 0) then
354 ! read it from string into value
355 read(all_args(num)%value, *, iostat=ierr) val
356 found = .true.
357 end if
358
359 if(present(exists)) then
360 exists = found
361 end if
362
363 ! return value is whether value is found and correctly parsed
364 get_arg_num_dbl = (found .and. (ierr == 0))
365
Here is the caller graph for this function:

◆ get_arg_num_float()

logical function command_line::get_arg_num_float ( integer, intent(in) num,
real(kind=real32), intent(inout) val,
logical, intent(out), optional exists )
private

Read by number for single precision (float) values.

Author
H. Ratcliffe
Date
2024
Parameters
numargument number to read
valvalue to read into
existswhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 424 of file command_line.f90.

425 logical :: get_arg_num_float
426 integer, intent(in) :: num
427 real(kind=real32), intent(inout) :: val
428 real(kind=real64) :: tmp
429 logical, intent(out), optional :: exists
430
431 get_arg_num_float = get_arg_num_dbl(num, tmp, exists)
432 if( abs(tmp) < huge(val)) then
433 !value in range. convert. note: there may be precision loss
434 val = real(tmp, kind=real32)
435 else
436 !value out of range, can't be parsed
437 get_arg_num_float = .false.
438 end if
439
Here is the caller graph for this function:

◆ get_arg_num_int()

logical function command_line::get_arg_num_int ( integer, intent(in) num,
integer(kind=int32), intent(inout) val,
logical, intent(out), optional exists )
private

read by number for integer values

Author
H. Ratcliffe
Date
2024
Parameters
numargument number to read
valvalue to read into
existswhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 482 of file command_line.f90.

483
484 logical :: get_arg_num_int
485 integer, intent(in) :: num
486 integer(kind=int32), intent(inout) :: val
487 logical, intent(out), optional :: exists
488 logical :: found
489 integer :: ierr
490
491 call initial_parse
492
493 found = .false.
494 ! check requested number is in range
495 if(num <= num_args .and. num > 0) then
496 ! read it from string into value
497 ! we don't need to specify the format in general
498 read(all_args(num)%value, *, iostat=ierr) val
499 found = .true.
500 end if
501
502 if(present(exists)) then
503 exists = found
504 end if
505
506 ! return value is whether value is found and correctly parsed
507 get_arg_num_int = (found .and. (ierr == 0))
508
Here is the caller graph for this function:

◆ get_arg_num_logical()

logical function command_line::get_arg_num_logical ( integer, intent(in) num,
logical, intent(inout) val,
logical, intent(out), optional exists )
private

read by number for logical values

Author
H. Ratcliffe
Date
2024
Parameters
numargument number to read
valvalue to read into
existswhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 249 of file command_line.f90.

250
251 logical :: get_arg_num_logical
252 integer, intent(in) :: num
253 logical, intent(inout) :: val
254 logical, intent(out), optional :: exists
255 logical :: found
256 integer :: ierr
257
258 call initial_parse
259
260 found = .false.
261 ! check requested number is in range
262 if(num <= num_args .and. num > 0) then
263 ! read it from string into value
264 read(all_args(num)%value, *, iostat=ierr) val
265 found = .true.
266 end if
267
268 if(present(exists)) then
269 exists = found
270 end if
271
272 ! return value is whether value is found and correctly parsed
273 get_arg_num_logical = (found .and. (ierr == 0))
274
Here is the caller graph for this function:

◆ get_arg_num_long()

logical function command_line::get_arg_num_long ( integer, intent(in) num,
integer(kind=int64), intent(inout) val,
logical, intent(out), optional exists )
private

read by number for long integer values

Author
H. Ratcliffe
Date
2024
Parameters
numargument number to read
valvalue to read into
existswhether the name was found
Returns
true if the name is found and parsed, false otherwise

Definition at line 562 of file command_line.f90.

563
564 logical :: get_arg_num_long
565 integer, intent(in) :: num
566 integer(kind=int64), intent(inout) :: val
567 logical, intent(out), optional :: exists
568 logical :: found
569 integer :: ierr
570
571 call initial_parse
572
573 found = .false.
574 ! check requested number is in range
575 if(num <= num_args .and. num > 0) then
576 ! read it from string into value
577 ! we don't need to specify the format in general
578 read(all_args(num)%value, *, iostat=ierr) val
579 found = .true.
580 end if
581
582 if(present(exists)) then
583 exists = found
584 end if
585
586 ! return value is whether value is found and correctly parsed
587 get_arg_num_long = (found .and. (ierr == 0))
588
Here is the caller graph for this function:

◆ get_arg_num_str()

logical function command_line::get_arg_num_str ( integer, intent(in) num,
character(len=*), intent(inout) val,
logical, intent(out), optional exists )
private

read by number for string/character values

Author
H. Ratcliffe
Date
2024
Parameters
numargument number to read
valvalue to read into
existswhether the name was found - this is already contained in the return value, but is given for consistency with the other members
Returns
true if the name is found and parsed, false otherwise

Definition at line 643 of file command_line.f90.

644
645 logical :: get_arg_num_str
646 integer, intent(in) :: num
647 character(len=*), intent(inout) :: val
648 logical, intent(out), optional :: exists
649 logical :: found
650
651 call initial_parse
652
653 found = .false.
654 ! check requested number is in range
655 if(num <= num_args .and. num > 0) then
656 ! read it from string into value
657 ! we don't need to specify the format in general
658 val = all_args(num)%value
659 found = .true.
660 end if
661
662 if(present(exists)) then
663 exists = found
664 end if
665
666 ! return value is whether value is found and correctly parsed
667 get_arg_num_str = found
668
Here is the caller graph for this function:

◆ get_arg_value()

character(len=:) function, allocatable, public command_line::get_arg_value ( character(len=*), intent(in) name,
logical, intent(out), optional exists )

lookup an argument by name and return the value as an (allocatable) string if the name is not present, an empty string is returned

Author
H. Ratcliffe
Date
2024
Parameters
nameargument name to look up
existswhether the name was found
Returns
the string value associated with the given name

Definition at line 779 of file command_line.f90.

780
781 character(len=:), allocatable :: get_arg_value
782 character(len=*), intent(in) :: name
783 logical, intent(out), optional :: exists
784 integer :: i
785 logical :: found
786
787 call initial_parse
788
789 found = .false.
790
791 do i = 1, num_args
792 if(all_args(i)%name .eq. trim(adjustl(name))) then
793 allocate(get_arg_value, source=all_args(i)%value)
794 found = .true.
795 exit
796 end if
797 end do
798
799 ! return empty string, not unallocated one.
800 if(.not. allocated(get_arg_value)) allocate(character(len=0) :: get_arg_value)
801 if(present(exists)) then
802 exists = found
803 end if
804
Here is the call graph for this function:
Here is the caller graph for this function:

◆ initial_parse()

subroutine command_line::initial_parse
private

helper function - do a parse if it hasn't been done yet

Definition at line 217 of file command_line.f90.

218
219 if(.not. initial_parse_done) then
220 call parse_args
221 initial_parse_done = .true.
222 end if
223
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_args()

subroutine command_line::parse_args
private

Parse out command line args.

This function can be called multiple times and will freshly parse all arguments each time we assume these are entered as 'name=value'. If there is no '=' sign, we set an empty value

Author
H. Ratcliffe
Date
2024

Definition at line 101 of file command_line.f90.

102
103 ! strictly we can't be sure any max_string_len is enough
104 ! but for command-line args it's enough if we're sensible
105 ! we wont overflow, but our strings may get truncated
106 ! we'll print an warning, since this is probably unintended input
107
108 ! note: some codes have reason to disable implicit re-allocation so we
109 ! take the extra effort to allocate all our strings manually
110
111 integer :: i_arg, i_tok, indx
112 type(cmd_arg), dimension(:), allocatable :: all_args_tmp
113 character(len=max_string_len) :: arg, tmp, tmp_name, tmp_val
114 integer :: arg_in_length, tmp_len
115 logical :: truncated
116
117 truncated = .false.
118
119 num_args = command_argument_count()
120 if(num_args > 0) then
121
122 ! if this is not the first call, all_args may be already allocated
123 ! deallocate if needed, and allocate to sufficient size
124 ! will be trimmed to actual size after parsing
125 if(allocated(all_args)) deallocate(all_args)
126 allocate(all_args(num_args))
127
128 i_arg = 1 !index of current arg
129 i_tok = 1 ! index of current input token
130 ! loop over all arguments and extract
131 do while (i_tok <= num_args)
132 ! first extract name and value parts in all cases
133 ! this consumes 1, 2 or 3 tokens depending on spaces
134
135 call get_command_argument(i_tok, arg, length=arg_in_length)
136 i_tok = i_tok + 1
137
138 if(arg_in_length > max_string_len) truncated = .true.
139
140 ! location of the '=' sign
141 ! if not found, return value of this is 0
142 indx = index(arg, '=')
143
144 !look at next chars - remove all whitespace
145 tmp = adjustl(arg(indx+1:))
146 tmp_len = len_trim(tmp)
147 if(indx > 1 .and. tmp_len > 0) then
148 ! all characters after '='
149 tmp_val = tmp
150 ! all characters up to '=', not including it
151 ! but with any leading spaces removed
152 tmp_name = adjustl(arg(1:indx-1))
153 else if(indx > 1) then
154 ! have an '=' but no following value
155 ! consume next token
156 call get_command_argument(i_tok, tmp, length=arg_in_length)
157 i_tok = i_tok + 1
158 if(arg_in_length > max_string_len) truncated = .true.
159
160 tmp_val = adjustl(tmp)
161 tmp_name = adjustl(arg(1:indx-1))
162 else ! have not yet found the equals!
163 ! set name, then hunt value...
164 tmp_name = adjustl(arg)
165
166 !peek next token - will need either 0, 1 or 2 more
167 call get_command_argument(i_tok, tmp, length=arg_in_length)
168 if(arg_in_length > max_string_len) truncated = .true.
169
170 indx = index(adjustl(tmp), '=')
171 if(indx /= 1) then
172 ! next token does not lead with '=', assume this is a flag and
173 ! do not consume next. set value for clarity, and mark
174 tmp_val = ""
175 all_args(i_arg)%has_value = .false.
176 else
177 ! consume this one and possibly one more
178 i_tok = i_tok + 1
179 if(len_trim(adjustl(tmp)) > 1) then
180 !this token has content following the '='
181 tmp_val = adjustl(tmp(2:))
182 else
183 ! consume another
184 call get_command_argument(i_tok, tmp, length=arg_in_length)
185 i_tok = i_tok + 1
186 if(arg_in_length > max_string_len) truncated = .true.
187
188 tmp_val = adjustl(tmp)
189 end if
190 end if
191 end if
192
193 ! explicitly allocate and set the values
194 allocate(character(len=len_trim(tmp_name)) :: all_args(i_arg)%name)
195 all_args(i_arg)%name = trim(tmp_name)
196 allocate(character(len=len_trim(tmp_val)) :: all_args(i_arg)%value)
197 all_args(i_arg)%value = trim(tmp_val)
198
199 i_arg = i_arg + 1
200 end do
201 !i_arg is now the actual parsed count
202 !shrink array to get rid of excess unfilled space
203 num_args = i_arg-1
204 call move_alloc(all_args, all_args_tmp)
205 allocate(all_args(num_args))
206 all_args = all_args_tmp(1:num_args)
207 deallocate(all_args_tmp)
208 endif
209
210 if(truncated) print'(a,i0, a)', "warning: very long argument truncated. to support arguments&
211 & longer than ", max_string_len, " increase the max_string_len parameter"
212
213
Here is the caller graph for this function:

Variable Documentation

◆ all_args

type(cmd_arg), dimension(:), allocatable, private command_line::all_args
private

the argument list

Definition at line 83 of file command_line.f90.

83 type(cmd_arg), dimension(:), allocatable :: all_args

◆ initial_parse_done

logical command_line::initial_parse_done = .false.
private

Definition at line 41 of file command_line.f90.

41 logical :: initial_parse_done = .false.

◆ max_string_len

integer, parameter command_line::max_string_len = 200
private

Definition at line 86 of file command_line.f90.

86 integer, parameter :: max_string_len = 200

◆ num_args

integer, private command_line::num_args = 0
private

the number of arguments

Definition at line 85 of file command_line.f90.

85 integer :: num_args = 0