PostgreSQL Source Code git master
Loading...
Searching...
No Matches
spell.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "miscadmin.h"
#include "tsearch/dicts/spell.h"
#include "tsearch/ts_locale.h"
#include "utils/formatting.h"
#include "utils/memutils.h"
Include dependency graph for spell.c:

Go to the source code of this file.

Data Structures

struct  SplitVar
 

Macros

#define tmpalloc(sz)   MemoryContextAlloc(Conf->buildCxt, (sz))
 
#define tmpalloc0(sz)   MemoryContextAllocZero(Conf->buildCxt, (sz))
 
#define COMPACT_ALLOC_CHUNK   8192 /* amount to get from palloc at once */
 
#define COMPACT_MAX_REQ   1024 /* must be < COMPACT_ALLOC_CHUNK */
 
#define cpalloc(size)   compact_palloc0(Conf, size)
 
#define cpalloc0(size)   compact_palloc0(Conf, size)
 
#define MAX_NORM   1024
 
#define MAXNORMLEN   256
 
#define STRNCMP(s, p)   strncmp( (s), (p), strlen(p) )
 
#define GETWCHAR(W, L, N, T)   ( ((const uint8*)(W))[ ((T)==FF_PREFIX) ? (N) : ( (L) - 1 - (N) ) ] )
 
#define GETCHAR(A, N, T)   GETWCHAR( (A)->repl, (A)->replen, N, T )
 
#define PAE_WAIT_MASK   0
 
#define PAE_INMASK   1
 
#define PAE_WAIT_FIND   2
 
#define PAE_INFIND   3
 
#define PAE_WAIT_REPL   4
 
#define PAE_INREPL   5
 
#define PAE_WAIT_TYPE   6
 
#define PAE_WAIT_FLAG   7
 

Typedefs

typedef struct SplitVar SplitVar
 

Functions

void NIStartBuild (IspellDict *Conf)
 
void NIFinishBuild (IspellDict *Conf)
 
static voidcompact_palloc0 (IspellDict *Conf, size_t size)
 
static charcpstrdup (IspellDict *Conf, const char *str)
 
static charlowerstr_ctx (IspellDict *Conf, const char *src)
 
static int cmpspell (const void *s1, const void *s2)
 
static int cmpspellaffix (const void *s1, const void *s2)
 
static int cmpcmdflag (const void *f1, const void *f2)
 
static charfindchar (char *str, int c)
 
static charfindchar2 (char *str, int c1, int c2)
 
static int strbcmp (const unsigned char *s1, const unsigned char *s2)
 
static int strbncmp (const unsigned char *s1, const unsigned char *s2, size_t count)
 
static int cmpaffix (const void *s1, const void *s2)
 
static void getNextFlagFromString (IspellDict *Conf, const char **sflagset, char *sflag)
 
static bool IsAffixFlagInUse (IspellDict *Conf, int affix, const char *affixflag)
 
static void NIAddSpell (IspellDict *Conf, const char *word, const char *flag)
 
void NIImportDictionary (IspellDict *Conf, const char *filename)
 
static int FindWord (IspellDict *Conf, const char *word, const char *affixflag, int flag)
 
static void NIAddAffix (IspellDict *Conf, const char *flag, char flagflags, const char *mask, const char *find, const char *repl, int type)
 
static bool get_nextfield (char **str, char *next)
 
static int parse_ooaffentry (char *str, char *type, char *flag, char *find, char *repl, char *mask)
 
static bool parse_affentry (char *str, char *mask, char *find, char *repl)
 
static void setCompoundAffixFlagValue (IspellDict *Conf, CompoundAffixFlag *entry, char *s, uint32 val)
 
static void addCompoundAffixFlagValue (IspellDict *Conf, char *s, uint32 val)
 
static int getCompoundAffixFlagValue (IspellDict *Conf, const char *s)
 
static const chargetAffixFlagSet (IspellDict *Conf, char *s)
 
static void NIImportOOAffixes (IspellDict *Conf, const char *filename)
 
void NIImportAffixes (IspellDict *Conf, const char *filename)
 
static int MergeAffix (IspellDict *Conf, int a1, int a2)
 
static uint32 makeCompoundFlags (IspellDict *Conf, int affix)
 
static SPNodemkSPNode (IspellDict *Conf, int low, int high, int level)
 
void NISortDictionary (IspellDict *Conf)
 
static AffixNodemkANode (IspellDict *Conf, int low, int high, int level, int type)
 
static void mkVoidAffix (IspellDict *Conf, bool issuffix, int startsuffix)
 
static bool isAffixInUse (IspellDict *Conf, const char *affixflag)
 
void NISortAffixes (IspellDict *Conf)
 
static AffixNodeDataFindAffixes (AffixNode *node, const char *word, int wrdlen, int *level, int type)
 
static charCheckAffix (const char *word, size_t len, AFFIX *Affix, int flagflags, char *newword, int *baselen)
 
static int addToResult (char **forms, char **cur, char *word)
 
static char ** NormalizeSubWord (IspellDict *Conf, const char *word, int flag)
 
static int CheckCompoundAffixes (CMPDAffix **ptr, const char *word, int len, bool CheckInPlace)
 
static SplitVarCopyVar (SplitVar *s, int makedup)
 
static void AddStem (SplitVar *v, char *word)
 
static SplitVarSplitToVariants (IspellDict *Conf, SPNode *snode, SplitVar *orig, const char *word, int wordlen, int startpos, int minpos)
 
static void addNorm (TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant)
 
TSLexemeNINormalizeWord (IspellDict *Conf, const char *word)
 

Variables

static const charVoidString = ""
 

Macro Definition Documentation

◆ COMPACT_ALLOC_CHUNK

#define COMPACT_ALLOC_CHUNK   8192 /* amount to get from palloc at once */

Definition at line 127 of file spell.c.

◆ COMPACT_MAX_REQ

#define COMPACT_MAX_REQ   1024 /* must be < COMPACT_ALLOC_CHUNK */

Definition at line 128 of file spell.c.

◆ cpalloc

#define cpalloc (   size)    compact_palloc0(Conf, size)

Definition at line 159 of file spell.c.

◆ cpalloc0

#define cpalloc0 (   size)    compact_palloc0(Conf, size)

Definition at line 160 of file spell.c.

◆ GETCHAR

#define GETCHAR (   A,
  N,
  T 
)    GETWCHAR( (A)->repl, (A)->replen, N, T )

Definition at line 193 of file spell.c.

◆ GETWCHAR

#define GETWCHAR (   W,
  L,
  N,
  T 
)    ( ((const uint8*)(W))[ ((T)==FF_PREFIX) ? (N) : ( (L) - 1 - (N) ) ] )

Definition at line 192 of file spell.c.

◆ MAX_NORM

#define MAX_NORM   1024

Definition at line 188 of file spell.c.

◆ MAXNORMLEN

#define MAXNORMLEN   256

Definition at line 189 of file spell.c.

◆ PAE_INFIND

#define PAE_INFIND   3

Definition at line 777 of file spell.c.

◆ PAE_INMASK

#define PAE_INMASK   1

Definition at line 775 of file spell.c.

◆ PAE_INREPL

#define PAE_INREPL   5

Definition at line 779 of file spell.c.

◆ PAE_WAIT_FIND

#define PAE_WAIT_FIND   2

Definition at line 776 of file spell.c.

◆ PAE_WAIT_FLAG

#define PAE_WAIT_FLAG   7

Definition at line 781 of file spell.c.

◆ PAE_WAIT_MASK

#define PAE_WAIT_MASK   0

Definition at line 774 of file spell.c.

◆ PAE_WAIT_REPL

#define PAE_WAIT_REPL   4

Definition at line 778 of file spell.c.

◆ PAE_WAIT_TYPE

#define PAE_WAIT_TYPE   6

Definition at line 780 of file spell.c.

◆ STRNCMP

#define STRNCMP (   s,
 
)    strncmp( (s), (p), strlen(p) )

Definition at line 191 of file spell.c.

◆ tmpalloc

#define tmpalloc (   sz)    MemoryContextAlloc(Conf->buildCxt, (sz))

Definition at line 80 of file spell.c.

◆ tmpalloc0

#define tmpalloc0 (   sz)    MemoryContextAllocZero(Conf->buildCxt, (sz))

Definition at line 81 of file spell.c.

Typedef Documentation

◆ SplitVar

Function Documentation

◆ addCompoundAffixFlagValue()

static void addCompoundAffixFlagValue ( IspellDict Conf,
char s,
uint32  val 
)
static

Definition at line 1064 of file spell.c.

1065{
1067 char sbuf[BUFSIZ];
1068 char *sflag;
1069
1070 while (*s && isspace((unsigned char) *s))
1071 s += pg_mblen_cstr(s);
1072
1073 if (!*s)
1074 ereport(ERROR,
1076 errmsg("syntax error")));
1077
1078 /* Get flag without \n */
1079 sflag = sbuf;
1080 while (*s && !isspace((unsigned char) *s) && *s != '\n')
1081 {
1082 int clen = ts_copychar_cstr(sflag, s);
1083
1084 sflag += clen;
1085 s += clen;
1086 }
1087 *sflag = '\0';
1088
1089 /* Resize array or allocate memory for array CompoundAffixFlag */
1090 if (Conf->nCompoundAffixFlag >= Conf->mCompoundAffixFlag)
1091 {
1092 if (Conf->mCompoundAffixFlag)
1093 {
1094 Conf->mCompoundAffixFlag *= 2;
1095 Conf->CompoundAffixFlags = (CompoundAffixFlag *)
1096 repalloc(Conf->CompoundAffixFlags,
1097 Conf->mCompoundAffixFlag * sizeof(CompoundAffixFlag));
1098 }
1099 else
1100 {
1101 Conf->mCompoundAffixFlag = 10;
1102 Conf->CompoundAffixFlags = (CompoundAffixFlag *)
1103 tmpalloc(Conf->mCompoundAffixFlag * sizeof(CompoundAffixFlag));
1104 }
1105 }
1106
1107 newValue = Conf->CompoundAffixFlags + Conf->nCompoundAffixFlag;
1108
1110
1111 Conf->usecompound = true;
1112 Conf->nCompoundAffixFlag++;
1113}
int errcode(int sqlerrcode)
Definition elog.c:864
int errmsg(const char *fmt,...)
Definition elog.c:1081
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
long val
Definition informix.c:689
int pg_mblen_cstr(const char *mbstr)
Definition mbutils.c:1045
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
static int fb(int x)
static void setCompoundAffixFlagValue(IspellDict *Conf, CompoundAffixFlag *entry, char *s, uint32 val)
Definition spell.c:1028
#define tmpalloc(sz)
Definition spell.c:80
static int ts_copychar_cstr(void *dest, const void *src)
Definition ts_locale.h:50

References ereport, errcode(), errmsg(), ERROR, fb(), pg_mblen_cstr(), repalloc(), setCompoundAffixFlagValue(), tmpalloc, ts_copychar_cstr(), and val.

Referenced by NIImportAffixes(), and NIImportOOAffixes().

◆ addNorm()

static void addNorm ( TSLexeme **  lres,
TSLexeme **  lcur,
char word,
int  flags,
uint16  NVariant 
)
static

Definition at line 2522 of file spell.c.

2523{
2524 if (*lres == NULL)
2526
2527 if (*lcur - *lres < MAX_NORM - 1)
2528 {
2529 (*lcur)->lexeme = word;
2530 (*lcur)->flags = flags;
2531 (*lcur)->nvariant = NVariant;
2532 (*lcur)++;
2533 (*lcur)->lexeme = NULL;
2534 }
2535}
#define palloc_array(type, count)
Definition fe_memutils.h:76
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition regcomp.c:1476
#define MAX_NORM
Definition spell.c:188

References fb(), MAX_NORM, palloc_array, and word().

Referenced by NINormalizeWord().

◆ AddStem()

static void AddStem ( SplitVar v,
char word 
)
static

Definition at line 2359 of file spell.c.

2360{
2361 if (v->nstem >= v->lenstem)
2362 {
2363 v->lenstem *= 2;
2364 v->stem = (char **) repalloc(v->stem, sizeof(char *) * v->lenstem);
2365 }
2366
2367 v->stem[v->nstem] = word;
2368 v->nstem++;
2369}
int nstem
Definition spell.c:2285
int lenstem
Definition spell.c:2286
char ** stem
Definition spell.c:2287

References SplitVar::lenstem, SplitVar::nstem, repalloc(), SplitVar::stem, and word().

Referenced by SplitToVariants().

◆ addToResult()

