Tangle: write code output
Previous: Initial scan ] [ Top: LPML alpha ] [ Next: Weave: Write documentation pages ]

The tangle step is really pretty easy. What we do in this step is use the $pieces hash we populated during the scan step to generate code. We insert items in other items by using the <insert> tag.

Since our coding language is XML, we can't use the character '<' explicitly in our code. Irritating, but that's one of the tiny little disadvantages of using XML, and it's offset by so many advantages that living with it isn't so hard. All we do is use '[[' instead (hard-coded in this version, soon to be specifiable.) So the tangle step also takes care of substituting our '<' back in.

Tangle is inherently recursive. I'm dumbly following the whole recursive structure in a depth-first manner; the smarter thing would be to cache items as they're tangled in case of reuse (then I wouldn't have to retangle that item). Since I'm working with small files here, that probably isn't worth the effort, so I'm not going into it.

Note also that since Perl can define subroutines right in the middle of the rest of the code, I found it more natural simply to include the recursive routine here right in the middle of things, instead of packing it off into some subroutine block.
See Definition of 'tangle_one' subroutine
foreach $obj (@objects) {
   open OUT, ">$obj";
   tangle_one ($starter{$obj});
   close OUT;

Definition of 'tangle_one' subroutine
The tangle procedure is recursive, and writes out the tangled output to the object file. Among other things, it needs to convert special characters to their literal equivalents; special characters are those, like < and &, which XML doesn't allow anywhere but in meaningful positions. These replacements occur right at the bottom.
sub tangle_one {
   my $item = shift;
   foreach $_ (split /\n/, $pieces{$item}) {
      if (/(<insert .*>)/i)
         $tag = $1;
         $tag =~ s/^<insert\s+//i;
         $attr = "";
         %thisobject = (name => '');
         foreach $piece (split /"/, $tag) {
            if ($attr eq '') {
               $attr = $piece;
               $attr =~ s/^\s*//;
               $attr =~ s/\s*=\s*$//;
            } else {
               $thisobject{$attr} = $piece;
               $attr = '';
         if ($thisobject{name} =~ /^\./) {
            $thisobject{name} = $item . $thisobject{name};
         if ($thisobject{name} eq '') {
            print STDERR "$. : Item to be inserted not named.\n";
         tangle_one ($thisobject{name});

      print OUT "$_\n";

Previous: Initial scan ] [ Top: lpml alpha ] [ Next: Weave: Write documentation pages ]

This code and documentation are released under the terms of the GNU license. They are copyright (c) 2000-2006, Vivtek. All rights reserved except those explicitly granted under the terms of the GNU license.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.