| 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
|
|
|
|
|