static int addToResult ( char **  forms,
char **  cur,
char word 
)
static

Definition at line 2159 of file spell.c.

2160{
2161 if (cur - forms >= MAX_NORM - 1)
2162 return 0;
2163 if (forms == cur || strcmp(word, *(cur - 1)) != 0)
2164 {
2165 *cur = pstrdup(word);
2166 *(cur + 1) = NULL;
2167 return 1;
2168 }
2169
2170 return 0;
2171}
struct cursor * cur
Definition ecpg.c:29
char * pstrdup(const char *in)
Definition mcxt.c:1781

References cur, fb(), MAX_NORM, pstrdup(), and word().

Referenced by NormalizeSubWord().

◆ CheckAffix()

static char * CheckAffix ( const char word,
size_t  len,
AFFIX Affix,
int  flagflags,
char newword,
int baselen 
)
static

Definition at line 2069 of file spell.c.

2070{
2071 /*
2072 * Check compound allow flags
2073 */
2074
2075 if (flagflags == 0)
2076 {
2077 if (Affix->flagflags & FF_COMPOUNDONLY)
2078 return NULL;
2079 }
2080 else if (flagflags & FF_COMPOUNDBEGIN)
2081 {
2082 if (Affix->flagflags & FF_COMPOUNDFORBIDFLAG)
2083 return NULL;
2084 if ((Affix->flagflags & FF_COMPOUNDBEGIN) == 0)
2085 if (Affix->type == FF_SUFFIX)
2086 return NULL;
2087 }
2088 else if (flagflags & FF_COMPOUNDMIDDLE)
2089 {
2090 if ((Affix->flagflags & FF_COMPOUNDMIDDLE) == 0 ||
2092 return NULL;
2093 }
2094 else if (flagflags & FF_COMPOUNDLAST)
2095 {
2096 if (Affix->flagflags & FF_COMPOUNDFORBIDFLAG)
2097 return NULL;
2098 if ((Affix->flagflags & FF_COMPOUNDLAST) == 0)
2099 if (Affix->type == FF_PREFIX)
2100 return NULL;
2101 }
2102
2103 /*
2104 * make replace pattern of affix
2105 */
2106 if (Affix->type == FF_SUFFIX)
2107 {
2109 strcpy(newword + len - Affix->replen, Affix->find);
2110 if (baselen) /* store length of non-changed part of word */
2111 *baselen = len - Affix->replen;
2112 }
2113 else
2114 {
2115 /*
2116 * if prefix is an all non-changed part's length then all word
2117 * contains only prefix and suffix, so out
2118 */
2119 if (baselen && *baselen + strlen(Affix->find) <= Affix->replen)
2120 return NULL;
2121 strcpy(newword, Affix->find);
2122 strcat(newword, word + Affix->replen);
2123 }
2124
2125 /*
2126 * check resulting word
2127 */
2128 if (Affix->issimple)
2129 return newword;
2130 else if (Affix->isregis)
2131 {
2132 if (RS_execute(&(Affix->reg.regis), newword))
2133 return newword;
2134 }
2135 else
2136 {
2137 pg_wchar *data;
2138 size_t data_len;
2139 int newword_len;
2140
2141 /* Convert data string to wide characters */
2145
2146 if (pg_regexec(Affix->reg.pregex, data, data_len,
2147 0, NULL, 0, NULL, 0) == REG_OKAY)
2148 {
2149 pfree(data);
2150 return newword;
2151 }
2152 pfree(data);
2153 }
2154
2155 return NULL;
2156}
unsigned int pg_wchar
Definition mbprint.c:31
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
Definition mbutils.c:997
void pfree(void *pointer)
Definition mcxt.c:1616
const void size_t len
const void * data
#define REG_OKAY
Definition regex.h:215
int pg_regexec(regex_t *re, const chr *string, size_t len, size_t search_start, rm_detail_t *details, size_t nmatch, regmatch_t pmatch[], int flags)
Definition regexec.c:185
bool RS_execute(Regis *r, char *str)
Definition regis.c:208
#define FF_SUFFIX
Definition spell.h:121
#define FF_PREFIX
Definition spell.h:122
#define FF_COMPOUNDFORBIDFLAG
Definition spell.h:114
#define FF_COMPOUNDBEGIN
Definition spell.h:43
#define FF_COMPOUNDMIDDLE
Definition spell.h:44
#define FF_COMPOUNDONLY
Definition spell.h:42
#define FF_COMPOUNDLAST
Definition spell.h:45
const char * find
Definition spell.h:96
uint32 isregis
Definition spell.h:94
uint32 type
Definition spell.h:91
Regis regis
Definition spell.h:106
uint32 replen
Definition spell.h:95
union aff_struct::@142 reg
regex_t * pregex
Definition spell.h:105
uint32 flagflags
Definition spell.h:92
uint32 issimple
Definition spell.h:93

References data, fb(), FF_COMPOUNDBEGIN, FF_COMPOUNDFORBIDFLAG, FF_COMPOUNDLAST, FF_COMPOUNDMIDDLE, FF_COMPOUNDONLY, FF_PREFIX, FF_SUFFIX, aff_struct::find, aff_struct::flagflags, aff_struct::isregis, aff_struct::issimple, len, palloc_array, pfree(), pg_mb2wchar_with_len(), pg_regexec(), aff_struct::pregex, aff_struct::reg, REG_OKAY, aff_struct::regis, aff_struct::replen, RS_execute(), aff_struct::type, and word().

Referenced by NormalizeSubWord().

◆ CheckCompoundAffixes()

static int CheckCompoundAffixes ( CMPDAffix **  ptr,
const char word,
int  len,
bool  CheckInPlace 
)
static

Definition at line 2292 of file spell.c.

2293{
2294 bool issuffix;
2295
2296 /* in case CompoundAffix is null: */
2297 if (*ptr == NULL)
2298 return -1;
2299
2300 if (CheckInPlace)
2301 {
2302 while ((*ptr)->affix)
2303 {
2304 if (len > (*ptr)->len && strncmp((*ptr)->affix, word, (*ptr)->len) == 0)
2305 {
2306 len = (*ptr)->len;
2307 issuffix = (*ptr)->issuffix;
2308 (*ptr)++;
2309 return (issuffix) ? len : 0;
2310 }
2311 (*ptr)++;
2312 }
2313 }
2314 else
2315 {
2316 const char *affbegin;
2317
2318 while ((*ptr)->affix)
2319 {
2320 if (len > (*ptr)->len && (affbegin = strstr(word, (*ptr)->affix)) != NULL)
2321 {
2322 len = (*ptr)->len + (affbegin - word);
2323 issuffix = (*ptr)->issuffix;
2324 (*ptr)++;
2325 return (issuffix) ? len : 0;
2326 }
2327 (*ptr)++;
2328 }
2329 }
2330 return -1;
2331}

References fb(), len, and word().

Referenced by SplitToVariants().

◆ cmpaffix()

static int cmpaffix ( const void s1,
const void s2 
)
static

Definition at line 312 of file spell.c.

313{
314 const AFFIX *a1 = (const AFFIX *) s1;
315 const AFFIX *a2 = (const AFFIX *) s2;
316
317 if (a1->type < a2->type)
318 return -1;
319 if (a1->type > a2->type)
320 return 1;
321 if (a1->type == FF_PREFIX)
322 return strcmp(a1->repl, a2->repl);
323 else
324 return strbcmp((const unsigned char *) a1->repl,
325 (const unsigned char *) a2->repl);
326}
static const FormData_pg_attribute a1
Definition heap.c:144
static const FormData_pg_attribute a2
Definition heap.c:157
char * s1
char * s2
static int strbcmp(const unsigned char *s1, const unsigned char *s2)
Definition spell.c:258

References a1, a2, fb(), FF_PREFIX, s1, s2, and strbcmp().

Referenced by NISortAffixes().

◆ cmpcmdflag()

static int cmpcmdflag ( const void f1,
const void f2 
)
static

Definition at line 211 of file spell.c.

212{
213 const CompoundAffixFlag *fv1 = f1;
214 const CompoundAffixFlag *fv2 = f2;
215
216 Assert(fv1->flagMode == fv2->flagMode);
217
218 if (fv1->flagMode == FM_NUM)
219 {
220 if (fv1->flag.i == fv2->flag.i)
221 return 0;
222
223 return (fv1->flag.i > fv2->flag.i) ? 1 : -1;
224 }
225
226 return strcmp(fv1->flag.s, fv2->flag.s);
227}
#define Assert(condition)
Definition c.h:873
@ FM_NUM
Definition spell.h:161
int f1[ARRAY_SIZE]
int f2[ARRAY_SIZE]

References Assert, f1, f2, fb(), and FM_NUM.

Referenced by getCompoundAffixFlagValue(), and NIImportOOAffixes().

◆ cmpspell()

static int cmpspell ( const void s1,
const void s2 
)
static

Definition at line 198 of file spell.c.

199{
200 return strcmp((*(SPELL *const *) s1)->word, (*(SPELL *const *) s2)->word);
201}

References fb(), s1, s2, and word().

Referenced by NISortDictionary().

◆ cmpspellaffix()

static int cmpspellaffix ( const void s1,
const void s2 
)
static

Definition at line 204 of file spell.c.

205{
206 return strcmp((*(SPELL *const *) s1)->p.flag,
207 (*(SPELL *const *) s2)->p.flag);
208}

References fb(), s1, and s2.

Referenced by NISortDictionary().

◆ compact_palloc0()

static void * compact_palloc0 ( IspellDict Conf,
size_t  size 
)
static

Definition at line 131 of file spell.c.

132{
133 void *result;
134
135 /* Should only be called during init */
136 Assert(Conf->buildCxt != NULL);
137
138 /* No point in this for large chunks */
139 if (size > COMPACT_MAX_REQ)
140 return palloc0(size);
141
142 /* Keep everything maxaligned */
143 size = MAXALIGN(size);
144
145 /* Need more space? */
146 if (size > Conf->avail)
147 {
148 Conf->firstfree = palloc0(COMPACT_ALLOC_CHUNK);
149 Conf->avail = COMPACT_ALLOC_CHUNK;
150 }
151
152 result = Conf->firstfree;
153 Conf->firstfree += size;
154 Conf->avail -= size;
155
156 return result;
157}
#define MAXALIGN(LEN)
Definition c.h:826
void * palloc0(Size size)
Definition mcxt.c:1417
#define COMPACT_ALLOC_CHUNK
Definition spell.c:127
#define COMPACT_MAX_REQ
Definition spell.c:128

References Assert, COMPACT_ALLOC_CHUNK, COMPACT_MAX_REQ, fb(), MAXALIGN, and palloc0().

◆ CopyVar()

static SplitVar * CopyVar ( SplitVar s,
int  makedup 
)
static

Definition at line 2334 of file spell.c.

2335{
2337
2338 v->next = NULL;
2339 if (s)
2340 {
2341 int i;
2342
2343 v->lenstem = s->lenstem;
2344 v->stem = palloc_array(char *, v->lenstem);
2345 v->nstem = s->nstem;
2346 for (i = 0; i < s->nstem; i++)
2347 v->stem[i] = (makedup) ? pstrdup(s->stem[i]) : s->stem[i];
2348 }
2349 else
2350 {
2351 v->lenstem = 16;
2352 v->stem = palloc_array(char *, v->lenstem);
2353 v->nstem = 0;
2354 }
2355 return v;
2356}
#define palloc_object(type)
Definition fe_memutils.h:74
int i
Definition isn.c:77
struct SplitVar * next
Definition spell.c:2288

References fb(), i, SplitVar::lenstem, SplitVar::next, SplitVar::nstem, palloc_array, palloc_object, pstrdup(), and SplitVar::stem.

Referenced by SplitToVariants().

◆ cpstrdup()

static char * cpstrdup ( IspellDict Conf,
const char str 
)
static

Definition at line 163 of file spell.c.

164{
165 char *res = cpalloc(strlen(str) + 1);
166
167 strcpy(res, str);
168 return res;
169}
const char * str
#define cpalloc(size)
Definition spell.c:159

References cpalloc, fb(), and str.

Referenced by NIAddAffix(), NIAddSpell(), NIImportOOAffixes(), NISortDictionary(), and setCompoundAffixFlagValue().

◆ FindAffixes()

static AffixNodeData * FindAffixes ( AffixNode node,
const char word,
int  wrdlen,
int level,
int  type 
)
static

Definition at line 2026 of file spell.c.

2027{
2029 *StopHigh,
2030 *StopMiddle;
2031 uint8 symbol;
2032
2033 if (node->isvoid)
2034 { /* search void affixes */
2035 if (node->data->naff)
2036 return node->data;
2037 node = node->data->node;
2038 }
2039
2040 while (node && *level < wrdlen)
2041 {
2042 StopLow = node->data;
2043 StopHigh = node->data + node->length;
2044 while (StopLow < StopHigh)
2045 {
2046 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
2047 symbol = GETWCHAR(word, wrdlen, *level, type);
2048
2049 if (StopMiddle->val == symbol)
2050 {
2051 (*level)++;
2052 if (StopMiddle->naff)
2053 return StopMiddle;
2054 node = StopMiddle->node;
2055 break;
2056 }
2057 else if (StopMiddle->val < symbol)
2058 StopLow = StopMiddle + 1;
2059 else
2061 }
2062 if (StopLow >= StopHigh)
2063 break;
2064 }
2065 return NULL;
2066}
unsigned char symbol
Definition api.h:4
uint8_t uint8
Definition c.h:544
#define GETWCHAR(W, L, N, T)
Definition spell.c:192
uint32 naff
Definition spell.h:133
struct AffixNode * node
Definition spell.h:135
uint32 isvoid
Definition spell.h:140
AffixNodeData data[FLEXIBLE_ARRAY_MEMBER]
Definition spell.h:142
uint32 length
Definition spell.h:141
const char * type

References AffixNode::data, fb(), GETWCHAR, AffixNode::isvoid, AffixNode::length, AffixNodeData::naff, AffixNodeData::node, type, and word().

Referenced by NormalizeSubWord().

◆ findchar()

static char * findchar ( char str,
int  c 
)
static

Definition at line 230 of file spell.c.

231{
232 while (*str)
233 {
234 if (t_iseq(str, c))
235 return str;
237 }
238
239 return NULL;
240}
char * c
#define t_iseq(x, c)
Definition ts_locale.h:38

References fb(), pg_mblen_cstr(), str, and t_iseq.

Referenced by NIImportDictionary().

◆ findchar2()

static char * findchar2 ( char str,
int  c1,
int  c2 
)
static

Definition at line 243 of file spell.c.

244{
245 while (*str)
246 {
247 if (t_iseq(str, c1) || t_iseq(str, c2))
248 return str;
250 }
251
252 return NULL;
253}

References fb(), pg_mblen_cstr(), str, and t_iseq.

Referenced by NIImportAffixes().

◆ FindWord()

static int FindWord ( IspellDict Conf,
const char word,
const char affixflag,
int  flag 
)
static

Definition at line 605 of file spell.c.

606{
607 SPNode *node = Conf->Dictionary;
609 *StopHigh,
610 *StopMiddle;
611 const uint8 *ptr = (const uint8 *) word;
612
614
615 while (node && *ptr)
616 {
617 StopLow = node->data;
618 StopHigh = node->data + node->length;
619 while (StopLow < StopHigh)
620 {
621 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
622 if (StopMiddle->val == *ptr)
623 {
624 if (*(ptr + 1) == '\0' && StopMiddle->isword)
625 {
626 if (flag == 0)
627 {
628 /*
629 * The word can be formed only with another word. And
630 * in the flag parameter there is not a sign that we
631 * search compound words.
632 */
633 if (StopMiddle->compoundflag & FF_COMPOUNDONLY)
634 return 0;
635 }
636 else if ((flag & StopMiddle->compoundflag) == 0)
637 return 0;
638
639 /*
640 * Check if this affix rule is presented in the affix set
641 * with index StopMiddle->affix.
642 */
644 return 1;
645 }
646 node = StopMiddle->node;
647 ptr++;
648 break;
649 }
650 else if (StopMiddle->val < *ptr)
651 StopLow = StopMiddle + 1;
652 else
654 }
655 if (StopLow >= StopHigh)
656 break;
657 }
658 return 0;
659}
static bool IsAffixFlagInUse(IspellDict *Conf, int affix, const char *affixflag)
Definition spell.c:457
#define FF_COMPOUNDFLAGMASK
Definition spell.h:48
Definition spell.h:51
SPNodeData data[FLEXIBLE_ARRAY_MEMBER]
Definition spell.h:53
uint32 length
Definition spell.h:52
char * flag(int b)
Definition test-ctype.c:33

References SPNode::data, fb(), FF_COMPOUNDFLAGMASK, FF_COMPOUNDONLY, flag(), IsAffixFlagInUse(), SPNode::length, and word().

Referenced by NormalizeSubWord().

◆ get_nextfield()

static bool get_nextfield ( char **  str,
char next 
)
static

Definition at line 794 of file spell.c.

795{
796 int state = PAE_WAIT_MASK;
797 int avail = BUFSIZ;
798
799 while (**str)
800 {
801 int clen = pg_mblen_cstr(*str);
802
803 if (state == PAE_WAIT_MASK)
804 {
805 if (t_iseq(*str, '#'))
806 return false;
807 else if (!isspace((unsigned char) **str))
808 {
809 if (clen < avail)
810 {
812 next += clen;
813 avail -= clen;
814 }
816 }
817 }
818 else /* state == PAE_INMASK */
819 {
820 if (isspace((unsigned char) **str))
821 {
822 *next = '\0';
823 return true;
824 }
825 else
826 {
827 if (clen < avail)
828 {
830 next += clen;
831 avail -= clen;
832 }
833 }
834 }
835 *str += clen;
836 }
837
838 *next = '\0';
839
840 return (state == PAE_INMASK); /* OK if we got a nonempty field */
841}
static int32 next
Definition blutils.c:225
#define PAE_INMASK
Definition spell.c:775
#define PAE_WAIT_MASK
Definition spell.c:774
static int ts_copychar_with_len(void *dest, const void *src, int length)
Definition ts_locale.h:42

References fb(), next, PAE_INMASK, PAE_WAIT_MASK, pg_mblen_cstr(), str, t_iseq, and ts_copychar_with_len().

Referenced by parse_ooaffentry().

◆ getAffixFlagSet()

static const char * getAffixFlagSet ( IspellDict Conf,
char s 
)
static

Definition at line 1156 of file spell.c.

1157{
1158 if (Conf->useFlagAliases && *s != '\0')
1159 {
1160 int curaffix;
1161 char *end;
1162
1163 errno = 0;
1164 curaffix = strtol(s, &end, 10);
1165 if (s == end || errno == ERANGE)
1166 ereport(ERROR,
1168 errmsg("invalid affix alias \"%s\"", s)));
1169
1170 if (curaffix > 0 && curaffix < Conf->nAffixData)
1171
1172 /*
1173 * Do not subtract 1 from curaffix because empty string was added
1174 * in NIImportOOAffixes
1175 */
1176 return Conf->AffixData[curaffix];
1177 else if (curaffix > Conf->nAffixData)
1178 ereport(ERROR,
1180 errmsg("invalid affix alias \"%s\"", s)));
1181 return VoidString;
1182 }
1183 else
1184 return s;
1185}
static const char * VoidString
Definition spell.c:195

