Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I would like to know is there a way you can use several
__DATA__ & __END__ at the same file .
Let's say I want to print these sections , which __DATA__
will I'll refer to ? The next one ? The first one ?
I think I'll be able to do it if I'll declare several
pacakges in the same file and each package will include
only one print function and one __DATA__ section.
What do you think guys ?
Thx
michaelg

Replies are listed 'Best First'.
Re: multiple __DATA__ && __END__
by gjb (Vicar) on Nov 20, 2003 at 13:51 UTC
Re: multiple __DATA__ && __END__
by jeffa (Bishop) on Nov 20, 2003 at 14:04 UTC

    Hello michaelg, did you forget to log in before you posted? If so, maybe now is the time to change your default theme to something that looks different, like i do (i use the Dark Theme). Also, you (and anyone else who reads this who is "guilty" of such) should stop using so many <br> tags. I used to be the same way until someone made me realize that this is a complete waste of your time. Remember, folks use different screen resolutions and application sizes ... when you use <br> tags to make line breaks, you are assuming that the folks who read your post are using the same resolution and application size as you. We don't! So please, stop using <br> tags to make line breaks: let the browser make the desicion,

    unless you prefer
    to write your posts like haikus
    please use the <p> tag
    ;)

    Now then, as for the question ... do as gjb says and look into Inline::Files. It's very easy to grasp, but i wonder if you are missing a better, more maintable solution? Why do you need two DATA sections in one file? I like to use Inline::Files for quick and dirty tests or examples that i post here at the Monastery, but i never use it in production. Sometimes doing it the "old way" is better - in this case, just store them as text files and open them up.

    UPDATE:
    I guess i'll have to explicitly add that when i say use <p> tags instead of <br/> tags ... i don't mean replace all of the <br/> tags in you post with <p> tags! I mean write a full paragraph and enclose that paragraph in a <p></p> tag pair.

    And for the record, i write one sentance paragraphs when they are appropriate. ;)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    

      hi jeffa

      Thanks for your answer, well I have 2 problems I work for a company with only so little respect to perl that meens that most of CPAN modules arn't installed here include inline. The second problem is that the app I'm writing should be deliver to customers as one binary file with no installation tree what so ever , just download it and use it. so I don't have any file that I can open, so I keep all my text in a .pm __DATA__ segment .

      well now I need to write help for the app and I 8 the thought that I have to create about 10 packages for that.

      So do you have something else in mind? :)

      Michael
      no theam yet ,SIR !!

        Ah. Without using modules you are restricted to a single __DATA__ per source file. You could store a Storable serialized object there though and that would give you arbitrary complexity. Storable is in the core perl distribution so your customers should have it.

        Or... if you need to package up a binary you should check out PAR to create the executable. Just keep in mind that you can't prevent (ever) your customers from being able to read your code.

Re: multiple __DATA__ && __END__
by synistar (Pilgrim) on Nov 20, 2003 at 15:16 UTC

    gjb's suggestion is probably what you want. But another approach you could try is storing a serialized data structure in the __DATA__ segment (for example using Data::Dumper or FreezeThaw). This allows you to store whatever you want and spares you the effort of parsing it too.

