PostgreSQL Source Code git master
Loading...
Searching...
No Matches
spell.h File Reference
#include "regex/regex.h"
#include "tsearch/dicts/regis.h"
#include "tsearch/ts_public.h"
Include dependency graph for spell.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  SPNodeData
 
struct  SPNode
 
struct  spell_struct
 
struct  aff_struct
 
struct  AffixNodeData
 
struct  AffixNode
 
struct  CMPDAffix
 
struct  CompoundAffixFlag
 
struct  IspellDict
 

Macros

#define FF_COMPOUNDONLY   0x01
 
#define FF_COMPOUNDBEGIN   0x02
 
#define FF_COMPOUNDMIDDLE   0x04
 
#define FF_COMPOUNDLAST   0x08
 
#define FF_COMPOUNDFLAG
 
#define FF_COMPOUNDFLAGMASK   0x0f
 
#define SPNHDRSZ   (offsetof(SPNode,data))
 
#define SPELLHDRSZ   (offsetof(SPELL, word))
 
#define FF_COMPOUNDPERMITFLAG   0x10
 
#define FF_COMPOUNDFORBIDFLAG   0x20
 
#define FF_CROSSPRODUCT   0x40
 
#define FF_SUFFIX   1
 
#define FF_PREFIX   0
 
#define ANHRDSZ   (offsetof(AffixNode, data))
 
#define FLAGNUM_MAXSIZE   (1 << 16)
 

Typedefs

typedef struct SPNode SPNode
 
typedef struct spell_struct SPELL
 
typedef struct aff_struct AFFIX
 
typedef struct AffixNode AffixNode
 
typedef struct CompoundAffixFlag CompoundAffixFlag
 

Enumerations

enum  FlagMode { FM_CHAR , FM_LONG , FM_NUM }
 

Functions

TSLexemeNINormalizeWord (IspellDict *Conf, const char *word)
 
void NIStartBuild (IspellDict *Conf)
 
void NIImportAffixes (IspellDict *Conf, const char *filename)
 
void NIImportDictionary (IspellDict *Conf, const char *filename)
 
void NISortDictionary (IspellDict *Conf)
 
void NISortAffixes (IspellDict *Conf)
 
void NIFinishBuild (IspellDict *Conf)
 

Macro Definition Documentation

◆ ANHRDSZ

#define ANHRDSZ   (offsetof(AffixNode, data))

Definition at line 145 of file spell.h.

◆ FF_COMPOUNDBEGIN

#define FF_COMPOUNDBEGIN   0x02

Definition at line 43 of file spell.h.

◆ FF_COMPOUNDFLAG

#define FF_COMPOUNDFLAG
Value:
#define FF_COMPOUNDBEGIN
Definition spell.h:43
#define FF_COMPOUNDMIDDLE
Definition spell.h:44
#define FF_COMPOUNDLAST
Definition spell.h:45

Definition at line 46 of file spell.h.

