Bram Moolenaar | e5e0fbc | 2017-03-25 14:51:01 +0100 | [diff] [blame] | 1 | #!/usr/bin/perl -w |
| 2 | # |
| 3 | # This script generates the tables cmdidxs1[] and cmdidxs2[][] which, |
| 4 | # given a Ex command, determine the first value to probe to find |
| 5 | # a matching command in cmdnames[] based on the first character |
| 6 | # and the first 2 characters of the command. |
| 7 | # This is used to speed up lookup in cmdnames[]. |
| 8 | # |
| 9 | # Script should be run every time new Ex commands are added in Vim, |
| 10 | # from the src/vim directory, since it reads commands from "ex_cmds.h". |
| 11 | |
Bram Moolenaar | 980128c | 2017-03-26 21:46:28 +0200 | [diff] [blame] | 12 | use strict; |
| 13 | |
Bram Moolenaar | e5e0fbc | 2017-03-25 14:51:01 +0100 | [diff] [blame] | 14 | # Find the list of Vim commands from cmdnames[] table in ex_cmds.h |
| 15 | my @cmds; |
Bram Moolenaar | 980128c | 2017-03-26 21:46:28 +0200 | [diff] [blame] | 16 | my $skipped_cmds; |
Bram Moolenaar | e5e0fbc | 2017-03-25 14:51:01 +0100 | [diff] [blame] | 17 | open(IN, "< ex_cmds.h") or die "can't open ex_cmds.h: $!\n"; |
| 18 | while (<IN>) { |
| 19 | if (/^EX\(CMD_\S*,\s*"([a-z][^"]*)"/) { |
Bram Moolenaar | 980128c | 2017-03-26 21:46:28 +0200 | [diff] [blame] | 20 | push @cmds, $1; |
Bram Moolenaar | e5e0fbc | 2017-03-25 14:51:01 +0100 | [diff] [blame] | 21 | } elsif (/^EX\(CMD_/) { |
Bram Moolenaar | 980128c | 2017-03-26 21:46:28 +0200 | [diff] [blame] | 22 | ++$skipped_cmds; |
Bram Moolenaar | e5e0fbc | 2017-03-25 14:51:01 +0100 | [diff] [blame] | 23 | } |
| 24 | } |
| 25 | |
| 26 | my %cmdidxs1; |
| 27 | my %cmdidxs2; |
| 28 | |
| 29 | for (my $i = $#cmds; $i >= 0; --$i) { |
| 30 | my $cmd = $cmds[$i]; |
| 31 | my $c1 = substr($cmd, 0, 1); # First character of command. |
| 32 | |
| 33 | $cmdidxs1{$c1} = $i; |
| 34 | |
| 35 | if (length($cmd) > 1) { |
| 36 | my $c2 = substr($cmd, 1, 1); # Second character of command. |
| 37 | $cmdidxs2{$c1}{$c2} = $i if (('a' lt $c2) and ($c2 lt 'z')); |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | print "/* Beginning of automatically generated code by create_cmdidxs.pl\n", |
| 42 | " *\n", |
| 43 | " * Table giving the index of the first command in cmdnames[] to lookup\n", |
| 44 | " * based on the first letter of a command.\n", |
| 45 | " */\n", |
| 46 | "static const unsigned short cmdidxs1[26] =\n{\n", |
| 47 | join(",\n", map(" /* $_ */ $cmdidxs1{$_}", ('a' .. 'z'))), |
| 48 | "\n};\n", |
| 49 | "\n", |
| 50 | "/*\n", |
| 51 | " * Table giving the index of the first command in cmdnames[] to lookup\n", |
| 52 | " * based on the first 2 letters of a command.\n", |
| 53 | " * Values in cmdidxs2[c1][c2] are relative to cmdidxs1[c1] so that they\n", |
| 54 | " * fit in a byte.\n", |
| 55 | " */\n", |
| 56 | "static const unsigned char cmdidxs2[26][26] =\n", |
| 57 | "{ /* 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"; |
| 58 | for my $c1 ('a' .. 'z') { |
| 59 | print " /* $c1 */ {"; |
| 60 | for my $c2 ('a' .. 'z') { |
| 61 | if (exists $cmdidxs2{$c1}{$c2}) { |
| 62 | printf "%3d,", $cmdidxs2{$c1}{$c2} - $cmdidxs1{$c1}; |
| 63 | } else { |
| 64 | printf " 0,"; |
| 65 | } |
| 66 | } |
| 67 | print " }"; |
| 68 | print "," unless ($c1 eq 'z'); |
| 69 | print "\n"; |
| 70 | } |
| 71 | print "};\n", |
| 72 | "\n", |
Bram Moolenaar | 980128c | 2017-03-26 21:46:28 +0200 | [diff] [blame] | 73 | "static const int command_count = ", scalar(@cmds) + $skipped_cmds, ";\n", |
Bram Moolenaar | e5e0fbc | 2017-03-25 14:51:01 +0100 | [diff] [blame] | 74 | "\n", |
| 75 | "/* End of automatically generated code by create_cmdidxs.pl */\n"; |