src/Tools/8bit/perl/generators/gen-isadoc.pl
author wenzelm
Mon, 29 Nov 1999 15:52:49 +0100
changeset 8039 a901bafe4578
parent 4636 f6b89d9b0076
permissions -rwxr-xr-x
Goal: tuned pris;

#!/usr/local/dist/bin/perl
'di';
'ig00';
###############################################
# Title:      Tools/8bit/perl/generators/gen-isa2latex
# ID:         $Id$
# Author:     Franz Regensburger
# Copyright   1996 TU Muenchen
#
# generates documentation form on the basis of the configuration
# files for keyboard map and translations
#
# Franz Regensburger <regensbu@informatik.tu-muenchen.de> 8.3.95
###############################################

# I like to see the output as it happens (flushed output)

$| = 1;

# cash current working directory 
require "pwd.pl";
&initpwd;

$initial_dir = $ENV{'PWD'};

########################
# comand line processing
# processes all known switches and ingnores others.
# First non-switch which is the name of a text file is 
# interpreted as name of translation file.
# Second non-switch which is the name of a text file is 
# interpreted as name of the keymap file.
#

# initialize
$translation_file="";
$keymap_file="";
$do_debug = 0;
$do_ddebug = 0;
$latex2e = 0;


while (@ARGV){
    $cur_arg = shift @ARGV;
    if ($cur_arg eq '-d')  {$do_debug = 1;}
    elsif ($cur_arg eq '-dd') {$do_debug = 1; $do_ddebug = 1;}
    elsif ($cur_arg eq '-2e') {$latex2e = 1;}
    elsif ((-T $cur_arg) && !$translation_file) {$translation_file = $cur_arg;}
    elsif ((-T $cur_arg) && !$keymap_file) {$keymap_file = $cur_arg;}
}

# complain if no translationsfile is found

if ($translation_file eq "") {
    print "\nno translation file suplied or argument is not a text file\n\n";
    print "usage gen-isadoc [-d -dd -2e ] translation-file keymap-file\n", 
          "options must be seperated by blanks!";
    die "\n";
}

if ($keymap_file eq "") {
    print "\nno keymap file suplied or argument is not a text file\n\n";
    print "usage gen-isadoc [-d -dd -2e] translation-file keymap-file\n", 
          "options must be seperated by blanks!";
    die "\n";
}

print "debug mode is on\n" if $do_debug;
print "double debug mode is on\n" if $do_ddebug;
print "documentation is produced with LaTeX-2e\n" if ($do_debug & $latex2e);
print "documentation is produced with LaTeX 2.09\n" if ($do_debug &!$latex2e);
print "name of translation file is $translation_file\n" if $do_debug;
print "name of keymap file is $keymap_file\n" if $do_debug;

########################
# open the translations  file

open(INFILE,$translation_file) || die "can't open $translation_file: $!\n";
print "opened translation file,\nprocessing\n" if $do_debug;

########################
# configuration of HI_TABLE
print "\nsetup for HI_TABLE\n" if $do_debug;

########################
# search for START_HI_TABLE
#
$start_hi_table = 
    &look_for_value('^\s*START_HI_TABLE\s*"(\d+)"',"START_HI_TABLE");

if ($start_hi_table eq "") {
    die "\ncan't find START_HI_TABLE in translation file\n";}

if ($start_hi_table < 128 || 255 < $start_hi_table) {
    die "\nSTART_HI_TABLE not in range 128 - 255\n";}

########################
# search for BEGIN_HI_TABLE

$found = &look_for_label('^\s*BEGIN_HI_TABL(E)',"BEGIN_HI_TABLE");

if ($found eq "") {
    die "\ncan't find BEGIN_HI_TABLE in translation file\n";}

########################
# read the HI_TABLE

$index = 0;
#$max_hi_len = 0; # for pretty printing
$found = 0;
$end_hi_table = 0;
$pattern = '^>\s*"([^"]*)"\s*"([^"]*)"\s*"([^"]*)"';

while (<INFILE> ){
    if (/^\s*END_HI_TABLE/){
	    print "line $.: END_HI_TABLE found\n" if $do_debug;
	    $found = 1;
	    $end_hi_table = $start_hi_table + $index - 1;
	    last;}
    elsif (($temp1,$temp2,$temp3) = /$pattern/){
	# no doubling of backslashes needed for docu files
#	$max_hi_len = length($temp2) if $max_hi_len < length($temp2);
	$hi_table[$index]= join('"',$temp2,$temp3);
	 # the " as seperator is perfect since it cannot occur inside the strings
	 # backslashes are duplicated
	printf "line $.: \"%s\" \t\t \"%s\"\n", 
	       $temp2,$temp3 if $do_ddebug;
	$index++;
    }
}

