hxtool-conv.pl (4289B)
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 21use utf8; 22 23my $reading_texi = 0; 24my $texiblock = ''; 25my @tables = (); 26 27sub 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 40sub 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 49sub 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. 115while (<>) { 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 137die "Unexpectedly still in texi block at EOF" if $reading_texi;