]>
Commit | Line | Data |
---|---|---|
2b63ec5f PM |
1 | #!/usr/bin/perl -w |
2 | # | |
3 | # Script to convert .hx file STEXI/ETEXI blocks to SRST/ERST | |
4 | # | |
5 | # Copyright (C) 2020 Linaro | |
6 | # | |
7 | # This work is licensed under the terms of the GNU GPL, version 2 or | |
8 | # (at your option) any later version. See the COPYING file in the | |
9 | # top-level directory. | |
10 | ||
11 | # This script was only ever intended as a one-off conversion operation. | |
12 | # Please excuse the places where it is a bit hacky. | |
13 | # Some manual intervention after the conversion is expected, as are | |
14 | # some warnings from makeinfo. | |
15 | # Warning: this script is not idempotent: don't try to run it on | |
16 | # a .hx file that already has SRST/ERST sections. | |
17 | ||
18 | # Expected usage: | |
19 | # scripts/hxtool-conv.pl file.hx > file.hx.new | |
20 | ||
21 | use utf8; | |
22 | ||
23 | my $reading_texi = 0; | |
24 | my $texiblock = ''; | |
25 | my @tables = (); | |
26 | ||
27 | sub update_tables($) { | |
28 | my ($texi) = @_; | |
29 | # Update our list of open table directives: every @table | |
30 | # line in the texi fragment is added to the list, and every | |
31 | # @end table line means we remove an entry from the list. | |
32 | # If this fragment had a completely self contained table with | |
33 | # both the @table and @end table lines, this will be a no-op. | |
34 | foreach (split(/\n/, $texi)) { | |
35 | push @tables, $_ if /^\@table/; | |
36 | pop @tables if /^\@end table/; | |
37 | } | |
38 | } | |
39 | ||
40 | sub only_table_directives($) { | |
41 | # Return true if every line in the fragment is a start or end table directive | |
42 | my ($texi) = @_; | |
43 | foreach (split(/\n/, $texi)) { | |
44 | return 0 unless /^\@table/ or /^\@end table/; | |
45 | } | |
46 | return 1; | |
47 | } | |
48 | ||
49 | sub output_rstblock($) { | |
50 | # Write the output to /tmp/frag.texi, wrapped in whatever current @table | |
51 | # lines we need. | |
52 | my ($texi) = @_; | |
53 | ||
54 | # As a special case, if this fragment is only table directives and | |
55 | # nothing else, update our set of open table directives but otherwise | |
56 | # ignore it. This avoids emitting an empty SRST/ERST block. | |
57 | if (only_table_directives($texi)) { | |
58 | update_tables($texi); | |
59 | return; | |
60 | } | |
61 | ||
62 | open(my $fragfh, '>', '/tmp/frag.texi'); | |
63 | # First output the currently active set of open table directives | |
64 | print $fragfh join("\n", @tables); | |
65 | # Next, update our list of open table directives. | |
66 | # We need to do this before we emit the closing table directives | |
67 | # so that we emit the right number if this fragment had an | |
68 | # unbalanced set of directives. | |
69 | update_tables($texi); | |
70 | # Then emit the texi fragment itself. | |
71 | print $fragfh "\n$texi\n"; | |
72 | # Finally, add the necessary closing table directives. | |
73 | print $fragfh "\@end table\n" x scalar @tables; | |
74 | close $fragfh; | |
75 | ||
76 | # Now invoke makeinfo/pandoc on it and slurp the results into a string | |
77 | open(my $fh, '-|', "makeinfo --force -o - --docbook " | |
78 | . "-D 'qemu_system_x86 QEMU_SYSTEM_X86_MACRO' " | |
79 | . "-D 'qemu_system QEMU_SYSTEM_MACRO' /tmp/frag.texi " | |
80 | . " | pandoc -f docbook -t rst") | |
81 | or die "can't start makeinfo/pandoc: $!"; | |
82 | ||
83 | binmode $fh, ':encoding(utf8)'; | |
84 | ||
85 | print "SRST\n"; | |
86 | ||
87 | # Slurp the whole thing into a string so we can do multiline | |
88 | # string matches on it. | |
89 | my $rst = do { | |
90 | local $/ = undef; | |
91 | <$fh>; | |
92 | }; | |
93 | $rst =~ s/^- − /- /gm; | |
94 | $rst =~ s/“/"/gm; | |
95 | $rst =~ s/”/"/gm; | |
96 | $rst =~ s/‘/'/gm; | |
97 | $rst =~ s/’/'/gm; | |
98 | $rst =~ s/QEMU_SYSTEM_MACRO/|qemu_system|/g; | |
99 | $rst =~ s/QEMU_SYSTEM_X86_MACRO/|qemu_system_x86|/g; | |
100 | $rst =~ s/(?=::\n\n +\|qemu)/.. parsed-literal/g; | |
101 | $rst =~ s/:\n\n::$/::/gm; | |
102 | ||
103 | # Fix up the invalid reference format makeinfo/pandoc emit: | |
104 | # `Some string here <#anchorname>`__ | |
105 | # should be: | |
106 | # :ref:`anchorname` | |
107 | $rst =~ s/\`[^<`]+\<\#([^>]+)\>\`__/:ref:`$1`/gm; | |
108 | print $rst; | |
109 | ||
110 | close $fh or die "error on close: $!"; | |
111 | print "ERST\n"; | |
112 | } | |
113 | ||
114 | # Read the whole .hx input file. | |
115 | while (<>) { | |
116 | # Always print the current line | |
117 | print; | |
118 | if (/STEXI/) { | |
119 | $reading_texi = 1; | |
120 | $texiblock = ''; | |
121 | next; | |
122 | } | |
123 | if (/ETEXI/) { | |
124 | $reading_texi = 0; | |
125 | # dump RST version of block | |
126 | output_rstblock($texiblock); | |
127 | next; | |
128 | } | |
129 | if ($reading_texi) { | |
130 | # Accumulate the texi into a string | |
131 | # but drop findex entries as they will confuse makeinfo | |
132 | next if /^\@findex/; | |
133 | $texiblock .= $_; | |
134 | } | |
135 | } | |
136 | ||
137 | die "Unexpectedly still in texi block at EOF" if $reading_texi; |