References ereport, errcode(), errmsg(), ERROR, fb(), and VoidString.

Referenced by NIImportOOAffixes().

◆ getCompoundAffixFlagValue()

static int getCompoundAffixFlagValue ( IspellDict Conf,
const char s 
)
static

Definition at line 1120 of file spell.c.

1121{
1122 uint32 flag = 0;
1123 CompoundAffixFlag *found,
1124 key;
1125 char sflag[BUFSIZ];
1126 const char *flagcur;
1127
1128 if (Conf->nCompoundAffixFlag == 0)
1129 return 0;
1130
1131 flagcur = s;
1132 while (*flagcur)
1133 {
1136
1137 found = (CompoundAffixFlag *)
1138 bsearch(&key, Conf->CompoundAffixFlags,
1139 Conf->nCompoundAffixFlag, sizeof(CompoundAffixFlag),
1140 cmpcmdflag);
1141 if (found != NULL)
1142 flag |= found->value;
1143 }
1144
1145 return flag;
1146}
uint32_t uint32
Definition c.h:546
static void getNextFlagFromString(IspellDict *Conf, const char **sflagset, char *sflag)
Definition spell.c:350
static int cmpcmdflag(const void *f1, const void *f2)
Definition spell.c:211

References cmpcmdflag(), fb(), flag(), getNextFlagFromString(), setCompoundAffixFlagValue(), and CompoundAffixFlag::value.

Referenced by makeCompoundFlags(), and NIImportOOAffixes().

◆ getNextFlagFromString()

static void getNextFlagFromString ( IspellDict Conf,
const char **  sflagset,
char sflag 
)
static

Definition at line 350 of file spell.c.

351{
352 int32 s;
353 char *next;
354 const char *sbuf = *sflagset;
355 int maxstep;
356 int clen;
357 bool stop = false;
358 bool met_comma = false;
359
360 maxstep = (Conf->flagMode == FM_LONG) ? 2 : 1;
361
362 while (**sflagset)
363 {
364 switch (Conf->flagMode)
365 {
366 case FM_LONG:
367 case FM_CHAR:
369 sflag += clen;
370
371 /* Go to start of the next flag */
372 *sflagset += clen;
373
374 /* Check if we get all characters of flag */
375 maxstep--;
376 stop = (maxstep == 0);
377 break;
378 case FM_NUM:
379 errno = 0;
380 s = strtol(*sflagset, &next, 10);
381 if (*sflagset == next || errno == ERANGE)
384 errmsg("invalid affix flag \"%s\"", *sflagset)));
388 errmsg("affix flag \"%s\" is out of range",
389 *sflagset)));
390 sflag += sprintf(sflag, "%0d", s);
391
392 /* Go to start of the next flag */
393 *sflagset = next;
394 while (**sflagset)
395 {
396 if (isdigit((unsigned char) **sflagset))
397 {
398 if (!met_comma)
401 errmsg("invalid affix flag \"%s\"",
402 *sflagset)));
403 break;
404 }
405 else if (t_iseq(*sflagset, ','))
406 {
407 if (met_comma)
410 errmsg("invalid affix flag \"%s\"",
411 *sflagset)));
412 met_comma = true;
413 }
414 else if (!isspace((unsigned char) **sflagset))
415 {
418 errmsg("invalid character in affix flag \"%s\"",
419 *sflagset)));
420 }
421
423 }
424 stop = true;
425 break;
426 default:
427 elog(ERROR, "unrecognized type of Conf->flagMode: %d",
428 Conf->flagMode);
429 }
430
431 if (stop)
432 break;
433 }
434
435 if (Conf->flagMode == FM_LONG && maxstep > 0)
438 errmsg("invalid affix flag \"%s\" with \"long\" flag value",
439 sbuf)));
440
441 *sflag = '\0';
442}
int32_t int32
Definition c.h:542
#define elog(elevel,...)
Definition elog.h:226
#define sprintf
Definition port.h:262
#define FLAGNUM_MAXSIZE
Definition spell.h:182
@ FM_LONG
Definition spell.h:160
@ FM_CHAR
Definition spell.h:159

References elog, ereport, errcode(), errmsg(), ERROR, fb(), FLAGNUM_MAXSIZE, FM_CHAR, FM_LONG, FM_NUM, next, pg_mblen_cstr(), sprintf, t_iseq, and ts_copychar_cstr().

Referenced by getCompoundAffixFlagValue(), and IsAffixFlagInUse().

◆ IsAffixFlagInUse()

static bool IsAffixFlagInUse ( IspellDict Conf,
int  affix,
const char affixflag 
)
static

Definition at line 457 of file spell.c.

458{
459 const char *flagcur;
460 char flag[BUFSIZ];
461
462 if (*affixflag == 0)
463 return true;
464
465 Assert(affix < Conf->nAffixData);
466
467 flagcur = Conf->AffixData[affix];
468
469 while (*flagcur)
470 {
472 /* Compare first affix flag in flagcur with affixflag */
473 if (strcmp(flag, affixflag) == 0)
474 return true;
475 }
476
477 /* Could not find affixflag */
478 return false;
479}

References Assert, fb(), flag(), and getNextFlagFromString().

Referenced by FindWord(), and isAffixInUse().

◆ isAffixInUse()

static bool isAffixInUse ( IspellDict Conf,
const char affixflag 
)
static

Definition at line 1959 of file spell.c.

1960{
1961 int i;
1962
1963 for (i = 0; i < Conf->nAffixData; i++)
1965 return true;
1966
1967 return false;
1968}

References fb(), i, and IsAffixFlagInUse().

Referenced by NISortAffixes().

◆ lowerstr_ctx()

static char * lowerstr_ctx ( IspellDict Conf,
const char src 
)
static

Definition at line 176 of file spell.c.

