CmUtils::IpFileFix

The CmUtils::IpFileFix package provides a simple mechanism for writing scripts to update CMISS ipfiles.

VERSION

0.3 (18 June 2002)

CHANGES

0.3

GBS: Now gives sensible error message if run not using perl >= 5.6.0

0.2

GBS: Added documentation.

GBS: Made pattern-checking optional for add_before and add_after, and removed it from the replace.

Script files

The current set of scripts (in $CMISS_ROOT/cmiss_utils/filefixes/20010215/) have been rewritten to use this module, and subsequent fixes are most easily copied from these files.

Each script should be named according to the files to be changed (e.g. fixipopti.pl) because the list of files to be changed is automatically generated from the script name. The file suffix is determined by the letters between "fixip" and the next "." or "_", allowing multiple scripts for one file type by including a description that starts with an underscore following the filetype (e.g. fixipopti_10dec99.pl).

Loading the module

The following header should be used to load the module.

  #!/usr/local/bin/perl -w
  use strict;
  use CmUtils::IpFileFix qw(fixfiles);

The standard interface is through the fixfiles() routine. See below in the /EXPERTS section for lower-level interaction.

fixfiles()

This routine takes one named argument called filter which should specify a code reference containing the commands required to "fix" each ipfile. This is most easily defined as an anonymous subroutine. The subroutine is called with one argument, which is a pointer to the file being processed.

  fixfiles(
    filter => sub {
      my $file = shift;
      ...
    }
  );

Earlier scripts processed the file line-by-line, but this led to confusion and inefficiencies. The fixfiles routine reads the entire file before calling the subroutine defined by filter for processing.

Modification functions

One or more file modification functions describe the actions to take to update the ipfiles, and are specified in the filter subroutine in the region ... above.

All functions have a named interface, which means that the arguments may occur in any order. Arguments are typically given as strings, although regular expressions may be used for greater flexibility. In all cases where answers will be included in the match, regular expressions should be used, as they allow for various answers/formats/spaces. Arguments given as strings will be quoted in any pattern matches that are done, and are therefore treated as literals.

Because the file is read into a single multi-line variable, if you want to tie your regular expression to the start/end of any line, you will need to use the multi-line (?m) option:

  qr/(?m)^  Enter/

otherwise ^ and $ will only match the start and end of the file.

Alternatively, if you wish to treat the file as one single line (for matching across more than one line), use the single-line (?s) option:

  qr/(?s)this.*that/

in which case the . will also match newlines. The \n character may always be used to specify a known newline.

add_before()

  $file->add_before(target => "", insert => "" [, unless => ""]);

Adds a string insert before another string/regexp target. Most often, a third string unless needs to be checked so that the addition is not applied several times.

  $file->add_before(
    target => " USE_MINOS     (0 or 1)",
    insert => " USE_MAPS      (0 or 1)[1]: 0\n",
    unless => " USE_MAPS      (0 or 1)"
  );
  $file->add_before(
    target => qr/(?m)^ USE_MINOS/,
    insert => " USE_MAPS      (0 or 1)[1]: 0\n",
    unless => qr/USE_MAPS/
  );
unless
String/regexp to test for. The string insertion is made unless this matches.
target
String/regexp before which the new string is inserted. As always, a string is treated as a literal.
insert

New string to be inserted. Makes no sense for this to be a regexp. Multi-line strings are most easily defined using <<.

  $file->add_before(
    target => " Do you want to use parallel element stiffness computations",
    insert => <<EOF,
 Specify the convergence criteria [1]:
   (1) Ratio of unconstrained to constrained residuals
   (2) Ratio of unconstrained residuals to maximum Gauss point value
    1
EOF
    unless => "Specify the convergence criteria"
  );

add_after()

  $file->add_after(target => "", insert => "" [, unless => ""]);

Adds a string insert after another string/regexp target, unless a third string unless is matched. As for add_before.

match()

Returns the result of attempting to match a given pattern in the file. Most often, a regular expression should be used, so that varying formatting will give correct answers. Results may be captured (using ()) for later use if necessary.

  my ($nodenum) = $file->match(pattern => qr/number of nodes:\s*(\d+)/);
  
  my @values = $file->match(
    pattern => qr/values for C2.*:\s*([\d.]+)\s+([\d.]+)\s+([\d.]+)/
  );
  my @values = map {split} $file->match(pattern => qr/for C2.*:(.*)\n/);

If the argument is a string, it will do a literal string match:

  if ( $file->match(pattern => "number of nodes:\n") ) {
    ...
  }

delete()

Deletes the first occurence of the given string from the file.

  $file->delete(string => " (default 1)");
  $file->delete(string => qr/(?m)^ Enter the step limit.*$/);

Global deletion (if ever needed) could be accomplished with:

  my $pattern = "something";
  while ($file->match(pattern => $pattern)) {
    $file->delete(string => $pattern);
  }

replace()

Replaces one given string or regexp with another string.

  $file->replace(target => "nubmer", replace => "number");
target
String/regexp searched for in the file. As always, a string is treated as a literal.
replace
Replacement string. Makes no sense for this to be a regexp.

EXPERTS

The variable holding the file is actually a blessed hash, with a single entry {text} containing the entire file as a single string. Any manipulations that cannot be done with the provided routines may be performed directly on the $file->{text} entry e.g.

  $file->{text} =~ tr[A-Z][a-z];

Additionally, files may be read and written directly.

new

Creates a CmUtils::IpFileFix hash. An optional argument specifies the filename.

  $file = new CmUtils::IpFileFix;
  $file = new CmUtils::IpFileFix ("file.ippara");

read

Stores a file in the {text} entry of the file hash.

  $file->read($filename);

write

Writes the {text} entry in the file hash to an output file.

  $file->write("output.ipfile");