1 | #!/usr/bin/perl |
1 | #!/usr/bin/perl |
2 | |
2 | |
3 | use Pod::Tree; |
3 | # TODO: texinfo fails on @cindex in title elements etc. *sigh* |
|
|
4 | |
|
|
5 | use Pod::POM; |
4 | |
6 | |
5 | sub escape_texi($) { |
7 | sub escape_texi($) { |
6 | local $_ = shift; |
8 | local $_ = shift; |
7 | s/([\@\{\}])/\@$1/g; |
9 | s/([\@\{\}])/\@$1/g; |
8 | s/\n+/ /g; |
10 | s/\n+/ /g; |
9 | $_; |
11 | $_; |
10 | } |
12 | } |
11 | |
13 | |
12 | sub example { |
14 | sub example { |
13 | my $text = $_[0]; |
15 | my $text = $_[0]; |
14 | print "\n\n\@example\n"; |
|
|
15 | $text =~ s/\n+$//; |
16 | $text =~ s/\n+$//; |
16 | $text =~ s/([\@\{\}])/\@$1/g; |
17 | $text =~ s/([\@\{\}])/\@$1/g; |
17 | print $text; |
18 | |
|
|
19 | "\n\n\@example\n" |
|
|
20 | . $text |
18 | print "\n\@end example\n\n"; |
21 | . "\n\@end example\n\n"; |
19 | } |
22 | } |
20 | |
23 | |
21 | while (<>) { |
24 | my @nodes; # nodelist |
22 | if (/^\@c INCLUDE-(\S+) (\S+)/) { |
25 | my @ctx; # curstack |
23 | my $type = $1; |
|
|
24 | my $name = $2; |
|
|
25 | my $path = $2; |
|
|
26 | |
26 | |
27 | $name =~ s/\.(\d)$/($1)/; |
27 | sub out { |
28 | |
28 | $ctx[-1]{out} .= join "", @_; |
29 | print "\@chapter $name\n\n"; |
|
|
30 | |
|
|
31 | if ($type eq "POD") { |
|
|
32 | open my $x, "<$path.pod" or die "$path.pod: $!"; |
|
|
33 | my $data = do { local $/; <$x> }; |
|
|
34 | |
|
|
35 | my $pod = new Pod::Tree; |
|
|
36 | $pod->load_string($data); |
|
|
37 | |
|
|
38 | my $walker; $walker = sub { |
|
|
39 | my $n = $_[0]; |
|
|
40 | if ($n->is_code) { |
|
|
41 | # nop |
|
|
42 | } elsif ($n->is_link) { |
|
|
43 | my $target = $n->get_target; |
|
|
44 | my $page = $target->get_page; |
|
|
45 | my $section = $target->get_section; |
|
|
46 | |
|
|
47 | #print "<b>"; |
|
|
48 | $walker->($_) for @{$n->get_children}; |
|
|
49 | #print "</b>"; |
|
|
50 | } elsif ($n->is_text) { |
|
|
51 | print escape_texi $n->get_text; |
|
|
52 | } elsif ($n->is_verbatim) { |
|
|
53 | example $n->get_text; |
|
|
54 | } elsif ($n->is_sequence) { |
|
|
55 | if ($n->get_letter eq "C") { |
|
|
56 | print "\@t{"; |
|
|
57 | $walker->($_) for @{$n->get_children}; |
|
|
58 | print "}"; |
|
|
59 | } elsif ($n->get_letter eq "B") { |
|
|
60 | print "\@strong{"; |
|
|
61 | $walker->($_) for @{$n->get_children}; |
|
|
62 | print "}"; |
|
|
63 | } elsif ($n->get_letter eq "I" or $n->get_letter eq "F") { |
|
|
64 | print "\@emph{"; |
|
|
65 | $walker->($_) for @{$n->get_children}; |
|
|
66 | print "}"; |
|
|
67 | } else { |
|
|
68 | # S would mean to use nbsp |
|
|
69 | $walker->($_) for @{$n->get_children}; |
|
|
70 | } |
|
|
71 | } elsif ($n->is_command) { |
|
|
72 | if ($n->is_c_head1) { |
|
|
73 | print "\n\@section "; |
|
|
74 | $walker->($_) for @{$n->get_children}; |
|
|
75 | print "\n"; |
|
|
76 | } elsif ($n->is_c_head2) { |
|
|
77 | print "\n\n\@subsection "; |
|
|
78 | $walker->($_) for @{$n->get_children}; |
|
|
79 | print "\n"; |
|
|
80 | } else { |
|
|
81 | # nop? |
|
|
82 | } |
|
|
83 | } elsif ($n->is_ordinary) { |
|
|
84 | $walker->($_) for @{$n->get_children}; |
|
|
85 | print "\@refill\n"; |
|
|
86 | } elsif ($n->is_root) { |
|
|
87 | $walker->($_) for @{$n->get_children}; |
|
|
88 | } elsif ($n->is_list) { |
|
|
89 | print "\n\n\@itemize\n"; |
|
|
90 | $walker->($_) for @{$n->get_children}; |
|
|
91 | print "\@end itemize\n\n"; |
|
|
92 | } elsif ($n->is_item) { |
|
|
93 | print "\n\n\@item\n"; |
|
|
94 | print "\@b{"; |
|
|
95 | $walker->($_) for @{$n->get_children}; |
|
|
96 | print "}\n\n"; |
|
|
97 | $walker->($_) for @{$n->get_siblings}; |
|
|
98 | } else { |
|
|
99 | die "UNKNOWN NODE $_[0]{type}<br/>"; |
|
|
100 | $walker->($_) for @{$n->get_children}; |
|
|
101 | } |
|
|
102 | }; |
|
|
103 | |
|
|
104 | $walker->($pod->get_root); |
|
|
105 | } elsif ($type eq "TEXT") { |
|
|
106 | open my $x, "<$path" or die "$path: $!"; |
|
|
107 | my $data = do { local $/; <$x> }; |
|
|
108 | |
|
|
109 | print $data; |
|
|
110 | } elsif ($type eq "EXAMPLE") { |
|
|
111 | open my $x, "<$path" or die "$path: $!"; |
|
|
112 | my $data = do { local $/; <$x> }; |
|
|
113 | |
|
|
114 | example $data; |
|
|
115 | } |
|
|
116 | } else { |
|
|
117 | print; |
|
|
118 | } |
|
|
119 | } |
29 | } |
120 | |
30 | |
|
|
31 | sub TEX::view_seq_code { "\@t{$_[1]}" } |
|
|
32 | sub TEX::view_seq_bold { "\@strong{$_[1]}" } |
|
|
33 | sub TEX::view_seq_italic { "\@emph{$_[1]}" } |
|
|
34 | |
|
|
35 | sub TEX::view_seq_space { escape_texi $_[1] } |
|
|
36 | sub TEX::view_seq_text { escape_texi $_[1] } |
|
|
37 | |
|
|
38 | sub TEX::view_seq_link { $_[1] } |
|
|
39 | sub TEX::view_seq_index { |
|
|
40 | "\n\@cindex $_[1]\n$_[1]" |
|
|
41 | } |
|
|
42 | |
|
|
43 | *TXT::view_seq_code = |
|
|
44 | *TXT::view_seq_bold = |
|
|
45 | *TXT::view_seq_italic = |
|
|
46 | *TXT::view_seq_space = |
|
|
47 | *TXT::view_seq_text = |
|
|
48 | *TXT::view_seq_link = |
|
|
49 | *TXT::view_seq_index = sub { $_[1] }; |
|
|
50 | |
|
|
51 | my %ignore = ( |
|
|
52 | "SEE ALSO" => 1, |
|
|
53 | "AUTHOR" => 1, |
|
|
54 | ); |
|
|
55 | |
|
|
56 | sub parse_pod { |
|
|
57 | my ($data) = @_; |
|
|
58 | local $out; |
|
|
59 | |
|
|
60 | local $Pod::POM::DEFAULT_VIEW = TEX::; |
|
|
61 | |
|
|
62 | my $parser = new Pod::POM; |
|
|
63 | my $pod = $parser->parse_text ($data) |
|
|
64 | or die; |
|
|
65 | |
|
|
66 | my $walker; $walker = sub { |
|
|
67 | my $n = $_[0]; |
|
|
68 | my $t = $n->type; |
|
|
69 | |
|
|
70 | if ($t eq "text") { |
|
|
71 | out $n->text . "\n\@refill\n"; |
|
|
72 | |
|
|
73 | } elsif ($t eq "pod") { |
|
|
74 | $walker->($_) for $n->content; |
|
|
75 | |
|
|
76 | } elsif ($t eq "verbatim") { |
|
|
77 | out example $n->text; |
|
|
78 | |
|
|
79 | } elsif ($t eq "head1") { |
|
|
80 | |
|
|
81 | return if $ignore{$n->title}; |
|
|
82 | |
|
|
83 | out "\n\@section " . $n->title . "\n"; |
|
|
84 | $walker->($_) for $n->content; |
|
|
85 | out "\n"; |
|
|
86 | |
|
|
87 | } elsif ($t eq "head2") { |
|
|
88 | out "\n\n\@subsection " . $n->title . "\n"; |
|
|
89 | $walker->($_) for $n->content; |
|
|
90 | |
|
|
91 | } elsif ($t eq "over") { |
|
|
92 | out "\n\n\@itemize\n"; |
|
|
93 | $walker->($_) for $n->content; |
|
|
94 | out "\@end itemize\n\n"; |
|
|
95 | |
|
|
96 | } elsif ($t eq "item") { |
|
|
97 | out "\n\n\@item\n\@b{" . $n->title . "}\n\n"; |
|
|
98 | |
|
|
99 | if ($n->title->present (TXT::) =~ /^\s*([a-zA-Z0-9\-\_]+)\s*=/) { |
|
|
100 | out "\@cindex $1\n"; |
|
|
101 | } |
|
|
102 | $walker->($_) for $n->content; |
|
|
103 | |
|
|
104 | } elsif ($t eq "begin") { |
|
|
105 | local $Pod::POM::DEFAULT_VIEW = Pod::POM::View::Pod; |
|
|
106 | my $format = $n->format; |
|
|
107 | |
|
|
108 | if ($format =~ /texinfo\s+header/) { |
|
|
109 | $header = $n->content; |
|
|
110 | } elsif ($format =~ /texinfo\s+footer/) { |
|
|
111 | $footer = $n->content; |
|
|
112 | } else { |
|
|
113 | out $n->content; |
|
|
114 | } |
|
|
115 | |
|
|
116 | } elsif ($t eq "for") { |
|
|
117 | my $text = $n->text; |
|
|
118 | |
|
|
119 | if ($text =~ /^menu-begin/) { |
|
|
120 | out "\n\@menu\n"; |
|
|
121 | |
|
|
122 | push @ctx, {}; # dummy node |
|
|
123 | |
|
|
124 | } elsif ($text =~ /^menu-item (.*?)::\s+(.*)/) { |
|
|
125 | my ($name, $desc) = ($1, $2); |
|
|
126 | |
|
|
127 | push @{ $ctx[-2]{menu} }, [$name, $desc]; |
|
|
128 | $ctx[-2]{width} = length $name if $ctx[-2]{width} < length $name; |
|
|
129 | |
|
|
130 | my $ctx = { |
|
|
131 | name => $name, |
|
|
132 | up => $ctx[-2]{name}, |
|
|
133 | }; |
|
|
134 | push @nodes, $ctx; |
|
|
135 | $ctx[-1] = $ctx; |
|
|
136 | |
|
|
137 | } elsif ($text =~ /^menu-end/) { |
|
|
138 | pop @ctx; |
|
|
139 | |
|
|
140 | for (@{ $ctx[-1]{menu} }) { |
|
|
141 | out sprintf "* %-*s %s\n", $ctx[-1]{width} + 2, "$_->[0]::", $_->[1]; |
|
|
142 | } |
|
|
143 | |
|
|
144 | out "\@end menu\n"; |
|
|
145 | |
|
|
146 | } elsif ($text =~ /^include (\S+) (.*)/) { |
|
|
147 | my ($type, $path) = ($1, $2); |
|
|
148 | |
|
|
149 | open my $x, "<$path" or die "$path: $!"; |
|
|
150 | my $data = do { local $/; <$x> }; |
|
|
151 | |
|
|
152 | if ($type eq "pod") { |
|
|
153 | out parse_pod ($data); |
|
|
154 | } elsif ($type eq "text") { |
|
|
155 | out $data; |
|
|
156 | } elsif ($type eq "example") { |
|
|
157 | out example $data; |
|
|
158 | } |
|
|
159 | |
|
|
160 | } else { |
|
|
161 | die "UNKNOWN for command <$text>\n"; |
|
|
162 | } |
|
|
163 | |
|
|
164 | } else { |
|
|
165 | die "UNKNOWN NODE $t\n"; |
|
|
166 | } |
|
|
167 | }; |
|
|
168 | |
|
|
169 | $walker->($pod); |
|
|
170 | } |
|
|
171 | |
|
|
172 | @ctx = @nodes = { |
|
|
173 | up => "(dir)", |
|
|
174 | name => "Top", |
|
|
175 | }; |
|
|
176 | |
|
|
177 | parse_pod do { local $/; <> }; |
|
|
178 | |
|
|
179 | print $header; |
|
|
180 | |
|
|
181 | for (0 .. $#nodes) { |
|
|
182 | my $node = $nodes[$_]; |
|
|
183 | my $prev = $_ > 0 ? $nodes[$_-1] : undef; |
|
|
184 | my $next = $nodes[$_+1]; |
|
|
185 | my $chapter = $node->{name} eq "Top" ? "Introduction" : $node->{name}; |
|
|
186 | |
|
|
187 | print "\@node $node->{name},$next->{name},$prev->{name},$node->{up}\n\n", |
|
|
188 | "\@chapter $chapter\n", |
|
|
189 | "$node->{out}\n\n"; |
|
|
190 | } |
|
|
191 | |
|
|
192 | print $footer; |
|
|
193 | |