#!/usr/bin/env perl
use strict;
exit main( @ARGV );
#---------------------------------------------------------------------
sub main {
my $stuff = {};
@ARGV = ();
print STDERR (join "\n", @ARGV, '');
EmitHeader( $stuff );
EmitBody( $stuff );
EmitFooter( $stuff );
return 0;
}
#---------------------------------------------------------------------
sub EmitHeader {
my ( $stuff ) = @_;
}
#---------------------------------------------------------------------
sub EmitBody {
my ( $stuff ) = @_;
while (my $line = <>) {
chomp $line;
if ( $line =~ m/\A@[f]ile(\s(.*)|)\z/ ) {
my $filename = $2;
HandleFile( $stuff, $filename );
}
elsif ( $line =~ m/\A@[b]egin docs (\d+)\z/ ) {
my $chunk_number = $1;
HandleDocs( $stuff, $chunk_number );
}
elsif ( $line =~ m/\A@[b]egin code (\d+)\z/ ) {
my $chunk_number = $1;
HandleCode( $stuff, $chunk_number );
}
}
}
#---------------------------------------------------------------------
sub EmitFooter {
my ( $stuff ) = @_;
}
#---------------------------------------------------------------------
sub HandleFile {
my ( $stuff, $filename ) = @_;
if ( $filename ) {
print STDOUT "
$filename
\n";
$stuff->{'filename'} = $filename;
}
}
#---------------------------------------------------------------------
sub ReadLinesUntil {
my ( $end ) = @_;
my @lines = ();
while ( my $line = <> ) {
chomp $line;
last if ( $line eq $end );
push @lines, $line;
}
return \@lines;
}
#---------------------------------------------------------------------
sub MakeChunkNameComment {
my ( $name, $seq, $lang ) = @_;
my %commenters = (
'lisp' => sub { my ( $nn ) = @_; return ";;; $nn"; },
'c' => sub { my ( $nn ) = @_; return "/* $nn */"; },
'c++' => sub { my ( $nn ) = @_; return "// $nn"; },
'default' => sub { my ( $nn ) = @_; return "# $nn"; },
);
if ( $seq > 0 ) {
return MakeChunkNameComment( "$name (cont.)", 0, $lang );
}
else {
my $commenter = $commenters{$lang};
if ( ! $commenter ) {
return MakeChunkNameComment( $name, 0, 'default' );
}
elsif ( ref( $commenter ) eq 'CODE' ) {
return &$commenter($name);
}
else {
return MakeChunkNameComment( $name, 0, $commenter );
}
}
}
#---------------------------------------------------------------------
sub GetChunkReference {
my ( $name, $lang ) = @_;
my %referencers = (
'lisp' => sub { my ( $nn ) = @_; return "#<:use \"$nn\">" },
'c' => 'default',
'c++' => 'c',
'default' => sub { my ( $nn ) = @_; return "<<$nn>>" },
);
my $referencer = $referencers{$lang};
if ( ! $referencer ) {
return GetChunkReference( $name, 'default' );
}
elsif ( ref( $referencer ) eq 'CODE' ) {
return &$referencer($name);
}
else {
return GetChunkReference( $name, $referencer );
}
}
#---------------------------------------------------------------------
sub HandleDocs {
my ( $stuff, $chunk_number ) = @_;
my $lines = ReadLinesUntil( '@end docs ' . $chunk_number );
my $last_was_nl = 0;
foreach my $line ( @$lines ) {
if ( $line =~ m/\A@[t]ext (.*)\z/ ) {
my $text = $1;
print STDOUT $text;
$last_was_nl = 0 if $text;
}
elsif ( $line =~ m/\A@[n]l\z/ ) {
if ( $last_was_nl == 1 ) {
print STDOUT "\n\n";
}
else {
print STDOUT " ";
}
++$last_was_nl;
}
elsif ( $line =~ m/\A@[q]uote\z/ ) {
print STDOUT "[cci]";
$last_was_nl = 0;
}
elsif ( $line =~ m/\A@[e]ndquote\z/ ) {
print STDOUT "[/cci]";
$last_was_nl = 0;
}
elsif ( $line =~ m/\A@[u]se (.*)\z/ ) {
my $name = $1;
my $reference = GetChunkReference( $name, 'default' );
print STDOUT $reference;
$last_was_nl = 0;
}
}
}
#---------------------------------------------------------------------
sub MakeAnchor {
my ( $name, $seq ) = @_;
my $ret = ( $seq > 0 ) ? "$name $seq" : "$name";
$ret =~ s/\s+/-/g;
return $ret;
}
#---------------------------------------------------------------------
sub HandleCode {
my ( $stuff, $chunk_number ) = @_;
my $lines = ReadLinesUntil( '@end code ' . $chunk_number );
my $lang = '';
my $name = '';
foreach my $line ( @$lines ) {
if ( $line =~ m/\A@[l]anguage (.*)\z/ ) {
$lang = $1;
}
elsif ( $line =~ m/\A@[d]efn (.*)\z/ ) {
$name = $1;
}
}
my $seq = scalar @{ $stuff->{'chunks_for'}{$name} || [] };
my $anchor = MakeAnchor( $name, $seq );
push @{ $stuff->{'chunks_for'}{$name} }, $anchor;
print STDOUT "";
print STDOUT "[cc";
print STDOUT " lang=\"$lang\"" if $lang;
print STDOUT "]\n";
print STDOUT MakeChunkNameComment( $name, $seq, $lang );
foreach my $line ( @$lines ) {
if ( $line =~ m/\A@[t]ext (.*)\z/ ) {
my $text = $1;
print STDOUT $text;
}
elsif ( $line =~ m/\A@[n]l\z/ ) {
print STDOUT "\n";
}
elsif ( $line =~ m/\A@[u]se (.*)\z/ ) {
my $name = $1;
my $reference = GetChunkReference( $name, $lang );
print STDOUT $reference;
}
}
print STDOUT "[/cc]\n";
}