1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
#!/usr/bin/perl -w
use strict;
my (%OPS, %MAP_FUNC_TO_OP, %MAP_OP_TO_SEQSET, %DOC, $map);
my (%GENERIC_OP_TO_FUNC);
my $xml = shift @ARGV;
open F, "cat @ARGV |" or die "OPS*: $!";
while (<F>) {
if ( /^\s+_fmt\((\w+),\s+N_\("(.+)"\)\)/ ) {
$OPS{$1} = $2;
}
}
close F;
while (<STDIN>) {
if (/^const struct MenuFuncOp Op.*{ \/\* map: (.*) \*\//) {
$map = $1;
$DOC{$map} = "";
$MAP_FUNC_TO_OP{$map} = {};
$MAP_OP_TO_SEQSET{$map} = {};
while (<STDIN>) {
last if (/^}/);
if (/^\s*\*\*\s*(.*)/) {
$DOC{$map} .= "$1\n";
}
elsif (/{\s*"(.+)"\s*,\s*(\w+)\s*}/) {
my ($function, $op) = ($1, $2);
die "unknown OP $op" unless $OPS{$op};
$MAP_OP_TO_SEQSET{$map}->{$op} = {};
if (!exists($MAP_FUNC_TO_OP{$map}->{$function})) {
$MAP_FUNC_TO_OP{$map}->{$function} = $op;
}
if ($map eq "generic" && !exists($GENERIC_OP_TO_FUNC{$op})) {
$GENERIC_OP_TO_FUNC{$op} = $function;
}
}
}
}
elsif (/^const struct MenuOpSeq .*{ \/\* map: (.*) \*\//) {
$map = $1;
die "unknown map $map" unless $MAP_FUNC_TO_OP{$map};
while (<STDIN>) {
last if (/^}/);
if (/{\s*(\w+)\s*,\s*"(.+)"\s*}/) {
my ($op, $binding) = ($1, $2);
# If the $op is NOT in the current map, but it IS
# in the generic map, then we need to add a stub entry
# in $MAP_FUNC_TO_OP and $MAP_OP_TO_SEQSET for this case.
unless ($MAP_OP_TO_SEQSET{$map}->{$op}) {
if (($map eq "pager") or ($map eq "editor")) {
die "unknown OP $op for map $map";
}
my $function = $GENERIC_OP_TO_FUNC{$op};
unless ($function) {
die "unknown OP $op for map $map";
}
$MAP_FUNC_TO_OP{$map}->{$function} = $op;
$MAP_OP_TO_SEQSET{$map}->{$op} = {};
}
$binding =~ s/&/&/;
# for <key>, try CamelCasing into <Key>
$binding =~ s/<(.)(.+)>/<\U$1\E$2>/;
$binding =~ s/</</;
$binding =~ s/>/>/;
$binding =~ s/ /<Space>/;
$binding =~ s/^\\033/Esc /;
$binding =~ s/^\\010/<Backspace>/;
$binding =~ s/^\\177/<Delete>/;
$binding =~ s/^\\(0\d+)$/'^'.chr(64+oct($1))/e;
$binding =~ s/^\\(0\d+)(.)/'^'.chr(64+oct($1)) ." $2"/e;
$binding =~ s/\\t/<Tab>/;
$binding =~ s/\\r/<Return>/;
$binding =~ s/\\n/<Enter>/;
die "unknown key $binding" if $binding =~ /\\[^\\]|<|>/;
$MAP_OP_TO_SEQSET{$map}->{$op}->{$binding} = 1;
}
}
}
}
open XML, $xml or die "$xml: $!";
while (<XML>) {
if (/__print_map\((.*)\)/) {
my $map = $1;
my $mapid = $1;
my $maptitle = $1;
$mapid =~ s/\s+/-/g;
$maptitle =~ s/\b(\w)/\u$1/g;
unless ($MAP_FUNC_TO_OP{$map}) {
warn "map $map undefined";
next;
}
print <<EOT;
<sect2 id="${mapid}-map">
<title>$maptitle Menu</title>
$DOC{$map}
<table id="tab-${mapid}-bindings">
<title>Default $maptitle Menu Bindings</title>
<tgroup cols="3">
<thead>
<row><entry>Function</entry><entry>Default key</entry><entry>Description</entry></row>
</thead>
<tbody>
EOT
# Sort the map entries by function, then by binding
foreach my $function (sort keys %{$MAP_FUNC_TO_OP{$map}}) {
my $op = $MAP_FUNC_TO_OP{$map}->{$function};
my $bindings = $MAP_OP_TO_SEQSET{$map}->{$op};
if (scalar keys %{$bindings}) {
foreach my $binding (sort keys %{$bindings}) {
print "<row><entry><literal><" .
$function .
"></literal></entry><entry>" .
$binding .
"</entry><entry>" .
$OPS{$op} .
"</entry></row>\n";
}
}
else {
print "<row><entry><literal><" .
$function .
"></literal></entry><entry>" .
"</entry><entry>" .
$OPS{$op} .
"</entry></row>\n";
}
}
print <<EOT;
</tbody>
</tgroup>
</table>
</sect2>
EOT
delete $MAP_FUNC_TO_OP{$map};
} else {
print;
}
}
close XML;
warn "unprinted maps: ". join(" ", keys %MAP_FUNC_TO_OP) if %MAP_FUNC_TO_OP;
|