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(&times[i]);
11298 counts[i] = 0;
11299 }
11300 profile_start(&current);
11301 profile_start(&total);
11302 }
11303
11304 /* call before changing state */
11305 static void
11306 prof_store(state_T state)
11307 {
11308 profile_end(&current);
11309 profile_add(&times[state], &current);
11310 ++counts[state];
11311 profile_start(&current);
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(&times[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 /*