loadfiles

Accession:44027
perl script reads load_file() statements in a hoc file to create a single hoc output file with loaded hoc code inserted in place of the load_file statements uses HOC_LIBRARY_PATH to locate files several options available -- call without args for help limitations: 1. does not read xopen() commands 2. does not process 2 arg load_file() command 3. cannot handle a load_file() embedded in an if {} or other other control structure (this requires logical parsing of the whole file as can only be done by hoc parser) -- will generate an error
Tool Information (Click on a link to find other Tools with that property)
Tool Type: File manipulation;
Simulation Environment: NEURON;
\
loadfile
README
loadfiles
                            
#!/usr/bin/perl
# $Id: loadfiles,v 1.41 2004/01/30 15:09:08 billl Exp $

$append=$quiet=$debug=$includeall=0;
$indent=$include_allowed=1;

# pick up flags
while ($_ = $ARGV[0],/^-/) {
  $flag=shift;
  if (substr($flag,0,2) eq "-q") { $quiet=1; }
  if (substr($flag,0,2) eq "-a") { $append=1; }
  if (substr($flag,0,2) eq "-o") { $out=shift; }
  if (substr($flag,0,2) eq "-n") { $indent=0; }
  if (substr($flag,0,2) eq "-i") { $includeall=1; }
}

$mainf = shift;
if (! $mainf or $mainf =~ /help/) {
  die qq|    
  ****************************************************************
                USAGE: loadfiles [args] FILE.hoc
  ****************************************************************
  Recursively and uniquely inserts contents of files referenced by load_file() statements
  Input filename should be of form FILE.hoc and output will be FILE_.hoc

  NB: reads HOC_LIBRARY_PATH from environment
      will not insert files in 'nrn/share/nrn/lib/hoc'

  Options (precede filename): 
    -q # quiet
    -a # append instead of creating new output file
    -o FNAME # output to FNAME
    -n # (noindent) don't indent lines for output file
    -i # (includeall) also insert files from stdrun path
|;}
if (! -f $mainf) { die "File $mainf not found.\n"; }

# create $out files of form filename_.hoc
if (! $out) { $out = $mainf; $out =~ s/(.+)\.(.+)/\1_.\2/; }
$sep = "//================================================================\n";

open(IN,$mainf) || die "Can't open $mainf.\n";
if ($append) {
  open(OUT,">> $out") || die "Can't open $out.\n";
} else {
  open(OUT,"> $out") || die "Can't open $out.\n";
}

$date = `date +"%D %T"`;  chop $date;
print OUT "// Created $date by $0\n";

# pick file search path out of env and prepend current directory
$stdrunpath = `which nrniv`; chop $stdrunpath;
if (-l $stdrunpath) { $stdrunpath = readlink($stdrunpath); }
$stdrunpath =~ s|[^/]+/bin/nrniv|share/nrn/lib/hoc|;
@hocpath=($stdrunpath,".",split("[: ]",$ENV{"HOC_LIBRARY_PATH"}));
$quiet or print STDERR "HOCPATH: @hocpath\n";

# regular expression to pick out load_file() commands
# possible terminal comma for use of load_file("filename", "name")
$lfrxp = q%^[{ ]*load_file\("([^"]+)"[\)]%;
$num=1; %files=%loaded=();

&load($mainf);
if (! $quiet) {
  print STDERR "LOADED: ";
  foreach $key (sort(keys %loaded)) { print STDERR "$key "; }
  print STDERR "\n";
  print STDERR "Output to $out\n";
}

sub load {
  local($file) = @_;  
  my $dfile,$line;
  local $brac=0;   # needs to be a local not a my somehow
  $debug and print STDERR "load called with $file\n";
  $files{$file}=$num++;  # number files as they are encountered
  if (-e $file) {
    $dfile=$file;
  } else { 
    foreach $dir (@hocpath) {	# look through path for this file
      $dfile=$dir."/".$file;
      if (-e $dfile) {
	last;		# found it
      }}}
  if (!$includeall && $dfile =~ $stdrunpath) {  # don't link the standard stuff
    print OUT qq|load_file("$file")\n|;
    return; 
  }
  $debug and print STDERR "Loading $dfile\n";
  $loaded{$file}=$num;  # loaded list may be fewer than files list
  print OUT "$sep// INSERTED $dfile\n";  # header in the output file
  open my $df,$dfile or die "Can't open $dfile\n";  # 'my $df' gives local filehandle
  while ($line=<$df>) {
    if ($line =~ /$lfrxp/) { # a load_file command
      if ($files{$1}) {           # file is already loaded
	$debug and print STDERR "$1 already loaded\n";
      } else {                    # recursive call to load this file
	if (! $include_allowed) { die "ERR2: load_file() not permitted: $dfile, line $.\n"; }
	if ($brac==1) { print OUT "}\n"; } # close it
	&load($1); 
	if ($brac==1) { print OUT "{\n"; } # open again
	# print STDERR "RETURNED to $file $df\n"
      }	
    } else {
      print OUT ($indent?" "x(2*$brac):"").$line;            # standard case: output line to file
      if (!$quiet && $line =~ /load_file/) { chop($line);
	print "\t$line left alone ($dfile, line $.).\n"; }
    }
    $brac+= ($inc=&csubstr($line,"{")); $brac -= &csubstr($line,"}"); 
    if ($brac<0) {       die "ERR1: brace count < 0 in $dfile, line $.\n"; 
    } elsif ($brac==0) { $include_allowed=1;
    } elsif ($brac> 1) { $include_allowed=0;
    } elsif ($inc ==1) { $include_allowed=$naked;  # OK if that bracket was naked
    }
  }
  print OUT "// END $dfile\n$sep";  # end of file marker
  close $df;
  return;
}

# csubstr(STRING,SUBSTR) returns number of occurrences
sub csubstr () {  
  my($a,$b) = @_;  
  $naked = ($line =~ /^{$/); # side effect with bare {
  @_ = ($a=~/$b/g); 
  return $#_+1; 
}