if (!$found){
	die "\ncan't find END_HI_TABLE in translation file\n";}

if ($end_hi_table < $start_hi_table || 255 < $end_hi_table ){
	die "\nEND_HI_TABLE $end_hi_table not in range $start_low_table - 255\n";}
    else {print "computed index for END_HI_TABLE is $end_hi_table\n"  if $do_debug;
#          print "maximal length of entries is $max_hi_len\n"   if $do_ddebug;
}

########################
# configuration of SEQ_TABLE
print "\nsetup for SEQ_TABLE\n" if $do_debug;

########################
# search for BEGIN_SEQ_TABLE

$found = &look_for_label('^\s*BEGIN_SEQ_TABL(E)',"BEGIN_SEQ_TABLE");

if ($found eq "") {
    die "\ncan't find BEGIN_SEQ_TABLE in translation file\n";}


########################
# read the SEQ_TABLE

$index = 0;
#$max_seq_len = 0; # for pretty printing
$found = 0;
$seq_table = 0;
$pattern = '^>\s*"([^"]*)"\s*"([^"]*)"\s*"([^"]*)"\s*"([^"]*)"';

while (<INFILE> ){
    if (/^\s*END_SEQ_TABLE/){
	    print "line $.: END_SEQ_TABLE found\n" if $do_debug;
	    $found = 1;
	    $seq_table = $index;
	    last;}
        elsif (($temp1,$temp2,$temp3,$temp4) = /$pattern/){
#	    $max_seq_len = length($temp1) if $max_seq_len < length($temp1);
	    $seq_table[$index]= join('"',$temp1,$temp4);
	     # the " as seperator is perfect since it cannot occur inside the strings
	     # backslashes are only expanded in the latex replacement
	    printf "line $.: \"%s\" \t\t \"%s\"\n", 
	           $temp3, $temp4 if $do_ddebug;
	    $index +=1;
	}
}

if ($found == 0) {
    die "\ncan't find END_SEQ_TABLE in translation file\n";}
    else {print "computed index for SEQ_TABLE is $seq_table\n"  if $do_debug;
#          print "maximal length of entries is $max_seq_len\n"   if $do_ddebug;
}

########################
# we reached the end of the translation file

print "\nprocessing of translation file completed\n" if $do_debug;

########################
# close the handle for config file
close(INFILE);
print "closed translation file\n" if $do_debug;

########################
# open the keymap file

open(INFILE,$keymap_file) || die "can't open $keymap_file: $!\n";
print "opened keymap file,\nprocessing\n" if $do_debug;

########################
# search for PACK

$pack = $ENV{'ISABELLE8BIT'};

if ($pack eq "") {
    die "\ncan't find label PACK in keymap file\n";}

if (! (-d $pack)){
    die "\nPACK is not a directory\n";}


########################
# configuration of KEY_MAP
print "\nsetup for KEY_MAP\n" if $do_debug;

########################
# search for BEGIN_KEY_MAP

$found = &look_for_label('^\s*BEGIN_KEY_MA(P)',"BEGIN_KEY_MAP");

if ($found eq "") {
    die "\ncan't find BEGIN_KEY_MAP in keymap file\n";}
				 
########################
# read the KEY_MAP

$index = 0;
$found = 0;
$end_key_map = 0; 
$pattern = 
'^\s*MOD\s*(None|Mod1|Mod2|Mod4|Shift|Ctrl)\s*KEY\s*([a-zA-Z]+|F\d{1,2})\s*CODE\s*([0-9a-fA-F][0-9a-fA-F](\s*,\s*[0-9a-fA-F][0-9a-fA-F])*)\s*$';

#'

while (<INFILE> ){
    if (/^\s*END_KEY_MAP/){
	    print "line $.: END_KEY_MAP found\n" if $do_debug;
	    $found = 1;
	    $end_key_map = $index - 1;
	    last;}
    elsif (($modifiers,$key,$codeseq) = /$pattern/){
	$key_map[$index]= join(':',$modifiers,$key,$codeseq);
	print "line $.: \"$key_map[$index]\"\n" if $do_ddebug;
	$index +=1;
    }
    else {
	print "Is this a comment? line $.: $_\n" ;}
}
if (!$found){
	die "\ncan't find END_KEY_MAP in keymap file\n";}

