MC logo

Include Example

^  CSc 231 Perl Assignments

finclude.pl
use strict;

#
# This program implements file inclusion.  It obeys lines of the form
#   include filename
# and otherwise copies input to output.  It starts with a file name on the
# command line, if any, otherwise it uses standard input.
#

# File pointer.  (Technically, a reference to a file pointer.)
my $fp;

# Initialize file pointer.
if(@ARGV) {
    open($fp, $ARGV[0]) or die "Cannot open $ARGV[0]: $!\n";
} else {
    $fp = \*STDIN;
}

# Stack of file handles indicating the the chain back to the starting file.
# Does not include the current input.
my @stack = ();

# Repeat until done.  Notice that the outer while loop is labeled, and the
# the last statement refers to it.  This allows the last to exit both
# looping levels.
outer: while(1) {
    # Read a line.  If that fails, pop a file descriptor and try again.
    # If the pop fails, leave the outer loop.
    my $l;
    while(!($l = <$fp>)) {
        close $fp;
        $fp = pop @stack or last outer;
    }

    chomp $l;

    # Check for the include input line which we obey.
    if($l =~ /^\s*include\s+(.*?)\s*$/) {
        my $fn = $1;               # Get file name from pattern match.
        my $newfp;                 # New descriptor.
        if(open($newfp, $fn)) {    # Open the new descriptor.
            push @stack, $fp;      # Stack the previous descriptor.
            $fp = $newfp;          # Switch to new one.
        } else {
            print "$fn: $!\n";     # Open failed.  Print message.
        }
        next;                      # Succeed or fail, proceed to next line.
    }

    # Echo the input line.
    print "$l\n";
}