#!/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 () { next if ! /^OP_/; /(\w+)\s+N_\("(.+)"\)/ or die "$.: parse error"; $OPS{$1} = $2; } close F; while () { if (/^const struct menu_func_op_t Op.*{ \/\* map: (.*) \*\//) { $map = $1; $DOC{$map} = ""; $MAP_FUNC_TO_OP{$map} = {}; $MAP_OP_TO_SEQSET{$map} = {}; while () { 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_FUNC_TO_OP{$map}->{$function} = $op; $MAP_OP_TO_SEQSET{$map}->{$op} = {}; if ($map eq "generic") { $GENERIC_OP_TO_FUNC{$op} = $function; } } } } elsif (/^const struct menu_op_seq_t .*{ \/\* map: (.*) \*\//) { $map = $1; die "unknown map $map" unless $MAP_FUNC_TO_OP{$map}; while () { 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 , try CamelCasing into $binding =~ s/<(.)(.+)>/<\U$1\E$2>/; $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 () { 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 < $maptitle Menu $DOC{$map} Default $maptitle Menu Bindings FunctionDefault keyDescription 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 "<" . $function . ">" . $binding . "" . $OPS{$op} . "\n"; } } else { print "<" . $function . ">" . "" . $OPS{$op} . "\n"; } } print <
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;