51{
52 uint32 length;
54} SPNode;
55
56#define SPNHDRSZ (offsetof(SPNode,data))
57
58/*
59 * Represents an entry in a words list.
60 */
61typedef struct spell_struct
62{
63 union
64 {
65 /*
66 * flag is filled in by NIImportDictionary(). After
67 * NISortDictionary(), d is used instead of flag.
68 */
69 const char *flag;
70 /* d is used in mkSPNode() */
71 struct
72 {
73 /* Reference to an entry of the AffixData field */
74 int affix;
75 /* Length of the word */
76 int len;
77 } d;
78 } p;
80} SPELL;
81
82#define SPELLHDRSZ (offsetof(SPELL, word))
83
84/*
85 * Represents an entry in an affix list.
86 */
87typedef struct aff_struct
88{
89 const char *flag;
90 /* FF_SUFFIX or FF_PREFIX */
91 uint32 type:1,
92 flagflags:7,
93 issimple:1,
94 isregis:1,
95 replen:14;
96 const char *find;
97 const char *repl;
98 union
99 {
100 /*
101 * Arrays of AFFIX are moved and sorted. We'll use a pointer to
102 * regex_t to keep this struct small, and avoid assuming that regex_t
103 * is movable.
104 */
106 Regis regis;
107 } reg;
108} AFFIX;
109
110/*
111 * affixes use dictionary flags too
112 */
113#define FF_COMPOUNDPERMITFLAG 0x10
114#define FF_COMPOUNDFORBIDFLAG 0x20
115#define FF_CROSSPRODUCT 0x40
116
117/*
118 * Don't change the order of these. Initialization sorts by these,
119 * and expects prefixes to come first after sorting.
120 */
121#define FF_SUFFIX 1
122#define FF_PREFIX 0
123
124/*
125 * AffixNode and AffixNodeData are used to represent prefix tree (Trie) to store
126 * an affix list.
127 */
128struct AffixNode;
129
130typedef struct
131{
132 uint32 val:8,
133 naff:24;
134 AFFIX **aff;
135 struct AffixNode *node;
137
138typedef struct AffixNode
139{
140 uint32 isvoid:1,
141 length:31;
143} AffixNode;
144
145#define ANHRDSZ (offsetof(AffixNode, data))
146
147typedef struct
148{
149 const char *affix;
150 int len;
151 bool issuffix;
152} CMPDAffix;
153
154/*
155 * Type of encoding affix flags in Hunspell dictionaries
156 */
157typedef enum
158{
159 FM_CHAR, /* one character (like ispell) */
160 FM_LONG, /* two characters */
161 FM_NUM, /* number, >= 0 and < 65536 */
162} FlagMode;
163
164/*
165 * Structure to store Hunspell options. Flag representation depends on flag
166 * type. These flags are about support of compound words.
167 */
168typedef struct CompoundAffixFlag
169{
170 union
171 {
172 /* Flag name if flagMode is FM_CHAR or FM_LONG */
173 const char *s;
174 /* Flag name if flagMode is FM_NUM */
175 uint32 i;
176 } flag;
177 /* we don't have a bsearch_arg version, so, copy FlagMode */
181
182#define FLAGNUM_MAXSIZE (1 << 16)
183
184typedef struct
185{
186 int maffixes;
187 int naffixes;
188 AFFIX *Affix;
189
190 AffixNode *Suffix;
191 AffixNode *Prefix;
192
193 SPNode *Dictionary;
194 /* Array of sets of affixes */
195 const char **AffixData;
196 int lenAffixData;
197 int nAffixData;
198 bool useFlagAliases;
199
200 CMPDAffix *CompoundAffix;
201
202 bool usecompound;
203 FlagMode flagMode;
204
205 /*
206 * All follow fields are actually needed only for initialization
207 */
208
209 /* Array of Hunspell options in affix file */
210 CompoundAffixFlag *CompoundAffixFlags;
211 /* number of entries in CompoundAffixFlags array */
212 int nCompoundAffixFlag;
213 /* allocated length of CompoundAffixFlags array */
214 int mCompoundAffixFlag;
215
216 /*
217 * Remaining fields are only used during dictionary construction; they are
218 * set up by NIStartBuild and cleared by NIFinishBuild.
219 */
220 MemoryContext buildCxt; /* temp context for construction */
221
222 /* Temporary array of all words in the dict file */
223 SPELL **Spell;
224 int nspell; /* number of valid entries in Spell array */
225 int mspell; /* allocated length of Spell array */
226
227 /* These are used to allocate "compact" data without palloc overhead */
228 char *firstfree; /* first free address (always maxaligned) */
229 size_t avail; /* free space remaining at firstfree */
230} IspellDict;
231
232extern TSLexeme *NINormalizeWord(IspellDict *Conf, const char *word);
233
234extern void NIStartBuild(IspellDict *Conf);
235extern void NIImportAffixes(IspellDict *Conf, const char *filename);
236extern void NIImportDictionary(IspellDict *Conf, const char *filename);
237extern void NISortDictionary(IspellDict *Conf);
238extern void NISortAffixes(IspellDict *Conf);
239extern void NIFinishBuild(IspellDict *Conf);
240
241#endif
#define FLEXIBLE_ARRAY_MEMBER
Definition c.h:480
uint32_t uint32
Definition c.h:546
long val
Definition informix.c:689
const void size_t len
const void * data
static char * filename
Definition pg_dumpall.c:120
static int fb(int x)
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition regcomp.c:1476
#define regex_t
Definition regex.h:245
void NIStartBuild(IspellDict *Conf)
Definition spell.c:89
void NIFinishBuild(IspellDict *Conf)
Definition spell.c:104
void NIImportAffixes(IspellDict *Conf, const char *filename)
Definition spell.c:1423
void NISortDictionary(IspellDict *Conf)
Definition spell.c:1719
void NISortAffixes(IspellDict *Conf)
Definition spell.c:1974
struct spell_struct SPELL
void NIImportDictionary(IspellDict *Conf, const char *filename)
Definition spell.c:520
TSLexeme * NINormalizeWord(IspellDict *Conf, const char *word)
Definition spell.c:2538
FlagMode
Definition spell.h:158
@ FM_LONG
Definition spell.h:160
@ FM_CHAR
Definition spell.h:159
@ FM_NUM
Definition spell.h:161
struct aff_struct AFFIX
uint32 isvoid
Definition spell.h:140
AffixNodeData data[FLEXIBLE_ARRAY_MEMBER]
Definition spell.h:142
uint32 length
Definition spell.h:141
union CompoundAffixFlag::@143 flag
FlagMode flagMode
Definition spell.h:178
const char * s
Definition spell.h:173
Definition regis.h:33
Definition spell.h:51
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
const char * flag
Definition spell.h:89
uint32 replen
Definition spell.h:95
union aff_struct::@142 reg
regex_t * pregex
Definition spell.h:105
uint32 flagflags
Definition spell.h:92
const char * repl
Definition spell.h:97
uint32 issimple
Definition spell.h:93
union spell_struct::@140 p
int len
Definition spell.h:76
const char * flag
Definition spell.h:69
struct spell_struct::@140::@141 d
char word[FLEXIBLE_ARRAY_MEMBER]
Definition spell.h:79
int affix
Definition spell.h:74

◆ FF_COMPOUNDFLAGMASK

#define FF_COMPOUNDFLAGMASK   0x0f

Definition at line 48 of file spell.h.

◆ FF_COMPOUNDFORBIDFLAG

#define FF_COMPOUNDFORBIDFLAG   0x20

Definition at line 114 of file spell.h.

◆ FF_COMPOUNDLAST

#define FF_COMPOUNDLAST   0x08

Definition at line 45 of file spell.h.

◆ FF_COMPOUNDMIDDLE

#define FF_COMPOUNDMIDDLE   0x04

Definition at line 44 of file spell.h.

◆ FF_COMPOUNDONLY

#define FF_COMPOUNDONLY   0x01

Definition at line 42 of file spell.h.

◆ FF_COMPOUNDPERMITFLAG

#define FF_COMPOUNDPERMITFLAG   0x10

Definition at line 113 of file spell.h.

◆ FF_CROSSPRODUCT

#define FF_CROSSPRODUCT   0x40

Definition at line 115 of file spell.h.

◆ FF_PREFIX

#define FF_PREFIX   0

Definition at line 122 of file spell.h.

◆ FF_SUFFIX

#define FF_SUFFIX   1

Definition at line 121 of file spell.h.

◆ FLAGNUM_MAXSIZE

#define FLAGNUM_MAXSIZE   (1 << 16)

Definition at line 182 of file spell.h.

◆ SPELLHDRSZ

#define SPELLHDRSZ   (offsetof(SPELL, word))

Definition at line 82 of file spell.h.

◆ SPNHDRSZ

#define SPNHDRSZ   (offsetof(SPNode,data))

Definition at line 56 of file spell.h.

Typedef Documentation

◆ AFFIX

◆ AffixNode

◆ CompoundAffixFlag

◆ SPELL

◆ SPNode

Enumeration Type Documentation

◆ FlagMode

Enumerator
FM_CHAR 
FM_LONG 
FM_NUM 

Definition at line 157 of file spell.h.

158{
159 FM_CHAR, /* one character (like ispell) */
160 FM_LONG, /* two characters */
161 FM_NUM, /* number, >= 0 and < 65536 */
162} FlagMode;

Function Documentation

◆ NIFinishBuild()

void NIFinishBuild ( IspellDict Conf)
extern

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

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}
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
char * str_tolower(const char *buff, size_t nbytes, Oid collid)
int pg_mblen_cstr(const char *mbstr)
Definition mbutils.c:1045
void pfree(void *pointer)
Definition mcxt.c:1616
static void prefixes(struct vars *v)
Definition regc_lex.c:99
static int find(struct vars *v, struct cnfa *cnfa, struct colormap *cm)
Definition regexec.c:419
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_SUFFIX
Definition spell.h:121
#define FF_COMPOUNDFLAG
Definition spell.h:46
#define FF_PREFIX
Definition spell.h:122
#define FF_CROSSPRODUCT
Definition spell.h:115
#define FF_COMPOUNDONLY
Definition spell.h:42
char * flag(int b)
Definition test-ctype.c:33
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 
)
extern

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().

◆ NINormalizeWord()

TSLexeme * NINormalizeWord ( IspellDict Conf,
const char word 
)
extern

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
int i
Definition isn.c:77
char * pstrdup(const char *in)
Definition mcxt.c:1781
#define MAX_NORM
Definition spell.c:188
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
int nstem
Definition spell.c:2285
struct SplitVar * next
Definition spell.c:2288
char ** stem
Definition spell.c:2287

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

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}
#define palloc_array(type, count)
Definition fe_memutils.h:76
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
#define qsort(a, b, c, d)
Definition port.h:495
static AffixNode * mkANode(IspellDict *Conf, int low, int high, int level, int type)
Definition spell.c:1828
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)
extern

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}
#define Assert(condition)
Definition c.h:873
#define palloc0_array(type, count)
Definition fe_memutils.h:77
static char * cpstrdup(IspellDict *Conf, const char *str)
Definition spell.c:163
static SPNode * mkSPNode(IspellDict *Conf, int low, int high, int level)
Definition spell.c:1637
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)
extern

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().