/ UCI ESS / Zender Group / SNG / [G95] [Gfortran]
SNG Homepage


Welcome to the SNG Homepage

A getopt_long()-like module for Fortran9X/2K

Current version is last updated on


What is SNG?

SNG is a portable fortran9X/2K command line parser and string manipulation library. SNG comprises subroutines for parsing GNU/POSIX-style long command-line options a la the GNU getopt_long() package. SNG is written in pure Fortran9X/200X so that your modern fortran codes can kick the namelist habit.
License:
The core library, sng_mdl.F90, has a free, non-restrictive, non-copyleft, GPL-compatible, X11-style license. The demo front end program, sng.F90, and a supporting utility, dbg_mdl.F90, which are both cleanly segregable from the core library, are in the public domain.


SNG News


Documentation

The nascent SNG documentation is a simple text format file:

Currently, the file describes the command line processing philosophy. The real documentation is the front-end program sng.F90 which demonstrates how to use most SNG features. Contributions of additional sections are most welcome. Instructions for compiling and testing sng are contained at the top of the sng.F90 driver program. They are short and simple so I repeat them here, with the example output from the demo program sng.F90:
zender@lanina:~/f$ pgf90 -o dbg_mdl.o -c dbg_mdl.F90
zender@lanina:~/f$ pgf90 -o sng_mdl.o -c sng_mdl.F90
zender@lanina:~/f$ pgf90 -o sng sng_mdl.o dbg_mdl.o sng.F90
zender@lanina:~/f$ sng --dbg=0 --dbl=1.234e234 --flt=-5.67e-37 --int=12345678 --lgc=T --sng="GNU's Not UNIX" --drc_out=${HOME}/output/directory
 Before command line parsing and string manipulation: 
 main() reports cmd_ln = 
 main() reports dbl_foo =    0.0000000000000000E+000
 main() reports flt_foo =    0.0000000E+00
 main() reports int_foo =             1
 main() reports lgc_foo =   F
 main() reports sng_foo = Default value
 main() reports fl_in = in.nc
 main() reports fl_out = foo.nc
 main() reports drc_in = /home/user/input/dir
 main() reports drc_out = 
 After command line parsing and string manipulation: 
 main() reports cmd_ln = 
 sng --dbg=0 --dbl=1.234e234 --flt=-5.67e-37 --int=12345678 --lgc=T --sng=GNU's Not UNIX --drc_out=/home/zender/output/directory
 main() reports dbl_foo =    1.2339999999999977E+234
 main() reports flt_foo =   -5.6700002E-37
 main() reports int_foo =      12345678
 main() reports lgc_foo =   T
 main() reports sng_foo = GNU's Not UNIX
 main() reports fl_in = /home/user/input/dir/in.nc
 main() reports fl_out = /home/zender/output/directory/foo.nc
 main() reports drc_in = /home/user/input/dir
 main() reports drc_out = /home/zender/output/directory
The Fortran variables have their type-specific default values until SNG and parses the command line options.

