Mercurial > vim
diff src/create_cmdidxs.pl @ 11236:62c96fee518e v8.0.0504
patch 8.0.0504: looking up an Ex command is a bit slow
commit https://github.com/vim/vim/commit/e5e0fbcd4244d032a0635ad7defe2831f251c639
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Mar 25 14:51:01 2017 +0100
patch 8.0.0504: looking up an Ex command is a bit slow
Problem: Looking up an Ex command is a bit slow.
Solution: Instead of just using the first letter, also use the second letter
to skip ahead in the list of commands. Generate the table with a
Perl script. (Dominique Pelle, closes #1589)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 25 Mar 2017 15:00:05 +0100 |
parents | |
children | 17ba19406c50 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/src/create_cmdidxs.pl @@ -0,0 +1,74 @@ +#!/usr/bin/perl -w +# +# This script generates the tables cmdidxs1[] and cmdidxs2[][] which, +# given a Ex command, determine the first value to probe to find +# a matching command in cmdnames[] based on the first character +# and the first 2 characters of the command. +# This is used to speed up lookup in cmdnames[]. +# +# Script should be run every time new Ex commands are added in Vim, +# from the src/vim directory, since it reads commands from "ex_cmds.h". + +# Find the list of Vim commands from cmdnames[] table in ex_cmds.h +my @cmds; +my @skipped; +open(IN, "< ex_cmds.h") or die "can't open ex_cmds.h: $!\n"; +while (<IN>) { + if (/^EX\(CMD_\S*,\s*"([a-z][^"]*)"/) { + push (@cmds, $1); + } elsif (/^EX\(CMD_/) { + push (@skipped, $1); + } +} + +my %cmdidxs1; +my %cmdidxs2; + +for (my $i = $#cmds; $i >= 0; --$i) { + my $cmd = $cmds[$i]; + my $c1 = substr($cmd, 0, 1); # First character of command. + + $cmdidxs1{$c1} = $i; + + if (length($cmd) > 1) { + my $c2 = substr($cmd, 1, 1); # Second character of command. + $cmdidxs2{$c1}{$c2} = $i if (('a' lt $c2) and ($c2 lt 'z')); + } +} + +print "/* Beginning of automatically generated code by create_cmdidxs.pl\n", + " *\n", + " * Table giving the index of the first command in cmdnames[] to lookup\n", + " * based on the first letter of a command.\n", + " */\n", + "static const unsigned short cmdidxs1[26] =\n{\n", + join(",\n", map(" /* $_ */ $cmdidxs1{$_}", ('a' .. 'z'))), + "\n};\n", + "\n", + "/*\n", + " * Table giving the index of the first command in cmdnames[] to lookup\n", + " * based on the first 2 letters of a command.\n", + " * Values in cmdidxs2[c1][c2] are relative to cmdidxs1[c1] so that they\n", + " * fit in a byte.\n", + " */\n", + "static const unsigned char cmdidxs2[26][26] =\n", + "{ /* a b c d e f g h i j k l m n o p q r s t u v w x y z */\n"; +for my $c1 ('a' .. 'z') { + print " /* $c1 */ {"; + for my $c2 ('a' .. 'z') { + if (exists $cmdidxs2{$c1}{$c2}) { + printf "%3d,", $cmdidxs2{$c1}{$c2} - $cmdidxs1{$c1}; + } else { + printf " 0,"; + } + } + print " }"; + print "," unless ($c1 eq 'z'); + print "\n"; +} +print "};\n", + "\n", + "static int command_count = ", $#cmds + $#skipped + 2 , ";\n", + "\n", + "/* End of automatically generated code by create_cmdidxs.pl */\n"; +