Bug 1788655 - Update Hunspell to 1.7.1. r=masayuki

Differential Revision: https://phabricator.services.mozilla.com/D156177
This commit is contained in:
Ryan VanderMeulen 2022-09-01 23:48:12 +00:00
parent 6f6c74f081
commit 27774619e2
26 changed files with 748 additions and 441 deletions

View file

@ -1,138 +1,3 @@
# HG changeset patch
# User Kris Maglione <maglione.k@gmail.com>
# Date 1524774544 25200
# Thu Apr 26 13:29:04 2018 -0700
# Node ID 3dd497b3e3f15b06e3e786d00addcd5ef85b97cb
# Parent 2f1e8f0e6b5316f9119a7111100af50c4b7025af
Bug 1410214: Part 2 - Add a stub Hunspell FileMgr that allows it to read URLs. r=masayuki
This will allow us to store dictionaries in packed extension XPIs and/or
omni.ja, which should give us a significant startup performance win.
MozReview-Commit-ID: K7fzJJAywjC
diff --git a/extensions/spellcheck/hunspell/src/filemgr.cxx b/extensions/spellcheck/hunspell/src/filemgr.cxx
deleted file mode 100644
--- a/extensions/spellcheck/hunspell/src/filemgr.cxx
+++ /dev/null
@@ -1,117 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * Copyright (C) 2002-2017 Németh László
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * Hunspell is based on MySpell which is Copyright (C) 2002 Kevin Hendricks.
- *
- * Contributor(s): David Einstein, Davide Prina, Giuseppe Modugno,
- * Gianluca Turconi, Simon Brouwer, Noll János, Bíró Árpád,
- * Goldman Eleonóra, Sarlós Tamás, Bencsáth Boldizsár, Halácsy Péter,
- * Dvornik László, Gefferth András, Nagy Viktor, Varga Dániel, Chris Halls,
- * Rene Engelhard, Bram Moolenaar, Dafydd Jones, Harri Pitkänen
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-/*
- * Copyright 2002 Kevin B. Hendricks, Stratford, Ontario, Canada
- * And Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. All modifications to the source code must be clearly marked as
- * such. Binary redistributions based on modified source code
- * must be clearly marked as modified versions in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY KEVIN B. HENDRICKS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * KEVIN B. HENDRICKS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "filemgr.hxx"
-#include "csutil.hxx"
-
-int FileMgr::fail(const char* err, const char* par) {
- fprintf(stderr, err, par);
- return -1;
-}
-
-FileMgr::FileMgr(const char* file, const char* key) : hin(NULL), linenum(0) {
- in[0] = '\0';
-
- myopen(fin, file, std::ios_base::in);
- if (!fin.is_open()) {
- // check hzipped file
- std::string st(file);
- st.append(HZIP_EXTENSION);
- hin = new Hunzip(st.c_str(), key);
- }
- if (!fin.is_open() && !hin->is_open())
- fail(MSG_OPEN, file);
-}
-
-FileMgr::~FileMgr() {
- delete hin;
-}
-
-bool FileMgr::getline(std::string& dest) {
- bool ret = false;
- ++linenum;
- if (fin.is_open()) {
- ret = static_cast<bool>(std::getline(fin, dest));
- } else if (hin->is_open()) {
- ret = hin->getline(dest);
- }
- if (!ret) {
- --linenum;
- }
- return ret;
-}
-
-int FileMgr::getlinenum() {
- return linenum;
-}
diff --git a/extensions/spellcheck/hunspell/src/filemgr.hxx b/extensions/spellcheck/hunspell/src/filemgr.hxx
--- a/extensions/spellcheck/hunspell/src/filemgr.hxx
+++ b/extensions/spellcheck/hunspell/src/filemgr.hxx

View file

@ -0,0 +1,190 @@
diff --git a/extensions/spellcheck/hunspell/src/csutil.cxx b/extensions/spellcheck/hunspell/src/csutil.cxx
--- a/extensions/spellcheck/hunspell/src/csutil.cxx
+++ b/extensions/spellcheck/hunspell/src/csutil.cxx
@@ -90,21 +90,17 @@
#else
#ifndef MOZILLA_CLIENT
#include "utf_info.hxx"
#define UTF_LST_LEN (sizeof(utf_lst) / (sizeof(unicode_info)))
#endif
#endif
#ifdef MOZILLA_CLIENT
-#include "nsCOMPtr.h"
-#include "nsUnicharUtils.h"
-#include "mozilla/Encoding.h"
-
-using namespace mozilla;
+#include "mozHunspellRLBoxGlue.h"
#endif
struct unicode_info2 {
char cletter;
unsigned short cupper;
unsigned short clower;
};
@@ -2277,101 +2273,18 @@ struct cs_info* get_current_cs(const std
"error: unknown encoding %s: using %s as fallback\n", es.c_str(),
encds[0].enc_name);
ccs = encds[0].cs_table;
}
return ccs;
}
#else
-// XXX This function was rewritten for mozilla. Instead of storing the
-// conversion tables static in this file, create them when needed
-// with help the mozilla backend.
struct cs_info* get_current_cs(const std::string& es) {
- struct cs_info* ccs = new cs_info[256];
- // Initialze the array with dummy data so that we wouldn't need
- // to return null in case of failures.
- for (int i = 0; i <= 0xff; ++i) {
- ccs[i].ccase = false;
- ccs[i].clower = i;
- ccs[i].cupper = i;
- }
-
- auto encoding = Encoding::ForLabelNoReplacement(es);
- if (!encoding) {
- return ccs;
- }
- auto encoder = encoding->NewEncoder();
- auto decoder = encoding->NewDecoderWithoutBOMHandling();
-
- for (unsigned int i = 0; i <= 0xff; ++i) {
- bool success = false;
- // We want to find the upper/lowercase equivalents of each byte
- // in this 1-byte character encoding. Call our encoding/decoding
- // APIs separately for each byte since they may reject some of the
- // bytes, and we want to handle errors separately for each byte.
- uint8_t lower, upper;
- do {
- if (i == 0)
- break;
- uint8_t source = uint8_t(i);
- char16_t uni[2];
- char16_t uniCased;
- uint8_t destination[4];
- auto src1 = MakeSpan(&source, 1);
- auto dst1 = MakeSpan(uni);
- auto src2 = MakeSpan(&uniCased, 1);
- auto dst2 = MakeSpan(destination);
-
- uint32_t result;
- size_t read;
- size_t written;
- Tie(result, read, written) =
- decoder->DecodeToUTF16WithoutReplacement(src1, dst1, true);
- if (result != kInputEmpty || read != 1 || written != 1) {
- break;
- }
-
- uniCased = ToLowerCase(uni[0]);
- Tie(result, read, written) =
- encoder->EncodeFromUTF16WithoutReplacement(src2, dst2, true);
- if (result != kInputEmpty || read != 1 || written != 1) {
- break;
- }
- lower = destination[0];
-
- uniCased = ToUpperCase(uni[0]);
- Tie(result, read, written) =
- encoder->EncodeFromUTF16WithoutReplacement(src2, dst2, true);
- if (result != kInputEmpty || read != 1 || written != 1) {
- break;
- }
- upper = destination[0];
-
- success = true;
- } while (0);
-
- encoding->NewEncoderInto(*encoder);
- encoding->NewDecoderWithoutBOMHandlingInto(*decoder);
-
- if (success) {
- ccs[i].cupper = upper;
- ccs[i].clower = lower;
- } else {
- ccs[i].cupper = i;
- ccs[i].clower = i;
- }
-
- if (ccs[i].clower != (unsigned char)i)
- ccs[i].ccase = true;
- else
- ccs[i].ccase = false;
- }
-
- return ccs;
+ return moz_hunspell_GetCurrentCS(es.c_str());
}
#endif
// primitive isalpha() replacement for tokenization
std::string get_casechars(const char* enc) {
struct cs_info* csconv = get_current_cs(enc);
std::string expw;
for (int i = 0; i <= 255; ++i) {
@@ -2455,34 +2368,34 @@ unsigned short unicodetoupper(unsigned s
// There are a dotless lower case i pair of upper `I',
// and an upper I with dot pair of lower `i'.
if (c == 0x0069 && ((langnum == LANG_az) || (langnum == LANG_tr) || (langnum == LANG_crh)))
return 0x0130;
#ifdef OPENOFFICEORG
return static_cast<unsigned short>(u_toupper(c));
#else
#ifdef MOZILLA_CLIENT
- return ToUpperCase((char16_t)c);
+ return moz_hunspell_ToUpperCase((char16_t)c);
#else
return (utf_tbl) ? utf_tbl[c].cupper : c;
#endif
#endif
}
unsigned short unicodetolower(unsigned short c, int langnum) {
// In Azeri and Turkish, I and i dictinct letters:
// There are a dotless lower case i pair of upper `I',
// and an upper I with dot pair of lower `i'.
if (c == 0x0049 && ((langnum == LANG_az) || (langnum == LANG_tr) || (langnum == LANG_crh)))
return 0x0131;
#ifdef OPENOFFICEORG
return static_cast<unsigned short>(u_tolower(c));
#else
#ifdef MOZILLA_CLIENT
- return ToLowerCase((char16_t)c);
+ return moz_hunspell_ToLowerCase((char16_t)c);
#else
return (utf_tbl) ? utf_tbl[c].clower : c;
#endif
#endif
}
int unicodeisalpha(unsigned short c) {
#ifdef OPENOFFICEORG
diff --git a/extensions/spellcheck/hunspell/src/csutil.hxx b/extensions/spellcheck/hunspell/src/csutil.hxx
--- a/extensions/spellcheck/hunspell/src/csutil.hxx
+++ b/extensions/spellcheck/hunspell/src/csutil.hxx
@@ -77,20 +77,16 @@
#include <fstream>
#include <string>
#include <vector>
#include <string.h>
#include "w_char.hxx"
#include "htypes.hxx"
-#ifdef MOZILLA_CLIENT
-#include "nscore.h" // for mozalloc headers
-#endif
-
// casing
#define NOCAP 0
#define INITCAP 1
#define ALLCAP 2
#define HUHCAP 3
#define HUHINITCAP 4
// default encoding and keystring

View file

@ -1,8 +1,12 @@
diff --git a/extensions/spellcheck/hunspell/src/hashmgr.cxx b/extensions/spellcheck/hunspell/src/hashmgr.cxx
index 7e843c3e76624..5b7e847304f50 100644
--- a/extensions/spellcheck/hunspell/src/hashmgr.cxx
+++ b/extensions/spellcheck/hunspell/src/hashmgr.cxx
@@ -68,6 +68,7 @@
@@ -63,16 +63,17 @@
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
@ -10,7 +14,17 @@ index 7e843c3e76624..5b7e847304f50 100644
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -123,8 +124,8 @@ HashMgr::~HashMgr() {
#include <ctype.h>
#include <limits>
#include <sstream>
#include "hashmgr.hxx"
@@ -118,52 +119,54 @@ HashMgr::~HashMgr() {
// go through column by column of the table
for (int i = 0; i < tablesize; i++) {
struct hentry* pt = tableptr[i];
struct hentry* nt = NULL;
while (pt) {
nt = pt->next;
if (pt->astr &&
(!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen)))
@ -21,7 +35,9 @@ index 7e843c3e76624..5b7e847304f50 100644
pt = nt;
}
}
@@ -134,18 +135,18 @@ HashMgr::~HashMgr() {
free(tableptr);
}
tablesize = 0;
if (aliasf) {
for (int j = 0; j < (numaliasf); j++)
@ -45,7 +61,13 @@ index 7e843c3e76624..5b7e847304f50 100644
aliasm = NULL;
}
@@ -159,6 +160,8 @@ HashMgr::~HashMgr() {
#ifndef OPENOFFICEORG
#ifndef MOZILLA_CLIENT
if (utf8)
free_utf_tbl();
#endif
#endif
#ifdef MOZILLA_CLIENT
delete[] csconv;
#endif
@ -54,7 +76,17 @@ index 7e843c3e76624..5b7e847304f50 100644
}
// lookup a root word in the hashtable
@@ -227,7 +230,7 @@ int HashMgr::add_word(const std::string& in_word,
struct hentry* HashMgr::lookup(const char* word) const {
struct hentry* dp;
if (tableptr) {
dp = tableptr[hash(word)];
@@ -222,17 +225,17 @@ int HashMgr::add_word(const std::string&
word = word_copy;
}
bool upcasehomonym = false;
int descl = desc ? (aliasm ? sizeof(char*) : desc->size() + 1) : 0;
// variable-length hash record with word and optional fields
struct hentry* hp =
@ -63,7 +95,17 @@ index 7e843c3e76624..5b7e847304f50 100644
if (!hp) {
delete desc_copy;
delete word_copy;
@@ -371,10 +374,10 @@ int HashMgr::add_word(const std::string& in_word,
return 1;
}
char* hpw = hp->word;
strcpy(hpw, word->c_str());
@@ -366,57 +369,57 @@ int HashMgr::add_word(const std::string&
delete word_copy;
return 0;
}
while (dp->next != NULL) {
if ((!dp->next_homonym) && (strcmp(hp->word, dp->word) == 0)) {
// remove hidden onlyupcase homonym
if (!onlyupcase) {
if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) {
@ -76,7 +118,16 @@ index 7e843c3e76624..5b7e847304f50 100644
delete desc_copy;
delete word_copy;
return 0;
@@ -391,10 +394,10 @@ int HashMgr::add_word(const std::string& in_word,
} else {
dp->next_homonym = hp;
}
} else {
upcasehomonym = true;
}
}
dp = dp->next;
}
if (strcmp(hp->word, dp->word) == 0) {
// remove hidden onlyupcase homonym
if (!onlyupcase) {
if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) {
@ -89,7 +140,15 @@ index 7e843c3e76624..5b7e847304f50 100644
delete desc_copy;
delete word_copy;
return 0;
@@ -410,8 +413,8 @@ int HashMgr::add_word(const std::string& in_word,
} else {
dp->next_homonym = hp;
}
} else {
upcasehomonym = true;
}
}
if (!upcasehomonym) {
dp->next = hp;
} else {
// remove hidden onlyupcase homonym
if (hp->astr)
@ -100,7 +159,17 @@ index 7e843c3e76624..5b7e847304f50 100644
}
delete desc_copy;
@@ -435,7 +438,7 @@ int HashMgr::add_hidden_capitalized_word(const std::string& word,
delete word_copy;
return 0;
}
int HashMgr::add_hidden_capitalized_word(const std::string& word,
@@ -430,17 +433,17 @@ int HashMgr::add_hidden_capitalized_word
// add inner capitalized forms to handle the following allcap forms:
// Mixed caps: OpenOffice.org -> OPENOFFICE.ORG
// Allcaps with suffixes: CIA's -> CIA'S
if (((captype == HUHCAP) || (captype == HUHINITCAP) ||
((captype == ALLCAP) && (flagslen != 0))) &&
!((flagslen != 0) && TESTAFF(flags, forbiddenword, flagslen))) {
unsigned short* flags2 =
@ -109,7 +178,17 @@ index 7e843c3e76624..5b7e847304f50 100644
if (!flags2)
return 1;
if (flagslen)
@@ -484,13 +487,13 @@ int HashMgr::remove(const std::string& word) {
memcpy(flags2, flags, flagslen * sizeof(unsigned short));
flags2[flagslen] = ONLYUPCASEFLAG;
if (utf8) {
std::string st;
std::vector<w_char> w;
@@ -479,23 +482,23 @@ int HashMgr::get_clen_and_captype(const
}
// remove word (personal dictionary function for standalone applications)
int HashMgr::remove(const std::string& word) {
struct hentry* dp = lookup(word.c_str());
while (dp) {
if (dp->alen == 0 || !TESTAFF(dp->astr, forbiddenword, dp->alen)) {
unsigned short* flags =
@ -125,7 +204,17 @@ index 7e843c3e76624..5b7e847304f50 100644
dp->astr = flags;
dp->alen++;
std::sort(flags, flags + dp->alen);
@@ -538,7 +541,7 @@ int HashMgr::add_with_affix(const std::string& word, const std::string& example)
}
dp = dp->next_homonym;
}
return 0;
}
@@ -533,17 +536,17 @@ int HashMgr::add_with_affix(const std::s
remove_forbidden_flag(word);
if (dp && dp->astr) {
int captype;
int wcl = get_clen_and_captype(word, &captype);
if (aliasf) {
add_word(word, wcl, dp->astr, dp->alen, NULL, false, captype);
} else {
unsigned short* flags =
@ -134,7 +223,17 @@ index 7e843c3e76624..5b7e847304f50 100644
if (flags) {
memcpy((void*)flags, (void*)dp->astr,
dp->alen * sizeof(unsigned short));
@@ -673,7 +676,7 @@ int HashMgr::load_tables(const char* tpath, const char* key) {
add_word(word, wcl, flags, dp->alen, NULL, false, captype);
} else
return 1;
}
return add_hidden_capitalized_word(word, wcl, dp->astr,
@@ -668,17 +671,17 @@ int HashMgr::load_tables(const char* tpa
if (aliasf) {
int index = atoi(ap.c_str());
al = get_aliasf(index, &flags, dict);
if (!al) {
HUNSPELL_WARNING(stderr, "error: line %d: bad flag vector alias\n",
dict->getlinenum());
}
} else {
@ -143,7 +242,17 @@ index 7e843c3e76624..5b7e847304f50 100644
if (al == -1) {
HUNSPELL_WARNING(stderr, "Can't allocate memory.\n");
delete dict;
@@ -714,7 +717,8 @@ int HashMgr::hash(const char* word) const {
return 6;
}
std::sort(flags, flags + al);
}
} else {
@@ -709,47 +712,48 @@ int HashMgr::hash(const char* word) cons
hv = (hv << 8) | (*word++);
while (*word != 0) {
ROTATE(hv, ROTATE_LEN);
hv ^= (*word++);
}
return (unsigned long)hv % tablesize;
}
@ -153,7 +262,12 @@ index 7e843c3e76624..5b7e847304f50 100644
int len;
if (flags.empty()) {
*result = NULL;
@@ -727,7 +731,7 @@ int HashMgr::decode_flags(unsigned short** result, const std::string& flags, Fil
return 0;
}
switch (flag_mode) {
case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
len = flags.size();
if (len % 2 == 1)
HUNSPELL_WARNING(stderr, "error: line %d: bad flagvector\n",
af->getlinenum());
len /= 2;
@ -162,7 +276,16 @@ index 7e843c3e76624..5b7e847304f50 100644
if (!*result)
return -1;
for (int i = 0; i < len; i++) {
@@ -744,7 +748,7 @@ int HashMgr::decode_flags(unsigned short** result, const std::string& flags, Fil
(*result)[i] = ((unsigned short)((unsigned char)flags[i * 2]) << 8) +
(unsigned char)flags[i * 2 + 1];
}
break;
}
case FLAG_NUM: { // decimal numbers separated by comma (4521,23,233 -> 4521
// 23 233)
len = 1;
unsigned short* dest;
for (size_t i = 0; i < flags.size(); ++i) {
if (flags[i] == ',')
len++;
}
@ -171,7 +294,17 @@ index 7e843c3e76624..5b7e847304f50 100644
if (!*result)
return -1;
dest = *result;
@@ -779,7 +783,7 @@ int HashMgr::decode_flags(unsigned short** result, const std::string& flags, Fil
const char* src = flags.c_str();
for (const char* p = src; *p; p++) {
if (*p == ',') {
int i = atoi(src);
if (i >= DEFAULTFLAGS)
@@ -774,26 +778,26 @@ int HashMgr::decode_flags(unsigned short
HUNSPELL_WARNING(stderr, "error: line %d: 0 is wrong flag id\n",
af->getlinenum());
break;
}
case FLAG_UNI: { // UTF-8 characters
std::vector<w_char> w;
u8_u16(w, flags);
len = w.size();
@ -179,8 +312,9 @@ index 7e843c3e76624..5b7e847304f50 100644
+ *result = (unsigned short*)alloc(len * sizeof(unsigned short));
if (!*result)
return -1;
memcpy(*result, &w[0], len * sizeof(short));
@@ -788,7 +792,7 @@ int HashMgr::decode_flags(unsigned short** result, const std::string& flags, Fil
memcpy(*result, w.data(), len * sizeof(short));
break;
}
default: { // Ispell's one-character flags (erfg -> e r f g)
unsigned short* dest;
len = flags.size();
@ -189,7 +323,17 @@ index 7e843c3e76624..5b7e847304f50 100644
if (!*result)
return -1;
dest = *result;
@@ -895,6 +899,8 @@ unsigned short HashMgr::decode_flag(const char* f) const {
for (size_t i = 0; i < flags.size(); ++i) {
*dest = (unsigned char)flags[i];
dest++;
}
}
@@ -890,16 +894,18 @@ unsigned short HashMgr::decode_flag(cons
default:
s = *(unsigned char*)f;
}
if (s == 0)
HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
return s;
}
@ -198,7 +342,17 @@ index 7e843c3e76624..5b7e847304f50 100644
char* HashMgr::encode_flag(unsigned short f) const {
if (f == 0)
return mystrdup("(NULL)");
@@ -1075,15 +1081,15 @@ bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) {
std::string ch;
if (flag_mode == FLAG_LONG) {
ch.push_back((unsigned char)(f >> 8));
ch.push_back((unsigned char)(f - ((f >> 8) << 8)));
} else if (flag_mode == FLAG_NUM) {
@@ -1070,42 +1076,42 @@ bool HashMgr::parse_aliasf(const std::st
numaliasf = 0;
aliasf = NULL;
aliasflen = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
af->getlinenum());
return false;
}
aliasf =
@ -218,7 +372,15 @@ index 7e843c3e76624..5b7e847304f50 100644
aliasf = NULL;
aliasflen = NULL;
return false;
@@ -1099,8 +1105,8 @@ bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) {
}
np++;
break;
}
default:
break;
}
++i;
start_piece = mystrsep(line, iter);
}
if (np != 2) {
numaliasf = 0;
@ -229,30 +391,37 @@ index 7e843c3e76624..5b7e847304f50 100644
aliasf = NULL;
aliasflen = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
@@ -1124,8 +1130,8 @@ bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) {
case 0: {
if (nl.compare(start_piece - nl.begin(), 2, "AF", 2) != 0) {
numaliasf = 0;
- free(aliasf);
- free(aliasflen);
+ arena_free(aliasf);
+ arena_free(aliasflen);
aliasf = NULL;
aliasflen = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
@@ -1137,7 +1143,7 @@ bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) {
case 1: {
std::string piece(start_piece, iter);
aliasflen[j] =
- (unsigned short)decode_flags(&(aliasf[j]), piece, af);
+ (unsigned short)decode_flags(&(aliasf[j]), piece, af, /* arena = */ true);
std::sort(aliasf[j], aliasf[j] + aliasflen[j]);
break;
af->getlinenum());
return false;
}
/* now parse the numaliasf lines to read in the remainder of the table */
@@ -1126,33 +1132,33 @@ bool HashMgr::parse_aliasf(const std::st
errored = true;
break;
}
break;
}
case 1: {
std::string piece(start_piece, iter);
aliasflen[j] =
- (unsigned short)decode_flags(&(aliasf[j]), piece, af);
+ (unsigned short)decode_flags(&(aliasf[j]), piece, af, /* arena = */ true);
std::sort(aliasf[j], aliasf[j] + aliasflen[j]);
break;
}
default:
break;
}
@@ -1148,8 +1154,8 @@ bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) {
start_piece = mystrsep(nl, iter);
++i;
start_piece = mystrsep(nl, iter);
}
}
if (!aliasf[j]) {
for (int k = 0; k < j; ++k) {
- free(aliasf[k]);
+ arena_free(aliasf[k]);
}
- free(aliasf);
- free(aliasflen);
+ arena_free(aliasf);
@ -260,7 +429,17 @@ index 7e843c3e76624..5b7e847304f50 100644
aliasf = NULL;
aliasflen = NULL;
numaliasf = 0;
@@ -1200,7 +1206,7 @@ bool HashMgr::parse_aliasm(const std::string& line, FileMgr* af) {
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
return false;
}
}
@@ -1193,33 +1199,33 @@ bool HashMgr::parse_aliasm(const std::st
}
case 1: {
numaliasm = atoi(std::string(start_piece, iter).c_str());
if (numaliasm < 1) {
HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
af->getlinenum());
return false;
}
@ -269,7 +448,15 @@ index 7e843c3e76624..5b7e847304f50 100644
if (!aliasm) {
numaliasm = 0;
return false;
@@ -1216,7 +1222,7 @@ bool HashMgr::parse_aliasm(const std::string& line, FileMgr* af) {
}
np++;
break;
}
default:
break;
}
++i;
start_piece = mystrsep(line, iter);
}
if (np != 2) {
numaliasm = 0;
@ -278,38 +465,57 @@ index 7e843c3e76624..5b7e847304f50 100644
aliasm = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
af->getlinenum());
@@ -1240,7 +1246,7 @@ bool HashMgr::parse_aliasm(const std::string& line, FileMgr* af) {
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
numaliasm = 0;
- free(aliasm);
+ arena_free(aliasm);
aliasm = NULL;
return false;
return false;
}
/* now parse the numaliasm lines to read in the remainder of the table */
for (int j = 0; j < numaliasm; j++) {
@@ -1245,32 +1251,36 @@ bool HashMgr::parse_aliasm(const std::st
std::string::const_iterator end = nl.end();
std::string chunk(start_piece, end);
if (complexprefixes) {
if (utf8)
reverseword_utf(chunk);
else
reverseword(chunk);
}
- aliasm[j] = mystrdup(chunk.c_str());
+ size_t sl = chunk.length() + 1;
+ aliasm[j] = (char*)arena_alloc(sl);
+ if (aliasm[j]) {
+ memcpy(aliasm[j], chunk.c_str(), sl);
+ }
break;
}
@@ -1256,7 +1262,11 @@ bool HashMgr::parse_aliasm(const std::string& line, FileMgr* af) {
else
reverseword(chunk);
}
- aliasm[j] = mystrdup(chunk.c_str());
+ size_t sl = chunk.length() + 1;
+ aliasm[j] = (char*)arena_alloc(sl);
+ if (aliasm[j]) {
+ memcpy(aliasm[j], chunk.c_str(), sl);
+ }
break;
default:
break;
}
default:
@@ -1267,7 +1277,7 @@ bool HashMgr::parse_aliasm(const std::string& line, FileMgr* af) {
++i;
start_piece = mystrsep(nl, iter);
}
}
if (!aliasm[j]) {
numaliasm = 0;
for (int k = 0; k < j; ++k) {
- free(aliasm[k]);
+ arena_free(aliasm[k]);
}
- free(aliasm);
+ arena_free(aliasm);
aliasm = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
@@ -1387,3 +1397,25 @@ bool HashMgr::parse_reptable(const std::string& line, FileMgr* af) {
return false;
}
}
return true;
}
@@ -1379,8 +1389,27 @@ bool HashMgr::parse_reptable(const std::
}
return true;
}
// return replacing table
const std::vector<replentry>& HashMgr::get_reptable() const {
return reptable;
}
@ -333,10 +539,14 @@ index 7e843c3e76624..5b7e847304f50 100644
+ assert(outstanding_arena_allocations >= 0);
+}
diff --git a/extensions/spellcheck/hunspell/src/hashmgr.hxx b/extensions/spellcheck/hunspell/src/hashmgr.hxx
index b6eadddecc5b9..9cb447a978cf2 100644
--- a/extensions/spellcheck/hunspell/src/hashmgr.hxx
+++ b/extensions/spellcheck/hunspell/src/hashmgr.hxx
@@ -72,6 +72,8 @@
@@ -67,16 +67,18 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef HASHMGR_HXX_
#define HASHMGR_HXX_
#include <stdio.h>
@ -345,7 +555,17 @@ index b6eadddecc5b9..9cb447a978cf2 100644
#include <string>
#include <vector>
@@ -121,7 +123,13 @@ class HashMgr {
#include "htypes.hxx"
#include "filemgr.hxx"
#include "w_char.hxx"
enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI };
@@ -116,17 +118,23 @@ class HashMgr {
struct hentry* lookup(const char*) const;
int hash(const char*) const;
struct hentry* walk_hashtable(int& col, struct hentry* hp) const;
int add(const std::string& word);
int add_with_affix(const std::string& word, const std::string& pattern);
int remove(const std::string& word);
@ -360,7 +580,17 @@ index b6eadddecc5b9..9cb447a978cf2 100644
bool decode_flags(std::vector<unsigned short>& result, const std::string& flags, FileMgr* af) const;
unsigned short decode_flag(const char* flag) const;
char* encode_flag(unsigned short flag) const;
@@ -153,6 +161,22 @@ class HashMgr {
int is_aliasf() const;
int get_aliasf(int index, unsigned short** fvec, FileMgr* af) const;
int is_aliasm() const;
char* get_aliasm(int index) const;
const std::vector<replentry>& get_reptable() const;
@@ -148,11 +156,27 @@ class HashMgr {
int wcl,
unsigned short* flags,
int al,
const std::string* dp,
int captype);
bool parse_aliasm(const std::string& line, FileMgr* af);
bool parse_reptable(const std::string& line, FileMgr* af);
int remove_forbidden_flag(const std::string& word);

View file

@ -60,6 +60,12 @@ Main features of Hunspell command line tool, developed by László Németh:
See man hunspell, man 3 hunspell, man 5 hunspell for complete manual.
Translations: Hunspell has been translated into several languages already. If your language is missing or incomplete, please use [Weblate](https://hosted.weblate.org/engage/hunspell/) to help translate Hunspell.
<a href="https://hosted.weblate.org/engage/hunspell/">
<img src="https://hosted.weblate.org/widgets/hunspell/-/translations/horizontal-auto.svg" alt="Stanje prijevoda" />
</a>
# Dependencies
Build only dependencies:
@ -95,7 +101,7 @@ For dictionary development, use the `--with-warnings` option of
configure.
For interactive user interface of Hunspell executable, use the
`--with-ui option`.
`--with-ui` option.
Optional developer packages:
@ -115,7 +121,11 @@ dependencies are build with that.
brew install autoconf automake libtool gettext
brew link gettext --force
Then run autoreconf, configure, make. See above.
Then run:
autoreconf -vfi
./configure
make
# Compiling on Windows
@ -304,8 +314,8 @@ Hunspell (MySpell) dictionaries:
- https://wiki.documentfoundation.org/Language_support_of_LibreOffice
- http://cgit.freedesktop.org/libreoffice/dictionaries
- http://extensions.libreoffice.org
- http://extensions.openoffice.org
- http://wiki.services.openoffice.org/wiki/Dictionaries
- https://extensions.openoffice.org
- https://wiki.openoffice.org/wiki/Dictionaries
Aspell dictionaries (conversion: man 5 hunspell):

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
@ -146,7 +146,7 @@ inline int PfxEntry::test_condition(const char* st) {
break;
}
case ']': {
if ((neg && ingroup) || (!neg && !ingroup))
if (bool(neg) == bool(ingroup))
return 0;
pos = NULL;
p = nextchar(p);
@ -224,7 +224,7 @@ struct hentry* PfxEntry::checkword(const char* word,
// back any characters that would have been stripped
std::string tmpword(strip);
tmpword.append(word + appnd.size());
tmpword.append(word + appnd.size(), tmpl);
// now make sure all of the conditions on characters
// are met. Please see the appendix at the end of

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
@ -1052,7 +1052,7 @@ int AffixMgr::encodeit(AffEntry& entry, const char* cs) {
} else if (cs[MAXCONDLEN]) {
//there is more conditions than fit in fixed space, so its
//a long condition
entry.opts += aeLONGCOND;
entry.opts |= aeLONGCOND;
entry.c.l.conds2 = mystrdup(cs + MAXCONDLEN_1);
if (!entry.c.l.conds2)
return 1;
@ -1600,8 +1600,12 @@ struct hentry* AffixMgr::compound_check(const std::string& word,
HUNSPELL_THREAD_LOCAL clock_t timelimit;
if (wordnum == 0)
timelimit = clock();
if (wordnum == 0) {
// get the start time, seeing as we're reusing this set to 0
// to flag timeout, use clock() + 1 to avoid start clock()
// of 0 as being a timeout
timelimit = clock() + 1;
}
else if (timelimit != 0 && (clock() > timelimit + TIMELIMIT)) {
timelimit = 0;
}
@ -2206,8 +2210,12 @@ int AffixMgr::compound_check_morph(const char* word,
HUNSPELL_THREAD_LOCAL clock_t timelimit;
if (wordnum == 0)
timelimit = clock();
if (wordnum == 0) {
// get the start time, seeing as we're reusing this set to 0
// to flag timeout, use clock() + 1 to avoid start clock()
// of 0 as being a timeout
timelimit = clock() + 1;
}
else if (timelimit != 0 && (clock() > timelimit + TIMELIMIT)) {
timelimit = 0;
}
@ -4359,7 +4367,7 @@ void AffixMgr::reverse_condition(std::string& piece) {
case '^': {
if (*(k - 1) == ']')
neg = 1;
else
else if (neg)
*(k - 1) = *k;
break;
}
@ -4492,11 +4500,11 @@ bool AffixMgr::parse_affix(const std::string& line,
char opts = ff;
if (utf8)
opts += aeUTF8;
opts |= aeUTF8;
if (pHMgr->is_aliasf())
opts += aeALIASF;
opts |= aeALIASF;
if (pHMgr->is_aliasm())
opts += aeALIASM;
opts |= aeALIASM;
affentries.initialize(numents, opts, aflag);
}

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
@ -252,15 +252,15 @@ int HashMgr::add_word(const std::string& in_word,
// store the description string or its pointer
if (desc) {
hp->var += H_OPT;
hp->var |= H_OPT;
if (aliasm) {
hp->var += H_OPT_ALIASM;
hp->var |= H_OPT_ALIASM;
store_pointer(hpw + word->size() + 1, get_aliasm(atoi(desc->c_str())));
} else {
strcpy(hpw + word->size() + 1, desc->c_str());
}
if (strstr(HENTRY_DATA(hp), MORPH_PHON)) {
hp->var += H_OPT_PHON;
hp->var |= H_OPT_PHON;
// store ph: fields (pronounciation, misspellings, old orthography etc.)
// of a morphological description in reptable to use in REP replacements.
if (reptable.capacity() < (unsigned int)(tablesize/MORPH_PHON_RATIO))
@ -786,7 +786,7 @@ int HashMgr::decode_flags(unsigned short** result, const std::string& flags, Fil
*result = (unsigned short*)alloc(len * sizeof(unsigned short));
if (!*result)
return -1;
memcpy(*result, &w[0], len * sizeof(short));
memcpy(*result, w.data(), len * sizeof(short));
break;
}
default: { // Ispell's one-character flags (erfg -> e r f g)
@ -857,7 +857,7 @@ bool HashMgr::decode_flags(std::vector<unsigned short>& result, const std::strin
size_t len = w.size();
size_t origsize = result.size();
result.resize(origsize + len);
memcpy(&result[origsize], &w[0], len * sizeof(short));
memcpy(result.data() + origsize, w.data(), len * sizeof(short));
break;
}
default: { // Ispell's one-character flags (erfg -> e r f g)
@ -888,7 +888,7 @@ unsigned short HashMgr::decode_flag(const char* f) const {
std::vector<w_char> w;
u8_u16(w, f);
if (!w.empty())
memcpy(&s, &w[0], 1 * sizeof(short));
memcpy(&s, w.data(), 1 * sizeof(short));
break;
}
default:
@ -1117,43 +1117,41 @@ bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) {
/* now parse the numaliasf lines to read in the remainder of the table */
for (int j = 0; j < numaliasf; j++) {
std::string nl;
if (!af->getline(nl))
return false;
mychomp(nl);
i = 0;
aliasf[j] = NULL;
aliasflen[j] = 0;
iter = nl.begin();
start_piece = mystrsep(nl, iter);
while (start_piece != nl.end()) {
switch (i) {
case 0: {
if (nl.compare(start_piece - nl.begin(), 2, "AF", 2) != 0) {
numaliasf = 0;
arena_free(aliasf);
arena_free(aliasflen);
aliasf = NULL;
aliasflen = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
return false;
}
break;
}
case 1: {
std::string piece(start_piece, iter);
aliasflen[j] =
(unsigned short)decode_flags(&(aliasf[j]), piece, af, /* arena = */ true);
std::sort(aliasf[j], aliasf[j] + aliasflen[j]);
break;
}
default:
break;
}
++i;
i = 0;
if (af->getline(nl)) {
mychomp(nl);
iter = nl.begin();
start_piece = mystrsep(nl, iter);
bool errored = false;
while (!errored && start_piece != nl.end()) {
switch (i) {
case 0: {
if (nl.compare(start_piece - nl.begin(), 2, "AF", 2) != 0) {
errored = true;
break;
}
break;
}
case 1: {
std::string piece(start_piece, iter);
aliasflen[j] =
(unsigned short)decode_flags(&(aliasf[j]), piece, af, /* arena = */ true);
std::sort(aliasf[j], aliasf[j] + aliasflen[j]);
break;
}
default:
break;
}
++i;
start_piece = mystrsep(nl, iter);
}
}
if (!aliasf[j]) {
for (int k = 0; k < j; ++k) {
arena_free(aliasf[k]);
}
arena_free(aliasf);
arena_free(aliasflen);
aliasf = NULL;
@ -1232,51 +1230,51 @@ bool HashMgr::parse_aliasm(const std::string& line, FileMgr* af) {
/* now parse the numaliasm lines to read in the remainder of the table */
for (int j = 0; j < numaliasm; j++) {
std::string nl;
if (!af->getline(nl))
return false;
mychomp(nl);
aliasm[j] = NULL;
iter = nl.begin();
i = 0;
start_piece = mystrsep(nl, iter);
while (start_piece != nl.end()) {
switch (i) {
case 0: {
if (nl.compare(start_piece - nl.begin(), 2, "AM", 2) != 0) {
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
numaliasm = 0;
arena_free(aliasm);
aliasm = NULL;
return false;
}
break;
}
case 1: {
// add the remaining of the line
std::string::const_iterator end = nl.end();
std::string chunk(start_piece, end);
if (complexprefixes) {
if (utf8)
reverseword_utf(chunk);
else
reverseword(chunk);
}
size_t sl = chunk.length() + 1;
aliasm[j] = (char*)arena_alloc(sl);
if (aliasm[j]) {
memcpy(aliasm[j], chunk.c_str(), sl);
}
break;
}
default:
break;
}
++i;
if (af->getline(nl)) {
mychomp(nl);
iter = nl.begin();
i = 0;
start_piece = mystrsep(nl, iter);
bool errored = false;
while (!errored && start_piece != nl.end()) {
switch (i) {
case 0: {
if (nl.compare(start_piece - nl.begin(), 2, "AM", 2) != 0) {
errored = true;
break;
}
break;
}
case 1: {
// add the remaining of the line
std::string::const_iterator end = nl.end();
std::string chunk(start_piece, end);
if (complexprefixes) {
if (utf8)
reverseword_utf(chunk);
else
reverseword(chunk);
}
size_t sl = chunk.length() + 1;
aliasm[j] = (char*)arena_alloc(sl);
if (aliasm[j]) {
memcpy(aliasm[j], chunk.c_str(), sl);
}
break;
}
default:
break;
}
++i;
start_piece = mystrsep(nl, iter);
}
}
if (!aliasm[j]) {
numaliasm = 0;
for (int k = 0; k < j; ++k) {
arena_free(aliasm[k]);
}
arena_free(aliasm);
aliasm = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
@ -1342,46 +1340,45 @@ bool HashMgr::parse_reptable(const std::string& line, FileMgr* af) {
/* now parse the numrep lines to read in the remainder of the table */
for (int j = 0; j < numrep; ++j) {
std::string nl;
if (!af->getline(nl))
return false;
mychomp(nl);
reptable.push_back(replentry());
iter = nl.begin();
i = 0;
int type = 0;
start_piece = mystrsep(nl, iter);
while (start_piece != nl.end()) {
switch (i) {
case 0: {
if (nl.compare(start_piece - nl.begin(), 3, "REP", 3) != 0) {
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
reptable.clear();
return false;
}
break;
}
case 1: {
if (*start_piece == '^')
type = 1;
reptable.back().pattern.assign(start_piece + type, iter);
mystrrep(reptable.back().pattern, "_", " ");
if (!reptable.back().pattern.empty() && reptable.back().pattern[reptable.back().pattern.size() - 1] == '$') {
type += 2;
reptable.back().pattern.resize(reptable.back().pattern.size() - 1);
}
break;
}
case 2: {
reptable.back().outstrings[type].assign(start_piece, iter);
mystrrep(reptable.back().outstrings[type], "_", " ");
break;
}
default:
break;
}
++i;
if (af->getline(nl)) {
mychomp(nl);
iter = nl.begin();
i = 0;
start_piece = mystrsep(nl, iter);
bool errored = false;
while (!errored && start_piece != nl.end()) {
switch (i) {
case 0: {
if (nl.compare(start_piece - nl.begin(), 3, "REP", 3) != 0) {
errored = true;
break;
}
break;
}
case 1: {
if (*start_piece == '^')
type = 1;
reptable.back().pattern.assign(start_piece + type, iter);
mystrrep(reptable.back().pattern, "_", " ");
if (!reptable.back().pattern.empty() && reptable.back().pattern[reptable.back().pattern.size() - 1] == '$') {
type += 2;
reptable.back().pattern.resize(reptable.back().pattern.size() - 1);
}
break;
}
case 2: {
reptable.back().outstrings[type].assign(start_piece, iter);
mystrrep(reptable.back().outstrings[type], "_", " ");
break;
}
default:
break;
}
++i;
start_piece = mystrsep(nl, iter);
}
}
if (reptable.back().pattern.empty() || reptable.back().outstrings[type].empty()) {
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
@ -160,10 +160,10 @@ private:
void insert_sug(std::vector<std::string>& slst, const std::string& word);
void cat_result(std::string& result, const std::string& st);
std::vector<std::string> spellml(const std::string& word);
std::string get_xml_par(const char* par);
const char* get_xml_pos(const char* s, const char* attr);
std::vector<std::string> get_xml_list(const char* list, const char* tag);
int check_xml_par(const char* q, const char* attr, const char* value);
std::string get_xml_par(const std::string& par, std::string::size_type pos);
std::string::size_type get_xml_pos(const std::string& s, std::string::size_type pos, const char* attr);
std::vector<std::string> get_xml_list(const std::string& list, std::string::size_type pos, const char* tag);
int check_xml_par(const std::string& q, std::string::size_type pos, const char* attr, const char* value);
private:
HunspellImpl(const HunspellImpl&);
HunspellImpl& operator=(const HunspellImpl&);
@ -521,7 +521,7 @@ bool HunspellImpl::spell_internal(const std::string& word, int* info, std::strin
case HUHCAP:
/* FALLTHROUGH */
case HUHINITCAP:
*info += SPELL_ORIGCAP;
*info |= SPELL_ORIGCAP;
/* FALLTHROUGH */
case NOCAP:
rv = checkword(scw, info, root);
@ -532,7 +532,7 @@ bool HunspellImpl::spell_internal(const std::string& word, int* info, std::strin
}
break;
case ALLCAP: {
*info += SPELL_ORIGCAP;
*info |= SPELL_ORIGCAP;
rv = checkword(scw, info, root);
if (rv)
break;
@ -603,7 +603,7 @@ bool HunspellImpl::spell_internal(const std::string& word, int* info, std::strin
case INITCAP: {
// handle special capitalization of dotted I
bool Idot = (utf8 && (unsigned char) scw[0] == 0xc4 && (unsigned char) scw[1] == 0xb0);
*info += SPELL_ORIGCAP;
*info |= SPELL_ORIGCAP;
if (captype == ALLCAP) {
mkallsmall2(scw, sunicw);
mkinitcap2(scw, sunicw);
@ -611,10 +611,10 @@ bool HunspellImpl::spell_internal(const std::string& word, int* info, std::strin
scw.replace(0, 1, "\xc4\xb0");
}
if (captype == INITCAP)
*info += SPELL_INITCAP;
*info |= SPELL_INITCAP;
rv = checkword(scw, info, root);
if (captype == INITCAP)
*info -= SPELL_INITCAP;
*info &= ~SPELL_INITCAP;
// forbid bad capitalization
// (for example, ijs -> Ijs instead of IJs in Dutch)
// use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag)
@ -639,10 +639,10 @@ bool HunspellImpl::spell_internal(const std::string& word, int* info, std::strin
u8buffer = scw;
u8buffer.push_back('.');
if (captype == INITCAP)
*info += SPELL_INITCAP;
*info |= SPELL_INITCAP;
rv = checkword(u8buffer, info, root);
if (captype == INITCAP)
*info -= SPELL_INITCAP;
*info &= ~SPELL_INITCAP;
if (rv && is_keepcase(rv) && (captype == ALLCAP))
rv = NULL;
break;
@ -663,7 +663,7 @@ bool HunspellImpl::spell_internal(const std::string& word, int* info, std::strin
if (rv) {
if (pAMgr && pAMgr->get_warn() && rv->astr &&
TESTAFF(rv->astr, pAMgr->get_warn(), rv->alen)) {
*info += SPELL_WARN;
*info |= SPELL_WARN;
if (pAMgr->get_forbidwarn())
return false;
return true;
@ -770,7 +770,6 @@ bool HunspellImpl::spell_internal(const std::string& word, int* info, std::strin
}
struct hentry* HunspellImpl::checkword(const std::string& w, int* info, std::string* root) {
bool usebuffer = false;
std::string w2;
const char* word;
int len;
@ -780,26 +779,19 @@ struct hentry* HunspellImpl::checkword(const std::string& w, int* info, std::str
word = w2.c_str();
len = w2.size();
usebuffer = true;
if (!len)
return NULL;
// word reversing wrapper for complex prefixes
if (complexprefixes) {
if (!usebuffer) {
w2.assign(word);
usebuffer = true;
}
if (utf8)
reverseword_utf(w2);
else
reverseword(w2);
}
if (usebuffer) {
word = w2.c_str();
}
word = w2.c_str();
// look word in hash table
struct hentry* he = NULL;
@ -810,13 +802,13 @@ struct hentry* HunspellImpl::checkword(const std::string& w, int* info, std::str
if ((he) && (he->astr) && (pAMgr) &&
TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
if (info)
*info += SPELL_FORBIDDEN;
*info |= SPELL_FORBIDDEN;
// LANG_hu section: set dash information for suggestions
if (langnum == LANG_hu) {
if (pAMgr->get_compoundflag() &&
TESTAFF(he->astr, pAMgr->get_compoundflag(), he->alen)) {
if (info)
*info += SPELL_COMPOUND;
*info |= SPELL_COMPOUND;
}
}
return NULL;
@ -851,7 +843,7 @@ struct hentry* HunspellImpl::checkword(const std::string& w, int* info, std::str
if ((he->astr) && (pAMgr) &&
TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
if (info)
*info += SPELL_FORBIDDEN;
*info |= SPELL_FORBIDDEN;
return NULL;
}
if (root) {
@ -884,7 +876,7 @@ struct hentry* HunspellImpl::checkword(const std::string& w, int* info, std::str
}
}
if (info)
*info += SPELL_COMPOUND;
*info |= SPELL_COMPOUND;
}
}
}
@ -1732,10 +1724,11 @@ std::vector<std::string> HunspellImpl::generate(const std::string& word, const s
}
// minimal XML parser functions
std::string HunspellImpl::get_xml_par(const char* par) {
std::string HunspellImpl::get_xml_par(const std::string& in_par, std::string::size_type pos) {
std::string dest;
if (!par)
if (pos == std::string::npos)
return dest;
const char* par = in_par.c_str() + pos;
char end = *par;
if (end == '>')
end = '<';
@ -1763,42 +1756,47 @@ bool HunspellImpl::input_conv(const std::string& word, std::string& dest) {
}
// return the beginning of the element (attr == NULL) or the attribute
const char* HunspellImpl::get_xml_pos(const char* s, const char* attr) {
const char* end = strchr(s, '>');
std::string::size_type HunspellImpl::get_xml_pos(const std::string& s, std::string::size_type pos, const char* attr) {
if (pos == std::string::npos)
return std::string::npos;
std::string::size_type endpos = s.find('>', pos);
if (attr == NULL)
return end;
const char* p = s;
while (1) {
p = strstr(p, attr);
if (!p || p >= end)
return 0;
if (*(p - 1) == ' ' || *(p - 1) == '\n')
return endpos;
while (true) {
pos = s.find(attr, pos);
if (pos == std::string::npos || pos >= endpos)
return std::string::npos;
if (s[pos - 1] == ' ' || s[pos - 1] == '\n')
break;
p += strlen(attr);
pos += strlen(attr);
}
return p + strlen(attr);
return pos + strlen(attr);
}
int HunspellImpl::check_xml_par(const char* q,
const char* attr,
const char* value) {
std::string cw = get_xml_par(get_xml_pos(q, attr));
int HunspellImpl::check_xml_par(const std::string& q, std::string::size_type pos,
const char* attr,
const char* value) {
std::string cw = get_xml_par(q, get_xml_pos(q, pos, attr));
if (cw == value)
return 1;
return 0;
}
std::vector<std::string> HunspellImpl::get_xml_list(const char* list, const char* tag) {
std::vector<std::string> HunspellImpl::get_xml_list(const std::string& list, std::string::size_type pos, const char* tag) {
std::vector<std::string> slst;
if (!list)
if (pos == std::string::npos)
return slst;
const char* p = list;
for (size_t n = 0; ((p = strstr(p, tag)) != NULL); ++p, ++n) {
std::string cw = get_xml_par(p + strlen(tag) - 1);
while (true) {
pos = list.find(tag, pos);
if (pos == std::string::npos)
break;
std::string cw = get_xml_par(list, pos + strlen(tag) - 1);
if (cw.empty()) {
break;
}
slst.push_back(cw);
++pos;
}
return slst;
}
@ -1806,19 +1804,20 @@ std::vector<std::string> HunspellImpl::get_xml_list(const char* list, const char
std::vector<std::string> HunspellImpl::spellml(const std::string& in_word) {
std::vector<std::string> slst;
const char* word = in_word.c_str();
std::string::size_type qpos = in_word.find("<query");
if (qpos == std::string::npos)
return slst; // bad XML input
const char* q = strstr(word, "<query");
if (!q)
std::string::size_type q2pos = in_word.find('>', qpos);
if (q2pos == std::string::npos)
return slst; // bad XML input
const char* q2 = strchr(q, '>');
if (!q2)
q2pos = in_word.find("<word", q2pos);
if (q2pos == std::string::npos)
return slst; // bad XML input
q2 = strstr(q2, "<word");
if (!q2)
return slst; // bad XML input
if (check_xml_par(q, "type=", "analyze")) {
std::string cw = get_xml_par(strchr(q2, '>'));
if (check_xml_par(in_word, qpos, "type=", "analyze")) {
std::string cw = get_xml_par(in_word, in_word.find('>', q2pos));
if (!cw.empty())
slst = analyze(cw);
if (slst.empty())
@ -1841,23 +1840,24 @@ std::vector<std::string> HunspellImpl::spellml(const std::string& in_word) {
slst.clear();
slst.push_back(r);
return slst;
} else if (check_xml_par(q, "type=", "stem")) {
std::string cw = get_xml_par(strchr(q2, '>'));
} else if (check_xml_par(in_word, qpos, "type=", "stem")) {
std::string cw = get_xml_par(in_word, in_word.find('>', q2pos));
if (!cw.empty())
return stem(cw);
} else if (check_xml_par(q, "type=", "generate")) {
std::string cw = get_xml_par(strchr(q2, '>'));
} else if (check_xml_par(in_word, qpos, "type=", "generate")) {
std::string cw = get_xml_par(in_word, in_word.find('>', q2pos));
if (cw.empty())
return slst;
const char* q3 = strstr(q2 + 1, "<word");
if (q3) {
std::string cw2 = get_xml_par(strchr(q3, '>'));
std::string::size_type q3pos = in_word.find("<word", q2pos + 1);
if (q3pos != std::string::npos) {
std::string cw2 = get_xml_par(in_word, in_word.find('>', q3pos));
if (!cw2.empty()) {
return generate(cw, cw2);
}
} else {
if ((q2 = strstr(q2 + 1, "<code")) != NULL) {
std::vector<std::string> slst2 = get_xml_list(strchr(q2, '>'), "<a>");
q2pos = in_word.find("<code", q2pos + 1);
if (q2pos != std::string::npos) {
std::vector<std::string> slst2 = get_xml_list(in_word, in_word.find('>', q2pos), "<a>");
if (!slst2.empty()) {
slst = generate(cw, slst2);
uniqlist(slst);
@ -1865,13 +1865,13 @@ std::vector<std::string> HunspellImpl::spellml(const std::string& in_word) {
}
}
}
} else if (check_xml_par(q, "type=", "add")) {
std::string cw = get_xml_par(strchr(q2, '>'));
} else if (check_xml_par(in_word, qpos, "type=", "add")) {
std::string cw = get_xml_par(in_word, in_word.find('>', q2pos));
if (cw.empty())
return slst;
const char* q3 = strstr(q2 + 1, "<word");
if (q3) {
std::string cw2 = get_xml_par(strchr(q3, '>'));
std::string::size_type q3pos = in_word.find("<word", q2pos + 1);
if (q3pos != std::string::npos) {
std::string cw2 = get_xml_par(in_word, in_word.find('>', q3pos));
if (!cw2.empty()) {
add_with_affix(cw, cw2);
} else {
@ -1982,6 +1982,7 @@ int HunspellImpl::stem(char*** slst, const char* word) {
int HunspellImpl::stem(char*** slst, char** desc, int n) {
std::vector<std::string> morph;
morph.reserve(n);
for (int i = 0; i < n; ++i)
morph.push_back(desc[i]);
@ -1996,6 +1997,7 @@ int HunspellImpl::generate(char*** slst, const char* word, const char* pattern)
int HunspellImpl::generate(char*** slst, const char* word, char** pl, int pln) {
std::vector<std::string> morph;
morph.reserve(pln);
for (int i = 0; i < pln; ++i)
morph.push_back(pl[i]);

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
@ -78,7 +78,10 @@
#define SPELL_XML "<?xml?>"
#ifndef MAXSUGGESTION
#define MAXSUGGESTION 15
#endif
#define MAXSHARPS 5
#ifndef MAXWORDLEN

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
@ -227,7 +227,7 @@ bool SuggestMgr::suggest(std::vector<std::string>& slst,
if (slst.size() < maxSug) {
size_t i = slst.size();
if (utf8)
capchars_utf(slst, &word_utf[0], wl, cpdsuggest);
capchars_utf(slst, word_utf.data(), wl, cpdsuggest);
else
capchars(slst, word, cpdsuggest);
if (slst.size() > i)
@ -259,7 +259,7 @@ bool SuggestMgr::suggest(std::vector<std::string>& slst,
// did we swap the order of chars by mistake
if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
if (utf8)
swapchar_utf(slst, &word_utf[0], wl, cpdsuggest);
swapchar_utf(slst, word_utf.data(), wl, cpdsuggest);
else
swapchar(slst, word, cpdsuggest);
}
@ -269,7 +269,7 @@ bool SuggestMgr::suggest(std::vector<std::string>& slst,
// did we swap the order of non adjacent chars by mistake
if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
if (utf8)
longswapchar_utf(slst, &word_utf[0], wl, cpdsuggest);
longswapchar_utf(slst, word_utf.data(), wl, cpdsuggest);
else
longswapchar(slst, word, cpdsuggest);
}
@ -279,7 +279,7 @@ bool SuggestMgr::suggest(std::vector<std::string>& slst,
// did we just hit the wrong key in place of a good char (case and keyboard)
if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
if (utf8)
badcharkey_utf(slst, &word_utf[0], wl, cpdsuggest);
badcharkey_utf(slst, word_utf.data(), wl, cpdsuggest);
else
badcharkey(slst, word, cpdsuggest);
}
@ -289,7 +289,7 @@ bool SuggestMgr::suggest(std::vector<std::string>& slst,
// did we add a char that should not be there
if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
if (utf8)
extrachar_utf(slst, &word_utf[0], wl, cpdsuggest);
extrachar_utf(slst, word_utf.data(), wl, cpdsuggest);
else
extrachar(slst, word, cpdsuggest);
}
@ -299,7 +299,7 @@ bool SuggestMgr::suggest(std::vector<std::string>& slst,
// did we forgot a char
if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
if (utf8)
forgotchar_utf(slst, &word_utf[0], wl, cpdsuggest);
forgotchar_utf(slst, word_utf.data(), wl, cpdsuggest);
else
forgotchar(slst, word, cpdsuggest);
}
@ -309,7 +309,7 @@ bool SuggestMgr::suggest(std::vector<std::string>& slst,
// did we move a char
if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
if (utf8)
movechar_utf(slst, &word_utf[0], wl, cpdsuggest);
movechar_utf(slst, word_utf.data(), wl, cpdsuggest);
else
movechar(slst, word, cpdsuggest);
}
@ -319,7 +319,7 @@ bool SuggestMgr::suggest(std::vector<std::string>& slst,
// did we just hit the wrong key in place of a good char
if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
if (utf8)
badchar_utf(slst, &word_utf[0], wl, cpdsuggest);
badchar_utf(slst, word_utf.data(), wl, cpdsuggest);
else
badchar(slst, word, cpdsuggest);
}
@ -329,7 +329,7 @@ bool SuggestMgr::suggest(std::vector<std::string>& slst,
// did we double two characters
if ((slst.size() < maxSug) && (!cpdsuggest || (slst.size() < oldSug + maxcpdsugs))) {
if (utf8)
doubletwochars_utf(slst, &word_utf[0], wl, cpdsuggest);
doubletwochars_utf(slst, word_utf.data(), wl, cpdsuggest);
else
doubletwochars(slst, word, cpdsuggest);
}
@ -2040,7 +2040,7 @@ int SuggestMgr::leftcommonsubstring(
int l2 = su2.size();
// decapitalize dictionary word
if (complexprefixes) {
if (su1[l1 - 1] == su2[l2 - 1])
if (l1 && l2 && su1[l1 - 1] == su2[l2 - 1])
return 1;
} else {
unsigned short idx = su2.empty() ? 0 : (su2[0].h << 8) + su2[0].l;

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -1,7 +1,7 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Copyright (C) 2002-2017 Németh László
* Copyright (C) 2002-2022 Németh László
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with

View file

@ -12,20 +12,22 @@ git clone https://github.com/hunspell/hunspell --depth 1 --branch $1 ${tmpcloned
# Back up mozilla files
cp ${hunspell_dir}/src/moz.build ${tmpclonedir}/src/hunspell
cp ${hunspell_dir}/src/moz.yaml ${tmpclonedir}/src/hunspell
cp ${hunspell_dir}/src/sources.mozbuild ${tmpclonedir}/src/hunspell
rm -rf ${hunspell_dir}/src
cp -r ${tmpclonedir}/src/hunspell/ ${hunspell_dir}/src
cp ${tmpclonedir}/license.hunspell ${hunspell_dir}/src
cp ${tmpclonedir}/license.myspell ${hunspell_dir}/src
cp ${tmpclonedir}/license.hunspell ${hunspell_dir}/src/LICENSE
cp ${tmpclonedir}/README ${hunspell_dir}/src
cp ${tmpclonedir}/README.md ${hunspell_dir}/src
rm ${hunspell_dir}/src/Makefile.am
rm ${hunspell_dir}/src/filemgr.cxx
rm ${hunspell_dir}/src/hunvisapi.h.in
rm ${hunspell_dir}/src/hunzip.cxx
rm ${hunspell_dir}/src/hunzip.hxx
rm ${hunspell_dir}/src/utf_info.cxx
rm ${hunspell_dir}/src/utf_info.hxx
rm -rf ${tmpclonedir}
cd ${hunspell_dir}/src
patch -p5 < ../patches/bug1410214.patch
patch -p5 < ../patches/bug1653659.patch
patch -p5 < ../patches/bug1739761.patch