Skip to content

Commit

Permalink
patch 8.2.4252: generating the normal command table at runtime is ine…
Browse files Browse the repository at this point in the history
…fficient

Problem:    Generating the normal command table at runtime is inefficient.
Solution:   Generate the table with a Vim script and put it in a header file.
            (Yegappan Lakshmanan, closes #9648)
  • Loading branch information
yegappan authored and brammool committed Jan 29, 2022
1 parent 97c554d commit 4dc0dd8
Show file tree
Hide file tree
Showing 14 changed files with 399 additions and 64 deletions.
2 changes: 2 additions & 0 deletions Filelist
Expand Up @@ -113,6 +113,7 @@ SRC_ALL = \
src/nbdebug.h \
src/netbeans.c \
src/normal.c \
src/nv_cmdidxs.h \
src/ops.c \
src/option.c \
src/option.h \
Expand Down Expand Up @@ -443,6 +444,7 @@ SRC_UNIX = \
src/configure \
src/configure.ac \
src/create_cmdidxs.vim \
src/create_nvcmdidxs.vim \
src/gui_at_fs.c \
src/gui_at_sb.c \
src/gui_at_sb.h \
Expand Down
6 changes: 6 additions & 0 deletions runtime/doc/builtin.txt
Expand Up @@ -292,6 +292,7 @@ inputrestore() Number restore typeahead
inputsave() Number save and clear typeahead
inputsecret({prompt} [, {text}]) String like input() but hiding the text
insert({object}, {item} [, {idx}]) List insert {item} in {object} [before {idx}]
internal_get_nv_cmdchar({idx}) Number command character at this index
interrupt() none interrupt script execution
invert({expr}) Number bitwise invert
isdirectory({directory}) Number |TRUE| if {directory} is a directory
Expand Down Expand Up @@ -4622,6 +4623,11 @@ insert({object}, {item} [, {idx}]) *insert()*

Can also be used as a |method|: >
mylist->insert(item)
<
*internal_get_nv_cmdchar()*
internal_get_nv_cmdchar({idx})
Return the normal/visual mode command character at the
specified index. To be used only during the Vim build process.

interrupt() *interrupt()*
Interrupt script execution. It works more or less like the
Expand Down
1 change: 1 addition & 0 deletions runtime/doc/usr_41.txt
Expand Up @@ -1110,6 +1110,7 @@ Testing: *test-functions*
assert_nobeep() assert that a command does not cause a beep
assert_fails() assert that a command fails
assert_report() report a test failure
internal_get_nv_cmdchar() normal/visual command character at an index
test_alloc_fail() make memory allocation fail
test_autochdir() enable 'autochdir' during startup
test_override() test with Vim internal overrides
Expand Down
12 changes: 12 additions & 0 deletions src/Make_cyg_ming.mak
Expand Up @@ -1147,6 +1147,16 @@ endif
cmdidxs: ex_cmds.h
vim --clean -X --not-a-term -u create_cmdidxs.vim

# Run vim script to generate the normal/visual mode command lookup table.
# This only needs to be run when a new normal/visual mode command has been
# added. If this fails because you don't have Vim yet:
# - change nv_cmds[] in normal.c to add the new normal/visual mode command.
# - build Vim
# - run "make nvcmdidxs" using the new Vim to generate nv_cmdidxs.h
# - rebuild Vim to use the newly generated nv_cmdidxs.h file.
nvcmdidxs: normal.c
./$(TARGET) --clean -X --not-a-term -u create_nvcmdidxs.vim

###########################################################################
INCL = vim.h alloc.h ascii.h ex_cmds.h feature.h errors.h globals.h \
keymap.h macros.h option.h os_dos.h os_win32.h proto.h regexp.h \
Expand Down Expand Up @@ -1209,6 +1219,8 @@ $(OUTDIR)/hardcopy.o: hardcopy.c $(INCL) version.h

$(OUTDIR)/misc1.o: misc1.c $(INCL) version.h

$(OUTDIR)/normal.o: normal.c $(INCL) nv_cmdidxs.h

$(OUTDIR)/netbeans.o: netbeans.c $(INCL) version.h

$(OUTDIR)/version.o: version.c $(INCL) version.h
Expand Down
12 changes: 11 additions & 1 deletion src/Make_mvc.mak
Expand Up @@ -1446,6 +1446,16 @@ clean: testclean
cmdidxs: ex_cmds.h
vim --clean -X --not-a-term -u create_cmdidxs.vim

# Run vim script to generate the normal/visual mode command lookup table.
# This only needs to be run when a new normal/visual mode command has been
# added. If this fails because you don't have Vim yet:
# - change nv_cmds[] in normal.c to add the new normal/visual mode command.
# - build Vim
# - run "make nvcmdidxs" using the new Vim to generate nv_cmdidxs.h
# - rebuild Vim to use the newly generated nv_cmdidxs.h file.
nvcmdidxs: normal.c
.\$(VIM) --clean -X --not-a-term -u create_nvcmdidxs.vim

test:
cd testdir
$(MAKE) /NOLOGO -f Make_dos.mak
Expand Down Expand Up @@ -1709,7 +1719,7 @@ $(OUTDIR)/netbeans.obj: $(OUTDIR) netbeans.c $(NBDEBUG_SRC) $(INCL) version.h

$(OUTDIR)/channel.obj: $(OUTDIR) channel.c $(INCL)

$(OUTDIR)/normal.obj: $(OUTDIR) normal.c $(INCL)
$(OUTDIR)/normal.obj: $(OUTDIR) normal.c $(INCL) nv_cmdidxs.h

$(OUTDIR)/option.obj: $(OUTDIR) option.c $(INCL) optiondefs.h

Expand Down
2 changes: 1 addition & 1 deletion src/Make_vms.mms
Expand Up @@ -977,7 +977,7 @@ mbyte.obj : mbyte.c vim.h [.auto]config.h feature.h os_unix.h \
normal.obj : normal.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
errors.h globals.h
errors.h globals.h nv_cmdidxs.h
ops.obj : ops.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h gui.h beval.h \
[.proto]gui_beval.pro option.h ex_cmds.h proto.h errors.h globals.h
Expand Down
12 changes: 11 additions & 1 deletion src/Makefile
Expand Up @@ -2144,6 +2144,16 @@ autoconf:
cmdidxs: ex_cmds.h
vim --clean -X --not-a-term -u create_cmdidxs.vim

# Run vim script to generate the normal/visual mode command lookup table.
# This only needs to be run when a new normal/visual mode command has been
# added. If this fails because you don't have Vim yet:
# - change nv_cmds[] in normal.c to add the new normal/visual mode command.
# - build Vim
# - run "make nvcmdidxs" using the new Vim to generate nv_cmdidxs.h
# - rebuild Vim to use the newly generated nv_cmdidxs.h file.
nvcmdidxs: normal.c
./$(VIMTARGET) --clean -X --not-a-term -u create_nvcmdidxs.vim


# The normal command to compile a .c file to its .o file.
# Without or with ALL_CFLAGS.
Expand Down Expand Up @@ -4002,7 +4012,7 @@ objects/move.o: move.c vim.h protodef.h auto/config.h feature.h os_unix.h \
objects/normal.o: normal.c vim.h protodef.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
proto.h globals.h errors.h
proto.h globals.h errors.h nv_cmdidxs.h
objects/ops.o: ops.c vim.h protodef.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
Expand Down
72 changes: 72 additions & 0 deletions src/create_nvcmdidxs.vim
@@ -0,0 +1,72 @@
vim9script

# This script generates the table nv_cmd_idx[] which contains the index in
# nv_cmds[] table (normal.c) for each of the command character supported in
# normal/visual mode.
# This is used to speed up the command lookup in nv_cmds[].
#
# Script should be run using "make nvcmdidxs", every time the nv_cmds[] table
# in src/normal.c changes.

def Create_nvcmdidxs_table()
var nv_cmdtbl: list<dict<number>> = []

# Generate the table of normal/visual mode command characters and their
# corresponding index.
var idx: number = 0
var ch: number
while true
ch = internal_get_nv_cmdchar(idx)
if ch == -1
break
endif
add(nv_cmdtbl, {idx: idx, cmdchar: ch})
idx += 1
endwhile

# sort the table by the command character
sort(nv_cmdtbl, (a, b) => a.cmdchar - b.cmdchar)

# Compute the highest index upto which the command character can be directly
# used as an index.
var nv_max_linear: number = 0
for i in range(nv_cmdtbl->len())
if i != nv_cmdtbl[i].cmdchar
nv_max_linear = i - 1
break
endif
endfor

# Generate a header file with the table
var output: list<string> =<< trim END
/*
* Automatically generated code by the create_nvcmdidxs.vim script.
*
* Table giving the index in nv_cmds[] to lookup based on
* the command character.
*/

// nv_cmd_idx[<normal mode command character>] => nv_cmds[] index
static const unsigned short nv_cmd_idx[] =
{
END

# Add each command character in comment and the corresponding index
var tbl: list<string> = mapnew(nv_cmdtbl, (k, v) =>
' /* ' .. printf('%5d', v.cmdchar) .. ' */ ' ..
printf('%3d', v.idx) .. ','
)
output += tbl

output += [ '};', '',
'// The highest index for which',
'// nv_cmds[idx].cmd_char == nv_cmd_idx[nv_cmds[idx].cmd_char]']
output += ['static const int nv_max_linear = ' .. nv_max_linear .. ';']

writefile(output, "nv_cmdidxs.h")
enddef

Create_nvcmdidxs_table()
quit

# vim: shiftwidth=2 sts=2 expandtab
2 changes: 2 additions & 0 deletions src/evalfunc.c
Expand Up @@ -1737,6 +1737,8 @@ static funcentry_T global_functions[] =
ret_string, f_inputsecret},
{"insert", 2, 3, FEARG_1, arg23_insert,
ret_first_arg, f_insert},
{"internal_get_nv_cmdchar", 1, 1, FEARG_1, arg1_number,
ret_number, f_internal_get_nv_cmdchar},
{"interrupt", 0, 0, 0, NULL,
ret_void, f_interrupt},
{"invert", 1, 1, FEARG_1, arg1_number,
Expand Down
3 changes: 0 additions & 3 deletions src/main.c
Expand Up @@ -901,9 +901,6 @@ common_init(mparm_T *paramp)
qnx_init(); // PhAttach() for clipboard, (and gui)
#endif

// Init the table of Normal mode commands.
init_normal_cmds();

/*
* Allocate space for the generic buffers (needed for set_init_1() and
* emsg()).
Expand Down

0 comments on commit 4dc0dd8

Please sign in to comment.