177{
179 char *dst;
180
184
185 return dst;
186}
char * str_tolower(const char *buff, size_t nbytes, Oid collid)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124

References fb(), MemoryContextSwitchTo(), and str_tolower().

Referenced by NIImportDictionary(), and NIImportOOAffixes().

◆ makeCompoundFlags()

static uint32 makeCompoundFlags ( IspellDict Conf,
int  affix 
)
static

Definition at line 1620 of file spell.c.

1621{
1622 Assert(affix < Conf->nAffixData);
1623
1624 return (getCompoundAffixFlagValue(Conf, Conf->AffixData[affix]) &
1626}
static int getCompoundAffixFlagValue(IspellDict *Conf, const char *s)
Definition spell.c:1120

References Assert, fb(), FF_COMPOUNDFLAGMASK, and getCompoundAffixFlagValue().

Referenced by mkSPNode().

◆ MergeAffix()

static int MergeAffix ( IspellDict Conf,
int  a1,
int  a2 
)
static

Definition at line 1569 of file spell.c.

1570{
1571 const char **ptr;
1572
1573 Assert(a1 < Conf->nAffixData && a2 < Conf->nAffixData);
1574
1575 /* Do not merge affix flags if one of affix flags is empty */
1576 if (*Conf->AffixData[a1] == '\0')
1577 return a2;
1578 else if (*Conf->AffixData[a2] == '\0')
1579 return a1;
1580
1581 /* Double the size of AffixData if there's not enough space */
1582 if (Conf->nAffixData + 1 >= Conf->lenAffixData)
1583 {
1584 Conf->lenAffixData *= 2;
1585 Conf->AffixData = (const char **) repalloc(Conf->AffixData,
1586 sizeof(char *) * Conf->lenAffixData);
1587 }
1588
1589 ptr = Conf->AffixData + Conf->nAffixData;
1590 if (Conf->flagMode == FM_NUM)
1591 {
1592 char *p = cpalloc(strlen(Conf->AffixData[a1]) +
1593 strlen(Conf->AffixData[a2]) +
1594 1 /* comma */ + 1 /* \0 */ );
1595
1596 sprintf(p, "%s,%s", Conf->AffixData[a1], Conf->AffixData[a2]);
1597 *ptr = p;
1598 }
1599 else
1600 {
1601 char *p = cpalloc(strlen(Conf->AffixData[a1]) +
1602 strlen(Conf->AffixData[a2]) +
1603 1 /* \0 */ );
1604
1605 sprintf(p, "%s%s", Conf->AffixData[a1], Conf->AffixData[a2]);
1606 *ptr = p;
1607 }
1608 ptr++;
1609 *ptr = NULL;
1610 Conf->nAffixData++;
1611
1612 return Conf->nAffixData - 1;
1613}

References a1, a2, Assert, cpalloc, fb(), FM_NUM, repalloc(), and sprintf.

Referenced by mkSPNode().

◆ mkANode()

static AffixNode * mkANode ( IspellDict Conf,
int  low,
int  high,
int  level,
int  type 
)
static

Definition at line 1828 of file spell.c.

1829{
1830 int i;
1831 int nchar = 0;
1832 uint8 lastchar = '\0';
1833 AffixNode *rs;
1835 int lownew = low;
1836 int naff;
1837 AFFIX **aff;
1838
1839 for (i = low; i < high; i++)
1840 if (Conf->Affix[i].replen > level && lastchar != GETCHAR(Conf->Affix + i, level, type))
1841 {
1842 nchar++;
1843 lastchar = GETCHAR(Conf->Affix + i, level, type);
1844 }
1845
1846 if (!nchar)
1847 return NULL;
1848
1849 aff = (AFFIX **) tmpalloc(sizeof(AFFIX *) * (high - low + 1));
1850 naff = 0;
1851
1852 rs = (AffixNode *) cpalloc0(ANHRDSZ + nchar * sizeof(AffixNodeData));
1853 rs->length = nchar;
1854 data = rs->data;
1855
1856 lastchar = '\0';
1857 for (i = low; i < high; i++)
1858 if (Conf->Affix[i].replen > level)
1859 {
1860 if (lastchar != GETCHAR(Conf->Affix + i, level, type))
1861 {
1862 if (lastchar)
1863 {
1864 /* Next level of the prefix tree */
1865 data->node = mkANode(Conf, lownew, i, level + 1, type);
1866 if (naff)
1867 {
1868 data->naff = naff;
1869 data->aff = (AFFIX **) cpalloc(sizeof(AFFIX *) * naff);
1870 memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
1871 naff = 0;
1872 }
1873 data++;
1874 lownew = i;
1875 }
1876 lastchar = GETCHAR(Conf->Affix + i, level, type);
1877 }
1878 data->val = GETCHAR(Conf->Affix + i, level, type);
1879 if (Conf->Affix[i].replen == level + 1)
1880 { /* affix stopped */
1881 aff[naff++] = Conf->Affix + i;
1882 }
1883 }
1884
1885 /* Next level of the prefix tree */
1886 data->node = mkANode(Conf, lownew, high, level + 1, type);
1887 if (naff)
1888 {
1889 data->naff = naff;
1890 data->aff = (AFFIX **) cpalloc(sizeof(AFFIX *) * naff);
1891 memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
1892 naff = 0;
1893 }
1894
1895 pfree(aff);
1896
1897 return rs;
1898}
#define GETCHAR(A, N, T)
Definition spell.c:193
static AffixNode * mkANode(IspellDict *Conf, int low, int high, int level, int type)
Definition spell.c:1828
#define cpalloc0(size)
Definition spell.c:160
#define ANHRDSZ
Definition spell.h:145

References ANHRDSZ, cpalloc, cpalloc0, AffixNode::data, data, fb(), GETCHAR, i, AffixNode::length, mkANode(), AffixNodeData::node, pfree(), tmpalloc, and type.

Referenced by mkANode(), and NISortAffixes().

◆ mkSPNode()

static SPNode * mkSPNode ( IspellDict Conf,
int  low,
int  high,
int  level 
)
static

Definition at line 1637 of file spell.c.

1638{
1639 int i;
1640 int nchar = 0;
1641 char lastchar = '\0';
1642 SPNode *rs;
1644 int lownew = low;
1645
1646 for (i = low; i < high; i++)
1647 if (Conf->Spell[i]->p.d.len > level && lastchar != Conf->Spell[i]->word[level])
1648 {
1649 nchar++;
1650 lastchar = Conf->Spell[i]->word[level];
1651 }
1652
1653 if (!nchar)
1654 return NULL;
1655
1656 rs = (SPNode *) cpalloc0(SPNHDRSZ + nchar * sizeof(SPNodeData));
1657 rs->length = nchar;
1658 data = rs->data;
1659
1660 lastchar = '\0';
1661 for (i = low; i < high; i++)
1662 if (Conf->Spell[i]->p.d.len > level)
1663 {
1664 if (lastchar != Conf->Spell[i]->word[level])
1665 {
1666 if (lastchar)
1667 {
1668 /* Next level of the prefix tree */
1669 data->node = mkSPNode(Conf, lownew, i, level + 1);
1670 lownew = i;
1671 data++;
1672 }
1673 lastchar = Conf->Spell[i]->word[level];
1674 }
1675 data->val = ((uint8 *) (Conf->Spell[i]->word))[level];
1676 if (Conf->Spell[i]->p.d.len == level + 1)
1677 {
1678 bool clearCompoundOnly = false;
1679
1680 if (data->isword && data->affix != Conf->Spell[i]->p.d.affix)
1681 {
1682 /*
1683 * MergeAffix called a few times. If one of word is
1684 * allowed to be in compound word and another isn't, then
1685 * clear FF_COMPOUNDONLY flag.
1686 */
1687
1688 clearCompoundOnly = (FF_COMPOUNDONLY & data->compoundflag
1689 & makeCompoundFlags(Conf, Conf->Spell[i]->p.d.affix))
1690 ? false : true;
1691 data->affix = MergeAffix(Conf, data->affix, Conf->Spell[i]->p.d.affix);
1692 }
1693 else
1694 data->affix = Conf->Spell[i]->p.d.affix;
1695 data->isword = 1;
1696
1697 data->compoundflag = makeCompoundFlags(Conf, data->affix);
1698
1699 if ((data->compoundflag & FF_COMPOUNDONLY) &&
1700 (data->compoundflag & FF_COMPOUNDFLAG) == 0)
1701 data->compoundflag |= FF_COMPOUNDFLAG;
1702
1704 data->compoundflag &= ~FF_COMPOUNDONLY;
1705 }
1706 }
1707
1708 /* Next level of the prefix tree */
1709 data->node = mkSPNode(Conf, lownew, high, level + 1);
1710
1711 return rs;
1712}
return true
Definition isn.c:130
static SPNode * mkSPNode(IspellDict *Conf, int low, int high, int level)
Definition spell.c:1637
static uint32 makeCompoundFlags(IspellDict *Conf, int affix)
Definition spell.c:1620
static int MergeAffix(IspellDict *Conf, int a1, int a2)
Definition spell.c:1569
#define FF_COMPOUNDFLAG
Definition spell.h:46
#define SPNHDRSZ
Definition spell.h:56
struct SPNode * node
Definition spell.h:35

References cpalloc0, SPNode::data, data, fb(), FF_COMPOUNDFLAG, FF_COMPOUNDONLY, i, SPNode::length, makeCompoundFlags(), MergeAffix(), mkSPNode(), SPNodeData::node, and SPNHDRSZ.

Referenced by mkSPNode(), and NISortDictionary().

◆ mkVoidAffix()

static void mkVoidAffix ( IspellDict Conf,
bool  issuffix,
int  startsuffix 
)
static

Definition at line 1905 of file spell.c.

1906{
1907 int i,
1908 cnt = 0;
1909 int start = (issuffix) ? startsuffix : 0;
1910 int end = (issuffix) ? Conf->naffixes : startsuffix;
1911 AffixNode *Affix = (AffixNode *) palloc0(ANHRDSZ + sizeof(AffixNodeData));
1912
1913 Affix->length = 1;
1914 Affix->isvoid = 1;
1915
1916 if (issuffix)
1917 {
1918 Affix->data->node = Conf->Suffix;
1919 Conf->Suffix = Affix;
1920 }
1921 else
1922 {
1923 Affix->data->node = Conf->Prefix;
1924 Conf->Prefix = Affix;
1925 }
1926
1927 /* Count affixes with empty replace string */
1928 for (i = start; i < end; i++)
1929 if (Conf->Affix[i].replen == 0)
1930 cnt++;
1931
1932 /* There is not affixes with empty replace string */
1933 if (cnt == 0)
1934 return;
1935
1936 Affix->data->aff = (AFFIX **) cpalloc(sizeof(AFFIX *) * cnt);
1937 Affix->data->naff = (uint32) cnt;
1938
1939 cnt = 0;
1940 for (i = start; i < end; i++)
1941 if (Conf->Affix[i].replen == 0)
1942 {
1943 Affix->data->aff[cnt] = Conf->Affix + i;
1944 cnt++;
1945 }
1946}
return str start
AFFIX ** aff
Definition spell.h:134

References AffixNodeData::aff, ANHRDSZ, cpalloc, AffixNode::data, fb(), i, AffixNode::isvoid, AffixNode::length, AffixNodeData::naff, AffixNodeData::node, palloc0(), and start.

Referenced by NISortAffixes().

◆ NIAddAffix()

static void NIAddAffix ( IspellDict Conf,
const char flag,
char  flagflags,
const char mask,
const char find,
const char repl,
int  type 
)
static

Definition at line 680 of file spell.c.

682{
683 AFFIX *Affix;
684
685 if (Conf->naffixes >= Conf->maffixes)
686 {
687 if (Conf->maffixes)
688 {
689 Conf->maffixes *= 2;
690 Conf->Affix = (AFFIX *) repalloc(Conf->Affix, Conf->maffixes * sizeof(AFFIX));
691 }
692 else
693 {
694 Conf->maffixes = 16;
695 Conf->Affix = palloc_array(AFFIX, Conf->maffixes);
696 }
697 }
698
699 Affix = Conf->Affix + Conf->naffixes;
700
701 /* This affix rule can be applied for words with any ending */
702 if (strcmp(mask, ".") == 0 || *mask == '\0')
703 {
704 Affix->issimple = 1;
705 Affix->isregis = 0;
706 }
707 /* This affix rule will use regis to search word ending */
708 else if (RS_isRegis(mask))
709 {
710 Affix->issimple = 0;
711 Affix->isregis = 1;
712 RS_compile(&(Affix->reg.regis), (type == FF_SUFFIX),
713 *mask ? mask : VoidString);
714 }
715 /* This affix rule will use regex_t to search word ending */
716 else
717 {
718 int masklen;
719 int wmasklen;
720 int err;
722 char *tmask;
723
724 Affix->issimple = 0;
725 Affix->isregis = 0;
726 tmask = (char *) tmpalloc(strlen(mask) + 3);
727 if (type == FF_SUFFIX)
728 sprintf(tmask, "%s$", mask);
729 else
730 sprintf(tmask, "^%s", mask);
731
732 masklen = strlen(tmask);
733 wmask = (pg_wchar *) tmpalloc((masklen + 1) * sizeof(pg_wchar));
735
736 /*
737 * The regex and all internal state created by pg_regcomp are
738 * allocated in the dictionary's memory context, and will be freed
739 * automatically when it is destroyed.
740 */
745 if (err)
746 {
747 char errstr[100];
748
749 pg_regerror(err, Affix->reg.pregex, errstr, sizeof(errstr));
752 errmsg("invalid regular expression: %s", errstr)));
753 }
754 }
755
756 Affix->flagflags = flagflags;
757 if ((Affix->flagflags & FF_COMPOUNDONLY) || (Affix->flagflags & FF_COMPOUNDPERMITFLAG))
758 {
759 if ((Affix->flagflags & FF_COMPOUNDFLAG) == 0)
760 Affix->flagflags |= FF_COMPOUNDFLAG;
761 }
762 Affix->flag = cpstrdup(Conf, flag);
763 Affix->type = type;
764
765 Affix->find = (find && *find) ? cpstrdup(Conf, find) : VoidString;
766 if ((Affix->replen = strlen(repl)) > 0)
767 Affix->repl = cpstrdup(Conf, repl);
768 else
769 Affix->repl = VoidString;
770 Conf->naffixes++;
771}
void err(int eval, const char *fmt,...)
Definition err.c:43
int pg_regcomp(regex_t *re, const chr *string, size_t len, int flags, Oid collation)
Definition regcomp.c:372
size_t pg_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
Definition regerror.c:60
#define REG_ADVANCED
Definition regex.h:181
#define REG_NOSUB
Definition regex.h:185
#define regex_t
Definition regex.h:245
static int find(struct vars *v, struct cnfa *cnfa, struct colormap *cm)
Definition regexec.c:419
void RS_compile(Regis *r, bool issuffix, const char *str)
Definition regis.c:85
bool RS_isRegis(const char *str)
Definition regis.c:31
static char * cpstrdup(IspellDict *Conf, const char *str)
Definition spell.c:163
#define FF_COMPOUNDPERMITFLAG
Definition spell.h:113
const char * flag
Definition spell.h:89
const char * repl
Definition spell.h:97