How much code overhead does it take to implement this getopt_long()-like capability in the front end program? Certainly not more than a namelist parsing routine! The above command line parser was implemented with

  arg_nbr=command_argument_count() ! [nbr] Number of command line arguments
  arg_idx=1 ! [idx] Counting index
  do while (arg_idx <= arg_nbr)
     call ftn_getarg_wrp(arg_idx,arg_val) ! [sbr] Call getarg, increment arg_idx
     dsh_key=arg_val(1:2) ! [sng] First two characters of option
     if (dsh_key == "--") then
        opt_lng=ftn_opt_lng_get(arg_val) ! [nbr] Length of option
        if (opt_lng <= 0) stop "Long option has no name"
        opt_sng=arg_val(3:2+opt_lng) ! [sng] Option string
        if (dbg_lvl >= dbg_io) write (6,"(5a,i3)") prg_nm(1:ftn_strlen(prg_nm)), &
             ": DEBUG Double hyphen indicates multi-character option: ", &
             "opt_sng = ",opt_sng(1:ftn_strlen(opt_sng)),", opt_lng = ",opt_lng
        if (opt_sng == "dbg" .or. opt_sng == "dbg_lvl" ) then
           call ftn_arg_get(arg_idx,arg_val,dbg_lvl) ! [enm] Debugging level
        else if (opt_sng == "dbl" .or. opt_sng == "dbl_foo" ) then
           call ftn_arg_get(arg_idx,arg_val,dbl_foo) ! [frc] Double
        else if (opt_sng == "drc_in") then
           call ftn_arg_get(arg_idx,arg_val,drc_in) ! [sng] Input directory
        else if (opt_sng == "drc_out") then
           call ftn_arg_get(arg_idx,arg_val,drc_out) ! [sng] Output directory
        else if (opt_sng == "fl_in") then
           call ftn_arg_get(arg_idx,arg_val,fl_in) ! [sng] Input file
        else if (opt_sng == "fl_out") then
           call ftn_arg_get(arg_idx,arg_val,fl_out) ! [sng] Output file
        else if (opt_sng == "flt" .or. opt_sng == "flt_foo" ) then
           call ftn_arg_get(arg_idx,arg_val,flt_foo) ! [frc] Float
        else if (opt_sng == "int" .or. opt_sng == "int_foo" ) then
           call ftn_arg_get(arg_idx,arg_val,int_foo) ! [nbr] Integer
        else if (opt_sng == "lgc" .or. opt_sng == "lgc_foo" ) then
           call ftn_arg_get(arg_idx,arg_val,lgc_foo) ! [lgc] Logical
        else if (opt_sng == "sng" .or. opt_sng == "sng_foo") then
           call ftn_arg_get(arg_idx,arg_val,sng_foo) ! [sng] String
        else ! Option not recognized
           arg_idx=arg_idx-1 ! [idx] Counting index
           call ftn_getarg_err(arg_idx,arg_val) ! [sbr] Error handler for getarg()
        endif ! endif option is recognized
        ! Jump to top of while loop
        cycle ! C, F77, and F90 use "continue", "goto", and "cycle"
     endif ! endif long option
     ! Handle short options
     if (dsh_key == "-D") then
        call ftn_arg_get(arg_idx,arg_val,dbg_lvl) ! [enm] Debugging level
     else if (dsh_key == "-f") then
        call ftn_arg_get(arg_idx,arg_val,flt_foo) ! [frc] Float
     else if (dsh_key == "-i") then
        call ftn_arg_get(arg_idx,arg_val,fl_in) ! [sng] Input file
     else if (dsh_key == "-l") then
        call ftn_arg_get(arg_idx,arg_val,int_foo)
     else if (dsh_key == "-p") then
        lgc_foo=.not.lgc_foo
     else if (dsh_key == "-o") then
        call ftn_arg_get(arg_idx,arg_val,fl_out) ! [sng] Output file
     else if (dsh_key == "-s") then
        call ftn_arg_get(arg_idx,arg_val,sng_foo) ! [sng] String
     else if (dsh_key == "-v") then
        goto 1000 ! Goto exit with error status
     else ! Option not recognized
        arg_idx=arg_idx-1 ! [idx] Counting index
        call ftn_getarg_err(arg_idx,arg_val) ! [sbr] Error handler for getarg()
     endif ! endif arg_val
  end do                    ! end while (arg_idx <= arg_nbr)
  ! Compute any quantities that might depend on command line input
  ! Prepend user-specified path, if any, to input data file names
  if (ftn_strlen(drc_in) > 0) call ftn_drcpfx(drc_in,fl_in) ! [sng] Input file
  ! Prepend user-specified path, if any, to output data file names
  if (ftn_strlen(drc_out) > 0) call ftn_drcpfx(drc_out,fl_out) ! [sng] Output file
which is admittedly overkill in that it includes comments, debugging code, and short option equivalents to certain long options. ftn_arg_get(), which is overloaded for all data types, implements the bulk of the work so SNG has the same interface for all data types.

Version Summary


Download SNG model source distribution.

The distribution includes the complete SNG source code necessary to build and run SNG on your own machine.

Subversion access to SNG will be set-up on request