Oops.
On Friday, May 28, 2004 "Ron D. Smith" said: > On Friday, May 28, 2004 [EMAIL PROTECTED] said: > > Hi, > > > > I have a not-so-important, cosmetic question. > > > > I'm trying to convert some weird Windows based build system > > to GNU Makefiles on Unix. The script at the bottom of this > > mail works for me, but I do appreciate any comments on that. > > > > My question is: first I've written this action which didn't work: > > > > export: path <skip: '[ \t]+'> path(?) { > > # ignore if a special keyword has been used as destination > > return 1 if $item[-1]->[0] =~ /^(IGNORE|MANUAL|SUPPORT)$/i; > > # rest of the action, pretty long > > } > > Which does not work because you subvert the rest of the "hidden" code put in > there for you by PR::D. > > > > > So I had to remove the "return 1" above and use this instead > > > > export: path <skip: '[ \t]+'> path(?) { > > # ignore if a special keyword has been used as destination > > if ($item[-1]->[0] =~ /^(IGNORE|MANUAL|SUPPORT)$/i) { > > 1; > > } else { > > # rest of the action, pretty long > > } > > > > which feels a bit awkward to me. Is there a nicer way? > > Only to set the value of the "$return" variable. > > Remember what is happening here, PR::D is *really* a compiler. It takes your > description and produces a full stand-alone code stream. Any action is > actually part of a whole subroutine that PR::D creates. To create the action > you have to stick within the semantics of the environment just as if you were > programming in 'C'. > > To show you what I mean, turn on $::RD_TRACE and then look at the code it > produces (called, oddly enough "RD_TRACE"). When you look for the code in > your action you will get a lot of "extra" stuff that you did not define. > This is being put there by the PR::D 'compiler' to make the resulting code > stream self consistent according to the internal structure of PR::D. > > Alternative plan 'B' is a look-ahead: > > > export: path <skip: '[ \t]+'> path(?) { > blah blah > } > > path /"[^"]*"/ | ...!sectionorkeyword /\S+/ > > sectionorkeyword: section | /^(IGNORE|MANUAL|SUPPORT)$/i > > Here export will fail because path fails, and path fails because it contains > your magic keyword. > > > For example try this: > use strict; use vars qw($parser $text %prj_exports %prj_testexports); use Data::Dumper; use Parse::RecDescent; use File::Spec; use File::Spec::Win32; use File::Spec::Unix; use Getopt::Std; # where to copy the exported files by default use constant DEFINCDIR => 'epoc32/include'; #$RD_WARN = 1; #$RD_HINT = 1; $RD_TRACE = 120; $parser = Parse::RecDescent->new(q( inffile: chunk(s) /^\Z/ chunk: prj_export | prj_testexport | <error> prj_export: /PRJ_EXPORTS\b/i export[\%::prj_exports](s?) prj_testexport: /PRJ_TESTEXPORTS\b/i export[\%::prj_testexports](s?) export: path <skip: '[ \t]+'> path(?) ...!sectionorkeyword { # ignore if a special keyword has been used as destination # reference to the %prj_exports or %prj_testexports my $href = $arg[0]; # the 1st "path" above is source the 2nd - destination. # split the both paths into drive (unused) + dir + filename my ($srcdrive, $srcdir, $srcfile) = File::Spec::Win32->splitpath($item[1]); my ($dstdrive, $dstdir, $dstfile) = File::Spec::Win32->splitpath($item[-1]->[0]); # replace backslashes through slashes in both dirs $srcdir =~ y|\\\\|/|; $dstdir =~ y|\\\\|/|; # the full paths, consisting of dir + filename my ($srcpath, $dstpath); # if no destination specified, use default dir + source file if (not $dstdir) { $dstdir = ::DEFINCDIR; $dstfile = $srcfile; # if destination is just a dir, use the source filename } elsif (not $dstfile) { $dstfile = $srcfile; } # a source file can go to several destinations, so use # the latter as the hash keys, because they are unique $srcpath = File::Spec::Unix->catfile($srcdir, $srcfile); $dstpath = File::Spec::Unix->catfile($dstdir, $dstfile); $href->{$dstpath} = $srcpath; } | path keyword path: /"[^"]*"/ | ...!sectionorkeyword /\S+/ sectionorkeyword: section | keyword keyword: /(IGNORE|MANUAL|SUPPORT)\b/i section: /PRJ_EXPORTS\b/i | /PRJ_TESTEXPORTS\b/i )) or die 'Bad grammar'; $text .= $_ while (<DATA>); defined $parser->inffile($text) or die 'Bad text'; print STDERR Data::Dumper->Dump([\%prj_exports, \%prj_testexports], [qw(prj_exports prj_testexports)]); __DATA__ PRJ_EXPORTS ..\inc\cmmphonebookstoreextinterface.h \tcf\cmmphonebookstoreextinterface.h ..\inc\cmmphonebookstoremesshandler.h \tcf ..\inc\cmmonstoremesshandler.h MANUAL ..\inc\cmmonstoreextinterface.h ignore PRJ_TESTEXPORTS ..\inc\cmmenstoreextinterface.h \tcf\cmmenstoreextinterface.h ..\inc\cmmenstoremesshandler.h mmstorageiface.iby \epoc32\rom\include\mmstorageiface.iby > > > > > Regards > > Alex > > > > #!/usr/bin/perl > > > > use strict; > > use vars qw($parser $text %prj_exports %prj_testexports); > > use Data::Dumper; > > use Parse::RecDescent; > > use File::Spec; > > use File::Spec::Win32; > > use File::Spec::Unix; > > use Getopt::Std; > > # where to copy the exported files by default > > use constant DEFINCDIR => 'epoc32/include'; > > #$RD_WARN = 1; > > #$RD_HINT = 1; > > #$RD_TRACE = 120; > > $parser = Parse::RecDescent->new(q( > > > > inffile: chunk(s) /^\Z/ > > chunk: prj_export | > > prj_testexport | > > <error> > > prj_export: /PRJ_EXPORTS\b/i export[\%::prj_exports](s?) > > prj_testexport: /PRJ_TESTEXPORTS\b/i export[\%::prj_testexports](s?) > > export: path <skip: '[ \t]+'> path(?) { > > # ignore if a special keyword has been used as destination > > if ($item[-1]->[0] =~ /^(IGNORE|MANUAL|SUPPORT)$/i) { > > 1; > > } else { > > # reference to the %prj_exports or %prj_testexports > > my $href = $arg[0]; > > # the 1st "path" above is source the 2nd - destination. > > # split the both paths into drive (unused) + dir + filename > > my ($srcdrive, $srcdir, $srcfile) = > > File::Spec::Win32->splitpath($item[1]); > > my ($dstdrive, $dstdir, $dstfile) = > > File::Spec::Win32->splitpath($item[-1]->[0]); > > # replace backslashes through slashes in both dirs > > $srcdir =~ y|\\\\|/|; > > $dstdir =~ y|\\\\|/|; > > # the full paths, consisting of dir + filename > > my ($srcpath, $dstpath); > > # if no destination specified, use default dir + source file > > if (not $dstdir) { > > $dstdir = ::DEFINCDIR; > > $dstfile = $srcfile; > > # if destination is just a dir, use the source filename > > } elsif (not $dstfile) { > > $dstfile = $srcfile; > > } > > # a source file can go to several destinations, so use > > # the latter as the hash keys, because they are unique > > $srcpath = File::Spec::Unix->catfile($srcdir, $srcfile); > > $dstpath = File::Spec::Unix->catfile($dstdir, $dstfile); > > $href->{$dstpath} = $srcpath; > > } > > } > > path: /"[^"]*"/ | ...!section /\S+/ > > section: > > /PRJ_EXPORTS\b/i | > > /PRJ_TESTEXPORTS\b/i > > > > )) or die 'Bad grammar'; > > $text .= $_ while (<DATA>); > > defined $parser->inffile($text) or die 'Bad text'; > > print STDERR Data::Dumper->Dump([\%prj_exports, \%prj_testexports], > > [qw(prj_exports prj_testexports)]); > > __DATA__ > > PRJ_EXPORTS > > ..\inc\cmmphonebookstoreextinterface.h \tcf\cmmphonebookstoreextinterface.h > > ..\inc\cmmphonebookstoremesshandler.h \tcf > > > > ..\inc\cmmonstoremesshandler.h MANUAL > > ..\inc\cmmonstoreextinterface.h ignore > > > > PRJ_TESTEXPORTS > > ..\inc\cmmenstoreextinterface.h \tcf\cmmenstoreextinterface.h > > ..\inc\cmmenstoremesshandler.h > > > > mmstorageiface.iby \epoc32\rom\include\mmstorageiface.iby > > > > > -- > Intel, Corp. > 5000 W. Chandler Blvd. > Chandler, AZ 85226 > > -- > Intel, Corp. > 5000 W. Chandler Blvd. > Chandler, AZ 85226 > -- Intel, Corp. 5000 W. Chandler Blvd. Chandler, AZ 85226 -- Intel, Corp. 5000 W. Chandler Blvd. Chandler, AZ 85226