References cpstrdup(), ereport, err(), errcode(), errmsg(), ERROR, fb(), FF_COMPOUNDFLAG, FF_COMPOUNDONLY, FF_COMPOUNDPERMITFLAG, FF_SUFFIX, find(), aff_struct::find, aff_struct::flag, flag(), aff_struct::flagflags, aff_struct::isregis, aff_struct::issimple, palloc_array, palloc_object, pg_mb2wchar_with_len(), pg_regcomp(), pg_regerror(), aff_struct::pregex, aff_struct::reg, REG_ADVANCED, REG_NOSUB, regex_t, aff_struct::regis, repalloc(), aff_struct::repl, aff_struct::replen, RS_compile(), RS_isRegis(), sprintf, tmpalloc, type, aff_struct::type, and VoidString.

Referenced by NIImportAffixes(), and NIImportOOAffixes().

◆ NIAddSpell()

static void NIAddSpell ( IspellDict Conf,
const char word,
const char flag 
)
static

Definition at line 489 of file spell.c.

490{
491 if (Conf->nspell >= Conf->mspell)
492 {
493 if (Conf->mspell)
494 {
495 Conf->mspell *= 2;
496 Conf->Spell = (SPELL **) repalloc(Conf->Spell, Conf->mspell * sizeof(SPELL *));
497 }
498 else
499 {
500 Conf->mspell = 1024 * 20;
501 Conf->Spell = (SPELL **) tmpalloc(Conf->mspell * sizeof(SPELL *));
502 }
503 }
504 Conf->Spell[Conf->nspell] = (SPELL *) tmpalloc(SPELLHDRSZ + strlen(word) + 1);
505 strcpy(Conf->Spell[Conf->nspell]->word, word);
506 Conf->Spell[Conf->nspell]->p.flag = (*flag != '\0')
508 Conf->nspell++;
509}
#define SPELLHDRSZ
Definition spell.h:82

References cpstrdup(), fb(), flag(), repalloc(), SPELLHDRSZ, tmpalloc, VoidString, and word().

Referenced by NIImportDictionary().

◆ NIFinishBuild()

void NIFinishBuild ( IspellDict Conf)

Definition at line 104 of file spell.c.

105{
106 /* Release no-longer-needed temp memory */
107 MemoryContextDelete(Conf->buildCxt);
108 /* Just for cleanliness, zero the now-dangling pointers */
109 Conf->buildCxt = NULL;
110 Conf->Spell = NULL;
111 Conf->firstfree = NULL;
112 Conf->CompoundAffixFlags = NULL;
113}
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472

References fb(), and MemoryContextDelete().

Referenced by dispell_init().

◆ NIImportAffixes()

void NIImportAffixes ( IspellDict Conf,
const char filename 
)

Definition at line 1423 of file spell.c.

1424{
1425 char *pstr = NULL;
1426 char flag[BUFSIZ];
1427 char mask[BUFSIZ];
1428 char find[BUFSIZ];
1429 char repl[BUFSIZ];
1430 char *s;
1431 bool suffixes = false;
1432 bool prefixes = false;
1433 char flagflags = 0;
1435 bool oldformat = false;
1436 char *recoded = NULL;
1437
1439 ereport(ERROR,
1441 errmsg("could not open affix file \"%s\": %m",
1442 filename)));
1443
1444 Conf->usecompound = false;
1445 Conf->useFlagAliases = false;
1446 Conf->flagMode = FM_CHAR;
1447
1448 while ((recoded = tsearch_readline(&trst)) != NULL)
1449 {
1451
1452 /* Skip comments and empty lines */
1453 if (*pstr == '#' || *pstr == '\n')
1454 goto nextline;
1455
1456 if (STRNCMP(pstr, "compoundwords") == 0)
1457 {
1458 /* Find case-insensitive L flag in non-lowercased string */
1459 s = findchar2(recoded, 'l', 'L');
1460 if (s)
1461 {
1462 while (*s && !isspace((unsigned char) *s))
1463 s += pg_mblen_cstr(s);
1464 while (*s && isspace((unsigned char) *s))
1465 s += pg_mblen_cstr(s);
1466
1467 if (*s && pg_mblen_cstr(s) == 1)
1468 {
1470 Conf->usecompound = true;
1471 }
1472 oldformat = true;
1473 goto nextline;
1474 }
1475 }
1476 if (STRNCMP(pstr, "suffixes") == 0)
1477 {
1478 suffixes = true;
1479 prefixes = false;
1480 oldformat = true;
1481 goto nextline;
1482 }
1483 if (STRNCMP(pstr, "prefixes") == 0)
1484 {
1485 suffixes = false;
1486 prefixes = true;
1487 oldformat = true;
1488 goto nextline;
1489 }
1490 if (STRNCMP(pstr, "flag") == 0)
1491 {
1492 s = recoded + 4; /* we need non-lowercased string */
1493 flagflags = 0;
1494
1495 while (*s && isspace((unsigned char) *s))
1496 s += pg_mblen_cstr(s);
1497
1498 if (*s == '*')
1499 {
1500 flagflags |= FF_CROSSPRODUCT;
1501 s++;
1502 }
1503 else if (*s == '~')
1504 {
1505 flagflags |= FF_COMPOUNDONLY;
1506 s++;
1507 }
1508
1509 if (*s == '\\')
1510 s++;
1511
1512 /*
1513 * An old-format flag is a single ASCII character; we expect it to
1514 * be followed by EOL, whitespace, or ':'. Otherwise this is a
1515 * new-format flag command.
1516 */
1517 if (*s && pg_mblen_cstr(s) == 1)
1518 {
1519 flag[0] = *s++;
1520 flag[1] = '\0';
1521
1522 if (*s == '\0' || *s == '#' || *s == '\n' || *s == ':' ||
1523 isspace((unsigned char) *s))
1524 {
1525 oldformat = true;
1526 goto nextline;
1527 }
1528 }
1529 goto isnewformat;
1530 }
1531 if (STRNCMP(recoded, "COMPOUNDFLAG") == 0 ||
1532 STRNCMP(recoded, "COMPOUNDMIN") == 0 ||
1533 STRNCMP(recoded, "PFX") == 0 ||
1534 STRNCMP(recoded, "SFX") == 0)
1535 goto isnewformat;
1536
1537 if ((!suffixes) && (!prefixes))
1538 goto nextline;
1539
1540 if (!parse_affentry(pstr, mask, find, repl))
1541 goto nextline;
1542
1543 NIAddAffix(Conf, flag, flagflags, mask, find, repl, suffixes ? FF_SUFFIX : FF_PREFIX);
1544
1545nextline:
1546 pfree(recoded);
1547 pfree(pstr);
1548 }
1550 return;
1551
1553 if (oldformat)
1554 ereport(ERROR,
1556 errmsg("affix file contains both old-style and new-style commands")));
1558
1560}
static char * filename
Definition pg_dumpall.c:120
static void prefixes(struct vars *v)
Definition regc_lex.c:99
static void NIImportOOAffixes(IspellDict *Conf, const char *filename)
Definition spell.c:1194
static void NIAddAffix(IspellDict *Conf, const char *flag, char flagflags, const char *mask, const char *find, const char *repl, int type)
Definition spell.c:680
#define STRNCMP(s, p)
Definition spell.c:191
static char * findchar2(char *str, int c1, int c2)
Definition spell.c:243
static bool parse_affentry(char *str, char *mask, char *find, char *repl)
Definition spell.c:914
static void addCompoundAffixFlagValue(IspellDict *Conf, char *s, uint32 val)
Definition spell.c:1064
#define FF_CROSSPRODUCT
Definition spell.h:115
bool tsearch_readline_begin(tsearch_readline_state *stp, const char *filename)
Definition ts_locale.c:85
char * tsearch_readline(tsearch_readline_state *stp)
Definition ts_locale.c:108
void tsearch_readline_end(tsearch_readline_state *stp)
Definition ts_locale.c:153

References addCompoundAffixFlagValue(), ereport, errcode(), errmsg(), ERROR, fb(), FF_COMPOUNDFLAG, FF_COMPOUNDONLY, FF_CROSSPRODUCT, FF_PREFIX, FF_SUFFIX, filename, find(), findchar2(), flag(), FM_CHAR, NIAddAffix(), NIImportOOAffixes(), parse_affentry(), pfree(), pg_mblen_cstr(), prefixes(), str_tolower(), STRNCMP, tsearch_readline(), tsearch_readline_begin(), and tsearch_readline_end().

Referenced by dispell_init().

◆ NIImportDictionary()

void NIImportDictionary ( IspellDict Conf,
const char filename 
)

Definition at line 520 of file spell.c.

521{
523 char *line;
524
528 errmsg("could not open dictionary file \"%s\": %m",
529 filename)));
530
531 while ((line = tsearch_readline(&trst)) != NULL)
532 {
533 char *s,
534 *pstr;
535
536 /* Set of affix flags */
537 const char *flag;
538
539 /* Extract flag from the line */
540 flag = NULL;
541 if ((s = findchar(line, '/')))
542 {
543 *s++ = '\0';
544 flag = s;
545 while (*s)
546 {
547 /* we allow only single encoded flags for faster works */
548 if (pg_mblen_cstr(s) == 1 && isprint((unsigned char) *s) && !isspace((unsigned char) *s))
549 s++;
550 else
551 {
552 *s = '\0';
553 break;
554 }
555 }
556 }
557 else
558 flag = "";
559
560 /* Remove trailing spaces */
561 s = line;
562 while (*s)
563 {
564 if (isspace((unsigned char) *s))
565 {
566 *s = '\0';
567 break;
568 }
569 s += pg_mblen_cstr(s);
570 }
571 pstr = lowerstr_ctx(Conf, line);
572
574 pfree(pstr);
575
576 pfree(line);
577 }
579}
static void NIAddSpell(IspellDict *Conf, const char *word, const char *flag)
Definition spell.c:489
static char * findchar(char *str, int c)
Definition spell.c:230
static char * lowerstr_ctx(IspellDict *Conf, const char *src)
Definition spell.c:176

