[comp.lang.perl] Novice Perl Programming Question

glewis@fws204.pcocd2.intel.com (Glenn M. Lewis ~) (01/24/91)

[]
	I have decided that it would be a good idea for me to Perl.  So
I figured, "What better way than by writing a Perl program?"  Now I have
a few questions that maybe you could help me with.

	I want this program to read an input file, strip off all C-style
comments and TeX-style comments ('%...'), process any directives like
'#include "file"' and "#define a b", do any necessary search and replace
from previous "#define"s, and then check if the current line's first
word is the name of an executable file in my environment's $path.  If it
is, execute it and pipe its output recursively through this Perl filter.
If the word is not an executable in my $path, then simply echo the line
to the STDOUT.
	Simple, right?  Well, I seem to have things working pretty well
except for the piping mechanism (and the restriction that C-style
comments can not be nested and must appear on a single line...  *and*
the search of the executable only takes place in the current directory).
	Since this is my very first program, I would appreciate it if
you critique my Perl programming techniques.  Is this terribly
inefficient?   Is it ugly?  Is there a much easier way to do this?  It
would also be nice if you could help me make it work as described above.
	Thank you very much for your help!  I doubt this is of general
interest, so e-mail responses would be fantastic.

							-- Glenn Lewis

glewis%pcocd2.intel.com@Relay.CS.Net | These are my own opinions... not Intel's


#!/usr/local/mcfg/bin/perl
# $Id: pipe,v 1.3 1991/01/24 06:36:27 glewis Exp glewis $
# $Log: pipe,v $
# Revision 1.3  1991/01/24  06:36:27  glewis
# Right before messing around with cterm...
#
# Revision 1.2  1991/01/24  01:00:57  glewis
# Made main block into a subroutine
#
# Revision 1.1  1991/01/24  00:55:56  glewis
# Initial revision
#
$| = 1;     # Flush output automatically
if ($#ARGV<0 && -t) { die "No files to be processed"; }
# print(STDERR "Processing $ARGV...\n");
#
sub process_line {
    s/[ \t\n]*$//;                          # Remove trailing white space
    s/^[ \t]*//;                            # Remove leading white space
    s@[ \t]*/\*.*\*/@@;                     # Remove C-style comments
    s/[ \t]*%.*$//;                         # Remove '%'-style comments
    s/\t/ /g;                               # Change all '\t' to ' '
    # Process directives...
    if (/#/) {
        if (/#include/) {
            s/^.*#include *//;              # Remove directive
            s/;$//;                         # Strip trailing semicolon
            s/"//g;                         # Remove quotes
            if (! -T) {
                print(STDERR "  Can't open $_ for input\n");
            } else {
                print(STDERR "  Processing: $_\n");
                open(FILE, $_);
                while (<FILE>) {
                    &process_line;
                }
                close(FILE);
            }
            next;
        }
        if (/#define/) {                    # Save definitions
            s/^.*#define *//;               # Remove directive
            split;                          # Separate components
            $name = $_[0];                  # Definition name
            s/$name *//;                    # Remove name
            $definition{$name} = $_;
            print(STDERR "  Equating '$name' = '$definition{$name}'\n");
            next;
        }
    }
    # Process through list of "#define"s...
    while (($key,$value) = each %definition) { s/$key/$value/g; }
    # Finally, take a look at the resulting string...
    $num = split;
    next if (!$num);                        # Skip blank line
#   print(STDERR "$num items: '$_'\n");
    if (-x $_[0]) {
        print(STDERR "  Processing: $_\n");

    pipe(PROGIN,PERLOUT) || die "pipe can\'t create pipe PROGIN/PERLOUT" ; 
    pipe(PERLIN,PROGOUT) || die "pipe can\'t create pipe PERLIN/PROGOUT" ; 

    $pipePid = fork ;
    $command = $_;
    $fileno_in  = fileno(PROGIN);
    $fileno_out = fileno(PROGOUT);

    if ( $pipePid == 0 )
      { close(PERLIN)  || die "pipe can\'t close PERLIN" ;
        close(PERLOUT) || die "pipe can\'t close PERLOUT" ;
        exec("$command <&$fileno_in >&$fileno_out") ;
        die "pipe can\'t exec $command" ;
      }
    else
      { close(PROGIN)  || die "pipe can\'t close PROGIN" ;
        close(PROGOUT) || die "pipe can\'t close PROGOUT" ;
        open(SAVESTDIN, "<&STDIN")  || die 'pipe can\'t save STDIN' ;
        open(SAVESTDOUT,">&STDOUT") || die 'pipe can\'t save STDOUT' ;
        open(STDIN, "<&PERLIN")     || die 'pipe can\'t redirect STDIN' ;
        open(STDOUT,">&PERLOUT")    || die 'pipe can\'t redirect STDOUT' ;
        $prePipeSelect = select(STDOUT);
        $| = 0;
      }

        while (<PERLIN>) {
            &process_line;
        }

    close(PERLOUT) ;
    sleep 1 ;
    close(PERLIN) ;
    open(STDIN, "<&SAVESTDIN")  || die 'pipe can\'t reredirect STDIN' ;
    open(STDOUT,">&SAVESTDOUT") || die 'pipe can\'t reredirect STDOUT' ;
    close(SAVESTDIN) ;
    close(SAVESTDOUT) ;
    select($prePipeSelect);
    $| = 1;

    } else {
        print("$_\n");
    }
}
#
# End of process_line subroutine
#
while (<>) {
    &process_line;
}
exit(0);


--
glewis%pcocd2.intel.com@Relay.CS.Net | These are my own opinions... not Intel's

glewis@fws204.intel.com (Glenn M. Lewis ~) (01/25/91)

[]
	I am very sorry for the wasted bandwidth, by the "From:" line in
my previous posting was wrong, hence any replies would bounce.  You can
send mail to me at "glewis@pcocd2.intel.com" or
"glewis%pcocd2.intel.com@uunet.uu.net".
	Also, the first line said "...a good idea for me to Perl".  I
meant to say "...a good idea for me to LEARN Perl."  Ooops.
	Thanks again for any help you can provide.

							-- Glenn Lewis
--
glewis%pcocd2.intel.com@Relay.CS.Net | These are my own opinions... not Intel's