Tangle: write code output

Previous: Initial scan ] [ Top: xmlp 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
 
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";
            next;
         }
         tangle_one ($thisobject{name});
         next;
      }

      s/\[\[/</g;
      print OUT "$_\n";
   }
}

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


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