References ereport, errcode(), errmsg(), ERROR, fb(), filename, findchar(), flag(), lowerstr_ctx(), NIAddSpell(), pfree(), pg_mblen_cstr(), tsearch_readline(), tsearch_readline_begin(), and tsearch_readline_end().

Referenced by dispell_init().

◆ NIImportOOAffixes()

static void NIImportOOAffixes ( IspellDict Conf,
const char filename 
)
static

Definition at line 1194 of file spell.c.

1195{
1196 char type[BUFSIZ],
1197 *ptype = NULL;
1198 char sflag[BUFSIZ];
1199 char mask[BUFSIZ],
1200 *pmask;
1201 char find[BUFSIZ],
1202 *pfind;
1203 char repl[BUFSIZ],
1204 *prepl;
1205 bool isSuffix = false;
1206 int naffix = 0,
1207 curaffix = 0;
1208 int sflaglen = 0;
1209 char flagflags = 0;
1211 char *recoded;
1212
1213 /* read file to find any flag */
1214 Conf->usecompound = false;
1215 Conf->useFlagAliases = false;
1216 Conf->flagMode = FM_CHAR;
1217
1219 ereport(ERROR,
1221 errmsg("could not open affix file \"%s\": %m",
1222 filename)));
1223
1224 while ((recoded = tsearch_readline(&trst)) != NULL)
1225 {
1226 if (*recoded == '\0' || isspace((unsigned char) *recoded) || t_iseq(recoded, '#'))
1227 {
1228 pfree(recoded);
1229 continue;
1230 }
1231
1232 if (STRNCMP(recoded, "COMPOUNDFLAG") == 0)
1233 addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDFLAG"),
1235 else if (STRNCMP(recoded, "COMPOUNDBEGIN") == 0)
1236 addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDBEGIN"),
1238 else if (STRNCMP(recoded, "COMPOUNDLAST") == 0)
1239 addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDLAST"),
1241 /* COMPOUNDLAST and COMPOUNDEND are synonyms */
1242 else if (STRNCMP(recoded, "COMPOUNDEND") == 0)
1243 addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDEND"),
1245 else if (STRNCMP(recoded, "COMPOUNDMIDDLE") == 0)
1246 addCompoundAffixFlagValue(Conf, recoded + strlen("COMPOUNDMIDDLE"),
1248 else if (STRNCMP(recoded, "ONLYINCOMPOUND") == 0)
1249 addCompoundAffixFlagValue(Conf, recoded + strlen("ONLYINCOMPOUND"),
1251 else if (STRNCMP(recoded, "COMPOUNDPERMITFLAG") == 0)
1253 recoded + strlen("COMPOUNDPERMITFLAG"),
1255 else if (STRNCMP(recoded, "COMPOUNDFORBIDFLAG") == 0)
1257 recoded + strlen("COMPOUNDFORBIDFLAG"),
1259 else if (STRNCMP(recoded, "FLAG") == 0)
1260 {
1261 char *s = recoded + strlen("FLAG");
1262
1263 while (*s && isspace((unsigned char) *s))
1264 s += pg_mblen_cstr(s);
1265
1266 if (*s)
1267 {
1268 if (STRNCMP(s, "long") == 0)
1269 Conf->flagMode = FM_LONG;
1270 else if (STRNCMP(s, "num") == 0)
1271 Conf->flagMode = FM_NUM;
1272 else if (STRNCMP(s, "default") != 0)
1273 ereport(ERROR,
1275 errmsg("Ispell dictionary supports only "
1276 "\"default\", \"long\", "
1277 "and \"num\" flag values")));
1278 }
1279 }
1280
1281 pfree(recoded);
1282 }
1284
1285 if (Conf->nCompoundAffixFlag > 1)
1286 qsort(Conf->CompoundAffixFlags, Conf->nCompoundAffixFlag,
1287 sizeof(CompoundAffixFlag), cmpcmdflag);
1288
1290 ereport(ERROR,
1292 errmsg("could not open affix file \"%s\": %m",
1293 filename)));
1294
1295 while ((recoded = tsearch_readline(&trst)) != NULL)
1296 {
1297 int fields_read;
1298
1299 if (*recoded == '\0' || isspace((unsigned char) *recoded) || t_iseq(recoded, '#'))
1300 goto nextline;
1301
1303
1304 if (ptype)
1305 pfree(ptype);
1306 ptype = lowerstr_ctx(Conf, type);
1307
1308 /* First try to parse AF parameter (alias compression) */
1309 if (STRNCMP(ptype, "af") == 0)
1310 {
1311 /* First line is the number of aliases */
1312 if (!Conf->useFlagAliases)
1313 {
1314 Conf->useFlagAliases = true;
1315 naffix = atoi(sflag);
1316 if (naffix <= 0)
1317 ereport(ERROR,
1319 errmsg("invalid number of flag vector aliases")));
1320
1321 /* Also reserve place for empty flag set */
1322 naffix++;
1323
1324 Conf->AffixData = palloc0_array(const char *, naffix);
1325 Conf->lenAffixData = Conf->nAffixData = naffix;
1326
1327 /* Add empty flag set into AffixData */
1328 Conf->AffixData[curaffix] = VoidString;
1329 curaffix++;
1330 }
1331 /* Other lines are aliases */
1332 else
1333 {
1334 if (curaffix < naffix)
1335 {
1336 Conf->AffixData[curaffix] = cpstrdup(Conf, sflag);
1337 curaffix++;
1338 }
1339 else
1340 ereport(ERROR,
1342 errmsg("number of aliases exceeds specified number %d",
1343 naffix - 1)));
1344 }
1345 goto nextline;
1346 }
1347 /* Else try to parse prefixes and suffixes */
1348 if (fields_read < 4 ||
1349 (STRNCMP(ptype, "sfx") != 0 && STRNCMP(ptype, "pfx") != 0))
1350 goto nextline;
1351
1353 if (sflaglen == 0
1354 || (sflaglen > 1 && Conf->flagMode == FM_CHAR)
1355 || (sflaglen > 2 && Conf->flagMode == FM_LONG))
1356 goto nextline;
1357
1358 /*--------
1359 * Affix header. For example:
1360 * SFX \ N 1
1361 *--------
1362 */
1363 if (fields_read == 4)
1364 {
1365 isSuffix = (STRNCMP(ptype, "sfx") == 0);
1366 if (t_iseq(find, 'y') || t_iseq(find, 'Y'))
1367 flagflags = FF_CROSSPRODUCT;
1368 else
1369 flagflags = 0;
1370 }
1371 /*--------
1372 * Affix fields. For example:
1373 * SFX \ 0 Y/L [^Y]
1374 *--------
1375 */
1376 else
1377 {
1378 char *ptr;
1379 int aflg = 0;
1380
1381 /* Get flags after '/' (flags are case sensitive) */
1382 if ((ptr = strchr(repl, '/')) != NULL)
1385 ptr + 1));
1386 /* Get lowercased version of string before '/' */
1387 prepl = lowerstr_ctx(Conf, repl);
1388 if ((ptr = strchr(prepl, '/')) != NULL)
1389 *ptr = '\0';
1391 pmask = lowerstr_ctx(Conf, mask);
1392 if (t_iseq(find, '0'))
1393 *pfind = '\0';
1394 if (t_iseq(repl, '0'))
1395 *prepl = '\0';
1396
1397 NIAddAffix(Conf, sflag, flagflags | aflg, pmask, pfind, prepl,
1399 pfree(prepl);
1400 pfree(pfind);
1401 pfree(pmask);
1402 }
1403
1404nextline:
1405 pfree(recoded);
1406 }
1407
1409 if (ptype)
1410 pfree(ptype);
1411}
#define palloc0_array(type, count)
Definition fe_memutils.h:77
#define qsort(a, b, c, d)
Definition port.h:495
static int parse_ooaffentry(char *str, char *type, char *flag, char *find, char *repl, char *mask)
Definition spell.c:858
static const char * getAffixFlagSet(IspellDict *Conf, char *s)
Definition spell.c:1156

References addCompoundAffixFlagValue(), cmpcmdflag(), cpstrdup(), ereport, errcode(), errmsg(), ERROR, fb(), FF_COMPOUNDBEGIN, FF_COMPOUNDFLAG, FF_COMPOUNDFORBIDFLAG, FF_COMPOUNDLAST, FF_COMPOUNDMIDDLE, FF_COMPOUNDONLY, FF_COMPOUNDPERMITFLAG, FF_CROSSPRODUCT, FF_PREFIX, FF_SUFFIX, filename, find(), FM_CHAR, FM_LONG, FM_NUM, getAffixFlagSet(), getCompoundAffixFlagValue(), lowerstr_ctx(), NIAddAffix(), palloc0_array, parse_ooaffentry(), pfree(), pg_mblen_cstr(), qsort, STRNCMP, t_iseq, tsearch_readline(), tsearch_readline_begin(), tsearch_readline_end(), type, and VoidString.

Referenced by NIImportAffixes().

◆ NINormalizeWord()

TSLexeme * NINormalizeWord ( IspellDict Conf,
const char word 
)

Definition at line 2538 of file spell.c.

2539{
2540 char **res;
2541 TSLexeme *lcur = NULL,
2542 *lres = NULL;
2543 uint16 NVariant = 1;
2544
2545 res = NormalizeSubWord(Conf, word, 0);
2546
2547 if (res)
2548 {
2549 char **ptr = res;
2550
2551 while (*ptr && (lcur - lres) < MAX_NORM)
2552 {
2553 addNorm(&lres, &lcur, *ptr, 0, NVariant++);
2554 ptr++;
2555 }
2556 pfree(res);
2557 }
2558
2559 if (Conf->usecompound)
2560 {
2561 int wordlen = strlen(word);
2562 SplitVar *ptr,
2563 *var = SplitToVariants(Conf, NULL, NULL, word, wordlen, 0, -1);
2564 int i;
2565
2566 while (var)
2567 {
2568 if (var->nstem > 1)
2569 {
2570 char **subres = NormalizeSubWord(Conf, var->stem[var->nstem - 1], FF_COMPOUNDLAST);
2571
2572 if (subres)
2573 {
2574 char **subptr = subres;
2575
2576 while (*subptr)
2577 {
2578 for (i = 0; i < var->nstem - 1; i++)
2579 {
2580 addNorm(&lres, &lcur, (subptr == subres) ? var->stem[i] : pstrdup(var->stem[i]), 0, NVariant);
2581 }
2582
2583 addNorm(&lres, &lcur, *subptr, 0, NVariant);
2584 subptr++;
2585 NVariant++;
2586 }
2587
2588 pfree(subres);
2589 var->stem[0] = NULL;
2590 pfree(var->stem[var->nstem - 1]);
2591 }
2592 }
2593
2594 for (i = 0; i < var->nstem && var->stem[i]; i++)
2595 pfree(var->stem[i]);
2596 ptr = var->next;
2597 pfree(var->stem);
2598 pfree(var);
2599 var = ptr;
2600 }
2601 }
2602
2603 return lres;
2604}
uint16_t uint16
Definition c.h:545
static void addNorm(TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant)
Definition spell.c:2522
static char ** NormalizeSubWord(IspellDict *Conf, const char *word, int flag)
Definition spell.c:2174
static SplitVar * SplitToVariants(IspellDict *Conf, SPNode *snode, SplitVar *orig, const char *word, int wordlen, int startpos, int minpos)
Definition spell.c:2372

References addNorm(), fb(), FF_COMPOUNDLAST, i, MAX_NORM, SplitVar::next, NormalizeSubWord(), SplitVar::nstem, pfree(), pstrdup(), SplitToVariants(), SplitVar::stem, and word().

Referenced by dispell_lexize().

◆ NISortAffixes()

void NISortAffixes ( IspellDict Conf)

Definition at line 1974 of file spell.c.

