I need to parse a file that contains C-like #DEFINE statements, but I don't think I can use something like C::Scan because the file I'm parsing is not actually in C (plus any module I use has to be in the standard Perl distribution). My problem arises when many of the #DEFINEs include things that were previously defined. Here is an example of what my file might look like:
------------------
#DEFINE <PATH> /path/to/something
#DEFINE <VERSION> v12<REV>
#DEFINE <REV> 3
#DEFINE <FILE> <PATH>/foo_<VERSION>.txt
------------------
Suppose I want to know what the parameter "FILE" is; parseDefines("definefile.txt", "FILE") should return "/path/to/something/foo_v123.txt"
Here is the code I have so far:
sub parseDefines {
my ($filename, $option);
open(FILE, $filename) or die "Couldn't open file $filename";
my %defines;
while(<FILE>) {
chomp;
if (/^\#DEFINE/) {
/^\#DEFINE\s+<(\w+)>\s+(.*$)/;
# I think its ok to use .* because I really
# want to match EVERYTHING to the end of line
# (yes, I did read Ovid's "Death to Dot Star" :)
$defines{$1} = $2;
}
}
for (sort keys %defines) {
$defines{$_} =~ s/<(\w+)>/$defines{$1}/g;
print $defines{$_} . "\t=>\t" . $defines{$1} . "\n";
}
close FILE;
return $defines{$option};
}
My concern is that this doesn't check to make sure every single DEFINE is evaluated all the way up. Since I did a "sort keys", everything gets evaluated in alphabetical order, so FILE will turn out to put "/path/to/something/foo_v12<REV>.txt" (since VERSION wasn't evaluated before it got put into FILE).
I can wrap another for(0..10) around the existing for loop to make sure it just goes through and evaluated everything a bunch of times, but these are large files and I'm thinking there is a better, neater way to do things.
Any ideas?