Re: multiple __DATA__ && __END__
by Anonymous Monk on Nov 20, 2003 at 21:53 UTC

    I was unaware of the nifty modules mentioned. Up until now I have tended use prefixes to distinguish multiple categories of data in the __DATA__ section. If for aesthetic reasons you want to stick a __DATA__ section before __END__ (after which you could, e.g., have your POD), just stop reading from DATA when you see /^__END__$/.

    E.g.:

    use strict;
    use warnings;
    
    while (<DATA>) {
      chomp;
      last if /^__END__$/;         # stop when __END__ is encountered
      next if /^\s*(#.*|\s*)$/;   # skip blank lines or comment lines
      # Clip out and remove category prefix ("word" characters terminated by a colon)
      if (s/^(\w+)://) {
        my $category = $1;
        # P.S.  It's not really necessary to copy $1, but good if you are going to be 
        # fooling with other regex stuff.
        print "$_ is in the $category category\n";
      } else {
        die "unexpected input in __DATA__ section: '$_'";
      }
    }
    
    exit 0;
    
    __DATA__
    
    # 3 categories: animal, vegetable, and mineral
    ANIMAL:dog
    ANIMAL:cat
    
    VEGETABLE:apple
    VEGETABLE:mushroom, the State Vegetable of Pennsylvania,
    
    MINERAL:granite
    
    __END__
    
    =pod
    
    hoo hah
    
    =cut
    
Re: multiple __DATA__ && __END__
by Coruscate (Sexton) on Nov 20, 2003 at 23:27 UTC

    Whenever this question comes up, the first solution mentioned is always "use Inline::Files". While the module does do what is asked, I find that the module lacks a little. I've looked at the source and decided my perl foo is not strong enough to make the changes I'd like to see introduced.

    The problem is the simple fact that if you use Inline::Files, you cannot use the 3-arg form of open(). It's as simple as that. The following program will not function as expected, because Inline::Files overrides perl's open(). So all Inline::Files sees is open my $fh, '>';, which opens an *ANON filehandle at the end of your file (so the contents of *FOO and *BAR are appended to your file, rather than to 'foo.txt'. The non-working example:

    #!c:/perl/bin/perl -w $|++; use strict; use Inline::Files; open my $fh, '>', 'foo.txt' or die "open failed: $!"; print $fh do { local $/; (<FOO>, <BAR>) }; close $fh; __FOO__ foo here __BAR__ bar here

    There is one solution to this. Whenever I wish to open a _real_ file (such as 'foo.txt'), I can call 'CORE::open()', rather than 'open()'. I just choose not to do so, because I don't like it :)

    This little snippet is located in my junk drawer. I've never really used it, I discovered the wonderful world of templates shortly after I threw it together. But it works. It doesn't do the extensive cool stuff that Inline::Files does (such as opening these data sections for writing), but it gets the job of reading them done :)

    #!c:/perl/bin/perl -w $|++; use strict; CHECK { no strict 'refs'; my %fh = ( do { local $/; <DATA> } =~ m#^__(.+?)__\n(.*?)\n?(?=\n?__|\z)#msg ); open *{$_}, '<', \$fh{$_} or die "inline open failed: $!" for keys %fh; } use vars qw(*FOO *BAR); open my $fh, '>', 'foo.txt' or die "open failed: $!"; print $fh do { local $/; (<FOO>, <BAR>) }; close $fh; __DATA__ __FOO__ foo here __BAR__ bar here

Re: multiple __DATA__ && __END__
by davido (Cardinal) on Nov 20, 2003 at 23:54 UTC
    tell and seek may be used to jump around in the single __DATA__ section, allowing pretty flexible access. But let me mention something else.

    I know this isn't exactly what you're asking. But there are instances where it might be just as appropriate, and somewhat simpler to use one or more HERE documents instead of the <DATA> filehandle. ...just a thought... there's always more than one way to do it. ;) A HERE doc will be equivilant to slurping an entire file into a scalar. But maybe that's not so bad in some situations. And with multiple HERE docs, the possibilities open up.


    Dave


    "If I had my life to live over again, I'd be a plumber." -- Albert Einstein

      tell and seek may be used to jump around in the single __DATA__ section.

      Quite true. I'm just going to throw in the mention that tell() really is needed if you are planning to seek() your way through *DATA. Simply because *DATA is an extension of your file, so seek DATA, 0, 0; brings you to the start of the file, rather than the start of the __DATA__ section. (P.S.: I gather that you already knew this, as per your mention of tell(). Just wanted to throw in the extra info for anyone who stumbles across this and wonders how to do such a thing).

      #!c:/perl/bin/perl -w $|++; use strict; # incorrect - maybe not what you expect print scalar <DATA>; seek DATA, 0, 0; # seeks to first line of file! print scalar <DATA>; __DATA__ foo bar

      #!c:/perl/bin/perl -w $|++; use strict; # correct my $start = tell DATA; # tells us where __DATA__ begins print scalar <DATA>; seek DATA, $start, 0; # seek to the saved point print scalar <DATA>; __DATA__ foo bar

Re: multiple __DATA__ && __END__
by Anonymous Monk on Nov 21, 2003 at 10:03 UTC

    Hi,

    As Inline::Files seems to be the solution you could do something really dirty to be able to use it!

    #!C:/activeperl/bin/perl-w use strict; open(OFILE,">myfile.pm") or die("Can't open myfile.pm\n$!"); print OFILE <<EOF; package myTestPackage; sub mytest() { print "hello World!\n"; } 1 EOF close(OFILE); require "myfile.pm"; myTestPackage::mytest();

    Horrible solution but this simple code works. Don't see why you can't put the Inline::Files code in the here document...

    - Mark