1975{
1976 AFFIX *Affix;
1977 size_t i;
1978 CMPDAffix *ptr;
1979 int firstsuffix = Conf->naffixes;
1980
1981 if (Conf->naffixes == 0)
1982 return;
1983
1984 /* Store compound affixes in the Conf->CompoundAffix array */
1985 if (Conf->naffixes > 1)
1986 qsort(Conf->Affix, Conf->naffixes, sizeof(AFFIX), cmpaffix);
1987 Conf->CompoundAffix = ptr = palloc_array(CMPDAffix, Conf->naffixes);
1988 ptr->affix = NULL;
1989
1990 for (i = 0; i < Conf->naffixes; i++)
1991 {
1992 Affix = &(((AFFIX *) Conf->Affix)[i]);
1993 if (Affix->type == FF_SUFFIX && i < firstsuffix)
1994 firstsuffix = i;
1995
1996 if ((Affix->flagflags & FF_COMPOUNDFLAG) && Affix->replen > 0 &&
1997 isAffixInUse(Conf, Affix->flag))
1998 {
1999 bool issuffix = (Affix->type == FF_SUFFIX);
2000
2001 if (ptr == Conf->CompoundAffix ||
2002 issuffix != (ptr - 1)->issuffix ||
2003 strbncmp((const unsigned char *) (ptr - 1)->affix,
2004 (const unsigned char *) Affix->repl,
2005 (ptr - 1)->len))
2006 {
2007 /* leave only unique and minimal suffixes */
2008 ptr->affix = Affix->repl;
2009 ptr->len = Affix->replen;
2010 ptr->issuffix = issuffix;
2011 ptr++;
2012 }
2013 }
2014 }
2015 ptr->affix = NULL;
2016 Conf->CompoundAffix = (CMPDAffix *) repalloc(Conf->CompoundAffix, sizeof(CMPDAffix) * (ptr - Conf->CompoundAffix + 1));
2017
2018 /* Start build a prefix tree */
2019 Conf->Prefix = mkANode(Conf, 0, firstsuffix, 0, FF_PREFIX);
2020 Conf->Suffix = mkANode(Conf, firstsuffix, Conf->naffixes, 0, FF_SUFFIX);
2022 mkVoidAffix(Conf, false, firstsuffix);
2023}
static int strbncmp(const unsigned char *s1, const unsigned char *s2, size_t count)
Definition spell.c:281
static void mkVoidAffix(IspellDict *Conf, bool issuffix, int startsuffix)
Definition spell.c:1905
static bool isAffixInUse(IspellDict *Conf, const char *affixflag)
Definition spell.c:1959
static int cmpaffix(const void *s1, const void *s2)
Definition spell.c:312
int len
Definition spell.h:150
bool issuffix
Definition spell.h:151
const char * affix
Definition spell.h:149

References CMPDAffix::affix, cmpaffix(), fb(), FF_COMPOUNDFLAG, FF_PREFIX, FF_SUFFIX, aff_struct::flag, aff_struct::flagflags, i, isAffixInUse(), CMPDAffix::issuffix, CMPDAffix::len, mkANode(), mkVoidAffix(), palloc_array, qsort, repalloc(), aff_struct::repl, aff_struct::replen, strbncmp(), and aff_struct::type.

Referenced by dispell_init().

◆ NISortDictionary()

void NISortDictionary ( IspellDict Conf)

Definition at line 1719 of file spell.c.

1720{
1721 int i;
1722 int naffix;
1723 int curaffix;
1724
1725 /* compress affixes */
1726
1727 /*
1728 * If we use flag aliases then we need to use Conf->AffixData filled in
1729 * the NIImportOOAffixes().
1730 */
1731 if (Conf->useFlagAliases)
1732 {
1733 for (i = 0; i < Conf->nspell; i++)
1734 {
1735 char *end;
1736
1737 if (*Conf->Spell[i]->p.flag != '\0')
1738 {
1739 errno = 0;
1740 curaffix = strtol(Conf->Spell[i]->p.flag, &end, 10);
1741 if (Conf->Spell[i]->p.flag == end || errno == ERANGE)
1742 ereport(ERROR,
1744 errmsg("invalid affix alias \"%s\"",
1745 Conf->Spell[i]->p.flag)));
1746 if (curaffix < 0 || curaffix >= Conf->nAffixData)
1747 ereport(ERROR,
1749 errmsg("invalid affix alias \"%s\"",
1750 Conf->Spell[i]->p.flag)));
1751 if (*end != '\0' && !isdigit((unsigned char) *end) && !isspace((unsigned char) *end))
1752 ereport(ERROR,
1754 errmsg("invalid affix alias \"%s\"",
1755 Conf->Spell[i]->p.flag)));
1756 }
1757 else
1758 {
1759 /*
1760 * If Conf->Spell[i]->p.flag is empty, then get empty value of
1761 * Conf->AffixData (0 index).
1762 */
1763 curaffix = 0;
1764 }
1765
1766 Conf->Spell[i]->p.d.affix = curaffix;
1767 Conf->Spell[i]->p.d.len = strlen(Conf->Spell[i]->word);
1768 }
1769 }
1770 /* Otherwise fill Conf->AffixData here */
1771 else
1772 {
1773 /* Count the number of different flags used in the dictionary */
1774 qsort(Conf->Spell, Conf->nspell, sizeof(SPELL *),
1776
1777 naffix = 0;
1778 for (i = 0; i < Conf->nspell; i++)
1779 {
1780 if (i == 0 ||
1781 strcmp(Conf->Spell[i]->p.flag, Conf->Spell[i - 1]->p.flag) != 0)
1782 naffix++;
1783 }
1784
1785 /*
1786 * Fill in Conf->AffixData with the affixes that were used in the
1787 * dictionary. Replace textual flag-field of Conf->Spell entries with
1788 * indexes into Conf->AffixData array.
1789 */
1790 Conf->AffixData = palloc0_array(const char *, naffix);
1791
1792 curaffix = -1;
1793 for (i = 0; i < Conf->nspell; i++)
1794 {
1795 if (i == 0 ||
1796 strcmp(Conf->Spell[i]->p.flag, Conf->AffixData[curaffix]) != 0)
1797 {
1798 curaffix++;
1800 Conf->AffixData[curaffix] = cpstrdup(Conf,
1801 Conf->Spell[i]->p.flag);
1802 }
1803
1804 Conf->Spell[i]->p.d.affix = curaffix;
1805 Conf->Spell[i]->p.d.len = strlen(Conf->Spell[i]->word);
1806 }
1807
1808 Conf->lenAffixData = Conf->nAffixData = naffix;
1809 }
1810
1811 /* Start build a prefix tree */
1812 qsort(Conf->Spell, Conf->nspell, sizeof(SPELL *), cmpspell);
1813 Conf->Dictionary = mkSPNode(Conf, 0, Conf->nspell, 0);
1814}
static int cmpspell(const void *s1, const void *s2)
Definition spell.c:198
static int cmpspellaffix(const void *s1, const void *s2)
Definition spell.c:204

References Assert, cmpspell(), cmpspellaffix(), cpstrdup(), ereport, errcode(), errmsg(), ERROR, fb(), i, mkSPNode(), palloc0_array, and qsort.

Referenced by dispell_init().

◆ NIStartBuild()

void NIStartBuild ( IspellDict Conf)

Definition at line 89 of file spell.c.

90{
91 /*
92 * The temp context is a child of CurTransactionContext, so that it will
93 * go away automatically on error.
94 */
96 "Ispell dictionary init context",
98}
MemoryContext CurTransactionContext
Definition mcxt.c:172
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurTransactionContext, and fb().

Referenced by dispell_init().

◆ NormalizeSubWord()

static char ** NormalizeSubWord ( IspellDict Conf,
const char word,
int  flag 
)
static

Definition at line 2174 of file spell.c.

2175{
2176 AffixNodeData *suffix = NULL,
2177 *prefix = NULL;
2178 int slevel = 0,
2179 plevel = 0;
2180 int wrdlen = strlen(word),
2181 swrdlen;
2182 char **forms;
2183 char **cur;
2184 char newword[2 * MAXNORMLEN] = "";
2185 char pnewword[2 * MAXNORMLEN] = "";
2186 AffixNode *snode = Conf->Suffix,
2187 *pnode;
2188 int i,
2189 j;
2190
2191 if (wrdlen > MAXNORMLEN)
2192 return NULL;
2193 cur = forms = palloc_array(char *, MAX_NORM);
2194 *cur = NULL;
2195
2196
2197 /* Check that the word itself is normal form */
2199 {
2200 *cur = pstrdup(word);
2201 cur++;
2202 *cur = NULL;
2203 }
2204
2205 /* Find all other NORMAL forms of the 'word' (check only prefix) */
2206 pnode = Conf->Prefix;
2207 plevel = 0;
2208 while (pnode)
2209 {
2211 if (!prefix)
2212 break;
2213 for (j = 0; j < prefix->naff; j++)
2214 {
2215 if (CheckAffix(word, wrdlen, prefix->aff[j], flag, newword, NULL))
2216 {
2217 /* prefix success */
2218 if (FindWord(Conf, newword, prefix->aff[j]->flag, flag))
2220 }
2221 }
2222 pnode = prefix->node;
2223 }
2224
2225 /*
2226 * Find all other NORMAL forms of the 'word' (check suffix and then
2227 * prefix)
2228 */
2229 while (snode)
2230 {
2231 int baselen = 0;
2232
2233 /* find possible suffix */
2235 if (!suffix)
2236 break;
2237 /* foreach suffix check affix */
2238 for (i = 0; i < suffix->naff; i++)
2239 {
2240 if (CheckAffix(word, wrdlen, suffix->aff[i], flag, newword, &baselen))
2241 {
2242 /* suffix success */
2243 if (FindWord(Conf, newword, suffix->aff[i]->flag, flag))
2245
2246 /* now we will look changed word with prefixes */
2247 pnode = Conf->Prefix;
2248 plevel = 0;
2250 while (pnode)
2251 {
2253 if (!prefix)
2254 break;
2255 for (j = 0; j < prefix->naff; j++)
2256 {
2257 if (CheckAffix(newword, swrdlen, prefix->aff[j], flag, pnewword, &baselen))
2258 {
2259 /* prefix success */
2260 const char *ff = (prefix->aff[j]->flagflags & suffix->aff[i]->flagflags & FF_CROSSPRODUCT) ?
2261 VoidString : prefix->aff[j]->flag;
2262
2263 if (FindWord(Conf, pnewword, ff, flag))
2265 }
2266 }
2267 pnode = prefix->node;
2268 }
2269 }
2270 }
2271
2272 snode = suffix->node;
2273 }
2274
2275 if (cur == forms)
2276 {
2277 pfree(forms);
2278 return NULL;
2279 }
2280 return forms;
2281}
int j
Definition isn.c:78
static int FindWord(IspellDict *Conf, const char *word, const char *affixflag, int flag)
Definition spell.c:605
static AffixNodeData * FindAffixes(AffixNode *node, const char *word, int wrdlen, int *level, int type)
Definition spell.c:2026
static char * CheckAffix(const char *word, size_t len, AFFIX *Affix, int flagflags, char *newword, int *baselen)
Definition spell.c:2069
#define MAXNORMLEN
Definition spell.c:189
static int addToResult(char **forms, char **cur, char *word)
Definition spell.c:2159

References addToResult(), AffixNodeData::aff, CheckAffix(), cur, fb(), FF_CROSSPRODUCT, FF_PREFIX, FF_SUFFIX, FindAffixes(), FindWord(), aff_struct::flag, flag(), aff_struct::flagflags, i, j, MAX_NORM, MAXNORMLEN, AffixNodeData::naff, AffixNodeData::node, palloc_array, pfree(), pstrdup(), VoidString, and word().

Referenced by NINormalizeWord(), and SplitToVariants().

◆ parse_affentry()

static bool parse_affentry ( char str,
char mask,
char find,
char repl 
)
static

Definition at line 914 of file spell.c.

