This version is dependent upon Fortran 2008 features and other GPF (General Purpose Fortran) modules. See the simpler Fortran 2003 and FORTRAN 77 versions if you are looking for older stable versions that do not require other CLI (Command Line Interface) modules from the GPF collection.
To get a demonstration program and the source for the M_kracken module download the source files for the module, other modules it is dependent on, and many example programs that call KRACKEN(3f).
M_kracken(3fm) - [ARGUMENTS:M_kracken] parse command line options of Fortran programs using Unix-like syntax (LICENSE:PD)
KRACKEN(3f) is a Fortran command line argument parser designed to provide for easy entry of lists of negative numbers, strings, and exponential numbers without generally requiring quotes on the command line. It provides:
You can call your command like this:
mycode -r 333.333 -file /home/testin -l -i 300
with very little code:
program myprogram use M_kracken character(255) filename logical lval ! define command arguments, default values and crack command line call kracken('cmd','-i 10 -r 10e3 -d 4.1123344d0 -l .false. -file input') ! get values call retrev('cmd_f',filename,iflen,ier) ! get -f FILENAME lval = lget('cmd_l') ! get -l present? rval = rget('cmd_r') ! get -r RVAL dval = dget('cmd_d') ! get -d DBLEVAL ival = iget('cmd_i') ! get -i IVAL ! all done parsing; do something with the values print *, "filename=",filename(:iflen) print *, " i=",ival, " r=",rval, " l=",lval, "d=",dval end program myprogram
See the documentation for the procedures for detailed descriptions. Each procedure description includes a working example program.
The returned strings obtained by calls to RETREV(3f) can be converted to numeric values using procedures from the M_strings(3fm) module such as STRING_TO_VALUE(3F), which converts strings to a numeric value, and SPLIT(3F), which can break a string into a list of words. But more commonly, the following convenience routines are used ...
There are scalar convenience functions for getting simple values that are used in most cases as an alternative to RETREV(3f) that convert the values directly to common scalar types:
lval=lget(VERB_ARGNAME) !gets a "logical" value. rval=rget(VERB_ARGNAME) !gets a "real" value. dval=dget(VERB_ARGNAME) !gets a "doubleprecision" value. ival=iget(VERB_ARGNAME) !gets a "integer" value sval=sget(VERB_ARGNAME) !gets a "character" value
There are also convenience routines for returning arrays of scalar values that typically use allocatable arrays. Just add 's' to the end of the scalar convenience functions.
lvals=lgets(VERB_ARGNAME) !gets a "logical" array. rvals=rgets(VERB_ARGNAME) !gets a "real" array. dvals=dgets(VERB_ARGNAME) !gets a "doubleprecision" array. ivals=igets(VERB_ARGNAME) !gets a "integer" array svals=sgets(VERB_ARGNAME) !gets a "character" array
public :: setprompts ! define prompts for commands in interactive mode
dissect ! for user-defined commands: define defaults, then process user input parse ! parse user command and store tokens into Language Dictionary store ! replace dictionary name's value (if allow=add add name if necessary) show ! display dictionary contents for information
NOTE: many parameters may be reduced in size so as to just accommodate being used as a command line parser. In particular, some might want to change:
logical,public :: stop_command=.false. ! indication to return stop_command as false in interactive mode integer, parameter,public :: IPvalue=4096*16 ! length of keyword value integer, parameter,public :: IPverb=20 ! length of verb character(len=1),save,public :: kracken_comment='#' character(len=:),allocatable,public :: leftover ! remaining command(s) on line integer,public,save :: current_command_length=0 ! length of options for current command
The menu mode feature is in a state of flux and may change significantly ...
All commands automatically have the parameter "-?". If it is present, a menu appears after any specified options have been applied that allows for changing parameters interactively.
The default prompts are the keywords themselves and their current values. To set your own prompts call SETPROMPTS(3f):
call setprompts(verb_name,options_and_prompts)
where the special prompt string "#N#" means to not allow prompting for this parameter. For example:
! set prompts for interactive mode ... call setprompts('copy',' & & -oo "#N#" & & -i Enter input file name & & -o Enter output file name & & -version "#N#" & & -help "#N#" & & ') call kracken('copy','-i -o -version .false. -help .false')
Then the command
copy -?would only prompt for the -i and -o parameters.
A description on how to use the menu mode can be generated by entering a question mark ("?") at the prompt once menu mode has been invoked.
Everything before any switch is always referred to as 'VERB_oo' in RETREV(3f). This same value can also be set later in the command line by using the reserved keyword -oo (or the alias --). Often, you can ignore it exists, but the -oo option is always there. Unlike other parameters a default value is ignored unless no parameters are specified on the command line. That is, in general do not set a default value for the -oo parameter. It should almost always be initially a blank string.
Note that you can just put the calls to RETREV() or the convenience routines where you need the information in your program instead of parsing everything in a single routine. But parsing them and storing them into a COMMON or MODULE is more efficient if the routine doing the parsing is called many times.
Sample showing -oo parameter and retrieving data in subroutines program demo_M_kracken use M_kracken, only : kracken implicit none real :: x, y ! define and crack command line arguments call kracken('cmd',' DEFAULT STRING -x 123 -y 456 ') call showstring() call showvalue() contains subroutine showstring() use M_kracken, only : sget character(len=:),allocatable :: string ! get value of string before any switch string=trim(sget('cmd_oo')) write(*,*)'string is ',string end subroutine showstring subroutine showvalue() use M_kracken, only : rget ! show values for -x and -y parameters x=rget('cmd_x') y=rget('cmd_y') write(*,*)' X and Y are ',x,y end subroutine showvalue end program demo_M_kracken xxx string is DEFAULT STRING X and Y are 123.000000 456.000000 xxx -x 987.653992 string is X and Y are 987.653992 456.000000 xxx -oo BBBB -oo CCCC string is BBBB CCCC X and Y are 123.000000 456.000000 xxx AAAA BBBB -oo CCCC string is AAAA BBBB CCCC X and Y are 123.000000 456.000000
You may note that the parsing rules are not identical to Unix, although very similar.
SYNTAX: verb[-oo|--] value for kw_oo [-kw1 value_for_kw1] [-kw2 value_for_kw2] [-kw3 value_for_kw3] ... where "kw" stands for a keyword name
cmd -title This is my title -value 10.3e2would produce a value of "This is my title" for dictionary value "cmd_title". This does mean if your value contains " -letter" you must quote your command such that the program sees the string surrounded with double-quotes. Depending on the shell you are using this can be awkward. For example, in the bash shell you might use
cmd -title '"-A is a bad title to need"' cmd -title /"-A is a bad title to need/"
cmd * -value 10.3e2Many (but not all) Unix commands have such values allowed wherever another value is not allowed (Surprised? "ls -r * -l" works as well as "ls -r -l *" .). This is why quoting and specification of which keywords require values and which do not is usually required on Unix commands. Alternatively, just ignore the -oo field and always require keywords for all values.
cmd -string \"\"to give the "cmd_string" dictionary value the simple value '"'.
cmd -D 10 -D 20 -D 30would set the dictionary variable "cmd_D" to '10 20 30'.
If you actually prefer quoting your arguments and having your unnamed variables at the end of your command and support for the "--" option supported by some GNU and Unix commands you can set the command line parsing option "style='args'". This will not change how you specify the parameters to the kracken(3f) command except possibly for Boolean switches, but allows for entering commands in a manner more like the C routine getopts(3c). If you turn the mode on the "-oo" parameter is ignored unless you specifically assign it a value by name; the values need quoted if they contain spaces and the option "--" specifies that the rest of the command line is composed of unnamed strings. The unnamed values will go into the CHARACTER array "unnamed". The way the command line input is parsed is the same as in the M_args(3f) module. That means instead of entering:
Add "style='args'" to the kracken call and "unnamed" from the M_kracken(3fm) module, and the unnamed values will be in the string array "unnamed" instead of obtained from something like "sgets('cmd_oo').
With "style='args' other differences are in how you specify your command prototype. You MUST use the string ".false." for any boolean switch variable default value; and basically the values ".true." and ".false." are reserved, regardless of case. This is normally how you specify booleans anyway; but in the default style you can set your default to ".true." or use other values for ".false." like "F" or ".F.".
The way the arguments will then be read upon input are the same as described in the M_args(3fm) module.
Sample usage: # first program uses default M_kracken parsing cmd *.f90 -x 100 --title A new title -y 200 # or cmd -x 100 --title A new title -y 200 -oo *.f90 # second program uses alternate command-line parsing. # the unnamed values go into the string array # UNNAMED but can appear anywhere on the command. # multi-word values require being quoted. cmd -x 100 -y 200 --title 'A new title' *.f90
Contributors:
- John S. Urban -- Author (last change: Oct. 2019)
- Felix Becker -- Enhancements to reduce limitations on parameter lengths (2013-05-28)
- Walid Keyrouz -- Upgrades to bring code into conformance with recommended practices (2013-12-06)