1818#define GETWCHAR (W ,L ,N ,T ) ( ((uint8*)(W))[ ((T)==FF_PREFIX) ? (N) : ( (L) - 1 - (N) ) ] )
1919#define GETCHAR (A ,N ,T ) GETWCHAR( (A)->repl, (A)->replen, N, T )
2020
21+ static char * VoidString = "" ;
2122
2223#define MEMOUT (X ) if ( !(X) ) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory")))
2324
2425static int
2526cmpspell (const void * s1 ,const void * s2 )
2627{
27- return (strcmp (((const SPELL * )s1 )-> word , ((const SPELL * )s2 )-> word ));
28+ return (strcmp ((* (const SPELL * * )s1 )-> word , (* (const SPELL * * )s2 )-> word ));
2829}
2930static int
3031cmpspellaffix (const void * s1 ,const void * s2 )
3132{
32- return (strcmp (((const SPELL * )s1 )-> p .flag , ((const SPELL * )s2 )-> p .flag ));
33+ return (strcmp ((* (const SPELL * * )s1 )-> p .flag , (* (const SPELL * * )s2 )-> p .flag ));
3334}
3435
3536static char *
@@ -128,18 +129,17 @@ NIAddSpell(IspellDict * Conf, const char *word, const char *flag)
128129if (Conf -> mspell )
129130{
130131Conf -> mspell += 1024 * 20 ;
131- Conf -> Spell = (SPELL * ) realloc (Conf -> Spell ,Conf -> mspell * sizeof (SPELL ));
132+ Conf -> Spell = (SPELL * * ) repalloc (Conf -> Spell ,Conf -> mspell * sizeof (SPELL * ));
132133}
133134else
134135{
135136Conf -> mspell = 1024 * 20 ;
136- Conf -> Spell = (SPELL * ) malloc (Conf -> mspell * sizeof (SPELL ));
137+ Conf -> Spell = (SPELL * * ) palloc (Conf -> mspell * sizeof (SPELL * ));
137138}
138- MEMOUT (Conf -> Spell );
139139}
140- Conf -> Spell [Conf -> nspell ]. word = strdup ( word );
141- MEMOUT ( Conf -> Spell [Conf -> nspell ]. word );
142- strncpy (Conf -> Spell [Conf -> nspell ]. p .flag ,flag ,16 );
140+ Conf -> Spell [Conf -> nspell ]= ( SPELL * ) palloc ( SPELLHDRSZ + strlen ( word ) + 1 );
141+ strcpy ( Conf -> Spell [Conf -> nspell ]-> word , word );
142+ strncpy (Conf -> Spell [Conf -> nspell ]-> p .flag ,flag ,16 );
143143Conf -> nspell ++ ;
144144return (0 );
145145}
@@ -261,13 +261,13 @@ NIAddAffix(IspellDict * Conf, int flag, char flagflags, const char *mask, const
261261{
262262Conf -> Affix [Conf -> naffixes ].issimple = 1 ;
263263Conf -> Affix [Conf -> naffixes ].isregis = 0 ;
264- Conf -> Affix [Conf -> naffixes ].mask = strdup ( "" ) ;
264+ Conf -> Affix [Conf -> naffixes ].mask = VoidString ;
265265}
266266else if (RS_isRegis (mask ))
267267{
268268Conf -> Affix [Conf -> naffixes ].issimple = 0 ;
269269Conf -> Affix [Conf -> naffixes ].isregis = 1 ;
270- Conf -> Affix [Conf -> naffixes ].mask = strdup (mask );
270+ Conf -> Affix [Conf -> naffixes ].mask = ( mask && * mask ) ? strdup (mask ) : VoidString ;
271271}
272272else
273273{
@@ -287,11 +287,13 @@ NIAddAffix(IspellDict * Conf, int flag, char flagflags, const char *mask, const
287287Conf -> Affix [Conf -> naffixes ].flag = flag ;
288288Conf -> Affix [Conf -> naffixes ].type = type ;
289289
290- Conf -> Affix [Conf -> naffixes ].find = strdup (find );
290+ Conf -> Affix [Conf -> naffixes ].find = ( find && * find ) ? strdup (find ) : VoidString ;
291291MEMOUT (Conf -> Affix [Conf -> naffixes ].find );
292- Conf -> Affix [Conf -> naffixes ].repl = strdup (repl );
293- MEMOUT (Conf -> Affix [Conf -> naffixes ].repl );
294- Conf -> Affix [Conf -> naffixes ].replen = strlen (repl );
292+ if ( (Conf -> Affix [Conf -> naffixes ].replen = strlen (repl ))> 0 ) {
293+ Conf -> Affix [Conf -> naffixes ].repl = strdup (repl );
294+ MEMOUT (Conf -> Affix [Conf -> naffixes ].repl );
295+ }else
296+ Conf -> Affix [Conf -> naffixes ].repl = VoidString ;
295297Conf -> naffixes ++ ;
296298return (0 );
297299}
@@ -506,10 +508,10 @@ mkSPNode(IspellDict * Conf, int low, int high, int level)
506508int lownew = low ;
507509
508510for (i = low ;i < high ;i ++ )
509- if (Conf -> Spell [i ]. p .d .len > level && lastchar != Conf -> Spell [i ]. word [level ])
511+ if (Conf -> Spell [i ]-> p .d .len > level && lastchar != Conf -> Spell [i ]-> word [level ])
510512{
511513nchar ++ ;
512- lastchar = Conf -> Spell [i ]. word [level ];
514+ lastchar = Conf -> Spell [i ]-> word [level ];
513515}
514516
515517if (!nchar )
@@ -523,34 +525,34 @@ mkSPNode(IspellDict * Conf, int low, int high, int level)
523525
524526lastchar = '\0' ;
525527for (i = low ;i < high ;i ++ )
526- if (Conf -> Spell [i ]. p .d .len > level )
528+ if (Conf -> Spell [i ]-> p .d .len > level )
527529{
528- if (lastchar != Conf -> Spell [i ]. word [level ])
530+ if (lastchar != Conf -> Spell [i ]-> word [level ])
529531{
530532if (lastchar )
531533{
532534data -> node = mkSPNode (Conf ,lownew ,i ,level + 1 );
533535lownew = i ;
534536data ++ ;
535537}
536- lastchar = Conf -> Spell [i ]. word [level ];
538+ lastchar = Conf -> Spell [i ]-> word [level ];
537539}
538- data -> val = ((uint8 * ) (Conf -> Spell [i ]. word ))[level ];
539- if (Conf -> Spell [i ]. p .d .len == level + 1 )
540+ data -> val = ((uint8 * ) (Conf -> Spell [i ]-> word ))[level ];
541+ if (Conf -> Spell [i ]-> p .d .len == level + 1 )
540542{
541- if (data -> isword && data -> affix != Conf -> Spell [i ]. p .d .affix )
543+ if (data -> isword && data -> affix != Conf -> Spell [i ]-> p .d .affix )
542544{
543545/*
544546 * fprintf(stderr,"Word already exists: %s (affixes: '%s'
545- * and '%s')\n", Conf->Spell[i]. word,
547+ * and '%s')\n", Conf->Spell[i]-> word,
546548 * Conf->AffixData[data->affix],
547- * Conf->AffixData[Conf->Spell[i]. p.d.affix] );
549+ * Conf->AffixData[Conf->Spell[i]-> p.d.affix] );
548550 */
549551/* MergeAffix called a few times */
550- data -> affix = MergeAffix (Conf ,data -> affix ,Conf -> Spell [i ]. p .d .affix );
552+ data -> affix = MergeAffix (Conf ,data -> affix ,Conf -> Spell [i ]-> p .d .affix );
551553}
552554else
553- data -> affix = Conf -> Spell [i ]. p .d .affix ;
555+ data -> affix = Conf -> Spell [i ]-> p .d .affix ;
554556data -> isword = 1 ;
555557if (strchr (Conf -> AffixData [data -> affix ],Conf -> compoundcontrol ))
556558data -> compoundallow = 1 ;
@@ -562,18 +564,16 @@ mkSPNode(IspellDict * Conf, int low, int high, int level)
562564return rs ;
563565}
564566
565-
566-
567567void
568568NISortDictionary (IspellDict * Conf )
569569{
570570size_t i ;
571571int naffix = 3 ;
572572
573573/* compress affixes */
574- qsort ((void * )Conf -> Spell ,Conf -> nspell ,sizeof (SPELL ),cmpspellaffix );
574+ qsort ((void * )Conf -> Spell ,Conf -> nspell ,sizeof (SPELL * ),cmpspellaffix );
575575for (i = 1 ;i < Conf -> nspell ;i ++ )
576- if (strcmp (Conf -> Spell [i ]. p .flag ,Conf -> Spell [i - 1 ]. p .flag ))
576+ if (strcmp (Conf -> Spell [i ]-> p .flag ,Conf -> Spell [i - 1 ]-> p .flag ))
577577naffix ++ ;
578578
579579Conf -> AffixData = (char * * )malloc (naffix * sizeof (char * ));
@@ -582,28 +582,28 @@ NISortDictionary(IspellDict * Conf)
582582naffix = 1 ;
583583Conf -> AffixData [0 ]= strdup ("" );
584584MEMOUT (Conf -> AffixData [0 ]);
585- Conf -> AffixData [1 ]= strdup (Conf -> Spell [0 ]. p .flag );
585+ Conf -> AffixData [1 ]= strdup (Conf -> Spell [0 ]-> p .flag );
586586MEMOUT (Conf -> AffixData [1 ]);
587- Conf -> Spell [0 ]. p .d .affix = 1 ;
588- Conf -> Spell [0 ]. p .d .len = strlen (Conf -> Spell [0 ]. word );
587+ Conf -> Spell [0 ]-> p .d .affix = 1 ;
588+ Conf -> Spell [0 ]-> p .d .len = strlen (Conf -> Spell [0 ]-> word );
589589for (i = 1 ;i < Conf -> nspell ;i ++ )
590590{
591- if (strcmp (Conf -> Spell [i ]. p .flag ,Conf -> AffixData [naffix ]))
591+ if (strcmp (Conf -> Spell [i ]-> p .flag ,Conf -> AffixData [naffix ]))
592592{
593593naffix ++ ;
594- Conf -> AffixData [naffix ]= strdup (Conf -> Spell [i ]. p .flag );
594+ Conf -> AffixData [naffix ]= strdup (Conf -> Spell [i ]-> p .flag );
595595MEMOUT (Conf -> AffixData [naffix ]);
596596}
597- Conf -> Spell [i ]. p .d .affix = naffix ;
598- Conf -> Spell [i ]. p .d .len = strlen (Conf -> Spell [i ]. word );
597+ Conf -> Spell [i ]-> p .d .affix = naffix ;
598+ Conf -> Spell [i ]-> p .d .len = strlen (Conf -> Spell [i ]-> word );
599599}
600600
601- qsort ((void * )Conf -> Spell ,Conf -> nspell ,sizeof (SPELL ),cmpspell );
601+ qsort ((void * )Conf -> Spell ,Conf -> nspell ,sizeof (SPELL * ),cmpspell );
602602Conf -> Dictionary = mkSPNode (Conf ,0 ,Conf -> nspell ,0 );
603603
604604for (i = 0 ;i < Conf -> nspell ;i ++ )
605- free (Conf -> Spell [i ]. word );
606- free (Conf -> Spell );
605+ pfree (Conf -> Spell [i ]);
606+ pfree (Conf -> Spell );
607607Conf -> Spell = NULL ;
608608}
609609
@@ -724,7 +724,6 @@ NISortAffixes(IspellDict * Conf)
724724
725725if (Conf -> naffixes > 1 )
726726qsort ((void * )Conf -> Affix ,Conf -> naffixes ,sizeof (AFFIX ),cmpaffix );
727-
728727Conf -> CompoundAffix = ptr = (CMPDAffix * )malloc (sizeof (CMPDAffix )* Conf -> naffixes );
729728MEMOUT (Conf -> CompoundAffix );
730729ptr -> affix = NULL ;
@@ -803,7 +802,7 @@ FinfAffixes(AffixNode * node, const char *word, int wrdlen, int *level, int type
803802}
804803
805804static char *
806- CheckAffix (const char * word ,size_t len ,AFFIX * Affix ,char flagflags ,char * newword )
805+ CheckAffix (const char * word ,size_t len ,AFFIX * Affix ,char flagflags ,char * newword , int * baselen )
807806{
808807
809808if (flagflags & FF_COMPOUNDONLYAFX )
@@ -821,9 +820,15 @@ CheckAffix(const char *word, size_t len, AFFIX * Affix, char flagflags, char *ne
821820{
822821strcpy (newword ,word );
823822strcpy (newword + len - Affix -> replen ,Affix -> find );
823+ if (baselen )/* store length of non-changed part of word */
824+ * baselen = len - Affix -> replen ;
824825}
825826else
826827{
828+ /* if prefix is a all non-chaged part's length then all word contains only prefix and suffix,
829+ so out */
830+ if (baselen && * baselen + strlen (Affix -> find ) <=Affix -> replen )
831+ return NULL ;
827832strcpy (newword ,Affix -> find );
828833strcat (newword ,word + Affix -> replen );
829834}
@@ -927,7 +932,7 @@ NormalizeSubWord(IspellDict * Conf, char *word, char flag)
927932break ;
928933for (j = 0 ;j < prefix -> naff ;j ++ )
929934{
930- if (CheckAffix (word ,wrdlen ,prefix -> aff [j ],flag ,newword ))
935+ if (CheckAffix (word ,wrdlen ,prefix -> aff [j ],flag ,newword , NULL ))
931936{
932937/* prefix success */
933938if (FindWord (Conf ,newword ,prefix -> aff [j ]-> flag ,flag & FF_COMPOUNDWORD )&& (cur - forms )< (MAX_NORM - 1 ))
@@ -948,14 +953,16 @@ NormalizeSubWord(IspellDict * Conf, char *word, char flag)
948953 */
949954while (snode )
950955{
956+ int baselen = 0 ;
957+
951958/* find possible suffix */
952959suffix = FinfAffixes (snode ,word ,wrdlen ,& slevel ,FF_SUFFIX );
953960if (!suffix )
954961break ;
955962/* foreach suffix check affix */
956963for (i = 0 ;i < suffix -> naff ;i ++ )
957964{
958- if (CheckAffix (word ,wrdlen ,suffix -> aff [i ],flag ,newword ))
965+ if (CheckAffix (word ,wrdlen ,suffix -> aff [i ],flag ,newword , & baselen ))
959966{
960967/* suffix success */
961968if (FindWord (Conf ,newword ,suffix -> aff [i ]-> flag ,flag & FF_COMPOUNDWORD )&& (cur - forms )< (MAX_NORM - 1 ))
@@ -976,7 +983,7 @@ NormalizeSubWord(IspellDict * Conf, char *word, char flag)
976983break ;
977984for (j = 0 ;j < prefix -> naff ;j ++ )
978985{
979- if (CheckAffix (newword ,swrdlen ,prefix -> aff [j ],flag ,pnewword ))
986+ if (CheckAffix (newword ,swrdlen ,prefix -> aff [j ],flag ,pnewword , & baselen ))
980987{
981988/* prefix success */
982989int ff = (prefix -> aff [j ]-> flagflags & suffix -> aff [i ]-> flagflags & FF_CROSSPRODUCT ) ?
@@ -1323,15 +1330,15 @@ NIFree(IspellDict * Conf)
13231330else
13241331pg_regfree (& (Affix [i ].reg .regex ));
13251332}
1326- free (Affix [i ].mask );
1327- free (Affix [i ].find );
1328- free (Affix [i ].repl );
1333+ if ( Affix [ i ]. mask != VoidString ) free (Affix [i ].mask );
1334+ if ( Affix [ i ]. find != VoidString ) free (Affix [i ].find );
1335+ if ( Affix [ i ]. repl != VoidString ) free (Affix [i ].repl );
13291336}
13301337if (Conf -> Spell )
13311338{
13321339for (i = 0 ;i < Conf -> nspell ;i ++ )
1333- free (Conf -> Spell [i ]. word );
1334- free (Conf -> Spell );
1340+ pfree (Conf -> Spell [i ]-> word );
1341+ pfree (Conf -> Spell );
13351342}
13361343
13371344if (Conf -> Affix )