Conf->buildCxt = NULL;
Conf->Spell = NULL;
Conf->firstfree = NULL;
+ Conf->CompoundAffixFlags = NULL;
}
(*(SPELL *const *) s2)->p.flag));
}
+static int
+cmpcmdflag(const void *f1, const void *f2)
+{
+ CompoundAffixFlag *fv1 = (CompoundAffixFlag *) f1,
+ *fv2 = (CompoundAffixFlag *) f2;
+
+ Assert(fv1->flagMode == fv2->flagMode);
+
+ if (fv1->flagMode == FM_NUM)
+ {
+ if (fv1->flag.i == fv2->flag.i)
+ return 0;
+
+ return (fv1->flag.i > fv2->flag.i) ? 1 : -1;
+ }
+
+ return strcmp(fv1->flag.s, fv2->flag.s);
+}
+
static char *
findchar(char *str, int c)
{
}
/*
- * Gets an affix flag from string representation (a set of affixes).
+ * Gets an affix flag from the set of affix flags (sflagset).
*
* Several flags can be stored in a single string. Flags can be represented by:
- * - 1 character (FM_CHAR).
- * - 2 characters (FM_LONG).
+ * - 1 character (FM_CHAR). A character may be Unicode.
+ * - 2 characters (FM_LONG). A character may be Unicode.
* - numbers from 1 to 65000 (FM_NUM).
*
* Depending on the flagMode an affix string can have the following format:
* Here we have 3 flags: 200, 205 and 50
*
* Conf: current dictionary.
- * sflag: string representation (a set of affixes) of an affix flag.
- * sflagnext: returns reference to the start of a next affix flag in the sflag.
- *
- * Returns an integer representation of the affix flag.
+ * sflagset: the set of affix flags. Returns a reference to the start of a next
+ * affix flag.
+ * sflag: returns an affix flag from sflagset.
*/
-static uint16
-DecodeFlag(IspellDict *Conf, char *sflag, char **sflagnext)
+static void
+getNextFlagFromString(IspellDict *Conf, char **sflagset, char *sflag)
{
- int32 s;
- char *next;
- unsigned char *usflag;
+ int32 s;
+ char *next,
+ *sbuf = *sflagset;
+ int maxstep;
+ bool stop = false;
+ bool met_comma = false;
+
+ maxstep = (Conf->flagMode == FM_LONG) ? 2 : 1;
- switch (Conf->flagMode)
+ while(**sflagset)
{
- case FM_LONG:
- /*
- * Hunspell docs says flag could contains only
- * ASCII characters
- */
- if (!(pg_mblen(sflag) == 1 && isascii(sflag[0]) &&
- pg_mblen(sflag + 1) == 1 && isascii(sflag[1])))
- ereport(ERROR,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("non-ASCII affix flag \"%s\"", sflag)));
+ switch (Conf->flagMode)
+ {
+ case FM_LONG:
+ case FM_CHAR:
+ COPYCHAR(sflag, *sflagset);
+ sflag += pg_mblen(*sflagset);
- usflag = (unsigned char *)sflag;
- s = ((int)usflag[0]) << 8 | ((int)usflag[1]);
- if (sflagnext)
/* Go to start of the next flag */
- *sflagnext = sflag + 2;
- break;
- case FM_NUM:
- s = strtol(sflag, &next, 10);
- if (s <= 0 || s > FLAGNUM_MAXSIZE)
- ereport(ERROR,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("invalid affix flag \"%s\"", sflag)));
+ *sflagset += pg_mblen(*sflagset);
+
+ /* Check if we get all characters of flag */
+ maxstep--;
+ stop = (maxstep == 0);
+ break;
+ case FM_NUM:
+ s = strtol(*sflagset, &next, 10);
+ if (*sflagset == next || errno == ERANGE)
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("invalid affix flag \"%s\"", *sflagset)));
+ if (s < 0 || s > FLAGNUM_MAXSIZE)
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("affix flag \"%s\" is out of range",
+ *sflagset)));
+ sflag += sprintf(sflag, "%0d", s);
- if (sflagnext)
- {
/* Go to start of the next flag */
- if (next)
+ *sflagset = next;
+ while (**sflagset)
{
- bool met_comma = false;
-
- while (*next)
+ if (t_isdigit(*sflagset))
{
- if (!(pg_mblen(next) == 1 && isascii(*next)))
- {
+ if (!met_comma)
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("non-ASCII affix flag \"%s\"",
- sflag)));
- }
- else if (isdigit((unsigned char) *next))
- {
- if (!met_comma)
- ereport(ERROR,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("invalid affix flag \"%s\"",
- sflag)));
- break;
- }
- else if (*next == ',')
- {
- if (met_comma)
- ereport(ERROR,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("invalid affix flag \"%s\"",
- sflag)));
- met_comma = true;
- }
- else if (!isspace((unsigned char) *next))
- {
+ errmsg("invalid affix flag \"%s\"",
+ *sflagset)));
+ break;
+ }
+ else if (t_iseq(*sflagset, ','))
+ {
+ if (met_comma)
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("invalid character in affix flag \"%s\"", sflag)));
- }
-
- next++;
+ errmsg("invalid affix flag \"%s\"",
+ *sflagset)));
+ met_comma = true;
+ }
+ else if (!t_isspace(*sflagset))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("invalid character in affix flag \"%s\"",
+ *sflagset)));
}
- if (*next == '\0')
- next = NULL;
+ *sflagset += pg_mblen(*sflagset);
}
+ stop = true;
+ break;
+ default:
+ elog(ERROR, "unrecognized type of Conf->flagMode: %d",
+ Conf->flagMode);
+ }
- *sflagnext = next;
- }
+ if (stop)
break;
- default:
- if (!(pg_mblen(sflag) == 1 && isascii(*sflag)))
- ereport(ERROR,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("non-ASCII affix flag \"%s\"", sflag)));
-
- s = *sflag;
- if (sflagnext)
- /* Go to start of the next flag */
- *sflagnext = sflag + pg_mblen(sflag);
}
- return (uint16)s;
+ if (Conf->flagMode == FM_LONG && maxstep > 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("invalid affix flag \"%s\" with long flag value", sbuf)));
+
+ *sflag = '\0';
}
/*
* Checks if the affix set Conf->AffixData[affix] contains affixflag.
- * Conf->AffixData[affix] is the string representation of an affix flags.
* Conf->AffixData[affix] does not contain affixflag if this flag is not used
* actually by the .dict file.
*
* Conf: current dictionary.
* affix: index of the Conf->AffixData array.
- * affixflag: integer representation of the affix flag.
+ * affixflag: the affix flag.
*
* Returns true if the string Conf->AffixData[affix] contains affixflag,
* otherwise returns false.
*/
static bool
-IsAffixFlagInUse(IspellDict *Conf, int affix, uint16 affixflag)
+IsAffixFlagInUse(IspellDict *Conf, int affix, char *affixflag)
{
- char *flagcur;
- char *flagnext = NULL;
+ char *flagcur;
+ char flag[BUFSIZ];
- if (affixflag == 0)
+ if (*affixflag == 0)
return true;
flagcur = Conf->AffixData[affix];
while (*flagcur)
{
+ getNextFlagFromString(Conf, &flagcur, flag);
/* Compare first affix flag in flagcur with affixflag */
- if (DecodeFlag(Conf, flagcur, &flagnext) == affixflag)
+ if (strcmp(flag, affixflag) == 0)
return true;
- /* Otherwise go to next flag */
- if (flagnext)
- flagcur = flagnext;
- /* If we have not flags anymore then exit */
- else
- break;
}
/* Could not find affixflag */
*
* Conf: current dictionary.
* word: new word.
- * flag: set of affix flags. Integer representation of flag can be got by
- * DecodeFlag().
+ * flag: set of affix flags. Single flag can be get by getNextFlagFromString().
*/
static void
NIAddSpell(IspellDict *Conf, const char *word, const char *flag)
*
* Conf: current dictionary.
* word: basic form of word.
- * affixflag: integer representation of the affix flag, by which a basic form of
- * word was generated.
+ * affixflag: affix flag, by which a basic form of word was generated.
* flag: compound flag used to compare with StopMiddle->compoundflag.
*
* Returns 1 if the word was found in the prefix tree, else returns 0.
*/
static int
-FindWord(IspellDict *Conf, const char *word, int affixflag, int flag)
+FindWord(IspellDict *Conf, const char *word, char *affixflag, int flag)
{
SPNode *node = Conf->Dictionary;
SPNodeData *StopLow,
*StopMiddle;
const uint8 *ptr = (const uint8 *) word;
- flag &= FF_DICTFLAGMASK;
+ flag &= FF_COMPOUNDFLAGMASK;
while (node && *ptr)
{
* Adds a new affix rule to the Affix field.
*
* Conf: current dictionary.
- * flag: integer representation of the affix flag ('\' in the below example).
+ * flag: affix flag ('\' in the below example).
* flagflags: set of flags from the flagval field for this affix rule. This set
* is listed after '/' character in the added string (repl).
*
* type: FF_SUFFIX or FF_PREFIX.
*/
static void
-NIAddAffix(IspellDict *Conf, int flag, char flagflags, const char *mask, const char *find, const char *repl, int type)
+NIAddAffix(IspellDict *Conf, const char* flag, char flagflags, const char *mask,
+ const char *find, const char *repl, int type)
{
AFFIX *Affix;
if ((Affix->flagflags & FF_COMPOUNDFLAG) == 0)
Affix->flagflags |= FF_COMPOUNDFLAG;
}
- Affix->flag = flag;
+ Affix->flag = cpstrdup(Conf, flag);
Affix->type = type;
Affix->find = (find && *find) ? cpstrdup(Conf, find) : VoidString;
return (*mask && (*find || *repl));
}
+/*
+ * Sets a Hunspell options depending on flag type.
+ */
+static void
+setCompoundAffixFlagValue(IspellDict *Conf, CompoundAffixFlag *entry,
+ char *s, uint32 val)
+{
+ if (Conf->flagMode == FM_NUM)
+ {
+ char *next;
+ int i;
+
+ i = strtol(s, &next, 10);
+ if (s == next || errno == ERANGE)
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("invalid affix flag \"%s\"", s)));
+ if (i < 0 || i > FLAGNUM_MAXSIZE)
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("affix flag \"%s\" is out of range", s)));
+
+ entry->flag.i = i;
+ }
+ else
+ entry->flag.s = cpstrdup(Conf, s);
+
+ entry->flagMode = Conf->flagMode;
+ entry->value = val;
+}
+
/*
* Sets up a correspondence for the affix parameter with the affix flag.
*
* val: affix parameter.
*/
static void
-addFlagValue(IspellDict *Conf, char *s, uint32 val)
+addCompoundAffixFlagValue(IspellDict *Conf, char *s, uint32 val)
{
+ CompoundAffixFlag *newValue;
+ char sbuf[BUFSIZ];
+ char *sflag;
+ int clen;
+
while (*s && t_isspace(s))
s += pg_mblen(s);
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("syntax error")));
- if (pg_mblen(s) != 1)
- ereport(ERROR,
- (errcode(ERRCODE_CONFIG_FILE_ERROR),
- errmsg("multibyte flag character is not allowed")));
+ /* Get flag without \n */
+ sflag = sbuf;
+ while (*s && !t_isspace(s) && *s != '\n')
+ {
+ clen = pg_mblen(s);
+ COPYCHAR(sflag, s);
+ sflag += clen;
+ s += clen;
+ }
+ *sflag = '\0';
+
+ /* Resize array or allocate memory for array CompoundAffixFlag */
+ if (Conf->nCompoundAffixFlag >= Conf->mCompoundAffixFlag)
+ {
+ if (Conf->mCompoundAffixFlag)
+ {
+ Conf->mCompoundAffixFlag *= 2;
+ Conf->CompoundAffixFlags = (CompoundAffixFlag *)
+ repalloc((void *) Conf->CompoundAffixFlags,
+ Conf->mCompoundAffixFlag * sizeof(CompoundAffixFlag));
+ }
+ else
+ {
+ Conf->mCompoundAffixFlag = 10;
+ Conf->CompoundAffixFlags = (CompoundAffixFlag *)
+ tmpalloc(Conf->mCompoundAffixFlag * sizeof(CompoundAffixFlag));
+ }
+ }
+
+ newValue = Conf->CompoundAffixFlags + Conf->nCompoundAffixFlag;
+
+ setCompoundAffixFlagValue(Conf, newValue, sbuf, val);
- Conf->flagval[DecodeFlag(Conf, s, (char **)NULL)] = (unsigned char) val;
Conf->usecompound = true;
+ Conf->nCompoundAffixFlag++;
}
/*
* flags s.
*/
static int
-getFlagValues(IspellDict *Conf, char *s)
+getCompoundAffixFlagValue(IspellDict *Conf, char *s)
{
- uint32 flag = 0;
- char *flagcur;
- char *flagnext = NULL;
+ uint32 flag = 0;
+ CompoundAffixFlag *found,
+ key;
+ char sflag[BUFSIZ];
+ char *flagcur;
+
+ if (Conf->nCompoundAffixFlag == 0)
+ return 0;
flagcur = s;
while (*flagcur)
{
- flag |= Conf->flagval[DecodeFlag(Conf, flagcur, &flagnext)];
- if (flagnext)
- flagcur = flagnext;
- else
- break;
+ getNextFlagFromString(Conf, &flagcur, sflag);
+ setCompoundAffixFlagValue(Conf, &key, sflag, 0);
+
+ found = (CompoundAffixFlag *)
+ bsearch(&key, (void *) Conf->CompoundAffixFlags,
+ Conf->nCompoundAffixFlag, sizeof(CompoundAffixFlag),
+ cmpcmdflag);
+ if (found != NULL)
+ flag |= found->value;
}
return flag;
* Else function returns the s parameter.
*/
static char *
-getFlags(IspellDict *Conf, char *s)
+getAffixFlagSet(IspellDict *Conf, char *s)
{
- if (Conf->useFlagAliases)
+ if (Conf->useFlagAliases && *s != '\0')
{
- int curaffix = strtol(s, (char **)NULL, 10);
+ int curaffix;
+ char *end;
- if (curaffix && curaffix <= Conf->nAffixData)
+ curaffix = strtol(s, &end, 10);
+ if (s == end || errno == ERANGE)
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("invalid affix alias \"%s\"", s)));
+
+ if (curaffix > 0 && curaffix <= Conf->nAffixData)
/*
* Do not substract 1 from curaffix
* because empty string was added in NIImportOOAffixes
bool isSuffix = false;
int naffix = 0,
curaffix = 0;
- int flag = 0,
- sflaglen = 0;
+ int sflaglen = 0;
char flagflags = 0;
tsearch_readline_state trst;
char *recoded;
/* read file to find any flag */
- memset(Conf->flagval, 0, sizeof(Conf->flagval));
Conf->usecompound = false;
Conf->useFlagAliases = false;
Conf->flagMode = FM_CHAR;
}
if (STRNCMP(recoded, "COMPOUNDFLAG") == 0)
- addFlagValue(Conf, recoded + strlen("COMPOUNDFLAG"),
- FF_COMPOUNDFLAG);
+ addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDFLAG"),
+ FF_COMPOUNDFLAG);
else if (STRNCMP(recoded, "COMPOUNDBEGIN") == 0)
- addFlagValue(Conf, recoded + strlen("COMPOUNDBEGIN"),
- FF_COMPOUNDBEGIN);
+ addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDBEGIN"),
+ FF_COMPOUNDBEGIN);
else if (STRNCMP(recoded, "COMPOUNDLAST") == 0)
- addFlagValue(Conf, recoded + strlen("COMPOUNDLAST"),
- FF_COMPOUNDLAST);
+ addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDLAST"),
+ FF_COMPOUNDLAST);
/* COMPOUNDLAST and COMPOUNDEND are synonyms */
else if (STRNCMP(recoded, "COMPOUNDEND") == 0)
- addFlagValue(Conf, recoded + strlen("COMPOUNDEND"),
- FF_COMPOUNDLAST);
+ addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDEND"),
+ FF_COMPOUNDLAST);
else if (STRNCMP(recoded, "COMPOUNDMIDDLE") == 0)
- addFlagValue(Conf, recoded + strlen("COMPOUNDMIDDLE"),
- FF_COMPOUNDMIDDLE);
+ addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDMIDDLE"),
+ FF_COMPOUNDMIDDLE);
else if (STRNCMP(recoded, "ONLYINCOMPOUND") == 0)
- addFlagValue(Conf, recoded + strlen("ONLYINCOMPOUND"),
- FF_COMPOUNDONLY);
+ addCompoundAffixFlagValue(Conf, recoded + strlen("ONLYINCOMPOUND"),
+ FF_COMPOUNDONLY);
else if (STRNCMP(recoded, "COMPOUNDPERMITFLAG") == 0)
- addFlagValue(Conf, recoded + strlen("COMPOUNDPERMITFLAG"),
- FF_COMPOUNDPERMITFLAG);
+ addCompoundAffixFlagValue(Conf,
+ recoded + strlen("COMPOUNDPERMITFLAG"),
+ FF_COMPOUNDPERMITFLAG);
else if (STRNCMP(recoded, "COMPOUNDFORBIDFLAG") == 0)
- addFlagValue(Conf, recoded + strlen("COMPOUNDFORBIDFLAG"),
- FF_COMPOUNDFORBIDFLAG);
+ addCompoundAffixFlagValue(Conf,
+ recoded + strlen("COMPOUNDFORBIDFLAG"),
+ FF_COMPOUNDFORBIDFLAG);
else if (STRNCMP(recoded, "FLAG") == 0)
{
char *s = recoded + strlen("FLAG");
}
tsearch_readline_end(&trst);
+ if (Conf->nCompoundAffixFlag > 1)
+ qsort((void *) Conf->CompoundAffixFlags, Conf->nCompoundAffixFlag,
+ sizeof(CompoundAffixFlag), cmpcmdflag);
+
if (!tsearch_readline_begin(&trst, filename))
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
*/
if (fields_read == 4)
{
- /* Convert the affix flag to int */
- flag = DecodeFlag(Conf, sflag, (char **)NULL);
-
isSuffix = (STRNCMP(ptype, "sfx") == 0);
if (t_iseq(find, 'y') || t_iseq(find, 'Y'))
flagflags = FF_CROSSPRODUCT;
char *ptr;
int aflg = 0;
- if (flag == 0)
- goto nextline;
/* Get flags after '/' (flags are case sensitive) */
if ((ptr = strchr(repl, '/')) != NULL)
- aflg |= getFlagValues(Conf, getFlags(Conf, ptr + 1));
+ aflg |= getCompoundAffixFlagValue(Conf,
+ getAffixFlagSet(Conf,
+ ptr + 1));
/* Get lowercased version of string before '/' */
prepl = lowerstr_ctx(Conf, repl);
if ((ptr = strchr(prepl, '/')) != NULL)
if (t_iseq(repl, '0'))
*prepl = '\0';
- NIAddAffix(Conf, flag, flagflags | aflg, pmask, pfind, prepl,
+ NIAddAffix(Conf, sflag, flagflags | aflg, pmask, pfind, prepl,
isSuffix ? FF_SUFFIX : FF_PREFIX);
pfree(prepl);
pfree(pfind);
NIImportAffixes(IspellDict *Conf, const char *filename)
{
char *pstr = NULL;
+ char flag[BUFSIZ];
char mask[BUFSIZ];
char find[BUFSIZ];
char repl[BUFSIZ];
char *s;
bool suffixes = false;
bool prefixes = false;
- int flag = 0;
char flagflags = 0;
tsearch_readline_state trst;
bool oldformat = false;
errmsg("could not open affix file \"%s\": %m",
filename)));
- memset(Conf->flagval, 0, sizeof(Conf->flagval));
Conf->usecompound = false;
Conf->useFlagAliases = false;
Conf->flagMode = FM_CHAR;
if (*s && pg_mblen(s) == 1)
{
- Conf->flagval[*(unsigned char *) s] = FF_COMPOUNDFLAG;
+ addCompoundAffixFlagValue(Conf, s, FF_COMPOUNDFLAG);
Conf->usecompound = true;
}
oldformat = true;
*/
if (*s && pg_mblen(s) == 1)
{
- flag = *(unsigned char *) s;
+ COPYCHAR(flag, s);
+ flag[1] = '\0';
+
s++;
if (*s == '\0' || *s == '#' || *s == '\n' || *s == ':' ||
t_isspace(s))
makeCompoundFlags(IspellDict *Conf, int affix)
{
char *str = Conf->AffixData[affix];
- return (getFlagValues(Conf, str) & FF_DICTFLAGMASK);
+ return (getCompoundAffixFlagValue(Conf, str) & FF_COMPOUNDFLAGMASK);
}
/*
{
for (i = 0; i < Conf->nspell; i++)
{
- curaffix = strtol(Conf->Spell[i]->p.flag, (char **)NULL, 10);
- if (curaffix && curaffix <= Conf->nAffixData)
- Conf->Spell[i]->p.d.affix = curaffix;
+ char *end;
+
+ if (*Conf->Spell[i]->p.flag != '\0')
+ {
+ curaffix = strtol(Conf->Spell[i]->p.flag, &end, 10);
+ if (Conf->Spell[i]->p.flag == end || errno == ERANGE)
+ ereport(ERROR,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("invalid affix alias \"%s\"",
+ Conf->Spell[i]->p.flag)));
+ }
else
+ {
/*
* If Conf->Spell[i]->p.flag is empty, then get empty value of
* Conf->AffixData (0 index).
*/
- Conf->Spell[i]->p.d.affix = 0;
+ curaffix = 0;
+ }
+
+ Conf->Spell[i]->p.d.affix = curaffix;
Conf->Spell[i]->p.d.len = strlen(Conf->Spell[i]->word);
}
}
{
/* Count the number of different flags used in the dictionary */
qsort((void *) Conf->Spell, Conf->nspell, sizeof(SPELL *),
- cmpspellaffix);
+ cmpspellaffix);
naffix = 0;
for (i = 0; i < Conf->nspell; i++)
* contain affixflag if this flag is not used actually by the .dict file.
*
* Conf: current dictionary.
- * affixflag: integer representation of the affix flag.
+ * affixflag: affix flag.
*
* Returns true if the Conf->AffixData array contains affixflag, otherwise
* returns false.
*/
static bool
-isAffixInUse(IspellDict *Conf, uint16 affixflag)
+isAffixInUse(IspellDict *Conf, char *affixflag)
{
int i;
/* Check that the word itself is normal form */
- if (FindWord(Conf, word, 0, flag))
+ if (FindWord(Conf, word, VoidString, flag))
{
*cur = pstrdup(word);
cur++;
if (CheckAffix(newword, swrdlen, prefix->aff[j], flag, pnewword, &baselen))
{
/* prefix success */
- int ff = (prefix->aff[j]->flagflags & suffix->aff[i]->flagflags & FF_CROSSPRODUCT) ?
- 0 : prefix->aff[j]->flag;
+ char *ff = (prefix->aff[j]->flagflags & suffix->aff[i]->flagflags & FF_CROSSPRODUCT) ?
+ VoidString : prefix->aff[j]->flag;
if (FindWord(Conf, pnewword, ff, flag))
cur += addToResult(forms, cur, pnewword);