if ($end_low_table < $start_low_table){
	die "\nNo entries in KEY_MAP\n";}
    else {print 
	"computed index for END_KEY_MAP is $end_key_map\n" if $do_debug;}

########################
# we reached the end of the keymap file

print "\nprocessing of keymap file completed\n" if $do_debug;

########################
# close the handle for config file 
close(INFILE);
print "closed keymap file\n" if $do_debug;

#######################################################################
# generate the documentation
#######################################################################

########################
# change to directory `doc' 
				 
chdir $pack."/doc" || die "can't cd to directory $pack/doc: $!\n";


########################
# open the file `fontindex.tex' 
print "generating LaTeX file `fontindex.tex'\n" if $do_debug;

$filename = "fontindex.tex";
open(OUTFILE,">$filename") || die "can't open file $filename: $!\n";
print "opened $filename for writing\n" if $do_ddebug;


########################
# generate the fonttable
# 

#initialize the fonttable

$index = $start_hi_table;
while ($index <= $end_hi_table) {
    $fonttable[$index - $start_hi_table]=$hi_table[$index - $start_hi_table]; 
    $index++;
}

# append information from the keymap

$index = 0;
while ($index <= $end_key_map) {
    ($mod,$key,$code) = split(/:/,$key_map[$index]);
    # split the sequence of key codes
    @codelist = split(/\s*,\s*/,$code);

    if ($#codelist == 0 && # not a code sequence
        $start_hi_table <= hex($codelist[0]) && 
        hex($codelist[0]) <= $end_hi_table ) { # we are in range of hi_table

      #translate the modifier
      if ($mod eq "None") { # delete if None modifier 
         $mod = "";}
      elsif ($mod eq "Mod1"){ 
         $mod = "Meta";}
      elsif ($mod eq "Mod2"){
         $mod = "Alt";}
      elsif ($mod eq "Mod4"){ 
         $mod = "AltGraph";}
      elsif ($mod eq "Ctrl"){ 
         $mod = "Ctrl";}

      $fonttable[hex($codelist[0]) - $start_hi_table] = join('"',
            split(/\"/,$fonttable[hex($codelist[0]) - $start_hi_table]),
            $mod." ".$key);
      }
    $index++;
}


## print the TeX prelude
if ($latex2e){
printf OUTFILE 
'\documentclass[a4paper,11pt]{article}
\usepackage{latexsym,amssymb,supertab}

\begin{document}

\begin{center}
{\Large 
  Description of Isabelle Font \\\\ 
      Indexed by Code}\\\\
  Date: \today 

\vspace*{.5cm}

\tablehead{\hline
Oct & Dec & Hex & ASCII & \LaTeX & Key Sequence\\\\
\hline}
\tabletail{\hline}

\begin{supertabular}{|l|l|l|l|l|l|}
';
}
else{
printf OUTFILE 
'\documentstyle[a4,11pt,latexsym,amssymb,supertab]{article}
\begin{document}

\begin{center}
{\Large 
  Description of Isabelle Font \\\\ 
      Indexed by Code}\\\\
  Date: \today 

\vspace*{.5cm}

\tablehead{\hline
Oct & Dec & Hex & ASCII & \LaTeX & Key Sequence\\\\
\hline}
\tabletail{\hline}

\begin{supertabular}{|l|l|l|l|l|l|}
';
}
## print the fonttable

$index = $start_hi_table;
while ($index <= $end_hi_table) {
    ($ascii,$latex,$keystring) = split(/\"/,
                                     $fonttable[$index - $start_hi_table],3);

    # generate List of Keystrokes
    @keylist = split(/\"/,$keystring);

    $keystring= shift(@keylist);
    foreach $string (@keylist){
   	$keystring .= ", $string";}

    if ($index == $end_hi_table) {
        $postfix = "\\\\";}
    else {$postfix = "\\nextline";}
       
   
    printf(OUTFILE "%o & %d & %x & %s & %s & %s$postfix\n", 
                 $index,
                 $index,
                 $index,
                 "\\verb*\"".$ascii."\"",
                 $latex,
                 $keystring);

    $index++;
}

## print rest of TeX
printf OUTFILE 
'\end{supertabular}
\end{center}
\end{document}
';

close(OUTFILE);
print "closed $filename\n" if $do_ddebug;

########################
# open the file `keyindex.tex' 
print "generating LaTeX file `keyindex.tex'\n" if $do_debug;

$filename = "keyindex.tex";
open(OUTFILE,">$filename") || die "can't open file $filename: $!\n";
print "opened $filename for writing\n" if $do_ddebug;


########################
# generate an assoc array of those lex-expressions in seq_table that consist
# purely of hexnumbers or graphical characters (with highest bit set). 
# These are candidates for the codesequences in key_map.
#
# This is just a simple heuristic!
# 

print "compute the assoc array of code sequences\n" if $do_ddebug;

$index = 0;
while ($index < $seq_table ) {
    ($temp1,$temp2) = split(/\"/,$seq_table[$index]); 
    if ($temp1 =~ /^(\\x[0-9a-fA-F][0-9a-fA-F])+$/){# filter out the pure hex sequences
       	$temp1 =~ s/\\x([0-9a-fA-F][0-9a-fA-F])/$1,/g;
	chop($temp1);
	print "found candidate: key $temp1  latex $temp2\n" if $do_ddebug;
	$assoc_seq_table{$temp1} = $temp2;}
    elsif ($temp1 =~ /^([\x80-\xff])+$/){# filter out the pure graphical characters
	$temp1 = unpack("H*",$temp1);
        $temp1 =~ /^([0-9a-f][0-9a-f])+$/;
       	$temp1 =~ s/([0-9a-f][0-9a-f])/$1,/g;
	chop($temp1);
	print "found candidate: key $temp1  latex $temp2\n" if $do_ddebug;
	$assoc_seq_table{$temp1} = $temp2;}

    $index++;
}

########################
# generate the keytable
# 

$index = 0;
while ($index <= $end_key_map) {
     ($mod,$key,$code) = split(/:/,$key_map[$index]);

     #translate the modifier `None' for sorting; a dirty trick
     if ($mod eq "None") { # delete if None modifier 
        $mod = "AAAA";}
     
     @codelist = split(/\s*,\s*/,$code);
     if ($#codelist != 0){ # we have  a code sequence, look up in assoc array
	 $latex = $assoc_seq_table{join(',',@codelist)};
	 if ($latex eq "") {# there was no assoc
	    $latex = "unknown";}
	}	 
     elsif ( $start_hi_table <= hex($codelist[0]) && 
             hex($codelist[0]) <= $end_hi_table ) {# we are in range of hi_table
       @temp4 = split(/\"/,$hi_table[hex($codelist[0]) - $start_hi_table]);
       $latex = pop(@temp4);}

     else { # we can"t associate a LaTeX code
	 $latex = "unknown";}

     $keytable[$index]= join('"',$mod,$key,join(',',@codelist),$latex);
     $index++;
}

########################
# sort the keytable
# 

@keytable = sort(sortbykey @keytable);


## print the TeX prelude
if ($latex2e){
printf OUTFILE 
'\documentclass[a4paper,11pt]{article}
\usepackage{latexsym,amssymb,supertab}

\begin{document}

\begin{center}
{\Large 
  Description of Keyboard Mapping\\\\
      Indexed by Key Sequence}\\\\
  Date: \today 

\vspace*{.5cm}

\tablehead{\hline
Key Sequence & Code Sequence in Hex & \LaTeX \\\\
\hline}
\tabletail{\hline}

\begin{supertabular}{|l|l|l|}
';
}
else {
printf OUTFILE 
'\documentstyle[a4,11pt,latexsym,amssymb,supertab]{article}
\begin{document}

\begin{center}
{\Large 
  Description of Keyboard Mapping\\\\
      Indexed by Key Sequence}\\\\
  Date: \today 

\vspace*{.5cm}

\tablehead{\hline
Key Sequence & Code Sequence in Hex & \LaTeX \\\\
\hline}
\tabletail{\hline}

\begin{supertabular}{|l|l|l|}
';
}
## print the keyboard mapping

$index = 0;
while ($index <= $end_key_map) {
    ($mod,$key,$code,$latex) = split(/\"/,$keytable[$index]);

    #translate the modifier
      if ($mod eq "AAAA") { # delete if AAAA rsp. None modifier 
         $mod = "";}
      elsif ($mod eq "Mod1"){ 
         $mod = "Meta";}
      elsif ($mod eq "Mod2"){
         $mod = "Alt";}
      elsif ($mod eq "Mod4"){ 
         $mod = "AltGraph";}
      elsif ($mod eq "Ctrl"){ 
         $mod = "Ctrl";}

    if ($index == $end_key_map) {
        $postfix = "\\\\";}
    else {$postfix = "\\nextline";}

    printf(OUTFILE "%s & %s & %s$postfix\n", 
                 $mod." ".$key,
                 $code,
	   $latex);

    $index++;
}


## print rest of TeX
printf OUTFILE 
'\end{supertabular}
\end{center}
\end{document}
';

close(OUTFILE);
print "closed $filename\n" if $do_ddebug;

########################
# open the file `fkmatrix.tex' 
print "generating LaTeX file `fkmatrix.tex'\n" if $do_debug;

$filename = "fkmatrix.tex";
open(OUTFILE,">$filename") || die "can't open file $filename: $!\n";
print "opened $filename for writing\n" if $do_ddebug;


########################
# generate the matrix for function key mappings
# 
# we support only documentation of keys F1 - F12 

# initialize the assoc array

$fkmat{"AAAA"} = join('"',(" "," "," "," "," "," "," "," "," "," "," "," "));
$fkmat{"Mod1"} = join('"',(" "," "," "," "," "," "," "," "," "," "," "," "));
$fkmat{"Mod2"} = join('"',(" "," "," "," "," "," "," "," "," "," "," "," "));
$fkmat{"Mod4"} = join('"',(" "," "," "," "," "," "," "," "," "," "," "," "));
$fkmat{"Ctrl"} = join('"',(" "," "," "," "," "," "," "," "," "," "," "," "));

print "building fkmatrix\n" if $do_ddebug;

$index = 0;
while ($index <= $end_key_map) {
    local (@keylist);

    ($mod,$key,$code,$latex) = split(/\"/,$keytable[$index]);

    if ($key =~ /^F\d{1,2}$/){ # key is a function key
	$key =~ s/^F(\d{1,2})$/$1/;
	@keylist = split(/\"/,$fkmat{$mod});
	if( 0<$key && $key<=12){
            # we support only F1 - F12
	    $keylist[$key-1]=$latex;}
	$fkmat{$mod} = join('"',@keylist);    
    }
    $index++;
}
print "fkmatrix completed\n" if $do_ddebug;

## print the TeX prelude
if ($latex2e){
printf OUTFILE 
'\documentclass[a4paper,11pt]{article}
\usepackage{latexsym,latexsym,amssymb,supertab}

\begin{document}

\begin{center}
{\Large 
  Keyboard Mapping for Function Keys F1 - F12}\\\\ 
  Date: \today 

\vspace*{.5cm}

\tablehead{\hline
Modifier & F1 &F2 &F3 &F4 &F5 &F6 &F7 &F8 &F9 & F10 &F11 &F12\\\\
\hline}
\tabletail{\hline}

\begin{supertabular}{|l|l|l|l|l|l|l|l|l|l|l|l|l|}
';}
else {
printf OUTFILE 
'\documentstyle[a4,11pt,latexsym,amssymb,supertab]{article}
\begin{document}

\begin{center}
{\Large 
  Keyboard Mapping for Function Keys F1 - F12}\\\\ 
  Date: \today 

\vspace*{.5cm}

\tablehead{\hline
Modifier & F1 &F2 &F3 &F4 &F5 &F6 &F7 &F8 &F9 & F10 &F11 &F12\\\\
\hline}
\tabletail{\hline}

\begin{supertabular}{|l|l|l|l|l|l|l|l|l|l|l|l|l|}
';
}
## print the matrix
printf(OUTFILE "None&%s\\nextline\n",
       join('&',split(/\"/,$fkmat{"AAAA"})));
printf(OUTFILE "\\hline\n");
printf(OUTFILE "Shift&%s\\nextline\n",
       join('&',split(/\"/,$fkmat{"Shift"})));
printf(OUTFILE "\\hline\n");
printf(OUTFILE "Ctrl&%s\\\\\n",
       join('&',split(/\"/,$fkmat{"Ctrl"})));
printf(OUTFILE "\\hline\n");
printf(OUTFILE "Alt&%s\\nextline\n",
       join('&',split(/\"/,$fkmat{"Mod2"})));
printf(OUTFILE "\\hline\n");
printf(OUTFILE "AltGraph&%s\\nextline\n",
       join('&',split(/\"/,$fkmat{"Mod4"})));
printf(OUTFILE "\\hline\n");
printf(OUTFILE "Meta&%s\\nextline\n",
       join('&',split(/\"/,$fkmat{"Mod1"})));

## print rest of TeX
printf OUTFILE 
'\end{supertabular}
\end{center}
\end{document}
';

close(OUTFILE);
print "closed $filename\n" if $do_ddebug;

########################
# execute  Makefile

print "\nexecuting Makefile\n" if $do_debug;
$status = system("make fontdocfiles") ;
if ($status) { die "\"make fontdocfiles\" executed abnormally: $!\n";}

#print "\nexecuting Makefile, cleaning up\n" if $do_debug;
#$status = system("make clean");
#if ($status) { die "\"make clean\" executed abnormally: $!\n";}

########################
# END of script
# 

print "\ngeneration of font and keymap documentation properly terminated\n\n";
exit(0);

#######################################################################
# subroutines
#######################################################################

sub look_for_value {
    local ($pattern,$label) = @_;
    local ($temp) = "";

    while (<INFILE> ){
	if (($temp) = /$pattern/){
	    print "line $.: $label is $temp\n" if $do_debug;
	    last;}
    }
    return $temp;
}


sub look_for_label {
    local ($pattern,$label) = @_;
    local ($temp) = "";

    while (<INFILE> ){
	if (($temp) = /$pattern/){
	    print "line $.: $label found\n" if $do_debug;
	    last;}
    }
    return $temp;
}

sub replicate_until {
    local ($pattern,$label) = @_;
    local ($temp) = "";

    while (<INFILE> ){
	if (($temp) = /$pattern/){
	    print "line $.: $label found\n" if $do_debug;
	    last;}
	else {printf(OUTFILE "%s",$_);}
    }
    return $temp;
}

sub skip_until {
    local ($pattern,$label) = @_;
    local ($temp) = "";

    while (<INFILE> ){
	if (($temp) = /$pattern/){
	    print "line $.: $label found\n" if $do_debug;
	    last;}
    }
    return $temp;
}

sub double_bs {
    local ($string) = @_;
    local ($element);
    local (@temp1);
    local (@temp2) = (); 

    # find the hex-numbers
    @temp1 = split(/(\\x[0-9a-fA-F][0-9a-fA-F])/,$string);

    #duplicate all backslashes in elements which are not hexnumbers
    while(@temp1) { 
	$element = shift(@temp1);
	if ($element =~ /\\x[0-9a-fA-F][0-9a-fA-F]/){
	    push(@temp2,$element);} 
	else{
	    $element =~ s/\\/\\\\/g;
	    push(@temp2,$element);}
    }
    return (join('',@temp2));
}

sub squeeze_bs {
    local ($string) = @_;

    $string =~ s/\\\\/\\/g;
    return $string;
}

sub show_blanks {
    local ($string) = @_;

    $string =~ s/ /\\_/g;
    return $string;
}

sub sortbykey {
    local ($mod1,$key1,$code1,$latex1) = split(/\"/,$a);
    local ($mod2,$key2,$code2,$latex2) = split(/\"/,$b);

    if ($mod1 eq $mod2){ # subsort by key 
	if ($key1 =~ /^F\d{1,2}$/){ # key1 is a function key
	    if ($key2 =~ /^F\d{1,2}$/){ # key2 is a function key too 
		$key1 =~ s/^F(\d{1,2})$/$1/;
		$key2 =~ s/^F(\d{1,2})$/$1/;
		return (int($key1) <=> int($key2));}
	    else {return 1;}  # function is always greater
	    } 
	elsif ($key2 =~ /^F\d{1,2}$/){ # key2 is a function key, key1 not
	      return -1;} # non function is always less
	else { # both are non function keys
	    return ($key1 cmp $key2);}
    }
    else { return ($mod1 cmp $mod2);}
}
###############################################################

    # These next few lines are legal in both Perl and nroff.

.00;                       # finish .ig
 
'di           \" finish diversion--previous line must be blank
.nr nl 0-1    \" fake up transition to first page again
.nr % 0         \" start at page 1
'; __END__ ##### From here on it's a standard manual page #####