Index: chrome/third_party/hunspell/src/hunspell/affixmgr.cxx |
=================================================================== |
--- chrome/third_party/hunspell/src/hunspell/affixmgr.cxx (revision 21721) |
+++ chrome/third_party/hunspell/src/hunspell/affixmgr.cxx (working copy) |
@@ -7,9 +7,9 @@ |
#include <cctype> |
#include <cstdio> |
#else |
-#include <stdlib.h> |
+#include <stdlib.h> |
#include <string.h> |
-#include <stdio.h> |
+#include <stdio.h> |
#include <ctype.h> |
#endif |
@@ -20,21 +20,24 @@ |
#include "csutil.hxx" |
#ifndef MOZILLA_CLIENT |
-#ifndef W32 |
+#ifndef WIN32 |
using namespace std; |
#endif |
#endif |
#ifdef HUNSPELL_CHROME_CLIENT |
-AffixMgr::AffixMgr(hunspell::BDictReader* reader, HashMgr* ptr) |
+AffixMgr::AffixMgr(hunspell::BDictReader* reader, HashMgr** ptr, int * md) |
{ |
bdict_reader = reader; |
#else |
-AffixMgr::AffixMgr(FILE* aff_handle, HashMgr* ptr) |
+AffixMgr::AffixMgr(FILE* aff_handle, HashMgr** ptr, int * md, const char * key) |
{ |
#endif |
// register hash manager and load affix data from aff file |
- pHMgr = ptr; |
+ pHMgr = ptr[0]; |
+ alldic = ptr; |
+ maxdic = md; |
+ keystring = NULL; |
trystring = NULL; |
encoding=NULL; |
utf8 = 0; |
@@ -45,10 +48,15 @@ |
numbreak = 0; |
reptable = NULL; |
numrep = 0; |
+ iconvtable = NULL; |
+ oconvtable = NULL; |
checkcpdtable = NULL; |
+ // allow simplified compound forms (see 3rd field of CHECKCOMPOUNDPATTERN) |
+ simplifiedcpd = 0; |
numcheckcpd = 0; |
defcpdtable = NULL; |
numdefcpd = 0; |
+ phone = NULL; |
compoundflag = FLAG_NULL; // permits word in compound forms |
compoundbegin = FLAG_NULL; // may be first word in compound forms |
compoundmiddle = FLAG_NULL; // may be middle word in compound forms |
@@ -60,11 +68,12 @@ |
checkcompoundrep = 0; // forbid bad compounds (may be non compound word with a REP substitution) |
checkcompoundcase = 0; // forbid upper and lowercase combinations at word bounds |
checkcompoundtriple = 0; // forbid compounds with triple letters |
- forbiddenword = FLAG_NULL; // forbidden word signing flag |
+ simplifiedtriple = 0; // allow simplified triple letters in compounds (Schiff+fahrt -> Schiffahrt) |
+ forbiddenword = FORBIDDENWORD; // forbidden word signing flag |
nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag |
lang = NULL; // language |
langnum = 0; // language code (see http://l10n.openoffice.org/languages.html) |
- pseudoroot = FLAG_NULL; // forbidden root, allowed only with suffixes |
+ needaffix = FLAG_NULL; // forbidden root, allowed only with suffixes |
cpdwordmax = -1; // default: unlimited wordcount in compound words |
cpdmin = -1; // undefined |
cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words |
@@ -88,14 +97,14 @@ |
lemma_present = FLAG_NULL; |
circumfix = FLAG_NULL; |
onlyincompound = FLAG_NULL; |
- flag_mode = FLAG_CHAR; // default one-character flags in affix and dic file |
maxngramsugs = -1; // undefined |
nosplitsugs = 0; |
sugswithdots = 0; |
keepcase = 0; |
checksharps = 0; |
+ substandard = FLAG_NULL; |
+ fullstrip = 0; |
- derived = NULL; // XXX not threadsafe variable for experimental stemming |
sfx = NULL; |
pfx = NULL; |
@@ -109,14 +118,14 @@ |
#ifdef HUNSPELL_CHROME_CLIENT |
if (parse_file()) { |
#else |
+ |
for (int j=0; j < CONTSIZE; j++) { |
contclasses[j] = 0; |
} |
- if (parse_file(aff_handle)) { |
+ if (parse_file(affpath, key)) { |
#endif |
HUNSPELL_WARNING(stderr, "Failure loading aff file\n"); |
- wordchars = mystrdup("qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"); |
} |
if (cpdmin == -1) cpdmin = MINCPDLEN; |
@@ -154,6 +163,8 @@ |
sStart[j] = NULL; |
} |
+ if (keystring) free(keystring); |
+ keystring=NULL; |
if (trystring) free(trystring); |
trystring=NULL; |
if (encoding) free(encoding); |
@@ -178,16 +189,26 @@ |
breaktable = NULL; |
} |
numbreak = 0; |
- if (reptable) { |
+ if (reptable) { |
for (int j=0; j < numrep; j++) { |
free(reptable[j].pattern); |
free(reptable[j].pattern2); |
- reptable[j].pattern = NULL; |
- reptable[j].pattern2 = NULL; |
} |
free(reptable); |
reptable = NULL; |
} |
+ if (iconvtable) delete iconvtable; |
+ if (oconvtable) delete oconvtable; |
+ if (phone && phone->rules) { |
+ for (int j=0; j < phone->num + 1; j++) { |
+ free(phone->rules[j * 2]); |
+ free(phone->rules[j * 2 + 1]); |
+ } |
+ free(phone->rules); |
+ free(phone); |
+ phone = NULL; |
+ } |
+ |
if (defcpdtable) { |
for (int j=0; j < numdefcpd; j++) { |
free(defcpdtable[j].def); |
@@ -201,8 +222,10 @@ |
for (int j=0; j < numcheckcpd; j++) { |
free(checkcpdtable[j].pattern); |
free(checkcpdtable[j].pattern2); |
+ free(checkcpdtable[j].pattern3); |
checkcpdtable[j].pattern = NULL; |
checkcpdtable[j].pattern2 = NULL; |
+ checkcpdtable[j].pattern3 = NULL; |
} |
free(checkcpdtable); |
checkcpdtable = NULL; |
@@ -217,7 +240,7 @@ |
FREE_FLAG(compoundroot); |
FREE_FLAG(forbiddenword); |
FREE_FLAG(nosuggest); |
- FREE_FLAG(pseudoroot); |
+ FREE_FLAG(needaffix); |
FREE_FLAG(lemma_present); |
FREE_FLAG(circumfix); |
FREE_FLAG(onlyincompound); |
@@ -236,30 +259,20 @@ |
if (ignorechars) free(ignorechars); |
if (ignorechars_utf16) free(ignorechars_utf16); |
if (version) free(version); |
- if (derived) free(derived); |
checknum=0; |
} |
// read in aff file and build up prefix and suffix entry objects |
#ifdef HUNSPELL_CHROME_CLIENT |
- // Hack to avoid having to comment out all the fclose calls below on errors. |
- #define fclose(a); |
- |
int AffixMgr::parse_file() |
#else |
-int AffixMgr::parse_file(FILE* aff_handle) |
+int AffixMgr::parse_file(FILE* aff_handle, const char * key) |
#endif |
{ |
- // io buffers |
- char line[MAXLNLEN+1]; |
- |
- // affix type |
- char ft; |
- |
- // first line indicator for removing byte order mark |
- int firstline = 1; |
- |
+ char * line = new char[MAXLNLEN+1]; // io buffers |
+ char ft; // affix type |
+ |
// open the affix file |
#ifdef HUNSPELL_CHROME_CLIENT |
// We're always UTF-8 |
@@ -286,44 +299,65 @@ |
char dupflags[CONTSIZE]; |
char dupflags_ini = 1; |
- FILE * afflst; |
- afflst = _fdopen(_dup(_fileno(aff_handle)), "r"); |
+ // first line indicator for removing byte order mark |
+ int firstline = 1; |
+ |
+ // open the affix file |
+ FileMgr * afflst = new FileMgr(affpath, key); |
if (!afflst) { |
- HUNSPELL_WARNING(stderr, "error: could not open affix description file\n"); |
+ HUNSPELL_WARNING(stderr, "error: could not open affix description file %s\n",affpath); |
return 1; |
} |
- fseek(afflst, 0, SEEK_SET); |
// step one is to parse the affix file building up the internal |
// affix data structures |
- |
// read in each line ignoring any that do not |
// start with a known line type indicator |
- while (fgets(line,MAXLNLEN,afflst)) { |
+ while ((line = afflst->getline())) { |
mychomp(line); |
/* remove byte order mark */ |
if (firstline) { |
firstline = 0; |
- if (strncmp(line,"\xef\xbb\xbf",3) == 0) { |
+ if (strncmp(line,"\xEF\xBB\xBF",3) == 0) { |
memmove(line, line+3, strlen(line+3)+1); |
HUNSPELL_WARNING(stderr, "warning: affix file begins with byte order mark: possible incompatibility with old Hunspell versions\n"); |
} |
} |
#endif |
+ /* parse in the keyboard string */ |
+ if (strncmp(line,"KEY",3) == 0) { |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_string(line, &keystring, 0)) { |
+#else |
+ if (parse_string(line, &keystring, afflst->getlinenum())) { |
+ delete afflst; |
+#endif |
+ return 1; |
+ } |
+ } |
+ |
/* parse in the try string */ |
if (strncmp(line,"TRY",3) == 0) { |
- if (parse_string(line, &trystring, "TRY")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_string(line, &trystring, 0)) { |
+#else |
+ if (parse_string(line, &trystring, afflst->getlinenum())) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the name of the character set used by the .dict and .aff */ |
if (strncmp(line,"SET",3) == 0) { |
- if (parse_string(line, &encoding, "SET")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_string(line, &encoding, 0)) { |
+#else |
+ if (parse_string(line, &encoding, afflst->getlinenum())) { |
+ delete afflst; |
+#endif |
return 1; |
} |
if (strcmp(encoding, "UTF-8") == 0) { |
@@ -342,8 +376,12 @@ |
/* parse in the flag used by the controlled compound words */ |
if (strncmp(line,"COMPOUNDFLAG",12) == 0) { |
- if (parse_flag(line, &compoundflag, "COMPOUNDFLAG")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &compoundflag)) { |
+#else |
+ if (parse_flag(line, &compoundflag, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
@@ -351,13 +389,21 @@ |
/* parse in the flag used by compound words */ |
if (strncmp(line,"COMPOUNDBEGIN",13) == 0) { |
if (complexprefixes) { |
- if (parse_flag(line, &compoundend, "COMPOUNDBEGIN")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &compoundend)) { |
+#else |
+ if (parse_flag(line, &compoundend, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} else { |
- if (parse_flag(line, &compoundbegin, "COMPOUNDBEGIN")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &compoundbegin)) { |
+#else |
+ if (parse_flag(line, &compoundbegin, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
@@ -365,21 +411,33 @@ |
/* parse in the flag used by compound words */ |
if (strncmp(line,"COMPOUNDMIDDLE",14) == 0) { |
- if (parse_flag(line, &compoundmiddle, "COMPOUNDMIDDLE")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &compoundmiddle)) { |
+#else |
+ if (parse_flag(line, &compoundmiddle, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the flag used by compound words */ |
if (strncmp(line,"COMPOUNDEND",11) == 0) { |
if (complexprefixes) { |
- if (parse_flag(line, &compoundbegin, "COMPOUNDEND")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &compoundbegin)) { |
+#else |
+ if (parse_flag(line, &compoundbegin, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} else { |
- if (parse_flag(line, &compoundend, "COMPOUNDEND")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &compoundend)) { |
+#else |
+ if (parse_flag(line, &compoundend, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
@@ -387,32 +445,48 @@ |
/* parse in the data used by compound_check() method */ |
if (strncmp(line,"COMPOUNDWORDMAX",15) == 0) { |
- if (parse_num(line, &cpdwordmax, "COMPOUNDWORDMAX")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_num(line, &cpdwordmax)) { |
+#else |
+ if (parse_num(line, &cpdwordmax, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the flag sign compounds in dictionary */ |
if (strncmp(line,"COMPOUNDROOT",12) == 0) { |
- if (parse_flag(line, &compoundroot, "COMPOUNDROOT")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &compoundroot)) { |
+#else |
+ if (parse_flag(line, &compoundroot, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the flag used by compound_check() method */ |
if (strncmp(line,"COMPOUNDPERMITFLAG",18) == 0) { |
- if (parse_flag(line, &compoundpermitflag, "COMPOUNDPERMITFLAG")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &compoundpermitflag)) { |
+#else |
+ if (parse_flag(line, &compoundpermitflag, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the flag used by compound_check() method */ |
if (strncmp(line,"COMPOUNDFORBIDFLAG",18) == 0) { |
- if (parse_flag(line, &compoundforbidflag, "COMPOUNDFORBIDFLAG")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &compoundforbidflag)) { |
+#else |
+ if (parse_flag(line, &compoundforbidflag, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
@@ -429,69 +503,105 @@ |
checkcompoundtriple = 1; |
} |
+ if (strncmp(line,"SIMPLIFIEDTRIPLE",16) == 0) { |
+ simplifiedtriple = 1; |
+ } |
+ |
if (strncmp(line,"CHECKCOMPOUNDCASE",17) == 0) { |
checkcompoundcase = 1; |
} |
if (strncmp(line,"NOSUGGEST",9) == 0) { |
- if (parse_flag(line, &nosuggest, "NOSUGGEST")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &nosuggest)) { |
+#else |
+ if (parse_flag(line, &nosuggest, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the flag used by forbidden words */ |
if (strncmp(line,"FORBIDDENWORD",13) == 0) { |
- if (parse_flag(line, &forbiddenword, "FORBIDDENWORD")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &forbiddenword)) { |
+#else |
+ if (parse_flag(line, &forbiddenword, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the flag used by forbidden words */ |
if (strncmp(line,"LEMMA_PRESENT",13) == 0) { |
- if (parse_flag(line, &lemma_present, "LEMMA_PRESENT")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &lemma_present)) { |
+#else |
+ if (parse_flag(line, &lemma_present, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the flag used by circumfixes */ |
if (strncmp(line,"CIRCUMFIX",9) == 0) { |
- if (parse_flag(line, &circumfix, "CIRCUMFIX")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &circumfix)) { |
+#else |
+ if (parse_flag(line, &circumfix, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the flag used by fogemorphemes */ |
if (strncmp(line,"ONLYINCOMPOUND",14) == 0) { |
- if (parse_flag(line, &onlyincompound, "ONLYINCOMPOUND")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &onlyincompound)) { |
+#else |
+ if (parse_flag(line, &onlyincompound, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
- /* parse in the flag used by `pseudoroots' */ |
+ /* parse in the flag used by `needaffixs' */ |
if (strncmp(line,"PSEUDOROOT",10) == 0) { |
- if (parse_flag(line, &pseudoroot, "PSEUDOROOT")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &needaffix)) { |
+#else |
+ if (parse_flag(line, &needaffix, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
- /* parse in the flag used by `pseudoroots' */ |
+ /* parse in the flag used by `needaffixs' */ |
if (strncmp(line,"NEEDAFFIX",9) == 0) { |
- if (parse_flag(line, &pseudoroot, "NEEDAFFIX")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &needaffix)) { |
+#else |
+ if (parse_flag(line, &needaffix, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the minimal length for words in compounds */ |
if (strncmp(line,"COMPOUNDMIN",11) == 0) { |
- if (parse_num(line, &cpdmin, "COMPOUNDMIN")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_num(line, &cpdmin)) { |
+#else |
+ if (parse_num(line, &cpdmin, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
if (cpdmin < 1) cpdmin = 1; |
@@ -499,16 +609,24 @@ |
/* parse in the max. words and syllables in compounds */ |
if (strncmp(line,"COMPOUNDSYLLABLE",16) == 0) { |
+#ifdef HUNSPELL_CHROME_CLIENT |
if (parse_cpdsyllable(line)) { |
- fclose(afflst); |
+#else |
+ if (parse_cpdsyllable(line, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the flag used by compound_check() method */ |
if (strncmp(line,"SYLLABLENUM",11) == 0) { |
- if (parse_string(line, &cpdsyllablenum, "SYLLABLENUM")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_string(line, &cpdsyllablenum, 0)) { |
+#else |
+ if (parse_string(line, &cpdsyllablenum, afflst->getlinenum())) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
@@ -520,34 +638,74 @@ |
/* parse in the extra word characters */ |
if (strncmp(line,"WORDCHARS",9) == 0) { |
- if (parse_array(line, &wordchars, &wordchars_utf16, &wordchars_utf16_len, "WORDCHARS", utf8)) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_array(line, &wordchars, &wordchars_utf16, &wordchars_utf16_len, utf8, 0)) { |
+#else |
+ if (parse_array(line, &wordchars, &wordchars_utf16, &wordchars_utf16_len, utf8, afflst->getlinenum())) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the ignored characters (for example, Arabic optional diacretics charachters */ |
if (strncmp(line,"IGNORE",6) == 0) { |
- if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, utf8, 0)) { |
+#else |
+ if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, utf8, afflst->getlinenum())) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
+#ifndef HUNSPELL_CHROME_CLIENT |
/* parse in the typical fault correcting table */ |
-#ifndef HUNSPELL_CHROME_CLIENT |
if (strncmp(line,"REP",3) == 0) { |
if (parse_reptable(line, afflst)) { |
- fclose(afflst); |
+ delete afflst; |
return 1; |
} |
} |
#endif |
+ /* parse in the input conversion table */ |
+ if (strncmp(line,"ICONV",5) == 0) { |
+ if (parse_convtable(line, afflst, &iconvtable, "ICONV")) { |
+#ifndef HUNSPELL_CHROME_CLIENT |
+ delete afflst; |
+#endif |
+ return 1; |
+ } |
+ } |
+ |
+ /* parse in the input conversion table */ |
+ if (strncmp(line,"OCONV",5) == 0) { |
+ if (parse_convtable(line, afflst, &oconvtable, "OCONV")) { |
+#ifndef HUNSPELL_CHROME_CLIENT |
+ delete afflst; |
+#endif |
+ return 1; |
+ } |
+ } |
+ |
+ /* parse in the phonetic translation table */ |
+ if (strncmp(line,"PHONE",5) == 0) { |
+ if (parse_phonetable(line, afflst)) { |
+#ifndef HUNSPELL_CHROME_CLIENT |
+ delete afflst; |
+#endif |
+ return 1; |
+ } |
+ } |
+ |
/* parse in the checkcompoundpattern table */ |
if (strncmp(line,"CHECKCOMPOUNDPATTERN",20) == 0) { |
if (parse_checkcpdtable(line, afflst)) { |
- fclose(afflst); |
+#ifndef HUNSPELL_CHROME_CLIENT |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
@@ -555,7 +713,9 @@ |
/* parse in the defcompound table */ |
if (strncmp(line,"COMPOUNDRULE",12) == 0) { |
if (parse_defcpdtable(line, afflst)) { |
- fclose(afflst); |
+#ifndef HUNSPELL_CHROME_CLIENT |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
@@ -563,7 +723,9 @@ |
/* parse in the related character map table */ |
if (strncmp(line,"MAP",3) == 0) { |
if (parse_maptable(line, afflst)) { |
- fclose(afflst); |
+#ifndef HUNSPELL_CHROME_CLIENT |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
@@ -571,30 +733,38 @@ |
/* parse in the word breakpoints table */ |
if (strncmp(line,"BREAK",5) == 0) { |
if (parse_breaktable(line, afflst)) { |
- fclose(afflst); |
+#ifndef HUNSPELL_CHROME_CLIENT |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
/* parse in the language for language specific codes */ |
if (strncmp(line,"LANG",4) == 0) { |
- if (parse_string(line, &lang, "LANG")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_string(line, &lang, 0)) { |
+#else |
+ if (parse_string(line, &lang, afflst->getlinenum())) { |
+ delete afflst; |
+#endif |
return 1; |
} |
langnum = get_lang_num(lang); |
} |
if (strncmp(line,"VERSION",7) == 0) { |
- if (parse_string(line, &version, "VERSION")) { |
- fclose(afflst); |
- return 1; |
- } |
+ for(line = line + 7; *line == ' ' || *line == '\t'; line++); |
+ version = mystrdup(line); |
} |
if (strncmp(line,"MAXNGRAMSUGS",12) == 0) { |
- if (parse_num(line, &maxngramsugs, "MAXNGRAMSUGS")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_num(line, &maxngramsugs)) { |
+#else |
+ if (parse_num(line, &maxngramsugs, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
@@ -603,18 +773,38 @@ |
nosplitsugs=1; |
} |
+ if (strncmp(line,"FULLSTRIP",9) == 0) { |
+ fullstrip=1; |
+ } |
+ |
if (strncmp(line,"SUGSWITHDOTS",12) == 0) { |
sugswithdots=1; |
} |
/* parse in the flag used by forbidden words */ |
if (strncmp(line,"KEEPCASE",8) == 0) { |
- if (parse_flag(line, &keepcase, "KEEPCASE")) { |
- fclose(afflst); |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &keepcase)) { |
+#else |
+ if (parse_flag(line, &keepcase, afflst)) { |
+ delete afflst; |
+#endif |
return 1; |
} |
} |
+ /* parse in the flag used by the affix generator */ |
+ if (strncmp(line,"SUBSTANDARD",11) == 0) { |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (parse_flag(line, &substandard)) { |
+#else |
+ if (parse_flag(line, &substandard, afflst)) { |
+ delete afflst; |
+#endif |
+ return 1; |
+ } |
+ } |
+ |
if (strncmp(line,"CHECKSHARPS",11) == 0) { |
checksharps=1; |
} |
@@ -630,7 +820,7 @@ |
dupflags_ini = 0; |
} |
if (parse_affix(line, ft, afflst, dupflags)) { |
- fclose(afflst); |
+ delete afflst; |
process_pfx_tree_to_list(); |
process_sfx_tree_to_list(); |
return 1; |
@@ -640,7 +830,7 @@ |
} |
#ifndef HUNSPELL_CHROME_CLIENT |
- fclose(afflst); |
+ delete afflst; |
#endif |
// convert affix trees to sorted list |
@@ -673,8 +863,8 @@ |
process_pfx_order(); |
process_sfx_order(); |
- // expand wordchars string, based on csutil (for external tokenization) |
- |
+ /* get encoding for CHECKCOMPOUNDCASE */ |
+ if (!utf8) { |
char * enc = get_encoding(); |
csconv = get_current_cs(enc); |
free(enc); |
@@ -695,16 +885,20 @@ |
} |
wordchars = mystrdup(expw); |
+ } |
- // temporary BREAK definition for German dash handling (OOo issue 64400) |
- if ((langnum == LANG_de) && (!breaktable)) { |
- breaktable = (char **) malloc(sizeof(char *)); |
+ // default BREAK definition |
+ if (!breaktable) { |
+ breaktable = (char **) malloc(sizeof(char *) * 3); |
if (!breaktable) return 1; |
breaktable[0] = mystrdup("-"); |
- numbreak = 1; |
+ breaktable[1] = mystrdup("^-"); |
+ breaktable[2] = mystrdup("-$"); |
+ if (breaktable[0] && breaktable[1] && breaktable[2]) numbreak = 3; |
} |
return 0; |
} |
+ |
#ifdef HUNSPELL_CHROME_CLIENT |
#undef fclose |
#endif |
@@ -977,197 +1171,52 @@ |
return 0; |
} |
+// add flags to the result for dictionary debugging |
+void AffixMgr::debugflag(char * result, unsigned short flag) { |
+ char * st = encode_flag(flag); |
+ mystrcat(result, " ", MAXLNLEN); |
+ mystrcat(result, MORPH_FLAG, MAXLNLEN); |
+ if (st) { |
+ mystrcat(result, st, MAXLNLEN); |
+ free(st); |
+ } |
+} |
+// calculate the character length of the condition |
+int AffixMgr::condlen(char * st) |
+{ |
+ int l = 0; |
+ bool group = false; |
+ for(; *st; st++) { |
+ if (*st == '[') { |
+ group = true; |
+ l++; |
+ } else if (*st == ']') group = false; |
+ else if (!group && (!utf8 || |
+ (!(*st & 0x80) || ((*st & 0xc0) == 0x80)))) l++; |
+ } |
+ return l; |
+} |
-// takes aff file condition string and creates the |
-// conds array - please see the appendix at the end of the |
-// file affentry.cxx which describes what is going on here |
-// in much more detail |
- |
int AffixMgr::encodeit(struct affentry * ptr, char * cs) |
{ |
- unsigned char c; |
- int i, j, k; |
- unsigned char mbr[MAXLNLEN]; |
- w_char wmbr[MAXLNLEN]; |
- w_char * wpos = wmbr; |
- |
- // now clear the conditions array */ |
- for (i=0;i<SETSIZE;i++) ptr->conds.base[i] = (unsigned char) 0; |
- |
- // now parse the string to create the conds array */ |
- int nc = strlen(cs); |
- unsigned char neg = 0; // complement indicator |
- int grp = 0; // group indicator |
- unsigned char n = 0; // number of conditions |
- int ec = 0; // end condition indicator |
- int nm = 0; // number of member in group |
- |
- // if no condition just return |
- if (strcmp(cs,".")==0) { |
+ if (strcmp(cs,".") != 0) { |
+ ptr->numconds = (char) condlen(cs); |
+ strncpy(ptr->c.conds, cs, MAXCONDLEN); |
+ // long condition (end of conds padded by strncpy) |
+ if (ptr->c.conds[MAXCONDLEN - 1] && cs[MAXCONDLEN]) { |
+ ptr->opts += aeLONGCOND; |
+ ptr->c.l.conds2 = mystrdup(cs + MAXCONDLEN_1); |
+ if (!ptr->c.l.conds2) return 1; |
+ } |
+ } else { |
ptr->numconds = 0; |
- return 0; |
+ ptr->c.conds[0] = '\0'; |
} |
- |
- i = 0; |
- while (i < nc) { |
- c = *((unsigned char *)(cs + i)); |
- |
- // start group indicator |
- if (c == '[') { |
- grp = 1; |
- c = 0; |
- } |
- |
- // complement flag |
- if ((grp == 1) && (c == '^')) { |
- neg = 1; |
- c = 0; |
- } |
- |
- // end goup indicator |
- if (c == ']') { |
- ec = 1; |
- c = 0; |
- } |
- |
- // add character of group to list |
- if ((grp == 1) && (c != 0)) { |
- *(mbr + nm) = c; |
- nm++; |
- c = 0; |
- } |
- |
- // end of condition |
- if (c != 0) { |
- ec = 1; |
- } |
- |
- if (ec) { |
- if (!utf8) { |
- if (grp == 1) { |
- if (neg == 0) { |
- // set the proper bits in the condition array vals for those chars |
- for (j=0;j<nm;j++) { |
- k = (unsigned int) mbr[j]; |
- ptr->conds.base[k] = ptr->conds.base[k] | ((unsigned char)1 << n); |
- } |
- } else { |
- // complement so set all of them and then unset indicated ones |
- for (j=0;j<SETSIZE;j++) ptr->conds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n); |
- for (j=0;j<nm;j++) { |
- k = (unsigned int) mbr[j]; |
- ptr->conds.base[k] = ptr->conds.base[k] & ~((unsigned char)1 << n); |
- } |
- } |
- neg = 0; |
- grp = 0; |
- nm = 0; |
- } else { |
- // not a group so just set the proper bit for this char |
- // but first handle special case of . inside condition |
- if (c == '.') { |
- // wild card character so set them all |
- for (j=0;j<SETSIZE;j++) ptr->conds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n); |
- } else { |
- ptr->conds.base[(unsigned int) c] = ptr->conds.base[(unsigned int)c] | ((unsigned char)1 << n); |
- } |
- } |
- n++; |
- ec = 0; |
- } else { // UTF-8 character set |
- if (grp == 1) { |
- ptr->conds.utf8.neg[n] = neg; |
- if (neg == 0) { |
- // set the proper bits in the condition array vals for those chars |
- for (j=0;j<nm;j++) { |
- k = (unsigned int) mbr[j]; |
- if (k >> 7) { |
- u8_u16(wpos, 1, (char *) mbr + j); |
- wpos++; |
- if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character |
- } else { |
- ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] | ((unsigned char)1 << n); |
- } |
- } |
- } else { // neg == 1 |
- // complement so set all of them and then unset indicated ones |
- for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n); |
- for (j=0;j<nm;j++) { |
- k = (unsigned int) mbr[j]; |
- if (k >> 7) { |
- u8_u16(wpos, 1, (char *) mbr + j); |
- wpos++; |
- if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character |
- } else { |
- ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] & ~((unsigned char)1 << n); |
- } |
- } |
- } |
- neg = 0; |
- grp = 0; |
- nm = 0; |
- ptr->conds.utf8.wlen[n] = wpos - wmbr; |
- if ((wpos - wmbr) != 0) { |
- ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char) * (wpos - wmbr)); |
- if (!ptr->conds.utf8.wchars[n]) return 1; |
- memcpy(ptr->conds.utf8.wchars[n], wmbr, sizeof(w_char) * (wpos - wmbr)); |
- flag_qsort((unsigned short *) ptr->conds.utf8.wchars[n], 0, ptr->conds.utf8.wlen[n]); |
- wpos = wmbr; |
- } |
- } else { // grp == 0 |
- // is UTF-8 character? |
- if (c >> 7) { |
- ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char)); |
- if (!ptr->conds.utf8.wchars[n]) return 1; |
- ptr->conds.utf8.wlen[n] = 1; |
- u8_u16(ptr->conds.utf8.wchars[n], 1, cs + i); |
- if ((c & 0xe0) == 0xe0) i+=2; else i++; // 3-byte UFT-8 character |
- } else { |
- ptr->conds.utf8.wchars[n] = NULL; |
- // not a group so just set the proper bit for this char |
- // but first handle special case of . inside condition |
- if (c == '.') { |
- ptr->conds.utf8.all[n] = 1; |
- // wild card character so set them all |
- for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n); |
- } else { |
- ptr->conds.utf8.all[n] = 0; |
- ptr->conds.utf8.ascii[(unsigned int) c] = ptr->conds.utf8.ascii[(unsigned int)c] | ((unsigned char)1 << n); |
- } |
- } |
- neg = 0; |
- } |
- n++; |
- if (n > 8) { |
- HUNSPELL_WARNING(stderr, "Number of conditions is larger than 8. This" |
- "version of Hunspell does not support more than 8 conditions." |
- "Please, get rid of affentries with more than 8 conditions."); |
- break; |
- } |
- ec = 0; |
- neg = 0; |
- } |
- } |
- |
- i++; |
- } |
- ptr->numconds = n; |
return 0; |
} |
- // return 1 if s1 is a leading subset of s2 |
-/* inline int AffixMgr::isSubset(const char * s1, const char * s2) |
- { |
- while ((*s1 == *s2) && *s1) { |
- s1++; |
- s2++; |
- } |
- return (*s1 == '\0'); |
- } |
-*/ |
- |
- // return 1 if s1 is a leading subset of s2 (dots are for infixes) |
+// return 1 if s1 is a leading subset of s2 (dots are for infixes) |
inline int AffixMgr::isSubset(const char * s1, const char * s2) |
{ |
while (((*s1 == *s2) || (*s1 == '.')) && (*s1 != '\0')) { |
@@ -1277,7 +1326,6 @@ |
return NULL; |
} |
-#ifdef HUNSPELL_EXPERIMENTAL |
// check word for prefixes |
char * AffixMgr::prefix_check_morph(const char * word, int len, char in_compound, |
const FLAG needflag) |
@@ -1295,7 +1343,7 @@ |
while (pe) { |
st = pe->check_morph(word,len,in_compound, needflag); |
if (st) { |
- strcat(result, st); |
+ mystrcat(result, st, MAXLNLEN); |
free(st); |
} |
// if (rv) return rv; |
@@ -1313,7 +1361,7 @@ |
// fogemorpheme |
if ((in_compound != IN_CPD_NOT) || !((pptr->getCont() && |
(TESTAFF(pptr->getCont(), onlyincompound, pptr->getContLen()))))) { |
- strcat(result, st); |
+ mystrcat(result, st, MAXLNLEN); |
pfx = (AffEntry *)pptr; |
} |
free(st); |
@@ -1346,7 +1394,7 @@ |
while (pe) { |
st = pe->check_twosfx_morph(word,len,in_compound, needflag); |
if (st) { |
- strcat(result, st); |
+ mystrcat(result, st, MAXLNLEN); |
free(st); |
} |
pe = pe->getNext(); |
@@ -1360,7 +1408,7 @@ |
if (isSubset(pptr->getKey(),word)) { |
st = pptr->check_twosfx_morph(word, len, in_compound, needflag); |
if (st) { |
- strcat(result, st); |
+ mystrcat(result, st, MAXLNLEN); |
free(st); |
pfx = (AffEntry *)pptr; |
} |
@@ -1373,9 +1421,7 @@ |
if (*result) return mystrdup(result); |
return NULL; |
} |
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE |
- |
// Is word a non compound with a REP substitution (see checkcompoundrep)? |
int AffixMgr::cpdrep_check(const char * word, int wl) |
{ |
@@ -1424,11 +1470,15 @@ |
} |
// forbid compoundings when there are special patterns at word bound |
-int AffixMgr::cpdpat_check(const char * word, int pos) |
+int AffixMgr::cpdpat_check(const char * word, int pos, hentry * r1, hentry * r2) |
{ |
int len; |
for (int i = 0; i < numcheckcpd; i++) { |
if (isSubset(checkcpdtable[i].pattern2, word + pos) && |
+ (!r1 || !checkcpdtable[i].cond || |
+ (r1->astr && TESTAFF(r1->astr, checkcpdtable[i].cond, r1->alen))) && |
+ (!r2 || !checkcpdtable[i].cond2 || |
+ (r2->astr && TESTAFF(r2->astr, checkcpdtable[i].cond2, r2->alen))) && |
(len = strlen(checkcpdtable[i].pattern)) && (pos > len) && |
(strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)) return 1; |
} |
@@ -1446,10 +1496,8 @@ |
u8_u16(&w, 1, p); |
unsigned short a = (u.h << 8) + u.l; |
unsigned short b = (w.h << 8) + w.l; |
- // CHROME MODIFICATION: We add the checks for the dashes as they are used |
- // below in the non-UTF-8 case. This seems to be a bug in Hunspell. It |
- // causes some of the tests to fail since we convert everything to UTF-8. |
- if (((unicodetoupper(a, langnum) == a) || (unicodetoupper(b, langnum) == b)) && (a != '-') && (b != '-')) return 1; |
+ if (((unicodetoupper(a, langnum) == a) || (unicodetoupper(b, langnum) == b)) && |
+ (a != '-') && (b != '-')) return 1; |
} else { |
unsigned char a = *(word + pos - 1); |
unsigned char b = *(word + pos); |
@@ -1465,16 +1513,36 @@ |
signed short btwp[MAXWORDLEN]; // word positions for metacharacters |
int btnum[MAXWORDLEN]; // number of matched characters in metacharacter positions |
short bt = 0; |
- int i; |
+ int i, j; |
int ok; |
int w = 0; |
+ |
if (!*words) { |
w = 1; |
*words = def; |
} |
(*words)[wnum] = rv; |
+ // has the last word COMPOUNDRULE flag? |
+ if (rv->alen == 0) { |
+ (*words)[wnum] = NULL; |
+ if (w) *words = NULL; |
+ return 0; |
+ } |
+ ok = 0; |
for (i = 0; i < numdefcpd; i++) { |
+ for (j = 0; j < defcpdtable[i].len; j++) { |
+ if (defcpdtable[i].def[j] != '*' && defcpdtable[i].def[j] != '?' && |
+ TESTAFF(rv->astr, defcpdtable[i].def[j], rv->alen)) ok = 1; |
+ } |
+ } |
+ if (ok == 0) { |
+ (*words)[wnum] = NULL; |
+ if (w) *words = NULL; |
+ return 0; |
+ } |
+ |
+ for (i = 0; i < numdefcpd; i++) { |
signed short pp = 0; // pattern position |
signed short wp = 0; // "words" position |
int ok2; |
@@ -1518,17 +1586,18 @@ |
while ((defcpdtable[i].len > r) && ((r+1) < defcpdtable[i].len) && |
((defcpdtable[i].def[r+1] == '*') || (defcpdtable[i].def[r+1] == '?'))) r+=2; |
if (defcpdtable[i].len <= r) return 1; |
- } |
+ } |
// backtrack |
if (bt) do { |
ok = 1; |
btnum[bt - 1]--; |
pp = btpp[bt - 1]; |
- wp = btwp[bt - 1] + btnum[bt - 1]; |
+ wp = btwp[bt - 1] + (signed short) btnum[bt - 1]; |
} while ((btnum[bt - 1] < 0) && --bt); |
} while (bt); |
- if (ok && ok2 && (!all || (defcpdtable[i].len <= pp))) return 1; |
+ if (ok && ok2 && (!all || (defcpdtable[i].len <= pp))) return 1; |
+ |
// check zero ending |
while (ok && ok2 && (defcpdtable[i].len > pp) && ((pp+1) < defcpdtable[i].len) && |
((defcpdtable[i].def[pp+1] == '*') || (defcpdtable[i].def[pp+1] == '?'))) pp+=2; |
@@ -1568,7 +1637,7 @@ |
} else if (cpdvowels_utf16) { |
w_char w[MAXWORDUTF8LEN]; |
int i = u8_u16(w, MAXWORDUTF8LEN, word); |
- for (; i; i--) { |
+ for (; i > 0; i--) { |
if (flag_bsearch((unsigned short *) cpdvowels_utf16, |
((unsigned short *) w)[i - 1], cpdvowels_utf16_len)) num++; |
} |
@@ -1576,15 +1645,29 @@ |
return num; |
} |
+void AffixMgr::setcminmax(int * cmin, int * cmax, const char * word, int len) { |
+ if (utf8) { |
+ int i; |
+ for (*cmin = 0, i = 0; (i < cpdmin) && word[*cmin]; i++) { |
+ for ((*cmin)++; (word[*cmin] & 0xc0) == 0x80; (*cmin)++); |
+ } |
+ for (*cmax = len, i = 0; (i < (cpdmin - 1)) && *cmax; i++) { |
+ for ((*cmax)--; (word[*cmax] & 0xc0) == 0x80; (*cmax)--); |
+ } |
+ } else { |
+ *cmin = cpdmin; |
+ *cmax = len - cpdmin + 1; |
+ } |
+} |
+ |
// check if compound word is correctly spelled |
// hu_mov_rule = spec. Hungarian rule (XXX) |
struct hentry * AffixMgr::compound_check(const char * word, int len, |
short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL, |
- char hu_mov_rule = 0, int * cmpdstemnum = NULL, int * cmpdstem = NULL, char is_sug = 0) |
+ char hu_mov_rule = 0, char is_sug = 0) |
{ |
int i; |
short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2; |
- int oldcmpdstemnum = 0; |
struct hentry * rv = NULL; |
struct hentry * rv_first; |
struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking |
@@ -1592,31 +1675,17 @@ |
char ch; |
int cmin; |
int cmax; |
- |
+ int striple = 0; |
+ int scpd = 0; |
+ int soldi = 0; |
+ int oldcmin = 0; |
+ int oldcmax = 0; |
+ int oldlen = 0; |
+ int checkedstriple = 0; |
+ |
int checked_prefix; |
-#ifdef HUNSTEM |
- if (cmpdstemnum) { |
- if (wordnum == 0) { |
- *cmpdstemnum = 1; |
- } else { |
- (*cmpdstemnum)++; |
- } |
- } |
-#endif |
- if (utf8) { |
- for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) { |
- cmin++; |
- for (; (word[cmin] & 0xc0) == 0x80; cmin++); |
- } |
- for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) { |
- cmax--; |
- for (; (word[cmax] & 0xc0) == 0x80; cmax--); |
- } |
- } else { |
- cmin = cpdmin; |
- cmax = len - cpdmin + 1; |
- } |
+ setcminmax(&cmin, &cmax, word, len); |
strcpy(st, word); |
@@ -1632,20 +1701,42 @@ |
if (i >= cmax) return NULL; |
} |
- |
+ do { // simplified checkcompoundpattern loop |
+ |
+ if (scpd > 0) { |
+ for (; scpd <= numcheckcpd && (!checkcpdtable[scpd-1].pattern3 || |
+ strncmp(word + i, checkcpdtable[scpd-1].pattern3, strlen(checkcpdtable[scpd-1].pattern3)) != 0); scpd++); |
+ |
+ if (scpd > numcheckcpd) break; // break simplified checkcompoundpattern loop |
+ strcpy(st + i, checkcpdtable[scpd-1].pattern); |
+ soldi = i; |
+ i += strlen(checkcpdtable[scpd-1].pattern); |
+ strcpy(st + i, checkcpdtable[scpd-1].pattern2); |
+ strcpy(st + i + strlen(checkcpdtable[scpd-1].pattern2), word + soldi + strlen(checkcpdtable[scpd-1].pattern3)); |
+ |
+ oldlen = len; |
+ len += strlen(checkcpdtable[scpd-1].pattern) + strlen(checkcpdtable[scpd-1].pattern2) - strlen(checkcpdtable[scpd-1].pattern3); |
+ oldcmin = cmin; |
+ oldcmax = cmax; |
+ setcminmax(&cmin, &cmax, st, len); |
+ |
+ cmax = len - cpdmin + 1; |
+ } |
+ |
+ |
ch = st[i]; |
st[i] = '\0'; |
sfx = NULL; |
pfx = NULL; |
- |
+ |
// FIRST WORD |
- |
+ |
rv = lookup(st); // perhaps without prefix |
// search homonym with compound flag |
while ((rv) && !hu_mov_rule && |
- ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) || |
+ ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || |
!((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || |
(compoundbegin && !wordnum && |
TESTAFF(rv->astr, compoundbegin, rv->alen)) || |
@@ -1653,8 +1744,10 @@ |
TESTAFF(rv->astr, compoundmiddle, rv->alen)) || |
(numdefcpd && |
((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) || |
- (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)))) |
- ))) { |
+ (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))) || |
+ (scpd != 0 && checkcpdtable[scpd-1].cond != FLAG_NULL && |
+ !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond, rv->alen))) |
+ ) { |
rv = rv->next_homonym; |
} |
@@ -1671,6 +1764,7 @@ |
rv = NULL; |
} |
} |
+ |
if (rv || |
(((wordnum == 0) && compoundbegin && |
((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || |
@@ -1679,9 +1773,9 @@ |
((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || |
(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle))))) |
) checked_prefix = 1; |
- // else check forbiddenwords and pseudoroot |
+ // else check forbiddenwords and needaffix |
} else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) || |
- TESTAFF(rv->astr, pseudoroot, rv->alen) || |
+ TESTAFF(rv->astr, needaffix, rv->alen) || |
(is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)) |
)) { |
st[i] = ch; |
@@ -1709,7 +1803,7 @@ |
((SfxEntry*)sfx)->getContLen())))) { |
rv = NULL; |
} |
- |
+ |
// check compoundmiddle flag in suffix and prefix |
if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle && !hu_mov_rule && |
((pfx && ((PfxEntry*)pfx)->getCont() && |
@@ -1719,7 +1813,7 @@ |
TESTAFF(((SfxEntry*)sfx)->getCont(), compoundmiddle, |
((SfxEntry*)sfx)->getContLen())))) { |
rv = NULL; |
- } |
+ } |
// check forbiddenwords |
if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) || |
@@ -1749,19 +1843,20 @@ |
) |
) |
// END of LANG_hu section |
+ ) && |
+ ( |
+ // test CHECKCOMPOUNDPATTERN conditions |
+ scpd == 0 || checkcpdtable[scpd-1].cond == FLAG_NULL || |
+ TESTAFF(rv->astr, checkcpdtable[scpd-1].cond, rv->alen) |
) |
- && ! (( checkcompoundtriple && // test triple letters |
+ && ! (( checkcompoundtriple && scpd == 0 && !words && // test triple letters |
(word[i-1]==word[i]) && ( |
- ((i>1) && (word[i-1]==word[i-2])) || |
+ ((i>1) && (word[i-1]==word[i-2])) || |
((word[i-1]==word[i+1])) // may be word[i+1] == '\0' |
) |
) || |
- ( |
- // test CHECKCOMPOUNDPATTERN |
- numcheckcpd && cpdpat_check(word, i) |
- ) || |
- ( |
- checkcompoundcase && cpdcase_check(word, i) |
+ ( |
+ checkcompoundcase && scpd == 0 && !words && cpdcase_check(word, i) |
)) |
) |
// LANG_hu section: spec. Hungarian rule |
@@ -1769,15 +1864,14 @@ |
(sfx && ((SfxEntry*)sfx)->getCont() && ( // XXX hardwired Hungarian dic. codes |
TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) 'x', ((SfxEntry*)sfx)->getContLen()) || |
TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) '%', ((SfxEntry*)sfx)->getContLen()) |
- ) |
+ ) |
) |
) |
-// END of LANG_hu section |
- ) { |
+ ) { // first word is ok condition |
// LANG_hu section: spec. Hungarian rule |
if (langnum == LANG_hu) { |
- // calculate syllable number of the word |
+ // calculate syllable number of the word |
numsyllable += get_syllable(st, i); |
// + 1 word, if syllable number of the prefix > 1 (hungarian convention) |
@@ -1785,23 +1879,35 @@ |
} |
// END of LANG_hu section |
-#ifdef HUNSTEM |
- if (cmpdstem) cmpdstem[*cmpdstemnum - 1] = i; |
-#endif |
// NEXT WORD(S) |
rv_first = rv; |
- rv = lookup((word+i)); // perhaps without prefix |
+ st[i] = ch; |
+ do { // striple loop |
+ |
+ // check simplifiedtriple |
+ if (simplifiedtriple) { |
+ if (striple) { |
+ checkedstriple = 1; |
+ i--; // check "fahrt" instead of "ahrt" in "Schiffahrt" |
+ } else if (i > 2 && *(word+i - 1) == *(word + i - 2)) striple = 1; |
+ } |
+ |
+ rv = lookup((st+i)); // perhaps without prefix |
+ |
// search homonym with compound flag |
- while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) || |
+ while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || |
!((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || |
(compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) || |
- (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))))) { |
+ (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))) || |
+ (scpd != 0 && checkcpdtable[scpd-1].cond2 != FLAG_NULL && |
+ !TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen)) |
+ )) { |
rv = rv->next_homonym; |
} |
- if (rv && words && words[wnum + 1]) return rv; |
+ if (rv && words && words[wnum + 1]) return rv_first; |
oldnumsyllable2 = numsyllable; |
oldwordnum2 = wordnum; |
@@ -1833,20 +1939,27 @@ |
) |
&& ( |
((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || |
- ((cpdmaxsyllable==0) || |
- (numsyllable + get_syllable(rv->word,rv->wlen)<=cpdmaxsyllable)) |
- ) |
- && ( |
+ ((cpdmaxsyllable!=0) && |
+ (numsyllable + get_syllable(HENTRY_WORD(rv), rv->clen)<=cpdmaxsyllable)) |
+ ) && |
+ ( |
+ // test CHECKCOMPOUNDPATTERN |
+ !numcheckcpd || scpd != 0 || !cpdpat_check(word, i, rv_first, rv) |
+ ) && |
+ ( |
(!checkcompounddup || (rv != rv_first)) |
) |
+ // test CHECKCOMPOUNDPATTERN conditions |
+ && (scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL || |
+ TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen)) |
) |
{ |
// forbid compound word, if it is a non compound word with typical fault |
if (checkcompoundrep && cpdrep_check(word,len)) return NULL; |
- return rv; |
+ return rv_first; |
} |
- numsyllable = oldnumsyllable2 ; |
+ numsyllable = oldnumsyllable2; |
wordnum = oldwordnum2; |
// perhaps second word has prefix or/and suffix |
@@ -1858,12 +1971,20 @@ |
pfx = NULL; |
rv = affix_check((word+i),strlen(word+i), compoundend, IN_CPD_END); |
} |
- |
+ |
if (!rv && numdefcpd && words) { |
rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END); |
- if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv; |
+ if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv_first; |
+ rv = NULL; |
} |
+ // test CHECKCOMPOUNDPATTERN conditions (allowed forms) |
+ if (rv && !(scpd == 0 || checkcpdtable[scpd-1].cond2 == FLAG_NULL || |
+ TESTAFF(rv->astr, checkcpdtable[scpd-1].cond2, rv->alen))) rv = NULL; |
+ |
+ // test CHECKCOMPOUNDPATTERN conditions (forbidden compounds) |
+ if (rv && numcheckcpd && scpd == 0 && cpdpat_check(word, i, rv_first, rv)) rv = NULL; |
+ |
// check non_compound flag in suffix and prefix |
if ((rv) && |
((pfx && ((PfxEntry*)pfx)->getCont() && |
@@ -1887,7 +2008,7 @@ |
if (langnum == LANG_hu) { |
// calculate syllable number of the word |
numsyllable += get_syllable(word + i, strlen(word + i)); |
- |
+ |
// - affix syllable num. |
// XXX only second suffix (inflections, not derivations) |
if (sfxappnd) { |
@@ -1895,13 +2016,13 @@ |
numsyllable -= get_syllable(tmp, strlen(tmp)); |
free(tmp); |
} |
- |
+ |
// + 1 word, if syllable number of the prefix > 1 (hungarian convention) |
if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++; |
// increment syllable num, if last word has a SYLLABLENUM flag |
// and the suffix is beginning `s' |
- |
+ |
if (cpdsyllablenum) { |
switch (sfxflag) { |
case 'c': { numsyllable+=2; break; } |
@@ -1910,7 +2031,7 @@ |
} |
} |
} |
- |
+ |
// increment word number, if the second word has a compoundroot flag |
if ((rv) && (compoundroot) && |
(TESTAFF(rv->astr, compoundroot, rv->alen))) { |
@@ -1924,7 +2045,7 @@ |
if ((rv) && |
( |
((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) || |
- ((cpdmaxsyllable == 0) || |
+ ((cpdmaxsyllable != 0) && |
(numsyllable <= cpdmaxsyllable)) |
) |
&& ( |
@@ -1932,41 +2053,61 @@ |
)) { |
// forbid compound word, if it is a non compound word with typical fault |
if (checkcompoundrep && cpdrep_check(word, len)) return NULL; |
- return rv; |
+ return rv_first; |
} |
numsyllable = oldnumsyllable2; |
wordnum = oldwordnum2; |
-#ifdef HUNSTEM |
- if (cmpdstemnum) oldcmpdstemnum = *cmpdstemnum; |
-#endif |
+ |
// perhaps second word is a compound word (recursive call) |
if (wordnum < maxwordnum) { |
- rv = compound_check((word+i),strlen(word+i), wordnum+1, |
- numsyllable, maxwordnum, wnum + 1, words, |
- 0, cmpdstemnum, cmpdstem, is_sug); |
+ rv = compound_check((st+i),strlen(st+i), wordnum+1, |
+ numsyllable, maxwordnum, wnum + 1, words, 0, is_sug); |
+ if (rv && numcheckcpd && (scpd == 0 && cpdpat_check(word, i, rv_first, rv) || |
+ scpd != 0 && !cpdpat_check(word, i, rv_first, rv))) rv = NULL; |
} else { |
rv=NULL; |
} |
if (rv) { |
// forbid compound word, if it is a non compound word with typical fault |
if (checkcompoundrep && cpdrep_check(word, len)) return NULL; |
- return rv; |
- } else { |
-#ifdef HUNSTEM |
- if (cmpdstemnum) *cmpdstemnum = oldcmpdstemnum; |
-#endif |
+ return rv_first; |
} |
+ } while (striple && !checkedstriple); // end of striple loop |
+ |
+ if (checkedstriple) { |
+ i++; |
+ checkedstriple = 0; |
+ striple = 0; |
+ } |
+ |
+ } // first word is ok condition |
+ |
+ if (soldi != 0) { |
+ i = soldi; |
+ soldi = 0; |
+ len = oldlen; |
+ cmin = oldcmin; |
+ cmax = oldcmax; |
} |
- st[i] = ch; |
+ scpd++; |
+ |
+ } while (simplifiedcpd && scpd <= numcheckcpd); // end of simplifiedcpd loop |
+ |
+ if (soldi != 0) { |
+ i = soldi; |
+ strcpy(st, word); // XXX add more optim. |
+ soldi = 0; |
+ } else st[i] = ch; |
+ |
+ scpd = 0; |
wordnum = oldwordnum; |
numsyllable = oldnumsyllable; |
} |
- |
+ |
return NULL; |
-} |
+} |
-#ifdef HUNSPELL_EXPERIMENTAL |
// check if compound word is correctly spelled |
// hu_mov_rule = spec. Hungarian rule (XXX) |
int AffixMgr::compound_check_morph(const char * word, int len, |
@@ -1982,27 +2123,15 @@ |
struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking |
char st [MAXWORDUTF8LEN + 4]; |
char ch; |
- |
+ |
int checked_prefix; |
char presult[MAXLNLEN]; |
int cmin; |
int cmax; |
- |
- if (utf8) { |
- for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) { |
- cmin++; |
- for (; (word[cmin] & 0xc0) == 0x80; cmin++); |
- } |
- for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) { |
- cmax--; |
- for (; (word[cmax] & 0xc0) == 0x80; cmax--); |
- } |
- } else { |
- cmin = cpdmin; |
- cmax = len - cpdmin + 1; |
- } |
+ setcminmax(&cmin, &cmax, word, len); |
+ |
strcpy(st, word); |
for (i = cmin; i < cmax; i++) { |
@@ -2015,7 +2144,7 @@ |
for (; (st[i] & 0xc0) == 0x80; i++); |
if (i >= cmax) return 0; |
} |
- |
+ |
ch = st[i]; |
st[i] = '\0'; |
sfx = NULL; |
@@ -2023,12 +2152,12 @@ |
// FIRST WORD |
*presult = '\0'; |
if (partresult) strcat(presult, partresult); |
- |
+ |
rv = lookup(st); // perhaps without prefix |
// search homonym with compound flag |
while ((rv) && !hu_mov_rule && |
- ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) || |
+ ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || |
!((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || |
(compoundbegin && !wordnum && |
TESTAFF(rv->astr, compoundbegin, rv->alen)) || |
@@ -2042,13 +2171,16 @@ |
} |
if (rv) { |
- if (rv->description) { |
- if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen)) |
- strcat(presult, st); |
- strcat(presult, rv->description); |
+ sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_PART, st); |
+ if (!HENTRY_FIND(rv, MORPH_STEM)) { |
+ sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_STEM, st); |
} |
- } |
- |
+ // store the pointer of the hash entry |
+// sprintf(presult + strlen(presult), "%c%s%p", MSEP_FLD, MORPH_HENTRY, rv); |
+ if (HENTRY_DATA(rv)) { |
+ sprintf(presult + strlen(presult), "%c%s", MSEP_FLD, HENTRY_DATA2(rv)); |
+ } |
+ } |
if (!rv) { |
if (compoundflag && |
!(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) { |
@@ -2062,7 +2194,7 @@ |
rv = NULL; |
} |
} |
- |
+ |
if (rv || |
(((wordnum == 0) && compoundbegin && |
((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || |
@@ -2071,35 +2203,28 @@ |
((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || |
(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle))))) |
) { |
- //char * p = prefix_check_morph(st, i, 0, compound); |
+ // char * p = prefix_check_morph(st, i, 0, compound); |
char * p = NULL; |
if (compoundflag) p = affix_check_morph(st, i, compoundflag); |
if (!p || (*p == '\0')) { |
+ if (p) free(p); |
+ p = NULL; |
if ((wordnum == 0) && compoundbegin) { |
p = affix_check_morph(st, i, compoundbegin); |
} else if ((wordnum > 0) && compoundmiddle) { |
p = affix_check_morph(st, i, compoundmiddle); |
} |
} |
- if (*p != '\0') { |
- line_uniq(p); |
- if (strchr(p, '\n')) { |
- strcat(presult, "("); |
- strcat(presult, line_join(p, '|')); |
- strcat(presult, ")"); |
- } else { |
- strcat(presult, p); |
- } |
+ if (p && (*p != '\0')) { |
+ sprintf(presult + strlen(presult), "%c%s%s%s", MSEP_FLD, |
+ MORPH_PART, st, line_uniq_app(&p, MSEP_REC)); |
} |
- if (presult[strlen(presult) - 1] == '\n') { |
- presult[strlen(presult) - 1] = '\0'; |
- } |
+ if (p) free(p); |
checked_prefix = 1; |
- //strcat(presult, "+"); |
} |
// else check forbiddenwords |
} else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) || |
- TESTAFF(rv->astr, pseudoroot, rv->alen))) { |
+ TESTAFF(rv->astr, needaffix, rv->alen))) { |
st[i] = ch; |
continue; |
} |
@@ -2162,7 +2287,7 @@ |
) |
// END of LANG_hu section |
) |
- && ! (( checkcompoundtriple && // test triple letters |
+ && ! (( checkcompoundtriple && !words && // test triple letters |
(word[i-1]==word[i]) && ( |
((i>1) && (word[i-1]==word[i-2])) || |
((word[i-1]==word[i+1])) // may be word[i+1] == '\0' |
@@ -2170,10 +2295,10 @@ |
) || |
( |
// test CHECKCOMPOUNDPATTERN |
- numcheckcpd && cpdpat_check(word, i) |
+ numcheckcpd && !words && cpdpat_check(word, i, rv, NULL) |
) || |
( |
- checkcompoundcase && cpdcase_check(word, i) |
+ checkcompoundcase && !words && cpdcase_check(word, i) |
)) |
) |
// LANG_hu section: spec. Hungarian rule |
@@ -2202,7 +2327,7 @@ |
rv = lookup((word+i)); // perhaps without prefix |
// search homonym with compound flag |
- while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) || |
+ while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || |
!((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || |
(compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) || |
(numdefcpd && defcpd_check(&words, wnum + 1, rv, NULL,1))))) { |
@@ -2211,11 +2336,21 @@ |
if (rv && words && words[wnum + 1]) { |
strcat(*result, presult); |
- if (complexprefixes && rv->description) strcat(*result, rv->description); |
- if (rv->description && ((!rv->astr) || |
- !TESTAFF(rv->astr, lemma_present, rv->alen))) |
- strcat(*result, rv->word); |
- if (!complexprefixes && rv->description) strcat(*result, rv->description); |
+ strcat(*result, " "); |
+ strcat(*result, MORPH_PART); |
+ strcat(*result, word+i); |
+ if (complexprefixes && HENTRY_DATA(rv)) strcat(*result, HENTRY_DATA2(rv)); |
+ if (!HENTRY_FIND(rv, MORPH_STEM)) { |
+ strcat(*result, " "); |
+ strcat(*result, MORPH_STEM); |
+ strcat(*result, HENTRY_WORD(rv)); |
+ } |
+ // store the pointer of the hash entry |
+// sprintf(*result + strlen(*result), " %s%p", MORPH_HENTRY, rv); |
+ if (!complexprefixes && HENTRY_DATA(rv)) { |
+ strcat(*result, " "); |
+ strcat(*result, HENTRY_DATA2(rv)); |
+ } |
strcat(*result, "\n"); |
ok = 1; |
return 0; |
@@ -2240,7 +2375,7 @@ |
st[i] = ch; |
continue; |
} |
- |
+ |
// second word is acceptable, as a root? |
// hungarian conventions: compounding is acceptable, |
// when compound forms consist of 2 words, or if more, |
@@ -2251,8 +2386,8 @@ |
) |
&& ( |
((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || |
- ((cpdmaxsyllable==0) || |
- (numsyllable+get_syllable(rv->word,rv->wlen)<=cpdmaxsyllable)) |
+ ((cpdmaxsyllable!=0) && |
+ (numsyllable+get_syllable(HENTRY_WORD(rv),rv->blen)<=cpdmaxsyllable)) |
) |
&& ( |
(!checkcompounddup || (rv != rv_first)) |
@@ -2261,12 +2396,23 @@ |
{ |
// bad compound word |
strcat(*result, presult); |
- |
- if (rv->description) { |
- if (complexprefixes) strcat(*result, rv->description); |
- if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen)) |
- strcat(*result, rv->word); |
- if (!complexprefixes) strcat(*result, rv->description); |
+ strcat(*result, " "); |
+ strcat(*result, MORPH_PART); |
+ strcat(*result, word+i); |
+ |
+ if (HENTRY_DATA(rv)) { |
+ if (complexprefixes) strcat(*result, HENTRY_DATA2(rv)); |
+ if (! HENTRY_FIND(rv, MORPH_STEM)) { |
+ strcat(*result, " "); |
+ strcat(*result, MORPH_STEM); |
+ strcat(*result, HENTRY_WORD(rv)); |
+ } |
+ // store the pointer of the hash entry |
+// sprintf(*result + strlen(*result), " %s%p", MORPH_HENTRY, rv); |
+ if (!complexprefixes) { |
+ strcat(*result, " "); |
+ strcat(*result, HENTRY_DATA2(rv)); |
+ } |
} |
strcat(*result, "\n"); |
ok = 1; |
@@ -2292,20 +2438,16 @@ |
if (rv && words && defcpd_check(&words, wnum + 1, rv, NULL, 1)) { |
char * m = NULL; |
if (compoundflag) m = affix_check_morph((word+i),strlen(word+i), compoundflag); |
- if ((!m || *m == '\0') && compoundend) |
+ if ((!m || *m == '\0') && compoundend) { |
+ if (m) free(m); |
m = affix_check_morph((word+i),strlen(word+i), compoundend); |
+ } |
strcat(*result, presult); |
- if (m) { |
- line_uniq(m); |
- if (strchr(m, '\n')) { |
- strcat(*result, "("); |
- strcat(*result, line_join(m, '|')); |
- strcat(*result, ")"); |
- } else { |
- strcat(*result, m); |
- } |
- free(m); |
+ if (m || (*m != '\0')) { |
+ sprintf(*result + strlen(*result), "%c%s%s%s", MSEP_FLD, |
+ MORPH_PART, word + i, line_uniq_app(&m, MSEP_REC)); |
} |
+ if (m) free(m); |
strcat(*result, "\n"); |
ok = 1; |
} |
@@ -2324,7 +2466,7 @@ |
// check forbiddenwords |
if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen)) |
- && (! TESTAFF(rv->astr, pseudoroot, rv->alen))) { |
+ && (! TESTAFF(rv->astr, needaffix, rv->alen))) { |
st[i] = ch; |
continue; |
} |
@@ -2368,7 +2510,7 @@ |
if ((rv) && |
( |
((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || |
- ((cpdmaxsyllable==0) || |
+ ((cpdmaxsyllable!=0) && |
(numsyllable <= cpdmaxsyllable)) |
) |
&& ( |
@@ -2376,21 +2518,17 @@ |
)) { |
char * m = NULL; |
if (compoundflag) m = affix_check_morph((word+i),strlen(word+i), compoundflag); |
- if ((!m || *m == '\0') && compoundend) |
+ if ((!m || *m == '\0') && compoundend) { |
+ if (m) free(m); |
m = affix_check_morph((word+i),strlen(word+i), compoundend); |
+ } |
strcat(*result, presult); |
- if (m) { |
- line_uniq(m); |
- if (strchr(m, '\n')) { |
- strcat(*result, "("); |
- strcat(*result, line_join(m, '|')); |
- strcat(*result, ")"); |
- } else { |
- strcat(*result, m); |
- } |
- free(m); |
+ if (m && (*m != '\0')) { |
+ sprintf(*result + strlen(*result), "%c%s%s%s", MSEP_FLD, |
+ MORPH_PART, word + i, line_uniq_app(&m, MSEP_REC)); |
} |
- strcat(*result, "\n"); |
+ if (m) free(m); |
+ sprintf(*result + strlen(*result), "%c", MSEP_REC); |
ok = 1; |
} |
@@ -2411,7 +2549,6 @@ |
} |
return 0; |
} |
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE |
// return 1 if s1 (reversed) is a leading subset of end of s2 |
/* inline int AffixMgr::isRevSubset(const char * s1, const char * end_of_s2, int len) |
@@ -2442,8 +2579,6 @@ |
const FLAG cclass, const FLAG needflag, char in_compound) |
{ |
struct hentry * rv = NULL; |
- char result[MAXLNLEN]; |
- |
PfxEntry* ep = (PfxEntry *) ppfx; |
// first handle the special case of 0 length suffixes |
@@ -2467,11 +2602,11 @@ |
// fogemorpheme |
(in_compound || |
!((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) && |
- // pseudoroot on prefix or first suffix |
+ // needaffix on prefix or first suffix |
(cclass || |
- !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) || |
+ !(se->getCont() && TESTAFF(se->getCont(), needaffix, se->getContLen())) || |
(ppfx && !((ep->getCont()) && |
- TESTAFF(ep->getCont(), pseudoroot, |
+ TESTAFF(ep->getCont(), needaffix, |
ep->getContLen()))) |
) |
) { |
@@ -2509,11 +2644,11 @@ |
// fogemorpheme |
(in_compound || |
!((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) && |
- // pseudoroot on prefix or first suffix |
+ // needaffix on prefix or first suffix |
(cclass || |
- !(sptr->getCont() && TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) || |
+ !(sptr->getCont() && TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) || |
(ppfx && !((ep->getCont()) && |
- TESTAFF(ep->getCont(), pseudoroot, |
+ TESTAFF(ep->getCont(), needaffix, |
ep->getContLen()))) |
) |
) { |
@@ -2523,17 +2658,6 @@ |
sfx=(AffEntry *)sptr; // BUG: sfx not stateless |
sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless |
if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless |
- if (cclass || sptr->getCont()) { |
- if (!derived) { |
- derived = mystrdup(word); |
- } else { |
- strcpy(result, derived); // XXX check size |
- strcat(result, "\n"); |
- strcat(result, word); |
- free(derived); |
- derived = mystrdup(result); |
- } |
- } |
return rv; |
} |
} |
@@ -2588,7 +2712,6 @@ |
return NULL; |
} |
-#ifdef HUNSPELL_EXPERIMENTAL |
char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len, |
int sfxopts, AffEntry * ppfx, const FLAG needflag) |
{ |
@@ -2610,12 +2733,18 @@ |
st = se->check_twosfx_morph(word,len, sfxopts, ppfx, needflag); |
if (st) { |
if (ppfx) { |
- if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph()); |
+ if (((PfxEntry *) ppfx)->getMorph()) { |
+ mystrcat(result, ((PfxEntry *) ppfx)->getMorph(), MAXLNLEN); |
+ mystrcat(result, " ", MAXLNLEN); |
+ } else debugflag(result, ((PfxEntry *) ppfx)->getFlag()); |
} |
- strcat(result, st); |
+ mystrcat(result, st, MAXLNLEN); |
free(st); |
- if (se->getMorph()) strcat(result, se->getMorph()); |
- strcat(result, "\n"); |
+ if (se->getMorph()) { |
+ mystrcat(result, " ", MAXLNLEN); |
+ mystrcat(result, se->getMorph(), MAXLNLEN); |
+ } else debugflag(result, se->getFlag()); |
+ mystrcat(result, "\n", MAXLNLEN); |
} |
} |
se = se->getNext(); |
@@ -2637,19 +2766,14 @@ |
free(st); |
result3[0] = '\0'; |
-#ifdef DEBUG |
- unsigned short flag = sptr->getFlag(); |
- if (flag_mode == FLAG_NUM) { |
- sprintf(result3, "<%d>", sptr->getKey()); |
- } else if (flag_mode == FLAG_LONG) { |
- sprintf(result3, "<%c%c>", flag >> 8, (flag << 8) >>8); |
- } else sprintf(result3, "<%c>", flag); |
- strcat(result3, ":"); |
-#endif |
- if (sptr->getMorph()) strcat(result3, sptr->getMorph()); |
+ |
+ if (sptr->getMorph()) { |
+ mystrcat(result3, " ", MAXLNLEN); |
+ mystrcat(result3, sptr->getMorph(), MAXLNLEN); |
+ } else debugflag(result3, sptr->getFlag()); |
strlinecat(result2, result3); |
- strcat(result2, "\n"); |
- strcat(result, result2); |
+ mystrcat(result2, "\n", MAXLNLEN); |
+ mystrcat(result, result2, MAXLNLEN); |
} |
} |
sptr = sptr->getNextEQ(); |
@@ -2657,7 +2781,7 @@ |
sptr = sptr->getNextNE(); |
} |
} |
- if (result) return mystrdup(result); |
+ if (*result) return mystrdup(result); |
return NULL; |
} |
@@ -2692,26 +2816,40 @@ |
// fogemorpheme |
(in_compound || |
!((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) && |
- // pseudoroot on prefix or first suffix |
+ // needaffix on prefix or first suffix |
(cclass || |
- !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) || |
+ !(se->getCont() && TESTAFF(se->getCont(), needaffix, se->getContLen())) || |
(ppfx && !((ep->getCont()) && |
- TESTAFF(ep->getCont(), pseudoroot, |
+ TESTAFF(ep->getCont(), needaffix, |
ep->getContLen()))) |
) |
)) |
rv = se->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag); |
while (rv) { |
if (ppfx) { |
- if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph()); |
+ if (((PfxEntry *) ppfx)->getMorph()) { |
+ mystrcat(result, ((PfxEntry *) ppfx)->getMorph(), MAXLNLEN); |
+ mystrcat(result, " ", MAXLNLEN); |
+ } else debugflag(result, ((PfxEntry *) ppfx)->getFlag()); |
} |
- if (complexprefixes && rv->description) strcat(result, rv->description); |
- if (rv->description && ((!rv->astr) || |
- !TESTAFF(rv->astr, lemma_present, rv->alen))) |
- strcat(result, rv->word); |
- if (!complexprefixes && rv->description) strcat(result, rv->description); |
- if (se->getMorph()) strcat(result, se->getMorph()); |
- strcat(result, "\n"); |
+ if (complexprefixes && HENTRY_DATA(rv)) mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN); |
+ if (! HENTRY_FIND(rv, MORPH_STEM)) { |
+ mystrcat(result, " ", MAXLNLEN); |
+ mystrcat(result, MORPH_STEM, MAXLNLEN); |
+ mystrcat(result, HENTRY_WORD(rv), MAXLNLEN); |
+ } |
+ // store the pointer of the hash entry |
+// sprintf(result + strlen(result), " %s%p", MORPH_HENTRY, rv); |
+ |
+ if (!complexprefixes && HENTRY_DATA(rv)) { |
+ mystrcat(result, " ", MAXLNLEN); |
+ mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN); |
+ } |
+ if (se->getMorph()) { |
+ mystrcat(result, " ", MAXLNLEN); |
+ mystrcat(result, se->getMorph(), MAXLNLEN); |
+ } else debugflag(result, se->getFlag()); |
+ mystrcat(result, "\n", MAXLNLEN); |
rv = se->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag); |
} |
} |
@@ -2741,30 +2879,36 @@ |
// fogemorpheme |
(in_compound || |
!((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) && |
- // pseudoroot on first suffix |
+ // needaffix on first suffix |
(cclass || !(sptr->getCont() && |
- TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen()))) |
+ TESTAFF(sptr->getCont(), needaffix, sptr->getContLen()))) |
)) rv = sptr->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag); |
while (rv) { |
if (ppfx) { |
- if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph()); |
+ if (((PfxEntry *) ppfx)->getMorph()) { |
+ mystrcat(result, ((PfxEntry *) ppfx)->getMorph(), MAXLNLEN); |
+ mystrcat(result, " ", MAXLNLEN); |
+ } else debugflag(result, ((PfxEntry *) ppfx)->getFlag()); |
} |
- if (complexprefixes && rv->description) strcat(result, rv->description); |
- if (rv->description && ((!rv->astr) || |
- !TESTAFF(rv->astr, lemma_present, rv->alen))) strcat(result, rv->word); |
- if (!complexprefixes && rv->description) strcat(result, rv->description); |
-#ifdef DEBUG |
- unsigned short flag = sptr->getFlag(); |
- if (flag_mode == FLAG_NUM) { |
- sprintf(result, "<%d>", sptr->getKey()); |
- } else if (flag_mode == FLAG_LONG) { |
- sprintf(result, "<%c%c>", flag >> 8, (flag << 8) >>8); |
- } else sprintf(result, "<%c>", flag); |
- strcat(result, ":"); |
-#endif |
+ if (complexprefixes && HENTRY_DATA(rv)) mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN); |
+ if (! HENTRY_FIND(rv, MORPH_STEM)) { |
+ mystrcat(result, " ", MAXLNLEN); |
+ mystrcat(result, MORPH_STEM, MAXLNLEN); |
+ mystrcat(result, HENTRY_WORD(rv), MAXLNLEN); |
+ } |
+ // store the pointer of the hash entry |
+// sprintf(result + strlen(result), " %s%p", MORPH_HENTRY, rv); |
- if (sptr->getMorph()) strcat(result, sptr->getMorph()); |
- strcat(result, "\n"); |
+ if (!complexprefixes && HENTRY_DATA(rv)) { |
+ mystrcat(result, " ", MAXLNLEN); |
+ mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN); |
+ } |
+ |
+ if (sptr->getMorph()) { |
+ mystrcat(result, " ", MAXLNLEN); |
+ mystrcat(result, sptr->getMorph(), MAXLNLEN); |
+ } else debugflag(result, sptr->getFlag()); |
+ mystrcat(result, "\n", MAXLNLEN); |
rv = sptr->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag); |
} |
sptr = sptr->getNextEQ(); |
@@ -2776,15 +2920,11 @@ |
if (*result) return mystrdup(result); |
return NULL; |
} |
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE |
- |
// check if word with affixes is correctly spelled |
struct hentry * AffixMgr::affix_check (const char * word, int len, const FLAG needflag, char in_compound) |
{ |
struct hentry * rv= NULL; |
- if (derived) free(derived); |
- derived = NULL; |
// check all prefixes (also crossed with suffixes if allowed) |
rv = prefix_check(word, len, in_compound, needflag); |
@@ -2806,7 +2946,6 @@ |
return rv; |
} |
-#ifdef HUNSPELL_EXPERIMENTAL |
// check if word with affixes is correctly spelled |
char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needflag, char in_compound) |
{ |
@@ -2818,14 +2957,14 @@ |
// check all prefixes (also crossed with suffixes if allowed) |
st = prefix_check_morph(word, len, in_compound); |
if (st) { |
- strcat(result, st); |
+ mystrcat(result, st, MAXLNLEN); |
free(st); |
} |
// if still not found check all suffixes |
st = suffix_check_morph(word, len, 0, NULL, '\0', needflag, in_compound); |
if (st) { |
- strcat(result, st); |
+ mystrcat(result, st, MAXLNLEN); |
free(st); |
} |
@@ -2835,54 +2974,133 @@ |
// if still not found check all two-level suffixes |
st = suffix_check_twosfx_morph(word, len, 0, NULL, needflag); |
if (st) { |
- strcat(result, st); |
+ mystrcat(result, st, MAXLNLEN); |
free(st); |
} |
// if still not found check all two-level suffixes |
st = prefix_check_twosfx_morph(word, len, IN_CPD_NOT, needflag); |
if (st) { |
- strcat(result, st); |
+ mystrcat(result, st, MAXLNLEN); |
free(st); |
} |
} |
- |
+ |
return mystrdup(result); |
} |
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE |
+char * AffixMgr::morphgen(char * ts, int wl, const unsigned short * ap, |
+ unsigned short al, char * morph, char * targetmorph, int level) |
+{ |
+ // handle suffixes |
+ char * stemmorph; |
+ char * stemmorphcatpos; |
+ char mymorph[MAXLNLEN]; |
+ if (!morph && !targetmorph) return NULL; |
+ |
+ // check substandard flag |
+ if (TESTAFF(ap, substandard, al)) return NULL; |
+ |
+ if (morphcmp(morph, targetmorph) == 0) return mystrdup(ts); |
+ |
+// int targetcount = get_sfxcount(targetmorph); |
+ |
+ // use input suffix fields, if exist |
+ if (strstr(morph, MORPH_INFL_SFX) || strstr(morph, MORPH_DERI_SFX)) { |
+ stemmorph = mymorph; |
+ strcpy(stemmorph, morph); |
+ strcat(stemmorph, " "); |
+ stemmorphcatpos = stemmorph + strlen(stemmorph); |
+ } else { |
+ stemmorph = morph; |
+ stemmorphcatpos = NULL; |
+ } |
+ |
+ for (int i = 0; i < al; i++) { |
+ const unsigned char c = (unsigned char) (ap[i] & 0x00FF); |
+ SfxEntry * sptr = (SfxEntry *)sFlag[c]; |
+ while (sptr) { |
+ if (sptr->getFlag() == ap[i] && sptr->getMorph() && ((sptr->getContLen() == 0) || |
+ // don't generate forms with substandard affixes |
+ !TESTAFF(sptr->getCont(), substandard, sptr->getContLen()))) { |
+ |
+ if (stemmorphcatpos) strcpy(stemmorphcatpos, sptr->getMorph()); |
+ else stemmorph = (char *) sptr->getMorph(); |
+ |
+ int cmp = morphcmp(stemmorph, targetmorph); |
+ |
+ if (cmp == 0) { |
+ char * newword = sptr->add(ts, wl); |
+ if (newword) { |
+ hentry * check = pHMgr->lookup(newword); // XXX extra dic |
+ if (!check || !check->astr || |
+ !TESTAFF(check->astr, forbiddenword, check->alen)) { |
+ return newword; |
+ } |
+ free(newword); |
+ } |
+ } |
+ |
+ // recursive call for secondary suffixes |
+ if ((level == 0) && (cmp == 1) && (sptr->getContLen() > 0) && |
+// (get_sfxcount(stemmorph) < targetcount) && |
+ !TESTAFF(sptr->getCont(), substandard, sptr->getContLen())) { |
+ char * newword = sptr->add(ts, wl); |
+ if (newword) { |
+ char * newword2 = morphgen(newword, strlen(newword), sptr->getCont(), |
+ sptr->getContLen(), stemmorph, targetmorph, 1); |
+ |
+ if (newword2) { |
+ free(newword); |
+ return newword2; |
+ } |
+ free(newword); |
+ newword = NULL; |
+ } |
+ } |
+ } |
+ sptr = (SfxEntry *)sptr ->getFlgNxt(); |
+ } |
+ } |
+ return NULL; |
+} |
+ |
+ |
int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts, |
- int wl, const unsigned short * ap, unsigned short al, char * bad, int badl) |
+ int wl, const unsigned short * ap, unsigned short al, char * bad, int badl, |
+ char * phon) |
{ |
- |
int nh=0; |
- |
// first add root word to list |
- if ((nh < maxn) && !(al && ((pseudoroot && TESTAFF(ap, pseudoroot, al)) || |
+ if ((nh < maxn) && !(al && ((needaffix && TESTAFF(ap, needaffix, al)) || |
(onlyincompound && TESTAFF(ap, onlyincompound, al))))) { |
wlst[nh].word = mystrdup(ts); |
+ if (!wlst[nh].word) return 0; |
wlst[nh].allow = (1 == 0); |
+ wlst[nh].orig = NULL; |
nh++; |
+ // add special phonetic version |
+ if (phon && (nh < maxn)) { |
+ wlst[nh].word = mystrdup(phon); |
+ if (!wlst[nh].word) return nh - 1; |
+ wlst[nh].allow = (1 == 0); |
+ wlst[nh].orig = mystrdup(ts); |
+ if (!wlst[nh].orig) return nh - 1; |
+ nh++; |
+ } |
} |
// handle suffixes |
for (int i = 0; i < al; i++) { |
-#ifdef HUNSPELL_CHROME_CLIENT |
- // This change is taken from a future version of Hunspell. In other |
- // places, the index is clamped to a byte, so I think this is correct. |
- // Our array is only 256 entries anyway, so it is required. |
const unsigned char c = (unsigned char) (ap[i] & 0x00FF); |
-#else |
- unsigned short c = (unsigned short) ap[i]; |
-#endif |
SfxEntry * sptr = (SfxEntry *)sFlag[c]; |
while (sptr) { |
- if (!sptr->getKeyLen() || ((badl > sptr->getKeyLen()) && |
- (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0)) && |
- // check pseudoroot flag |
- !(sptr->getCont() && ((pseudoroot && |
- TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) || |
+ if ((sptr->getFlag() == ap[i]) && (!sptr->getKeyLen() || ((badl > sptr->getKeyLen()) && |
+ (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0))) && |
+ // check needaffix flag |
+ !(sptr->getCont() && ((needaffix && |
+ TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) || |
(circumfix && |
TESTAFF(sptr->getCont(), circumfix, sptr->getContLen())) || |
(onlyincompound && |
@@ -2892,8 +3110,22 @@ |
if (newword) { |
if (nh < maxn) { |
wlst[nh].word = newword; |
- wlst[nh].allow = sptr->allowCross(); |
- nh++; |
+ wlst[nh].allow = sptr->allowCross(); |
+ wlst[nh].orig = NULL; |
+ nh++; |
+ // add special phonetic version |
+ if (phon && (nh < maxn)) { |
+ char st[MAXWORDUTF8LEN]; |
+ strcpy(st, phon); |
+ strcat(st, sptr->getKey()); |
+ reverseword(st + strlen(phon)); |
+ wlst[nh].word = mystrdup(st); |
+ if (!wlst[nh].word) return nh - 1; |
+ wlst[nh].allow = (1 == 0); |
+ wlst[nh].orig = mystrdup(newword); |
+ if (!wlst[nh].orig) return nh - 1; |
+ nh++; |
+ } |
} else { |
free(newword); |
} |
@@ -2909,15 +3141,10 @@ |
for (int j=1;j<n ;j++) |
if (wlst[j].allow) { |
for (int k = 0; k < al; k++) { |
-#ifdef HUNSPELL_CHROME_CLIENT |
- // See similar change above. |
const unsigned char c = (unsigned char) (ap[k] & 0x00FF); |
-#else |
- unsigned short c = (unsigned short) ap[k]; |
-#endif |
PfxEntry * cptr = (PfxEntry *) pFlag[c]; |
while (cptr) { |
- if (cptr->allowCross() && (!cptr->getKeyLen() || ((badl > cptr->getKeyLen()) && |
+ if ((cptr->getFlag() == ap[k]) && cptr->allowCross() && (!cptr->getKeyLen() || ((badl > cptr->getKeyLen()) && |
(strncmp(cptr->getKey(), bad, cptr->getKeyLen()) == 0)))) { |
int l1 = strlen(wlst[j].word); |
char * newword = cptr->add(wlst[j].word, l1); |
@@ -2925,6 +3152,7 @@ |
if (nh < maxn) { |
wlst[nh].word = newword; |
wlst[nh].allow = cptr->allowCross(); |
+ wlst[nh].orig = NULL; |
nh++; |
} else { |
free(newword); |
@@ -2939,19 +3167,14 @@ |
// now handle pure prefixes |
for (int m = 0; m < al; m ++) { |
-#ifdef HUNSPELL_CHROME_CLIENT |
- // See similar change above. |
const unsigned char c = (unsigned char) (ap[m] & 0x00FF); |
-#else |
- unsigned short c = (unsigned short) ap[m]; |
-#endif |
PfxEntry * ptr = (PfxEntry *) pFlag[c]; |
while (ptr) { |
- if (!ptr->getKeyLen() || ((badl > ptr->getKeyLen()) && |
- (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0)) && |
- // check pseudoroot flag |
- !(ptr->getCont() && ((pseudoroot && |
- TESTAFF(ptr->getCont(), pseudoroot, ptr->getContLen())) || |
+ if ((ptr->getFlag() == ap[m]) && (!ptr->getKeyLen() || ((badl > ptr->getKeyLen()) && |
+ (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0))) && |
+ // check needaffix flag |
+ !(ptr->getCont() && ((needaffix && |
+ TESTAFF(ptr->getCont(), needaffix, ptr->getContLen())) || |
(circumfix && |
TESTAFF(ptr->getCont(), circumfix, ptr->getContLen())) || |
(onlyincompound && |
@@ -2962,6 +3185,7 @@ |
if (nh < maxn) { |
wlst[nh].word = newword; |
wlst[nh].allow = ptr->allowCross(); |
+ wlst[nh].orig = NULL; |
nh++; |
} else { |
free(newword); |
@@ -2975,8 +3199,6 @@ |
return nh; |
} |
- |
- |
// return length of replacing table |
int AffixMgr::get_numrep() |
{ |
@@ -2990,6 +3212,27 @@ |
return reptable; |
} |
+// return iconv table |
+RepList * AffixMgr::get_iconvtable() |
+{ |
+ if (! iconvtable ) return NULL; |
+ return iconvtable; |
+} |
+ |
+// return oconv table |
+RepList * AffixMgr::get_oconvtable() |
+{ |
+ if (! oconvtable ) return NULL; |
+ return oconvtable; |
+} |
+ |
+// return replacing table |
+struct phonetable * AffixMgr::get_phonetable() |
+{ |
+ if (! phone ) return NULL; |
+ return phone; |
+} |
+ |
// return length of character map table |
int AffixMgr::get_nummap() |
{ |
@@ -3019,9 +3262,7 @@ |
// return text encoding of dictionary |
char * AffixMgr::get_encoding() |
{ |
- if (! encoding ) { |
- encoding = mystrdup("ISO8859-1"); |
- } |
+ if (! encoding ) encoding = mystrdup(SPELL_ENCODING); |
return mystrdup(encoding); |
} |
@@ -3037,6 +3278,12 @@ |
return complexprefixes; |
} |
+// return FULLSTRIP option |
+int AffixMgr::get_fullstrip() |
+{ |
+ return fullstrip; |
+} |
+ |
FLAG AffixMgr::get_keepcase() |
{ |
return keepcase; |
@@ -3047,11 +3294,17 @@ |
return checksharps; |
} |
+char * AffixMgr::encode_flag(unsigned short aflag) |
+{ |
+ return pHMgr->encode_flag(aflag); |
+} |
+ |
+ |
// return the preferred ignore string for suggestions |
char * AffixMgr::get_ignore() |
{ |
if (!ignorechars) return NULL; |
- return mystrdup(ignorechars); |
+ return ignorechars; |
} |
// return the preferred ignore string for suggestions |
@@ -3061,6 +3314,13 @@ |
return ignorechars_utf16; |
} |
+// return the keyboard string for suggestions |
+char * AffixMgr::get_key_string() |
+{ |
+ if (! keystring ) keystring = mystrdup(SPELL_KEYSTRING); |
+ return mystrdup(keystring); |
+} |
+ |
// return the preferred try string for suggestions |
char * AffixMgr::get_try_string() |
{ |
@@ -3105,9 +3365,9 @@ |
} |
// return the forbidden words flag modify flag |
-FLAG AffixMgr::get_pseudoroot() |
+FLAG AffixMgr::get_needaffix() |
{ |
- return pseudoroot; |
+ return needaffix; |
} |
// return the onlyincompound flag |
@@ -3147,12 +3407,6 @@ |
return sfxappnd; |
} |
-// return the value of derived form (base word with first suffix). |
-const char * AffixMgr::get_derived() |
-{ |
- return derived; |
-} |
- |
// return the value of suffix |
const char * AffixMgr::get_version() |
{ |
@@ -3168,8 +3422,12 @@ |
// utility method to look up root words in hash table |
struct hentry * AffixMgr::lookup(const char * word) |
{ |
- if (! pHMgr) return NULL; |
- return pHMgr->lookup(word); |
+ int i; |
+ struct hentry * he = NULL; |
+ for (i = 0; i < *maxdic && !he; i++) { |
+ he = (alldic[i])->lookup(word); |
+ } |
+ return he; |
} |
// return the value of suffix |
@@ -3203,33 +3461,47 @@ |
} |
/* parse flag */ |
-int AffixMgr::parse_flag(char * line, unsigned short * out, const char * name) { |
+#ifdef HUNSPELL_CHROME_CLIENT |
+int AffixMgr::parse_flag(char * line, unsigned short * out) |
+#else |
+int AffixMgr::parse_flag(char * line, unsigned short * out, FileMgr * af) |
+#endif |
+{ |
char * s = NULL; |
- if (*out != FLAG_NULL) { |
- HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name); |
+ if (*out != FLAG_NULL && !(*out >= DEFAULTFLAGS)) { |
+ HUNSPELL_WARNING(stderr, "error:multiple definitions of an affix file parameter\n"); |
return 1; |
} |
- if (parse_string(line, &s, name)) return 1; |
+ if (parse_string(line, &s, 0)) return 1; |
*out = pHMgr->decode_flag(s); |
free(s); |
return 0; |
} |
/* parse num */ |
-int AffixMgr::parse_num(char * line, int * out, const char * name) { |
+#ifdef HUNSPELL_CHROME_CLIENT |
+int AffixMgr::parse_num(char * line, int * out) |
+#else |
+int AffixMgr::parse_num(char * line, int * out, FileMgr * af) |
+#endif |
+{ |
char * s = NULL; |
if (*out != -1) { |
- HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name); |
+ HUNSPELL_WARNING(stderr, "error: multiple definitions of an affix file parameter\n"); |
return 1; |
} |
- if (parse_string(line, &s, name)) return 1; |
+ if (parse_string(line, &s, 0)) return 1; |
*out = atoi(s); |
free(s); |
return 0; |
} |
/* parse in the max syllablecount of compound words and */ |
+#ifdef HUNSPELL_CHROME_CLIENT |
int AffixMgr::parse_cpdsyllable(char * line) |
+#else |
+int AffixMgr::parse_cpdsyllable(char * line, FileMgr * af) |
+#endif |
{ |
char * tp = line; |
char * piece; |
@@ -3262,7 +3534,6 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if (np < 2) { |
@@ -3273,12 +3544,12 @@ |
return 0; |
} |
+#ifndef HUNSPELL_CHROME_CLIENT |
/* parse in the typical fault correcting table */ |
-#ifndef HUNSPELL_CHROME_CLIENT |
-int AffixMgr::parse_reptable(char * line, FILE * af) |
+int AffixMgr::parse_reptable(char * line, FileMgr * af) |
{ |
if (numrep != 0) { |
- HUNSPELL_WARNING(stderr, "error: duplicate REP tables used\n"); |
+ HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); |
return 1; |
} |
char * tp = line; |
@@ -3293,8 +3564,7 @@ |
case 1: { |
numrep = atoi(piece); |
if (numrep < 1) { |
- HUNSPELL_WARNING(stderr, "incorrect number of entries in replacement table\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: line %d: incorrect entry number\n", af->getlinenum()); |
return 1; |
} |
reptable = (replentry *) malloc(numrep * sizeof(struct replentry)); |
@@ -3306,18 +3576,17 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if (np != 2) { |
- HUNSPELL_WARNING(stderr, "error: missing replacement table information\n"); |
+ HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); |
return 1; |
} |
/* now parse the numrep lines to read in the remainder of the table */ |
- char * nl = line; |
+ char * nl; |
for (int j=0; j < numrep; j++) { |
- if (!fgets(nl,MAXLNLEN,af)) return 1; |
+ if (!(nl = af->getline())) return 1; |
mychomp(nl); |
tp = nl; |
i = 0; |
@@ -3329,8 +3598,8 @@ |
switch(i) { |
case 0: { |
if (strncmp(piece,"REP",3) != 0) { |
- HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); |
+ numrep = 0; |
return 1; |
} |
break; |
@@ -3341,11 +3610,11 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) { |
- HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n"); |
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); |
+ numrep = 0; |
return 1; |
} |
} |
@@ -3353,15 +3622,198 @@ |
} |
#endif |
+/* parse in the typical fault correcting table */ |
+#ifdef HUNSPELL_CHROME_CLIENT |
+int AffixMgr::parse_convtable(char * line, hunspell::LineIterator* iterator, RepList ** rl, const char * keyword) |
+#else |
+int AffixMgr::parse_convtable(char * line, FileMgr * af, RepList ** rl, const char * keyword) |
+#endif |
+{ |
+ if (*rl) { |
+ HUNSPELL_WARNING(stderr, "error: multiple table definitions\n"); |
+ return 1; |
+ } |
+ char * tp = line; |
+ char * piece; |
+ int i = 0; |
+ int np = 0; |
+ int numrl = 0; |
+ piece = mystrsep(&tp, 0); |
+ while (piece) { |
+ if (*piece != '\0') { |
+ switch(i) { |
+ case 0: { np++; break; } |
+ case 1: { |
+ numrl = atoi(piece); |
+ if (numrl < 1) { |
+ HUNSPELL_WARNING(stderr, "error: incorrect entry number\n"); |
+ return 1; |
+ } |
+ *rl = new RepList(numrl); |
+ if (!rl) return 1; |
+ np++; |
+ break; |
+ } |
+ default: break; |
+ } |
+ i++; |
+ } |
+ piece = mystrsep(&tp, 0); |
+ } |
+ if (np != 2) { |
+ HUNSPELL_WARNING(stderr, "error: missing data\n"); |
+ return 1; |
+ } |
+ |
+ /* now parse the num lines to read in the remainder of the table */ |
+ char * nl = line; |
+ for (int j=0; j < numrl; j++) { |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (!iterator->AdvanceAndCopy(nl, MAXLNLEN)) |
+ return 1; |
+#else |
+ if (!(nl = af->getline())) return 1; |
+#endif |
+ mychomp(nl); |
+ tp = nl; |
+ i = 0; |
+ char * pattern = NULL; |
+ char * pattern2 = NULL; |
+ piece = mystrsep(&tp, 0); |
+ while (piece) { |
+ if (*piece != '\0') { |
+ switch(i) { |
+ case 0: { |
+ if (strncmp(piece, keyword, sizeof(keyword)) != 0) { |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ delete *rl; |
+ *rl = NULL; |
+ return 1; |
+ } |
+ break; |
+ } |
+ case 1: { pattern = mystrrep(mystrdup(piece),"_"," "); break; } |
+ case 2: { |
+ pattern2 = mystrrep(mystrdup(piece),"_"," "); |
+ break; |
+ } |
+ default: break; |
+ } |
+ i++; |
+ } |
+ piece = mystrsep(&tp, 0); |
+ } |
+ if (!pattern || !pattern2) { |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ return 1; |
+ } |
+ (*rl)->add(pattern, pattern2); |
+ } |
+ return 0; |
+} |
+ |
+ |
+/* parse in the typical fault correcting table */ |
+#ifdef HUNSPELL_CHROME_CLIENT |
+int AffixMgr::parse_phonetable(char * line, hunspell::LineIterator* iterator) |
+#else |
+int AffixMgr::parse_phonetable(char * line, FileMgr * af) |
+#endif |
+{ |
+ if (phone) { |
+ HUNSPELL_WARNING(stderr, "error: multiple table definitions\n"); |
+ return 1; |
+ } |
+ char * tp = line; |
+ char * piece; |
+ int i = 0; |
+ int np = 0; |
+ piece = mystrsep(&tp, 0); |
+ while (piece) { |
+ if (*piece != '\0') { |
+ switch(i) { |
+ case 0: { np++; break; } |
+ case 1: { |
+ phone = (phonetable *) malloc(sizeof(struct phonetable)); |
+ phone->num = atoi(piece); |
+ phone->rules = NULL; |
+ phone->utf8 = (char) utf8; |
+ if (!phone) return 1; |
+ if (phone->num < 1) { |
+ HUNSPELL_WARNING(stderr, "error: line bad entry number\n"); |
+ return 1; |
+ } |
+ phone->rules = (char * *) malloc(2 * (phone->num + 1) * sizeof(char *)); |
+ if (!phone->rules) return 1; |
+ np++; |
+ break; |
+ } |
+ default: break; |
+ } |
+ i++; |
+ } |
+ piece = mystrsep(&tp, 0); |
+ } |
+ if (np != 2) { |
+ HUNSPELL_WARNING(stderr, "error: missing data\n"); |
+ return 1; |
+ } |
+ |
+ /* now parse the phone->num lines to read in the remainder of the table */ |
+ char * nl = line; |
+ for (int j=0; j < phone->num; j++) { |
+#ifdef HUNSPELL_CHROME_CLIENT |
+ if (!iterator->AdvanceAndCopy(nl, MAXLNLEN)) |
+ return 1; |
+#else |
+ if (!(nl = af->getline())) return 1; |
+#endif |
+ mychomp(nl); |
+ tp = nl; |
+ i = 0; |
+ phone->rules[j * 2] = NULL; |
+ phone->rules[j * 2 + 1] = NULL; |
+ piece = mystrsep(&tp, 0); |
+ while (piece) { |
+ if (*piece != '\0') { |
+ switch(i) { |
+ case 0: { |
+ if (strncmp(piece,"PHONE",5) != 0) { |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ phone->num = 0; |
+ return 1; |
+ } |
+ break; |
+ } |
+ case 1: { phone->rules[j * 2] = mystrrep(mystrdup(piece),"_",""); break; } |
+ case 2: { phone->rules[j * 2 + 1] = mystrrep(mystrdup(piece),"_",""); break; } |
+ default: break; |
+ } |
+ i++; |
+ } |
+ piece = mystrsep(&tp, 0); |
+ } |
+ if ((!(phone->rules[j * 2])) || (!(phone->rules[j * 2 + 1]))) { |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ phone->num = 0; |
+ return 1; |
+ } |
+ } |
+ phone->rules[phone->num * 2] = mystrdup(""); |
+ phone->rules[phone->num * 2 + 1] = mystrdup(""); |
+ init_phonet_hash(*phone); |
+ return 0; |
+} |
+ |
/* parse in the checkcompoundpattern table */ |
#if HUNSPELL_CHROME_CLIENT |
int AffixMgr::parse_checkcpdtable(char * line, hunspell::LineIterator* iterator) |
#else |
-int AffixMgr::parse_checkcpdtable(char * line, FILE * af) |
+int AffixMgr::parse_checkcpdtable(char * line, FileMgr * af) |
#endif |
{ |
if (numcheckcpd != 0) { |
- HUNSPELL_WARNING(stderr, "error: duplicate compound pattern tables used\n"); |
+ HUNSPELL_WARNING(stderr, "error: multiple table definitions\n"); |
return 1; |
} |
char * tp = line; |
@@ -3376,11 +3828,10 @@ |
case 1: { |
numcheckcpd = atoi(piece); |
if (numcheckcpd < 1) { |
- HUNSPELL_WARNING(stderr, "incorrect number of entries in compound pattern table\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: bad entry number\n"); |
return 1; |
} |
- checkcpdtable = (replentry *) malloc(numcheckcpd * sizeof(struct replentry)); |
+ checkcpdtable = (patentry *) malloc(numcheckcpd * sizeof(struct patentry)); |
if (!checkcpdtable) return 1; |
np++; |
break; |
@@ -3389,14 +3840,13 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if (np != 2) { |
- HUNSPELL_WARNING(stderr, "error: missing compound pattern table information\n"); |
+ HUNSPELL_WARNING(stderr, "error: missing data\n"); |
return 1; |
- } |
- |
+ } |
+ |
/* now parse the numcheckcpd lines to read in the remainder of the table */ |
char * nl = line; |
for (int j=0; j < numcheckcpd; j++) { |
@@ -3404,36 +3854,55 @@ |
if (!iterator->AdvanceAndCopy(nl, MAXLNLEN)) |
return 1; |
#else |
- if (!fgets(nl,MAXLNLEN,af)) return 1; |
+ if (!(nl = af->getline())) return 1; |
#endif |
mychomp(nl); |
tp = nl; |
i = 0; |
checkcpdtable[j].pattern = NULL; |
checkcpdtable[j].pattern2 = NULL; |
+ checkcpdtable[j].pattern3 = NULL; |
+ checkcpdtable[j].cond = FLAG_NULL; |
+ checkcpdtable[j].cond2 = FLAG_NULL; |
piece = mystrsep(&tp, 0); |
while (piece) { |
if (*piece != '\0') { |
switch(i) { |
case 0: { |
if (strncmp(piece,"CHECKCOMPOUNDPATTERN",20) != 0) { |
- HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ numcheckcpd = 0; |
return 1; |
} |
break; |
} |
- case 1: { checkcpdtable[j].pattern = mystrdup(piece); break; } |
- case 2: { checkcpdtable[j].pattern2 = mystrdup(piece); break; } |
+ case 1: { |
+ checkcpdtable[j].pattern = mystrdup(piece); |
+ char * p = strchr(checkcpdtable[j].pattern, '/'); |
+ if (p) { |
+ *p = '\0'; |
+ checkcpdtable[j].cond = pHMgr->decode_flag(p + 1); |
+ } |
+ break; } |
+ case 2: { |
+ checkcpdtable[j].pattern2 = mystrdup(piece); |
+ char * p = strchr(checkcpdtable[j].pattern2, '/'); |
+ if (p) { |
+ *p = '\0'; |
+ checkcpdtable[j].cond2 = pHMgr->decode_flag(p + 1); |
+ } |
+ break; |
+ } |
+ case 3: { checkcpdtable[j].pattern3 = mystrdup(piece); simplifiedcpd = 1; break; } |
default: break; |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if ((!(checkcpdtable[j].pattern)) || (!(checkcpdtable[j].pattern2))) { |
- HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n"); |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ numcheckcpd = 0; |
return 1; |
} |
} |
@@ -3444,11 +3913,11 @@ |
#ifdef HUNSPELL_CHROME_CLIENT |
int AffixMgr::parse_defcpdtable(char * line, hunspell::LineIterator* iterator) |
#else |
-int AffixMgr::parse_defcpdtable(char * line, FILE * af) |
+int AffixMgr::parse_defcpdtable(char * line, FileMgr * af) |
#endif |
{ |
if (numdefcpd != 0) { |
- HUNSPELL_WARNING(stderr, "error: duplicate compound rule tables used\n"); |
+ HUNSPELL_WARNING(stderr, "error: multiple table definitions\n"); |
return 1; |
} |
char * tp = line; |
@@ -3463,8 +3932,7 @@ |
case 1: { |
numdefcpd = atoi(piece); |
if (numdefcpd < 1) { |
- HUNSPELL_WARNING(stderr, "incorrect number of entries in compound rule table\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: bad entry number\n"); |
return 1; |
} |
defcpdtable = (flagentry *) malloc(numdefcpd * sizeof(flagentry)); |
@@ -3476,11 +3944,10 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if (np != 2) { |
- HUNSPELL_WARNING(stderr, "error: missing compound rule table information\n"); |
+ HUNSPELL_WARNING(stderr, "error: missing data\n"); |
return 1; |
} |
@@ -3491,7 +3958,7 @@ |
if (!iterator->AdvanceAndCopy(nl, MAXLNLEN)) |
return 1; |
#else |
- if (!fgets(nl,MAXLNLEN,af)) return 1; |
+ if (!(nl = af->getline())) return 1; |
#endif |
mychomp(nl); |
tp = nl; |
@@ -3503,26 +3970,46 @@ |
switch(i) { |
case 0: { |
if (strncmp(piece, "COMPOUNDRULE", 12) != 0) { |
- HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ numdefcpd = 0; |
return 1; |
} |
break; |
} |
- case 1: { |
- defcpdtable[j].len = |
- pHMgr->decode_flags(&(defcpdtable[j].def), piece); |
+ case 1: { // handle parenthesized flags |
+ if (strchr(piece, '(')) { |
+ defcpdtable[j].def = (FLAG *) malloc(sizeof(piece) * sizeof(FLAG)); |
+ defcpdtable[j].len = 0; |
+ int end = 0; |
+ FLAG * conv; |
+ while (!end) { |
+ char * par = piece + 1; |
+ while (*par != '(' && *par != ')' && *par != '\0') par++; |
+ if (*par == '\0') end = 1; else *par = '\0'; |
+ if (*piece == '(') piece++; |
+ if (*piece == '*' || *piece == '?') { |
+ defcpdtable[j].def[defcpdtable[j].len++] = (FLAG) *piece; |
+ } else if (*piece != '\0') { |
+ int l = pHMgr->decode_flags(&conv, piece); |
+ for (int k = 0; k < l; k++) defcpdtable[j].def[defcpdtable[j].len++] = conv[k]; |
+ free(conv); |
+ } |
+ piece = par + 1; |
+ } |
+ } else { |
+ defcpdtable[j].len = pHMgr->decode_flags(&(defcpdtable[j].def), piece); |
+ } |
break; |
} |
default: break; |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if (!defcpdtable[j].len) { |
- HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n"); |
+ HUNSPELL_WARNING(stderr, "error: line table is corrupt\n"); |
+ numdefcpd = 0; |
return 1; |
} |
} |
@@ -3534,11 +4021,11 @@ |
#ifdef HUNSPELL_CHROME_CLIENT |
int AffixMgr::parse_maptable(char * line, hunspell::LineIterator* iterator) |
#else |
-int AffixMgr::parse_maptable(char * line, FILE * af) |
+int AffixMgr::parse_maptable(char * line, FileMgr * af) |
#endif |
{ |
if (nummap != 0) { |
- HUNSPELL_WARNING(stderr, "error: duplicate MAP tables used\n"); |
+ HUNSPELL_WARNING(stderr, "error: multiple table definitions\n"); |
return 1; |
} |
char * tp = line; |
@@ -3553,8 +4040,7 @@ |
case 1: { |
nummap = atoi(piece); |
if (nummap < 1) { |
- HUNSPELL_WARNING(stderr, "incorrect number of entries in map table\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: bad entry number\n"); |
return 1; |
} |
maptable = (mapentry *) malloc(nummap * sizeof(struct mapentry)); |
@@ -3566,11 +4052,10 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if (np != 2) { |
- HUNSPELL_WARNING(stderr, "error: missing map table information\n"); |
+ HUNSPELL_WARNING(stderr, "error: line missing data\n"); |
return 1; |
} |
@@ -3581,7 +4066,7 @@ |
if (!iterator->AdvanceAndCopy(nl, MAXLNLEN)) |
return 1; |
#else |
- if (!fgets(nl,MAXLNLEN,af)) return 1; |
+ if (!(nl = af->getline())) return 1; |
#endif |
mychomp(nl); |
tp = nl; |
@@ -3594,8 +4079,8 @@ |
switch(i) { |
case 0: { |
if (strncmp(piece,"MAP",3) != 0) { |
- HUNSPELL_WARNING(stderr, "error: map table is corrupt\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ nummap = 0; |
return 1; |
} |
break; |
@@ -3623,11 +4108,11 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if ((!(maptable[j].set || maptable[j].set_utf16)) || (!(maptable[j].len))) { |
- HUNSPELL_WARNING(stderr, "error: map table is corrupt\n"); |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ nummap = 0; |
return 1; |
} |
} |
@@ -3638,11 +4123,11 @@ |
#ifdef HUNSPELL_CHROME_CLIENT |
int AffixMgr::parse_breaktable(char * line, hunspell::LineIterator* iterator) |
#else |
-int AffixMgr::parse_breaktable(char * line, FILE * af) |
+int AffixMgr::parse_breaktable(char * line, FileMgr * af) |
#endif |
{ |
if (numbreak != 0) { |
- HUNSPELL_WARNING(stderr, "error: duplicate word breakpoint tables used\n"); |
+ HUNSPELL_WARNING(stderr, "error: multiple table definitions\n"); |
return 1; |
} |
char * tp = line; |
@@ -3657,8 +4142,7 @@ |
case 1: { |
numbreak = atoi(piece); |
if (numbreak < 1) { |
- HUNSPELL_WARNING(stderr, "incorrect number of entries in BREAK table\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: bad entry number\n"); |
return 1; |
} |
breaktable = (char **) malloc(numbreak * sizeof(char *)); |
@@ -3670,11 +4154,10 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if (np != 2) { |
- HUNSPELL_WARNING(stderr, "error: missing word breakpoint table information\n"); |
+ HUNSPELL_WARNING(stderr, "error: missing data\n"); |
return 1; |
} |
@@ -3685,7 +4168,7 @@ |
if (!iterator->AdvanceAndCopy(nl, MAXLNLEN)) |
return 1; |
#else |
- if (!fgets(nl,MAXLNLEN,af)) return 1; |
+ if (!(nl = af->getline())) return 1; |
#endif |
mychomp(nl); |
tp = nl; |
@@ -3696,8 +4179,8 @@ |
switch(i) { |
case 0: { |
if (strncmp(piece,"BREAK",5) != 0) { |
- HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n"); |
- free(piece); |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ numbreak = 0; |
return 1; |
} |
break; |
@@ -3710,21 +4193,45 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
if (!breaktable) { |
- HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n"); |
+ HUNSPELL_WARNING(stderr, "error: table is corrupt\n"); |
+ numbreak = 0; |
return 1; |
} |
} |
return 0; |
} |
+void AffixMgr::reverse_condition(char * piece) { |
+ int neg = 0; |
+ for (char * k = piece + strlen(piece) - 1; k >= piece; k--) { |
+ switch(*k) { |
+ case '[': { |
+ if (neg) *(k+1) = '['; else *k = ']'; |
+ break; |
+ } |
+ case ']': { |
+ *k = '['; |
+ if (neg) *(k+1) = '^'; |
+ neg = 0; |
+ break; |
+ } |
+ case '^': { |
+ if (*(k+1) == ']') neg = 1; else *(k+1) = *k; |
+ break; |
+ } |
+ default: { |
+ if (neg) *(k+1) = *k; |
+ } |
+ } |
+ } |
+} |
#ifdef HUNSPELL_CHROME_CLIENT |
int AffixMgr::parse_affix(char * line, const char at, hunspell::LineIterator* iterator) |
#else |
-int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflags) |
+int AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupflags) |
#endif |
{ |
int numents = 0; // number of affentry structures to parse |
@@ -3748,6 +4255,7 @@ |
// split affix header line into pieces |
int np = 0; |
+ |
piece = mystrsep(&tp, 0); |
while (piece) { |
if (*piece != '\0') { |
@@ -3762,10 +4270,11 @@ |
#ifndef HUNSPELL_CHROME_CLIENT // We don't check for duplicates. |
if (((at == 'S') && (dupflags[aflag] & dupSFX)) || |
((at == 'P') && (dupflags[aflag] & dupPFX))) { |
- HUNSPELL_WARNING(stderr, "error: duplicate affix flag %s in line %s\n", piece, nl); |
+ HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions of an affix flag\n", |
+ af->getlinenum()); |
// return 1; XXX permissive mode for bad dictionaries |
} |
- dupflags[aflag] += ((at == 'S') ? dupSFX : dupPFX); |
+ dupflags[aflag] += (char) ((at == 'S') ? dupSFX : dupPFX); |
#endif |
break; |
} |
@@ -3778,19 +4287,18 @@ |
numents = atoi(piece); |
if (numents == 0) { |
char * err = pHMgr->encode_flag(aflag); |
- HUNSPELL_WARNING(stderr, "error: affix %s header has incorrect entry count in line %s\n", |
- err, nl); |
- free(err); |
+ if (err) { |
+ HUNSPELL_WARNING(stderr, "error: line bad entry number\n"); |
+ free(err); |
+ } |
return 1; |
} |
- ptr = (struct affentry *) calloc(numents, sizeof(struct affentry)); |
+ ptr = (struct affentry *) malloc(numents * sizeof(struct affentry)); |
if (!ptr) return 1; |
ptr->opts = ff; |
if (utf8) ptr->opts += aeUTF8; |
if (pHMgr->is_aliasf()) ptr->opts += aeALIASF; |
-#ifdef HUNSPELL_EXPERIMENTAL |
if (pHMgr->is_aliasm()) ptr->opts += aeALIASM; |
-#endif |
ptr->aflag = aflag; |
} |
@@ -3798,14 +4306,15 @@ |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
// check to make sure we parsed enough pieces |
if (np != 4) { |
- char * err = pHMgr->encode_flag(aflag); |
- HUNSPELL_WARNING(stderr, "error: affix %s header has insufficient data in line %s\n", err, nl); |
- free(err); |
+ char * err = pHMgr->encode_flag(aflag); |
+ if (err) { |
+ HUNSPELL_WARNING(stderr, "error: missing data\n"); |
+ free(err); |
+ } |
free(ptr); |
return 1; |
} |
@@ -3819,7 +4328,7 @@ |
if (!iterator->AdvanceAndCopy(nl, MAXLNLEN)) |
return 1; |
#else |
- if (!fgets(nl,MAXLNLEN,af)) return 1; |
+ if (!(nl = af->getline())) return 1; |
#endif |
mychomp(nl); |
tp = nl; |
@@ -3834,7 +4343,8 @@ |
// piece 1 - is type |
case 0: { |
np++; |
- if (nptr != ptr) nptr->opts = ptr->opts; |
+ if (nptr != ptr) nptr->opts = ptr->opts & |
+ (char) (aeXPRODUCT + aeUTF8 + aeALIASF + aeALIASM); |
break; |
} |
@@ -3843,10 +4353,10 @@ |
np++; |
if (pHMgr->decode_flag(piece) != aflag) { |
char * err = pHMgr->encode_flag(aflag); |
- HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl); |
- HUNSPELL_WARNING(stderr, "error: possible incorrect count\n"); |
- free(err); |
- free(piece); |
+ if (err) { |
+ HUNSPELL_WARNING(stderr, "error: affix %s is corrupt\n", err); |
+ free(err); |
+ } |
return 1; |
} |
@@ -3873,9 +4383,7 @@ |
// piece 4 - is affix string or 0 for null |
case 3: { |
char * dash; |
-#ifdef HUNSPELL_EXPERIMENTAL |
nptr->morphcode = NULL; |
-#endif |
nptr->contclass = NULL; |
nptr->contclasslen = 0; |
np++; |
@@ -3890,15 +4398,16 @@ |
remove_ignored_chars(piece,ignorechars); |
} |
} |
- |
+ |
if (complexprefixes) { |
if (utf8) reverseword_utf(piece); else reverseword(piece); |
} |
nptr->appnd = mystrdup(piece); |
- |
+ |
if (pHMgr->is_aliasf()) { |
int index = atoi(dash + 1); |
nptr->contclasslen = (unsigned short) pHMgr->get_aliasf(index, &(nptr->contclass)); |
+ if (!nptr->contclasslen) HUNSPELL_WARNING(stderr, "error: bad affix flag alias: \"%s\"\n", dash+1); |
} else { |
nptr->contclasslen = (unsigned short) pHMgr->decode_flags(&(nptr->contclass), dash + 1); |
flag_qsort(nptr->contclass, 0, nptr->contclasslen); |
@@ -3921,9 +4430,9 @@ |
if (complexprefixes) { |
if (utf8) reverseword_utf(piece); else reverseword(piece); |
} |
- nptr->appnd = mystrdup(piece); |
+ nptr->appnd = mystrdup(piece); |
} |
- |
+ |
nptr->appndl = (unsigned char) strlen(nptr->appnd); |
if (strcmp(nptr->appnd,"0") == 0) { |
free(nptr->appnd); |
@@ -3937,82 +4446,66 @@ |
case 4: { |
np++; |
if (complexprefixes) { |
- int neg = 0; |
if (utf8) reverseword_utf(piece); else reverseword(piece); |
- // reverse condition |
- for (char * k = piece + strlen(piece) - 1; k >= piece; k--) { |
- switch(*k) { |
- case '[': { |
- if (neg) *(k+1) = '['; else *k = ']'; |
- break; |
- } |
- case ']': { |
- *k = '['; |
- if (neg) *(k+1) = '^'; |
- neg = 0; |
- break; |
- } |
- case '^': { |
- if (*(k+1) == ']') neg = 1; else *(k+1) = *k; |
- break; |
- } |
- default: { |
- if (neg) *(k+1) = *k; |
- } |
- } |
- } |
+ reverse_condition(piece); |
} |
if (nptr->stripl && (strcmp(piece, ".") != 0) && |
- redundant_condition(at, nptr->strip, nptr->stripl, piece, nl)) |
+ redundant_condition(at, nptr->strip, nptr->stripl, piece, 0)) |
strcpy(piece, "."); |
- if (encodeit(nptr,piece)) return 1; |
+ if (at == 'S') { |
+ reverseword(piece); |
+ reverse_condition(piece); |
+ } |
+ if (encodeit(nptr, piece)) return 1; |
break; |
} |
- |
-#ifdef HUNSPELL_EXPERIMENTAL |
+ |
case 5: { |
np++; |
if (pHMgr->is_aliasm()) { |
int index = atoi(piece); |
nptr->morphcode = pHMgr->get_aliasm(index); |
} else { |
- if (complexprefixes) { |
+ if (complexprefixes) { // XXX - fix me for morph. gen. |
if (utf8) reverseword_utf(piece); else reverseword(piece); |
} |
+ // add the remaining of the line |
+ if (*tp) { |
+ *(tp - 1) = ' '; |
+ tp = tp + strlen(tp); |
+ } |
nptr->morphcode = mystrdup(piece); |
+ if (!nptr->morphcode) return 1; |
} |
break; |
} |
-#endif |
- |
default: break; |
} |
i++; |
} |
- free(piece); |
piece = mystrsep(&tp, 0); |
} |
// check to make sure we parsed enough pieces |
if (np < 4) { |
char * err = pHMgr->encode_flag(aflag); |
- HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl); |
- free(err); |
+ if (err) { |
+ HUNSPELL_WARNING(stderr, "error: affix %s is corrupt\n", err); |
+ free(err); |
+ } |
free(ptr); |
return 1; |
} |
#ifdef DEBUG |
-#ifdef HUNSPELL_EXPERIMENTAL |
// detect unnecessary fields, excepting comments |
if (basefieldnum) { |
int fieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6); |
if (fieldnum != basefieldnum) |
- HUNSPELL_WARNING(stderr, "warning: bad field number:\n%s\n", nl); |
+ HUNSPELL_WARNING(stderr, "warning: line %d: bad field number\n", af->getlinenum()); |
} else { |
basefieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6); |
} |
#endif |
-#endif |
nptr++; |
} |
@@ -4028,12 +4521,12 @@ |
build_sfxtree((AffEntry *)sfxptr); |
} |
nptr++; |
- } |
+ } |
free(ptr); |
return 0; |
} |
-int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char * cond, char * line) { |
+int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char * cond, int linenum) { |
int condl = strlen(cond); |
int i; |
int j; |
@@ -4046,7 +4539,8 @@ |
for (i = 0, j = 0; (i < stripl) && (j < condl); i++, j++) { |
if (cond[j] != '[') { |
if (cond[j] != strip[i]) { |
- HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", line); |
+ HUNSPELL_WARNING(stderr, "warning: line %d: incompatible stripping characters and condition\n", linenum); |
+ return 0; |
} |
} else { |
neg = (cond[j+1] == '^') ? 1 : 0; |
@@ -4056,12 +4550,12 @@ |
if (strip[i] == cond[j]) in = 1; |
} while ((j < (condl - 1)) && (cond[j] != ']')); |
if (j == (condl - 1) && (cond[j] != ']')) { |
- HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", line); |
+ HUNSPELL_WARNING(stderr, "error: line %d: missing ] in condition:\n%s\n", linenum); |
return 0; |
} |
if ((!neg && !in) || (neg && in)) { |
- HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", line); |
- return 0; |
+ HUNSPELL_WARNING(stderr, "warning: line %d: incompatible stripping characters and condition\n", linenum); |
+ return 0; |
} |
} |
} |
@@ -4074,7 +4568,8 @@ |
for (i = stripl - 1, j = condl - 1; (i >= 0) && (j >= 0); i--, j--) { |
if (cond[j] != ']') { |
if (cond[j] != strip[i]) { |
- HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", line); |
+ HUNSPELL_WARNING(stderr, "warning: line %d: incompatible stripping characters and condition\n", linenum); |
+ return 0; |
} |
} else { |
in = 0; |
@@ -4083,18 +4578,18 @@ |
if (strip[i] == cond[j]) in = 1; |
} while ((j > 0) && (cond[j] != '[')); |
if ((j == 0) && (cond[j] != '[')) { |
- HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", line); |
+ HUNSPELL_WARNING(stderr, "error: error: %d: missing ] in condition:\n%s\n", linenum); |
return 0; |
} |
neg = (cond[j+1] == '^') ? 1 : 0; |
if ((!neg && !in) || (neg && in)) { |
- HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", line); |
- return 0; |
+ HUNSPELL_WARNING(stderr, "warning: line %d: incompatible stripping characters and condition\n", linenum); |
+ return 0; |
} |
} |
} |
if (j < 0) return 1; |
- } |
+ } |
} |
return 0; |
} |
Property changes on: chrome\third_party\hunspell\src\hunspell\affixmgr.cxx |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |