Mercurial > vim
comparison src/spell.c @ 7509:a64793340689 v7.4.1056
commit https://github.com/vim/vim/commit/ca1fe985175385c609f8e06672a1014729aba05c
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Jan 7 16:22:06 2016 +0100
patch 7.4.1056
Problem: Don't know why finding spell suggestions is slow.
Solution: Add some code to gather profiling information.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 07 Jan 2016 16:30:09 +0100 |
parents | ad432f8f68fb |
children | 08c1f73efcde |
comparison
equal
deleted
inserted
replaced
7508:3eda97270667 | 7509:a64793340689 |
---|---|
11277 RESCORE(SCORE_REP, 0), 0, TRUE, su->su_sallang, FALSE); | 11277 RESCORE(SCORE_REP, 0), 0, TRUE, su->su_sallang, FALSE); |
11278 } | 11278 } |
11279 } | 11279 } |
11280 | 11280 |
11281 /* | 11281 /* |
11282 * Change the 0 to 1 to measure how much time is spent in each state. | |
11283 * Output is dumped in "suggestprof". | |
11284 */ | |
11285 #if 0 | |
11286 # define SUGGEST_PROFILE | |
11287 proftime_T current; | |
11288 proftime_T total; | |
11289 proftime_T times[STATE_FINAL + 1]; | |
11290 long counts[STATE_FINAL + 1]; | |
11291 | |
11292 static void | |
11293 prof_init(void) | |
11294 { | |
11295 for (int i = 0; i <= STATE_FINAL; ++i) | |
11296 { | |
11297 profile_zero(×[i]); | |
11298 counts[i] = 0; | |
11299 } | |
11300 profile_start(¤t); | |
11301 profile_start(&total); | |
11302 } | |
11303 | |
11304 /* call before changing state */ | |
11305 static void | |
11306 prof_store(state_T state) | |
11307 { | |
11308 profile_end(¤t); | |
11309 profile_add(×[state], ¤t); | |
11310 ++counts[state]; | |
11311 profile_start(¤t); | |
11312 } | |
11313 # define PROF_STORE(state) prof_store(state); | |
11314 | |
11315 static void | |
11316 prof_report(char *name) | |
11317 { | |
11318 FILE *fd = fopen("suggestprof", "a"); | |
11319 | |
11320 profile_end(&total); | |
11321 fprintf(fd, "-----------------------\n"); | |
11322 fprintf(fd, "%s: %s\n", name, profile_msg(&total)); | |
11323 for (int i = 0; i <= STATE_FINAL; ++i) | |
11324 fprintf(fd, "%d: %s (%ld)\n", i, profile_msg(×[i]), counts[i]); | |
11325 fclose(fd); | |
11326 } | |
11327 #else | |
11328 # define PROF_STORE(state) | |
11329 #endif | |
11330 | |
11331 /* | |
11282 * Try finding suggestions by adding/removing/swapping letters. | 11332 * Try finding suggestions by adding/removing/swapping letters. |
11283 */ | 11333 */ |
11284 static void | 11334 static void |
11285 suggest_try_change(su) | 11335 suggest_try_change(su) |
11286 suginfo_T *su; | 11336 suginfo_T *su; |
11307 * everything has been cleared. */ | 11357 * everything has been cleared. */ |
11308 if (lp->lp_slang->sl_fbyts == NULL) | 11358 if (lp->lp_slang->sl_fbyts == NULL) |
11309 continue; | 11359 continue; |
11310 | 11360 |
11311 /* Try it for this language. Will add possible suggestions. */ | 11361 /* Try it for this language. Will add possible suggestions. */ |
11362 #ifdef SUGGEST_PROFILE | |
11363 prof_init(); | |
11364 #endif | |
11312 suggest_trie_walk(su, lp, fword, FALSE); | 11365 suggest_trie_walk(su, lp, fword, FALSE); |
11366 #ifdef SUGGEST_PROFILE | |
11367 prof_report("try_change"); | |
11368 #endif | |
11313 } | 11369 } |
11314 } | 11370 } |
11315 | 11371 |
11316 /* Check the maximum score, if we go over it we won't try this change. */ | 11372 /* Check the maximum score, if we go over it we won't try this change. */ |
11317 #define TRY_DEEPER(su, stack, depth, add) \ | 11373 #define TRY_DEEPER(su, stack, depth, add) \ |
11465 ; | 11521 ; |
11466 sp->ts_curi += n; | 11522 sp->ts_curi += n; |
11467 | 11523 |
11468 /* Always past NUL bytes now. */ | 11524 /* Always past NUL bytes now. */ |
11469 n = (int)sp->ts_state; | 11525 n = (int)sp->ts_state; |
11526 PROF_STORE(sp->ts_state) | |
11470 sp->ts_state = STATE_ENDNUL; | 11527 sp->ts_state = STATE_ENDNUL; |
11471 sp->ts_save_badflags = su->su_badflags; | 11528 sp->ts_save_badflags = su->su_badflags; |
11472 | 11529 |
11473 /* At end of a prefix or at start of prefixtree: check for | 11530 /* At end of a prefix or at start of prefixtree: check for |
11474 * following word. */ | 11531 * following word. */ |
11508 } | 11565 } |
11509 | 11566 |
11510 if (sp->ts_curi > len || byts[arridx] != 0) | 11567 if (sp->ts_curi > len || byts[arridx] != 0) |
11511 { | 11568 { |
11512 /* Past bytes in node and/or past NUL bytes. */ | 11569 /* Past bytes in node and/or past NUL bytes. */ |
11570 PROF_STORE(sp->ts_state) | |
11513 sp->ts_state = STATE_ENDNUL; | 11571 sp->ts_state = STATE_ENDNUL; |
11514 sp->ts_save_badflags = su->su_badflags; | 11572 sp->ts_save_badflags = su->su_badflags; |
11515 break; | 11573 break; |
11516 } | 11574 } |
11517 | 11575 |
11907 sprintf(changename[depth], "%.*s-%s: compound", | 11965 sprintf(changename[depth], "%.*s-%s: compound", |
11908 sp->ts_twordlen, tword, fword + sp->ts_fidx); | 11966 sp->ts_twordlen, tword, fword + sp->ts_fidx); |
11909 #endif | 11967 #endif |
11910 /* Save things to be restored at STATE_SPLITUNDO. */ | 11968 /* Save things to be restored at STATE_SPLITUNDO. */ |
11911 sp->ts_save_badflags = su->su_badflags; | 11969 sp->ts_save_badflags = su->su_badflags; |
11970 PROF_STORE(sp->ts_state) | |
11912 sp->ts_state = STATE_SPLITUNDO; | 11971 sp->ts_state = STATE_SPLITUNDO; |
11913 | 11972 |
11914 ++depth; | 11973 ++depth; |
11915 sp = &stack[depth]; | 11974 sp = &stack[depth]; |
11916 | 11975 |
11981 if (pbyts != NULL) | 12040 if (pbyts != NULL) |
11982 { | 12041 { |
11983 byts = pbyts; | 12042 byts = pbyts; |
11984 idxs = pidxs; | 12043 idxs = pidxs; |
11985 sp->ts_prefixdepth = PFD_PREFIXTREE; | 12044 sp->ts_prefixdepth = PFD_PREFIXTREE; |
12045 PROF_STORE(sp->ts_state) | |
11986 sp->ts_state = STATE_NOPREFIX; | 12046 sp->ts_state = STATE_NOPREFIX; |
11987 } | 12047 } |
11988 } | 12048 } |
11989 } | 12049 } |
11990 } | 12050 } |
11993 case STATE_SPLITUNDO: | 12053 case STATE_SPLITUNDO: |
11994 /* Undo the changes done for word split or compound word. */ | 12054 /* Undo the changes done for word split or compound word. */ |
11995 su->su_badflags = sp->ts_save_badflags; | 12055 su->su_badflags = sp->ts_save_badflags; |
11996 | 12056 |
11997 /* Continue looking for NUL bytes. */ | 12057 /* Continue looking for NUL bytes. */ |
12058 PROF_STORE(sp->ts_state) | |
11998 sp->ts_state = STATE_START; | 12059 sp->ts_state = STATE_START; |
11999 | 12060 |
12000 /* In case we went into the prefix tree. */ | 12061 /* In case we went into the prefix tree. */ |
12001 byts = fbyts; | 12062 byts = fbyts; |
12002 idxs = fidxs; | 12063 idxs = fidxs; |
12010 && sp->ts_tcharlen == 0 | 12071 && sp->ts_tcharlen == 0 |
12011 #endif | 12072 #endif |
12012 ) | 12073 ) |
12013 { | 12074 { |
12014 /* The badword ends, can't use STATE_PLAIN. */ | 12075 /* The badword ends, can't use STATE_PLAIN. */ |
12076 PROF_STORE(sp->ts_state) | |
12015 sp->ts_state = STATE_DEL; | 12077 sp->ts_state = STATE_DEL; |
12016 break; | 12078 break; |
12017 } | 12079 } |
12080 PROF_STORE(sp->ts_state) | |
12018 sp->ts_state = STATE_PLAIN; | 12081 sp->ts_state = STATE_PLAIN; |
12019 /*FALLTHROUGH*/ | 12082 /*FALLTHROUGH*/ |
12020 | 12083 |
12021 case STATE_PLAIN: | 12084 case STATE_PLAIN: |
12022 /* | 12085 /* |
12026 arridx = sp->ts_arridx; | 12089 arridx = sp->ts_arridx; |
12027 if (sp->ts_curi > byts[arridx]) | 12090 if (sp->ts_curi > byts[arridx]) |
12028 { | 12091 { |
12029 /* Done all bytes at this node, do next state. When still at | 12092 /* Done all bytes at this node, do next state. When still at |
12030 * already changed bytes skip the other tricks. */ | 12093 * already changed bytes skip the other tricks. */ |
12094 PROF_STORE(sp->ts_state) | |
12031 if (sp->ts_fidx >= sp->ts_fidxtry) | 12095 if (sp->ts_fidx >= sp->ts_fidxtry) |
12032 sp->ts_state = STATE_DEL; | 12096 sp->ts_state = STATE_DEL; |
12033 else | 12097 else |
12034 sp->ts_state = STATE_FINAL; | 12098 sp->ts_state = STATE_FINAL; |
12035 } | 12099 } |
12182 #ifdef FEAT_MBYTE | 12246 #ifdef FEAT_MBYTE |
12183 /* When past the first byte of a multi-byte char don't try | 12247 /* When past the first byte of a multi-byte char don't try |
12184 * delete/insert/swap a character. */ | 12248 * delete/insert/swap a character. */ |
12185 if (has_mbyte && sp->ts_tcharlen > 0) | 12249 if (has_mbyte && sp->ts_tcharlen > 0) |
12186 { | 12250 { |
12251 PROF_STORE(sp->ts_state) | |
12187 sp->ts_state = STATE_FINAL; | 12252 sp->ts_state = STATE_FINAL; |
12188 break; | 12253 break; |
12189 } | 12254 } |
12190 #endif | 12255 #endif |
12191 /* | 12256 /* |
12192 * Try skipping one character in the bad word (delete it). | 12257 * Try skipping one character in the bad word (delete it). |
12193 */ | 12258 */ |
12259 PROF_STORE(sp->ts_state) | |
12194 sp->ts_state = STATE_INS_PREP; | 12260 sp->ts_state = STATE_INS_PREP; |
12195 sp->ts_curi = 1; | 12261 sp->ts_curi = 1; |
12196 if (soundfold && sp->ts_fidx == 0 && fword[sp->ts_fidx] == '*') | 12262 if (soundfold && sp->ts_fidx == 0 && fword[sp->ts_fidx] == '*') |
12197 /* Deleting a vowel at the start of a word counts less, see | 12263 /* Deleting a vowel at the start of a word counts less, see |
12198 * soundalike_score(). */ | 12264 * soundalike_score(). */ |
12243 case STATE_INS_PREP: | 12309 case STATE_INS_PREP: |
12244 if (sp->ts_flags & TSF_DIDDEL) | 12310 if (sp->ts_flags & TSF_DIDDEL) |
12245 { | 12311 { |
12246 /* If we just deleted a byte then inserting won't make sense, | 12312 /* If we just deleted a byte then inserting won't make sense, |
12247 * a substitute is always cheaper. */ | 12313 * a substitute is always cheaper. */ |
12314 PROF_STORE(sp->ts_state) | |
12248 sp->ts_state = STATE_SWAP; | 12315 sp->ts_state = STATE_SWAP; |
12249 break; | 12316 break; |
12250 } | 12317 } |
12251 | 12318 |
12252 /* skip over NUL bytes */ | 12319 /* skip over NUL bytes */ |
12254 for (;;) | 12321 for (;;) |
12255 { | 12322 { |
12256 if (sp->ts_curi > byts[n]) | 12323 if (sp->ts_curi > byts[n]) |
12257 { | 12324 { |
12258 /* Only NUL bytes at this node, go to next state. */ | 12325 /* Only NUL bytes at this node, go to next state. */ |
12326 PROF_STORE(sp->ts_state) | |
12259 sp->ts_state = STATE_SWAP; | 12327 sp->ts_state = STATE_SWAP; |
12260 break; | 12328 break; |
12261 } | 12329 } |
12262 if (byts[n + sp->ts_curi] != NUL) | 12330 if (byts[n + sp->ts_curi] != NUL) |
12263 { | 12331 { |
12264 /* Found a byte to insert. */ | 12332 /* Found a byte to insert. */ |
12333 PROF_STORE(sp->ts_state) | |
12265 sp->ts_state = STATE_INS; | 12334 sp->ts_state = STATE_INS; |
12266 break; | 12335 break; |
12267 } | 12336 } |
12268 ++sp->ts_curi; | 12337 ++sp->ts_curi; |
12269 } | 12338 } |
12276 * node. */ | 12345 * node. */ |
12277 n = sp->ts_arridx; | 12346 n = sp->ts_arridx; |
12278 if (sp->ts_curi > byts[n]) | 12347 if (sp->ts_curi > byts[n]) |
12279 { | 12348 { |
12280 /* Done all bytes at this node, go to next state. */ | 12349 /* Done all bytes at this node, go to next state. */ |
12350 PROF_STORE(sp->ts_state) | |
12281 sp->ts_state = STATE_SWAP; | 12351 sp->ts_state = STATE_SWAP; |
12282 break; | 12352 break; |
12283 } | 12353 } |
12284 | 12354 |
12285 /* Do one more byte at this node, but: | 12355 /* Do one more byte at this node, but: |
12347 p = fword + sp->ts_fidx; | 12417 p = fword + sp->ts_fidx; |
12348 c = *p; | 12418 c = *p; |
12349 if (c == NUL) | 12419 if (c == NUL) |
12350 { | 12420 { |
12351 /* End of word, can't swap or replace. */ | 12421 /* End of word, can't swap or replace. */ |
12422 PROF_STORE(sp->ts_state) | |
12352 sp->ts_state = STATE_FINAL; | 12423 sp->ts_state = STATE_FINAL; |
12353 break; | 12424 break; |
12354 } | 12425 } |
12355 | 12426 |
12356 /* Don't swap if the first character is not a word character. | 12427 /* Don't swap if the first character is not a word character. |
12357 * SWAP3 etc. also don't make sense then. */ | 12428 * SWAP3 etc. also don't make sense then. */ |
12358 if (!soundfold && !spell_iswordp(p, curwin)) | 12429 if (!soundfold && !spell_iswordp(p, curwin)) |
12359 { | 12430 { |
12431 PROF_STORE(sp->ts_state) | |
12360 sp->ts_state = STATE_REP_INI; | 12432 sp->ts_state = STATE_REP_INI; |
12361 break; | 12433 break; |
12362 } | 12434 } |
12363 | 12435 |
12364 #ifdef FEAT_MBYTE | 12436 #ifdef FEAT_MBYTE |
12385 } | 12457 } |
12386 | 12458 |
12387 /* When the second character is NUL we can't swap. */ | 12459 /* When the second character is NUL we can't swap. */ |
12388 if (c2 == NUL) | 12460 if (c2 == NUL) |
12389 { | 12461 { |
12462 PROF_STORE(sp->ts_state) | |
12390 sp->ts_state = STATE_REP_INI; | 12463 sp->ts_state = STATE_REP_INI; |
12391 break; | 12464 break; |
12392 } | 12465 } |
12393 | 12466 |
12394 /* When characters are identical, swap won't do anything. | 12467 /* When characters are identical, swap won't do anything. |
12395 * Also get here if the second char is not a word character. */ | 12468 * Also get here if the second char is not a word character. */ |
12396 if (c == c2) | 12469 if (c == c2) |
12397 { | 12470 { |
12471 PROF_STORE(sp->ts_state) | |
12398 sp->ts_state = STATE_SWAP3; | 12472 sp->ts_state = STATE_SWAP3; |
12399 break; | 12473 break; |
12400 } | 12474 } |
12401 if (c2 != NUL && TRY_DEEPER(su, stack, depth, SCORE_SWAP)) | 12475 if (c2 != NUL && TRY_DEEPER(su, stack, depth, SCORE_SWAP)) |
12402 { | 12476 { |
12404 #ifdef DEBUG_TRIEWALK | 12478 #ifdef DEBUG_TRIEWALK |
12405 sprintf(changename[depth], "%.*s-%s: swap %c and %c", | 12479 sprintf(changename[depth], "%.*s-%s: swap %c and %c", |
12406 sp->ts_twordlen, tword, fword + sp->ts_fidx, | 12480 sp->ts_twordlen, tword, fword + sp->ts_fidx, |
12407 c, c2); | 12481 c, c2); |
12408 #endif | 12482 #endif |
12483 PROF_STORE(sp->ts_state) | |
12409 sp->ts_state = STATE_UNSWAP; | 12484 sp->ts_state = STATE_UNSWAP; |
12410 ++depth; | 12485 ++depth; |
12411 #ifdef FEAT_MBYTE | 12486 #ifdef FEAT_MBYTE |
12412 if (has_mbyte) | 12487 if (has_mbyte) |
12413 { | 12488 { |
12423 p[1] = c; | 12498 p[1] = c; |
12424 stack[depth].ts_fidxtry = sp->ts_fidx + 2; | 12499 stack[depth].ts_fidxtry = sp->ts_fidx + 2; |
12425 } | 12500 } |
12426 } | 12501 } |
12427 else | 12502 else |
12503 { | |
12428 /* If this swap doesn't work then SWAP3 won't either. */ | 12504 /* If this swap doesn't work then SWAP3 won't either. */ |
12505 PROF_STORE(sp->ts_state) | |
12429 sp->ts_state = STATE_REP_INI; | 12506 sp->ts_state = STATE_REP_INI; |
12507 } | |
12430 break; | 12508 break; |
12431 | 12509 |
12432 case STATE_UNSWAP: | 12510 case STATE_UNSWAP: |
12433 /* Undo the STATE_SWAP swap: "21" -> "12". */ | 12511 /* Undo the STATE_SWAP swap: "21" -> "12". */ |
12434 p = fword + sp->ts_fidx; | 12512 p = fword + sp->ts_fidx; |
12482 * Also skip when c3 is NUL. | 12560 * Also skip when c3 is NUL. |
12483 * Also get here when the third character is not a word character. | 12561 * Also get here when the third character is not a word character. |
12484 * Second character may any char: "a.b" -> "b.a" */ | 12562 * Second character may any char: "a.b" -> "b.a" */ |
12485 if (c == c3 || c3 == NUL) | 12563 if (c == c3 || c3 == NUL) |
12486 { | 12564 { |
12565 PROF_STORE(sp->ts_state) | |
12487 sp->ts_state = STATE_REP_INI; | 12566 sp->ts_state = STATE_REP_INI; |
12488 break; | 12567 break; |
12489 } | 12568 } |
12490 if (TRY_DEEPER(su, stack, depth, SCORE_SWAP3)) | 12569 if (TRY_DEEPER(su, stack, depth, SCORE_SWAP3)) |
12491 { | 12570 { |
12493 #ifdef DEBUG_TRIEWALK | 12572 #ifdef DEBUG_TRIEWALK |
12494 sprintf(changename[depth], "%.*s-%s: swap3 %c and %c", | 12573 sprintf(changename[depth], "%.*s-%s: swap3 %c and %c", |
12495 sp->ts_twordlen, tword, fword + sp->ts_fidx, | 12574 sp->ts_twordlen, tword, fword + sp->ts_fidx, |
12496 c, c3); | 12575 c, c3); |
12497 #endif | 12576 #endif |
12577 PROF_STORE(sp->ts_state) | |
12498 sp->ts_state = STATE_UNSWAP3; | 12578 sp->ts_state = STATE_UNSWAP3; |
12499 ++depth; | 12579 ++depth; |
12500 #ifdef FEAT_MBYTE | 12580 #ifdef FEAT_MBYTE |
12501 if (has_mbyte) | 12581 if (has_mbyte) |
12502 { | 12582 { |
12513 p[2] = c; | 12593 p[2] = c; |
12514 stack[depth].ts_fidxtry = sp->ts_fidx + 3; | 12594 stack[depth].ts_fidxtry = sp->ts_fidx + 3; |
12515 } | 12595 } |
12516 } | 12596 } |
12517 else | 12597 else |
12598 { | |
12599 PROF_STORE(sp->ts_state) | |
12518 sp->ts_state = STATE_REP_INI; | 12600 sp->ts_state = STATE_REP_INI; |
12601 } | |
12519 break; | 12602 break; |
12520 | 12603 |
12521 case STATE_UNSWAP3: | 12604 case STATE_UNSWAP3: |
12522 /* Undo STATE_SWAP3: "321" -> "123" */ | 12605 /* Undo STATE_SWAP3: "321" -> "123" */ |
12523 p = fword + sp->ts_fidx; | 12606 p = fword + sp->ts_fidx; |
12545 | 12628 |
12546 if (!soundfold && !spell_iswordp(p, curwin)) | 12629 if (!soundfold && !spell_iswordp(p, curwin)) |
12547 { | 12630 { |
12548 /* Middle char is not a word char, skip the rotate. First and | 12631 /* Middle char is not a word char, skip the rotate. First and |
12549 * third char were already checked at swap and swap3. */ | 12632 * third char were already checked at swap and swap3. */ |
12633 PROF_STORE(sp->ts_state) | |
12550 sp->ts_state = STATE_REP_INI; | 12634 sp->ts_state = STATE_REP_INI; |
12551 break; | 12635 break; |
12552 } | 12636 } |
12553 | 12637 |
12554 /* Rotate three characters left: "123" -> "231". We change | 12638 /* Rotate three characters left: "123" -> "231". We change |
12560 p = fword + sp->ts_fidx; | 12644 p = fword + sp->ts_fidx; |
12561 sprintf(changename[depth], "%.*s-%s: rotate left %c%c%c", | 12645 sprintf(changename[depth], "%.*s-%s: rotate left %c%c%c", |
12562 sp->ts_twordlen, tword, fword + sp->ts_fidx, | 12646 sp->ts_twordlen, tword, fword + sp->ts_fidx, |
12563 p[0], p[1], p[2]); | 12647 p[0], p[1], p[2]); |
12564 #endif | 12648 #endif |
12649 PROF_STORE(sp->ts_state) | |
12565 sp->ts_state = STATE_UNROT3L; | 12650 sp->ts_state = STATE_UNROT3L; |
12566 ++depth; | 12651 ++depth; |
12567 p = fword + sp->ts_fidx; | 12652 p = fword + sp->ts_fidx; |
12568 #ifdef FEAT_MBYTE | 12653 #ifdef FEAT_MBYTE |
12569 if (has_mbyte) | 12654 if (has_mbyte) |
12585 p[2] = c; | 12670 p[2] = c; |
12586 stack[depth].ts_fidxtry = sp->ts_fidx + 3; | 12671 stack[depth].ts_fidxtry = sp->ts_fidx + 3; |
12587 } | 12672 } |
12588 } | 12673 } |
12589 else | 12674 else |
12675 { | |
12676 PROF_STORE(sp->ts_state) | |
12590 sp->ts_state = STATE_REP_INI; | 12677 sp->ts_state = STATE_REP_INI; |
12678 } | |
12591 break; | 12679 break; |
12592 | 12680 |
12593 case STATE_UNROT3L: | 12681 case STATE_UNROT3L: |
12594 /* Undo ROT3L: "231" -> "123" */ | 12682 /* Undo ROT3L: "231" -> "123" */ |
12595 p = fword + sp->ts_fidx; | 12683 p = fword + sp->ts_fidx; |
12621 p = fword + sp->ts_fidx; | 12709 p = fword + sp->ts_fidx; |
12622 sprintf(changename[depth], "%.*s-%s: rotate right %c%c%c", | 12710 sprintf(changename[depth], "%.*s-%s: rotate right %c%c%c", |
12623 sp->ts_twordlen, tword, fword + sp->ts_fidx, | 12711 sp->ts_twordlen, tword, fword + sp->ts_fidx, |
12624 p[0], p[1], p[2]); | 12712 p[0], p[1], p[2]); |
12625 #endif | 12713 #endif |
12714 PROF_STORE(sp->ts_state) | |
12626 sp->ts_state = STATE_UNROT3R; | 12715 sp->ts_state = STATE_UNROT3R; |
12627 ++depth; | 12716 ++depth; |
12628 p = fword + sp->ts_fidx; | 12717 p = fword + sp->ts_fidx; |
12629 #ifdef FEAT_MBYTE | 12718 #ifdef FEAT_MBYTE |
12630 if (has_mbyte) | 12719 if (has_mbyte) |
12646 *p = c; | 12735 *p = c; |
12647 stack[depth].ts_fidxtry = sp->ts_fidx + 3; | 12736 stack[depth].ts_fidxtry = sp->ts_fidx + 3; |
12648 } | 12737 } |
12649 } | 12738 } |
12650 else | 12739 else |
12740 { | |
12741 PROF_STORE(sp->ts_state) | |
12651 sp->ts_state = STATE_REP_INI; | 12742 sp->ts_state = STATE_REP_INI; |
12743 } | |
12652 break; | 12744 break; |
12653 | 12745 |
12654 case STATE_UNROT3R: | 12746 case STATE_UNROT3R: |
12655 /* Undo ROT3R: "312" -> "123" */ | 12747 /* Undo ROT3R: "312" -> "123" */ |
12656 p = fword + sp->ts_fidx; | 12748 p = fword + sp->ts_fidx; |
12682 * - already applied a REP item or swapped here */ | 12774 * - already applied a REP item or swapped here */ |
12683 if ((lp->lp_replang == NULL && !soundfold) | 12775 if ((lp->lp_replang == NULL && !soundfold) |
12684 || sp->ts_score + SCORE_REP >= su->su_maxscore | 12776 || sp->ts_score + SCORE_REP >= su->su_maxscore |
12685 || sp->ts_fidx < sp->ts_fidxtry) | 12777 || sp->ts_fidx < sp->ts_fidxtry) |
12686 { | 12778 { |
12779 PROF_STORE(sp->ts_state) | |
12687 sp->ts_state = STATE_FINAL; | 12780 sp->ts_state = STATE_FINAL; |
12688 break; | 12781 break; |
12689 } | 12782 } |
12690 | 12783 |
12691 /* Use the first byte to quickly find the first entry that may | 12784 /* Use the first byte to quickly find the first entry that may |
12695 else | 12788 else |
12696 sp->ts_curi = lp->lp_replang->sl_rep_first[fword[sp->ts_fidx]]; | 12789 sp->ts_curi = lp->lp_replang->sl_rep_first[fword[sp->ts_fidx]]; |
12697 | 12790 |
12698 if (sp->ts_curi < 0) | 12791 if (sp->ts_curi < 0) |
12699 { | 12792 { |
12793 PROF_STORE(sp->ts_state) | |
12700 sp->ts_state = STATE_FINAL; | 12794 sp->ts_state = STATE_FINAL; |
12701 break; | 12795 break; |
12702 } | 12796 } |
12703 | 12797 |
12798 PROF_STORE(sp->ts_state) | |
12704 sp->ts_state = STATE_REP; | 12799 sp->ts_state = STATE_REP; |
12705 /*FALLTHROUGH*/ | 12800 /*FALLTHROUGH*/ |
12706 | 12801 |
12707 case STATE_REP: | 12802 case STATE_REP: |
12708 /* Try matching with REP items from the .aff file. For each match | 12803 /* Try matching with REP items from the .aff file. For each match |
12731 sprintf(changename[depth], "%.*s-%s: replace %s with %s", | 12826 sprintf(changename[depth], "%.*s-%s: replace %s with %s", |
12732 sp->ts_twordlen, tword, fword + sp->ts_fidx, | 12827 sp->ts_twordlen, tword, fword + sp->ts_fidx, |
12733 ftp->ft_from, ftp->ft_to); | 12828 ftp->ft_from, ftp->ft_to); |
12734 #endif | 12829 #endif |
12735 /* Need to undo this afterwards. */ | 12830 /* Need to undo this afterwards. */ |
12831 PROF_STORE(sp->ts_state) | |
12736 sp->ts_state = STATE_REP_UNDO; | 12832 sp->ts_state = STATE_REP_UNDO; |
12737 | 12833 |
12738 /* Change the "from" to the "to" string. */ | 12834 /* Change the "from" to the "to" string. */ |
12739 ++depth; | 12835 ++depth; |
12740 fl = (int)STRLEN(ftp->ft_from); | 12836 fl = (int)STRLEN(ftp->ft_from); |
12752 break; | 12848 break; |
12753 } | 12849 } |
12754 } | 12850 } |
12755 | 12851 |
12756 if (sp->ts_curi >= gap->ga_len && sp->ts_state == STATE_REP) | 12852 if (sp->ts_curi >= gap->ga_len && sp->ts_state == STATE_REP) |
12853 { | |
12757 /* No (more) matches. */ | 12854 /* No (more) matches. */ |
12855 PROF_STORE(sp->ts_state) | |
12758 sp->ts_state = STATE_FINAL; | 12856 sp->ts_state = STATE_FINAL; |
12857 } | |
12759 | 12858 |
12760 break; | 12859 break; |
12761 | 12860 |
12762 case STATE_REP_UNDO: | 12861 case STATE_REP_UNDO: |
12763 /* Undo a REP replacement and continue with the next one. */ | 12862 /* Undo a REP replacement and continue with the next one. */ |
12773 { | 12872 { |
12774 STRMOVE(p + fl, p + tl); | 12873 STRMOVE(p + fl, p + tl); |
12775 repextra -= tl - fl; | 12874 repextra -= tl - fl; |
12776 } | 12875 } |
12777 mch_memmove(p, ftp->ft_from, fl); | 12876 mch_memmove(p, ftp->ft_from, fl); |
12877 PROF_STORE(sp->ts_state) | |
12778 sp->ts_state = STATE_REP; | 12878 sp->ts_state = STATE_REP; |
12779 break; | 12879 break; |
12780 | 12880 |
12781 default: | 12881 default: |
12782 /* Did all possible states at this level, go up one level. */ | 12882 /* Did all possible states at this level, go up one level. */ |
13285 spell_soundfold(slang, su->su_fbadword, TRUE, salword); | 13385 spell_soundfold(slang, su->su_fbadword, TRUE, salword); |
13286 | 13386 |
13287 /* try all kinds of inserts/deletes/swaps/etc. */ | 13387 /* try all kinds of inserts/deletes/swaps/etc. */ |
13288 /* TODO: also soundfold the next words, so that we can try joining | 13388 /* TODO: also soundfold the next words, so that we can try joining |
13289 * and splitting */ | 13389 * and splitting */ |
13390 #ifdef SUGGEST_PROFILE | |
13391 prof_init(); | |
13392 #endif | |
13290 suggest_trie_walk(su, lp, salword, TRUE); | 13393 suggest_trie_walk(su, lp, salword, TRUE); |
13394 #ifdef SUGGEST_PROFILE | |
13395 prof_report("soundalike"); | |
13396 #endif | |
13291 } | 13397 } |
13292 } | 13398 } |
13293 } | 13399 } |
13294 | 13400 |
13295 /* | 13401 /* |