The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Fortran::F90Namelist - Parse F90 namelists into hash and export in different formats

SYNOPSIS

  use Fortran::F90Namelist;
  my $nl = Fortran::F90Namelist->new() or die "Couldn't get object\n";

  $nl->parse("&runpars\nx=2,y=3\nvec1=1,2,3\nvec2=3*1.3\n/");

  # Operate on each namelist in $text (only works with [mutable]
  # strings, not with files)
  my $text = "&spars\nx=2,y=3\n/\n&runpars\nvec1=1,2,3\nvec2=3*1.3\n/";
  while ($nl->parse($text)) {
      print $nl->name(), "\n";
  }

Dump in arbitrary order:

  use Data::Dumper;
  print "F90Namelist ", $nl->name(), " has ", $nl->nslots(), " slots:\n";
  print Dumper($nl->hash());

Retain original order:

  print "&",$nl->name(),"\n";
  my $nl_hash = $nl->hash();
  foreach my $var (@{$nl->slots()}) {
    print "  $var: ", Dumper($nl_hash->{$var});
  }
  print "/\n";

Read from file:

  # Read one namelist from file `one_list.nml'
  $nl->parse(file => 't/files/one_list.nml');

  # Read one namelist from file handle
  open(my $fh , "< t/files/one_list.nml") or die "Couldn't get file handle\n";
  $nl->parse(file => $fh);
  # or
  open(NAMELIST , "< t/files/one_list.nml") or die "Couldn't open file\n";
  $nl->parse(file => \*NAMELIST);

Read all namelists from file `start.in' and merge into one namelist called `nlist'

  $nl->parse(file     => 't/files/start.in',
             all      => 1,
             namelist => 'nlist');
  print "Merged namelist ", $nl->name, " contains:\n",
      join(",  ", @{$nl->slots}), "\n";

Merge two namelists

  my $nl2 = Fortran::F90Namelist->new() or die "Couldn't get object\n";
  $nl2->parse(file => 't/files/one_list.nml');
  $nl->merge($nl2,
             { dups_ok => 1 } );
  print $nl->name, " now has ", $nl->nslots, " slots\n";

Write namelist:

  # Write namelist in F90 namelist format
  print "F90 format:\n", $nl->output();

  # Write namelist as IDL structure
  print "IDL format:\n", $nl->output(format => 'idl', name => 'par2');

DESCRIPTION

Fortran::F90Namelist is a module for parsing Fortran90 namelists into hashs and re-exporting these hashs in different formats. Currently, the following data types are supported:

  • integer

  • float/double

  • complex numbers

  • strings [character(LEN=*)], possibly containing all sorts of quotation marks

  • logical

The following backends exist for re-exporting (or importing into other languages):

  • F90 namelist

  • IDL struct

This module is used with the Pencil Code (http://www.nordita.dk/software/pencil-code/) to import the values of all available input parameters into GDL/IDL or other visualization software.

Methods

$nl->new()

Create a new namelist object

$nl->parse(string)
$nl->parse(text => string)
$nl->parse(file =>(fname|FHANDLE))
$nl->parse(file => (fname|FHANDLE) [, options ])
$nl->parse(\%options)

Parse string or the file represented by fname or FHANDLE (a file handle), returns the name of the namelist parsed, or undef if parsing failed.

When reading from a mutable text string $text, the string is modified and contains everything following the namelist just parsed.

This allows while loops like

  while ($nl->parse($text)) {
      print $nl->name(), "\n";
  }

to work. This does however not work for files or immutable strings, so

  while ($nl->parse(file => "t/files/start.in")) {
      print $nl->name(), "\n";
  }

and

  while ($nl->parse("&nl1\nx=5.\n/\n&nl2\n/")) {
      print $nl->name(), "\n";
  }

will fail.

Generally speaking, Fortran::F90Namelist::Group is the more appropriate tool for handling several namelists in one file or string.

Additional options are:

merge

If true, merge data from namelist with any data that may already be stored in the object. See Fortran::F90Namelist::Group for a more flexible framework for dealing with groups of namelists.

all

If true, parse all namelists from string or file and merge them into one namelist object.

name

Set name of resulting namelist (default: name of first namelist read).

dups_ok

With merge, don't warn if new slots have same names, but different values as existing slots.

broken

Try to parse broken namelists as produced by ifc 7.x, where you can get something like

   COOLING_PROFILE='gaussian              ',COOLTYPE='Temp    
   'COOL= 0.0,CS2COOL= 0.0,RCOOL= 1.000000

if the closing quote for a string (`Temp ') would end up in column 81.

All options can be passed in a hash(-ref):

  my %options = ( file   => 't/files/one_list.nml',
                  name   => 'broken_nlist',
                  broken => 1 );
  $nl->parse(%options);
  $nl->parse(\%options);  # the same
$nl->merge($nl2 [, options])

Merge namelist object $nl2 into $nl.

Options are:

name

Set name of resulting namelist (default: name of $nl).

dups_ok

With merge, don't warn if new slots have same names, but different values as existing slots.

$nl->name()
$nl->name($newname)

Return or set name of namelist.

$nl->nslots()

Return number of slots in namelist

$nl->slots()

Return ref to list of variable (slot) names in original order

$nl->hash()

Return namelists as Perl hashref. See HASH FORMAT below for details of the hash format.

$nl->output([options])

Write namelist in given format.

Options are

format=format

Set the output format. Currently supported formats are `f90' (default), and `idl'.

name=name

Set the name of the namelist (default: $nl->name()).

trim

Trim all trailing whitespace from strings.

double

Write all floating point numbers as double precision numbers.

oneline

Print whole namelist in one line (if compatible with the output format).

maxslots=N

Print only N slots per line. Useful for programs like IDL that have restrictions on the length of lines read from a pipe, so oneline is dangerous.

HASH FORMAT

The hash method returns a hash reference of the following structure:

    { 'name of var1' => { 'value' => [ value1, value2, ..],
                          'type'  => numerical_type,
                          'stype' => "type string"
                        },
      'name of var2' => { 'value' => [ value1, value2, ..],
                          'type'  => numerical_type
                          'stype' => "type string"
                        },
      ...
    }

Here numerical_type is a number identifying each data type, while stype is a textual description of the given data type.

E.g.

    { 'xyz0' => { 'value' => [ 0., -3.141593, 0. ],
                  'type'  => 6,
                  'stype' => 'single precision float'
                },
      'nt'   => { 'value' => [ '1000' ],
                  'type'  => 4,
                  'stype' => 'integer'
                }
    }

Note: This is currently just the internal format used to represent namelists and can thus change in the future. In particular the type numbers should not considered to be stable between releases.

TO DO

  1. new(), parse(), output(), etc. should check for unknown args and complain, not silently ignore them as is currently the case.

  2. More output methods:

    • Octave/matlab , C structs, YAML, XML(?), ...

BUGS AND LIMITATIONS

  • No user-defined types (records) are supported, so if you have these LaTeX comment characters in your namelist data, you are out of luck.

AUTHOR

Wolfgang Dobler <Wolfgang.Dobler@kis.uni-freiburg.de>

LICENSE AND COPYRIGHT

Copyright (c) 2007, Wolfgang Dobler <Wolfgang.Dobler@kis.uni-freiburg.de>. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same conditions as Perl or under the GNU General Public License, version 2 or later.

DISCLAIMER OF WARRANTY

Use completely at your own risk.

SEE ALSO

Fortran::Namelist by Victor Marcello Santillan. That module has a more limited scope (reading a namelist group from file, inserting namelists, and writing the resulting group to another file [my interpretation]), but is way faster on large files.