_ZN8PfxEntryC2EP8AffixMgr:
   99|      8|    : pmyMgr(pmgr)
  100|      8|    , next(nullptr)
  101|      8|    , nexteq(nullptr)
  102|      8|    , nextne(nullptr)
  103|      8|    , flgnxt(nullptr) {}
_ZN8PfxEntry3addEPKcm:
  106|      4|std::string PfxEntry::add(const char* word, size_t len) {
  107|      4|  std::string result;
  108|      4|  if ((len > strip.size() || (len == 0 && pmyMgr->get_fullstrip())) &&
  ------------------
  |  Branch (108:7): [True: 4, False: 0]
  |  Branch (108:8): [True: 4, False: 0]
  |  Branch (108:31): [True: 0, False: 0]
  |  Branch (108:43): [True: 0, False: 0]
  ------------------
  109|      4|      (len >= numconds) && test_condition(word) &&
  ------------------
  |  Branch (109:7): [True: 4, False: 0]
  |  Branch (109:28): [True: 4, False: 0]
  ------------------
  110|      4|      (strip.empty() ||
  ------------------
  |  Branch (110:8): [True: 4, False: 0]
  ------------------
  111|      4|      (len >= strip.size() && strncmp(word, strip.c_str(), strip.size()) == 0))) {
  ------------------
  |  Branch (111:8): [True: 0, False: 0]
  |  Branch (111:31): [True: 0, False: 0]
  ------------------
  112|       |    /* we have a match so add prefix */
  113|      4|    result.assign(appnd);
  114|      4|    result.append(word + strip.size());
  115|      4|  }
  116|      4|  return result;
  117|      4|}
_ZNK8PfxEntry10applies_toEPK6hentrytPK8TraceCtx:
  219|      2|                          const TraceCtx* t) const {
  220|      2|  bool ok = TESTAFF(he->astr, aflag, he->alen);
  ------------------
  |  |  102|      2|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  221|      2|  if (t)
  ------------------
  |  Branch (221:7): [True: 0, False: 2]
  ------------------
  222|      0|    trace_test(*t, "pfx-aflag", pmyMgr, aflag, "dic", he->astr, he->alen,
  223|      0|               ok ? "pass" : "fail");
  ------------------
  |  Branch (223:16): [True: 0, False: 0]
  ------------------
  224|      2|  if (!ok)
  ------------------
  |  Branch (224:7): [True: 2, False: 0]
  ------------------
  225|      2|    return false;
  226|       |
  227|       |  // forbid single prefixes with needaffix flag
  228|      0|  FLAG needaffix = pmyMgr->get_needaffix();
  ------------------
  |  |   98|      0|#define FLAG unsigned short
  ------------------
  229|      0|  ok = !TESTAFF(contclass, needaffix, contclasslen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  230|      0|  if (t && needaffix)
  ------------------
  |  Branch (230:7): [True: 0, False: 0]
  |  Branch (230:12): [True: 0, False: 0]
  ------------------
  231|      0|    trace_test(*t, "needaffix", pmyMgr, needaffix, "pfx-cont", contclass,
  232|      0|               contclasslen,
  233|      0|               ok ? "pass" : "fail, this prefix needs a further affix");
  ------------------
  |  Branch (233:16): [True: 0, False: 0]
  ------------------
  234|      0|  if (!ok)
  ------------------
  |  Branch (234:7): [True: 0, False: 0]
  ------------------
  235|      0|    return false;
  236|       |
  237|       |  // a circumfix prefix needs a matching circumfix suffix, so it cannot stand
  238|       |  // on its own
  239|      0|  FLAG circumfix = pmyMgr->get_circumfix();
  ------------------
  |  |   98|      0|#define FLAG unsigned short
  ------------------
  240|      0|  ok = !TESTAFF(contclass, circumfix, contclasslen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  241|      0|  if (t && circumfix)
  ------------------
  |  Branch (241:7): [True: 0, False: 0]
  |  Branch (241:12): [True: 0, False: 0]
  ------------------
  242|      0|    trace_test(*t, "circumfix", pmyMgr, circumfix, "pfx-cont", contclass,
  243|      0|               contclasslen,
  244|      0|               ok ? "pass, prefix may stand alone"
  ------------------
  |  Branch (244:16): [True: 0, False: 0]
  ------------------
  245|      0|                  : "fail, a circumfix prefix needs its suffix");
  246|      0|  if (!ok)
  ------------------
  |  Branch (246:7): [True: 0, False: 0]
  ------------------
  247|      0|    return false;
  248|       |
  249|       |  // needflag
  250|      0|  if (needflag) {
  ------------------
  |  Branch (250:7): [True: 0, False: 0]
  ------------------
  251|      0|    bool in_dic = TESTAFF(he->astr, needflag, he->alen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  252|      0|    bool in_cont = contclass && TESTAFF(contclass, needflag, contclasslen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (252:20): [True: 0, False: 0]
  ------------------
  253|      0|    if (t) {
  ------------------
  |  Branch (253:9): [True: 0, False: 0]
  ------------------
  254|      0|      if (in_cont && !in_dic)
  ------------------
  |  Branch (254:11): [True: 0, False: 0]
  |  Branch (254:22): [True: 0, False: 0]
  ------------------
  255|      0|        trace_test(*t, "needflag", pmyMgr, needflag, "pfx-cont", contclass,
  256|      0|                   contclasslen, "pass");
  257|      0|      else
  258|      0|        trace_test(*t, "needflag", pmyMgr, needflag, "dic", he->astr, he->alen,
  259|      0|                   in_dic ? "pass"
  ------------------
  |  Branch (259:20): [True: 0, False: 0]
  ------------------
  260|      0|                          : "fail, the stem lacks the flag the caller asked for");
  261|      0|    }
  262|      0|    if (!in_dic && !in_cont)
  ------------------
  |  Branch (262:9): [True: 0, False: 0]
  |  Branch (262:20): [True: 0, False: 0]
  ------------------
  263|      0|      return false;
  264|      0|  }
  265|       |
  266|      0|  return true;
  267|      0|}
_ZN8PfxEntry9checkwordERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmctR12AffixScratch:
  275|  1.57M|                                   AffixScratch& scratch) {
  276|  1.57M|  struct hentry* he;  // hash entry of root word or NULL
  277|       |
  278|  1.57M|  TraceCtx* t = trace_on(scratch.trace);
  279|  1.57M|  if (t)
  ------------------
  |  Branch (279:7): [True: 0, False: 1.57M]
  ------------------
  280|      0|    trace_affix(*t, "pfx", pmyMgr, *this);
  281|  1.57M|  TraceScope trace_depth(t);
  282|       |
  283|       |  // on entry prefix is 0 length or already matches the beginning of the word.
  284|       |  // So if the remaining root word has positive length
  285|       |  // and if there are enough chars in root word and added back strip chars
  286|       |  // to meet the number of characters conditions, then test it
  287|       |
  288|  1.57M|  if (len < appnd.size())
  ------------------
  |  Branch (288:7): [True: 0, False: 1.57M]
  ------------------
  289|      0|    return nullptr;
  290|       |
  291|  1.57M|  size_t tmpl = len - appnd.size(); // length of tmpword
  292|       |
  293|  1.57M|  if (tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) {
  ------------------
  |  Branch (293:7): [True: 1.56M, False: 3.03k]
  |  Branch (293:20): [True: 3.03k, False: 0]
  |  Branch (293:33): [True: 0, False: 3.03k]
  ------------------
  294|       |    // generate new root word by removing prefix and adding
  295|       |    // back any characters that would have been stripped
  296|       |
  297|  1.56M|    std::string& tmpword = scratch.pfx_check_word;
  298|  1.56M|    tmpword.assign(strip);
  299|  1.56M|    tmpword.append(word, start + appnd.size(), tmpl);
  300|       |
  301|       |    // now make sure all of the conditions on characters
  302|       |    // are met.  Please see the appendix at the end of
  303|       |    // this file for more info on exactly what is being
  304|       |    // tested
  305|       |
  306|       |    // if all conditions are met then check if resulting
  307|       |    // root word in the dictionary
  308|       |
  309|  1.56M|    if (t)
  ------------------
  |  Branch (309:9): [True: 0, False: 1.56M]
  ------------------
  310|      0|      trace(*t, "stem \"%s\"", tmpword.c_str());
  311|       |
  312|  1.56M|    bool passes = test_condition(tmpword);
  313|  1.56M|    if (t)
  ------------------
  |  Branch (313:9): [True: 0, False: 1.56M]
  ------------------
  314|      0|      trace(*t, "test condition cond=\"%s\" on \"%s\" -> %s",
  315|      0|            get_condition().c_str(),
  316|      0|            tmpword.c_str(), passes ? "pass" : "fail");
  ------------------
  |  Branch (316:30): [True: 0, False: 0]
  ------------------
  317|       |
  318|  1.56M|    if (passes) {
  ------------------
  |  Branch (318:9): [True: 18.1k, False: 1.55M]
  ------------------
  319|  18.1k|      tmpl += strip.size();
  320|  18.1k|      if ((he = pmyMgr->lookup(tmpword.c_str(), tmpword.size())) != nullptr) {
  ------------------
  |  Branch (320:11): [True: 2, False: 18.1k]
  ------------------
  321|      2|        if (t)
  ------------------
  |  Branch (321:13): [True: 0, False: 2]
  ------------------
  322|      0|          trace(*t, "lookup \"%s\" -> entry \"%s\" flags=%s", tmpword.c_str(),
  323|      0|                he->word, trace_flags(pmyMgr, he->astr, he->alen).c_str());
  324|      2|        do {
  325|      2|          if (applies_to(he, needflag, t)) {
  ------------------
  |  Branch (325:15): [True: 0, False: 2]
  ------------------
  326|      0|            if (t)
  ------------------
  |  Branch (326:17): [True: 0, False: 0]
  ------------------
  327|      0|              trace(*t, "accept");
  328|      0|            return he;
  329|      0|          }
  330|      2|          he = he->next_homonym;  // check homonyms
  331|      2|          if (t) {
  ------------------
  |  Branch (331:15): [True: 0, False: 2]
  ------------------
  332|      0|            if (he)
  ------------------
  |  Branch (332:17): [True: 0, False: 0]
  ------------------
  333|      0|              trace(*t, "lookup \"%s\" -> entry \"%s\" flags=%s",
  334|      0|                    tmpword.c_str(), he->word,
  335|      0|                    trace_flags(pmyMgr, he->astr, he->alen).c_str());
  336|      0|            else
  337|      0|              trace(*t, "lookup \"%s\" -> no more homonyms", tmpword.c_str());
  338|      0|          }
  339|      2|        } while (he);
  ------------------
  |  Branch (339:18): [True: 0, False: 2]
  ------------------
  340|  18.1k|      } else if (t) {
  ------------------
  |  Branch (340:18): [True: 0, False: 18.1k]
  ------------------
  341|      0|        trace(*t, "lookup \"%s\" -> miss", tmpword.c_str());
  342|      0|      }
  343|       |
  344|       |      // prefix matched but no root word was found
  345|       |      // if aeXPRODUCT is allowed, try again but now
  346|       |      // ross checked combined with a suffix
  347|       |
  348|       |      // if ((opts & aeXPRODUCT) && in_compound) {
  349|  18.1k|      if ((opts & aeXPRODUCT)) {
  ------------------
  |  |   65|  18.1k|#define aeXPRODUCT (1 << 0)
  ------------------
  |  Branch (349:11): [True: 18.1k, False: 0]
  ------------------
  350|  18.1k|        he = pmyMgr->suffix_check(tmpword, 0, tmpl, aeXPRODUCT, this,
  ------------------
  |  |   65|  18.1k|#define aeXPRODUCT (1 << 0)
  ------------------
  351|  18.1k|                                  scratch, FLAG_NULL, needflag, in_compound);
  ------------------
  |  |   99|  18.1k|#define FLAG_NULL 0x00
  ------------------
  352|  18.1k|        if (he)
  ------------------
  |  Branch (352:13): [True: 0, False: 18.1k]
  ------------------
  353|      0|          return he;
  354|  18.1k|      }
  355|  18.1k|    }
  356|  1.56M|  } else if (t) {
  ------------------
  |  Branch (356:14): [True: 0, False: 3.03k]
  ------------------
  357|      0|    trace(*t, "test length have=%d -> fail, nothing would be left of the word",
  358|      0|          static_cast<int>(tmpl));
  359|      0|  }
  360|  1.57M|  return nullptr;
  361|  1.57M|}
_ZN8PfxEntry12check_twosfxERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmctR12AffixScratch:
  369|  1.56M|                                      AffixScratch& scratch) {
  370|       |  // on entry prefix is 0 length or already matches the beginning of the word.
  371|       |  // So if the remaining root word has positive length
  372|       |  // and if there are enough chars in root word and added back strip chars
  373|       |  // to meet the number of characters conditions, then test it
  374|       |
  375|  1.56M|  if (len < appnd.size())
  ------------------
  |  Branch (375:7): [True: 0, False: 1.56M]
  ------------------
  376|      0|    return nullptr;
  377|       |
  378|  1.56M|  size_t tmpl = len - appnd.size(); // length of tmpword
  379|       |
  380|  1.56M|  if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) &&
  ------------------
  |  Branch (380:8): [True: 1.56M, False: 2.77k]
  |  Branch (380:21): [True: 2.77k, False: 0]
  |  Branch (380:34): [True: 0, False: 2.77k]
  ------------------
  381|  1.56M|      (tmpl + strip.size() >= numconds)) {
  ------------------
  |  Branch (381:7): [True: 1.49M, False: 69.3k]
  ------------------
  382|       |    // generate new root word by removing prefix and adding
  383|       |    // back any characters that would have been stripped
  384|       |
  385|  1.49M|    std::string& tmpword = scratch.pfx_check_twosfx;
  386|  1.49M|    tmpword.assign(strip);
  387|  1.49M|    tmpword.append(word, start + appnd.size(), tmpl);
  388|       |
  389|       |    // now make sure all of the conditions on characters
  390|       |    // are met.  Please see the appendix at the end of
  391|       |    // this file for more info on exactly what is being
  392|       |    // tested
  393|       |
  394|       |    // if all conditions are met then check if resulting
  395|       |    // root word in the dictionary
  396|       |
  397|  1.49M|    if (test_condition(tmpword)) {
  ------------------
  |  Branch (397:9): [True: 12.4k, False: 1.48M]
  ------------------
  398|  12.4k|      tmpl += strip.size();
  399|       |
  400|       |      // prefix matched but no root word was found
  401|       |      // if aeXPRODUCT is allowed, try again but now
  402|       |      // cross checked combined with a suffix
  403|       |
  404|  12.4k|      if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
  ------------------
  |  |   65|  12.4k|#define aeXPRODUCT (1 << 0)
  ------------------
                    if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
  ------------------
  |  |   76|  12.4k|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (404:11): [True: 12.4k, False: 0]
  |  Branch (404:34): [True: 12.4k, False: 0]
  ------------------
  405|       |        // hash entry of root word or NULL
  406|  12.4k|        struct hentry* he = pmyMgr->suffix_check_twosfx(tmpword, 0, tmpl, aeXPRODUCT, this,
  ------------------
  |  |   65|  12.4k|#define aeXPRODUCT (1 << 0)
  ------------------
  407|  12.4k|                                                        scratch, needflag);
  408|  12.4k|        if (he)
  ------------------
  |  Branch (408:13): [True: 0, False: 12.4k]
  ------------------
  409|      0|          return he;
  410|  12.4k|      }
  411|  12.4k|    }
  412|  1.49M|  }
  413|  1.56M|  return nullptr;
  414|  1.56M|}
_ZN8PfxEntry18check_twosfx_morphERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmctR12AffixScratch:
  422|    654|                                         AffixScratch& scratch) {
  423|    654|  std::string result;
  424|       |  // on entry prefix is 0 length or already matches the beginning of the word.
  425|       |  // So if the remaining root word has positive length
  426|       |  // and if there are enough chars in root word and added back strip chars
  427|       |  // to meet the number of characters conditions, then test it
  428|    654|  if (len < appnd.size())
  ------------------
  |  Branch (428:7): [True: 0, False: 654]
  ------------------
  429|      0|    return result;
  430|       |
  431|    654|  size_t tmpl = len - appnd.size(); // length of tmpword
  432|       |
  433|    654|  if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) &&
  ------------------
  |  Branch (433:8): [True: 654, False: 0]
  |  Branch (433:21): [True: 0, False: 0]
  |  Branch (433:34): [True: 0, False: 0]
  ------------------
  434|    654|      (tmpl + strip.size() >= numconds)) {
  ------------------
  |  Branch (434:7): [True: 565, False: 89]
  ------------------
  435|       |    // generate new root word by removing prefix and adding
  436|       |    // back any characters that would have been stripped
  437|       |
  438|    565|    std::string& tmpword = scratch.pfx_check_twosfx;
  439|    565|    tmpword.assign(strip);
  440|    565|    tmpword.append(word, start + appnd.size(), tmpl);
  441|       |
  442|       |    // now make sure all of the conditions on characters
  443|       |    // are met.  Please see the appendix at the end of
  444|       |    // this file for more info on exactly what is being
  445|       |    // tested
  446|       |
  447|       |    // if all conditions are met then check if resulting
  448|       |    // root word in the dictionary
  449|       |
  450|    565|    if (test_condition(tmpword)) {
  ------------------
  |  Branch (450:9): [True: 0, False: 565]
  ------------------
  451|      0|      tmpl += strip.size();
  452|       |
  453|       |      // prefix matched but no root word was found
  454|       |      // if aeXPRODUCT is allowed, try again but now
  455|       |      // ross checked combined with a suffix
  456|       |
  457|      0|      if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
  ------------------
  |  |   65|      0|#define aeXPRODUCT (1 << 0)
  ------------------
                    if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
  ------------------
  |  |   76|      0|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (457:11): [True: 0, False: 0]
  |  Branch (457:34): [True: 0, False: 0]
  ------------------
  458|      0|        result = pmyMgr->suffix_check_twosfx_morph(tmpword, 0, tmpl,
  459|      0|                                                   aeXPRODUCT,
  ------------------
  |  |   65|      0|#define aeXPRODUCT (1 << 0)
  ------------------
  460|      0|                                                   this, scratch, needflag);
  461|      0|      }
  462|      0|    }
  463|    565|  }
  464|    654|  return result;
  465|    654|}
_ZN8PfxEntry11check_morphERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmctR12AffixScratch:
  473|    655|                                  AffixScratch& scratch) {
  474|    655|  std::string result;
  475|       |
  476|       |  // on entry prefix is 0 length or already matches the beginning of the word.
  477|       |  // So if the remaining root word has positive length
  478|       |  // and if there are enough chars in root word and added back strip chars
  479|       |  // to meet the number of characters conditions, then test it
  480|       |
  481|    655|  if (len < appnd.size())
  ------------------
  |  Branch (481:7): [True: 0, False: 655]
  ------------------
  482|      0|    return result;
  483|       |
  484|    655|  size_t tmpl = len - appnd.size(); // length of tmpword
  485|       |
  486|    655|  if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) &&
  ------------------
  |  Branch (486:8): [True: 655, False: 0]
  |  Branch (486:21): [True: 0, False: 0]
  |  Branch (486:34): [True: 0, False: 0]
  ------------------
  487|    655|      (tmpl + strip.size() >= numconds)) {
  ------------------
  |  Branch (487:7): [True: 566, False: 89]
  ------------------
  488|       |    // generate new root word by removing prefix and adding
  489|       |    // back any characters that would have been stripped
  490|       |
  491|    566|    std::string& tmpword = scratch.pfx_check_word;
  492|    566|    tmpword.assign(strip);
  493|    566|    tmpword.append(word, start + appnd.size(), tmpl);
  494|       |
  495|       |    // now make sure all of the conditions on characters
  496|       |    // are met.  Please see the appendix at the end of
  497|       |    // this file for more info on exactly what is being
  498|       |    // tested
  499|       |
  500|       |    // if all conditions are met then check if resulting
  501|       |    // root word in the dictionary
  502|       |
  503|    566|    if (test_condition(tmpword)) {
  ------------------
  |  Branch (503:9): [True: 1, False: 565]
  ------------------
  504|      1|      tmpl += strip.size();
  505|      1|      struct hentry* he;  // hash entry of root word or NULL
  506|      1|      if ((he = pmyMgr->lookup(tmpword.c_str(), tmpword.size())) != nullptr) {
  ------------------
  |  Branch (506:11): [True: 0, False: 1]
  ------------------
  507|      0|        do {
  508|      0|          if (applies_to(he, needflag, nullptr)) {
  ------------------
  |  Branch (508:15): [True: 0, False: 0]
  ------------------
  509|      0|            if (morphcode) {
  ------------------
  |  Branch (509:17): [True: 0, False: 0]
  ------------------
  510|      0|              result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
  511|      0|              result.append(morphcode);
  512|      0|            } else
  513|      0|              result.append(getKey());
  514|      0|            append_morph_stem(result, he, pmyMgr->get_complexprefixes());
  515|       |            // store the pointer of the hash entry
  516|      0|            if (HENTRY_DATA(he)) {
  ------------------
  |  Branch (516:17): [True: 0, False: 0]
  ------------------
  517|      0|              result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
  518|      0|              result.append(HENTRY_DATA2(he));
  519|      0|            } else {
  520|       |              // return with debug information
  521|      0|              std::string flag = pmyMgr->encode_flag(getFlag());
  522|      0|              result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
  523|      0|              result.append(MORPH_FLAG);
  ------------------
  |  |  113|      0|#define MORPH_FLAG "fl:"
  ------------------
  524|      0|              result.append(flag);
  525|      0|            }
  526|      0|            result.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
  527|      0|          }
  528|      0|          he = he->next_homonym;
  529|      0|        } while (he);
  ------------------
  |  Branch (529:18): [True: 0, False: 0]
  ------------------
  530|      0|      }
  531|       |
  532|       |      // prefix matched but no root word was found
  533|       |      // if aeXPRODUCT is allowed, try again but now
  534|       |      // ross checked combined with a suffix
  535|       |
  536|      1|      if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
  ------------------
  |  |   65|      1|#define aeXPRODUCT (1 << 0)
  ------------------
                    if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
  ------------------
  |  |   76|      1|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (536:11): [True: 1, False: 0]
  |  Branch (536:34): [True: 1, False: 0]
  ------------------
  537|      1|        std::string st = pmyMgr->suffix_check_morph(tmpword, 0, tmpl, aeXPRODUCT, this,
  ------------------
  |  |   65|      1|#define aeXPRODUCT (1 << 0)
  ------------------
  538|      1|                                                    scratch, FLAG_NULL, needflag);
  ------------------
  |  |   99|      1|#define FLAG_NULL 0x00
  ------------------
  539|      1|        if (!st.empty()) {
  ------------------
  |  Branch (539:13): [True: 0, False: 1]
  ------------------
  540|      0|          result.append(st);
  541|      0|        }
  542|      1|      }
  543|      1|    }
  544|    566|  }
  545|       |
  546|    655|  return result;
  547|    655|}
_ZN8SfxEntryC2EP8AffixMgr:
  550|     34|    : pmyMgr(pmgr)  // register affix manager
  551|     34|    , next(nullptr)
  552|     34|    , nexteq(nullptr)
  553|     34|    , nextne(nullptr)
  554|     34|    , flgnxt(nullptr)
  555|     34|    , l_morph(nullptr)
  556|     34|    , r_morph(nullptr)
  557|     34|    , eq_morph(nullptr) {}
_ZN8SfxEntry3addEPKcm:
  587|     30|std::string SfxEntry::add(const char* word, size_t len) {
  588|     30|  std::string result;
  589|       |  /* make sure all conditions match */
  590|     30|  if ((len > strip.size() || (len == 0 && pmyMgr->get_fullstrip())) &&
  ------------------
  |  Branch (590:8): [True: 30, False: 0]
  |  Branch (590:31): [True: 0, False: 0]
  |  Branch (590:43): [True: 0, False: 0]
  ------------------
  591|     30|      (len >= numconds) && test_condition(word + len, word) &&
  ------------------
  |  Branch (591:7): [True: 30, False: 0]
  |  Branch (591:28): [True: 30, False: 0]
  ------------------
  592|     30|      (strip.empty() ||
  ------------------
  |  Branch (592:8): [True: 30, False: 0]
  ------------------
  593|     30|       (len >= strip.size() && strcmp(word + len - strip.size(), strip.c_str()) == 0))) {
  ------------------
  |  Branch (593:9): [True: 0, False: 0]
  |  Branch (593:32): [True: 0, False: 0]
  ------------------
  594|     30|    result.assign(word, len);
  595|       |    /* we have a match so add suffix */
  596|     30|    result.replace(len - strip.size(), std::string::npos, appnd);
  597|     30|  }
  598|     30|  return result;
  599|     30|}
_ZNK8SfxEntry10applies_toEPK6hentryiP8PfxEntrytttPK8TraceCtx:
  739|     10|                          const TraceCtx* t) const {
  740|       |  // the suffix flag is either on the entry itself, or on a prefix that enables
  741|       |  // this suffix
  742|     10|  bool in_dic = TESTAFF(he->astr, aflag, he->alen);
  ------------------
  |  |  102|     10|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  743|     10|  bool in_prefix = ep && ep->getCont() &&
  ------------------
  |  Branch (743:20): [True: 0, False: 10]
  |  Branch (743:26): [True: 0, False: 0]
  ------------------
  744|      0|                   TESTAFF(ep->getCont(), aflag, ep->getContLen());
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  745|     10|  if (t) {
  ------------------
  |  Branch (745:7): [True: 0, False: 10]
  ------------------
  746|      0|    if (in_prefix && !in_dic)
  ------------------
  |  Branch (746:9): [True: 0, False: 0]
  |  Branch (746:22): [True: 0, False: 0]
  ------------------
  747|      0|      trace_test(*t, "sfx-aflag", pmyMgr, aflag, "pfx-cont", ep->getCont(),
  748|      0|                 ep->getContLen(), "pass, the prefix enables this suffix");
  749|      0|    else
  750|      0|      trace_test(*t, "sfx-aflag", pmyMgr, aflag, "dic", he->astr, he->alen,
  751|      0|                 in_dic ? "pass" : "fail");
  ------------------
  |  Branch (751:18): [True: 0, False: 0]
  ------------------
  752|      0|  }
  753|     10|  if (!in_dic && !in_prefix)
  ------------------
  |  Branch (753:7): [True: 10, False: 0]
  |  Branch (753:18): [True: 10, False: 0]
  ------------------
  754|     10|    return false;
  755|       |
  756|       |  // the prefix and the suffix have to be allowed to meet
  757|      0|  if ((optflags & aeXPRODUCT) != 0) {
  ------------------
  |  |   65|      0|#define aeXPRODUCT (1 << 0)
  ------------------
  |  Branch (757:7): [True: 0, False: 0]
  ------------------
  758|      0|    FLAG pflag = ep ? ep->getFlag() : FLAG_NULL;
  ------------------
  |  |   98|      0|#define FLAG unsigned short
  ------------------
                  FLAG pflag = ep ? ep->getFlag() : FLAG_NULL;
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
  |  Branch (758:18): [True: 0, False: 0]
  ------------------
  759|      0|    in_dic = ep && TESTAFF(he->astr, pflag, he->alen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (759:14): [True: 0, False: 0]
  ------------------
  760|      0|    bool in_cont = contclass && ep && TESTAFF(contclass, pflag, contclasslen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (760:20): [True: 0, False: 0]
  |  Branch (760:33): [True: 0, False: 0]
  ------------------
  761|      0|    if (t) {
  ------------------
  |  Branch (761:9): [True: 0, False: 0]
  ------------------
  762|      0|      if (in_cont && !in_dic)
  ------------------
  |  Branch (762:11): [True: 0, False: 0]
  |  Branch (762:22): [True: 0, False: 0]
  ------------------
  763|      0|        trace_test(*t, "xprod", pmyMgr, pflag, "sfx-cont", contclass,
  764|      0|                   contclasslen, "pass, this suffix enables the prefix");
  765|      0|      else
  766|      0|        trace_test(*t, "xprod", pmyMgr, pflag, "dic", he->astr, he->alen,
  767|      0|                   in_dic ? "pass"
  ------------------
  |  Branch (767:20): [True: 0, False: 0]
  ------------------
  768|      0|                          : "fail, the stem does not take the prefix as well");
  769|      0|    }
  770|      0|    if (!in_dic && !in_cont)
  ------------------
  |  Branch (770:9): [True: 0, False: 0]
  |  Branch (770:20): [True: 0, False: 0]
  ------------------
  771|      0|      return false;
  772|      0|  }
  773|       |
  774|       |  // handle cont. class
  775|      0|  if (cclass) {
  ------------------
  |  Branch (775:7): [True: 0, False: 0]
  ------------------
  776|      0|    bool ok = contclass && TESTAFF(contclass, cclass, contclasslen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (776:15): [True: 0, False: 0]
  ------------------
  777|      0|    if (t)
  ------------------
  |  Branch (777:9): [True: 0, False: 0]
  ------------------
  778|      0|      trace_test(*t, "cclass", pmyMgr, cclass, "sfx-cont", contclass,
  779|      0|                 contclasslen,
  780|      0|                 ok ? "pass" : "fail, this suffix does not continue the last one");
  ------------------
  |  Branch (780:18): [True: 0, False: 0]
  ------------------
  781|      0|    if (!ok)
  ------------------
  |  Branch (781:9): [True: 0, False: 0]
  ------------------
  782|      0|      return false;
  783|      0|  }
  784|       |
  785|       |  // check only in compound homonyms (bad flags)
  786|      0|  if (badflag) {
  ------------------
  |  Branch (786:7): [True: 0, False: 0]
  ------------------
  787|      0|    bool ok = !TESTAFF(he->astr, badflag, he->alen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  788|      0|    if (t)
  ------------------
  |  Branch (788:9): [True: 0, False: 0]
  ------------------
  789|      0|      trace_test(*t, "badflag", pmyMgr, badflag, "dic", he->astr, he->alen,
  790|      0|                 ok ? "pass" : "fail, the stem has a flag this context forbids");
  ------------------
  |  Branch (790:18): [True: 0, False: 0]
  ------------------
  791|      0|    if (!ok)
  ------------------
  |  Branch (791:9): [True: 0, False: 0]
  ------------------
  792|      0|      return false;
  793|      0|  }
  794|       |
  795|       |  // handle required flag
  796|      0|  if (needflag) {
  ------------------
  |  Branch (796:7): [True: 0, False: 0]
  ------------------
  797|      0|    in_dic = TESTAFF(he->astr, needflag, he->alen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  798|      0|    bool in_cont = contclass && TESTAFF(contclass, needflag, contclasslen);
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (798:20): [True: 0, False: 0]
  ------------------
  799|      0|    if (t) {
  ------------------
  |  Branch (799:9): [True: 0, False: 0]
  ------------------
  800|      0|      if (in_cont && !in_dic)
  ------------------
  |  Branch (800:11): [True: 0, False: 0]
  |  Branch (800:22): [True: 0, False: 0]
  ------------------
  801|      0|        trace_test(*t, "needflag", pmyMgr, needflag, "sfx-cont", contclass,
  802|      0|                   contclasslen, "pass");
  803|      0|      else
  804|      0|        trace_test(*t, "needflag", pmyMgr, needflag, "dic", he->astr, he->alen,
  805|      0|                   in_dic ? "pass"
  ------------------
  |  Branch (805:20): [True: 0, False: 0]
  ------------------
  806|      0|                          : "fail, the stem lacks the flag the caller asked for");
  807|      0|    }
  808|      0|    if (!in_dic && !in_cont)
  ------------------
  |  Branch (808:9): [True: 0, False: 0]
  |  Branch (808:20): [True: 0, False: 0]
  ------------------
  809|      0|      return false;
  810|      0|  }
  811|       |
  812|      0|  return true;
  813|      0|}
_ZN8SfxEntry9checkwordERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmiP8PfxEntrytttR12AffixScratch:
  824|  44.7k|                                   AffixScratch& scratch) {
  825|  44.7k|  struct hentry* he;  // hash entry pointer
  826|  44.7k|  PfxEntry* ep = ppfx;
  827|       |
  828|  44.7k|  TraceCtx* t = trace_on(scratch.trace);
  829|  44.7k|  if (t)
  ------------------
  |  Branch (829:7): [True: 0, False: 44.7k]
  ------------------
  830|      0|    trace_affix(*t, "sfx", pmyMgr, *this);
  831|  44.7k|  TraceScope trace_depth(t);
  832|       |
  833|       |  // if this suffix is being cross checked with a prefix
  834|       |  // but it does not support cross products skip it
  835|       |
  836|  44.7k|  if (((optflags & aeXPRODUCT) != 0) && ((opts & aeXPRODUCT) == 0)) {
  ------------------
  |  |   65|  44.7k|#define aeXPRODUCT (1 << 0)
  ------------------
                if (((optflags & aeXPRODUCT) != 0) && ((opts & aeXPRODUCT) == 0)) {
  ------------------
  |  |   65|      0|#define aeXPRODUCT (1 << 0)
  ------------------
  |  Branch (836:7): [True: 0, False: 44.7k]
  |  Branch (836:41): [True: 0, False: 0]
  ------------------
  837|      0|    if (t)
  ------------------
  |  Branch (837:9): [True: 0, False: 0]
  ------------------
  838|      0|      trace(*t, "test xprod -> fail, this suffix class does not cross with a"
  839|      0|                " prefix");
  840|      0|    return nullptr;
  841|      0|  }
  842|       |
  843|       |  // upon entry suffix is 0 length or already matches the end of the word.
  844|       |  // So if the remaining root word has positive length
  845|       |  // and if there are enough chars in root word and added back strip chars
  846|       |  // to meet the number of characters conditions, then test it
  847|       |
  848|  44.7k|  if (len < appnd.size())
  ------------------
  |  Branch (848:7): [True: 0, False: 44.7k]
  ------------------
  849|      0|    return nullptr;
  850|       |
  851|  44.7k|  size_t tmpl = len - appnd.size(); // length of tmpword
  852|       |  // the second condition is not enough for UTF-8 strings
  853|       |  // it checked in test_condition()
  854|       |
  855|  44.7k|  if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) &&
  ------------------
  |  Branch (855:8): [True: 42.9k, False: 1.71k]
  |  Branch (855:21): [True: 1.71k, False: 0]
  |  Branch (855:34): [True: 0, False: 1.71k]
  ------------------
  856|  42.9k|      (tmpl + strip.size() >= numconds)) {
  ------------------
  |  Branch (856:7): [True: 42.9k, False: 0]
  ------------------
  857|       |    // generate new root word by removing suffix and adding
  858|       |    // back any characters that would have been stripped or
  859|       |    // or null terminating the shorter string
  860|       |
  861|  42.9k|    std::string& tmpword = scratch.sfx_check_word;
  862|  42.9k|    tmpword.assign(word, start, tmpl);
  863|  42.9k|    if (!strip.empty()) {
  ------------------
  |  Branch (863:9): [True: 0, False: 42.9k]
  ------------------
  864|      0|      tmpword.append(strip);
  865|      0|    }
  866|       |
  867|  42.9k|    const char* beg = tmpword.c_str();
  868|  42.9k|    const char* end = beg + tmpword.size();
  869|       |
  870|       |    // now make sure all of the conditions on characters
  871|       |    // are met.  Please see the appendix at the end of
  872|       |    // this file for more info on exactly what is being
  873|       |    // tested
  874|       |
  875|       |    // if all conditions are met then check if resulting
  876|       |    // root word in the dictionary
  877|       |
  878|  42.9k|    if (t)
  ------------------
  |  Branch (878:9): [True: 0, False: 42.9k]
  ------------------
  879|      0|      trace(*t, "stem \"%s\"", tmpword.c_str());
  880|       |
  881|  42.9k|    bool passes = test_condition(end, beg);
  882|  42.9k|    if (t)
  ------------------
  |  Branch (882:9): [True: 0, False: 42.9k]
  ------------------
  883|      0|      trace(*t, "test condition cond=\"%s\" on \"%s\" -> %s",
  884|      0|            get_condition().c_str(),
  885|      0|            tmpword.c_str(), passes ? "pass" : "fail");
  ------------------
  |  Branch (885:30): [True: 0, False: 0]
  ------------------
  886|       |
  887|  42.9k|    if (passes) {
  ------------------
  |  Branch (887:9): [True: 42.9k, False: 0]
  ------------------
  888|       |#ifdef SZOSZABLYA_POSSIBLE_ROOTS
  889|       |      fprintf(stdout, "%s %s %c\n", word.c_str() + start, beg, aflag);
  890|       |#endif
  891|  42.9k|      if ((he = pmyMgr->lookup(tmpword.c_str(), tmpword.size())) != nullptr) {
  ------------------
  |  Branch (891:11): [True: 10, False: 42.9k]
  ------------------
  892|     10|        if (t)
  ------------------
  |  Branch (892:13): [True: 0, False: 10]
  ------------------
  893|      0|          trace(*t, "lookup \"%s\" -> entry \"%s\" flags=%s", tmpword.c_str(),
  894|      0|                he->word, trace_flags(pmyMgr, he->astr, he->alen).c_str());
  895|     10|        do {
  896|     10|          if (applies_to(he, optflags, ep, cclass, needflag, badflag, t)) {
  ------------------
  |  Branch (896:15): [True: 0, False: 10]
  ------------------
  897|      0|            if (t)
  ------------------
  |  Branch (897:17): [True: 0, False: 0]
  ------------------
  898|      0|              trace(*t, "accept");
  899|      0|            return he;
  900|      0|          }
  901|     10|          he = he->next_homonym;  // check homonyms
  902|     10|          if (t) {
  ------------------
  |  Branch (902:15): [True: 0, False: 10]
  ------------------
  903|      0|            if (he)
  ------------------
  |  Branch (903:17): [True: 0, False: 0]
  ------------------
  904|      0|              trace(*t, "lookup \"%s\" -> entry \"%s\" flags=%s",
  905|      0|                    tmpword.c_str(), he->word,
  906|      0|                    trace_flags(pmyMgr, he->astr, he->alen).c_str());
  907|      0|            else
  908|      0|              trace(*t, "lookup \"%s\" -> no more homonyms", tmpword.c_str());
  909|      0|          }
  910|     10|        } while (he);
  ------------------
  |  Branch (910:18): [True: 0, False: 10]
  ------------------
  911|  42.9k|      } else if (t) {
  ------------------
  |  Branch (911:18): [True: 0, False: 42.9k]
  ------------------
  912|      0|        trace(*t, "lookup \"%s\" -> miss", tmpword.c_str());
  913|      0|      }
  914|  42.9k|    }
  915|  42.9k|  } else if (t) {
  ------------------
  |  Branch (915:14): [True: 0, False: 1.71k]
  ------------------
  916|      0|    trace(*t, "test length have=%d need=%d -> fail, too little is left of the"
  917|      0|              " word to test", static_cast<int>(tmpl), (int)numconds);
  918|      0|  }
  919|  44.7k|  return nullptr;
  920|  44.7k|}
_ZN8SfxEntry12check_twosfxERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmiP8PfxEntrytR12AffixScratch:
  929|  22.8k|                                      AffixScratch& scratch) {
  930|  22.8k|  PfxEntry* ep = ppfx;
  931|       |
  932|       |  // if this suffix is being cross checked with a prefix
  933|       |  // but it does not support cross products skip it
  934|       |
  935|  22.8k|  if ((optflags & aeXPRODUCT) != 0 && (opts & aeXPRODUCT) == 0)
  ------------------
  |  |   65|  22.8k|#define aeXPRODUCT (1 << 0)
  ------------------
                if ((optflags & aeXPRODUCT) != 0 && (opts & aeXPRODUCT) == 0)
  ------------------
  |  |   65|      0|#define aeXPRODUCT (1 << 0)
  ------------------
  |  Branch (935:7): [True: 0, False: 22.8k]
  |  Branch (935:39): [True: 0, False: 0]
  ------------------
  936|      0|    return nullptr;
  937|       |
  938|       |  // upon entry suffix is 0 length or already matches the end of the word.
  939|       |  // So if the remaining root word has positive length
  940|       |  // and if there are enough chars in root word and added back strip chars
  941|       |  // to meet the number of characters conditions, then test it
  942|       |
  943|  22.8k|  if (len < appnd.size())
  ------------------
  |  Branch (943:7): [True: 0, False: 22.8k]
  ------------------
  944|      0|    return nullptr;
  945|       |
  946|  22.8k|  size_t tmpl = len - appnd.size(); // length of tmpword
  947|       |
  948|  22.8k|  if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) &&
  ------------------
  |  Branch (948:8): [True: 22.7k, False: 139]
  |  Branch (948:21): [True: 139, False: 0]
  |  Branch (948:34): [True: 0, False: 139]
  ------------------
  949|  22.7k|      (tmpl + strip.size() >= numconds)) {
  ------------------
  |  Branch (949:7): [True: 22.7k, False: 0]
  ------------------
  950|       |    // generate new root word by removing suffix and adding
  951|       |    // back any characters that would have been stripped or
  952|       |    // or null terminating the shorter string
  953|       |
  954|  22.7k|    std::string& tmpword = scratch.sfx_check_twosfx;
  955|  22.7k|    tmpword.assign(word, start, std::string::npos);
  956|  22.7k|    tmpword.resize(tmpl);
  957|  22.7k|    tmpword.append(strip);
  958|  22.7k|    tmpl += strip.size();
  959|       |
  960|  22.7k|    const char* beg = tmpword.c_str();
  961|  22.7k|    const char* end = beg + tmpl;
  962|       |
  963|       |    // now make sure all of the conditions on characters
  964|       |    // are met.  Please see the appendix at the end of
  965|       |    // this file for more info on exactly what is being
  966|       |    // tested
  967|       |
  968|       |    // if all conditions are met then recall suffix_check
  969|       |
  970|  22.7k|    if (test_condition(end, beg)) {
  ------------------
  |  Branch (970:9): [True: 22.7k, False: 0]
  ------------------
  971|  22.7k|      struct hentry* he;  // hash entry pointer
  972|  22.7k|      if (ppfx) {
  ------------------
  |  Branch (972:11): [True: 0, False: 22.7k]
  ------------------
  973|       |        // handle conditional suffix
  974|      0|        if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (974:13): [True: 0, False: 0]
  |  Branch (974:13): [True: 0, False: 0]
  ------------------
  975|      0|          he = pmyMgr->suffix_check(tmpword, 0, tmpl, 0, nullptr, scratch, (FLAG)aflag, needflag, IN_CPD_NOT);
  ------------------
  |  |   75|      0|#define IN_CPD_NOT 0
  ------------------
  976|      0|        else
  977|      0|          he = pmyMgr->suffix_check(tmpword, 0, tmpl, optflags, ppfx,
  978|      0|                                    scratch, (FLAG)aflag, needflag, IN_CPD_NOT);
  ------------------
  |  |   75|      0|#define IN_CPD_NOT 0
  ------------------
  979|  22.7k|      } else {
  980|  22.7k|        he = pmyMgr->suffix_check(tmpword, 0, tmpl, 0, nullptr, scratch, (FLAG)aflag, needflag, IN_CPD_NOT);
  ------------------
  |  |   75|  22.7k|#define IN_CPD_NOT 0
  ------------------
  981|  22.7k|      }
  982|  22.7k|      if (he)
  ------------------
  |  Branch (982:11): [True: 0, False: 22.7k]
  ------------------
  983|      0|        return he;
  984|  22.7k|    }
  985|  22.7k|  }
  986|  22.8k|  return nullptr;
  987|  22.8k|}
_ZN8SfxEntry15initReverseWordEv:
 1100|     34|void SfxEntry::initReverseWord() {
 1101|     34|  rappnd = appnd;
 1102|     34|  reverseword(rappnd);
 1103|     34|}
_ZN8PfxEntry14test_conditionERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  134|  3.06M|inline int PfxEntry::test_condition(const std::string& s) {
  135|  3.06M|  size_t st = 0;
  136|  3.06M|  size_t pos = std::string::npos;  // group with pos input position
  137|  3.06M|  bool neg = false;        // complementer
  138|  3.06M|  bool ingroup = false;    // character in the group
  139|  3.06M|  if (numconds == 0)
  ------------------
  |  Branch (139:7): [True: 5.70k, False: 3.05M]
  ------------------
  140|  5.70k|    return 1;
  141|  3.05M|  char* p = c.conds;
  142|  3.18M|  while (true) {
  ------------------
  |  Branch (142:10): [True: 3.18M, Folded]
  ------------------
  143|  3.18M|    switch (*p) {
  144|      0|      case '\0':
  ------------------
  |  Branch (144:7): [True: 0, False: 3.18M]
  ------------------
  145|      0|        return 1;
  146|  24.9k|      case '[': {
  ------------------
  |  Branch (146:7): [True: 24.9k, False: 3.15M]
  ------------------
  147|  24.9k|        neg = false;
  148|  24.9k|        ingroup = false;
  149|  24.9k|        p = nextchar(p);
  150|  24.9k|        pos = st;
  151|  24.9k|        break;
  152|      0|      }
  153|  24.9k|      case '^': {
  ------------------
  |  Branch (153:7): [True: 24.9k, False: 3.15M]
  ------------------
  154|  24.9k|        p = nextchar(p);
  155|  24.9k|        neg = true;
  156|  24.9k|        break;
  157|      0|      }
  158|  24.9k|      case ']': {
  ------------------
  |  Branch (158:7): [True: 24.9k, False: 3.15M]
  ------------------
  159|  24.9k|        if (bool(neg) == bool(ingroup))
  ------------------
  |  Branch (159:13): [True: 0, False: 24.9k]
  ------------------
  160|      0|          return 0;
  161|  24.9k|        pos = std::string::npos;
  162|  24.9k|        p = nextchar(p);
  163|       |        // skip the next character
  164|  24.9k|        if (!ingroup && st < s.size())
  ------------------
  |  Branch (164:13): [True: 24.9k, False: 0]
  |  Branch (164:25): [True: 23.6k, False: 1.29k]
  ------------------
  165|  23.6k|          st = (opts & aeUTF8) ? utf8_next(s, st) : st + 1;
  ------------------
  |  |   66|  23.6k|#define aeUTF8 (1 << 1)
  ------------------
  |  Branch (165:16): [True: 23.6k, False: 0]
  ------------------
  166|  24.9k|        if (st == s.size() && p)
  ------------------
  |  Branch (166:13): [True: 3.48k, False: 21.4k]
  |  Branch (166:31): [True: 0, False: 3.48k]
  ------------------
  167|      0|          return 0;  // word <= condition
  168|  24.9k|        break;
  169|  24.9k|      }
  170|  24.9k|      case '.':
  ------------------
  |  Branch (170:7): [True: 0, False: 3.18M]
  ------------------
  171|      0|        if (pos == std::string::npos) {  // dots are not metacharacters in groups: [.]
  ------------------
  |  Branch (171:13): [True: 0, False: 0]
  ------------------
  172|      0|          if (st == s.size())
  ------------------
  |  Branch (172:15): [True: 0, False: 0]
  ------------------
  173|      0|            return 0;  // dot has no character to match
  174|      0|          p = nextchar(p);
  175|       |          // skip the next character
  176|      0|          st = (opts & aeUTF8) ? utf8_next(s, st) : st + 1;
  ------------------
  |  |   66|      0|#define aeUTF8 (1 << 1)
  ------------------
  |  Branch (176:16): [True: 0, False: 0]
  ------------------
  177|      0|          break;
  178|      0|        }
  179|       |      /* FALLTHROUGH */
  180|  3.10M|      default: {
  ------------------
  |  Branch (180:7): [True: 3.10M, False: 74.8k]
  ------------------
  181|  3.10M|        if (st < s.size() && s[st] == *p) {
  ------------------
  |  Branch (181:13): [True: 3.10M, False: 2.59k]
  |  Branch (181:30): [True: 25.0k, False: 3.08M]
  ------------------
  182|  25.0k|          ++st;
  183|  25.0k|          p = nextchar(p);
  184|  25.0k|          if ((opts & aeUTF8) && (s[st - 1] & 0x80)) {  // multibyte
  ------------------
  |  |   66|  25.0k|#define aeUTF8 (1 << 1)
  ------------------
  |  Branch (184:15): [True: 25.0k, False: 0]
  |  Branch (184:34): [True: 25.0k, False: 0]
  ------------------
  185|  49.9k|            while (p && is_utf8_cont(*p)) {             // character
  ------------------
  |  Branch (185:20): [True: 49.9k, False: 0]
  |  Branch (185:25): [True: 25.0k, False: 24.9k]
  ------------------
  186|  25.0k|              if (st >= s.size() || *p != s[st]) {
  ------------------
  |  Branch (186:19): [True: 0, False: 25.0k]
  |  Branch (186:37): [True: 60, False: 24.9k]
  ------------------
  187|     60|                if (pos == std::string::npos)
  ------------------
  |  Branch (187:21): [True: 60, False: 0]
  ------------------
  188|     60|                  return 0;
  189|      0|                st = pos;
  190|      0|                break;
  191|     60|              }
  192|  24.9k|              p = nextchar(p);
  193|  24.9k|              ++st;
  194|  24.9k|            }
  195|  24.9k|            if (pos != std::string::npos && st != pos) {
  ------------------
  |  Branch (195:17): [True: 0, False: 24.9k]
  |  Branch (195:45): [True: 0, False: 0]
  ------------------
  196|      0|              ingroup = true;
  197|      0|              while (p && *p != ']' && ((p = nextchar(p)) != nullptr)) {
  ------------------
  |  Branch (197:22): [True: 0, False: 0]
  |  Branch (197:27): [True: 0, False: 0]
  |  Branch (197:40): [True: 0, False: 0]
  ------------------
  198|      0|              }
  199|      0|            }
  200|  24.9k|          } else if (pos != std::string::npos) {
  ------------------
  |  Branch (200:22): [True: 0, False: 0]
  ------------------
  201|      0|            ingroup = true;
  202|      0|            while (p && *p != ']' && ((p = nextchar(p)) != nullptr)) {
  ------------------
  |  Branch (202:20): [True: 0, False: 0]
  |  Branch (202:25): [True: 0, False: 0]
  |  Branch (202:38): [True: 0, False: 0]
  ------------------
  203|      0|            }
  204|      0|          }
  205|  3.08M|        } else if (pos != std::string::npos) {  // group
  ------------------
  |  Branch (205:20): [True: 49.9k, False: 3.03M]
  ------------------
  206|  49.9k|          p = nextchar(p);
  207|  49.9k|        } else
  208|  3.03M|          return 0;
  209|  3.10M|      }
  210|  3.18M|    }
  211|   149k|    if (!p)
  ------------------
  |  Branch (211:9): [True: 24.9k, False: 124k]
  ------------------
  212|  24.9k|      return 1;
  213|   149k|  }
  214|  3.05M|}
_ZN8PfxEntry8nextcharEPc:
  119|   174k|inline char* PfxEntry::nextchar(char* p) {
  120|   174k|  if (p) {
  ------------------
  |  Branch (120:7): [True: 174k, False: 0]
  ------------------
  121|   174k|    p++;
  122|   174k|    if (opts & aeLONGCOND) {
  ------------------
  |  |   69|   174k|#define aeLONGCOND (1 << 4)
  ------------------
  |  Branch (122:9): [True: 0, False: 174k]
  ------------------
  123|       |      // jump to the 2nd part of the condition
  124|      0|      if (p == c.conds + MAXCONDLEN_1)
  ------------------
  |  |   94|      0|#define MAXCONDLEN_1 (MAXCONDLEN - sizeof(char*))
  |  |  ------------------
  |  |  |  |   93|      0|#define MAXCONDLEN 20
  |  |  ------------------
  ------------------
  |  Branch (124:11): [True: 0, False: 0]
  ------------------
  125|      0|        return c.l.conds2;
  126|       |      // end of the MAXCONDLEN length condition
  127|   174k|    } else if (p == c.conds + MAXCONDLEN)
  ------------------
  |  |   93|   174k|#define MAXCONDLEN 20
  ------------------
  |  Branch (127:16): [True: 0, False: 174k]
  ------------------
  128|      0|      return nullptr;
  129|   174k|    return *p ? p : nullptr;
  ------------------
  |  Branch (129:12): [True: 149k, False: 24.9k]
  ------------------
  130|   174k|  }
  131|      0|  return nullptr;
  132|   174k|}
_ZN8SfxEntry14test_conditionEPKcS1_:
  616|  65.7k|inline int SfxEntry::test_condition(const char* st, const char* beg) {
  617|  65.7k|  const char* pos = nullptr;  // group with pos input position
  618|  65.7k|  bool neg = false;        // complementer
  619|  65.7k|  bool ingroup = false;    // character in the group
  620|  65.7k|  if (numconds == 0)
  ------------------
  |  Branch (620:7): [True: 65.7k, False: 0]
  ------------------
  621|  65.7k|    return 1;
  622|      0|  char* p = c.conds;
  623|      0|  st--;
  624|      0|  int i = 1;
  625|      0|  while (true) {
  ------------------
  |  Branch (625:10): [True: 0, Folded]
  ------------------
  626|      0|    switch (*p) {
  627|      0|      case '\0':
  ------------------
  |  Branch (627:7): [True: 0, False: 0]
  ------------------
  628|      0|        return 1;
  629|      0|      case '[':
  ------------------
  |  Branch (629:7): [True: 0, False: 0]
  ------------------
  630|      0|        p = nextchar(p);
  631|      0|        pos = st;
  632|      0|        break;
  633|      0|      case '^':
  ------------------
  |  Branch (633:7): [True: 0, False: 0]
  ------------------
  634|      0|        p = nextchar(p);
  635|      0|        neg = true;
  636|      0|        break;
  637|      0|      case ']':
  ------------------
  |  Branch (637:7): [True: 0, False: 0]
  ------------------
  638|      0|        if (!neg && !ingroup)
  ------------------
  |  Branch (638:13): [True: 0, False: 0]
  |  Branch (638:21): [True: 0, False: 0]
  ------------------
  639|      0|          return 0;
  640|      0|        i++;
  641|       |        // skip the next character
  642|      0|        if (!ingroup) {
  ------------------
  |  Branch (642:13): [True: 0, False: 0]
  ------------------
  643|      0|          for (; (opts & aeUTF8) && (st >= beg) && is_utf8_cont(*st); st--)
  ------------------
  |  |   66|      0|#define aeUTF8 (1 << 1)
  ------------------
  |  Branch (643:18): [True: 0, False: 0]
  |  Branch (643:37): [True: 0, False: 0]
  |  Branch (643:52): [True: 0, False: 0]
  ------------------
  644|      0|            ;
  645|      0|          st--;
  646|      0|        }
  647|      0|        pos = nullptr;
  648|      0|        neg = false;
  649|      0|        ingroup = false;
  650|      0|        p = nextchar(p);
  651|      0|        if (st < beg && p)
  ------------------
  |  Branch (651:13): [True: 0, False: 0]
  |  Branch (651:25): [True: 0, False: 0]
  ------------------
  652|      0|          return 0;  // word <= condition
  653|      0|        break;
  654|      0|      case '.':
  ------------------
  |  Branch (654:7): [True: 0, False: 0]
  ------------------
  655|      0|        if (!pos) {
  ------------------
  |  Branch (655:13): [True: 0, False: 0]
  ------------------
  656|       |          // dots are not metacharacters in groups: [.]
  657|      0|          p = nextchar(p);
  658|       |          // skip one character to the left. Walk back over any UTF-8
  659|       |          // continuation bytes of that character to its leading byte first,
  660|       |          // then step past it, so a single-byte match preceded by a
  661|       |          // multibyte character does not consume the multibyte character.
  662|      0|          for (; (opts & aeUTF8) && (st >= beg) && is_utf8_cont(*st); st--)
  ------------------
  |  |   66|      0|#define aeUTF8 (1 << 1)
  ------------------
  |  Branch (662:18): [True: 0, False: 0]
  |  Branch (662:37): [True: 0, False: 0]
  |  Branch (662:52): [True: 0, False: 0]
  ------------------
  663|      0|            ;
  664|      0|          st--;
  665|      0|          if (st < beg) {  // word <= condition
  ------------------
  |  Branch (665:15): [True: 0, False: 0]
  ------------------
  666|      0|            if (p)
  ------------------
  |  Branch (666:17): [True: 0, False: 0]
  ------------------
  667|      0|              return 0;
  668|      0|            else
  669|      0|              return 1;
  670|      0|          }
  671|      0|          break;
  672|      0|        }
  673|       |      /* FALLTHROUGH */
  674|      0|      default: {
  ------------------
  |  Branch (674:7): [True: 0, False: 0]
  ------------------
  675|      0|        if (*st == *p) {
  ------------------
  |  Branch (675:13): [True: 0, False: 0]
  ------------------
  676|      0|          p = nextchar(p);
  677|      0|          if ((opts & aeUTF8) && (*st & 0x80)) {
  ------------------
  |  |   66|      0|#define aeUTF8 (1 << 1)
  ------------------
  |  Branch (677:15): [True: 0, False: 0]
  |  Branch (677:34): [True: 0, False: 0]
  ------------------
  678|      0|            st--;
  679|      0|            while (p && (st >= beg)) {
  ------------------
  |  Branch (679:20): [True: 0, False: 0]
  |  Branch (679:25): [True: 0, False: 0]
  ------------------
  680|      0|              if (*p != *st) {
  ------------------
  |  Branch (680:19): [True: 0, False: 0]
  ------------------
  681|      0|                if (!pos)
  ------------------
  |  Branch (681:21): [True: 0, False: 0]
  ------------------
  682|      0|                  return 0;
  683|      0|                st = pos;
  684|      0|                break;
  685|      0|              }
  686|       |              // first byte of the UTF-8 multibyte character
  687|      0|              if (!is_utf8_cont(*p))
  ------------------
  |  Branch (687:19): [True: 0, False: 0]
  ------------------
  688|      0|                break;
  689|      0|              p = nextchar(p);
  690|      0|              st--;
  691|      0|            }
  692|      0|            if (pos && st != pos) {
  ------------------
  |  Branch (692:17): [True: 0, False: 0]
  |  Branch (692:24): [True: 0, False: 0]
  ------------------
  693|      0|              if (neg)
  ------------------
  |  Branch (693:19): [True: 0, False: 0]
  ------------------
  694|      0|                return 0;
  695|      0|              else if (i == numconds)
  ------------------
  |  Branch (695:24): [True: 0, False: 0]
  ------------------
  696|      0|                return 1;
  697|      0|              ingroup = true;
  698|      0|              while (p && *p != ']' && ((p = nextchar(p)) != nullptr)) {
  ------------------
  |  Branch (698:22): [True: 0, False: 0]
  |  Branch (698:27): [True: 0, False: 0]
  |  Branch (698:40): [True: 0, False: 0]
  ------------------
  699|      0|              }
  700|      0|              st--;
  701|      0|            }
  702|      0|            if (p && *p != ']')
  ------------------
  |  Branch (702:17): [True: 0, False: 0]
  |  Branch (702:22): [True: 0, False: 0]
  ------------------
  703|      0|              p = nextchar(p);
  704|      0|          } else if (pos) {
  ------------------
  |  Branch (704:22): [True: 0, False: 0]
  ------------------
  705|      0|            if (neg)
  ------------------
  |  Branch (705:17): [True: 0, False: 0]
  ------------------
  706|      0|              return 0;
  707|      0|            else if (i == numconds)
  ------------------
  |  Branch (707:22): [True: 0, False: 0]
  ------------------
  708|      0|              return 1;
  709|      0|            ingroup = true;
  710|      0|            while (p && *p != ']' && ((p = nextchar(p)) != nullptr)) {
  ------------------
  |  Branch (710:20): [True: 0, False: 0]
  |  Branch (710:25): [True: 0, False: 0]
  |  Branch (710:38): [True: 0, False: 0]
  ------------------
  711|      0|            }
  712|       |            // if (p && *p != ']') p = nextchar(p);
  713|      0|            st--;
  714|      0|          }
  715|      0|          if (!pos) {
  ------------------
  |  Branch (715:15): [True: 0, False: 0]
  ------------------
  716|      0|            i++;
  717|      0|            st--;
  718|      0|          }
  719|      0|          if (st < beg && p && *p != ']')
  ------------------
  |  Branch (719:15): [True: 0, False: 0]
  |  Branch (719:27): [True: 0, False: 0]
  |  Branch (719:32): [True: 0, False: 0]
  ------------------
  720|      0|            return 0;      // word <= condition
  721|      0|        } else if (pos) {  // group
  ------------------
  |  Branch (721:20): [True: 0, False: 0]
  ------------------
  722|      0|          p = nextchar(p);
  723|      0|        } else
  724|      0|          return 0;
  725|      0|      }
  726|      0|    }
  727|      0|    if (!p)
  ------------------
  |  Branch (727:9): [True: 0, False: 0]
  ------------------
  728|      0|      return 1;
  729|      0|  }
  730|      0|}

_ZN8PfxEntry7getContEv:
  136|  4.70M|  inline const unsigned short* getCont() { return contclass; }
_ZN8PfxEntry10getContLenEv:
  137|  1.56M|  inline unsigned short getContLen() { return contclasslen; }
_ZN8SfxEntry7getContEv:
  226|   312k|  inline const unsigned short* getCont() { return contclass; }
_ZN8SfxEntry10getContLenEv:
  227|  40.2k|  inline unsigned short getContLen() { return contclasslen; }
_ZN8PfxEntry7getFlagEv:
  128|    930|  FLAG getFlag() { return aflag; }
_ZN8PfxEntry6getKeyEv:
  129|   125k|  const char* getKey() { return appnd.c_str(); }
_ZN8SfxEntry7getFlagEv:
  220|   105k|  FLAG getFlag() { return aflag; }
_ZN8SfxEntry8getAffixEv:
  228|  35.4k|  inline const char* getAffix() { return appnd.c_str(); }
_ZNK8PfxEntry10allowCrossEv:
   94|      4|  bool allowCross() const { return ((opts & aeXPRODUCT) != 0); }
  ------------------
  |  |   65|      4|#define aeXPRODUCT (1 << 0)
  ------------------
_ZN8PfxEntry9getKeyLenEv:
  132|  2.76k|  inline size_t getKeyLen() { return appnd.size(); }
_ZN8PfxEntry7getNextEv:
  139|  3.06M|  inline PfxEntry* getNext() { return next; }
_ZN8PfxEntry9getNextNEEv:
  140|  46.4k|  inline PfxEntry* getNextNE() { return nextne; }
_ZN8PfxEntry9getNextEQEv:
  141|  77.9k|  inline PfxEntry* getNextEQ() { return nexteq; }
_ZN8PfxEntry9getFlgNxtEv:
  142|    922|  inline PfxEntry* getFlgNxt() { return flgnxt; }
_ZN8PfxEntry7setNextEPS_:
  144|      8|  inline void setNext(PfxEntry* ptr) { next = ptr; }
_ZN8PfxEntry9setNextNEEPS_:
  145|     16|  inline void setNextNE(PfxEntry* ptr) { nextne = ptr; }
_ZN8PfxEntry9setNextEQEPS_:
  146|     14|  inline void setNextEQ(PfxEntry* ptr) { nexteq = ptr; }
_ZN8PfxEntry9setFlgNxtEPS_:
  147|      8|  inline void setFlgNxt(PfxEntry* ptr) { flgnxt = ptr; }
_ZNK8SfxEntry10allowCrossEv:
  176|     30|  bool allowCross() const { return ((opts & aeXPRODUCT) != 0); }
  ------------------
  |  |   65|     30|#define aeXPRODUCT (1 << 0)
  ------------------
_ZN8SfxEntry6getKeyEv:
  221|   296k|  const char* getKey() { return rappnd.c_str(); }
_ZN8SfxEntry9getKeyLenEv:
  230|   160k|  inline size_t getKeyLen() { return appnd.size(); }
_ZN8SfxEntry7getNextEv:
  232|    228|  inline SfxEntry* getNext() { return next; }
_ZN8SfxEntry9getNextNEEv:
  233|  65.9k|  inline SfxEntry* getNextNE() { return nextne; }
_ZN8SfxEntry9getNextEQEv:
  234|   230k|  inline SfxEntry* getNextEQ() { return nexteq; }
_ZN8SfxEntry9getFlgNxtEv:
  239|  62.6k|  inline SfxEntry* getFlgNxt() { return flgnxt; }
_ZN8SfxEntry7setNextEPS_:
  241|     34|  inline void setNext(SfxEntry* ptr) { next = ptr; }
_ZN8SfxEntry9setNextNEEPS_:
  242|     80|  inline void setNextNE(SfxEntry* ptr) { nextne = ptr; }
_ZN8SfxEntry9setNextEQEPS_:
  243|     88|  inline void setNextEQ(SfxEntry* ptr) { nexteq = ptr; }
_ZN8SfxEntry9setFlgNxtEPS_:
  244|     34|  inline void setFlgNxt(SfxEntry* ptr) { flgnxt = ptr; }

_ZN8AffixMgrC2EPKcRKNSt3__16vectorINS2_10unique_ptrI7HashMgrNS2_14default_deleteIS5_EEEENS2_9allocatorIS8_EEEES1_:
  137|     38|  : alldic(ptr)
  138|     38|  , pHMgr(ptr[0].get()) {
  139|       |
  140|       |  // register hash manager and load affix data from aff file
  141|     38|  csconv = nullptr;
  142|     38|  utf8 = 0;
  143|     38|  complexprefixes = 0;
  144|     38|  parsedmaptable = false;
  145|     38|  parsedbreaktable = false;
  146|     38|  iconvtable = nullptr;
  147|     38|  oconvtable = nullptr;
  148|       |  // allow simplified compound forms (see 3rd field of CHECKCOMPOUNDPATTERN)
  149|     38|  simplifiedcpd = 0;
  150|     38|  parsedcheckcpd = false;
  151|     38|  parseddefcpd = false;
  152|     38|  phone = nullptr;
  153|     38|  compoundflag = FLAG_NULL;        // permits word in compound forms
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  154|     38|  compoundbegin = FLAG_NULL;       // may be first word in compound forms
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  155|     38|  compoundmiddle = FLAG_NULL;      // may be middle word in compound forms
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  156|     38|  compoundend = FLAG_NULL;         // may be last word in compound forms
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  157|     38|  compoundroot = FLAG_NULL;        // compound word signing flag
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  158|     38|  compoundpermitflag = FLAG_NULL;  // compound permitting flag for suffixed word
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  159|     38|  compoundforbidflag = FLAG_NULL;  // compound fordidden flag for suffixed word
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  160|     38|  compoundmoresuffixes = 0;        // allow more suffixes within compound words
  161|     38|  checkcompounddup = 0;            // forbid double words in compounds
  162|     38|  checkcompoundrep = 0;  // forbid bad compounds (may be non-compound word with
  163|       |                         // a REP substitution)
  164|     38|  checkcompoundcase =
  165|     38|      0;  // forbid upper and lowercase combinations at word bounds
  166|     38|  checkcompoundtriple = 0;  // forbid compounds with triple letters
  167|     38|  simplifiedtriple = 0;     // allow simplified triple letters in compounds
  168|       |                            // (Schiff+fahrt -> Schiffahrt)
  169|     38|  forbiddenword = FORBIDDENWORD;  // forbidden word signing flag
  ------------------
  |  |  123|     38|#define FORBIDDENWORD 65510
  ------------------
  170|     38|  nosuggest = FLAG_NULL;  // don't suggest words signed with NOSUGGEST flag
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  171|     38|  nongramsuggest = FLAG_NULL;
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  172|     38|  langnum = 0;  // language code (see http://l10n.openoffice.org/languages.html)
  173|     38|  needaffix = FLAG_NULL;  // forbidden root, allowed only with suffixes
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  174|     38|  cpdwordmax = -1;        // default: unlimited wordcount in compound words
  175|     38|  cpdmin = -1;            // undefined
  176|     38|  cpdmaxsyllable = 0;     // default: unlimited syllablecount in compound words
  177|     38|  pfxappnd = nullptr;     // previous prefix for counting syllables of the prefix BUG
  178|     38|  sfxappnd = nullptr;     // previous suffix for counting syllables of the suffix BUG
  179|     38|  sfxextra = 0;     // modifier for syllable count of sfxappnd BUG
  180|     38|  checknum = 0;               // checking numbers, and word with numbers
  181|     38|  havecontclass = 0;  // flags of possible continuing classes (double affix)
  182|       |  // LEMMA_PRESENT: not put root into the morphological output. Lemma presents
  183|       |  // in morhological description in dictionary file. It's often combined with
  184|       |  // PSEUDOROOT.
  185|     38|  lemma_present = FLAG_NULL;
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  186|     38|  circumfix = FLAG_NULL;
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  187|     38|  onlyincompound = FLAG_NULL;
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  188|     38|  maxngramsugs = -1;  // undefined
  189|     38|  maxdiff = -1;       // undefined
  190|     38|  onlymaxdiff = 0;
  191|     38|  maxcpdsugs = -1;  // undefined
  192|     38|  nosplitsugs = 0;
  193|     38|  sugswithdots = 0;
  194|     38|  keepcase = 0;
  195|     38|  forceucase = 0;
  196|     38|  warn = 0;
  197|     38|  forbidwarn = 0;
  198|     38|  checksharps = 0;
  199|     38|  substandard = FLAG_NULL;
  ------------------
  |  |   99|     38|#define FLAG_NULL 0x00
  ------------------
  200|     38|  fullstrip = 0;
  201|       |
  202|     38|  sfx = nullptr;
  203|     38|  pfx = nullptr;
  204|       |
  205|  9.76k|  for (int i = 0; i < SETSIZE; i++) {
  ------------------
  |  |   61|  9.76k|#define SETSIZE 256
  ------------------
  |  Branch (205:19): [True: 9.72k, False: 38]
  ------------------
  206|  9.72k|    pStart[i] = nullptr;
  207|  9.72k|    sStart[i] = nullptr;
  208|  9.72k|    pFlag[i] = nullptr;
  209|  9.72k|    sFlag[i] = nullptr;
  210|  9.72k|  }
  211|       |
  212|     38|  if (parse_file(affpath, key)) {
  ------------------
  |  Branch (212:7): [True: 0, False: 38]
  ------------------
  213|      0|    fprintf(stderr, "Failure loading aff file %s\n", affpath);
  214|      0|  }
  215|       |
  216|       |  /* get encoding for CHECKCOMPOUNDCASE */
  217|     38|  if (!utf8) {
  ------------------
  |  Branch (217:7): [True: 20, False: 18]
  ------------------
  218|     20|    csconv = get_current_cs(get_encoding());
  219|  5.14k|    for (int i = 0; i <= 255; i++) {
  ------------------
  |  Branch (219:21): [True: 5.12k, False: 20]
  ------------------
  220|  5.12k|      if ((csconv[i].cupper != csconv[i].clower) &&
  ------------------
  |  Branch (220:11): [True: 2.24k, False: 2.88k]
  ------------------
  221|  2.24k|          (wordchars.find((char)i) == std::string::npos)) {
  ------------------
  |  Branch (221:11): [True: 2.24k, False: 0]
  ------------------
  222|  2.24k|        wordchars.push_back((char)i);
  223|  2.24k|      }
  224|  5.12k|    }
  225|     20|  }
  226|       |
  227|       |  // default BREAK definition
  228|     38|  if (!parsedbreaktable) {
  ------------------
  |  Branch (228:7): [True: 34, False: 4]
  ------------------
  229|     34|    breaktable.emplace_back("-");
  230|     34|    breaktable.emplace_back("^-");
  231|     34|    breaktable.emplace_back("-$");
  232|     34|    parsedbreaktable = true;
  233|     34|  }
  234|       |
  235|     38|#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
  236|       |  // not entirely sure this is invalid, so only for fuzzing for now
  237|     38|  if (iconvtable && !iconvtable->check_against_breaktable(breaktable)) {
  ------------------
  |  Branch (237:7): [True: 2, False: 36]
  |  Branch (237:21): [True: 0, False: 2]
  ------------------
  238|      0|      delete iconvtable;
  239|      0|      iconvtable = nullptr;
  240|      0|  }
  241|     38|#endif
  242|       |
  243|     38|  if (cpdmin == -1)
  ------------------
  |  Branch (243:7): [True: 34, False: 4]
  ------------------
  244|     34|    cpdmin = MINCPDLEN;
  ------------------
  |  |   91|     34|#define MINCPDLEN 3
  ------------------
  245|     38|}
_ZN8AffixMgr13finishFileMgrEP7FileMgr:
  302|     38|void AffixMgr::finishFileMgr(FileMgr* afflst) {
  303|     38|  delete afflst;
  304|       |
  305|       |  // convert affix trees to sorted list
  306|     38|  process_pfx_tree_to_list();
  307|     38|  process_sfx_tree_to_list();
  308|     38|}
_ZN8AffixMgr10parse_fileEPKcS1_:
  311|     38|int AffixMgr::parse_file(const char* affpath, const char* key) {
  312|       |
  313|       |  // checking flag duplication
  314|     38|  char dupflags[CONTSIZE];
  315|     38|  char dupflags_ini = 1;
  316|       |
  317|       |  // first line indicator for removing byte order mark
  318|     38|  int firstline = 1;
  319|       |
  320|       |  // open the affix file
  321|     38|  FileMgr* afflst = new FileMgr(affpath, key);
  322|       |
  323|       |  // step one is to parse the affix file building up the internal
  324|       |  // affix data structures
  325|       |
  326|       |  // read in each line ignoring any that do not
  327|       |  // start with a known line type indicator
  328|     38|  std::string line;
  329|    646|  while (afflst->getline(line)) {
  ------------------
  |  Branch (329:10): [True: 608, False: 38]
  ------------------
  330|    608|    mychomp(line);
  331|       |
  332|       |    /* remove byte order mark */
  333|    608|    if (firstline) {
  ------------------
  |  Branch (333:9): [True: 38, False: 570]
  ------------------
  334|     38|      firstline = 0;
  335|       |      // Affix file begins with byte order mark: possible incompatibility with
  336|       |      // old Hunspell versions
  337|     38|      if (line.compare(0, 3, "\xEF\xBB\xBF", 3) == 0) {
  ------------------
  |  Branch (337:11): [True: 0, False: 38]
  ------------------
  338|      0|        line.erase(0, 3);
  339|      0|      }
  340|     38|    }
  341|       |
  342|       |    /* parse in the keyboard string */
  343|    608|    if (line.compare(0, 3, "KEY", 3) == 0) {
  ------------------
  |  Branch (343:9): [True: 0, False: 608]
  ------------------
  344|      0|      if (!parse_string(line, keystring, afflst->getlinenum())) {
  ------------------
  |  Branch (344:11): [True: 0, False: 0]
  ------------------
  345|      0|        finishFileMgr(afflst);
  346|      0|        return 1;
  347|      0|      }
  348|      0|    }
  349|       |
  350|       |    /* parse in the try string */
  351|    608|    if (line.compare(0, 3, "TRY", 3) == 0) {
  ------------------
  |  Branch (351:9): [True: 2, False: 606]
  ------------------
  352|      2|      if (!parse_string(line, trystring, afflst->getlinenum())) {
  ------------------
  |  Branch (352:11): [True: 0, False: 2]
  ------------------
  353|      0|        finishFileMgr(afflst);
  354|      0|        return 1;
  355|      0|      }
  356|      2|    }
  357|       |
  358|       |    /* parse in the name of the character set used by the .dict and .aff */
  359|    608|    if (line.compare(0, 3, "SET", 3) == 0) {
  ------------------
  |  Branch (359:9): [True: 18, False: 590]
  ------------------
  360|     18|      if (!parse_string(line, encoding, afflst->getlinenum())) {
  ------------------
  |  Branch (360:11): [True: 0, False: 18]
  ------------------
  361|      0|        finishFileMgr(afflst);
  362|      0|        return 1;
  363|      0|      }
  364|     18|      if (encoding == "UTF-8") {
  ------------------
  |  Branch (364:11): [True: 18, False: 0]
  ------------------
  365|     18|        utf8 = 1;
  366|     18|      }
  367|     18|    }
  368|       |
  369|       |    /* parse COMPLEXPREFIXES for agglutinative languages with right-to-left
  370|       |     * writing system */
  371|    608|    if (line.compare(0, 15, "COMPLEXPREFIXES", 15) == 0)
  ------------------
  |  Branch (371:9): [True: 2, False: 606]
  ------------------
  372|      2|      complexprefixes = 1;
  373|       |
  374|       |    /* parse in the flag used by the controlled compound words */
  375|    608|    if (line.compare(0, 12, "COMPOUNDFLAG", 12) == 0) {
  ------------------
  |  Branch (375:9): [True: 8, False: 600]
  ------------------
  376|      8|      if (!parse_flag(line, &compoundflag, afflst)) {
  ------------------
  |  Branch (376:11): [True: 0, False: 8]
  ------------------
  377|      0|        finishFileMgr(afflst);
  378|      0|        return 1;
  379|      0|      }
  380|      8|    }
  381|       |
  382|       |    /* parse in the flag used by compound words */
  383|    608|    if (line.compare(0, 13, "COMPOUNDBEGIN", 13) == 0) {
  ------------------
  |  Branch (383:9): [True: 0, False: 608]
  ------------------
  384|      0|      if (complexprefixes) {
  ------------------
  |  Branch (384:11): [True: 0, False: 0]
  ------------------
  385|      0|        if (!parse_flag(line, &compoundend, afflst)) {
  ------------------
  |  Branch (385:13): [True: 0, False: 0]
  ------------------
  386|      0|          finishFileMgr(afflst);
  387|      0|          return 1;
  388|      0|        }
  389|      0|      } else {
  390|      0|        if (!parse_flag(line, &compoundbegin, afflst)) {
  ------------------
  |  Branch (390:13): [True: 0, False: 0]
  ------------------
  391|      0|          finishFileMgr(afflst);
  392|      0|          return 1;
  393|      0|        }
  394|      0|      }
  395|      0|    }
  396|       |
  397|       |    /* parse in the flag used by compound words */
  398|    608|    if (line.compare(0, 14, "COMPOUNDMIDDLE", 14) == 0) {
  ------------------
  |  Branch (398:9): [True: 0, False: 608]
  ------------------
  399|      0|      if (!parse_flag(line, &compoundmiddle, afflst)) {
  ------------------
  |  Branch (399:11): [True: 0, False: 0]
  ------------------
  400|      0|        finishFileMgr(afflst);
  401|      0|        return 1;
  402|      0|      }
  403|      0|    }
  404|       |
  405|       |    /* parse in the flag used by compound words */
  406|    608|    if (line.compare(0, 11, "COMPOUNDEND", 11) == 0) {
  ------------------
  |  Branch (406:9): [True: 0, False: 608]
  ------------------
  407|      0|      if (complexprefixes) {
  ------------------
  |  Branch (407:11): [True: 0, False: 0]
  ------------------
  408|      0|        if (!parse_flag(line, &compoundbegin, afflst)) {
  ------------------
  |  Branch (408:13): [True: 0, False: 0]
  ------------------
  409|      0|          finishFileMgr(afflst);
  410|      0|          return 1;
  411|      0|        }
  412|      0|      } else {
  413|      0|        if (!parse_flag(line, &compoundend, afflst)) {
  ------------------
  |  Branch (413:13): [True: 0, False: 0]
  ------------------
  414|      0|          finishFileMgr(afflst);
  415|      0|          return 1;
  416|      0|        }
  417|      0|      }
  418|      0|    }
  419|       |
  420|       |    /* parse in the data used by compound_check() method */
  421|    608|    if (line.compare(0, 15, "COMPOUNDWORDMAX", 15) == 0) {
  ------------------
  |  Branch (421:9): [True: 2, False: 606]
  ------------------
  422|      2|      if (!parse_num(line, &cpdwordmax, afflst)) {
  ------------------
  |  Branch (422:11): [True: 0, False: 2]
  ------------------
  423|      0|        finishFileMgr(afflst);
  424|      0|        return 1;
  425|      0|      }
  426|      2|    }
  427|       |
  428|       |    /* parse in the flag sign compounds in dictionary */
  429|    608|    if (line.compare(0, 12, "COMPOUNDROOT", 12) == 0) {
  ------------------
  |  Branch (429:9): [True: 0, False: 608]
  ------------------
  430|      0|      if (!parse_flag(line, &compoundroot, afflst)) {
  ------------------
  |  Branch (430:11): [True: 0, False: 0]
  ------------------
  431|      0|        finishFileMgr(afflst);
  432|      0|        return 1;
  433|      0|      }
  434|      0|    }
  435|       |
  436|       |    /* parse in the flag used by compound_check() method */
  437|    608|    if (line.compare(0, 18, "COMPOUNDPERMITFLAG", 18) == 0) {
  ------------------
  |  Branch (437:9): [True: 2, False: 606]
  ------------------
  438|      2|      if (!parse_flag(line, &compoundpermitflag, afflst)) {
  ------------------
  |  Branch (438:11): [True: 0, False: 2]
  ------------------
  439|      0|        finishFileMgr(afflst);
  440|      0|        return 1;
  441|      0|      }
  442|      2|    }
  443|       |
  444|       |    /* parse in the flag used by compound_check() method */
  445|    608|    if (line.compare(0, 18, "COMPOUNDFORBIDFLAG", 18) == 0) {
  ------------------
  |  Branch (445:9): [True: 2, False: 606]
  ------------------
  446|      2|      if (!parse_flag(line, &compoundforbidflag, afflst)) {
  ------------------
  |  Branch (446:11): [True: 0, False: 2]
  ------------------
  447|      0|        finishFileMgr(afflst);
  448|      0|        return 1;
  449|      0|      }
  450|      2|    }
  451|       |
  452|    608|    if (line.compare(0, 20, "COMPOUNDMORESUFFIXES", 20) == 0) {
  ------------------
  |  Branch (452:9): [True: 0, False: 608]
  ------------------
  453|      0|      compoundmoresuffixes = 1;
  454|      0|    }
  455|       |
  456|    608|    if (line.compare(0, 16, "CHECKCOMPOUNDDUP", 16) == 0) {
  ------------------
  |  Branch (456:9): [True: 0, False: 608]
  ------------------
  457|      0|      checkcompounddup = 1;
  458|      0|    }
  459|       |
  460|    608|    if (line.compare(0, 16, "CHECKCOMPOUNDREP", 16) == 0) {
  ------------------
  |  Branch (460:9): [True: 2, False: 606]
  ------------------
  461|      2|      checkcompoundrep = 1;
  462|      2|    }
  463|       |
  464|    608|    if (line.compare(0, 19, "CHECKCOMPOUNDTRIPLE", 19) == 0) {
  ------------------
  |  Branch (464:9): [True: 0, False: 608]
  ------------------
  465|      0|      checkcompoundtriple = 1;
  466|      0|    }
  467|       |
  468|    608|    if (line.compare(0, 16, "SIMPLIFIEDTRIPLE", 16) == 0) {
  ------------------
  |  Branch (468:9): [True: 0, False: 608]
  ------------------
  469|      0|      simplifiedtriple = 1;
  470|      0|    }
  471|       |
  472|    608|    if (line.compare(0, 17, "CHECKCOMPOUNDCASE", 17) == 0) {
  ------------------
  |  Branch (472:9): [True: 0, False: 608]
  ------------------
  473|      0|      checkcompoundcase = 1;
  474|      0|    }
  475|       |
  476|    608|    if (line.compare(0, 9, "NOSUGGEST", 9) == 0) {
  ------------------
  |  Branch (476:9): [True: 0, False: 608]
  ------------------
  477|      0|      if (!parse_flag(line, &nosuggest, afflst)) {
  ------------------
  |  Branch (477:11): [True: 0, False: 0]
  ------------------
  478|      0|        finishFileMgr(afflst);
  479|      0|        return 1;
  480|      0|      }
  481|      0|    }
  482|       |
  483|    608|    if (line.compare(0, 14, "NONGRAMSUGGEST", 14) == 0) {
  ------------------
  |  Branch (483:9): [True: 0, False: 608]
  ------------------
  484|      0|      if (!parse_flag(line, &nongramsuggest, afflst)) {
  ------------------
  |  Branch (484:11): [True: 0, False: 0]
  ------------------
  485|      0|        finishFileMgr(afflst);
  486|      0|        return 1;
  487|      0|      }
  488|      0|    }
  489|       |
  490|       |    /* parse in the flag used by forbidden words */
  491|    608|    if (line.compare(0, 13, "FORBIDDENWORD", 13) == 0) {
  ------------------
  |  Branch (491:9): [True: 2, False: 606]
  ------------------
  492|      2|      if (!parse_flag(line, &forbiddenword, afflst)) {
  ------------------
  |  Branch (492:11): [True: 0, False: 2]
  ------------------
  493|      0|        finishFileMgr(afflst);
  494|      0|        return 1;
  495|      0|      }
  496|      2|    }
  497|       |
  498|       |    /* parse in the flag used by forbidden words (is deprecated) */
  499|    608|    if (line.compare(0, 13, "LEMMA_PRESENT", 13) == 0) {
  ------------------
  |  Branch (499:9): [True: 0, False: 608]
  ------------------
  500|      0|      if (!parse_flag(line, &lemma_present, afflst)) {
  ------------------
  |  Branch (500:11): [True: 0, False: 0]
  ------------------
  501|      0|        finishFileMgr(afflst);
  502|      0|        return 1;
  503|      0|      }
  504|      0|    }
  505|       |
  506|       |    /* parse in the flag used by circumfixes */
  507|    608|    if (line.compare(0, 9, "CIRCUMFIX", 9) == 0) {
  ------------------
  |  Branch (507:9): [True: 2, False: 606]
  ------------------
  508|      2|      if (!parse_flag(line, &circumfix, afflst)) {
  ------------------
  |  Branch (508:11): [True: 0, False: 2]
  ------------------
  509|      0|        finishFileMgr(afflst);
  510|      0|        return 1;
  511|      0|      }
  512|      2|    }
  513|       |
  514|       |    /* parse in the flag used by fogemorphemes */
  515|    608|    if (line.compare(0, 14, "ONLYINCOMPOUND", 14) == 0) {
  ------------------
  |  Branch (515:9): [True: 0, False: 608]
  ------------------
  516|      0|      if (!parse_flag(line, &onlyincompound, afflst)) {
  ------------------
  |  Branch (516:11): [True: 0, False: 0]
  ------------------
  517|      0|        finishFileMgr(afflst);
  518|      0|        return 1;
  519|      0|      }
  520|      0|    }
  521|       |
  522|       |    /* parse in the flag used by `needaffixs' (is deprecated) */
  523|    608|    if (line.compare(0, 10, "PSEUDOROOT", 10) == 0) {
  ------------------
  |  Branch (523:9): [True: 0, False: 608]
  ------------------
  524|      0|      if (!parse_flag(line, &needaffix, afflst)) {
  ------------------
  |  Branch (524:11): [True: 0, False: 0]
  ------------------
  525|      0|        finishFileMgr(afflst);
  526|      0|        return 1;
  527|      0|      }
  528|      0|    }
  529|       |
  530|       |    /* parse in the flag used by `needaffixs' */
  531|    608|    if (line.compare(0, 9, "NEEDAFFIX", 9) == 0) {
  ------------------
  |  Branch (531:9): [True: 2, False: 606]
  ------------------
  532|      2|      if (!parse_flag(line, &needaffix, afflst)) {
  ------------------
  |  Branch (532:11): [True: 0, False: 2]
  ------------------
  533|      0|        finishFileMgr(afflst);
  534|      0|        return 1;
  535|      0|      }
  536|      2|    }
  537|       |
  538|       |    /* parse in the minimal length for words in compounds */
  539|    608|    if (line.compare(0, 11, "COMPOUNDMIN", 11) == 0) {
  ------------------
  |  Branch (539:9): [True: 4, False: 604]
  ------------------
  540|      4|      if (!parse_num(line, &cpdmin, afflst)) {
  ------------------
  |  Branch (540:11): [True: 0, False: 4]
  ------------------
  541|      0|        finishFileMgr(afflst);
  542|      0|        return 1;
  543|      0|      }
  544|      4|      if (cpdmin < 1)
  ------------------
  |  Branch (544:11): [True: 0, False: 4]
  ------------------
  545|      0|        cpdmin = 1;
  546|      4|    }
  547|       |
  548|       |    /* parse in the max. words and syllables in compounds */
  549|    608|    if (line.compare(0, 16, "COMPOUNDSYLLABLE", 16) == 0) {
  ------------------
  |  Branch (549:9): [True: 2, False: 606]
  ------------------
  550|      2|      if (!parse_cpdsyllable(line, afflst)) {
  ------------------
  |  Branch (550:11): [True: 0, False: 2]
  ------------------
  551|      0|        finishFileMgr(afflst);
  552|      0|        return 1;
  553|      0|      }
  554|      2|    }
  555|       |
  556|       |    /* parse in the flag used by compound_check() method */
  557|    608|    if (line.compare(0, 11, "SYLLABLENUM", 11) == 0) {
  ------------------
  |  Branch (557:9): [True: 0, False: 608]
  ------------------
  558|      0|      if (!parse_string(line, cpdsyllablenum, afflst->getlinenum())) {
  ------------------
  |  Branch (558:11): [True: 0, False: 0]
  ------------------
  559|      0|        finishFileMgr(afflst);
  560|      0|        return 1;
  561|      0|      }
  562|      0|    }
  563|       |
  564|       |    /* parse in the flag used by the controlled compound words */
  565|    608|    if (line.compare(0, 8, "CHECKNUM", 8) == 0) {
  ------------------
  |  Branch (565:9): [True: 0, False: 608]
  ------------------
  566|      0|      checknum = 1;
  567|      0|    }
  568|       |
  569|       |    /* parse in the extra word characters */
  570|    608|    if (line.compare(0, 9, "WORDCHARS", 9) == 0) {
  ------------------
  |  Branch (570:9): [True: 6, False: 602]
  ------------------
  571|      6|      if (!parse_array(line, wordchars, wordchars_utf16,
  ------------------
  |  Branch (571:11): [True: 0, False: 6]
  ------------------
  572|      6|                       utf8, afflst->getlinenum())) {
  573|      0|        finishFileMgr(afflst);
  574|      0|        return 1;
  575|      0|      }
  576|      6|    }
  577|       |
  578|       |    /* parse in the ignored characters (for example, Arabic optional diacretics
  579|       |     * charachters */
  580|    608|    if (line.compare(0, 6, "IGNORE", 6) == 0) {
  ------------------
  |  Branch (580:9): [True: 4, False: 604]
  ------------------
  581|      4|      if (!parse_array(line, ignorechars, ignorechars_utf16,
  ------------------
  |  Branch (581:11): [True: 0, False: 4]
  ------------------
  582|      4|                       utf8, afflst->getlinenum())) {
  583|      0|        finishFileMgr(afflst);
  584|      0|        return 1;
  585|      0|      }
  586|      4|    }
  587|       |
  588|       |    /* parse in the input conversion table */
  589|    608|    if (line.compare(0, 5, "ICONV", 5) == 0) {
  ------------------
  |  Branch (589:9): [True: 2, False: 606]
  ------------------
  590|      2|      if (!parse_convtable(line, afflst, &iconvtable, "ICONV")) {
  ------------------
  |  Branch (590:11): [True: 0, False: 2]
  ------------------
  591|      0|        finishFileMgr(afflst);
  592|      0|        return 1;
  593|      0|      }
  594|      2|    }
  595|       |
  596|       |    /* parse in the output conversion table */
  597|    608|    if (line.compare(0, 5, "OCONV", 5) == 0) {
  ------------------
  |  Branch (597:9): [True: 2, False: 606]
  ------------------
  598|      2|      if (!parse_convtable(line, afflst, &oconvtable, "OCONV")) {
  ------------------
  |  Branch (598:11): [True: 0, False: 2]
  ------------------
  599|      0|        finishFileMgr(afflst);
  600|      0|        return 1;
  601|      0|      }
  602|      2|    }
  603|       |
  604|       |    /* parse in the phonetic translation table */
  605|    608|    if (line.compare(0, 5, "PHONE", 5) == 0) {
  ------------------
  |  Branch (605:9): [True: 2, False: 606]
  ------------------
  606|      2|      if (!parse_phonetable(line, afflst)) {
  ------------------
  |  Branch (606:11): [True: 0, False: 2]
  ------------------
  607|      0|        finishFileMgr(afflst);
  608|      0|        return 1;
  609|      0|      }
  610|      2|    }
  611|       |
  612|       |    /* parse in the checkcompoundpattern table */
  613|    608|    if (line.compare(0, 20, "CHECKCOMPOUNDPATTERN", 20) == 0) {
  ------------------
  |  Branch (613:9): [True: 2, False: 606]
  ------------------
  614|      2|      if (!parse_checkcpdtable(line, afflst)) {
  ------------------
  |  Branch (614:11): [True: 0, False: 2]
  ------------------
  615|      0|        finishFileMgr(afflst);
  616|      0|        return 1;
  617|      0|      }
  618|      2|    }
  619|       |
  620|       |    /* parse in the defcompound table */
  621|    608|    if (line.compare(0, 12, "COMPOUNDRULE", 12) == 0) {
  ------------------
  |  Branch (621:9): [True: 0, False: 608]
  ------------------
  622|      0|      if (!parse_defcpdtable(line, afflst)) {
  ------------------
  |  Branch (622:11): [True: 0, False: 0]
  ------------------
  623|      0|        finishFileMgr(afflst);
  624|      0|        return 1;
  625|      0|      }
  626|      0|    }
  627|       |
  628|       |    /* parse in the related character map table */
  629|    608|    if (line.compare(0, 3, "MAP", 3) == 0) {
  ------------------
  |  Branch (629:9): [True: 2, False: 606]
  ------------------
  630|      2|      if (!parse_maptable(line, afflst)) {
  ------------------
  |  Branch (630:11): [True: 0, False: 2]
  ------------------
  631|      0|        finishFileMgr(afflst);
  632|      0|        return 1;
  633|      0|      }
  634|      2|    }
  635|       |
  636|       |    /* parse in the word breakpoints table */
  637|    608|    if (line.compare(0, 5, "BREAK", 5) == 0) {
  ------------------
  |  Branch (637:9): [True: 4, False: 604]
  ------------------
  638|      4|      if (!parse_breaktable(line, afflst)) {
  ------------------
  |  Branch (638:11): [True: 0, False: 4]
  ------------------
  639|      0|        finishFileMgr(afflst);
  640|      0|        return 1;
  641|      0|      }
  642|      4|    }
  643|       |
  644|       |    /* parse in the language for language specific codes */
  645|    608|    if (line.compare(0, 4, "LANG", 4) == 0) {
  ------------------
  |  Branch (645:9): [True: 2, False: 606]
  ------------------
  646|      2|      if (!parse_string(line, lang, afflst->getlinenum())) {
  ------------------
  |  Branch (646:11): [True: 0, False: 2]
  ------------------
  647|      0|        finishFileMgr(afflst);
  648|      0|        return 1;
  649|      0|      }
  650|      2|      langnum = get_lang_num(lang);
  651|      2|    }
  652|       |
  653|    608|    if (line.compare(0, 7, "VERSION", 7) == 0) {
  ------------------
  |  Branch (653:9): [True: 0, False: 608]
  ------------------
  654|      0|      size_t startpos = line.find_first_not_of(" \t", 7);
  655|      0|      if (startpos != std::string::npos) {
  ------------------
  |  Branch (655:11): [True: 0, False: 0]
  ------------------
  656|      0|          version = line.substr(startpos);
  657|      0|      }
  658|      0|    }
  659|       |
  660|    608|    if (line.compare(0, 12, "MAXNGRAMSUGS", 12) == 0) {
  ------------------
  |  Branch (660:9): [True: 4, False: 604]
  ------------------
  661|      4|      if (!parse_num(line, &maxngramsugs, afflst)) {
  ------------------
  |  Branch (661:11): [True: 0, False: 4]
  ------------------
  662|      0|        finishFileMgr(afflst);
  663|      0|        return 1;
  664|      0|      }
  665|      4|    }
  666|       |
  667|    608|    if (line.compare(0, 11, "ONLYMAXDIFF", 11) == 0)
  ------------------
  |  Branch (667:9): [True: 0, False: 608]
  ------------------
  668|      0|      onlymaxdiff = 1;
  669|       |
  670|    608|    if (line.compare(0, 7, "MAXDIFF", 7) == 0) {
  ------------------
  |  Branch (670:9): [True: 0, False: 608]
  ------------------
  671|      0|      if (!parse_num(line, &maxdiff, afflst)) {
  ------------------
  |  Branch (671:11): [True: 0, False: 0]
  ------------------
  672|      0|        finishFileMgr(afflst);
  673|      0|        return 1;
  674|      0|      }
  675|      0|    }
  676|       |
  677|    608|    if (line.compare(0, 10, "MAXCPDSUGS", 10) == 0) {
  ------------------
  |  Branch (677:9): [True: 0, False: 608]
  ------------------
  678|      0|      if (!parse_num(line, &maxcpdsugs, afflst)) {
  ------------------
  |  Branch (678:11): [True: 0, False: 0]
  ------------------
  679|      0|        finishFileMgr(afflst);
  680|      0|        return 1;
  681|      0|      }
  682|      0|    }
  683|       |
  684|    608|    if (line.compare(0, 11, "NOSPLITSUGS", 11) == 0) {
  ------------------
  |  Branch (684:9): [True: 0, False: 608]
  ------------------
  685|      0|      nosplitsugs = 1;
  686|      0|    }
  687|       |
  688|    608|    if (line.compare(0, 9, "FULLSTRIP", 9) == 0) {
  ------------------
  |  Branch (688:9): [True: 0, False: 608]
  ------------------
  689|      0|      fullstrip = 1;
  690|      0|    }
  691|       |
  692|    608|    if (line.compare(0, 12, "SUGSWITHDOTS", 12) == 0) {
  ------------------
  |  Branch (692:9): [True: 0, False: 608]
  ------------------
  693|      0|      sugswithdots = 1;
  694|      0|    }
  695|       |
  696|       |    /* parse in the flag used by forbidden words */
  697|    608|    if (line.compare(0, 8, "KEEPCASE", 8) == 0) {
  ------------------
  |  Branch (697:9): [True: 2, False: 606]
  ------------------
  698|      2|      if (!parse_flag(line, &keepcase, afflst)) {
  ------------------
  |  Branch (698:11): [True: 0, False: 2]
  ------------------
  699|      0|        finishFileMgr(afflst);
  700|      0|        return 1;
  701|      0|      }
  702|      2|    }
  703|       |
  704|       |    /* parse in the flag used by `forceucase' */
  705|    608|    if (line.compare(0, 10, "FORCEUCASE", 10) == 0) {
  ------------------
  |  Branch (705:9): [True: 0, False: 608]
  ------------------
  706|      0|      if (!parse_flag(line, &forceucase, afflst)) {
  ------------------
  |  Branch (706:11): [True: 0, False: 0]
  ------------------
  707|      0|        finishFileMgr(afflst);
  708|      0|        return 1;
  709|      0|      }
  710|      0|    }
  711|       |
  712|       |    /* parse in the flag used by `warn' */
  713|    608|    if (line.compare(0, 4, "WARN", 4) == 0) {
  ------------------
  |  Branch (713:9): [True: 2, False: 606]
  ------------------
  714|      2|      if (!parse_flag(line, &warn, afflst)) {
  ------------------
  |  Branch (714:11): [True: 0, False: 2]
  ------------------
  715|      0|        finishFileMgr(afflst);
  716|      0|        return 1;
  717|      0|      }
  718|      2|    }
  719|       |
  720|    608|    if (line.compare(0, 10, "FORBIDWARN", 10) == 0) {
  ------------------
  |  Branch (720:9): [True: 0, False: 608]
  ------------------
  721|      0|      forbidwarn = 1;
  722|      0|    }
  723|       |
  724|       |    /* parse in the flag used by the affix generator */
  725|    608|    if (line.compare(0, 11, "SUBSTANDARD", 11) == 0) {
  ------------------
  |  Branch (725:9): [True: 0, False: 608]
  ------------------
  726|      0|      if (!parse_flag(line, &substandard, afflst)) {
  ------------------
  |  Branch (726:11): [True: 0, False: 0]
  ------------------
  727|      0|        finishFileMgr(afflst);
  728|      0|        return 1;
  729|      0|      }
  730|      0|    }
  731|       |
  732|    608|    if (line.compare(0, 11, "CHECKSHARPS", 11) == 0) {
  ------------------
  |  Branch (732:9): [True: 0, False: 608]
  ------------------
  733|      0|      checksharps = 1;
  734|      0|    }
  735|       |
  736|       |    /* parse this affix: P - prefix, S - suffix */
  737|       |    // affix type
  738|    608|    char ft = ' ';
  739|    608|    if (line.compare(0, 3, "PFX", 3) == 0)
  ------------------
  |  Branch (739:9): [True: 12, False: 596]
  ------------------
  740|     12|      ft = complexprefixes ? 'S' : 'P';
  ------------------
  |  Branch (740:12): [True: 4, False: 8]
  ------------------
  741|    608|    if (line.compare(0, 3, "SFX", 3) == 0)
  ------------------
  |  Branch (741:9): [True: 14, False: 594]
  ------------------
  742|     14|      ft = complexprefixes ? 'P' : 'S';
  ------------------
  |  Branch (742:12): [True: 0, False: 14]
  ------------------
  743|    608|    if (ft != ' ') {
  ------------------
  |  Branch (743:9): [True: 26, False: 582]
  ------------------
  744|     26|      if (dupflags_ini) {
  ------------------
  |  Branch (744:11): [True: 18, False: 8]
  ------------------
  745|     18|        memset(dupflags, 0, sizeof(dupflags));
  746|     18|        dupflags_ini = 0;
  747|     18|      }
  748|     26|      if (!parse_affix(line, ft, afflst, dupflags)) {
  ------------------
  |  Branch (748:11): [True: 0, False: 26]
  ------------------
  749|      0|        finishFileMgr(afflst);
  750|      0|        return 1;
  751|      0|      }
  752|     26|    }
  753|    608|  }
  754|       |
  755|     38|  finishFileMgr(afflst);
  756|       |  // affix trees are sorted now
  757|       |
  758|       |  // now we can speed up performance greatly taking advantage of the
  759|       |  // relationship between the affixes and the idea of "subsets".
  760|       |
  761|       |  // View each prefix as a potential leading subset of another and view
  762|       |  // each suffix (reversed) as a potential trailing subset of another.
  763|       |
  764|       |  // To illustrate this relationship if we know the prefix "ab" is found in the
  765|       |  // word to examine, only prefixes that "ab" is a leading subset of need be
  766|       |  // examined.
  767|       |  // Furthermore is "ab" is not present then none of the prefixes that "ab" is
  768|       |  // is a subset need be examined.
  769|       |  // The same argument goes for suffix string that are reversed.
  770|       |
  771|       |  // Then to top this off why not examine the first char of the word to quickly
  772|       |  // limit the set of prefixes to examine (i.e. the prefixes to examine must
  773|       |  // be leading supersets of the first character of the word (if they exist)
  774|       |
  775|       |  // To take advantage of this "subset" relationship, we need to add two links
  776|       |  // from entry.  One to take next if the current prefix is found (call it
  777|       |  // nexteq)
  778|       |  // and one to take next if the current prefix is not found (call it nextne).
  779|       |
  780|       |  // Since we have built ordered lists, all that remains is to properly
  781|       |  // initialize
  782|       |  // the nextne and nexteq pointers that relate them
  783|       |
  784|     38|  process_pfx_order();
  785|     38|  process_sfx_order();
  786|       |
  787|     38|  return 0;
  788|     38|}
_ZN8AffixMgr13build_pfxtreeEP8PfxEntry:
  794|      8|int AffixMgr::build_pfxtree(PfxEntry* pfxptr) {
  795|      8|  PfxEntry* ptr;
  796|      8|  PfxEntry* pptr;
  797|      8|  PfxEntry* ep = pfxptr;
  798|       |
  799|       |  // get the right starting points
  800|      8|  const char* key = ep->getKey();
  801|      8|  const auto flg = (unsigned char)(ep->getFlag() & 0x00FF);
  802|       |
  803|       |  // first index by flag which must exist
  804|      8|  ptr = pFlag[flg];
  805|      8|  ep->setFlgNxt(ptr);
  806|      8|  pFlag[flg] = ep;
  807|       |
  808|       |  // handle the special case of null affix string
  809|      8|  if (*key == '\0') {
  ------------------
  |  Branch (809:7): [True: 2, False: 6]
  ------------------
  810|       |    // always inset them at head of list at element 0
  811|      2|    ptr = pStart[0];
  812|      2|    ep->setNext(ptr);
  813|      2|    pStart[0] = ep;
  814|      2|    return 0;
  815|      2|  }
  816|       |
  817|       |  // now handle the normal case
  818|      6|  ep->setNextEQ(nullptr);
  819|      6|  ep->setNextNE(nullptr);
  820|       |
  821|      6|  unsigned char sp = *((const unsigned char*)key);
  822|      6|  ptr = pStart[sp];
  823|       |
  824|       |  // handle the first insert
  825|      6|  if (!ptr) {
  ------------------
  |  Branch (825:7): [True: 4, False: 2]
  ------------------
  826|      4|    pStart[sp] = ep;
  827|      4|    return 0;
  828|      4|  }
  829|       |
  830|       |  // otherwise use binary tree insertion so that a sorted
  831|       |  // list can easily be generated later
  832|      2|  pptr = nullptr;
  833|      2|  for (;;) {
  834|      2|    pptr = ptr;
  835|      2|    if (strcmp(ep->getKey(), ptr->getKey()) <= 0) {
  ------------------
  |  Branch (835:9): [True: 0, False: 2]
  ------------------
  836|      0|      ptr = ptr->getNextEQ();
  837|      0|      if (!ptr) {
  ------------------
  |  Branch (837:11): [True: 0, False: 0]
  ------------------
  838|      0|        pptr->setNextEQ(ep);
  839|      0|        break;
  840|      0|      }
  841|      2|    } else {
  842|      2|      ptr = ptr->getNextNE();
  843|      2|      if (!ptr) {
  ------------------
  |  Branch (843:11): [True: 2, False: 0]
  ------------------
  844|      2|        pptr->setNextNE(ep);
  845|      2|        break;
  846|      2|      }
  847|      2|    }
  848|      2|  }
  849|      2|  return 0;
  850|      6|}
_ZN8AffixMgr13build_sfxtreeEP8SfxEntry:
  855|     34|int AffixMgr::build_sfxtree(SfxEntry* sfxptr) {
  856|       |
  857|     34|  sfxptr->initReverseWord();
  858|       |
  859|     34|  SfxEntry* ptr;
  860|     34|  SfxEntry* pptr;
  861|     34|  SfxEntry* ep = sfxptr;
  862|       |
  863|       |  /* get the right starting point */
  864|     34|  const char* key = ep->getKey();
  865|     34|  const auto flg = (unsigned char)(ep->getFlag() & 0x00FF);
  866|       |
  867|       |  // first index by flag which must exist
  868|     34|  ptr = sFlag[flg];
  869|     34|  ep->setFlgNxt(ptr);
  870|     34|  sFlag[flg] = ep;
  871|       |
  872|       |  // next index by affix string
  873|       |
  874|       |  // handle the special case of null affix string
  875|     34|  if (*key == '\0') {
  ------------------
  |  Branch (875:7): [True: 0, False: 34]
  ------------------
  876|       |    // always inset them at head of list at element 0
  877|      0|    ptr = sStart[0];
  878|      0|    ep->setNext(ptr);
  879|      0|    sStart[0] = ep;
  880|      0|    return 0;
  881|      0|  }
  882|       |
  883|       |  // now handle the normal case
  884|     34|  ep->setNextEQ(nullptr);
  885|     34|  ep->setNextNE(nullptr);
  886|       |
  887|     34|  unsigned char sp = *((const unsigned char*)key);
  888|     34|  ptr = sStart[sp];
  889|       |
  890|       |  // handle the first insert
  891|     34|  if (!ptr) {
  ------------------
  |  Branch (891:7): [True: 22, False: 12]
  ------------------
  892|     22|    sStart[sp] = ep;
  893|     22|    return 0;
  894|     22|  }
  895|       |
  896|       |  // otherwise use binary tree insertion so that a sorted
  897|       |  // list can easily be generated later
  898|     12|  pptr = nullptr;
  899|     20|  for (;;) {
  900|     20|    pptr = ptr;
  901|     20|    if (strcmp(ep->getKey(), ptr->getKey()) <= 0) {
  ------------------
  |  Branch (901:9): [True: 18, False: 2]
  ------------------
  902|     18|      ptr = ptr->getNextEQ();
  903|     18|      if (!ptr) {
  ------------------
  |  Branch (903:11): [True: 10, False: 8]
  ------------------
  904|     10|        pptr->setNextEQ(ep);
  905|     10|        break;
  906|     10|      }
  907|     18|    } else {
  908|      2|      ptr = ptr->getNextNE();
  909|      2|      if (!ptr) {
  ------------------
  |  Branch (909:11): [True: 2, False: 0]
  ------------------
  910|      2|        pptr->setNextNE(ep);
  911|      2|        break;
  912|      2|      }
  913|      2|    }
  914|     20|  }
  915|     12|  return 0;
  916|     34|}
_ZN8AffixMgr24process_pfx_tree_to_listEv:
  936|     38|int AffixMgr::process_pfx_tree_to_list() {
  937|  9.72k|  for (int i = 1; i < SETSIZE; i++) {
  ------------------
  |  |   61|  9.72k|#define SETSIZE 256
  ------------------
  |  Branch (937:19): [True: 9.69k, False: 38]
  ------------------
  938|  9.69k|    pStart[i] = process_pfx_in_order(pStart[i], nullptr);
  939|  9.69k|  }
  940|     38|  return 0;
  941|     38|}
_ZN8AffixMgr20process_pfx_in_orderEP8PfxEntryS1_:
  943|  9.69k|PfxEntry* AffixMgr::process_pfx_in_order(PfxEntry* ptr, PfxEntry* nptr) {
  944|  9.69k|  return link_in_order(ptr, nptr);
  945|  9.69k|}
_ZN8AffixMgr24process_sfx_tree_to_listEv:
  948|     38|int AffixMgr::process_sfx_tree_to_list() {
  949|  9.72k|  for (int i = 1; i < SETSIZE; i++) {
  ------------------
  |  |   61|  9.72k|#define SETSIZE 256
  ------------------
  |  Branch (949:19): [True: 9.69k, False: 38]
  ------------------
  950|  9.69k|    sStart[i] = process_sfx_in_order(sStart[i], nullptr);
  951|  9.69k|  }
  952|     38|  return 0;
  953|     38|}
_ZN8AffixMgr20process_sfx_in_orderEP8SfxEntryS1_:
  955|  9.69k|SfxEntry* AffixMgr::process_sfx_in_order(SfxEntry* ptr, SfxEntry* nptr) {
  956|  9.69k|  return link_in_order(ptr, nptr);
  957|  9.69k|}
_ZN8AffixMgr17process_pfx_orderEv:
  961|     38|int AffixMgr::process_pfx_order() {
  962|     38|  PfxEntry* ptr;
  963|       |
  964|       |  // loop through each prefix list starting point
  965|  9.72k|  for (int i = 1; i < SETSIZE; i++) {
  ------------------
  |  |   61|  9.72k|#define SETSIZE 256
  ------------------
  |  Branch (965:19): [True: 9.69k, False: 38]
  ------------------
  966|  9.69k|    ptr = pStart[i];
  967|       |
  968|       |    // look through the remainder of the list
  969|       |    //  and find next entry with affix that
  970|       |    // the current one is not a subset of
  971|       |    // mark that as destination for NextNE
  972|       |    // use next in list that you are a subset
  973|       |    // of as NextEQ
  974|       |
  975|  9.69k|    for (; ptr != nullptr; ptr = ptr->getNext()) {
  ------------------
  |  Branch (975:12): [True: 6, False: 9.69k]
  ------------------
  976|      6|      PfxEntry* nptr = ptr->getNext();
  977|      8|      for (; nptr != nullptr; nptr = nptr->getNext()) {
  ------------------
  |  Branch (977:14): [True: 2, False: 6]
  ------------------
  978|      2|        if (!isSubset(ptr->getKey(), nptr->getKey()))
  ------------------
  |  Branch (978:13): [True: 0, False: 2]
  ------------------
  979|      0|          break;
  980|      2|      }
  981|      6|      ptr->setNextNE(nptr);
  982|      6|      ptr->setNextEQ(nullptr);
  983|      6|      if ((ptr->getNext()) &&
  ------------------
  |  Branch (983:11): [True: 2, False: 4]
  ------------------
  984|      2|          isSubset(ptr->getKey(), (ptr->getNext())->getKey()))
  ------------------
  |  Branch (984:11): [True: 2, False: 0]
  ------------------
  985|      2|        ptr->setNextEQ(ptr->getNext());
  986|      6|    }
  987|       |
  988|       |    // now clean up by adding smart search termination strings:
  989|       |    // if you are already a superset of the previous prefix
  990|       |    // but not a subset of the next, search can end here
  991|       |    // so set NextNE properly
  992|       |
  993|  9.69k|    ptr = pStart[i];
  994|  9.69k|    for (; ptr != nullptr; ptr = ptr->getNext()) {
  ------------------
  |  Branch (994:12): [True: 6, False: 9.69k]
  ------------------
  995|      6|      PfxEntry* nptr = ptr->getNext();
  996|      6|      PfxEntry* mptr = nullptr;
  997|      8|      for (; nptr != nullptr; nptr = nptr->getNext()) {
  ------------------
  |  Branch (997:14): [True: 2, False: 6]
  ------------------
  998|      2|        if (!isSubset(ptr->getKey(), nptr->getKey()))
  ------------------
  |  Branch (998:13): [True: 0, False: 2]
  ------------------
  999|      0|          break;
 1000|      2|        mptr = nptr;
 1001|      2|      }
 1002|      6|      if (mptr)
  ------------------
  |  Branch (1002:11): [True: 2, False: 4]
  ------------------
 1003|      2|        mptr->setNextNE(nullptr);
 1004|      6|    }
 1005|  9.69k|  }
 1006|     38|  return 0;
 1007|     38|}
_ZN8AffixMgr17process_sfx_orderEv:
 1011|     38|int AffixMgr::process_sfx_order() {
 1012|     38|  SfxEntry* ptr;
 1013|       |
 1014|       |  // loop through each prefix list starting point
 1015|  9.72k|  for (int i = 1; i < SETSIZE; i++) {
  ------------------
  |  |   61|  9.72k|#define SETSIZE 256
  ------------------
  |  Branch (1015:19): [True: 9.69k, False: 38]
  ------------------
 1016|  9.69k|    ptr = sStart[i];
 1017|       |
 1018|       |    // look through the remainder of the list
 1019|       |    //  and find next entry with affix that
 1020|       |    // the current one is not a subset of
 1021|       |    // mark that as destination for NextNE
 1022|       |    // use next in list that you are a subset
 1023|       |    // of as NextEQ
 1024|       |
 1025|  9.72k|    for (; ptr != nullptr; ptr = ptr->getNext()) {
  ------------------
  |  Branch (1025:12): [True: 34, False: 9.69k]
  ------------------
 1026|     34|      SfxEntry* nptr = ptr->getNext();
 1027|     52|      for (; nptr != nullptr; nptr = nptr->getNext()) {
  ------------------
  |  Branch (1027:14): [True: 20, False: 32]
  ------------------
 1028|     20|        if (!isSubset(ptr->getKey(), nptr->getKey()))
  ------------------
  |  Branch (1028:13): [True: 2, False: 18]
  ------------------
 1029|      2|          break;
 1030|     20|      }
 1031|     34|      ptr->setNextNE(nptr);
 1032|     34|      ptr->setNextEQ(nullptr);
 1033|     34|      if ((ptr->getNext()) &&
  ------------------
  |  Branch (1033:11): [True: 12, False: 22]
  ------------------
 1034|     12|          isSubset(ptr->getKey(), (ptr->getNext())->getKey()))
  ------------------
  |  Branch (1034:11): [True: 10, False: 2]
  ------------------
 1035|     10|        ptr->setNextEQ(ptr->getNext());
 1036|     34|    }
 1037|       |
 1038|       |    // now clean up by adding smart search termination strings:
 1039|       |    // if you are already a superset of the previous suffix
 1040|       |    // but not a subset of the next, search can end here
 1041|       |    // so set NextNE properly
 1042|       |
 1043|  9.69k|    ptr = sStart[i];
 1044|  9.72k|    for (; ptr != nullptr; ptr = ptr->getNext()) {
  ------------------
  |  Branch (1044:12): [True: 34, False: 9.69k]
  ------------------
 1045|     34|      SfxEntry* nptr = ptr->getNext();
 1046|     34|      SfxEntry* mptr = nullptr;
 1047|     52|      for (; nptr != nullptr; nptr = nptr->getNext()) {
  ------------------
  |  Branch (1047:14): [True: 20, False: 32]
  ------------------
 1048|     20|        if (!isSubset(ptr->getKey(), nptr->getKey()))
  ------------------
  |  Branch (1048:13): [True: 2, False: 18]
  ------------------
 1049|      2|          break;
 1050|     18|        mptr = nptr;
 1051|     18|      }
 1052|     34|      if (mptr)
  ------------------
  |  Branch (1052:11): [True: 10, False: 24]
  ------------------
 1053|     10|        mptr->setNextNE(nullptr);
 1054|     34|    }
 1055|  9.69k|  }
 1056|     38|  return 0;
 1057|     38|}
_ZN8AffixMgr7condlenERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1070|      8|int AffixMgr::condlen(const std::string& s) {
 1071|      8|  int l = 0;
 1072|      8|  bool group = false;
 1073|      8|  size_t i = 0;
 1074|     42|  while (i < s.size()) {
  ------------------
  |  Branch (1074:10): [True: 34, False: 8]
  ------------------
 1075|     34|    if (s[i] == '[') {
  ------------------
  |  Branch (1075:9): [True: 4, False: 30]
  ------------------
 1076|      4|      group = true;
 1077|      4|      ++l;
 1078|      4|      ++i;
 1079|     30|    } else if (s[i] == ']') {
  ------------------
  |  Branch (1079:16): [True: 4, False: 26]
  ------------------
 1080|      4|      group = false;
 1081|      4|      ++i;
 1082|     26|    } else if (group) {
  ------------------
  |  Branch (1082:16): [True: 18, False: 8]
  ------------------
 1083|     18|      ++i;
 1084|     18|    } else {
 1085|      8|      ++l;
 1086|      8|      i = utf8 ? utf8_next(s, i) : i + 1;
  ------------------
  |  Branch (1086:11): [True: 8, False: 0]
  ------------------
 1087|      8|    }
 1088|     34|  }
 1089|      8|  return l;
 1090|      8|}
_ZN8AffixMgr8encodeitER8AffEntryRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 1092|     42|int AffixMgr::encodeit(AffEntry& entry, const std::string& cs) {
 1093|     42|  if (cs.compare(".") != 0) {
  ------------------
  |  Branch (1093:7): [True: 8, False: 34]
  ------------------
 1094|      8|    int n = condlen(cs);
 1095|      8|    if (n > std::numeric_limits<unsigned char>::max()) {
  ------------------
  |  Branch (1095:9): [True: 0, False: 8]
  ------------------
 1096|      0|      HUNSPELL_WARNING(stderr, "error: condition length %d is over max limit\n", n);
 1097|      0|      return 1;
 1098|      0|    }
 1099|      8|    entry.numconds = (unsigned char)n;
 1100|      8|    const size_t cslen = cs.size();
 1101|      8|    const size_t short_part = std::min<size_t>(MAXCONDLEN, cslen);
  ------------------
  |  |   93|      8|#define MAXCONDLEN 20
  ------------------
 1102|      8|    memcpy(entry.c.conds, cs.data(), short_part);
 1103|      8|    if (short_part < MAXCONDLEN) {
  ------------------
  |  |   93|      8|#define MAXCONDLEN 20
  ------------------
  |  Branch (1103:9): [True: 8, False: 0]
  ------------------
 1104|       |      //blank out the remaining space
 1105|      8|      memset(entry.c.conds + short_part, 0, MAXCONDLEN - short_part);
  ------------------
  |  |   93|      8|#define MAXCONDLEN 20
  ------------------
 1106|      8|    } else if (cs[MAXCONDLEN]) {
  ------------------
  |  |   93|      0|#define MAXCONDLEN 20
  ------------------
  |  Branch (1106:16): [True: 0, False: 0]
  ------------------
 1107|       |      //there is more conditions than fit in fixed space, so its
 1108|       |      //a long condition
 1109|      0|      entry.opts |= aeLONGCOND;
  ------------------
  |  |   69|      0|#define aeLONGCOND (1 << 4)
  ------------------
 1110|      0|      size_t remaining = cs.size() - MAXCONDLEN_1;
  ------------------
  |  |   94|      0|#define MAXCONDLEN_1 (MAXCONDLEN - sizeof(char*))
  |  |  ------------------
  |  |  |  |   93|      0|#define MAXCONDLEN 20
  |  |  ------------------
  ------------------
 1111|      0|      entry.c.l.conds2 = new char[1 + remaining];
 1112|      0|      memcpy(entry.c.l.conds2, cs.data() + MAXCONDLEN_1, remaining);
  ------------------
  |  |   94|      0|#define MAXCONDLEN_1 (MAXCONDLEN - sizeof(char*))
  |  |  ------------------
  |  |  |  |   93|      0|#define MAXCONDLEN 20
  |  |  ------------------
  ------------------
 1113|      0|      entry.c.l.conds2[remaining] = 0;
 1114|      0|    }
 1115|     34|  } else {
 1116|     34|    entry.numconds = 0;
 1117|     34|    entry.c.conds[0] = '\0';
 1118|     34|  }
 1119|     42|  return 0;
 1120|     42|}
_ZN8AffixMgr12prefix_checkERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmcR12AffixScratchtt:
 1138|   584M|                                      const FLAG avoidflag) {
 1139|   584M|  struct hentry* rv = nullptr;
 1140|       |
 1141|   584M|  pfx = nullptr;
 1142|   584M|  pfxappnd = nullptr;
 1143|   584M|  sfxappnd = nullptr;
 1144|   584M|  sfxextra = 0;
 1145|       |
 1146|   584M|  TraceCtx* t = trace_on(scratch.trace);
 1147|   584M|  int candidates = 0;
 1148|       |
 1149|       |  // first handle the special case of 0 length prefixes
 1150|   584M|  PfxEntry* pe = pStart[0];
 1151|   585M|  while (pe) {
  ------------------
  |  Branch (1151:10): [True: 1.52M, False: 584M]
  ------------------
 1152|  1.52M|    if (
 1153|       |        // fogemorpheme
 1154|  1.52M|        ((in_compound != IN_CPD_NOT) ||
  ------------------
  |  |   75|  1.52M|#define IN_CPD_NOT 0
  ------------------
  |  Branch (1154:10): [True: 0, False: 1.52M]
  ------------------
 1155|  1.52M|         !(pe->getCont() &&
  ------------------
  |  Branch (1155:12): [True: 1.52M, False: 0]
  ------------------
 1156|  1.52M|           (TESTAFF(pe->getCont(), onlyincompound, pe->getContLen())))) &&
  ------------------
  |  |  102|  1.52M|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (1156:12): [True: 0, False: 1.52M]
  ------------------
 1157|       |        // permit prefixes in compounds
 1158|  1.52M|        ((in_compound != IN_CPD_END) ||
  ------------------
  |  |   77|  1.52M|#define IN_CPD_END 2
  ------------------
  |  Branch (1158:10): [True: 1.52M, False: 0]
  ------------------
 1159|      0|         (pe->getCont() &&
  ------------------
  |  Branch (1159:11): [True: 0, False: 0]
  ------------------
 1160|  1.52M|          (TESTAFF(pe->getCont(), compoundpermitflag, pe->getContLen()))))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (1160:11): [True: 0, False: 0]
  ------------------
 1161|       |      // check prefix
 1162|  1.52M|      ++candidates;
 1163|  1.52M|      rv = pe->checkword(word, start, len, in_compound, needflag, scratch);
 1164|       |      // Skip a stem with the avoid flag and keep scanning the other prefixes.
 1165|  1.52M|      if (rv && avoidflag != FLAG_NULL && TESTAFF(rv->astr, avoidflag, rv->alen)) {
  ------------------
  |  |   99|  1.52M|#define FLAG_NULL 0x00
  ------------------
                    if (rv && avoidflag != FLAG_NULL && TESTAFF(rv->astr, avoidflag, rv->alen)) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (1165:11): [True: 0, False: 1.52M]
  |  Branch (1165:17): [True: 0, False: 0]
  ------------------
 1166|      0|        trace_avoidflag(t, avoidflag, rv);
 1167|      0|        rv = nullptr;
 1168|      0|      }
 1169|  1.52M|      if (rv) {
  ------------------
  |  Branch (1169:11): [True: 0, False: 1.52M]
  ------------------
 1170|      0|        pfx = pe;  // BUG: pfx not stateless
 1171|      0|        return rv;
 1172|      0|      }
 1173|  1.52M|    }
 1174|  1.52M|    pe = pe->getNext();
 1175|  1.52M|  }
 1176|       |
 1177|       |  // now handle the general case
 1178|   584M|  unsigned char sp = word[start];
 1179|   584M|  PfxEntry* pptr = pStart[sp];
 1180|       |
 1181|   584M|  while (pptr) {
  ------------------
  |  Branch (1181:10): [True: 65.1k, False: 584M]
  ------------------
 1182|  65.1k|    if (isSubset(pptr->getKey(), word.c_str() + start)) {
  ------------------
  |  Branch (1182:9): [True: 41.9k, False: 23.2k]
  ------------------
 1183|  41.9k|      if (
 1184|       |          // fogemorpheme
 1185|  41.9k|          ((in_compound != IN_CPD_NOT) ||
  ------------------
  |  |   75|  41.9k|#define IN_CPD_NOT 0
  ------------------
  |  Branch (1185:12): [True: 0, False: 41.9k]
  ------------------
 1186|  41.9k|           !(pptr->getCont() &&
  ------------------
  |  Branch (1186:14): [True: 35.9k, False: 5.95k]
  ------------------
 1187|  35.9k|             (TESTAFF(pptr->getCont(), onlyincompound, pptr->getContLen())))) &&
  ------------------
  |  |  102|  35.9k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (1187:14): [True: 0, False: 35.9k]
  ------------------
 1188|       |          // permit prefixes in compounds
 1189|  41.9k|          ((in_compound != IN_CPD_END) ||
  ------------------
  |  |   77|  41.9k|#define IN_CPD_END 2
  ------------------
  |  Branch (1189:12): [True: 41.9k, False: 0]
  ------------------
 1190|      0|           (pptr->getCont() && (TESTAFF(pptr->getCont(), compoundpermitflag,
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (1190:13): [True: 0, False: 0]
  |  Branch (1190:32): [True: 0, False: 0]
  ------------------
 1191|  41.9k|                                        pptr->getContLen()))))) {
 1192|       |        // check prefix
 1193|  41.9k|        ++candidates;
 1194|  41.9k|        rv = pptr->checkword(word, start, len, in_compound, needflag, scratch);
 1195|  41.9k|        if (rv && avoidflag != FLAG_NULL && TESTAFF(rv->astr, avoidflag, rv->alen)) {
  ------------------
  |  |   99|  41.9k|#define FLAG_NULL 0x00
  ------------------
                      if (rv && avoidflag != FLAG_NULL && TESTAFF(rv->astr, avoidflag, rv->alen)) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (1195:13): [True: 0, False: 41.9k]
  |  Branch (1195:19): [True: 0, False: 0]
  ------------------
 1196|      0|          trace_avoidflag(t, avoidflag, rv);
 1197|      0|          rv = nullptr;
 1198|      0|        }
 1199|  41.9k|        if (rv) {
  ------------------
  |  Branch (1199:13): [True: 0, False: 41.9k]
  ------------------
 1200|      0|          pfx = pptr;  // BUG: pfx not stateless
 1201|      0|          return rv;
 1202|      0|        }
 1203|  41.9k|      }
 1204|  41.9k|      pptr = pptr->getNextEQ();
 1205|  41.9k|    } else {
 1206|  23.2k|      pptr = pptr->getNextNE();
 1207|  23.2k|    }
 1208|  65.1k|  }
 1209|       |
 1210|       |  // a pass that had nothing to try says so, which is different from a pass that
 1211|       |  // did not run
 1212|   584M|  if (t && candidates == 0)
  ------------------
  |  Branch (1212:7): [True: 0, False: 584M]
  |  Branch (1212:12): [True: 0, False: 0]
  ------------------
 1213|      0|    trace(*t, "pfx \"%s\" candidates=0", word.substr(start, len).c_str());
 1214|       |
 1215|   584M|  return nullptr;
 1216|   584M|}
_ZN8AffixMgr19prefix_check_twosfxERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmcR12AffixScratcht:
 1224|  18.3M|                                             const FLAG needflag) {
 1225|  18.3M|  struct hentry* rv = nullptr;
 1226|       |
 1227|  18.3M|  pfx = nullptr;
 1228|  18.3M|  sfxappnd = nullptr;
 1229|  18.3M|  sfxextra = 0;
 1230|       |
 1231|       |  // first handle the special case of 0 length prefixes
 1232|  18.3M|  PfxEntry* pe = pStart[0];
 1233|       |
 1234|  19.9M|  while (pe) {
  ------------------
  |  Branch (1234:10): [True: 1.52M, False: 18.3M]
  ------------------
 1235|  1.52M|    rv = pe->check_twosfx(word, start, len, in_compound, needflag, scratch);
 1236|  1.52M|    if (rv)
  ------------------
  |  Branch (1236:9): [True: 0, False: 1.52M]
  ------------------
 1237|      0|      return rv;
 1238|  1.52M|    pe = pe->getNext();
 1239|  1.52M|  }
 1240|       |
 1241|       |  // now handle the general case
 1242|  18.3M|  unsigned char sp = word[start];
 1243|  18.3M|  PfxEntry* pptr = pStart[sp];
 1244|       |
 1245|  18.4M|  while (pptr) {
  ------------------
  |  Branch (1245:10): [True: 59.2k, False: 18.3M]
  ------------------
 1246|  59.2k|    if (isSubset(pptr->getKey(), word.c_str() + start)) {
  ------------------
  |  Branch (1246:9): [True: 35.9k, False: 23.2k]
  ------------------
 1247|  35.9k|      rv = pptr->check_twosfx(word, start, len, in_compound, needflag, scratch);
 1248|  35.9k|      if (rv) {
  ------------------
  |  Branch (1248:11): [True: 0, False: 35.9k]
  ------------------
 1249|      0|        pfx = pptr;
 1250|      0|        return rv;
 1251|      0|      }
 1252|  35.9k|      pptr = pptr->getNextEQ();
 1253|  35.9k|    } else {
 1254|  23.2k|      pptr = pptr->getNextNE();
 1255|  23.2k|    }
 1256|  59.2k|  }
 1257|       |
 1258|  18.3M|  return nullptr;
 1259|  18.3M|}
_ZN8AffixMgr18prefix_check_morphERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmcR12AffixScratcht:
 1267|  11.9k|                                         const FLAG needflag) {
 1268|       |
 1269|       |  // many prefixes can analyse a word the same way
 1270|  11.9k|  DistinctRecords result(MSEP_REC);
  ------------------
  |  |  118|  11.9k|#define MSEP_REC '\n'
  ------------------
 1271|       |
 1272|  11.9k|  pfx = nullptr;
 1273|  11.9k|  sfxappnd = nullptr;
 1274|  11.9k|  sfxextra = 0;
 1275|       |
 1276|       |  // first handle the special case of 0 length prefixes
 1277|  11.9k|  PfxEntry* pe = pStart[0];
 1278|  12.5k|  while (pe) {
  ------------------
  |  Branch (1278:10): [True: 654, False: 11.9k]
  ------------------
 1279|    654|    std::string st = pe->check_morph(word, start, len, in_compound, needflag, scratch);
 1280|    654|    if (!st.empty()) {
  ------------------
  |  Branch (1280:9): [True: 0, False: 654]
  ------------------
 1281|      0|      result.append(st);
 1282|      0|    }
 1283|    654|    pe = pe->getNext();
 1284|    654|  }
 1285|       |
 1286|       |  // now handle the general case
 1287|  11.9k|  unsigned char sp = word[start];
 1288|  11.9k|  PfxEntry* pptr = pStart[sp];
 1289|       |
 1290|  11.9k|  while (pptr) {
  ------------------
  |  Branch (1290:10): [True: 1, False: 11.9k]
  ------------------
 1291|      1|    if (isSubset(pptr->getKey(), word.c_str() + start)) {
  ------------------
  |  Branch (1291:9): [True: 1, False: 0]
  ------------------
 1292|      1|      std::string st = pptr->check_morph(word, start, len, in_compound, needflag, scratch);
 1293|      1|      if (!st.empty()) {
  ------------------
  |  Branch (1293:11): [True: 0, False: 1]
  ------------------
 1294|       |        // fogemorpheme
 1295|      0|        if ((in_compound != IN_CPD_NOT) ||
  ------------------
  |  |   75|      0|#define IN_CPD_NOT 0
  ------------------
  |  Branch (1295:13): [True: 0, False: 0]
  ------------------
 1296|      0|            !((pptr->getCont() && (TESTAFF(pptr->getCont(), onlyincompound,
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (1296:16): [True: 0, False: 0]
  |  Branch (1296:35): [True: 0, False: 0]
  ------------------
 1297|      0|                                           pptr->getContLen()))))) {
 1298|      0|          result.append(st);
 1299|      0|          pfx = pptr;
 1300|      0|        }
 1301|      0|      }
 1302|      1|      pptr = pptr->getNextEQ();
 1303|      1|    } else {
 1304|      0|      pptr = pptr->getNextNE();
 1305|      0|    }
 1306|      1|  }
 1307|       |
 1308|  11.9k|  return result.join();
 1309|  11.9k|}
_ZN8AffixMgr25prefix_check_twosfx_morphERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmcR12AffixScratcht:
 1317|  3.74k|                                                const FLAG needflag) {
 1318|       |  // every prefix crosses with every pair of suffixes
 1319|  3.74k|  DistinctRecords result(MSEP_REC);
  ------------------
  |  |  118|  3.74k|#define MSEP_REC '\n'
  ------------------
 1320|       |
 1321|  3.74k|  pfx = nullptr;
 1322|  3.74k|  sfxappnd = nullptr;
 1323|  3.74k|  sfxextra = 0;
 1324|       |
 1325|       |  // first handle the special case of 0 length prefixes
 1326|  3.74k|  PfxEntry* pe = pStart[0];
 1327|  4.40k|  while (pe) {
  ------------------
  |  Branch (1327:10): [True: 654, False: 3.74k]
  ------------------
 1328|    654|    std::string st = pe->check_twosfx_morph(word, start, len, in_compound, needflag, scratch);
 1329|    654|    if (!st.empty()) {
  ------------------
  |  Branch (1329:9): [True: 0, False: 654]
  ------------------
 1330|      0|      result.append(st);
 1331|      0|    }
 1332|    654|    pe = pe->getNext();
 1333|    654|  }
 1334|       |
 1335|       |  // now handle the general case
 1336|  3.74k|  unsigned char sp = word[start];
 1337|  3.74k|  PfxEntry* pptr = pStart[sp];
 1338|       |
 1339|  3.74k|  while (pptr) {
  ------------------
  |  Branch (1339:10): [True: 0, False: 3.74k]
  ------------------
 1340|      0|    if (isSubset(pptr->getKey(), word.c_str() + start)) {
  ------------------
  |  Branch (1340:9): [True: 0, False: 0]
  ------------------
 1341|      0|      std::string st = pptr->check_twosfx_morph(word, start, len, in_compound, needflag, scratch);
 1342|      0|      if (!st.empty()) {
  ------------------
  |  Branch (1342:11): [True: 0, False: 0]
  ------------------
 1343|      0|        result.append(st);
 1344|      0|        pfx = pptr;
 1345|      0|      }
 1346|      0|      pptr = pptr->getNextEQ();
 1347|      0|    } else {
 1348|      0|      pptr = pptr->getNextNE();
 1349|      0|    }
 1350|      0|  }
 1351|       |
 1352|  3.74k|  return result.join();
 1353|  3.74k|}
_ZN8AffixMgr12get_syllableERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1701|    564|short AffixMgr::get_syllable(const std::string& word) {
 1702|    564|  if (cpdmaxsyllable == 0)
  ------------------
  |  Branch (1702:7): [True: 0, False: 564]
  ------------------
 1703|      0|    return 0;
 1704|       |
 1705|    564|  short num = 0;
 1706|       |
 1707|    564|  if (!utf8) {
  ------------------
  |  Branch (1707:7): [True: 0, False: 564]
  ------------------
 1708|      0|    num = (short)std::count_if(word.begin(), word.end(),
 1709|      0|          [&](char c) {
 1710|      0|            return std::binary_search(cpdvowels.begin(), cpdvowels.end(), c);
 1711|      0|          });
 1712|    564|  } else if (!cpdvowels_utf16.empty()) {
  ------------------
  |  Branch (1712:14): [True: 564, False: 0]
  ------------------
 1713|    564|    std::vector<w_char> w;
 1714|    564|    u8_u16(w, word);
 1715|    564|    num = (short)std::count_if(w.begin(), w.end(),
 1716|    564|          [&](w_char wc) {
 1717|    564|            return std::binary_search(cpdvowels_utf16.begin(), cpdvowels_utf16.end(), wc);
 1718|    564|          });
 1719|    564|  }
 1720|       |
 1721|    564|  return num;
 1722|    564|}
_ZN8AffixMgr10setcminmaxEPmS0_PKcm:
 1724|  25.9M|void AffixMgr::setcminmax(size_t* cmin, size_t* cmax, const char* word, size_t len) {
 1725|  25.9M|  if (utf8) {
  ------------------
  |  Branch (1725:7): [True: 1.78M, False: 24.1M]
  ------------------
 1726|  1.78M|    int i;
 1727|  5.31M|    for (*cmin = 0, i = 0; (i < cpdmin) && *cmin < len; i++) {
  ------------------
  |  Branch (1727:28): [True: 3.55M, False: 1.75M]
  |  Branch (1727:44): [True: 3.53M, False: 26.4k]
  ------------------
 1728|  3.94M|      for ((*cmin)++; *cmin < len && is_utf8_cont(word[*cmin]); (*cmin)++)
  ------------------
  |  Branch (1728:23): [True: 3.90M, False: 45.2k]
  |  Branch (1728:38): [True: 417k, False: 3.48M]
  ------------------
 1729|   417k|        ;
 1730|  3.53M|    }
 1731|  3.55M|    for (*cmax = len, i = 0; (i < (cpdmin - 1)) && *cmax > 0; i++) {
  ------------------
  |  Branch (1731:30): [True: 1.78M, False: 1.77M]
  |  Branch (1731:52): [True: 1.77M, False: 3.32k]
  ------------------
 1732|  2.71M|      for ((*cmax)--; *cmax > 0 && is_utf8_cont(word[*cmax]); (*cmax)--)
  ------------------
  |  Branch (1732:23): [True: 2.68M, False: 23.0k]
  |  Branch (1732:36): [True: 934k, False: 1.75M]
  ------------------
 1733|   934k|        ;
 1734|  1.77M|    }
 1735|  24.1M|  } else {
 1736|  24.1M|    *cmin = cpdmin;
 1737|  24.1M|    *cmax = len - cpdmin + 1;
 1738|  24.1M|  }
 1739|  25.9M|}
_ZN8AffixMgr14compound_checkERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEssssPP6hentrySB_ccPiR12AffixScratch:
 1753|  25.9M|                                        AffixScratch& scratch) {
 1754|  25.9M|  short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
 1755|  25.9M|  hentry *rv = nullptr, *rv_first;
 1756|  25.9M|  std::string st;
 1757|  25.9M|  char ch = '\0', affixed;
 1758|  25.9M|  size_t cmin, cmax;
 1759|  25.9M|  int striple = 0, checkedstriple = 0;
 1760|  25.9M|  size_t soldi = 0, oldcmin = 0, oldcmax = 0, oldlen = 0;
 1761|  25.9M|  hentry** oldwords = words;
 1762|  25.9M|  size_t scpd = 0, len = word.size();
 1763|       |
 1764|  25.9M|  TraceCtx* t = trace_on(scratch.trace);
 1765|       |
 1766|       |  // protect subsequent words[wnum + 1] reads and any recursion
 1767|  25.9M|  if (wnum + 1 >= maxwordnum)
  ------------------
  |  Branch (1767:7): [True: 0, False: 25.9M]
  ------------------
 1768|      0|    return nullptr;
 1769|       |
 1770|  25.9M|  int checked_prefix;
 1771|       |
 1772|       |  // add a time limit to handle possible
 1773|       |  // combinatorical explosion of the overlapping words
 1774|       |
 1775|  25.9M|  HUNSPELL_THREAD_LOCAL std::chrono::steady_clock::time_point clock_time_start;
  ------------------
  |  |   60|  25.9M|#  define HUNSPELL_THREAD_LOCAL thread_local
  ------------------
 1776|  25.9M|  HUNSPELL_THREAD_LOCAL bool timelimit_exceeded;
  ------------------
  |  |   60|  25.9M|#  define HUNSPELL_THREAD_LOCAL thread_local
  ------------------
 1777|       |
 1778|       |  // get the current time
 1779|  25.9M|  std::chrono::steady_clock::time_point clock_now = std::chrono::steady_clock::now();
 1780|       |
 1781|  25.9M|  if (wnum == 0) {
  ------------------
  |  Branch (1781:7): [True: 25.9M, False: 182]
  ------------------
 1782|       |      // set the start time
 1783|  25.9M|      clock_time_start = clock_now;
 1784|  25.9M|      timelimit_exceeded = false;
 1785|  25.9M|  }
 1786|    182|  else if (clock_now - clock_time_start > TIMELIMIT_MS)
  ------------------
  |  |  109|    182|#define TIMELIMIT_MS std::chrono::milliseconds(50)
  ------------------
  |  Branch (1786:12): [True: 0, False: 182]
  ------------------
 1787|      0|      timelimit_exceeded = true;
 1788|       |
 1789|  25.9M|  setcminmax(&cmin, &cmax, word.c_str(), len);
 1790|       |
 1791|       |  // with SIMPLIFIEDTRIPLE a second part that starts at a doubled letter is one letter longer
 1792|       |  // than the surface shows, so the split can go one letter past cmax
 1793|  25.9M|  size_t cmaxtriple = simplifiedtriple ? (utf8 ? utf8_next(word, cmax) : cmax + 1) : cmax;
  ------------------
  |  Branch (1793:23): [True: 0, False: 25.9M]
  |  Branch (1793:43): [True: 0, False: 0]
  ------------------
 1794|       |
 1795|  25.9M|  st.assign(word);
 1796|       |
 1797|   557M|  for (size_t i = cmin; i < cmaxtriple; ++i) {
  ------------------
  |  Branch (1797:25): [True: 532M, False: 24.4M]
  ------------------
 1798|       |    // go to end of the UTF-8 character
 1799|   532M|    if (utf8) {
  ------------------
  |  Branch (1799:9): [True: 43.2M, False: 489M]
  ------------------
 1800|  50.1M|      for (; is_utf8_cont(st[i]); i++)
  ------------------
  |  Branch (1800:14): [True: 6.92M, False: 43.2M]
  ------------------
 1801|  6.92M|        ;
 1802|  43.2M|      if (i >= cmaxtriple)
  ------------------
  |  Branch (1802:11): [True: 141k, False: 43.1M]
  ------------------
 1803|   141k|        return nullptr;
 1804|  43.2M|    }
 1805|   532M|    if (i >= cmax && !(i > 2 && word[i - 1] == word[i - 2]))
  ------------------
  |  Branch (1805:9): [True: 0, False: 532M]
  |  Branch (1805:24): [True: 0, False: 0]
  |  Branch (1805:33): [True: 0, False: 0]
  ------------------
 1806|      0|      break;
 1807|       |
 1808|   532M|    words = oldwords;
 1809|   532M|    int onlycpdrule = (words) ? 1 : 0;
  ------------------
  |  Branch (1809:23): [True: 0, False: 532M]
  ------------------
 1810|       |
 1811|   532M|    do {  // onlycpdrule loop
 1812|       |
 1813|   532M|      oldnumsyllable = numsyllable;
 1814|   532M|      oldwordnum = wordnum;
 1815|   532M|      checked_prefix = 0;
 1816|       |
 1817|   532M|      do {  // simplified checkcompoundpattern loop
 1818|       |
 1819|   532M|        if (timelimit_exceeded ||
  ------------------
  |  Branch (1819:13): [True: 0, False: 532M]
  |  Branch (1819:13): [True: 0, False: 532M]
  ------------------
 1820|   532M|            std::chrono::steady_clock::now() - clock_time_start > TIMELIMIT_MS) {
  ------------------
  |  |  109|   532M|#define TIMELIMIT_MS std::chrono::milliseconds(50)
  ------------------
  |  Branch (1820:13): [True: 0, False: 532M]
  ------------------
 1821|      0|          if (t && !timelimit_exceeded)
  ------------------
  |  Branch (1821:15): [True: 0, False: 0]
  |  Branch (1821:20): [True: 0, False: 0]
  ------------------
 1822|      0|            trace(*t, "test timelimit -> fail, the compound search stops here and gives up");
 1823|      0|          timelimit_exceeded = true;
 1824|      0|          return nullptr;
 1825|      0|        }
 1826|       |
 1827|   532M|        if (scpd > 0) {
  ------------------
  |  Branch (1827:13): [True: 0, False: 532M]
  ------------------
 1828|      0|          for (; scpd <= checkcpdtable.size() &&
  ------------------
  |  Branch (1828:18): [True: 0, False: 0]
  ------------------
 1829|      0|                 (checkcpdtable[scpd - 1].pattern3.empty() ||
  ------------------
  |  Branch (1829:19): [True: 0, False: 0]
  ------------------
 1830|      0|                  i > word.size() ||
  ------------------
  |  Branch (1830:19): [True: 0, False: 0]
  ------------------
 1831|      0|                  word.compare(i, checkcpdtable[scpd - 1].pattern3.size(), checkcpdtable[scpd - 1].pattern3) != 0);
  ------------------
  |  Branch (1831:19): [True: 0, False: 0]
  ------------------
 1832|      0|               scpd++)
 1833|      0|            ;
 1834|       |
 1835|      0|          if (scpd > checkcpdtable.size())
  ------------------
  |  Branch (1835:15): [True: 0, False: 0]
  ------------------
 1836|      0|            break;  // break simplified checkcompoundpattern loop
 1837|      0|          st.replace(i, std::string::npos, checkcpdtable[scpd - 1].pattern);
 1838|      0|          soldi = i;
 1839|      0|          i += checkcpdtable[scpd - 1].pattern.size();
 1840|      0|          st.replace(i, std::string::npos, checkcpdtable[scpd - 1].pattern2);
 1841|      0|          st.replace(i + checkcpdtable[scpd - 1].pattern2.size(), std::string::npos,
 1842|      0|                 word.substr(soldi + checkcpdtable[scpd - 1].pattern3.size()));
 1843|       |
 1844|      0|          oldlen = len;
 1845|      0|          len += checkcpdtable[scpd - 1].pattern.size() +
 1846|      0|                 checkcpdtable[scpd - 1].pattern2.size() -
 1847|      0|                 checkcpdtable[scpd - 1].pattern3.size();
 1848|      0|          oldcmin = cmin;
 1849|      0|          oldcmax = cmax;
 1850|      0|          setcminmax(&cmin, &cmax, st.c_str(), len);
 1851|       |
 1852|      0|          cmax = len - cpdmin + 1;
 1853|      0|        }
 1854|       |
 1855|   532M|        if (i >= st.size())
  ------------------
  |  Branch (1855:13): [True: 1.30M, False: 531M]
  ------------------
 1856|  1.30M|          return nullptr;
 1857|       |
 1858|   531M|        ch = st[i];
 1859|   531M|        if (t) {
  ------------------
  |  Branch (1859:13): [True: 0, False: 531M]
  ------------------
 1860|       |          // a non-zero scpd means this split is the retry that one CHECKCOMPOUNDPATTERN entry asks
 1861|       |          // for, with the text at the join replaced by the two sides of that entry
 1862|      0|          if (scpd != 0)
  ------------------
  |  Branch (1862:15): [True: 0, False: 0]
  ------------------
 1863|      0|            trace(*t, "split at=%d left=\"%s\" right=\"%s\" cpdpattern=%d", (int)i,
 1864|      0|                  st.substr(0, i).c_str(), st.substr(i).c_str(), (int)scpd);
 1865|      0|          else
 1866|      0|            trace(*t, "split at=%d left=\"%s\" right=\"%s\"", (int)i,
 1867|      0|                  st.substr(0, i).c_str(), st.substr(i).c_str());
 1868|      0|        }
 1869|       |        // everything this split point tries belongs to the split
 1870|   531M|        TraceScope split_depth(t);
 1871|   531M|        st[i] = '\0';
 1872|       |
 1873|   531M|        sfx = nullptr;
 1874|   531M|        pfx = nullptr;
 1875|       |
 1876|       |        // FIRST WORD
 1877|       |
 1878|   531M|        affixed = 1;
 1879|   531M|        rv = lookup(st.c_str(), i);  // perhaps without prefix
 1880|   531M|        if (t) {
  ------------------
  |  Branch (1880:13): [True: 0, False: 531M]
  ------------------
 1881|      0|          if (rv)
  ------------------
  |  Branch (1881:15): [True: 0, False: 0]
  ------------------
 1882|      0|            trace(*t, "first \"%s\" -> entry \"%s\" flags=%s", st.c_str(),
 1883|      0|                  rv->word, trace_flags(this, rv->astr, rv->alen).c_str());
 1884|      0|          else
 1885|      0|            trace(*t, "first \"%s\" -> miss", st.c_str());
 1886|      0|        }
 1887|       |
 1888|       |        // forbid dictionary stems with COMPOUNDFORBIDFLAG in
 1889|       |        // compound words, overriding the effect of COMPOUNDPERMITFLAG
 1890|   531M|        if ((rv) && compoundforbidflag &&
  ------------------
  |  Branch (1890:13): [True: 3.30M, False: 527M]
  |  Branch (1890:21): [True: 58.0k, False: 3.24M]
  ------------------
 1891|  58.0k|                TESTAFF(rv->astr, compoundforbidflag, rv->alen) && !hu_mov_rule) {
  ------------------
  |  |  102|   531M|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 58.0k]
  |  |  ------------------
  ------------------
  |  Branch (1891:68): [True: 0, False: 0]
  ------------------
 1892|      0|            bool would_continue = !onlycpdrule && simplifiedcpd;
  ------------------
  |  Branch (1892:35): [True: 0, False: 0]
  |  Branch (1892:51): [True: 0, False: 0]
  ------------------
 1893|      0|            if (!scpd && would_continue) {
  ------------------
  |  Branch (1893:17): [True: 0, False: 0]
  |  Branch (1893:26): [True: 0, False: 0]
  ------------------
 1894|       |                // given the while conditions that continue jumps to, this situation
 1895|       |                // never ends
 1896|      0|                HUNSPELL_WARNING(stderr, "break infinite loop\n");
 1897|      0|                break;
 1898|      0|            }
 1899|       |
 1900|      0|            if (scpd > 0 && would_continue) {
  ------------------
  |  Branch (1900:17): [True: 0, False: 0]
  |  Branch (1900:29): [True: 0, False: 0]
  ------------------
 1901|       |                // undo this pattern's rewrite and move to the next pattern, as the end of the loop
 1902|       |                // does
 1903|      0|                i = soldi;
 1904|      0|                len = oldlen;
 1905|      0|                cmin = oldcmin;
 1906|      0|                cmax = oldcmax;
 1907|      0|                scpd++;
 1908|      0|            }
 1909|      0|            continue;
 1910|      0|        }
 1911|       |
 1912|       |        // search homonym with compound flag
 1913|   534M|        while ((rv) && !hu_mov_rule &&
  ------------------
  |  Branch (1913:16): [True: 3.30M, False: 531M]
  |  Branch (1913:24): [True: 3.30M, False: 337]
  ------------------
 1914|  3.30M|               ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
  ------------------
  |  |  102|  1.08M|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 32, False: 1.08M]
  |  |  ------------------
  ------------------
  |  Branch (1914:18): [True: 1.08M, False: 2.22M]
  ------------------
 1915|  3.30M|                !((compoundflag && !words && !onlycpdrule &&
  ------------------
  |  Branch (1915:20): [True: 3.30M, False: 0]
  |  Branch (1915:36): [True: 3.30M, False: 0]
  |  Branch (1915:46): [True: 3.30M, False: 0]
  ------------------
 1916|  3.30M|                   TESTAFF(rv->astr, compoundflag, rv->alen)) ||
  ------------------
  |  |  102|  3.30M|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 268, False: 3.30M]
  |  |  ------------------
  ------------------
 1917|  3.30M|                  (compoundbegin && !wordnum && !onlycpdrule &&
  ------------------
  |  Branch (1917:20): [True: 0, False: 3.30M]
  |  Branch (1917:37): [True: 0, False: 0]
  |  Branch (1917:49): [True: 0, False: 0]
  ------------------
 1918|      0|                   TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1919|  3.30M|                  (compoundmiddle && wordnum && !words && !onlycpdrule &&
  ------------------
  |  Branch (1919:20): [True: 0, False: 3.30M]
  |  Branch (1919:38): [True: 0, False: 0]
  |  Branch (1919:49): [True: 0, False: 0]
  |  Branch (1919:59): [True: 0, False: 0]
  ------------------
 1920|      0|                   TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1921|  3.30M|                  (!defcpdtable.empty() && onlycpdrule &&
  ------------------
  |  Branch (1921:20): [True: 0, False: 3.30M]
  |  Branch (1921:44): [True: 0, False: 0]
  ------------------
 1922|      0|                   ((!words && !wordnum &&
  ------------------
  |  Branch (1922:22): [True: 0, False: 0]
  |  Branch (1922:32): [True: 0, False: 0]
  ------------------
 1923|      0|                     defcpd_check(&words, wnum, maxwordnum, rv, rwords, 0)) ||
  ------------------
  |  Branch (1923:22): [True: 0, False: 0]
  ------------------
 1924|      0|                    (words &&
  ------------------
  |  Branch (1924:22): [True: 0, False: 0]
  ------------------
 1925|      0|                     defcpd_check(&words, wnum, maxwordnum, rv, rwords, 0))))) ||
  ------------------
  |  Branch (1925:22): [True: 0, False: 0]
  ------------------
 1926|    268|                (scpd != 0 && checkcpdtable[scpd - 1].cond != FLAG_NULL &&
  ------------------
  |  |   99|    268|#define FLAG_NULL 0x00
  ------------------
  |  Branch (1926:18): [True: 0, False: 268]
  |  Branch (1926:31): [True: 0, False: 0]
  ------------------
 1927|  3.30M|                 !TESTAFF(rv->astr, checkcpdtable[scpd - 1].cond, rv->alen)))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (1927:18): [True: 0, False: 0]
  ------------------
 1928|  3.30M|          rv = rv->next_homonym;
 1929|  3.30M|        }
 1930|       |
 1931|   531M|        if (rv)
  ------------------
  |  Branch (1931:13): [True: 605, False: 531M]
  ------------------
 1932|    605|          affixed = 0;
 1933|       |
 1934|   531M|        if (!rv) {
  ------------------
  |  Branch (1934:13): [True: 531M, False: 605]
  ------------------
 1935|   531M|          if (onlycpdrule)
  ------------------
  |  Branch (1935:15): [True: 0, False: 531M]
  ------------------
 1936|      0|            break;
 1937|   531M|          if (compoundflag &&
  ------------------
  |  Branch (1937:15): [True: 531M, False: 0]
  ------------------
 1938|   531M|              !(rv = prefix_check(st, 0, i,
  ------------------
  |  Branch (1938:15): [True: 531M, False: 0]
  ------------------
 1939|   531M|                                  hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
  ------------------
  |  |   78|   151k|#define IN_CPD_OTHER 3
  ------------------
                                                hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
  ------------------
  |  |   76|  1.06G|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (1939:35): [True: 151k, False: 531M]
  ------------------
 1940|   531M|                                  scratch, compoundflag))) {
 1941|   531M|            if (((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   99|   531M|#define FLAG_NULL 0x00
  ------------------
                          if (((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   78|   151k|#define IN_CPD_OTHER 3
  ------------------
                          if (((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   76|  1.06G|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (1941:18): [True: 0, False: 531M]
  |  Branch (1941:93): [True: 151k, False: 531M]
  ------------------
 1942|   531M|                 (compoundmoresuffixes && (rv = suffix_check_twosfx(st, 0, i, 0, nullptr, scratch, compoundflag)))) &&
  ------------------
  |  Branch (1942:19): [True: 0, False: 531M]
  |  Branch (1942:43): [True: 0, False: 0]
  ------------------
 1943|      0|                !hu_mov_rule && sfx->getCont() &&
  ------------------
  |  Branch (1943:17): [True: 0, False: 0]
  |  Branch (1943:33): [True: 0, False: 0]
  ------------------
 1944|      0|                ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, sfx->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (1944:19): [True: 0, False: 0]
  ------------------
 1945|      0|                 (compoundend && TESTAFF(sfx->getCont(), compoundend, sfx->getContLen())))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (1945:19): [True: 0, False: 0]
  ------------------
 1946|      0|              rv = nullptr;
 1947|       |              // the suffix is dropped with the word it built
 1948|      0|              sfx = nullptr;
 1949|      0|            }
 1950|   531M|          }
 1951|       |
 1952|   531M|          if (rv ||
  ------------------
  |  Branch (1952:15): [True: 0, False: 531M]
  ------------------
 1953|   531M|              (((wordnum == 0) && compoundbegin &&
  ------------------
  |  Branch (1953:17): [True: 531M, False: 154k]
  |  Branch (1953:35): [True: 0, False: 531M]
  ------------------
 1954|      0|                ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
                              ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                              ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   76|      0|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (1954:18): [True: 0, False: 0]
  |  Branch (1954:94): [True: 0, False: 0]
  ------------------
 1955|      0|                 (compoundmoresuffixes && (rv = suffix_check_twosfx(st, 0, i, 0, nullptr, scratch,
  ------------------
  |  Branch (1955:19): [True: 0, False: 0]
  |  Branch (1955:43): [True: 0, False: 0]
  ------------------
 1956|      0|                                                                    compoundbegin))) ||  // twofold suffixes + compound
 1957|      0|                 (rv = prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, scratch, compoundbegin)))) ||
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                               (rv = prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, scratch, compoundbegin)))) ||
  ------------------
  |  |   76|      0|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (1957:18): [True: 0, False: 0]
  |  Branch (1957:47): [True: 0, False: 0]
  ------------------
 1958|   531M|               ((wordnum > 0) && compoundmiddle &&
  ------------------
  |  Branch (1958:17): [True: 2.23k, False: 531M]
  |  Branch (1958:34): [True: 0, False: 2.23k]
  ------------------
 1959|      0|                ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
                              ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                              ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   76|      0|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (1959:18): [True: 0, False: 0]
  |  Branch (1959:95): [True: 0, False: 0]
  ------------------
 1960|      0|                 (compoundmoresuffixes && (rv = suffix_check_twosfx(st, 0, i, 0, nullptr, scratch,
  ------------------
  |  Branch (1960:19): [True: 0, False: 0]
  |  Branch (1960:43): [True: 0, False: 0]
  ------------------
 1961|      0|                                                                    compoundmiddle))) ||  // twofold suffixes + compound
 1962|      0|                 (rv = prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, scratch, compoundmiddle))))))
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                               (rv = prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, scratch, compoundmiddle))))))
  ------------------
  |  |   76|      0|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (1962:18): [True: 0, False: 0]
  |  Branch (1962:47): [True: 0, False: 0]
  ------------------
 1963|      0|            checked_prefix = 1;
 1964|       |          // else check forbiddenwords and needaffix
 1965|   531M|        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
  ------------------
  |  |  102|    638|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 319]
  |  |  ------------------
  ------------------
  |  Branch (1965:20): [True: 319, False: 286]
  |  Branch (1965:20): [True: 0, False: 605]
  ------------------
 1966|    319|                                TESTAFF(rv->astr, needaffix, rv->alen) ||
  ------------------
  |  |  102|    638|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 319]
  |  |  ------------------
  ------------------
 1967|    319|                                TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
  ------------------
  |  |  102|    638|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 319]
  |  |  ------------------
  ------------------
 1968|    319|                                (is_sug && nosuggest &&
  ------------------
  |  Branch (1968:34): [True: 38, False: 281]
  |  Branch (1968:44): [True: 0, False: 38]
  ------------------
 1969|      0|                                 TESTAFF(rv->astr, nosuggest, rv->alen)))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1970|      0|          st[i] = ch;
 1971|       |          // continue;
 1972|      0|          break;
 1973|      0|        }
 1974|       |
 1975|       |        // check non_compound flag in suffix and prefix
 1976|   531M|        if ((rv) && !hu_mov_rule &&
  ------------------
  |  Branch (1976:13): [True: 605, False: 531M]
  |  Branch (1976:21): [True: 268, False: 337]
  ------------------
 1977|    268|            ((pfx && pfx->getCont() &&
  ------------------
  |  Branch (1977:15): [True: 0, False: 268]
  |  Branch (1977:22): [True: 0, False: 0]
  ------------------
 1978|      0|              TESTAFF(pfx->getCont(), compoundforbidflag, pfx->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1979|    268|             (sfx && sfx->getCont() &&
  ------------------
  |  Branch (1979:15): [True: 0, False: 268]
  |  Branch (1979:22): [True: 0, False: 0]
  ------------------
 1980|      0|              TESTAFF(sfx->getCont(), compoundforbidflag,
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1981|    268|                      sfx->getContLen())))) {
 1982|      0|          rv = nullptr;
 1983|      0|        }
 1984|       |
 1985|       |        // check compoundend flag in suffix and prefix
 1986|   531M|        if ((rv) && !checked_prefix && compoundend && !hu_mov_rule &&
  ------------------
  |  Branch (1986:13): [True: 605, False: 531M]
  |  Branch (1986:21): [True: 605, False: 0]
  |  Branch (1986:40): [True: 0, False: 605]
  |  Branch (1986:55): [True: 0, False: 0]
  ------------------
 1987|      0|            ((pfx && pfx->getCont() &&
  ------------------
  |  Branch (1987:15): [True: 0, False: 0]
  |  Branch (1987:22): [True: 0, False: 0]
  ------------------
 1988|      0|              TESTAFF(pfx->getCont(), compoundend, pfx->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1989|      0|             (sfx && sfx->getCont() &&
  ------------------
  |  Branch (1989:15): [True: 0, False: 0]
  |  Branch (1989:22): [True: 0, False: 0]
  ------------------
 1990|      0|              TESTAFF(sfx->getCont(), compoundend, sfx->getContLen())))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1991|      0|          rv = nullptr;
 1992|      0|        }
 1993|       |
 1994|       |        // check compoundmiddle flag in suffix and prefix
 1995|   531M|        if ((rv) && !checked_prefix && (wordnum == 0) && compoundmiddle &&
  ------------------
  |  Branch (1995:13): [True: 605, False: 531M]
  |  Branch (1995:21): [True: 605, False: 0]
  |  Branch (1995:40): [True: 268, False: 337]
  |  Branch (1995:58): [True: 0, False: 268]
  ------------------
 1996|      0|            !hu_mov_rule &&
  ------------------
  |  Branch (1996:13): [True: 0, False: 0]
  ------------------
 1997|      0|            ((pfx && pfx->getCont() &&
  ------------------
  |  Branch (1997:15): [True: 0, False: 0]
  |  Branch (1997:22): [True: 0, False: 0]
  ------------------
 1998|      0|              TESTAFF(pfx->getCont(), compoundmiddle, pfx->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1999|      0|             (sfx && sfx->getCont() &&
  ------------------
  |  Branch (1999:15): [True: 0, False: 0]
  |  Branch (1999:22): [True: 0, False: 0]
  ------------------
 2000|      0|              TESTAFF(sfx->getCont(), compoundmiddle, sfx->getContLen())))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2001|      0|          rv = nullptr;
 2002|      0|        }
 2003|       |
 2004|       |        // check forbiddenwords
 2005|   531M|        if ((rv) && (rv->astr) &&
  ------------------
  |  Branch (2005:13): [True: 605, False: 531M]
  |  Branch (2005:13): [True: 0, False: 531M]
  |  Branch (2005:21): [True: 319, False: 286]
  ------------------
 2006|    319|            (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
  ------------------
  |  |  102|    638|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 319]
  |  |  ------------------
  ------------------
 2007|    319|             TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
  ------------------
  |  |  102|    638|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 319]
  |  |  ------------------
  ------------------
 2008|    319|             (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2008:15): [True: 38, False: 281]
  |  Branch (2008:25): [True: 0, False: 38]
  ------------------
 2009|      0|          return nullptr;
 2010|      0|        }
 2011|       |
 2012|       |        // increment word number, if the second root has a compoundroot flag
 2013|   531M|        if ((rv) && compoundroot &&
  ------------------
  |  Branch (2013:13): [True: 605, False: 531M]
  |  Branch (2013:21): [True: 0, False: 605]
  ------------------
 2014|      0|            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2014:13): [True: 0, False: 0]
  ------------------
 2015|      0|          wordnum++;
 2016|      0|        }
 2017|       |
 2018|       |        // first word is acceptable in compound words?
 2019|   531M|        if (((rv) &&
  ------------------
  |  Branch (2019:13): [True: 316, False: 531M]
  |  Branch (2019:14): [True: 605, False: 531M]
  ------------------
 2020|    605|             (checked_prefix || (words && words[wnum]) ||
  ------------------
  |  Branch (2020:15): [True: 0, False: 605]
  |  Branch (2020:34): [True: 0, False: 605]
  |  Branch (2020:43): [True: 0, False: 0]
  ------------------
 2021|    605|              (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
  ------------------
  |  |  102|    605|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 316, False: 289]
  |  |  ------------------
  ------------------
  |  Branch (2021:16): [True: 605, False: 0]
  ------------------
 2022|    289|              ((oldwordnum == 0) && compoundbegin &&
  ------------------
  |  Branch (2022:16): [True: 0, False: 289]
  |  Branch (2022:37): [True: 0, False: 0]
  ------------------
 2023|      0|               TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2024|    289|              ((oldwordnum > 0) && compoundmiddle &&
  ------------------
  |  Branch (2024:16): [True: 0, False: 289]
  |  Branch (2024:36): [True: 0, False: 0]
  ------------------
 2025|      0|               TESTAFF(rv->astr, compoundmiddle, rv->alen))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2026|       |
 2027|       |              // LANG_hu section: spec. Hungarian rule
 2028|    289|              || ((langnum == LANG_hu) && hu_mov_rule &&
  ------------------
  |  Branch (2028:19): [True: 289, False: 0]
  |  Branch (2028:43): [True: 289, False: 0]
  ------------------
 2029|    289|                  (TESTAFF(
  ------------------
  |  |  102|    578|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 289]
  |  |  ------------------
  ------------------
 2030|    289|                       rv->astr, 'F',
 2031|    289|                       rv->alen) ||  // XXX hardwired Hungarian dictionary codes
 2032|    289|                   TESTAFF(rv->astr, 'G', rv->alen) ||
  ------------------
  |  |  102|    578|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 289]
  |  |  ------------------
  ------------------
 2033|    289|                   TESTAFF(rv->astr, 'H', rv->alen)))
  ------------------
  |  |  102|    289|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 289]
  |  |  ------------------
  ------------------
 2034|       |              // END of LANG_hu section
 2035|    605|              ) &&
 2036|    316|             (
 2037|       |                 // test CHECKCOMPOUNDPATTERN conditions
 2038|    316|                 scpd == 0 || checkcpdtable[scpd - 1].cond == FLAG_NULL ||
  ------------------
  |  |   99|    316|#define FLAG_NULL 0x00
  ------------------
  |  Branch (2038:18): [True: 316, False: 0]
  |  Branch (2038:31): [True: 0, False: 0]
  ------------------
 2039|      0|                 join_side_has_flag(rv, checkcpdtable[scpd - 1].cond, pfx, sfx)) &&
  ------------------
  |  Branch (2039:18): [True: 0, False: 0]
  ------------------
 2040|    316|             !((checkcompoundtriple && scpd == 0 &&
  ------------------
  |  Branch (2040:17): [True: 0, False: 316]
  |  Branch (2040:40): [True: 0, False: 0]
  ------------------
 2041|      0|                !words && i < word.size() && // test triple letters
  ------------------
  |  Branch (2041:17): [True: 0, False: 0]
  |  Branch (2041:27): [True: 0, False: 0]
  ------------------
 2042|      0|                (word[i - 1] == word[i]) &&
  ------------------
  |  Branch (2042:17): [True: 0, False: 0]
  ------------------
 2043|      0|                (((i > 1) && (word[i - 1] == word[i - 2])) ||
  ------------------
  |  Branch (2043:19): [True: 0, False: 0]
  |  Branch (2043:30): [True: 0, False: 0]
  ------------------
 2044|      0|                 ((word[i - 1] == word[i + 1]))  // may be word[i+1] == '\0'
  ------------------
  |  Branch (2044:18): [True: 0, False: 0]
  ------------------
 2045|      0|                 )) ||
 2046|    316|               (checkcompoundcase && scpd == 0 && !words && i < word.size() &&
  ------------------
  |  Branch (2046:17): [True: 0, False: 316]
  |  Branch (2046:38): [True: 0, False: 0]
  |  Branch (2046:51): [True: 0, False: 0]
  |  Branch (2046:61): [True: 0, False: 0]
  ------------------
 2047|      0|                cpdcase_check(word, i))))
  ------------------
  |  Branch (2047:17): [True: 0, False: 0]
  ------------------
 2048|       |            // LANG_hu section: spec. Hungarian rule
 2049|   531M|            || ((!rv) && (langnum == LANG_hu) && hu_mov_rule &&
  ------------------
  |  Branch (2049:17): [True: 531M, False: 289]
  |  Branch (2049:26): [True: 43.1M, False: 488M]
  |  Branch (2049:50): [True: 151k, False: 42.9M]
  ------------------
 2050|   151k|                (rv = affix_check(st, 0, i, scratch)) &&
  ------------------
  |  Branch (2050:17): [True: 0, False: 151k]
  ------------------
 2051|      0|                (sfx && sfx->getCont() &&
  ------------------
  |  Branch (2051:18): [True: 0, False: 0]
  |  Branch (2051:25): [True: 0, False: 0]
  ------------------
 2052|      0|                 (  // XXX hardwired Hungarian dic. codes
 2053|      0|                     TESTAFF(sfx->getCont(), (unsigned short)'x',
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2054|      0|                             sfx->getContLen()) ||
 2055|      0|                     TESTAFF(
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2056|      0|                         sfx->getCont(), (unsigned short)'%',
 2057|    316|                         sfx->getContLen()))))) {  // first word is ok condition
 2058|       |
 2059|       |          // LANG_hu section: spec. Hungarian rule
 2060|    316|          if (langnum == LANG_hu) {
  ------------------
  |  Branch (2060:15): [True: 282, False: 34]
  ------------------
 2061|       |            // calculate syllable number of the word
 2062|    282|            numsyllable += get_syllable(st.substr(0, i));
 2063|       |            // + 1 word, if syllable number of the prefix > 1 (hungarian
 2064|       |            // convention)
 2065|    282|            if (pfx && (get_syllable(pfx->getKey()) > 1))
  ------------------
  |  Branch (2065:17): [True: 0, False: 282]
  |  Branch (2065:17): [True: 0, False: 282]
  |  Branch (2065:24): [True: 0, False: 0]
  ------------------
 2066|      0|              wordnum++;
 2067|    282|          }
 2068|       |          // END of LANG_hu section
 2069|       |
 2070|       |          // NEXT WORD(S)
 2071|    316|          rv_first = rv;
 2072|       |          // the affixes that built the first word, so its continuation classes stay reachable once
 2073|       |          // the second word has overwritten pfx and sfx
 2074|    316|          PfxEntry* rv_first_pfx = pfx;
 2075|    316|          SfxEntry* rv_first_sfx = sfx;
 2076|    316|          st[i] = ch;
 2077|       |
 2078|    316|          do {  // striple loop
 2079|       |
 2080|       |            // check simplifiedtriple
 2081|    316|            if (simplifiedtriple) {
  ------------------
  |  Branch (2081:17): [True: 0, False: 316]
  ------------------
 2082|      0|              if (striple) {
  ------------------
  |  Branch (2082:19): [True: 0, False: 0]
  ------------------
 2083|      0|                checkedstriple = 1;
 2084|      0|                i--;  // check "fahrt" instead of "ahrt" in "Schiffahrt"
 2085|      0|              } else if (i > 2 && i <= word.size() && word[i - 1] == word[i - 2]) {
  ------------------
  |  Branch (2085:26): [True: 0, False: 0]
  |  Branch (2085:35): [True: 0, False: 0]
  |  Branch (2085:55): [True: 0, False: 0]
  ------------------
 2086|      0|                striple = 1;
 2087|       |                // past cmax the surface split is too short, so only the form with the letter
 2088|       |                // put back is tried
 2089|      0|                if (i >= cmax) {
  ------------------
  |  Branch (2089:21): [True: 0, False: 0]
  ------------------
 2090|      0|                  checkedstriple = 1;
 2091|      0|                  i--;
 2092|      0|                }
 2093|      0|              }
 2094|      0|            }
 2095|       |
 2096|    316|            rv = lookup(st.c_str() + i, st.size() - i);  // perhaps without prefix
 2097|    316|            if (t) {
  ------------------
  |  Branch (2097:17): [True: 0, False: 316]
  ------------------
 2098|      0|              if (rv)
  ------------------
  |  Branch (2098:19): [True: 0, False: 0]
  ------------------
 2099|      0|                trace(*t, "second \"%s\" -> entry \"%s\" flags=%s", st.c_str() + i,
 2100|      0|                      rv->word, trace_flags(this, rv->astr, rv->alen).c_str());
 2101|      0|              else
 2102|      0|                trace(*t, "second \"%s\" -> miss", st.c_str() + i);
 2103|      0|            }
 2104|       |
 2105|       |            // search homonym with compound flag
 2106|    316|            while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2106:20): [True: 0, False: 316]
  |  Branch (2106:30): [True: 0, False: 0]
  ------------------
 2107|      0|                            !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2107:32): [True: 0, False: 0]
  |  Branch (2107:48): [True: 0, False: 0]
  ------------------
 2108|      0|                              (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2108:32): [True: 0, False: 0]
  |  Branch (2108:47): [True: 0, False: 0]
  ------------------
 2109|      0|                              (!defcpdtable.empty() && words && defcpd_check(&words, wnum + 1, maxwordnum, rv, nullptr, 1))) ||
  ------------------
  |  Branch (2109:32): [True: 0, False: 0]
  |  Branch (2109:56): [True: 0, False: 0]
  |  Branch (2109:65): [True: 0, False: 0]
  ------------------
 2110|      0|                            (scpd != 0 && checkcpdtable[scpd - 1].cond2 != FLAG_NULL &&
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
  |  Branch (2110:30): [True: 0, False: 0]
  |  Branch (2110:43): [True: 0, False: 0]
  ------------------
 2111|      0|                             !TESTAFF(rv->astr, checkcpdtable[scpd - 1].cond2, rv->alen)))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2111:30): [True: 0, False: 0]
  ------------------
 2112|      0|              rv = rv->next_homonym;
 2113|      0|            }
 2114|       |
 2115|       |            // check FORCEUCASE
 2116|    316|            if (rv && forceucase &&
  ------------------
  |  Branch (2116:17): [True: 0, False: 316]
  |  Branch (2116:23): [True: 0, False: 0]
  ------------------
 2117|      0|                (TESTAFF(rv->astr, forceucase, rv->alen)) &&
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2117:17): [True: 0, False: 0]
  ------------------
 2118|      0|                !(info && *info & SPELL_ORIGCAP))
  ------------------
  |  |   86|      0|#define SPELL_ORIGCAP (1 << 5)
  ------------------
  |  Branch (2118:19): [True: 0, False: 0]
  |  Branch (2118:27): [True: 0, False: 0]
  ------------------
 2119|      0|              rv = nullptr;
 2120|       |
 2121|    316|            if (rv && words && words[wnum + 1])
  ------------------
  |  Branch (2121:17): [True: 0, False: 316]
  |  Branch (2121:23): [True: 0, False: 0]
  |  Branch (2121:32): [True: 0, False: 0]
  ------------------
 2122|      0|              return rv_first;
 2123|       |
 2124|    316|            oldnumsyllable2 = numsyllable;
 2125|    316|            oldwordnum2 = wordnum;
 2126|       |
 2127|       |            // LANG_hu section: spec. Hungarian rule, XXX hardwired dictionary
 2128|       |            // code
 2129|    316|            if ((rv) && (langnum == LANG_hu) &&
  ------------------
  |  Branch (2129:17): [True: 0, False: 316]
  |  Branch (2129:17): [True: 0, False: 316]
  |  Branch (2129:25): [True: 0, False: 0]
  ------------------
 2130|      0|                (TESTAFF(rv->astr, 'I', rv->alen)) &&
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2130:17): [True: 0, False: 0]
  ------------------
 2131|      0|                !(TESTAFF(rv->astr, 'J', rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2131:17): [True: 0, False: 0]
  ------------------
 2132|      0|              numsyllable--;
 2133|      0|            }
 2134|       |            // END of LANG_hu section
 2135|       |
 2136|       |            // increment word number, if the second root has a compoundroot flag
 2137|    316|            if ((rv) && (compoundroot) &&
  ------------------
  |  Branch (2137:17): [True: 0, False: 316]
  |  Branch (2137:25): [True: 0, False: 0]
  ------------------
 2138|      0|                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2138:17): [True: 0, False: 0]
  ------------------
 2139|      0|              wordnum++;
 2140|      0|            }
 2141|       |
 2142|       |            // check forbiddenwords
 2143|    316|            if ((rv) && (rv->astr) &&
  ------------------
  |  Branch (2143:17): [True: 0, False: 316]
  |  Branch (2143:17): [True: 0, False: 316]
  |  Branch (2143:25): [True: 0, False: 0]
  ------------------
 2144|      0|                (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2145|      0|                 TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2146|      0|                 (is_sug && nosuggest &&
  ------------------
  |  Branch (2146:19): [True: 0, False: 0]
  |  Branch (2146:29): [True: 0, False: 0]
  ------------------
 2147|      0|                  TESTAFF(rv->astr, nosuggest, rv->alen))))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2148|      0|              return nullptr;
 2149|       |
 2150|       |            // second word is acceptable, as a root?
 2151|       |            // hungarian conventions: compounding is acceptable,
 2152|       |            // when compound forms consist of 2 words, or if more,
 2153|       |            // then the syllable number of root words must be 6, or lesser.
 2154|       |
 2155|    316|            if ((rv) &&
  ------------------
  |  Branch (2155:17): [True: 0, False: 316]
  |  Branch (2155:17): [True: 0, False: 316]
  ------------------
 2156|      0|                ((compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2156:19): [True: 0, False: 0]
  ------------------
 2157|      0|                 (compoundend && TESTAFF(rv->astr, compoundend, rv->alen))) &&
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2157:19): [True: 0, False: 0]
  ------------------
 2158|      0|                (((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) ||
  ------------------
  |  Branch (2158:19): [True: 0, False: 0]
  |  Branch (2158:41): [True: 0, False: 0]
  ------------------
 2159|      0|                 ((cpdmaxsyllable != 0) &&
  ------------------
  |  Branch (2159:19): [True: 0, False: 0]
  ------------------
 2160|      0|                  (numsyllable + get_syllable(std::string(HENTRY_WORD(rv), rv->blen)) <=
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
  |  Branch (2160:19): [True: 0, False: 0]
  ------------------
 2161|      0|                   cpdmaxsyllable))) &&
 2162|      0|                (
 2163|       |                    // test CHECKCOMPOUNDPATTERN
 2164|      0|                    checkcpdtable.empty() || scpd != 0 ||
  ------------------
  |  Branch (2164:21): [True: 0, False: 0]
  |  Branch (2164:46): [True: 0, False: 0]
  ------------------
 2165|      0|                    (i < word.size() && !cpdpat_check(word, i, rv_first, rv, 0, t, rv_first_pfx, rv_first_sfx, nullptr, nullptr))) &&
  ------------------
  |  Branch (2165:22): [True: 0, False: 0]
  |  Branch (2165:41): [True: 0, False: 0]
  ------------------
 2166|      0|                ((!checkcompounddup || (rv != rv_first)))
  ------------------
  |  Branch (2166:19): [True: 0, False: 0]
  |  Branch (2166:40): [True: 0, False: 0]
  ------------------
 2167|       |                // test CHECKCOMPOUNDPATTERN conditions
 2168|      0|                &&
 2169|      0|                (scpd == 0 || checkcpdtable[scpd - 1].cond2 == FLAG_NULL ||
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
  |  Branch (2169:18): [True: 0, False: 0]
  |  Branch (2169:31): [True: 0, False: 0]
  ------------------
 2170|      0|                 TESTAFF(rv->astr, checkcpdtable[scpd - 1].cond2, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2171|       |              // forbid compound word, if it is a non-compound word with typical
 2172|       |              // fault
 2173|      0|              if ((checkcompoundrep && cpdrep_check(word, len, scratch, timelimit_exceeded, clock_time_start)) ||
  ------------------
  |  Branch (2173:20): [True: 0, False: 0]
  |  Branch (2173:40): [True: 0, False: 0]
  ------------------
 2174|      0|                  cpdwordpair_check(word, len, scratch, timelimit_exceeded, clock_time_start))
  ------------------
  |  Branch (2174:19): [True: 0, False: 0]
  ------------------
 2175|      0|                return nullptr;
 2176|      0|              return rv_first;
 2177|      0|            }
 2178|       |
 2179|    316|            numsyllable = oldnumsyllable2;
 2180|    316|            wordnum = oldwordnum2;
 2181|       |
 2182|       |            // perhaps second word has prefix or/and suffix
 2183|    316|            sfx = nullptr;
 2184|    316|            sfxflag = FLAG_NULL;
  ------------------
  |  |   99|    316|#define FLAG_NULL 0x00
  ------------------
 2185|       |            // the affixes that built the second word, kept because affix_check clears the members
 2186|    316|            PfxEntry* rv_second_pfx = nullptr;
 2187|    316|            SfxEntry* rv_second_sfx = nullptr;
 2188|    316|            rv = (compoundflag && !onlycpdrule && i < word.size()) ? affix_check(word, i, word.size() - i, scratch, compoundflag, IN_CPD_END, FLAG_NULL, &rv_second_pfx, &rv_second_sfx)
  ------------------
  |  |   77|    316|#define IN_CPD_END 2
  ------------------
                          rv = (compoundflag && !onlycpdrule && i < word.size()) ? affix_check(word, i, word.size() - i, scratch, compoundflag, IN_CPD_END, FLAG_NULL, &rv_second_pfx, &rv_second_sfx)
  ------------------
  |  |   99|    316|#define FLAG_NULL 0x00
  ------------------
  |  Branch (2188:19): [True: 316, False: 0]
  |  Branch (2188:35): [True: 316, False: 0]
  |  Branch (2188:51): [True: 316, False: 0]
  ------------------
 2189|    316|                                                                   : nullptr;
 2190|    316|            if (!rv && compoundend && !onlycpdrule) {
  ------------------
  |  Branch (2190:17): [True: 316, False: 0]
  |  Branch (2190:24): [True: 0, False: 316]
  |  Branch (2190:39): [True: 0, False: 0]
  ------------------
 2191|      0|              sfx = nullptr;
 2192|      0|              pfx = nullptr;
 2193|      0|              if (i < word.size())
  ------------------
  |  Branch (2193:19): [True: 0, False: 0]
  ------------------
 2194|      0|                rv = affix_check(word, i, word.size() - i, scratch, compoundend, IN_CPD_END, FLAG_NULL, &rv_second_pfx, &rv_second_sfx);
  ------------------
  |  |   77|      0|#define IN_CPD_END 2
  ------------------
                              rv = affix_check(word, i, word.size() - i, scratch, compoundend, IN_CPD_END, FLAG_NULL, &rv_second_pfx, &rv_second_sfx);
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
 2195|      0|            }
 2196|       |
 2197|    316|            if (!rv && !defcpdtable.empty() && words) {
  ------------------
  |  Branch (2197:17): [True: 316, False: 0]
  |  Branch (2197:24): [True: 0, False: 316]
  |  Branch (2197:48): [True: 0, False: 0]
  ------------------
 2198|      0|              if (i < word.size())
  ------------------
  |  Branch (2198:19): [True: 0, False: 0]
  ------------------
 2199|      0|                rv = affix_check(word, i, word.size() - i, scratch, 0, IN_CPD_END);
  ------------------
  |  |   77|      0|#define IN_CPD_END 2
  ------------------
 2200|      0|              if (rv && defcpd_check(&words, wnum + 1, maxwordnum, rv, nullptr, 1))
  ------------------
  |  Branch (2200:19): [True: 0, False: 0]
  |  Branch (2200:25): [True: 0, False: 0]
  ------------------
 2201|      0|                return rv_first;
 2202|      0|              rv = nullptr;
 2203|      0|            }
 2204|       |
 2205|       |            // test CHECKCOMPOUNDPATTERN conditions (allowed forms)
 2206|    316|            if (rv &&
  ------------------
  |  Branch (2206:17): [True: 0, False: 316]
  ------------------
 2207|      0|                !(scpd == 0 || checkcpdtable[scpd - 1].cond2 == FLAG_NULL ||
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
  |  Branch (2207:19): [True: 0, False: 0]
  |  Branch (2207:32): [True: 0, False: 0]
  ------------------
 2208|      0|                  join_side_has_flag(rv, checkcpdtable[scpd - 1].cond2, rv_second_pfx,
  ------------------
  |  Branch (2208:19): [True: 0, False: 0]
  ------------------
 2209|      0|                                     rv_second_sfx)))
 2210|      0|              rv = nullptr;
 2211|       |
 2212|       |            // test CHECKCOMPOUNDPATTERN conditions (forbidden compounds)
 2213|    316|            if (rv && !checkcpdtable.empty() && scpd == 0 &&
  ------------------
  |  Branch (2213:17): [True: 0, False: 316]
  |  Branch (2213:23): [True: 0, False: 0]
  |  Branch (2213:49): [True: 0, False: 0]
  ------------------
 2214|      0|                cpdpat_check(word, i, rv_first, rv, affixed, t, rv_first_pfx, rv_first_sfx, rv_second_pfx, rv_second_sfx))
  ------------------
  |  Branch (2214:17): [True: 0, False: 0]
  ------------------
 2215|      0|              rv = nullptr;
 2216|       |
 2217|       |            // check non_compound flag in suffix and prefix
 2218|    316|            if ((rv) && ((pfx && pfx->getCont() &&
  ------------------
  |  Branch (2218:17): [True: 0, False: 316]
  |  Branch (2218:27): [True: 0, False: 0]
  |  Branch (2218:34): [True: 0, False: 0]
  ------------------
 2219|      0|                          TESTAFF(pfx->getCont(), compoundforbidflag,
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2220|      0|                                  pfx->getContLen())) ||
 2221|      0|                         (sfx && sfx->getCont() &&
  ------------------
  |  Branch (2221:27): [True: 0, False: 0]
  |  Branch (2221:34): [True: 0, False: 0]
  ------------------
 2222|      0|                          TESTAFF(sfx->getCont(), compoundforbidflag,
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2223|      0|                                  sfx->getContLen())))) {
 2224|      0|              rv = nullptr;
 2225|      0|            }
 2226|       |
 2227|       |            // check FORCEUCASE
 2228|    316|            if (rv && forceucase &&
  ------------------
  |  Branch (2228:17): [True: 0, False: 316]
  |  Branch (2228:23): [True: 0, False: 0]
  ------------------
 2229|      0|                (TESTAFF(rv->astr, forceucase, rv->alen)) &&
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2229:17): [True: 0, False: 0]
  ------------------
 2230|      0|                !(info && *info & SPELL_ORIGCAP))
  ------------------
  |  |   86|      0|#define SPELL_ORIGCAP (1 << 5)
  ------------------
  |  Branch (2230:19): [True: 0, False: 0]
  |  Branch (2230:27): [True: 0, False: 0]
  ------------------
 2231|      0|              rv = nullptr;
 2232|       |
 2233|       |            // check forbiddenwords
 2234|    316|            if ((rv) && (rv->astr) &&
  ------------------
  |  Branch (2234:17): [True: 0, False: 316]
  |  Branch (2234:17): [True: 0, False: 316]
  |  Branch (2234:25): [True: 0, False: 0]
  ------------------
 2235|      0|                (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2236|      0|                 TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2237|      0|                 (is_sug && nosuggest &&
  ------------------
  |  Branch (2237:19): [True: 0, False: 0]
  |  Branch (2237:29): [True: 0, False: 0]
  ------------------
 2238|      0|                  TESTAFF(rv->astr, nosuggest, rv->alen))))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2239|      0|              return nullptr;
 2240|       |
 2241|       |            // pfxappnd = prefix of word+i, or NULL
 2242|       |            // calculate syllable number of prefix.
 2243|       |            // hungarian convention: when syllable number of prefix is more,
 2244|       |            // than 1, the prefix+word counts as two words.
 2245|       |
 2246|    316|            if (langnum == LANG_hu) {
  ------------------
  |  Branch (2246:17): [True: 282, False: 34]
  ------------------
 2247|    282|              if (i < word.size()) {
  ------------------
  |  Branch (2247:19): [True: 282, False: 0]
  ------------------
 2248|       |                // calculate syllable number of the word
 2249|    282|                numsyllable += get_syllable(word.substr(i));
 2250|    282|              }
 2251|       |
 2252|       |              // - affix syllable num.
 2253|       |              // XXX only second suffix (inflections, not derivations)
 2254|    282|              if (sfxappnd) {
  ------------------
  |  Branch (2254:19): [True: 0, False: 282]
  ------------------
 2255|      0|                std::string tmp(sfxappnd);
 2256|      0|                reverseword(tmp);
 2257|      0|                numsyllable -= short(get_syllable(tmp) + sfxextra);
 2258|    282|              } else {
 2259|    282|                numsyllable -= short(sfxextra);
 2260|    282|              }
 2261|       |
 2262|       |              // + 1 word, if syllable number of the prefix > 1 (hungarian
 2263|       |              // convention)
 2264|    282|              if (pfx && (get_syllable(pfx->getKey()) > 1))
  ------------------
  |  Branch (2264:19): [True: 0, False: 282]
  |  Branch (2264:19): [True: 0, False: 282]
  |  Branch (2264:26): [True: 0, False: 0]
  ------------------
 2265|      0|                wordnum++;
 2266|       |
 2267|       |              // increment syllable num, if last word has a SYLLABLENUM flag
 2268|       |              // and the suffix is beginning `s'
 2269|       |
 2270|    282|              if (!cpdsyllablenum.empty()) {
  ------------------
  |  Branch (2270:19): [True: 0, False: 282]
  ------------------
 2271|      0|                switch (sfxflag) {
  ------------------
  |  Branch (2271:25): [True: 0, False: 0]
  ------------------
 2272|      0|                  case 'c': {
  ------------------
  |  Branch (2272:19): [True: 0, False: 0]
  ------------------
 2273|      0|                    numsyllable += 2;
 2274|      0|                    break;
 2275|      0|                  }
 2276|      0|                  case 'J': {
  ------------------
  |  Branch (2276:19): [True: 0, False: 0]
  ------------------
 2277|      0|                    numsyllable += 1;
 2278|      0|                    break;
 2279|      0|                  }
 2280|      0|                  case 'I': {
  ------------------
  |  Branch (2280:19): [True: 0, False: 0]
  ------------------
 2281|      0|                    if (rv && TESTAFF(rv->astr, 'J', rv->alen))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2281:25): [True: 0, False: 0]
  |  Branch (2281:25): [True: 0, False: 0]
  ------------------
 2282|      0|                      numsyllable += 1;
 2283|      0|                    break;
 2284|      0|                  }
 2285|      0|                }
 2286|      0|              }
 2287|    282|            }
 2288|       |
 2289|       |            // increment word number, if the second word has a compoundroot flag
 2290|    316|            if ((rv) && (compoundroot) &&
  ------------------
  |  Branch (2290:17): [True: 0, False: 316]
  |  Branch (2290:25): [True: 0, False: 0]
  ------------------
 2291|      0|                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2291:17): [True: 0, False: 0]
  ------------------
 2292|      0|              wordnum++;
 2293|      0|            }
 2294|       |            // second word is acceptable, as a word with prefix or/and suffix?
 2295|       |            // hungarian conventions: compounding is acceptable,
 2296|       |            // when compound forms consist 2 word, otherwise
 2297|       |            // the syllable number of root words is 6, or lesser.
 2298|    316|            if ((rv) &&
  ------------------
  |  Branch (2298:17): [True: 0, False: 316]
  ------------------
 2299|      0|                (((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) ||
  ------------------
  |  Branch (2299:19): [True: 0, False: 0]
  |  Branch (2299:41): [True: 0, False: 0]
  ------------------
 2300|      0|                 ((cpdmaxsyllable != 0) && (numsyllable <= cpdmaxsyllable))) &&
  ------------------
  |  Branch (2300:19): [True: 0, False: 0]
  |  Branch (2300:44): [True: 0, False: 0]
  ------------------
 2301|      0|                ((!checkcompounddup || (rv != rv_first)))) {
  ------------------
  |  Branch (2301:19): [True: 0, False: 0]
  |  Branch (2301:40): [True: 0, False: 0]
  ------------------
 2302|       |              // forbid compound word, if it is a non-compound word with typical
 2303|       |              // fault
 2304|      0|              if ((checkcompoundrep && cpdrep_check(word, len, scratch, timelimit_exceeded, clock_time_start)) ||
  ------------------
  |  Branch (2304:20): [True: 0, False: 0]
  |  Branch (2304:40): [True: 0, False: 0]
  ------------------
 2305|      0|                  cpdwordpair_check(word, len, scratch, timelimit_exceeded, clock_time_start))
  ------------------
  |  Branch (2305:19): [True: 0, False: 0]
  ------------------
 2306|      0|                return nullptr;
 2307|      0|              return rv_first;
 2308|      0|            }
 2309|       |
 2310|    316|            numsyllable = oldnumsyllable2;
 2311|    316|            wordnum = oldwordnum2;
 2312|       |
 2313|       |            // perhaps second word is a compound word (recursive call)
 2314|       |            // (only if SPELL_COMPOUND_2 is not set and maxwordnum is not exceeded)
 2315|    316|            if ((!info || !(*info & SPELL_COMPOUND_2)) && wordnum + 2 < maxwordnum && wnum + 1 < maxwordnum) {
  ------------------
  |  |   88|    316|#define SPELL_COMPOUND_2 (1 << 7)  // permit only 2 dictionary words in the compound
  ------------------
  |  Branch (2315:18): [True: 0, False: 316]
  |  Branch (2315:27): [True: 182, False: 134]
  |  Branch (2315:59): [True: 182, False: 0]
  |  Branch (2315:87): [True: 182, False: 0]
  ------------------
 2316|    182|              rv = compound_check(st.substr(i), wordnum + 1,
 2317|    182|                                  numsyllable, maxwordnum, wnum + 1, words, rwords, 0,
 2318|    182|                                  is_sug, info, scratch);
 2319|       |
 2320|    182|              if (rv && !checkcpdtable.empty() && i < word.size() &&
  ------------------
  |  Branch (2320:19): [True: 0, False: 182]
  |  Branch (2320:25): [True: 0, False: 0]
  |  Branch (2320:51): [True: 0, False: 0]
  ------------------
 2321|      0|                  ((scpd == 0 &&
  ------------------
  |  Branch (2321:21): [True: 0, False: 0]
  ------------------
 2322|      0|                    cpdpat_check(word, i, rv_first, rv, affixed, t, rv_first_pfx, rv_first_sfx, nullptr, nullptr)) ||
  ------------------
  |  Branch (2322:21): [True: 0, False: 0]
  ------------------
 2323|      0|                   (scpd != 0 &&
  ------------------
  |  Branch (2323:21): [True: 0, False: 0]
  ------------------
 2324|      0|                    !cpdpat_check(word, i, rv_first, rv, affixed, t, rv_first_pfx, rv_first_sfx, nullptr, nullptr))))
  ------------------
  |  Branch (2324:21): [True: 0, False: 0]
  ------------------
 2325|      0|                rv = nullptr;
 2326|    182|            } else {
 2327|    134|              rv = nullptr;
 2328|    134|            }
 2329|    316|            if (rv) {
  ------------------
  |  Branch (2329:17): [True: 0, False: 316]
  ------------------
 2330|       |              // forbid compound word, if it is a non-compound word with typical
 2331|       |              // fault, or a dictionary word pair
 2332|       |
 2333|      0|              if (cpdwordpair_check(word, len, scratch, timelimit_exceeded, clock_time_start))
  ------------------
  |  Branch (2333:19): [True: 0, False: 0]
  ------------------
 2334|      0|                return nullptr;
 2335|       |
 2336|      0|              if (checkcompoundrep || forbiddenword) {
  ------------------
  |  Branch (2336:19): [True: 0, False: 0]
  |  Branch (2336:39): [True: 0, False: 0]
  ------------------
 2337|      0|                if (checkcompoundrep && cpdrep_check(word, len, scratch, timelimit_exceeded, clock_time_start))
  ------------------
  |  Branch (2337:21): [True: 0, False: 0]
  |  Branch (2337:41): [True: 0, False: 0]
  ------------------
 2338|      0|                  return nullptr;
 2339|       |
 2340|       |                // check first part
 2341|      0|                if (i < word.size() && word.compare(i, rv->blen, rv->word, rv->blen) == 0) {
  ------------------
  |  Branch (2341:21): [True: 0, False: 0]
  |  Branch (2341:40): [True: 0, False: 0]
  ------------------
 2342|      0|                  char r = st[i + rv->blen];
 2343|      0|                  st[i + rv->blen] = '\0';
 2344|       |
 2345|      0|                  if ((checkcompoundrep && cpdrep_check(st, i + rv->blen, scratch, timelimit_exceeded, clock_time_start)) ||
  ------------------
  |  Branch (2345:24): [True: 0, False: 0]
  |  Branch (2345:44): [True: 0, False: 0]
  ------------------
 2346|      0|                      cpdwordpair_check(st, i + rv->blen, scratch, timelimit_exceeded, clock_time_start)) {
  ------------------
  |  Branch (2346:23): [True: 0, False: 0]
  ------------------
 2347|      0|                    st[ + i + rv->blen] = r;
 2348|      0|                    continue;
 2349|      0|                  }
 2350|       |
 2351|      0|                  if (forbiddenword) {
  ------------------
  |  Branch (2351:23): [True: 0, False: 0]
  ------------------
 2352|      0|                    struct hentry* rv2 = lookup(word.c_str(), word.size());
 2353|      0|                    if (!rv2 && len <= word.size())
  ------------------
  |  Branch (2353:25): [True: 0, False: 0]
  |  Branch (2353:33): [True: 0, False: 0]
  ------------------
 2354|      0|                      rv2 = affix_check(word, 0, len, scratch);
 2355|      0|                    if (rv2 && rv2->astr &&
  ------------------
  |  Branch (2355:25): [True: 0, False: 0]
  |  Branch (2355:32): [True: 0, False: 0]
  ------------------
 2356|      0|                        TESTAFF(rv2->astr, forbiddenword, rv2->alen) &&
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2357|      0|                        (strncmp(rv2->word, st.c_str(), i + rv->blen) == 0)) {
  ------------------
  |  Branch (2357:25): [True: 0, False: 0]
  ------------------
 2358|      0|                      return nullptr;
 2359|      0|                    }
 2360|      0|                  }
 2361|      0|                  st[i + rv->blen] = r;
 2362|      0|                }
 2363|      0|              }
 2364|      0|              return rv_first;
 2365|      0|            }
 2366|    316|          } while (striple && !checkedstriple);  // end of striple loop
  ------------------
  |  Branch (2366:20): [True: 0, False: 316]
  |  Branch (2366:31): [True: 0, False: 0]
  ------------------
 2367|       |
 2368|    316|          if (checkedstriple) {
  ------------------
  |  Branch (2368:15): [True: 0, False: 316]
  ------------------
 2369|      0|            i++;
 2370|      0|            checkedstriple = 0;
 2371|      0|            striple = 0;
 2372|      0|          }
 2373|       |
 2374|    316|        }  // first word is ok condition
 2375|       |
 2376|   531M|        if (soldi != 0) {
  ------------------
  |  Branch (2376:13): [True: 0, False: 531M]
  ------------------
 2377|      0|          i = soldi;
 2378|      0|          len = oldlen;
 2379|      0|          cmin = oldcmin;
 2380|      0|          cmax = oldcmax;
 2381|      0|        }
 2382|   531M|        scpd++;
 2383|       |
 2384|   531M|      } while (!onlycpdrule && simplifiedcpd &&
  ------------------
  |  Branch (2384:16): [True: 531M, False: 0]
  |  Branch (2384:32): [True: 0, False: 531M]
  ------------------
 2385|      0|               scpd <= checkcpdtable.size());  // end of simplifiedcpd loop
  ------------------
  |  Branch (2385:16): [True: 0, False: 0]
  ------------------
 2386|       |
 2387|   531M|      scpd = 0;
 2388|   531M|      wordnum = oldwordnum;
 2389|   531M|      numsyllable = oldnumsyllable;
 2390|       |
 2391|   531M|      if (soldi != 0) {
  ------------------
  |  Branch (2391:11): [True: 0, False: 531M]
  ------------------
 2392|      0|        i = soldi;
 2393|      0|        st.assign(word);  // XXX add more optim.
 2394|      0|        soldi = 0;
 2395|      0|        len = oldlen;
 2396|      0|        cmin = oldcmin;
 2397|      0|        cmax = oldcmax;
 2398|      0|      } else
 2399|   531M|        st[i] = ch;
 2400|       |
 2401|   531M|    } while (!defcpdtable.empty() && oldwordnum == 0 &&
  ------------------
  |  Branch (2401:14): [True: 0, False: 531M]
  |  Branch (2401:38): [True: 0, False: 0]
  ------------------
 2402|      0|             onlycpdrule++ < 1);  // end of onlycpd loop
  ------------------
  |  Branch (2402:14): [True: 0, False: 0]
  ------------------
 2403|   532M|  }
 2404|       |
 2405|  24.4M|  return nullptr;
 2406|  25.9M|}
_ZN8AffixMgr20compound_check_morphERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEssssPP6hentrySB_cRS6_PS7_R12AffixScratch:
 2420|  2.04k|                                   AffixScratch& scratch) {
 2421|  2.04k|  short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
 2422|  2.04k|  hentry *rv = nullptr, *rv_first;
 2423|  2.04k|  std::string st, presult;
 2424|  2.04k|  char ch, affixed = 0;
 2425|  2.04k|  int checked_prefix, ok = 0;
 2426|  2.04k|  size_t cmin, cmax;
 2427|  2.04k|  hentry** oldwords = words;
 2428|  2.04k|  size_t len = word.size();
 2429|       |
 2430|       |  // protect subsequent words[wnum + 1] reads and any recursion
 2431|  2.04k|  if (wnum + 1 >= maxwordnum)
  ------------------
  |  Branch (2431:7): [True: 0, False: 2.04k]
  ------------------
 2432|      0|    return 0;
 2433|       |
 2434|       |  // add a time limit to handle possible
 2435|       |  // combinatorical explosion of the overlapping words
 2436|       |
 2437|  2.04k|  HUNSPELL_THREAD_LOCAL std::chrono::steady_clock::time_point clock_time_start;
  ------------------
  |  |   60|  2.04k|#  define HUNSPELL_THREAD_LOCAL thread_local
  ------------------
 2438|  2.04k|  HUNSPELL_THREAD_LOCAL bool timelimit_exceeded;
  ------------------
  |  |   60|  2.04k|#  define HUNSPELL_THREAD_LOCAL thread_local
  ------------------
 2439|       |
 2440|       |  // get the current time
 2441|  2.04k|  std::chrono::steady_clock::time_point clock_now = std::chrono::steady_clock::now();
 2442|       |
 2443|  2.04k|  if (wnum == 0) {
  ------------------
  |  Branch (2443:7): [True: 2.04k, False: 0]
  ------------------
 2444|       |      // set the start time
 2445|  2.04k|      clock_time_start = clock_now;
 2446|  2.04k|      timelimit_exceeded = false;
 2447|  2.04k|  }
 2448|      0|  else if (clock_now - clock_time_start > TIMELIMIT_MS)
  ------------------
  |  |  109|      0|#define TIMELIMIT_MS std::chrono::milliseconds(50)
  ------------------
  |  Branch (2448:12): [True: 0, False: 0]
  ------------------
 2449|      0|      timelimit_exceeded = true;
 2450|       |
 2451|  2.04k|  setcminmax(&cmin, &cmax, word.c_str(), len);
 2452|       |
 2453|  2.04k|  st.assign(word);
 2454|       |
 2455|  31.4k|  for (size_t i = cmin; i < cmax; ++i) {
  ------------------
  |  Branch (2455:25): [True: 29.6k, False: 1.80k]
  ------------------
 2456|       |    // go to end of the UTF-8 character
 2457|  29.6k|    if (utf8) {
  ------------------
  |  Branch (2457:9): [True: 8.08k, False: 21.5k]
  ------------------
 2458|  9.59k|      for (; is_utf8_cont(st[i]); i++)
  ------------------
  |  Branch (2458:14): [True: 1.51k, False: 8.08k]
  ------------------
 2459|  1.51k|        ;
 2460|  8.08k|      if (i >= cmax)
  ------------------
  |  Branch (2460:11): [True: 40, False: 8.04k]
  ------------------
 2461|     40|        return 0;
 2462|  8.08k|    }
 2463|       |
 2464|  29.6k|    words = oldwords;
 2465|  29.6k|    int onlycpdrule = (words) ? 1 : 0;
  ------------------
  |  Branch (2465:23): [True: 0, False: 29.6k]
  ------------------
 2466|       |
 2467|  29.6k|    do {  // onlycpdrule loop
 2468|       |
 2469|  29.6k|      if (timelimit_exceeded ||
  ------------------
  |  Branch (2469:11): [True: 0, False: 29.6k]
  |  Branch (2469:11): [True: 0, False: 29.6k]
  ------------------
 2470|  29.6k|          std::chrono::steady_clock::now() - clock_time_start > TIMELIMIT_MS) {
  ------------------
  |  |  109|  29.6k|#define TIMELIMIT_MS std::chrono::milliseconds(50)
  ------------------
  |  Branch (2470:11): [True: 0, False: 29.6k]
  ------------------
 2471|      0|        timelimit_exceeded = true;
 2472|      0|        return 0;
 2473|      0|      }
 2474|       |
 2475|  29.6k|      if (result.size() > MAXMORPHRESULT)
  ------------------
  |  |  114|  29.6k|#define MAXMORPHRESULT (4 * 1024 * 1024)
  ------------------
  |  Branch (2475:11): [True: 0, False: 29.6k]
  ------------------
 2476|      0|        return 0;
 2477|       |
 2478|  29.6k|      oldnumsyllable = numsyllable;
 2479|  29.6k|      oldwordnum = wordnum;
 2480|  29.6k|      checked_prefix = 0;
 2481|       |
 2482|  29.6k|      if (i >= st.size())
  ------------------
  |  Branch (2482:11): [True: 195, False: 29.4k]
  ------------------
 2483|    195|        return 0;
 2484|       |
 2485|  29.4k|      ch = st[i];
 2486|  29.4k|      st[i] = '\0';
 2487|  29.4k|      sfx = nullptr;
 2488|       |
 2489|       |      // FIRST WORD
 2490|       |
 2491|  29.4k|      affixed = 1;
 2492|       |
 2493|  29.4k|      presult.clear();
 2494|  29.4k|      if (partresult)
  ------------------
  |  Branch (2494:11): [True: 0, False: 29.4k]
  ------------------
 2495|      0|        presult.append(*partresult);
 2496|       |
 2497|  29.4k|      rv = lookup(st.c_str(), i);  // perhaps without prefix
 2498|       |
 2499|       |      // forbid dictionary stems with COMPOUNDFORBIDFLAG in
 2500|       |      // compound words, overriding the effect of COMPOUNDPERMITFLAG
 2501|  29.4k|      if ((rv) && compoundforbidflag &&
  ------------------
  |  Branch (2501:11): [True: 335, False: 29.0k]
  |  Branch (2501:19): [True: 116, False: 219]
  ------------------
 2502|    116|              TESTAFF(rv->astr, compoundforbidflag, rv->alen) && !hu_mov_rule) {
  ------------------
  |  |  102|  29.5k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 116]
  |  |  ------------------
  ------------------
  |  Branch (2502:66): [True: 0, False: 0]
  ------------------
 2503|      0|        st[i] = ch;
 2504|      0|        continue;
 2505|      0|      }
 2506|       |
 2507|       |      // search homonym with compound flag
 2508|  29.7k|      while ((rv) && !hu_mov_rule &&
  ------------------
  |  Branch (2508:14): [True: 335, False: 29.4k]
  |  Branch (2508:22): [True: 335, False: 0]
  ------------------
 2509|    335|             ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
  ------------------
  |  |  102|     73|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 73]
  |  |  ------------------
  ------------------
  |  Branch (2509:16): [True: 73, False: 262]
  ------------------
 2510|    335|              !((compoundflag && !words && !onlycpdrule &&
  ------------------
  |  Branch (2510:18): [True: 335, False: 0]
  |  Branch (2510:34): [True: 335, False: 0]
  |  Branch (2510:44): [True: 335, False: 0]
  ------------------
 2511|    335|                 TESTAFF(rv->astr, compoundflag, rv->alen)) ||
  ------------------
  |  |  102|    335|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 335]
  |  |  ------------------
  ------------------
 2512|    335|                (compoundbegin && !wordnum && !onlycpdrule &&
  ------------------
  |  Branch (2512:18): [True: 0, False: 335]
  |  Branch (2512:35): [True: 0, False: 0]
  |  Branch (2512:47): [True: 0, False: 0]
  ------------------
 2513|      0|                 TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2514|    335|                (compoundmiddle && wordnum && !words && !onlycpdrule &&
  ------------------
  |  Branch (2514:18): [True: 0, False: 335]
  |  Branch (2514:36): [True: 0, False: 0]
  |  Branch (2514:47): [True: 0, False: 0]
  |  Branch (2514:57): [True: 0, False: 0]
  ------------------
 2515|      0|                 TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2516|    335|                (!defcpdtable.empty() && onlycpdrule &&
  ------------------
  |  Branch (2516:18): [True: 0, False: 335]
  |  Branch (2516:42): [True: 0, False: 0]
  ------------------
 2517|      0|                 ((!words && !wordnum &&
  ------------------
  |  Branch (2517:20): [True: 0, False: 0]
  |  Branch (2517:30): [True: 0, False: 0]
  ------------------
 2518|      0|                   defcpd_check(&words, wnum, maxwordnum, rv, rwords, 0)) ||
  ------------------
  |  Branch (2518:20): [True: 0, False: 0]
  ------------------
 2519|      0|                  (words &&
  ------------------
  |  Branch (2519:20): [True: 0, False: 0]
  ------------------
 2520|    335|                   defcpd_check(&words, wnum, maxwordnum, rv, rwords, 0))))))) {
  ------------------
  |  Branch (2520:20): [True: 0, False: 0]
  ------------------
 2521|    335|        rv = rv->next_homonym;
 2522|    335|      }
 2523|       |
 2524|       |
 2525|  29.4k|      if (rv)
  ------------------
  |  Branch (2525:11): [True: 0, False: 29.4k]
  ------------------
 2526|      0|        affixed = 0;
 2527|       |
 2528|  29.4k|      if (rv) {
  ------------------
  |  Branch (2528:11): [True: 0, False: 29.4k]
  ------------------
 2529|      0|        presult.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2530|      0|        presult.append(MORPH_PART);
  ------------------
  |  |  112|      0|#define MORPH_PART "pa:"
  ------------------
 2531|      0|        presult.append(st, 0, i);
 2532|      0|        if (!HENTRY_FIND(rv, MORPH_STEM)) {
  ------------------
  |  |   99|      0|#define MORPH_STEM "st:"
  ------------------
  |  Branch (2532:13): [True: 0, False: 0]
  ------------------
 2533|      0|          presult.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2534|      0|          presult.append(MORPH_STEM);
  ------------------
  |  |   99|      0|#define MORPH_STEM "st:"
  ------------------
 2535|      0|          presult.append(st, 0, i);
 2536|      0|        }
 2537|      0|        if (HENTRY_DATA(rv)) {
  ------------------
  |  Branch (2537:13): [True: 0, False: 0]
  ------------------
 2538|      0|          presult.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2539|      0|          presult.append(HENTRY_DATA2(rv));
 2540|      0|        }
 2541|      0|      }
 2542|       |
 2543|  29.4k|      if (!rv) {
  ------------------
  |  Branch (2543:11): [True: 29.4k, False: 0]
  ------------------
 2544|  29.4k|        if (compoundflag &&
  ------------------
  |  Branch (2544:13): [True: 29.4k, False: 0]
  ------------------
 2545|  29.4k|            !(rv =
  ------------------
  |  Branch (2545:13): [True: 29.4k, False: 0]
  ------------------
 2546|  29.4k|                  prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                                prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
  ------------------
  |  |   76|  58.8k|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (2546:42): [True: 0, False: 29.4k]
  ------------------
 2547|  29.4k|                               scratch, compoundflag))) {
 2548|  29.4k|          if (((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   99|  29.4k|#define FLAG_NULL 0x00
  ------------------
                        if (((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                        if (((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   76|  58.8k|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (2548:16): [True: 0, False: 29.4k]
  |  Branch (2548:91): [True: 0, False: 29.4k]
  ------------------
 2549|  29.4k|               (compoundmoresuffixes && (rv = suffix_check_twosfx(st, 0, i, 0, nullptr, scratch, compoundflag)))) &&
  ------------------
  |  Branch (2549:17): [True: 0, False: 29.4k]
  |  Branch (2549:41): [True: 0, False: 0]
  ------------------
 2550|      0|              !hu_mov_rule && sfx->getCont() &&
  ------------------
  |  Branch (2550:15): [True: 0, False: 0]
  |  Branch (2550:31): [True: 0, False: 0]
  ------------------
 2551|      0|              ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, sfx->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2551:17): [True: 0, False: 0]
  ------------------
 2552|      0|               (compoundend && TESTAFF(sfx->getCont(), compoundend, sfx->getContLen())))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2552:17): [True: 0, False: 0]
  ------------------
 2553|      0|            rv = nullptr;
 2554|      0|          }
 2555|  29.4k|        }
 2556|       |
 2557|  29.4k|        if (rv ||
  ------------------
  |  Branch (2557:13): [True: 0, False: 29.4k]
  ------------------
 2558|  29.4k|            (((wordnum == 0) && compoundbegin &&
  ------------------
  |  Branch (2558:15): [True: 29.4k, False: 0]
  |  Branch (2558:33): [True: 0, False: 29.4k]
  ------------------
 2559|      0|              ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
                            ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                            ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   76|      0|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (2559:16): [True: 0, False: 0]
  |  Branch (2559:92): [True: 0, False: 0]
  ------------------
 2560|      0|               (compoundmoresuffixes && (rv = suffix_check_twosfx(st, 0, i, 0, nullptr, scratch,
  ------------------
  |  Branch (2560:17): [True: 0, False: 0]
  |  Branch (2560:41): [True: 0, False: 0]
  ------------------
 2561|      0|                                                                  compoundbegin))) ||  // twofold suffix+compound
 2562|      0|               (rv = prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, scratch, compoundbegin)))) ||
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                             (rv = prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, scratch, compoundbegin)))) ||
  ------------------
  |  |   76|      0|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (2562:16): [True: 0, False: 0]
  |  Branch (2562:45): [True: 0, False: 0]
  ------------------
 2563|  29.4k|             ((wordnum > 0) && compoundmiddle &&
  ------------------
  |  Branch (2563:15): [True: 0, False: 29.4k]
  |  Branch (2563:32): [True: 0, False: 0]
  ------------------
 2564|      0|              ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
                            ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                            ((rv = suffix_check(st, 0, i, 0, nullptr, scratch, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
  ------------------
  |  |   76|      0|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (2564:16): [True: 0, False: 0]
  |  Branch (2564:93): [True: 0, False: 0]
  ------------------
 2565|      0|               (compoundmoresuffixes && (rv = suffix_check_twosfx(st, 0, i, 0, nullptr, scratch,
  ------------------
  |  Branch (2565:17): [True: 0, False: 0]
  |  Branch (2565:41): [True: 0, False: 0]
  ------------------
 2566|      0|                                                                  compoundmiddle))) ||  // twofold suffix+compound
 2567|      0|               (rv = prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, scratch, compoundmiddle)))))) {
  ------------------
  |  |   78|      0|#define IN_CPD_OTHER 3
  ------------------
                             (rv = prefix_check(st, 0, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, scratch, compoundmiddle)))))) {
  ------------------
  |  |   76|      0|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (2567:16): [True: 0, False: 0]
  |  Branch (2567:45): [True: 0, False: 0]
  ------------------
 2568|      0|          std::string p;
 2569|      0|          if (compoundflag)
  ------------------
  |  Branch (2569:15): [True: 0, False: 0]
  ------------------
 2570|      0|            p = affix_check_morph(st, 0, i, scratch, compoundflag);
 2571|      0|          if (p.empty()) {
  ------------------
  |  Branch (2571:15): [True: 0, False: 0]
  ------------------
 2572|      0|            if ((wordnum == 0) && compoundbegin) {
  ------------------
  |  Branch (2572:17): [True: 0, False: 0]
  |  Branch (2572:35): [True: 0, False: 0]
  ------------------
 2573|      0|              p = affix_check_morph(st, 0, i, scratch, compoundbegin);
 2574|      0|            } else if ((wordnum > 0) && compoundmiddle) {
  ------------------
  |  Branch (2574:24): [True: 0, False: 0]
  |  Branch (2574:41): [True: 0, False: 0]
  ------------------
 2575|      0|              p = affix_check_morph(st, 0, i, scratch, compoundmiddle);
 2576|      0|            }
 2577|      0|          }
 2578|      0|          presult.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2579|      0|          presult.append(MORPH_PART);
  ------------------
  |  |  112|      0|#define MORPH_PART "pa:"
  ------------------
 2580|      0|          presult.append(st, 0, i);
 2581|      0|          if (!p.empty()) {
  ------------------
  |  Branch (2581:15): [True: 0, False: 0]
  ------------------
 2582|      0|            line_uniq_app(p, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 2583|      0|            if (!p.empty() && p[0] != MSEP_FLD)
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
  |  Branch (2583:17): [True: 0, False: 0]
  |  Branch (2583:31): [True: 0, False: 0]
  ------------------
 2584|      0|              presult.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2585|      0|            presult.append(p);
 2586|      0|          }
 2587|      0|          checked_prefix = 1;
 2588|      0|        }
 2589|       |        // else check forbiddenwords
 2590|  29.4k|      } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2590:18): [True: 0, False: 0]
  |  Branch (2590:18): [True: 0, False: 0]
  ------------------
 2591|      0|                              TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2592|      0|                              TESTAFF(rv->astr, needaffix, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2593|      0|        st[i] = ch;
 2594|      0|        continue;
 2595|      0|      }
 2596|       |
 2597|       |      // check non_compound flag in suffix and prefix
 2598|  29.4k|      if ((rv) && !hu_mov_rule &&
  ------------------
  |  Branch (2598:11): [True: 0, False: 29.4k]
  |  Branch (2598:19): [True: 0, False: 0]
  ------------------
 2599|      0|          ((pfx && pfx->getCont() &&
  ------------------
  |  Branch (2599:13): [True: 0, False: 0]
  |  Branch (2599:20): [True: 0, False: 0]
  ------------------
 2600|      0|            TESTAFF(pfx->getCont(), compoundforbidflag, pfx->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2601|      0|           (sfx && sfx->getCont() &&
  ------------------
  |  Branch (2601:13): [True: 0, False: 0]
  |  Branch (2601:20): [True: 0, False: 0]
  ------------------
 2602|      0|            TESTAFF(sfx->getCont(), compoundforbidflag, sfx->getContLen())))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2603|      0|        st[i] = ch;
 2604|      0|        continue;
 2605|      0|      }
 2606|       |
 2607|       |      // check compoundend flag in suffix and prefix
 2608|  29.4k|      if ((rv) && !checked_prefix && compoundend && !hu_mov_rule &&
  ------------------
  |  Branch (2608:11): [True: 0, False: 29.4k]
  |  Branch (2608:19): [True: 0, False: 0]
  |  Branch (2608:38): [True: 0, False: 0]
  |  Branch (2608:53): [True: 0, False: 0]
  ------------------
 2609|      0|          ((pfx && pfx->getCont() &&
  ------------------
  |  Branch (2609:13): [True: 0, False: 0]
  |  Branch (2609:20): [True: 0, False: 0]
  ------------------
 2610|      0|            TESTAFF(pfx->getCont(), compoundend, pfx->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2611|      0|           (sfx && sfx->getCont() &&
  ------------------
  |  Branch (2611:13): [True: 0, False: 0]
  |  Branch (2611:20): [True: 0, False: 0]
  ------------------
 2612|      0|            TESTAFF(sfx->getCont(), compoundend, sfx->getContLen())))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2613|      0|        st[i] = ch;
 2614|      0|        continue;
 2615|      0|      }
 2616|       |
 2617|       |      // check compoundmiddle flag in suffix and prefix
 2618|  29.4k|      if ((rv) && !checked_prefix && (wordnum == 0) && compoundmiddle &&
  ------------------
  |  Branch (2618:11): [True: 0, False: 29.4k]
  |  Branch (2618:19): [True: 0, False: 0]
  |  Branch (2618:38): [True: 0, False: 0]
  |  Branch (2618:56): [True: 0, False: 0]
  ------------------
 2619|      0|          !hu_mov_rule &&
  ------------------
  |  Branch (2619:11): [True: 0, False: 0]
  ------------------
 2620|      0|          ((pfx && pfx->getCont() &&
  ------------------
  |  Branch (2620:13): [True: 0, False: 0]
  |  Branch (2620:20): [True: 0, False: 0]
  ------------------
 2621|      0|            TESTAFF(pfx->getCont(), compoundmiddle, pfx->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2622|      0|           (sfx && sfx->getCont() &&
  ------------------
  |  Branch (2622:13): [True: 0, False: 0]
  |  Branch (2622:20): [True: 0, False: 0]
  ------------------
 2623|      0|            TESTAFF(sfx->getCont(), compoundmiddle, sfx->getContLen())))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2624|      0|        rv = nullptr;
 2625|      0|      }
 2626|       |
 2627|       |      // check forbiddenwords
 2628|  29.4k|      if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2628:11): [True: 0, False: 29.4k]
  |  Branch (2628:11): [True: 0, False: 29.4k]
  |  Branch (2628:19): [True: 0, False: 0]
  ------------------
 2629|      0|                                 TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2630|      0|        st[i] = ch;
 2631|      0|        continue;
 2632|      0|      }
 2633|       |
 2634|       |      // increment word number, if the second root has a compoundroot flag
 2635|  29.4k|      if ((rv) && (compoundroot) &&
  ------------------
  |  Branch (2635:11): [True: 0, False: 29.4k]
  |  Branch (2635:19): [True: 0, False: 0]
  ------------------
 2636|      0|          (TESTAFF(rv->astr, compoundroot, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2636:11): [True: 0, False: 0]
  ------------------
 2637|      0|        wordnum++;
 2638|      0|      }
 2639|       |
 2640|       |      // first word is acceptable in compound words?
 2641|  29.4k|      if (((rv) &&
  ------------------
  |  Branch (2641:11): [True: 0, False: 29.4k]
  |  Branch (2641:12): [True: 0, False: 29.4k]
  ------------------
 2642|      0|           (checked_prefix || (words && words[wnum]) || (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2642:13): [True: 0, False: 0]
  |  Branch (2642:32): [True: 0, False: 0]
  |  Branch (2642:41): [True: 0, False: 0]
  |  Branch (2642:58): [True: 0, False: 0]
  ------------------
 2643|      0|            ((oldwordnum == 0) && compoundbegin && TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2643:14): [True: 0, False: 0]
  |  Branch (2643:35): [True: 0, False: 0]
  ------------------
 2644|      0|            ((oldwordnum > 0) && compoundmiddle && TESTAFF(rv->astr, compoundmiddle, rv->alen))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2644:14): [True: 0, False: 0]
  |  Branch (2644:34): [True: 0, False: 0]
  ------------------
 2645|       |            // LANG_hu section: spec. Hungarian rule
 2646|      0|            || ((langnum == LANG_hu) &&  // hu_mov_rule
  ------------------
  |  Branch (2646:17): [True: 0, False: 0]
  ------------------
 2647|      0|                hu_mov_rule &&
  ------------------
  |  Branch (2647:17): [True: 0, False: 0]
  ------------------
 2648|      0|                (TESTAFF(rv->astr, 'F', rv->alen) || TESTAFF(rv->astr, 'G', rv->alen) || TESTAFF(rv->astr, 'H', rv->alen)))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
                              (TESTAFF(rv->astr, 'F', rv->alen) || TESTAFF(rv->astr, 'G', rv->alen) || TESTAFF(rv->astr, 'H', rv->alen)))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
                              (TESTAFF(rv->astr, 'F', rv->alen) || TESTAFF(rv->astr, 'G', rv->alen) || TESTAFF(rv->astr, 'H', rv->alen)))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2649|       |            // END of LANG_hu section
 2650|      0|            ) &&
 2651|      0|           !((checkcompoundtriple && !words &&  // test triple letters
  ------------------
  |  Branch (2651:15): [True: 0, False: 0]
  |  Branch (2651:38): [True: 0, False: 0]
  ------------------
 2652|      0|              (word[i - 1] == word[i]) &&
  ------------------
  |  Branch (2652:15): [True: 0, False: 0]
  ------------------
 2653|      0|              (((i > 1) && (word[i - 1] == word[i - 2])) || ((word[i - 1] == word[i + 1]))  // may be word[i+1] == '\0'
  ------------------
  |  Branch (2653:17): [True: 0, False: 0]
  |  Branch (2653:28): [True: 0, False: 0]
  |  Branch (2653:61): [True: 0, False: 0]
  ------------------
 2654|      0|               )) ||
 2655|      0|             (
 2656|       |                 // test CHECKCOMPOUNDPATTERN
 2657|      0|                 !checkcpdtable.empty() && !words && cpdpat_check(word, i, rv, nullptr, affixed, nullptr, nullptr, nullptr, nullptr, nullptr)) ||
  ------------------
  |  Branch (2657:18): [True: 0, False: 0]
  |  Branch (2657:44): [True: 0, False: 0]
  |  Branch (2657:54): [True: 0, False: 0]
  ------------------
 2658|      0|             (checkcompoundcase && !words && cpdcase_check(word, i))))
  ------------------
  |  Branch (2658:15): [True: 0, False: 0]
  |  Branch (2658:36): [True: 0, False: 0]
  |  Branch (2658:46): [True: 0, False: 0]
  ------------------
 2659|       |          // LANG_hu section: spec. Hungarian rule
 2660|  29.4k|          || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st, 0, i, scratch)) &&
  ------------------
  |  Branch (2660:15): [True: 29.4k, False: 0]
  |  Branch (2660:24): [True: 8.04k, False: 21.3k]
  |  Branch (2660:48): [True: 0, False: 8.04k]
  |  Branch (2660:63): [True: 0, False: 0]
  ------------------
 2661|      0|              (sfx && sfx->getCont() &&
  ------------------
  |  Branch (2661:16): [True: 0, False: 0]
  |  Branch (2661:23): [True: 0, False: 0]
  ------------------
 2662|      0|               (TESTAFF(sfx->getCont(), (unsigned short)'x', sfx->getContLen()) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2663|      0|                TESTAFF(sfx->getCont(), (unsigned short)'%', sfx->getContLen()))))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2664|       |          // END of LANG_hu section
 2665|  29.4k|      ) {
 2666|       |        // LANG_hu section: spec. Hungarian rule
 2667|      0|        if (langnum == LANG_hu) {
  ------------------
  |  Branch (2667:13): [True: 0, False: 0]
  ------------------
 2668|       |          // calculate syllable number of the word
 2669|      0|          numsyllable += get_syllable(st.substr(0, i));
 2670|       |
 2671|       |          // + 1 word, if syllable number of the prefix > 1 (hungarian
 2672|       |          // convention)
 2673|      0|          if (pfx && (get_syllable(pfx->getKey()) > 1))
  ------------------
  |  Branch (2673:15): [True: 0, False: 0]
  |  Branch (2673:15): [True: 0, False: 0]
  |  Branch (2673:22): [True: 0, False: 0]
  ------------------
 2674|      0|            wordnum++;
 2675|      0|        }
 2676|       |        // END of LANG_hu section
 2677|       |
 2678|       |        // NEXT WORD(S)
 2679|      0|        rv_first = rv;
 2680|      0|        rv = lookup(word.c_str() + i, word.size() - i);  // perhaps without prefix
 2681|       |
 2682|       |        // search homonym with compound flag
 2683|      0|        while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2683:16): [True: 0, False: 0]
  |  Branch (2683:26): [True: 0, False: 0]
  ------------------
 2684|      0|                        !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2684:28): [True: 0, False: 0]
  |  Branch (2684:44): [True: 0, False: 0]
  ------------------
 2685|      0|                          (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2685:28): [True: 0, False: 0]
  |  Branch (2685:43): [True: 0, False: 0]
  ------------------
 2686|      0|                          (!defcpdtable.empty() && words && defcpd_check(&words, wnum + 1, maxwordnum, rv, nullptr, 1))))) {
  ------------------
  |  Branch (2686:28): [True: 0, False: 0]
  |  Branch (2686:52): [True: 0, False: 0]
  |  Branch (2686:61): [True: 0, False: 0]
  ------------------
 2687|      0|          rv = rv->next_homonym;
 2688|      0|        }
 2689|       |
 2690|      0|        if (rv && words && words[wnum + 1]) {
  ------------------
  |  Branch (2690:13): [True: 0, False: 0]
  |  Branch (2690:19): [True: 0, False: 0]
  |  Branch (2690:28): [True: 0, False: 0]
  ------------------
 2691|      0|          result.append(presult);
 2692|      0|          result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2693|      0|          result.append(MORPH_PART);
  ------------------
  |  |  112|      0|#define MORPH_PART "pa:"
  ------------------
 2694|      0|          result.append(word, i, word.size());
 2695|      0|          if (complexprefixes && HENTRY_DATA(rv))
  ------------------
  |  Branch (2695:15): [True: 0, False: 0]
  |  Branch (2695:34): [True: 0, False: 0]
  ------------------
 2696|      0|            result.append(HENTRY_DATA2(rv));
 2697|      0|          if (!HENTRY_FIND(rv, MORPH_STEM)) {
  ------------------
  |  |   99|      0|#define MORPH_STEM "st:"
  ------------------
  |  Branch (2697:15): [True: 0, False: 0]
  ------------------
 2698|      0|            result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2699|      0|            result.append(MORPH_STEM);
  ------------------
  |  |   99|      0|#define MORPH_STEM "st:"
  ------------------
 2700|      0|            result.append(HENTRY_WORD(rv));
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 2701|      0|          }
 2702|       |          // store the pointer of the hash entry
 2703|      0|          if (!complexprefixes && HENTRY_DATA(rv)) {
  ------------------
  |  Branch (2703:15): [True: 0, False: 0]
  |  Branch (2703:35): [True: 0, False: 0]
  ------------------
 2704|      0|            result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2705|      0|            result.append(HENTRY_DATA2(rv));
 2706|      0|          }
 2707|      0|          result.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 2708|      0|          return 0;
 2709|      0|        }
 2710|       |
 2711|      0|        oldnumsyllable2 = numsyllable;
 2712|      0|        oldwordnum2 = wordnum;
 2713|       |
 2714|       |        // LANG_hu section: spec. Hungarian rule
 2715|      0|        if ((rv) && (langnum == LANG_hu) &&
  ------------------
  |  Branch (2715:13): [True: 0, False: 0]
  |  Branch (2715:13): [True: 0, False: 0]
  |  Branch (2715:21): [True: 0, False: 0]
  ------------------
 2716|      0|            (TESTAFF(rv->astr, 'I', rv->alen)) &&
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2716:13): [True: 0, False: 0]
  ------------------
 2717|      0|            !(TESTAFF(rv->astr, 'J', rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2717:13): [True: 0, False: 0]
  ------------------
 2718|      0|          numsyllable--;
 2719|      0|        }
 2720|       |        // END of LANG_hu section
 2721|       |        // increment word number, if the second root has a compoundroot flag
 2722|      0|        if ((rv) && (compoundroot) &&
  ------------------
  |  Branch (2722:13): [True: 0, False: 0]
  |  Branch (2722:21): [True: 0, False: 0]
  ------------------
 2723|      0|            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2723:13): [True: 0, False: 0]
  ------------------
 2724|      0|          wordnum++;
 2725|      0|        }
 2726|       |
 2727|       |        // check forbiddenwords
 2728|      0|        if ((rv) && (rv->astr) &&
  ------------------
  |  Branch (2728:13): [True: 0, False: 0]
  |  Branch (2728:13): [True: 0, False: 0]
  |  Branch (2728:21): [True: 0, False: 0]
  ------------------
 2729|      0|            (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2730|      0|             TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2731|      0|          st[i] = ch;
 2732|      0|          wordnum = oldwordnum;
 2733|      0|          numsyllable = oldnumsyllable;
 2734|      0|          continue;
 2735|      0|        }
 2736|       |
 2737|       |        // second word is acceptable, as a root?
 2738|       |        // hungarian conventions: compounding is acceptable,
 2739|       |        // when compound forms consist of 2 words, or if more,
 2740|       |        // then the syllable number of root words must be 6, or lesser.
 2741|      0|        if ((rv) &&
  ------------------
  |  Branch (2741:13): [True: 0, False: 0]
  |  Branch (2741:13): [True: 0, False: 0]
  ------------------
 2742|      0|            ((compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2742:15): [True: 0, False: 0]
  ------------------
 2743|      0|             (compoundend && TESTAFF(rv->astr, compoundend, rv->alen))) &&
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2743:15): [True: 0, False: 0]
  ------------------
 2744|      0|            (((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) ||
  ------------------
  |  Branch (2744:15): [True: 0, False: 0]
  |  Branch (2744:37): [True: 0, False: 0]
  ------------------
 2745|      0|             ((cpdmaxsyllable != 0) &&
  ------------------
  |  Branch (2745:15): [True: 0, False: 0]
  ------------------
 2746|      0|              (numsyllable + get_syllable(std::string(HENTRY_WORD(rv), rv->blen)) <=
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
  |  Branch (2746:15): [True: 0, False: 0]
  ------------------
 2747|      0|               cpdmaxsyllable))) &&
 2748|      0|            ((!checkcompounddup || (rv != rv_first)))) {
  ------------------
  |  Branch (2748:15): [True: 0, False: 0]
  |  Branch (2748:36): [True: 0, False: 0]
  ------------------
 2749|       |          // bad compound word
 2750|      0|          result.append(presult);
 2751|      0|          result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2752|      0|          result.append(MORPH_PART);
  ------------------
  |  |  112|      0|#define MORPH_PART "pa:"
  ------------------
 2753|      0|          result.append(word, i, word.size());
 2754|       |
 2755|      0|          if (HENTRY_DATA(rv)) {
  ------------------
  |  Branch (2755:15): [True: 0, False: 0]
  ------------------
 2756|      0|            if (complexprefixes)
  ------------------
  |  Branch (2756:17): [True: 0, False: 0]
  ------------------
 2757|      0|              result.append(HENTRY_DATA2(rv));
 2758|      0|            if (!HENTRY_FIND(rv, MORPH_STEM)) {
  ------------------
  |  |   99|      0|#define MORPH_STEM "st:"
  ------------------
  |  Branch (2758:17): [True: 0, False: 0]
  ------------------
 2759|      0|              result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2760|      0|              result.append(MORPH_STEM);
  ------------------
  |  |   99|      0|#define MORPH_STEM "st:"
  ------------------
 2761|      0|              result.append(HENTRY_WORD(rv));
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 2762|      0|            }
 2763|       |            // store the pointer of the hash entry
 2764|      0|            if (!complexprefixes) {
  ------------------
  |  Branch (2764:17): [True: 0, False: 0]
  ------------------
 2765|      0|              result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2766|      0|              result.append(HENTRY_DATA2(rv));
 2767|      0|            }
 2768|      0|          }
 2769|      0|          result.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 2770|      0|          ok = 1;
 2771|      0|        }
 2772|       |
 2773|      0|        numsyllable = oldnumsyllable2;
 2774|      0|        wordnum = oldwordnum2;
 2775|       |
 2776|       |        // perhaps second word has prefix or/and suffix
 2777|      0|        sfx = nullptr;
 2778|      0|        sfxflag = FLAG_NULL;
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
 2779|       |
 2780|      0|        if (compoundflag && !onlycpdrule)
  ------------------
  |  Branch (2780:13): [True: 0, False: 0]
  |  Branch (2780:29): [True: 0, False: 0]
  ------------------
 2781|      0|          rv = affix_check(word, i, word.size() - i, scratch, compoundflag);
 2782|      0|        else
 2783|      0|          rv = nullptr;
 2784|       |
 2785|      0|        if (!rv && compoundend && !onlycpdrule) {
  ------------------
  |  Branch (2785:13): [True: 0, False: 0]
  |  Branch (2785:20): [True: 0, False: 0]
  |  Branch (2785:35): [True: 0, False: 0]
  ------------------
 2786|      0|          sfx = nullptr;
 2787|      0|          pfx = nullptr;
 2788|      0|          rv = affix_check(word, i, word.size() - i, scratch, compoundend, IN_CPD_END);
  ------------------
  |  |   77|      0|#define IN_CPD_END 2
  ------------------
 2789|      0|        }
 2790|       |
 2791|      0|        if (!rv && !defcpdtable.empty() && words) {
  ------------------
  |  Branch (2791:13): [True: 0, False: 0]
  |  Branch (2791:20): [True: 0, False: 0]
  |  Branch (2791:44): [True: 0, False: 0]
  ------------------
 2792|      0|          rv = affix_check(word, i, word.size() - i, scratch, 0, IN_CPD_END);
  ------------------
  |  |   77|      0|#define IN_CPD_END 2
  ------------------
 2793|      0|          if (rv && words && defcpd_check(&words, wnum + 1, maxwordnum, rv, nullptr, 1)) {
  ------------------
  |  Branch (2793:15): [True: 0, False: 0]
  |  Branch (2793:21): [True: 0, False: 0]
  |  Branch (2793:30): [True: 0, False: 0]
  ------------------
 2794|      0|            std::string m;
 2795|      0|            if (compoundflag)
  ------------------
  |  Branch (2795:17): [True: 0, False: 0]
  ------------------
 2796|      0|              m = affix_check_morph(word, i, word.size() - i, scratch, compoundflag);
 2797|      0|            if (m.empty() && compoundend) {
  ------------------
  |  Branch (2797:17): [True: 0, False: 0]
  |  Branch (2797:30): [True: 0, False: 0]
  ------------------
 2798|      0|              m = affix_check_morph(word, i, word.size() - i, scratch, compoundend);
 2799|      0|            }
 2800|      0|            result.append(presult);
 2801|      0|            if (!m.empty()) {
  ------------------
  |  Branch (2801:17): [True: 0, False: 0]
  ------------------
 2802|      0|              result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2803|      0|              result.append(MORPH_PART);
  ------------------
  |  |  112|      0|#define MORPH_PART "pa:"
  ------------------
 2804|      0|              result.append(word, i, word.size());
 2805|      0|              line_uniq_app(m, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 2806|      0|              result.append(m);
 2807|      0|            }
 2808|      0|            result.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 2809|      0|            ok = 1;
 2810|      0|          }
 2811|      0|        }
 2812|       |
 2813|       |        // check non_compound flag in suffix and prefix
 2814|      0|        if ((rv) &&
  ------------------
  |  Branch (2814:13): [True: 0, False: 0]
  ------------------
 2815|      0|            ((pfx && pfx->getCont() &&
  ------------------
  |  Branch (2815:15): [True: 0, False: 0]
  |  Branch (2815:22): [True: 0, False: 0]
  ------------------
 2816|      0|              TESTAFF(pfx->getCont(), compoundforbidflag, pfx->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2817|      0|             (sfx && sfx->getCont() &&
  ------------------
  |  Branch (2817:15): [True: 0, False: 0]
  |  Branch (2817:22): [True: 0, False: 0]
  ------------------
 2818|      0|              TESTAFF(sfx->getCont(), compoundforbidflag,
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2819|      0|                      sfx->getContLen())))) {
 2820|      0|          rv = nullptr;
 2821|      0|        }
 2822|       |
 2823|       |        // check forbiddenwords
 2824|      0|        if ((rv) && (rv->astr) &&
  ------------------
  |  Branch (2824:13): [True: 0, False: 0]
  |  Branch (2824:13): [True: 0, False: 0]
  |  Branch (2824:21): [True: 0, False: 0]
  ------------------
 2825|      0|            (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2826|      0|             TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen)) &&
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2827|      0|            (!TESTAFF(rv->astr, needaffix, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2827:13): [True: 0, False: 0]
  ------------------
 2828|      0|          st[i] = ch;
 2829|      0|          wordnum = oldwordnum;
 2830|      0|          numsyllable = oldnumsyllable;
 2831|      0|          continue;
 2832|      0|        }
 2833|       |
 2834|      0|        if (langnum == LANG_hu) {
  ------------------
  |  Branch (2834:13): [True: 0, False: 0]
  ------------------
 2835|       |          // calculate syllable number of the word
 2836|      0|          numsyllable += get_syllable(word.c_str() + i);
 2837|       |
 2838|       |          // - affix syllable num.
 2839|       |          // XXX only second suffix (inflections, not derivations)
 2840|      0|          if (sfxappnd) {
  ------------------
  |  Branch (2840:15): [True: 0, False: 0]
  ------------------
 2841|      0|            std::string tmp(sfxappnd);
 2842|      0|            reverseword(tmp);
 2843|      0|            numsyllable -= short(get_syllable(tmp) + sfxextra);
 2844|      0|          } else {
 2845|      0|            numsyllable -= short(sfxextra);
 2846|      0|          }
 2847|       |
 2848|       |          // + 1 word, if syllable number of the prefix > 1 (hungarian
 2849|       |          // convention)
 2850|      0|          if (pfx && (get_syllable(pfx->getKey()) > 1))
  ------------------
  |  Branch (2850:15): [True: 0, False: 0]
  |  Branch (2850:15): [True: 0, False: 0]
  |  Branch (2850:22): [True: 0, False: 0]
  ------------------
 2851|      0|            wordnum++;
 2852|       |
 2853|       |          // increment syllable num, if last word has a SYLLABLENUM flag
 2854|       |          // and the suffix is beginning `s'
 2855|       |
 2856|      0|          if (!cpdsyllablenum.empty()) {
  ------------------
  |  Branch (2856:15): [True: 0, False: 0]
  ------------------
 2857|      0|            switch (sfxflag) {
  ------------------
  |  Branch (2857:21): [True: 0, False: 0]
  ------------------
 2858|      0|              case 'c': {
  ------------------
  |  Branch (2858:15): [True: 0, False: 0]
  ------------------
 2859|      0|                numsyllable += 2;
 2860|      0|                break;
 2861|      0|              }
 2862|      0|              case 'J': {
  ------------------
  |  Branch (2862:15): [True: 0, False: 0]
  ------------------
 2863|      0|                numsyllable += 1;
 2864|      0|                break;
 2865|      0|              }
 2866|      0|              case 'I': {
  ------------------
  |  Branch (2866:15): [True: 0, False: 0]
  ------------------
 2867|      0|                if (rv && TESTAFF(rv->astr, 'J', rv->alen))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2867:21): [True: 0, False: 0]
  |  Branch (2867:21): [True: 0, False: 0]
  ------------------
 2868|      0|                  numsyllable += 1;
 2869|      0|                break;
 2870|      0|              }
 2871|      0|            }
 2872|      0|          }
 2873|      0|        }
 2874|       |
 2875|       |        // increment word number, if the second word has a compoundroot flag
 2876|      0|        if ((rv) && (compoundroot) &&
  ------------------
  |  Branch (2876:13): [True: 0, False: 0]
  |  Branch (2876:21): [True: 0, False: 0]
  ------------------
 2877|      0|            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  ------------------
  |  Branch (2877:13): [True: 0, False: 0]
  ------------------
 2878|      0|          wordnum++;
 2879|      0|        }
 2880|       |        // second word is acceptable, as a word with prefix or/and suffix?
 2881|       |        // hungarian conventions: compounding is acceptable,
 2882|       |        // when compound forms consist 2 word, otherwise
 2883|       |        // the syllable number of root words is 6, or lesser.
 2884|      0|        if ((rv) &&
  ------------------
  |  Branch (2884:13): [True: 0, False: 0]
  ------------------
 2885|      0|            (((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) ||
  ------------------
  |  Branch (2885:15): [True: 0, False: 0]
  |  Branch (2885:37): [True: 0, False: 0]
  ------------------
 2886|      0|             ((cpdmaxsyllable != 0) && (numsyllable <= cpdmaxsyllable))) &&
  ------------------
  |  Branch (2886:15): [True: 0, False: 0]
  |  Branch (2886:40): [True: 0, False: 0]
  ------------------
 2887|      0|            ((!checkcompounddup || (rv != rv_first)))) {
  ------------------
  |  Branch (2887:15): [True: 0, False: 0]
  |  Branch (2887:36): [True: 0, False: 0]
  ------------------
 2888|      0|          std::string m;
 2889|      0|          if (compoundflag)
  ------------------
  |  Branch (2889:15): [True: 0, False: 0]
  ------------------
 2890|      0|            m = affix_check_morph(word, i, word.size() - i, scratch, compoundflag, IN_CPD_END);
  ------------------
  |  |   77|      0|#define IN_CPD_END 2
  ------------------
 2891|      0|          if (m.empty() && compoundend) {
  ------------------
  |  Branch (2891:15): [True: 0, False: 0]
  |  Branch (2891:28): [True: 0, False: 0]
  ------------------
 2892|      0|            m = affix_check_morph(word, i, word.size() - i, scratch, compoundend, IN_CPD_END);
  ------------------
  |  |   77|      0|#define IN_CPD_END 2
  ------------------
 2893|      0|          }
 2894|      0|          result.append(presult);
 2895|      0|          if (!m.empty()) {
  ------------------
  |  Branch (2895:15): [True: 0, False: 0]
  ------------------
 2896|      0|            result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2897|      0|            result.append(MORPH_PART);
  ------------------
  |  |  112|      0|#define MORPH_PART "pa:"
  ------------------
 2898|      0|            result.append(word, i, word.size());
 2899|      0|            line_uniq_app(m, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 2900|      0|            result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 2901|      0|            result.append(m);
 2902|      0|          }
 2903|      0|          result.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 2904|      0|          ok = 1;
 2905|      0|        }
 2906|       |
 2907|      0|        numsyllable = oldnumsyllable2;
 2908|      0|        wordnum = oldwordnum2;
 2909|       |
 2910|       |        // perhaps second word is a compound word (recursive call)
 2911|      0|        if ((wordnum + 2 < maxwordnum) && (wnum + 1 < maxwordnum) && (ok == 0)) {
  ------------------
  |  Branch (2911:13): [True: 0, False: 0]
  |  Branch (2911:43): [True: 0, False: 0]
  |  Branch (2911:70): [True: 0, False: 0]
  ------------------
 2912|      0|          compound_check_morph(word.substr(i), wordnum + 1,
 2913|      0|                               numsyllable, maxwordnum, wnum + 1, words, rwords, 0,
 2914|      0|                               result, &presult, scratch);
 2915|      0|        } else {
 2916|      0|          rv = nullptr;
 2917|      0|        }
 2918|      0|      }
 2919|  29.4k|      st[i] = ch;
 2920|  29.4k|      wordnum = oldwordnum;
 2921|  29.4k|      numsyllable = oldnumsyllable;
 2922|       |
 2923|  29.4k|    } while (!defcpdtable.empty() && oldwordnum == 0 &&
  ------------------
  |  Branch (2923:14): [True: 0, False: 29.4k]
  |  Branch (2923:38): [True: 0, False: 0]
  ------------------
 2924|      0|             onlycpdrule++ < 1);  // end of onlycpd loop
  ------------------
  |  Branch (2924:14): [True: 0, False: 0]
  ------------------
 2925|  29.6k|  }
 2926|  1.80k|  return 0;
 2927|  2.04k|}
_ZNK8AffixMgr12circumfix_okEP8PfxEntryP8SfxEntryPK8TraceCtx:
 2943|  44.7k|bool AffixMgr::circumfix_ok(PfxEntry* pfx, SfxEntry* sfx, const TraceCtx* t) const {
 2944|  44.7k|  if (!circumfix)
  ------------------
  |  Branch (2944:7): [True: 44.7k, False: 0]
  ------------------
 2945|  44.7k|    return true;
 2946|      0|  bool in_prefix = pfx && pfx->getCont() &&
  ------------------
  |  Branch (2946:20): [True: 0, False: 0]
  |  Branch (2946:27): [True: 0, False: 0]
  ------------------
 2947|      0|                   TESTAFF(pfx->getCont(), circumfix, pfx->getContLen());
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2948|      0|  bool in_suffix = sfx->getCont() &&
  ------------------
  |  Branch (2948:20): [True: 0, False: 0]
  ------------------
 2949|      0|                   TESTAFF(sfx->getCont(), circumfix, sfx->getContLen());
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2950|      0|  if (t)
  ------------------
  |  Branch (2950:7): [True: 0, False: 0]
  ------------------
 2951|      0|    trace_circumfix(*t, this, circumfix, pfx, sfx, in_prefix, in_suffix);
 2952|      0|  return in_prefix == in_suffix;
 2953|  44.7k|}
_ZNK8AffixMgr17suffix_applicableEP8PfxEntryP8SfxEntrytcPK8TraceCtx:
 2973|   187k|                                 const TraceCtx* t) const {
 2974|       |  // suffixes are only allowed at the beginning of a compound when they are signed with the
 2975|       |  // compoundpermitflag flag
 2976|   187k|  if (in_compound == IN_CPD_BEGIN &&
  ------------------
  |  |   76|   375k|#define IN_CPD_BEGIN 1
  ------------------
  |  Branch (2976:7): [True: 142k, False: 44.7k]
  ------------------
 2977|   142k|      !(sfx->getCont() && compoundpermitflag &&
  ------------------
  |  Branch (2977:9): [True: 142k, False: 0]
  |  Branch (2977:27): [True: 0, False: 142k]
  ------------------
 2978|   142k|        TESTAFF(sfx->getCont(), compoundpermitflag, sfx->getContLen()))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2979|   142k|    if (t)
  ------------------
  |  Branch (2979:9): [True: 0, False: 142k]
  ------------------
 2980|      0|      trace_test(*t, "compoundpermit", this, compoundpermitflag, "sfx-cont",
 2981|      0|                 sfx->getCont(), sfx->getContLen(),
 2982|      0|                 "fail, a suffix at the start of a compound needs this flag");
 2983|   142k|    return false;
 2984|   142k|  }
 2985|       |
 2986|  44.7k|  if (!circumfix_ok(pfx, sfx, t))
  ------------------
  |  Branch (2986:7): [True: 0, False: 44.7k]
  ------------------
 2987|      0|    return false;
 2988|       |
 2989|       |  // a fogemorpheme is only allowed inside a compound
 2990|  44.7k|  if (!in_compound && sfx->getCont() &&
  ------------------
  |  Branch (2990:7): [True: 44.7k, False: 0]
  |  Branch (2990:23): [True: 20.1k, False: 24.5k]
  ------------------
 2991|  20.1k|      TESTAFF(sfx->getCont(), onlyincompound, sfx->getContLen())) {
  ------------------
  |  |  102|  20.1k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 20.1k]
  |  |  ------------------
  ------------------
 2992|      0|    if (t)
  ------------------
  |  Branch (2992:9): [True: 0, False: 0]
  ------------------
 2993|      0|      trace_test(*t, "onlyincompound", this, onlyincompound, "sfx-cont",
 2994|      0|                 sfx->getCont(), sfx->getContLen(),
 2995|      0|                 "fail, this suffix is only allowed inside a compound");
 2996|      0|    return false;
 2997|      0|  }
 2998|       |
 2999|       |  // a needaffix suffix needs a further affix, so it is allowed either as a second suffix or
 3000|       |  // when a prefix is present that does not itself need one
 3001|  44.7k|  if (!cclass && sfx->getCont() &&
  ------------------
  |  Branch (3001:7): [True: 43.7k, False: 914]
  |  Branch (3001:18): [True: 20.1k, False: 23.6k]
  ------------------
 3002|  20.1k|      TESTAFF(sfx->getCont(), needaffix, sfx->getContLen()) &&
  ------------------
  |  |  102|  64.8k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 20.1k]
  |  |  ------------------
  ------------------
 3003|      0|      !(pfx && !(pfx->getCont() &&
  ------------------
  |  Branch (3003:9): [True: 0, False: 0]
  |  Branch (3003:18): [True: 0, False: 0]
  ------------------
 3004|      0|                 TESTAFF(pfx->getCont(), needaffix, pfx->getContLen())))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3005|      0|    if (t)
  ------------------
  |  Branch (3005:9): [True: 0, False: 0]
  ------------------
 3006|      0|      trace_test(*t, "needaffix", this, needaffix, "sfx-cont", sfx->getCont(),
 3007|      0|                 sfx->getContLen(),
 3008|      0|                 "fail, this suffix needs a further affix and has none");
 3009|      0|    return false;
 3010|      0|  }
 3011|       |
 3012|  44.7k|  return true;
 3013|  44.7k|}
_ZN8AffixMgr12suffix_checkERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmiP8PfxEntryR12AffixScratchttct:
 3025|   584M|                                      const FLAG avoidflag) {
 3026|   584M|  struct hentry* rv = nullptr;
 3027|       |
 3028|   584M|  TraceCtx* t = trace_on(scratch.trace);
 3029|   584M|  int candidates = 0;
 3030|       |  // a pass that had nothing to try says so, which is different from a pass that
 3031|       |  // did not run
 3032|   584M|  auto report_empty_pass = [t, &word, start, len, sfxopts, &candidates]() {
 3033|   584M|    if (t && candidates == 0)
 3034|   584M|      trace(*t, "sfx \"%s\" candidates=0%s", word.substr(start, len).c_str(),
 3035|   584M|            (sfxopts & aeXPRODUCT) != 0 ? " xprod=Y" : "");
 3036|   584M|  };
 3037|       |  // a rule the suffix conditions turned away never reaches checkword, so name
 3038|       |  // the rule here and run the conditions again to say which of them refused it
 3039|   584M|  auto report_refused = [this, t, ppfx, cclass, in_compound,
 3040|   584M|                         &candidates](SfxEntry* se) {
 3041|   584M|    if (!t)
 3042|   584M|      return;
 3043|   584M|    ++candidates;
 3044|   584M|    trace_affix(*t, "sfx", this, *se);
 3045|   584M|    TraceScope trace_depth(t);
 3046|   584M|    (void)suffix_applicable(ppfx, se, cclass, in_compound, t);
 3047|   584M|  };
 3048|       |
 3049|       |  // first handle the special case of 0 length suffixes
 3050|   584M|  SfxEntry* se = sStart[0];
 3051|       |
 3052|   584M|  while (se) {
  ------------------
  |  Branch (3052:10): [True: 0, False: 584M]
  ------------------
 3053|      0|    if (!cclass || se->getCont()) {
  ------------------
  |  Branch (3053:9): [True: 0, False: 0]
  |  Branch (3053:20): [True: 0, False: 0]
  ------------------
 3054|      0|      if (suffix_applicable(ppfx, se, cclass, in_compound, nullptr)) {
  ------------------
  |  Branch (3054:11): [True: 0, False: 0]
  ------------------
 3055|      0|        ++candidates;
 3056|      0|        rv = se->checkword(word, start, len, sfxopts, ppfx,
 3057|      0|                           (FLAG)cclass, needflag,
 3058|      0|                           (in_compound ? 0 : onlyincompound),
  ------------------
  |  Branch (3058:29): [True: 0, False: 0]
  ------------------
 3059|      0|                           scratch);
 3060|       |        // Skip a stem with the avoid flag and keep scanning the other suffixes.
 3061|      0|        if (rv && avoidflag != FLAG_NULL && TESTAFF(rv->astr, avoidflag, rv->alen)) {
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
                      if (rv && avoidflag != FLAG_NULL && TESTAFF(rv->astr, avoidflag, rv->alen)) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (3061:13): [True: 0, False: 0]
  |  Branch (3061:19): [True: 0, False: 0]
  ------------------
 3062|      0|          trace_avoidflag(t, avoidflag, rv);
 3063|      0|          rv = nullptr;
 3064|      0|        }
 3065|      0|        if (rv) {
  ------------------
  |  Branch (3065:13): [True: 0, False: 0]
  ------------------
 3066|      0|          sfx = se;  // BUG: sfx not stateless
 3067|      0|          return rv;
 3068|      0|        }
 3069|      0|      } else {
 3070|      0|        report_refused(se);
 3071|      0|      }
 3072|      0|    }
 3073|      0|    se = se->getNext();
 3074|      0|  }
 3075|       |
 3076|       |  // now handle the general case
 3077|   584M|  if (len == 0) {
  ------------------
  |  Branch (3077:7): [True: 35.7k, False: 584M]
  ------------------
 3078|  35.7k|    report_empty_pass();
 3079|  35.7k|    return nullptr;  // FULLSTRIP
 3080|  35.7k|  }
 3081|   584M|  unsigned char sp = word[start + len - 1];
 3082|   584M|  SfxEntry* sptr = sStart[sp];
 3083|       |
 3084|   584M|  while (sptr) {
  ------------------
  |  Branch (3084:10): [True: 221k, False: 584M]
  ------------------
 3085|   221k|    if (isRevSubset(sptr->getKey(), word.c_str() + start + len - 1, len)) {
  ------------------
  |  Branch (3085:9): [True: 187k, False: 34.0k]
  ------------------
 3086|   187k|      if (!suffix_applicable(ppfx, sptr, cclass, in_compound, nullptr))
  ------------------
  |  Branch (3086:11): [True: 142k, False: 44.7k]
  ------------------
 3087|   142k|        report_refused(sptr);
 3088|  44.7k|      else if (in_compound != IN_CPD_END || ppfx ||
  ------------------
  |  |   77|  89.4k|#define IN_CPD_END 2
  ------------------
  |  Branch (3088:16): [True: 44.7k, False: 0]
  |  Branch (3088:45): [True: 0, False: 0]
  ------------------
 3089|      0|               !(sptr->getCont() &&
  ------------------
  |  Branch (3089:18): [True: 0, False: 0]
  ------------------
 3090|  44.7k|                 TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3091|  44.7k|        ++candidates;
 3092|  44.7k|        rv = sptr->checkword(word, start, len, sfxopts, ppfx,
 3093|  44.7k|                             cclass, needflag,
 3094|  44.7k|                             (in_compound ? 0 : onlyincompound),
  ------------------
  |  Branch (3094:31): [True: 0, False: 44.7k]
  ------------------
 3095|  44.7k|                             scratch);
 3096|  44.7k|        if (rv && avoidflag != FLAG_NULL && TESTAFF(rv->astr, avoidflag, rv->alen)) {
  ------------------
  |  |   99|  44.7k|#define FLAG_NULL 0x00
  ------------------
                      if (rv && avoidflag != FLAG_NULL && TESTAFF(rv->astr, avoidflag, rv->alen)) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (3096:13): [True: 0, False: 44.7k]
  |  Branch (3096:19): [True: 0, False: 0]
  ------------------
 3097|      0|          trace_avoidflag(t, avoidflag, rv);
 3098|      0|          rv = nullptr;
 3099|      0|        }
 3100|  44.7k|        if (rv) {
  ------------------
  |  Branch (3100:13): [True: 0, False: 44.7k]
  ------------------
 3101|      0|          sfx = sptr;                 // BUG: sfx not stateless
 3102|      0|          sfxflag = sptr->getFlag();  // BUG: sfxflag not stateless
 3103|      0|          if (!sptr->getCont())
  ------------------
  |  Branch (3103:15): [True: 0, False: 0]
  ------------------
 3104|      0|            sfxappnd = sptr->getKey();  // BUG: sfxappnd not stateless
 3105|       |          // LANG_hu section: spec. Hungarian rule
 3106|      0|          else if (langnum == LANG_hu && sptr->getKeyLen() &&
  ------------------
  |  Branch (3106:20): [True: 0, False: 0]
  |  Branch (3106:42): [True: 0, False: 0]
  ------------------
 3107|      0|                   sptr->getKey()[0] == 'i' && sptr->getKey()[1] != 'y' &&
  ------------------
  |  Branch (3107:20): [True: 0, False: 0]
  |  Branch (3107:48): [True: 0, False: 0]
  ------------------
 3108|      0|                   sptr->getKey()[1] != 't') {
  ------------------
  |  Branch (3108:20): [True: 0, False: 0]
  ------------------
 3109|      0|            sfxextra = 1;
 3110|      0|          }
 3111|       |          // END of LANG_hu section
 3112|      0|          return rv;
 3113|      0|        }
 3114|  44.7k|      }
 3115|   187k|      sptr = sptr->getNextEQ();
 3116|   187k|    } else {
 3117|  34.0k|      sptr = sptr->getNextNE();
 3118|  34.0k|    }
 3119|   221k|  }
 3120|       |
 3121|   584M|  report_empty_pass();
 3122|       |
 3123|   584M|  return nullptr;
 3124|   584M|}
_ZN8AffixMgr19suffix_check_twosfxERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmiP8PfxEntryR12AffixScratcht:
 3133|  18.3M|                                             const FLAG needflag) {
 3134|  18.3M|  struct hentry* rv = nullptr;
 3135|       |
 3136|       |  // first handle the special case of 0 length suffixes
 3137|  18.3M|  SfxEntry* se = sStart[0];
 3138|  18.3M|  while (se) {
  ------------------
  |  Branch (3138:10): [True: 0, False: 18.3M]
  ------------------
 3139|      0|    if (contclasses[se->getFlag()]) {
  ------------------
  |  Branch (3139:9): [True: 0, False: 0]
  ------------------
 3140|      0|      rv = se->check_twosfx(word, start, len, sfxopts, ppfx, needflag, scratch);
 3141|      0|      if (rv)
  ------------------
  |  Branch (3141:11): [True: 0, False: 0]
  ------------------
 3142|      0|        return rv;
 3143|      0|    }
 3144|      0|    se = se->getNext();
 3145|      0|  }
 3146|       |
 3147|       |  // now handle the general case
 3148|  18.3M|  if (len == 0)
  ------------------
  |  Branch (3148:7): [True: 10.7k, False: 18.3M]
  ------------------
 3149|  10.7k|    return nullptr;  // FULLSTRIP
 3150|  18.3M|  unsigned char sp = word[start + len - 1];
 3151|  18.3M|  SfxEntry* sptr = sStart[sp];
 3152|       |
 3153|  18.4M|  while (sptr) {
  ------------------
  |  Branch (3153:10): [True: 74.8k, False: 18.3M]
  ------------------
 3154|  74.8k|    if (isRevSubset(sptr->getKey(), word.c_str() + start + len - 1, len)) {
  ------------------
  |  Branch (3154:9): [True: 43.0k, False: 31.8k]
  ------------------
 3155|  43.0k|      if (contclasses[sptr->getFlag()]) {
  ------------------
  |  Branch (3155:11): [True: 22.8k, False: 20.1k]
  ------------------
 3156|  22.8k|        rv = sptr->check_twosfx(word, start, len, sfxopts, ppfx, needflag, scratch);
 3157|  22.8k|        if (rv) {
  ------------------
  |  Branch (3157:13): [True: 0, False: 22.8k]
  ------------------
 3158|      0|          sfxflag = sptr->getFlag();  // BUG: sfxflag not stateless
 3159|      0|          if (!sptr->getCont())
  ------------------
  |  Branch (3159:15): [True: 0, False: 0]
  ------------------
 3160|      0|            sfxappnd = sptr->getKey();  // BUG: sfxappnd not stateless
 3161|      0|          return rv;
 3162|      0|        }
 3163|  22.8k|      }
 3164|  43.0k|      sptr = sptr->getNextEQ();
 3165|  43.0k|    } else {
 3166|  31.8k|      sptr = sptr->getNextNE();
 3167|  31.8k|    }
 3168|  74.8k|  }
 3169|       |
 3170|  18.3M|  return nullptr;
 3171|  18.3M|}
_ZN8AffixMgr25suffix_check_twosfx_morphERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmiP8PfxEntryR12AffixScratcht:
 3180|  3.74k|                                                const FLAG needflag) {
 3181|  3.74k|  std::string result2;
 3182|  3.74k|  std::string result3;
 3183|       |  // the second suffix runs the whole suffix table again for every first suffix
 3184|  3.74k|  DistinctRecords result(MSEP_REC);
  ------------------
  |  |  118|  3.74k|#define MSEP_REC '\n'
  ------------------
 3185|       |
 3186|       |  // first handle the special case of 0 length suffixes
 3187|  3.74k|  SfxEntry* se = sStart[0];
 3188|  3.74k|  while (se) {
  ------------------
  |  Branch (3188:10): [True: 0, False: 3.74k]
  ------------------
 3189|      0|    if (contclasses[se->getFlag()]) {
  ------------------
  |  Branch (3189:9): [True: 0, False: 0]
  ------------------
 3190|      0|      std::string st = se->check_twosfx_morph(word, start, len, sfxopts, ppfx, needflag, scratch);
 3191|      0|      if (!st.empty()) {
  ------------------
  |  Branch (3191:11): [True: 0, False: 0]
  ------------------
 3192|      0|        std::string analysis;
 3193|      0|        if (ppfx) {
  ------------------
  |  Branch (3193:13): [True: 0, False: 0]
  ------------------
 3194|      0|          if (ppfx->getMorph()) {
  ------------------
  |  Branch (3194:15): [True: 0, False: 0]
  ------------------
 3195|      0|            analysis.append(ppfx->getMorph());
 3196|      0|            analysis.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 3197|      0|          } else
 3198|      0|            debugflag(analysis, ppfx->getFlag());
 3199|      0|        }
 3200|      0|        analysis.append(st);
 3201|      0|        if (se->getMorph()) {
  ------------------
  |  Branch (3201:13): [True: 0, False: 0]
  ------------------
 3202|      0|          analysis.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 3203|      0|          analysis.append(se->getMorph());
 3204|      0|        } else
 3205|      0|          debugflag(analysis, se->getFlag());
 3206|      0|        result.append(analysis);
 3207|      0|      }
 3208|      0|    }
 3209|      0|    se = se->getNext();
 3210|      0|  }
 3211|       |
 3212|       |  // now handle the general case
 3213|  3.74k|  if (len == 0)
  ------------------
  |  Branch (3213:7): [True: 0, False: 3.74k]
  ------------------
 3214|      0|    return { };  // FULLSTRIP
 3215|  3.74k|  unsigned char sp = word[start + len - 1];
 3216|  3.74k|  SfxEntry* sptr = sStart[sp];
 3217|       |
 3218|  3.74k|  while (sptr) {
  ------------------
  |  Branch (3218:10): [True: 0, False: 3.74k]
  ------------------
 3219|      0|    if (isRevSubset(sptr->getKey(), word.c_str() + start + len - 1, len)) {
  ------------------
  |  Branch (3219:9): [True: 0, False: 0]
  ------------------
 3220|      0|      if (contclasses[sptr->getFlag()]) {
  ------------------
  |  Branch (3220:11): [True: 0, False: 0]
  ------------------
 3221|      0|        std::string st = sptr->check_twosfx_morph(word, start, len, sfxopts, ppfx, needflag, scratch);
 3222|      0|        if (!st.empty()) {
  ------------------
  |  Branch (3222:13): [True: 0, False: 0]
  ------------------
 3223|      0|          sfxflag = sptr->getFlag();  // BUG: sfxflag not stateless
 3224|      0|          if (!sptr->getCont())
  ------------------
  |  Branch (3224:15): [True: 0, False: 0]
  ------------------
 3225|      0|            sfxappnd = sptr->getKey();  // BUG: sfxappnd not stateless
 3226|      0|          result2.assign(st);
 3227|       |
 3228|      0|          result3.clear();
 3229|       |
 3230|      0|          if (sptr->getMorph()) {
  ------------------
  |  Branch (3230:15): [True: 0, False: 0]
  ------------------
 3231|      0|            result3.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 3232|      0|            result3.append(sptr->getMorph());
 3233|      0|          } else
 3234|      0|            debugflag(result3, sptr->getFlag());
 3235|      0|          strlinecat(result2, result3);
 3236|      0|          result.append(result2);
 3237|      0|        }
 3238|      0|      }
 3239|      0|      sptr = sptr->getNextEQ();
 3240|      0|    } else {
 3241|      0|      sptr = sptr->getNextNE();
 3242|      0|    }
 3243|      0|  }
 3244|       |
 3245|  3.74k|  return result.join();
 3246|  3.74k|}
_ZN8AffixMgr18suffix_check_morphERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmiP8PfxEntryR12AffixScratchttc:
 3256|  11.9k|                                         char in_compound) {
 3257|  11.9k|  std::string result;
 3258|       |
 3259|  11.9k|  struct hentry* rv = nullptr;
 3260|       |
 3261|       |  // first handle the special case of 0 length suffixes
 3262|  11.9k|  SfxEntry* se = sStart[0];
 3263|  11.9k|  while (se) {
  ------------------
  |  Branch (3263:10): [True: 0, False: 11.9k]
  ------------------
 3264|      0|    if (!cclass || se->getCont()) {
  ------------------
  |  Branch (3264:9): [True: 0, False: 0]
  |  Branch (3264:20): [True: 0, False: 0]
  ------------------
 3265|      0|      if (suffix_applicable(ppfx, se, cclass, in_compound, nullptr))
  ------------------
  |  Branch (3265:11): [True: 0, False: 0]
  ------------------
 3266|      0|        rv = se->checkword(word, start, len, sfxopts, ppfx, cclass,
 3267|      0|                           needflag, FLAG_NULL, scratch);
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
 3268|      0|      while (rv) {
  ------------------
  |  Branch (3268:14): [True: 0, False: 0]
  ------------------
 3269|      0|        if (ppfx) {
  ------------------
  |  Branch (3269:13): [True: 0, False: 0]
  ------------------
 3270|      0|          if (ppfx->getMorph()) {
  ------------------
  |  Branch (3270:15): [True: 0, False: 0]
  ------------------
 3271|      0|            result.append(ppfx->getMorph());
 3272|      0|            result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 3273|      0|          } else
 3274|      0|            debugflag(result, ppfx->getFlag());
 3275|      0|        }
 3276|      0|        if (complexprefixes && HENTRY_DATA(rv))
  ------------------
  |  Branch (3276:13): [True: 0, False: 0]
  |  Branch (3276:32): [True: 0, False: 0]
  ------------------
 3277|      0|          result.append(HENTRY_DATA2(rv));
 3278|      0|        append_morph_stem(result, rv, complexprefixes);
 3279|       |
 3280|      0|        if (!complexprefixes && HENTRY_DATA(rv)) {
  ------------------
  |  Branch (3280:13): [True: 0, False: 0]
  |  Branch (3280:33): [True: 0, False: 0]
  ------------------
 3281|      0|          result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 3282|      0|          result.append(HENTRY_DATA2(rv));
 3283|      0|        }
 3284|      0|        if (se->getMorph()) {
  ------------------
  |  Branch (3284:13): [True: 0, False: 0]
  ------------------
 3285|      0|          result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 3286|      0|          result.append(se->getMorph());
 3287|      0|        } else
 3288|      0|          debugflag(result, se->getFlag());
 3289|      0|        result.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 3290|      0|        rv = se->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag);
 3291|      0|      }
 3292|      0|    }
 3293|      0|    se = se->getNext();
 3294|      0|  }
 3295|       |
 3296|       |  // now handle the general case
 3297|  11.9k|  if (len == 0)
  ------------------
  |  Branch (3297:7): [True: 0, False: 11.9k]
  ------------------
 3298|      0|    return { };  // FULLSTRIP
 3299|  11.9k|  unsigned char sp = word[start + len - 1];
 3300|  11.9k|  SfxEntry* sptr = sStart[sp];
 3301|       |
 3302|  11.9k|  while (sptr) {
  ------------------
  |  Branch (3302:10): [True: 0, False: 11.9k]
  ------------------
 3303|      0|    if (isRevSubset(sptr->getKey(), word.c_str() + start + len - 1, len)) {
  ------------------
  |  Branch (3303:9): [True: 0, False: 0]
  ------------------
 3304|      0|      if (suffix_applicable(ppfx, sptr, cclass, in_compound, nullptr))
  ------------------
  |  Branch (3304:11): [True: 0, False: 0]
  ------------------
 3305|      0|        rv = sptr->checkword(word, start, len, sfxopts, ppfx, cclass,
 3306|      0|                             needflag, FLAG_NULL, scratch);
  ------------------
  |  |   99|      0|#define FLAG_NULL 0x00
  ------------------
 3307|      0|      while (rv) {
  ------------------
  |  Branch (3307:14): [True: 0, False: 0]
  ------------------
 3308|      0|        if (ppfx) {
  ------------------
  |  Branch (3308:13): [True: 0, False: 0]
  ------------------
 3309|      0|          if (ppfx->getMorph()) {
  ------------------
  |  Branch (3309:15): [True: 0, False: 0]
  ------------------
 3310|      0|            result.append(ppfx->getMorph());
 3311|      0|            result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 3312|      0|          } else
 3313|      0|            debugflag(result, ppfx->getFlag());
 3314|      0|        }
 3315|      0|        if (complexprefixes && HENTRY_DATA(rv))
  ------------------
  |  Branch (3315:13): [True: 0, False: 0]
  |  Branch (3315:32): [True: 0, False: 0]
  ------------------
 3316|      0|          result.append(HENTRY_DATA2(rv));
 3317|      0|        append_morph_stem(result, rv, complexprefixes);
 3318|       |
 3319|      0|        if (!complexprefixes && HENTRY_DATA(rv)) {
  ------------------
  |  Branch (3319:13): [True: 0, False: 0]
  |  Branch (3319:33): [True: 0, False: 0]
  ------------------
 3320|      0|          result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 3321|      0|          result.append(HENTRY_DATA2(rv));
 3322|      0|        }
 3323|       |
 3324|      0|        if (sptr->getMorph()) {
  ------------------
  |  Branch (3324:13): [True: 0, False: 0]
  ------------------
 3325|      0|          result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 3326|      0|          result.append(sptr->getMorph());
 3327|      0|        } else
 3328|      0|          debugflag(result, sptr->getFlag());
 3329|      0|        result.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 3330|      0|        rv = sptr->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag);
 3331|      0|      }
 3332|      0|      sptr = sptr->getNextEQ();
 3333|      0|    } else {
 3334|      0|      sptr = sptr->getNextNE();
 3335|      0|    }
 3336|      0|  }
 3337|       |
 3338|  11.9k|  return result;
 3339|  11.9k|}
_ZN8AffixMgr11affix_checkERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmR12AffixScratchtctPP8PfxEntryPP8SfxEntry:
 3374|  21.1M|                                     SfxEntry** found_sfx) {
 3375|       |
 3376|  21.1M|  TraceCtx* t = trace_on(scratch.trace);
 3377|       |  // the affixes that built the word are reported before the members holding them are cleared
 3378|  21.1M|  auto report_form = [this, t, &word, start, len, found_pfx, found_sfx](const struct hentry* rv) {
 3379|  21.1M|    if (!rv)
 3380|  21.1M|      return;
 3381|  21.1M|    if (t)
 3382|  21.1M|      trace_form(*t, this, word.substr(start, len), rv->word, pfx, sfx);
 3383|  21.1M|    if (found_pfx)
 3384|  21.1M|      *found_pfx = pfx;
 3385|  21.1M|    if (found_sfx)
 3386|  21.1M|      *found_sfx = sfx;
 3387|  21.1M|  };
 3388|       |
 3389|       |  // check all prefixes (also crossed with suffixes if allowed)
 3390|  21.1M|  struct hentry* rv = prefix_check(word, start, len, in_compound, scratch, needflag, avoidflag);
 3391|  21.1M|  if (rv) {
  ------------------
  |  Branch (3391:7): [True: 0, False: 21.1M]
  ------------------
 3392|      0|    report_form(rv);
 3393|      0|    return rv;
 3394|      0|  }
 3395|       |
 3396|       |  // if still not found check all suffixes
 3397|  21.1M|  rv = suffix_check(word, start, len, 0, nullptr, scratch, FLAG_NULL, needflag, in_compound, avoidflag);
  ------------------
  |  |   99|  21.1M|#define FLAG_NULL 0x00
  ------------------
 3398|       |
 3399|  21.1M|  if (havecontclass) {
  ------------------
  |  Branch (3399:7): [True: 7.02M, False: 14.0M]
  ------------------
 3400|  7.02M|    if (rv)
  ------------------
  |  Branch (3400:9): [True: 0, False: 7.02M]
  ------------------
 3401|      0|      report_form(rv);
 3402|       |
 3403|  7.02M|    sfx = nullptr;
 3404|  7.02M|    pfx = nullptr;
 3405|       |
 3406|  7.02M|    if (rv)
  ------------------
  |  Branch (3406:9): [True: 0, False: 7.02M]
  ------------------
 3407|      0|      return rv;
 3408|       |    // if still not found check all two-level suffixes
 3409|  7.02M|    rv = suffix_check_twosfx(word, start, len, 0, nullptr, scratch, needflag);
 3410|       |
 3411|  7.02M|    if (rv) {
  ------------------
  |  Branch (3411:9): [True: 0, False: 7.02M]
  ------------------
 3412|      0|      report_form(rv);
 3413|      0|      return rv;
 3414|      0|    }
 3415|       |    // if still not found check all two-level suffixes
 3416|  7.02M|    rv = prefix_check_twosfx(word, start, len, IN_CPD_NOT, scratch, needflag);
  ------------------
  |  |   75|  7.02M|#define IN_CPD_NOT 0
  ------------------
 3417|  7.02M|  }
 3418|       |
 3419|  21.1M|  report_form(rv);
 3420|       |
 3421|  21.1M|  return rv;
 3422|  21.1M|}
_ZN8AffixMgr17affix_check_morphERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmR12AffixScratchtc:
 3430|  11.9k|                                  char in_compound) {
 3431|       |  // the four checks below overlap
 3432|  11.9k|  DistinctRecords result(MSEP_REC);
  ------------------
  |  |  118|  11.9k|#define MSEP_REC '\n'
  ------------------
 3433|       |
 3434|       |  // check all prefixes (also crossed with suffixes if allowed)
 3435|  11.9k|  std::string st = prefix_check_morph(word, start, len, in_compound, scratch);
 3436|  11.9k|  if (!st.empty()) {
  ------------------
  |  Branch (3436:7): [True: 0, False: 11.9k]
  ------------------
 3437|      0|    result.append(st);
 3438|      0|  }
 3439|       |
 3440|       |  // if still not found check all suffixes
 3441|  11.9k|  st = suffix_check_morph(word, start, len, 0, nullptr, scratch, '\0', needflag, in_compound);
 3442|  11.9k|  if (!st.empty()) {
  ------------------
  |  Branch (3442:7): [True: 0, False: 11.9k]
  ------------------
 3443|      0|    result.append(st);
 3444|      0|  }
 3445|       |
 3446|  11.9k|  if (havecontclass) {
  ------------------
  |  Branch (3446:7): [True: 3.74k, False: 8.17k]
  ------------------
 3447|  3.74k|    sfx = nullptr;
 3448|  3.74k|    pfx = nullptr;
 3449|       |    // if still not found check all two-level suffixes
 3450|  3.74k|    st = suffix_check_twosfx_morph(word, start, len, 0, nullptr, scratch, needflag);
 3451|  3.74k|    if (!st.empty()) {
  ------------------
  |  Branch (3451:9): [True: 0, False: 3.74k]
  ------------------
 3452|      0|      result.append(st);
 3453|      0|    }
 3454|       |
 3455|       |    // if still not found check all two-level suffixes
 3456|  3.74k|    st = prefix_check_twosfx_morph(word, start, len, IN_CPD_NOT, scratch, needflag);
  ------------------
  |  |   75|  3.74k|#define IN_CPD_NOT 0
  ------------------
 3457|  3.74k|    if (!st.empty()) {
  ------------------
  |  Branch (3457:9): [True: 0, False: 3.74k]
  ------------------
 3458|      0|      result.append(st);
 3459|      0|    }
 3460|  3.74k|  }
 3461|       |
 3462|  11.9k|  return result.join();
 3463|  11.9k|}
_ZN8AffixMgr15expand_rootwordEP9guesswordiPKciPKttS3_mS3_:
 3659|   698k|                              const char* phon) {
 3660|   698k|  int nh = 0;
 3661|       |  // first add root word to list
 3662|   698k|  if ((nh < maxn) &&
  ------------------
  |  Branch (3662:7): [True: 698k, False: 0]
  ------------------
 3663|   698k|      !(al && ((needaffix && TESTAFF(ap, needaffix, al)) ||
  ------------------
  |  |  102|  4.38k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 2.19k, False: 2.19k]
  |  |  ------------------
  ------------------
  |  Branch (3663:9): [True: 94.2k, False: 603k]
  |  Branch (3663:17): [True: 4.38k, False: 89.8k]
  ------------------
 3664|   695k|               (onlyincompound && TESTAFF(ap, onlyincompound, al))))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (3664:17): [True: 0, False: 92.0k]
  ------------------
 3665|   695k|    wlst[nh].word = mystrdup(ts);
 3666|   695k|    wlst[nh].allow = false;
 3667|   695k|    wlst[nh].orig = nullptr;
 3668|   695k|    nh++;
 3669|       |    // add special phonetic version
 3670|   695k|    if (phon && (nh < maxn)) {
  ------------------
  |  Branch (3670:9): [True: 911, False: 695k]
  |  Branch (3670:17): [True: 911, False: 0]
  ------------------
 3671|    911|      wlst[nh].word = mystrdup(phon);
 3672|    911|      wlst[nh].allow = false;
 3673|    911|      wlst[nh].orig = mystrdup(ts);
 3674|    911|      nh++;
 3675|    911|    }
 3676|   695k|  }
 3677|       |
 3678|       |  // handle suffixes
 3679|   804k|  for (int i = 0; i < al; i++) {
  ------------------
  |  Branch (3679:19): [True: 105k, False: 698k]
  ------------------
 3680|   105k|    const auto c = (unsigned char)(ap[i] & 0x00FF);
 3681|   105k|    SfxEntry* sptr = sFlag[c];
 3682|   168k|    while (sptr) {
  ------------------
  |  Branch (3682:12): [True: 62.6k, False: 105k]
  ------------------
 3683|  62.6k|      if ((sptr->getFlag() == ap[i]) &&
  ------------------
  |  Branch (3683:11): [True: 62.6k, False: 0]
  ------------------
 3684|  62.6k|          (!sptr->getKeyLen() ||
  ------------------
  |  Branch (3684:12): [True: 0, False: 62.6k]
  ------------------
 3685|  62.6k|           ((badl > sptr->getKeyLen()) &&
  ------------------
  |  Branch (3685:13): [True: 35.4k, False: 27.1k]
  ------------------
 3686|  35.4k|            (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0))) &&
  ------------------
  |  Branch (3686:13): [True: 30, False: 35.4k]
  ------------------
 3687|       |          // check needaffix flag
 3688|     30|          !(sptr->getCont() &&
  ------------------
  |  Branch (3688:13): [True: 14, False: 16]
  ------------------
 3689|     14|            ((needaffix &&
  ------------------
  |  Branch (3689:15): [True: 6, False: 8]
  ------------------
 3690|      6|              TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) ||
  ------------------
  |  |  102|      6|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 6]
  |  |  ------------------
  ------------------
 3691|     14|             (circumfix &&
  ------------------
  |  Branch (3691:15): [True: 0, False: 14]
  ------------------
 3692|      0|              TESTAFF(sptr->getCont(), circumfix, sptr->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3693|     14|             (onlyincompound &&
  ------------------
  |  Branch (3693:15): [True: 0, False: 14]
  ------------------
 3694|     30|              TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3695|     30|        std::string newword = sptr->add(ts, wl);
 3696|     30|        if (!newword.empty()) {
  ------------------
  |  Branch (3696:13): [True: 30, False: 0]
  ------------------
 3697|     30|          if (nh < maxn) {
  ------------------
  |  Branch (3697:15): [True: 30, False: 0]
  ------------------
 3698|     30|            wlst[nh].word = mystrdup(newword.c_str());
 3699|     30|            wlst[nh].allow = sptr->allowCross();
 3700|     30|            wlst[nh].orig = nullptr;
 3701|     30|            nh++;
 3702|       |            // add special phonetic version
 3703|     30|            if (phon && (nh < maxn)) {
  ------------------
  |  Branch (3703:17): [True: 0, False: 30]
  |  Branch (3703:25): [True: 0, False: 0]
  ------------------
 3704|      0|              std::string prefix(phon);
 3705|      0|              std::string key(sptr->getKey());
 3706|      0|              reverseword(key);
 3707|      0|              prefix.append(key);
 3708|      0|              wlst[nh].word = mystrdup(prefix.c_str());
 3709|      0|              wlst[nh].allow = false;
 3710|      0|              wlst[nh].orig = mystrdup(newword.c_str());
 3711|      0|              nh++;
 3712|      0|            }
 3713|     30|          }
 3714|     30|        }
 3715|     30|      }
 3716|  62.6k|      sptr = sptr->getFlgNxt();
 3717|  62.6k|    }
 3718|   105k|  }
 3719|       |
 3720|   698k|  int n = nh;
 3721|       |
 3722|       |  // handle cross products of prefixes and suffixes
 3723|   699k|  for (int j = 1; j < n; j++)
  ------------------
  |  Branch (3723:19): [True: 935, False: 698k]
  ------------------
 3724|    935|    if (wlst[j].allow) {
  ------------------
  |  Branch (3724:9): [True: 24, False: 911]
  ------------------
 3725|     72|      for (int k = 0; k < al; k++) {
  ------------------
  |  Branch (3725:23): [True: 48, False: 24]
  ------------------
 3726|     48|        const auto c = (unsigned char)(ap[k] & 0x00FF);
 3727|     48|        PfxEntry* cptr = pFlag[c];
 3728|     48|        while (cptr) {
  ------------------
  |  Branch (3728:16): [True: 0, False: 48]
  ------------------
 3729|      0|          if ((cptr->getFlag() == ap[k]) && cptr->allowCross() &&
  ------------------
  |  Branch (3729:15): [True: 0, False: 0]
  |  Branch (3729:45): [True: 0, False: 0]
  ------------------
 3730|      0|              (!cptr->getKeyLen() ||
  ------------------
  |  Branch (3730:16): [True: 0, False: 0]
  ------------------
 3731|      0|               ((badl > cptr->getKeyLen()) &&
  ------------------
  |  Branch (3731:17): [True: 0, False: 0]
  ------------------
 3732|      0|                (strncmp(cptr->getKey(), bad, cptr->getKeyLen()) == 0)))) {
  ------------------
  |  Branch (3732:17): [True: 0, False: 0]
  ------------------
 3733|      0|            size_t l1 = strlen(wlst[j].word);
 3734|      0|            std::string newword = cptr->add(wlst[j].word, l1);
 3735|      0|            if (!newword.empty()) {
  ------------------
  |  Branch (3735:17): [True: 0, False: 0]
  ------------------
 3736|      0|              if (nh < maxn) {
  ------------------
  |  Branch (3736:19): [True: 0, False: 0]
  ------------------
 3737|      0|                wlst[nh].word = mystrdup(newword.c_str());
 3738|      0|                wlst[nh].allow = cptr->allowCross();
 3739|      0|                wlst[nh].orig = nullptr;
 3740|      0|                nh++;
 3741|      0|              }
 3742|      0|            }
 3743|      0|          }
 3744|      0|          cptr = cptr->getFlgNxt();
 3745|      0|        }
 3746|     48|      }
 3747|     24|    }
 3748|       |
 3749|       |  // now handle pure prefixes
 3750|   804k|  for (int m = 0; m < al; m++) {
  ------------------
  |  Branch (3750:19): [True: 105k, False: 698k]
  ------------------
 3751|   105k|    const auto c = (unsigned char)(ap[m] & 0x00FF);
 3752|   105k|    PfxEntry* ptr = pFlag[c];
 3753|   106k|    while (ptr) {
  ------------------
  |  Branch (3753:12): [True: 922, False: 105k]
  ------------------
 3754|    922|      if ((ptr->getFlag() == ap[m]) &&
  ------------------
  |  Branch (3754:11): [True: 922, False: 0]
  ------------------
 3755|    922|          (!ptr->getKeyLen() ||
  ------------------
  |  Branch (3755:12): [True: 0, False: 922]
  ------------------
 3756|    922|           ((badl > ptr->getKeyLen()) &&
  ------------------
  |  Branch (3756:13): [True: 922, False: 0]
  ------------------
 3757|    922|            (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0))) &&
  ------------------
  |  Branch (3757:13): [True: 4, False: 918]
  ------------------
 3758|       |          // check needaffix flag
 3759|      4|          !(ptr->getCont() &&
  ------------------
  |  Branch (3759:13): [True: 0, False: 4]
  ------------------
 3760|      0|            ((needaffix &&
  ------------------
  |  Branch (3760:15): [True: 0, False: 0]
  ------------------
 3761|      0|              TESTAFF(ptr->getCont(), needaffix, ptr->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3762|      0|             (circumfix &&
  ------------------
  |  Branch (3762:15): [True: 0, False: 0]
  ------------------
 3763|      0|              TESTAFF(ptr->getCont(), circumfix, ptr->getContLen())) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3764|      0|             (onlyincompound &&
  ------------------
  |  Branch (3764:15): [True: 0, False: 0]
  ------------------
 3765|      4|              TESTAFF(ptr->getCont(), onlyincompound, ptr->getContLen()))))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3766|      4|        std::string newword = ptr->add(ts, wl);
 3767|      4|        if (!newword.empty()) {
  ------------------
  |  Branch (3767:13): [True: 4, False: 0]
  ------------------
 3768|      4|          if (nh < maxn) {
  ------------------
  |  Branch (3768:15): [True: 4, False: 0]
  ------------------
 3769|      4|            wlst[nh].word = mystrdup(newword.c_str());
 3770|      4|            wlst[nh].allow = ptr->allowCross();
 3771|      4|            wlst[nh].orig = nullptr;
 3772|      4|            nh++;
 3773|      4|          }
 3774|      4|        }
 3775|      4|      }
 3776|    922|      ptr = ptr->getFlgNxt();
 3777|    922|    }
 3778|   105k|  }
 3779|       |
 3780|   698k|  return nh;
 3781|   698k|}
_ZNK8AffixMgr12get_reptableEv:
 3784|   394k|const std::vector<replentry>& AffixMgr::get_reptable() const {
 3785|   394k|  return pHMgr->get_reptable();
 3786|   394k|}
_ZNK8AffixMgr14get_iconvtableEv:
 3789|  17.5M|RepList* AffixMgr::get_iconvtable() const {
 3790|  17.5M|  if (!iconvtable)
  ------------------
  |  Branch (3790:7): [True: 17.0M, False: 490k]
  ------------------
 3791|  17.0M|    return nullptr;
 3792|   490k|  return iconvtable;
 3793|  17.5M|}
_ZNK8AffixMgr14get_oconvtableEv:
 3796|   102k|RepList* AffixMgr::get_oconvtable() const {
 3797|   102k|  if (!oconvtable)
  ------------------
  |  Branch (3797:7): [True: 96.7k, False: 5.49k]
  ------------------
 3798|  96.7k|    return nullptr;
 3799|  5.49k|  return oconvtable;
 3800|   102k|}
_ZNK8AffixMgr14get_phonetableEv:
 3803|  62.5k|struct phonetable* AffixMgr::get_phonetable() const {
 3804|  62.5k|  if (!phone)
  ------------------
  |  Branch (3804:7): [True: 58.9k, False: 3.56k]
  ------------------
 3805|  58.9k|    return nullptr;
 3806|  3.56k|  return phone;
 3807|  62.5k|}
_ZNK8AffixMgr12get_maptableEv:
 3810|   394k|const std::vector<mapentry>& AffixMgr::get_maptable() const {
 3811|   394k|  return maptable;
 3812|   394k|}
_ZNK8AffixMgr14get_breaktableEv:
 3815|     38|const std::vector<std::string>& AffixMgr::get_breaktable() const {
 3816|     38|  return breaktable;
 3817|     38|}
_ZN8AffixMgr12get_encodingEv:
 3820|     78|const std::string& AffixMgr::get_encoding() {
 3821|     78|  if (encoding.empty())
  ------------------
  |  Branch (3821:7): [True: 20, False: 58]
  ------------------
 3822|     20|    encoding = SPELL_ENCODING;
  ------------------
  |  |   95|     20|#define SPELL_ENCODING "ISO8859-1"
  ------------------
 3823|     78|  return encoding;
 3824|     78|}
_ZNK8AffixMgr11get_langnumEv:
 3827|     76|int AffixMgr::get_langnum() const {
 3828|     76|  return langnum;
 3829|     76|}
_ZNK8AffixMgr19get_complexprefixesEv:
 3832|     76|int AffixMgr::get_complexprefixes() const {
 3833|     76|  return complexprefixes;
 3834|     76|}
_ZNK8AffixMgr13get_fullstripEv:
 3837|  7.65k|int AffixMgr::get_fullstrip() const {
 3838|  7.65k|  return fullstrip;
 3839|  7.65k|}
_ZNK8AffixMgr12get_keepcaseEv:
 3841|   103k|FLAG AffixMgr::get_keepcase() const {
 3842|   103k|  return keepcase;
 3843|   103k|}
_ZNK8AffixMgr14get_forceucaseEv:
 3845|  19.5k|FLAG AffixMgr::get_forceucase() const {
 3846|  19.5k|  return forceucase;
 3847|  19.5k|}
_ZNK8AffixMgr8get_warnEv:
 3849|  60.0k|FLAG AffixMgr::get_warn() const {
 3850|  60.0k|  return warn;
 3851|  60.0k|}
_ZNK8AffixMgr15get_checksharpsEv:
 3857|   649k|int AffixMgr::get_checksharps() const {
 3858|   649k|  return checksharps;
 3859|   649k|}
_ZNK8AffixMgr10get_ignoreEv:
 3866|  38.5M|const char* AffixMgr::get_ignore() const {
 3867|  38.5M|  if (ignorechars.empty())
  ------------------
  |  Branch (3867:7): [True: 34.8M, False: 3.72M]
  ------------------
 3868|  34.8M|    return nullptr;
 3869|  3.72M|  return ignorechars.c_str();
 3870|  38.5M|}
_ZNK8AffixMgr16get_ignore_utf16Ev:
 3873|   820k|const std::vector<w_char>& AffixMgr::get_ignore_utf16() const {
 3874|   820k|  return ignorechars_utf16;
 3875|   820k|}
_ZN8AffixMgr14get_key_stringEv:
 3878|     38|const std::string& AffixMgr::get_key_string() {
 3879|     38|  if (keystring.empty())
  ------------------
  |  Branch (3879:7): [True: 38, False: 0]
  ------------------
 3880|     38|    keystring = SPELL_KEYSTRING;
  ------------------
  |  |   96|     38|#define SPELL_KEYSTRING "qwertyuiop|asdfghjkl|zxcvbnm"
  ------------------
 3881|     38|  return keystring;
 3882|     38|}
_ZNK8AffixMgr14get_try_stringEv:
 3885|     38|const std::string& AffixMgr::get_try_string() const {
 3886|     38|  return trystring;
 3887|     38|}
_ZNK8AffixMgr12get_compoundEv:
 3899|  81.6M|int AffixMgr::get_compound() const {
 3900|  81.6M|  return compoundflag || compoundbegin || !defcpdtable.empty();
  ------------------
  |  Branch (3900:10): [True: 20.5M, False: 61.1M]
  |  Branch (3900:26): [True: 0, False: 61.1M]
  |  Branch (3900:43): [True: 0, False: 61.1M]
  ------------------
 3901|  81.6M|}
_ZNK8AffixMgr16get_compoundflagEv:
 3904|  61.9k|FLAG AffixMgr::get_compoundflag() const {
 3905|  61.9k|  return compoundflag;
 3906|  61.9k|}
_ZNK8AffixMgr17get_forbiddenwordEv:
 3909|   163k|FLAG AffixMgr::get_forbiddenword() const {
 3910|   163k|  return forbiddenword;
 3911|   163k|}
_ZNK8AffixMgr13get_nosuggestEv:
 3914|  62.6k|FLAG AffixMgr::get_nosuggest() const {
 3915|  62.6k|  return nosuggest;
 3916|  62.6k|}
_ZNK8AffixMgr18get_nongramsuggestEv:
 3919|  62.5k|FLAG AffixMgr::get_nongramsuggest() const {
 3920|  62.5k|  return nongramsuggest;
 3921|  62.5k|}
_ZNK8AffixMgr15get_substandardEv:
 3924|     91|FLAG AffixMgr::get_substandard() const {
 3925|     91|  return substandard;
 3926|     91|}
_ZNK8AffixMgr13get_needaffixEv:
 3929|  1.31k|FLAG AffixMgr::get_needaffix() const {
 3930|  1.31k|  return needaffix;
 3931|  1.31k|}
_ZNK8AffixMgr18get_onlyincompoundEv:
 3939|  63.7k|FLAG AffixMgr::get_onlyincompound() const {
 3940|  63.7k|  return onlyincompound;
 3941|  63.7k|}
_ZN8AffixMgr6lookupEPKcm:
 3949|   563M|struct hentry* AffixMgr::lookup(const char* word, size_t len) {
 3950|   563M|  struct hentry* he = nullptr;
 3951|  1.12G|  for (size_t i = 0; i < alldic.size() && !he; ++i) {
  ------------------
  |  Branch (3951:22): [True: 563M, False: 563M]
  |  Branch (3951:43): [True: 563M, False: 0]
  ------------------
 3952|   563M|    he = alldic[i]->lookup(word, len);
 3953|   563M|  }
 3954|   563M|  return he;
 3955|   563M|}
_ZNK8AffixMgr14have_contclassEv:
 3958|  31.9M|int AffixMgr::have_contclass() const {
 3959|  31.9M|  return havecontclass;
 3960|  31.9M|}
_ZNK8AffixMgr8get_utf8Ev:
 3963|     76|int AffixMgr::get_utf8() const {
 3964|     76|  return utf8;
 3965|     76|}
_ZNK8AffixMgr16get_maxngramsugsEv:
 3967|  70.2k|int AffixMgr::get_maxngramsugs() const {
 3968|  70.2k|  return maxngramsugs;
 3969|  70.2k|}
_ZNK8AffixMgr14get_maxcpdsugsEv:
 3971|     38|int AffixMgr::get_maxcpdsugs() const {
 3972|     38|  return maxcpdsugs;
 3973|     38|}
_ZNK8AffixMgr11get_maxdiffEv:
 3975|  47.4k|int AffixMgr::get_maxdiff() const {
 3976|  47.4k|  return maxdiff;
 3977|  47.4k|}
_ZNK8AffixMgr15get_onlymaxdiffEv:
 3979|  6.80k|int AffixMgr::get_onlymaxdiff() const {
 3980|  6.80k|  return onlymaxdiff;
 3981|  6.80k|}
_ZNK8AffixMgr15get_nosplitsugsEv:
 3984|     38|int AffixMgr::get_nosplitsugs() const {
 3985|     38|  return nosplitsugs;
 3986|     38|}
_ZNK8AffixMgr16get_sugswithdotsEv:
 3989|  3.40k|int AffixMgr::get_sugswithdots() const {
 3990|  3.40k|  return sugswithdots;
 3991|  3.40k|}
_ZN8AffixMgr10parse_flagERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPtP7FileMgr:
 3994|     22|bool AffixMgr::parse_flag(const std::string& line, unsigned short* out, FileMgr* af) {
 3995|     22|  if (*out != FLAG_NULL && !(*out >= DEFAULTFLAGS)) {
  ------------------
  |  |   99|     44|#define FLAG_NULL 0x00
  ------------------
                if (*out != FLAG_NULL && !(*out >= DEFAULTFLAGS)) {
  ------------------
  |  |  122|      2|#define DEFAULTFLAGS 65510
  ------------------
  |  Branch (3995:7): [True: 2, False: 20]
  |  Branch (3995:28): [True: 0, False: 2]
  ------------------
 3996|      0|    HUNSPELL_WARNING(
 3997|      0|        stderr,
 3998|      0|        "error: line %d: multiple definitions of an affix file parameter\n",
 3999|      0|        af->getlinenum());
 4000|      0|    return false;
 4001|      0|  }
 4002|     22|  std::string s;
 4003|     22|  if (!parse_string(line, s, af->getlinenum()))
  ------------------
  |  Branch (4003:7): [True: 0, False: 22]
  ------------------
 4004|      0|    return false;
 4005|     22|  *out = pHMgr->decode_flag(s);
 4006|     22|  return true;
 4007|     22|}
_ZN8AffixMgr9parse_numERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPiP7FileMgr:
 4010|     10|bool AffixMgr::parse_num(const std::string& line, int* out, FileMgr* af) {
 4011|     10|  if (*out != -1) {
  ------------------
  |  Branch (4011:7): [True: 0, False: 10]
  ------------------
 4012|      0|    HUNSPELL_WARNING(
 4013|      0|        stderr,
 4014|      0|        "error: line %d: multiple definitions of an affix file parameter\n",
 4015|      0|        af->getlinenum());
 4016|      0|    return false;
 4017|      0|  }
 4018|     10|  std::string s;
 4019|     10|  if (!parse_string(line, s, af->getlinenum()))
  ------------------
  |  Branch (4019:7): [True: 0, False: 10]
  ------------------
 4020|      0|    return false;
 4021|     10|  *out = atoi(s.c_str());
 4022|     10|  return true;
 4023|     10|}
_ZN8AffixMgr17parse_cpdsyllableERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEP7FileMgr:
 4026|      2|bool AffixMgr::parse_cpdsyllable(const std::string& line, FileMgr* af) {
 4027|      2|  int i = 0;
 4028|      2|  int np = 0;
 4029|      2|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 4030|      8|  while (start_piece != line.end()) {
  ------------------
  |  Branch (4030:10): [True: 6, False: 2]
  ------------------
 4031|      6|    switch (i) {
 4032|      2|      case 0: {
  ------------------
  |  Branch (4032:7): [True: 2, False: 4]
  ------------------
 4033|      2|        np++;
 4034|      2|        break;
 4035|      0|      }
 4036|      2|      case 1: {
  ------------------
  |  Branch (4036:7): [True: 2, False: 4]
  ------------------
 4037|      2|        cpdmaxsyllable = atoi(std::string(start_piece, iter).c_str());
 4038|      2|        np++;
 4039|      2|        break;
 4040|      0|      }
 4041|      2|      case 2: {
  ------------------
  |  Branch (4041:7): [True: 2, False: 4]
  ------------------
 4042|      2|        if (!utf8) {
  ------------------
  |  Branch (4042:13): [True: 0, False: 2]
  ------------------
 4043|      0|          cpdvowels.assign(start_piece, iter);
 4044|      0|          std::sort(cpdvowels.begin(), cpdvowels.end());
 4045|      2|        } else {
 4046|      2|          std::string piece(start_piece, iter);
 4047|      2|          u8_u16(cpdvowels_utf16, piece);
 4048|      2|          std::sort(cpdvowels_utf16.begin(), cpdvowels_utf16.end());
 4049|      2|        }
 4050|      2|        np++;
 4051|      2|        break;
 4052|      0|      }
 4053|      0|      default:
  ------------------
  |  Branch (4053:7): [True: 0, False: 6]
  ------------------
 4054|      0|        break;
 4055|      6|    }
 4056|      6|    ++i;
 4057|      6|    start_piece = mystrsep(line, iter);
 4058|      6|  }
 4059|      2|  if (np < 2) {
  ------------------
  |  Branch (4059:7): [True: 0, False: 2]
  ------------------
 4060|      0|    HUNSPELL_WARNING(stderr,
 4061|      0|                     "error: line %d: missing compoundsyllable information\n",
 4062|      0|                     af->getlinenum());
 4063|      0|    return false;
 4064|      0|  }
 4065|      2|  if (np == 2)
  ------------------
  |  Branch (4065:7): [True: 0, False: 2]
  ------------------
 4066|      0|    cpdvowels = "AEIOUaeiou";
 4067|      2|  return true;
 4068|      2|}
_ZN8AffixMgr15parse_convtableERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEP7FileMgrPP7RepListS8_:
 4073|      4|                              const std::string& keyword) {
 4074|      4|  if (*rl) {
  ------------------
  |  Branch (4074:7): [True: 0, False: 4]
  ------------------
 4075|      0|    HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
 4076|      0|                     af->getlinenum());
 4077|      0|    return false;
 4078|      0|  }
 4079|      4|  int i = 0;
 4080|      4|  int np = 0;
 4081|      4|  int numrl = 0;
 4082|      4|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 4083|     18|  while (start_piece != line.end()) {
  ------------------
  |  Branch (4083:10): [True: 14, False: 4]
  ------------------
 4084|     14|    switch (i) {
 4085|      4|      case 0: {
  ------------------
  |  Branch (4085:7): [True: 4, False: 10]
  ------------------
 4086|      4|        np++;
 4087|      4|        break;
 4088|      0|      }
 4089|      4|      case 1: {
  ------------------
  |  Branch (4089:7): [True: 4, False: 10]
  ------------------
 4090|      4|        numrl = atoi(std::string(start_piece, iter).c_str());
 4091|      4|        if (numrl < 1) {
  ------------------
  |  Branch (4091:13): [True: 0, False: 4]
  ------------------
 4092|      0|          HUNSPELL_WARNING(stderr, "error: line %d: incorrect entry number\n",
 4093|      0|                           af->getlinenum());
 4094|      0|          return false;
 4095|      0|        }
 4096|      4|        *rl = new RepList(numrl);
 4097|      4|        if (!*rl)
  ------------------
  |  Branch (4097:13): [True: 0, False: 4]
  ------------------
 4098|      0|          return false;
 4099|      4|        np++;
 4100|      4|        break;
 4101|      4|      }
 4102|      6|      default:
  ------------------
  |  Branch (4102:7): [True: 6, False: 8]
  ------------------
 4103|      6|        break;
 4104|     14|    }
 4105|     14|    ++i;
 4106|     14|    start_piece = mystrsep(line, iter);
 4107|     14|  }
 4108|      4|  if (np != 2) {
  ------------------
  |  Branch (4108:7): [True: 0, False: 4]
  ------------------
 4109|      0|    HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
 4110|      0|                     af->getlinenum());
 4111|      0|    return false;
 4112|      0|  }
 4113|       |
 4114|       |  /* now parse the num lines to read in the remainder of the table */
 4115|     26|  for (int j = 0; j < numrl; j++) {
  ------------------
  |  Branch (4115:19): [True: 22, False: 4]
  ------------------
 4116|     22|    std::string nl;
 4117|     22|    if (!af->getline(nl))
  ------------------
  |  Branch (4117:9): [True: 0, False: 22]
  ------------------
 4118|      0|      return false;
 4119|     22|    mychomp(nl);
 4120|     22|    i = 0;
 4121|     22|    std::string pattern;
 4122|     22|    std::string pattern2;
 4123|     22|    iter = nl.begin();
 4124|     22|    start_piece = mystrsep(nl, iter);
 4125|    130|    while (start_piece != nl.end()) {
  ------------------
  |  Branch (4125:12): [True: 108, False: 22]
  ------------------
 4126|    108|      {
 4127|    108|        switch (i) {
 4128|     22|          case 0: {
  ------------------
  |  Branch (4128:11): [True: 22, False: 86]
  ------------------
 4129|     22|            if (nl.compare(start_piece - nl.begin(), keyword.size(), keyword, 0, keyword.size()) != 0) {
  ------------------
  |  Branch (4129:17): [True: 0, False: 22]
  ------------------
 4130|      0|              HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4131|      0|                               af->getlinenum());
 4132|      0|              delete *rl;
 4133|      0|              *rl = nullptr;
 4134|      0|              return false;
 4135|      0|            }
 4136|     22|            break;
 4137|     22|          }
 4138|     22|          case 1: {
  ------------------
  |  Branch (4138:11): [True: 22, False: 86]
  ------------------
 4139|     22|            pattern.assign(start_piece, iter);
 4140|     22|            break;
 4141|     22|          }
 4142|     22|          case 2: {
  ------------------
  |  Branch (4142:11): [True: 22, False: 86]
  ------------------
 4143|     22|            pattern2.assign(start_piece, iter);
 4144|     22|            break;
 4145|     22|          }
 4146|     42|          default:
  ------------------
  |  Branch (4146:11): [True: 42, False: 66]
  ------------------
 4147|     42|            break;
 4148|    108|        }
 4149|    108|        ++i;
 4150|    108|      }
 4151|      0|      start_piece = mystrsep(nl, iter);
 4152|    108|    }
 4153|     22|    if (pattern.empty() || pattern2.empty()) {
  ------------------
  |  Branch (4153:9): [True: 0, False: 22]
  |  Branch (4153:28): [True: 0, False: 22]
  ------------------
 4154|      0|      HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4155|      0|                       af->getlinenum());
 4156|      0|      return false;
 4157|      0|    }
 4158|       |
 4159|     22|    (*rl)->add(pattern, pattern2);
 4160|     22|  }
 4161|      4|  return true;
 4162|      4|}
_ZN8AffixMgr16parse_phonetableERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEP7FileMgr:
 4165|      2|bool AffixMgr::parse_phonetable(const std::string& line, FileMgr* af) {
 4166|      2|  if (phone) {
  ------------------
  |  Branch (4166:7): [True: 0, False: 2]
  ------------------
 4167|      0|    HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
 4168|      0|                     af->getlinenum());
 4169|      0|    return false;
 4170|      0|  }
 4171|      2|  std::unique_ptr<phonetable> new_phone;
 4172|      2|  int num = -1;
 4173|      2|  int i = 0;
 4174|      2|  int np = 0;
 4175|      2|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 4176|      6|  while (start_piece != line.end()) {
  ------------------
  |  Branch (4176:10): [True: 4, False: 2]
  ------------------
 4177|      4|    switch (i) {
 4178|      2|      case 0: {
  ------------------
  |  Branch (4178:7): [True: 2, False: 2]
  ------------------
 4179|      2|        np++;
 4180|      2|        break;
 4181|      0|      }
 4182|      2|      case 1: {
  ------------------
  |  Branch (4182:7): [True: 2, False: 2]
  ------------------
 4183|      2|        num = atoi(std::string(start_piece, iter).c_str());
 4184|      2|        if (num < 1) {
  ------------------
  |  Branch (4184:13): [True: 0, False: 2]
  ------------------
 4185|      0|          HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
 4186|      0|                           af->getlinenum());
 4187|      0|          return false;
 4188|      0|        }
 4189|      2|        new_phone = std::make_unique<phonetable>();
 4190|      2|        new_phone->utf8 = (char)utf8;
 4191|      2|        np++;
 4192|      2|        break;
 4193|      2|      }
 4194|      0|      default:
  ------------------
  |  Branch (4194:7): [True: 0, False: 4]
  ------------------
 4195|      0|        break;
 4196|      4|    }
 4197|      4|    ++i;
 4198|      4|    start_piece = mystrsep(line, iter);
 4199|      4|  }
 4200|      2|  if (np != 2) {
  ------------------
  |  Branch (4200:7): [True: 0, False: 2]
  ------------------
 4201|      0|    HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
 4202|      0|                     af->getlinenum());
 4203|      0|    return false;
 4204|      0|  }
 4205|       |
 4206|       |  /* now parse the phone->num lines to read in the remainder of the table */
 4207|    212|  for (int j = 0; j < num; ++j) {
  ------------------
  |  Branch (4207:19): [True: 210, False: 2]
  ------------------
 4208|    210|    std::string nl;
 4209|    210|    if (!af->getline(nl))
  ------------------
  |  Branch (4209:9): [True: 0, False: 210]
  ------------------
 4210|      0|      return false;
 4211|    210|    mychomp(nl);
 4212|    210|    i = 0;
 4213|    210|    const size_t old_size = new_phone->rules.size();
 4214|    210|    iter = nl.begin();
 4215|    210|    start_piece = mystrsep(nl, iter);
 4216|    840|    while (start_piece != nl.end()) {
  ------------------
  |  Branch (4216:12): [True: 630, False: 210]
  ------------------
 4217|    630|      {
 4218|    630|        switch (i) {
 4219|    210|          case 0: {
  ------------------
  |  Branch (4219:11): [True: 210, False: 420]
  ------------------
 4220|    210|            if (nl.compare(start_piece - nl.begin(), 5, "PHONE", 5) != 0) {
  ------------------
  |  Branch (4220:17): [True: 0, False: 210]
  ------------------
 4221|      0|              HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4222|      0|                               af->getlinenum());
 4223|      0|              return false;
 4224|      0|            }
 4225|    210|            break;
 4226|    210|          }
 4227|    210|          case 1: {
  ------------------
  |  Branch (4227:11): [True: 210, False: 420]
  ------------------
 4228|    210|            new_phone->rules.emplace_back(start_piece, iter);
 4229|    210|            break;
 4230|    210|          }
 4231|    210|          case 2: {
  ------------------
  |  Branch (4231:11): [True: 210, False: 420]
  ------------------
 4232|    210|            new_phone->rules.emplace_back(start_piece, iter);
 4233|    210|            mystrrep(new_phone->rules.back(), "_", "");
 4234|    210|            break;
 4235|    210|          }
 4236|      0|          default:
  ------------------
  |  Branch (4236:11): [True: 0, False: 630]
  ------------------
 4237|      0|            break;
 4238|    630|        }
 4239|    630|        ++i;
 4240|    630|      }
 4241|      0|      start_piece = mystrsep(nl, iter);
 4242|    630|    }
 4243|    210|    if (new_phone->rules.size() != old_size + 2) {
  ------------------
  |  Branch (4243:9): [True: 0, False: 210]
  ------------------
 4244|      0|      HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4245|      0|                       af->getlinenum());
 4246|      0|      return false;
 4247|      0|    }
 4248|    210|  }
 4249|      2|  new_phone->rules.emplace_back("");
 4250|      2|  new_phone->rules.emplace_back("");
 4251|      2|  init_phonet_hash(*new_phone);
 4252|      2|  phone = new_phone.release();
 4253|      2|  return true;
 4254|      2|}
_ZN8AffixMgr19parse_checkcpdtableERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEP7FileMgr:
 4257|      2|bool AffixMgr::parse_checkcpdtable(const std::string& line, FileMgr* af) {
 4258|      2|  if (parsedcheckcpd) {
  ------------------
  |  Branch (4258:7): [True: 0, False: 2]
  ------------------
 4259|      0|    HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
 4260|      0|                     af->getlinenum());
 4261|      0|    return false;
 4262|      0|  }
 4263|      2|  parsedcheckcpd = true;
 4264|      2|  int numcheckcpd = -1;
 4265|      2|  int i = 0;
 4266|      2|  int np = 0;
 4267|      2|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 4268|      6|  while (start_piece != line.end()) {
  ------------------
  |  Branch (4268:10): [True: 4, False: 2]
  ------------------
 4269|      4|    switch (i) {
 4270|      2|      case 0: {
  ------------------
  |  Branch (4270:7): [True: 2, False: 2]
  ------------------
 4271|      2|        np++;
 4272|      2|        break;
 4273|      0|      }
 4274|      2|      case 1: {
  ------------------
  |  Branch (4274:7): [True: 2, False: 2]
  ------------------
 4275|      2|        numcheckcpd = atoi(std::string(start_piece, iter).c_str());
 4276|      2|        if (numcheckcpd < 1) {
  ------------------
  |  Branch (4276:13): [True: 0, False: 2]
  ------------------
 4277|      0|          HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
 4278|      0|                           af->getlinenum());
 4279|      0|          return false;
 4280|      0|        }
 4281|      2|        checkcpdtable.reserve(std::min(numcheckcpd, 16384));
 4282|      2|        np++;
 4283|      2|        break;
 4284|      2|      }
 4285|      0|      default:
  ------------------
  |  Branch (4285:7): [True: 0, False: 4]
  ------------------
 4286|      0|        break;
 4287|      4|    }
 4288|      4|    ++i;
 4289|      4|    start_piece = mystrsep(line, iter);
 4290|      4|  }
 4291|      2|  if (np != 2) {
  ------------------
  |  Branch (4291:7): [True: 0, False: 2]
  ------------------
 4292|      0|    HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
 4293|      0|                     af->getlinenum());
 4294|      0|    return false;
 4295|      0|  }
 4296|       |
 4297|       |  /* now parse the numcheckcpd lines to read in the remainder of the table */
 4298|      6|  for (int j = 0; j < numcheckcpd; ++j) {
  ------------------
  |  Branch (4298:19): [True: 4, False: 2]
  ------------------
 4299|      4|    std::string nl;
 4300|      4|    if (!af->getline(nl))
  ------------------
  |  Branch (4300:9): [True: 0, False: 4]
  ------------------
 4301|      0|      return false;
 4302|      4|    mychomp(nl);
 4303|      4|    i = 0;
 4304|      4|    checkcpdtable.emplace_back();
 4305|      4|    iter = nl.begin();
 4306|      4|    start_piece = mystrsep(nl, iter);
 4307|     16|    while (start_piece != nl.end()) {
  ------------------
  |  Branch (4307:12): [True: 12, False: 4]
  ------------------
 4308|     12|      switch (i) {
 4309|      4|        case 0: {
  ------------------
  |  Branch (4309:9): [True: 4, False: 8]
  ------------------
 4310|      4|          if (nl.compare(start_piece - nl.begin(), 20, "CHECKCOMPOUNDPATTERN", 20) != 0) {
  ------------------
  |  Branch (4310:15): [True: 0, False: 4]
  ------------------
 4311|      0|            HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4312|      0|                             af->getlinenum());
 4313|      0|            checkcpdtable.clear();
 4314|      0|            return false;
 4315|      0|          }
 4316|      4|          break;
 4317|      4|        }
 4318|      4|        case 1: {
  ------------------
  |  Branch (4318:9): [True: 4, False: 8]
  ------------------
 4319|      4|          checkcpdtable.back().pattern.assign(start_piece, iter);
 4320|      4|          size_t slash_pos = checkcpdtable.back().pattern.find('/');
 4321|      4|          if (slash_pos != std::string::npos) {
  ------------------
  |  Branch (4321:15): [True: 0, False: 4]
  ------------------
 4322|      0|            std::string chunk(checkcpdtable.back().pattern, slash_pos + 1);
 4323|      0|            checkcpdtable.back().pattern.resize(slash_pos);
 4324|      0|            checkcpdtable.back().cond = pHMgr->decode_flag(chunk);
 4325|      0|          }
 4326|      4|          break;
 4327|      4|        }
 4328|      4|        case 2: {
  ------------------
  |  Branch (4328:9): [True: 4, False: 8]
  ------------------
 4329|      4|          checkcpdtable.back().pattern2.assign(start_piece, iter);
 4330|      4|          size_t slash_pos = checkcpdtable.back().pattern2.find('/');
 4331|      4|          if (slash_pos != std::string::npos) {
  ------------------
  |  Branch (4331:15): [True: 0, False: 4]
  ------------------
 4332|      0|            std::string chunk(checkcpdtable.back().pattern2, slash_pos + 1);
 4333|      0|            checkcpdtable.back().pattern2.resize(slash_pos);
 4334|      0|            checkcpdtable.back().cond2 = pHMgr->decode_flag(chunk);
 4335|      0|          }
 4336|      4|          break;
 4337|      4|        }
 4338|      0|        case 3: {
  ------------------
  |  Branch (4338:9): [True: 0, False: 12]
  ------------------
 4339|      0|          checkcpdtable.back().pattern3.assign(start_piece, iter);
 4340|      0|          simplifiedcpd = 1;
 4341|      0|          break;
 4342|      4|        }
 4343|      0|        default:
  ------------------
  |  Branch (4343:9): [True: 0, False: 12]
  ------------------
 4344|      0|          break;
 4345|     12|      }
 4346|     12|      i++;
 4347|     12|      start_piece = mystrsep(nl, iter);
 4348|     12|    }
 4349|      4|  }
 4350|      2|  return true;
 4351|      2|}
_ZN8AffixMgr14parse_maptableERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEP7FileMgr:
 4455|      2|bool AffixMgr::parse_maptable(const std::string& line, FileMgr* af) {
 4456|      2|  if (parsedmaptable) {
  ------------------
  |  Branch (4456:7): [True: 0, False: 2]
  ------------------
 4457|      0|    HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
 4458|      0|                     af->getlinenum());
 4459|      0|    return false;
 4460|      0|  }
 4461|      2|  parsedmaptable = true;
 4462|      2|  int nummap = -1;
 4463|      2|  int i = 0;
 4464|      2|  int np = 0;
 4465|      2|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 4466|      6|  while (start_piece != line.end()) {
  ------------------
  |  Branch (4466:10): [True: 4, False: 2]
  ------------------
 4467|      4|    switch (i) {
 4468|      2|      case 0: {
  ------------------
  |  Branch (4468:7): [True: 2, False: 2]
  ------------------
 4469|      2|        np++;
 4470|      2|        break;
 4471|      0|      }
 4472|      2|      case 1: {
  ------------------
  |  Branch (4472:7): [True: 2, False: 2]
  ------------------
 4473|      2|        nummap = atoi(std::string(start_piece, iter).c_str());
 4474|      2|        if (nummap < 1) {
  ------------------
  |  Branch (4474:13): [True: 0, False: 2]
  ------------------
 4475|      0|          HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
 4476|      0|                           af->getlinenum());
 4477|      0|          return false;
 4478|      0|        }
 4479|      2|        maptable.reserve(std::min(nummap, 16384));
 4480|      2|        np++;
 4481|      2|        break;
 4482|      2|      }
 4483|      0|      default:
  ------------------
  |  Branch (4483:7): [True: 0, False: 4]
  ------------------
 4484|      0|        break;
 4485|      4|    }
 4486|      4|    ++i;
 4487|      4|    start_piece = mystrsep(line, iter);
 4488|      4|  }
 4489|      2|  if (np != 2) {
  ------------------
  |  Branch (4489:7): [True: 0, False: 2]
  ------------------
 4490|      0|    HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
 4491|      0|                     af->getlinenum());
 4492|      0|    return false;
 4493|      0|  }
 4494|       |
 4495|       |  /* now parse the nummap lines to read in the remainder of the table */
 4496|      8|  for (int j = 0; j < nummap; ++j) {
  ------------------
  |  Branch (4496:19): [True: 6, False: 2]
  ------------------
 4497|      6|    std::string nl;
 4498|      6|    if (!af->getline(nl))
  ------------------
  |  Branch (4498:9): [True: 0, False: 6]
  ------------------
 4499|      0|      return false;
 4500|      6|    mychomp(nl);
 4501|      6|    i = 0;
 4502|      6|    maptable.emplace_back();
 4503|      6|    iter = nl.begin();
 4504|      6|    start_piece = mystrsep(nl, iter);
 4505|     18|    while (start_piece != nl.end()) {
  ------------------
  |  Branch (4505:12): [True: 12, False: 6]
  ------------------
 4506|     12|      switch (i) {
 4507|      6|        case 0: {
  ------------------
  |  Branch (4507:9): [True: 6, False: 6]
  ------------------
 4508|      6|          if (nl.compare(start_piece - nl.begin(), 3, "MAP", 3) != 0) {
  ------------------
  |  Branch (4508:15): [True: 0, False: 6]
  ------------------
 4509|      0|            HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4510|      0|                             af->getlinenum());
 4511|      0|            nummap = 0;
 4512|      0|            return false;
 4513|      0|          }
 4514|      6|          break;
 4515|      6|        }
 4516|      6|        case 1: {
  ------------------
  |  Branch (4516:9): [True: 6, False: 6]
  ------------------
 4517|     22|          for (auto k = start_piece; k != iter; ++k) {
  ------------------
  |  Branch (4517:38): [True: 16, False: 6]
  ------------------
 4518|     16|            auto chb = k, che = k + 1;
 4519|     16|            if (*k == '(') {
  ------------------
  |  Branch (4519:17): [True: 2, False: 14]
  ------------------
 4520|      2|              auto parpos = std::find(k, iter, ')');
 4521|      2|              if (parpos != iter) {
  ------------------
  |  Branch (4521:19): [True: 2, False: 0]
  ------------------
 4522|      2|                chb = k + 1;
 4523|      2|                che = parpos;
 4524|      2|                k = parpos;
 4525|      2|              }
 4526|     14|            } else {
 4527|     14|              if (utf8 && (*k & 0xc0) == 0xc0) {
  ------------------
  |  Branch (4527:19): [True: 14, False: 0]
  |  Branch (4527:27): [True: 10, False: 4]
  ------------------
 4528|     10|                ++k;
 4529|     20|                while (k != iter && is_utf8_cont(*k))
  ------------------
  |  Branch (4529:24): [True: 18, False: 2]
  |  Branch (4529:37): [True: 10, False: 8]
  ------------------
 4530|     10|                    ++k;
 4531|     10|                che = k;
 4532|     10|                --k;
 4533|     10|              }
 4534|     14|            }
 4535|     16|            if (chb == che) {
  ------------------
  |  Branch (4535:17): [True: 0, False: 16]
  ------------------
 4536|      0|              HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4537|      0|                              af->getlinenum());
 4538|      0|            }
 4539|       |
 4540|     16|            maptable.back().emplace_back(chb, che);
 4541|     16|          }
 4542|      6|          break;
 4543|      6|        }
 4544|      0|        default:
  ------------------
  |  Branch (4544:9): [True: 0, False: 12]
  ------------------
 4545|      0|          break;
 4546|     12|      }
 4547|     12|      ++i;
 4548|     12|      start_piece = mystrsep(nl, iter);
 4549|     12|    }
 4550|      6|    if (maptable.back().empty()) {
  ------------------
  |  Branch (4550:9): [True: 0, False: 6]
  ------------------
 4551|      0|      HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4552|      0|                       af->getlinenum());
 4553|      0|      return false;
 4554|      0|    }
 4555|      6|  }
 4556|      2|  return true;
 4557|      2|}
_ZN8AffixMgr16parse_breaktableERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEP7FileMgr:
 4560|      4|bool AffixMgr::parse_breaktable(const std::string& line, FileMgr* af) {
 4561|      4|  if (parsedbreaktable) {
  ------------------
  |  Branch (4561:7): [True: 0, False: 4]
  ------------------
 4562|      0|    HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
 4563|      0|                     af->getlinenum());
 4564|      0|    return false;
 4565|      0|  }
 4566|      4|  parsedbreaktable = true;
 4567|      4|  int numbreak = -1;
 4568|      4|  int i = 0;
 4569|      4|  int np = 0;
 4570|      4|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 4571|     12|  while (start_piece != line.end()) {
  ------------------
  |  Branch (4571:10): [True: 8, False: 4]
  ------------------
 4572|      8|    switch (i) {
 4573|      4|      case 0: {
  ------------------
  |  Branch (4573:7): [True: 4, False: 4]
  ------------------
 4574|      4|        np++;
 4575|      4|        break;
 4576|      0|      }
 4577|      4|      case 1: {
  ------------------
  |  Branch (4577:7): [True: 4, False: 4]
  ------------------
 4578|      4|        numbreak = atoi(std::string(start_piece, iter).c_str());
 4579|      4|        if (numbreak < 0) {
  ------------------
  |  Branch (4579:13): [True: 0, False: 4]
  ------------------
 4580|      0|          HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
 4581|      0|                           af->getlinenum());
 4582|      0|          return false;
 4583|      0|        }
 4584|      4|        if (numbreak == 0)
  ------------------
  |  Branch (4584:13): [True: 0, False: 4]
  ------------------
 4585|      0|          return true;
 4586|      4|        breaktable.reserve(std::min(numbreak, 16384));
 4587|      4|        np++;
 4588|      4|        break;
 4589|      4|      }
 4590|      0|      default:
  ------------------
  |  Branch (4590:7): [True: 0, False: 8]
  ------------------
 4591|      0|        break;
 4592|      8|    }
 4593|      8|    ++i;
 4594|      8|    start_piece = mystrsep(line, iter);
 4595|      8|  }
 4596|      4|  if (np != 2) {
  ------------------
  |  Branch (4596:7): [True: 0, False: 4]
  ------------------
 4597|      0|    HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
 4598|      0|                     af->getlinenum());
 4599|      0|    return false;
 4600|      0|  }
 4601|       |
 4602|       |  /* now parse the numbreak lines to read in the remainder of the table */
 4603|     10|  for (int j = 0; j < numbreak; ++j) {
  ------------------
  |  Branch (4603:19): [True: 6, False: 4]
  ------------------
 4604|      6|    std::string nl;
 4605|      6|    if (!af->getline(nl))
  ------------------
  |  Branch (4605:9): [True: 0, False: 6]
  ------------------
 4606|      0|      return false;
 4607|      6|    mychomp(nl);
 4608|      6|    i = 0;
 4609|      6|    iter = nl.begin();
 4610|      6|    start_piece = mystrsep(nl, iter);
 4611|     18|    while (start_piece != nl.end()) {
  ------------------
  |  Branch (4611:12): [True: 12, False: 6]
  ------------------
 4612|     12|      switch (i) {
 4613|      6|        case 0: {
  ------------------
  |  Branch (4613:9): [True: 6, False: 6]
  ------------------
 4614|      6|          if (nl.compare(start_piece - nl.begin(), 5, "BREAK", 5) != 0) {
  ------------------
  |  Branch (4614:15): [True: 0, False: 6]
  ------------------
 4615|      0|            HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4616|      0|                             af->getlinenum());
 4617|      0|            numbreak = 0;
 4618|      0|            return false;
 4619|      0|          }
 4620|      6|          break;
 4621|      6|        }
 4622|      6|        case 1: {
  ------------------
  |  Branch (4622:9): [True: 6, False: 6]
  ------------------
 4623|      6|          breaktable.emplace_back(start_piece, iter);
 4624|      6|          break;
 4625|      6|        }
 4626|      0|        default:
  ------------------
  |  Branch (4626:9): [True: 0, False: 12]
  ------------------
 4627|      0|          break;
 4628|     12|      }
 4629|     12|      ++i;
 4630|     12|      start_piece = mystrsep(nl, iter);
 4631|     12|    }
 4632|      6|  }
 4633|       |
 4634|      4|  if (breaktable.size() != static_cast<size_t>(numbreak)) {
  ------------------
  |  Branch (4634:7): [True: 0, False: 4]
  ------------------
 4635|      0|    HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 4636|      0|                     af->getlinenum());
 4637|      0|    return false;
 4638|      0|  }
 4639|       |
 4640|      4|  return true;
 4641|      4|}
_ZN8AffixMgr17reverse_conditionERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 4643|     38|void AffixMgr::reverse_condition(std::string& piece) {
 4644|     38|  if (piece.empty())
  ------------------
  |  Branch (4644:7): [True: 0, False: 38]
  ------------------
 4645|      0|      return;
 4646|       |
 4647|     38|  int neg = 0;
 4648|       |  // iterate backwards; k wraps to npos (SIZE_MAX) when decremented past 0
 4649|     92|  for (size_t k = piece.size() - 1; k != std::string::npos; --k) {
  ------------------
  |  Branch (4649:37): [True: 54, False: 38]
  ------------------
 4650|     54|    switch (piece[k]) {
 4651|      2|      case '[': {
  ------------------
  |  Branch (4651:7): [True: 2, False: 52]
  ------------------
 4652|      2|        if (neg)
  ------------------
  |  Branch (4652:13): [True: 0, False: 2]
  ------------------
 4653|      0|          piece[k + 1] = '[';
 4654|      2|        else
 4655|      2|          piece[k] = ']';
 4656|      2|        break;
 4657|      0|      }
 4658|      2|      case ']': {
  ------------------
  |  Branch (4658:7): [True: 2, False: 52]
  ------------------
 4659|      2|        piece[k] = '[';
 4660|      2|        if (neg)
  ------------------
  |  Branch (4660:13): [True: 0, False: 2]
  ------------------
 4661|      0|          piece[k + 1] = '^';
 4662|      2|        neg = 0;
 4663|      2|        break;
 4664|      0|      }
 4665|      0|      case '^': {
  ------------------
  |  Branch (4665:7): [True: 0, False: 54]
  ------------------
 4666|      0|        if (piece[k + 1] == ']')
  ------------------
  |  Branch (4666:13): [True: 0, False: 0]
  ------------------
 4667|      0|          neg = 1;
 4668|      0|        else if (neg)
  ------------------
  |  Branch (4668:18): [True: 0, False: 0]
  ------------------
 4669|      0|          piece[k + 1] = piece[k];
 4670|      0|        break;
 4671|      0|      }
 4672|     50|      default: {
  ------------------
  |  Branch (4672:7): [True: 50, False: 4]
  ------------------
 4673|     50|        if (neg)
  ------------------
  |  Branch (4673:13): [True: 0, False: 50]
  ------------------
 4674|      0|          piece[k + 1] = piece[k];
 4675|     50|      }
 4676|     54|    }
 4677|     54|  }
 4678|     38|}
_ZN8AffixMgr11parse_affixERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEcP7FileMgrPc:
 4732|     26|                          char* dupflags) {
 4733|     26|  int numents = 0;  // number of AffEntry structures to parse
 4734|       |
 4735|     26|  unsigned short aflag = 0;  // affix char identifier
 4736|       |
 4737|     26|  char ff = 0;
 4738|     26|  char xprod = 0;
 4739|     26|  int headerline = af->getlinenum();
 4740|     26|  entries_container affentries(at, this);
 4741|       |
 4742|     26|  int i = 0;
 4743|       |
 4744|       |// checking lines with bad syntax
 4745|       |#ifdef DEBUG
 4746|       |  int basefieldnum = 0;
 4747|       |#endif
 4748|       |
 4749|       |  // split affix header line into pieces
 4750|       |
 4751|     26|  int np = 0;
 4752|     26|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 4753|    130|  while (start_piece != line.end()) {
  ------------------
  |  Branch (4753:10): [True: 104, False: 26]
  ------------------
 4754|    104|    switch (i) {
 4755|       |      // piece 1 - is type of affix
 4756|     26|      case 0: {
  ------------------
  |  Branch (4756:7): [True: 26, False: 78]
  ------------------
 4757|     26|        np++;
 4758|     26|        break;
 4759|      0|      }
 4760|       |
 4761|       |      // piece 2 - is affix char
 4762|     26|      case 1: {
  ------------------
  |  Branch (4762:7): [True: 26, False: 78]
  ------------------
 4763|     26|        np++;
 4764|     26|        aflag = pHMgr->decode_flag(std::string(start_piece, iter));
 4765|     26|        if (((at == 'S') && (dupflags[aflag] & dupSFX)) ||
  ------------------
  |  |   90|     18|#define dupSFX (1 << 0)
  ------------------
  |  Branch (4765:14): [True: 18, False: 8]
  |  Branch (4765:29): [True: 0, False: 18]
  ------------------
 4766|     26|            ((at == 'P') && (dupflags[aflag] & dupPFX))) {
  ------------------
  |  |   91|      8|#define dupPFX (1 << 1)
  ------------------
  |  Branch (4766:14): [True: 8, False: 18]
  |  Branch (4766:29): [True: 0, False: 8]
  ------------------
 4767|      0|          HUNSPELL_WARNING(
 4768|      0|              stderr,
 4769|      0|              "error: line %d: multiple definitions of an affix flag\n",
 4770|      0|              af->getlinenum());
 4771|      0|        }
 4772|     26|        dupflags[aflag] = static_cast<char>(dupflags[aflag] + ((at == 'S') ? dupSFX : dupPFX));
  ------------------
  |  |   90|     18|#define dupSFX (1 << 0)
  ------------------
                      dupflags[aflag] = static_cast<char>(dupflags[aflag] + ((at == 'S') ? dupSFX : dupPFX));
  ------------------
  |  |   91|      8|#define dupPFX (1 << 1)
  ------------------
  |  Branch (4772:64): [True: 18, False: 8]
  ------------------
 4773|     26|        break;
 4774|      0|      }
 4775|       |      // piece 3 - is cross product indicator
 4776|     26|      case 2: {
  ------------------
  |  Branch (4776:7): [True: 26, False: 78]
  ------------------
 4777|     26|        np++;
 4778|     26|        xprod = *start_piece;
 4779|     26|        if (xprod == 'Y')
  ------------------
  |  Branch (4779:13): [True: 26, False: 0]
  ------------------
 4780|     26|          ff = aeXPRODUCT;
  ------------------
  |  |   65|     26|#define aeXPRODUCT (1 << 0)
  ------------------
 4781|     26|        break;
 4782|      0|      }
 4783|       |
 4784|       |      // piece 4 - is number of affentries
 4785|     26|      case 3: {
  ------------------
  |  Branch (4785:7): [True: 26, False: 78]
  ------------------
 4786|     26|        np++;
 4787|     26|        numents = atoi(std::string(start_piece, iter).c_str());
 4788|     26|        if ((numents <= 0) || ((std::numeric_limits<size_t>::max() /
  ------------------
  |  Branch (4788:13): [True: 0, False: 26]
  |  Branch (4788:31): [True: 0, False: 26]
  ------------------
 4789|     26|                                sizeof(AffEntry)) < static_cast<size_t>(numents))) {
 4790|      0|          std::string err = pHMgr->encode_flag(aflag);
 4791|      0|          HUNSPELL_WARNING(stderr, "error: line %d: affix %s: bad entry number\n",
 4792|      0|                           af->getlinenum(), err.c_str());
 4793|      0|          return false;
 4794|      0|        }
 4795|       |
 4796|     26|        char opts = ff;
 4797|     26|        if (utf8)
  ------------------
  |  Branch (4797:13): [True: 6, False: 20]
  ------------------
 4798|      6|          opts |= aeUTF8;
  ------------------
  |  |   66|      6|#define aeUTF8 (1 << 1)
  ------------------
 4799|     26|        if (pHMgr->is_aliasf())
  ------------------
  |  Branch (4799:13): [True: 4, False: 22]
  ------------------
 4800|      4|          opts |= aeALIASF;
  ------------------
  |  |   67|      4|#define aeALIASF (1 << 2)
  ------------------
 4801|     26|        if (pHMgr->is_aliasm())
  ------------------
  |  Branch (4801:13): [True: 0, False: 26]
  ------------------
 4802|      0|          opts |= aeALIASM;
  ------------------
  |  |   68|      0|#define aeALIASM (1 << 3)
  ------------------
 4803|     26|        affentries.initialize(numents, opts, aflag);
 4804|     26|      }
 4805|       |
 4806|     26|      default:
  ------------------
  |  Branch (4806:7): [True: 0, False: 104]
  ------------------
 4807|     26|        break;
 4808|    104|    }
 4809|    104|    ++i;
 4810|    104|    start_piece = mystrsep(line, iter);
 4811|    104|  }
 4812|       |  // check to make sure we parsed enough pieces
 4813|     26|  if (np != 4) {
  ------------------
  |  Branch (4813:7): [True: 0, False: 26]
  ------------------
 4814|      0|    std::string err = pHMgr->encode_flag(aflag);
 4815|      0|    HUNSPELL_WARNING(stderr, "error: line %d: affix %s: missing data\n",
 4816|      0|                     af->getlinenum(), err.c_str());
 4817|      0|    return false;
 4818|      0|  }
 4819|       |
 4820|       |  // now parse numents affentries for this affix
 4821|     26|  AffEntry* entry = affentries.first_entry();
 4822|     68|  for (int ent = 0; ent < numents; ++ent) {
  ------------------
  |  Branch (4822:21): [True: 42, False: 26]
  ------------------
 4823|     42|    std::string nl;
 4824|     42|    if (!af->getline(nl))
  ------------------
  |  Branch (4824:9): [True: 0, False: 42]
  ------------------
 4825|      0|      return false;
 4826|     42|    mychomp(nl);
 4827|     42|    int ruleline = af->getlinenum();
 4828|       |
 4829|     42|    iter = nl.begin();
 4830|     42|    i = 0;
 4831|     42|    np = 0;
 4832|       |
 4833|       |    // split line into pieces
 4834|     42|    start_piece = mystrsep(nl, iter);
 4835|    258|    while (start_piece != nl.end()) {
  ------------------
  |  Branch (4835:12): [True: 216, False: 42]
  ------------------
 4836|    216|      switch (i) {
 4837|       |        // piece 1 - is type
 4838|     42|        case 0: {
  ------------------
  |  Branch (4838:9): [True: 42, False: 174]
  ------------------
 4839|     42|          np++;
 4840|     42|          if (ent != 0)
  ------------------
  |  Branch (4840:15): [True: 16, False: 26]
  ------------------
 4841|     16|            entry = affentries.add_entry((char)(aeXPRODUCT | aeUTF8 | aeALIASF | aeALIASM));
  ------------------
  |  |   65|     16|#define aeXPRODUCT (1 << 0)
  ------------------
                          entry = affentries.add_entry((char)(aeXPRODUCT | aeUTF8 | aeALIASF | aeALIASM));
  ------------------
  |  |   66|     16|#define aeUTF8 (1 << 1)
  ------------------
                          entry = affentries.add_entry((char)(aeXPRODUCT | aeUTF8 | aeALIASF | aeALIASM));
  ------------------
  |  |   67|     16|#define aeALIASF (1 << 2)
  ------------------
                          entry = affentries.add_entry((char)(aeXPRODUCT | aeUTF8 | aeALIASF | aeALIASM));
  ------------------
  |  |   68|     16|#define aeALIASM (1 << 3)
  ------------------
 4842|     42|          break;
 4843|      0|        }
 4844|       |
 4845|       |        // piece 2 - is affix char
 4846|     42|        case 1: {
  ------------------
  |  Branch (4846:9): [True: 42, False: 174]
  ------------------
 4847|     42|          np++;
 4848|     42|          std::string chunk(start_piece, iter);
 4849|     42|          if (pHMgr->decode_flag(chunk) != aflag) {
  ------------------
  |  Branch (4849:15): [True: 0, False: 42]
  ------------------
 4850|      0|            std::string err = pHMgr->encode_flag(aflag);
 4851|      0|            HUNSPELL_WARNING(stderr,
 4852|      0|                             "error: line %d: affix %s is corrupt\n",
 4853|      0|                             af->getlinenum(), err.c_str());
 4854|      0|            return false;
 4855|      0|          }
 4856|       |
 4857|     42|          if (ent != 0) {
  ------------------
  |  Branch (4857:15): [True: 16, False: 26]
  ------------------
 4858|     16|            AffEntry* start_entry = affentries.first_entry();
 4859|     16|            entry->aflag = start_entry->aflag;
 4860|     16|          }
 4861|     42|          break;
 4862|     42|        }
 4863|       |
 4864|       |        // piece 3 - is string to strip or 0 for null
 4865|     42|        case 2: {
  ------------------
  |  Branch (4865:9): [True: 42, False: 174]
  ------------------
 4866|     42|          np++;
 4867|     42|          entry->strip = std::string(start_piece, iter);
 4868|     42|          if (complexprefixes) {
  ------------------
  |  Branch (4868:15): [True: 4, False: 38]
  ------------------
 4869|      4|            if (utf8)
  ------------------
  |  Branch (4869:17): [True: 0, False: 4]
  ------------------
 4870|      0|              reverseword_utf(entry->strip);
 4871|      4|            else
 4872|      4|              reverseword(entry->strip);
 4873|      4|          }
 4874|     42|          if (entry->strip.compare("0") == 0) {
  ------------------
  |  Branch (4874:15): [True: 36, False: 6]
  ------------------
 4875|     36|            entry->strip.clear();
 4876|     36|          }
 4877|     42|          break;
 4878|     42|        }
 4879|       |
 4880|       |        // piece 4 - is affix string or 0 for null
 4881|     42|        case 3: {
  ------------------
  |  Branch (4881:9): [True: 42, False: 174]
  ------------------
 4882|     42|          entry->morphcode = nullptr;
 4883|     42|          entry->contclass = nullptr;
 4884|     42|          entry->contclasslen = 0;
 4885|     42|          np++;
 4886|     42|          std::string::const_iterator dash = std::find(start_piece, iter, '/');
 4887|     42|          if (dash != iter) {
  ------------------
  |  Branch (4887:15): [True: 18, False: 24]
  ------------------
 4888|     18|            entry->appnd = std::string(start_piece, dash);
 4889|     18|            std::string dash_str(dash + 1, iter);
 4890|       |
 4891|     18|            if (!ignorechars.empty() && !has_no_ignored_chars(entry->appnd, ignorechars)) {
  ------------------
  |  Branch (4891:17): [True: 2, False: 16]
  |  Branch (4891:41): [True: 0, False: 2]
  ------------------
 4892|      0|              if (utf8) {
  ------------------
  |  Branch (4892:19): [True: 0, False: 0]
  ------------------
 4893|      0|                remove_ignored_chars_utf(entry->appnd, ignorechars_utf16);
 4894|      0|              } else {
 4895|      0|                remove_ignored_chars(entry->appnd, ignorechars);
 4896|      0|              }
 4897|      0|            }
 4898|       |
 4899|     18|            if (complexprefixes) {
  ------------------
  |  Branch (4899:17): [True: 2, False: 16]
  ------------------
 4900|      2|              if (utf8)
  ------------------
  |  Branch (4900:19): [True: 0, False: 2]
  ------------------
 4901|      0|                reverseword_utf(entry->appnd);
 4902|      2|              else
 4903|      2|                reverseword(entry->appnd);
 4904|      2|            }
 4905|       |
 4906|     18|            if (pHMgr->is_aliasf()) {
  ------------------
  |  Branch (4906:17): [True: 2, False: 16]
  ------------------
 4907|      2|              int index = atoi(dash_str.c_str());
 4908|      2|              entry->contclasslen = (unsigned short)pHMgr->get_aliasf(
 4909|      2|                  index, &(entry->contclass), af);
 4910|      2|              if (!entry->contclasslen)
  ------------------
  |  Branch (4910:19): [True: 0, False: 2]
  ------------------
 4911|      0|                HUNSPELL_WARNING(stderr,
 4912|      0|                                 "error: bad affix flag alias: \"%s\"\n",
 4913|      0|                                 dash_str.c_str());
 4914|     16|            } else {
 4915|     16|              entry->contclasslen = (unsigned short)pHMgr->decode_flags(
 4916|     16|                  &(entry->contclass), dash_str, af);
 4917|     16|              std::sort(entry->contclass, entry->contclass + entry->contclasslen);
 4918|     16|            }
 4919|       |
 4920|     18|            havecontclass = 1;
 4921|     44|            for (unsigned short _i = 0; _i < entry->contclasslen; _i++) {
  ------------------
  |  Branch (4921:41): [True: 26, False: 18]
  ------------------
 4922|     26|              contclasses[(entry->contclass)[_i]] = true;
 4923|     26|            }
 4924|     24|          } else {
 4925|     24|            entry->appnd = std::string(start_piece, iter);
 4926|       |
 4927|     24|            if (!ignorechars.empty() && !has_no_ignored_chars(entry->appnd, ignorechars)) {
  ------------------
  |  Branch (4927:17): [True: 2, False: 22]
  |  Branch (4927:41): [True: 2, False: 0]
  ------------------
 4928|      2|              if (utf8) {
  ------------------
  |  Branch (4928:19): [True: 0, False: 2]
  ------------------
 4929|      0|                remove_ignored_chars_utf(entry->appnd, ignorechars_utf16);
 4930|      2|              } else {
 4931|      2|                remove_ignored_chars(entry->appnd, ignorechars);
 4932|      2|              }
 4933|      2|            }
 4934|       |
 4935|     24|            if (complexprefixes) {
  ------------------
  |  Branch (4935:17): [True: 2, False: 22]
  ------------------
 4936|      2|              if (utf8)
  ------------------
  |  Branch (4936:19): [True: 0, False: 2]
  ------------------
 4937|      0|                reverseword_utf(entry->appnd);
 4938|      2|              else
 4939|      2|                reverseword(entry->appnd);
 4940|      2|            }
 4941|     24|          }
 4942|       |
 4943|     42|          if (entry->appnd.compare("0") == 0) {
  ------------------
  |  Branch (4943:15): [True: 2, False: 40]
  ------------------
 4944|      2|            entry->appnd.clear();
 4945|      2|          }
 4946|     42|          break;
 4947|     42|        }
 4948|       |
 4949|       |        // piece 5 - is the conditions descriptions
 4950|     42|        case 4: {
  ------------------
  |  Branch (4950:9): [True: 42, False: 174]
  ------------------
 4951|     42|          std::string chunk(start_piece, iter);
 4952|     42|          np++;
 4953|     42|          if (complexprefixes) {
  ------------------
  |  Branch (4953:15): [True: 4, False: 38]
  ------------------
 4954|      4|            if (utf8)
  ------------------
  |  Branch (4954:17): [True: 0, False: 4]
  ------------------
 4955|      0|              reverseword_utf(chunk);
 4956|      4|            else
 4957|      4|              reverseword(chunk);
 4958|      4|            reverse_condition(chunk);
 4959|      4|          }
 4960|     42|          if (!entry->strip.empty() && chunk != "." &&
  ------------------
  |  Branch (4960:15): [True: 6, False: 36]
  |  Branch (4960:40): [True: 6, False: 0]
  ------------------
 4961|      6|              redundant_condition(at, entry->strip, chunk,
  ------------------
  |  Branch (4961:15): [True: 6, False: 0]
  ------------------
 4962|      6|                                  af->getlinenum())) {
 4963|      6|            chunk = ".";
 4964|      6|            entry->opts |= aeREDUNDANTCOND;
  ------------------
  |  |   72|      6|#define aeREDUNDANTCOND (1 << 5)
  ------------------
 4965|      6|          }
 4966|     42|          if (at == 'S') {
  ------------------
  |  Branch (4966:15): [True: 34, False: 8]
  ------------------
 4967|     34|            reverseword(chunk);
 4968|     34|            reverse_condition(chunk);
 4969|     34|          }
 4970|     42|          if (encodeit(*entry, chunk))
  ------------------
  |  Branch (4970:15): [True: 0, False: 42]
  ------------------
 4971|      0|            return false;
 4972|     42|          break;
 4973|     42|        }
 4974|       |
 4975|     42|        case 5: {
  ------------------
  |  Branch (4975:9): [True: 6, False: 210]
  ------------------
 4976|      6|          std::string chunk(start_piece, iter);
 4977|      6|          np++;
 4978|      6|          if (pHMgr->is_aliasm()) {
  ------------------
  |  Branch (4978:15): [True: 0, False: 6]
  ------------------
 4979|      0|            int index = atoi(chunk.c_str());
 4980|      0|            entry->morphcode = pHMgr->get_aliasm(index);
 4981|      6|          } else {
 4982|      6|            if (complexprefixes) {  // XXX - fix me for morph. gen.
  ------------------
  |  Branch (4982:17): [True: 0, False: 6]
  ------------------
 4983|      0|              if (utf8)
  ------------------
  |  Branch (4983:19): [True: 0, False: 0]
  ------------------
 4984|      0|                reverseword_utf(chunk);
 4985|      0|              else
 4986|      0|                reverseword(chunk);
 4987|      0|            }
 4988|       |            // add the remaining of the line
 4989|      6|            std::string::const_iterator end = nl.end();
 4990|      6|            if (iter != end) {
  ------------------
  |  Branch (4990:17): [True: 0, False: 6]
  ------------------
 4991|      0|              chunk.append(iter, end);
 4992|      0|            }
 4993|      6|            entry->morphcode = mystrdup(chunk.c_str());
 4994|      6|          }
 4995|      6|          break;
 4996|     42|        }
 4997|      0|        default:
  ------------------
  |  Branch (4997:9): [True: 0, False: 216]
  ------------------
 4998|      0|          break;
 4999|    216|      }
 5000|    216|      i++;
 5001|    216|      start_piece = mystrsep(nl, iter);
 5002|    216|    }
 5003|       |    // check to make sure we parsed enough pieces
 5004|     42|    if (np < 4) {
  ------------------
  |  Branch (5004:9): [True: 0, False: 42]
  ------------------
 5005|      0|      std::string err = pHMgr->encode_flag(aflag);
 5006|      0|      HUNSPELL_WARNING(stderr, "error: line %d: affix %s is corrupt\n",
 5007|      0|                       af->getlinenum(), err.c_str());
 5008|      0|      return false;
 5009|      0|    }
 5010|       |
 5011|     42|    entry->line = ruleline;
 5012|     42|    entry->headerline = headerline;
 5013|     42|    entry->xprod = xprod;
 5014|       |
 5015|       |#ifdef DEBUG
 5016|       |    // detect unnecessary fields, excepting comments
 5017|       |    if (basefieldnum) {
 5018|       |      int fieldnum =
 5019|       |          !(entry->morphcode) ? 5 : ((*(entry->morphcode) == '#') ? 5 : 6);
 5020|       |      if (fieldnum != basefieldnum)
 5021|       |        HUNSPELL_WARNING(stderr, "warning: line %d: bad field number\n",
 5022|       |                         af->getlinenum());
 5023|       |    } else {
 5024|       |      basefieldnum =
 5025|       |          !(entry->morphcode) ? 5 : ((*(entry->morphcode) == '#') ? 5 : 6);
 5026|       |    }
 5027|       |#endif
 5028|     42|  }
 5029|       |
 5030|       |  // now create SfxEntry or PfxEntry objects and use links to
 5031|       |  // build an ordered (sorted by affix string) list
 5032|     26|  auto start = affentries.begin(), end = affentries.end();
 5033|     68|  for (auto affentry = start; affentry != end; ++affentry) {
  ------------------
  |  Branch (5033:31): [True: 42, False: 26]
  ------------------
 5034|     42|    if (at == 'P') {
  ------------------
  |  Branch (5034:9): [True: 8, False: 34]
  ------------------
 5035|      8|      build_pfxtree(static_cast<PfxEntry*>(*affentry));
 5036|     34|    } else {
 5037|     34|      build_sfxtree(static_cast<SfxEntry*>(*affentry));
 5038|     34|    }
 5039|     42|  }
 5040|       |
 5041|       |  //contents belong to AffixMgr now
 5042|     26|  affentries.release();
 5043|       |
 5044|     26|  return true;
 5045|     26|}
_ZN8AffixMgr19redundant_conditionEcRKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_i:
 5050|      6|                                  int linenum) {
 5051|       |  // both strings come from one affix file line, which is read into a buffer of BUFSIZE + 50 bytes,
 5052|       |  // so each length fits an int
 5053|      6|  int stripl = static_cast<int>(strip.size()), condl = static_cast<int>(cond.size()), i, j, neg, in;
 5054|      6|  if (ft == 'P') {  // prefix
  ------------------
  |  Branch (5054:7): [True: 0, False: 6]
  ------------------
 5055|      0|    if (strip.compare(0, condl, cond) == 0)
  ------------------
  |  Branch (5055:9): [True: 0, False: 0]
  ------------------
 5056|      0|      return 1;
 5057|      0|    if (utf8) {
  ------------------
  |  Branch (5057:9): [True: 0, False: 0]
  ------------------
 5058|      0|    } else {
 5059|      0|      for (i = 0, j = 0; (i < stripl) && (j < condl); i++, j++) {
  ------------------
  |  Branch (5059:26): [True: 0, False: 0]
  |  Branch (5059:42): [True: 0, False: 0]
  ------------------
 5060|      0|        if (cond[j] != '[') {
  ------------------
  |  Branch (5060:13): [True: 0, False: 0]
  ------------------
 5061|      0|          if (cond[j] != strip[i]) {
  ------------------
  |  Branch (5061:15): [True: 0, False: 0]
  ------------------
 5062|      0|            HUNSPELL_WARNING(stderr,
 5063|      0|                             "warning: line %d: incompatible stripping "
 5064|      0|                             "characters and condition\n",
 5065|      0|                             linenum);
 5066|      0|            return 0;
 5067|      0|          }
 5068|      0|        } else {
 5069|      0|          neg = (cond[j + 1] == '^') ? 1 : 0;
  ------------------
  |  Branch (5069:17): [True: 0, False: 0]
  ------------------
 5070|      0|          in = 0;
 5071|      0|          do {
 5072|      0|            j++;
 5073|      0|            if (strip[i] == cond[j])
  ------------------
  |  Branch (5073:17): [True: 0, False: 0]
  ------------------
 5074|      0|              in = 1;
 5075|      0|          } while ((j < (condl - 1)) && (cond[j] != ']'));
  ------------------
  |  Branch (5075:20): [True: 0, False: 0]
  |  Branch (5075:41): [True: 0, False: 0]
  ------------------
 5076|      0|          if (j == (condl - 1) && (cond[j] != ']')) {
  ------------------
  |  Branch (5076:15): [True: 0, False: 0]
  |  Branch (5076:35): [True: 0, False: 0]
  ------------------
 5077|      0|            HUNSPELL_WARNING(stderr,
 5078|      0|                             "error: line %d: missing ] in condition:\n%s\n",
 5079|      0|                             linenum, cond.c_str());
 5080|      0|            return 0;
 5081|      0|          }
 5082|      0|          if ((!neg && !in) || (neg && in)) {
  ------------------
  |  Branch (5082:16): [True: 0, False: 0]
  |  Branch (5082:24): [True: 0, False: 0]
  |  Branch (5082:33): [True: 0, False: 0]
  |  Branch (5082:40): [True: 0, False: 0]
  ------------------
 5083|      0|            HUNSPELL_WARNING(stderr,
 5084|      0|                             "warning: line %d: incompatible stripping "
 5085|      0|                             "characters and condition\n",
 5086|      0|                             linenum);
 5087|      0|            return 0;
 5088|      0|          }
 5089|      0|        }
 5090|      0|      }
 5091|      0|      if (j >= condl)
  ------------------
  |  Branch (5091:11): [True: 0, False: 0]
  ------------------
 5092|      0|        return 1;
 5093|      0|    }
 5094|      6|  } else {  // suffix
 5095|      6|    if ((stripl >= condl) && strip.compare(stripl - condl, std::string::npos, cond) == 0)
  ------------------
  |  Branch (5095:9): [True: 6, False: 0]
  |  Branch (5095:30): [True: 6, False: 0]
  ------------------
 5096|      6|      return 1;
 5097|      0|    if (utf8) {
  ------------------
  |  Branch (5097:9): [True: 0, False: 0]
  ------------------
 5098|      0|    } else {
 5099|      0|      for (i = stripl - 1, j = condl - 1; (i >= 0) && (j >= 0); i--, j--) {
  ------------------
  |  Branch (5099:43): [True: 0, False: 0]
  |  Branch (5099:55): [True: 0, False: 0]
  ------------------
 5100|      0|        if (cond[j] != ']') {
  ------------------
  |  Branch (5100:13): [True: 0, False: 0]
  ------------------
 5101|      0|          if (cond[j] != strip[i]) {
  ------------------
  |  Branch (5101:15): [True: 0, False: 0]
  ------------------
 5102|      0|            HUNSPELL_WARNING(stderr,
 5103|      0|                             "warning: line %d: incompatible stripping "
 5104|      0|                             "characters and condition\n",
 5105|      0|                             linenum);
 5106|      0|            return 0;
 5107|      0|          }
 5108|      0|        } else if (j > 0) {
  ------------------
  |  Branch (5108:20): [True: 0, False: 0]
  ------------------
 5109|      0|          in = 0;
 5110|      0|          do {
 5111|      0|            j--;
 5112|      0|            if (strip[i] == cond[j])
  ------------------
  |  Branch (5112:17): [True: 0, False: 0]
  ------------------
 5113|      0|              in = 1;
 5114|      0|          } while ((j > 0) && (cond[j] != '['));
  ------------------
  |  Branch (5114:20): [True: 0, False: 0]
  |  Branch (5114:31): [True: 0, False: 0]
  ------------------
 5115|      0|          if ((j == 0) && (cond[j] != '[')) {
  ------------------
  |  Branch (5115:15): [True: 0, False: 0]
  |  Branch (5115:27): [True: 0, False: 0]
  ------------------
 5116|      0|            HUNSPELL_WARNING(stderr,
 5117|      0|                             "error: line: %d: missing ] in condition:\n%s\n",
 5118|      0|                             linenum, cond.c_str());
 5119|      0|            return 0;
 5120|      0|          }
 5121|      0|          neg = (cond[j + 1] == '^') ? 1 : 0;
  ------------------
  |  Branch (5121:17): [True: 0, False: 0]
  ------------------
 5122|      0|          if ((!neg && !in) || (neg && in)) {
  ------------------
  |  Branch (5122:16): [True: 0, False: 0]
  |  Branch (5122:24): [True: 0, False: 0]
  |  Branch (5122:33): [True: 0, False: 0]
  |  Branch (5122:40): [True: 0, False: 0]
  ------------------
 5123|      0|            HUNSPELL_WARNING(stderr,
 5124|      0|                             "warning: line %d: incompatible stripping "
 5125|      0|                             "characters and condition\n",
 5126|      0|                             linenum);
 5127|      0|            return 0;
 5128|      0|          }
 5129|      0|        }
 5130|      0|      }
 5131|      0|      if (j < 0)
  ------------------
  |  Branch (5131:11): [True: 0, False: 0]
  ------------------
 5132|      0|        return 1;
 5133|      0|    }
 5134|      0|  }
 5135|      0|  return 0;
 5136|      6|}
_ZN8AffixMgr8isSubsetEPKcS1_:
 1123|   124k|inline int AffixMgr::isSubset(const char* s1, const char* s2) {
 1124|   177k|  while (((*s1 == *s2) || (*s1 == '.')) && (*s1 != '\0') && (*s2 != '\0')) {
  ------------------
  |  Branch (1124:11): [True: 124k, False: 52.1k]
  |  Branch (1124:27): [True: 0, False: 52.1k]
  |  Branch (1124:44): [True: 52.5k, False: 72.2k]
  |  Branch (1124:61): [True: 52.5k, False: 0]
  ------------------
 1125|  52.5k|    s1++;
 1126|  52.5k|    s2++;
 1127|  52.5k|  }
 1128|   124k|  return (*s1 == '\0');
 1129|   124k|}
affixmgr.cxx:_ZN12_GLOBAL__N_115DistinctRecordsC2Ec:
   97|  31.3k|    explicit DistinctRecords(char breakchar) : sep(breakchar) {}
affixmgr.cxx:_ZNK12_GLOBAL__N_115DistinctRecords4joinEv:
  117|  31.3k|    std::string join() const {
  118|  31.3k|      std::string text;
  119|  31.3k|      for (const std::string& record : records) {
  ------------------
  |  Branch (119:38): [True: 0, False: 31.3k]
  ------------------
  120|      0|        text.append(record);
  121|      0|        text.push_back(sep);
  122|      0|      }
  123|  31.3k|      return text;
  124|  31.3k|    }
affixmgr.cxx:_ZZN8AffixMgr12suffix_checkERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmiP8PfxEntryR12AffixScratchttctENK3$_1clEP8SfxEntry:
 3040|   142k|                         &candidates](SfxEntry* se) {
 3041|   142k|    if (!t)
  ------------------
  |  Branch (3041:9): [True: 142k, False: 0]
  ------------------
 3042|   142k|      return;
 3043|      0|    ++candidates;
 3044|      0|    trace_affix(*t, "sfx", this, *se);
 3045|      0|    TraceScope trace_depth(t);
 3046|      0|    (void)suffix_applicable(ppfx, se, cclass, in_compound, t);
 3047|      0|  };
affixmgr.cxx:_ZZN8AffixMgr12suffix_checkERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmiP8PfxEntryR12AffixScratchttctENK3$_0clEv:
 3032|   584M|  auto report_empty_pass = [t, &word, start, len, sfxopts, &candidates]() {
 3033|   584M|    if (t && candidates == 0)
  ------------------
  |  Branch (3033:9): [True: 0, False: 584M]
  |  Branch (3033:14): [True: 0, False: 0]
  ------------------
 3034|      0|      trace(*t, "sfx \"%s\" candidates=0%s", word.substr(start, len).c_str(),
 3035|      0|            (sfxopts & aeXPRODUCT) != 0 ? " xprod=Y" : "");
  ------------------
  |  |   65|      0|#define aeXPRODUCT (1 << 0)
  ------------------
  |  Branch (3035:13): [True: 0, False: 0]
  ------------------
 3036|   584M|  };
_ZN8AffixMgr11isRevSubsetEPKcS1_m:
 2932|   296k|                                 size_t len) {
 2933|   594k|  while ((len > 0) && (*s1 != '\0') && ((*s1 == *end_of_s2) || (*s1 == '.'))) {
  ------------------
  |  Branch (2933:10): [True: 587k, False: 6.92k]
  |  Branch (2933:23): [True: 359k, False: 227k]
  |  Branch (2933:41): [True: 297k, False: 62.2k]
  |  Branch (2933:64): [True: 0, False: 62.2k]
  ------------------
 2934|   297k|    s1++;
 2935|   297k|    end_of_s2--;
 2936|   297k|    len--;
 2937|   297k|  }
 2938|   296k|  return (*s1 == '\0');
 2939|   296k|}
affixmgr.cxx:_ZZN8AffixMgr11affix_checkERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmmR12AffixScratchtctPP8PfxEntryPP8SfxEntryENK3$_0clEPK6hentry:
 3378|  21.1M|  auto report_form = [this, t, &word, start, len, found_pfx, found_sfx](const struct hentry* rv) {
 3379|  21.1M|    if (!rv)
  ------------------
  |  Branch (3379:9): [True: 21.1M, False: 0]
  ------------------
 3380|  21.1M|      return;
 3381|      0|    if (t)
  ------------------
  |  Branch (3381:9): [True: 0, False: 0]
  ------------------
 3382|      0|      trace_form(*t, this, word.substr(start, len), rv->word, pfx, sfx);
 3383|      0|    if (found_pfx)
  ------------------
  |  Branch (3383:9): [True: 0, False: 0]
  ------------------
 3384|      0|      *found_pfx = pfx;
 3385|      0|    if (found_sfx)
  ------------------
  |  Branch (3385:9): [True: 0, False: 0]
  ------------------
 3386|      0|      *found_sfx = sfx;
 3387|      0|  };
affixmgr.cxx:_ZN12_GLOBAL__N_18mystrdupEPKc:
 3640|   697k|  char* mystrdup(const char* s) {
 3641|   697k|    char* d = nullptr;
 3642|   697k|    if (s) {
  ------------------
  |  Branch (3642:9): [True: 697k, False: 0]
  ------------------
 3643|   697k|      size_t sl = strlen(s) + 1;
 3644|   697k|      d = new char[sl];
 3645|   697k|      memcpy(d, s, sl);
 3646|   697k|    }
 3647|   697k|    return d;
 3648|   697k|  }
_ZN17entries_containerC2EcP8AffixMgr:
 4686|     26|    : m_mgr(mgr)
 4687|     26|    , m_at(at) {
 4688|     26|  }
_ZN17entries_container10initializeEict:
 4693|     26|                  char opts, unsigned short aflag) {
 4694|     26|    entries.reserve(std::min(numents, 16384));
 4695|       |
 4696|     26|    if (m_at == 'P') {
  ------------------
  |  Branch (4696:9): [True: 8, False: 18]
  ------------------
 4697|      8|      entries.push_back(new PfxEntry(m_mgr));
 4698|     18|    } else {
 4699|     18|      entries.push_back(new SfxEntry(m_mgr));
 4700|     18|    }
 4701|       |
 4702|     26|    entries.back()->opts = opts;
 4703|     26|    entries.back()->aflag = aflag;
 4704|     26|  }
_ZN17entries_container11first_entryEv:
 4717|     42|  AffEntry* first_entry() { return entries.empty() ? nullptr : entries[0]; }
  ------------------
  |  Branch (4717:36): [True: 0, False: 42]
  ------------------
_ZN17entries_container9add_entryEc:
 4706|     16|  AffEntry* add_entry(char opts) {
 4707|     16|    if (m_at == 'P') {
  ------------------
  |  Branch (4707:9): [True: 0, False: 16]
  ------------------
 4708|      0|      entries.push_back(new PfxEntry(m_mgr));
 4709|     16|    } else {
 4710|     16|      entries.push_back(new SfxEntry(m_mgr));
 4711|     16|    }
 4712|     16|    AffEntry* ret = entries.back();
 4713|     16|    ret->opts = entries[0]->opts & opts;
 4714|     16|    return ret;
 4715|     16|  }
_ZN17entries_container5beginEv:
 4725|     26|  std::vector<AffEntry*>::iterator begin() { return entries.begin(); }
_ZN17entries_container3endEv:
 4726|     26|  std::vector<AffEntry*>::iterator end() { return entries.end(); }
_ZN17entries_container7releaseEv:
 4689|     26|  void release() {
 4690|     26|    entries.clear();
 4691|     26|  }
_ZN17entries_containerD2Ev:
 4719|     26|  ~entries_container() {
 4720|     26|    for (auto& entry : entries) {
  ------------------
  |  Branch (4720:22): [True: 0, False: 26]
  ------------------
 4721|      0|      delete entry;
 4722|      0|    }
 4723|     26|  }
affixmgr.cxx:_ZN12_GLOBAL__N_113link_in_orderI8PfxEntryEEPT_S3_S3_:
  920|  9.69k|  template <typename T> T* link_in_order(T* ptr, T* nptr) {
  921|  9.69k|    std::vector<T*> path;
  922|  9.69k|    while (ptr || !path.empty()) {
  ------------------
  |  Branch (922:12): [True: 4, False: 9.69k]
  |  Branch (922:19): [True: 2, False: 9.69k]
  ------------------
  923|     12|      for (; ptr; ptr = ptr->getNextNE())
  ------------------
  |  Branch (923:14): [True: 6, False: 6]
  ------------------
  924|      6|        path.push_back(ptr);
  925|      6|      ptr = path.back();
  926|      6|      path.pop_back();
  927|      6|      ptr->setNext(nptr);
  928|      6|      nptr = ptr;
  929|      6|      ptr = ptr->getNextEQ();
  930|      6|    }
  931|  9.69k|    return nptr;
  932|  9.69k|  }
affixmgr.cxx:_ZN12_GLOBAL__N_113link_in_orderI8SfxEntryEEPT_S3_S3_:
  920|  9.69k|  template <typename T> T* link_in_order(T* ptr, T* nptr) {
  921|  9.69k|    std::vector<T*> path;
  922|  9.72k|    while (ptr || !path.empty()) {
  ------------------
  |  Branch (922:12): [True: 32, False: 9.69k]
  |  Branch (922:19): [True: 2, False: 9.69k]
  ------------------
  923|     68|      for (; ptr; ptr = ptr->getNextNE())
  ------------------
  |  Branch (923:14): [True: 34, False: 34]
  ------------------
  924|     34|        path.push_back(ptr);
  925|     34|      ptr = path.back();
  926|     34|      path.pop_back();
  927|     34|      ptr->setNext(nptr);
  928|     34|      nptr = ptr;
  929|     34|      ptr = ptr->getNextEQ();
  930|     34|    }
  931|  9.69k|    return nptr;
  932|  9.69k|  }
affixmgr.cxx:_ZZN8AffixMgr12get_syllableERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEENK3$_1clE6w_char:
 1716|  3.54k|          [&](w_char wc) {
 1717|  3.54k|            return std::binary_search(cpdvowels_utf16.begin(), cpdvowels_utf16.end(), wc);
 1718|  3.54k|          });

_ZN9guesswordC2Ev:
  121|  4.74M|    : word(nullptr)
  122|  4.74M|    , allow(false)
  123|  4.74M|    , orig(nullptr)
  124|  4.74M|  {
  125|  4.74M|  }
_ZN8patentryC2Ev:
  138|      4|    : cond(FLAG_NULL)
  ------------------
  |  |   99|      4|#define FLAG_NULL 0x00
  ------------------
  139|      4|    , cond2(FLAG_NULL) {
  ------------------
  |  |   99|      4|#define FLAG_NULL 0x00
  ------------------
  140|      4|  }
csutil.cxx:_ZL16HUNSPELL_WARNINGP8_IO_FILEPKcz:
   48|  1.67M|static inline void HUNSPELL_WARNING(FILE*, const char*, ...) {}

_ZN8AffEntryC2Ev:
   46|     42|      : morphcode(nullptr)
   47|     42|      , contclass(nullptr)
   48|     42|      , line(0)
   49|     42|      , headerline(0)
   50|     42|      , aflag(0)
   51|     42|      , contclasslen(0)
   52|     42|      , numconds(0)
   53|     42|      , opts(0)
   54|     42|      , xprod(0) {}

_Z6myopenRNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEEPKcj:
  107|    114|{
  108|       |#if defined(_WIN32) && defined(_MSC_VER)
  109|       |#define WIN32_LONG_PATH_PREFIX "\\\\?\\"
  110|       |  if (strncmp(path, WIN32_LONG_PATH_PREFIX, 4) == 0) {
  111|       |    int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
  112|       |    wchar_t* buff = new wchar_t[len];
  113|       |    wchar_t* buff2 = new wchar_t[len];
  114|       |    MultiByteToWideChar(CP_UTF8, 0, path, -1, buff, len);
  115|       |    if (_wfullpath(buff2, buff, len) != NULL) {
  116|       |      stream.open(buff2, mode);
  117|       |    }
  118|       |    delete [] buff;
  119|       |    delete [] buff2;
  120|       |  }
  121|       |  else
  122|       |#endif
  123|    114|  stream.open(path, mode);
  124|    114|}
_Z6u16_u8RNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_6vectorI6w_charNS3_IS8_EEEE:
  131|  23.7M|std::string& u16_u8(std::string& dest, const std::vector<w_char>& src) {
  132|  23.7M|  dest.clear();
  133|  23.7M|  dest.reserve(src.size());
  134|   657M|  for (const w_char& wc : src) {
  ------------------
  |  Branch (134:25): [True: 657M, False: 23.7M]
  ------------------
  135|   657M|    uint16_t cp = (static_cast<uint16_t>(wc.h) << 8) | wc.l;
  136|   657M|    if (cp < 0x80) {
  ------------------
  |  Branch (136:9): [True: 599M, False: 58.1M]
  ------------------
  137|   599M|      dest.push_back(static_cast<char>(cp));
  138|   599M|    } else if (cp < 0x800) {
  ------------------
  |  Branch (138:16): [True: 2.12M, False: 56.0M]
  ------------------
  139|  2.12M|      dest.push_back(static_cast<char>(0xc0 | (cp >> 6)));
  140|  2.12M|      dest.push_back(static_cast<char>(0x80 | (cp & 0x3f)));
  141|  56.0M|    } else {
  142|  56.0M|      dest.push_back(static_cast<char>(0xe0 | (cp >> 12)));
  143|  56.0M|      dest.push_back(static_cast<char>(0x80 | ((cp >> 6) & 0x3f)));
  144|  56.0M|      dest.push_back(static_cast<char>(0x80 | (cp & 0x3f)));
  145|  56.0M|    }
  146|   657M|  }
  147|  23.7M|  return dest;
  148|  23.7M|}
_Z6u8_u16RNSt3__16vectorI6w_charNS_9allocatorIS1_EEEERKNS_12basic_stringIcNS_11char_traitsIcEENS2_IcEEEEb:
  166|  5.56M|int u8_u16(std::vector<w_char>& dest, const std::string& src, bool only_convert_first_letter) {
  167|       |  // faster to oversize initially, assign to elements and resize to what's used
  168|       |  // than to reserve and push_back
  169|  5.56M|  dest.resize(only_convert_first_letter ? 1 : src.size());
  ------------------
  |  Branch (169:15): [True: 0, False: 5.56M]
  ------------------
  170|  5.56M|  auto out = dest.begin();
  171|  5.56M|  auto p = src.begin(), end = src.end();
  172|       |
  173|  50.5M|  while (p < end) {
  ------------------
  |  Branch (173:10): [True: 45.4M, False: 5.04M]
  ------------------
  174|  45.4M|    uint8_t b0 = static_cast<uint8_t>(*p);
  175|  45.4M|    uint16_t cp;
  176|       |
  177|  45.4M|    if (b0 < 0x80) {
  ------------------
  |  Branch (177:9): [True: 40.8M, False: 4.62M]
  ------------------
  178|       |      // 1-byte ASCII
  179|  40.8M|      cp = b0;
  180|  40.8M|    } else if (b0 < 0xc0) {
  ------------------
  |  Branch (180:16): [True: 414k, False: 4.20M]
  ------------------
  181|       |      // continuation byte at lead position
  182|   414k|      HUNSPELL_WARNING(stderr,
  183|   414k|                       "UTF-8 encoding error. Unexpected continuation bytes "
  184|   414k|                       "in %ld. character position\n%s\n",
  185|   414k|                       static_cast<long>(std::distance(src.begin(), p)),
  186|   414k|                       src.c_str());
  187|   414k|      cp = 0xfffd;
  188|  4.20M|    } else if (b0 < 0xe0) {
  ------------------
  |  Branch (188:16): [True: 795k, False: 3.41M]
  ------------------
  189|       |      // 2-byte sequence: 110xxxxx 10yyyyyy
  190|   795k|      if (p + 1 < end && is_utf8_cont(p[1])) {
  ------------------
  |  Branch (190:11): [True: 695k, False: 99.9k]
  |  Branch (190:11): [True: 155k, False: 640k]
  |  Branch (190:26): [True: 155k, False: 540k]
  ------------------
  191|   155k|        cp = ((b0 & 0x1f) << 6) | (static_cast<uint8_t>(p[1]) & 0x3f);
  192|   155k|        ++p;  // step past lead; loop bottom steps past cont
  193|   640k|      } else {
  194|   640k|        warn_missing_cont(src, p);
  195|   640k|        cp = 0xfffd;
  196|   640k|      }
  197|  3.41M|    } else if (b0 < 0xf0) {
  ------------------
  |  Branch (197:16): [True: 2.89M, False: 517k]
  ------------------
  198|       |      // 3-byte sequence: 1110xxxx 10yyyyyy 10zzzzzz
  199|  2.89M|      if (p + 1 < end && is_utf8_cont(p[1])) {
  ------------------
  |  Branch (199:11): [True: 2.87M, False: 18.1k]
  |  Branch (199:11): [True: 2.79M, False: 95.0k]
  |  Branch (199:26): [True: 2.79M, False: 76.8k]
  ------------------
  200|  2.79M|        uint8_t b1 = static_cast<uint8_t>(p[1]);
  201|  2.79M|        ++p;  // step past lead
  202|  2.79M|        if (p + 1 < end && is_utf8_cont(p[1])) {
  ------------------
  |  Branch (202:13): [True: 2.79M, False: 4.61k]
  |  Branch (202:13): [True: 2.79M, False: 6.84k]
  |  Branch (202:28): [True: 2.79M, False: 2.23k]
  ------------------
  203|  2.79M|          cp = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (static_cast<uint8_t>(p[1]) & 0x3f);
  204|  2.79M|          ++p;  // step past first cont; loop bottom steps past second cont
  205|  2.79M|        } else {
  206|  6.84k|          warn_missing_cont(src, p);
  207|  6.84k|          cp = 0xfffd;
  208|  6.84k|        }
  209|  2.79M|      } else {
  210|  95.0k|        warn_missing_cont(src, p);
  211|  95.0k|        cp = 0xfffd;
  212|  95.0k|      }
  213|  2.89M|    } else {
  214|       |      // 4+ byte lead: codepoint >= U+10000, can't fit in w_char
  215|   517k|      HUNSPELL_WARNING(stderr,
  216|   517k|                       "This UTF-8 encoding can't convert to UTF-16:\n%s\n",
  217|   517k|                       src.c_str());
  218|   517k|      out->h = 0xff;
  219|   517k|      out->l = 0xfd;
  220|   517k|      ++out;
  221|   517k|      dest.resize(out - dest.begin());
  222|   517k|      return -1;
  223|   517k|    }
  224|       |
  225|  44.9M|    out->h = static_cast<unsigned char>(cp >> 8);
  226|  44.9M|    out->l = static_cast<unsigned char>(cp);
  227|  44.9M|    ++out;
  228|  44.9M|    if (only_convert_first_letter)
  ------------------
  |  Branch (228:9): [True: 0, False: 44.9M]
  ------------------
  229|      0|      break;
  230|  44.9M|    ++p;  // consume lead byte
  231|  44.9M|  }
  232|       |
  233|  5.04M|  int size = static_cast<int>(out - dest.begin());
  234|  5.04M|  dest.resize(size);
  235|  5.04M|  return size;
  236|  5.56M|}
_Z8mystrsepRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS_11__wrap_iterIPKcEE:
  251|  1.80k|                                     std::string::const_iterator& start) {
  252|  1.80k|  auto end = str.end();
  253|       |
  254|  1.80k|  is_any_of op(" \t");
  255|       |  // don't use isspace() here, the string can be in some random charset
  256|       |  // that's way different than the locale's
  257|  1.80k|  auto sp = start;
  258|  5.87k|  while (sp != end && op(*sp))
  ------------------
  |  Branch (258:10): [True: 5.43k, False: 442]
  |  Branch (258:23): [True: 4.07k, False: 1.35k]
  ------------------
  259|  4.07k|      ++sp;
  260|       |
  261|  1.80k|  auto dp = sp;
  262|  6.69k|  while (dp != end && !op(*dp))
  ------------------
  |  Branch (262:10): [True: 5.81k, False: 882]
  |  Branch (262:23): [True: 4.89k, False: 918]
  ------------------
  263|  4.89k|      ++dp;
  264|       |
  265|  1.80k|  start = dp;
  266|  1.80k|  return sp;
  267|  1.80k|}
_Z7mychompRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
  270|  1.99k|void mychomp(std::string& s) {
  271|  1.99k|  size_t k = s.size();
  272|  1.99k|  size_t newsize = k;
  273|  1.99k|  if ((k > 0) && ((s[k - 1] == '\r') || (s[k - 1] == '\n')))
  ------------------
  |  Branch (273:7): [True: 1.80k, False: 190]
  |  Branch (273:19): [True: 0, False: 1.80k]
  |  Branch (273:41): [True: 0, False: 1.80k]
  ------------------
  274|      0|    --newsize;
  275|  1.99k|  if ((k > 1) && (s[k - 2] == '\r'))
  ------------------
  |  Branch (275:7): [True: 1.60k, False: 384]
  |  Branch (275:18): [True: 0, False: 1.60k]
  ------------------
  276|      0|    --newsize;
  277|  1.99k|  s.resize(newsize);
  278|  1.99k|}
_Z8line_tokRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEc:
  281|   185k|std::vector<std::string> line_tok(const std::string& text, char breakchar) {
  282|   185k|  std::vector<std::string> ret;
  283|   185k|  if (text.empty()) {
  ------------------
  |  Branch (283:7): [True: 10.1k, False: 175k]
  ------------------
  284|  10.1k|    return ret;
  285|  10.1k|  }
  286|       |
  287|   175k|  std::stringstream ss(text);
  288|   175k|  std::string tok;
  289|   351k|  while(std::getline(ss, tok, breakchar)) {
  ------------------
  |  Branch (289:9): [True: 175k, False: 175k]
  ------------------
  290|   175k|    if (!tok.empty()) {
  ------------------
  |  Branch (290:9): [True: 175k, False: 72]
  ------------------
  291|   175k|      ret.push_back(tok);
  292|   175k|    }
  293|   175k|  }
  294|       |
  295|   175k|  return ret;
  296|   185k|}
_Z9line_uniqRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEc:
  308|  11.9k|{
  309|  11.9k|  std::vector<std::string> lines = line_tok(text, breakchar);
  310|  11.9k|  text.clear();
  311|  11.9k|  if (lines.empty()) {
  ------------------
  |  Branch (311:7): [True: 10.1k, False: 1.76k]
  ------------------
  312|  10.1k|    return;
  313|  10.1k|  }
  314|       |
  315|  1.76k|  drop_repeated_lines(lines);
  316|       |
  317|  1.76k|  text = lines[0];
  318|  1.77k|  for (size_t i = 1; i < lines.size(); ++i) {
  ------------------
  |  Branch (318:22): [True: 10, False: 1.76k]
  ------------------
  319|     10|    text.push_back(breakchar);
  320|     10|    text.append(lines[i]);
  321|     10|  }
  322|  1.76k|}
_Z21append_compound_partsRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERS5_:
  373|   171k|size_t append_compound_parts(const std::string& desc, std::string& result) {
  374|       |  // find by offset, a search from a bare pointer remeasures the rest of desc on every step
  375|   171k|  size_t part = desc.find(MORPH_PART);
  ------------------
  |  |  112|   171k|#define MORPH_PART "pa:"
  ------------------
  376|   171k|  if (part == std::string::npos)
  ------------------
  |  Branch (376:7): [True: 171k, False: 0]
  ------------------
  377|   171k|    return 0;
  378|      0|  static const char separators[] = {' ', '\t', '\n', '\0'};
  379|      0|  size_t nextpart = desc.find(MORPH_PART, part + 1);
  ------------------
  |  |  112|      0|#define MORPH_PART "pa:"
  ------------------
  380|      0|  while (nextpart != std::string::npos) {
  ------------------
  |  Branch (380:10): [True: 0, False: 0]
  ------------------
  381|      0|    const auto field = desc.begin() + part + MORPH_TAG_LEN;
  ------------------
  |  |  115|      0|#define MORPH_TAG_LEN strlen(MORPH_STEM)
  |  |  ------------------
  |  |  |  |   99|      0|#define MORPH_STEM "st:"
  |  |  ------------------
  ------------------
  382|      0|    const auto end = desc.begin() + nextpart;
  383|      0|    result.append(field, std::find_first_of(field, end, std::begin(separators),
  384|      0|                                            std::end(separators)));
  385|      0|    part = nextpart;
  386|      0|    nextpart = desc.find(MORPH_PART, part + 1);
  ------------------
  |  |  112|      0|#define MORPH_PART "pa:"
  ------------------
  387|      0|  }
  388|      0|  return part;
  389|   171k|}
_Z10copy_fieldRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKS5_S8_:
  393|   173k|                const std::string& var) {
  394|   173k|  if (morph.empty())
  ------------------
  |  Branch (394:7): [True: 0, False: 173k]
  ------------------
  395|      0|    return false;
  396|   173k|  size_t pos = morph.find(var);
  397|   173k|  if (pos == std::string::npos)
  ------------------
  |  Branch (397:7): [True: 0, False: 173k]
  ------------------
  398|      0|    return false;
  399|   173k|  pos += MORPH_TAG_LEN;
  ------------------
  |  |  115|   173k|#define MORPH_TAG_LEN strlen(MORPH_STEM)
  |  |  ------------------
  |  |  |  |   99|   173k|#define MORPH_STEM "st:"
  |  |  ------------------
  ------------------
  400|       |  // copy the field value up to the next whitespace, without first
  401|       |  // making a throwaway copy of the whole remaining tail of the string
  402|   173k|  size_t end = morph.find_first_of(" \t\n", pos);
  403|   173k|  dest.assign(morph, pos, end == std::string::npos ? std::string::npos : end - pos);
  ------------------
  |  Branch (403:27): [True: 159k, False: 13.8k]
  ------------------
  404|       |
  405|   173k|  return true;
  406|   173k|}
_Z8mystrrepRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKS5_S8_:
  410|   999k|                      const std::string& replace) {
  411|   999k|  size_t pos = 0;
  412|  1.06M|  while ((pos = str.find(search, pos)) != std::string::npos) {
  ------------------
  |  Branch (412:10): [True: 69.9k, False: 999k]
  ------------------
  413|  69.9k|    str.replace(pos, search.length(), replace);
  414|  69.9k|    pos += replace.length();
  415|  69.9k|  }
  416|   999k|  return str;
  417|   999k|}
_Z11reversewordRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
  420|  1.09M|size_t reverseword(std::string& word) {
  421|  1.09M|  std::reverse(word.begin(), word.end());
  422|  1.09M|  return word.size();
  423|  1.09M|}
_Z8uniqlistRNSt3__16vectorINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEENS4_IS6_EEEE:
  500|  7.06k|void uniqlist(std::vector<std::string>& list) {
  501|  7.06k|  if (list.size() < 2)
  ------------------
  |  Branch (501:7): [True: 7.05k, False: 10]
  ------------------
  502|  7.05k|    return;
  503|       |
  504|     10|  std::vector<std::string> ret;
  505|     10|  ret.push_back(list[0]);
  506|       |
  507|     20|  for (size_t i = 1; i < list.size(); ++i) {
  ------------------
  |  Branch (507:22): [True: 10, False: 10]
  ------------------
  508|     10|    if (std::find(ret.begin(), ret.end(), list[i]) == ret.end())
  ------------------
  |  Branch (508:9): [True: 10, False: 0]
  ------------------
  509|     10|        ret.push_back(list[i]);
  510|     10|  }
  511|       |
  512|     10|  list.swap(ret);
  513|     10|}
_Z9upper_utf6w_chari:
  532|  4.43M|w_char upper_utf(w_char u, int langnum) {
  533|       |
  534|  4.43M|#if defined(_WIN32) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__))  || defined(__LITTLE_ENDIAN__)
  535|       |
  536|       |//with these optimizations, msvc can optimize this function to one jmp instruction
  537|       |//but g++ remains in five instructions
  538|       |//maybe use inline asm for g++?
  539|       |
  540|       |#if (__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) && defined __cpp_lib_bit_cast && __cpp_lib_bit_cast >= 201806L
  541|       |  return std::bit_cast<w_char>(unicodetoupper((unsigned short)u, langnum));
  542|       |#else
  543|  4.43M|  const auto us = unicodetoupper((unsigned short)u, langnum);
  544|  4.43M|  memcpy(&u, &us, sizeof(unsigned short));
  545|  4.43M|  return u;
  546|  4.43M|#endif
  547|       |
  548|       |#else
  549|       |  const auto us = unicodetoupper((unsigned short)u, langnum);
  550|       |  u.h = (unsigned char)(us >> 8);
  551|       |  u.l = (unsigned char)(us & 0xff);
  552|       |  return u;
  553|       |#endif
  554|  4.43M|}
_Z9lower_utf6w_chari:
  556|  9.80M|w_char lower_utf(w_char u, int langnum) {
  557|       |
  558|  9.80M|#if defined(_WIN32) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__))  || defined(__LITTLE_ENDIAN__)
  559|       |
  560|       |//with these optimizations, msvc can optimize this function to one jmp instruction
  561|       |//but g++ remains in five instructions
  562|       |//maybe use inline asm for g++?
  563|       |
  564|       |#if (__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) && defined __cpp_lib_bit_cast && __cpp_lib_bit_cast >= 201806L
  565|       |  return std::bit_cast<w_char>(unicodetolower((unsigned short)u, langnum));
  566|       |#else
  567|  9.80M|  const auto us = unicodetolower((unsigned short)u, langnum);
  568|  9.80M|  memcpy(&u, &us, sizeof(unsigned short));
  569|  9.80M|  return u;
  570|  9.80M|#endif
  571|       |
  572|       |#else
  573|       |  const auto us = unicodetolower((unsigned short)u, langnum);
  574|       |  u.h = (unsigned char)(us >> 8);
  575|       |  u.l = (unsigned char)(us & 0xff);
  576|       |  return u;
  577|       |#endif
  578|  9.80M|}
_Z8mkallcapRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPK7cs_info:
  581|   276k|std::string& mkallcap(std::string& s, const struct cs_info* csconv) {
  582|  5.49M|  for (char& aI : s) {
  ------------------
  |  Branch (582:17): [True: 5.49M, False: 276k]
  ------------------
  583|  5.49M|    aI = cupper(csconv, static_cast<unsigned char>(aI));
  584|  5.49M|  }
  585|   276k|  return s;
  586|   276k|}
_Z10mkallsmallRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPK7cs_info:
  589|  2.46M|std::string& mkallsmall(std::string& s, const struct cs_info* csconv) {
  590|  25.3M|  for (char& aI : s) {
  ------------------
  |  Branch (590:17): [True: 25.3M, False: 2.46M]
  ------------------
  591|  25.3M|    aI = clower(csconv, static_cast<unsigned char>(aI));
  592|  25.3M|  }
  593|  2.46M|  return s;
  594|  2.46M|}
_Z14mkallsmall_utfRNSt3__16vectorI6w_charNS_9allocatorIS1_EEEEi:
  596|  1.41M|std::vector<w_char>& mkallsmall_utf(std::vector<w_char>& u, int langnum) {
  597|  9.69M|  for (auto& i : u) {
  ------------------
  |  Branch (597:16): [True: 9.69M, False: 1.41M]
  ------------------
  598|  9.69M|    i = lower_utf(i, langnum);
  599|  9.69M|  }
  600|  1.41M|  return u;
  601|  1.41M|}
_Z12mkallcap_utfRNSt3__16vectorI6w_charNS_9allocatorIS1_EEEEi:
  603|   164k|std::vector<w_char>& mkallcap_utf(std::vector<w_char>& u, int langnum) {
  604|  1.98M|  for (auto& i : u) {
  ------------------
  |  Branch (604:16): [True: 1.98M, False: 164k]
  ------------------
  605|  1.98M|    i = upper_utf(i, langnum);
  606|  1.98M|  }
  607|   164k|  return u;
  608|   164k|}
_Z9mkinitcapRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPK7cs_info:
  610|  1.70M|std::string& mkinitcap(std::string& s, const struct cs_info* csconv) {
  611|  1.70M|  if (!s.empty()) {
  ------------------
  |  Branch (611:7): [True: 1.70M, False: 136]
  ------------------
  612|  1.70M|    s[0] = cupper(csconv, static_cast<unsigned char>(s[0]));
  613|  1.70M|  }
  614|  1.70M|  return s;
  615|  1.70M|}
_Z13mkinitcap_utfRNSt3__16vectorI6w_charNS_9allocatorIS1_EEEEi:
  617|   468k|std::vector<w_char>& mkinitcap_utf(std::vector<w_char>& u, int langnum) {
  618|   468k|  if (!u.empty()) {
  ------------------
  |  Branch (618:7): [True: 468k, False: 0]
  ------------------
  619|   468k|    u[0] = upper_utf(u[0], langnum);
  620|   468k|  }
  621|   468k|  return u;
  622|   468k|}
_Z11mkinitsmallRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPK7cs_info:
  624|   315k|std::string& mkinitsmall(std::string& s, const struct cs_info* csconv) {
  625|   315k|  if (!s.empty()) {
  ------------------
  |  Branch (625:7): [True: 315k, False: 0]
  ------------------
  626|   315k|    s[0] = clower(csconv, static_cast<unsigned char>(s[0]));
  627|   315k|  }
  628|   315k|  return s;
  629|   315k|}
_Z15mkinitsmall_utfRNSt3__16vectorI6w_charNS_9allocatorIS1_EEEEi:
  631|  41.1k|std::vector<w_char>& mkinitsmall_utf(std::vector<w_char>& u, int langnum) {
  632|  41.1k|  if (!u.empty()) {
  ------------------
  |  Branch (632:7): [True: 41.1k, False: 0]
  ------------------
  633|  41.1k|    u[0] = lower_utf(u[0], langnum);
  634|  41.1k|  }
  635|  41.1k|  return u;
  636|  41.1k|}
_Z14get_current_csRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
 2294|  1.92k|const struct cs_info* get_current_cs(const std::string& es) {
 2295|  1.92k|  char* normalized_encoding = new char[es.size() + 1];
 2296|  1.92k|  toAsciiLowerAndRemoveNonAlphanumeric(es.c_str(), normalized_encoding);
 2297|       |
 2298|  1.92k|  const struct cs_info* ccs = nullptr;
 2299|  1.92k|  for (const auto& encd : encds) {
  ------------------
  |  Branch (2299:25): [True: 1.92k, False: 0]
  ------------------
 2300|  1.92k|    if (strcmp(normalized_encoding, encd.enc_name) == 0) {
  ------------------
  |  Branch (2300:9): [True: 1.92k, False: 0]
  ------------------
 2301|  1.92k|      ccs = encd.cs_table;
 2302|  1.92k|      break;
 2303|  1.92k|    }
 2304|  1.92k|  }
 2305|       |
 2306|  1.92k|  delete[] normalized_encoding;
 2307|       |
 2308|  1.92k|  if (!ccs) {
  ------------------
  |  Branch (2308:7): [True: 0, False: 1.92k]
  ------------------
 2309|      0|    HUNSPELL_WARNING(stderr,
 2310|      0|                     "error: unknown encoding %s: using %s as fallback\n", es.c_str(),
 2311|      0|                     encds[0].enc_name);
 2312|      0|    ccs = encds[0].cs_table;
 2313|      0|  }
 2314|       |
 2315|  1.92k|  return ccs;
 2316|  1.92k|}
_Z12get_lang_numRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
 2363|      4|int get_lang_num(const std::string& lang) {
 2364|     72|  for (const auto& i : lang2enc) {
  ------------------
  |  Branch (2364:22): [True: 72, False: 0]
  ------------------
 2365|     72|    if (strcmp(lang.c_str(), i.lang) == 0) {
  ------------------
  |  Branch (2365:9): [True: 4, False: 68]
  ------------------
 2366|      4|      return i.num;
 2367|      4|    }
 2368|     72|  }
 2369|      0|  return LANG_xx;
 2370|      4|}
_Z14unicodetoupperti:
 2372|  34.6M|unsigned short unicodetoupper(unsigned short c, int langnum) {
 2373|       |  // In Azeri and Turkish, I and i dictinct letters:
 2374|       |  // There are a dotless lower case i pair of upper `I',
 2375|       |  // and an upper I with dot pair of lower `i'.
 2376|  34.6M|  if (c == 0x0069 && ((langnum == LANG_az) || (langnum == LANG_tr) || (langnum == LANG_crh)))
  ------------------
  |  Branch (2376:7): [True: 334k, False: 34.2M]
  |  Branch (2376:23): [True: 0, False: 334k]
  |  Branch (2376:47): [True: 0, False: 334k]
  |  Branch (2376:71): [True: 0, False: 334k]
  ------------------
 2377|      0|    return 0x0130;
 2378|       |#ifdef OPENOFFICEORG
 2379|       |  return static_cast<unsigned short>(u_toupper(c));
 2380|       |#else
 2381|       |#ifdef MOZILLA_CLIENT
 2382|       |  return moz_hunspell_ToUpperCase((char16_t)c);
 2383|       |#else
 2384|  34.6M|  unsigned short up = utf_pages[utf_page_index[c >> 8]][c & 0xFF].cupper;
 2385|  34.6M|  return up ? up : c;
  ------------------
  |  Branch (2385:10): [True: 4.73M, False: 29.8M]
  ------------------
 2386|  34.6M|#endif
 2387|  34.6M|#endif
 2388|  34.6M|}
_Z14unicodetolowerti:
 2390|  41.1M|unsigned short unicodetolower(unsigned short c, int langnum) {
 2391|       |  // In Azeri and Turkish, I and i dictinct letters:
 2392|       |  // There are a dotless lower case i pair of upper `I',
 2393|       |  // and an upper I with dot pair of lower `i'.
 2394|  41.1M|  if (c == 0x0049 && ((langnum == LANG_az) || (langnum == LANG_tr) || (langnum == LANG_crh)))
  ------------------
  |  Branch (2394:7): [True: 107k, False: 41.0M]
  |  Branch (2394:23): [True: 0, False: 107k]
  |  Branch (2394:47): [True: 0, False: 107k]
  |  Branch (2394:71): [True: 0, False: 107k]
  ------------------
 2395|      0|    return 0x0131;
 2396|       |#ifdef OPENOFFICEORG
 2397|       |  return static_cast<unsigned short>(u_tolower(c));
 2398|       |#else
 2399|       |#ifdef MOZILLA_CLIENT
 2400|       |  return moz_hunspell_ToLowerCase((char16_t)c);
 2401|       |#else
 2402|  41.1M|  unsigned short lo = utf_pages[utf_page_index[c >> 8]][c & 0xFF].clower;
 2403|  41.1M|  return lo ? lo : c;
  ------------------
  |  Branch (2403:10): [True: 3.14M, False: 38.0M]
  ------------------
 2404|  41.1M|#endif
 2405|  41.1M|#endif
 2406|  41.1M|}
_Z11get_captypeRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPK7cs_info:
 2422|  13.9M|int get_captype(const std::string& word, const cs_info* csconv) {
 2423|       |  // now determine the capitalization type of the first nl letters
 2424|  13.9M|  size_t ncap = 0;
 2425|  13.9M|  size_t nneutral = 0;
 2426|  13.9M|  size_t firstcap = 0;
 2427|  13.9M|  if (csconv == nullptr)
  ------------------
  |  Branch (2427:7): [True: 0, False: 13.9M]
  ------------------
 2428|      0|    return NOCAP;
  ------------------
  |  |   88|      0|#define NOCAP 0
  ------------------
 2429|   148M|  for (char q : word) {
  ------------------
  |  Branch (2429:15): [True: 148M, False: 13.9M]
  ------------------
 2430|   148M|    const auto nIndex = static_cast<unsigned char>(q);
 2431|   148M|    if (ccase(csconv, nIndex))
  ------------------
  |  Branch (2431:9): [True: 5.30M, False: 143M]
  ------------------
 2432|  5.30M|      ncap++;
 2433|   148M|    if (cupper(csconv, nIndex) == clower(csconv, nIndex))
  ------------------
  |  Branch (2433:9): [True: 114M, False: 34.2M]
  ------------------
 2434|   114M|      nneutral++;
 2435|   148M|  }
 2436|  13.9M|  if (ncap) {
  ------------------
  |  Branch (2436:7): [True: 2.30M, False: 11.6M]
  ------------------
 2437|  2.30M|    const auto nIndex = static_cast<unsigned char>(word[0]);
 2438|  2.30M|    firstcap = csconv[nIndex].ccase;
 2439|  2.30M|  }
 2440|       |
 2441|       |  // now finally set the captype
 2442|  13.9M|  if (ncap == 0) {
  ------------------
  |  Branch (2442:7): [True: 11.6M, False: 2.30M]
  ------------------
 2443|  11.6M|    return NOCAP;
  ------------------
  |  |   88|  11.6M|#define NOCAP 0
  ------------------
 2444|  11.6M|  } else if ((ncap == 1) && firstcap) {
  ------------------
  |  Branch (2444:14): [True: 1.18M, False: 1.11M]
  |  Branch (2444:29): [True: 449k, False: 734k]
  ------------------
 2445|   449k|    return INITCAP;
  ------------------
  |  |   89|   449k|#define INITCAP 1
  ------------------
 2446|  1.85M|  } else if ((ncap == word.size()) || ((ncap + nneutral) == word.size())) {
  ------------------
  |  Branch (2446:14): [True: 7.52k, False: 1.84M]
  |  Branch (2446:39): [True: 520k, False: 1.32M]
  ------------------
 2447|   527k|    return ALLCAP;
  ------------------
  |  |   90|   527k|#define ALLCAP 2
  ------------------
 2448|  1.32M|  } else if ((ncap > 1) && firstcap) {
  ------------------
  |  Branch (2448:14): [True: 811k, False: 515k]
  |  Branch (2448:28): [True: 321k, False: 489k]
  ------------------
 2449|   321k|    return HUHINITCAP;
  ------------------
  |  |   92|   321k|#define HUHINITCAP 4
  ------------------
 2450|   321k|  }
 2451|  1.00M|  return HUHCAP;
  ------------------
  |  |   91|  1.00M|#define HUHCAP 3
  ------------------
 2452|  13.9M|}
_Z16get_captype_utf8RKNSt3__16vectorI6w_charNS_9allocatorIS1_EEEEi:
 2454|  3.29M|int get_captype_utf8(const std::vector<w_char>& word, int langnum) {
 2455|       |  // now determine the capitalization type of the first nl letters
 2456|  3.29M|  size_t ncap = 0;
 2457|  3.29M|  size_t nneutral = 0;
 2458|  3.29M|  size_t firstcap = 0;
 2459|       |
 2460|  3.29M|  auto it = word.begin(), it_end = word.end();
 2461|  33.2M|  while (it != it_end) {
  ------------------
  |  Branch (2461:10): [True: 29.9M, False: 3.29M]
  ------------------
 2462|  29.9M|    const auto idx = (unsigned short)*it;
 2463|  29.9M|    const auto lwridx = unicodetolower(idx, langnum);
 2464|  29.9M|    if (idx != lwridx)
  ------------------
  |  Branch (2464:9): [True: 1.17M, False: 28.8M]
  ------------------
 2465|  1.17M|      ncap++;
 2466|  29.9M|    if (unicodetoupper(idx, langnum) == lwridx)
  ------------------
  |  Branch (2466:9): [True: 25.2M, False: 4.75M]
  ------------------
 2467|  25.2M|      nneutral++;
 2468|  29.9M|    ++it;
 2469|  29.9M|  }
 2470|  3.29M|  if (ncap) {
  ------------------
  |  Branch (2470:7): [True: 442k, False: 2.85M]
  ------------------
 2471|   442k|    const auto idx = (unsigned short)word[0];
 2472|   442k|    firstcap = (idx != unicodetolower(idx, langnum));
 2473|   442k|  }
 2474|       |
 2475|       |  // now finally set the captype
 2476|  3.29M|  if (ncap == 0) {
  ------------------
  |  Branch (2476:7): [True: 2.85M, False: 442k]
  ------------------
 2477|  2.85M|    return NOCAP;
  ------------------
  |  |   88|  2.85M|#define NOCAP 0
  ------------------
 2478|  2.85M|  } else if ((ncap == 1) && firstcap) {
  ------------------
  |  Branch (2478:14): [True: 296k, False: 145k]
  |  Branch (2478:29): [True: 108k, False: 187k]
  ------------------
 2479|   108k|    return INITCAP;
  ------------------
  |  |   89|   108k|#define INITCAP 1
  ------------------
 2480|   333k|  } else if ((ncap == word.size()) || ((ncap + nneutral) == word.size())) {
  ------------------
  |  Branch (2480:14): [True: 2.82k, False: 330k]
  |  Branch (2480:39): [True: 130k, False: 200k]
  ------------------
 2481|   132k|    return ALLCAP;
  ------------------
  |  |   90|   132k|#define ALLCAP 2
  ------------------
 2482|   200k|  } else if ((ncap > 1) && firstcap) {
  ------------------
  |  Branch (2482:14): [True: 87.8k, False: 112k]
  |  Branch (2482:28): [True: 41.5k, False: 46.3k]
  ------------------
 2483|  41.5k|    return HUHINITCAP;
  ------------------
  |  |   92|  41.5k|#define HUHINITCAP 4
  ------------------
 2484|  41.5k|  }
 2485|   158k|  return HUHCAP;
  ------------------
  |  |   91|   158k|#define HUHCAP 3
  ------------------
 2486|  3.29M|}
_Z24remove_ignored_chars_utfRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_6vectorI6w_charNS3_IS8_EEEE:
 2490|   820k|                                const std::vector<w_char>& ignored_chars) {
 2491|   820k|  std::vector<w_char> w;
 2492|   820k|  std::vector<w_char> w2;
 2493|   820k|  u8_u16(w, word);
 2494|       |
 2495|   820k|  std::copy_if(w.begin(), w.end(), std::back_inserter(w2),
 2496|   820k|  [&ignored_chars](w_char wc) {
 2497|   820k|    return !std::binary_search(ignored_chars.begin(), ignored_chars.end(), wc);
 2498|   820k|  });
 2499|       |
 2500|   820k|  u16_u8(word, w2);
 2501|   820k|  return w2.size();
 2502|   820k|}
_Z20remove_ignored_charsRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKS5_:
 2506|  2.90M|                            const std::string& ignored_chars) {
 2507|  2.90M|  word.erase(
 2508|  2.90M|      std::remove_if(word.begin(), word.end(), is_any_of(ignored_chars)),
 2509|  2.90M|      word.end());
 2510|  2.90M|  return word.size();
 2511|  2.90M|}
_Z12parse_stringRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERS5_i:
 2513|     90|bool parse_string(const std::string& line, std::string& out, int ln) {
 2514|     90|  if (!out.empty()) {
  ------------------
  |  Branch (2514:7): [True: 0, False: 90]
  ------------------
 2515|      0|    HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions\n", ln);
 2516|      0|    return false;
 2517|      0|  }
 2518|     90|  int i = 0;
 2519|     90|  int np = 0;
 2520|     90|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 2521|    270|  while (start_piece != line.end()) {
  ------------------
  |  Branch (2521:10): [True: 180, False: 90]
  ------------------
 2522|    180|    switch (i) {
 2523|     90|      case 0: {
  ------------------
  |  Branch (2523:7): [True: 90, False: 90]
  ------------------
 2524|     90|        np++;
 2525|     90|        break;
 2526|      0|      }
 2527|     90|      case 1: {
  ------------------
  |  Branch (2527:7): [True: 90, False: 90]
  ------------------
 2528|     90|        out.assign(start_piece, iter);
 2529|     90|        np++;
 2530|     90|        break;
 2531|      0|      }
 2532|      0|      default:
  ------------------
  |  Branch (2532:7): [True: 0, False: 180]
  ------------------
 2533|      0|        break;
 2534|    180|    }
 2535|    180|    ++i;
 2536|    180|     start_piece = mystrsep(line, iter);
 2537|    180|  }
 2538|     90|  if (np != 2) {
  ------------------
  |  Branch (2538:7): [True: 0, False: 90]
  ------------------
 2539|      0|    HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", ln);
 2540|      0|    return false;
 2541|      0|  }
 2542|     90|  return true;
 2543|     90|}
_Z11parse_arrayRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERS5_RNS_6vectorI6w_charNS3_ISA_EEEEii:
 2549|     14|                 int ln) {
 2550|     14|  if (!parse_string(line, out, ln))
  ------------------
  |  Branch (2550:7): [True: 0, False: 14]
  ------------------
 2551|      0|    return false;
 2552|     14|  if (utf8) {
  ------------------
  |  Branch (2552:7): [True: 8, False: 6]
  ------------------
 2553|      8|    u8_u16(out_utf16, out);
 2554|      8|    std::sort(out_utf16.begin(), out_utf16.end());
 2555|      8|  }
 2556|     14|  return true;
 2557|     14|}
csutil.cxx:_ZL17warn_missing_contRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEENS_11__wrap_iterIPKcEE:
  150|   742k|static void warn_missing_cont(const std::string& src, std::string::const_iterator p) {
  151|       |  HUNSPELL_WARNING(stderr,
  152|   742k|                   "UTF-8 encoding error. Missing continuation byte in "
  153|   742k|                   "%ld. character position:\n%s\n",
  154|   742k|                   static_cast<long>(std::distance(src.begin(), p)),
  155|   742k|                   src.c_str());
  156|   742k|}
csutil.cxx:_ZN12_GLOBAL__N_19is_any_ofC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  241|  2.90M|  explicit is_any_of(const std::string& in) : chars(in) {}
csutil.cxx:_ZNK12_GLOBAL__N_19is_any_ofclEc:
  243|  32.7M|  bool operator()(char c) const { return chars.find(c) != std::string::npos; }
csutil.cxx:_ZL19drop_repeated_linesRNSt3__16vectorINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEENS4_IS6_EEEE:
  299|  1.76k|static void drop_repeated_lines(std::vector<std::string>& lines) {
  300|  1.76k|  std::unordered_set<std::string> seen;
  301|  1.76k|  auto firstrepeat = std::remove_if(lines.begin(), lines.end(),
  302|  1.76k|                                    [&seen](const std::string& line) { return !seen.insert(line).second; });
  303|  1.76k|  lines.erase(firstrepeat, lines.end());
  304|  1.76k|}
csutil.cxx:_ZZL19drop_repeated_linesRNSt3__16vectorINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEENS4_IS6_EEEEENK3$_0clERKS6_:
  302|  2.09k|                                    [&seen](const std::string& line) { return !seen.insert(line).second; });
csutil.cxx:_ZN12_GLOBAL__N_16cupperEPK7cs_infoi:
  516|   155M|unsigned char cupper(const struct cs_info* csconv, int nIndex) {
  517|   155M|  assert(nIndex >= 0 && nIndex <= 255);
  ------------------
  |  Branch (517:3): [True: 155M, False: 0]
  |  Branch (517:3): [True: 155M, False: 0]
  |  Branch (517:3): [True: 155M, False: 0]
  ------------------
  518|   155M|  return csconv[nIndex].cupper;
  519|   155M|}
csutil.cxx:_ZN12_GLOBAL__N_16clowerEPK7cs_infoi:
  521|   174M|unsigned char clower(const struct cs_info* csconv, int nIndex) {
  522|   174M|  assert(nIndex >= 0 && nIndex <= 255);
  ------------------
  |  Branch (522:3): [True: 174M, False: 0]
  |  Branch (522:3): [True: 174M, False: 0]
  |  Branch (522:3): [True: 174M, False: 0]
  ------------------
  523|   174M|  return csconv[nIndex].clower;
  524|   174M|}
csutil.cxx:_ZL36toAsciiLowerAndRemoveNonAlphanumericPKcPc:
 2274|  1.92k|                                                 char* pBuf) {
 2275|  17.4k|  while (*pName) {
  ------------------
  |  Branch (2275:10): [True: 15.5k, False: 1.92k]
  ------------------
 2276|       |    /* A-Z */
 2277|  15.5k|    if ((*pName >= 0x41) && (*pName <= 0x5A)) {
  ------------------
  |  Branch (2277:9): [True: 5.78k, False: 9.73k]
  |  Branch (2277:29): [True: 294, False: 5.49k]
  ------------------
 2278|    294|      *pBuf = (*pName) + 0x20; /* toAsciiLower */
 2279|    294|      pBuf++;
 2280|    294|    }
 2281|       |    /* a-z, 0-9 */
 2282|  15.2k|    else if (((*pName >= 0x61) && (*pName <= 0x7A)) ||
  ------------------
  |  Branch (2282:15): [True: 5.49k, False: 9.73k]
  |  Branch (2282:35): [True: 5.49k, False: 0]
  ------------------
 2283|  15.1k|             ((*pName >= 0x30) && (*pName <= 0x39))) {
  ------------------
  |  Branch (2283:15): [True: 9.64k, False: 98]
  |  Branch (2283:35): [True: 9.64k, False: 0]
  ------------------
 2284|  15.1k|      *pBuf = *pName;
 2285|  15.1k|      pBuf++;
 2286|  15.1k|    }
 2287|       |
 2288|  15.5k|    pName++;
 2289|  15.5k|  }
 2290|       |
 2291|  1.92k|  *pBuf = '\0';
 2292|  1.92k|}
csutil.cxx:_ZN12_GLOBAL__N_15ccaseEPK7cs_infoi:
  526|   148M|unsigned char ccase(const struct cs_info* csconv, int nIndex) {
  527|   148M|  assert(nIndex >= 0 && nIndex <= 255);
  ------------------
  |  Branch (527:3): [True: 148M, False: 0]
  |  Branch (527:3): [True: 148M, False: 0]
  |  Branch (527:3): [True: 148M, False: 0]
  ------------------
  528|   148M|  return csconv[nIndex].ccase;
  529|   148M|}
csutil.cxx:_ZZ24remove_ignored_chars_utfRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_6vectorI6w_charNS3_IS8_EEEEENK3$_0clES8_:
 2496|  8.54M|  [&ignored_chars](w_char wc) {
 2497|  8.54M|    return !std::binary_search(ignored_chars.begin(), ignored_chars.end(), wc);
 2498|  8.54M|  });

_Z12is_utf8_contc:
  139|  64.8M|inline bool is_utf8_cont(char c) {
  140|  64.8M|  return (static_cast<unsigned char>(c) & 0xc0) == 0x80;
  141|  64.8M|}
_Z9utf8_nextRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm:
  144|  23.6k|inline size_t utf8_next(const std::string& s, size_t pos) {
  145|  23.6k|  if (pos < s.size()) {
  ------------------
  |  Branch (145:7): [True: 23.6k, False: 0]
  ------------------
  146|  23.6k|    ++pos;
  147|  27.6k|    while (pos < s.size() && is_utf8_cont(s[pos]))
  ------------------
  |  Branch (147:12): [True: 25.4k, False: 2.19k]
  |  Branch (147:30): [True: 3.94k, False: 21.4k]
  ------------------
  148|  3.94k|      ++pos;
  149|  23.6k|  }
  150|  23.6k|  return pos;
  151|  23.6k|}
_Z20has_no_ignored_charsRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEES7_:
  290|    814|                            const std::string& ignored_chars) {
  291|    814|  return std::all_of(ignored_chars.begin(), ignored_chars.end(),
  292|    814|    [&word](char ic) { return word.find(ic) == std::string::npos; });
  293|    814|}
_Z11HENTRY_DATAP6hentry:
  296|  1.22M|inline char* HENTRY_DATA(struct hentry* h) {
  297|  1.22M|  char* ret;
  298|  1.22M|  if (!(h->var & H_OPT))
  ------------------
  |  |   47|  1.22M|#define H_OPT (1 << 0)          // is there optional morphological data?
  ------------------
  |  Branch (298:7): [True: 1.22M, False: 1.82k]
  ------------------
  299|  1.22M|    ret = nullptr;
  300|  1.82k|  else if (h->var & H_OPT_ALIASM)
  ------------------
  |  |   48|  1.82k|#define H_OPT_ALIASM (1 << 1)   // using alias compression?
  ------------------
  |  Branch (300:12): [True: 0, False: 1.82k]
  ------------------
  301|      0|    ret = get_stored_pointer(HENTRY_WORD(h) + h->blen + 1);
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
  302|  1.82k|  else
  303|  1.82k|    ret = HENTRY_WORD(h) + h->blen + 1;
  ------------------
  |  |   54|  1.82k|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
  304|  1.22M|  return ret;
  305|  1.22M|}
_Z11HENTRY_DATAPK6hentry:
  308|  2.08k|    const struct hentry* h) {
  309|  2.08k|  const char* ret;
  310|  2.08k|  if (!(h->var & H_OPT))
  ------------------
  |  |   47|  2.08k|#define H_OPT (1 << 0)          // is there optional morphological data?
  ------------------
  |  Branch (310:7): [True: 2.08k, False: 0]
  ------------------
  311|  2.08k|    ret = nullptr;
  312|      0|  else if (h->var & H_OPT_ALIASM)
  ------------------
  |  |   48|      0|#define H_OPT_ALIASM (1 << 1)   // using alias compression?
  ------------------
  |  Branch (312:12): [True: 0, False: 0]
  ------------------
  313|      0|    ret = get_stored_pointer(HENTRY_WORD(h) + h->blen + 1);
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
  314|      0|  else
  315|      0|    ret = HENTRY_WORD(h) + h->blen + 1;
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
  316|  2.08k|  return ret;
  317|  2.08k|}
_Z11HENTRY_FINDP6hentryPKc:
  332|      4|inline char* HENTRY_FIND(struct hentry* h, const char* p) {
  333|      4|  char* data = HENTRY_DATA(h);
  334|      4|  return data ? strstr(data, p) : nullptr;
  ------------------
  |  Branch (334:10): [True: 4, False: 0]
  ------------------
  335|      4|}
_Z17append_morph_stemRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPK6hentryb:
  340|  2.08k|inline void append_morph_stem(std::string& result, const struct hentry* h, bool complexprefixes) {
  341|  2.08k|  const char* data = HENTRY_DATA(h);
  342|  2.08k|  if (data && strstr(data, complexprefixes ? ":ts" : MORPH_STEM))
  ------------------
  |  |   99|      0|#define MORPH_STEM "st:"
  ------------------
  |  Branch (342:7): [True: 0, False: 2.08k]
  |  Branch (342:15): [True: 0, False: 0]
  |  Branch (342:28): [True: 0, False: 0]
  ------------------
  343|      0|    return;
  344|  2.08k|  result.push_back(MSEP_FLD);
  ------------------
  |  |  117|  2.08k|#define MSEP_FLD ' '
  ------------------
  345|  2.08k|  if (complexprefixes) {
  ------------------
  |  Branch (345:7): [True: 135, False: 1.94k]
  ------------------
  346|    135|    result.append(HENTRY_WORD(h));
  ------------------
  |  |   54|    135|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
  347|    135|    result.append(":ts");
  348|  1.94k|  } else {
  349|  1.94k|    result.append(MORPH_STEM);
  ------------------
  |  |   99|  1.94k|#define MORPH_STEM "st:"
  ------------------
  350|  1.94k|    result.append(HENTRY_WORD(h));
  ------------------
  |  |   54|  1.94k|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
  351|  1.94k|  }
  352|  2.08k|}
_ZZ20has_no_ignored_charsRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEES7_ENKUlcE_clEc:
  292|  6.31k|    [&word](char ic) { return word.find(ic) == std::string::npos; });

_ZN7FileMgrC2EPKcS1_:
   84|    114|    : hin(nullptr)
   85|    114|    , linenum(0) {
   86|    114|  in[0] = '\0';
   87|       |
   88|    114|  if (!file || !strlen(file))
  ------------------
  |  Branch (88:7): [True: 0, False: 114]
  |  Branch (88:16): [True: 0, False: 114]
  ------------------
   89|      0|    return;
   90|    114|  myopen(fin, file, std::ios_base::in);
   91|    114|  if (!fin.is_open()) {
  ------------------
  |  Branch (91:7): [True: 0, False: 114]
  ------------------
   92|       |    // check hzipped file
   93|      0|    std::string st(file);
   94|      0|    st.append(HZIP_EXTENSION);
  ------------------
  |  |   51|      0|#define HZIP_EXTENSION ".hz"
  ------------------
   95|      0|    hin = new Hunzip(st.c_str(), key);
   96|      0|  }
   97|    114|  if (!fin.is_open() && !hin->is_open())
  ------------------
  |  Branch (97:7): [True: 0, False: 114]
  |  Branch (97:25): [True: 0, False: 0]
  ------------------
   98|      0|    fail(MSG_OPEN, file);
  ------------------
  |  |   53|      0|#define MSG_OPEN "error: %s: cannot open\n"
  ------------------
   99|    114|}
_ZN7FileMgrD2Ev:
  101|    114|FileMgr::~FileMgr() {
  102|    114|  delete hin;
  103|    114|}
_ZN7FileMgr7getlineERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  105|  2.10k|bool FileMgr::getline(std::string& dest) {
  106|  2.10k|  bool ret = false;
  107|  2.10k|  ++linenum;
  108|  2.10k|  if (fin.is_open()) {
  ------------------
  |  Branch (108:7): [True: 2.10k, False: 0]
  ------------------
  109|       |    // a line longer than the buffer ends the read the same way the end of the
  110|       |    // file does
  111|  2.10k|    fin.getline(in, sizeof(in));
  112|  2.10k|    ret = !fin.fail();
  113|  2.10k|    if (ret)
  ------------------
  |  Branch (113:9): [True: 1.99k, False: 112]
  ------------------
  114|  1.99k|      dest.assign(in);
  115|  2.10k|  } else if (hin && hin->is_open()) {
  ------------------
  |  Branch (115:14): [True: 0, False: 0]
  |  Branch (115:21): [True: 0, False: 0]
  ------------------
  116|      0|    ret = hin->getline(dest);
  117|      0|  }
  118|  2.10k|  if (!ret) {
  ------------------
  |  Branch (118:7): [True: 112, False: 1.99k]
  ------------------
  119|    112|    --linenum;
  120|    112|  }
  121|  2.10k|  return ret;
  122|  2.10k|}
_ZN7FileMgr10getlinenumEv:
  124|    164|int FileMgr::getlinenum() {
  125|    164|  return linenum;
  126|    164|}

_ZN7HashMgrC2EPKcS1_S1_:
   93|     38|    : flag_mode(FLAG_CHAR)
   94|     38|    , complexprefixes(0)
   95|     38|    , utf8(0)
   96|     38|    , forbiddenword(FORBIDDENWORD)  // forbidden word signing flag
  ------------------
  |  |  123|     38|#define FORBIDDENWORD 65510
  ------------------
   97|     38|    , langnum(0)
   98|     38|    , csconv(nullptr) {
   99|     38|  load_config(apath, key);
  100|     38|  if (!csconv)
  ------------------
  |  Branch (100:7): [True: 38, False: 0]
  ------------------
  101|     38|    csconv = get_current_cs(SPELL_ENCODING);
  ------------------
  |  |   95|     38|#define SPELL_ENCODING "ISO8859-1"
  ------------------
  102|     38|  int ec = load_tables(tpath, key);
  103|     38|  if (ec) {
  ------------------
  |  Branch (103:7): [True: 0, False: 38]
  ------------------
  104|       |    /* error condition - what should we do here */
  105|      0|    fprintf(stderr, "Hash Manager Error : %d\n", ec);
  106|      0|    free_table();
  107|       |    //keep table size to 1 to fix possible division with zero
  108|      0|    tableptr.resize(1, nullptr);
  109|      0|  }
  110|     38|}
_ZN7HashMgr13release_flagsEPtb:
  112|    323|void HashMgr::release_flags(unsigned short* astr, bool owned) {
  113|    323|  if (owned)
  ------------------
  |  Branch (113:7): [True: 182, False: 141]
  ------------------
  114|    182|    delete[] astr;
  115|    323|}
_ZNK7HashMgr6lookupEPKcm:
  154|   584M|struct hentry* HashMgr::lookup(const char* word, size_t len) const {
  155|   584M|  struct hentry* dp = tableptr[hash(word, len)];
  156|   584M|  if (!dp)
  ------------------
  |  Branch (156:7): [True: 517M, False: 67.3M]
  ------------------
  157|   517M|    return nullptr;
  158|   140M|  for (; dp != nullptr; dp = dp->next) {
  ------------------
  |  Branch (158:10): [True: 76.4M, False: 63.7M]
  ------------------
  159|  76.4M|    if (strcmp(word, dp->word) == 0)
  ------------------
  |  Branch (159:9): [True: 3.57M, False: 72.9M]
  ------------------
  160|  3.57M|      return dp;
  161|  76.4M|  }
  162|  63.7M|  return nullptr;
  163|  67.3M|}
_ZN7HashMgr8add_wordERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmPtmPS7_bib:
  173|  7.91k|                      bool own_aff) {
  174|       |
  175|  7.91k|  if (al > std::numeric_limits<short>::max()) {
  ------------------
  |  Branch (175:7): [True: 0, False: 7.91k]
  ------------------
  176|      0|    HUNSPELL_WARNING(stderr, "error: affix len %zu is over max limit\n", al);
  177|      0|    release_flags(aff, own_aff);
  178|      0|    return 1;
  179|      0|  }
  180|       |
  181|  7.91k|  const std::string* word = &in_word;
  182|  7.91k|  const std::string* desc = in_desc;
  183|       |
  184|  7.91k|  std::string* word_copy = nullptr;
  185|  7.91k|  std::string* desc_copy = nullptr;
  186|  7.91k|  if ((!ignorechars.empty() && !has_no_ignored_chars(in_word, ignorechars)) || complexprefixes) {
  ------------------
  |  Branch (186:8): [True: 810, False: 7.10k]
  |  Branch (186:32): [True: 170, False: 640]
  |  Branch (186:80): [True: 482, False: 7.26k]
  ------------------
  187|    652|    word_copy = new std::string(in_word);
  188|       |
  189|    652|    if (!ignorechars.empty()) {
  ------------------
  |  Branch (189:9): [True: 170, False: 482]
  ------------------
  190|    170|      if (utf8) {
  ------------------
  |  Branch (190:11): [True: 34, False: 136]
  ------------------
  191|     34|        wcl = remove_ignored_chars_utf(*word_copy, ignorechars_utf16);
  192|    136|      } else {
  193|    136|        remove_ignored_chars(*word_copy, ignorechars);
  194|    136|      }
  195|    170|    }
  196|       |
  197|    652|    if (complexprefixes) {
  ------------------
  |  Branch (197:9): [True: 482, False: 170]
  ------------------
  198|    482|      if (utf8)
  ------------------
  |  Branch (198:11): [True: 0, False: 482]
  ------------------
  199|      0|        wcl = reverseword_utf(*word_copy);
  200|    482|      else
  201|    482|        reverseword(*word_copy);
  202|       |
  203|    482|      if (in_desc && aliasm.empty()) {
  ------------------
  |  Branch (203:11): [True: 0, False: 482]
  |  Branch (203:22): [True: 0, False: 0]
  ------------------
  204|      0|        desc_copy = new std::string(*in_desc);
  205|       |
  206|      0|        if (complexprefixes) {
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|          if (utf8)
  ------------------
  |  Branch (207:15): [True: 0, False: 0]
  ------------------
  208|      0|            reverseword_utf(*desc_copy);
  209|      0|          else
  210|      0|            reverseword(*desc_copy);
  211|      0|        }
  212|      0|        desc = desc_copy;
  213|      0|      }
  214|    482|    }
  215|       |
  216|    652|    word = word_copy;
  217|    652|  }
  218|       |
  219|       |  // limit of hp->blen
  220|  7.91k|  if (word->size() > std::numeric_limits<unsigned short>::max()) {
  ------------------
  |  Branch (220:7): [True: 0, False: 7.91k]
  ------------------
  221|      0|    HUNSPELL_WARNING(stderr, "error: word len %ld is over max limit\n", word->size());
  222|      0|    delete desc_copy;
  223|      0|    delete word_copy;
  224|      0|    release_flags(aff, own_aff);
  225|      0|    return 1;
  226|      0|  }
  227|       |
  228|  7.91k|  bool upcasehomonym = false;
  229|  7.91k|  size_t descl = desc ? (!aliasm.empty() ? sizeof(char*) : desc->size() + 1) : 0;
  ------------------
  |  Branch (229:18): [True: 4, False: 7.91k]
  |  Branch (229:26): [True: 0, False: 4]
  ------------------
  230|       |  // variable-length hash record with word and optional fields
  231|  7.91k|  auto hp =
  232|  7.91k|      (struct hentry*)arena_alloc(sizeof(struct hentry) + word->size() + descl,
  233|  7.91k|                                  alignof(struct hentry));
  234|  7.91k|  if (!hp) {
  ------------------
  |  Branch (234:7): [True: 0, False: 7.91k]
  ------------------
  235|      0|    delete desc_copy;
  236|      0|    delete word_copy;
  237|      0|    release_flags(aff, own_aff);
  238|      0|    return 1;
  239|      0|  }
  240|       |
  241|  7.91k|  char* hpw = hp->word;
  242|  7.91k|  memcpy(hpw, word->data(), word->size());
  243|  7.91k|  hpw[word->size()] = 0;
  244|       |
  245|  7.91k|  size_t i = hash(hpw, word->size());
  246|       |
  247|  7.91k|  hp->blen = (unsigned short)word->size();
  248|  7.91k|  hp->clen = (unsigned short)wcl;
  249|  7.91k|  hp->alen = (short)al;
  250|  7.91k|  hp->astr = aff;
  251|  7.91k|  hp->next = nullptr;
  252|  7.91k|  hp->next_homonym = nullptr;
  253|  7.91k|  hp->var = (captype == INITCAP) ? H_OPT_INITCAP : 0;
  ------------------
  |  |   89|  7.91k|#define INITCAP 1
  ------------------
                hp->var = (captype == INITCAP) ? H_OPT_INITCAP : 0;
  ------------------
  |  |   50|  4.66k|#define H_OPT_INITCAP (1 << 3)  // is dictionary word capitalized?
  ------------------
  |  Branch (253:13): [True: 4.66k, False: 3.24k]
  ------------------
  254|  7.91k|  if (own_aff)
  ------------------
  |  Branch (254:7): [True: 5.43k, False: 2.47k]
  ------------------
  255|  5.43k|    hp->var |= H_OPT_OWNFLAGS;
  ------------------
  |  |   51|  5.43k|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  256|       |
  257|       |  // store the description string or its pointer
  258|  7.91k|  if (desc) {
  ------------------
  |  Branch (258:7): [True: 4, False: 7.91k]
  ------------------
  259|      4|    hp->var |= H_OPT;
  ------------------
  |  |   47|      4|#define H_OPT (1 << 0)          // is there optional morphological data?
  ------------------
  260|      4|    if (!aliasm.empty()) {
  ------------------
  |  Branch (260:9): [True: 0, False: 4]
  ------------------
  261|      0|      hp->var |= H_OPT_ALIASM;
  ------------------
  |  |   48|      0|#define H_OPT_ALIASM (1 << 1)   // using alias compression?
  ------------------
  262|      0|      store_pointer(hpw + word->size() + 1, get_aliasm(atoi(desc->c_str())));
  263|      4|    } else {
  264|      4|      strcpy(hpw + word->size() + 1, desc->c_str());
  265|      4|    }
  266|      4|    if (HENTRY_FIND(hp, MORPH_PHON)) {
  ------------------
  |  |  110|      4|#define MORPH_PHON "ph:"
  ------------------
  |  Branch (266:9): [True: 2, False: 2]
  ------------------
  267|      2|      hp->var |= H_OPT_PHON;
  ------------------
  |  |   49|      2|#define H_OPT_PHON (1 << 2)     // is there ph: field in the morphological data?
  ------------------
  268|       |      // store ph: fields (pronounciation, misspellings, old orthography etc.)
  269|       |      // of a morphological description in reptable to use in REP replacements.
  270|      2|      size_t predicted = tableptr.size() / MORPH_PHON_RATIO;
  ------------------
  |  |   90|      2|#define MORPH_PHON_RATIO 500
  ------------------
  271|      2|      if (reptable.capacity() < predicted)
  ------------------
  |  Branch (271:11): [True: 2, False: 0]
  ------------------
  272|      2|          reptable.reserve(predicted);
  273|      2|      std::string fields = HENTRY_DATA(hp);
  274|      2|      std::string::const_iterator iter = fields.begin(), start_piece = mystrsep(fields, iter);
  275|      4|      while (start_piece != fields.end()) {
  ------------------
  |  Branch (275:14): [True: 2, False: 2]
  ------------------
  276|      2|        if (std::string(start_piece, iter).find(MORPH_PHON) == 0) {
  ------------------
  |  |  110|      2|#define MORPH_PHON "ph:"
  ------------------
  |  Branch (276:13): [True: 2, False: 0]
  ------------------
  277|      2|          std::string ph = std::string(start_piece, iter).substr(sizeof MORPH_PHON - 1);
  ------------------
  |  |  110|      2|#define MORPH_PHON "ph:"
  ------------------
  278|      2|          if (!ph.empty()) {
  ------------------
  |  Branch (278:15): [True: 2, False: 0]
  ------------------
  279|      2|            std::vector<w_char> w;
  280|      2|            size_t strippatt;
  281|      2|            std::string wordpart;
  282|       |            // dictionary based REP replacement, separated by "->"
  283|       |            // for example "pretty ph:prity ph:priti->pretti" to handle
  284|       |            // both prity -> pretty and pritier -> prettiest suggestions.
  285|      2|            if (((strippatt = ph.find("->")) != std::string::npos) &&
  ------------------
  |  Branch (285:17): [True: 0, False: 2]
  ------------------
  286|      0|                    (strippatt > 0) && (strippatt < ph.size() - 2)) {
  ------------------
  |  Branch (286:21): [True: 0, False: 0]
  |  Branch (286:40): [True: 0, False: 0]
  ------------------
  287|      0|                wordpart = ph.substr(strippatt + 2);
  288|      0|                ph.erase(ph.begin() + strippatt, ph.end());
  289|      0|            } else
  290|      2|                wordpart = in_word;
  291|       |            // when the ph: field ends with the character *,
  292|       |            // strip last character of the pattern and the replacement
  293|       |            // to match in REP suggestions also at character changes,
  294|       |            // for example, "pretty ph:prity*" results "prit->prett"
  295|       |            // REP replacement instead of "prity->pretty", to get
  296|       |            // prity->pretty and pritiest->prettiest suggestions.
  297|      2|            if (ph.at(ph.size()-1) == '*') {
  ------------------
  |  Branch (297:17): [True: 0, False: 2]
  ------------------
  298|      0|              strippatt = 1;
  299|      0|              size_t stripword = 0;
  300|      0|              if (utf8) {
  ------------------
  |  Branch (300:19): [True: 0, False: 0]
  ------------------
  301|      0|                while ((strippatt < ph.size()) &&
  ------------------
  |  Branch (301:24): [True: 0, False: 0]
  ------------------
  302|      0|                  is_utf8_cont(ph.at(ph.size()-strippatt-1)))
  ------------------
  |  Branch (302:19): [True: 0, False: 0]
  ------------------
  303|      0|                     ++strippatt;
  304|      0|                while ((stripword < wordpart.size()) &&
  ------------------
  |  Branch (304:24): [True: 0, False: 0]
  ------------------
  305|      0|                  is_utf8_cont(wordpart.at(wordpart.size()-stripword-1)))
  ------------------
  |  Branch (305:19): [True: 0, False: 0]
  ------------------
  306|      0|                     ++stripword;
  307|      0|              }
  308|      0|              ++strippatt;
  309|      0|              ++stripword;
  310|      0|              if ((ph.size() > strippatt) && (wordpart.size() > stripword)) {
  ------------------
  |  Branch (310:19): [True: 0, False: 0]
  |  Branch (310:46): [True: 0, False: 0]
  ------------------
  311|      0|                ph.erase(ph.size()-strippatt, strippatt);
  312|      0|                wordpart.erase(wordpart.size()-stripword, stripword);
  313|      0|              }
  314|      0|            }
  315|       |            // capitalize lowercase pattern for capitalized words to support
  316|       |            // good suggestions also for capitalized misspellings, eg.
  317|       |            // Wednesday ph:wendsay
  318|       |            // results wendsay -> Wednesday and Wendsay -> Wednesday, too.
  319|      2|            if (captype == INITCAP) {
  ------------------
  |  |   89|      2|#define INITCAP 1
  ------------------
  |  Branch (319:17): [True: 0, False: 2]
  ------------------
  320|      0|              std::string ph_capitalized;
  321|      0|              if (utf8) {
  ------------------
  |  Branch (321:19): [True: 0, False: 0]
  ------------------
  322|      0|                u8_u16(w, ph);
  323|      0|                if (get_captype_utf8(w, langnum) == NOCAP) {
  ------------------
  |  |   88|      0|#define NOCAP 0
  ------------------
  |  Branch (323:21): [True: 0, False: 0]
  ------------------
  324|      0|                  mkinitcap_utf(w, langnum);
  325|      0|                  u16_u8(ph_capitalized, w);
  326|      0|                }
  327|      0|              } else if (get_captype(ph, csconv) == NOCAP)
  ------------------
  |  |   88|      0|#define NOCAP 0
  ------------------
  |  Branch (327:26): [True: 0, False: 0]
  ------------------
  328|      0|                  mkinitcap(ph_capitalized, csconv);
  329|       |
  330|      0|              if (!ph_capitalized.empty()) {
  ------------------
  |  Branch (330:19): [True: 0, False: 0]
  ------------------
  331|       |                // add also lowercase word in the case of German or
  332|       |                // Hungarian to support lowercase suggestions lowercased by
  333|       |                // compound word generation or derivational suffixes
  334|       |                // (for example by adjectival suffix "-i" of geographical
  335|       |                // names in Hungarian:
  336|       |                // Massachusetts ph:messzecsuzec
  337|       |                // messzecsuzeci -> massachusettsi (adjective)
  338|       |                // For lowercasing by conditional PFX rules, see
  339|       |                // tests/germancompounding test example or the
  340|       |                // Hungarian dictionary.)
  341|      0|                if (langnum == LANG_de || langnum == LANG_hu) {
  ------------------
  |  Branch (341:21): [True: 0, False: 0]
  |  Branch (341:43): [True: 0, False: 0]
  ------------------
  342|      0|                  std::string wordpart_lower(wordpart);
  343|      0|                  if (utf8) {
  ------------------
  |  Branch (343:23): [True: 0, False: 0]
  ------------------
  344|      0|                    u8_u16(w, wordpart_lower);
  345|      0|                    mkallsmall_utf(w, langnum);
  346|      0|                    u16_u8(wordpart_lower, w);
  347|      0|                  } else {
  348|      0|                    mkallsmall(wordpart_lower, csconv);
  349|      0|                  }
  350|      0|                  reptable.emplace_back();
  351|      0|                  reptable.back().pattern.assign(ph);
  352|      0|                  reptable.back().outstrings[0].assign(wordpart_lower);
  353|      0|                }
  354|      0|                reptable.emplace_back();
  355|      0|                reptable.back().pattern.assign(ph_capitalized);
  356|      0|                reptable.back().outstrings[0].assign(wordpart);
  357|      0|              }
  358|      0|            }
  359|      2|            reptable.emplace_back();
  360|      2|            reptable.back().pattern.assign(ph);
  361|      2|            reptable.back().outstrings[0].assign(wordpart);
  362|      2|          }
  363|      2|        }
  364|      2|        start_piece = mystrsep(fields, iter);
  365|      2|      }
  366|      2|    }
  367|      4|  }
  368|       |
  369|  7.91k|  struct hentry* dp = tableptr[i];
  370|  7.91k|  if (!dp) {
  ------------------
  |  Branch (370:7): [True: 6.11k, False: 1.79k]
  ------------------
  371|  6.11k|    tableptr[i] = hp;
  372|  6.11k|    delete desc_copy;
  373|  6.11k|    delete word_copy;
  374|  6.11k|    return 0;
  375|  6.11k|  }
  376|  2.18k|  while (dp->next != nullptr) {
  ------------------
  |  Branch (376:10): [True: 397, False: 1.78k]
  ------------------
  377|    397|    if ((!dp->next_homonym) && (strcmp(hp->word, dp->word) == 0)) {
  ------------------
  |  Branch (377:9): [True: 388, False: 9]
  |  Branch (377:32): [True: 10, False: 378]
  ------------------
  378|       |      // remove hidden onlyupcase homonym
  379|     10|      if (!onlyupcase) {
  ------------------
  |  Branch (379:11): [True: 9, False: 1]
  ------------------
  380|      9|        if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) {
  ------------------
  |  |  102|      8|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 8, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (380:13): [True: 8, False: 1]
  |  Branch (380:13): [True: 8, False: 1]
  ------------------
  381|      8|          release_flags(dp->astr, dp->var & H_OPT_OWNFLAGS);
  ------------------
  |  |   51|      8|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  382|      8|          dp->astr = hp->astr;
  383|      8|          dp->alen = hp->alen;
  384|      8|          dp->var &= ~H_OPT_OWNFLAGS;
  ------------------
  |  |   51|      8|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  385|      8|          dp->var |= (hp->var & H_OPT_OWNFLAGS);
  ------------------
  |  |   51|      8|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  386|      8|          arena_free(hp);
  387|      8|          delete desc_copy;
  388|      8|          delete word_copy;
  389|      8|          return 0;
  390|      8|        } else if (!dp->astr && dp->alen == 0 &&
  ------------------
  |  Branch (390:20): [True: 1, False: 0]
  |  Branch (390:33): [True: 1, False: 0]
  ------------------
  391|      1|                   !hp->astr && hp->alen == 0) {
  ------------------
  |  Branch (391:20): [True: 1, False: 0]
  |  Branch (391:33): [True: 1, False: 0]
  ------------------
  392|       |          // word already exists with no flags, skip duplicate
  393|      1|          release_flags(hp->astr, hp->var & H_OPT_OWNFLAGS);
  ------------------
  |  |   51|      1|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  394|      1|          arena_free(hp);
  395|      1|          delete desc_copy;
  396|      1|          delete word_copy;
  397|      1|          return 0;
  398|      1|        } else {
  399|      0|          dp->next_homonym = hp;
  400|      0|        }
  401|      9|      } else {
  402|      1|        upcasehomonym = true;
  403|      1|      }
  404|     10|    }
  405|    388|    dp = dp->next;
  406|    388|  }
  407|  1.78k|  if (strcmp(hp->word, dp->word) == 0) {
  ------------------
  |  Branch (407:7): [True: 322, False: 1.46k]
  ------------------
  408|       |    // remove hidden onlyupcase homonym
  409|    322|    if (!onlyupcase) {
  ------------------
  |  Branch (409:9): [True: 191, False: 131]
  ------------------
  410|    191|      if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) {
  ------------------
  |  |  102|     28|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 28, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (410:11): [True: 28, False: 163]
  |  Branch (410:11): [True: 28, False: 163]
  ------------------
  411|     28|        release_flags(dp->astr, dp->var & H_OPT_OWNFLAGS);
  ------------------
  |  |   51|     28|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  412|     28|        dp->astr = hp->astr;
  413|     28|        dp->alen = hp->alen;
  414|     28|        dp->var &= ~H_OPT_OWNFLAGS;
  ------------------
  |  |   51|     28|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  415|     28|        dp->var |= (hp->var & H_OPT_OWNFLAGS);
  ------------------
  |  |   51|     28|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  416|     28|        arena_free(hp);
  417|     28|        delete desc_copy;
  418|     28|        delete word_copy;
  419|     28|        return 0;
  420|    163|      } else if (!dp->astr && dp->alen == 0 &&
  ------------------
  |  Branch (420:18): [True: 163, False: 0]
  |  Branch (420:31): [True: 163, False: 0]
  ------------------
  421|    163|                 !hp->astr && hp->alen == 0) {
  ------------------
  |  Branch (421:18): [True: 154, False: 9]
  |  Branch (421:31): [True: 154, False: 0]
  ------------------
  422|       |        // word already exists with no flags, skip duplicate
  423|    154|        release_flags(hp->astr, hp->var & H_OPT_OWNFLAGS);
  ------------------
  |  |   51|    154|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  424|    154|        arena_free(hp);
  425|    154|        delete desc_copy;
  426|    154|        delete word_copy;
  427|    154|        return 0;
  428|    154|      } else {
  429|      9|        dp->next_homonym = hp;
  430|      9|      }
  431|    191|    } else {
  432|    131|      upcasehomonym = true;
  433|    131|    }
  434|    322|  }
  435|  1.60k|  if (!upcasehomonym) {
  ------------------
  |  Branch (435:7): [True: 1.47k, False: 132]
  ------------------
  436|  1.47k|    dp->next = hp;
  437|  1.47k|  } else {
  438|       |    // remove hidden onlyupcase homonym
  439|    132|    release_flags(hp->astr, hp->var & H_OPT_OWNFLAGS);
  ------------------
  |  |   51|    132|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  440|    132|    arena_free(hp);
  441|    132|  }
  442|       |
  443|  1.60k|  delete desc_copy;
  444|  1.60k|  delete word_copy;
  445|  1.60k|  return 0;
  446|  1.78k|}
_ZN7HashMgr27add_hidden_capitalized_wordERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmPtmPS7_i:
  453|  5.59k|                                         int captype) {
  454|  5.59k|  if (flags == nullptr)
  ------------------
  |  Branch (454:7): [True: 5.47k, False: 127]
  ------------------
  455|  5.47k|    flagslen = 0;
  456|       |
  457|       |  // add inner capitalized forms to handle the following allcap forms:
  458|       |  // Mixed caps: OpenOffice.org -> OPENOFFICE.ORG
  459|       |  // Allcaps with suffixes: CIA's -> CIA'S
  460|  5.59k|  if (((captype == HUHCAP) || (captype == HUHINITCAP) ||
  ------------------
  |  |   91|  5.59k|#define HUHCAP 3
  ------------------
                if (((captype == HUHCAP) || (captype == HUHINITCAP) ||
  ------------------
  |  |   92|  5.27k|#define HUHINITCAP 4
  ------------------
  |  Branch (460:8): [True: 320, False: 5.27k]
  |  Branch (460:31): [True: 1.99k, False: 3.28k]
  ------------------
  461|  3.28k|       ((captype == ALLCAP) && (flagslen != 0))) &&
  ------------------
  |  |   90|  3.28k|#define ALLCAP 2
  ------------------
  |  Branch (461:9): [True: 207, False: 3.07k]
  |  Branch (461:32): [True: 0, False: 207]
  ------------------
  462|  2.31k|      !((flagslen != 0) && TESTAFF(flags, forbiddenword, flagslen))) {
  ------------------
  |  |  102|     45|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 45]
  |  |  ------------------
  ------------------
  |  Branch (462:9): [True: 45, False: 2.27k]
  ------------------
  463|  2.31k|    auto flags2 = (unsigned short*)arena_alloc((flagslen + 1) * sizeof(unsigned short),
  464|  2.31k|                                                alignof(unsigned short));
  465|  2.31k|    flags2[flagslen] = ONLYUPCASEFLAG;
  ------------------
  |  |  124|  2.31k|#define ONLYUPCASEFLAG 65511
  ------------------
  466|  2.31k|    if (flagslen) {
  ------------------
  |  Branch (466:9): [True: 45, False: 2.27k]
  ------------------
  467|     45|      memcpy(flags2, flags, flagslen * sizeof(unsigned short));
  468|     45|      std::sort(flags2, flags2 + flagslen + 1);
  469|     45|    }
  470|  2.31k|    if (utf8) {
  ------------------
  |  Branch (470:9): [True: 333, False: 1.98k]
  ------------------
  471|    333|      std::string st;
  472|    333|      std::vector<w_char> w;
  473|    333|      u8_u16(w, word);
  474|    333|      mkallsmall_utf(w, langnum);
  475|    333|      mkinitcap_utf(w, langnum);
  476|    333|      u16_u8(st, w);
  477|    333|      return add_word(st, wcl, flags2, flagslen + 1, dp, true, INITCAP, false);
  ------------------
  |  |   89|    333|#define INITCAP 1
  ------------------
  478|  1.98k|    } else {
  479|  1.98k|      std::string new_word(word);
  480|  1.98k|      mkallsmall(new_word, csconv);
  481|  1.98k|      mkinitcap(new_word, csconv);
  482|  1.98k|      int ret = add_word(new_word, wcl, flags2, flagslen + 1, dp, true, INITCAP, false);
  ------------------
  |  |   89|  1.98k|#define INITCAP 1
  ------------------
  483|  1.98k|      return ret;
  484|  1.98k|    }
  485|  2.31k|  }
  486|  3.28k|  return 0;
  487|  5.59k|}
_ZN7HashMgr20get_clen_and_captypeERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPiRNS0_6vectorI6w_charNS4_ISB_EEEE:
  490|  5.59k|size_t HashMgr::get_clen_and_captype(const std::string& word, int* captype, std::vector<w_char> &workbuf) {
  491|  5.59k|  size_t len;
  492|  5.59k|  if (utf8) {
  ------------------
  |  Branch (492:7): [True: 2.65k, False: 2.94k]
  ------------------
  493|  2.65k|    u8_u16(workbuf, word);
  494|  2.65k|    len = workbuf.size();
  495|  2.65k|    *captype = get_captype_utf8(workbuf, langnum);
  496|  2.94k|  } else {
  497|  2.94k|    len = word.size();
  498|  2.94k|    *captype = get_captype(word, csconv);
  499|  2.94k|  }
  500|  5.59k|  return len;
  501|  5.59k|}
_ZN7HashMgr20get_clen_and_captypeERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPi:
  503|  5.43k|size_t HashMgr::get_clen_and_captype(const std::string& word, int* captype) {
  504|  5.43k|  std::vector<w_char> workbuf;
  505|  5.43k|  return get_clen_and_captype(word, captype, workbuf);
  506|  5.43k|}
_ZN7HashMgr21remove_forbidden_flagERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  536|  7.44k|void HashMgr::remove_forbidden_flag(const std::string& word) {
  537|  7.44k|  struct hentry* dp = lookup(word.c_str(), word.size());
  538|  7.44k|  if (!dp)
  ------------------
  |  Branch (538:7): [True: 7.09k, False: 350]
  ------------------
  539|  7.09k|    return;
  540|    709|  while (dp) {
  ------------------
  |  Branch (540:10): [True: 359, False: 350]
  ------------------
  541|    359|    if (dp->astr && TESTAFF(dp->astr, forbiddenword, dp->alen)) {
  ------------------
  |  |  102|     33|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 33]
  |  |  ------------------
  ------------------
  |  Branch (541:9): [True: 33, False: 326]
  ------------------
  542|      0|      if (dp->alen == 1) {
  ------------------
  |  Branch (542:11): [True: 0, False: 0]
  ------------------
  543|      0|        release_flags(dp->astr, dp->var & H_OPT_OWNFLAGS);
  ------------------
  |  |   51|      0|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  544|      0|        dp->astr = nullptr;
  545|      0|        dp->alen = 0;
  546|      0|        dp->var &= ~H_OPT_OWNFLAGS;
  ------------------
  |  |   51|      0|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  547|      0|      } else {
  548|      0|        auto newflags = new unsigned short[dp->alen - 1];
  549|      0|        int j = 0;
  550|      0|        for (int i = 0; i < dp->alen; i++) {
  ------------------
  |  Branch (550:25): [True: 0, False: 0]
  ------------------
  551|      0|          if (dp->astr[i] != forbiddenword)
  ------------------
  |  Branch (551:15): [True: 0, False: 0]
  ------------------
  552|      0|            newflags[j++] = dp->astr[i];
  553|      0|        }
  554|      0|        release_flags(dp->astr, dp->var & H_OPT_OWNFLAGS);
  ------------------
  |  |   51|      0|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  555|      0|        dp->astr = newflags;
  556|      0|        dp->alen = (short)j;
  557|      0|        dp->var |= H_OPT_OWNFLAGS;
  ------------------
  |  |   51|      0|#define H_OPT_OWNFLAGS (1 << 4) // astr is independently allocated?
  ------------------
  558|      0|      }
  559|      0|    }
  560|    359|    dp = dp->next_homonym;
  561|    359|  }
  562|    350|}
_ZN7HashMgr3addERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  565|  5.39k|int HashMgr::add(const std::string& word) {
  566|  5.39k|  remove_forbidden_flag(word);
  567|  5.39k|  int captype, al = 0;
  568|  5.39k|  unsigned short* flags = nullptr;
  569|  5.39k|  size_t wcl = get_clen_and_captype(word, &captype);
  570|  5.39k|  if (add_word(word, wcl, flags, al, nullptr, false, captype, true))
  ------------------
  |  Branch (570:7): [True: 0, False: 5.39k]
  ------------------
  571|      0|    return 1;
  572|  5.39k|  return add_hidden_capitalized_word(word, wcl, flags, al, nullptr, captype);
  573|  5.39k|}
_ZN7HashMgr14add_with_affixERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_:
  590|  2.05k|int HashMgr::add_with_affix(const std::string& word, const std::string& example) {
  591|       |  // detect captype and modify word length for UTF-8 encoding
  592|  2.05k|  struct hentry* dp = lookup(example.c_str(), example.size());
  593|  2.05k|  remove_forbidden_flag(word);
  594|  2.05k|  if (dp && dp->astr) {
  ------------------
  |  Branch (594:7): [True: 155, False: 1.89k]
  |  Branch (594:13): [True: 45, False: 110]
  ------------------
  595|     45|    int captype;
  596|     45|    size_t wcl = get_clen_and_captype(word, &captype);
  597|     45|    auto flags = new unsigned short[dp->alen];
  598|     45|    memcpy(flags, dp->astr, dp->alen * sizeof(unsigned short));
  599|     45|    if (add_word(word, wcl, flags, dp->alen, nullptr, false, captype, true))
  ------------------
  |  Branch (599:9): [True: 0, False: 45]
  ------------------
  600|      0|      return 1;
  601|     45|    return add_hidden_capitalized_word(word, wcl, flags, dp->alen, nullptr, captype);
  602|     45|  }
  603|  2.00k|  return 1;
  604|  2.05k|}
_ZNK7HashMgr14walk_hashtableERiP6hentry:
  608|  2.14M|struct hentry* HashMgr::walk_hashtable(int& col, struct hentry* hp) const {
  609|  2.14M|  if (hp && hp->next != nullptr)
  ------------------
  |  Branch (609:7): [True: 2.08M, False: 62.5k]
  |  Branch (609:13): [True: 185k, False: 1.89M]
  ------------------
  610|   185k|    return hp->next;
  611|  63.1M|  for (col++; col < (int)tableptr.size(); ++col) {
  ------------------
  |  Branch (611:15): [True: 63.1M, False: 62.5k]
  ------------------
  612|  63.1M|    if (tableptr[col])
  ------------------
  |  Branch (612:9): [True: 1.89M, False: 61.2M]
  ------------------
  613|  1.89M|      return tableptr[col];
  614|  63.1M|  }
  615|       |  // null at end and reset to start
  616|  62.5k|  col = -1;
  617|  62.5k|  return nullptr;
  618|  1.95M|}
_ZN7HashMgr11load_tablesEPKcS1_:
  621|     38|int HashMgr::load_tables(const char* tpath, const char* key) {
  622|       |  // open dictionary file
  623|     38|  FileMgr* dict = new FileMgr(tpath, key);
  624|       |
  625|       |  // first read the first line of file to get hash table size
  626|     38|  std::string ts;
  627|     38|  if (!dict->getline(ts)) {
  ------------------
  |  Branch (627:7): [True: 0, False: 38]
  ------------------
  628|      0|    fprintf(stderr, "error: empty dic file %s\n", tpath);
  629|      0|    delete dict;
  630|      0|    return 2;
  631|      0|  }
  632|     38|  mychomp(ts);
  633|       |
  634|       |  /* remove byte order mark */
  635|     38|  if (ts.compare(0, 3, "\xEF\xBB\xBF", 3) == 0) {
  ------------------
  |  Branch (635:7): [True: 0, False: 38]
  ------------------
  636|      0|    ts.erase(0, 3);
  637|      0|  }
  638|       |
  639|     38|  int tablesize = atoi(ts.c_str());
  640|       |
  641|     38|  const int nExtra = 5 + USERWORD;
  ------------------
  |  |   57|     38|#define USERWORD 1000
  ------------------
  642|       |#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
  643|       |  // covers full-form uncompressed dictionaries (~7M for uk_UA expanded)
  644|       |  const int max_allowed = 10000000;
  645|       |#else
  646|     38|  const int max_allowed = (10000 - 1 - nExtra) / int(sizeof(struct hentry*));
  647|     38|#endif
  648|       |
  649|     38|  if (tablesize <= 0 || tablesize >= max_allowed) {
  ------------------
  |  Branch (649:7): [True: 0, False: 38]
  |  Branch (649:25): [True: 0, False: 38]
  ------------------
  650|      0|    fprintf(stderr,
  651|      0|            "error: %s: line 1: missing or bad word count in the dic file\n",
  652|      0|            tpath);
  653|      0|    delete dict;
  654|      0|    return 4;
  655|      0|  }
  656|     38|  tablesize += nExtra;
  657|     38|  if ((tablesize & 1) == 0)
  ------------------
  |  Branch (657:7): [True: 18, False: 20]
  ------------------
  658|     18|    tablesize++;
  659|       |
  660|       |  // allocate the hash table
  661|     38|  tableptr.resize(tablesize, nullptr);
  662|       |
  663|       |  // loop through all words on much list and add to hash
  664|       |  // table and create word and affix strings
  665|       |
  666|     38|  std::vector<w_char> workbuf;
  667|       |
  668|     38|  int nLineCount(0);
  669|    198|  while (dict->getline(ts)) {
  ------------------
  |  Branch (669:10): [True: 160, False: 38]
  ------------------
  670|    160|    ++nLineCount;
  671|    160|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  672|       |    // limit words loaded to avoid O(n^2) hash chain walk timeout
  673|    160|    if (nLineCount >= tablesize)
  ------------------
  |  Branch (673:9): [True: 0, False: 160]
  ------------------
  674|      0|      break;
  675|    160|#endif
  676|    160|    mychomp(ts);
  677|       |    // split each line into word and morphological description
  678|    160|    size_t dp_pos = 0;
  679|    160|    while ((dp_pos = ts.find(':', dp_pos)) != std::string::npos) {
  ------------------
  |  Branch (679:12): [True: 4, False: 156]
  ------------------
  680|      4|      if ((dp_pos > 3) && (ts[dp_pos - 3] == ' ' || ts[dp_pos - 3] == '\t')) {
  ------------------
  |  Branch (680:11): [True: 4, False: 0]
  |  Branch (680:28): [True: 0, False: 4]
  |  Branch (680:53): [True: 4, False: 0]
  ------------------
  681|      4|        for (dp_pos -= 3; dp_pos > 0 && (ts[dp_pos-1] == ' ' || ts[dp_pos-1] == '\t'); --dp_pos)
  ------------------
  |  Branch (681:27): [True: 4, False: 0]
  |  Branch (681:42): [True: 0, False: 4]
  |  Branch (681:65): [True: 0, False: 4]
  ------------------
  682|      0|          ;
  683|      4|        if (dp_pos == 0) {  // missing word
  ------------------
  |  Branch (683:13): [True: 0, False: 4]
  ------------------
  684|      0|          dp_pos = std::string::npos;
  685|      4|        } else {
  686|      4|          ++dp_pos;
  687|      4|        }
  688|      4|        break;
  689|      4|      }
  690|      0|      ++dp_pos;
  691|      0|    }
  692|       |
  693|       |    // tabulator is the old morphological field separator
  694|    160|    size_t dp2_pos = ts.find('\t');
  695|    160|    if (dp2_pos != std::string::npos && (dp_pos == std::string::npos || dp2_pos < dp_pos)) {
  ------------------
  |  Branch (695:9): [True: 4, False: 156]
  |  Branch (695:42): [True: 0, False: 4]
  |  Branch (695:73): [True: 4, False: 0]
  ------------------
  696|      4|      dp_pos = dp2_pos + 1;
  697|      4|    }
  698|       |
  699|    160|    std::string dp;
  700|    160|    if (dp_pos != std::string::npos) {
  ------------------
  |  Branch (700:9): [True: 4, False: 156]
  ------------------
  701|      4|      dp.assign(ts.substr(dp_pos));
  702|      4|      ts.resize(dp_pos - 1);
  703|      4|    }
  704|       |
  705|       |    // split each line into word and affix char strings
  706|       |    // "\/" signs slash in words (not affix separator)
  707|       |    // "/" at beginning of the line is word character (not affix separator)
  708|    160|    size_t ap_pos = ts.find('/');
  709|    160|    while (ap_pos != std::string::npos) {
  ------------------
  |  Branch (709:12): [True: 82, False: 78]
  ------------------
  710|     82|      if (ap_pos == 0) {
  ------------------
  |  Branch (710:11): [True: 0, False: 82]
  ------------------
  711|      0|        ++ap_pos;
  712|      0|        ap_pos = ts.find('/', ap_pos);
  713|      0|        continue;
  714|     82|      } else if (ts[ap_pos - 1] != '\\')
  ------------------
  |  Branch (714:18): [True: 82, False: 0]
  ------------------
  715|     82|        break;
  716|       |      // replace "\/" with "/"
  717|      0|      ts.erase(ap_pos - 1, 1);
  718|      0|      ap_pos = ts.find('/', ap_pos);
  719|      0|    }
  720|       |
  721|    160|    unsigned short* flags;
  722|    160|    size_t al;
  723|    160|    if (ap_pos != std::string::npos && ap_pos != ts.size()) {
  ------------------
  |  Branch (723:9): [True: 82, False: 78]
  |  Branch (723:40): [True: 82, False: 0]
  ------------------
  724|     82|      std::string ap(ts.substr(ap_pos + 1));
  725|     82|      ts.resize(ap_pos);
  726|     82|      if (!aliasf.empty()) {
  ------------------
  |  Branch (726:11): [True: 2, False: 80]
  ------------------
  727|      2|        int index = atoi(ap.c_str());
  728|      2|        al = get_aliasf(index, &flags, dict);
  729|      2|        if (!al) {
  ------------------
  |  Branch (729:13): [True: 0, False: 2]
  ------------------
  730|      0|          HUNSPELL_WARNING(stderr, "error: line %d: bad flag vector alias\n",
  731|      0|                           dict->getlinenum());
  732|      0|        }
  733|     80|      } else {
  734|     80|        al = decode_flags(&flags, ap, dict, /* arena = */ true);
  735|     80|        std::sort(flags, flags + al);
  736|     80|      }
  737|     82|    } else {
  738|     78|      al = 0;
  739|     78|      flags = nullptr;
  740|     78|    }
  741|       |
  742|    160|    int captype;
  743|    160|    size_t wcl = get_clen_and_captype(ts, &captype, workbuf);
  744|    160|    const std::string* dp_str = dp.empty() ? nullptr : &dp;
  ------------------
  |  Branch (744:33): [True: 156, False: 4]
  ------------------
  745|       |    // add the word and its index plus its capitalized form optionally
  746|       |    // flags are arena-allocated, so own_aff must be false
  747|    160|    bool own = false;
  748|    160|    if (add_word(ts, wcl, flags, al, dp_str, false, captype, own) ||
  ------------------
  |  Branch (748:9): [True: 0, False: 160]
  ------------------
  749|    160|        add_hidden_capitalized_word(ts, wcl, flags, al, dp_str, captype)) {
  ------------------
  |  Branch (749:9): [True: 0, False: 160]
  ------------------
  750|      0|      delete dict;
  751|      0|      return 5;
  752|      0|    }
  753|    160|  }
  754|       |
  755|     38|  int ret(0);
  756|       |
  757|       |  // reject ludicrous tablesizes
  758|     38|  if (tablesize > 8192 + nExtra && tablesize > nLineCount * 10 + nExtra) {
  ------------------
  |  Branch (758:7): [True: 0, False: 38]
  |  Branch (758:36): [True: 0, False: 0]
  ------------------
  759|      0|    HUNSPELL_WARNING(stderr, ".dic initial approximate word count line value of %d is too large for %d lines\n", tablesize, nLineCount);
  760|      0|    ret = 3;
  761|      0|  }
  762|       |
  763|     38|  delete dict;
  764|     38|  return ret;
  765|     38|}
_ZNK7HashMgr4hashEPKcm:
  769|   584M|size_t HashMgr::hash(const char* word, size_t len) const {
  770|   584M|  unsigned long hv = 0;
  771|   584M|  size_t i = 0;
  772|  2.88G|  while (i < 4 && i < len)
  ------------------
  |  Branch (772:10): [True: 2.32G, False: 555M]
  |  Branch (772:19): [True: 2.29G, False: 29.0M]
  ------------------
  773|  2.29G|    hv = (hv << 8) | word[i++];
  774|  11.7G|  while (i < len) {
  ------------------
  |  Branch (774:10): [True: 11.1G, False: 584M]
  ------------------
  775|  11.1G|    ROTATE(hv, ROTATE_LEN);
  ------------------
  |  |   44|  11.1G|  (v) = ((v) << (q)) | (((v) >> (32 - q)) & ((1 << (q)) - 1));
  ------------------
  776|  11.1G|    hv ^= word[i++];
  777|  11.1G|  }
  778|   584M|  return (unsigned long)hv % tableptr.size();
  779|   584M|}
_ZNK7HashMgr12decode_flagsEPPtRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEP7FileMgr:
  781|     16|size_t HashMgr::decode_flags(unsigned short** result, const std::string& flags, FileMgr* af) const {
  782|     16|  return decode_flags(result, flags, af, /* arena = */ false);
  783|     16|}
_ZNK7HashMgr12decode_flagsEPPtRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEP7FileMgrb:
  785|    100|size_t HashMgr::decode_flags(unsigned short** result, const std::string& flags, FileMgr* af, bool use_arena) const {
  786|    100|  auto alloc = [&](size_t n) -> unsigned short* {
  787|    100|    return use_arena ? (unsigned short*)this->arena_alloc(n * sizeof(unsigned short),
  788|    100|                                                          alignof(unsigned short))
  789|    100|                     : new unsigned short[n];
  790|    100|  };
  791|    100|  size_t len;
  792|    100|  if (flags.empty()) {
  ------------------
  |  Branch (792:7): [True: 0, False: 100]
  ------------------
  793|      0|    *result = nullptr;
  794|      0|    return 0;
  795|      0|  }
  796|    100|  switch (flag_mode) {
  797|      0|    case FLAG_LONG: {  // two-character flags (1x2yZz -> 1x 2y Zz)
  ------------------
  |  Branch (797:5): [True: 0, False: 100]
  ------------------
  798|      0|      len = flags.size();
  799|      0|      if ((len & 1) == 1 && af != nullptr)
  ------------------
  |  Branch (799:11): [True: 0, False: 0]
  |  Branch (799:29): [True: 0, False: 0]
  ------------------
  800|      0|        HUNSPELL_WARNING(stderr, "error: line %d: bad flagvector\n",
  801|      0|                         af->getlinenum());
  802|      0|      len >>= 1;
  803|      0|      *result = alloc(len);
  804|      0|      for (size_t i = 0; i < len; i++) {
  ------------------
  |  Branch (804:26): [True: 0, False: 0]
  ------------------
  805|      0|        unsigned short flag = ((unsigned short)((unsigned char)flags[i << 1]) << 8) |
  806|      0|                              ((unsigned short)((unsigned char)flags[(i << 1) | 1]));
  807|       |
  808|      0|        (*result)[i] = flag;
  809|      0|      }
  810|      0|      break;
  811|      0|    }
  812|      0|    case FLAG_NUM: {  // decimal numbers separated by comma (4521,23,233 -> 4521
  ------------------
  |  Branch (812:5): [True: 0, False: 100]
  ------------------
  813|       |                      // 23 233)
  814|      0|      len = size_t(1 + std::count_if(flags.begin(), flags.end(), [](char c) { return c == ','; }));
  815|      0|      *result = alloc(len);
  816|      0|      unsigned short* dest = *result;
  817|      0|      const char* src = flags.c_str();
  818|      0|      for (size_t p = 0; p < flags.size(); ++p) {
  ------------------
  |  Branch (818:26): [True: 0, False: 0]
  ------------------
  819|      0|        if (flags[p] == ',') {
  ------------------
  |  Branch (819:13): [True: 0, False: 0]
  ------------------
  820|      0|          int i = atoi(src);
  821|      0|          if ((i > std::numeric_limits<unsigned short>::max() || i < 0) && af != nullptr) {
  ------------------
  |  Branch (821:16): [True: 0, False: 0]
  |  Branch (821:66): [True: 0, False: 0]
  |  Branch (821:76): [True: 0, False: 0]
  ------------------
  822|      0|            HUNSPELL_WARNING(
  823|      0|                stderr, "error: line %d: flag id %d is out of range\n",
  824|      0|                af->getlinenum(), i);
  825|      0|             i = 0;
  826|      0|          }
  827|      0|          *dest = (unsigned short)i;
  828|      0|          if (*dest == 0 && af != nullptr)
  ------------------
  |  Branch (828:15): [True: 0, False: 0]
  |  Branch (828:29): [True: 0, False: 0]
  ------------------
  829|      0|            HUNSPELL_WARNING(stderr, "error: line %d: 0 is wrong flag id\n",
  830|      0|                             af->getlinenum());
  831|      0|          src = flags.c_str() + p + 1;
  832|      0|          dest++;
  833|      0|        }
  834|      0|      }
  835|      0|      int i = atoi(src);
  836|      0|      if ((i > std::numeric_limits<unsigned short>::max() || i < 0) && af) {
  ------------------
  |  Branch (836:12): [True: 0, False: 0]
  |  Branch (836:62): [True: 0, False: 0]
  |  Branch (836:72): [True: 0, False: 0]
  ------------------
  837|      0|        HUNSPELL_WARNING(stderr,
  838|      0|                         "error: line %d: flag id %d is out of range\n",
  839|      0|                         af->getlinenum(), i);
  840|      0|        i = 0;
  841|      0|      }
  842|      0|      *dest = (unsigned short)i;
  843|      0|      if (*dest == 0 && af)
  ------------------
  |  Branch (843:11): [True: 0, False: 0]
  |  Branch (843:25): [True: 0, False: 0]
  ------------------
  844|      0|        HUNSPELL_WARNING(stderr, "error: line %d: 0 is wrong flag id\n",
  845|      0|                         af->getlinenum());
  846|      0|      break;
  847|      0|    }
  848|      0|    case FLAG_UNI: {  // UTF-8 characters
  ------------------
  |  Branch (848:5): [True: 0, False: 100]
  ------------------
  849|      0|      std::vector<w_char> w;
  850|      0|      u8_u16(w, flags);
  851|      0|      len = w.size();
  852|      0|      *result = alloc(len);
  853|      0|#if defined(_WIN32) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__))  || defined(__LITTLE_ENDIAN__)
  854|      0|      memcpy(*result, w.data(), len * sizeof(unsigned short));
  855|       |#else
  856|       |      unsigned short* dest = *result;
  857|       |      for (const w_char wc : w) {
  858|       |        *dest = (unsigned short)wc;
  859|       |        dest++;
  860|       |      }
  861|       |#endif
  862|      0|      break;
  863|      0|    }
  864|    100|    default: {  // Ispell's one-character flags (erfg -> e r f g)
  ------------------
  |  Branch (864:5): [True: 100, False: 0]
  ------------------
  865|    100|      len = flags.size();
  866|    100|      *result = alloc(len);
  867|    100|      unsigned short* dest = *result;
  868|    118|      for (const char flag : flags) {
  ------------------
  |  Branch (868:28): [True: 118, False: 100]
  ------------------
  869|    118|        *dest = (unsigned char)flag;
  870|    118|        dest++;
  871|    118|      }
  872|    100|    }
  873|    100|  }
  874|    100|  return len;
  875|    100|}
_ZNK7HashMgr11decode_flagERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  951|     92|unsigned short HashMgr::decode_flag(const std::string& f) const {
  952|     92|  unsigned short s = 0;
  953|     92|  int i;
  954|     92|  switch (flag_mode) {
  955|      0|    case FLAG_LONG:
  ------------------
  |  Branch (955:5): [True: 0, False: 92]
  ------------------
  956|      0|      if (f.size() >= 2)
  ------------------
  |  Branch (956:11): [True: 0, False: 0]
  ------------------
  957|      0|        s = ((unsigned short)((unsigned char)f[0]) << 8) | ((unsigned short)((unsigned char)f[1]));
  958|      0|      break;
  959|      0|    case FLAG_NUM:
  ------------------
  |  Branch (959:5): [True: 0, False: 92]
  ------------------
  960|      0|      i = atoi(f.c_str());
  961|      0|      if (i > std::numeric_limits<unsigned short>::max() || i < 0) {
  ------------------
  |  Branch (961:11): [True: 0, False: 0]
  |  Branch (961:61): [True: 0, False: 0]
  ------------------
  962|      0|        HUNSPELL_WARNING(stderr, "error: flag id %d is out of range\n", i);
  963|      0|        i = 0;
  964|      0|      }
  965|      0|      s = (unsigned short)i;
  966|      0|      break;
  967|      0|    case FLAG_UNI: {
  ------------------
  |  Branch (967:5): [True: 0, False: 92]
  ------------------
  968|      0|      std::vector<w_char> w;
  969|      0|      u8_u16(w, f);
  970|      0|      if (!w.empty())
  ------------------
  |  Branch (970:11): [True: 0, False: 0]
  ------------------
  971|      0|        s = (unsigned short)w[0];
  972|      0|      break;
  973|      0|    }
  974|     92|    default:
  ------------------
  |  Branch (974:5): [True: 92, False: 0]
  ------------------
  975|     92|      if (!f.empty())
  ------------------
  |  Branch (975:11): [True: 92, False: 0]
  ------------------
  976|     92|        s = (unsigned char)f[0];
  977|     92|  }
  978|     92|  if (s == 0)
  ------------------
  |  Branch (978:7): [True: 0, False: 92]
  ------------------
  979|      0|    HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
  980|     92|  return s;
  981|     92|}
_ZN7HashMgr11load_configEPKcS1_:
 1017|     38|int HashMgr::load_config(const char* affpath, const char* key) {
 1018|     38|  int firstline = 1;
 1019|       |
 1020|       |  // open the affix file
 1021|     38|  FileMgr* afflst = new FileMgr(affpath, key);
 1022|       |
 1023|       |  // read in each line ignoring any that do not
 1024|       |  // start with a known line type indicator
 1025|       |
 1026|     38|  std::string line;
 1027|    922|  while (afflst->getline(line)) {
  ------------------
  |  Branch (1027:10): [True: 886, False: 36]
  ------------------
 1028|    886|    mychomp(line);
 1029|       |
 1030|       |    /* remove byte order mark */
 1031|    886|    if (firstline) {
  ------------------
  |  Branch (1031:9): [True: 38, False: 848]
  ------------------
 1032|     38|      firstline = 0;
 1033|     38|      if (line.compare(0, 3, "\xEF\xBB\xBF", 3) == 0) {
  ------------------
  |  Branch (1033:11): [True: 0, False: 38]
  ------------------
 1034|      0|        line.erase(0, 3);
 1035|      0|      }
 1036|     38|    }
 1037|       |
 1038|       |    /* parse in the try string */
 1039|    886|    if ((line.compare(0, 4, "FLAG", 4) == 0) && line.size() > 4 && isspace((unsigned char)line[4])) {
  ------------------
  |  Branch (1039:9): [True: 0, False: 886]
  |  Branch (1039:49): [True: 0, False: 0]
  |  Branch (1039:68): [True: 0, False: 0]
  ------------------
 1040|      0|      if (flag_mode != FLAG_CHAR) {
  ------------------
  |  Branch (1040:11): [True: 0, False: 0]
  ------------------
 1041|      0|        HUNSPELL_WARNING(stderr,
 1042|      0|                         "error: line %d: multiple definitions of the FLAG "
 1043|      0|                         "affix file parameter\n",
 1044|      0|                         afflst->getlinenum());
 1045|      0|      }
 1046|      0|      if (line.find("long") != std::string::npos)
  ------------------
  |  Branch (1046:11): [True: 0, False: 0]
  ------------------
 1047|      0|        flag_mode = FLAG_LONG;
 1048|      0|      if (line.find("num") != std::string::npos)
  ------------------
  |  Branch (1048:11): [True: 0, False: 0]
  ------------------
 1049|      0|        flag_mode = FLAG_NUM;
 1050|      0|      if (line.find("UTF-8") != std::string::npos)
  ------------------
  |  Branch (1050:11): [True: 0, False: 0]
  ------------------
 1051|      0|        flag_mode = FLAG_UNI;
 1052|      0|      if (flag_mode == FLAG_CHAR) {
  ------------------
  |  Branch (1052:11): [True: 0, False: 0]
  ------------------
 1053|      0|        HUNSPELL_WARNING(
 1054|      0|            stderr,
 1055|      0|            "error: line %d: FLAG needs `num', `long' or `UTF-8' parameter\n",
 1056|      0|            afflst->getlinenum());
 1057|      0|      }
 1058|      0|    }
 1059|       |
 1060|    886|    if (line.compare(0, 13, "FORBIDDENWORD", 13) == 0) {
  ------------------
  |  Branch (1060:9): [True: 2, False: 884]
  ------------------
 1061|      2|      std::string st;
 1062|      2|      if (!parse_string(line, st, afflst->getlinenum())) {
  ------------------
  |  Branch (1062:11): [True: 0, False: 2]
  ------------------
 1063|      0|        delete afflst;
 1064|      0|        return 1;
 1065|      0|      }
 1066|      2|      forbiddenword = decode_flag(st);
 1067|      2|    }
 1068|       |
 1069|    886|    if (line.compare(0, 3, "SET", 3) == 0) {
  ------------------
  |  Branch (1069:9): [True: 18, False: 868]
  ------------------
 1070|     18|      if (!parse_string(line, enc, afflst->getlinenum())) {
  ------------------
  |  Branch (1070:11): [True: 0, False: 18]
  ------------------
 1071|      0|        delete afflst;
 1072|      0|        return 1;
 1073|      0|      }
 1074|     18|      if (enc == "UTF-8") {
  ------------------
  |  Branch (1074:11): [True: 18, False: 0]
  ------------------
 1075|     18|        utf8 = 1;
 1076|     18|      } else
 1077|      0|        csconv = get_current_cs(enc);
 1078|     18|    }
 1079|       |
 1080|    886|    if (line.compare(0, 4, "LANG", 4) == 0) {
  ------------------
  |  Branch (1080:9): [True: 2, False: 884]
  ------------------
 1081|      2|      if (!parse_string(line, lang, afflst->getlinenum())) {
  ------------------
  |  Branch (1081:11): [True: 0, False: 2]
  ------------------
 1082|      0|        delete afflst;
 1083|      0|        return 1;
 1084|      0|      }
 1085|      2|      langnum = get_lang_num(lang);
 1086|      2|    }
 1087|       |
 1088|       |    /* parse in the ignored characters (for example, Arabic optional diacritics
 1089|       |     * characters */
 1090|    886|    if (line.compare(0, 6, "IGNORE", 6) == 0) {
  ------------------
  |  Branch (1090:9): [True: 4, False: 882]
  ------------------
 1091|      4|      if (!parse_array(line, ignorechars, ignorechars_utf16,
  ------------------
  |  Branch (1091:11): [True: 0, False: 4]
  ------------------
 1092|      4|                       utf8, afflst->getlinenum())) {
 1093|      0|        delete afflst;
 1094|      0|        return 1;
 1095|      0|      }
 1096|      4|    }
 1097|       |
 1098|    886|    if ((line.compare(0, 2, "AF", 2) == 0) && line.size() > 2 && isspace((unsigned char)line[2])) {
  ------------------
  |  Branch (1098:9): [True: 2, False: 884]
  |  Branch (1098:47): [True: 2, False: 0]
  |  Branch (1098:66): [True: 2, False: 0]
  ------------------
 1099|      2|      if (!parse_aliasf(line, afflst)) {
  ------------------
  |  Branch (1099:11): [True: 0, False: 2]
  ------------------
 1100|      0|        delete afflst;
 1101|      0|        return 1;
 1102|      0|      }
 1103|      2|    }
 1104|       |
 1105|    886|    if ((line.compare(0, 2, "AM", 2) == 0) && line.size() > 2 && isspace((unsigned char)line[2])) {
  ------------------
  |  Branch (1105:9): [True: 0, False: 886]
  |  Branch (1105:47): [True: 0, False: 0]
  |  Branch (1105:66): [True: 0, False: 0]
  ------------------
 1106|      0|      if (!parse_aliasm(line, afflst)) {
  ------------------
  |  Branch (1106:11): [True: 0, False: 0]
  ------------------
 1107|      0|        delete afflst;
 1108|      0|        return 1;
 1109|      0|      }
 1110|      0|    }
 1111|       |
 1112|    886|    if (line.compare(0, 15, "COMPLEXPREFIXES", 15) == 0)
  ------------------
  |  Branch (1112:9): [True: 2, False: 884]
  ------------------
 1113|      2|      complexprefixes = 1;
 1114|       |
 1115|       |    /* parse in the typical fault correcting table */
 1116|    886|    if (line.compare(0, 3, "REP", 3) == 0) {
  ------------------
  |  Branch (1116:9): [True: 6, False: 880]
  ------------------
 1117|      6|      if (!parse_reptable(line, afflst)) {
  ------------------
  |  Branch (1117:11): [True: 0, False: 6]
  ------------------
 1118|      0|        delete afflst;
 1119|      0|        return 1;
 1120|      0|      }
 1121|      6|    }
 1122|       |
 1123|       |    // don't check the full affix file, yet
 1124|    886|    if (((line.compare(0, 3, "SFX", 3) == 0) ||
  ------------------
  |  Branch (1124:10): [True: 42, False: 844]
  ------------------
 1125|    844|         (line.compare(0, 3, "PFX", 3) == 0)) &&
  ------------------
  |  Branch (1125:10): [True: 24, False: 820]
  ------------------
 1126|     66|            line.size() > 3 && isspace((unsigned char)line[3]) &&
  ------------------
  |  Branch (1126:13): [True: 66, False: 0]
  |  Branch (1126:32): [True: 66, False: 0]
  ------------------
 1127|     66|            !reptable.empty()) // (REP table is in the end of Afrikaans aff file)
  ------------------
  |  Branch (1127:13): [True: 2, False: 64]
  ------------------
 1128|      2|      break;
 1129|    886|  }
 1130|       |
 1131|     38|  delete afflst;
 1132|     38|  return 0;
 1133|     38|}
_ZN7HashMgr12parse_aliasfERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEP7FileMgr:
 1136|      2|bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) {
 1137|      2|  if (!aliasf.empty()) {
  ------------------
  |  Branch (1137:7): [True: 0, False: 2]
  ------------------
 1138|      0|    HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
 1139|      0|                     af->getlinenum());
 1140|      0|    return false;
 1141|      0|  }
 1142|      2|  int i = 0, np = 0, numaliasf = 0;
 1143|      2|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 1144|      6|  while (start_piece != line.end()) {
  ------------------
  |  Branch (1144:10): [True: 4, False: 2]
  ------------------
 1145|      4|    switch (i) {
 1146|      2|      case 0: {
  ------------------
  |  Branch (1146:7): [True: 2, False: 2]
  ------------------
 1147|      2|        np++;
 1148|      2|        break;
 1149|      0|      }
 1150|      2|      case 1: {
  ------------------
  |  Branch (1150:7): [True: 2, False: 2]
  ------------------
 1151|      2|        numaliasf = atoi(std::string(start_piece, iter).c_str());
 1152|      2|        if (numaliasf < 1) {
  ------------------
  |  Branch (1152:13): [True: 0, False: 2]
  ------------------
 1153|      0|          aliasf.clear();
 1154|      0|          aliasflen.clear();
 1155|      0|          HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
 1156|      0|                           af->getlinenum());
 1157|      0|          return false;
 1158|      0|        }
 1159|      2|        aliasf.reserve(std::min(numaliasf, 16384));
 1160|      2|        aliasflen.reserve(std::min(numaliasf, 16384));
 1161|      2|        np++;
 1162|      2|        break;
 1163|      2|      }
 1164|      0|      default:
  ------------------
  |  Branch (1164:7): [True: 0, False: 4]
  ------------------
 1165|      0|        break;
 1166|      4|    }
 1167|      4|    ++i;
 1168|      4|    start_piece = mystrsep(line, iter);
 1169|      4|  }
 1170|      2|  if (np != 2) {
  ------------------
  |  Branch (1170:7): [True: 0, False: 2]
  ------------------
 1171|      0|    aliasf.clear();
 1172|      0|    aliasflen.clear();
 1173|      0|    HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
 1174|      0|                     af->getlinenum());
 1175|      0|    return false;
 1176|      0|  }
 1177|       |
 1178|       |  /* now parse the numaliasf lines to read in the remainder of the table */
 1179|      6|  for (int j = 0; j < numaliasf; ++j) {
  ------------------
  |  Branch (1179:19): [True: 4, False: 2]
  ------------------
 1180|      4|    std::string nl;
 1181|      4|    unsigned short* alias = nullptr;
 1182|      4|    size_t aliaslen = 0;
 1183|      4|    i = 0;
 1184|      4|    if (af->getline(nl)) {
  ------------------
  |  Branch (1184:9): [True: 4, False: 0]
  ------------------
 1185|      4|      mychomp(nl);
 1186|      4|      iter = nl.begin();
 1187|      4|      start_piece = mystrsep(nl, iter);
 1188|      4|      bool errored = false;
 1189|     12|      while (!errored && start_piece != nl.end()) {
  ------------------
  |  Branch (1189:14): [True: 12, False: 0]
  |  Branch (1189:14): [True: 8, False: 4]
  |  Branch (1189:26): [True: 8, False: 4]
  ------------------
 1190|      8|        switch (i) {
 1191|      4|          case 0: {
  ------------------
  |  Branch (1191:11): [True: 4, False: 4]
  ------------------
 1192|      4|            if (nl.compare(start_piece - nl.begin(), 2, "AF", 2) != 0) {
  ------------------
  |  Branch (1192:17): [True: 0, False: 4]
  ------------------
 1193|      0|              errored = true;
 1194|      0|              break;
 1195|      0|            }
 1196|      4|            break;
 1197|      4|          }
 1198|      4|          case 1: {
  ------------------
  |  Branch (1198:11): [True: 4, False: 4]
  ------------------
 1199|      4|            std::string piece(start_piece, iter);
 1200|      4|            aliaslen = decode_flags(&alias, piece, af, /* arena = */ true);
 1201|      4|            std::sort(alias, alias + aliaslen);
 1202|      4|            break;
 1203|      4|          }
 1204|      0|          default:
  ------------------
  |  Branch (1204:11): [True: 0, False: 8]
  ------------------
 1205|      0|            break;
 1206|      8|        }
 1207|      8|        ++i;
 1208|      8|        start_piece = mystrsep(nl, iter);
 1209|      8|      }
 1210|      4|    }
 1211|      4|    if (!alias) {
  ------------------
  |  Branch (1211:9): [True: 0, False: 4]
  ------------------
 1212|      0|      for (int k = 0; k < j; ++k) {
  ------------------
  |  Branch (1212:23): [True: 0, False: 0]
  ------------------
 1213|      0|        arena_free(aliasf[k]);
 1214|      0|      }
 1215|      0|      aliasf.clear();
 1216|      0|      aliasflen.clear();
 1217|      0|      HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 1218|      0|                       af->getlinenum());
 1219|      0|      return false;
 1220|      0|    }
 1221|       |
 1222|      4|    aliasf.push_back(alias);
 1223|      4|    aliasflen.push_back(aliaslen);
 1224|      4|  }
 1225|      2|  return true;
 1226|      2|}
_ZNK7HashMgr9is_aliasfEv:
 1228|     44|int HashMgr::is_aliasf() const {
 1229|     44|  return !aliasf.empty();
 1230|     44|}
_ZNK7HashMgr10get_aliasfEiPPtP7FileMgr:
 1232|      4|size_t HashMgr::get_aliasf(int index, unsigned short** fvec, FileMgr* af) const {
 1233|      4|  if (index > 0 && static_cast<size_t>(index) <= aliasflen.size()) {
  ------------------
  |  Branch (1233:7): [True: 4, False: 0]
  |  Branch (1233:20): [True: 4, False: 0]
  ------------------
 1234|      4|    *fvec = aliasf[index - 1];
 1235|      4|    return aliasflen[index - 1];
 1236|      4|  }
 1237|      0|  HUNSPELL_WARNING(stderr, "error: line %d: bad flag alias index: %d\n",
 1238|      0|                   af->getlinenum(), index);
 1239|      0|  *fvec = nullptr;
 1240|      0|  return 0;
 1241|      4|}
_ZNK7HashMgr9is_aliasmEv:
 1339|     32|int HashMgr::is_aliasm() const {
 1340|     32|  return !aliasm.empty();
 1341|     32|}
_ZN7HashMgr14parse_reptableERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEP7FileMgr:
 1351|      6|bool HashMgr::parse_reptable(const std::string& line, FileMgr* af) {
 1352|      6|  if (!reptable.empty()) {
  ------------------
  |  Branch (1352:7): [True: 0, False: 6]
  ------------------
 1353|      0|    HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
 1354|      0|                     af->getlinenum());
 1355|      0|    return false;
 1356|      0|  }
 1357|      6|  int numrep = -1, i = 0, np = 0;
 1358|      6|  auto iter = line.begin(), start_piece = mystrsep(line, iter);
 1359|     18|  while (start_piece != line.end()) {
  ------------------
  |  Branch (1359:10): [True: 12, False: 6]
  ------------------
 1360|     12|    switch (i) {
 1361|      6|      case 0: {
  ------------------
  |  Branch (1361:7): [True: 6, False: 6]
  ------------------
 1362|      6|        np++;
 1363|      6|        break;
 1364|      0|      }
 1365|      6|      case 1: {
  ------------------
  |  Branch (1365:7): [True: 6, False: 6]
  ------------------
 1366|      6|        numrep = atoi(std::string(start_piece, iter).c_str());
 1367|      6|        if (numrep < 1) {
  ------------------
  |  Branch (1367:13): [True: 0, False: 6]
  ------------------
 1368|      0|          HUNSPELL_WARNING(stderr, "error: line %d: incorrect entry number\n",
 1369|      0|                           af->getlinenum());
 1370|      0|          return false;
 1371|      0|        }
 1372|      6|        reptable.reserve(std::min(numrep, 16384));
 1373|      6|        np++;
 1374|      6|        break;
 1375|      6|      }
 1376|      0|      default:
  ------------------
  |  Branch (1376:7): [True: 0, False: 12]
  ------------------
 1377|      0|        break;
 1378|     12|    }
 1379|     12|    ++i;
 1380|     12|    start_piece = mystrsep(line, iter);
 1381|     12|  }
 1382|      6|  if (np != 2) {
  ------------------
  |  Branch (1382:7): [True: 0, False: 6]
  ------------------
 1383|      0|    HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
 1384|      0|                     af->getlinenum());
 1385|      0|    return false;
 1386|      0|  }
 1387|       |
 1388|       |  /* now parse the numrep lines to read in the remainder of the table */
 1389|     12|  for (int j = 0; j < numrep; ++j) {
  ------------------
  |  Branch (1389:19): [True: 6, False: 6]
  ------------------
 1390|      6|    std::string nl;
 1391|      6|    reptable.emplace_back();
 1392|      6|    int type = 0;
 1393|      6|    if (af->getline(nl)) {
  ------------------
  |  Branch (1393:9): [True: 6, False: 0]
  ------------------
 1394|      6|      mychomp(nl);
 1395|      6|      iter = nl.begin();
 1396|      6|      i = 0;
 1397|      6|      start_piece = mystrsep(nl, iter);
 1398|      6|      bool errored = false;
 1399|     24|      while (!errored && start_piece != nl.end()) {
  ------------------
  |  Branch (1399:14): [True: 24, False: 0]
  |  Branch (1399:14): [True: 18, False: 6]
  |  Branch (1399:26): [True: 18, False: 6]
  ------------------
 1400|     18|        switch (i) {
 1401|      6|          case 0: {
  ------------------
  |  Branch (1401:11): [True: 6, False: 12]
  ------------------
 1402|      6|            if (nl.compare(start_piece - nl.begin(), 3, "REP", 3) != 0) {
  ------------------
  |  Branch (1402:17): [True: 0, False: 6]
  ------------------
 1403|      0|              errored = true;
 1404|      0|              break;
 1405|      0|            }
 1406|      6|            break;
 1407|      6|          }
 1408|      6|          case 1: {
  ------------------
  |  Branch (1408:11): [True: 6, False: 12]
  ------------------
 1409|      6|            if (*start_piece == '^')
  ------------------
  |  Branch (1409:17): [True: 0, False: 6]
  ------------------
 1410|      0|              type = 1;
 1411|      6|            reptable.back().pattern.assign(start_piece + type, iter);
 1412|      6|            mystrrep(reptable.back().pattern, "_", " ");
 1413|      6|            if (!reptable.back().pattern.empty() && reptable.back().pattern[reptable.back().pattern.size() - 1] == '$') {
  ------------------
  |  Branch (1413:17): [True: 6, False: 0]
  |  Branch (1413:53): [True: 0, False: 6]
  ------------------
 1414|      0|              type += 2;
 1415|      0|              reptable.back().pattern.resize(reptable.back().pattern.size() - 1);
 1416|      0|            }
 1417|      6|            break;
 1418|      6|          }
 1419|      6|          case 2: {
  ------------------
  |  Branch (1419:11): [True: 6, False: 12]
  ------------------
 1420|      6|            reptable.back().outstrings[type].assign(start_piece, iter);
 1421|      6|            mystrrep(reptable.back().outstrings[type], "_", " ");
 1422|      6|            break;
 1423|      6|          }
 1424|      0|          default:
  ------------------
  |  Branch (1424:11): [True: 0, False: 18]
  ------------------
 1425|      0|            break;
 1426|     18|        }
 1427|     18|        ++i;
 1428|     18|        start_piece = mystrsep(nl, iter);
 1429|     18|      }
 1430|      6|    }
 1431|      6|    if (reptable.back().pattern.empty() || reptable.back().outstrings[type].empty()) {
  ------------------
  |  Branch (1431:9): [True: 0, False: 6]
  |  Branch (1431:44): [True: 0, False: 6]
  ------------------
 1432|      0|      HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
 1433|      0|                       af->getlinenum());
 1434|      0|      reptable.clear();
 1435|      0|      return false;
 1436|      0|    }
 1437|      6|  }
 1438|      6|  return true;
 1439|      6|}
_ZNK7HashMgr12get_reptableEv:
 1442|   394k|const std::vector<replentry>& HashMgr::get_reptable() const {
 1443|   394k|  return reptable;
 1444|   394k|}
_ZNK7HashMgr11arena_allocEmm:
 1446|  10.3k|void* HashMgr::arena_alloc(size_t num_bytes, size_t alignment) const {
 1447|       |  // Fixed-size 64KB chunks: small enough to avoid significant waste on small
 1448|       |  // dictionaries, large enough to amortize per-chunk malloc overhead on large
 1449|       |  // ones. make_unique throws std::bad_alloc on OOM.
 1450|  10.3k|  static const size_t MIN_CHUNK_SIZE = 65536;
 1451|  10.3k|  static const size_t MAX_ALIGNMENT = alignof(max_align_t);
 1452|       |  // Chunk sizes are rounded up to MAX_ALIGNMENT below; with this invariant,
 1453|       |  // any alignment that divides MAX_ALIGNMENT keeps aligned_offset within bounds.
 1454|  10.3k|  assert(alignment > 0 && alignment <= MAX_ALIGNMENT);
  ------------------
  |  Branch (1454:3): [True: 10.3k, False: 0]
  |  Branch (1454:3): [True: 10.3k, False: 0]
  |  Branch (1454:3): [True: 10.3k, False: 0]
  ------------------
 1455|       |  // Pad the offset up to the requested alignment before placing this allocation.
 1456|       |  // make_unique returns memory aligned for any scalar, so chunk-start is fine.
 1457|  10.3k|  size_t aligned_offset = (current_chunk_offset + alignment - 1) & ~(alignment - 1);
 1458|  10.3k|  if (arena.empty() || current_chunk_size - aligned_offset < num_bytes) {
  ------------------
  |  Branch (1458:7): [True: 38, False: 10.2k]
  |  Branch (1458:24): [True: 66, False: 10.2k]
  ------------------
 1459|       |    // Round the new chunk's size up to a multiple of MAX_ALIGNMENT so that an
 1460|       |    // oversized num_bytes (>= MIN_CHUNK_SIZE) cannot leave a non-aligned
 1461|       |    // current_chunk_size that would later cause aligned_offset to overshoot.
 1462|       |    // Allocate before mutating current_chunk_size so a throwing make_unique
 1463|       |    // leaves the HashMgr in a consistent state.
 1464|    104|    size_t new_size = std::max(MIN_CHUNK_SIZE, num_bytes);
 1465|    104|    new_size = (new_size + MAX_ALIGNMENT - 1) & ~(MAX_ALIGNMENT - 1);
 1466|    104|    arena.push_back(std::make_unique<uint8_t[]>(new_size));
 1467|    104|    current_chunk_size = new_size;
 1468|    104|    aligned_offset = 0;
 1469|    104|  }
 1470|       |
 1471|  10.3k|  uint8_t* ptr = &arena.back()[aligned_offset];
 1472|  10.3k|  current_chunk_offset = aligned_offset + num_bytes;
 1473|  10.3k|  ++outstanding_arena_allocations;
 1474|  10.3k|  return ptr;
 1475|  10.3k|}
_ZNK7HashMgr10arena_freeEPv:
 1477|    323|void HashMgr::arena_free(void*) const {
 1478|       |  // The arena vector owns all allocations and frees them in bulk at HashMgr
 1479|       |  // destruction, so this is a no-op for the memory itself. The counter is a
 1480|       |  // memory-safety check: more arena_free calls than arena_alloc calls would
 1481|       |  // indicate a double-free or use-after-free in Hunspell. Abort hard rather
 1482|       |  // than silently desynchronize tracking, even in release builds.
 1483|    323|  if (outstanding_arena_allocations == 0) {
  ------------------
  |  Branch (1483:7): [True: 0, False: 323]
  ------------------
 1484|      0|    std::abort();
 1485|      0|  }
 1486|    323|  --outstanding_arena_allocations;
 1487|    323|}
hashmgr.cxx:_ZZNK7HashMgr12decode_flagsEPPtRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEP7FileMgrbENK3$_0clEm:
  786|    100|  auto alloc = [&](size_t n) -> unsigned short* {
  787|    100|    return use_arena ? (unsigned short*)this->arena_alloc(n * sizeof(unsigned short),
  ------------------
  |  Branch (787:12): [True: 84, False: 16]
  ------------------
  788|     84|                                                          alignof(unsigned short))
  789|    100|                     : new unsigned short[n];
  790|    100|  };

_ZN12HunspellImplC2EPKcS1_S1_:
  198|     38|  : m_trace(std::make_unique<TraceCtx>(nullptr, nullptr))
  199|     38|  , affixpath(affpath)
  200|     38|  , affixkey(key ? key : "") {
  ------------------
  |  Branch (200:14): [True: 0, False: 38]
  ------------------
  201|     38|  csconv = nullptr;
  202|     38|  utf8 = 0;
  203|     38|  complexprefixes = 0;
  204|       |
  205|       |  /* first set up the hash manager */
  206|     38|  m_HMgrs.push_back(std::make_unique<HashMgr>(dpath, affpath, key));
  207|       |
  208|       |  /* next set up the affix manager */
  209|       |  /* it needs access to the hash manager lookup methods */
  210|     38|  pAMgr = std::make_unique<AffixMgr>(affpath, m_HMgrs, key);
  211|       |
  212|       |  /* get the preferred try string and the dictionary */
  213|       |  /* encoding from the Affix Manager for that dictionary */
  214|     38|  std::string try_string = pAMgr->get_try_string();
  215|     38|  encoding = pAMgr->get_encoding();
  216|     38|  langnum = pAMgr->get_langnum();
  217|     38|  utf8 = pAMgr->get_utf8();
  218|     38|  if (!utf8)
  ------------------
  |  Branch (218:7): [True: 20, False: 18]
  ------------------
  219|     20|    csconv = get_current_cs(encoding);
  220|     38|  complexprefixes = pAMgr->get_complexprefixes();
  221|     38|  wordbreak = pAMgr->get_breaktable();
  222|       |
  223|       |  /* and finally set up the suggestion manager */
  224|     38|  pSMgr = std::make_unique<SuggestMgr>(try_string, MAXSUGGESTION, pAMgr.get());
  ------------------
  |  |   83|     38|#define MAXSUGGESTION 15
  ------------------
  225|     38|}
_ZN12HunspellImpl12clean_ignoreERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERKS6_:
  247|  38.5M|                                const std::string& src) {
  248|  38.5M|  dest.clear();
  249|  38.5M|  dest.assign(src);
  250|  38.5M|  const char* ignoredchars = pAMgr ? pAMgr->get_ignore() : nullptr;
  ------------------
  |  Branch (250:30): [True: 38.5M, False: 0]
  ------------------
  251|  38.5M|  if (ignoredchars != nullptr) {
  ------------------
  |  Branch (251:7): [True: 3.72M, False: 34.8M]
  ------------------
  252|  3.72M|    if (utf8) {
  ------------------
  |  Branch (252:9): [True: 820k, False: 2.90M]
  ------------------
  253|   820k|      const std::vector<w_char>& ignoredchars_utf16 =
  254|   820k|          pAMgr->get_ignore_utf16();
  255|   820k|      remove_ignored_chars_utf(dest, ignoredchars_utf16);
  256|  2.90M|    } else {
  257|  2.90M|      remove_ignored_chars(dest, ignoredchars);
  258|  2.90M|    }
  259|  3.72M|  }
  260|  38.5M|}
_ZN12HunspellImpl10cleanword2ERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERNS0_6vectorI6w_charNS4_IS9_EEEERKS6_PiPm:
  274|  17.5M|                         size_t* pabbrev) {
  275|  17.5M|  dest.clear();
  276|  17.5M|  dest_utf.clear();
  277|       |
  278|       |  // remove IGNORE characters from the string
  279|  17.5M|  std::string w2;
  280|  17.5M|  clean_ignore(w2, src);
  281|       |
  282|  17.5M|  const char* q = w2.c_str();
  283|  17.5M|  size_t nl = w2.size();
  284|       |
  285|       |  // first skip over any leading blanks
  286|  17.7M|  while (*q == ' ') {
  ------------------
  |  Branch (286:10): [True: 147k, False: 17.5M]
  ------------------
  287|   147k|    ++q;
  288|   147k|    nl--;
  289|   147k|  }
  290|       |
  291|       |  // now strip off any trailing periods (recording their presence)
  292|  17.5M|  *pabbrev = 0;
  293|       |
  294|  19.7M|  while ((nl > 0) && (*(q + nl - 1) == '.')) {
  ------------------
  |  Branch (294:10): [True: 19.4M, False: 291k]
  |  Branch (294:22): [True: 2.18M, False: 17.2M]
  ------------------
  295|  2.18M|    nl--;
  296|  2.18M|    (*pabbrev)++;
  297|  2.18M|  }
  298|       |
  299|       |  // if no characters are left it can't be capitalized
  300|  17.5M|  if (nl == 0) {
  ------------------
  |  Branch (300:7): [True: 291k, False: 17.2M]
  ------------------
  301|   291k|    *pcaptype = NOCAP;
  ------------------
  |  |   88|   291k|#define NOCAP 0
  ------------------
  302|   291k|    return 0;
  303|   291k|  }
  304|       |
  305|  17.2M|  dest.append(q, nl);
  306|  17.2M|  nl = dest.size();
  307|  17.2M|  if (utf8) {
  ------------------
  |  Branch (307:7): [True: 3.28M, False: 13.9M]
  ------------------
  308|  3.28M|    u8_u16(dest_utf, dest);
  309|  3.28M|    *pcaptype = get_captype_utf8(dest_utf, langnum);
  310|  13.9M|  } else {
  311|  13.9M|    *pcaptype = get_captype(dest, csconv);
  312|  13.9M|  }
  313|  17.2M|  return nl;
  314|  17.5M|}
_ZN12HunspellImpl9cleanwordERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERKS6_PiSA_:
  319|  6.35k|                        int* pabbrev) {
  320|  6.35k|  dest.clear();
  321|  6.35k|  const unsigned char* q = (const unsigned char*)src.c_str();
  322|  6.35k|  int firstcap = 0, nl = (int)src.size();
  323|       |
  324|       |  // first skip over any leading blanks
  325|  12.1k|  while (*q == ' ') {
  ------------------
  |  Branch (325:10): [True: 5.79k, False: 6.35k]
  ------------------
  326|  5.79k|    ++q;
  327|  5.79k|    nl--;
  328|  5.79k|  }
  329|       |
  330|       |  // now strip off any trailing periods (recording their presence)
  331|  6.35k|  *pabbrev = 0;
  332|       |
  333|  20.7k|  while ((nl > 0) && (*(q + nl - 1) == '.')) {
  ------------------
  |  Branch (333:10): [True: 20.5k, False: 266]
  |  Branch (333:22): [True: 14.4k, False: 6.08k]
  ------------------
  334|  14.4k|    nl--;
  335|  14.4k|    (*pabbrev)++;
  336|  14.4k|  }
  337|       |
  338|       |  // if no characters are left it can't be capitalized
  339|  6.35k|  if (nl <= 0) {
  ------------------
  |  Branch (339:7): [True: 266, False: 6.08k]
  ------------------
  340|    266|    *pcaptype = NOCAP;
  ------------------
  |  |   88|    266|#define NOCAP 0
  ------------------
  341|    266|    return;
  342|    266|  }
  343|       |
  344|       |  // now determine the capitalization type of the first nl letters
  345|  6.08k|  int ncap = 0;
  346|  6.08k|  int nneutral = 0;
  347|  6.08k|  int nc = 0;
  348|       |
  349|  6.08k|  if (!utf8) {
  ------------------
  |  Branch (349:7): [True: 3.22k, False: 2.86k]
  ------------------
  350|   542k|    while (nl > 0) {
  ------------------
  |  Branch (350:12): [True: 539k, False: 3.22k]
  ------------------
  351|   539k|      nc++;
  352|   539k|      if (csconv[(*q)].ccase)
  ------------------
  |  Branch (352:11): [True: 449k, False: 89.3k]
  ------------------
  353|   449k|        ncap++;
  354|   539k|      if (csconv[(*q)].cupper == csconv[(*q)].clower)
  ------------------
  |  Branch (354:11): [True: 79.4k, False: 459k]
  ------------------
  355|  79.4k|        nneutral++;
  356|   539k|      dest.push_back(*q++);
  357|   539k|      nl--;
  358|   539k|    }
  359|       |    // remember to terminate the destination string
  360|  3.22k|    firstcap = csconv[static_cast<unsigned char>(dest[0])].ccase;
  361|  3.22k|  } else {
  362|  2.86k|    std::vector<w_char> t;
  363|  2.86k|    u8_u16(t, src);
  364|   169k|    for (auto& wc : t) {
  ------------------
  |  Branch (364:19): [True: 169k, False: 2.86k]
  ------------------
  365|   169k|      const auto idx = (unsigned short)wc;
  366|   169k|      const auto low = unicodetolower(idx, langnum);
  367|   169k|      if (idx != low)
  ------------------
  |  Branch (367:11): [True: 113k, False: 55.2k]
  ------------------
  368|   113k|        ncap++;
  369|   169k|      if (unicodetoupper(idx, langnum) == low)
  ------------------
  |  Branch (369:11): [True: 52.6k, False: 116k]
  ------------------
  370|  52.6k|        nneutral++;
  371|   169k|    }
  372|  2.86k|    u16_u8(dest, t);
  373|  2.86k|    if (ncap) {
  ------------------
  |  Branch (373:9): [True: 1.48k, False: 1.37k]
  ------------------
  374|  1.48k|      const auto idx = (unsigned short)t[0];
  375|  1.48k|      firstcap = (idx != unicodetolower(idx, langnum));
  376|  1.48k|    }
  377|  2.86k|  }
  378|       |
  379|       |  // now finally set the captype
  380|  6.08k|  if (ncap == 0) {
  ------------------
  |  Branch (380:7): [True: 2.51k, False: 3.56k]
  ------------------
  381|  2.51k|    *pcaptype = NOCAP;
  ------------------
  |  |   88|  2.51k|#define NOCAP 0
  ------------------
  382|  3.56k|  } else if ((ncap == 1) && firstcap) {
  ------------------
  |  Branch (382:14): [True: 1.81k, False: 1.75k]
  |  Branch (382:29): [True: 1.52k, False: 292]
  ------------------
  383|  1.52k|    *pcaptype = INITCAP;
  ------------------
  |  |   89|  1.52k|#define INITCAP 1
  ------------------
  384|  2.04k|  } else if ((ncap == nc) || ((ncap + nneutral) == nc)) {
  ------------------
  |  Branch (384:14): [True: 100, False: 1.94k]
  |  Branch (384:30): [True: 260, False: 1.68k]
  ------------------
  385|    360|    *pcaptype = ALLCAP;
  ------------------
  |  |   90|    360|#define ALLCAP 2
  ------------------
  386|  1.68k|  } else if ((ncap > 1) && firstcap) {
  ------------------
  |  Branch (386:14): [True: 1.44k, False: 242]
  |  Branch (386:28): [True: 1.22k, False: 221]
  ------------------
  387|  1.22k|    *pcaptype = HUHINITCAP;
  ------------------
  |  |   92|  1.22k|#define HUHINITCAP 4
  ------------------
  388|  1.22k|  } else {
  389|    463|    *pcaptype = HUHCAP;
  ------------------
  |  |   91|    463|#define HUHCAP 3
  ------------------
  390|    463|  }
  391|  6.08k|}
_ZN12HunspellImpl8mkallcapERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  393|  3.10k|void HunspellImpl::mkallcap(std::string& u8) {
  394|  3.10k|  if (utf8) {
  ------------------
  |  Branch (394:7): [True: 2.06k, False: 1.03k]
  ------------------
  395|  2.06k|    std::vector<w_char> u16;
  396|  2.06k|    u8_u16(u16, u8);
  397|  2.06k|    ::mkallcap_utf(u16, langnum);
  398|  2.06k|    u16_u8(u8, u16);
  399|  2.06k|  } else {
  400|  1.03k|    ::mkallcap(u8, csconv);
  401|  1.03k|  }
  402|  3.10k|}
_ZN12HunspellImpl11mkallsmall2ERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERNS0_6vectorI6w_charNS4_IS9_EEEE:
  404|  2.08M|size_t HunspellImpl::mkallsmall2(std::string& u8, std::vector<w_char>& u16) {
  405|  2.08M|  if (utf8) {
  ------------------
  |  Branch (405:7): [True: 446k, False: 1.63M]
  ------------------
  406|   446k|    ::mkallsmall_utf(u16, langnum);
  407|   446k|    u16_u8(u8, u16);
  408|  1.63M|  } else {
  409|  1.63M|    ::mkallsmall(u8, csconv);
  410|  1.63M|  }
  411|  2.08M|  return u8.size();
  412|  2.08M|}
_ZN12HunspellImpl11is_keepcaseEPK6hentry:
  450|  44.1k|int HunspellImpl::is_keepcase(const hentry* rv) {
  451|  44.1k|  return pAMgr && rv->astr && pAMgr->get_keepcase() &&
  ------------------
  |  Branch (451:10): [True: 44.1k, False: 0]
  |  Branch (451:19): [True: 273, False: 43.8k]
  |  Branch (451:31): [True: 35, False: 238]
  ------------------
  452|     35|         TESTAFF(rv->astr, pAMgr->get_keepcase(), rv->alen);
  ------------------
  |  |  102|  44.1k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 27, False: 8]
  |  |  ------------------
  ------------------
  453|  44.1k|}
_ZN12HunspellImpl10insert_sugERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_:
  456|  18.4k|void HunspellImpl::insert_sug(std::vector<std::string>& slst, const std::string& word) {
  457|  18.4k|  slst.insert(slst.begin(), word);
  458|  18.4k|}
_ZN12HunspellImpl5spellERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERNS0_6vectorIS6_NS4_IS6_EEEEPiPS6_NS0_6chrono10time_pointINSF_12steady_clockENSF_8durationIxNS0_5ratioILl1ELl1000000000EEEEEEE:
  462|  18.2M|                         std::chrono::steady_clock::time_point suggest_start) {
  463|       |  // something very broken if spell ends up calling itself with the same word
  464|  18.2M|  if (std::find(candidate_stack.begin(), candidate_stack.end(), word) != candidate_stack.end())
  ------------------
  |  Branch (464:7): [True: 0, False: 18.2M]
  ------------------
  465|      0|    return false;
  466|       |
  467|  18.2M|  if (candidate_stack.size() >= MAXBREAKDEPTH)
  ------------------
  |  |   87|  18.2M|#define MAXBREAKDEPTH 10
  ------------------
  |  Branch (467:7): [True: 0, False: 18.2M]
  ------------------
  468|      0|    return false;
  469|       |
  470|  18.2M|  if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  18.2M|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (470:7): [True: 0, False: 18.2M]
  ------------------
  471|      0|    return false;
  472|       |
  473|  18.2M|  TraceCtx* t = active_trace();
  474|  18.2M|  if (t)
  ------------------
  |  Branch (474:7): [True: 0, False: 18.2M]
  ------------------
  475|      0|    trace(*t, "word \"%s\"", word.c_str());
  476|       |  // A word split on a BREAK pattern nests its parts a further level in.
  477|  18.2M|  TraceScope trace_depth(t);
  478|       |
  479|  18.2M|  candidate_stack.push_back(word);
  480|  18.2M|  bool r = spell_internal(word, candidate_stack, info, root, suggest_start);
  481|  18.2M|  candidate_stack.pop_back();
  482|       |
  483|  18.2M|  if (t)
  ------------------
  |  Branch (483:7): [True: 0, False: 18.2M]
  ------------------
  484|      0|    trace(*t, "result %s", r ? "correct" : "incorrect");
  ------------------
  |  Branch (484:28): [True: 0, False: 0]
  ------------------
  485|       |
  486|  18.2M|  if (r && root) {
  ------------------
  |  Branch (486:7): [True: 2.91M, False: 15.3M]
  |  Branch (486:12): [True: 0, False: 2.91M]
  ------------------
  487|       |    // output conversion
  488|      0|    RepList* rl = (pAMgr) ? pAMgr->get_oconvtable() : nullptr;
  ------------------
  |  Branch (488:19): [True: 0, False: 0]
  ------------------
  489|      0|    if (rl) {
  ------------------
  |  Branch (489:9): [True: 0, False: 0]
  ------------------
  490|      0|      std::string wspace;
  491|      0|      if (rl->conv(*root, wspace)) {
  ------------------
  |  Branch (491:11): [True: 0, False: 0]
  ------------------
  492|      0|        *root = std::move(wspace);
  493|      0|      }
  494|      0|    }
  495|      0|  }
  496|  18.2M|  return r;
  497|  18.2M|}
_ZN12HunspellImpl14spell_internalERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERNS0_6vectorIS6_NS4_IS6_EEEEPiPS6_NS0_6chrono10time_pointINSF_12steady_clockENSF_8durationIxNS0_5ratioILl1ELl1000000000EEEEEEE:
  501|  18.2M|                                  std::chrono::steady_clock::time_point suggest_start) {
  502|  18.2M|  struct hentry* rv = nullptr;
  503|       |
  504|  18.2M|  int info2 = 0;
  505|  18.2M|  if (!info)
  ------------------
  |  Branch (505:7): [True: 18.2M, False: 165]
  ------------------
  506|  18.2M|    info = &info2;
  507|    165|  else
  508|    165|    *info = 0;
  509|       |
  510|       |  // Hunspell supports XML input of the simplified API (see manual)
  511|  18.2M|  if (word == SPELL_XML)
  ------------------
  |  |   80|  18.2M|#define SPELL_XML "<?xml?>"
  ------------------
  |  Branch (511:7): [True: 772k, False: 17.4M]
  ------------------
  512|   772k|    return true;
  513|  17.4M|  if (utf8) {
  ------------------
  |  Branch (513:7): [True: 3.31M, False: 14.1M]
  ------------------
  514|  3.31M|    if (word.size() >= MAXWORDUTF8LEN)
  ------------------
  |  |   87|  3.31M|#define MAXWORDUTF8LEN (MAXWORDLEN * 3)
  |  |  ------------------
  |  |  |  |   90|  3.31M|#define MAXWORDLEN 100
  |  |  ------------------
  ------------------
  |  Branch (514:9): [True: 3.82k, False: 3.31M]
  ------------------
  515|  3.82k|      return false;
  516|  14.1M|  } else {
  517|  14.1M|    if (word.size() >= MAXWORDLEN)
  ------------------
  |  |   90|  14.1M|#define MAXWORDLEN 100
  ------------------
  |  Branch (517:9): [True: 6.88k, False: 14.1M]
  ------------------
  518|  6.88k|      return false;
  519|  14.1M|  }
  520|  17.4M|  int captype = NOCAP;
  ------------------
  |  |   88|  17.4M|#define NOCAP 0
  ------------------
  521|  17.4M|  size_t abbv = 0;
  522|  17.4M|  size_t wl = 0;
  523|       |
  524|  17.4M|  std::string scw;
  525|  17.4M|  std::vector<w_char> sunicw;
  526|       |
  527|       |  // input conversion
  528|  17.4M|  RepList* rl = pAMgr ? pAMgr->get_iconvtable() : nullptr;
  ------------------
  |  Branch (528:17): [True: 17.4M, False: 0]
  ------------------
  529|  17.4M|  {
  530|  17.4M|    std::string wspace;
  531|       |
  532|  17.4M|    bool convstatus = rl ? rl->conv(word, wspace) : false;
  ------------------
  |  Branch (532:23): [True: 485k, False: 17.0M]
  ------------------
  533|  17.4M|    if (convstatus) {
  ------------------
  |  Branch (533:9): [True: 0, False: 17.4M]
  ------------------
  534|       |      // the input conversion can grow the word without limit, so hold the
  535|       |      // converted word to the same maximum length as the raw word
  536|      0|      if (utf8 ? wspace.size() >= MAXWORDUTF8LEN : wspace.size() >= MAXWORDLEN)
  ------------------
  |  |   87|      0|#define MAXWORDUTF8LEN (MAXWORDLEN * 3)
  |  |  ------------------
  |  |  |  |   90|      0|#define MAXWORDLEN 100
  |  |  ------------------
  ------------------
                    if (utf8 ? wspace.size() >= MAXWORDUTF8LEN : wspace.size() >= MAXWORDLEN)
  ------------------
  |  |   90|      0|#define MAXWORDLEN 100
  ------------------
  |  Branch (536:11): [True: 0, False: 0]
  |  Branch (536:11): [True: 0, False: 0]
  ------------------
  537|      0|        return false;
  538|      0|      wl = cleanword2(scw, sunicw, wspace, &captype, &abbv);
  539|      0|    } else
  540|  17.4M|      wl = cleanword2(scw, sunicw, word, &captype, &abbv);
  541|  17.4M|  }
  542|       |
  543|  17.4M|#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
  544|  17.4M|    if (wl > 32768)
  ------------------
  |  Branch (544:9): [True: 0, False: 17.4M]
  ------------------
  545|      0|      return false;
  546|  17.4M|#endif
  547|       |
  548|       |#ifdef MOZILLA_CLIENT
  549|       |  // accept the abbreviated words without dots
  550|       |  // workaround for the incomplete tokenization of Mozilla
  551|       |  abbv = 1;
  552|       |#endif
  553|       |
  554|  17.4M|  if (wl == 0 || m_HMgrs.empty())
  ------------------
  |  Branch (554:7): [True: 290k, False: 17.1M]
  |  Branch (554:18): [True: 0, False: 17.1M]
  ------------------
  555|   290k|    return true;
  556|  17.1M|  if (root)
  ------------------
  |  Branch (556:7): [True: 0, False: 17.1M]
  ------------------
  557|      0|    root->clear();
  558|       |
  559|       |  // allow numbers with dots, dashes and commas (but forbid double separators:
  560|       |  // "..", "--" etc.). Besides the ASCII digits, accept the Arabic-Indic and
  561|       |  // Extended Arabic-Indic (Persian) digit ranges so those numbers are passed
  562|       |  // over the same way ASCII numbers are.
  563|  17.1M|  enum { NBEGIN, NNUM, NSEP };
  564|  17.1M|  int nstate = NBEGIN;
  565|  17.1M|  size_t i;
  566|  17.1M|  size_t n = utf8 ? sunicw.size() : wl;
  ------------------
  |  Branch (566:14): [True: 3.25M, False: 13.9M]
  ------------------
  567|       |
  568|  29.2M|  for (i = 0; (i < n); i++) {
  ------------------
  |  Branch (568:15): [True: 28.3M, False: 848k]
  ------------------
  569|  28.3M|    unsigned short c = utf8 ? static_cast<unsigned short>(sunicw[i]) : static_cast<unsigned char>(scw[i]);
  ------------------
  |  Branch (569:24): [True: 5.91M, False: 22.4M]
  ------------------
  570|  28.3M|    if ((c >= '0' && c <= '9') || (c >= 0x0660 && c <= 0x0669) ||  // Arabic-Indic digits
  ------------------
  |  Branch (570:10): [True: 19.3M, False: 9.09M]
  |  Branch (570:22): [True: 11.3M, False: 7.94M]
  |  Branch (570:36): [True: 449k, False: 16.5M]
  |  Branch (570:51): [True: 0, False: 449k]
  ------------------
  571|  17.0M|        (c >= 0x06F0 && c <= 0x06F9)) {                            // Extended Arabic-Indic (Persian) digits
  ------------------
  |  Branch (571:10): [True: 449k, False: 16.5M]
  |  Branch (571:25): [True: 0, False: 449k]
  ------------------
  572|  11.3M|      nstate = NNUM;
  573|  17.0M|    } else if ((c == ',') || (c == '.') || (c == '-')) {
  ------------------
  |  Branch (573:16): [True: 145k, False: 16.8M]
  |  Branch (573:30): [True: 1.57M, False: 15.3M]
  |  Branch (573:44): [True: 3.88M, False: 11.4M]
  ------------------
  574|  5.59M|      if ((nstate == NSEP) || (i == 0))
  ------------------
  |  Branch (574:11): [True: 115k, False: 5.48M]
  |  Branch (574:31): [True: 4.79M, False: 693k]
  ------------------
  575|  4.90M|        break;
  576|   693k|      nstate = NSEP;
  577|   693k|    } else
  578|  11.4M|      break;
  579|  28.3M|  }
  580|  17.1M|  if ((i == n) && (nstate == NNUM))
  ------------------
  |  Branch (580:7): [True: 848k, False: 16.3M]
  |  Branch (580:19): [True: 660k, False: 187k]
  ------------------
  581|   660k|    return true;
  582|       |
  583|  16.5M|  switch (captype) {
  ------------------
  |  Branch (583:11): [True: 16.5M, False: 0]
  ------------------
  584|  1.14M|    case HUHCAP:
  ------------------
  |  |   91|  1.14M|#define HUHCAP 3
  ------------------
  |  Branch (584:5): [True: 1.14M, False: 15.3M]
  ------------------
  585|       |    /* FALLTHROUGH */
  586|  1.49M|    case HUHINITCAP:
  ------------------
  |  |   92|  1.49M|#define HUHINITCAP 4
  ------------------
  |  Branch (586:5): [True: 345k, False: 16.1M]
  ------------------
  587|  1.49M|      *info |= SPELL_ORIGCAP;
  ------------------
  |  |   86|  1.49M|#define SPELL_ORIGCAP (1 << 5)
  ------------------
  588|       |    /* FALLTHROUGH */
  589|  15.3M|    case NOCAP:
  ------------------
  |  |   88|  15.3M|#define NOCAP 0
  ------------------
  |  Branch (589:5): [True: 13.8M, False: 2.67M]
  ------------------
  590|  15.3M|      rv = checkword(scw, info, root, suggest_start);
  591|  15.3M|      if ((abbv) && !(rv)) {
  ------------------
  |  Branch (591:11): [True: 1.57M, False: 13.7M]
  |  Branch (591:21): [True: 1.57M, False: 289]
  ------------------
  592|  1.57M|        std::string u8buffer(scw);
  593|  1.57M|        u8buffer.push_back('.');
  594|  1.57M|        rv = checkword(u8buffer, info, root, suggest_start);
  595|  1.57M|      }
  596|       |      // A stem with an inner capital, capitalised at the start of a sentence
  597|       |      // (uLinda written ULinda), is found by lowering only the first letter.
  598|  15.3M|      if (!rv && captype == HUHINITCAP) {
  ------------------
  |  |   92|  15.3M|#define HUHINITCAP 4
  ------------------
  |  Branch (598:11): [True: 15.3M, False: 15.8k]
  |  Branch (598:18): [True: 342k, False: 14.9M]
  ------------------
  599|   342k|        std::string u8buffer(scw);
  600|   342k|        std::vector<w_char> u16buffer(std::move(sunicw));
  601|   342k|        mkinitsmall2(u8buffer, u16buffer);
  602|   342k|        rv = checkword(u8buffer, info, root, suggest_start);
  603|   342k|        if (rv && is_keepcase(rv))
  ------------------
  |  Branch (603:13): [True: 4, False: 342k]
  |  Branch (603:19): [True: 0, False: 4]
  ------------------
  604|      0|          rv = nullptr;
  605|   342k|      }
  606|  15.3M|      break;
  607|   649k|    case ALLCAP: {
  ------------------
  |  |   90|   649k|#define ALLCAP 2
  ------------------
  |  Branch (607:5): [True: 649k, False: 15.8M]
  ------------------
  608|   649k|      *info |= SPELL_ORIGCAP;
  ------------------
  |  |   86|   649k|#define SPELL_ORIGCAP (1 << 5)
  ------------------
  609|   649k|      rv = checkword(scw, info, root, suggest_start);
  610|   649k|      if (rv)
  ------------------
  |  Branch (610:11): [True: 181, False: 649k]
  ------------------
  611|    181|        break;
  612|   649k|      if (abbv) {
  ------------------
  |  Branch (612:11): [True: 92.2k, False: 557k]
  ------------------
  613|  92.2k|        std::string u8buffer(scw);
  614|  92.2k|        u8buffer.push_back('.');
  615|  92.2k|        rv = checkword(u8buffer, info, root, suggest_start);
  616|  92.2k|        if (rv)
  ------------------
  |  Branch (616:13): [True: 0, False: 92.2k]
  ------------------
  617|      0|          break;
  618|  92.2k|      }
  619|       |      // Spec. prefix handling for Catalan, French, Italian:
  620|       |      // prefixes separated by apostrophe (SANT'ELIA -> Sant'+Elia).
  621|   649k|      size_t apos = pAMgr ? scw.find('\'') : std::string::npos;
  ------------------
  |  Branch (621:21): [True: 649k, False: 0]
  ------------------
  622|   649k|      if (apos != std::string::npos) {
  ------------------
  |  Branch (622:11): [True: 172k, False: 476k]
  ------------------
  623|   172k|        mkallsmall2(scw, sunicw);
  624|       |        //conversion may result in string with different len to pre-mkallsmall2
  625|       |        //so re-scan
  626|   172k|        if (apos != std::string::npos && apos < scw.size() - 1) {
  ------------------
  |  Branch (626:13): [True: 172k, False: 0]
  |  Branch (626:42): [True: 158k, False: 14.0k]
  ------------------
  627|   158k|          std::string part1 = scw.substr(0, apos + 1), part2 = scw.substr(apos + 1);
  628|   158k|          if (utf8) {
  ------------------
  |  Branch (628:15): [True: 49.6k, False: 109k]
  ------------------
  629|  49.6k|            std::vector<w_char> part1u, part2u;
  630|  49.6k|            u8_u16(part1u, part1);
  631|  49.6k|            u8_u16(part2u, part2);
  632|  49.6k|            mkinitcap2(part2, part2u);
  633|  49.6k|            scw = part1 + part2;
  634|  49.6k|            sunicw = std::move(part1u);
  635|  49.6k|            sunicw.insert(sunicw.end(), part2u.begin(), part2u.end());
  636|  49.6k|            rv = checkword(scw, info, root, suggest_start);
  637|  49.6k|            if (rv)
  ------------------
  |  Branch (637:17): [True: 0, False: 49.6k]
  ------------------
  638|      0|              break;
  639|   109k|          } else {
  640|   109k|            mkinitcap2(part2, sunicw);
  641|   109k|            scw = part1 + part2;
  642|   109k|            rv = checkword(scw, info, root, suggest_start);
  643|   109k|            if (rv)
  ------------------
  |  Branch (643:17): [True: 1, False: 109k]
  ------------------
  644|      1|              break;
  645|   109k|          }
  646|   158k|          mkinitcap2(scw, sunicw);
  647|   158k|          rv = checkword(scw, info, root, suggest_start);
  648|   158k|          if (rv)
  ------------------
  |  Branch (648:15): [True: 0, False: 158k]
  ------------------
  649|      0|            break;
  650|   158k|        }
  651|   172k|      }
  652|   649k|      if (pAMgr && pAMgr->get_checksharps() && scw.find("SS") != std::string::npos) {
  ------------------
  |  Branch (652:11): [True: 649k, False: 0]
  |  Branch (652:20): [True: 0, False: 649k]
  |  Branch (652:48): [True: 0, False: 0]
  ------------------
  653|       |
  654|      0|        mkallsmall2(scw, sunicw);
  655|      0|        std::string u8buffer(scw);
  656|      0|        rv = spellsharps(u8buffer, 0, 0, 0, info, root, suggest_start);
  657|      0|        if (!rv) {
  ------------------
  |  Branch (657:13): [True: 0, False: 0]
  ------------------
  658|      0|          mkinitcap2(scw, sunicw);
  659|      0|          rv = spellsharps(scw, 0, 0, 0, info, root, suggest_start);
  660|      0|        }
  661|      0|        if ((abbv) && !(rv)) {
  ------------------
  |  Branch (661:13): [True: 0, False: 0]
  |  Branch (661:23): [True: 0, False: 0]
  ------------------
  662|      0|          u8buffer.push_back('.');
  663|      0|          rv = spellsharps(u8buffer, 0, 0, 0, info, root, suggest_start);
  664|      0|          if (!rv) {
  ------------------
  |  Branch (664:15): [True: 0, False: 0]
  ------------------
  665|      0|            u8buffer = std::string(scw);
  666|      0|            u8buffer.push_back('.');
  667|      0|            rv = spellsharps(u8buffer, 0, 0, 0, info, root, suggest_start);
  668|      0|          }
  669|      0|        }
  670|      0|        if (rv)
  ------------------
  |  Branch (670:13): [True: 0, False: 0]
  ------------------
  671|      0|          break;
  672|      0|      }
  673|   649k|    }
  674|       |      /* FALLTHROUGH */
  675|  1.18M|    case INITCAP: {
  ------------------
  |  |   89|  1.18M|#define INITCAP 1
  ------------------
  |  Branch (675:5): [True: 536k, False: 16.0M]
  ------------------
  676|       |      // handle special capitalization of dotted I
  677|  1.18M|      bool Idot = (utf8 && (unsigned char) scw[0] == 0xc4 && (unsigned char) scw[1] == 0xb0);
  ------------------
  |  Branch (677:20): [True: 223k, False: 962k]
  |  Branch (677:28): [True: 8, False: 223k]
  |  Branch (677:62): [True: 0, False: 8]
  ------------------
  678|  1.18M|      *info |= SPELL_ORIGCAP;
  ------------------
  |  |   86|  1.18M|#define SPELL_ORIGCAP (1 << 5)
  ------------------
  679|  1.18M|      if (captype == ALLCAP) {
  ------------------
  |  |   90|  1.18M|#define ALLCAP 2
  ------------------
  |  Branch (679:11): [True: 649k, False: 536k]
  ------------------
  680|   649k|          mkallsmall2(scw, sunicw);
  681|   649k|          mkinitcap2(scw, sunicw);
  682|   649k|          if (Idot)
  ------------------
  |  Branch (682:15): [True: 0, False: 649k]
  ------------------
  683|      0|             scw.replace(0, 1, "\xc4\xb0");
  684|   649k|      }
  685|  1.18M|      if (captype == INITCAP)
  ------------------
  |  |   89|  1.18M|#define INITCAP 1
  ------------------
  |  Branch (685:11): [True: 536k, False: 649k]
  ------------------
  686|   536k|        *info |= SPELL_INITCAP;
  ------------------
  |  |   85|   536k|#define SPELL_INITCAP (1 << 4)
  ------------------
  687|  1.18M|      rv = checkword(scw, info, root, suggest_start);
  688|  1.18M|      if (captype == INITCAP)
  ------------------
  |  |   89|  1.18M|#define INITCAP 1
  ------------------
  |  Branch (688:11): [True: 536k, False: 649k]
  ------------------
  689|   536k|        *info &= ~SPELL_INITCAP;
  ------------------
  |  |   85|   536k|#define SPELL_INITCAP (1 << 4)
  ------------------
  690|       |      // forbid bad capitalization
  691|       |      // (for example, ijs -> Ijs instead of IJs in Dutch)
  692|       |      // use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag)
  693|  1.18M|      if (*info & SPELL_FORBIDDEN) {
  ------------------
  |  |   82|  1.18M|#define SPELL_FORBIDDEN (1 << 1)
  ------------------
  |  Branch (693:11): [True: 0, False: 1.18M]
  ------------------
  694|      0|        rv = nullptr;
  695|      0|        break;
  696|      0|      }
  697|  1.18M|      if (rv && is_keepcase(rv) && (captype == ALLCAP))
  ------------------
  |  |   90|      7|#define ALLCAP 2
  ------------------
  |  Branch (697:11): [True: 43.4k, False: 1.14M]
  |  Branch (697:17): [True: 7, False: 43.4k]
  |  Branch (697:36): [True: 0, False: 7]
  ------------------
  698|      0|        rv = nullptr;
  699|  1.18M|      if (rv || (Idot && langnum != LANG_az && langnum != LANG_tr && langnum != LANG_crh))
  ------------------
  |  Branch (699:11): [True: 43.4k, False: 1.14M]
  |  Branch (699:18): [True: 0, False: 1.14M]
  |  Branch (699:26): [True: 0, False: 0]
  |  Branch (699:48): [True: 0, False: 0]
  |  Branch (699:70): [True: 0, False: 0]
  ------------------
  700|  43.4k|        break;
  701|       |
  702|  1.14M|      mkallsmall2(scw, sunicw);
  703|  1.14M|      std::string u8buffer(scw);
  704|  1.14M|      mkinitcap2(scw, sunicw);
  705|       |
  706|  1.14M|      rv = checkword(u8buffer, info, root, suggest_start);
  707|  1.14M|      if (abbv && !rv) {
  ------------------
  |  Branch (707:11): [True: 174k, False: 967k]
  |  Branch (707:19): [True: 174k, False: 44]
  ------------------
  708|   174k|        u8buffer.push_back('.');
  709|   174k|        rv = checkword(u8buffer, info, root, suggest_start);
  710|   174k|        if (!rv) {
  ------------------
  |  Branch (710:13): [True: 174k, False: 0]
  ------------------
  711|   174k|          u8buffer = scw;
  712|   174k|          u8buffer.push_back('.');
  713|   174k|          if (captype == INITCAP)
  ------------------
  |  |   89|   174k|#define INITCAP 1
  ------------------
  |  Branch (713:15): [True: 82.6k, False: 92.2k]
  ------------------
  714|  82.6k|            *info |= SPELL_INITCAP;
  ------------------
  |  |   85|  82.6k|#define SPELL_INITCAP (1 << 4)
  ------------------
  715|   174k|          rv = checkword(u8buffer, info, root, suggest_start);
  716|   174k|          if (captype == INITCAP)
  ------------------
  |  |   89|   174k|#define INITCAP 1
  ------------------
  |  Branch (716:15): [True: 82.6k, False: 92.2k]
  ------------------
  717|  82.6k|            *info &= ~SPELL_INITCAP;
  ------------------
  |  |   85|  82.6k|#define SPELL_INITCAP (1 << 4)
  ------------------
  718|   174k|          if (rv && is_keepcase(rv) && (captype == ALLCAP))
  ------------------
  |  |   90|     20|#define ALLCAP 2
  ------------------
  |  Branch (718:15): [True: 20, False: 174k]
  |  Branch (718:21): [True: 20, False: 0]
  |  Branch (718:40): [True: 2, False: 18]
  ------------------
  719|      2|            rv = nullptr;
  720|   174k|          break;
  721|   174k|        }
  722|   174k|      }
  723|   967k|      if (rv && is_keepcase(rv) &&
  ------------------
  |  Branch (723:11): [True: 612, False: 967k]
  |  Branch (723:17): [True: 0, False: 612]
  ------------------
  724|      0|          ((captype == ALLCAP) ||
  ------------------
  |  |   90|      0|#define ALLCAP 2
  ------------------
  |  Branch (724:12): [True: 0, False: 0]
  ------------------
  725|       |           // if CHECKSHARPS: KEEPCASE words with \xDF  are allowed
  726|       |           // in INITCAP form, too.
  727|      0|           !(pAMgr->get_checksharps() &&
  ------------------
  |  Branch (727:14): [True: 0, False: 0]
  ------------------
  728|      0|             ((utf8 && u8buffer.find("\xC3\x9F") != std::string::npos) ||
  ------------------
  |  Branch (728:16): [True: 0, False: 0]
  |  Branch (728:24): [True: 0, False: 0]
  ------------------
  729|      0|              (!utf8 && u8buffer.find('\xDF') != std::string::npos)))))
  ------------------
  |  Branch (729:16): [True: 0, False: 0]
  |  Branch (729:25): [True: 0, False: 0]
  ------------------
  730|      0|        rv = nullptr;
  731|   967k|      break;
  732|  1.14M|    }
  733|  16.5M|  }
  734|       |
  735|  16.5M|  if (rv) {
  ------------------
  |  Branch (735:7): [True: 60.0k, False: 16.4M]
  ------------------
  736|  60.0k|    if (pAMgr && pAMgr->get_warn() && rv->astr &&
  ------------------
  |  Branch (736:9): [True: 60.0k, False: 0]
  |  Branch (736:9): [True: 0, False: 60.0k]
  |  Branch (736:18): [True: 5.31k, False: 54.7k]
  |  Branch (736:39): [True: 8, False: 5.30k]
  ------------------
  737|      8|        TESTAFF(rv->astr, pAMgr->get_warn(), rv->alen)) {
  ------------------
  |  |  102|      8|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 8]
  |  |  ------------------
  ------------------
  738|      0|      *info |= SPELL_WARN;
  ------------------
  |  |   87|      0|#define SPELL_WARN (1 << 6)
  ------------------
  739|      0|      if (pAMgr->get_forbidwarn())
  ------------------
  |  Branch (739:11): [True: 0, False: 0]
  ------------------
  740|      0|        return false;
  741|      0|      return true;
  742|      0|    }
  743|  60.0k|    return true;
  744|  60.0k|  }
  745|       |
  746|       |  // recursive breaking at break points
  747|  16.4M|  if (!wordbreak.empty() && !(*info & SPELL_FORBIDDEN)) {
  ------------------
  |  |   82|  16.4M|#define SPELL_FORBIDDEN (1 << 1)
  ------------------
  |  Branch (747:7): [True: 16.4M, False: 0]
  |  Branch (747:29): [True: 16.4M, False: 0]
  ------------------
  748|       |
  749|  16.4M|    int nbr = 0;
  750|  16.4M|    wl = scw.size();
  751|       |
  752|       |    // calculate break points for recursion limit
  753|  49.3M|    for (auto& j : wordbreak) {
  ------------------
  |  Branch (753:18): [True: 49.3M, False: 16.4M]
  ------------------
  754|  49.3M|      size_t pos = 0;
  755|  67.7M|      while ((pos = scw.find(j, pos)) != std::string::npos) {
  ------------------
  |  Branch (755:14): [True: 18.4M, False: 49.3M]
  ------------------
  756|  18.4M|        ++nbr;
  757|  18.4M|        pos += j.size();
  758|  18.4M|      }
  759|  49.3M|    }
  760|  16.4M|    if (nbr >= MAXBREAKDEPTH)
  ------------------
  |  |   87|  16.4M|#define MAXBREAKDEPTH 10
  ------------------
  |  Branch (760:9): [True: 7.45k, False: 16.4M]
  ------------------
  761|  7.45k|      return false;
  762|       |
  763|       |    // check boundary patterns (^begin and end$)
  764|  49.1M|    for (auto& j : wordbreak) {
  ------------------
  |  Branch (764:18): [True: 49.1M, False: 15.4M]
  ------------------
  765|  49.1M|      size_t plen = j.size();
  766|  49.1M|      if (plen == 1 || plen > wl)
  ------------------
  |  Branch (766:11): [True: 16.4M, False: 32.7M]
  |  Branch (766:24): [True: 4.97M, False: 27.7M]
  ------------------
  767|  21.4M|        continue;
  768|       |
  769|  27.7M|      if (j[0] == '^' && scw.compare(0, plen - 1, j, 1, plen - 1) == 0 &&
  ------------------
  |  Branch (769:11): [True: 13.9M, False: 13.8M]
  |  Branch (769:11): [True: 124k, False: 27.6M]
  |  Branch (769:26): [True: 1.54M, False: 12.3M]
  ------------------
  770|  1.54M|          spell(scw.substr(plen - 1), candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (770:11): [True: 124k, False: 1.41M]
  ------------------
  771|   124k|        *info |= SPELL_COMPOUND;
  ------------------
  |  |   81|   124k|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
  772|   124k|        return true;
  773|   124k|      }
  774|       |
  775|  27.6M|      if (j[plen - 1] == '$' &&
  ------------------
  |  Branch (775:11): [True: 13.8M, False: 13.8M]
  ------------------
  776|  13.8M|          scw.compare(wl - plen + 1, plen - 1, j, 0, plen - 1) == 0) {
  ------------------
  |  Branch (776:11): [True: 5.18M, False: 8.62M]
  ------------------
  777|  5.18M|        std::string suffix(scw.substr(wl - plen + 1));
  778|  5.18M|        scw.resize(wl - plen + 1);
  779|  5.18M|        if (spell(scw, candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (779:13): [True: 933k, False: 4.24M]
  ------------------
  780|   933k|          *info |= SPELL_COMPOUND;
  ------------------
  |  |   81|   933k|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
  781|   933k|          return true;
  782|   933k|        }
  783|  4.24M|        scw.append(suffix);
  784|  4.24M|      }
  785|  27.6M|    }
  786|       |
  787|       |    // other patterns
  788|  46.0M|    for (auto& j : wordbreak) {
  ------------------
  |  Branch (788:18): [True: 46.0M, False: 15.3M]
  ------------------
  789|  46.0M|      size_t plen = j.size();
  790|  46.0M|      size_t found = scw.find(j);
  791|  46.0M|      if ((found > 0) && (found < wl - plen)) {
  ------------------
  |  Branch (791:11): [True: 42.8M, False: 3.16M]
  |  Branch (791:26): [True: 4.81M, False: 38.0M]
  ------------------
  792|  4.81M|        size_t found2 = scw.find(j, found + 1);
  793|       |        // try to break at the second occurance
  794|       |        // to recognize dictionary words with wordbreak
  795|  4.81M|        if (found2 > 0 && (found2 < wl - plen))
  ------------------
  |  Branch (795:13): [True: 4.81M, False: 0]
  |  Branch (795:27): [True: 1.93M, False: 2.88M]
  ------------------
  796|  1.93M|            found = found2;
  797|  4.81M|        std::string substring(scw.substr(found + plen));
  798|  4.81M|        if (!spell(substring, candidate_stack, nullptr, nullptr, suggest_start))
  ------------------
  |  Branch (798:13): [True: 3.83M, False: 984k]
  ------------------
  799|  3.83M|          continue;
  800|   984k|        std::string suffix(scw.substr(found));
  801|   984k|        scw.resize(found);
  802|       |        // examine 2 sides of the break point
  803|   984k|        if (spell(scw, candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (803:13): [True: 64.5k, False: 920k]
  ------------------
  804|  64.5k|          *info |= SPELL_COMPOUND;
  ------------------
  |  |   81|  64.5k|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
  805|  64.5k|          return true;
  806|  64.5k|        }
  807|   920k|        scw.append(suffix);
  808|       |
  809|       |        // LANG_hu: spec. dash rule
  810|   920k|        if (langnum == LANG_hu && j == "-") {
  ------------------
  |  Branch (810:13): [True: 357, False: 919k]
  |  Branch (810:35): [True: 357, False: 0]
  ------------------
  811|    357|          suffix = scw.substr(found + 1);
  812|    357|          scw.resize(found + 1);
  813|    357|          if (spell(scw, candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (813:15): [True: 0, False: 357]
  ------------------
  814|      0|            *info |= SPELL_COMPOUND;
  ------------------
  |  |   81|      0|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
  815|      0|            return true;  // check the first part with dash
  816|      0|          }
  817|    357|          scw.append(suffix);
  818|    357|        }
  819|       |        // end of LANG specific region
  820|   920k|      }
  821|  46.0M|    }
  822|       |
  823|       |    // other patterns (break at first break point)
  824|  45.9M|    for (auto& j : wordbreak) {
  ------------------
  |  Branch (824:18): [True: 45.9M, False: 15.3M]
  ------------------
  825|  45.9M|      size_t plen = j.size(), found = scw.find(j);
  826|  45.9M|      if ((found > 0) && (found < wl - plen)) {
  ------------------
  |  Branch (826:11): [True: 42.7M, False: 3.16M]
  |  Branch (826:26): [True: 4.74M, False: 38.0M]
  ------------------
  827|  4.74M|        if (!spell(scw.substr(found + plen), candidate_stack, nullptr, nullptr, suggest_start))
  ------------------
  |  Branch (827:13): [True: 4.00M, False: 735k]
  ------------------
  828|  4.00M|          continue;
  829|   735k|        std::string suffix(scw.substr(found));
  830|   735k|        scw.resize(found);
  831|       |        // examine 2 sides of the break point
  832|   735k|        if (spell(scw, candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (832:13): [True: 5.73k, False: 730k]
  ------------------
  833|  5.73k|          *info |= SPELL_COMPOUND;
  ------------------
  |  |   81|  5.73k|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
  834|  5.73k|          return true;
  835|  5.73k|        }
  836|   730k|        scw.append(suffix);
  837|       |
  838|       |        // LANG_hu: spec. dash rule
  839|   730k|        if (langnum == LANG_hu && j == "-") {
  ------------------
  |  Branch (839:13): [True: 219, False: 729k]
  |  Branch (839:35): [True: 219, False: 0]
  ------------------
  840|    219|          suffix = scw.substr(found + 1);
  841|    219|          scw.resize(found + 1);
  842|    219|          if (spell(scw, candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (842:15): [True: 0, False: 219]
  ------------------
  843|      0|            *info |= SPELL_COMPOUND;
  ------------------
  |  |   81|      0|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
  844|      0|            return true;  // check the first part with dash
  845|      0|          }
  846|    219|          scw.append(suffix);
  847|    219|        }
  848|       |        // end of LANG specific region
  849|   730k|      }
  850|  45.9M|    }
  851|  15.3M|  }
  852|       |
  853|  15.3M|  return false;
  854|  16.4M|}
_ZN12HunspellImpl9checkwordERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPiPS6_NS0_6chrono10time_pointINSB_12steady_clockENSB_8durationIxNS0_5ratioILl1ELl1000000000EEEEEEE:
  857|  21.0M|                                       std::chrono::steady_clock::time_point suggest_start) {
  858|       |  // check overall suggest time limit
  859|  21.0M|  if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  21.0M|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (859:7): [True: 0, False: 21.0M]
  ------------------
  860|      0|    return nullptr;
  861|       |
  862|  21.0M|  std::string word;
  863|       |
  864|       |  // remove IGNORE characters from the string
  865|  21.0M|  clean_ignore(word, w);
  866|       |
  867|  21.0M|  if (word.empty())
  ------------------
  |  Branch (867:7): [True: 1.32k, False: 21.0M]
  ------------------
  868|  1.32k|    return nullptr;
  869|       |
  870|       |  // word reversing wrapper for complex prefixes
  871|  21.0M|  if (complexprefixes) {
  ------------------
  |  Branch (871:7): [True: 1.08M, False: 19.9M]
  ------------------
  872|  1.08M|    if (utf8)
  ------------------
  |  Branch (872:9): [True: 0, False: 1.08M]
  ------------------
  873|      0|      reverseword_utf(word);
  874|  1.08M|    else
  875|  1.08M|      reverseword(word);
  876|  1.08M|  }
  877|       |
  878|  21.0M|  size_t len = word.size();
  879|       |
  880|       |  // look word in hash table
  881|  21.0M|  struct hentry* he = nullptr;
  882|  21.0M|  TraceCtx* t = active_trace();
  883|  42.0M|  for (size_t i = 0; (i < m_HMgrs.size()) && !he; ++i) {
  ------------------
  |  Branch (883:22): [True: 21.0M, False: 21.0M]
  |  Branch (883:46): [True: 21.0M, False: 0]
  ------------------
  884|  21.0M|    he = m_HMgrs[i]->lookup(word.c_str(), word.size());
  885|       |
  886|  21.0M|    if (t) {
  ------------------
  |  Branch (886:9): [True: 0, False: 21.0M]
  ------------------
  887|      0|      std::string dic;
  888|      0|      if (m_HMgrs.size() > 1)
  ------------------
  |  Branch (888:11): [True: 0, False: 0]
  ------------------
  889|      0|        dic = " dic=" + std::to_string(i);
  890|      0|      if (he)
  ------------------
  |  Branch (890:11): [True: 0, False: 0]
  ------------------
  891|      0|        trace(*t, "lookup \"%s\"%s -> entry \"%s\" flags=%s", word.c_str(),
  892|      0|              dic.c_str(), he->word,
  893|      0|              trace_flags(pAMgr.get(), he->astr, he->alen).c_str());
  894|      0|      else
  895|      0|        trace(*t, "lookup \"%s\"%s -> miss", word.c_str(), dic.c_str());
  896|      0|    }
  897|       |
  898|       |    // check forbidden and onlyincompound words
  899|  21.0M|    if ((he) && (he->astr) && (pAMgr) &&
  ------------------
  |  Branch (899:9): [True: 60.3k, False: 20.9M]
  |  Branch (899:9): [True: 0, False: 21.0M]
  |  Branch (899:17): [True: 541, False: 59.7k]
  |  Branch (899:31): [True: 541, False: 0]
  ------------------
  900|    541|        TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
  ------------------
  |  |  102|    541|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 541]
  |  |  ------------------
  ------------------
  901|      0|      if (t)
  ------------------
  |  Branch (901:11): [True: 0, False: 0]
  ------------------
  902|      0|        trace(*t, "test forbidden flag=%s in=dic have=%s"
  903|      0|                  " -> fail, the word is forbidden",
  904|      0|              pAMgr->encode_flag(pAMgr->get_forbiddenword()).c_str(),
  905|      0|              trace_flags(pAMgr.get(), he->astr, he->alen).c_str());
  906|      0|      if (info)
  ------------------
  |  Branch (906:11): [True: 0, False: 0]
  ------------------
  907|      0|        *info |= SPELL_FORBIDDEN;
  ------------------
  |  |   82|      0|#define SPELL_FORBIDDEN (1 << 1)
  ------------------
  908|       |      // LANG_hu section: set dash information for suggestions
  909|      0|      if (langnum == LANG_hu) {
  ------------------
  |  Branch (909:11): [True: 0, False: 0]
  ------------------
  910|      0|        if (pAMgr->get_compoundflag() &&
  ------------------
  |  Branch (910:13): [True: 0, False: 0]
  |  Branch (910:13): [True: 0, False: 0]
  ------------------
  911|      0|            TESTAFF(he->astr, pAMgr->get_compoundflag(), he->alen)) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  912|      0|          if (info)
  ------------------
  |  Branch (912:15): [True: 0, False: 0]
  ------------------
  913|      0|            *info |= SPELL_COMPOUND;
  ------------------
  |  |   81|      0|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
  914|      0|        }
  915|      0|      }
  916|      0|      return nullptr;
  917|      0|    }
  918|       |
  919|       |    // he = next not needaffix, onlyincompound homonym or onlyupcase word
  920|  21.0M|    const struct hentry* first_he = he;
  921|  21.0M|    while (he && (he->astr) && pAMgr &&
  ------------------
  |  Branch (921:12): [True: 60.3k, False: 20.9M]
  |  Branch (921:12): [True: 238, False: 21.0M]
  |  Branch (921:18): [True: 541, False: 59.7k]
  |  Branch (921:32): [True: 541, False: 0]
  ------------------
  922|    541|           ((pAMgr->get_needaffix() &&
  ------------------
  |  Branch (922:14): [True: 43, False: 498]
  ------------------
  923|     43|             TESTAFF(he->astr, pAMgr->get_needaffix(), he->alen)) ||
  ------------------
  |  |  102|     43|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 43]
  |  |  ------------------
  ------------------
  924|    541|            (pAMgr->get_onlyincompound() &&
  ------------------
  |  Branch (924:14): [True: 0, False: 541]
  ------------------
  925|      0|             TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  926|    541|            (info && (*info & SPELL_INITCAP) &&
  ------------------
  |  |   85|    541|#define SPELL_INITCAP (1 << 4)
  ------------------
  |  Branch (926:14): [True: 541, False: 0]
  |  Branch (926:22): [True: 263, False: 278]
  ------------------
  927|    263|             TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) {
  ------------------
  |  |  102|    263|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 238, False: 25]
  |  |  ------------------
  ------------------
  928|    238|      if (t) {
  ------------------
  |  Branch (928:11): [True: 0, False: 238]
  ------------------
  929|       |        // Name the branch that fired, in the order the condition tests them.
  930|      0|        const char* reason = "onlyupcase";
  931|      0|        FLAG flag = ONLYUPCASEFLAG;
  ------------------
  |  |   98|      0|#define FLAG unsigned short
  ------------------
                      FLAG flag = ONLYUPCASEFLAG;
  ------------------
  |  |  124|      0|#define ONLYUPCASEFLAG 65511
  ------------------
  932|      0|        if (pAMgr->get_needaffix() &&
  ------------------
  |  Branch (932:13): [True: 0, False: 0]
  |  Branch (932:13): [True: 0, False: 0]
  ------------------
  933|      0|            TESTAFF(he->astr, pAMgr->get_needaffix(), he->alen)) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  934|      0|          reason = "needaffix";
  935|      0|          flag = pAMgr->get_needaffix();
  936|      0|        } else if (pAMgr->get_onlyincompound() &&
  ------------------
  |  Branch (936:20): [True: 0, False: 0]
  |  Branch (936:20): [True: 0, False: 0]
  ------------------
  937|      0|                   TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  938|      0|          reason = "onlyincompound";
  939|      0|          flag = pAMgr->get_onlyincompound();
  940|      0|        }
  941|      0|        trace(*t, "test %s flag=%s in=dic have=%s"
  942|      0|                  " -> fail, on to the next homonym",
  943|      0|              reason, trace_flag(pAMgr.get(), flag).c_str(),
  944|      0|              trace_flags(pAMgr.get(), he->astr, he->alen).c_str());
  945|      0|      }
  946|    238|      he = he->next_homonym;
  947|    238|    }
  948|       |
  949|       |    // Say which entry the walk left in hand, so the transcript does not end
  950|       |    // on a homonym that was passed over.
  951|  21.0M|    if (t && he != first_he) {
  ------------------
  |  Branch (951:9): [True: 0, False: 21.0M]
  |  Branch (951:14): [True: 0, False: 0]
  ------------------
  952|      0|      if (he)
  ------------------
  |  Branch (952:11): [True: 0, False: 0]
  ------------------
  953|      0|        trace(*t, "lookup \"%s\" -> entry \"%s\" flags=%s", word.c_str(),
  954|      0|              he->word, trace_flags(pAMgr.get(), he->astr, he->alen).c_str());
  955|      0|      else
  956|      0|        trace(*t, "lookup \"%s\" -> no more homonyms", word.c_str());
  957|      0|    }
  958|  21.0M|  }
  959|       |
  960|       |  // check with affixes
  961|  21.0M|  if (!he && pAMgr) {
  ------------------
  |  Branch (961:7): [True: 20.9M, False: 60.1k]
  |  Branch (961:14): [True: 20.9M, False: 0]
  ------------------
  962|       |    // try stripping off affixes
  963|  20.9M|    AffixScratch scratch;
  964|  20.9M|    scratch.trace = t;
  965|       |    // For an initial-capital query, make affix_check skip an all-uppercase-only
  966|       |    // stem and keep looking, so a valid mixed-case match behind it is found.
  967|  20.9M|    FLAG avoidflag = (info && (*info & SPELL_INITCAP)) ? ONLYUPCASEFLAG : FLAG_NULL;
  ------------------
  |  |   98|  20.9M|#define FLAG unsigned short
  ------------------
                  FLAG avoidflag = (info && (*info & SPELL_INITCAP)) ? ONLYUPCASEFLAG : FLAG_NULL;
  ------------------
  |  |   85|  20.9M|#define SPELL_INITCAP (1 << 4)
  ------------------
                  FLAG avoidflag = (info && (*info & SPELL_INITCAP)) ? ONLYUPCASEFLAG : FLAG_NULL;
  ------------------
  |  |  124|   577k|#define ONLYUPCASEFLAG 65511
  ------------------
                  FLAG avoidflag = (info && (*info & SPELL_INITCAP)) ? ONLYUPCASEFLAG : FLAG_NULL;
  ------------------
  |  |   99|  41.3M|#define FLAG_NULL 0x00
  ------------------
  |  Branch (967:23): [True: 20.9M, False: 0]
  |  Branch (967:31): [True: 577k, False: 20.3M]
  ------------------
  968|  20.9M|    he = pAMgr->affix_check(word, 0, len, scratch, 0, IN_CPD_NOT, avoidflag);
  ------------------
  |  |   75|  20.9M|#define IN_CPD_NOT 0
  ------------------
  969|       |
  970|       |    // check compound restriction and onlyupcase
  971|  20.9M|    if (he && he->astr &&
  ------------------
  |  Branch (971:9): [True: 0, False: 20.9M]
  |  Branch (971:9): [True: 0, False: 20.9M]
  |  Branch (971:15): [True: 0, False: 0]
  ------------------
  972|      0|        ((pAMgr->get_onlyincompound() &&
  ------------------
  |  Branch (972:11): [True: 0, False: 0]
  ------------------
  973|      0|          TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  974|      0|         (info && (*info & SPELL_INITCAP) &&
  ------------------
  |  |   85|      0|#define SPELL_INITCAP (1 << 4)
  ------------------
  |  Branch (974:11): [True: 0, False: 0]
  |  Branch (974:19): [True: 0, False: 0]
  ------------------
  975|      0|          TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  976|      0|      he = nullptr;
  977|      0|    }
  978|       |
  979|  20.9M|    if (he) {
  ------------------
  |  Branch (979:9): [True: 0, False: 20.9M]
  ------------------
  980|      0|      if ((he->astr) && (pAMgr) &&
  ------------------
  |  Branch (980:11): [True: 0, False: 0]
  |  Branch (980:11): [True: 0, False: 0]
  |  Branch (980:25): [True: 0, False: 0]
  ------------------
  981|      0|          TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  982|      0|        if (info)
  ------------------
  |  Branch (982:13): [True: 0, False: 0]
  ------------------
  983|      0|          *info |= SPELL_FORBIDDEN;
  ------------------
  |  |   82|      0|#define SPELL_FORBIDDEN (1 << 1)
  ------------------
  984|      0|        return nullptr;
  985|      0|      }
  986|      0|      if (root) {
  ------------------
  |  Branch (986:11): [True: 0, False: 0]
  ------------------
  987|      0|        root->assign(he->word);
  988|      0|        if (complexprefixes) {
  ------------------
  |  Branch (988:13): [True: 0, False: 0]
  ------------------
  989|      0|          if (utf8)
  ------------------
  |  Branch (989:15): [True: 0, False: 0]
  ------------------
  990|      0|            reverseword_utf(*root);
  991|      0|          else
  992|      0|            reverseword(*root);
  993|      0|        }
  994|      0|      }
  995|       |      // try check compound word
  996|  20.9M|    } else if (pAMgr->get_compound()) {
  ------------------
  |  Branch (996:16): [True: 5.38M, False: 15.5M]
  ------------------
  997|  5.38M|      struct hentry* rwords[100] = {};  // buffer for COMPOUND pattern checking
  998|       |
  999|       |      // first allow only 2 words in the compound
 1000|  5.38M|      int setinfo = SPELL_COMPOUND_2;
  ------------------
  |  |   88|  5.38M|#define SPELL_COMPOUND_2 (1 << 7)  // permit only 2 dictionary words in the compound
  ------------------
 1001|  5.38M|      if (info)
  ------------------
  |  Branch (1001:11): [True: 5.38M, False: 0]
  ------------------
 1002|  5.38M|        setinfo |= *info;
 1003|  5.38M|      if (TraceCtx* t = trace_on(scratch.trace))
  ------------------
  |  Branch (1003:21): [True: 0, False: 5.38M]
  ------------------
 1004|      0|        trace(*t, "compound words=2");
 1005|  5.38M|      {
 1006|  5.38M|        TraceScope compound_depth(trace_on(scratch.trace));
 1007|  5.38M|        he = pAMgr->compound_check(word, 0, 0, 100, 0, nullptr, (hentry**)&rwords, 0, 0, &setinfo, scratch);
 1008|  5.38M|      }
 1009|  5.38M|      if (info)
  ------------------
  |  Branch (1009:11): [True: 5.38M, False: 0]
  ------------------
 1010|  5.38M|        *info = setinfo & ~SPELL_COMPOUND_2;
  ------------------
  |  |   88|  5.38M|#define SPELL_COMPOUND_2 (1 << 7)  // permit only 2 dictionary words in the compound
  ------------------
 1011|       |      // if not 2-word compoud word, try with 3 or more words
 1012|       |      // (only if original info didn't forbid it)
 1013|  5.38M|      if (!he && info && !(*info & SPELL_COMPOUND_2)) {
  ------------------
  |  |   88|  5.38M|#define SPELL_COMPOUND_2 (1 << 7)  // permit only 2 dictionary words in the compound
  ------------------
  |  Branch (1013:11): [True: 5.38M, False: 0]
  |  Branch (1013:18): [True: 5.38M, False: 0]
  |  Branch (1013:26): [True: 5.38M, False: 0]
  ------------------
 1014|  5.38M|        *info &= ~SPELL_COMPOUND_2;
  ------------------
  |  |   88|  5.38M|#define SPELL_COMPOUND_2 (1 << 7)  // permit only 2 dictionary words in the compound
  ------------------
 1015|  5.38M|        if (TraceCtx* t = trace_on(scratch.trace))
  ------------------
  |  Branch (1015:23): [True: 0, False: 5.38M]
  ------------------
 1016|      0|          trace(*t, "compound words=3+");
 1017|  5.38M|        {
 1018|  5.38M|          TraceScope compound_depth(trace_on(scratch.trace));
 1019|  5.38M|          he = pAMgr->compound_check(word, 0, 0, 100, 0, nullptr, (hentry**)&rwords, 0, 0, info, scratch);
 1020|  5.38M|        }
 1021|       |        // accept the compound with 3 or more words only if it is
 1022|       |        // - not a dictionary word with a typo and
 1023|       |        // - not two words written separately,
 1024|       |        // - or if it's an arbitrary number accepted by compound rules (e.g. 999%)
 1025|  5.38M|        if (he && !isdigit((unsigned char)word[0]))
  ------------------
  |  Branch (1025:13): [True: 0, False: 5.38M]
  |  Branch (1025:19): [True: 0, False: 0]
  ------------------
 1026|      0|        {
 1027|      0|          std::vector<std::string> slst;
 1028|      0|          bool simple;
 1029|      0|          {
 1030|       |            // the suggester runs its whole search here, so report what it
 1031|       |            // decided rather than every candidate it tried
 1032|      0|            TraceSuppress no_trace(scratch.trace);
 1033|      0|            simple = pSMgr->suggest(slst, word, nullptr, /*test_simplesug=*/true);
 1034|      0|          }
 1035|      0|          if (TraceCtx* t = trace_on(scratch.trace))
  ------------------
  |  Branch (1035:25): [True: 0, False: 0]
  ------------------
 1036|      0|            trace(*t, "test simplesug -> %s",
 1037|      0|                  simple ? "fail, a simpler form of this word exists"
  ------------------
  |  Branch (1037:19): [True: 0, False: 0]
  ------------------
 1038|      0|                         : "pass, no simpler form of this word exists");
 1039|      0|          if (simple)
  ------------------
  |  Branch (1039:15): [True: 0, False: 0]
  ------------------
 1040|      0|            he = nullptr;
 1041|      0|        }
 1042|  5.38M|      }
 1043|       |
 1044|       |      // LANG_hu section: `moving rule' with last dash
 1045|  5.38M|      if ((!he) && (langnum == LANG_hu) && (word[len - 1] == '-')) {
  ------------------
  |  Branch (1045:11): [True: 5.38M, False: 0]
  |  Branch (1045:20): [True: 40.1k, False: 5.34M]
  |  Branch (1045:44): [True: 16.4k, False: 23.6k]
  ------------------
 1046|  16.4k|        std::string dup(word, 0, len - 1);
 1047|  16.4k|        he = pAMgr->compound_check(dup, -5, 0, 100, 0, nullptr, (hentry**)&rwords, 1, 0, info, scratch);
 1048|  16.4k|      }
 1049|       |      // end of LANG specific region
 1050|  5.38M|      if (he) {
  ------------------
  |  Branch (1050:11): [True: 0, False: 5.38M]
  ------------------
 1051|      0|        if (root) {
  ------------------
  |  Branch (1051:13): [True: 0, False: 0]
  ------------------
 1052|      0|          root->assign(he->word);
 1053|      0|          if (complexprefixes) {
  ------------------
  |  Branch (1053:15): [True: 0, False: 0]
  ------------------
 1054|      0|            if (utf8)
  ------------------
  |  Branch (1054:17): [True: 0, False: 0]
  ------------------
 1055|      0|              reverseword_utf(*root);
 1056|      0|            else
 1057|      0|              reverseword(*root);
 1058|      0|          }
 1059|      0|        }
 1060|      0|        if (info)
  ------------------
  |  Branch (1060:13): [True: 0, False: 0]
  ------------------
 1061|      0|          *info |= SPELL_COMPOUND;
  ------------------
  |  |   81|      0|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
 1062|      0|      }
 1063|  5.38M|    }
 1064|  20.9M|  }
 1065|       |
 1066|  21.0M|  return he;
 1067|  21.0M|}
_ZN12HunspellImpl7suggestERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERNS0_6vectorIS6_NS4_IS6_EEEENS0_6chrono10time_pointINSD_12steady_clockENSD_8durationIxNS0_5ratioILl1ELl1000000000EEEEEEE:
 1075|  93.9k|std::vector<std::string> HunspellImpl::suggest(const std::string& word, std::vector<std::string>& suggest_candidate_stack, std::chrono::steady_clock::time_point suggest_start) {
 1076|       |
 1077|  93.9k|  if (suggest_candidate_stack.size() > MAX_CANDIDATE_STACK_DEPTH || // apply a fairly arbitrary depth limit
  ------------------
  |  | 1070|   187k|#define MAX_CANDIDATE_STACK_DEPTH 512
  ------------------
  |  Branch (1077:7): [True: 0, False: 93.9k]
  |  Branch (1077:7): [True: 0, False: 93.9k]
  ------------------
 1078|       |      // something very broken if suggest ends up calling itself with the same word
 1079|  93.9k|      std::find(suggest_candidate_stack.begin(), suggest_candidate_stack.end(), word) != suggest_candidate_stack.end()) {
  ------------------
  |  Branch (1079:7): [True: 0, False: 93.9k]
  ------------------
 1080|      0|    return { };
 1081|      0|  }
 1082|       |
 1083|  93.9k|  if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  93.9k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1083:7): [True: 0, False: 93.9k]
  ------------------
 1084|      0|    return { };
 1085|       |
 1086|  93.9k|  bool capwords;
 1087|  93.9k|  size_t abbv;
 1088|  93.9k|  int captype;
 1089|  93.9k|  std::vector<std::string> spell_candidate_stack;
 1090|  93.9k|  suggest_candidate_stack.push_back(word);
 1091|  93.9k|  std::vector<std::string> slst = suggest_internal(word, spell_candidate_stack, suggest_candidate_stack,
 1092|  93.9k|                                                   capwords, abbv, captype, suggest_start);
 1093|  93.9k|  suggest_candidate_stack.pop_back();
 1094|       |  // word reversing wrapper for complex prefixes
 1095|  93.9k|  if (complexprefixes) {
  ------------------
  |  Branch (1095:7): [True: 4.85k, False: 89.0k]
  ------------------
 1096|  4.85k|    for (auto& j : slst) {
  ------------------
  |  Branch (1096:18): [True: 2.31k, False: 4.85k]
  ------------------
 1097|  2.31k|      if (utf8)
  ------------------
  |  Branch (1097:11): [True: 0, False: 2.31k]
  ------------------
 1098|      0|        reverseword_utf(j);
 1099|  2.31k|      else
 1100|  2.31k|        reverseword(j);
 1101|  2.31k|    }
 1102|  4.85k|  }
 1103|       |
 1104|       |  // capitalize
 1105|  93.9k|  if (capwords) {
  ------------------
  |  Branch (1105:7): [True: 26.2k, False: 67.6k]
  ------------------
 1106|  26.2k|    for (auto& j : slst) {
  ------------------
  |  Branch (1106:18): [True: 18.4k, False: 26.2k]
  ------------------
 1107|  18.4k|      std::string capitalized(j);
 1108|  18.4k|      mkinitcap(capitalized);
 1109|  18.4k|      if (capitalized == word)
  ------------------
  |  Branch (1109:11): [True: 9, False: 18.4k]
  ------------------
 1110|      9|        continue;  // capitalizing would just reproduce the misspelled word
 1111|  18.4k|      j = std::move(capitalized);
 1112|  18.4k|    }
 1113|  26.2k|  }
 1114|       |
 1115|       |  // expand suggestions with dot(s)
 1116|  93.9k|  if (abbv && pAMgr && pAMgr->get_sugswithdots() && word.size() >= abbv) {
  ------------------
  |  Branch (1116:7): [True: 3.40k, False: 90.5k]
  |  Branch (1116:15): [True: 3.40k, False: 0]
  |  Branch (1116:24): [True: 0, False: 3.40k]
  |  Branch (1116:53): [True: 0, False: 0]
  ------------------
 1117|      0|    for (auto& j : slst) {
  ------------------
  |  Branch (1117:18): [True: 0, False: 0]
  ------------------
 1118|      0|      j.append(word.substr(word.size() - abbv));
 1119|      0|    }
 1120|      0|  }
 1121|       |
 1122|       |  // remove bad capitalized and forbidden forms
 1123|  93.9k|  if (pAMgr && (pAMgr->get_keepcase() || pAMgr->get_forbiddenword())) {
  ------------------
  |  Branch (1123:7): [True: 93.9k, False: 0]
  |  Branch (1123:17): [True: 4.87k, False: 89.0k]
  |  Branch (1123:42): [True: 89.0k, False: 0]
  ------------------
 1124|  93.9k|    switch (captype) {
  ------------------
  |  Branch (1124:13): [True: 50.9k, False: 43.0k]
  ------------------
 1125|  11.2k|      case INITCAP:
  ------------------
  |  |   89|  11.2k|#define INITCAP 1
  ------------------
  |  Branch (1125:7): [True: 11.2k, False: 82.6k]
  ------------------
 1126|  20.6k|      case ALLCAP:
  ------------------
  |  |   90|  20.6k|#define ALLCAP 2
  ------------------
  |  Branch (1126:7): [True: 9.41k, False: 84.4k]
  ------------------
 1127|  35.9k|      case HUHCAP:
  ------------------
  |  |   91|  35.9k|#define HUHCAP 3
  ------------------
  |  Branch (1127:7): [True: 15.2k, False: 78.6k]
  ------------------
 1128|  50.9k|      case HUHINITCAP: {
  ------------------
  |  |   92|  50.9k|#define HUHINITCAP 4
  ------------------
  |  Branch (1128:7): [True: 14.9k, False: 78.9k]
  ------------------
 1129|  50.9k|        size_t l = 0;
 1130|  85.7k|        for (size_t j = 0; j < slst.size(); ++j) {
  ------------------
  |  Branch (1130:28): [True: 34.8k, False: 50.9k]
  ------------------
 1131|       |          // A space-containing suggestion can be an "insert a space" split
 1132|       |          // whose parts each spell on their own, so it is good when every
 1133|       |          // part spells even though the whole string does not.
 1134|  34.8k|          bool bad = !spell(slst[j], spell_candidate_stack, nullptr, nullptr, suggest_start);
 1135|  34.8k|          if (bad && slst[j].find(' ') != std::string::npos) {
  ------------------
  |  Branch (1135:15): [True: 19.6k, False: 15.2k]
  |  Branch (1135:22): [True: 8.62k, False: 11.0k]
  ------------------
 1136|  8.62k|            bad = false;
 1137|  17.4k|            for (size_t start = 0; start <= slst[j].size(); ) {
  ------------------
  |  Branch (1137:36): [True: 17.4k, False: 0]
  ------------------
 1138|  17.4k|              size_t sp = slst[j].find(' ', start);
 1139|  17.4k|              size_t end = (sp == std::string::npos) ? slst[j].size() : sp;
  ------------------
  |  Branch (1139:28): [True: 1.97k, False: 15.4k]
  ------------------
 1140|  17.4k|              std::string part = slst[j].substr(start, end - start);
 1141|  17.4k|              if (!part.empty() &&
  ------------------
  |  Branch (1141:19): [True: 11.1k, False: 6.27k]
  ------------------
 1142|  11.1k|                  !spell(part, spell_candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (1142:19): [True: 7.73k, False: 3.39k]
  ------------------
 1143|  7.73k|                bad = true;
 1144|  7.73k|                break;
 1145|  7.73k|              }
 1146|  9.67k|              if (sp == std::string::npos)
  ------------------
  |  Branch (1146:19): [True: 888, False: 8.78k]
  ------------------
 1147|    888|                break;
 1148|  8.78k|              start = sp + 1;
 1149|  8.78k|            }
 1150|  8.62k|          }
 1151|  34.8k|          if (bad) {
  ------------------
  |  Branch (1151:15): [True: 18.7k, False: 16.0k]
  ------------------
 1152|  18.7k|            std::string s;
 1153|  18.7k|            std::vector<w_char> w;
 1154|  18.7k|            if (utf8) {
  ------------------
  |  Branch (1154:17): [True: 8.25k, False: 10.4k]
  ------------------
 1155|  8.25k|              u8_u16(w, slst[j]);
 1156|  10.4k|            } else {
 1157|  10.4k|              s = slst[j];
 1158|  10.4k|            }
 1159|  18.7k|            mkallsmall2(s, w);
 1160|  18.7k|            if (spell(s, spell_candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (1160:17): [True: 45, False: 18.6k]
  ------------------
 1161|     45|              slst[l] = std::move(s);
 1162|     45|              ++l;
 1163|  18.6k|            } else {
 1164|  18.6k|              mkinitcap2(s, w);
 1165|  18.6k|              if (spell(s, spell_candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (1165:19): [True: 59, False: 18.6k]
  ------------------
 1166|     59|                slst[l] = std::move(s);
 1167|     59|                ++l;
 1168|     59|              }
 1169|  18.6k|            }
 1170|  18.7k|          } else {
 1171|  16.0k|            slst[l] = slst[j];
 1172|  16.0k|            ++l;
 1173|  16.0k|          }
 1174|  34.8k|        }
 1175|  50.9k|        slst.resize(l);
 1176|  50.9k|      }
 1177|  93.9k|    }
 1178|  93.9k|  }
 1179|       |
 1180|       |  // remove duplications
 1181|  93.9k|  size_t l = 0;
 1182|   113k|  for (size_t j = 0; j < slst.size(); ++j) {
  ------------------
  |  Branch (1182:22): [True: 19.2k, False: 93.9k]
  ------------------
 1183|  19.2k|    slst[l] = slst[j];
 1184|  28.7k|    for (size_t k = 0; k < l; ++k) {
  ------------------
  |  Branch (1184:24): [True: 10.2k, False: 18.5k]
  ------------------
 1185|  10.2k|      if (slst[k] == slst[j]) {
  ------------------
  |  Branch (1185:11): [True: 746, False: 9.53k]
  ------------------
 1186|    746|        --l;
 1187|    746|        break;
 1188|    746|      }
 1189|  10.2k|    }
 1190|  19.2k|    ++l;
 1191|  19.2k|  }
 1192|  93.9k|  slst.resize(l);
 1193|       |
 1194|       |  // output conversion
 1195|  93.9k|  RepList* rl = (pAMgr) ? pAMgr->get_oconvtable() : nullptr;
  ------------------
  |  Branch (1195:17): [True: 93.9k, False: 0]
  ------------------
 1196|  93.9k|  if (rl) {
  ------------------
  |  Branch (1196:7): [True: 5.06k, False: 88.8k]
  ------------------
 1197|       |    // hold the converted suggestions to the same ceiling as an analysis
 1198|  5.06k|    size_t total = 0;
 1199|  5.06k|    size_t l = 0;
 1200|  5.86k|    for (size_t i = 0; i < slst.size(); ++i) {
  ------------------
  |  Branch (1200:24): [True: 806, False: 5.06k]
  ------------------
 1201|    806|      std::string wspace;
 1202|    806|      if (rl->conv(slst[i], wspace, MAXMORPHRESULT - total)) {
  ------------------
  |  |  114|    806|#define MAXMORPHRESULT (4 * 1024 * 1024)
  ------------------
  |  Branch (1202:11): [True: 263, False: 543]
  ------------------
 1203|    263|        slst[i] = std::move(wspace);
 1204|    263|      }
 1205|    806|      if (slst[i].size() > MAXMORPHRESULT - total)
  ------------------
  |  |  114|    806|#define MAXMORPHRESULT (4 * 1024 * 1024)
  ------------------
  |  Branch (1205:11): [True: 0, False: 806]
  ------------------
 1206|      0|        break;
 1207|    806|      total += slst[i].size();
 1208|       |      // gh#1002: OCONV can map a generated form back to the input word
 1209|       |      // (e.g. "románórum" -> "romanórum" when the user typed "romanórum"),
 1210|       |      // leaving the misspelled word as its own suggestion.
 1211|    806|      if (slst[i] == word)
  ------------------
  |  Branch (1211:11): [True: 0, False: 806]
  ------------------
 1212|      0|        continue;
 1213|    806|      if (l != i)
  ------------------
  |  Branch (1213:11): [True: 0, False: 806]
  ------------------
 1214|      0|        slst[l] = std::move(slst[i]);
 1215|    806|      ++l;
 1216|    806|    }
 1217|  5.06k|    slst.resize(l);
 1218|  5.06k|  }
 1219|  93.9k|  return slst;
 1220|  93.9k|}
_ZN12HunspellImpl7suggestERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1222|  65.3k|std::vector<std::string> HunspellImpl::suggest(const std::string& word) {
 1223|  65.3k|  std::vector<std::string> suggest_candidate_stack;
 1224|  65.3k|  auto suggest_start = std::chrono::steady_clock::now();
 1225|  65.3k|  return suggest(word, suggest_candidate_stack, suggest_start);
 1226|  65.3k|}
_ZN12HunspellImpl16suggest_internalERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERNS0_6vectorIS6_NS4_IS6_EEEESC_RbRmRiNS0_6chrono10time_pointINSG_12steady_clockENSG_8durationIxNS0_5ratioILl1ELl1000000000EEEEEEE:
 1232|  93.9k|        std::chrono::steady_clock::time_point suggest_start) {
 1233|       |  // The candidates tried here are the tool's own guesses, not the word the
 1234|       |  // user asked about.
 1235|  93.9k|  TraceSuppress no_trace(m_trace.get());
 1236|       |
 1237|  93.9k|  captype = NOCAP;
  ------------------
  |  |   88|  93.9k|#define NOCAP 0
  ------------------
 1238|  93.9k|  abbv = 0;
 1239|  93.9k|  capwords = false;
 1240|       |
 1241|  93.9k|  std::vector<std::string> slst;
 1242|       |
 1243|  93.9k|  int onlycmpdsug = 0;
 1244|  93.9k|  if (!pSMgr || m_HMgrs.empty())
  ------------------
  |  Branch (1244:7): [True: 0, False: 93.9k]
  |  Branch (1244:17): [True: 0, False: 93.9k]
  ------------------
 1245|      0|    return slst;
 1246|       |
 1247|       |  // process XML input of the simplified API (see manual)
 1248|  93.9k|  if (word.compare(0, sizeof(SPELL_XML) - 3, SPELL_XML, sizeof(SPELL_XML) - 3) == 0) {
  ------------------
  |  |   80|  93.9k|#define SPELL_XML "<?xml?>"
  ------------------
                if (word.compare(0, sizeof(SPELL_XML) - 3, SPELL_XML, sizeof(SPELL_XML) - 3) == 0) {
  ------------------
  |  |   80|  93.9k|#define SPELL_XML "<?xml?>"
  ------------------
                if (word.compare(0, sizeof(SPELL_XML) - 3, SPELL_XML, sizeof(SPELL_XML) - 3) == 0) {
  ------------------
  |  |   80|  93.9k|#define SPELL_XML "<?xml?>"
  ------------------
  |  Branch (1248:7): [True: 23.0k, False: 70.8k]
  ------------------
 1249|  23.0k|    if (word.size() > MAXSPELLMLLEN)
  ------------------
  |  |   88|  23.0k|#define MAXSPELLMLLEN 8192
  ------------------
  |  Branch (1249:9): [True: 551, False: 22.5k]
  ------------------
 1250|    551|      return slst;
 1251|  22.5k|    return spellml(word);
 1252|  23.0k|  }
 1253|  70.8k|  if (utf8) {
  ------------------
  |  Branch (1253:7): [True: 34.3k, False: 36.4k]
  ------------------
 1254|  34.3k|    if (word.size() >= MAXWORDUTF8LEN)
  ------------------
  |  |   87|  34.3k|#define MAXWORDUTF8LEN (MAXWORDLEN * 3)
  |  |  ------------------
  |  |  |  |   90|  34.3k|#define MAXWORDLEN 100
  |  |  ------------------
  ------------------
  |  Branch (1254:9): [True: 153, False: 34.2k]
  ------------------
 1255|    153|      return slst;
 1256|  36.4k|  } else {
 1257|  36.4k|    if (word.size() >= MAXWORDLEN)
  ------------------
  |  |   90|  36.4k|#define MAXWORDLEN 100
  ------------------
  |  Branch (1257:9): [True: 200, False: 36.2k]
  ------------------
 1258|    200|      return slst;
 1259|  36.4k|  }
 1260|  70.4k|  size_t wl = 0;
 1261|       |
 1262|  70.4k|  std::string scw;
 1263|  70.4k|  std::vector<w_char> sunicw;
 1264|       |
 1265|       |  // input conversion
 1266|  70.4k|  RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : nullptr;
  ------------------
  |  Branch (1266:17): [True: 70.4k, False: 0]
  ------------------
 1267|  70.4k|  {
 1268|  70.4k|    std::string wspace;
 1269|       |
 1270|  70.4k|    bool convstatus = rl ? rl->conv(word, wspace) : false;
  ------------------
  |  Branch (1270:23): [True: 3.83k, False: 66.6k]
  ------------------
 1271|  70.4k|    if (convstatus) {
  ------------------
  |  Branch (1271:9): [True: 0, False: 70.4k]
  ------------------
 1272|       |      // the input conversion can grow the word without limit, so hold the
 1273|       |      // converted word to the same maximum length as the raw word
 1274|      0|      if (utf8 ? wspace.size() >= MAXWORDUTF8LEN : wspace.size() >= MAXWORDLEN)
  ------------------
  |  |   87|      0|#define MAXWORDUTF8LEN (MAXWORDLEN * 3)
  |  |  ------------------
  |  |  |  |   90|      0|#define MAXWORDLEN 100
  |  |  ------------------
  ------------------
                    if (utf8 ? wspace.size() >= MAXWORDUTF8LEN : wspace.size() >= MAXWORDLEN)
  ------------------
  |  |   90|      0|#define MAXWORDLEN 100
  ------------------
  |  Branch (1274:11): [True: 0, False: 0]
  |  Branch (1274:11): [True: 0, False: 0]
  ------------------
 1275|      0|        return slst;
 1276|      0|      wl = cleanword2(scw, sunicw, wspace, &captype, &abbv);
 1277|      0|    } else
 1278|  70.4k|      wl = cleanword2(scw, sunicw, word, &captype, &abbv);
 1279|       |
 1280|  70.4k|    if (wl == 0)
  ------------------
  |  Branch (1280:9): [True: 0, False: 70.4k]
  ------------------
 1281|      0|      return slst;
 1282|       |
 1283|  70.4k|#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
 1284|  70.4k|    if (wl > 32768)
  ------------------
  |  Branch (1284:9): [True: 0, False: 70.4k]
  ------------------
 1285|      0|      return slst;
 1286|  70.4k|#endif
 1287|  70.4k|  }
 1288|       |
 1289|  70.4k|  bool good = false;
 1290|       |
 1291|       |  // check capitalized form for FORCEUCASE
 1292|  70.4k|  if (pAMgr && captype == NOCAP && pAMgr->get_forceucase()) {
  ------------------
  |  |   88|   140k|#define NOCAP 0
  ------------------
  |  Branch (1292:7): [True: 70.4k, False: 0]
  |  Branch (1292:16): [True: 19.5k, False: 50.9k]
  |  Branch (1292:36): [True: 0, False: 19.5k]
  ------------------
 1293|      0|    int info = SPELL_ORIGCAP;
  ------------------
  |  |   86|      0|#define SPELL_ORIGCAP (1 << 5)
  ------------------
 1294|      0|    if (checkword(scw, &info, nullptr, suggest_start)) {
  ------------------
  |  Branch (1294:9): [True: 0, False: 0]
  ------------------
 1295|      0|      std::string form(std::move(scw));
 1296|      0|      mkinitcap(form);
 1297|      0|      slst.push_back(std::move(form));
 1298|      0|      return slst;
 1299|      0|    }
 1300|      0|  }
 1301|       |
 1302|  70.4k|  switch (captype) {
  ------------------
  |  Branch (1302:11): [True: 70.4k, False: 0]
  ------------------
 1303|  19.5k|    case NOCAP: {
  ------------------
  |  |   88|  19.5k|#define NOCAP 0
  ------------------
  |  Branch (1303:5): [True: 19.5k, False: 50.9k]
  ------------------
 1304|  19.5k|      good |= pSMgr->suggest(slst, scw, &onlycmpdsug);
 1305|  19.5k|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  19.5k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1305:11): [True: 0, False: 19.5k]
  ------------------
 1306|      0|          return slst;
 1307|  19.5k|      if (abbv) {
  ------------------
  |  Branch (1307:11): [True: 1.53k, False: 18.0k]
  ------------------
 1308|  1.53k|        std::string wspace(scw);
 1309|  1.53k|        wspace.push_back('.');
 1310|  1.53k|        good |= pSMgr->suggest(slst, wspace, &onlycmpdsug);
 1311|  1.53k|        if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  1.53k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1311:13): [True: 0, False: 1.53k]
  ------------------
 1312|      0|            return slst;
 1313|  1.53k|      }
 1314|  19.5k|      break;
 1315|  19.5k|    }
 1316|       |
 1317|  19.5k|    case INITCAP: {
  ------------------
  |  |   89|  11.2k|#define INITCAP 1
  ------------------
  |  Branch (1317:5): [True: 11.2k, False: 59.2k]
  ------------------
 1318|  11.2k|      capwords = true;
 1319|  11.2k|      good |= pSMgr->suggest(slst, scw, &onlycmpdsug);
 1320|  11.2k|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  11.2k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1320:11): [True: 0, False: 11.2k]
  ------------------
 1321|      0|          return slst;
 1322|  11.2k|      std::string wspace(scw);
 1323|  11.2k|      mkallsmall2(wspace, sunicw);
 1324|  11.2k|      good |= pSMgr->suggest(slst, wspace, &onlycmpdsug);
 1325|  11.2k|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  11.2k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1325:11): [True: 0, False: 11.2k]
  ------------------
 1326|      0|          return slst;
 1327|  11.2k|      break;
 1328|  11.2k|    }
 1329|  14.9k|    case HUHINITCAP:
  ------------------
  |  |   92|  14.9k|#define HUHINITCAP 4
  ------------------
  |  Branch (1329:5): [True: 14.9k, False: 55.5k]
  ------------------
 1330|  14.9k|      capwords = true;
 1331|       |      /* FALLTHROUGH */
 1332|  30.2k|    case HUHCAP: {
  ------------------
  |  |   91|  30.2k|#define HUHCAP 3
  ------------------
  |  Branch (1332:5): [True: 15.2k, False: 55.2k]
  ------------------
 1333|  30.2k|      good |= pSMgr->suggest(slst, scw, &onlycmpdsug);
 1334|  30.2k|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  30.2k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1334:11): [True: 0, False: 30.2k]
  ------------------
 1335|      0|          return slst;
 1336|       |      // something.The -> something. The
 1337|  30.2k|      size_t dot_pos = scw.find('.');
 1338|  30.2k|      if (dot_pos != std::string::npos) {
  ------------------
  |  Branch (1338:11): [True: 11.3k, False: 18.9k]
  ------------------
 1339|  11.3k|        std::string postdot = scw.substr(dot_pos + 1);
 1340|  11.3k|        int captype_;
 1341|  11.3k|        if (utf8) {
  ------------------
  |  Branch (1341:13): [True: 3.20k, False: 8.09k]
  ------------------
 1342|  3.20k|          std::vector<w_char> postdotu;
 1343|  3.20k|          u8_u16(postdotu, postdot);
 1344|  3.20k|          captype_ = get_captype_utf8(postdotu, langnum);
 1345|  8.09k|        } else {
 1346|  8.09k|          captype_ = get_captype(postdot, csconv);
 1347|  8.09k|        }
 1348|  11.3k|        if (captype_ == INITCAP) {
  ------------------
  |  |   89|  11.3k|#define INITCAP 1
  ------------------
  |  Branch (1348:13): [True: 6.02k, False: 5.27k]
  ------------------
 1349|  6.02k|          std::string str(scw);
 1350|  6.02k|          str.insert(dot_pos + 1, 1, ' ');
 1351|  6.02k|          insert_sug(slst, str);
 1352|  6.02k|        }
 1353|  11.3k|      }
 1354|       |
 1355|  30.2k|      std::string wspace;
 1356|       |
 1357|  30.2k|      if (captype == HUHINITCAP) {
  ------------------
  |  |   92|  30.2k|#define HUHINITCAP 4
  ------------------
  |  Branch (1357:11): [True: 14.9k, False: 15.2k]
  ------------------
 1358|       |        // TheOpenOffice.org -> The OpenOffice.org
 1359|  14.9k|        wspace = scw;
 1360|  14.9k|        mkinitsmall2(wspace, sunicw);
 1361|  14.9k|        good |= pSMgr->suggest(slst, wspace, &onlycmpdsug);
 1362|  14.9k|        if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  14.9k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1362:13): [True: 0, False: 14.9k]
  ------------------
 1363|      0|            return slst;
 1364|  14.9k|      }
 1365|  30.2k|      wspace = scw;
 1366|  30.2k|      mkallsmall2(wspace, sunicw);
 1367|  30.2k|      if (spell(wspace, spell_candidate_stack, nullptr, nullptr, suggest_start))
  ------------------
  |  Branch (1367:11): [True: 1.41k, False: 28.8k]
  ------------------
 1368|  1.41k|        insert_sug(slst, wspace);
 1369|  30.2k|      size_t prevns = slst.size();
 1370|  30.2k|      good |= pSMgr->suggest(slst, wspace, &onlycmpdsug);
 1371|  30.2k|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  30.2k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1371:11): [True: 0, False: 30.2k]
  ------------------
 1372|      0|          return slst;
 1373|  30.2k|      if (captype == HUHINITCAP) {
  ------------------
  |  |   92|  30.2k|#define HUHINITCAP 4
  ------------------
  |  Branch (1373:11): [True: 14.9k, False: 15.2k]
  ------------------
 1374|  14.9k|        mkinitcap2(wspace, sunicw);
 1375|  14.9k|        if (spell(wspace, spell_candidate_stack, nullptr, nullptr, suggest_start))
  ------------------
  |  Branch (1375:13): [True: 432, False: 14.5k]
  ------------------
 1376|    432|          insert_sug(slst, wspace);
 1377|  14.9k|        good |= pSMgr->suggest(slst, wspace, &onlycmpdsug);
 1378|  14.9k|        if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  14.9k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1378:13): [True: 0, False: 14.9k]
  ------------------
 1379|      0|            return slst;
 1380|  14.9k|      }
 1381|       |      // aNew -> "a New" (instead of "a new")
 1382|  30.8k|      for (size_t j = prevns; j < slst.size(); ++j) {
  ------------------
  |  Branch (1382:31): [True: 659, False: 30.2k]
  ------------------
 1383|    659|        const char* space = strchr(slst[j].c_str(), ' ');
 1384|    659|        if (space) {
  ------------------
  |  Branch (1384:13): [True: 391, False: 268]
  ------------------
 1385|    391|          size_t slen = strlen(space + 1);
 1386|       |          // different case after space (need capitalisation)
 1387|    391|          if ((slen < wl) && strcmp(scw.c_str() + wl - slen, space + 1) != 0) {
  ------------------
  |  Branch (1387:15): [True: 391, False: 0]
  |  Branch (1387:30): [True: 375, False: 16]
  ------------------
 1388|    375|            std::string first(slst[j].c_str(), space + 1);
 1389|    375|            std::string second(space + 1);
 1390|    375|            std::vector<w_char> w;
 1391|    375|            if (utf8)
  ------------------
  |  Branch (1391:17): [True: 112, False: 263]
  ------------------
 1392|    112|              u8_u16(w, second);
 1393|    375|            mkinitcap2(second, w);
 1394|       |            // set as first suggestion
 1395|    375|            slst.erase(slst.begin() + j);
 1396|    375|            slst.insert(slst.begin(), first + second);
 1397|    375|          }
 1398|    391|        }
 1399|    659|      }
 1400|  30.2k|      break;
 1401|  30.2k|    }
 1402|       |
 1403|  9.41k|    case ALLCAP: {
  ------------------
  |  |   90|  9.41k|#define ALLCAP 2
  ------------------
  |  Branch (1403:5): [True: 9.41k, False: 61.0k]
  ------------------
 1404|  9.41k|      std::string wspace(scw);
 1405|  9.41k|      mkallsmall2(wspace, sunicw);
 1406|  9.41k|      good |= pSMgr->suggest(slst, wspace, &onlycmpdsug);
 1407|  9.41k|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  9.41k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1407:11): [True: 0, False: 9.41k]
  ------------------
 1408|      0|          return slst;
 1409|  9.41k|      if (pAMgr && pAMgr->get_keepcase() && spell(wspace, spell_candidate_stack, nullptr, nullptr, suggest_start))
  ------------------
  |  Branch (1409:11): [True: 9.41k, False: 0]
  |  Branch (1409:20): [True: 375, False: 9.04k]
  |  Branch (1409:45): [True: 0, False: 375]
  ------------------
 1410|      0|        insert_sug(slst, wspace);
 1411|  9.41k|      mkinitcap2(wspace, sunicw);
 1412|  9.41k|      good |= pSMgr->suggest(slst, wspace, &onlycmpdsug);
 1413|  9.41k|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  9.41k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1413:11): [True: 0, False: 9.41k]
  ------------------
 1414|      0|          return slst;
 1415|  9.41k|      for (auto& j : slst) {
  ------------------
  |  Branch (1415:20): [True: 402, False: 9.41k]
  ------------------
 1416|    402|        mkallcap(j);
 1417|    402|        if (pAMgr && pAMgr->get_checksharps()) {
  ------------------
  |  Branch (1417:13): [True: 402, False: 0]
  |  Branch (1417:22): [True: 0, False: 402]
  ------------------
 1418|      0|          if (utf8) {
  ------------------
  |  Branch (1418:15): [True: 0, False: 0]
  ------------------
 1419|      0|            mystrrep(j, "\xC3\x9F", "SS");
 1420|      0|          } else {
 1421|      0|            mystrrep(j, "\xDF", "SS");
 1422|      0|          }
 1423|      0|        }
 1424|    402|      }
 1425|  9.41k|      break;
 1426|  9.41k|    }
 1427|  70.4k|  }
 1428|       |
 1429|       |  // LANG_hu section: replace '-' with ' ' in Hungarian
 1430|  70.4k|  if (langnum == LANG_hu) {
  ------------------
  |  Branch (1430:7): [True: 3.91k, False: 66.5k]
  ------------------
 1431|  3.91k|    for (auto& j : slst) {
  ------------------
  |  Branch (1431:18): [True: 400, False: 3.91k]
  ------------------
 1432|    400|      size_t pos = j.find('-');
 1433|    400|      if (pos != std::string::npos) {
  ------------------
  |  Branch (1433:11): [True: 165, False: 235]
  ------------------
 1434|    165|        int info = 0;
 1435|    165|        std::string w(j.substr(0, pos));
 1436|    165|        w.append(j.substr(pos + 1));
 1437|    165|        (void)spell(w, spell_candidate_stack, &info, nullptr, suggest_start);
 1438|    165|        if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
  ------------------
  |  |   81|    165|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
                      if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
  ------------------
  |  |   82|      1|#define SPELL_FORBIDDEN (1 << 1)
  ------------------
  |  Branch (1438:13): [True: 1, False: 164]
  |  Branch (1438:40): [True: 0, False: 1]
  ------------------
 1439|      0|          j[pos] = ' ';
 1440|      0|        } else
 1441|    165|          j[pos] = '-';
 1442|    165|      }
 1443|    400|    }
 1444|  3.91k|  }
 1445|       |  // END OF LANG_hu section
 1446|       |  // try ngram approach since found nothing good suggestion
 1447|  70.4k|  if (!good && pAMgr && (slst.empty() || onlycmpdsug) && (pAMgr->get_maxngramsugs() != 0)) {
  ------------------
  |  Branch (1447:7): [True: 70.4k, False: 59]
  |  Branch (1447:16): [True: 70.4k, False: 0]
  |  Branch (1447:26): [True: 60.3k, False: 10.0k]
  |  Branch (1447:42): [True: 9.87k, False: 194]
  |  Branch (1447:58): [True: 62.5k, False: 7.70k]
  ------------------
 1448|  62.5k|    switch (captype) {
  ------------------
  |  Branch (1448:13): [True: 62.5k, False: 0]
  ------------------
 1449|  16.6k|      case NOCAP: {
  ------------------
  |  |   88|  16.6k|#define NOCAP 0
  ------------------
  |  Branch (1449:7): [True: 16.6k, False: 45.8k]
  ------------------
 1450|  16.6k|        pSMgr->ngsuggest(slst, scw.c_str(), m_HMgrs, NOCAP);
  ------------------
  |  |   88|  16.6k|#define NOCAP 0
  ------------------
 1451|  16.6k|        if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  16.6k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1451:13): [True: 0, False: 16.6k]
  ------------------
 1452|      0|            return slst;
 1453|  16.6k|        break;
 1454|  16.6k|      }
 1455|       |      /* FALLTHROUGH */
 1456|  16.6k|      case HUHINITCAP:
  ------------------
  |  |   92|  14.1k|#define HUHINITCAP 4
  ------------------
  |  Branch (1456:7): [True: 14.1k, False: 48.3k]
  ------------------
 1457|  14.1k|        capwords = true;
 1458|       |      /* FALLTHROUGH */
 1459|  28.1k|      case HUHCAP: {
  ------------------
  |  |   91|  28.1k|#define HUHCAP 3
  ------------------
  |  Branch (1459:7): [True: 14.0k, False: 48.5k]
  ------------------
 1460|  28.1k|        std::string wspace(scw);
 1461|  28.1k|        mkallsmall2(wspace, sunicw);
 1462|  28.1k|        pSMgr->ngsuggest(slst, wspace.c_str(), m_HMgrs, HUHCAP);
  ------------------
  |  |   91|  28.1k|#define HUHCAP 3
  ------------------
 1463|  28.1k|        if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  28.1k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1463:13): [True: 0, False: 28.1k]
  ------------------
 1464|      0|            return slst;
 1465|  28.1k|        break;
 1466|  28.1k|      }
 1467|  28.1k|      case INITCAP: {
  ------------------
  |  |   89|  9.58k|#define INITCAP 1
  ------------------
  |  Branch (1467:7): [True: 9.58k, False: 52.9k]
  ------------------
 1468|  9.58k|        capwords = true;
 1469|  9.58k|        std::string wspace(scw);
 1470|  9.58k|        mkallsmall2(wspace, sunicw);
 1471|  9.58k|        pSMgr->ngsuggest(slst, wspace.c_str(), m_HMgrs, INITCAP);
  ------------------
  |  |   89|  9.58k|#define INITCAP 1
  ------------------
 1472|  9.58k|        if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  9.58k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1472:13): [True: 0, False: 9.58k]
  ------------------
 1473|      0|            return slst;
 1474|  9.58k|        break;
 1475|  9.58k|      }
 1476|  9.58k|      case ALLCAP: {
  ------------------
  |  |   90|  8.14k|#define ALLCAP 2
  ------------------
  |  Branch (1476:7): [True: 8.14k, False: 54.3k]
  ------------------
 1477|  8.14k|        std::string wspace(scw);
 1478|  8.14k|        mkallsmall2(wspace, sunicw);
 1479|  8.14k|        size_t oldns = slst.size();
 1480|  8.14k|        pSMgr->ngsuggest(slst, wspace.c_str(), m_HMgrs, ALLCAP);
  ------------------
  |  |   90|  8.14k|#define ALLCAP 2
  ------------------
 1481|  8.14k|        if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  8.14k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1481:13): [True: 0, False: 8.14k]
  ------------------
 1482|      0|            return slst;
 1483|  10.8k|        for (size_t j = oldns; j < slst.size(); ++j) {
  ------------------
  |  Branch (1483:32): [True: 2.70k, False: 8.14k]
  ------------------
 1484|  2.70k|          mkallcap(slst[j]);
 1485|  2.70k|        }
 1486|  8.14k|        break;
 1487|  8.14k|      }
 1488|  62.5k|    }
 1489|  62.5k|  }
 1490|       |
 1491|       |  // try dash suggestion (Afo-American -> Afro-American)
 1492|       |  // Note: LibreOffice was modified to treat dashes as word
 1493|       |  // characters to check "scot-free" etc. word forms, but
 1494|       |  // we need to handle suggestions for "Afo-American", etc.,
 1495|       |  // while "Afro-American" is missing from the dictionary.
 1496|       |  // TODO avoid possible overgeneration
 1497|  70.4k|  size_t dash_pos = scw.find('-');
 1498|  70.4k|  if (dash_pos != std::string::npos) {
  ------------------
  |  Branch (1498:7): [True: 35.5k, False: 34.9k]
  ------------------
 1499|  35.5k|    int nodashsug = 1;
 1500|  46.2k|    for (size_t j = 0; j < slst.size() && nodashsug == 1; ++j) {
  ------------------
  |  Branch (1500:24): [True: 11.4k, False: 34.8k]
  |  Branch (1500:43): [True: 10.7k, False: 692]
  ------------------
 1501|  10.7k|      if (slst[j].find('-') != std::string::npos)
  ------------------
  |  Branch (1501:11): [True: 6.31k, False: 4.46k]
  ------------------
 1502|  6.31k|        nodashsug = 0;
 1503|  10.7k|    }
 1504|       |
 1505|  35.5k|    size_t prev_pos = 0;
 1506|  35.5k|    bool last = false;
 1507|       |
 1508|   105k|    while (!good && nodashsug && !last) {
  ------------------
  |  Branch (1508:12): [True: 105k, False: 27]
  |  Branch (1508:21): [True: 71.0k, False: 34.8k]
  |  Branch (1508:34): [True: 70.3k, False: 634]
  ------------------
 1509|  70.3k|      if (dash_pos == scw.size())
  ------------------
  |  Branch (1509:11): [True: 5.15k, False: 65.2k]
  ------------------
 1510|  5.15k|        last = true;
 1511|  70.3k|      std::string chunk = scw.substr(prev_pos, dash_pos - prev_pos);
 1512|  70.3k|      if (chunk != word && !spell(chunk, spell_candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (1512:11): [True: 70.3k, False: 0]
  |  Branch (1512:28): [True: 28.5k, False: 41.8k]
  ------------------
 1513|  28.5k|        std::vector<std::string> nlst = suggest(chunk, suggest_candidate_stack, suggest_start);
 1514|  28.5k|        if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|  28.5k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1514:13): [True: 0, False: 28.5k]
  ------------------
 1515|      0|            return slst;
 1516|  39.1k|        for (auto j = nlst.rbegin(); j != nlst.rend(); ++j) {
  ------------------
  |  Branch (1516:38): [True: 10.6k, False: 28.5k]
  ------------------
 1517|  10.6k|          std::string wspace = scw.substr(0, prev_pos);
 1518|  10.6k|          wspace.append(*j);
 1519|  10.6k|          if (!last) {
  ------------------
  |  Branch (1519:15): [True: 9.06k, False: 1.55k]
  ------------------
 1520|  9.06k|            wspace.append("-");
 1521|  9.06k|            wspace.append(scw.substr(dash_pos + 1));
 1522|  9.06k|          }
 1523|  10.6k|          int info = 0;
 1524|  10.6k|          if (pAMgr && pAMgr->get_forbiddenword())
  ------------------
  |  Branch (1524:15): [True: 10.6k, False: 0]
  |  Branch (1524:24): [True: 10.6k, False: 0]
  ------------------
 1525|  10.6k|            checkword(wspace, &info, nullptr, suggest_start);
 1526|  10.6k|          if (!(info & SPELL_FORBIDDEN))
  ------------------
  |  |   82|  10.6k|#define SPELL_FORBIDDEN (1 << 1)
  ------------------
  |  Branch (1526:15): [True: 10.6k, False: 0]
  ------------------
 1527|  10.6k|            insert_sug(slst, wspace);
 1528|  10.6k|        }
 1529|  28.5k|        nodashsug = 0;
 1530|  28.5k|      }
 1531|  70.3k|      if (!last) {
  ------------------
  |  Branch (1531:11): [True: 65.2k, False: 5.15k]
  ------------------
 1532|  65.2k|        prev_pos = dash_pos + 1;
 1533|  65.2k|        dash_pos = scw.find('-', prev_pos);
 1534|  65.2k|      }
 1535|  70.3k|      if (dash_pos == std::string::npos)
  ------------------
  |  Branch (1535:11): [True: 12.0k, False: 58.3k]
  ------------------
 1536|  12.0k|        dash_pos = scw.size();
 1537|  70.3k|    }
 1538|  35.5k|  }
 1539|  70.4k|  return slst;
 1540|  70.4k|}
_ZN12HunspellImpl4stemERKNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEE:
 1546|    987|std::vector<std::string> HunspellImpl::stem(const std::vector<std::string>& desc) {
 1547|    987|  std::vector<std::string> slst;
 1548|       |
 1549|    987|  std::string result2;
 1550|    987|  if (desc.empty())
  ------------------
  |  Branch (1550:7): [True: 915, False: 72]
  ------------------
 1551|    915|    return slst;
 1552|     82|  for (const auto& i : desc) {
  ------------------
  |  Branch (1552:22): [True: 82, False: 72]
  ------------------
 1553|     82|    if (result2.size() > MAXMORPHRESULT)
  ------------------
  |  |  114|     82|#define MAXMORPHRESULT (4 * 1024 * 1024)
  ------------------
  |  Branch (1553:9): [True: 0, False: 82]
  ------------------
 1554|      0|      break;
 1555|       |
 1556|     82|    std::string result;
 1557|       |
 1558|       |    // add compound word parts (except the last one)
 1559|     82|    std::string tok(i, append_compound_parts(i, result));
 1560|     82|    size_t alt = 0;
 1561|     82|    while ((alt = tok.find(" | ", alt)) != std::string::npos) {
  ------------------
  |  Branch (1561:12): [True: 0, False: 82]
  ------------------
 1562|      0|      tok[alt + 1] = MSEP_ALT;
  ------------------
  |  |  119|      0|#define MSEP_ALT '\v'
  ------------------
 1563|      0|    }
 1564|     82|    std::vector<std::string> pl = line_tok(tok, MSEP_ALT);
  ------------------
  |  |  119|     82|#define MSEP_ALT '\v'
  ------------------
 1565|     82|    for (auto& k : pl) {
  ------------------
  |  Branch (1565:18): [True: 82, False: 82]
  ------------------
 1566|     82|      if (result2.size() > MAXMORPHRESULT)
  ------------------
  |  |  114|     82|#define MAXMORPHRESULT (4 * 1024 * 1024)
  ------------------
  |  Branch (1566:11): [True: 0, False: 82]
  ------------------
 1567|      0|        break;
 1568|       |
 1569|       |      // add derivational suffixes
 1570|     82|      if (k.find(MORPH_DERI_SFX) != std::string::npos) {
  ------------------
  |  |  105|     82|#define MORPH_DERI_SFX "ds:"
  ------------------
  |  Branch (1570:11): [True: 0, False: 82]
  ------------------
 1571|       |        // remove inflectional suffixes
 1572|      0|        const size_t is = k.find(MORPH_INFL_SFX);
  ------------------
  |  |  106|      0|#define MORPH_INFL_SFX "is:"
  ------------------
 1573|      0|        if (is != std::string::npos)
  ------------------
  |  Branch (1573:13): [True: 0, False: 0]
  ------------------
 1574|      0|          k.resize(is);
 1575|      0|        std::vector<std::string> singlepl;
 1576|      0|        singlepl.push_back(k);
 1577|      0|        std::string sg = pSMgr->suggest_gen(singlepl, k);
 1578|      0|        if (!sg.empty()) {
  ------------------
  |  Branch (1578:13): [True: 0, False: 0]
  ------------------
 1579|      0|          std::vector<std::string> gen = line_tok(sg, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 1580|      0|          for (auto& j : gen) {
  ------------------
  |  Branch (1580:24): [True: 0, False: 0]
  ------------------
 1581|      0|            result2.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 1582|      0|            result2.append(result);
 1583|      0|            result2.append(j);
 1584|      0|          }
 1585|      0|        }
 1586|     82|      } else {
 1587|     82|        result2.push_back(MSEP_REC);
  ------------------
  |  |  118|     82|#define MSEP_REC '\n'
  ------------------
 1588|     82|        result2.append(result);
 1589|     82|        if (k.find(MORPH_SURF_PFX) != std::string::npos) {
  ------------------
  |  |  108|     82|#define MORPH_SURF_PFX "sp:"
  ------------------
  |  Branch (1589:13): [True: 0, False: 82]
  ------------------
 1590|      0|          std::string field;
 1591|      0|          copy_field(field, k, MORPH_SURF_PFX);
  ------------------
  |  |  108|      0|#define MORPH_SURF_PFX "sp:"
  ------------------
 1592|      0|          result2.append(field);
 1593|      0|        }
 1594|     82|        std::string field;
 1595|     82|        copy_field(field, k, MORPH_STEM);
  ------------------
  |  |   99|     82|#define MORPH_STEM "st:"
  ------------------
 1596|     82|        result2.append(field);
 1597|     82|      }
 1598|     82|    }
 1599|     82|  }
 1600|     72|  slst = line_tok(result2, MSEP_REC);
  ------------------
  |  |  118|     72|#define MSEP_REC '\n'
  ------------------
 1601|     72|  uniqlist(slst);
 1602|     72|  return slst;
 1603|    987|}
_ZN12HunspellImpl4stemERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1605|    987|std::vector<std::string> HunspellImpl::stem(const std::string& word) {
 1606|    987|  return stem(analyze(word));
 1607|    987|}
_ZN12HunspellImpl9mkinitcapERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1617|  18.4k|void HunspellImpl::mkinitcap(std::string& u8) {
 1618|  18.4k|  if (utf8) {
  ------------------
  |  Branch (1618:7): [True: 5.72k, False: 12.7k]
  ------------------
 1619|  5.72k|    std::vector<w_char> u16;
 1620|  5.72k|    u8_u16(u16, u8);
 1621|  5.72k|    ::mkinitcap_utf(u16, langnum);
 1622|  5.72k|    u16_u8(u8, u16);
 1623|  12.7k|  } else {
 1624|  12.7k|    ::mkinitcap(u8, csconv);
 1625|  12.7k|  }
 1626|  18.4k|}
_ZN12HunspellImpl10mkinitcap2ERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERNS0_6vectorI6w_charNS4_IS9_EEEE:
 1628|  2.15M|size_t HunspellImpl::mkinitcap2(std::string& u8, std::vector<w_char>& u16) {
 1629|  2.15M|  if (utf8) {
  ------------------
  |  Branch (1629:7): [True: 462k, False: 1.69M]
  ------------------
 1630|   462k|    ::mkinitcap_utf(u16, langnum);
 1631|   462k|    u16_u8(u8, u16);
 1632|  1.69M|  } else {
 1633|  1.69M|    ::mkinitcap(u8, csconv);
 1634|  1.69M|  }
 1635|  2.15M|  return u8.size();
 1636|  2.15M|}
_ZN12HunspellImpl12mkinitsmall2ERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERNS0_6vectorI6w_charNS4_IS9_EEEE:
 1638|   357k|size_t HunspellImpl::mkinitsmall2(std::string& u8, std::vector<w_char>& u16) {
 1639|   357k|  if (utf8) {
  ------------------
  |  Branch (1639:7): [True: 41.1k, False: 315k]
  ------------------
 1640|  41.1k|    ::mkinitsmall_utf(u16, langnum);
 1641|  41.1k|    u16_u8(u8, u16);
 1642|   315k|  } else {
 1643|   315k|    ::mkinitsmall(u8, csconv);
 1644|   315k|  }
 1645|   357k|  return u8.size();
 1646|   357k|}
_ZN12HunspellImpl3addERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1648|  5.39k|int HunspellImpl::add(const std::string& word) {
 1649|  5.39k|  if (!m_HMgrs.empty()) {
  ------------------
  |  Branch (1649:7): [True: 5.39k, False: 0]
  ------------------
 1650|  5.39k|    std::string converted;
 1651|  5.39k|    input_conv(word, converted);
 1652|  5.39k|    return m_HMgrs[0]->add(converted);
 1653|  5.39k|  }
 1654|      0|  return 0;
 1655|  5.39k|}
_ZN12HunspellImpl14add_with_affixERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_:
 1666|  2.05k|int HunspellImpl::add_with_affix(const std::string& word, const std::string& example) {
 1667|  2.05k|  if (!m_HMgrs.empty()) {
  ------------------
  |  Branch (1667:7): [True: 2.05k, False: 0]
  ------------------
 1668|  2.05k|    std::string converted, converted_example;
 1669|  2.05k|    input_conv(word, converted);
 1670|  2.05k|    input_conv(example, converted_example);
 1671|  2.05k|    return m_HMgrs[0]->add_with_affix(converted, converted_example);
 1672|  2.05k|  }
 1673|      0|  return 0;
 1674|  2.05k|}
_ZN12HunspellImpl10cat_resultERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERKS6_:
 1696|   408k|void HunspellImpl::cat_result(std::string& result, const std::string& st) {
 1697|   408k|  if (result.size() > MAXMORPHRESULT)
  ------------------
  |  |  114|   408k|#define MAXMORPHRESULT (4 * 1024 * 1024)
  ------------------
  |  Branch (1697:7): [True: 0, False: 408k]
  ------------------
 1698|      0|    return;
 1699|   408k|  if (!st.empty()) {
  ------------------
  |  Branch (1699:7): [True: 1.76k, False: 406k]
  ------------------
 1700|  1.76k|    if (!result.empty())
  ------------------
  |  Branch (1700:9): [True: 10, False: 1.75k]
  ------------------
 1701|     10|      result.append("\n");
 1702|  1.76k|    result.append(st);
 1703|  1.76k|  }
 1704|   408k|}
_ZN12HunspellImpl7analyzeERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1706|  8.30k|std::vector<std::string> HunspellImpl::analyze(const std::string& word) {
 1707|  8.30k|  std::vector<std::string> slst = analyze_internal(word);
 1708|       |  // output conversion
 1709|  8.30k|  RepList* rl = (pAMgr) ? pAMgr->get_oconvtable() : nullptr;
  ------------------
  |  Branch (1709:17): [True: 8.30k, False: 0]
  ------------------
 1710|  8.30k|  if (rl) {
  ------------------
  |  Branch (1710:7): [True: 434, False: 7.87k]
  ------------------
 1711|       |    // the output conversion can multiply the length of every line, so hold the
 1712|       |    // converted analysis to the same ceiling as the raw analysis
 1713|    434|    size_t total = 0;
 1714|    434|    size_t i = 0;
 1715|    468|    for (; i < slst.size(); ++i) {
  ------------------
  |  Branch (1715:12): [True: 34, False: 434]
  ------------------
 1716|     34|      std::string wspace;
 1717|     34|      if (rl->conv(slst[i], wspace, MAXMORPHRESULT - total)) {
  ------------------
  |  |  114|     34|#define MAXMORPHRESULT (4 * 1024 * 1024)
  ------------------
  |  Branch (1717:11): [True: 0, False: 34]
  ------------------
 1718|      0|        slst[i] = std::move(wspace);
 1719|      0|      }
 1720|     34|      if (slst[i].size() > MAXMORPHRESULT - total)
  ------------------
  |  |  114|     34|#define MAXMORPHRESULT (4 * 1024 * 1024)
  ------------------
  |  Branch (1720:11): [True: 0, False: 34]
  ------------------
 1721|      0|        break;
 1722|     34|      total += slst[i].size();
 1723|     34|    }
 1724|    434|    slst.resize(i);
 1725|    434|  }
 1726|  8.30k|  return slst;
 1727|  8.30k|}
_ZN12HunspellImpl16analyze_internalERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1729|  8.30k|std::vector<std::string> HunspellImpl::analyze_internal(const std::string& word) {
 1730|  8.30k|  std::vector<std::string> candidate_stack, slst;
 1731|  8.30k|  if (!pSMgr || m_HMgrs.empty())
  ------------------
  |  Branch (1731:7): [True: 0, False: 8.30k]
  |  Branch (1731:17): [True: 0, False: 8.30k]
  ------------------
 1732|      0|    return slst;
 1733|  8.30k|  if (utf8) {
  ------------------
  |  Branch (1733:7): [True: 3.92k, False: 4.38k]
  ------------------
 1734|  3.92k|    if (word.size() >= MAXWORDUTF8LEN)
  ------------------
  |  |   87|  3.92k|#define MAXWORDUTF8LEN (MAXWORDLEN * 3)
  |  |  ------------------
  |  |  |  |   90|  3.92k|#define MAXWORDLEN 100
  |  |  ------------------
  ------------------
  |  Branch (1734:9): [True: 351, False: 3.56k]
  ------------------
 1735|    351|      return slst;
 1736|  4.38k|  } else {
 1737|  4.38k|    if (word.size() >= MAXWORDLEN)
  ------------------
  |  |   90|  4.38k|#define MAXWORDLEN 100
  ------------------
  |  Branch (1737:9): [True: 580, False: 3.80k]
  ------------------
 1738|    580|      return slst;
 1739|  4.38k|  }
 1740|  7.37k|  int captype = NOCAP;
  ------------------
  |  |   88|  7.37k|#define NOCAP 0
  ------------------
 1741|  7.37k|  size_t abbv = 0;
 1742|  7.37k|  size_t wl = 0;
 1743|       |
 1744|  7.37k|  std::string scw;
 1745|  7.37k|  std::vector<w_char> sunicw;
 1746|       |
 1747|       |  // input conversion
 1748|  7.37k|  RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : nullptr;
  ------------------
  |  Branch (1748:17): [True: 7.37k, False: 0]
  ------------------
 1749|  7.37k|  {
 1750|  7.37k|    std::string wspace;
 1751|       |
 1752|  7.37k|    bool convstatus = rl ? rl->conv(word, wspace) : false;
  ------------------
  |  Branch (1752:23): [True: 395, False: 6.98k]
  ------------------
 1753|  7.37k|    if (convstatus) {
  ------------------
  |  Branch (1753:9): [True: 0, False: 7.37k]
  ------------------
 1754|       |      // the input conversion can grow the word without limit, so hold the
 1755|       |      // converted word to the same maximum length as the raw word
 1756|      0|      if (utf8 ? wspace.size() >= MAXWORDUTF8LEN : wspace.size() >= MAXWORDLEN)
  ------------------
  |  |   87|      0|#define MAXWORDUTF8LEN (MAXWORDLEN * 3)
  |  |  ------------------
  |  |  |  |   90|      0|#define MAXWORDLEN 100
  |  |  ------------------
  ------------------
                    if (utf8 ? wspace.size() >= MAXWORDUTF8LEN : wspace.size() >= MAXWORDLEN)
  ------------------
  |  |   90|      0|#define MAXWORDLEN 100
  ------------------
  |  Branch (1756:11): [True: 0, False: 0]
  |  Branch (1756:11): [True: 0, False: 0]
  ------------------
 1757|      0|        return slst;
 1758|      0|      wl = cleanword2(scw, sunicw, wspace, &captype, &abbv);
 1759|      0|    } else
 1760|  7.37k|      wl = cleanword2(scw, sunicw, word, &captype, &abbv);
 1761|       |
 1762|  7.37k|#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
 1763|  7.37k|    if (wl > 32768)
  ------------------
  |  Branch (1763:9): [True: 0, False: 7.37k]
  ------------------
 1764|      0|      return slst;
 1765|  7.37k|#endif
 1766|  7.37k|  }
 1767|       |
 1768|  7.37k|  if (wl == 0) {
  ------------------
  |  Branch (1768:7): [True: 482, False: 6.89k]
  ------------------
 1769|    482|    if (abbv) {
  ------------------
  |  Branch (1769:9): [True: 294, False: 188]
  ------------------
 1770|    294|      scw.clear();
 1771|  7.19k|      for (wl = 0; wl < abbv; wl++)
  ------------------
  |  Branch (1771:20): [True: 6.90k, False: 294]
  ------------------
 1772|  6.90k|        scw.push_back('.');
 1773|    294|      abbv = 0;
 1774|    294|    } else
 1775|    188|      return slst;
 1776|    482|  }
 1777|       |
 1778|  7.19k|  std::string result;
 1779|       |
 1780|  7.19k|  auto suggest_start = std::chrono::steady_clock::now();
 1781|       |
 1782|  7.19k|  size_t n = 0;
 1783|       |  // test numbers
 1784|       |  // LANG_hu section: set dash information for suggestions
 1785|  7.19k|  if (langnum == LANG_hu) {
  ------------------
  |  Branch (1785:7): [True: 385, False: 6.80k]
  ------------------
 1786|    385|    size_t n2 = 0;
 1787|    385|    size_t n3 = 0;
 1788|       |
 1789|    519|    while ((n < wl) && (((scw[n] <= '9') && (scw[n] >= '0')) ||
  ------------------
  |  Branch (1789:12): [True: 493, False: 26]
  |  Branch (1789:26): [True: 273, False: 220]
  |  Branch (1789:45): [True: 134, False: 139]
  ------------------
 1790|    359|                        (((scw[n] == '.') || (scw[n] == ',')) && (n > 0)))) {
  ------------------
  |  Branch (1790:27): [True: 31, False: 328]
  |  Branch (1790:46): [True: 0, False: 328]
  |  Branch (1790:66): [True: 0, False: 31]
  ------------------
 1791|    134|      n++;
 1792|    134|      if ((scw[n] == '.') || (scw[n] == ',')) {
  ------------------
  |  Branch (1792:11): [True: 0, False: 134]
  |  Branch (1792:30): [True: 0, False: 134]
  ------------------
 1793|      0|        if (((n2 == 0) && (n > 3)) ||
  ------------------
  |  Branch (1793:14): [True: 0, False: 0]
  |  Branch (1793:27): [True: 0, False: 0]
  ------------------
 1794|      0|            ((n2 > 0) && ((scw[n - 1] == '.') || (scw[n - 1] == ','))))
  ------------------
  |  Branch (1794:14): [True: 0, False: 0]
  |  Branch (1794:27): [True: 0, False: 0]
  |  Branch (1794:50): [True: 0, False: 0]
  ------------------
 1795|      0|          break;
 1796|      0|        n2++;
 1797|      0|        n3 = n;
 1798|      0|      }
 1799|    134|    }
 1800|       |
 1801|    385|    if ((n == wl) && (n3 > 0) && (n - n3 > 3))
  ------------------
  |  Branch (1801:9): [True: 26, False: 359]
  |  Branch (1801:22): [True: 0, False: 26]
  |  Branch (1801:34): [True: 0, False: 0]
  ------------------
 1802|      0|      return slst;
 1803|    385|    if ((n == wl) || ((n > 0) && ((scw[n] == '%') || (scw[n] == '\xB0')) && checkword(scw.substr(n), nullptr, nullptr, suggest_start))) {
  ------------------
  |  Branch (1803:9): [True: 26, False: 359]
  |  Branch (1803:9): [True: 26, False: 359]
  |  Branch (1803:23): [True: 13, False: 346]
  |  Branch (1803:35): [True: 0, False: 13]
  |  Branch (1803:54): [True: 0, False: 13]
  |  Branch (1803:77): [True: 0, False: 0]
  ------------------
 1804|     26|      result.append(scw);
 1805|     26|      result.resize(n - 1);
 1806|     26|      if (n == wl)
  ------------------
  |  Branch (1806:11): [True: 26, False: 0]
  ------------------
 1807|     26|        cat_result(result, pSMgr->suggest_morph(scw.substr(n - 1)));
 1808|      0|      else {
 1809|      0|        std::string chunk = scw.substr(n - 1, 1);
 1810|      0|        cat_result(result, pSMgr->suggest_morph(chunk));
 1811|      0|        result.push_back('+');  // XXX SPEC. MORPHCODE
 1812|      0|        cat_result(result, pSMgr->suggest_morph(scw.substr(n)));
 1813|      0|      }
 1814|     26|      return line_tok(result, MSEP_REC);
  ------------------
  |  |  118|     26|#define MSEP_REC '\n'
  ------------------
 1815|     26|    }
 1816|    385|  }
 1817|       |  // END OF LANG_hu section
 1818|       |
 1819|  7.16k|  switch (captype) {
  ------------------
  |  Branch (1819:11): [True: 7.16k, False: 0]
  ------------------
 1820|    371|    case HUHCAP:
  ------------------
  |  |   91|    371|#define HUHCAP 3
  ------------------
  |  Branch (1820:5): [True: 371, False: 6.79k]
  ------------------
 1821|  1.11k|    case HUHINITCAP:
  ------------------
  |  |   92|  1.11k|#define HUHINITCAP 4
  ------------------
  |  Branch (1821:5): [True: 740, False: 6.42k]
  ------------------
 1822|  4.30k|    case NOCAP: {
  ------------------
  |  |   88|  4.30k|#define NOCAP 0
  ------------------
  |  Branch (1822:5): [True: 3.19k, False: 3.96k]
  ------------------
 1823|  4.30k|      cat_result(result, pSMgr->suggest_morph(scw));
 1824|  4.30k|      if (abbv) {
  ------------------
  |  Branch (1824:11): [True: 268, False: 4.03k]
  ------------------
 1825|    268|        std::string u8buffer(scw);
 1826|    268|        u8buffer.push_back('.');
 1827|    268|        cat_result(result, pSMgr->suggest_morph(u8buffer));
 1828|    268|      }
 1829|  4.30k|      break;
 1830|  1.11k|    }
 1831|  1.92k|    case INITCAP: {
  ------------------
  |  |   89|  1.92k|#define INITCAP 1
  ------------------
  |  Branch (1831:5): [True: 1.92k, False: 5.23k]
  ------------------
 1832|  1.92k|      mkallsmall2(scw, sunicw);
 1833|  1.92k|      std::string u8buffer(scw);
 1834|  1.92k|      mkinitcap2(scw, sunicw);
 1835|  1.92k|      cat_result(result, pSMgr->suggest_morph(u8buffer));
 1836|  1.92k|      cat_result(result, pSMgr->suggest_morph(scw));
 1837|  1.92k|      if (abbv) {
  ------------------
  |  Branch (1837:11): [True: 170, False: 1.75k]
  ------------------
 1838|    170|        u8buffer.push_back('.');
 1839|    170|        cat_result(result, pSMgr->suggest_morph(u8buffer));
 1840|       |
 1841|    170|        u8buffer = scw;
 1842|    170|        u8buffer.push_back('.');
 1843|       |
 1844|    170|        cat_result(result, pSMgr->suggest_morph(u8buffer));
 1845|    170|      }
 1846|  1.92k|      break;
 1847|  1.11k|    }
 1848|    928|    case ALLCAP: {
  ------------------
  |  |   90|    928|#define ALLCAP 2
  ------------------
  |  Branch (1848:5): [True: 928, False: 6.23k]
  ------------------
 1849|    928|      cat_result(result, pSMgr->suggest_morph(scw));
 1850|    928|      if (abbv) {
  ------------------
  |  Branch (1850:11): [True: 112, False: 816]
  ------------------
 1851|    112|        std::string u8buffer(scw);
 1852|    112|        u8buffer.push_back('.');
 1853|    112|        cat_result(result, pSMgr->suggest_morph(u8buffer));
 1854|    112|      }
 1855|    928|      mkallsmall2(scw, sunicw);
 1856|    928|      std::string u8buffer(scw);
 1857|    928|      mkinitcap2(scw, sunicw);
 1858|       |
 1859|    928|      cat_result(result, pSMgr->suggest_morph(u8buffer));
 1860|    928|      cat_result(result, pSMgr->suggest_morph(scw));
 1861|    928|      if (abbv) {
  ------------------
  |  Branch (1861:11): [True: 112, False: 816]
  ------------------
 1862|    112|        u8buffer.push_back('.');
 1863|    112|        cat_result(result, pSMgr->suggest_morph(u8buffer));
 1864|       |
 1865|    112|        u8buffer = scw;
 1866|    112|        u8buffer.push_back('.');
 1867|       |
 1868|    112|        cat_result(result, pSMgr->suggest_morph(u8buffer));
 1869|    112|      }
 1870|    928|      break;
 1871|  1.11k|    }
 1872|  7.16k|  }
 1873|       |
 1874|  7.16k|  if (!result.empty()) {
  ------------------
  |  Branch (1874:7): [True: 1.74k, False: 5.42k]
  ------------------
 1875|       |    // word reversing wrapper for complex prefixes
 1876|  1.74k|    if (complexprefixes) {
  ------------------
  |  Branch (1876:9): [True: 134, False: 1.60k]
  ------------------
 1877|    134|      if (utf8)
  ------------------
  |  Branch (1877:11): [True: 0, False: 134]
  ------------------
 1878|      0|        reverseword_utf(result);
 1879|    134|      else
 1880|    134|        reverseword(result);
 1881|    134|    }
 1882|  1.74k|    return line_tok(result, MSEP_REC);
  ------------------
  |  |  118|  1.74k|#define MSEP_REC '\n'
  ------------------
 1883|  1.74k|  }
 1884|       |
 1885|       |  // compound word with dash (HU) I18n
 1886|       |  // LANG_hu section: set dash information for suggestions
 1887|       |
 1888|  5.42k|  size_t dash_pos = langnum == LANG_hu ? scw.find('-') : std::string::npos;
  ------------------
  |  Branch (1888:21): [True: 342, False: 5.08k]
  ------------------
 1889|  5.42k|  if (dash_pos != std::string::npos) {
  ------------------
  |  Branch (1889:7): [True: 41, False: 5.38k]
  ------------------
 1890|     41|    int nresult = 0;
 1891|       |
 1892|     41|    std::string part1 = scw.substr(0, dash_pos), part2 = scw.substr(dash_pos + 1);
 1893|       |
 1894|       |    // examine 2 sides of the dash
 1895|     41|    if (part2.empty()) {  // base word ending with dash
  ------------------
  |  Branch (1895:9): [True: 8, False: 33]
  ------------------
 1896|      8|      if (spell(part1, candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (1896:11): [True: 0, False: 8]
  ------------------
 1897|      0|        std::string p = pSMgr->suggest_morph(part1);
 1898|      0|        if (!p.empty()) {
  ------------------
  |  Branch (1898:13): [True: 0, False: 0]
  ------------------
 1899|      0|          slst = line_tok(p, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 1900|      0|          return slst;
 1901|      0|        }
 1902|      0|      }
 1903|     33|    } else if (part2.size() == 1 && part2[0] == 'e') {  // XXX (HU) -e hat.
  ------------------
  |  Branch (1903:16): [True: 1, False: 32]
  |  Branch (1903:37): [True: 0, False: 1]
  ------------------
 1904|      0|      if (spell(part1, candidate_stack, nullptr, nullptr, suggest_start) &&
  ------------------
  |  Branch (1904:11): [True: 0, False: 0]
  |  Branch (1904:11): [True: 0, False: 0]
  ------------------
 1905|      0|          (spell("-e", candidate_stack, nullptr, nullptr, suggest_start))) {
  ------------------
  |  Branch (1905:11): [True: 0, False: 0]
  ------------------
 1906|      0|        std::string st = pSMgr->suggest_morph(part1);
 1907|      0|        if (!st.empty()) {
  ------------------
  |  Branch (1907:13): [True: 0, False: 0]
  ------------------
 1908|      0|          result.append(st);
 1909|      0|        }
 1910|      0|        result.push_back('+');  // XXX spec. separator in MORPHCODE
 1911|      0|        st = pSMgr->suggest_morph("-e");
 1912|      0|        if (!st.empty()) {
  ------------------
  |  Branch (1912:13): [True: 0, False: 0]
  ------------------
 1913|      0|          result.append(st);
 1914|      0|        }
 1915|      0|        return line_tok(result, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 1916|      0|      }
 1917|     33|    } else {
 1918|       |      // first word ending with dash: word- XXX ???
 1919|     33|      part1.push_back(' ');
 1920|     33|      nresult = spell(part1, candidate_stack, nullptr, nullptr, suggest_start);
 1921|     33|      part1.erase(part1.size() - 1);
 1922|     33|      if (nresult && spell(part2, candidate_stack, nullptr, nullptr, suggest_start) &&
  ------------------
  |  Branch (1922:11): [True: 2, False: 31]
  |  Branch (1922:22): [True: 1, False: 1]
  ------------------
 1923|      1|          ((part2.size() > 1) || ((part2[0] > '0') && (part2[0] < '9')))) {
  ------------------
  |  Branch (1923:12): [True: 0, False: 1]
  |  Branch (1923:35): [True: 0, False: 1]
  |  Branch (1923:55): [True: 0, False: 0]
  ------------------
 1924|      0|        std::string st = pSMgr->suggest_morph(part1);
 1925|      0|        if (!st.empty()) {
  ------------------
  |  Branch (1925:13): [True: 0, False: 0]
  ------------------
 1926|      0|          result.append(st);
 1927|      0|          result.push_back('+');  // XXX spec. separator in MORPHCODE
 1928|      0|        }
 1929|      0|        st = pSMgr->suggest_morph(part2);
 1930|      0|        if (!st.empty()) {
  ------------------
  |  Branch (1930:13): [True: 0, False: 0]
  ------------------
 1931|      0|          result.append(st);
 1932|      0|        }
 1933|      0|        return line_tok(result, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 1934|      0|      }
 1935|     33|    }
 1936|       |    // affixed number in correct word
 1937|     41|    if (nresult && (dash_pos > 0) &&
  ------------------
  |  Branch (1937:9): [True: 2, False: 39]
  |  Branch (1937:20): [True: 0, False: 2]
  ------------------
 1938|      0|        (((scw[dash_pos - 1] <= '9') && (scw[dash_pos - 1] >= '0')) ||
  ------------------
  |  Branch (1938:11): [True: 0, False: 0]
  |  Branch (1938:41): [True: 0, False: 0]
  ------------------
 1939|      0|         (scw[dash_pos - 1] == '.'))) {
  ------------------
  |  Branch (1939:10): [True: 0, False: 0]
  ------------------
 1940|      0|      n = 1;
 1941|      0|      if (scw[dash_pos - n] == '.')
  ------------------
  |  Branch (1941:11): [True: 0, False: 0]
  ------------------
 1942|      0|        n++;
 1943|       |      // search first not a number character to left from dash
 1944|      0|      while ((dash_pos >= n) && ((scw[dash_pos - n] == '0') || (n < 3)) &&
  ------------------
  |  Branch (1944:14): [True: 0, False: 0]
  |  Branch (1944:34): [True: 0, False: 0]
  |  Branch (1944:64): [True: 0, False: 0]
  ------------------
 1945|      0|             (n < 6)) {
  ------------------
  |  Branch (1945:14): [True: 0, False: 0]
  ------------------
 1946|      0|        n++;
 1947|      0|      }
 1948|      0|      if (dash_pos < n)
  ------------------
  |  Branch (1948:11): [True: 0, False: 0]
  ------------------
 1949|      0|        n--;
 1950|       |      // numbers: valami1000000-hoz
 1951|       |      // examine 100000-hoz, 10000-hoz 1000-hoz, 10-hoz,
 1952|       |      // 56-hoz, 6-hoz
 1953|      0|      for (; n >= 1; n--) {
  ------------------
  |  Branch (1953:14): [True: 0, False: 0]
  ------------------
 1954|      0|        if (scw[dash_pos - n] < '0' || scw[dash_pos - n] > '9') {
  ------------------
  |  Branch (1954:13): [True: 0, False: 0]
  |  Branch (1954:40): [True: 0, False: 0]
  ------------------
 1955|      0|            continue;
 1956|      0|        }
 1957|      0|        std::string chunk = scw.substr(dash_pos - n);
 1958|      0|        if (checkword(chunk, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (1958:13): [True: 0, False: 0]
  ------------------
 1959|      0|          result.append(chunk);
 1960|      0|          std::string st = pSMgr->suggest_morph(chunk);
 1961|      0|          if (!st.empty()) {
  ------------------
  |  Branch (1961:15): [True: 0, False: 0]
  ------------------
 1962|      0|            result.append(st);
 1963|      0|          }
 1964|      0|          return line_tok(result, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 1965|      0|        }
 1966|      0|      }
 1967|      0|    }
 1968|     41|  }
 1969|  5.42k|  return slst;
 1970|  5.42k|}
_ZN12HunspellImpl8generateERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERKNS0_6vectorIS6_NS4_IS6_EEEE:
 1972|  6.99k|std::vector<std::string> HunspellImpl::generate(const std::string& word, const std::vector<std::string>& pl) {
 1973|  6.99k|  std::vector<std::string> slst;
 1974|  6.99k|  if (!pSMgr || pl.empty())
  ------------------
  |  Branch (1974:7): [True: 0, False: 6.99k]
  |  Branch (1974:17): [True: 639, False: 6.35k]
  ------------------
 1975|    639|    return slst;
 1976|  6.35k|  std::vector<std::string> pl2 = analyze(word);
 1977|  6.35k|  int captype = NOCAP, abbv = 0;
  ------------------
  |  |   88|  6.35k|#define NOCAP 0
  ------------------
 1978|  6.35k|  std::string cw;
 1979|  6.35k|  cleanword(cw, word, &captype, &abbv);
 1980|  6.35k|  std::string result;
 1981|       |
 1982|  6.35k|  auto suggest_start = std::chrono::steady_clock::now();
 1983|   396k|  for (const auto& i : pl) {
  ------------------
  |  Branch (1983:22): [True: 396k, False: 6.35k]
  ------------------
 1984|   396k|    cat_result(result, pSMgr->suggest_gen(pl2, i, suggest_start));
 1985|   396k|  }
 1986|       |
 1987|  6.35k|  if (!result.empty()) {
  ------------------
  |  Branch (1987:7): [True: 0, False: 6.35k]
  ------------------
 1988|       |    // allcap
 1989|      0|    if (captype == ALLCAP)
  ------------------
  |  |   90|      0|#define ALLCAP 2
  ------------------
  |  Branch (1989:9): [True: 0, False: 0]
  ------------------
 1990|      0|      mkallcap(result);
 1991|       |
 1992|       |    // line split
 1993|      0|    slst = line_tok(result, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 1994|       |
 1995|       |    // capitalize
 1996|      0|    if (captype == INITCAP || captype == HUHINITCAP) {
  ------------------
  |  |   89|      0|#define INITCAP 1
  ------------------
                  if (captype == INITCAP || captype == HUHINITCAP) {
  ------------------
  |  |   92|      0|#define HUHINITCAP 4
  ------------------
  |  Branch (1996:9): [True: 0, False: 0]
  |  Branch (1996:31): [True: 0, False: 0]
  ------------------
 1997|      0|      for (auto& str : slst) {
  ------------------
  |  Branch (1997:22): [True: 0, False: 0]
  ------------------
 1998|      0|        mkinitcap(str);
 1999|      0|      }
 2000|      0|    }
 2001|       |
 2002|       |    // temporary filtering of prefix related errors (eg.
 2003|       |    // generate("undrinkable", "eats") --> "undrinkables" and "*undrinks")
 2004|      0|    auto it = slst.begin();
 2005|      0|    while (it != slst.end()) {
  ------------------
  |  Branch (2005:12): [True: 0, False: 0]
  ------------------
 2006|      0|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|      0|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (2006:11): [True: 0, False: 0]
  ------------------
 2007|      0|        break;
 2008|      0|      std::vector<std::string> candidate_stack;
 2009|      0|      if (!spell(*it, candidate_stack, nullptr, nullptr, suggest_start)) {
  ------------------
  |  Branch (2009:11): [True: 0, False: 0]
  ------------------
 2010|      0|        it = slst.erase(it);
 2011|      0|      } else  {
 2012|      0|        ++it;
 2013|      0|      }
 2014|      0|    }
 2015|      0|  }
 2016|  6.35k|  return slst;
 2017|  6.99k|}
_ZN12HunspellImpl8generateERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_:
 2019|    760|std::vector<std::string> HunspellImpl::generate(const std::string& word, const std::string& pattern) {
 2020|    760|  std::vector<std::string> pl = analyze(pattern);
 2021|    760|  std::vector<std::string> slst = generate(word, pl);
 2022|    760|  uniqlist(slst);
 2023|    760|  return slst;
 2024|    760|}
_ZN12HunspellImpl11get_xml_parERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEm:
 2027|   491k|std::string HunspellImpl::get_xml_par(const std::string& in_par, std::string::size_type pos) {
 2028|   491k|  std::string dest;
 2029|   491k|  if (pos == std::string::npos)
  ------------------
  |  Branch (2029:7): [True: 6.76k, False: 485k]
  ------------------
 2030|  6.76k|    return dest;
 2031|   485k|  const char* par = in_par.c_str() + pos;
 2032|   485k|  char end = *par;
 2033|   485k|  if (end == '>')
  ------------------
  |  Branch (2033:7): [True: 481k, False: 3.51k]
  ------------------
 2034|   481k|    end = '<';
 2035|  3.51k|  else if (end != '\'' && end != '"')
  ------------------
  |  Branch (2035:12): [True: 3.09k, False: 418]
  |  Branch (2035:27): [True: 1.36k, False: 1.72k]
  ------------------
 2036|  1.36k|    return dest;  // bad XML
 2037|  10.4M|  for (par++; *par != '\0' && *par != end; ++par) {
  ------------------
  |  Branch (2037:15): [True: 10.4M, False: 32.0k]
  |  Branch (2037:31): [True: 10.0M, False: 451k]
  ------------------
 2038|  10.0M|    dest.push_back(*par);
 2039|  10.0M|  }
 2040|   483k|  mystrrep(dest, "&lt;", "<");
 2041|   483k|  mystrrep(dest, "&amp;", "&");
 2042|   483k|  return dest;
 2043|   485k|}
_ZN12HunspellImpl10input_convERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERS6_:
 2049|  9.49k|bool HunspellImpl::input_conv(const std::string& word, std::string& dest) {
 2050|  9.49k|  RepList* rl = pAMgr ? pAMgr->get_iconvtable() : nullptr;
  ------------------
  |  Branch (2050:17): [True: 9.49k, False: 0]
  ------------------
 2051|  9.49k|  if (rl) {
  ------------------
  |  Branch (2051:7): [True: 500, False: 8.99k]
  ------------------
 2052|    500|    return rl->conv(word, dest);
 2053|    500|  }
 2054|  8.99k|  dest.assign(word);
 2055|  8.99k|  return false;
 2056|  9.49k|}
_ZN12HunspellImpl11get_xml_posERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmPKc:
 2059|  72.9k|std::string::size_type HunspellImpl::get_xml_pos(const std::string& s, std::string::size_type pos, const char* attr) {
 2060|  72.9k|  if (pos == std::string::npos)
  ------------------
  |  Branch (2060:7): [True: 0, False: 72.9k]
  ------------------
 2061|      0|    return std::string::npos;
 2062|       |
 2063|  72.9k|  std::string::size_type endpos = s.find('>', pos);
 2064|  72.9k|  if (attr == nullptr)
  ------------------
  |  Branch (2064:7): [True: 0, False: 72.9k]
  ------------------
 2065|      0|    return endpos;
 2066|   213k|  while (true) {
  ------------------
  |  Branch (2066:10): [True: 213k, Folded]
  ------------------
 2067|   213k|    pos = s.find(attr, pos);
 2068|   213k|    if (pos == std::string::npos || pos >= endpos)
  ------------------
  |  Branch (2068:9): [True: 3.72k, False: 209k]
  |  Branch (2068:37): [True: 1.82k, False: 208k]
  ------------------
 2069|  5.54k|      return std::string::npos;
 2070|   208k|    if (pos == 0 || s[pos - 1] == ' ' || s[pos - 1] == '\n')
  ------------------
  |  Branch (2070:9): [True: 0, False: 208k]
  |  Branch (2070:21): [True: 2.18k, False: 205k]
  |  Branch (2070:42): [True: 65.1k, False: 140k]
  ------------------
 2071|  67.3k|      break;
 2072|   140k|    pos += strlen(attr);
 2073|   140k|  }
 2074|  67.3k|  return pos + strlen(attr);
 2075|  72.9k|}
_ZN12HunspellImpl13check_xml_parERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmPKcSA_:
 2079|  72.9k|                                const char* value) {
 2080|  72.9k|  const std::string cw = get_xml_par(q, get_xml_pos(q, pos, attr));
 2081|  72.9k|  return cw == value ? 1 : 0;
  ------------------
  |  Branch (2081:10): [True: 17.9k, False: 54.9k]
  ------------------
 2082|  72.9k|}
_ZN12HunspellImpl12get_xml_listERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmPKc:
 2084|  7.22k|std::vector<std::string> HunspellImpl::get_xml_list(const std::string& list, std::string::size_type pos, const char* tag) {
 2085|  7.22k|  std::vector<std::string> slst;
 2086|  7.22k|  if (pos == std::string::npos)
  ------------------
  |  Branch (2086:7): [True: 76, False: 7.14k]
  ------------------
 2087|     76|    return slst;
 2088|   403k|  while (true) {
  ------------------
  |  Branch (2088:10): [True: 403k, Folded]
  ------------------
 2089|   403k|    pos = list.find(tag, pos);
 2090|   403k|    if (pos == std::string::npos)
  ------------------
  |  Branch (2090:9): [True: 5.66k, False: 397k]
  ------------------
 2091|  5.66k|        break;
 2092|   397k|    std::string cw = get_xml_par(list, pos + strlen(tag) - 1);
 2093|   397k|    if (cw.empty()) {
  ------------------
  |  Branch (2093:9): [True: 1.48k, False: 396k]
  ------------------
 2094|  1.48k|      break;
 2095|  1.48k|    }
 2096|   396k|    slst.push_back(std::move(cw));
 2097|   396k|    ++pos;
 2098|   396k|  }
 2099|  7.14k|  return slst;
 2100|  7.22k|}
_ZN12HunspellImpl7spellmlERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 2102|  22.5k|std::vector<std::string> HunspellImpl::spellml(const std::string& in_word) {
 2103|       |  // The XML interface spell checks words of its own to answer the query.
 2104|  22.5k|  TraceSuppress no_trace(m_trace.get());
 2105|       |
 2106|  22.5k|  std::vector<std::string> slst;
 2107|       |
 2108|  22.5k|  std::string::size_type qpos = in_word.find("<query");
 2109|  22.5k|  if (qpos == std::string::npos)
  ------------------
  |  Branch (2109:7): [True: 442, False: 22.0k]
  ------------------
 2110|    442|    return slst;  // bad XML input
 2111|       |
 2112|  22.0k|  std::string::size_type q2pos = in_word.find('>', qpos);
 2113|  22.0k|  if (q2pos == std::string::npos)
  ------------------
  |  Branch (2113:7): [True: 283, False: 21.8k]
  ------------------
 2114|    283|    return slst;  // bad XML input
 2115|       |
 2116|  21.8k|  q2pos = in_word.find("<word", q2pos);
 2117|  21.8k|  if (q2pos == std::string::npos)
  ------------------
  |  Branch (2117:7): [True: 362, False: 21.4k]
  ------------------
 2118|    362|    return slst;  // bad XML input
 2119|       |
 2120|  21.4k|  if (check_xml_par(in_word, qpos, "type=", "analyze")) {
  ------------------
  |  Branch (2120:7): [True: 570, False: 20.8k]
  ------------------
 2121|    570|    std::string cw = get_xml_par(in_word, in_word.find('>', q2pos));
 2122|    570|    if (!cw.empty())
  ------------------
  |  Branch (2122:9): [True: 209, False: 361]
  ------------------
 2123|    209|      slst = analyze(cw);
 2124|    570|    if (slst.empty())
  ------------------
  |  Branch (2124:9): [True: 549, False: 21]
  ------------------
 2125|    549|      return slst;
 2126|       |    // convert the result to <code><a>ana1</a><a>ana2</a></code> format
 2127|     21|    std::string r;
 2128|     21|    r.append("<code>");
 2129|     21|    for (auto entry : slst) {
  ------------------
  |  Branch (2129:21): [True: 21, False: 21]
  ------------------
 2130|     21|      r.append("<a>");
 2131|       |
 2132|     21|      mystrrep(entry, "\t", " ");
 2133|     21|      mystrrep(entry, "&", "&amp;");
 2134|     21|      mystrrep(entry, "<", "&lt;");
 2135|     21|      r.append(entry);
 2136|       |
 2137|     21|      r.append("</a>");
 2138|     21|    }
 2139|     21|    r.append("</code>");
 2140|     21|    slst.clear();
 2141|     21|    slst.push_back(std::move(r));
 2142|     21|    return slst;
 2143|  20.8k|  } else if (check_xml_par(in_word, qpos, "type=", "stem")) {
  ------------------
  |  Branch (2143:14): [True: 1.36k, False: 19.5k]
  ------------------
 2144|  1.36k|    std::string cw = get_xml_par(in_word, in_word.find('>', q2pos));
 2145|  1.36k|    if (!cw.empty())
  ------------------
  |  Branch (2145:9): [True: 987, False: 380]
  ------------------
 2146|    987|      return stem(cw);
 2147|  19.5k|  } else if (check_xml_par(in_word, qpos, "type=", "generate")) {
  ------------------
  |  Branch (2147:14): [True: 8.43k, False: 11.0k]
  ------------------
 2148|  8.43k|    std::string cw = get_xml_par(in_word, in_word.find('>', q2pos));
 2149|  8.43k|    if (cw.empty())
  ------------------
  |  Branch (2149:9): [True: 171, False: 8.26k]
  ------------------
 2150|    171|      return slst;
 2151|  8.26k|    std::string::size_type q3pos = in_word.find("<word", q2pos + 1);
 2152|  8.26k|    if (q3pos != std::string::npos) {
  ------------------
  |  Branch (2152:9): [True: 874, False: 7.39k]
  ------------------
 2153|    874|      std::string cw2 = get_xml_par(in_word, in_word.find('>', q3pos));
 2154|    874|      if (!cw2.empty()) {
  ------------------
  |  Branch (2154:11): [True: 760, False: 114]
  ------------------
 2155|    760|        return generate(cw, cw2);
 2156|    760|      }
 2157|  7.39k|    } else {
 2158|  7.39k|      q2pos = in_word.find("<code", q2pos + 1);
 2159|  7.39k|      if (q2pos != std::string::npos) {
  ------------------
  |  Branch (2159:11): [True: 7.22k, False: 171]
  ------------------
 2160|  7.22k|        std::vector<std::string> slst2 = get_xml_list(in_word, in_word.find('>', q2pos), "<a>");
 2161|  7.22k|        if (!slst2.empty()) {
  ------------------
  |  Branch (2161:13): [True: 6.23k, False: 988]
  ------------------
 2162|  6.23k|          slst = generate(cw, slst2);
 2163|  6.23k|          uniqlist(slst);
 2164|  6.23k|          return slst;
 2165|  6.23k|        }
 2166|  7.22k|      }
 2167|  7.39k|    }
 2168|  11.0k|  } else if (check_xml_par(in_word, qpos, "type=", "add")) {
  ------------------
  |  Branch (2168:14): [True: 7.53k, False: 3.53k]
  ------------------
 2169|  7.53k|    std::string cw = get_xml_par(in_word, in_word.find('>', q2pos));
 2170|  7.53k|    if (cw.empty())
  ------------------
  |  Branch (2170:9): [True: 95, False: 7.44k]
  ------------------
 2171|     95|      return slst;
 2172|  7.44k|    std::string::size_type q3pos = in_word.find("<word", q2pos + 1);
 2173|  7.44k|    if (q3pos != std::string::npos) {
  ------------------
  |  Branch (2173:9): [True: 2.33k, False: 5.10k]
  ------------------
 2174|  2.33k|      std::string cw2 = get_xml_par(in_word, in_word.find('>', q3pos));
 2175|  2.33k|      if (!cw2.empty()) {
  ------------------
  |  Branch (2175:11): [True: 2.05k, False: 285]
  ------------------
 2176|  2.05k|        add_with_affix(cw, cw2);
 2177|  2.05k|      } else {
 2178|    285|        add(cw);
 2179|    285|      }
 2180|  5.10k|    } else {
 2181|  5.10k|        add(cw);
 2182|  5.10k|    }
 2183|  7.44k|  }
 2184|  12.6k|  return slst;
 2185|  21.4k|}
_ZN8HunspellC2EPKcS1_S1_:
 2340|     38|  : m_Impl(new HunspellImpl(affpath, dpath, key)) {
 2341|     38|}
_ZN8Hunspell5spellERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPiPS6_:
 2352|  65.9k|bool Hunspell::spell(const std::string& word, int* info, std::string* root) {
 2353|  65.9k|  std::vector<std::string> candidate_stack;
 2354|  65.9k|  return m_Impl->spell(word, candidate_stack, info, root,
 2355|  65.9k|                       std::chrono::steady_clock::now());
 2356|  65.9k|}
_ZN8Hunspell7suggestERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 2358|  65.3k|std::vector<std::string> Hunspell::suggest(const std::string& word) {
 2359|  65.3k|  return m_Impl->suggest(word);
 2360|  65.3k|}
_ZNK12HunspellImpl12active_traceEv:
  143|  39.2M|  TraceCtx* active_trace() const {
  144|  39.2M|    return m_trace->on() ? m_trace.get() : nullptr;
  ------------------
  |  Branch (144:12): [True: 0, False: 39.2M]
  ------------------
  145|  39.2M|  }

_ZNK8TraceCtx2onEv:
  110|  39.2M|  bool on() const { return m_callback && m_suppressed == 0; }
  ------------------
  |  Branch (110:28): [True: 0, False: 39.2M]
  |  Branch (110:42): [True: 0, False: 0]
  ------------------
_ZN10TraceScopeC2EP8TraceCtx:
  131|   561M|  explicit TraceScope(TraceCtx* context) : m_context(context) {
  132|   561M|    if (m_context)
  ------------------
  |  Branch (132:9): [True: 0, False: 561M]
  ------------------
  133|      0|      ++m_context->m_depth;
  134|   561M|  }
_ZN10TraceScopeD2Ev:
  135|   561M|  ~TraceScope() {
  136|   561M|    if (m_context)
  ------------------
  |  Branch (136:9): [True: 0, False: 561M]
  ------------------
  137|      0|      --m_context->m_depth;
  138|   561M|  }
_Z8trace_onP8TraceCtx:
  165|  1.23G|inline TraceCtx* trace_on(TraceCtx* context) {
  166|  1.23G|  return (context && context->on()) ? context : nullptr;
  ------------------
  |  Branch (166:11): [True: 0, False: 1.23G]
  |  Branch (166:22): [True: 0, False: 0]
  ------------------
  167|  1.23G|}
_ZN13TraceSuppressC2EP8TraceCtx:
  148|   116k|  explicit TraceSuppress(TraceCtx* context) : m_context(context) {
  149|   116k|    if (m_context)
  ------------------
  |  Branch (149:9): [True: 116k, False: 0]
  ------------------
  150|   116k|      ++m_context->m_suppressed;
  151|   116k|  }
_ZN13TraceSuppressD2Ev:
  152|   116k|  ~TraceSuppress() {
  153|   116k|    if (m_context)
  ------------------
  |  Branch (153:9): [True: 116k, False: 0]
  ------------------
  154|   116k|      --m_context->m_suppressed;
  155|   116k|  }
_ZN8TraceCtxC2EPFvPviPKcES0_:
  103|     38|      : m_callback(callback), m_userdata(userdata) {}

_Z16init_phonet_hashR10phonetable:
   38|      2|void init_phonet_hash(phonetable& parms) {
   39|      2|  memset(parms.hash, 0xff, HASHSIZE * sizeof(int));
  ------------------
  |  |   33|      2|#define HASHSIZE 256
  ------------------
   40|       |
   41|    212|  for (int i = 0; parms.rules[i][0] != '\0'; i += 2) {
  ------------------
  |  Branch (41:19): [True: 210, False: 2]
  ------------------
   42|       |    /**  set hash value  **/
   43|    210|    int k = (unsigned char)parms.rules[i][0];
   44|       |
   45|    210|    if (parms.hash[k] < 0) {
  ------------------
  |  Branch (45:9): [True: 54, False: 156]
  ------------------
   46|     54|      parms.hash[k] = i;
   47|     54|    }
   48|    210|  }
   49|      2|}
_Z6phonetRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEER10phonetable:
   69|  10.4k|std::string phonet(const std::string& inword, phonetable& parms) {
   70|       |
   71|  10.4k|  int i, k = 0, p, z, k0, n0, p0 = -333;
   72|  10.4k|  char c;
   73|  10.4k|  using uchar = unsigned char;
   74|       |
   75|  10.4k|  size_t len = inword.size();
   76|  10.4k|  if (len > MAXPHONETUTF8LEN)
  ------------------
  |  |   35|  10.4k|#define MAXPHONETUTF8LEN (MAXPHONETLEN * 4)
  |  |  ------------------
  |  |  |  |   34|  10.4k|#define MAXPHONETLEN 256
  |  |  ------------------
  ------------------
  |  Branch (76:7): [True: 0, False: 10.4k]
  ------------------
   77|      0|    return {};
   78|  10.4k|  char word[MAXPHONETUTF8LEN + 1];
   79|  10.4k|  strncpy(word, inword.c_str(), MAXPHONETUTF8LEN);
  ------------------
  |  |   35|  10.4k|#define MAXPHONETUTF8LEN (MAXPHONETLEN * 4)
  |  |  ------------------
  |  |  |  |   34|  10.4k|#define MAXPHONETLEN 256
  |  |  ------------------
  ------------------
   80|  10.4k|  word[MAXPHONETUTF8LEN] = '\0';
  ------------------
  |  |   35|  10.4k|#define MAXPHONETUTF8LEN (MAXPHONETLEN * 4)
  |  |  ------------------
  |  |  |  |   34|  10.4k|#define MAXPHONETLEN 256
  |  |  ------------------
  ------------------
   81|       |
   82|  10.4k|  std::string target;
   83|       |  /**  check word  **/
   84|  10.4k|  i = z = 0;
   85|   102k|  while ((c = word[i]) != '\0') {
  ------------------
  |  Branch (85:10): [True: 92.1k, False: 10.4k]
  ------------------
   86|  92.1k|    int n = parms.hash[(uchar)c];
   87|  92.1k|    int z0 = 0;
   88|       |
   89|  92.1k|    if (n >= 0 && !parms.rules[n].empty()) {
  ------------------
  |  Branch (89:9): [True: 26.5k, False: 65.5k]
  |  Branch (89:19): [True: 26.5k, False: 0]
  ------------------
   90|       |      /**  check all rules for the same letter  **/
   91|  69.1k|      while (parms.rules[n][0] == c) {
  ------------------
  |  Branch (91:14): [True: 67.3k, False: 1.88k]
  ------------------
   92|       |        /**  check whole string  **/
   93|  67.3k|        k = 1; /** number of found letters  **/
   94|  67.3k|        p = 5; /** default priority  **/
   95|  67.3k|        const char*s = parms.rules[n].c_str();
   96|  67.3k|        s++; /**  important for (see below)  "*(s-1)"  **/
   97|       |
   98|  69.4k|        while (*s != '\0' && word[i + k] == *s && !isdigit((unsigned char)*s) && strchr("(-<^$", *s) == nullptr) {
  ------------------
  |  Branch (98:16): [True: 46.6k, False: 22.8k]
  |  Branch (98:30): [True: 2.25k, False: 44.3k]
  |  Branch (98:51): [True: 2.25k, False: 0]
  |  Branch (98:82): [True: 2.17k, False: 72]
  ------------------
   99|  2.17k|          k++;
  100|  2.17k|          s++;
  101|  2.17k|        }
  102|  67.3k|        if (*s == '(') {
  ------------------
  |  Branch (102:13): [True: 4.06k, False: 63.2k]
  ------------------
  103|       |          /**  check letters in "(..)"  **/
  104|  4.06k|          if (myisalpha(word[i + k])  // ...could be implied?
  ------------------
  |  Branch (104:15): [True: 3.00k, False: 1.05k]
  ------------------
  105|  3.00k|              && strchr(s + 1, word[i + k]) != nullptr) {
  ------------------
  |  Branch (105:18): [True: 274, False: 2.73k]
  ------------------
  106|    274|            k++;
  107|  1.55k|            while (*s && *s != ')')
  ------------------
  |  Branch (107:20): [True: 1.55k, False: 0]
  |  Branch (107:26): [True: 1.27k, False: 274]
  ------------------
  108|  1.27k|              s++;
  109|    274|            if (*s == ')')
  ------------------
  |  Branch (109:17): [True: 274, False: 0]
  ------------------
  110|    274|              s++;
  111|    274|          }
  112|  4.06k|        }
  113|  67.3k|        p0 = (int)*s;
  114|  67.3k|        k0 = k;
  115|  68.7k|        while (*s == '-' && k > 1) {
  ------------------
  |  Branch (115:16): [True: 1.41k, False: 67.3k]
  |  Branch (115:29): [True: 1.41k, False: 0]
  ------------------
  116|  1.41k|          k--;
  117|  1.41k|          s++;
  118|  1.41k|        }
  119|  67.3k|        if (*s == '<')
  ------------------
  |  Branch (119:13): [True: 76, False: 67.2k]
  ------------------
  120|     76|          s++;
  121|  67.3k|        if (isdigit((unsigned char)*s)) {
  ------------------
  |  Branch (121:13): [True: 65, False: 67.2k]
  ------------------
  122|       |          /**  determine priority  **/
  123|     65|          p = *s - '0';
  124|     65|          s++;
  125|     65|        }
  126|  67.3k|        if (*s == '^' && *(s + 1) == '^')
  ------------------
  |  Branch (126:13): [True: 2.80k, False: 64.5k]
  |  Branch (126:26): [True: 0, False: 2.80k]
  ------------------
  127|      0|          s++;
  128|       |
  129|  67.3k|        if (*s == '\0' || (*s == '^' && (i == 0 || !myisalpha(word[i - 1])) &&
  ------------------
  |  Branch (129:13): [True: 24.4k, False: 42.8k]
  |  Branch (129:28): [True: 2.80k, False: 40.0k]
  |  Branch (129:42): [True: 116, False: 2.69k]
  |  Branch (129:52): [True: 677, False: 2.01k]
  ------------------
  130|    793|                           (*(s + 1) != '$' || (!myisalpha(word[i + k0])))) ||
  ------------------
  |  Branch (130:29): [True: 793, False: 0]
  |  Branch (130:48): [True: 0, False: 0]
  ------------------
  131|  42.0k|            (*s == '$' && i > 0 && myisalpha(word[i - 1]) &&
  ------------------
  |  Branch (131:14): [True: 0, False: 42.0k]
  |  Branch (131:27): [True: 0, False: 0]
  |  Branch (131:36): [True: 0, False: 0]
  ------------------
  132|  25.2k|             (!myisalpha(word[i + k0])))) {
  ------------------
  |  Branch (132:14): [True: 0, False: 0]
  ------------------
  133|       |          /**  search for followup rules, if:     **/
  134|       |          /**  parms.followup and k > 1  and  NO '-' in searchstring **/
  135|  25.2k|          char c0 = word[i + k - 1];
  136|  25.2k|          n0 = parms.hash[(uchar)c0];
  137|       |
  138|       |          //            if (parms.followup  &&  k > 1  &&  n0 >= 0
  139|  25.2k|          if (k > 1 && n0 >= 0 && p0 != (int)'-' && word[i + k] != '\0' && !parms.rules[n0].empty()) {
  ------------------
  |  Branch (139:15): [True: 751, False: 24.4k]
  |  Branch (139:24): [True: 751, False: 0]
  |  Branch (139:35): [True: 707, False: 44]
  |  Branch (139:53): [True: 645, False: 62]
  |  Branch (139:76): [True: 645, False: 0]
  ------------------
  140|       |            /**  test follow-up rule for "word[i+k]"  **/
  141|  1.88k|            while (parms.rules[n0][0] == c0) {
  ------------------
  |  Branch (141:20): [True: 1.76k, False: 122]
  ------------------
  142|       |              /**  check whole string  **/
  143|  1.76k|              k0 = k;
  144|  1.76k|              p0 = 5;
  145|  1.76k|              s = parms.rules[n0].c_str();
  146|  1.76k|              s++;
  147|  2.28k|              while (*s != '\0' && word[i + k0] == *s && !isdigit((unsigned char)*s) && strchr("(-<^$", *s) == nullptr) {
  ------------------
  |  Branch (147:22): [True: 1.69k, False: 586]
  |  Branch (147:36): [True: 523, False: 1.17k]
  |  Branch (147:58): [True: 523, False: 0]
  |  Branch (147:89): [True: 523, False: 0]
  ------------------
  148|    523|                k0++;
  149|    523|                s++;
  150|    523|              }
  151|  1.76k|              if (*s == '(') {
  ------------------
  |  Branch (151:19): [True: 8, False: 1.75k]
  ------------------
  152|       |                /**  check letters  **/
  153|      8|                if (myisalpha(word[i + k0]) && strchr(s + 1, word[i + k0]) != nullptr) {
  ------------------
  |  Branch (153:21): [True: 6, False: 2]
  |  Branch (153:48): [True: 0, False: 6]
  ------------------
  154|      0|                  k0++;
  155|      0|                  while (*s != ')' && *s != '\0')
  ------------------
  |  Branch (155:26): [True: 0, False: 0]
  |  Branch (155:39): [True: 0, False: 0]
  ------------------
  156|      0|                    s++;
  157|      0|                  if (*s == ')')
  ------------------
  |  Branch (157:23): [True: 0, False: 0]
  ------------------
  158|      0|                    s++;
  159|      0|                }
  160|      8|              }
  161|  1.76k|              while (*s == '-') {
  ------------------
  |  Branch (161:22): [True: 1, False: 1.76k]
  ------------------
  162|       |                /**  "k0" gets NOT reduced   **/
  163|       |                /**  because "if (k0 == k)"  **/
  164|      1|                s++;
  165|      1|              }
  166|  1.76k|              if (*s == '<')
  ------------------
  |  Branch (166:19): [True: 4, False: 1.75k]
  ------------------
  167|      4|                s++;
  168|  1.76k|              if (isdigit((unsigned char)*s)) {
  ------------------
  |  Branch (168:19): [True: 54, False: 1.70k]
  ------------------
  169|     54|                p0 = *s - '0';
  170|     54|                s++;
  171|     54|              }
  172|       |
  173|  1.76k|              if (*s == '\0'
  ------------------
  |  Branch (173:19): [True: 645, False: 1.11k]
  ------------------
  174|       |                  /**  *s == '^' cuts  **/
  175|  1.11k|                  || (*s == '$' && !myisalpha(word[i + k0]))) {
  ------------------
  |  Branch (175:23): [True: 0, False: 1.11k]
  |  Branch (175:36): [True: 0, False: 0]
  ------------------
  176|    645|                if (k0 == k) {
  ------------------
  |  Branch (176:21): [True: 122, False: 523]
  ------------------
  177|       |                  /**  this is just a piece of the string  **/
  178|    122|                  n0 += 2;
  179|    122|                  continue;
  180|    122|                }
  181|       |
  182|    523|                if (p0 < p) {
  ------------------
  |  Branch (182:21): [True: 0, False: 523]
  ------------------
  183|       |                  /**  priority too low  **/
  184|      0|                  n0 += 2;
  185|      0|                  continue;
  186|      0|                }
  187|       |                /**  rule fits; stop search  **/
  188|    523|                break;
  189|    523|              }
  190|  1.11k|              n0 += 2;
  191|  1.11k|            } /**  End of "while (parms.rules[n0][0] == c0)"  **/
  192|       |
  193|    645|            if (p0 >= p && parms.rules[n0][0] == c0) {
  ------------------
  |  Branch (193:17): [True: 634, False: 11]
  |  Branch (193:28): [True: 523, False: 111]
  ------------------
  194|    523|              n += 2;
  195|    523|              continue;
  196|    523|            }
  197|    645|          } /** end of follow-up stuff **/
  198|       |
  199|       |          /**  replace string  **/
  200|  24.7k|          s = parms.rules[n + 1].c_str();
  201|  24.7k|          p0 = (!parms.rules[n].empty() && strchr(parms.rules[n].c_str() + 1, '<') != nullptr) ? 1 : 0;
  ------------------
  |  Branch (201:17): [True: 24.7k, False: 0]
  |  Branch (201:44): [True: 72, False: 24.6k]
  ------------------
  202|  24.7k|          if (p0 == 1 && z == 0) {
  ------------------
  |  Branch (202:15): [True: 72, False: 24.6k]
  |  Branch (202:26): [True: 72, False: 0]
  ------------------
  203|       |            /**  rule with '<' is used  **/
  204|     72|            if (!target.empty() && *s != '\0' &&
  ------------------
  |  Branch (204:17): [True: 54, False: 18]
  |  Branch (204:36): [True: 54, False: 0]
  ------------------
  205|     54|                (target[target.size()-1] == c || target[target.size()-1] == *s)) {
  ------------------
  |  Branch (205:18): [True: 0, False: 54]
  |  Branch (205:50): [True: 0, False: 54]
  ------------------
  206|      0|              target.erase(target.size() - 1);
  207|      0|            }
  208|     72|            z0 = 1;
  209|     72|            z = 1;
  210|     72|            k0 = 0;
  211|    144|            while (*s != '\0' && word[i + k0] != '\0') {
  ------------------
  |  Branch (211:20): [True: 72, False: 72]
  |  Branch (211:34): [True: 72, False: 0]
  ------------------
  212|     72|              word[i + k0] = *s;
  213|     72|              k0++;
  214|     72|              s++;
  215|     72|            }
  216|     72|            if (k > k0)
  ------------------
  |  Branch (216:17): [True: 4, False: 68]
  ------------------
  217|      4|              strmove(&word[0] + i + k0, &word[0] + i + k);
  218|       |
  219|       |            /**  new "actual letter"  **/
  220|     72|            c = word[i];
  221|  24.6k|          } else { /** no '<' rule used **/
  222|  24.6k|            i += k - 1;
  223|  24.6k|            z = 0;
  224|  24.9k|            while (*s != '\0' && *(s + 1) != '\0' && target.size() < len) {
  ------------------
  |  Branch (224:20): [True: 23.6k, False: 1.29k]
  |  Branch (224:34): [True: 461, False: 23.2k]
  |  Branch (224:54): [True: 344, False: 117]
  ------------------
  225|    344|              if (target.empty() || target[target.size()-1] != *s) {
  ------------------
  |  Branch (225:19): [True: 10, False: 334]
  |  Branch (225:37): [True: 164, False: 170]
  ------------------
  226|    174|                target.push_back(*s);
  227|    174|              }
  228|    344|              s++;
  229|    344|            }
  230|       |            /**  new "actual letter"  **/
  231|  24.6k|            c = *s;
  232|  24.6k|            if (!parms.rules[n].empty() && strstr(parms.rules[n].c_str() + 1, "^^") != nullptr) {
  ------------------
  |  Branch (232:17): [True: 24.6k, False: 0]
  |  Branch (232:44): [True: 0, False: 24.6k]
  ------------------
  233|      0|              if (c != '\0') {
  ------------------
  |  Branch (233:19): [True: 0, False: 0]
  ------------------
  234|      0|                target.push_back(c);
  235|      0|              }
  236|      0|              strmove(&word[0], &word[0] + i + 1);
  237|      0|              i = 0;
  238|      0|              z0 = 1;
  239|      0|            }
  240|  24.6k|          }
  241|  24.7k|          break;
  242|  25.2k|        } /** end of follow-up stuff **/
  243|  42.0k|        n += 2;
  244|  42.0k|      } /**  end of while (parms.rules[n][0] == c)  **/
  245|  26.5k|    }   /**  end of if (n >= 0)  **/
  246|  92.1k|    if (z0 == 0) {
  ------------------
  |  Branch (246:9): [True: 92.0k, False: 72]
  ------------------
  247|  92.0k|      if (k && !p0 && target.size() < len && c != '\0') {
  ------------------
  |  Branch (247:11): [True: 26.5k, False: 65.5k]
  |  Branch (247:16): [True: 24.6k, False: 1.88k]
  |  Branch (247:23): [True: 24.5k, False: 134]
  |  Branch (247:46): [True: 23.2k, False: 1.29k]
  ------------------
  248|       |        /**  condense only double letters  **/
  249|  23.2k|        target.push_back(c);
  250|       |        /// printf("\n setting \n");
  251|  23.2k|      }
  252|       |
  253|  92.0k|      i++;
  254|  92.0k|      z = 0;
  255|  92.0k|      k = 0;
  256|  92.0k|    }
  257|  92.1k|  } /**  end of   while ((c = word[i]) != '\0')  **/
  258|       |
  259|  10.4k|  return target;
  260|  10.4k|} /**  end of function "phonet"  **/
phonet.cxx:_ZL9myisalphac:
   59|  6.76k|static int myisalpha(char ch) {
   60|  6.76k|  if ((unsigned char)ch < 128)
  ------------------
  |  Branch (60:7): [True: 6.22k, False: 536]
  ------------------
   61|  6.22k|    return isalpha(ch);
   62|    536|  return 1;
   63|  6.76k|}
phonet.cxx:_ZL7strmovePcS_:
   53|      4|static inline void strmove(char* dest, char* src) {
   54|     38|  while (*src)
  ------------------
  |  Branch (54:10): [True: 34, False: 4]
  ------------------
   55|     34|    *dest++ = *src++;
   56|      4|  *dest = '\0';
   57|      4|}

_ZN7RepListC2Ei:
   79|      4|RepList::RepList(int n) {
   80|      4|  dat.reserve(std::min(n, 16384));
   81|      4|  can_use_trie = true;
   82|      4|}
_ZN7RepList4findEPKcm:
   90|     22|ptrdiff_t RepList::find(const char* word, size_t max_len) {
   91|     22|  ptrdiff_t p1 = 0;
   92|     22|  ptrdiff_t p2 = dat.size() - 1;
   93|     22|  ptrdiff_t ret = -1;
   94|     58|  while (p1 <= p2) {
  ------------------
  |  Branch (94:10): [True: 36, False: 22]
  ------------------
   95|     36|    ptrdiff_t m = (p1 + p2) >> 1;
   96|     36|    const std::string& pattern = dat[m]->pattern;
   97|       |    // compare only as far as max_len, so a caller can restrict the search to
   98|       |    // patterns no longer than a given length
   99|     36|    size_t cmplen = pattern.size() < max_len ? pattern.size() : max_len;
  ------------------
  |  Branch (99:21): [True: 6, False: 30]
  ------------------
  100|     36|    int c = strncmp(word, pattern.c_str(), cmplen);
  101|     36|    if (c < 0)
  ------------------
  |  Branch (101:9): [True: 12, False: 24]
  ------------------
  102|     12|      p2 = m - 1;
  103|     24|    else if (c > 0)
  ------------------
  |  Branch (103:14): [True: 24, False: 0]
  ------------------
  104|     24|      p1 = m + 1;
  105|      0|    else if (pattern.size() <= max_len) {  // a prefix within the limit
  ------------------
  |  Branch (105:14): [True: 0, False: 0]
  ------------------
  106|      0|      ret = m;                             // scan right for a longer match
  107|      0|      p1 = m + 1;
  108|      0|    } else {
  109|       |      // pattern shares the capped prefix but is too long; any shorter
  110|       |      // candidate sorts earlier
  111|      0|      p2 = m - 1;
  112|      0|    }
  113|     36|  }
  114|     22|  return ret;
  115|     22|}
_ZN7RepList3addERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_:
  126|     22|int RepList::add(const std::string& in_pat1, const std::string& pat2) {
  127|     22|  if (in_pat1.empty() || pat2.empty()) {
  ------------------
  |  Branch (127:7): [True: 0, False: 22]
  |  Branch (127:26): [True: 0, False: 22]
  ------------------
  128|      0|    return 1;
  129|      0|  }
  130|       |
  131|       |  // analyse word context
  132|     22|  int type = 0;
  133|     22|  std::string pat1(in_pat1);
  134|     22|  if (pat1[0] == '_') {
  ------------------
  |  Branch (134:7): [True: 0, False: 22]
  ------------------
  135|      0|    pat1.erase(0, 1);
  136|      0|    type = 1;
  137|      0|  }
  138|     22|  if (!pat1.empty() && pat1[pat1.size() - 1] == '_') {
  ------------------
  |  Branch (138:7): [True: 22, False: 0]
  |  Branch (138:24): [True: 0, False: 22]
  ------------------
  139|      0|    type = type + 2;
  140|      0|    pat1.erase(pat1.size() - 1);
  141|      0|  }
  142|     22|  mystrrep(pat1, "_", " ");
  143|       |
  144|       |  // The trie does unanchored whole-string replacement only. Anchored entries
  145|       |  // (a leading or trailing _) depend on the match position within the word,
  146|       |  // which the trie does not model, so fall back to the linear scan once one is
  147|       |  // seen. Feed the trie the same _-to-space normalised strings the linear path
  148|       |  // stores, otherwise the two paths would disagree on output.
  149|     22|  if (type == 0 && can_use_trie) {
  ------------------
  |  Branch (149:7): [True: 22, False: 0]
  |  Branch (149:20): [True: 22, False: 0]
  ------------------
  150|     22|    std::string out(pat2);
  151|     22|    mystrrep(out, "_", " ");
  152|     22|    trie.add(pat1, out);
  153|     22|  } else {
  154|      0|    can_use_trie = false;
  155|      0|  }
  156|       |
  157|       |  // find existing entry
  158|     22|  ptrdiff_t m = find(pat1.c_str(), pat1.size());
  159|     22|  if (m >= 0 && dat[m]->pattern == pat1) {
  ------------------
  |  Branch (159:7): [True: 0, False: 22]
  |  Branch (159:17): [True: 0, False: 0]
  ------------------
  160|       |    // since already used
  161|      0|    dat[m]->outstrings[type] = pat2;
  162|      0|    mystrrep(dat[m]->outstrings[type], "_", " ");
  163|      0|    return 0;
  164|      0|  }
  165|       |
  166|       |  // make a new entry if none exists
  167|     22|  replentry* r = new replentry;
  168|     22|  r->pattern = std::move(pat1);
  169|     22|  r->outstrings[type] = pat2;
  170|     22|  mystrrep(r->outstrings[type], "_", " ");
  171|     22|  dat.push_back(r);
  172|       |  // sort to the right place in the list
  173|     22|  size_t i;
  174|     36|  for (i = dat.size() - 1; i > 0; --i) {
  ------------------
  |  Branch (174:28): [True: 30, False: 6]
  ------------------
  175|     30|    if (strcmp(r->pattern.c_str(), dat[i - 1]->pattern.c_str()) < 0) {
  ------------------
  |  Branch (175:9): [True: 14, False: 16]
  ------------------
  176|     14|      dat[i] = dat[i - 1];
  177|     14|    } else
  178|     16|      break;
  179|     30|  }
  180|     22|  dat[i] = r;
  181|     22|  return 0;
  182|     22|}
_ZN7RepList4convERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERS6_m:
  184|   491k|bool RepList::conv(const std::string& in_word, std::string& dest, size_t maxlen) {
  185|       |  // get_status guards against a trie that overflowed its index type while
  186|       |  // building, in which case the linear scan below is the correct fallback.
  187|   491k|  if (can_use_trie && trie.get_status())
  ------------------
  |  Branch (187:7): [True: 491k, False: 0]
  |  Branch (187:23): [True: 491k, False: 0]
  ------------------
  188|   491k|    return trie.transcode(in_word, dest, maxlen) != TranscodeResult::None;
  189|       |
  190|      0|  dest.clear();
  191|       |
  192|      0|  const size_t wordlen = in_word.size();
  193|      0|  const char* word = in_word.c_str();
  194|       |
  195|      0|  bool change = false;
  196|      0|  for (size_t i = 0; i < wordlen && dest.size() <= maxlen; ++i) {
  ------------------
  |  Branch (196:22): [True: 0, False: 0]
  |  Branch (196:37): [True: 0, False: 0]
  ------------------
  197|      0|    ptrdiff_t n = -1;
  198|      0|    std::string l;
  199|       |
  200|       |    // Find the longest matching pattern whose replacement actually applies.
  201|       |    // The longest match may be rejected, for example an end-anchored key that
  202|       |    // is not at the end of the word, in which case retry with strictly shorter
  203|       |    // patterns so a shorter match can still apply.
  204|      0|    for (size_t max_len = wordlen - i; max_len > 0;) {
  ------------------
  |  Branch (204:40): [True: 0, False: 0]
  ------------------
  205|      0|      ptrdiff_t m = find(word + i, max_len);
  206|      0|      if (m < 0)
  ------------------
  |  Branch (206:11): [True: 0, False: 0]
  ------------------
  207|      0|        break;
  208|      0|      l = replace(wordlen - i, m, i == 0);
  209|      0|      if (!l.empty()) {
  ------------------
  |  Branch (209:11): [True: 0, False: 0]
  ------------------
  210|      0|        n = m;
  211|      0|        break;
  212|      0|      }
  213|      0|      size_t plen = dat[m]->pattern.size();
  214|      0|      if (plen == 0)
  ------------------
  |  Branch (214:11): [True: 0, False: 0]
  ------------------
  215|      0|        break;
  216|      0|      max_len = plen - 1;
  217|      0|    }
  218|       |
  219|      0|    if (n < 0) {
  ------------------
  |  Branch (219:9): [True: 0, False: 0]
  ------------------
  220|      0|      dest.push_back(word[i]);
  221|      0|      continue;
  222|      0|    }
  223|       |
  224|      0|    dest.append(l);
  225|      0|    if (!dat[n]->pattern.empty()) {
  ------------------
  |  Branch (225:9): [True: 0, False: 0]
  ------------------
  226|      0|      i += dat[n]->pattern.size() - 1;
  227|      0|    }
  228|      0|    change = true;
  229|      0|  }
  230|       |
  231|      0|  return change;
  232|   491k|}
_ZNK7RepList24check_against_breaktableERKNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEE:
  234|      2|bool RepList::check_against_breaktable(const std::vector<std::string>& breaktable) const {
  235|      8|  for (const auto i : dat) {
  ------------------
  |  Branch (235:21): [True: 8, False: 2]
  ------------------
  236|     32|    for (auto& outstring : i->outstrings) {
  ------------------
  |  Branch (236:26): [True: 32, False: 8]
  ------------------
  237|     96|      for (const auto& str : breaktable) {
  ------------------
  |  Branch (237:28): [True: 96, False: 32]
  ------------------
  238|     96|        if (outstring.find(str) != std::string::npos) {
  ------------------
  |  Branch (238:13): [True: 0, False: 96]
  ------------------
  239|      0|          return false;
  240|      0|        }
  241|     96|      }
  242|     32|    }
  243|      8|  }
  244|       |
  245|      2|  return true;
  246|      2|}

_ZN4TrieItLb1EEC2Ev:
  162|      4|    Trie() : status_ok(true) {
  163|       |        // Initialize the root node (Index 0)
  164|      4|        nodes.emplace_back();
  165|      4|        sub_info_arena.push_back(0xFFFFFFFF);
  166|      4|    }
_ZN4TrieItLb1EE3addERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_:
  168|     22|    void add(const std::string& key, const std::string& value) {
  169|     22|        if (!status_ok) return;
  ------------------
  |  Branch (169:13): [True: 0, False: 22]
  ------------------
  170|       |
  171|       |        // Size rules diagnostics for our 32-bit (24/8) packing format
  172|     22|        if (value.size() > 255) { status_ok = false; return; }
  ------------------
  |  Branch (172:13): [True: 0, False: 22]
  ------------------
  173|     22|        size_t offset = char_arena.size();
  174|     22|        if (offset > 0xFFFFFF) { status_ok = false; return; }
  ------------------
  |  Branch (174:13): [True: 0, False: 22]
  ------------------
  175|       |
  176|       |        // Append to the flat char arena
  177|     22|        char_arena.insert(char_arena.end(), value.begin(), value.end());
  178|     22|        uint32_t sub_val = (static_cast<uint32_t>(offset) << 8) | static_cast<uint8_t>(value.size());
  179|       |
  180|     22|        size_t curr_idx = 0;
  181|       |        
  182|       |        // Traverse the key, adding nodes as necessary
  183|     56|        for (size_t i = 0; i < key.size(); ++i) {
  ------------------
  |  Branch (183:28): [True: 34, False: 22]
  ------------------
  184|     34|            uint8_t byte = static_cast<uint8_t>(key[i]);
  185|       |            
  186|     34|            if (UseNibbles) {
  ------------------
  |  Branch (186:17): [True: 34, Folded]
  ------------------
  187|       |                // Loop unrolling: Process the High Nibble, then the Low Nibble
  188|     34|                curr_idx = advance_or_create(curr_idx, (byte >> 4) & 0x0F);
  189|     34|                if (!status_ok) return;
  ------------------
  |  Branch (189:21): [True: 0, False: 34]
  ------------------
  190|     34|                curr_idx = advance_or_create(curr_idx, byte & 0x0F);
  191|     34|                if (!status_ok) return;
  ------------------
  |  Branch (191:21): [True: 0, False: 34]
  ------------------
  192|     34|            } else {
  193|       |                // Process as a single 8-bit lookup
  194|      0|                curr_idx = advance_or_create(curr_idx, byte);
  195|      0|                if (!status_ok) return;
  ------------------
  |  Branch (195:21): [True: 0, False: 0]
  ------------------
  196|      0|            }
  197|     34|        }
  198|       |        // Mark the leaf node with the packed substitution metadata
  199|     22|        sub_info_arena[curr_idx] = sub_val;
  200|     22|    }
_ZN4TrieItLb1EE17advance_or_createEmh:
  139|     68|    size_t advance_or_create(size_t curr_idx, uint8_t symbol) {
  140|     68|        IndexType rel_idx = nodes[curr_idx].children[symbol];
  141|     68|        if (rel_idx == 0) {
  ------------------
  |  Branch (141:13): [True: 38, False: 30]
  ------------------
  142|     38|            size_t new_idx = nodes.size();
  143|     38|            size_t diff = new_idx - curr_idx;
  144|       |            
  145|       |            // Diagnostics: Halt execution if the trie outgrows the integer type
  146|     38|            if (diff > std::numeric_limits<IndexType>::max()) {
  ------------------
  |  Branch (146:17): [True: 0, False: 38]
  ------------------
  147|      0|                status_ok = false;
  148|      0|                return 0;
  149|      0|            }
  150|       |            
  151|     38|            nodes[curr_idx].children[symbol] = static_cast<IndexType>(diff);
  152|       |            
  153|       |            // emplace_back constructs the object directly in the vector's memory
  154|     38|            nodes.emplace_back(); 
  155|     38|            sub_info_arena.push_back(0xFFFFFFFF); // 0xFFFFFFFF = No substitution mapped here
  156|     38|            return new_idx;
  157|     38|        }
  158|     30|        return curr_idx + rel_idx;
  159|     68|    }
_ZNK4TrieItLb1EE10get_statusEv:
  276|   491k|    bool get_status() const { return status_ok; }
_ZNK4TrieItLb1EE9transcodeERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERS7_m:
  206|   491k|    TranscodeResult transcode(const std::string& src, std::string& dst, size_t maxlen) const {
  207|       |        // Halt and return None if the trie is in an invalid memory state
  208|   491k|        if (!status_ok || src.empty()) return TranscodeResult::None;
  ------------------
  |  Branch (208:13): [True: 0, False: 491k]
  |  Branch (208:27): [True: 1.87k, False: 489k]
  ------------------
  209|       |        
  210|   489k|        dst.clear();
  211|   489k|        dst.reserve(src.size()); 
  212|       |        
  213|       |        // State trackers for the 3-way outcome
  214|   489k|        bool any_substituted = false;
  215|   489k|        bool any_copied = false;
  216|       |        
  217|   489k|        size_t i = 0;
  218|       |        
  219|  6.11M|        while (i < src.size() && dst.size() <= maxlen) {
  ------------------
  |  Branch (219:16): [True: 5.62M, False: 489k]
  |  Branch (219:34): [True: 5.62M, False: 0]
  ------------------
  220|  5.62M|            size_t curr_idx = 0;
  221|  5.62M|            size_t match_len = 0;
  222|  5.62M|            uint32_t best_sub = 0xFFFFFFFF;
  223|       |
  224|  5.62M|            size_t j = i;
  225|       |            
  226|       |            // Greedily traverse the trie to find the longest matching sequence
  227|  5.62M|            while (j < src.size()) {
  ------------------
  |  Branch (227:20): [True: 5.62M, False: 173]
  ------------------
  228|  5.62M|                uint8_t byte = static_cast<uint8_t>(src[j]);
  229|       |                
  230|  5.62M|                if (UseNibbles) {
  ------------------
  |  Branch (230:21): [True: 5.62M, Folded]
  ------------------
  231|  5.62M|                    IndexType r1 = nodes[curr_idx].children[(byte >> 4) & 0x0F];
  232|  5.62M|                    if (r1 == 0) break;
  ------------------
  |  Branch (232:25): [True: 5.57M, False: 51.4k]
  ------------------
  233|  51.4k|                    curr_idx += r1;
  234|       |
  235|  51.4k|                    IndexType r2 = nodes[curr_idx].children[byte & 0x0F];
  236|  51.4k|                    if (r2 == 0) break;
  ------------------
  |  Branch (236:25): [True: 49.9k, False: 1.47k]
  ------------------
  237|  1.47k|                    curr_idx += r2;
  238|  1.47k|                } else {
  239|      0|                    IndexType r = nodes[curr_idx].children[byte];
  240|      0|                    if (r == 0) break;
  ------------------
  |  Branch (240:25): [True: 0, False: 0]
  ------------------
  241|      0|                    curr_idx += r;
  242|      0|                }
  243|       |                
  244|  1.47k|                ++j;
  245|       |                
  246|       |                // Track the deepest valid match found during traversal
  247|  1.47k|                if (sub_info_arena[curr_idx] != 0xFFFFFFFF) {
  ------------------
  |  Branch (247:21): [True: 405, False: 1.06k]
  ------------------
  248|    405|                    best_sub = sub_info_arena[curr_idx];
  249|    405|                    match_len = j - i;
  250|    405|                }
  251|  1.47k|            }
  252|       |
  253|  5.62M|            if (best_sub != 0xFFFFFFFF) {
  ------------------
  |  Branch (253:17): [True: 405, False: 5.62M]
  ------------------
  254|       |                // Decode the 24-bit offset and 8-bit size, append directly from arena
  255|    405|                dst.append(&char_arena[best_sub >> 8], best_sub & 0xFF);
  256|    405|                i += match_len;
  257|    405|                any_substituted = true; // State update: Substitution occurred
  258|  5.62M|            } else {
  259|       |                // Fallback: copy unmapped character directly to output
  260|  5.62M|                dst.push_back(src[i]);
  261|  5.62M|                ++i;
  262|  5.62M|                any_copied = true; // State update: Verbatim copy occurred
  263|  5.62M|            }
  264|  5.62M|        }
  265|       |        
  266|       |        // ALGORITHM: Outcome Evaluation
  267|   489k|        if (any_substituted && any_copied) {
  ------------------
  |  Branch (267:13): [True: 263, False: 489k]
  |  Branch (267:32): [True: 256, False: 7]
  ------------------
  268|    256|            return TranscodeResult::Partial;
  269|   489k|        } else if (any_substituted) {
  ------------------
  |  Branch (269:20): [True: 7, False: 489k]
  ------------------
  270|      7|            return TranscodeResult::All;
  271|      7|        }
  272|       |        
  273|   489k|        return TranscodeResult::None;
  274|   489k|    }

_ZN10SuggestMgrC2ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEjP8AffixMgr:
   87|     38|SuggestMgr::SuggestMgr(const std::string& tryme, unsigned int maxn, AffixMgr* aptr) {
   88|       |  // register affix manager and check in string of chars to
   89|       |  // try when building candidate suggestions
   90|     38|  pAMgr = aptr;
   91|       |
   92|     38|  csconv = nullptr;
   93|       |
   94|     38|  ckeyl = 0;
   95|       |
   96|     38|  ctryl = 0;
   97|       |
   98|     38|  utf8 = 0;
   99|     38|  langnum = 0;
  100|     38|  complexprefixes = 0;
  101|       |
  102|     38|  maxSug = maxn;
  103|     38|  nosplitsugs = 0;
  104|     38|  maxngramsugs = MAXNGRAMSUGS;
  ------------------
  |  |   77|     38|#define MAXNGRAMSUGS 4
  ------------------
  105|     38|  maxcpdsugs = MAXCOMPOUNDSUGS;
  ------------------
  |  |   79|     38|#define MAXCOMPOUNDSUGS 3
  ------------------
  106|       |
  107|     38|  if (pAMgr) {
  ------------------
  |  Branch (107:7): [True: 38, False: 0]
  ------------------
  108|     38|    langnum = pAMgr->get_langnum();
  109|     38|    ckey = pAMgr->get_key_string();
  110|     38|    nosplitsugs = pAMgr->get_nosplitsugs();
  111|     38|    if (pAMgr->get_maxngramsugs() >= 0)
  ------------------
  |  Branch (111:9): [True: 4, False: 34]
  ------------------
  112|      4|      maxngramsugs = pAMgr->get_maxngramsugs();
  113|     38|    utf8 = pAMgr->get_utf8();
  114|     38|    if (pAMgr->get_maxcpdsugs() >= 0)
  ------------------
  |  Branch (114:9): [True: 0, False: 38]
  ------------------
  115|      0|      maxcpdsugs = pAMgr->get_maxcpdsugs();
  116|     38|    if (!utf8) {
  ------------------
  |  Branch (116:9): [True: 20, False: 18]
  ------------------
  117|     20|      csconv = get_current_cs(pAMgr->get_encoding());
  118|     20|    }
  119|     38|    complexprefixes = pAMgr->get_complexprefixes();
  120|     38|  }
  121|       |
  122|     38|  if (!ckey.empty()) {
  ------------------
  |  Branch (122:7): [True: 38, False: 0]
  ------------------
  123|     38|    if (utf8) {
  ------------------
  |  Branch (123:9): [True: 18, False: 20]
  ------------------
  124|     18|      int len = u8_u16(ckey_utf, ckey);
  125|     18|      if (len != -1) {
  ------------------
  |  Branch (125:11): [True: 18, False: 0]
  ------------------
  126|     18|        ckeyl = len;
  127|     18|      }
  128|     20|    } else {
  129|     20|      ckeyl = ckey.size();
  130|     20|    }
  131|     38|  }
  132|       |
  133|     38|  ctry = tryme;
  134|     38|  if (!ctry.empty()) {
  ------------------
  |  Branch (134:7): [True: 2, False: 36]
  ------------------
  135|      2|    if (utf8) {
  ------------------
  |  Branch (135:9): [True: 2, False: 0]
  ------------------
  136|      2|      int len = u8_u16(ctry_utf, ctry);
  137|      2|      if (len != -1) {
  ------------------
  |  Branch (137:11): [True: 2, False: 0]
  ------------------
  138|      2|        ctryl = len;
  139|      2|      }
  140|      2|    } else {
  141|      0|      ctryl = ctry.size();
  142|      0|    }
  143|      2|  }
  144|       |
  145|       |  // language with possible dash usage
  146|       |  // (latin letters or dash in TRY characters)
  147|     38|  lang_with_dash_usage = ctry.find('-') != std::string::npos ||
  ------------------
  |  Branch (147:26): [True: 0, False: 38]
  ------------------
  148|     38|                         ctry.find('a') != std::string::npos;
  ------------------
  |  Branch (148:26): [True: 0, False: 38]
  ------------------
  149|     38|}
_ZN10SuggestMgr7testsugERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iPiPNS0_6chrono10time_pointINSE_12steady_clockENSE_8durationIxNS0_5ratioILl1ELl1000000000EEEEEEERi:
  166|  85.4M|                        int& info) {
  167|  85.4M|  if (wlst.size() == maxSug)
  ------------------
  |  Branch (167:7): [True: 0, False: 85.4M]
  ------------------
  168|      0|    return;
  169|       |
  170|  85.4M|  const int cwrd = std::find(wlst.begin(), wlst.end(), candidate) != wlst.end() ? 0 : 1;
  ------------------
  |  Branch (170:20): [True: 31.8k, False: 85.4M]
  ------------------
  171|       |
  172|  85.4M|  if (cwrd) {
  ------------------
  |  Branch (172:7): [True: 85.4M, False: 31.8k]
  ------------------
  173|  85.4M|    if (int result = checkword(candidate, cpdsuggest, timer, timelimit)) {
  ------------------
  |  Branch (173:13): [True: 2.02k, False: 85.4M]
  ------------------
  174|       |      // compound word in the dictionary
  175|  2.02k|      if (cpdsuggest == 0 && result >= 2)
  ------------------
  |  Branch (175:11): [True: 2.02k, False: 0]
  |  Branch (175:30): [True: 1, False: 2.01k]
  ------------------
  176|      1|          info |= SPELL_COMPOUND;
  ------------------
  |  |   81|      1|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
  177|  2.02k|      wlst.push_back(candidate);
  178|  2.02k|    }
  179|  85.4M|  }
  180|  85.4M|}
_ZN10SuggestMgr7suggestERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_Pib:
  190|   152k|                        int* onlycompoundsug, bool test_simplesug) {
  191|   152k|  int nocompoundtwowords = 0; // no second or third loops, see below
  192|   152k|  std::vector<w_char> word_utf;
  193|   152k|  size_t nsugorig = slst.size(), oldSug = 0;
  194|   152k|  std::string w2;
  195|   152k|  bool good_suggestion = false;
  196|       |
  197|       |  // word reversing wrapper for complex prefixes
  198|   152k|  if (complexprefixes) {
  ------------------
  |  Branch (198:7): [True: 8.83k, False: 144k]
  ------------------
  199|  8.83k|    w2.assign(w);
  200|  8.83k|    if (utf8)
  ------------------
  |  Branch (200:9): [True: 0, False: 8.83k]
  ------------------
  201|      0|      reverseword_utf(w2);
  202|  8.83k|    else
  203|  8.83k|      reverseword(w2);
  204|  8.83k|  }
  205|       |
  206|   152k|  const std::string& word = complexprefixes ? w2 : w;
  ------------------
  |  Branch (206:29): [True: 8.83k, False: 144k]
  ------------------
  207|       |
  208|   152k|  suggest_start = std::chrono::steady_clock::now();
  209|       |
  210|   152k|  if (utf8) {
  ------------------
  |  Branch (210:7): [True: 64.3k, False: 88.5k]
  ------------------
  211|  64.3k|    int wl = u8_u16(word_utf, word);
  212|  64.3k|    if (wl == -1) {
  ------------------
  |  Branch (212:9): [True: 10.1k, False: 54.1k]
  ------------------
  213|  10.1k|      return false;
  214|  10.1k|    }
  215|  64.3k|  }
  216|       |
  217|       |  // three loops:
  218|       |  // - the first without compounding,
  219|       |  // - the second one with 2-word compounding,
  220|       |  // - the third one with 3-or-more-word compounding
  221|       |  // Run second and third loops only if:
  222|       |  // - no ~good suggestion in the first loop
  223|       |  // - not for testing compound words with 3 or more words (test_simplesug == false)
  224|   142k|  int info = 0;
  225|   569k|  for (int cpdsuggest = 0; cpdsuggest < 3 && nocompoundtwowords == 0; cpdsuggest++) {
  ------------------
  |  Branch (225:28): [True: 427k, False: 142k]
  |  Branch (225:46): [True: 427k, False: 205]
  ------------------
  226|       |
  227|       |    // limit compound suggestion
  228|   427k|    if (cpdsuggest > 0)
  ------------------
  |  Branch (228:9): [True: 284k, False: 142k]
  ------------------
  229|   284k|      oldSug = slst.size();
  230|       |
  231|       |    // suggestions for an uppercase word (html -> HTML)
  232|   427k|    if (slst.size() < maxSug) {
  ------------------
  |  Branch (232:9): [True: 427k, False: 15]
  ------------------
  233|   427k|      size_t i = slst.size();
  234|   427k|      if (utf8)
  ------------------
  |  Branch (234:11): [True: 162k, False: 265k]
  ------------------
  235|   162k|        capchars_utf(slst, word_utf, cpdsuggest, info);
  236|   265k|      else
  237|   265k|        capchars(slst, word, cpdsuggest, info);
  238|   427k|      if (slst.size() > i)
  ------------------
  |  Branch (238:11): [True: 204, False: 427k]
  ------------------
  239|    204|        good_suggestion = true;
  240|   427k|    }
  241|       |
  242|       |    // perhaps we made a typical fault of spelling
  243|   427k|    if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (243:9): [True: 427k, False: 15]
  |  Branch (243:36): [True: 142k, False: 284k]
  |  Branch (243:51): [True: 284k, False: 0]
  ------------------
  244|   427k|      size_t i = slst.size();
  245|   427k|      replchars(slst, word, cpdsuggest, info);
  246|   427k|      if (slst.size() > i) {
  ------------------
  |  Branch (246:11): [True: 0, False: 427k]
  ------------------
  247|      0|        good_suggestion = true;
  248|      0|        if (info & SPELL_BEST_SUG)
  ------------------
  |  |   89|      0|#define SPELL_BEST_SUG (1 << 8)    // limit suggestions for the best ones, i.e. ph:
  ------------------
  |  Branch (248:13): [True: 0, False: 0]
  ------------------
  249|      0|          return true;
  250|      0|      }
  251|   427k|    }
  252|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (252:9): [True: 0, False: 427k]
  ------------------
  253|      0|      return good_suggestion;
  254|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (254:9): [True: 0, False: 427k]
  |  Branch (254:27): [True: 0, False: 0]
  ------------------
  255|      0|      return true;
  256|       |
  257|       |    // perhaps we made chose the wrong char from a related set
  258|   427k|    if ((slst.size() < maxSug) &&
  ------------------
  |  Branch (258:9): [True: 427k, False: 15]
  ------------------
  259|   427k|        (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (259:10): [True: 142k, False: 284k]
  |  Branch (259:25): [True: 284k, False: 0]
  ------------------
  260|   427k|      mapchars(slst, word, cpdsuggest, info);
  261|   427k|    }
  262|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (262:9): [True: 2, False: 427k]
  ------------------
  263|      2|      return good_suggestion;
  264|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (264:9): [True: 0, False: 427k]
  |  Branch (264:27): [True: 0, False: 0]
  ------------------
  265|      0|      return true;
  266|       |
  267|       |    // only suggest compound words when no other ~good suggestion
  268|   427k|    if ((cpdsuggest == 0) && (slst.size() > nsugorig))
  ------------------
  |  Branch (268:9): [True: 142k, False: 284k]
  |  Branch (268:30): [True: 204, False: 142k]
  ------------------
  269|    204|      nocompoundtwowords = 1;
  270|       |
  271|       |    // did we swap the order of chars by mistake
  272|   427k|    if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (272:9): [True: 427k, False: 15]
  |  Branch (272:36): [True: 142k, False: 284k]
  |  Branch (272:51): [True: 284k, False: 0]
  ------------------
  273|   427k|      if (utf8)
  ------------------
  |  Branch (273:11): [True: 162k, False: 265k]
  ------------------
  274|   162k|        swapchar_utf(slst, word_utf, cpdsuggest, info);
  275|   265k|      else
  276|   265k|        swapchar(slst, word, cpdsuggest, info);
  277|   427k|    }
  278|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (278:9): [True: 0, False: 427k]
  ------------------
  279|      0|      return good_suggestion;
  280|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (280:9): [True: 0, False: 427k]
  |  Branch (280:27): [True: 0, False: 0]
  ------------------
  281|      0|      return true;
  282|       |
  283|       |    // did we swap the order of non adjacent chars by mistake
  284|   427k|    if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (284:9): [True: 427k, False: 15]
  |  Branch (284:36): [True: 142k, False: 284k]
  |  Branch (284:51): [True: 284k, False: 0]
  ------------------
  285|   427k|      if (utf8)
  ------------------
  |  Branch (285:11): [True: 162k, False: 265k]
  ------------------
  286|   162k|        longswapchar_utf(slst, word_utf, cpdsuggest, info);
  287|   265k|      else
  288|   265k|        longswapchar(slst, word, cpdsuggest, info);
  289|   427k|    }
  290|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (290:9): [True: 0, False: 427k]
  ------------------
  291|      0|      return good_suggestion;
  292|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (292:9): [True: 0, False: 427k]
  |  Branch (292:27): [True: 0, False: 0]
  ------------------
  293|      0|      return true;
  294|       |
  295|       |    // did we just hit the wrong key in place of a good char (case and keyboard)
  296|   427k|    if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (296:9): [True: 427k, False: 15]
  |  Branch (296:36): [True: 142k, False: 284k]
  |  Branch (296:51): [True: 284k, False: 0]
  ------------------
  297|   427k|      if (utf8)
  ------------------
  |  Branch (297:11): [True: 162k, False: 265k]
  ------------------
  298|   162k|        badcharkey_utf(slst, word_utf, cpdsuggest, info);
  299|   265k|      else
  300|   265k|        badcharkey(slst, word, cpdsuggest, info);
  301|   427k|    }
  302|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (302:9): [True: 0, False: 427k]
  ------------------
  303|      0|      return good_suggestion;
  304|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (304:9): [True: 0, False: 427k]
  |  Branch (304:27): [True: 0, False: 0]
  ------------------
  305|      0|      return true;
  306|       |
  307|       |    // did we add a char that should not be there
  308|   427k|    if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (308:9): [True: 427k, False: 15]
  |  Branch (308:36): [True: 142k, False: 284k]
  |  Branch (308:51): [True: 284k, False: 0]
  ------------------
  309|   427k|      if (utf8)
  ------------------
  |  Branch (309:11): [True: 162k, False: 265k]
  ------------------
  310|   162k|        extrachar_utf(slst, word_utf, cpdsuggest, info);
  311|   265k|      else
  312|   265k|        extrachar(slst, word, cpdsuggest, info);
  313|   427k|    }
  314|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (314:9): [True: 0, False: 427k]
  ------------------
  315|      0|      return good_suggestion;
  316|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (316:9): [True: 0, False: 427k]
  |  Branch (316:27): [True: 0, False: 0]
  ------------------
  317|      0|      return true;
  318|       |
  319|       |    // did we forgot a char
  320|   427k|    if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (320:9): [True: 427k, False: 15]
  |  Branch (320:36): [True: 142k, False: 284k]
  |  Branch (320:51): [True: 284k, False: 0]
  ------------------
  321|   427k|      if (utf8)
  ------------------
  |  Branch (321:11): [True: 162k, False: 265k]
  ------------------
  322|   162k|        forgotchar_utf(slst, word_utf, cpdsuggest, info);
  323|   265k|      else
  324|   265k|        forgotchar(slst, word, cpdsuggest, info);
  325|   427k|    }
  326|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (326:9): [True: 0, False: 427k]
  ------------------
  327|      0|      return good_suggestion;
  328|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (328:9): [True: 0, False: 427k]
  |  Branch (328:27): [True: 0, False: 0]
  ------------------
  329|      0|      return true;
  330|       |
  331|       |    // did we move a char
  332|   427k|    if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (332:9): [True: 427k, False: 15]
  |  Branch (332:36): [True: 142k, False: 284k]
  |  Branch (332:51): [True: 284k, False: 0]
  ------------------
  333|   427k|      if (utf8)
  ------------------
  |  Branch (333:11): [True: 162k, False: 265k]
  ------------------
  334|   162k|        movechar_utf(slst, word_utf, cpdsuggest, info);
  335|   265k|      else
  336|   265k|        movechar(slst, word, cpdsuggest, info);
  337|   427k|    }
  338|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (338:9): [True: 0, False: 427k]
  ------------------
  339|      0|      return good_suggestion;
  340|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (340:9): [True: 0, False: 427k]
  |  Branch (340:27): [True: 0, False: 0]
  ------------------
  341|      0|      return true;
  342|       |
  343|       |    // did we just hit the wrong key in place of a good char
  344|   427k|    if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (344:9): [True: 427k, False: 15]
  |  Branch (344:36): [True: 142k, False: 284k]
  |  Branch (344:51): [True: 284k, False: 0]
  ------------------
  345|   427k|      if (utf8)
  ------------------
  |  Branch (345:11): [True: 162k, False: 265k]
  ------------------
  346|   162k|        badchar_utf(slst, word_utf, cpdsuggest, info);
  347|   265k|      else
  348|   265k|        badchar(slst, word, cpdsuggest, info);
  349|   427k|    }
  350|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (350:9): [True: 0, False: 427k]
  ------------------
  351|      0|      return good_suggestion;
  352|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (352:9): [True: 0, False: 427k]
  |  Branch (352:27): [True: 0, False: 0]
  ------------------
  353|      0|      return true;
  354|       |
  355|       |    // did we double two characters
  356|   427k|    if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
  ------------------
  |  Branch (356:9): [True: 427k, False: 15]
  |  Branch (356:36): [True: 142k, False: 284k]
  |  Branch (356:51): [True: 284k, False: 0]
  ------------------
  357|   427k|      if (utf8)
  ------------------
  |  Branch (357:11): [True: 162k, False: 265k]
  ------------------
  358|   162k|        doubletwochars_utf(slst, word_utf, cpdsuggest, info);
  359|   265k|      else
  360|   265k|        doubletwochars(slst, word, cpdsuggest, info);
  361|   427k|    }
  362|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (362:9): [True: 0, False: 427k]
  ------------------
  363|      0|      return good_suggestion;
  364|   427k|    if (test_simplesug && slst.size())
  ------------------
  |  Branch (364:9): [True: 0, False: 427k]
  |  Branch (364:27): [True: 0, False: 0]
  ------------------
  365|      0|      return true;
  366|       |
  367|       |    // perhaps we forgot to hit space and two words ran together
  368|       |    // (dictionary word pairs have top priority here, so
  369|       |    // we always suggest them, in despite of nosplitsugs, and
  370|       |    // drop compound word and other suggestions)
  371|   427k|    if (!cpdsuggest || (!nosplitsugs && slst.size() < oldSug + maxcpdsugs)) {
  ------------------
  |  Branch (371:9): [True: 142k, False: 284k]
  |  Branch (371:25): [True: 284k, False: 0]
  |  Branch (371:41): [True: 284k, False: 0]
  ------------------
  372|   427k|      good_suggestion = twowords(slst, word, cpdsuggest, good_suggestion, info);
  373|       |
  374|   427k|      if (info & SPELL_BEST_SUG)
  ------------------
  |  |   89|   427k|#define SPELL_BEST_SUG (1 << 8)    // limit suggestions for the best ones, i.e. ph:
  ------------------
  |  Branch (374:11): [True: 144, False: 427k]
  ------------------
  375|    144|        return true;
  376|   427k|    }
  377|   427k|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   427k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (377:9): [True: 0, False: 427k]
  ------------------
  378|      0|      return good_suggestion;
  379|       |
  380|       |    // testing returns after the first loop
  381|   427k|    if (test_simplesug)
  ------------------
  |  Branch (381:9): [True: 0, False: 427k]
  ------------------
  382|      0|      return slst.size() > 0;
  383|       |
  384|       |    // don't need third loop, if the second loop was successful or
  385|       |    // the first loop found a dictionary-based compound word
  386|       |    // (we don't need more, likely worse and false 3-or-more-word compound words)
  387|   427k|    if (cpdsuggest == 1 && (slst.size() > oldSug || (info & SPELL_COMPOUND)))
  ------------------
  |  |   81|   142k|#define SPELL_COMPOUND (1 << 0)    // the result is a compound word
  ------------------
  |  Branch (387:9): [True: 142k, False: 284k]
  |  Branch (387:29): [True: 0, False: 142k]
  |  Branch (387:53): [True: 1, False: 142k]
  ------------------
  388|      1|       nocompoundtwowords = 1;
  389|       |
  390|   427k|  }  // repeating ``for'' statement compounding support
  391|       |
  392|   142k|  if (!nocompoundtwowords && (!slst.empty()) && onlycompoundsug)
  ------------------
  |  Branch (392:7): [True: 142k, False: 205]
  |  Branch (392:30): [True: 17.8k, False: 124k]
  |  Branch (392:49): [True: 17.8k, False: 0]
  ------------------
  393|  17.8k|    *onlycompoundsug = 1;
  394|       |
  395|   142k|  return good_suggestion;
  396|   142k|}
_ZN10SuggestMgr12capchars_utfERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKNS1_I6w_charNS5_ISB_EEEEiRi:
  401|   162k|                              int cpdsuggest, int& info) {
  402|   162k|  std::vector<w_char> candidate_utf(word);
  403|   162k|  mkallcap_utf(candidate_utf, langnum);
  404|   162k|  std::string candidate;
  405|   162k|  u16_u8(candidate, candidate_utf);
  406|   162k|  testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  407|   162k|}
_ZN10SuggestMgr8capcharsERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
  412|   265k|                          int cpdsuggest, int& info) {
  413|   265k|  std::string candidate(word);
  414|   265k|  mkallcap(candidate, csconv);
  415|   265k|  testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  416|   265k|}
_ZN10SuggestMgr8mapcharsERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
  421|   427k|                            int cpdsuggest, int& info) {
  422|   427k|  std::string candidate;
  423|   427k|  std::chrono::steady_clock::time_point timelimit;
  424|   427k|  int timer;
  425|       |
  426|   427k|  if (word.size() < 2 || !pAMgr)
  ------------------
  |  Branch (426:7): [True: 32.5k, False: 394k]
  |  Branch (426:26): [True: 0, False: 394k]
  ------------------
  427|  32.5k|    return wlst.size();
  428|       |
  429|   394k|  const std::vector<mapentry>& maptable = pAMgr->get_maptable();
  430|   394k|  if (maptable.empty())
  ------------------
  |  Branch (430:7): [True: 378k, False: 16.2k]
  ------------------
  431|   378k|    return wlst.size();
  432|       |
  433|  16.2k|  timelimit = std::chrono::steady_clock::now();
  434|  16.2k|  timer = MINTIMER;
  ------------------
  |  |  110|  16.2k|#define MINTIMER 100
  ------------------
  435|  16.2k|  return map_related(word, candidate, 0, wlst, cpdsuggest,
  436|  16.2k|                     maptable, &timer, &timelimit, 0, info);
  437|   394k|}
_ZN10SuggestMgr11map_relatedERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERS6_mRNS0_6vectorIS6_NS4_IS6_EEEEiRKNSA_ISC_NS4_ISC_EEEEPiPNS0_6chrono10time_pointINSJ_12steady_clockENSJ_8durationIxNS0_5ratioILl1ELl1000000000EEEEEEEiRi:
  447|  2.00M|                               int depth, int& info) {
  448|  2.00M|  if (word.size() == wn) {
  ------------------
  |  Branch (448:7): [True: 1.12M, False: 881k]
  ------------------
  449|  1.12M|    if (candidate == word)
  ------------------
  |  Branch (449:9): [True: 16.2k, False: 1.11M]
  ------------------
  450|  16.2k|      return wlst.size();
  451|  1.11M|    const int cwrd = std::find(wlst.begin(), wlst.end(), candidate) != wlst.end() ? 0 : 1;
  ------------------
  |  Branch (451:22): [True: 0, False: 1.11M]
  ------------------
  452|  1.11M|    if ((cwrd) && checkword(candidate, cpdsuggest, timer, timelimit)) {
  ------------------
  |  Branch (452:9): [True: 1.11M, False: 0]
  |  Branch (452:19): [True: 0, False: 1.11M]
  ------------------
  453|      0|      if (wlst.size() < maxSug) {
  ------------------
  |  Branch (453:11): [True: 0, False: 0]
  ------------------
  454|      0|        wlst.push_back(candidate);
  455|      0|      }
  456|      0|    }
  457|  1.11M|    return wlst.size();
  458|  1.12M|  }
  459|       |
  460|   881k|  if (depth > 0x3F00) {
  ------------------
  |  Branch (460:7): [True: 0, False: 881k]
  ------------------
  461|      0|    *timer = 0;
  462|      0|    return wlst.size();
  463|      0|  }
  464|       |
  465|   881k|  int in_map = 0;
  466|  3.52M|  for (size_t j = 0; j < maptable.size(); ++j) {
  ------------------
  |  Branch (466:22): [True: 2.64M, False: 881k]
  ------------------
  467|  9.69M|    for (size_t k = 0; k < maptable[j].size(); ++k) {
  ------------------
  |  Branch (467:24): [True: 7.04M, False: 2.64M]
  ------------------
  468|  7.04M|      size_t len = maptable[j][k].size();
  469|  7.04M|      if (len && word.compare(wn, len, maptable[j][k]) == 0) {
  ------------------
  |  Branch (469:11): [True: 7.04M, False: 0]
  |  Branch (469:18): [True: 555k, False: 6.49M]
  ------------------
  470|   555k|        in_map = 1;
  471|   555k|        size_t cn = candidate.size();
  472|  2.22M|        for (size_t l = 0; l < maptable[j].size(); ++l) {
  ------------------
  |  Branch (472:28): [True: 1.66M, False: 555k]
  ------------------
  473|  1.66M|          candidate.resize(cn);
  474|  1.66M|          candidate.append(maptable[j][l]);
  475|  1.66M|          map_related(word, candidate, wn + len, wlst,
  476|  1.66M|                           cpdsuggest, maptable, timer, timelimit, depth + 1, info);
  477|  1.66M|          if (!(*timer))
  ------------------
  |  Branch (477:15): [True: 239, False: 1.66M]
  ------------------
  478|    239|            return wlst.size();
  479|  1.66M|          if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS) {
  ------------------
  |  |  108|  1.66M|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (479:15): [True: 2, False: 1.66M]
  ------------------
  480|      2|            *timer = 0;
  481|      2|            return wlst.size();
  482|      2|          }
  483|  1.66M|        }
  484|   555k|      }
  485|  7.04M|    }
  486|  2.64M|  }
  487|   881k|  if (!in_map) {
  ------------------
  |  Branch (487:7): [True: 325k, False: 555k]
  ------------------
  488|   325k|    candidate.push_back(word[wn]);
  489|   325k|    map_related(word, candidate, wn + 1, wlst, cpdsuggest,
  490|   325k|                maptable, timer, timelimit, depth + 1, info);
  491|   325k|  }
  492|   881k|  return wlst.size();
  493|   881k|}
_ZN10SuggestMgr9replcharsERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
  499|   427k|                             int cpdsuggest, int& info) {
  500|   427k|  std::string candidate;
  501|   427k|  size_t wl = word.size();
  502|   427k|  if (wl < 2 || !pAMgr)
  ------------------
  |  Branch (502:7): [True: 32.5k, False: 394k]
  |  Branch (502:17): [True: 0, False: 394k]
  ------------------
  503|  32.5k|    return wlst.size();
  504|   394k|  const std::vector<replentry>& reptable = pAMgr->get_reptable();
  505|   394k|  auto replchars_start = std::chrono::steady_clock::now();
  506|   394k|  for (const auto& entry : reptable) {
  ------------------
  |  Branch (506:26): [True: 82.0k, False: 394k]
  ------------------
  507|  82.0k|    size_t r = 0;
  508|       |    // search every occurence of the pattern in the word
  509|  82.0k|    while ((r = word.find(entry.pattern, r)) != std::string::npos) {
  ------------------
  |  Branch (509:12): [True: 6, False: 82.0k]
  ------------------
  510|      6|      if (std::chrono::steady_clock::now() - replchars_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|      6|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (510:11): [True: 0, False: 6]
  ------------------
  511|      0|        return wlst.size();
  512|      6|      int type = (r == 0) ? 1 : 0;
  ------------------
  |  Branch (512:18): [True: 0, False: 6]
  ------------------
  513|      6|      if (r + entry.pattern.size() == word.size())
  ------------------
  |  Branch (513:11): [True: 0, False: 6]
  ------------------
  514|      0|        type += 2;
  515|      6|      while (type && entry.outstrings[type].empty())
  ------------------
  |  Branch (515:14): [True: 0, False: 6]
  |  Branch (515:22): [True: 0, False: 0]
  ------------------
  516|      0|        type = (type == 2 && r != 0) ? 0 : type - 1;
  ------------------
  |  Branch (516:17): [True: 0, False: 0]
  |  Branch (516:30): [True: 0, False: 0]
  ------------------
  517|      6|      const std::string&out = entry.outstrings[type];
  518|      6|      if (out.empty()) {
  ------------------
  |  Branch (518:11): [True: 0, False: 6]
  ------------------
  519|      0|        ++r;
  520|      0|        continue;
  521|      0|      }
  522|      6|      candidate.assign(word, 0, r);
  523|      6|      candidate.append(entry.outstrings[type]);
  524|      6|      candidate.append(word, r + entry.pattern.size(), std::string::npos);
  525|      6|      size_t sp = candidate.find(' ');
  526|      6|      size_t oldns = wlst.size();
  527|      6|      testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  528|      6|      if (oldns < wlst.size()) {
  ------------------
  |  Branch (528:11): [True: 0, False: 6]
  ------------------
  529|       |        // REP suggestions are the best, don't search other type of suggestions
  530|      0|        info |= SPELL_BEST_SUG;
  ------------------
  |  |   89|      0|#define SPELL_BEST_SUG (1 << 8)    // limit suggestions for the best ones, i.e. ph:
  ------------------
  531|      0|      }
  532|       |
  533|       |      // check REP suggestions with space
  534|      6|      if (sp != std::string::npos) {
  ------------------
  |  Branch (534:11): [True: 0, False: 6]
  ------------------
  535|      0|        size_t prev = 0;
  536|      0|        while (sp != std::string::npos) {
  ------------------
  |  Branch (536:16): [True: 0, False: 0]
  ------------------
  537|      0|          std::string prev_chunk = candidate.substr(prev, sp - prev);
  538|      0|          if (checkword(prev_chunk, 0, nullptr, nullptr)) {
  ------------------
  |  Branch (538:15): [True: 0, False: 0]
  ------------------
  539|      0|            oldns = wlst.size();
  540|      0|            std::string post_chunk = candidate.substr(sp + 1);
  541|      0|            testsug(wlst, post_chunk, cpdsuggest, nullptr, nullptr, info);
  542|      0|            if (oldns < wlst.size()) {
  ------------------
  |  Branch (542:17): [True: 0, False: 0]
  ------------------
  543|      0|              wlst[wlst.size() - 1] = candidate;
  544|      0|            }
  545|      0|          }
  546|      0|          prev = sp + 1;
  547|      0|          sp = candidate.find(' ', prev);
  548|      0|        }
  549|      0|      }
  550|      6|      r++;  // search for the next letter
  551|      6|    }
  552|  82.0k|  }
  553|   394k|  return wlst.size();
  554|   394k|}
_ZN10SuggestMgr14doubletwocharsERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
  563|   265k|                                  int cpdsuggest, int& info) {
  564|   265k|  size_t wl = word.size();
  565|   265k|  if (wl < 5 || !pAMgr)
  ------------------
  |  Branch (565:7): [True: 52.2k, False: 212k]
  |  Branch (565:17): [True: 0, False: 212k]
  ------------------
  566|  52.2k|    return wlst.size();
  567|       |
  568|   212k|  int state = 0;
  569|  5.06M|  for (size_t i = 2; i < wl; ++i) {
  ------------------
  |  Branch (569:22): [True: 4.85M, False: 212k]
  ------------------
  570|  4.85M|    if (word[i] == word[i - 2]) {
  ------------------
  |  Branch (570:9): [True: 1.18M, False: 3.66M]
  ------------------
  571|  1.18M|      state++;
  572|  1.18M|      if (state == 3 || (state == 2 && i >= 4)) {
  ------------------
  |  Branch (572:11): [True: 5.72k, False: 1.17M]
  |  Branch (572:26): [True: 411k, False: 767k]
  |  Branch (572:40): [True: 402k, False: 8.93k]
  ------------------
  573|   408k|        auto word_iter = word.begin();
  574|   408k|        std::string candidate(word_iter, word_iter + i - 1);
  575|   408k|        candidate.insert(candidate.end(), word_iter + i + 1, word.end());
  576|   408k|        testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  577|   408k|        state = 0;
  578|   408k|      }
  579|  3.66M|    } else {
  580|  3.66M|      state = 0;
  581|  3.66M|    }
  582|  4.85M|  }
  583|   212k|  return wlst.size();
  584|   265k|}
_ZN10SuggestMgr18doubletwochars_utfERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKNS1_I6w_charNS5_ISB_EEEEiRi:
  593|   162k|                                      int cpdsuggest, int& info) {
  594|   162k|  size_t wl = word.size();
  595|   162k|  int state = 0;
  596|   162k|  if (wl < 5 || !pAMgr)
  ------------------
  |  Branch (596:7): [True: 56.9k, False: 105k]
  |  Branch (596:17): [True: 0, False: 105k]
  ------------------
  597|  56.9k|    return wlst.size();
  598|  1.73M|  for (size_t i = 2; i < wl; ++i) {
  ------------------
  |  Branch (598:22): [True: 1.62M, False: 105k]
  ------------------
  599|  1.62M|    if (word[i] == word[i - 2]) {
  ------------------
  |  Branch (599:9): [True: 471k, False: 1.15M]
  ------------------
  600|   471k|      state++;
  601|   471k|      if (state == 3 || (state == 2 && i >= 4)) {
  ------------------
  |  Branch (601:11): [True: 3.24k, False: 468k]
  |  Branch (601:26): [True: 160k, False: 307k]
  |  Branch (601:40): [True: 155k, False: 5.16k]
  ------------------
  602|   158k|        auto word_iter = word.begin();
  603|   158k|        std::vector<w_char> candidate_utf(word_iter, word_iter + i - 1);
  604|   158k|        candidate_utf.insert(candidate_utf.end(), word_iter + i + 1, word.end());
  605|   158k|        std::string candidate;
  606|   158k|        u16_u8(candidate, candidate_utf);
  607|   158k|        testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  608|   158k|        state = 0;
  609|   158k|      }
  610|  1.15M|    } else {
  611|  1.15M|      state = 0;
  612|  1.15M|    }
  613|  1.62M|  }
  614|   105k|  return wlst.size();
  615|   162k|}
_ZN10SuggestMgr10badcharkeyERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
  621|   265k|                              int cpdsuggest, int& info) {
  622|   265k|  std::string candidate(word);
  623|       |
  624|       |  // swap out each char one by one and try uppercase and neighbor
  625|       |  // keyboard chars in its place to see if that makes a good word
  626|  5.66M|  for (size_t i = 0, wl = candidate.size(); i < wl; ++i) {
  ------------------
  |  Branch (626:45): [True: 5.39M, False: 265k]
  ------------------
  627|  5.39M|    char tmpc = candidate[i];
  628|       |    // check with uppercase letters
  629|  5.39M|    candidate[i] = csconv[((unsigned char)tmpc)].cupper;
  630|  5.39M|    if (tmpc != candidate[i]) {
  ------------------
  |  Branch (630:9): [True: 1.38M, False: 4.01M]
  ------------------
  631|  1.38M|      testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  632|  1.38M|      candidate[i] = tmpc;
  633|  1.38M|    }
  634|       |    // check neighbor characters in keyboard string
  635|  5.39M|    if (ckey.empty())
  ------------------
  |  Branch (635:9): [True: 0, False: 5.39M]
  ------------------
  636|      0|      continue;
  637|  5.39M|    size_t loc = 0;
  638|   140M|    while ((loc < ckeyl) && ckey[loc] != tmpc)
  ------------------
  |  Branch (638:12): [True: 136M, False: 4.42M]
  |  Branch (638:29): [True: 135M, False: 970k]
  ------------------
  639|   135M|      ++loc;
  640|  6.40M|    while (loc < ckeyl) {
  ------------------
  |  Branch (640:12): [True: 1.00M, False: 5.39M]
  ------------------
  641|       |      // a long keyboard string can hold many neighbours for this
  642|       |      // character, so give up once the overall time budget is spent
  643|  1.00M|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|  1.00M|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (643:11): [True: 0, False: 1.00M]
  ------------------
  644|      0|        return wlst.size();
  645|  1.00M|      if ((loc > 0) && ckey[loc - 1] != '|') {
  ------------------
  |  Branch (645:11): [True: 834k, False: 170k]
  |  Branch (645:24): [True: 798k, False: 35.8k]
  ------------------
  646|   798k|        candidate[i] = ckey[loc - 1];
  647|   798k|        testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  648|   798k|      }
  649|  1.00M|      if (((loc + 1) < ckeyl) && (ckey[loc + 1] != '|')) {
  ------------------
  |  Branch (649:11): [True: 903k, False: 101k]
  |  Branch (649:34): [True: 806k, False: 97.0k]
  ------------------
  650|   806k|        candidate[i] = ckey[loc + 1];
  651|   806k|        testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  652|   806k|      }
  653|  15.6M|      do {
  654|  15.6M|        loc++;
  655|  15.6M|      } while ((loc < ckeyl) && ckey[loc] != tmpc);
  ------------------
  |  Branch (655:16): [True: 14.6M, False: 970k]
  |  Branch (655:33): [True: 14.6M, False: 33.7k]
  ------------------
  656|  1.00M|    }
  657|  5.39M|    candidate[i] = tmpc;
  658|  5.39M|  }
  659|   265k|  return wlst.size();
  660|   265k|}
_ZN10SuggestMgr14badcharkey_utfERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKNS1_I6w_charNS5_ISB_EEEEiRi:
  666|   162k|                                  int cpdsuggest, int& info) {
  667|   162k|  std::string candidate;
  668|   162k|  std::vector<w_char> candidate_utf(word);
  669|       |  // swap out each char one by one and try all the tryme
  670|       |  // chars in its place to see if that makes a good word
  671|  2.14M|  for (size_t i = 0, wl = word.size(); i < wl; ++i) {
  ------------------
  |  Branch (671:40): [True: 1.98M, False: 162k]
  ------------------
  672|  1.98M|    w_char tmpc = candidate_utf[i];
  673|       |    // check with uppercase letters
  674|  1.98M|    candidate_utf[i] = upper_utf(candidate_utf[i], 1);
  675|  1.98M|    if (tmpc != candidate_utf[i]) {
  ------------------
  |  Branch (675:9): [True: 499k, False: 1.48M]
  ------------------
  676|   499k|      u16_u8(candidate, candidate_utf);
  677|   499k|      testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  678|   499k|      candidate_utf[i] = tmpc;
  679|   499k|    }
  680|       |    // check neighbor characters in keyboard string
  681|  1.98M|    if (ckey_utf.empty())
  ------------------
  |  Branch (681:9): [True: 0, False: 1.98M]
  ------------------
  682|      0|      continue;
  683|  1.98M|    size_t loc = 0;
  684|  49.2M|    while ((loc < ckeyl) && ckey_utf[loc] != tmpc)
  ------------------
  |  Branch (684:12): [True: 47.7M, False: 1.47M]
  |  Branch (684:29): [True: 47.2M, False: 508k]
  ------------------
  685|  47.2M|      ++loc;
  686|  2.50M|    while (loc < ckeyl) {
  ------------------
  |  Branch (686:12): [True: 519k, False: 1.98M]
  ------------------
  687|       |      // a long keyboard string can hold many neighbours for this
  688|       |      // character, so give up once the overall time budget is spent
  689|   519k|      if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|   519k|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (689:11): [True: 0, False: 519k]
  ------------------
  690|      0|        return wlst.size();
  691|   519k|      if ((loc > 0) && ckey_utf[loc - 1] != W_VLINE) {
  ------------------
  |  Branch (691:11): [True: 412k, False: 107k]
  |  Branch (691:24): [True: 412k, False: 0]
  ------------------
  692|   412k|        candidate_utf[i] = ckey_utf[loc - 1];
  693|   412k|        u16_u8(candidate, candidate_utf);
  694|   412k|        testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  695|   412k|      }
  696|   519k|      if (((loc + 1) < ckeyl) && (ckey_utf[loc + 1] != W_VLINE)) {
  ------------------
  |  Branch (696:11): [True: 458k, False: 61.3k]
  |  Branch (696:34): [True: 458k, False: 0]
  ------------------
  697|   458k|        candidate_utf[i] = ckey_utf[loc + 1];
  698|   458k|        u16_u8(candidate, candidate_utf);
  699|   458k|        testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  700|   458k|      }
  701|  8.22M|      do {
  702|  8.22M|        loc++;
  703|  8.22M|      } while ((loc < ckeyl) && ckey_utf[loc] != tmpc);
  ------------------
  |  Branch (703:16): [True: 7.71M, False: 508k]
  |  Branch (703:33): [True: 7.70M, False: 11.3k]
  ------------------
  704|   519k|    }
  705|  1.98M|    candidate_utf[i] = tmpc;
  706|  1.98M|  }
  707|   162k|  return wlst.size();
  708|   162k|}
_ZN10SuggestMgr7badcharERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
  713|   265k|                                  int cpdsuggest, int& info) {
  714|   265k|  std::string candidate(word);
  715|   265k|  std::chrono::steady_clock::time_point timelimit = std::chrono::steady_clock::now();
  716|   265k|  int timer = MINTIMER;
  ------------------
  |  |  110|   265k|#define MINTIMER 100
  ------------------
  717|       |  // swap out each char one by one and try all the tryme
  718|       |  // chars in its place to see if that makes a good word
  719|   265k|  for (size_t j = 0; j < ctryl; ++j) {
  ------------------
  |  Branch (719:22): [True: 0, False: 265k]
  ------------------
  720|      0|    for (auto aI = candidate.rbegin(), aEnd = candidate.rend(); aI != aEnd; ++aI) {
  ------------------
  |  Branch (720:65): [True: 0, False: 0]
  ------------------
  721|      0|      char tmpc = *aI;
  722|      0|      if (ctry[j] == tmpc)
  ------------------
  |  Branch (722:11): [True: 0, False: 0]
  ------------------
  723|      0|        continue;
  724|      0|      *aI = ctry[j];
  725|      0|      testsug(wlst, candidate, cpdsuggest, &timer, &timelimit, info);
  726|      0|      if (!timer)
  ------------------
  |  Branch (726:11): [True: 0, False: 0]
  ------------------
  727|      0|        return wlst.size();
  728|      0|      *aI = tmpc;
  729|      0|    }
  730|      0|  }
  731|   265k|  return wlst.size();
  732|   265k|}
_ZN10SuggestMgr11badchar_utfERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKNS1_I6w_charNS5_ISB_EEEEiRi:
  737|   162k|                               int cpdsuggest, int& info) {
  738|   162k|  std::vector<w_char> candidate_utf(word);
  739|   162k|  std::string candidate;
  740|   162k|  std::chrono::steady_clock::time_point timelimit = std::chrono::steady_clock::now();
  741|   162k|  int timer = MINTIMER;
  ------------------
  |  |  110|   162k|#define MINTIMER 100
  ------------------
  742|       |  // swap out each char one by one and try all the tryme
  743|       |  // chars in its place to see if that makes a good word
  744|   180k|  for (size_t j = 0; j < ctryl; ++j) {
  ------------------
  |  Branch (744:22): [True: 18.6k, False: 162k]
  ------------------
  745|   251k|    for (auto aI = candidate_utf.rbegin(), aEnd = candidate_utf.rend(); aI != aEnd; ++aI) {
  ------------------
  |  Branch (745:73): [True: 232k, False: 18.6k]
  ------------------
  746|   232k|      w_char tmpc = *aI;
  747|   232k|      if (tmpc == ctry_utf[j])
  ------------------
  |  Branch (747:11): [True: 0, False: 232k]
  ------------------
  748|      0|        continue;
  749|   232k|      *aI = ctry_utf[j];
  750|   232k|      u16_u8(candidate, candidate_utf);
  751|   232k|      testsug(wlst, candidate, cpdsuggest, &timer, &timelimit, info);
  752|   232k|      if (!timer)
  ------------------
  |  Branch (752:11): [True: 0, False: 232k]
  ------------------
  753|      0|        return wlst.size();
  754|   232k|      *aI = tmpc;
  755|   232k|    }
  756|  18.6k|  }
  757|   162k|  return wlst.size();
  758|   162k|}
_ZN10SuggestMgr13extrachar_utfERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKNS1_I6w_charNS5_ISB_EEEEiRi:
  763|   162k|                                 int cpdsuggest, int& info) {
  764|   162k|  std::vector<w_char> candidate_utf(word);
  765|   162k|  if (candidate_utf.size() < 2)
  ------------------
  |  Branch (765:7): [True: 15.7k, False: 146k]
  ------------------
  766|  15.7k|    return wlst.size();
  767|       |  // try omitting one char of word at a time
  768|  2.11M|  for (size_t i = 0; i < candidate_utf.size(); ++i) {
  ------------------
  |  Branch (768:22): [True: 1.96M, False: 146k]
  ------------------
  769|  1.96M|    size_t index = candidate_utf.size() - 1 - i;
  770|  1.96M|    w_char tmpc = candidate_utf[index];
  771|  1.96M|    candidate_utf.erase(candidate_utf.begin() + index);
  772|  1.96M|    std::string candidate;
  773|  1.96M|    u16_u8(candidate, candidate_utf);
  774|  1.96M|    testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  775|  1.96M|    candidate_utf.insert(candidate_utf.begin() + index, tmpc);
  776|  1.96M|  }
  777|   146k|  return wlst.size();
  778|   162k|}
_ZN10SuggestMgr9extracharERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
  783|   265k|                             int cpdsuggest, int& info) {
  784|   265k|  std::string candidate(word);
  785|   265k|  if (candidate.size() < 2)
  ------------------
  |  Branch (785:7): [True: 17.3k, False: 247k]
  ------------------
  786|  17.3k|    return wlst.size();
  787|       |  // try omitting one char of word at a time
  788|  5.62M|  for (size_t i = 0; i < candidate.size(); ++i) {
  ------------------
  |  Branch (788:22): [True: 5.38M, False: 247k]
  ------------------
  789|  5.38M|    size_t index = candidate.size() - 1 - i;
  790|  5.38M|    char tmpc = candidate[index];
  791|  5.38M|    candidate.erase(candidate.begin() + index);
  792|  5.38M|    testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  793|  5.38M|    candidate.insert(candidate.begin() + index, tmpc);
  794|  5.38M|  }
  795|   247k|  return wlst.size();
  796|   265k|}
_ZN10SuggestMgr10forgotcharERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
  801|   265k|                              int cpdsuggest, int& info) {
  802|   265k|  std::string candidate(word);
  803|   265k|  std::chrono::steady_clock::time_point timelimit = std::chrono::steady_clock::now();
  804|   265k|  int timer = MINTIMER;
  ------------------
  |  |  110|   265k|#define MINTIMER 100
  ------------------
  805|       |
  806|       |  // try inserting a tryme character before every letter (and the null
  807|       |  // terminator)
  808|   265k|  for (size_t k = 0; k < ctryl; ++k) {
  ------------------
  |  Branch (808:22): [True: 0, False: 265k]
  ------------------
  809|      0|    for (size_t i = 0; i <= candidate.size(); ++i) {
  ------------------
  |  Branch (809:24): [True: 0, False: 0]
  ------------------
  810|      0|      size_t index = candidate.size() - i;
  811|      0|      candidate.insert(candidate.begin() + index, ctry[k]);
  812|      0|      testsug(wlst, candidate, cpdsuggest, &timer, &timelimit, info);
  813|      0|      if (!timer)
  ------------------
  |  Branch (813:11): [True: 0, False: 0]
  ------------------
  814|      0|        return wlst.size();
  815|      0|      candidate.erase(candidate.begin() + index);
  816|      0|    }
  817|      0|  }
  818|   265k|  return wlst.size();
  819|   265k|}
_ZN10SuggestMgr14forgotchar_utfERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKNS1_I6w_charNS5_ISB_EEEEiRi:
  824|   162k|                                  int cpdsuggest, int& info) {
  825|   162k|  std::vector<w_char> candidate_utf(word);
  826|   162k|  std::chrono::steady_clock::time_point timelimit = std::chrono::steady_clock::now();
  827|   162k|  int timer = MINTIMER;
  ------------------
  |  |  110|   162k|#define MINTIMER 100
  ------------------
  828|       |
  829|       |  // try inserting a tryme character at the end of the word and before every
  830|       |  // letter
  831|   180k|  for (size_t k = 0; k < ctryl; ++k) {
  ------------------
  |  Branch (831:22): [True: 18.6k, False: 162k]
  ------------------
  832|   270k|    for (size_t i = 0; i <= candidate_utf.size(); ++i) {
  ------------------
  |  Branch (832:24): [True: 251k, False: 18.6k]
  ------------------
  833|   251k|      size_t index = candidate_utf.size() - i;
  834|   251k|      candidate_utf.insert(candidate_utf.begin() + index, ctry_utf[k]);
  835|   251k|      std::string candidate;
  836|   251k|      u16_u8(candidate, candidate_utf);
  837|   251k|      testsug(wlst, candidate, cpdsuggest, &timer, &timelimit, info);
  838|   251k|      if (!timer)
  ------------------
  |  Branch (838:11): [True: 0, False: 251k]
  ------------------
  839|      0|        return wlst.size();
  840|   251k|      candidate_utf.erase(candidate_utf.begin() + index);
  841|   251k|    }
  842|  18.6k|  }
  843|   162k|  return wlst.size();
  844|   162k|}
_ZN10SuggestMgr8twowordsERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_ibRi:
  854|   427k|                         bool good, int& info) {
  855|   427k|  int c2, forbidden = 0, cwrd;
  856|   427k|  size_t wl = word.size();
  857|   427k|  if (wl < 3)
  ------------------
  |  Branch (857:7): [True: 54.4k, False: 372k]
  ------------------
  858|  54.4k|    return false;
  859|       |
  860|   372k|  if (langnum == LANG_hu)
  ------------------
  |  Branch (860:7): [True: 15.4k, False: 357k]
  ------------------
  861|  15.4k|    forbidden = check_forbidden(word);
  862|       |
  863|   372k|  char* candidate = new char[wl + 2];
  864|   372k|  memcpy(candidate + 1, word.data(), wl);
  865|   372k|  candidate[wl + 1] = 0;
  866|       |
  867|       |  // split the string into two pieces after every char
  868|       |  // if both pieces are good words make them a suggestion
  869|  4.92M|  for (char* p = candidate + 1; p[1] != '\0'; p++) {
  ------------------
  |  Branch (869:33): [True: 4.58M, False: 336k]
  ------------------
  870|  4.58M|    p[-1] = *p;
  871|       |    // go to end of the UTF-8 character
  872|  4.82M|    while (utf8 && is_utf8_cont(p[1])) {
  ------------------
  |  Branch (872:12): [True: 1.58M, False: 3.24M]
  |  Branch (872:20): [True: 242k, False: 1.34M]
  ------------------
  873|   242k|      *p = p[1];
  874|   242k|      p++;
  875|   242k|    }
  876|  4.58M|    if (utf8 && p[1] == '\0')
  ------------------
  |  Branch (876:9): [True: 1.34M, False: 3.24M]
  |  Branch (876:17): [True: 36.3k, False: 1.30M]
  ------------------
  877|  36.3k|      break;  // last UTF-8 character
  878|       |
  879|       |    // Suggest only word pairs, if they are listed in the dictionary.
  880|       |    // For example, adding "a lot" to the English dic file will
  881|       |    // result only "alot" -> "a lot" suggestion instead of
  882|       |    // "alto, slot, alt, lot, allot, aloft, aloe, clot, plot, blot, a lot".
  883|       |    // Note: using "ph:alot" keeps the other suggestions:
  884|       |    // a lot ph:alot
  885|       |    // alot -> a lot, alto, slot...
  886|  4.55M|    *p = ' ';
  887|  4.55M|    if (!cpdsuggest && checkword(candidate, cpdsuggest, nullptr, nullptr)) {
  ------------------
  |  Branch (887:9): [True: 1.51M, False: 3.03M]
  |  Branch (887:9): [True: 1.02k, False: 4.54M]
  |  Branch (887:24): [True: 1.02k, False: 1.51M]
  ------------------
  888|       |      // best solution
  889|  1.02k|      info |= SPELL_BEST_SUG;
  ------------------
  |  |   89|  1.02k|#define SPELL_BEST_SUG (1 << 8)    // limit suggestions for the best ones, i.e. ph:
  ------------------
  890|       |
  891|       |      // remove not word pair suggestions
  892|  1.02k|      if (!good) {
  ------------------
  |  Branch (892:11): [True: 144, False: 883]
  ------------------
  893|    144|        good = true;
  894|    144|        wlst.clear();
  895|    144|      }
  896|       |
  897|  1.02k|      wlst.insert(wlst.begin(), candidate);
  898|  1.02k|    }
  899|       |
  900|       |    // word pairs with dash?
  901|  4.55M|    if (lang_with_dash_usage) {
  ------------------
  |  Branch (901:9): [True: 0, False: 4.55M]
  ------------------
  902|      0|      *p = '-';
  903|       |
  904|      0|      if (!cpdsuggest && checkword(candidate, cpdsuggest, nullptr, nullptr)) {
  ------------------
  |  Branch (904:11): [True: 0, False: 0]
  |  Branch (904:11): [True: 0, False: 0]
  |  Branch (904:26): [True: 0, False: 0]
  ------------------
  905|       |        // best solution
  906|      0|        info |= SPELL_BEST_SUG;
  ------------------
  |  |   89|      0|#define SPELL_BEST_SUG (1 << 8)    // limit suggestions for the best ones, i.e. ph:
  ------------------
  907|       |
  908|       |        // remove not word pair suggestions
  909|      0|        if (!good) {
  ------------------
  |  Branch (909:13): [True: 0, False: 0]
  ------------------
  910|      0|          good = true;
  911|      0|          wlst.clear();
  912|      0|        }
  913|      0|        wlst.insert(wlst.begin(), candidate);
  914|      0|      }
  915|      0|    }
  916|       |
  917|  4.55M|    if (wlst.size() < maxSug && !nosplitsugs && !good) {
  ------------------
  |  Branch (917:9): [True: 4.55M, False: 247]
  |  Branch (917:33): [True: 4.55M, False: 0]
  |  Branch (917:49): [True: 4.54M, False: 780]
  ------------------
  918|  4.54M|      *p = '\0';
  919|  4.54M|      int c1 = checkword(candidate, cpdsuggest, nullptr, nullptr);
  920|  4.54M|      if (c1) {
  ------------------
  |  Branch (920:11): [True: 31.7k, False: 4.51M]
  ------------------
  921|  31.7k|        c2 = checkword((p + 1), cpdsuggest, nullptr, nullptr);
  922|  31.7k|        if (c2) {
  ------------------
  |  Branch (922:13): [True: 852, False: 30.8k]
  ------------------
  923|       |          // spec. Hungarian code (TODO need a better compound word support)
  924|    852|          if ((langnum == LANG_hu) && !forbidden &&
  ------------------
  |  Branch (924:15): [True: 10, False: 842]
  |  Branch (924:39): [True: 10, False: 0]
  ------------------
  925|       |              // if 3 repeating letter, use - instead of space
  926|     10|              (((p[-1] == p[1]) &&
  ------------------
  |  Branch (926:17): [True: 7, False: 3]
  ------------------
  927|      7|              (((p > candidate + 1) && (p[-1] == p[-2])) || (p[-1] == p[2]))) ||
  ------------------
  |  Branch (927:17): [True: 0, False: 7]
  |  Branch (927:40): [True: 0, False: 0]
  |  Branch (927:61): [True: 0, False: 7]
  ------------------
  928|       |              // or multiple compounding, with more, than 6 syllables
  929|     10|              ((c1 == 3) && (c2 >= 2))))
  ------------------
  |  Branch (929:16): [True: 0, False: 10]
  |  Branch (929:29): [True: 0, False: 0]
  ------------------
  930|      0|            *p = '-';
  931|    852|          else
  932|    852|            *p = ' ';
  933|       |
  934|    852|          cwrd = std::find(wlst.begin(), wlst.end(), candidate) != wlst.end() ? 0 : 1;
  ------------------
  |  Branch (934:18): [True: 10, False: 842]
  ------------------
  935|       |
  936|    852|          if (cwrd && (wlst.size() < maxSug))
  ------------------
  |  Branch (936:15): [True: 842, False: 10]
  |  Branch (936:23): [True: 842, False: 0]
  ------------------
  937|    842|              wlst.emplace_back(candidate);
  938|       |
  939|       |          // add two word suggestion with dash, depending on the language
  940|       |          // Note that cwrd doesn't modified for REP twoword sugg.
  941|    852|          if ( !nosplitsugs && lang_with_dash_usage &&
  ------------------
  |  Branch (941:16): [True: 852, False: 0]
  |  Branch (941:32): [True: 0, False: 852]
  ------------------
  942|      0|              mystrlen(p + 1) > 1 && mystrlen(candidate) - mystrlen(p) > 1) {
  ------------------
  |  Branch (942:15): [True: 0, False: 0]
  |  Branch (942:38): [True: 0, False: 0]
  ------------------
  943|      0|            *p = '-';
  944|      0|            for (auto& k : wlst) {
  ------------------
  |  Branch (944:26): [True: 0, False: 0]
  ------------------
  945|      0|              if (k == candidate) {
  ------------------
  |  Branch (945:19): [True: 0, False: 0]
  ------------------
  946|      0|                cwrd = 0;
  947|      0|                break;
  948|      0|              }
  949|      0|            }
  950|       |
  951|      0|            if ((wlst.size() < maxSug) && cwrd)
  ------------------
  |  Branch (951:17): [True: 0, False: 0]
  |  Branch (951:43): [True: 0, False: 0]
  ------------------
  952|      0|              wlst.emplace_back(candidate);
  953|      0|          }
  954|    852|        }
  955|  31.7k|      }
  956|  4.54M|    }
  957|  4.55M|  }
  958|   372k|  delete[] candidate;
  959|   372k|  return good;
  960|   427k|}
_ZN10SuggestMgr8swapcharERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
  965|   265k|                            int cpdsuggest, int& info) {
  966|   265k|  if (word.size() < 2)
  ------------------
  |  Branch (966:7): [True: 17.3k, False: 247k]
  ------------------
  967|  17.3k|    return wlst.size();
  968|       |
  969|   247k|  std::string candidate(word);
  970|       |
  971|       |  // try swapping adjacent chars one by one
  972|  5.38M|  for (size_t i = 0; i < candidate.size() - 1; ++i) {
  ------------------
  |  Branch (972:22): [True: 5.13M, False: 247k]
  ------------------
  973|  5.13M|    std::swap(candidate[i], candidate[i+1]);
  974|  5.13M|    testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  975|  5.13M|    std::swap(candidate[i], candidate[i+1]);
  976|  5.13M|  }
  977|       |
  978|       |  // try double swaps for short words
  979|       |  // ahev -> have, owudl -> would
  980|   247k|  if (candidate.size() == 4 || candidate.size() == 5) {
  ------------------
  |  Branch (980:7): [True: 11.9k, False: 235k]
  |  Branch (980:32): [True: 11.2k, False: 224k]
  ------------------
  981|  23.1k|    candidate[0] = word[1];
  982|  23.1k|    candidate[1] = word[0];
  983|  23.1k|    candidate[2] = word[2];
  984|  23.1k|    candidate[candidate.size() - 2] = word[candidate.size() - 1];
  985|  23.1k|    candidate[candidate.size() - 1] = word[candidate.size() - 2];
  986|  23.1k|    testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  987|  23.1k|    if (candidate.size() == 5) {
  ------------------
  |  Branch (987:9): [True: 11.2k, False: 11.9k]
  ------------------
  988|  11.2k|      candidate[0] = word[0];
  989|  11.2k|      candidate[1] = word[2];
  990|  11.2k|      candidate[2] = word[1];
  991|  11.2k|      testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
  992|  11.2k|    }
  993|  23.1k|  }
  994|       |
  995|   247k|  return wlst.size();
  996|   265k|}
_ZN10SuggestMgr12swapchar_utfERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKNS1_I6w_charNS5_ISB_EEEEiRi:
 1001|   162k|                                int cpdsuggest, int& info) {
 1002|   162k|  if (word.size() < 2)
  ------------------
  |  Branch (1002:7): [True: 15.7k, False: 146k]
  ------------------
 1003|  15.7k|    return wlst.size();
 1004|       |
 1005|   146k|  std::vector<w_char> candidate_utf(word);
 1006|       |
 1007|   146k|  std::string candidate;
 1008|       |  // try swapping adjacent chars one by one
 1009|  1.96M|  for (size_t i = 0; i < candidate_utf.size() - 1; ++i) {
  ------------------
  |  Branch (1009:22): [True: 1.82M, False: 146k]
  ------------------
 1010|  1.82M|    if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|  1.82M|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (1010:9): [True: 0, False: 1.82M]
  ------------------
 1011|      0|      return wlst.size();
 1012|  1.82M|    std::swap(candidate_utf[i], candidate_utf[i+1]);
 1013|  1.82M|    u16_u8(candidate, candidate_utf);
 1014|  1.82M|    testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
 1015|  1.82M|    std::swap(candidate_utf[i], candidate_utf[i+1]);
 1016|  1.82M|  }
 1017|       |
 1018|       |  // try double swaps for short words
 1019|       |  // ahev -> have, owudl -> would, suodn -> sound
 1020|   146k|  if (candidate_utf.size() == 4 || candidate_utf.size() == 5) {
  ------------------
  |  Branch (1020:7): [True: 19.1k, False: 127k]
  |  Branch (1020:36): [True: 10.8k, False: 116k]
  ------------------
 1021|  29.9k|    candidate_utf[0] = word[1];
 1022|  29.9k|    candidate_utf[1] = word[0];
 1023|  29.9k|    candidate_utf[2] = word[2];
 1024|  29.9k|    candidate_utf[candidate_utf.size() - 2] = word[candidate_utf.size() - 1];
 1025|  29.9k|    candidate_utf[candidate_utf.size() - 1] = word[candidate_utf.size() - 2];
 1026|  29.9k|    u16_u8(candidate, candidate_utf);
 1027|  29.9k|    testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
 1028|  29.9k|    if (candidate_utf.size() == 5) {
  ------------------
  |  Branch (1028:9): [True: 10.8k, False: 19.1k]
  ------------------
 1029|  10.8k|      candidate_utf[0] = word[0];
 1030|  10.8k|      candidate_utf[1] = word[2];
 1031|  10.8k|      candidate_utf[2] = word[1];
 1032|  10.8k|      u16_u8(candidate, candidate_utf);
 1033|  10.8k|      testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
 1034|  10.8k|    }
 1035|  29.9k|  }
 1036|   146k|  return wlst.size();
 1037|   146k|}
_ZN10SuggestMgr12longswapcharERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
 1042|   265k|                                int cpdsuggest, int& info) {
 1043|   265k|  std::string candidate(word);
 1044|       |  // try swapping not adjacent chars one by one
 1045|  5.66M|  for (auto p = candidate.begin(); p < candidate.end(); ++p) {
  ------------------
  |  Branch (1045:36): [True: 5.39M, False: 265k]
  ------------------
 1046|   195M|    for (auto q = candidate.begin(); q < candidate.end(); ++q) {
  ------------------
  |  Branch (1046:38): [True: 190M, False: 5.39M]
  ------------------
 1047|   190M|      const auto distance = std::abs(std::distance(q, p));
 1048|   190M|      if (distance > 1 && distance <= MAX_CHAR_DISTANCE && *p != *q) {
  ------------------
  |  |   84|   364M|#define MAX_CHAR_DISTANCE 4
  ------------------
  |  Branch (1048:11): [True: 174M, False: 15.6M]
  |  Branch (1048:27): [True: 27.9M, False: 146M]
  |  Branch (1048:60): [True: 21.4M, False: 6.48M]
  ------------------
 1049|  21.4M|        std::swap(*p, *q);
 1050|  21.4M|        testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
 1051|  21.4M|        std::swap(*p, *q);
 1052|  21.4M|      }
 1053|   190M|    }
 1054|  5.39M|  }
 1055|   265k|  return wlst.size();
 1056|   265k|}
_ZN10SuggestMgr16longswapchar_utfERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKNS1_I6w_charNS5_ISB_EEEEiRi:
 1061|   162k|                                    int cpdsuggest, int& info) {
 1062|   162k|  std::vector<w_char> candidate_utf(word);
 1063|       |  // try swapping not adjacent chars
 1064|  2.14M|  for (auto p = candidate_utf.begin(); p < candidate_utf.end(); ++p) {
  ------------------
  |  Branch (1064:40): [True: 1.98M, False: 162k]
  ------------------
 1065|  55.5M|    for (auto q = candidate_utf.begin(); q < candidate_utf.end(); ++q) {
  ------------------
  |  Branch (1065:42): [True: 53.5M, False: 1.98M]
  ------------------
 1066|  53.5M|      const auto distance = std::abs(std::distance(q, p));
 1067|  53.5M|      if (distance > 1 && distance <= MAX_CHAR_DISTANCE && *p != *q) {
  ------------------
  |  |   84|   101M|#define MAX_CHAR_DISTANCE 4
  ------------------
  |  Branch (1067:11): [True: 47.9M, False: 5.62M]
  |  Branch (1067:27): [True: 9.25M, False: 38.6M]
  |  Branch (1067:60): [True: 6.62M, False: 2.63M]
  ------------------
 1068|  6.62M|        std::swap(*p, *q);
 1069|  6.62M|        std::string candidate;
 1070|  6.62M|        u16_u8(candidate, candidate_utf);
 1071|  6.62M|        testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
 1072|  6.62M|        std::swap(*p, *q);
 1073|  6.62M|      }
 1074|  53.5M|    }
 1075|  1.98M|  }
 1076|   162k|  return wlst.size();
 1077|   162k|}
_ZN10SuggestMgr8movecharERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_iRi:
 1082|   265k|                            int cpdsuggest, int& info) {
 1083|   265k|  if (word.size() < 2)
  ------------------
  |  Branch (1083:7): [True: 17.3k, False: 247k]
  ------------------
 1084|  17.3k|    return wlst.size();
 1085|       |
 1086|   247k|  std::string candidate(word);
 1087|       |
 1088|       |  // try moving a char
 1089|  5.62M|  for (auto p = candidate.begin(); p < candidate.end(); ++p) {
  ------------------
  |  Branch (1089:36): [True: 5.38M, False: 247k]
  ------------------
 1090|  24.4M|    for (auto q = p + 1; q < candidate.end() && std::distance(p, q) <= MAX_CHAR_DISTANCE; ++q) {
  ------------------
  |  |   84|  23.3M|#define MAX_CHAR_DISTANCE 4
  ------------------
  |  Branch (1090:26): [True: 23.3M, False: 1.16M]
  |  Branch (1090:26): [True: 19.0M, False: 5.38M]
  |  Branch (1090:49): [True: 19.0M, False: 4.21M]
  ------------------
 1091|  19.0M|      std::swap(*q, *(q - 1));
 1092|  19.0M|      if (std::distance(p, q) < 2)
  ------------------
  |  Branch (1092:11): [True: 5.13M, False: 13.9M]
  ------------------
 1093|  5.13M|        continue;  // omit swap char
 1094|  13.9M|      testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
 1095|  13.9M|    }
 1096|  5.38M|    const auto word_iter = word.begin();
 1097|  5.38M|    std::copy_n(word_iter, candidate.size(), candidate.begin());
 1098|  5.38M|  }
 1099|       |
 1100|  5.38M|  for (auto p = candidate.rbegin(), pEnd = candidate.rend() - 1; p != pEnd; ++p) {
  ------------------
  |  Branch (1100:66): [True: 5.13M, False: 247k]
  ------------------
 1101|  24.2M|    for (auto q = p + 1, qEnd = candidate.rend(); q != qEnd && std::distance(p, q) <= MAX_CHAR_DISTANCE; ++q) {
  ------------------
  |  |   84|  23.3M|#define MAX_CHAR_DISTANCE 4
  ------------------
  |  Branch (1101:51): [True: 23.3M, False: 920k]
  |  Branch (1101:64): [True: 19.0M, False: 4.21M]
  ------------------
 1102|  19.0M|      std::swap(*q, *(q - 1));
 1103|  19.0M|      if (std::distance(p, q) < 2)
  ------------------
  |  Branch (1103:11): [True: 5.13M, False: 13.9M]
  ------------------
 1104|  5.13M|        continue;  // omit swap char
 1105|  13.9M|      testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
 1106|  13.9M|    }
 1107|  5.13M|    const auto word_iter = word.begin();
 1108|  5.13M|    std::copy_n(word_iter, candidate.size(), candidate.begin());
 1109|  5.13M|  }
 1110|       |
 1111|   247k|  return wlst.size();
 1112|   265k|}
_ZN10SuggestMgr12movechar_utfERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKNS1_I6w_charNS5_ISB_EEEEiRi:
 1117|   162k|                                int cpdsuggest, int& info) {
 1118|   162k|  if (word.size() < 2)
  ------------------
  |  Branch (1118:7): [True: 15.7k, False: 146k]
  ------------------
 1119|  15.7k|    return wlst.size();
 1120|       |
 1121|   146k|  std::vector<w_char> candidate_utf(word);
 1122|       |
 1123|       |  // try moving a char
 1124|  2.11M|  for (auto p = candidate_utf.begin(); p < candidate_utf.end(); ++p) {
  ------------------
  |  Branch (1124:40): [True: 1.96M, False: 146k]
  ------------------
 1125|  8.41M|    for (auto q = p + 1; q < candidate_utf.end() && std::distance(p, q) <= MAX_CHAR_DISTANCE; ++q) {
  ------------------
  |  |   84|  7.75M|#define MAX_CHAR_DISTANCE 4
  ------------------
  |  Branch (1125:26): [True: 7.75M, False: 657k]
  |  Branch (1125:26): [True: 6.44M, False: 1.96M]
  |  Branch (1125:53): [True: 6.44M, False: 1.30M]
  ------------------
 1126|  6.44M|      std::swap(*q, *(q - 1));
 1127|  6.44M|      if (std::distance(p, q) < 2)
  ------------------
  |  Branch (1127:11): [True: 1.82M, False: 4.62M]
  ------------------
 1128|  1.82M|        continue;  // omit swap char
 1129|  4.62M|      std::string candidate;
 1130|  4.62M|      u16_u8(candidate, candidate_utf);
 1131|  4.62M|      testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
 1132|  4.62M|    }
 1133|  1.96M|    const auto word_iter = word.begin();
 1134|  1.96M|    std::copy_n(word_iter, candidate_utf.size(), candidate_utf.begin());
 1135|  1.96M|  }
 1136|       |
 1137|  2.11M|  for (auto p = candidate_utf.rbegin(); p < candidate_utf.rend(); ++p) {
  ------------------
  |  Branch (1137:41): [True: 1.96M, False: 146k]
  ------------------
 1138|  8.41M|    for (auto q = p + 1; q < candidate_utf.rend() && std::distance(p, q) <= MAX_CHAR_DISTANCE; ++q) {
  ------------------
  |  |   84|  7.75M|#define MAX_CHAR_DISTANCE 4
  ------------------
  |  Branch (1138:26): [True: 7.75M, False: 657k]
  |  Branch (1138:26): [True: 6.44M, False: 1.96M]
  |  Branch (1138:54): [True: 6.44M, False: 1.30M]
  ------------------
 1139|  6.44M|      std::swap(*q, *(q - 1));
 1140|  6.44M|      if (std::distance(p, q) < 2)
  ------------------
  |  Branch (1140:11): [True: 1.82M, False: 4.62M]
  ------------------
 1141|  1.82M|        continue;  // omit swap char
 1142|  4.62M|      std::string candidate;
 1143|  4.62M|      u16_u8(candidate, candidate_utf);
 1144|  4.62M|      testsug(wlst, candidate, cpdsuggest, nullptr, nullptr, info);
 1145|  4.62M|    }
 1146|  1.96M|    const auto word_iter = word.begin();
 1147|  1.96M|    std::copy_n(word_iter, candidate_utf.size(), candidate_utf.begin());
 1148|  1.96M|  }
 1149|       |
 1150|   146k|  return wlst.size();
 1151|   162k|}
_ZN10SuggestMgr9ngsuggestERNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEEPKcRKNS1_INS0_10unique_ptrI7HashMgrNS0_14default_deleteISE_EEEENS5_ISH_EEEEi:
 1186|  62.5k|                          int captype) {
 1187|  62.5k|  int lval, sc, lp, lpphon, nonbmp = 0;
 1188|       |
 1189|       |  // exhaustively search through all root words
 1190|       |  // keeping track of the MAX_ROOTS most similar root words
 1191|  62.5k|  struct hentry* roots[MAX_ROOTS];
 1192|  62.5k|  char* rootsphon[MAX_ROOTS];
 1193|  62.5k|  int scores[MAX_ROOTS];
 1194|  62.5k|  int scoresphon[MAX_ROOTS];
 1195|  6.31M|  for (int i = 0; i < MAX_ROOTS; i++) {
  ------------------
  |  |   74|  6.31M|#define MAX_ROOTS 100
  ------------------
  |  Branch (1195:19): [True: 6.25M, False: 62.5k]
  ------------------
 1196|  6.25M|    roots[i] = nullptr;
 1197|  6.25M|    scores[i] = -100 * i;
 1198|  6.25M|    rootsphon[i] = nullptr;
 1199|  6.25M|    scoresphon[i] = -100 * i;
 1200|  6.25M|  }
 1201|  62.5k|  bool has_roots = false;
 1202|  62.5k|  bool has_rootsphon = false;
 1203|  62.5k|  lp = MAX_ROOTS - 1;
  ------------------
  |  |   74|  62.5k|#define MAX_ROOTS 100
  ------------------
 1204|  62.5k|  lpphon = MAX_ROOTS - 1;
  ------------------
  |  |   74|  62.5k|#define MAX_ROOTS 100
  ------------------
 1205|  62.5k|  int low = NGRAM_LOWERING;
  ------------------
  |  |   83|  62.5k|#define NGRAM_LOWERING (1 << 2)
  ------------------
 1206|       |
 1207|  62.5k|  std::string w2;
 1208|  62.5k|  const char* word = w;
 1209|       |
 1210|  62.5k|  int nc;
 1211|       |  // word reversing wrapper for complex prefixes
 1212|  62.5k|  if (complexprefixes) {
  ------------------
  |  Branch (1212:7): [True: 3.55k, False: 58.9k]
  ------------------
 1213|  3.55k|    w2.assign(w);
 1214|  3.55k|    if (utf8)
  ------------------
  |  Branch (1214:9): [True: 0, False: 3.55k]
  ------------------
 1215|      0|      reverseword_utf(w2);
 1216|  3.55k|    else
 1217|  3.55k|      reverseword(w2);
 1218|  3.55k|    word = w2.c_str();
 1219|  3.55k|    nc = (int)w2.size();
 1220|  58.9k|  } else {
 1221|  58.9k|    nc = (int)strlen(word);
 1222|  58.9k|  }
 1223|       |
 1224|  62.5k|  std::vector<w_char> u8;
 1225|  62.5k|  int n = (utf8) ? u8_u16(u8, word) : nc;
  ------------------
  |  Branch (1225:11): [True: 26.4k, False: 36.1k]
  ------------------
 1226|       |
 1227|       |  // set character based ngram suggestion for words with non-BMP Unicode
 1228|       |  // characters
 1229|  62.5k|  const struct cs_info* origconv = csconv;
 1230|  62.5k|  if (n == -1) {
  ------------------
  |  Branch (1230:7): [True: 1.83k, False: 60.6k]
  ------------------
 1231|  1.83k|    utf8 = 0;  // XXX not state-free
 1232|  1.83k|    if (!csconv)
  ------------------
  |  Branch (1232:9): [True: 1.83k, False: 0]
  ------------------
 1233|  1.83k|      csconv = get_current_cs("iso88591"); // XXX not state-free
 1234|  1.83k|    n = nc;
 1235|  1.83k|    nonbmp = 1;
 1236|  1.83k|    low = 0;
 1237|  1.83k|  }
 1238|  62.5k|  ngsuggest_guard restore_state(nonbmp, origconv, &utf8, &csconv);
 1239|  62.5k|  int max_word_len = (utf8) ? MAXWORDUTF8LEN : MAXWORDLEN;
  ------------------
  |  |   85|  24.5k|#define MAXWORDUTF8LEN (MAXWORDLEN * 3)
  |  |  ------------------
  |  |  |  |   90|  24.5k|#define MAXWORDLEN 100
  |  |  ------------------
  ------------------
                int max_word_len = (utf8) ? MAXWORDUTF8LEN : MAXWORDLEN;
  ------------------
  |  |   90|  37.9k|#define MAXWORDLEN 100
  ------------------
  |  Branch (1239:22): [True: 24.5k, False: 37.9k]
  ------------------
 1240|       |  // ofz#59067 a replist entry can generate a very long word, abandon
 1241|       |  // ngram if that odd-edge case arises
 1242|  62.5k|  if (n > max_word_len * 4)
  ------------------
  |  Branch (1242:7): [True: 0, False: 62.5k]
  ------------------
 1243|      0|      return;
 1244|       |
 1245|  62.5k|  struct hentry* hp = nullptr;
 1246|  62.5k|  int col = -1;
 1247|  62.5k|  phonetable* ph = (pAMgr) ? pAMgr->get_phonetable() : nullptr;
  ------------------
  |  Branch (1247:20): [True: 62.5k, False: 0]
  ------------------
 1248|  62.5k|  std::string target;
 1249|  62.5k|  std::string candidate;
 1250|  62.5k|  std::vector<w_char> w_candidate;
 1251|  62.5k|  if (ph) {
  ------------------
  |  Branch (1251:7): [True: 3.56k, False: 58.9k]
  ------------------
 1252|  3.56k|    if (utf8) {
  ------------------
  |  Branch (1252:9): [True: 0, False: 3.56k]
  ------------------
 1253|      0|      u8_u16(w_candidate, word);
 1254|      0|      mkallcap_utf(w_candidate, langnum);
 1255|      0|      u16_u8(candidate, w_candidate);
 1256|  3.56k|    } else {
 1257|  3.56k|      candidate.assign(word);
 1258|  3.56k|      if (!nonbmp)
  ------------------
  |  Branch (1258:11): [True: 3.56k, False: 0]
  ------------------
 1259|  3.56k|        mkallcap(candidate, csconv);
 1260|  3.56k|    }
 1261|  3.56k|    target = phonet(candidate, *ph);  // XXX phonet() is 8-bit (nc, not n)
 1262|  3.56k|  }
 1263|       |
 1264|  62.5k|  FLAG forbiddenword = pAMgr ? pAMgr->get_forbiddenword() : FLAG_NULL;
  ------------------
  |  |   98|  62.5k|#define FLAG unsigned short
  ------------------
                FLAG forbiddenword = pAMgr ? pAMgr->get_forbiddenword() : FLAG_NULL;
  ------------------
  |  |   99|  62.5k|#define FLAG_NULL 0x00
  ------------------
  |  Branch (1264:24): [True: 62.5k, False: 0]
  ------------------
 1265|  62.5k|  FLAG nosuggest = pAMgr ? pAMgr->get_nosuggest() : FLAG_NULL;
  ------------------
  |  |   98|  62.5k|#define FLAG unsigned short
  ------------------
                FLAG nosuggest = pAMgr ? pAMgr->get_nosuggest() : FLAG_NULL;
  ------------------
  |  |   99|  62.5k|#define FLAG_NULL 0x00
  ------------------
  |  Branch (1265:20): [True: 62.5k, False: 0]
  ------------------
 1266|  62.5k|  FLAG nongramsuggest = pAMgr ? pAMgr->get_nongramsuggest() : FLAG_NULL;
  ------------------
  |  |   98|  62.5k|#define FLAG unsigned short
  ------------------
                FLAG nongramsuggest = pAMgr ? pAMgr->get_nongramsuggest() : FLAG_NULL;
  ------------------
  |  |   99|  62.5k|#define FLAG_NULL 0x00
  ------------------
  |  Branch (1266:25): [True: 62.5k, False: 0]
  ------------------
 1267|  62.5k|  FLAG onlyincompound = pAMgr ? pAMgr->get_onlyincompound() : FLAG_NULL;
  ------------------
  |  |   98|  62.5k|#define FLAG unsigned short
  ------------------
                FLAG onlyincompound = pAMgr ? pAMgr->get_onlyincompound() : FLAG_NULL;
  ------------------
  |  |   99|  62.5k|#define FLAG_NULL 0x00
  ------------------
  |  Branch (1267:25): [True: 62.5k, False: 0]
  ------------------
 1268|       |
 1269|  62.5k|  std::vector<w_char> w_word, w_target;
 1270|  62.5k|  if (utf8) {
  ------------------
  |  Branch (1270:7): [True: 24.5k, False: 37.9k]
  ------------------
 1271|  24.5k|    u8_u16(w_word, word);
 1272|  24.5k|    u8_u16(w_target, target);
 1273|  24.5k|  }
 1274|       |
 1275|  62.5k|  std::string f;
 1276|  62.5k|  std::vector<w_char> w_f;
 1277|       |
 1278|  62.5k|  for (const auto& i : rHMgr) {
  ------------------
  |  Branch (1278:22): [True: 62.5k, False: 62.5k]
  ------------------
 1279|  2.14M|    while (nullptr != (hp = i->walk_hashtable(col, hp))) {
  ------------------
  |  Branch (1279:12): [True: 2.08M, False: 62.5k]
  ------------------
 1280|       |      // skip exceptions
 1281|  2.08M|      if (
 1282|       |           // skip it, if the word length different by 5 or
 1283|       |           // more characters (to avoid strange suggestions)
 1284|       |           // (except Unicode characters over BMP)
 1285|  2.08M|           (((abs(n - hp->clen) > 4) && !nonbmp)) ||
  ------------------
  |  Branch (1285:12): [True: 1.35M, False: 721k]
  |  Branch (1285:14): [True: 1.25M, False: 829k]
  |  Branch (1285:41): [True: 1.19M, False: 57.8k]
  ------------------
 1286|       |           // don't suggest capitalized dictionary words for
 1287|       |           // lower case misspellings in ngram suggestions, except
 1288|       |           // - PHONE usage, or
 1289|       |           // - in the case of German, where not only proper
 1290|       |           //   nouns are capitalized, or
 1291|       |           // - the capitalized word has special pronunciation
 1292|   887k|           ((captype == NOCAP) && (hp->var & H_OPT_INITCAP) &&
  ------------------
  |  |   88|   887k|#define NOCAP 0
  ------------------
                         ((captype == NOCAP) && (hp->var & H_OPT_INITCAP) &&
  ------------------
  |  |   50|   202k|#define H_OPT_INITCAP (1 << 3)  // is dictionary word capitalized?
  ------------------
  |  Branch (1292:13): [True: 202k, False: 684k]
  |  Branch (1292:35): [True: 98.2k, False: 104k]
  ------------------
 1293|  98.2k|              !ph && (langnum != LANG_de) && !(hp->var & H_OPT_PHON)) ||
  ------------------
  |  |   49|  96.7k|#define H_OPT_PHON (1 << 2)     // is there ph: field in the morphological data?
  ------------------
  |  Branch (1293:15): [True: 96.7k, False: 1.53k]
  |  Branch (1293:22): [True: 96.7k, False: 0]
  |  Branch (1293:46): [True: 96.7k, False: 0]
  ------------------
 1294|       |           // or it has one of the following special flags
 1295|   790k|           ((hp->astr) && (pAMgr) &&
  ------------------
  |  Branch (1295:13): [True: 166k, False: 623k]
  |  Branch (1295:27): [True: 166k, False: 0]
  ------------------
 1296|   166k|             (TESTAFF(hp->astr, forbiddenword, hp->alen) ||
  ------------------
  |  |  102|   333k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 2.13k, False: 164k]
  |  |  ------------------
  ------------------
 1297|   164k|             TESTAFF(hp->astr, ONLYUPCASEFLAG, hp->alen) ||
  ------------------
  |  |  102|   331k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 67.3k, False: 97.2k]
  |  |  ------------------
  ------------------
 1298|  97.2k|             TESTAFF(hp->astr, nosuggest, hp->alen) ||
  ------------------
  |  |  102|   264k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 97.2k]
  |  |  ------------------
  ------------------
 1299|  97.2k|             TESTAFF(hp->astr, nongramsuggest, hp->alen) ||
  ------------------
  |  |  102|   264k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 97.2k]
  |  |  ------------------
  ------------------
 1300|  97.2k|             TESTAFF(hp->astr, onlyincompound, hp->alen)))
  ------------------
  |  |  102|  97.2k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 97.2k]
  |  |  ------------------
  ------------------
 1301|  2.08M|         )
 1302|  1.35M|        continue;
 1303|       |
 1304|   721k|      if (utf8) {
  ------------------
  |  Branch (1304:11): [True: 396k, False: 324k]
  ------------------
 1305|   396k|        u8_u16(w_f, HENTRY_WORD(hp));
  ------------------
  |  |   54|   396k|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 1306|       |
 1307|   396k|        int leftcommon = leftcommonsubstring(w_word, w_f);
 1308|   396k|        if (low) {
  ------------------
  |  Branch (1308:13): [True: 396k, False: 0]
  ------------------
 1309|       |          // lowering dictionary word
 1310|   396k|          mkallsmall_utf(w_f, langnum);
 1311|   396k|        }
 1312|   396k|        sc = ngram(3, w_word, w_f, NGRAM_LONGER_WORSE) + leftcommon;
  ------------------
  |  |   81|   396k|#define NGRAM_LONGER_WORSE (1 << 0)
  ------------------
 1313|   396k|      } else {
 1314|   324k|        f.assign(HENTRY_WORD(hp));
  ------------------
  |  |   54|   324k|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 1315|       |
 1316|   324k|        int leftcommon = leftcommonsubstring(word, f.c_str());
 1317|   324k|        if (low) {
  ------------------
  |  Branch (1317:13): [True: 296k, False: 28.1k]
  ------------------
 1318|       |          // lowering dictionary word
 1319|   296k|          mkallsmall(f, csconv);
 1320|   296k|        }
 1321|   324k|        sc = ngram(3, word, f, NGRAM_LONGER_WORSE) + leftcommon;
  ------------------
  |  |   81|   324k|#define NGRAM_LONGER_WORSE (1 << 0)
  ------------------
 1322|   324k|      }
 1323|       |
 1324|       |      // check special pronunciation
 1325|   721k|      f.clear();
 1326|   721k|      if ((hp->var & H_OPT_PHON) &&
  ------------------
  |  |   49|   721k|#define H_OPT_PHON (1 << 2)     // is there ph: field in the morphological data?
  ------------------
  |  Branch (1326:11): [True: 911, False: 720k]
  |  Branch (1326:11): [True: 911, False: 720k]
  ------------------
 1327|    911|          copy_field(f, HENTRY_DATA(hp), MORPH_PHON)) {
  ------------------
  |  |  110|    911|#define MORPH_PHON "ph:"
  ------------------
  |  Branch (1327:11): [True: 911, False: 0]
  ------------------
 1328|    911|        int sc2;
 1329|    911|        if (utf8) {
  ------------------
  |  Branch (1329:13): [True: 0, False: 911]
  ------------------
 1330|      0|          u8_u16(w_f, f);
 1331|       |
 1332|      0|          int leftcommon = leftcommonsubstring(w_word, w_f);
 1333|      0|          if (low) {
  ------------------
  |  Branch (1333:15): [True: 0, False: 0]
  ------------------
 1334|       |            // lowering dictionary word
 1335|      0|            mkallsmall_utf(w_f, langnum);
 1336|      0|          }
 1337|      0|          sc2 = ngram(3, w_word, w_f, NGRAM_LONGER_WORSE) + leftcommon;
  ------------------
  |  |   81|      0|#define NGRAM_LONGER_WORSE (1 << 0)
  ------------------
 1338|    911|        } else {
 1339|    911|          int leftcommon = leftcommonsubstring(word, f.c_str());
 1340|    911|          if (low) {
  ------------------
  |  Branch (1340:15): [True: 911, False: 0]
  ------------------
 1341|       |            // lowering dictionary word
 1342|    911|            mkallsmall(f, csconv);
 1343|    911|          }
 1344|    911|          sc2 = ngram(3, word, f, NGRAM_LONGER_WORSE) + leftcommon;
  ------------------
  |  |   81|    911|#define NGRAM_LONGER_WORSE (1 << 0)
  ------------------
 1345|    911|        }
 1346|    911|        if (sc2 > sc)
  ------------------
  |  Branch (1346:13): [True: 478, False: 433]
  ------------------
 1347|    478|          sc = sc2;
 1348|    911|      }
 1349|       |
 1350|   721k|      int scphon = -20000;
 1351|   721k|      if (ph && (sc > 2) && (abs(n - (int)hp->clen) <= 3)) {
  ------------------
  |  Branch (1351:11): [True: 35.4k, False: 685k]
  |  Branch (1351:17): [True: 8.21k, False: 27.2k]
  |  Branch (1351:29): [True: 6.83k, False: 1.37k]
  ------------------
 1352|  6.83k|        if (utf8) {
  ------------------
  |  Branch (1352:13): [True: 0, False: 6.83k]
  ------------------
 1353|      0|          u8_u16(w_candidate, HENTRY_WORD(hp));
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 1354|      0|          mkallcap_utf(w_candidate, langnum);
 1355|      0|          u16_u8(candidate, w_candidate);
 1356|  6.83k|        } else {
 1357|  6.83k|          candidate = HENTRY_WORD(hp);
  ------------------
  |  |   54|  6.83k|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 1358|  6.83k|          mkallcap(candidate, csconv);
 1359|  6.83k|        }
 1360|  6.83k|        f = phonet(candidate, *ph);
 1361|  6.83k|        if (utf8) {
  ------------------
  |  Branch (1361:13): [True: 0, False: 6.83k]
  ------------------
 1362|      0|          u8_u16(w_f, f);
 1363|      0|          scphon = 2 * ngram(3, w_target, w_f,
 1364|      0|                             NGRAM_LONGER_WORSE);
  ------------------
  |  |   81|      0|#define NGRAM_LONGER_WORSE (1 << 0)
  ------------------
 1365|  6.83k|        } else {
 1366|  6.83k|          scphon = 2 * ngram(3, target, f,
 1367|  6.83k|                             NGRAM_LONGER_WORSE);
  ------------------
  |  |   81|  6.83k|#define NGRAM_LONGER_WORSE (1 << 0)
  ------------------
 1368|  6.83k|        }
 1369|  6.83k|      }
 1370|       |
 1371|   721k|      if (sc > scores[lp]) {
  ------------------
  |  Branch (1371:11): [True: 716k, False: 4.30k]
  ------------------
 1372|   716k|        scores[lp] = sc;
 1373|   716k|        roots[lp] = hp;
 1374|   716k|        has_roots = true;
 1375|   716k|        lval = sc;
 1376|  72.4M|        for (int j = 0; j < MAX_ROOTS; j++)
  ------------------
  |  |   74|  72.4M|#define MAX_ROOTS 100
  ------------------
  |  Branch (1376:25): [True: 71.6M, False: 716k]
  ------------------
 1377|  71.6M|          if (scores[j] < lval) {
  ------------------
  |  Branch (1377:15): [True: 53.0M, False: 18.6M]
  ------------------
 1378|  53.0M|            lp = j;
 1379|  53.0M|            lval = scores[j];
 1380|  53.0M|          }
 1381|   716k|      }
 1382|       |
 1383|   721k|      if (scphon > scoresphon[lpphon]) {
  ------------------
  |  Branch (1383:11): [True: 6.83k, False: 714k]
  ------------------
 1384|  6.83k|        scoresphon[lpphon] = scphon;
 1385|  6.83k|        rootsphon[lpphon] = HENTRY_WORD(hp);
  ------------------
  |  |   54|  6.83k|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 1386|  6.83k|        has_rootsphon = true;
 1387|  6.83k|        lval = scphon;
 1388|   690k|        for (int j = 0; j < MAX_ROOTS; j++)
  ------------------
  |  |   74|   690k|#define MAX_ROOTS 100
  ------------------
  |  Branch (1388:25): [True: 683k, False: 6.83k]
  ------------------
 1389|   683k|          if (scoresphon[j] < lval) {
  ------------------
  |  Branch (1389:15): [True: 605k, False: 78.1k]
  ------------------
 1390|   605k|            lpphon = j;
 1391|   605k|            lval = scoresphon[j];
 1392|   605k|          }
 1393|  6.83k|      }
 1394|   721k|    }
 1395|  62.5k|  }
 1396|       |
 1397|  62.5k|  if (!has_roots && !has_rootsphon) {
  ------------------
  |  Branch (1397:7): [True: 15.0k, False: 47.4k]
  |  Branch (1397:21): [True: 15.0k, False: 0]
  ------------------
 1398|       |    // with no roots there will be no guesses and no point running
 1399|       |    // ngram
 1400|  15.0k|    return;
 1401|  15.0k|  }
 1402|       |
 1403|       |  // find minimum threshold for a passable suggestion
 1404|       |  // mangle original word three differnt ways
 1405|       |  // and score them to generate a minimum acceptable score
 1406|  47.4k|  std::vector<w_char> w_mw;
 1407|  47.4k|  int thresh = 0;
 1408|   189k|  for (int sp = 1; sp < 4; sp++) {
  ------------------
  |  Branch (1408:20): [True: 142k, False: 47.4k]
  ------------------
 1409|   142k|    if (utf8) {
  ------------------
  |  Branch (1409:9): [True: 59.3k, False: 83.1k]
  ------------------
 1410|  59.3k|      w_mw = w_word;
 1411|   110k|      for (int k = sp; k < n; k += 4) {
  ------------------
  |  Branch (1411:24): [True: 51.6k, False: 59.3k]
  ------------------
 1412|  51.6k|        w_mw[k].l = '*';
 1413|  51.6k|        w_mw[k].h = 0;
 1414|  51.6k|      }
 1415|       |
 1416|  59.3k|      if (low) {
  ------------------
  |  Branch (1416:11): [True: 59.3k, False: 0]
  ------------------
 1417|       |        // lowering dictionary word
 1418|  59.3k|        mkallsmall_utf(w_mw, langnum);
 1419|  59.3k|      }
 1420|       |
 1421|  59.3k|      thresh += ngram(n, w_word, w_mw, NGRAM_ANY_MISMATCH);
  ------------------
  |  |   82|  59.3k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
 1422|  83.1k|    } else {
 1423|  83.1k|      std::string mw = word;
 1424|   200k|      for (int k = sp; k < n; k += 4)
  ------------------
  |  Branch (1424:24): [True: 117k, False: 83.1k]
  ------------------
 1425|   117k|        mw[k] = '*';
 1426|       |
 1427|  83.1k|      if (low) {
  ------------------
  |  Branch (1427:11): [True: 77.6k, False: 5.49k]
  ------------------
 1428|       |        // lowering dictionary word
 1429|  77.6k|        mkallsmall(mw, csconv);
 1430|  77.6k|      }
 1431|       |
 1432|  83.1k|      thresh += ngram(n, word, mw, NGRAM_ANY_MISMATCH);
  ------------------
  |  |   82|  83.1k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
 1433|  83.1k|    }
 1434|   142k|  }
 1435|  47.4k|  thresh = thresh / 3;
 1436|  47.4k|  thresh--;
 1437|       |
 1438|       |  // now expand affixes on each of these root words and
 1439|       |  // and use length adjusted ngram scores to select
 1440|       |  // possible suggestions
 1441|  47.4k|  char* guess[MAX_GUESS];
 1442|  47.4k|  char* guessorig[MAX_GUESS];
 1443|  47.4k|  int gscore[MAX_GUESS];
 1444|  9.54M|  for (int i = 0; i < MAX_GUESS; i++) {
  ------------------
  |  |   76|  9.54M|#define MAX_GUESS 200
  ------------------
  |  Branch (1444:19): [True: 9.49M, False: 47.4k]
  ------------------
 1445|  9.49M|    guess[i] = nullptr;
 1446|  9.49M|    guessorig[i] = nullptr;
 1447|  9.49M|    gscore[i] = -100 * i;
 1448|  9.49M|  }
 1449|       |
 1450|  47.4k|  lp = MAX_GUESS - 1;
  ------------------
  |  |   76|  47.4k|#define MAX_GUESS 200
  ------------------
 1451|       |
 1452|  47.4k|  std::vector<guessword> glst(MAX_WORDS);
  ------------------
  |  |   75|  47.4k|#define MAX_WORDS 100
  ------------------
 1453|       |
 1454|  4.74M|  for (auto& root : roots) {
  ------------------
  |  Branch (1454:19): [True: 4.74M, False: 47.4k]
  ------------------
 1455|  4.74M|    if (root) {
  ------------------
  |  Branch (1455:9): [True: 698k, False: 4.05M]
  ------------------
 1456|   698k|      struct hentry* rp = root;
 1457|       |
 1458|   698k|      f.clear();
 1459|   698k|      const char* field = nullptr;
 1460|   698k|      if ((rp->var & H_OPT_PHON) && copy_field(f, HENTRY_DATA(rp), MORPH_PHON))
  ------------------
  |  |   49|   698k|#define H_OPT_PHON (1 << 2)     // is there ph: field in the morphological data?
  ------------------
                    if ((rp->var & H_OPT_PHON) && copy_field(f, HENTRY_DATA(rp), MORPH_PHON))
  ------------------
  |  |  110|    911|#define MORPH_PHON "ph:"
  ------------------
  |  Branch (1460:11): [True: 911, False: 697k]
  |  Branch (1460:11): [True: 911, False: 697k]
  |  Branch (1460:37): [True: 911, False: 0]
  ------------------
 1461|    911|          field = f.c_str();
 1462|   698k|      int nw = pAMgr->expand_rootword(
 1463|   698k|          glst.data(), MAX_WORDS, HENTRY_WORD(rp), rp->blen, rp->astr, rp->alen, word,
  ------------------
  |  |   75|   698k|#define MAX_WORDS 100
  ------------------
                        glst.data(), MAX_WORDS, HENTRY_WORD(rp), rp->blen, rp->astr, rp->alen, word,
  ------------------
  |  |   54|   698k|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 1464|   698k|          nc, field);
 1465|       |
 1466|  1.39M|      for (int k = 0; k < nw; k++) {
  ------------------
  |  Branch (1466:23): [True: 696k, False: 698k]
  ------------------
 1467|   696k|        if (utf8) {
  ------------------
  |  Branch (1467:13): [True: 373k, False: 323k]
  ------------------
 1468|   373k|          u8_u16(w_f, glst[k].word);
 1469|       |
 1470|   373k|          int leftcommon = leftcommonsubstring(w_word, w_f);
 1471|   373k|          if (low) {
  ------------------
  |  Branch (1471:15): [True: 373k, False: 0]
  ------------------
 1472|       |            // lowering dictionary word
 1473|   373k|            mkallsmall_utf(w_f, langnum);
 1474|   373k|          }
 1475|       |
 1476|   373k|          sc = ngram(n, w_word, w_f, NGRAM_ANY_MISMATCH) + leftcommon;
  ------------------
  |  |   82|   373k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
 1477|   373k|        } else {
 1478|   323k|          f = glst[k].word;
 1479|       |
 1480|   323k|          int leftcommon = leftcommonsubstring(word, f.c_str());
 1481|   323k|          if (low) {
  ------------------
  |  Branch (1481:15): [True: 295k, False: 28.1k]
  ------------------
 1482|       |            // lowering dictionary word
 1483|   295k|            mkallsmall(f, csconv);
 1484|   295k|          }
 1485|       |
 1486|   323k|          sc = ngram(n, word, f, NGRAM_ANY_MISMATCH) + leftcommon;
  ------------------
  |  |   82|   323k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
 1487|   323k|        }
 1488|       |
 1489|   696k|        if (sc > thresh) {
  ------------------
  |  Branch (1489:13): [True: 184k, False: 512k]
  ------------------
 1490|   184k|          if (sc > gscore[lp]) {
  ------------------
  |  Branch (1490:15): [True: 184k, False: 0]
  ------------------
 1491|   184k|            if (guess[lp]) {
  ------------------
  |  Branch (1491:17): [True: 0, False: 184k]
  ------------------
 1492|      0|              delete[] guess[lp];
 1493|      0|              if (guessorig[lp]) {
  ------------------
  |  Branch (1493:19): [True: 0, False: 0]
  ------------------
 1494|      0|                delete[] guessorig[lp];
 1495|      0|                guessorig[lp] = nullptr;
 1496|      0|              }
 1497|      0|            }
 1498|   184k|            gscore[lp] = sc;
 1499|   184k|            guess[lp] = glst[k].word;
 1500|   184k|            guessorig[lp] = glst[k].orig;
 1501|   184k|            lval = sc;
 1502|  37.1M|            for (int j = 0; j < MAX_GUESS; j++)
  ------------------
  |  |   76|  37.1M|#define MAX_GUESS 200
  ------------------
  |  Branch (1502:29): [True: 36.9M, False: 184k]
  ------------------
 1503|  36.9M|              if (gscore[j] < lval) {
  ------------------
  |  Branch (1503:19): [True: 32.7M, False: 4.28M]
  ------------------
 1504|  32.7M|                lp = j;
 1505|  32.7M|                lval = gscore[j];
 1506|  32.7M|              }
 1507|   184k|          } else {
 1508|      0|            delete[] glst[k].word;
 1509|      0|            delete[] glst[k].orig;
 1510|      0|          }
 1511|   512k|        } else {
 1512|   512k|          delete[] glst[k].word;
 1513|   512k|          delete[] glst[k].orig;
 1514|   512k|        }
 1515|   696k|      }
 1516|   698k|    }
 1517|  4.74M|  }
 1518|  47.4k|  glst.clear();
 1519|       |
 1520|       |  // now we are done generating guesses
 1521|       |  // sort in order of decreasing score
 1522|       |
 1523|  47.4k|  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
  ------------------
  |  |   76|  47.4k|#define MAX_GUESS 200
  ------------------
 1524|  47.4k|  if (ph)
  ------------------
  |  Branch (1524:7): [True: 2.80k, False: 44.6k]
  ------------------
 1525|  2.80k|    bubblesort(&rootsphon[0], nullptr, &scoresphon[0], MAX_ROOTS);
  ------------------
  |  |   74|  2.80k|#define MAX_ROOTS 100
  ------------------
 1526|       |
 1527|       |  // weight suggestions with a similarity index, based on
 1528|       |  // the longest common subsequent algorithm and resort
 1529|       |
 1530|  47.4k|  int is_swap = 0;
 1531|  47.4k|  int re = 0;
 1532|  47.4k|  double fact = 1.0;
 1533|  47.4k|  if (pAMgr) {
  ------------------
  |  Branch (1533:7): [True: 47.4k, False: 0]
  ------------------
 1534|  47.4k|    int maxd = pAMgr->get_maxdiff();
 1535|  47.4k|    if (maxd >= 0)
  ------------------
  |  Branch (1535:9): [True: 0, False: 47.4k]
  ------------------
 1536|      0|      fact = (10.0 - maxd) / 5.0;
 1537|  47.4k|  }
 1538|       |
 1539|  47.4k|  std::vector<w_char> w_gl;
 1540|  9.09M|  for (int i = 0; i < MAX_GUESS; i++) {
  ------------------
  |  |   76|  9.09M|#define MAX_GUESS 200
  ------------------
  |  Branch (1540:19): [True: 9.04M, False: 45.1k]
  ------------------
 1541|  9.04M|    if (guess[i]) {
  ------------------
  |  Branch (1541:9): [True: 125k, False: 8.92M]
  ------------------
 1542|       |      // lowering guess[i]
 1543|   125k|      std::string gl;
 1544|   125k|      int len;
 1545|   125k|      if (utf8) {
  ------------------
  |  Branch (1545:11): [True: 71.1k, False: 54.6k]
  ------------------
 1546|  71.1k|        len = u8_u16(w_gl, guess[i]);
 1547|  71.1k|        mkallsmall_utf(w_gl, langnum);
 1548|  71.1k|        u16_u8(gl, w_gl);
 1549|  71.1k|      } else {
 1550|  54.6k|        gl.assign(guess[i]);
 1551|  54.6k|        if (!nonbmp)
  ------------------
  |  Branch (1551:13): [True: 54.5k, False: 102]
  ------------------
 1552|  54.5k|          mkallsmall(gl, csconv);
 1553|       |        // a guess is a dictionary word, at most 65535 bytes (the limit of hentry::blen), plus
 1554|       |        // its affixes
 1555|  54.6k|        len = static_cast<int>(strlen(guess[i]));
 1556|  54.6k|      }
 1557|       |
 1558|   125k|      int _lcs = lcslen(word, gl.c_str());
 1559|       |
 1560|       |      // same characters with different casing
 1561|   125k|      if ((n == len) && (n == _lcs)) {
  ------------------
  |  Branch (1561:11): [True: 17.9k, False: 107k]
  |  Branch (1561:25): [True: 2.37k, False: 15.5k]
  ------------------
 1562|  2.37k|        gscore[i] += 2000;
 1563|  2.37k|        break;
 1564|  2.37k|      }
 1565|       |      // using 2-gram instead of 3, and other weightening
 1566|       |
 1567|   123k|      if (utf8) {
  ------------------
  |  Branch (1567:11): [True: 69.1k, False: 54.2k]
  ------------------
 1568|  69.1k|        u8_u16(w_gl, gl);
 1569|       |        //w_gl is lowercase already at this point
 1570|  69.1k|        re = ngram(2, w_word, w_gl, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   82|  69.1k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
                      re = ngram(2, w_word, w_gl, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   84|  69.1k|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
 1571|  69.1k|        if (low) {
  ------------------
  |  Branch (1571:13): [True: 69.1k, False: 0]
  ------------------
 1572|  69.1k|          w_f = w_word;
 1573|       |          // lowering dictionary word
 1574|  69.1k|          mkallsmall_utf(w_f, langnum);
 1575|  69.1k|          re += ngram(2, w_gl, w_f, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   82|  69.1k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
                        re += ngram(2, w_gl, w_f, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   84|  69.1k|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
 1576|  69.1k|        } else {
 1577|      0|          re += ngram(2, w_gl, w_word, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   82|      0|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
                        re += ngram(2, w_gl, w_word, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   84|      0|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
 1578|      0|        }
 1579|  69.1k|      } else {
 1580|       |        //gl is lowercase already at this point
 1581|  54.2k|        re = ngram(2, word, gl, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   82|  54.2k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
                      re = ngram(2, word, gl, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   84|  54.2k|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
 1582|  54.2k|        if (low) {
  ------------------
  |  Branch (1582:13): [True: 54.1k, False: 102]
  ------------------
 1583|  54.1k|          f = word;
 1584|       |          // lowering dictionary word
 1585|  54.1k|          mkallsmall(f, csconv);
 1586|  54.1k|          re += ngram(2, gl, f, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   82|  54.1k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
                        re += ngram(2, gl, f, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   84|  54.1k|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
 1587|  54.1k|        } else {
 1588|    102|          re += ngram(2, gl, word, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   82|    102|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
                        re += ngram(2, gl, word, NGRAM_ANY_MISMATCH | NGRAM_WEIGHTED);
  ------------------
  |  |   84|    102|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
 1589|    102|        }
 1590|  54.2k|      }
 1591|       |
 1592|   123k|      int ngram_score, leftcommon_score;
 1593|   123k|      if (utf8) {
  ------------------
  |  Branch (1593:11): [True: 69.1k, False: 54.2k]
  ------------------
 1594|       |        //w_gl is lowercase already at this point
 1595|  69.1k|        ngram_score = ngram(4, w_word, w_gl, NGRAM_ANY_MISMATCH);
  ------------------
  |  |   82|  69.1k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
 1596|  69.1k|        leftcommon_score = leftcommonsubstring(w_word, w_gl);
 1597|  69.1k|      } else {
 1598|       |        //gl is lowercase already at this point
 1599|  54.2k|        ngram_score = ngram(4, word, gl, NGRAM_ANY_MISMATCH);
  ------------------
  |  |   82|  54.2k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
 1600|  54.2k|        leftcommon_score = leftcommonsubstring(word, gl.c_str());
 1601|  54.2k|      }
 1602|   123k|      gscore[i] =
 1603|       |          // length of longest common subsequent minus length difference
 1604|   123k|          2 * _lcs - abs((int)(n - len)) +
 1605|       |          // weight length of the left common substring
 1606|   123k|          leftcommon_score +
 1607|       |          // weight equal character positions
 1608|   123k|          (!nonbmp && commoncharacterpositions(word, gl.c_str(), &is_swap)
  ------------------
  |  Branch (1608:12): [True: 123k, False: 102]
  |  Branch (1608:23): [True: 104k, False: 19.2k]
  ------------------
 1609|   123k|               ? 1
 1610|   123k|               : 0) +
 1611|       |          // swap character (not neighboring)
 1612|   123k|          ((is_swap) ? 10 : 0) +
  ------------------
  |  Branch (1612:12): [True: 149, False: 123k]
  ------------------
 1613|       |          // ngram
 1614|   123k|          ngram_score +
 1615|       |          // weighted ngrams
 1616|   123k|          re +
 1617|       |          // different limit for dictionaries with PHONE rules
 1618|   123k|          (ph ? (re < len * fact ? -1000 : 0)
  ------------------
  |  Branch (1618:12): [True: 5.30k, False: 118k]
  |  Branch (1618:18): [True: 3.78k, False: 1.52k]
  ------------------
 1619|   123k|              : (re < (n + len) * fact ? -1000 : 0));
  ------------------
  |  Branch (1619:18): [True: 75.3k, False: 42.7k]
  ------------------
 1620|   123k|    }
 1621|  9.04M|  }
 1622|       |
 1623|  47.4k|  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
  ------------------
  |  |   76|  47.4k|#define MAX_GUESS 200
  ------------------
 1624|       |
 1625|       |  // phonetic version
 1626|  47.4k|  if (ph)
  ------------------
  |  Branch (1626:7): [True: 2.80k, False: 44.6k]
  ------------------
 1627|   283k|    for (int i = 0; i < MAX_ROOTS; i++) {
  ------------------
  |  |   74|   283k|#define MAX_ROOTS 100
  ------------------
  |  Branch (1627:21): [True: 280k, False: 2.80k]
  ------------------
 1628|   280k|      if (rootsphon[i]) {
  ------------------
  |  Branch (1628:11): [True: 6.83k, False: 274k]
  ------------------
 1629|       |        // lowering rootphon[i]
 1630|  6.83k|        std::string gl;
 1631|  6.83k|        int len;
 1632|  6.83k|        if (utf8) {
  ------------------
  |  Branch (1632:13): [True: 0, False: 6.83k]
  ------------------
 1633|      0|          len = u8_u16(w_gl, rootsphon[i]);
 1634|      0|          mkallsmall_utf(w_gl, langnum);
 1635|      0|          u16_u8(gl, w_gl);
 1636|  6.83k|        } else {
 1637|  6.83k|          gl.assign(rootsphon[i]);
 1638|  6.83k|          if (!nonbmp)
  ------------------
  |  Branch (1638:15): [True: 6.83k, False: 0]
  ------------------
 1639|  6.83k|            mkallsmall(gl, csconv);
 1640|       |          // a root is a dictionary word, at most 65535 bytes (the limit of hentry::blen)
 1641|  6.83k|          len = static_cast<int>(strlen(rootsphon[i]));
 1642|  6.83k|        }
 1643|       |
 1644|       |        // weight length of the left common substring
 1645|  6.83k|        int leftcommon_score;
 1646|  6.83k|        if (utf8)
  ------------------
  |  Branch (1646:13): [True: 0, False: 6.83k]
  ------------------
 1647|      0|          leftcommon_score = leftcommonsubstring(w_word, w_gl);
 1648|  6.83k|        else
 1649|  6.83k|          leftcommon_score = leftcommonsubstring(word, gl.c_str());
 1650|       |        // heuristic weigthing of ngram scores
 1651|  6.83k|        scoresphon[i] += 2 * lcslen(word, gl) - abs((int)(n - len)) +
 1652|  6.83k|                         leftcommon_score;
 1653|  6.83k|      }
 1654|   280k|    }
 1655|       |
 1656|  47.4k|  if (ph)
  ------------------
  |  Branch (1656:7): [True: 2.80k, False: 44.6k]
  ------------------
 1657|  2.80k|    bubblesort(&rootsphon[0], nullptr, &scoresphon[0], MAX_ROOTS);
  ------------------
  |  |   74|  2.80k|#define MAX_ROOTS 100
  ------------------
 1658|       |
 1659|       |  // copy over
 1660|  47.4k|  size_t oldns = wlst.size();
 1661|       |
 1662|  47.4k|  int same = 0;
 1663|  9.54M|  for (int i = 0; i < MAX_GUESS; i++) {
  ------------------
  |  |   76|  9.54M|#define MAX_GUESS 200
  ------------------
  |  Branch (1663:19): [True: 9.49M, False: 47.4k]
  ------------------
 1664|  9.49M|    if (guess[i]) {
  ------------------
  |  Branch (1664:9): [True: 184k, False: 9.31M]
  ------------------
 1665|   184k|      if ((wlst.size() < oldns + maxngramsugs) && (wlst.size() < maxSug) &&
  ------------------
  |  Branch (1665:11): [True: 165k, False: 18.9k]
  |  Branch (1665:51): [True: 165k, False: 0]
  ------------------
 1666|   165k|          (!same || (gscore[i] > 1000))) {
  ------------------
  |  Branch (1666:12): [True: 19.7k, False: 146k]
  |  Branch (1666:21): [True: 0, False: 146k]
  ------------------
 1667|  19.7k|        int unique = 1;
 1668|       |        // leave only excellent suggestions, if exists
 1669|  19.7k|        if (gscore[i] > 1000)
  ------------------
  |  Branch (1669:13): [True: 2.37k, False: 17.3k]
  ------------------
 1670|  2.37k|          same = 1;
 1671|  17.3k|        else if (gscore[i] < -100) {
  ------------------
  |  Branch (1671:18): [True: 8.51k, False: 8.86k]
  ------------------
 1672|  8.51k|          same = 1;
 1673|       |          // keep the best ngram suggestions, unless in ONLYMAXDIFF mode
 1674|  8.51k|          if (wlst.size() > oldns || (pAMgr && pAMgr->get_onlymaxdiff())) {
  ------------------
  |  Branch (1674:15): [True: 1.70k, False: 6.80k]
  |  Branch (1674:39): [True: 6.80k, False: 0]
  |  Branch (1674:48): [True: 0, False: 6.80k]
  ------------------
 1675|  1.70k|            delete[] guess[i];
 1676|  1.70k|            delete[] guessorig[i];
 1677|  1.70k|            continue;
 1678|  1.70k|          }
 1679|  8.51k|        }
 1680|  18.0k|        for (auto& j : wlst) {
  ------------------
  |  Branch (1680:22): [True: 13.5k, False: 15.0k]
  ------------------
 1681|       |          // don't suggest previous suggestions or a previous suggestion with
 1682|       |          // prefixes or affixes
 1683|  13.5k|          if ((!guessorig[i] && strstr(guess[i], j.c_str())) || (guessorig[i] && strstr(guessorig[i], j.c_str())) ||
  ------------------
  |  Branch (1683:15): [True: 2.95k, False: 10.5k]
  |  Branch (1683:16): [True: 13.5k, False: 0]
  |  Branch (1683:33): [True: 2.95k, False: 10.5k]
  |  Branch (1683:66): [True: 0, False: 10.5k]
  |  Branch (1683:82): [True: 0, False: 0]
  ------------------
 1684|       |              // check forbidden words
 1685|  10.5k|              !checkword(guess[i], 0, nullptr, nullptr)) {
  ------------------
  |  Branch (1685:15): [True: 0, False: 10.5k]
  ------------------
 1686|  2.95k|            unique = 0;
 1687|  2.95k|            break;
 1688|  2.95k|          }
 1689|  13.5k|        }
 1690|  18.0k|        if (unique) {
  ------------------
  |  Branch (1690:13): [True: 15.0k, False: 2.95k]
  ------------------
 1691|  15.0k|          if (guessorig[i]) {
  ------------------
  |  Branch (1691:15): [True: 0, False: 15.0k]
  ------------------
 1692|      0|            wlst.emplace_back(guessorig[i]);
 1693|  15.0k|          } else {
 1694|  15.0k|            wlst.emplace_back(guess[i]);
 1695|  15.0k|          }
 1696|  15.0k|        }
 1697|  18.0k|        delete[] guess[i];
 1698|  18.0k|        delete[] guessorig[i];
 1699|   165k|      } else {
 1700|   165k|        delete[] guess[i];
 1701|   165k|        delete[] guessorig[i];
 1702|   165k|      }
 1703|   184k|    }
 1704|  9.49M|  }
 1705|       |
 1706|  47.4k|  oldns = wlst.size();
 1707|  47.4k|  if (ph)
  ------------------
  |  Branch (1707:7): [True: 2.80k, False: 44.6k]
  ------------------
 1708|   280k|    for (auto& i : rootsphon) {
  ------------------
  |  Branch (1708:18): [True: 280k, False: 2.80k]
  ------------------
 1709|   280k|      if (i) {
  ------------------
  |  Branch (1709:11): [True: 6.83k, False: 274k]
  ------------------
 1710|  6.83k|        if ((wlst.size() < oldns + MAXPHONSUGS) && (wlst.size() < maxSug)) {
  ------------------
  |  |   78|  6.83k|#define MAXPHONSUGS 2
  ------------------
  |  Branch (1710:13): [True: 3.00k, False: 3.83k]
  |  Branch (1710:52): [True: 3.00k, False: 0]
  ------------------
 1711|  3.00k|          int unique = 1;
 1712|  5.76k|          for (auto& j : wlst) {
  ------------------
  |  Branch (1712:24): [True: 5.76k, False: 942]
  ------------------
 1713|       |            // don't suggest previous suggestions or a previous suggestion with
 1714|       |            // prefixes or affixes
 1715|  5.76k|            if (strstr(i, j.c_str()) ||
  ------------------
  |  Branch (1715:17): [True: 2.06k, False: 3.70k]
  |  Branch (1715:17): [True: 2.06k, False: 3.70k]
  ------------------
 1716|       |                // check forbidden words
 1717|  3.70k|                !checkword(i, 0, nullptr, nullptr)) {
  ------------------
  |  Branch (1717:17): [True: 0, False: 3.70k]
  ------------------
 1718|  2.06k|              unique = 0;
 1719|  2.06k|              break;
 1720|  2.06k|            }
 1721|  5.76k|          }
 1722|  3.00k|          if (unique) {
  ------------------
  |  Branch (1722:15): [True: 942, False: 2.06k]
  ------------------
 1723|    942|            wlst.emplace_back(i);
 1724|    942|          }
 1725|  3.00k|        }
 1726|  6.83k|      }
 1727|   280k|    }
 1728|  47.4k|}
_ZN10SuggestMgr9checkwordERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEiPiPNS0_6chrono10time_pointINSA_12steady_clockENSA_8durationIxNS0_5ratioILl1ELl1000000000EEEEEEE:
 1739|  92.6M|                          std::chrono::steady_clock::time_point* timelimit) {
 1740|       |  // check overall suggestion time limit
 1741|  92.6M|  if (std::chrono::steady_clock::now() - suggest_start > TIMELIMIT_SUGGESTION_MS)
  ------------------
  |  |  108|  92.6M|#define TIMELIMIT_SUGGESTION_MS std::chrono::milliseconds(100)
  ------------------
  |  Branch (1741:7): [True: 0, False: 92.6M]
  ------------------
 1742|      0|    return 0;
 1743|       |
 1744|       |  // check time limit
 1745|  92.6M|  if (timer) {
  ------------------
  |  Branch (1745:7): [True: 1.59M, False: 91.0M]
  ------------------
 1746|  1.59M|    (*timer)--;
 1747|  1.59M|    if (!(*timer) && timelimit) {
  ------------------
  |  Branch (1747:9): [True: 11.1k, False: 1.58M]
  |  Branch (1747:22): [True: 11.1k, False: 0]
  ------------------
 1748|  11.1k|      if (std::chrono::steady_clock::now() - *timelimit > TIMELIMIT_MS)
  ------------------
  |  |  109|  11.1k|#define TIMELIMIT_MS std::chrono::milliseconds(50)
  ------------------
  |  Branch (1748:11): [True: 2, False: 11.1k]
  ------------------
 1749|      2|        return 0;
 1750|  11.1k|      *timer = MAXPLUSTIMER;
  ------------------
  |  |  111|  11.1k|#define MAXPLUSTIMER 100
  ------------------
 1751|  11.1k|    }
 1752|  1.59M|  }
 1753|       |
 1754|  92.6M|  if (pAMgr) {
  ------------------
  |  Branch (1754:7): [True: 92.6M, False: 0]
  ------------------
 1755|  92.6M|    struct hentry* rv = nullptr;
 1756|  92.6M|    int nosuffix = 0;
 1757|  92.6M|    size_t len = word.size();
 1758|       |
 1759|  92.6M|    if (cpdsuggest >= 1) {
  ------------------
  |  Branch (1759:9): [True: 60.6M, False: 31.9M]
  ------------------
 1760|  60.6M|      if (pAMgr->get_compound()) {
  ------------------
  |  Branch (1760:11): [True: 15.1M, False: 45.5M]
  ------------------
 1761|  15.1M|        struct hentry* rv2 = nullptr;
 1762|  15.1M|        struct hentry* rwords[100] = {};  // buffer for COMPOUND pattern checking
 1763|  15.1M|        int info = (cpdsuggest == 1) ? SPELL_COMPOUND_2 : 0;
  ------------------
  |  |   88|  7.55M|#define SPELL_COMPOUND_2 (1 << 7)  // permit only 2 dictionary words in the compound
  ------------------
  |  Branch (1763:20): [True: 7.55M, False: 7.55M]
  ------------------
 1764|  15.1M|        AffixScratch scratch;
 1765|  15.1M|        rv = pAMgr->compound_check(word, 0, 0, 100, 0, nullptr, (hentry**)&rwords, 0, 1, &info, scratch);  // EXT
 1766|       |        // TODO filter 3-word or more compound words, as in spell()
 1767|       |        // (it's too slow to call suggest() here for all possible compound words)
 1768|  15.1M|        if (rv &&
  ------------------
  |  Branch (1768:13): [True: 0, False: 15.1M]
  |  Branch (1768:13): [True: 0, False: 15.1M]
  ------------------
 1769|      0|            (!(rv2 = pAMgr->lookup(word.c_str(), word.size())) || !rv2->astr ||
  ------------------
  |  Branch (1769:14): [True: 0, False: 0]
  |  Branch (1769:67): [True: 0, False: 0]
  ------------------
 1770|      0|             !(TESTAFF(rv2->astr, pAMgr->get_forbiddenword(), rv2->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1771|      0|               TESTAFF(rv2->astr, pAMgr->get_nosuggest(), rv2->alen))))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1772|      0|          return 3;  // XXX obsolote categorisation + only ICONV needs affix
 1773|       |                     // flag check?
 1774|  15.1M|      }
 1775|  60.6M|      return 0;
 1776|  60.6M|    }
 1777|       |
 1778|  31.9M|    rv = pAMgr->lookup(word.c_str(), word.size());
 1779|       |
 1780|  31.9M|    if (rv) {
  ------------------
  |  Branch (1780:9): [True: 50.0k, False: 31.9M]
  ------------------
 1781|  50.0k|      if ((rv->astr) &&
  ------------------
  |  Branch (1781:11): [True: 91, False: 49.9k]
  |  Branch (1781:11): [True: 0, False: 50.0k]
  ------------------
 1782|     91|          (TESTAFF(rv->astr, pAMgr->get_forbiddenword(), rv->alen) ||
  ------------------
  |  |  102|    182|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 91]
  |  |  ------------------
  ------------------
 1783|     91|           TESTAFF(rv->astr, pAMgr->get_nosuggest(), rv->alen) ||
  ------------------
  |  |  102|    182|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 91]
  |  |  ------------------
  ------------------
 1784|     91|           TESTAFF(rv->astr, pAMgr->get_substandard(), rv->alen)))
  ------------------
  |  |  102|     91|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 91]
  |  |  ------------------
  ------------------
 1785|      0|        return 0;
 1786|  50.0k|      while (rv) {
  ------------------
  |  Branch (1786:14): [True: 50.0k, False: 90]
  ------------------
 1787|  50.0k|        if (rv->astr &&
  ------------------
  |  Branch (1787:13): [True: 91, False: 49.9k]
  |  Branch (1787:13): [True: 90, False: 49.9k]
  ------------------
 1788|     91|            (TESTAFF(rv->astr, pAMgr->get_needaffix(), rv->alen) ||
  ------------------
  |  |  102|    182|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 91]
  |  |  ------------------
  ------------------
 1789|     91|             TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
  ------------------
  |  |  102|    182|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 90, False: 1]
  |  |  ------------------
  ------------------
 1790|     90|             TESTAFF(rv->astr, pAMgr->get_onlyincompound(), rv->alen))) {
  ------------------
  |  |  102|      1|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
 1791|     90|          rv = rv->next_homonym;
 1792|     90|        } else
 1793|  49.9k|          break;
 1794|  50.0k|      }
 1795|  31.9M|    } else {
 1796|  31.9M|      AffixScratch scratch;
 1797|  31.9M|      rv = pAMgr->prefix_check(word, 0, len,
 1798|  31.9M|                               0, scratch);  // only prefix, and prefix + suffix XXX
 1799|  31.9M|    }
 1800|       |
 1801|  31.9M|    if (rv) {
  ------------------
  |  Branch (1801:9): [True: 49.9k, False: 31.9M]
  ------------------
 1802|  49.9k|      nosuffix = 1;
 1803|  31.9M|    } else {
 1804|  31.9M|      AffixScratch scratch;
 1805|  31.9M|      rv = pAMgr->suffix_check(word, 0, len, 0, nullptr, scratch, FLAG_NULL, FLAG_NULL, IN_CPD_NOT);  // only suffix
  ------------------
  |  |   99|  31.9M|#define FLAG_NULL 0x00
  ------------------
                    rv = pAMgr->suffix_check(word, 0, len, 0, nullptr, scratch, FLAG_NULL, FLAG_NULL, IN_CPD_NOT);  // only suffix
  ------------------
  |  |   99|  31.9M|#define FLAG_NULL 0x00
  ------------------
                    rv = pAMgr->suffix_check(word, 0, len, 0, nullptr, scratch, FLAG_NULL, FLAG_NULL, IN_CPD_NOT);  // only suffix
  ------------------
  |  |   75|  31.9M|#define IN_CPD_NOT 0
  ------------------
 1806|  31.9M|    }
 1807|       |
 1808|  31.9M|    if (!rv && pAMgr->have_contclass()) {
  ------------------
  |  Branch (1808:9): [True: 31.9M, False: 49.9k]
  |  Branch (1808:16): [True: 11.3M, False: 20.5M]
  ------------------
 1809|  11.3M|      AffixScratch scratch;
 1810|  11.3M|      rv = pAMgr->suffix_check_twosfx(word, 0, len, 0, nullptr, scratch, FLAG_NULL);
  ------------------
  |  |   99|  11.3M|#define FLAG_NULL 0x00
  ------------------
 1811|  11.3M|      if (!rv)
  ------------------
  |  Branch (1811:11): [True: 11.3M, False: 0]
  ------------------
 1812|  11.3M|        rv = pAMgr->prefix_check_twosfx(word, 0, len, 0, scratch, FLAG_NULL);
  ------------------
  |  |   99|  11.3M|#define FLAG_NULL 0x00
  ------------------
 1813|  11.3M|    }
 1814|       |
 1815|       |    // check forbidden words
 1816|  31.9M|    if ((rv) && (rv->astr) &&
  ------------------
  |  Branch (1816:9): [True: 49.9k, False: 31.9M]
  |  Branch (1816:9): [True: 0, False: 31.9M]
  |  Branch (1816:17): [True: 1, False: 49.9k]
  ------------------
 1817|      1|        (TESTAFF(rv->astr, pAMgr->get_forbiddenword(), rv->alen) ||
  ------------------
  |  |  102|      2|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
 1818|      1|         TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
  ------------------
  |  |  102|      2|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
 1819|      1|         TESTAFF(rv->astr, pAMgr->get_nosuggest(), rv->alen) ||
  ------------------
  |  |  102|      2|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
 1820|      1|         TESTAFF(rv->astr, pAMgr->get_onlyincompound(), rv->alen)))
  ------------------
  |  |  102|      1|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
 1821|      0|      return 0;
 1822|       |
 1823|  31.9M|    if (rv) {  // XXX obsolote
  ------------------
  |  Branch (1823:9): [True: 49.9k, False: 31.9M]
  ------------------
 1824|  49.9k|      if ((pAMgr->get_compoundflag()) &&
  ------------------
  |  Branch (1824:11): [True: 12.0k, False: 37.9k]
  |  Branch (1824:11): [True: 1, False: 49.9k]
  ------------------
 1825|  12.0k|          TESTAFF(rv->astr, pAMgr->get_compoundflag(), rv->alen))
  ------------------
  |  |  102|  12.0k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 1, False: 12.0k]
  |  |  ------------------
  ------------------
 1826|      1|        return 2 + nosuffix;
 1827|  49.9k|      return 1;
 1828|  49.9k|    }
 1829|  31.9M|  }
 1830|  31.9M|  return 0;
 1831|  92.6M|}
_ZN10SuggestMgr15check_forbiddenERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1833|  15.4k|int SuggestMgr::check_forbidden(const std::string& word) {
 1834|  15.4k|  if (pAMgr) {
  ------------------
  |  Branch (1834:7): [True: 15.4k, False: 0]
  ------------------
 1835|  15.4k|    struct hentry* rv = pAMgr->lookup(word.c_str(), word.size());
 1836|  15.4k|    if (rv && rv->astr &&
  ------------------
  |  Branch (1836:9): [True: 0, False: 15.4k]
  |  Branch (1836:9): [True: 0, False: 15.4k]
  |  Branch (1836:15): [True: 0, False: 0]
  ------------------
 1837|      0|        (TESTAFF(rv->astr, pAMgr->get_needaffix(), rv->alen) ||
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1838|      0|         TESTAFF(rv->astr, pAMgr->get_onlyincompound(), rv->alen)))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1839|      0|      rv = nullptr;
 1840|  15.4k|    size_t len = word.size();
 1841|  15.4k|    AffixScratch scratch;
 1842|  15.4k|    if (!(pAMgr->prefix_check(word, 0, len, 1, scratch)))
  ------------------
  |  Branch (1842:9): [True: 15.4k, False: 0]
  ------------------
 1843|  15.4k|      rv = pAMgr->suffix_check(word, 0, len, 0, nullptr, scratch, FLAG_NULL, FLAG_NULL, IN_CPD_NOT);  // prefix+suffix, suffix
  ------------------
  |  |   99|  15.4k|#define FLAG_NULL 0x00
  ------------------
                    rv = pAMgr->suffix_check(word, 0, len, 0, nullptr, scratch, FLAG_NULL, FLAG_NULL, IN_CPD_NOT);  // prefix+suffix, suffix
  ------------------
  |  |   99|  15.4k|#define FLAG_NULL 0x00
  ------------------
                    rv = pAMgr->suffix_check(word, 0, len, 0, nullptr, scratch, FLAG_NULL, FLAG_NULL, IN_CPD_NOT);  // prefix+suffix, suffix
  ------------------
  |  |   75|  15.4k|#define IN_CPD_NOT 0
  ------------------
 1844|       |    // check forbidden words
 1845|  15.4k|    if ((rv) && (rv->astr) &&
  ------------------
  |  Branch (1845:9): [True: 0, False: 15.4k]
  |  Branch (1845:9): [True: 0, False: 15.4k]
  |  Branch (1845:17): [True: 0, False: 0]
  ------------------
 1846|      0|        TESTAFF(rv->astr, pAMgr->get_forbiddenword(), rv->alen))
  ------------------
  |  |  102|      0|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1847|      0|      return 1;
 1848|  15.4k|  }
 1849|  15.4k|  return 0;
 1850|  15.4k|}
_ZN10SuggestMgr13suggest_morphERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1852|  11.9k|std::string SuggestMgr::suggest_morph(const std::string& in_w) {
 1853|  11.9k|  std::string result;
 1854|       |
 1855|  11.9k|  struct hentry* rv = nullptr;
 1856|       |
 1857|  11.9k|  if (!pAMgr)
  ------------------
  |  Branch (1857:7): [True: 0, False: 11.9k]
  ------------------
 1858|      0|    return {};
 1859|       |
 1860|  11.9k|  std::string w(in_w);
 1861|       |
 1862|       |  // word reversing wrapper for complex prefixes
 1863|  11.9k|  if (complexprefixes) {
  ------------------
  |  Branch (1863:7): [True: 613, False: 11.3k]
  ------------------
 1864|    613|    if (utf8)
  ------------------
  |  Branch (1864:9): [True: 0, False: 613]
  ------------------
 1865|      0|      reverseword_utf(w);
 1866|    613|    else
 1867|    613|      reverseword(w);
 1868|    613|  }
 1869|       |
 1870|  11.9k|  rv = pAMgr->lookup(w.c_str(), w.size());
 1871|       |
 1872|  14.0k|  while (rv) {
  ------------------
  |  Branch (1872:10): [True: 2.08k, False: 11.9k]
  ------------------
 1873|  2.08k|    if ((!rv->astr) ||
  ------------------
  |  Branch (1873:9): [True: 1.44k, False: 635]
  |  Branch (1873:9): [True: 2.08k, False: 0]
  ------------------
 1874|    635|        !(TESTAFF(rv->astr, pAMgr->get_forbiddenword(), rv->alen) ||
  ------------------
  |  |  102|  1.27k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 635]
  |  |  ------------------
  ------------------
 1875|    635|          TESTAFF(rv->astr, pAMgr->get_needaffix(), rv->alen) ||
  ------------------
  |  |  102|  1.27k|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 635]
  |  |  ------------------
  ------------------
 1876|  2.08k|          TESTAFF(rv->astr, pAMgr->get_onlyincompound(), rv->alen))) {
  ------------------
  |  |  102|    635|#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
  |  |  ------------------
  |  |  |  Branch (102:26): [True: 0, False: 635]
  |  |  ------------------
  ------------------
 1877|  2.08k|      append_morph_stem(result, rv, complexprefixes);
 1878|  2.08k|      if (HENTRY_DATA(rv)) {
  ------------------
  |  Branch (1878:11): [True: 0, False: 2.08k]
  ------------------
 1879|      0|        result.push_back(MSEP_FLD);
  ------------------
  |  |  117|      0|#define MSEP_FLD ' '
  ------------------
 1880|      0|        result.append(HENTRY_DATA2(rv));
 1881|      0|      }
 1882|  2.08k|      result.push_back(MSEP_REC);
  ------------------
  |  |  118|  2.08k|#define MSEP_REC '\n'
  ------------------
 1883|  2.08k|    }
 1884|  2.08k|    rv = rv->next_homonym;
 1885|  2.08k|  }
 1886|       |
 1887|  11.9k|  AffixScratch scratch;
 1888|  11.9k|  std::string st = pAMgr->affix_check_morph(w, 0, w.size(), scratch);
 1889|  11.9k|  if (!st.empty()) {
  ------------------
  |  Branch (1889:7): [True: 0, False: 11.9k]
  ------------------
 1890|      0|    result.append(st);
 1891|      0|  }
 1892|       |
 1893|  11.9k|  if (pAMgr->get_compound() && result.empty()) {
  ------------------
  |  Branch (1893:7): [True: 2.48k, False: 9.43k]
  |  Branch (1893:32): [True: 2.04k, False: 439]
  ------------------
 1894|  2.04k|    struct hentry* rwords[100] = {};  // buffer for COMPOUND pattern checking
 1895|  2.04k|    pAMgr->compound_check_morph(w, 0, 0, 100, 0, nullptr, (hentry**)&rwords, 0, result, nullptr, scratch);
 1896|  2.04k|  }
 1897|       |
 1898|  11.9k|  line_uniq(result, MSEP_REC);
  ------------------
  |  |  118|  11.9k|#define MSEP_REC '\n'
  ------------------
 1899|       |
 1900|  11.9k|  return result;
 1901|  11.9k|}
_ZN10SuggestMgr18suggest_hentry_genEP6hentryPKc:
 1926|   408k|std::string SuggestMgr::suggest_hentry_gen(hentry* rv, const char* pattern) {
 1927|   408k|  std::string result;
 1928|   408k|  int sfxcount = get_sfxcount(pattern);
 1929|       |
 1930|   408k|  if (get_sfxcount(HENTRY_DATA(rv)) > sfxcount)
  ------------------
  |  Branch (1930:7): [True: 0, False: 408k]
  ------------------
 1931|      0|    return result;
 1932|       |
 1933|   408k|  if (HENTRY_DATA(rv)) {
  ------------------
  |  Branch (1933:7): [True: 0, False: 408k]
  ------------------
 1934|      0|    std::string aff = pAMgr->morphgen(HENTRY_WORD(rv), rv->blen, rv->astr, rv->alen,
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 1935|      0|                                      HENTRY_DATA(rv), pattern, 0);
 1936|      0|    if (!aff.empty()) {
  ------------------
  |  Branch (1936:9): [True: 0, False: 0]
  ------------------
 1937|      0|      result.append(aff);
 1938|      0|      result.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 1939|      0|    }
 1940|      0|  }
 1941|       |
 1942|       |  // check all allomorphs
 1943|   408k|  char* p = nullptr;
 1944|   408k|  if (HENTRY_DATA(rv))
  ------------------
  |  Branch (1944:7): [True: 0, False: 408k]
  ------------------
 1945|      0|    p = (char*)strstr(HENTRY_DATA2(rv), MORPH_ALLOMORPH);
  ------------------
  |  |  100|      0|#define MORPH_ALLOMORPH "al:"
  ------------------
 1946|   408k|  while (p) {
  ------------------
  |  Branch (1946:10): [True: 0, False: 408k]
  ------------------
 1947|      0|    p += MORPH_TAG_LEN;
  ------------------
  |  |  115|      0|#define MORPH_TAG_LEN strlen(MORPH_STEM)
  |  |  ------------------
  |  |  |  |   99|      0|#define MORPH_STEM "st:"
  |  |  ------------------
  ------------------
 1948|      0|    int plen = fieldlen(p);
 1949|      0|    std::string allomorph(p, plen);
 1950|      0|    struct hentry* rv2 = pAMgr->lookup(allomorph.c_str(), allomorph.size());
 1951|      0|    while (rv2) {
  ------------------
  |  Branch (1951:12): [True: 0, False: 0]
  ------------------
 1952|       |      //            if (HENTRY_DATA(rv2) && get_sfxcount(HENTRY_DATA(rv2)) <=
 1953|       |      //            sfxcount) {
 1954|      0|      if (HENTRY_DATA(rv2)) {
  ------------------
  |  Branch (1954:11): [True: 0, False: 0]
  ------------------
 1955|      0|        char* st = (char*)strstr(HENTRY_DATA2(rv2), MORPH_STEM);
  ------------------
  |  |   99|      0|#define MORPH_STEM "st:"
  ------------------
 1956|      0|        if (st && (strncmp(st + MORPH_TAG_LEN, HENTRY_WORD(rv),
  ------------------
  |  |  115|      0|#define MORPH_TAG_LEN strlen(MORPH_STEM)
  |  |  ------------------
  |  |  |  |   99|      0|#define MORPH_STEM "st:"
  |  |  ------------------
  ------------------
                      if (st && (strncmp(st + MORPH_TAG_LEN, HENTRY_WORD(rv),
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
  |  Branch (1956:13): [True: 0, False: 0]
  |  Branch (1956:19): [True: 0, False: 0]
  ------------------
 1957|      0|                           fieldlen(st + MORPH_TAG_LEN)) == 0)) {
  ------------------
  |  |  115|      0|#define MORPH_TAG_LEN strlen(MORPH_STEM)
  |  |  ------------------
  |  |  |  |   99|      0|#define MORPH_STEM "st:"
  |  |  ------------------
  ------------------
 1958|      0|          std::string aff = pAMgr->morphgen(HENTRY_WORD(rv2), rv2->blen, rv2->astr,
  ------------------
  |  |   54|      0|#define HENTRY_WORD(h) &(h->word[0])
  ------------------
 1959|      0|                                            rv2->alen, HENTRY_DATA(rv2), pattern, 0);
 1960|      0|          if (!aff.empty()) {
  ------------------
  |  Branch (1960:15): [True: 0, False: 0]
  ------------------
 1961|      0|            result.append(aff);
 1962|      0|            result.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 1963|      0|          }
 1964|      0|        }
 1965|      0|      }
 1966|      0|      rv2 = rv2->next_homonym;
 1967|      0|    }
 1968|      0|    p = strstr(p + plen, MORPH_ALLOMORPH);
  ------------------
  |  |  100|      0|#define MORPH_ALLOMORPH "al:"
  ------------------
 1969|      0|  }
 1970|       |
 1971|   408k|  return result;
 1972|   408k|}
_ZN10SuggestMgr11suggest_genERKNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEERKS7_NS0_6chrono10time_pointINSE_12steady_clockENSE_8durationIxNS0_5ratioILl1ELl1000000000EEEEEEE:
 1975|   396k|                                    std::chrono::steady_clock::time_point start_time) {
 1976|   396k|  if (desc.empty() || !pAMgr)
  ------------------
  |  Branch (1976:7): [True: 256k, False: 139k]
  |  Branch (1976:23): [True: 0, False: 139k]
  ------------------
 1977|   256k|    return {};
 1978|       |
 1979|   139k|  const char* pattern = in_pattern.c_str();
 1980|   139k|  std::string result2;
 1981|   139k|  std::string newpattern;
 1982|   139k|  struct hentry* rv = nullptr;
 1983|       |
 1984|       |  // search affixed forms with and without derivational suffixes
 1985|   171k|  while (true) {
  ------------------
  |  Branch (1985:10): [True: 171k, Folded]
  ------------------
 1986|   171k|    for (const auto& k : desc) {
  ------------------
  |  Branch (1986:24): [True: 171k, False: 171k]
  ------------------
 1987|   171k|      if (std::chrono::steady_clock::now() - start_time > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|   171k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (1987:11): [True: 0, False: 171k]
  ------------------
 1988|      0|        return result2;
 1989|   171k|      std::string result;
 1990|       |
 1991|       |      // add compound word parts (except the last one)
 1992|   171k|      const size_t lastpart = append_compound_parts(k, result);
 1993|   171k|      const char* s = k.c_str() + lastpart;
 1994|   171k|      std::string tok(k, lastpart);
 1995|   171k|      size_t pos = tok.find(" | ");
 1996|   171k|      while (pos != std::string::npos) {
  ------------------
  |  Branch (1996:14): [True: 0, False: 171k]
  ------------------
 1997|      0|        tok[pos + 1] = MSEP_ALT;
  ------------------
  |  |  119|      0|#define MSEP_ALT '\v'
  ------------------
 1998|      0|        pos = tok.find(" | ", pos);
 1999|      0|      }
 2000|   171k|      std::vector<std::string> pl = line_tok(tok, MSEP_ALT);
  ------------------
  |  |  119|   171k|#define MSEP_ALT '\v'
  ------------------
 2001|   171k|      for (auto& i : pl) {
  ------------------
  |  Branch (2001:20): [True: 171k, False: 171k]
  ------------------
 2002|       |        // remove inflectional and terminal suffixes
 2003|   171k|        size_t is = i.find(MORPH_INFL_SFX);
  ------------------
  |  |  106|   171k|#define MORPH_INFL_SFX "is:"
  ------------------
 2004|   171k|        if (is != std::string::npos)
  ------------------
  |  Branch (2004:13): [True: 0, False: 171k]
  ------------------
 2005|      0|          i.resize(is);
 2006|   171k|        size_t ts = i.find(MORPH_TERM_SFX);
  ------------------
  |  |  107|   171k|#define MORPH_TERM_SFX "ts:"
  ------------------
 2007|   171k|        while (ts != std::string::npos) {
  ------------------
  |  Branch (2007:16): [True: 0, False: 171k]
  ------------------
 2008|      0|          i[ts] = '_';
 2009|      0|          ts = i.find(MORPH_TERM_SFX);
  ------------------
  |  |  107|      0|#define MORPH_TERM_SFX "ts:"
  ------------------
 2010|      0|        }
 2011|   171k|        const char* st = strstr(s, MORPH_STEM);
  ------------------
  |  |   99|   171k|#define MORPH_STEM "st:"
  ------------------
 2012|   171k|        if (st) {
  ------------------
  |  Branch (2012:13): [True: 171k, False: 5]
  ------------------
 2013|   171k|          copy_field(tok, st, MORPH_STEM);
  ------------------
  |  |   99|   171k|#define MORPH_STEM "st:"
  ------------------
 2014|   171k|          rv = pAMgr->lookup(tok.c_str(), tok.size());
 2015|   376k|          while (rv) {
  ------------------
  |  Branch (2015:18): [True: 204k, False: 171k]
  ------------------
 2016|   204k|            if (std::chrono::steady_clock::now() - start_time > TIMELIMIT_GLOBAL_MS)
  ------------------
  |  |  107|   204k|#define TIMELIMIT_GLOBAL_MS std::chrono::milliseconds(250)
  ------------------
  |  Branch (2016:17): [True: 0, False: 204k]
  ------------------
 2017|      0|              return result2;
 2018|   204k|            std::string newpat(i);
 2019|   204k|            newpat.append(pattern);
 2020|   204k|            std::string sg = suggest_hentry_gen(rv, newpat.c_str());
 2021|   204k|            if (sg.empty())
  ------------------
  |  Branch (2021:17): [True: 204k, False: 0]
  ------------------
 2022|   204k|              sg = suggest_hentry_gen(rv, pattern);
 2023|   204k|            if (!sg.empty()) {
  ------------------
  |  Branch (2023:17): [True: 0, False: 204k]
  ------------------
 2024|      0|              std::vector<std::string> gen = line_tok(sg, MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 2025|      0|              for (auto& j : gen) {
  ------------------
  |  Branch (2025:28): [True: 0, False: 0]
  ------------------
 2026|      0|                result2.push_back(MSEP_REC);
  ------------------
  |  |  118|      0|#define MSEP_REC '\n'
  ------------------
 2027|      0|                result2.append(result);
 2028|      0|                if (i.find(MORPH_SURF_PFX) != std::string::npos) {
  ------------------
  |  |  108|      0|#define MORPH_SURF_PFX "sp:"
  ------------------
  |  Branch (2028:21): [True: 0, False: 0]
  ------------------
 2029|      0|                  std::string field;
 2030|      0|                  copy_field(field, i, MORPH_SURF_PFX);
  ------------------
  |  |  108|      0|#define MORPH_SURF_PFX "sp:"
  ------------------
 2031|      0|                  result2.append(field);
 2032|      0|                }
 2033|      0|                result2.append(j);
 2034|      0|              }
 2035|      0|            }
 2036|   204k|            rv = rv->next_homonym;
 2037|   204k|          }
 2038|   171k|        }
 2039|   171k|      }
 2040|   171k|    }
 2041|       |
 2042|   171k|    if (!result2.empty() || !strstr(pattern, MORPH_DERI_SFX))
  ------------------
  |  |  105|   171k|#define MORPH_DERI_SFX "ds:"
  ------------------
  |  Branch (2042:9): [True: 0, False: 171k]
  |  Branch (2042:29): [True: 139k, False: 31.8k]
  ------------------
 2043|   139k|      break;
 2044|       |
 2045|  31.8k|    newpattern.assign(pattern);
 2046|  31.8k|    mystrrep(newpattern, MORPH_DERI_SFX, MORPH_TERM_SFX);
  ------------------
  |  |  105|  31.8k|#define MORPH_DERI_SFX "ds:"
  ------------------
                  mystrrep(newpattern, MORPH_DERI_SFX, MORPH_TERM_SFX);
  ------------------
  |  |  107|  31.8k|#define MORPH_TERM_SFX "ts:"
  ------------------
 2047|  31.8k|    pattern = newpattern.c_str();
 2048|  31.8k|  }
 2049|   139k|  return result2;
 2050|   139k|}
_ZN10SuggestMgr5ngramEiRKNSt3__16vectorI6w_charNS0_9allocatorIS2_EEEES7_i:
 2056|  1.03M|                      int opt) {
 2057|       |  // the score arithmetic is signed; a word here is the input or a dictionary word, at most
 2058|       |  // 65535 bytes (the limit of hentry::blen)
 2059|  1.03M|  int nscore = 0, ns, l1 = static_cast<int>(su1.size()), l2 = static_cast<int>(su2.size());
 2060|       |
 2061|  1.03M|  if (l2 == 0)
  ------------------
  |  Branch (2061:7): [True: 7.97k, False: 1.02M]
  ------------------
 2062|  7.97k|    return 0;
 2063|  2.11M|  for (int j = 1; j <= n; j++) {
  ------------------
  |  Branch (2063:19): [True: 1.90M, False: 206k]
  ------------------
 2064|  1.90M|    ns = 0;
 2065|  8.67M|    for (int i = 0; i <= (l1 - j); i++) {
  ------------------
  |  Branch (2065:21): [True: 6.76M, False: 1.90M]
  ------------------
 2066|  6.76M|      int k = 0;
 2067|  25.2M|      for (int l = 0; l <= (l2 - j); l++) {
  ------------------
  |  Branch (2067:23): [True: 22.0M, False: 3.11M]
  ------------------
 2068|  30.3M|        for (k = 0; k < j; k++) {
  ------------------
  |  Branch (2068:21): [True: 26.7M, False: 3.65M]
  ------------------
 2069|  26.7M|          if (su1[i + k] != su2[l + k])
  ------------------
  |  Branch (2069:15): [True: 18.4M, False: 8.28M]
  ------------------
 2070|  18.4M|            break;
 2071|  26.7M|        }
 2072|  22.0M|        if (k == j) {
  ------------------
  |  Branch (2072:13): [True: 3.65M, False: 18.4M]
  ------------------
 2073|  3.65M|          ns++;
 2074|  3.65M|          break;
 2075|  3.65M|        }
 2076|  22.0M|      }
 2077|  6.76M|      if (k != j && opt & NGRAM_WEIGHTED) {
  ------------------
  |  |   84|  3.11M|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
  |  Branch (2077:11): [True: 3.11M, False: 3.65M]
  |  Branch (2077:21): [True: 197k, False: 2.91M]
  ------------------
 2078|   197k|        ns--;
 2079|   197k|        if (i == 0 || i == l1 - j)
  ------------------
  |  Branch (2079:13): [True: 45.2k, False: 152k]
  |  Branch (2079:23): [True: 62.2k, False: 90.4k]
  ------------------
 2080|   107k|          ns--;  // side weight
 2081|   197k|      }
 2082|  6.76M|    }
 2083|  1.90M|    nscore = nscore + ns;
 2084|  1.90M|    if (ns < 2 && !(opt & NGRAM_WEIGHTED))
  ------------------
  |  |   84|   934k|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
  |  Branch (2084:9): [True: 934k, False: 969k]
  |  Branch (2084:19): [True: 822k, False: 111k]
  ------------------
 2085|   822k|      break;
 2086|  1.90M|  }
 2087|       |
 2088|  1.02M|  ns = 0;
 2089|  1.02M|  if (opt & NGRAM_LONGER_WORSE)
  ------------------
  |  |   81|  1.02M|#define NGRAM_LONGER_WORSE (1 << 0)
  ------------------
  |  Branch (2089:7): [True: 396k, False: 632k]
  ------------------
 2090|   396k|    ns = (l2 - l1) - 2;
 2091|  1.02M|  if (opt & NGRAM_ANY_MISMATCH)
  ------------------
  |  |   82|  1.02M|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
  |  Branch (2091:7): [True: 632k, False: 396k]
  ------------------
 2092|   632k|    ns = abs(l2 - l1) - 2;
 2093|  1.02M|  ns = (nscore - ((ns > 0) ? ns : 0));
  ------------------
  |  Branch (2093:19): [True: 149k, False: 880k]
  ------------------
 2094|  1.02M|  return ns;
 2095|  1.03M|}
_ZN10SuggestMgr5ngramEiRKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_i:
 2101|   901k|                      int opt) {
 2102|       |  // the score arithmetic is signed; a word here is the input or a dictionary word, at most
 2103|       |  // 65535 bytes (the limit of hentry::blen)
 2104|   901k|  int nscore = 0, ns, l1, l2 = static_cast<int>(s2.size());
 2105|       |
 2106|   901k|  if (l2 == 0)
  ------------------
  |  Branch (2106:7): [True: 12.2k, False: 889k]
  ------------------
 2107|  12.2k|    return 0;
 2108|   889k|  l1 = static_cast<int>(s1.size());
 2109|  1.71M|  for (int j = 1; j <= n; j++) {
  ------------------
  |  Branch (2109:19): [True: 1.56M, False: 150k]
  ------------------
 2110|  1.56M|    ns = 0;
 2111|  13.3M|    for (int i = 0; i <= (l1 - j); i++) {
  ------------------
  |  Branch (2111:21): [True: 11.7M, False: 1.56M]
  ------------------
 2112|       |      //s2 is haystack, s1[i..i+j) is needle
 2113|  11.7M|      if (s2.find(s1.c_str()+i, 0, j) != std::string::npos) {
  ------------------
  |  Branch (2113:11): [True: 4.61M, False: 7.17M]
  ------------------
 2114|  4.61M|        ns++;
 2115|  7.17M|      } else if (opt & NGRAM_WEIGHTED) {
  ------------------
  |  |   84|  7.17M|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
  |  Branch (2115:18): [True: 442k, False: 6.73M]
  ------------------
 2116|   442k|        ns--;
 2117|   442k|        if (i == 0 || i == l1 - j)
  ------------------
  |  Branch (2117:13): [True: 40.7k, False: 402k]
  |  Branch (2117:23): [True: 111k, False: 290k]
  ------------------
 2118|   152k|          ns--;  // side weight
 2119|   442k|      }
 2120|  11.7M|    }
 2121|  1.56M|    nscore = nscore + ns;
 2122|  1.56M|    if (ns < 2 && !(opt & NGRAM_WEIGHTED))
  ------------------
  |  |   84|   876k|#define NGRAM_WEIGHTED (1 << 3)
  ------------------
  |  Branch (2122:9): [True: 876k, False: 686k]
  |  Branch (2122:19): [True: 738k, False: 137k]
  ------------------
 2123|   738k|      break;
 2124|  1.56M|  }
 2125|       |
 2126|   889k|  ns = 0;
 2127|   889k|  if (opt & NGRAM_LONGER_WORSE)
  ------------------
  |  |   81|   889k|#define NGRAM_LONGER_WORSE (1 << 0)
  ------------------
  |  Branch (2127:7): [True: 330k, False: 558k]
  ------------------
 2128|   330k|    ns = (l2 - l1) - 2;
 2129|   889k|  if (opt & NGRAM_ANY_MISMATCH)
  ------------------
  |  |   82|   889k|#define NGRAM_ANY_MISMATCH (1 << 1)
  ------------------
  |  Branch (2129:7): [True: 558k, False: 330k]
  ------------------
 2130|   558k|    ns = abs(l2 - l1) - 2;
 2131|   889k|  ns = (nscore - ((ns > 0) ? ns : 0));
  ------------------
  |  Branch (2131:19): [True: 194k, False: 695k]
  ------------------
 2132|   889k|  return ns;
 2133|   901k|}
_ZN10SuggestMgr19leftcommonsubstringERKNSt3__16vectorI6w_charNS0_9allocatorIS2_EEEES7_:
 2138|   839k|    const std::vector<w_char>& su2) {
 2139|       |  // a word here is the input or a dictionary word, at most 65535 bytes (the limit of
 2140|       |  // hentry::blen)
 2141|   839k|  int l1 = static_cast<int>(su1.size()), l2 = static_cast<int>(su2.size());
 2142|       |  // decapitalize dictionary word
 2143|   839k|  if (complexprefixes) {
  ------------------
  |  Branch (2143:7): [True: 0, False: 839k]
  ------------------
 2144|      0|    if (l1 && l2 && su1[l1 - 1] == su2[l2 - 1])
  ------------------
  |  Branch (2144:9): [True: 0, False: 0]
  |  Branch (2144:15): [True: 0, False: 0]
  |  Branch (2144:21): [True: 0, False: 0]
  ------------------
 2145|      0|      return 1;
 2146|   839k|  } else {
 2147|   839k|    unsigned short idx = su2.empty() ? 0 : (unsigned short)(su2[0]),
  ------------------
  |  Branch (2147:26): [True: 0, False: 839k]
  ------------------
 2148|   839k|                   otheridx = su1.empty() ? 0 : (unsigned short)(su1[0]);
  ------------------
  |  Branch (2148:31): [True: 26.9k, False: 812k]
  ------------------
 2149|   839k|    if (otheridx != idx && (otheridx != unicodetolower(idx, langnum)))
  ------------------
  |  Branch (2149:9): [True: 768k, False: 71.3k]
  |  Branch (2149:28): [True: 485k, False: 282k]
  ------------------
 2150|   485k|      return 0;
 2151|   353k|    int i;
 2152|   873k|    for (i = 1; (i < l1) && (i < l2) && (su1[i] == su2[i]);
  ------------------
  |  Branch (2152:17): [True: 742k, False: 130k]
  |  Branch (2152:29): [True: 713k, False: 28.9k]
  |  Branch (2152:41): [True: 519k, False: 193k]
  ------------------
 2153|   519k|         i++)
 2154|   519k|      ;
 2155|   353k|    return i;
 2156|   839k|  }
 2157|      0|  return 0;
 2158|   839k|}
_ZN10SuggestMgr19leftcommonsubstringEPKcS1_:
 2163|   709k|    const char* s2) {
 2164|   709k|  if (complexprefixes) {
  ------------------
  |  Branch (2164:7): [True: 56.9k, False: 652k]
  ------------------
 2165|       |    // a word here is the input or a dictionary word, at most 65535 bytes (the limit of
 2166|       |    // hentry::blen)
 2167|  56.9k|    int l1 = static_cast<int>(strlen(s1)), l2 = static_cast<int>(strlen(s2));
 2168|  56.9k|    if (l1 && l1 <= l2 && s1[l1 - 1] == s2[l2 - 1])
  ------------------
  |  Branch (2168:9): [True: 55.2k, False: 1.78k]
  |  Branch (2168:15): [True: 24.0k, False: 31.2k]
  |  Branch (2168:27): [True: 1.78k, False: 22.2k]
  ------------------
 2169|  1.78k|      return 1;
 2170|   652k|  } else if (csconv) {
  ------------------
  |  Branch (2170:14): [True: 652k, False: 0]
  ------------------
 2171|   652k|    const char* olds = s1;
 2172|       |    // decapitalise dictionary word
 2173|   652k|    if ((*s1 != *s2) && (((unsigned char)*s1) != csconv[((unsigned char)*s2)].clower))
  ------------------
  |  Branch (2173:9): [True: 597k, False: 55.5k]
  |  Branch (2173:25): [True: 443k, False: 153k]
  ------------------
 2174|   443k|      return 0;
 2175|   209k|    if (*s1 == '\0')
  ------------------
  |  Branch (2175:9): [True: 4, False: 209k]
  ------------------
 2176|      4|      return 0;
 2177|   482k|    do {
 2178|   482k|      s1++;
 2179|   482k|      s2++;
 2180|   482k|    } while ((*s1 == *s2) && (*s1 != '\0'));
  ------------------
  |  Branch (2180:14): [True: 273k, False: 208k]
  |  Branch (2180:30): [True: 273k, False: 385]
  ------------------
 2181|   209k|    return (int)(s1 - olds);
 2182|   209k|  }
 2183|  55.2k|  return 0;
 2184|   709k|}
_ZN10SuggestMgr24commoncharacterpositionsEPKcS1_Pi:
 2188|   123k|                                         int* is_swap) {
 2189|   123k|  int num = 0, diff = 0, diffpos[2];
 2190|   123k|  *is_swap = 0;
 2191|   123k|  if (utf8) {
  ------------------
  |  Branch (2191:7): [True: 69.1k, False: 54.1k]
  ------------------
 2192|  69.1k|    std::vector<w_char> su1;
 2193|  69.1k|    std::vector<w_char> su2;
 2194|  69.1k|    int l1 = u8_u16(su1, s1), l2 = u8_u16(su2, s2);
 2195|       |
 2196|  69.1k|    if (l1 <= 0 || l2 <= 0)
  ------------------
  |  Branch (2196:9): [True: 5.28k, False: 63.8k]
  |  Branch (2196:20): [True: 0, False: 63.8k]
  ------------------
 2197|  5.28k|      return 0;
 2198|       |
 2199|       |    // decapitalize dictionary word
 2200|  63.8k|    if (complexprefixes) {
  ------------------
  |  Branch (2200:9): [True: 0, False: 63.8k]
  ------------------
 2201|      0|      su2[l2 - 1] = lower_utf(su2[l2 - 1], langnum);
 2202|  63.8k|    } else {
 2203|  63.8k|      su2[0] = lower_utf(su2[0], langnum);
 2204|  63.8k|    }
 2205|   289k|    for (int i = 0; (i < l1) && (i < l2); i++) {
  ------------------
  |  Branch (2205:21): [True: 242k, False: 46.3k]
  |  Branch (2205:33): [True: 225k, False: 17.5k]
  ------------------
 2206|   225k|      if (su1[i] == su2[i]) {
  ------------------
  |  Branch (2206:11): [True: 165k, False: 59.5k]
  ------------------
 2207|   165k|        num++;
 2208|   165k|      } else {
 2209|  59.5k|        if (diff < 2)
  ------------------
  |  Branch (2209:13): [True: 46.9k, False: 12.5k]
  ------------------
 2210|  46.9k|          diffpos[diff] = i;
 2211|  59.5k|        diff++;
 2212|  59.5k|      }
 2213|   225k|    }
 2214|  63.8k|    if ((diff == 2) && (l1 == l2) &&
  ------------------
  |  Branch (2214:9): [True: 7.30k, False: 56.5k]
  |  Branch (2214:24): [True: 737, False: 6.56k]
  ------------------
 2215|    737|        (su1[diffpos[0]] == su2[diffpos[1]]) &&
  ------------------
  |  Branch (2215:9): [True: 166, False: 571]
  ------------------
 2216|    166|        (su1[diffpos[1]] == su2[diffpos[0]]))
  ------------------
  |  Branch (2216:9): [True: 62, False: 104]
  ------------------
 2217|     62|      *is_swap = 1;
 2218|  63.8k|  } else {
 2219|  54.1k|    if (!*s1 || !*s2)
  ------------------
  |  Branch (2219:9): [True: 5.50k, False: 48.6k]
  |  Branch (2219:17): [True: 0, False: 48.6k]
  ------------------
 2220|  5.50k|      return 0;
 2221|       |
 2222|  48.6k|    size_t i;
 2223|  48.6k|    std::string t(s2);
 2224|       |    // decapitalize dictionary word
 2225|  48.6k|    if (complexprefixes) {
  ------------------
  |  Branch (2225:9): [True: 3.25k, False: 45.3k]
  ------------------
 2226|  3.25k|      size_t l2 = t.size();
 2227|  3.25k|      t[l2 - 1] = csconv[(unsigned char)t[l2 - 1]].clower;
 2228|  45.3k|    } else {
 2229|  45.3k|      mkallsmall(t, csconv);
 2230|  45.3k|    }
 2231|   335k|    for (i = 0; i < t.size() && (*(s1 + i) != 0); ++i) {
  ------------------
  |  Branch (2231:17): [True: 304k, False: 31.2k]
  |  Branch (2231:33): [True: 287k, False: 17.3k]
  ------------------
 2232|   287k|      if (*(s1 + i) == t[i]) {
  ------------------
  |  Branch (2232:11): [True: 139k, False: 147k]
  ------------------
 2233|   139k|        num++;
 2234|   147k|      } else {
 2235|       |        // i is below the length of the input word, which is shorter than MAXWORDLEN
 2236|   147k|        if (diff < 2)
  ------------------
  |  Branch (2236:13): [True: 69.7k, False: 77.6k]
  ------------------
 2237|  69.7k|          diffpos[diff] = static_cast<int>(i);
 2238|   147k|        diff++;
 2239|   147k|      }
 2240|   287k|    }
 2241|  48.6k|    if ((diff == 2) && (*(s1 + i) == 0) && i == t.size() &&
  ------------------
  |  Branch (2241:9): [True: 10.9k, False: 37.6k]
  |  Branch (2241:24): [True: 7.11k, False: 3.83k]
  |  Branch (2241:44): [True: 2.25k, False: 4.85k]
  ------------------
 2242|  2.25k|        (*(s1 + diffpos[0]) == t[diffpos[1]]) &&
  ------------------
  |  Branch (2242:9): [True: 276, False: 1.98k]
  ------------------
 2243|    276|        (*(s1 + diffpos[1]) == t[diffpos[0]]))
  ------------------
  |  Branch (2243:9): [True: 87, False: 189]
  ------------------
 2244|     87|      *is_swap = 1;
 2245|  48.6k|  }
 2246|   112k|  return num;
 2247|   123k|}
_ZN10SuggestMgr10bubblesortEPPcS1_Pii:
 2259|   100k|void SuggestMgr::bubblesort(char** rword, char** rword2, int* rsc, int n) {
 2260|   100k|  int m = 1;
 2261|  19.5M|  while (m < n) {
  ------------------
  |  Branch (2261:10): [True: 19.4M, False: 100k]
  ------------------
 2262|  19.4M|    int j = m;
 2263|  50.5M|    while (j > 0) {
  ------------------
  |  Branch (2263:12): [True: 50.4M, False: 26.4k]
  ------------------
 2264|  50.4M|      if (rsc[j - 1] < rsc[j]) {
  ------------------
  |  Branch (2264:11): [True: 31.0M, False: 19.4M]
  ------------------
 2265|  31.0M|        int sctmp = rsc[j - 1];
 2266|  31.0M|        char* wdtmp = rword[j - 1];
 2267|  31.0M|        rsc[j - 1] = rsc[j];
 2268|  31.0M|        rword[j - 1] = rword[j];
 2269|  31.0M|        rsc[j] = sctmp;
 2270|  31.0M|        rword[j] = wdtmp;
 2271|  31.0M|        if (rword2) {
  ------------------
  |  Branch (2271:13): [True: 30.4M, False: 564k]
  ------------------
 2272|  30.4M|          wdtmp = rword2[j - 1];
 2273|  30.4M|          rword2[j - 1] = rword2[j];
 2274|  30.4M|          rword2[j] = wdtmp;
 2275|  30.4M|        }
 2276|  31.0M|        j--;
 2277|  31.0M|      } else
 2278|  19.4M|        break;
 2279|  50.4M|    }
 2280|  19.4M|    m++;
 2281|  19.4M|  }
 2282|   100k|}
_ZN10SuggestMgr3lcsEPKcS1_PiS2_:
 2288|   132k|                      int* l2) {
 2289|   132k|  int n, m, i, j;
 2290|   132k|  std::vector<w_char> su;
 2291|   132k|  std::vector<w_char> su2;
 2292|   132k|  if (utf8) {
  ------------------
  |  Branch (2292:7): [True: 71.1k, False: 61.5k]
  ------------------
 2293|  71.1k|    m = u8_u16(su, s);
 2294|  71.1k|    n = u8_u16(su2, s2);
 2295|  71.1k|  } else {
 2296|       |    // s is the input word, shorter than MAXWORDLEN, and s2 a guess built from a dictionary
 2297|       |    // word of at most 65535 bytes (the limit of hentry::blen)
 2298|  61.5k|    m = static_cast<int>(strlen(s));
 2299|  61.5k|    n = static_cast<int>(strlen(s2));
 2300|  61.5k|  }
 2301|   132k|  if (m <= 0 || n <= 0) {
  ------------------
  |  Branch (2301:7): [True: 10.9k, False: 121k]
  |  Branch (2301:17): [True: 0, False: 121k]
  ------------------
 2302|  10.9k|    *l1 = 0;
 2303|  10.9k|    *l2 = 0;
 2304|  10.9k|    return nullptr;
 2305|  10.9k|  }
 2306|   121k|  char* c = new char[(m + 1) * (n + 1)]();
 2307|   121k|  char* b = new char[(m + 1) * (n + 1)]();
 2308|   776k|  for (i = 1; i <= m; i++) {
  ------------------
  |  Branch (2308:15): [True: 655k, False: 121k]
  ------------------
 2309|  6.83M|    for (j = 1; j <= n; j++) {
  ------------------
  |  Branch (2309:17): [True: 6.18M, False: 655k]
  ------------------
 2310|  6.18M|      if (((utf8) && (su[i - 1] == su2[j - 1])) ||
  ------------------
  |  Branch (2310:12): [True: 1.18M, False: 4.99M]
  |  Branch (2310:22): [True: 256k, False: 927k]
  ------------------
 2311|  5.92M|          ((!utf8) && (s[i - 1] == s2[j - 1]))) {
  ------------------
  |  Branch (2311:12): [True: 4.99M, False: 927k]
  |  Branch (2311:23): [True: 1.05M, False: 3.94M]
  ------------------
 2312|  1.30M|        c[i * (n + 1) + j] = c[(i - 1) * (n + 1) + j - 1] + 1;
 2313|  1.30M|        b[i * (n + 1) + j] = LCS_UPLEFT;
 2314|  4.87M|      } else if (c[(i - 1) * (n + 1) + j] >= c[i * (n + 1) + j - 1]) {
  ------------------
  |  Branch (2314:18): [True: 3.37M, False: 1.49M]
  ------------------
 2315|  3.37M|        c[i * (n + 1) + j] = c[(i - 1) * (n + 1) + j];
 2316|  3.37M|        b[i * (n + 1) + j] = LCS_UP;
 2317|  3.37M|      } else {
 2318|  1.49M|        c[i * (n + 1) + j] = c[i * (n + 1) + j - 1];
 2319|  1.49M|        b[i * (n + 1) + j] = LCS_LEFT;
 2320|  1.49M|      }
 2321|  6.18M|    }
 2322|   655k|  }
 2323|   121k|  delete[] c;
 2324|   121k|  *l1 = m;
 2325|   121k|  *l2 = n;
 2326|   121k|  return b;
 2327|   132k|}
_ZN10SuggestMgr6lcslenEPKcS1_:
 2329|   132k|int SuggestMgr::lcslen(const char* s, const char* s2) {
 2330|   132k|  int m, n, len = 0;
 2331|   132k|  char* result = lcs(s, s2, &m, &n);
 2332|   132k|  if (!result)
  ------------------
  |  Branch (2332:7): [True: 10.9k, False: 121k]
  ------------------
 2333|  10.9k|    return 0;
 2334|   121k|  int i = m, j = n;
 2335|   953k|  while ((i != 0) && (j != 0)) {
  ------------------
  |  Branch (2335:10): [True: 845k, False: 107k]
  |  Branch (2335:22): [True: 831k, False: 14.2k]
  ------------------
 2336|   831k|    if (result[i * (n + 1) + j] == LCS_UPLEFT) {
  ------------------
  |  Branch (2336:9): [True: 411k, False: 419k]
  ------------------
 2337|   411k|      len++;
 2338|   411k|      i--;
 2339|   411k|      j--;
 2340|   419k|    } else if (result[i * (n + 1) + j] == LCS_UP) {
  ------------------
  |  Branch (2340:16): [True: 215k, False: 204k]
  ------------------
 2341|   215k|      i--;
 2342|   215k|    } else
 2343|   204k|      j--;
 2344|   831k|  }
 2345|   121k|  delete[] result;
 2346|   121k|  return len;
 2347|   132k|}
_ZN10SuggestMgr6lcslenERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_:
 2349|  6.83k|int SuggestMgr::lcslen(const std::string& s, const std::string& s2) {
 2350|  6.83k|  return lcslen(s.c_str(), s2.c_str());
 2351|  6.83k|}
suggestmgr.cxx:_ZN12_GLOBAL__N_115ngsuggest_guardC2EbPK7cs_infoPiPS3_:
 1165|  62.5k|      : m_nonbmp(nonbmp)
 1166|  62.5k|      , m_origconv(origconv)
 1167|  62.5k|      , m_utf8(utf8)
 1168|  62.5k|      , m_csconv(csconv)
 1169|  62.5k|    {
 1170|  62.5k|    }
suggestmgr.cxx:_ZN12_GLOBAL__N_115ngsuggest_guardD2Ev:
 1173|  62.5k|    {
 1174|  62.5k|      if (m_nonbmp) {
  ------------------
  |  Branch (1174:11): [True: 1.83k, False: 60.6k]
  ------------------
 1175|  1.83k|        *m_csconv = m_origconv;
 1176|  1.83k|        *m_utf8 = 1;
 1177|  1.83k|      }
 1178|  62.5k|    }
suggestmgr.cxx:_ZL12get_sfxcountPKc:
 1903|   817k|static int get_sfxcount(const char* morph) {
 1904|   817k|  if (!morph || !*morph)
  ------------------
  |  Branch (1904:7): [True: 408k, False: 408k]
  |  Branch (1904:17): [True: 0, False: 408k]
  ------------------
 1905|   408k|    return 0;
 1906|   408k|  int n = 0;
 1907|   408k|  const char* old = morph;
 1908|   408k|  morph = strstr(morph, MORPH_DERI_SFX);
  ------------------
  |  |  105|   408k|#define MORPH_DERI_SFX "ds:"
  ------------------
 1909|   408k|  if (!morph)
  ------------------
  |  Branch (1909:7): [True: 347k, False: 61.0k]
  ------------------
 1910|   347k|    morph = strstr(old, MORPH_INFL_SFX);
  ------------------
  |  |  106|   347k|#define MORPH_INFL_SFX "is:"
  ------------------
 1911|   408k|  if (!morph)
  ------------------
  |  Branch (1911:7): [True: 347k, False: 61.2k]
  ------------------
 1912|   347k|    morph = strstr(old, MORPH_TERM_SFX);
  ------------------
  |  |  107|   347k|#define MORPH_TERM_SFX "ts:"
  ------------------
 1913|   582k|  while (morph) {
  ------------------
  |  Branch (1913:10): [True: 173k, False: 408k]
  ------------------
 1914|   173k|    n++;
 1915|   173k|    old = morph;
 1916|   173k|    morph = strstr(morph + 1, MORPH_DERI_SFX);
  ------------------
  |  |  105|   173k|#define MORPH_DERI_SFX "ds:"
  ------------------
 1917|   173k|    if (!morph)
  ------------------
  |  Branch (1917:9): [True: 147k, False: 25.7k]
  ------------------
 1918|   147k|      morph = strstr(old + 1, MORPH_INFL_SFX);
  ------------------
  |  |  106|   147k|#define MORPH_INFL_SFX "is:"
  ------------------
 1919|   173k|    if (!morph)
  ------------------
  |  Branch (1919:9): [True: 147k, False: 25.7k]
  ------------------
 1920|   147k|      morph = strstr(old + 1, MORPH_TERM_SFX);
  ------------------
  |  |  107|   147k|#define MORPH_TERM_SFX "ts:"
  ------------------
 1921|   173k|  }
 1922|   408k|  return n;
 1923|   817k|}

_ZNK6w_charcvtEv:
   57|   316M|  {
   58|   316M|#if defined(_WIN32) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__))  || defined(__LITTLE_ENDIAN__)
   59|       |    //use little-endian optimized version
   60|       |#if (__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) && defined __cpp_lib_bit_cast && __cpp_lib_bit_cast >= 201806L
   61|       |    return std::bit_cast<unsigned short>(*this);
   62|       |#else
   63|   316M|    unsigned short u;
   64|   316M|    memcpy(&u, this, sizeof(unsigned short));
   65|   316M|    return u;
   66|   316M|#endif
   67|       |
   68|       |#else
   69|       |    return ((unsigned short)h << 8) | (unsigned short)l;
   70|       |#endif
   71|   316M|  }
_Zlt6w_charS_:
   73|  33.5M|  friend bool operator<(const w_char a, const w_char b) {
   74|  33.5M|    return (unsigned short)a < (unsigned short)b;
   75|  33.5M|  }
_Zeq6w_charS_:
   77|  98.3M|  friend bool operator==(const w_char a, const w_char b) {
   78|  98.3M|    return (unsigned short)a == (unsigned short)b;
   79|  98.3M|  }
_Zne6w_charS_:
   81|  94.3M|  friend bool operator!=(const w_char a, const w_char b) {
   82|  94.3M|    return !(a == b);
   83|  94.3M|  }

_Z8endswithRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEES7_:
   40|    200|{
   41|    200|    return str.size() >= suffix.size() &&
  ------------------
  |  Branch (41:12): [True: 192, False: 8]
  ------------------
   42|    192|           str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
  ------------------
  |  Branch (42:12): [True: 38, False: 154]
  ------------------
   43|    200|}
LLVMFuzzerInitialize:
   46|      2|{
   47|      2|    char* exe_path = (*argv)[0];
   48|       |    // dirname() can modify its argument.
   49|      2|    char* exe_path_copy = strdup(exe_path);
   50|      2|    char* dir = dirname(exe_path_copy);
   51|      2|    DIR* d = opendir(dir);
   52|      2|    struct dirent *direntry;
   53|      2|    std::vector<std::string> affs;
   54|    202|    while ((direntry = readdir(d)) != NULL)
  ------------------
  |  Branch (54:12): [True: 200, False: 2]
  ------------------
   55|    200|    {
   56|    200|        std::string entry(direntry->d_name);
   57|    200|        if (endswith(entry, ".aff"))
  ------------------
  |  Branch (57:13): [True: 38, False: 162]
  ------------------
   58|     38|            affs.push_back(std::move(entry));
   59|    200|    }
   60|      2|    closedir(d);
   61|      2|    free(exe_path_copy);
   62|       |
   63|       |    // sort so dict iteration order is reproducible across runs regardless of
   64|       |    // readdir ordering; a failing input then reproduces against the same dict
   65|      2|    std::sort(affs.begin(), affs.end());
   66|      2|    for (const auto& entry : affs)
  ------------------
  |  Branch (66:28): [True: 38, False: 2]
  ------------------
   67|     38|    {
   68|     38|        std::string dic = entry.substr(0, entry.size() - 4) + ".dic";
   69|     38|        dictionaries.emplace_back(new Hunspell(entry.c_str(), dic.c_str()));
   70|     38|    }
   71|       |
   72|      2|    return 0;
   73|      2|}
LLVMFuzzerTestOneInput:
   76|  3.47k|{
   77|  3.47k|    std::string word(data, size);
   78|  3.47k|    for (auto& dict : dictionaries)
  ------------------
  |  Branch (78:21): [True: 65.9k, False: 3.47k]
  ------------------
   79|  65.9k|    {
   80|  65.9k|        if (!dict->spell(word))
  ------------------
  |  Branch (80:13): [True: 65.3k, False: 586]
  ------------------
   81|  65.3k|            dict->suggest(word);
   82|  65.9k|    }
   83|  3.47k|    return 0;
   84|  3.47k|}

