├── ASCIIMathML_with_modified_escapes.js ├── MOLLY.html ├── MOLLY.pl ├── MOLLY.tangle ├── MOLLY.weave ├── README ├── eeerotate.jpg ├── examples ├── Finite.dimensional.Lie.algebras.mht ├── LiterateLie.litsrc └── README-example └── new_project_template.weave /MOLLY.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | #----------------------------------------------------------------------------------------- 4 | # MOLLY - A MO-DULE FOR LI-TERATE PROGRAMMING 5 | #----------------------------------------------------------------------------------------- 6 | # ............................................ 7 | # .......licensed under GPL version 3......... 8 | # ............................................ 9 | # ....... Author: unixtechie; email: ......... 10 | # .. /same/ .. at .. yahoo .. dot .. com .... 11 | # ............................................ 12 | # ..... Git depos. - docs and download: ...... 13 | # http://github.com/unixtechie/Literate-Molly/ 14 | # ............................................ 15 | # 16 | #----------------------------------------------------------------------------------------- 17 | #---|-4-|-8-|-12----|-20------|-30------|-40------|-50------|-60------|-70------|-80------| 18 | 19 | 20 | # need to fool the noweb "notangle" utility, switch markup modes etc. 21 | $lt = "<"; 22 | $gt = ">"; 23 | $lt_esc = "<"; 24 | $gt_esc = ">"; 25 | $dash = "-"; 26 | $dot = "\."; 27 | 28 | # ----- GENERAL settings ----- 29 | 30 | # print toc? 1:0 31 | $print_toc = 1 unless defined $print_toc; 32 | 33 | # keep TOC expanded on initial load? "block":"none" 34 | $toc_expanded = $toc_expanded || "block"; 35 | 36 | # keep TOC expanded in initial load? "block":"none" 37 | $ind_expanded = $ind_expanded || "none"; 38 | 39 | # what is the file extention to weave it? (perms must allow execution!) 40 | # e.g. "scriptname.weave" or "scriptname.cgi" etc. 41 | $weave_extension = $weave_extension || "weave"; # default is "weave" 42 | 43 | # what is the file extention to tangle it? (perms must allow execution!) 44 | # e.g. "scriptname.tangle", "scriptname.pl" etc. 45 | $tangle_extension = $tangle_extension || "tangle"; # default is "tangle" 46 | 47 | 48 | #When tangling, should I use the built-in tangler? 0:1 49 | # (if 0, the "pass-through" tangling will call "notangle" 50 | # from Ramsey's "noweb" tools, must be installed and in your path) 51 | # use_builtin_tangler = 0; # default for now is to use external "notangle" 52 | $use_builtin_tangler = $use_builtin_tangler || 0; 53 | 54 | # Actually, let's always do it and disallow unsetting 55 | # number lines ? 1 : else 56 | $line_numbering = 1; 57 | 58 | # Print LitSource's line nums as a reference in the tangled output? deflt is 0. 59 | $print_ref_linenos_when_tangling = $print_ref_linenos_when_tangling || 0; 60 | $code_sections_comment_symbol = $code_sections_comment_symbol || "# "; 61 | 62 | 63 | # find and print root chunks in the LitSrc (i.e. instead of tangling when it is run 64 | # as "./LitSrc.tangle" from command line) ? 0:1 65 | $show_all_roots = $show_all_roots || 0; # default is not (i.e. to tangle) 66 | 67 | 68 | # how are doc sections marked? "dotHTML":"rawHTML" 69 | $weave_markup = $weave_markup || "rawHTML"; # default is "rawHTML" 70 | 71 | if ($weave_markup eq "dotHTML") { 72 | $tag_open = $dot; # this will take care of default 73 | $tag_close = $dot; # when no var is set in the Lit Src file 74 | } 75 | elsif ($weave_markup eq "rawHTML") { 76 | $tag_open = $lt; 77 | $tag_close = $gt; 78 | } #fi 79 | 80 | 81 | # enable MathML interpretation? 1 : 0 82 | $enable_ASCIIMathML = $enable_ASCIIMathML || 0; 83 | # If enabled, set the path; default is local in current dir 84 | $path_to_ASCIIMathML = $path_to_ASCIIMathML || "ASCIIMathML_with_modified_escapes.js"; 85 | 86 | # -- MAIN DESPATCHER WITH CL---- 87 | use Getopt::Std; 88 | 89 | 90 | sub usage { 91 | 92 | print STDERR<<'end_of_usage'; 93 | 94 | USAGE: MOLLY.pl [options] [--] filename 95 | 96 | -h, or no filename 97 | get this help message 98 | 99 | 100 | TANGLING Options: 101 | Tangling mode is default, no special option to force needed. 102 | 103 | -R "root_chunk_name", 104 | tangle starting from this chunk. if omitted, "*" is default. 105 | 106 | -l 'comment symbol for your language', 107 | add comments with coresponding line numbers in Lit Src 108 | 109 | -i information on root chunks 110 | 111 | 112 | WEAVING options: 113 | 114 | -w, 115 | weave from the external target file (rawHTML), or 116 | -wd 117 | same for dotHTML-encoded files 118 | 119 | -m 'URL or path/to/ASCIIMathML.js library' 120 | process the file with ASCIIMathML lib. Option used in addition 121 | to mode-setting -w or -wd 122 | 123 | 124 | FORESTRY mode: 125 | 126 | -t -1, or -t 3 etc. (for default rawHTML-encoded files) 127 | -dt -2, or -dt 1 etc. (for "dotHTML"-encoded files) 128 | run as a "tree replant" filter: 129 | move subtree up 1 level or down 3 levels, etc. 130 | when employed as a filter on an editor's selected text. 131 | Renumbers html headings and vim folding marks. 132 | 133 | MOLLY.pl [-d] -t# < LitSource.file 134 | renumber headings and vim folding marks for a whole file from CL 135 | 136 | 137 | 138 | FOR INTERNALLY MOLLIFIED FILES: 139 | shortcut invocation - depending on file extension. If run as script 140 | 141 | "lit_prog_file.tangle" 142 | tangles to STDOUT, from default root "*" only. 143 | "lit_prog_file.weave" 144 | weaves to STDOUT as folding HTML; usable under CGI 145 | 146 | / OR: set your own extensions in your lit.source configuraton section / 147 | 148 | end_of_usage 149 | 150 | exit; 151 | } 152 | 153 | 154 | my @LITSOURCE_list = (); 155 | my %LITSOURCE_hash = (); 156 | 157 | # -1- shortcut invocations for "mollified" LitSrc file depending on its extension --- 158 | 159 | if ( $0 =~ m!\w+\.$weave_extension$! ) { 160 | 161 | open LITSOURCE, "< $0" or die "\n\tcould not open the target file\n\n"; 162 | goto WEAVE_ME; 163 | } 164 | elsif ( $0 =~ m!\w+\.$tangle_extension$! ) { 165 | 166 | open LITSOURCE0, "< $0" or die "\n\tcould not open the target file for tangling\n\n"; 167 | push @LITSOURCE_list, 'LITSOURCE0'; 168 | $LITSOURCE_hash{'LITSOURCE0'} = $0; 169 | goto TANGLE_ME; 170 | } 171 | 172 | # -2- MOLLY.pl as a standalone script is called from CGI, nothing in here yet --- 173 | 174 | elsif (defined $ENV{'REQUEST_METHOD'}) { 175 | 176 | 177 | print "Content-Type: text/html; charset=utf-8\n\n"; 178 | print <<_XXX_; 179 |
180 |
181 | I was caled as CGI, but this invocation seems to be meaningless.
182 | Maybe you meant to "weave", but set a wrong file extension.
183 | Goodbye.
184 | -- MOLLY.pl --
185 |
186 |
187 | _XXX_
188 |
189 | exit;
190 |
191 |
192 | }
193 |
194 | # -3- several cases for application of Molly to an external target file from CL ---
195 |
196 | #elsif (-t STDIN) {
197 | else { # do not check; assume it is command line now; will take piped input now.
198 |
199 |
200 | #print STDERR "$0 was called from command line..\n";
201 |
202 | #-- getopts invocation
203 | getopts("hwm:dt:l:R:i", \%cl_args);
204 |
205 | # -- set doc sections markup (if not default=html):
206 | if($cl_args{d}) {
207 | $tag_open = $dot;
208 | $tag_close = $dot;
209 | $weave_markup = "dotHTML";
210 | #print STDERR setting dotHTML markup\n";
211 | }
212 |
213 | # -- "forestry" mode - act as a filter to move subtree levels
214 | if($cl_args{t}) {
215 | $replant_tree = $cl_args{t};
216 | #print STDERR "moving subtree by '$replant_tree' levels\n";
217 | goto FORESTRY;
218 | }
219 |
220 |
221 | # -- print USAGE if not evoked correctly
222 | if( (! defined $ARGV[0] ) or ( $cl_args{h} ) ) { usage(); exit };
223 |
224 | # -- does target file exist?
225 | if ( -f $ARGV[0] ) {
226 | ; # nop, a debug printout
227 | #print STDERR "target file to operate on is $ARGV[0]\n";
228 | }
229 | else {
230 | die "\n\tERROR: No target file $ARGV[0] seem to exist\n\n";
231 | };
232 |
233 |
234 | # -- Final CL despatch, do it: --
235 |
236 |
237 | if($cl_args{w}) { # this is weaving - and I put "forestry" in here too
238 |
239 | if (@ARGV > 1) {
240 | print STDERR "\n\n\tDo not know how to weave several files\n";
241 | print STDERR "\tweaving the first one: $cl_args{w}\n\n";
242 | }
243 |
244 | if ($cl_args{m}) {
245 | # print STDERR "using ASCIIMathML.js - located at $cl_args{m}\n";
246 | $enable_ASCIIMathML = 1;
247 | $path_to_ASCIIMathML = $cl_args{m};
248 | }
249 |
250 | open LITSOURCE, "< $ARGV[0]" || die "could not open the target file\n";
251 | goto WEAVE_ME;
252 |
253 | }
254 |
255 | else { # this is tangling, default action, no opt
256 |
257 |
258 | if($cl_args{d}) {
259 | #print STDERR "doc sections in coments; comment char is $cl_args{d}\n";
260 | };
261 |
262 | if($cl_args{u}) {
263 | #print STDERR "applying UN-tangling with script char is $cl_args{u}\n";
264 | };
265 |
266 | if($cl_args{i}) {
267 | #print STDERR "printing information on roots, discovered chunks\n";
268 | $show_all_roots = 1;
269 |
270 | };
271 |
272 | if($cl_args{l}) {
273 | #print STDERR "will add reflines; comment char is $cl_args{l}\n";
274 | $print_ref_linenos_when_tangling = 1;
275 | $code_sections_comment_symbol = $cl_args{l};
276 | };
277 |
278 | # -- getting the root chunk for tangling --
279 | if($cl_args{R}) {
280 | $root_chunk = $cl_args{R};
281 | print STDERR "tangling root chunk '$root_chunk'\n";
282 | };
283 |
284 |
285 | for (my $countem=0; $countem < @ARGV; $countem++) {
286 |
287 | $LITSOURCE_multi = 'LITSOURCE' . $countem;
288 | open $LITSOURCE_multi, "< $ARGV[$countem]"
289 | or die "\n\tCould not open target file $ARGV[$countem]\n\n";
290 |
291 | push @LITSOURCE_list, $LITSOURCE_multi;
292 | $LITSOURCE_hash{$LITSOURCE_multi} = $ARGV[$countem];
293 |
294 | } # rof
295 |
296 | goto SEEK_PEEK_TANGLER;
297 |
298 | } # fi - CL final despatch
299 |
300 | exit; #redundant and unused
301 |
302 |
303 | }
304 |
305 | # # -4- other cases ---
306 | #
307 | # else {
308 | #
309 | # die "MOLLY.pl: I do not know how I was called, exiting anyway\n";
310 | #
311 | # } # esle, fi - end of despatcher
312 |
313 | exit; # just in case
314 |
315 |
316 | TANGLE_ME:
317 |
318 |
319 | if ( $use_builtin_tangler ) {
320 |
321 |
322 | SEEK_PEEK_TANGLER:
323 |
324 |
325 |
326 | my $chunk_beg_pattern = q(^<\<(.*)>\>=);
327 | my $chunk_end_pattern = q(^@\s.*$);
328 | my $chunk_ref_pattern = q(<\<(.*?)>\>[^=]); # can be used several times in a line
329 |
330 | my $current_chunk_name = "";
331 | my $current_chunk_start_foff = 0;; # "foff" is a "file offset"
332 | my $current_chunk_end_foff = 0;
333 |
334 | my %file_offsets_hash = ();
335 | my %file_lines_hash = ();
336 | my $parents_list = ();
337 |
338 | my $line_num = 0;
339 | my $previous_line_foff = 0; # "foff" is a "file offset"
340 |
341 |
342 | foreach $LITSOURCE_multi(@LITSOURCE_list) {
343 |
344 |
345 | while (<$LITSOURCE_multi>) {
346 | $line_num++;
347 |
348 | # --- CODE CHUNKS -- not inside documentation section
349 | if ( m!$chunk_beg_pattern! .. m!$chunk_end_pattern! ) {
350 |
351 |
352 | if ( $_ =~ m!$chunk_beg_pattern! ) {
353 | $current_chunk_name = $1;
354 | $current_chunk_start_foff = $LITSOURCE_multi . "-" . (tell $LITSOURCE_multi);
355 |
356 | # -- collecting offset and line number, actually
357 | push @{$file_offsets_hash{$current_chunk_name}}, $current_chunk_start_foff;
358 | push @{$file_lines_hash{$current_chunk_name}}, $LITSOURCE_multi . "-" . $.;
359 | #~ print "----> chunk $1 line $. offset $current_chunk_start_foff\n";
360 |
361 | }
362 |
363 |
364 | elsif ( $_ =~ m!$chunk_end_pattern! ) {
365 |
366 | $current_chunk_end_foff = $LITSOURCE_multi . "-" . $previous_line_foff;
367 | # -- collecting offset and line number:
368 | push @{$file_offsets_hash{$current_chunk_name}}, $current_chunk_end_foff;
369 | push @{$file_lines_hash{$current_chunk_name}}, $LITSOURCE_multi . "-" . $.;
370 | #~ print "\tline $. offset $current_chunk_end_foff<------\n";
371 |
372 | $current_chunk_name = "";
373 | }
374 |
375 |
376 | elsif ( $_ =~ m!$chunk_ref_pattern!g ) {
377 |
378 | my $line = $_;
379 | my $current_foff_pos = $previous_line_foff;
380 | my $initial_margin = "";
381 | my $homegrown_pos = 0;
382 |
383 | while ($line =~ m!(.*?)<\<(.*?)>\>!g) {
384 |
385 | my $pre_ref_match = $1;
386 | my $ref_match = $2;
387 | my $len_pre_ref_match = length $pre_ref_match;
388 | my $len_ref_match = length $ref_match;
389 |
390 | # "end" of prev pair; collecting offset and line number
391 | push @{$file_offsets_hash{$current_chunk_name}},
392 | $LITSOURCE_multi . "-" . ($current_foff_pos + $len_pre_ref_match);
393 | push @{$file_lines_hash{$current_chunk_name}}, $LITSOURCE_multi . "-" . $.;
394 |
395 |
396 | #-------deal with pushing ("ref", "chunkname") pair -----
397 | # special id string for refs
398 | push @{$file_offsets_hash{$current_chunk_name}}, "ref";
399 | # name of reference
400 | push @{$file_offsets_hash{$current_chunk_name}}, $ref_match;
401 | # .. and form pairs for toposort (cycles check, search roots):
402 | push @parents_list, ($current_chunk_name, $ref_match);
403 |
404 | # -- next a special entry for refs: (left_margin)
405 | # I keep tabs and spaces and subst all else to spaces
406 | $pre_ref_match =~ s!\S! !g;
407 | $initial_margin .= $pre_ref_match;
408 | push @{$file_offsets_hash{$current_chunk_name}}, $initial_margin;
409 | $initial_margin .= " " x ( $len_ref_match + 2*( length "<>") );
410 |
411 | my $homegrown_pos = $len_pre_ref_match + $len_ref_match + 2*(length "<>");
412 | my $end_of_match_pos = $current_foff_pos + $homegrown_pos;
413 |
414 | # "start" a new pair.. - ok, let's not use "pos" at all, if it fails
415 | # .. and collect both offset and the line number
416 | push @{$file_offsets_hash{$current_chunk_name}},
417 | $LITSOURCE_multi . "-" . $end_of_match_pos;
418 | push @{$file_lines_hash{$current_chunk_name}}, $LITSOURCE_multi . "-" . $.;
419 |
420 | # I'll need to reset current_foff_pos to the pos
421 | # (or to the directly caclucalted offset, if I prefer that):
422 | $current_foff_pos = $end_of_match_pos;
423 |
424 | } # elihw
425 |
426 | # This is where chunk refs get an extra newline ?
427 |
428 | } # fisle
429 |
430 |
431 | else { # chunk body
432 | ; # nop; here just not to hide an implicit case
433 | #~ print "."; # debug: show dots for lines
434 | }
435 |
436 |
437 | } #fi
438 |
439 | $previous_line_foff = tell $LITSOURCE_multi;
440 |
441 | } # eliwh
442 |
443 | } # hcaerof iteration over all files collecting file offsets
444 |
445 |
446 |
447 |
448 | sub topological_sort {
449 |
450 | my $flag_show_roots = shift;
451 | my %pairs; # all pairs ($l, $r)
452 | my %npred; # number of predecessors
453 | my %succ; # list of successors
454 | my $opt_b = 0;
455 |
456 | my @topo_list_out = '';
457 |
458 | while ( @_ ) {
459 | my $l = shift @_;
460 | my $r = shift @_;
461 | my @l = ($l, $r);
462 | #my ($l, $r) = my @l = split;
463 | next unless @l == 2;
464 | next if defined $pairs{$l}{$r};
465 | $pairs{$l}{$r}++;
466 | $npred {$l} += 0;
467 | ++$npred{$r};
468 | push @{$succ{$l}}, $r;
469 | }
470 |
471 | # create a list of nodes without predecessors
472 | my @list = grep {!$npred{$_}} keys %npred;
473 |
474 | #--print discovered roots, if asked--
475 | if ($flag_show_roots) {
476 | print "\n\t--roots of multi-chunk chains--\n";
477 | for (@list) { print "\t$lt$lt$_$gt$gt\n";}
478 | print "\t-------------------------------\n";
479 | }
480 |
481 | while (@list) {
482 | $_ = pop @list;
483 | unshift @topo_list_out, $_;
484 | #print "$_\n";
485 | foreach my $child (@{$succ{$_}}) {
486 | if ($opt_b) { # breadth-first
487 | unshift @list, $child unless --$npred{$child};
488 | } else { # depth-first (default)
489 | push @list, $child unless --$npred{$child};
490 | }
491 |
492 | }
493 | }
494 |
495 | # mm.. better if I warn, print out the list so far, and then exit
496 | # the user will have the place where the problem occured
497 | #~ warn "cycle detected\n" if grep {$npred{$_}} keys %npred;
498 | if ( grep {$npred{$_}} keys %npred ){
499 | warn "\n\tERROR: cycle detected - aborting execution!\n";
500 | print "\n---chunks discovered before the 'cycle' ERROR - sorted topologically ---\n";
501 | for (@topo_list_out) {
502 | print "$_\n";
503 | } # rof
504 |
505 | exit;
506 | } # fi check for cycles
507 |
508 | # -DEBUG-
509 | # if ($flag_show_roots){
510 | # print "\t--all chunks discovered--\n";
511 | # for (@topo_list_out) {
512 | # print $_, "\n";
513 | # }
514 | # exit;
515 | # }
516 |
517 | return @topo_list_out;
518 | #return 1;
519 | } # tros_lacigolopot
520 |
521 |
522 | # will abort if cycles detected. Does not detect all cycles? - need to check
523 | my @chunks_in_chains = topological_sort($show_all_roots, @parents_list);
524 |
525 | if ($show_all_roots){
526 |
527 | # non-standalone roots are already printed from inside "topological_sort"
528 | print "\n\t------single-chunk roots-------\n";
529 | my %lookup_hash = ();
530 | for (@chunks_in_chains){ $lookup_hash{$_} = 1;}
531 |
532 | for (keys %file_offsets_hash) {
533 | print "\t$lt$lt$_$gt$gt\n"
534 | unless exists $lookup_hash{$_};
535 | }
536 | print "\t-------------------------------\n\n";
537 | exit;
538 | }
539 |
540 |
541 | # USAGE: print_chunk(name_of_chunk, left_margin, print_newline_flag)
542 | sub print_chunk {
543 |
544 | (my $chunk_being_printed,
545 | my $snippet_left_margin,
546 | my $snippet_print_newline_flag, @rest) = @_;
547 |
548 |
549 | #~ print "\n---- printing chunk $chunk_being_printed --------\n";
550 | #~ print "DEBUG: got left.m. $snippet_left_margin nl. flag $snippet_print_newline_flag \n";
551 |
552 | # -- error mess. not to fail silently --
553 | unless ( defined $file_offsets_hash{$chunk_being_printed} ) {
554 | die "\n\tERROR: chunk $chunk_being_printed not found in file $ARGV[0]\n\n";
555 | }
556 |
557 |
558 | # iterate over splinters of a chunk, which are foff pairs
559 | my $iterate_lines = 0;
560 | for ( my $iterate_foffs = 0;
561 | exists $file_offsets_hash{$chunk_being_printed}[$iterate_foffs];)
562 | {
563 |
564 | my $snippet_position = $file_offsets_hash{$chunk_being_printed}[$iterate_foffs++];
565 | my $snippet_end = $file_offsets_hash{$chunk_being_printed}[$iterate_foffs++];
566 |
567 | #~ print "debug got: beg $snippet_position -- end $snippet_end\n";
568 |
569 |
570 | if ($snippet_position eq "ref") {
571 |
572 | my $snippet_left_margin_ref =
573 | $file_offsets_hash{$chunk_being_printed}[$iterate_foffs++];
574 |
575 | # any call to a ref uncurs "print newline" flag of 0
576 | print_chunk($snippet_end, $snippet_left_margin_ref, 0);
577 |
578 | }
579 |
580 | else { # .. print it here
581 |
582 | (my $litsrc_fhname_beg, my $litsrc_line_beg) =
583 | split '-', $file_lines_hash{$chunk_being_printed}[$iterate_lines++];
584 | (my $litsrc_fhname_end, my $litsrc_line_end) =
585 | split '-', $file_lines_hash{$chunk_being_printed}[$iterate_lines++];
586 |
587 | (my $litsrc_fhname_beg, my $litsrc_foff_beg) = split '-', $snippet_position;
588 | (my $litsrc_fhname_end, my $litsrc_foff_end) = split '-', $snippet_end;
589 | # DEBUG prints:
590 | #print "in file_beg $litsrc_fhname_beg $litsrc_foff_beg\n";
591 | #print "in file_end $litsrc_fhname_end $litsrc_foff_end\n------\n";
592 |
593 |
594 | # the file is always the same, though. You cannot have one chunk splinter
595 | # start in one file and end in another one. (2 splinters can live in 2 files)
596 | seek $litsrc_fhname_beg, $litsrc_foff_beg, 0;
597 | read $litsrc_fhname_end, $buffer_out, ($litsrc_foff_end - $litsrc_foff_beg);
598 |
599 | #----Newlines at the end of chunks and refs.
600 | # only for the last splinter of a chunk, do newline control:
601 | if ( ((scalar @{$file_offsets_hash{$chunk_being_printed}}) - $iterate_foffs ) == 0 )
602 | {
603 | # works, but is suspicious logically:
604 | # maybe I just have not invented a counterexample yet, and
605 | # it's a trap waiting for its quarry. But it works
606 | $buffer_out =~ s!\n([\s]*)$!$1! unless ($snippet_print_newline_flag);
607 | }
608 |
609 | #----Left indent/margin. Seems OK
610 |
611 | $chunk_left_margin = $snippet_left_margin;
612 | $buffer_out =~ s!(\n)!$1$chunk_left_margin!sg;
613 |
614 |
615 | #----And Print Out:
616 |
617 | if ($print_ref_linenos_when_tangling){
618 | print $code_sections_comment_symbol,
619 | "[line ", $litsrc_line_beg," in file ",
620 | $LITSOURCE_hash{$litsrc_fhname_beg}, "]__start" ;
621 | print "_________________________________\n";
622 | }
623 |
624 | print $buffer_out;
625 |
626 | if ($print_ref_linenos_when_tangling) {
627 | print $code_sections_comment_symbol,
628 | "[line ", $litsrc_line_end," in file ",
629 | $LITSOURCE_hash{$litsrc_fhname_end}, "]__end" ;
630 | print "___________________________________\n";
631 | }
632 |
633 | } #esle for printout
634 |
635 |
636 | } # rof non-destructive
637 |
638 | return 1;
639 | } # bus -- ends the recursive sub
640 |
641 |
642 | $root_chunk = $root_chunk || "*";
643 |
644 | # USAGE: print_chunk(name_of_chunk, left_margin, print_newline_flag)
645 | print_chunk($root_chunk, "", 1);
646 |
647 | # and close all the opened files
648 | for (@LITSOURCE_list){close $_;}
649 |
650 |
651 | exit;
652 |
653 |
654 | }
655 | else { # pass to "notangle" from "noweb" tools by Ramsey
656 |
657 | open TANGLE_PIPE, "| notangle -t4 -";
658 |
659 | while (";
940 | $html_body_table_end = "\n