915{
916 int state = PAE_WAIT_MASK;
917 char *pmask = mask,
918 *pfind = find,
919 *prepl = repl;
920
921 *mask = *find = *repl = '\0';
922
923 while (*str)
924 {
925 int clen = pg_mblen_cstr(str);
926
927 if (state == PAE_WAIT_MASK)
928 {
929 if (t_iseq(str, '#'))
930 return false;
931 else if (!isspace((unsigned char) *str))
932 {
935 }
936 }
937 else if (state == PAE_INMASK)
938 {
939 if (t_iseq(str, '>'))
940 {
941 *pmask = '\0';
943 }
944 else if (!isspace((unsigned char) *str))
945 {
947 }
948 }
949 else if (state == PAE_WAIT_FIND)
950 {
951 if (t_iseq(str, '-'))
952 {
954 }
955 else if (t_isalpha_cstr(str) || t_iseq(str, '\'') /* english 's */ )
956 {
959 }
960 else if (!isspace((unsigned char) *str))
963 errmsg("syntax error")));
964 }
965 else if (state == PAE_INFIND)
966 {
967 if (t_iseq(str, ','))
968 {
969 *pfind = '\0';
971 }
972 else if (t_isalpha_cstr(str))
973 {
975 }
976 else if (!isspace((unsigned char) *str))
979 errmsg("syntax error")));
980 }
981 else if (state == PAE_WAIT_REPL)
982 {
983 if (t_iseq(str, '-'))
984 {
985 break; /* void repl */
986 }
987 else if (t_isalpha_cstr(str))
988 {
991 }
992 else if (!isspace((unsigned char) *str))
995 errmsg("syntax error")));
996 }
997 else if (state == PAE_INREPL)
998 {
999 if (t_iseq(str, '#'))
1000 {
1001 *prepl = '\0';
1002 break;
1003 }
1004 else if (t_isalpha_cstr(str))
1005 {
1007 }
1008 else if (!isspace((unsigned char) *str))
1009 ereport(ERROR,
1011 errmsg("syntax error")));
1012 }
1013 else
1014 elog(ERROR, "unrecognized state in parse_affentry: %d", state);
1015
1016 str += clen;
1017 }
1018
1019 *pmask = *pfind = *prepl = '\0';
1020
1021 return (*mask && (*find || *repl));
1022}
#define PAE_WAIT_REPL
Definition spell.c:778
#define PAE_INREPL
Definition spell.c:779
#define PAE_WAIT_FIND
Definition spell.c:776
#define PAE_INFIND
Definition spell.c:777

References elog, ereport, errcode(), errmsg(), ERROR, fb(), find(), PAE_INFIND, PAE_INMASK, PAE_INREPL, PAE_WAIT_FIND, PAE_WAIT_MASK, PAE_WAIT_REPL, pg_mblen_cstr(), str, t_iseq, and ts_copychar_with_len().

Referenced by NIImportAffixes().

◆ parse_ooaffentry()

static int parse_ooaffentry ( char str,
char type,
char flag,
char find,
char repl,
char mask 
)
static

Definition at line 858 of file spell.c.

860{
861 int state = PAE_WAIT_TYPE;
862 int fields_read = 0;
863 bool valid = false;
864
865 *type = *flag = *find = *repl = *mask = '\0';
866
867 while (*str)
868 {
869 switch (state)
870 {
871 case PAE_WAIT_TYPE:
872 valid = get_nextfield(&str, type);
874 break;
875 case PAE_WAIT_FLAG:
876 valid = get_nextfield(&str, flag);
878 break;
879 case PAE_WAIT_FIND:
880 valid = get_nextfield(&str, find);
882 break;
883 case PAE_WAIT_REPL:
884 valid = get_nextfield(&str, repl);
886 break;
887 case PAE_WAIT_MASK:
888 valid = get_nextfield(&str, mask);
889 state = -1; /* force loop exit */
890 break;
891 default:
892 elog(ERROR, "unrecognized state in parse_ooaffentry: %d",
893 state);
894 break;
895 }
896 if (valid)
897 fields_read++;
898 else
899 break; /* early EOL */
900 if (state < 0)
901 break; /* got all fields */
902 }
903
904 return fields_read;
905}
static bool get_nextfield(char **str, char *next)
Definition spell.c:794
#define PAE_WAIT_FLAG
Definition spell.c:781
#define PAE_WAIT_TYPE
Definition spell.c:780

References elog, ERROR, fb(), find(), flag(), get_nextfield(), PAE_WAIT_FIND, PAE_WAIT_FLAG, PAE_WAIT_MASK, PAE_WAIT_REPL, PAE_WAIT_TYPE, str, and type.

Referenced by NIImportOOAffixes().

◆ setCompoundAffixFlagValue()

static void setCompoundAffixFlagValue ( IspellDict Conf,
CompoundAffixFlag entry,
char s,
uint32  val 
)
static

Definition at line 1028 of file spell.c.

1030{
1031 if (Conf->flagMode == FM_NUM)
1032 {
1033 char *next;
1034 int i;
1035
1036 errno = 0;
1037 i = strtol(s, &next, 10);
1038 if (s == next || errno == ERANGE)
1039 ereport(ERROR,
1041 errmsg("invalid affix flag \"%s\"", s)));
1043 ereport(ERROR,
1045 errmsg("affix flag \"%s\" is out of range", s)));
1046
1047 entry->flag.i = i;
1048 }
1049 else
1050 entry->flag.s = cpstrdup(Conf, s);
1051
1052 entry->flagMode = Conf->flagMode;
1053 entry->value = val;
1054}
union CompoundAffixFlag::@143 flag
FlagMode flagMode
Definition spell.h:178
const char * s
Definition spell.h:173

References cpstrdup(), ereport, errcode(), errmsg(), ERROR, fb(), CompoundAffixFlag::flag, CompoundAffixFlag::flagMode, FLAGNUM_MAXSIZE, FM_NUM, i, CompoundAffixFlag::i, next, CompoundAffixFlag::s, val, and CompoundAffixFlag::value.

Referenced by addCompoundAffixFlagValue(), and getCompoundAffixFlagValue().

◆ SplitToVariants()

static SplitVar * SplitToVariants ( IspellDict Conf,
SPNode snode,
SplitVar orig,
const char word,
int  wordlen,
int  startpos,
int  minpos 
)
static

Definition at line 2372 of file spell.c.

2373{
2374 SplitVar *var = NULL;
2376 *StopHigh,
2377 *StopMiddle = NULL;
2378 SPNode *node = (snode) ? snode : Conf->Dictionary;
2379 int level = (snode) ? minpos : startpos; /* recursive
2380 * minpos==level */
2381 int lenaff;
2382 CMPDAffix *caff;
2383 char *notprobed;
2384 int compoundflag = 0;
2385
2386 /* since this function recurses, it could be driven to stack overflow */
2388
2389 notprobed = (char *) palloc(wordlen);
2390 memset(notprobed, 1, wordlen);
2391 var = CopyVar(orig, 1);
2392
2393 while (level < wordlen)
2394 {
2395 /* find word with epenthetic or/and compound affix */
2396 caff = Conf->CompoundAffix;
2397 while (level > startpos && (lenaff = CheckCompoundAffixes(&caff, word + level, wordlen - level, (node) ? true : false)) >= 0)
2398 {
2399 /*
2400 * there is one of compound affixes, so check word for existings
2401 */
2402 char buf[MAXNORMLEN];
2403 char **subres;
2404
2405 lenaff = level - startpos + lenaff;
2406
2407 if (!notprobed[startpos + lenaff - 1])
2408 continue;
2409
2410 if (level + lenaff - 1 <= minpos)
2411 continue;
2412
2413 if (lenaff >= MAXNORMLEN)
2414 continue; /* skip too big value */
2415 if (lenaff > 0)
2417 buf[lenaff] = '\0';
2418
2419 if (level == 0)
2420 compoundflag = FF_COMPOUNDBEGIN;
2421 else if (level == wordlen - 1)
2422 compoundflag = FF_COMPOUNDLAST;
2423 else
2424 compoundflag = FF_COMPOUNDMIDDLE;
2425 subres = NormalizeSubWord(Conf, buf, compoundflag);
2426 if (subres)
2427 {
2428 /* Yes, it was a word from dictionary */
2429 SplitVar *new = CopyVar(var, 0);
2430 SplitVar *ptr = var;
2431 char **sptr = subres;
2432
2433 notprobed[startpos + lenaff - 1] = 0;
2434
2435 while (*sptr)
2436 {
2437 AddStem(new, *sptr);
2438 sptr++;
2439 }
2440 pfree(subres);
2441
2442 while (ptr->next)
2443 ptr = ptr->next;
2444 ptr->next = SplitToVariants(Conf, NULL, new, word, wordlen, startpos + lenaff, startpos + lenaff);
2445
2446 pfree(new->stem);
2447 pfree(new);
2448 }
2449 }
2450
2451 if (!node)
2452 break;
2453
2454 StopLow = node->data;
2455 StopHigh = node->data + node->length;
2456 while (StopLow < StopHigh)
2457 {
2458 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
2459 if (StopMiddle->val == ((const uint8 *) (word))[level])
2460 break;
2461 else if (StopMiddle->val < ((const uint8 *) (word))[level])
2462 StopLow = StopMiddle + 1;
2463 else
2465 }
2466
2467 if (StopLow < StopHigh)
2468 {
2469 if (startpos == 0)
2470 compoundflag = FF_COMPOUNDBEGIN;
2471 else if (level == wordlen - 1)
2472 compoundflag = FF_COMPOUNDLAST;
2473 else
2474 compoundflag = FF_COMPOUNDMIDDLE;
2475
2476 /* find infinitive */
2477 if (StopMiddle->isword &&
2478 (StopMiddle->compoundflag & compoundflag) &&
2479 notprobed[level])
2480 {
2481 /* ok, we found full compoundallowed word */
2482 if (level > minpos)
2483 {
2484 /* and its length more than minimal */
2485 if (wordlen == level + 1)
2486 {
2487 /* well, it was last word */
2488 AddStem(var, pnstrdup(word + startpos, wordlen - startpos));
2490 return var;
2491 }
2492 else
2493 {
2494 /* then we will search more big word at the same point */
2495 SplitVar *ptr = var;
2496
2497 while (ptr->next)
2498 ptr = ptr->next;
2499 ptr->next = SplitToVariants(Conf, node, var, word, wordlen, startpos, level);
2500 /* we can find next word */
2501 level++;
2502 AddStem(var, pnstrdup(word + startpos, level - startpos));
2503 node = Conf->Dictionary;
2504 startpos = level;
2505 continue;
2506 }
2507 }
2508 }
2509 node = StopMiddle->node;
2510 }
2511 else
2512 node = NULL;
2513 level++;
2514 }
2515
2516 AddStem(var, pnstrdup(word + startpos, wordlen - startpos));
2518 return var;
2519}
#define false
void * palloc(Size size)
Definition mcxt.c:1387
char * pnstrdup(const char *in, Size len)
Definition mcxt.c:1792
static XLogRecPtr startpos
static char buf[DEFAULT_XLOG_SEG_SIZE]
static SplitVar * CopyVar(SplitVar *s, int makedup)
Definition spell.c:2334
static int CheckCompoundAffixes(CMPDAffix **ptr, const char *word, int len, bool CheckInPlace)
Definition spell.c:2292
static void AddStem(SplitVar *v, char *word)
Definition spell.c:2359
void check_stack_depth(void)
Definition stack_depth.c:95

References AddStem(), buf, check_stack_depth(), CheckCompoundAffixes(), CopyVar(), SPNode::data, fb(), FF_COMPOUNDBEGIN, FF_COMPOUNDLAST, FF_COMPOUNDMIDDLE, SPNode::length, MAXNORMLEN, SplitVar::next, NormalizeSubWord(), palloc(), pfree(), pnstrdup(), SplitToVariants(), startpos, and word().

Referenced by NINormalizeWord(), and SplitToVariants().

◆ strbcmp()

static int strbcmp ( const unsigned char s1,
const unsigned char s2 
)
static

Definition at line 258 of file spell.c.

259{
260 int l1 = strlen((const char *) s1) - 1,
261 l2 = strlen((const char *) s2) - 1;
262
263 while (l1 >= 0 && l2 >= 0)
264 {
265 if (s1[l1] < s2[l2])
266 return -1;
267 if (s1[l1] > s2[l2])
268 return 1;
269 l1--;
270 l2--;
271 }
272 if (l1 < l2)
273 return -1;
274 if (l1 > l2)
275 return 1;
276
277 return 0;
278}

References fb(), s1, and s2.

Referenced by cmpaffix().

◆ strbncmp()

static int strbncmp ( const unsigned char s1,
const unsigned char s2,
size_t  count 
)
static

Definition at line 281 of file spell.c.

282{
283 int l1 = strlen((const char *) s1) - 1,
284 l2 = strlen((const char *) s2) - 1,
285 l = count;
286
287 while (l1 >= 0 && l2 >= 0 && l > 0)
288 {
289 if (s1[l1] < s2[l2])
290 return -1;
291 if (s1[l1] > s2[l2])
292 return 1;
293 l1--;
294 l2--;
295 l--;
296 }
297 if (l == 0)
298 return 0;
299 if (l1 < l2)
300 return -1;
301 if (l1 > l2)
302 return 1;
303 return 0;
304}

References fb(), s1, and s2.

Referenced by NISortAffixes().

Variable Documentation

◆ VoidString

const char* VoidString = ""
static

Definition at line 195 of file spell.c.

Referenced by getAffixFlagSet(), NIAddAffix(), NIAddSpell(), NIImportOOAffixes(), and NormalizeSubWord().