[PERCEPS] A useful (hopefully) input filter

David Farnham dfarnham@ligo.caltech.edu
Tue, 10 Aug 1999 09:49:46 -0700


Hello everyone,

I have written an input filter which searches through code for comments
of the form:

//!ppp: <some perl code>
//!ppp: <some more perl code>

It then runs the perl code on whatever code follows it (up to the next
!ppp: block or the end of the file).  The code which occurs after the
'ppp' statement is stored in a variable named 'block'.

***

For example, if I am using the namespace 'LFor' but I want to remove all
occurrences of 'LFor::' in a file for some reason, then I can put:

//!ppp: $block =~ s/LFor:://g;

at the beginning of the file.  More complicated sequences of Perl
commands can be used, and consecutive 'ppp' lines can be used to form a
larger sequence.

***

The 'ppp' stands for 'Perl Pre-Processor'.  The purpose of this was to
come up with a way to store perceps pre-processing information for a
file within the file itself.  So, if there was something that Perceps
choked on, I could write a simple Perl script to reformat the offending
code/comments and keep the script in the file with the code/comments.

I'm not a Perl programmer, so the input filter is probably pretty ugly
(A co-worker told me that it looked like I was trying to write Perl code
like I write C code, which pretty much sums it up).

I hope this helps someone!

***

sub filter {
  local($str)=@_;
  local($newstr,$block,$ppp,$readppp,$finishedppp);
  $readppp = 0;     # indicates whether we have read a ppp statement
yet.
  $finishedppp = 0; # true if we have finished reading a ppp statememt
  $ppp = "";        # the current ppp statement
  $block = "";      # the block which the current ppp will operate on
  $newstr = "";     # the stuff which has already been processed
  # Split up the file on newlines and cycle through each line
  foreach (split("\n",$str)) {
    # Check if the line is a ppp statement
    if(/^\/\/!ppp:\s*(.*)/) {
	  $readppp = 1; #Ok, we've read a ppp line
      if($finishedppp) {
		# This must be a new block. Process the last block.
		eval $ppp;                # run the perl command
		$newstr .= $block . "\n"; # add the result to the current result
		$block = "";              # clear the block to operator on
		$ppp = $1;                # assign the first line of the new perl cmd
		$finishedppp = 0;         # We're not yet finished loading the new cmd
	  }
	  else {
		# We're in the middle of loading a command
		$ppp .= $1 . "\n";
	  }
	}
    # OK, it's just part of a block
	else {
	  if(not $readppp) {
        # we haven't come across a ppp statement yet, just copy it
		$newstr .= $_ . "\n";
	  }
	  else {
		if(not $finishedppp) {
		  # This is the first line in a block.
		  $finishedppp = 1; # The ppp statement is now finished
		  $block = "";      # Clear the block
		}
		$block .= $_ . "\n"
	  }
	}
  }
  if($finishedppp) {
	# Finish up the last block
	eval $ppp;                # run the perl command
	$newstr .= $block . "\n"; # add the result to the current result
	$block = "";              # clear the block to operator on
  }
  return $newstr;
}

-- 
David Farnham <dfarnham@ligo.caltech.edu>
The LIGO Laboratory, MS 18-34
California Institute of Technology
Pasadena, CA 91125
Phone: (626)395-8517 Fax: (626)793-9744