#!/usr/bin/env perl
# $Id: mk-XKeysymDB,v 1.2 2012/07/22 22:31:05 friedman Exp $

use strict;
use Symbol;

my @header = qw(keysymdef.h
                ap_keysym.h
                DECkeysym.h
                HPkeysym.h
                Sunkeysym.h
                XF86keysym.h);

my @include = qw(/usr/include/X11
                 /usr/X11R6/include/X11
                 /usr/local/include/X11);

sub parse
{
  my ($fh, $tbl) = @_;
  my %collide;

  while (<$fh>)
    {
      if (m=^#define\s+(.*)XK_([\da-z_]+)\s+0x([\da-f]+)\s*(?:/\*\s*\(?(.*?)\)?\s*\*/|(.*))=i)
        {
          $tbl->{$1 . $2} = { keycode => $3,
                              desc    => $4,
                            };
        }
    }
}

sub sort_keysyms_pred
{
  my ($tbl, $a, $b) = @_;

  ((hex ($tbl->{$a}->{keycode}) <=> hex ($tbl->{$b}->{keycode}))
   || (lc ($a) cmp lc ($b))
   || ($a cmp $b));
}

sub display
{
  my ($tbl) = @_;

  for my $sym (sort { sort_keysyms_pred ($tbl, $a, $b) } keys %$tbl)
    {
      my $elt = $tbl->{$sym};
      if ($elt->{desc})
        {
          printf ("%-30s\t:%-8s\t! %s\n", $sym, uc ($elt->{keycode}), $elt->{desc});
        }
      else
        {
          printf ("%-30s\t:%s\n", $sym, uc ($elt->{keycode}));
        }
    }
}

sub open_header
{
  my $header = shift;
  my $fh = gensym;

  for my $dir (@include)
    {
      open ($fh, "$dir/$header") && return $fh;
    }
  return;
}

sub main
{
  my %tbl;

  for my $header (@header)
    {
      my $fh = open_header ($header);
      next unless $fh;
      parse ($fh, \%tbl);
    }

  display (\%tbl);
}

main (@ARGV);

# eof
