1 To: vim_dev@googlegroups.com
4 From: Bram Moolenaar <Bram@moolenaar.net>
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
11 Problem: Memfile is not tested sufficiently. Looking up blocks in a
12 memfile is slow when there are many blocks.
13 Solution: Add high level test and unittest. Adjust the number of hash
14 buckets to the number of blocks. (Ivan Krasilnikov)
15 Files: Filelist, src/Makefile, src/main.c, src/memfile.c,
16 src/memfile_test.c src/structs.h src/testdir/Make_amiga.mak,
17 src/testdir/Make_dos.mak, src/testdir/Make_ming.mak,
18 src/testdir/Make_os2.mak, src/testdir/Make_vms.mak,
19 src/testdir/Makefile, src/testdir/test77.in, src/testdir/test77.ok
22 *** ../vim-7.3.142/Filelist 2010-08-15 21:57:20.000000000 +0200
23 --- Filelist 2011-03-22 17:39:22.000000000 +0100
30 + src/memfile_test.c \
37 runtime/tutor/tutor.utf-8 \
38 runtime/tutor/tutor.?? \
39 runtime/tutor/tutor.??.* \
40 + runtime/tutor/tutor.bar \
41 + runtime/tutor/tutor.bar.* \
42 runtime/spell/README.txt \
43 runtime/spell/??/*.diff \
44 runtime/spell/??/main.aap \
45 *** ../vim-7.3.142/src/Makefile 2011-02-15 15:27:00.000000000 +0100
46 --- src/Makefile 2011-03-22 18:07:25.000000000 +0100
49 #CFLAGS = -g -O2 '-DSTARTUPTIME="vimstartup"' -fno-strength-reduce -Wall -Wmissing-prototypes
51 # Use this with GCC to check for mistakes, unused arguments, etc.
52 ! #CFLAGS = -g -Wall -Wextra -Wmissing-prototypes -Wunreachable-code -D_FORTIFY_SOURCE=1 -DU_DEBUG
53 #CFLAGS = -g -O2 -Wall -Wextra -Wmissing-prototypes -D_FORTIFY_SOURCE=1 -DU_DEBUG
54 #PYTHON_CFLAGS_EXTRA = -Wno-missing-field-initializers
55 #MZSCHEME_CFLAGS_EXTRA = -Wno-unreachable-code -Wno-unused-parameter
57 #CFLAGS = -g -O2 '-DSTARTUPTIME="vimstartup"' -fno-strength-reduce -Wall -Wmissing-prototypes
59 # Use this with GCC to check for mistakes, unused arguments, etc.
60 ! #CFLAGS = -g -Wall -Wextra -Wmissing-prototypes -Wunreachable-code -D_FORTIFY_SOURCE=1
61 #CFLAGS = -g -O2 -Wall -Wextra -Wmissing-prototypes -D_FORTIFY_SOURCE=1 -DU_DEBUG
62 #PYTHON_CFLAGS_EXTRA = -Wno-missing-field-initializers
63 #MZSCHEME_CFLAGS_EXTRA = -Wno-unreachable-code -Wno-unused-parameter
67 # PROFILING - Uncomment the next two lines to do profiling with gcc and gprof.
68 # Might not work with GUI or Perl.
69 ! # For unknown reasons adding "-lc" fixes a linking problem with GCC. That's
70 ! # probably a bug in the "-pg" implementation.
71 # Need to recompile everything after changing this: "make clean" "make".
72 #PROFILE_CFLAGS = -pg -g -DWE_ARE_PROFILING
76 # PROFILING - Uncomment the next two lines to do profiling with gcc and gprof.
77 # Might not work with GUI or Perl.
78 ! # For unknown reasons adding "-lc" fixes a linking problem with some versions
79 ! # of GCC. That's probably a bug in the "-pg" implementation.
80 ! # After running Vim see the profile result with: gmon vim gmon.out | vim -
81 # Need to recompile everything after changing this: "make clean" "make".
82 #PROFILE_CFLAGS = -pg -g -DWE_ARE_PROFILING
86 # Configuration is in the .ccmalloc or ~/.ccmalloc file.
87 # Doesn't work very well, since memory linked to from global variables
88 # (in libraries) is also marked as leaked memory.
89 ! #PROFILE_CFLAGS = -DEXITFREE
90 ! #PROFILE_LIBS = -lccmalloc
92 #####################################################
93 ### Specific systems, check if yours is listed! ### {{{
95 # Configuration is in the .ccmalloc or ~/.ccmalloc file.
96 # Doesn't work very well, since memory linked to from global variables
97 # (in libraries) is also marked as leaked memory.
98 ! #LEAK_CFLAGS = -DEXITFREE
99 ! #LEAK_LIBS = -lccmalloc
101 #####################################################
102 ### Specific systems, check if yours is listed! ### {{{
105 PRE_DEFS = -Iproto $(DEFS) $(GUI_DEFS) $(GUI_IPATH) $(CPPFLAGS) $(EXTRA_IPATHS)
106 POST_DEFS = $(X_CFLAGS) $(MZSCHEME_CFLAGS) $(TCL_CFLAGS) $(EXTRA_DEFS)
108 ! ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(PROFILE_CFLAGS) $(POST_DEFS)
110 # Exclude $CFLAGS for osdef.sh, for Mac 10.4 some flags don't work together
113 PRE_DEFS = -Iproto $(DEFS) $(GUI_DEFS) $(GUI_IPATH) $(CPPFLAGS) $(EXTRA_IPATHS)
114 POST_DEFS = $(X_CFLAGS) $(MZSCHEME_CFLAGS) $(TCL_CFLAGS) $(EXTRA_DEFS)
116 ! ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(PROFILE_CFLAGS) $(LEAK_CFLAGS) $(POST_DEFS)
118 # Exclude $CFLAGS for osdef.sh, for Mac 10.4 some flags don't work together
128 DEST_BIN = $(DESTDIR)$(BINDIR)
137 DEST_BIN = $(DESTDIR)$(BINDIR)
140 if_python.c if_python3.c if_tcl.c if_ruby.c if_sniff.c \
141 gui_beval.c workshop.c wsdebug.c integration.c netbeans.c
143 # All sources, also the ones that are not configured
144 ! ALL_SRC = $(BASIC_SRC) $(ALL_GUI_SRC) $(EXTRA_SRC)
146 # Which files to check with lint. Select one of these three lines. ALL_SRC
147 # checks more, but may not work well for checking a GUI that wasn't configured.
149 if_python.c if_python3.c if_tcl.c if_ruby.c if_sniff.c \
150 gui_beval.c workshop.c wsdebug.c integration.c netbeans.c
153 + MEMFILE_TEST_SRC = memfile_test.c
154 + MEMFILE_TEST_TARGET = memfile_test$(EXEEXT)
156 + UNITTEST_SRC = $(MEMFILE_TEST_SRC)
157 + UNITTEST_TARGETS = $(MEMFILE_TEST_TARGET)
159 # All sources, also the ones that are not configured
160 ! ALL_SRC = $(BASIC_SRC) $(ALL_GUI_SRC) $(UNITTEST_SRC) $(EXTRA_SRC)
162 # Which files to check with lint. Select one of these three lines. ALL_SRC
163 # checks more, but may not work well for checking a GUI that wasn't configured.
166 #LINT_SRC = $(ALL_SRC)
167 #LINT_SRC = $(BASIC_SRC)
174 #LINT_SRC = $(ALL_SRC)
175 #LINT_SRC = $(BASIC_SRC)
184 objects/if_cscope.o \
185 objects/if_xcmdsrv.o \
188 ! objects/memfile.o \
189 ! objects/memline.o \
195 objects/if_cscope.o \
196 objects/if_xcmdsrv.o \
198 ! objects/memline.o \
208 + objects/version.o \
218 + OBJ = $(OBJ_COMMON) \
220 + objects/memfile.o \
222 + MEMFILE_TEST_OBJ = $(OBJ_COMMON) \
223 + objects/memfile_test.o
230 $(VIMTARGET): auto/config.mk objects $(OBJ) version.c version.h
231 $(CCC) version.c -o objects/version.o
232 @LINK="$(PURIFY) $(SHRPENV) $(CClink) $(ALL_LIB_DIRS) $(LDFLAGS) \
233 ! -o $(VIMTARGET) $(OBJ) objects/version.o $(ALL_LIBS)" \
234 MAKE="$(MAKE)" LINK_AS_NEEDED=$(LINK_AS_NEEDED) \
238 $(VIMTARGET): auto/config.mk objects $(OBJ) version.c version.h
239 $(CCC) version.c -o objects/version.o
240 @LINK="$(PURIFY) $(SHRPENV) $(CClink) $(ALL_LIB_DIRS) $(LDFLAGS) \
241 ! -o $(VIMTARGET) $(OBJ) $(ALL_LIBS)" \
242 MAKE="$(MAKE)" LINK_AS_NEEDED=$(LINK_AS_NEEDED) \
248 ln -s $(VIMTARGET) vim; \
250 cd testdir; $(MAKE) -f Makefile $(GUI_TESTTARGET) VIMPROG=../$(VIMTARGET) $(GUI_TESTARG)
251 + $(MAKE) -f Makefile unittest
254 + $(MAKE) -f Makefile $(UNITTEST_TARGETS)
256 + unittest unittests: $(UNITTEST_TARGETS)
257 + @for t in $(UNITTEST_TARGETS); do \
258 + ./$$t || exit 1; echo $$t passed; \
262 cd testdir; $(MAKE) -f Makefile clean
266 cd $(PODIR); $(MAKE) checkclean; \
270 + # It's build just like Vim to satisfy all dependencies.
271 + $(MEMFILE_TEST_TARGET): auto/config.mk objects $(MEMFILE_TEST_OBJ)
272 + $(CCC) version.c -o objects/version.o
273 + @LINK="$(PURIFY) $(SHRPENV) $(CClink) $(ALL_LIB_DIRS) $(LDFLAGS) \
274 + -o $(MEMFILE_TEST_TARGET) $(MEMFILE_TEST_OBJ) $(ALL_LIBS)" \
275 + MAKE="$(MAKE)" LINK_AS_NEEDED=$(LINK_AS_NEEDED) \
276 + sh $(srcdir)/link.sh
280 install: $(GUI_INSTALL)
282 install_normal: installvim installtools $(INSTALL_LANGS) install-icons
286 -rm -f *.o objects/* core $(VIMTARGET).core $(VIMTARGET) vim xxd/*.o
287 -rm -f $(TOOLS) auto/osdef.h auto/pathdef.c auto/if_perl.c
288 -rm -f conftest* *~ auto/link.sed
289 + -rm -f $(UNITTEST_TARGETS)
290 -rm -f runtime pixmaps
292 -rm -rf mzscheme_base.c
296 objects/memfile.o: memfile.c
297 $(CCC) -o $@ memfile.c
299 + objects/memfile_test.o: memfile_test.c
300 + $(CCC) -o $@ memfile_test.c
302 objects/memline.o: memline.c
303 $(CCC) -o $@ memline.c
307 objects/os_unix.o: os_unix.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
308 ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
309 gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
310 ! arabic.h if_mzsch.h os_unixx.h
311 objects/pathdef.o: auto/pathdef.c vim.h auto/config.h feature.h os_unix.h \
312 auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
313 regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
315 objects/os_unix.o: os_unix.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
316 ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
317 gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
318 ! arabic.h os_unixx.h
319 objects/pathdef.o: auto/pathdef.c vim.h auto/config.h feature.h os_unix.h \
320 auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
321 regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
325 objects/pty.o: pty.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h ascii.h \
326 keymap.h term.h macros.h option.h structs.h regexp.h gui.h gui_beval.h \
327 proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h arabic.h
328 + objects/memfile_test.o: memfile_test.c main.c vim.h auto/config.h feature.h \
329 + os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h \
330 + structs.h regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h \
331 + proto.h globals.h farsi.h arabic.h farsi.c arabic.c memfile.c
332 objects/hangulin.o: hangulin.c vim.h auto/config.h feature.h os_unix.h \
333 auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
334 regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
337 objects/if_mzsch.o: if_mzsch.c vim.h auto/config.h feature.h os_unix.h \
338 auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
339 regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
340 ! globals.h farsi.h arabic.h if_mzsch.h mzscheme_base.c
341 objects/if_perl.o: auto/if_perl.c vim.h auto/config.h feature.h os_unix.h \
342 auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
343 regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
345 objects/if_mzsch.o: if_mzsch.c vim.h auto/config.h feature.h os_unix.h \
346 auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
347 regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
348 ! globals.h farsi.h arabic.h if_mzsch.h
349 objects/if_perl.o: auto/if_perl.c vim.h auto/config.h feature.h os_unix.h \
350 auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
351 regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
354 ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
355 gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
357 ! objects/if_ruby.o: if_ruby.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
358 ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
359 gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
362 ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
363 gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
365 ! objects/if_ruby.o: if_ruby.c auto/config.h vim.h feature.h os_unix.h auto/osdef.h \
366 ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
367 gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
369 *** ../vim-7.3.142/src/main.c 2011-02-15 16:29:54.000000000 +0100
370 --- src/main.c 2011-03-18 13:19:48.000000000 +0100
373 #define EDIT_TAG 3 /* tag name argument given, use tagname */
374 #define EDIT_QF 4 /* start in quickfix mode */
376 ! #if defined(UNIX) || defined(VMS)
377 static int file_owned __ARGS((char *fname));
379 static void mainerr __ARGS((int, char_u *));
380 static void main_msg __ARGS((char *s));
381 static void usage __ARGS((void));
382 static int get_number_arg __ARGS((char_u *p, int *idx, int def));
383 ! #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
384 static void init_locale __ARGS((void));
386 static void parse_command_name __ARGS((mparm_T *parmp));
387 static void early_arg_scan __ARGS((mparm_T *parmp));
388 static void command_line_scan __ARGS((mparm_T *parmp));
389 static void check_tty __ARGS((mparm_T *parmp));
390 static void read_stdin __ARGS((void));
391 static void create_windows __ARGS((mparm_T *parmp));
392 ! #ifdef FEAT_WINDOWS
393 static void edit_buffers __ARGS((mparm_T *parmp));
395 static void exe_pre_commands __ARGS((mparm_T *parmp));
396 static void exe_commands __ARGS((mparm_T *parmp));
397 static void source_startup_scripts __ARGS((mparm_T *parmp));
398 static void main_start_gui __ARGS((void));
399 ! #if defined(HAS_SWAP_EXISTS_ACTION)
400 static void check_swap_exists_action __ARGS((void));
402 ! #ifdef FEAT_CLIENTSERVER
403 static void exec_on_server __ARGS((mparm_T *parmp));
404 static void prepare_server __ARGS((mparm_T *parmp));
405 static void cmdsrv_main __ARGS((int *argc, char **argv, char_u *serverName_arg, char_u **serverStr));
406 static char_u *serverMakeName __ARGS((char_u *arg, char *cmd));
411 #define EDIT_TAG 3 /* tag name argument given, use tagname */
412 #define EDIT_QF 4 /* start in quickfix mode */
414 ! #if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN)
415 static int file_owned __ARGS((char *fname));
417 static void mainerr __ARGS((int, char_u *));
418 + #ifndef NO_VIM_MAIN
419 static void main_msg __ARGS((char *s));
420 static void usage __ARGS((void));
421 static int get_number_arg __ARGS((char_u *p, int *idx, int def));
422 ! # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
423 static void init_locale __ARGS((void));
425 static void parse_command_name __ARGS((mparm_T *parmp));
426 static void early_arg_scan __ARGS((mparm_T *parmp));
427 static void command_line_scan __ARGS((mparm_T *parmp));
428 static void check_tty __ARGS((mparm_T *parmp));
429 static void read_stdin __ARGS((void));
430 static void create_windows __ARGS((mparm_T *parmp));
431 ! # ifdef FEAT_WINDOWS
432 static void edit_buffers __ARGS((mparm_T *parmp));
434 static void exe_pre_commands __ARGS((mparm_T *parmp));
435 static void exe_commands __ARGS((mparm_T *parmp));
436 static void source_startup_scripts __ARGS((mparm_T *parmp));
437 static void main_start_gui __ARGS((void));
438 ! # if defined(HAS_SWAP_EXISTS_ACTION)
439 static void check_swap_exists_action __ARGS((void));
441 ! # if defined(FEAT_CLIENTSERVER) || defined(PROTO)
442 static void exec_on_server __ARGS((mparm_T *parmp));
443 static void prepare_server __ARGS((mparm_T *parmp));
444 static void cmdsrv_main __ARGS((int *argc, char **argv, char_u *serverName_arg, char_u **serverStr));
445 static char_u *serverMakeName __ARGS((char_u *arg, char *cmd));
452 #define ME_INVALID_ARG 5
455 ! #ifndef PROTO /* don't want a prototype for main() */
460 #define ME_INVALID_ARG 5
463 ! #ifndef NO_VIM_MAIN /* skip this for unittests */
464 ! #ifndef PROTO /* don't want a prototype for main() */
474 + #endif /* NO_VIM_MAIN */
477 * Main loop: Execute Normal mode commands until exiting Vim.
484 + #ifndef NO_VIM_MAIN
486 * Get a (optional) count for a Vim argument.
494 + #endif /* NO_VIM_MAIN */
497 * Get an environment variable, and execute it as Ex commands.
498 * Returns FAIL if the environment variable was not executed, OK otherwise.
504 ! #if defined(UNIX) || defined(VMS)
506 * Return TRUE if we are certain the user owns the file "fname".
507 * Used for ".vimrc" and ".exrc".
512 ! #if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN)
514 * Return TRUE if we are certain the user owns the file "fname".
515 * Used for ".vimrc" and ".exrc".
519 mainerr(ME_ARG_MISSING, str);
522 + #ifndef NO_VIM_MAIN
524 * print a message with three spaces prepended and '\n' appended.
534 #if defined(STARTUPTIME) || defined(PROTO)
535 static void time_diff __ARGS((struct timeval *then, struct timeval *now));
542 ! #if defined(FEAT_CLIENTSERVER) || defined(PROTO)
545 * Common code for the X command server and the Win32 command server.
550 ! #if (defined(FEAT_CLIENTSERVER) && !defined(NO_VIM_MAIN)) || defined(PROTO)
553 * Common code for the X command server and the Win32 command server.
560 + * Make our basic server name: use the specified "arg" if given, otherwise use
561 + * the tail of the command "cmd" we were started with.
562 + * Return the name in allocated memory. This doesn't include a serial number.
565 + serverMakeName(arg, cmd)
571 + if (arg != NULL && *arg != NUL)
572 + p = vim_strsave_up(arg);
575 + p = vim_strsave_up(gettail((char_u *)cmd));
576 + /* Remove .exe or .bat from the name. */
577 + if (p != NULL && vim_strchr(p, '.') != NULL)
578 + *vim_strchr(p, '.') = NUL;
582 + #endif /* FEAT_CLIENTSERVER */
584 + #if defined(FEAT_CLIENTSERVER) || defined(PROTO)
586 * Replace termcodes such as <CR> and insert as key presses if there is room.
597 ! * Make our basic server name: use the specified "arg" if given, otherwise use
598 ! * the tail of the command "cmd" we were started with.
599 ! * Return the name in allocated memory. This doesn't include a serial number.
602 ! serverMakeName(arg, cmd)
608 ! if (arg != NULL && *arg != NUL)
609 ! p = vim_strsave_up(arg);
612 ! p = vim_strsave_up(gettail((char_u *)cmd));
613 ! /* Remove .exe or .bat from the name. */
614 ! if (p != NULL && vim_strchr(p, '.') != NULL)
615 ! *vim_strchr(p, '.') = NUL;
619 ! #endif /* FEAT_CLIENTSERVER */
622 * When FEAT_FKMAP is defined, also compile the Farsi source code.
630 * When FEAT_FKMAP is defined, also compile the Farsi source code.
631 *** ../vim-7.3.142/src/memfile.c 2010-12-17 18:06:00.000000000 +0100
632 --- src/memfile.c 2011-03-03 18:47:39.000000000 +0100
636 static int mf_write_block __ARGS((memfile_T *mfp, bhdr_T *hp, off_t offset, unsigned size));
637 static int mf_trans_add __ARGS((memfile_T *, bhdr_T *));
638 static void mf_do_open __ARGS((memfile_T *, char_u *, int));
639 + static void mf_hash_init __ARGS((mf_hashtab_T *));
640 + static void mf_hash_free __ARGS((mf_hashtab_T *));
641 + static void mf_hash_free_all __ARGS((mf_hashtab_T *));
642 + static mf_hashitem_T *mf_hash_find __ARGS((mf_hashtab_T *, blocknr_T));
643 + static void mf_hash_add_item __ARGS((mf_hashtab_T *, mf_hashitem_T *));
644 + static void mf_hash_rem_item __ARGS((mf_hashtab_T *, mf_hashitem_T *));
645 + static int mf_hash_grow __ARGS((mf_hashtab_T *));
648 * The functions for using a memfile:
656 #if defined(STATFS) && defined(UNIX) && !defined(__QNX__)
661 mfp->mf_used_last = NULL;
662 mfp->mf_dirty = FALSE;
663 mfp->mf_used_count = 0;
664 ! for (i = 0; i < MEMHASHSIZE; ++i)
666 ! mfp->mf_hash[i] = NULL; /* hash lists are empty */
667 ! mfp->mf_trans[i] = NULL; /* trans lists are empty */
669 mfp->mf_page_size = MEMFILE_PAGE_SIZE;
671 mfp->mf_old_key = NULL;
673 mfp->mf_used_last = NULL;
674 mfp->mf_dirty = FALSE;
675 mfp->mf_used_count = 0;
676 ! mf_hash_init(&mfp->mf_hash);
677 ! mf_hash_init(&mfp->mf_trans);
678 mfp->mf_page_size = MEMFILE_PAGE_SIZE;
680 mfp->mf_old_key = NULL;
686 - NR_TRANS *tp, *tpnext;
689 if (mfp == NULL) /* safety check */
695 while (mfp->mf_free_first != NULL) /* free entries in free list */
696 vim_free(mf_rem_free(mfp));
697 ! for (i = 0; i < MEMHASHSIZE; ++i) /* free entries in trans lists */
698 ! for (tp = mfp->mf_trans[i]; tp != NULL; tp = tpnext)
700 ! tpnext = tp->nt_next;
703 vim_free(mfp->mf_fname);
704 vim_free(mfp->mf_ffname);
708 while (mfp->mf_free_first != NULL) /* free entries in free list */
709 vim_free(mf_rem_free(mfp));
710 ! mf_hash_free(&mfp->mf_hash);
711 ! mf_hash_free_all(&mfp->mf_trans); /* free hashtable and its items */
712 vim_free(mfp->mf_fname);
713 vim_free(mfp->mf_ffname);
723 ! hash = MEMHASH(hp->bh_bnum);
724 ! hhp = mfp->mf_hash[hash];
725 ! hp->bh_hash_next = hhp;
726 ! hp->bh_hash_prev = NULL;
728 ! hhp->bh_hash_prev = hp;
729 ! mfp->mf_hash[hash] = hp;
737 ! mf_hash_add_item(&mfp->mf_hash, (mf_hashitem_T *)hp);
746 ! if (hp->bh_hash_prev == NULL)
747 ! mfp->mf_hash[MEMHASH(hp->bh_bnum)] = hp->bh_hash_next;
749 ! hp->bh_hash_prev->bh_hash_next = hp->bh_hash_next;
751 ! if (hp->bh_hash_next)
752 ! hp->bh_hash_next->bh_hash_prev = hp->bh_hash_prev;
760 ! mf_hash_rem_item(&mfp->mf_hash, (mf_hashitem_T *)hp);
771 ! for (hp = mfp->mf_hash[MEMHASH(nr)]; hp != NULL; hp = hp->bh_hash_next)
772 ! if (hp->bh_bnum == nr)
782 ! return (bhdr_T *)mf_hash_find(&mfp->mf_hash, nr);
798 hp->bh_bnum = new_bnum;
799 mf_ins_hash(mfp, hp); /* insert in new hash list */
801 ! hash = MEMHASH(np->nt_old_bnum); /* insert in trans list */
802 ! np->nt_next = mfp->mf_trans[hash];
803 ! mfp->mf_trans[hash] = np;
804 ! if (np->nt_next != NULL)
805 ! np->nt_next->nt_prev = np;
806 ! np->nt_prev = NULL;
811 hp->bh_bnum = new_bnum;
812 mf_ins_hash(mfp, hp); /* insert in new hash list */
814 ! /* Insert "np" into "mf_trans" hashtable with key "np->nt_old_bnum" */
815 ! mf_hash_add_item(&mfp->mf_trans, (mf_hashitem_T *)np);
828 ! hash = MEMHASH(old_nr);
829 ! for (np = mfp->mf_trans[hash]; np != NULL; np = np->nt_next)
830 ! if (np->nt_old_bnum == old_nr)
832 if (np == NULL) /* not found */
836 new_bnum = np->nt_new_bnum;
837 ! if (np->nt_prev != NULL) /* remove entry from the trans list */
838 ! np->nt_prev->nt_next = np->nt_next;
840 ! mfp->mf_trans[hash] = np->nt_next;
841 ! if (np->nt_next != NULL)
842 ! np->nt_next->nt_prev = np->nt_prev;
853 ! np = (NR_TRANS *)mf_hash_find(&mfp->mf_trans, old_nr);
855 if (np == NULL) /* not found */
859 new_bnum = np->nt_new_bnum;
861 ! /* remove entry from the trans list */
862 ! mf_hash_rem_item(&mfp->mf_trans, (mf_hashitem_T *)np);
870 mch_hide(mfp->mf_fname); /* try setting the 'hidden' flag */
875 + * Implementation of mf_hashtab_T follows.
879 + * The number of buckets in the hashtable is increased by a factor of
880 + * MHT_GROWTH_FACTOR when the average number of items per bucket
881 + * exceeds 2 ^ MHT_LOG_LOAD_FACTOR.
883 + #define MHT_LOG_LOAD_FACTOR 6
884 + #define MHT_GROWTH_FACTOR 2 /* must be a power of two */
887 + * Initialize an empty hash table.
893 + vim_memset(mht, 0, sizeof(mf_hashtab_T));
894 + mht->mht_buckets = mht->mht_small_buckets;
895 + mht->mht_mask = MHT_INIT_SIZE - 1;
899 + * Free the array of a hash table. Does not free the items it contains!
900 + * The hash table must not be used again without another mf_hash_init() call.
906 + if (mht->mht_buckets != mht->mht_small_buckets)
907 + vim_free(mht->mht_buckets);
911 + * Free the array of a hash table and all the items it contains.
914 + mf_hash_free_all(mht)
918 + mf_hashitem_T *mhi;
919 + mf_hashitem_T *next;
921 + for (idx = 0; idx <= mht->mht_mask; idx++)
922 + for (mhi = mht->mht_buckets[idx]; mhi != NULL; mhi = next)
924 + next = mhi->mhi_next;
932 + * Find "key" in hashtable "mht".
933 + * Returns a pointer to a mf_hashitem_T or NULL if the item was not found.
935 + static mf_hashitem_T *
936 + mf_hash_find(mht, key)
940 + mf_hashitem_T *mhi;
942 + mhi = mht->mht_buckets[key & mht->mht_mask];
943 + while (mhi != NULL && mhi->mhi_key != key)
944 + mhi = mhi->mhi_next;
950 + * Add item "mhi" to hashtable "mht".
951 + * "mhi" must not be NULL.
954 + mf_hash_add_item(mht, mhi)
956 + mf_hashitem_T *mhi;
960 + idx = mhi->mhi_key & mht->mht_mask;
961 + mhi->mhi_next = mht->mht_buckets[idx];
962 + mhi->mhi_prev = NULL;
963 + if (mhi->mhi_next != NULL)
964 + mhi->mhi_next->mhi_prev = mhi;
965 + mht->mht_buckets[idx] = mhi;
970 + * Grow hashtable when we have more thank 2^MHT_LOG_LOAD_FACTOR
971 + * items per bucket on average
973 + if (mht->mht_fixed == 0
974 + && (mht->mht_count >> MHT_LOG_LOAD_FACTOR) > mht->mht_mask)
976 + if (mf_hash_grow(mht) == FAIL)
978 + /* stop trying to grow after first failure to allocate memory */
979 + mht->mht_fixed = 1;
985 + * Remove item "mhi" from hashtable "mht".
986 + * "mhi" must not be NULL and must have been inserted into "mht".
989 + mf_hash_rem_item(mht, mhi)
991 + mf_hashitem_T *mhi;
993 + if (mhi->mhi_prev == NULL)
994 + mht->mht_buckets[mhi->mhi_key & mht->mht_mask] = mhi->mhi_next;
996 + mhi->mhi_prev->mhi_next = mhi->mhi_next;
998 + if (mhi->mhi_next != NULL)
999 + mhi->mhi_next->mhi_prev = mhi->mhi_prev;
1003 + /* We could shrink the table here, but it typically takes little memory,
1004 + * so why bother? */
1008 + * Increase number of buckets in the hashtable by MHT_GROWTH_FACTOR and
1010 + * Returns FAIL when out of memory.
1014 + mf_hashtab_T *mht;
1018 + mf_hashitem_T *mhi;
1019 + mf_hashitem_T *tails[MHT_GROWTH_FACTOR];
1020 + mf_hashitem_T **buckets;
1023 + size = (mht->mht_mask + 1) * MHT_GROWTH_FACTOR * sizeof(void *);
1024 + buckets = (mf_hashitem_T **)lalloc_clear(size, FALSE);
1025 + if (buckets == NULL)
1029 + while ((mht->mht_mask >> shift) != 0)
1032 + for (i = 0; i <= mht->mht_mask; i++)
1035 + * Traverse the items in the i-th original bucket and move them into
1036 + * MHT_GROWTH_FACTOR new buckets, preserving their relative order
1037 + * within each new bucket. Preserving the order is important because
1038 + * mf_get() tries to keep most recently used items at the front of
1041 + * Here we strongly rely on the fact the hashes are computed modulo
1045 + vim_memset(tails, 0, sizeof(tails));
1047 + for (mhi = mht->mht_buckets[i]; mhi != NULL; mhi = mhi->mhi_next)
1049 + j = (mhi->mhi_key >> shift) & (MHT_GROWTH_FACTOR - 1);
1050 + if (tails[j] == NULL)
1052 + buckets[i + (j << shift)] = mhi;
1054 + mhi->mhi_prev = NULL;
1058 + tails[j]->mhi_next = mhi;
1059 + mhi->mhi_prev = tails[j];
1064 + for (j = 0; j < MHT_GROWTH_FACTOR; j++)
1065 + if (tails[j] != NULL)
1066 + tails[j]->mhi_next = NULL;
1069 + if (mht->mht_buckets != mht->mht_small_buckets)
1070 + vim_free(mht->mht_buckets);
1072 + mht->mht_buckets = buckets;
1073 + mht->mht_mask = (mht->mht_mask + 1) * MHT_GROWTH_FACTOR - 1;
1077 *** ../vim-7.3.142/src/memfile_test.c 2011-03-03 21:58:14.000000000 +0100
1078 --- src/memfile_test.c 2011-03-03 20:40:29.000000000 +0100
1082 + /* vi:set ts=8 sts=4 sw=4:
1084 + * VIM - Vi IMproved by Bram Moolenaar
1086 + * Do ":help uganda" in Vim to read copying and usage conditions.
1087 + * Do ":help credits" in Vim to see a list of people who contributed.
1088 + * See README.txt for an overview of the Vim source code.
1092 + * memfile_test.c: Unittests for memfile.c
1093 + * Mostly by Ivan Krasilnikov.
1097 + #include <assert.h>
1099 + /* Must include main.c because it contains much more than just main() */
1100 + #define NO_VIM_MAIN
1103 + /* This file has to be included because the tested functions are static */
1104 + #include "memfile.c"
1106 + #define index_to_key(i) ((i) ^ 15167)
1107 + #define TEST_COUNT 50000
1109 + static void test_mf_hash __ARGS((void));
1112 + * Test mf_hash_*() functions.
1118 + mf_hashitem_T *item;
1121 + long_u num_buckets;
1123 + mf_hash_init(&ht);
1125 + /* insert some items and check invariants */
1126 + for (i = 0; i < TEST_COUNT; i++)
1128 + assert(ht.mht_count == i);
1130 + /* check that number of buckets is a power of 2 */
1131 + num_buckets = ht.mht_mask + 1;
1132 + assert(num_buckets > 0 && (num_buckets & (num_buckets - 1)) == 0);
1134 + /* check load factor */
1135 + assert(ht.mht_count <= (num_buckets << MHT_LOG_LOAD_FACTOR));
1137 + if (i < (MHT_INIT_SIZE << MHT_LOG_LOAD_FACTOR))
1139 + /* first expansion shouldn't have occurred yet */
1140 + assert(num_buckets == MHT_INIT_SIZE);
1141 + assert(ht.mht_buckets == ht.mht_small_buckets);
1145 + assert(num_buckets > MHT_INIT_SIZE);
1146 + assert(ht.mht_buckets != ht.mht_small_buckets);
1149 + key = index_to_key(i);
1150 + assert(mf_hash_find(&ht, key) == NULL);
1152 + /* allocate and add new item */
1153 + item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);
1154 + assert(item != NULL);
1155 + item->mhi_key = key;
1156 + mf_hash_add_item(&ht, item);
1158 + assert(mf_hash_find(&ht, key) == item);
1160 + if (ht.mht_mask + 1 != num_buckets)
1162 + /* hash table was expanded */
1163 + assert(ht.mht_mask + 1 == num_buckets * MHT_GROWTH_FACTOR);
1164 + assert(i + 1 == (num_buckets << MHT_LOG_LOAD_FACTOR));
1168 + /* check presence of inserted items */
1169 + for (i = 0; i < TEST_COUNT; i++)
1171 + key = index_to_key(i);
1172 + item = mf_hash_find(&ht, key);
1173 + assert(item != NULL);
1174 + assert(item->mhi_key == key);
1177 + /* delete some items */
1178 + for (i = 0; i < TEST_COUNT; i++)
1182 + key = index_to_key(i);
1183 + item = mf_hash_find(&ht, key);
1184 + assert(item != NULL);
1185 + assert(item->mhi_key == key);
1187 + mf_hash_rem_item(&ht, item);
1188 + assert(mf_hash_find(&ht, key) == NULL);
1190 + mf_hash_add_item(&ht, item);
1191 + assert(mf_hash_find(&ht, key) == item);
1193 + mf_hash_rem_item(&ht, item);
1194 + assert(mf_hash_find(&ht, key) == NULL);
1201 + for (i = 0; i < TEST_COUNT; i++)
1203 + key = index_to_key(i);
1204 + item = mf_hash_find(&ht, key);
1208 + assert(item == NULL);
1212 + assert(item != NULL);
1213 + assert(item->mhi_key == key);
1217 + /* free hash table and all remaining items */
1218 + mf_hash_free_all(&ht);
1227 *** ../vim-7.3.142/src/structs.h 2011-02-15 17:39:14.000000000 +0100
1228 --- src/structs.h 2011-03-03 18:49:01.000000000 +0100
1232 typedef long blocknr_T;
1235 + * mf_hashtab_T is a chained hashtable with blocknr_T key and arbitrary
1236 + * structures as items. This is an intrusive data structure: we require
1237 + * that items begin with mf_hashitem_T which contains the key and linked
1238 + * list pointers. List of items in each bucket is doubly-linked.
1241 + typedef struct mf_hashitem_S mf_hashitem_T;
1243 + struct mf_hashitem_S
1245 + mf_hashitem_T *mhi_next;
1246 + mf_hashitem_T *mhi_prev;
1247 + blocknr_T mhi_key;
1250 + #define MHT_INIT_SIZE 64
1252 + typedef struct mf_hashtab_S
1254 + long_u mht_mask; /* mask used for hash value (nr of items
1255 + * in array is "mht_mask" + 1) */
1256 + long_u mht_count; /* nr of items inserted into hashtable */
1257 + mf_hashitem_T **mht_buckets; /* points to mht_small_buckets or
1258 + *dynamically allocated array */
1259 + mf_hashitem_T *mht_small_buckets[MHT_INIT_SIZE]; /* initial buckets */
1260 + char mht_fixed; /* non-zero value forbids growth */
1264 * for each (previously) used block in the memfile there is one block header.
1266 * The block may be linked in the used list OR in the free list.
1272 bhdr_T *bh_next; /* next block_hdr in free or used list */
1273 bhdr_T *bh_prev; /* previous block_hdr in used list */
1274 - bhdr_T *bh_hash_next; /* next block_hdr in hash list */
1275 - bhdr_T *bh_hash_prev; /* previous block_hdr in hash list */
1276 - blocknr_T bh_bnum; /* block number */
1277 char_u *bh_data; /* pointer to memory (for used block) */
1278 int bh_page_count; /* number of pages in this block */
1284 + mf_hashitem_T bh_hashitem; /* header for hash table and key */
1285 + #define bh_bnum bh_hashitem.mhi_key /* block number, part of bh_hashitem */
1287 bhdr_T *bh_next; /* next block_hdr in free or used list */
1288 bhdr_T *bh_prev; /* previous block_hdr in used list */
1289 char_u *bh_data; /* pointer to memory (for used block) */
1290 int bh_page_count; /* number of pages in this block */
1297 ! NR_TRANS *nt_next; /* next nr_trans in hash list */
1298 ! NR_TRANS *nt_prev; /* previous nr_trans in hash list */
1299 ! blocknr_T nt_old_bnum; /* old, negative, number */
1300 blocknr_T nt_new_bnum; /* new, positive, number */
1307 ! mf_hashitem_T nt_hashitem; /* header for hash table and key */
1308 ! #define nt_old_bnum nt_hashitem.mhi_key /* old, negative, number */
1310 blocknr_T nt_new_bnum; /* new, positive, number */
1316 typedef struct file_buffer buf_T; /* forward declaration */
1319 - * Simplistic hashing scheme to quickly locate the blocks in the used list.
1320 - * 64 blocks are found directly (64 * 4K = 256K, most files are smaller).
1322 - #define MEMHASHSIZE 64
1323 - #define MEMHASH(nr) ((nr) & (MEMHASHSIZE - 1))
1324 #define MF_SEED_LEN 8
1330 bhdr_T *mf_used_last; /* lru block_hdr in used list */
1331 unsigned mf_used_count; /* number of pages in used list */
1332 unsigned mf_used_count_max; /* maximum number of pages in memory */
1333 ! bhdr_T *mf_hash[MEMHASHSIZE]; /* array of hash lists */
1334 ! NR_TRANS *mf_trans[MEMHASHSIZE]; /* array of trans lists */
1335 blocknr_T mf_blocknr_max; /* highest positive block number + 1*/
1336 blocknr_T mf_blocknr_min; /* lowest negative block number - 1 */
1337 blocknr_T mf_neg_count; /* number of negative blocks numbers */
1339 bhdr_T *mf_used_last; /* lru block_hdr in used list */
1340 unsigned mf_used_count; /* number of pages in used list */
1341 unsigned mf_used_count_max; /* maximum number of pages in memory */
1342 ! mf_hashtab_T mf_hash; /* hash lists */
1343 ! mf_hashtab_T mf_trans; /* trans lists */
1344 blocknr_T mf_blocknr_max; /* highest positive block number + 1*/
1345 blocknr_T mf_blocknr_min; /* lowest negative block number - 1 */
1346 blocknr_T mf_neg_count; /* number of negative blocks numbers */
1347 *** ../vim-7.3.142/src/testdir/Make_amiga.mak 2010-11-10 16:54:16.000000000 +0100
1348 --- src/testdir/Make_amiga.mak 2011-03-03 17:04:14.000000000 +0100
1351 test61.out test62.out test63.out test64.out test65.out \
1352 test66.out test67.out test68.out test69.out test70.out \
1353 test71.out test72.out test73.out test74.out test75.out \
1359 test61.out test62.out test63.out test64.out test65.out \
1360 test66.out test67.out test68.out test69.out test70.out \
1361 test71.out test72.out test73.out test74.out test75.out \
1362 ! test76.out test77.out
1369 test74.out: test74.in
1370 test75.out: test75.in
1371 test76.out: test76.in
1372 + test77.out: test77.in
1373 *** ../vim-7.3.142/src/testdir/Make_dos.mak 2010-11-10 16:54:16.000000000 +0100
1374 --- src/testdir/Make_dos.mak 2011-03-03 17:04:20.000000000 +0100
1377 test37.out test38.out test39.out test40.out test41.out \
1378 test42.out test52.out test65.out test66.out test67.out \
1379 test68.out test69.out test71.out test72.out test73.out \
1380 ! test74.out test75.out test76.out
1382 SCRIPTS32 = test50.out test70.out
1385 test37.out test38.out test39.out test40.out test41.out \
1386 test42.out test52.out test65.out test66.out test67.out \
1387 test68.out test69.out test71.out test72.out test73.out \
1388 ! test74.out test75.out test76.out test77.out
1390 SCRIPTS32 = test50.out test70.out
1392 *** ../vim-7.3.142/src/testdir/Make_ming.mak 2010-11-10 16:54:16.000000000 +0100
1393 --- src/testdir/Make_ming.mak 2011-03-03 17:04:32.000000000 +0100
1396 test37.out test38.out test39.out test40.out test41.out \
1397 test42.out test52.out test65.out test66.out test67.out \
1398 test68.out test69.out test71.out test72.out test73.out \
1399 ! test74.out test75.out test76.out
1401 SCRIPTS32 = test50.out test70.out
1404 test37.out test38.out test39.out test40.out test41.out \
1405 test42.out test52.out test65.out test66.out test67.out \
1406 test68.out test69.out test71.out test72.out test73.out \
1407 ! test74.out test75.out test76.out test77.out
1409 SCRIPTS32 = test50.out test70.out
1411 *** ../vim-7.3.142/src/testdir/Make_os2.mak 2010-11-10 16:54:16.000000000 +0100
1412 --- src/testdir/Make_os2.mak 2011-03-03 17:04:48.000000000 +0100
1415 test61.out test62.out test63.out test64.out test65.out \
1416 test66.out test67.out test68.out test69.out test70.out \
1417 test71.out test72.out test73.out test74.out test75.out \
1423 test61.out test62.out test63.out test64.out test65.out \
1424 test66.out test67.out test68.out test69.out test70.out \
1425 test71.out test72.out test73.out test74.out test75.out \
1426 ! test76.out test77.out
1430 *** ../vim-7.3.142/src/testdir/Makefile 2010-11-10 16:54:16.000000000 +0100
1431 --- src/testdir/Makefile 2011-03-22 17:03:25.000000000 +0100
1434 test59.out test60.out test61.out test62.out test63.out \
1435 test64.out test65.out test66.out test67.out test68.out \
1436 test69.out test70.out test71.out test72.out test73.out \
1437 ! test74.out test75.out test76.out
1439 SCRIPTS_GUI = test16.out
1442 test59.out test60.out test61.out test62.out test63.out \
1443 test64.out test65.out test66.out test67.out test68.out \
1444 test69.out test70.out test71.out test72.out test73.out \
1445 ! test74.out test75.out test76.out test77.out
1447 SCRIPTS_GUI = test16.out
1452 else echo $* NO OUTPUT >>test.log; \
1454 ! -rm -rf X* test.ok viminfo
1456 test49.out: test49.vim
1460 else echo $* NO OUTPUT >>test.log; \
1462 ! # -rm -rf X* test.ok viminfo
1464 test49.out: test49.vim
1466 *** ../vim-7.3.142/src/testdir/test77.in 2011-03-03 21:59:10.000000000 +0100
1467 --- src/testdir/test77.in 2011-03-22 17:12:38.000000000 +0100
1471 + Inserts 2 million lines with consecutive integers starting from 1
1472 + (essentially, the output of GNU's seq 1 2000000), writes them to Xtest
1473 + and writes its cksum to test.out.
1475 + We need 2 million lines to trigger a call to mf_hash_grow(). If it would mess
1476 + up the lines the checksum would differ.
1478 + cksum is part of POSIX and so should be available on most Unixes.
1479 + If it isn't available then the test will be skipped.
1483 + :if !executable("cksum")
1488 + :set fileformat=unix undolevels=-1
1491 + :while i <= 2000000 | call append(i, range(i, i + 99)) | let i += 100 | endwhile
1494 + :!cksum Xtest > test.out
1498 *** ../vim-7.3.142/src/testdir/test77.ok 2011-03-03 21:59:10.000000000 +0100
1499 --- src/testdir/test77.ok 2011-03-22 17:10:14.000000000 +0100
1503 + 3678979763 14888896 Xtest
1504 *** ../vim-7.3.142/src/version.c 2011-03-22 15:47:18.000000000 +0100
1505 --- src/version.c 2011-03-22 18:01:48.000000000 +0100
1509 { /* Add new patch number below this line */
1515 SIGIRO -- irony detected (iron core dumped)
1517 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
1518 /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
1519 \\\ an exciting new programming language -- http://www.Zimbu.org ///
1520 \\\ help me help AIDS victims -- http://ICCF-Holland.org ///