79 #define tmpalloc(sz) MemoryContextAlloc(Conf->buildCxt, (sz))
80 #define tmpalloc0(sz) MemoryContextAllocZero(Conf->buildCxt, (sz))
95 "Ispell dictionary init context",
126 #define COMPACT_ALLOC_CHUNK 8192
127 #define COMPACT_MAX_REQ 1024
145 if (size > Conf->
avail)
158 #define cpalloc(size) compact_palloc0(Conf, size)
159 #define cpalloc0(size) compact_palloc0(Conf, size)
187 #define MAX_NORM 1024
188 #define MAXNORMLEN 256
190 #define STRNCMP(s,p) strncmp( (s), (p), strlen(p) )
191 #define GETWCHAR(W,L,N,T) ( ((const uint8*)(W))[ ((T)==FF_PREFIX) ? (N) : ( (L) - 1 - (N) ) ] )
192 #define GETCHAR(A,N,T) GETWCHAR( (A)->repl, (A)->replen, N, T )
205 return strcmp((*(
SPELL *
const *)
s1)->p.flag,
206 (*(
SPELL *
const *)
s2)->p.flag);
219 if (fv1->
flag.
i == fv2->flag.i)
222 return (fv1->
flag.
i > fv2->flag.i) ? 1 : -1;
225 return strcmp(fv1->
flag.
s, fv2->flag.s);
259 int l1 = strlen((
const char *)
s1) - 1,
260 l2 = strlen((
const char *)
s2) - 1;
262 while (l1 >= 0 && l2 >= 0)
280 strbncmp(
const unsigned char *
s1,
const unsigned char *
s2,
size_t count)
282 int l1 = strlen((
const char *)
s1) - 1,
283 l2 = strlen((
const char *)
s2) - 1,
286 while (l1 >= 0 && l2 >= 0 && l > 0)
316 if (
a1->type <
a2->type)
318 if (
a1->type >
a2->type)
321 return strcmp(
a1->repl,
a2->repl);
323 return strbcmp((
const unsigned char *)
a1->repl,
324 (
const unsigned char *)
a2->repl);
356 bool met_comma =
false;
374 stop = (maxstep == 0);
377 s = strtol(*sflagset, &
next, 10);
378 if (*sflagset ==
next || errno == ERANGE)
380 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
381 errmsg(
"invalid affix flag \"%s\"", *sflagset)));
384 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
385 errmsg(
"affix flag \"%s\" is out of range",
387 sflag +=
sprintf(sflag,
"%0d", s);
397 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
398 errmsg(
"invalid affix flag \"%s\"",
402 else if (
t_iseq(*sflagset,
','))
406 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
407 errmsg(
"invalid affix flag \"%s\"",
414 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
415 errmsg(
"invalid character in affix flag \"%s\"",
424 elog(
ERROR,
"unrecognized type of Conf->flagMode: %d",
434 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
435 errmsg(
"invalid affix flag \"%s\" with \"long\" flag value",
462 Assert(affix < Conf->nAffixData);
470 if (strcmp(
flag, affixflag) == 0)
524 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
525 errmsg(
"could not open dictionary file \"%s\": %m",
614 StopLow = node->
data;
616 while (StopLow < StopHigh)
618 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
619 if (StopMiddle->
val == *ptr)
621 if (*(ptr + 1) ==
'\0' && StopMiddle->
isword)
643 node = StopMiddle->
node;
647 else if (StopMiddle->
val < *ptr)
648 StopLow = StopMiddle + 1;
650 StopHigh = StopMiddle;
652 if (StopLow >= StopHigh)
678 const char *
find,
const char *repl,
int type)
699 if (strcmp(mask,
".") == 0 || *mask ==
'\0')
723 tmask = (
char *)
tmpalloc(strlen(mask) + 3);
729 masklen = strlen(tmask);
741 DEFAULT_COLLATION_OID);
748 (
errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
749 errmsg(
"invalid regular expression: %s", errstr)));
763 if ((Affix->
replen = strlen(repl)) > 0)
771 #define PAE_WAIT_MASK 0
773 #define PAE_WAIT_FIND 2
775 #define PAE_WAIT_REPL 4
777 #define PAE_WAIT_TYPE 6
778 #define PAE_WAIT_FLAG 7
858 char *repl,
char *mask)
891 elog(
ERROR,
"unrecognized state in parse_ooaffentry: %d",
920 *mask = *
find = *repl =
'\0';
962 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
979 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
996 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1013 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1014 errmsg(
"syntax error")));
1022 *pmask = *pfind = *prepl =
'\0';
1024 return (*mask && (*
find || *repl));
1039 i = strtol(s, &
next, 10);
1040 if (s ==
next || errno == ERANGE)
1042 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1043 errmsg(
"invalid affix flag \"%s\"", s)));
1046 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1047 errmsg(
"affix flag \"%s\" is out of range", s)));
1078 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1079 errmsg(
"syntax error")));
1083 while (*s && !
t_isspace(s) && *s !=
'\n')
1166 curaffix = strtol(s, &end, 10);
1167 if (s == end || errno == ERANGE)
1169 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1170 errmsg(
"invalid affix alias \"%s\"", s)));
1172 if (curaffix > 0 && curaffix < Conf->nAffixData)
1181 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1182 errmsg(
"invalid affix alias \"%s\"", s)));
1207 bool isSuffix =
false;
1222 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1223 errmsg(
"could not open affix file \"%s\": %m",
1234 if (
STRNCMP(recoded,
"COMPOUNDFLAG") == 0)
1237 else if (
STRNCMP(recoded,
"COMPOUNDBEGIN") == 0)
1240 else if (
STRNCMP(recoded,
"COMPOUNDLAST") == 0)
1244 else if (
STRNCMP(recoded,
"COMPOUNDEND") == 0)
1247 else if (
STRNCMP(recoded,
"COMPOUNDMIDDLE") == 0)
1250 else if (
STRNCMP(recoded,
"ONLYINCOMPOUND") == 0)
1253 else if (
STRNCMP(recoded,
"COMPOUNDPERMITFLAG") == 0)
1255 recoded + strlen(
"COMPOUNDPERMITFLAG"),
1257 else if (
STRNCMP(recoded,
"COMPOUNDFORBIDFLAG") == 0)
1259 recoded + strlen(
"COMPOUNDFORBIDFLAG"),
1261 else if (
STRNCMP(recoded,
"FLAG") == 0)
1263 char *s = recoded + strlen(
"FLAG");
1272 else if (
STRNCMP(s,
"num") == 0)
1274 else if (
STRNCMP(s,
"default") != 0)
1276 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1277 errmsg(
"Ispell dictionary supports only "
1278 "\"default\", \"long\", "
1279 "and \"num\" flag values")));
1293 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1294 errmsg(
"could not open affix file \"%s\": %m",
1311 if (
STRNCMP(ptype,
"af") == 0)
1317 naffix = atoi(sflag);
1320 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1321 errmsg(
"invalid number of flag vector aliases")));
1336 if (curaffix < naffix)
1343 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1344 errmsg(
"number of aliases exceeds specified number %d",
1350 if (fields_read < 4 ||
1354 sflaglen = strlen(sflag);
1365 if (fields_read == 4)
1367 isSuffix = (
STRNCMP(ptype,
"sfx") == 0);
1384 if ((ptr = strchr(repl,
'/')) != NULL)
1390 if ((ptr = strchr(prepl,
'/')) != NULL)
1399 NIAddAffix(Conf, sflag, flagflags | aflg, pmask, pfind, prepl,
1433 bool suffixes =
false;
1437 bool oldformat =
false;
1438 char *recoded = NULL;
1442 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1443 errmsg(
"could not open affix file \"%s\": %m",
1455 if (*pstr ==
'#' || *pstr ==
'\n')
1458 if (
STRNCMP(pstr,
"compoundwords") == 0)
1478 if (
STRNCMP(pstr,
"suffixes") == 0)
1485 if (
STRNCMP(pstr,
"prefixes") == 0)
1492 if (
STRNCMP(pstr,
"flag") == 0)
1525 if (*s ==
'\0' || *s ==
'#' || *s ==
'\n' || *s ==
':' ||
1534 if (
STRNCMP(recoded,
"COMPOUNDFLAG") == 0 ||
1535 STRNCMP(recoded,
"COMPOUNDMIN") == 0 ||
1536 STRNCMP(recoded,
"PFX") == 0 ||
1558 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1559 errmsg(
"affix file contains both old-style and new-style commands")));
1576 Assert(a1 < Conf->nAffixData && a2 < Conf->nAffixData);
1621 Assert(affix < Conf->nAffixData);
1640 char lastchar =
'\0';
1645 for (
i = low;
i < high;
i++)
1660 for (
i = low;
i < high;
i++)
1661 if (Conf->
Spell[
i]->
p.
d.len > level)
1675 if (Conf->
Spell[
i]->
p.
d.len == level + 1)
1677 bool clearCompoundOnly =
false;
1702 if (clearCompoundOnly)
1738 curaffix = strtol(Conf->
Spell[
i]->
p.
flag, &end, 10);
1739 if (Conf->
Spell[
i]->
p.
flag == end || errno == ERANGE)
1741 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1742 errmsg(
"invalid affix alias \"%s\"",
1744 if (curaffix < 0 || curaffix >= Conf->
nAffixData)
1746 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1747 errmsg(
"invalid affix alias \"%s\"",
1751 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1752 errmsg(
"invalid affix alias \"%s\"",
1764 Conf->
Spell[
i]->
p.
d.affix = curaffix;
1797 Assert(curaffix < naffix);
1802 Conf->
Spell[
i]->
p.
d.affix = curaffix;
1830 uint8 lastchar =
'\0';
1837 for (
i = low;
i < high;
i++)
1855 for (
i = low;
i < high;
i++)
1868 memcpy(
data->aff, aff,
sizeof(
AFFIX *) * naff);
1879 aff[naff++] = Conf->
Affix +
i;
1889 memcpy(
data->aff, aff,
sizeof(
AFFIX *) * naff);
1907 int start = (issuffix) ? startsuffix : 0;
1908 int end = (issuffix) ? Conf->
naffixes : startsuffix;
1916 Affix->data->node = Conf->
Suffix;
1926 for (
i = start;
i < end;
i++)
1935 Affix->data->naff = (
uint32) cnt;
1938 for (
i = start;
i < end;
i++)
1941 Affix->data->aff[cnt] = Conf->
Affix +
i;
2001 strbncmp((
const unsigned char *) (ptr - 1)->affix,
2002 (
const unsigned char *) Affix->
repl,
2038 while (node && *level < wrdlen)
2040 StopLow = node->
data;
2042 while (StopLow < StopHigh)
2044 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
2050 if (StopMiddle->
naff)
2052 node = StopMiddle->
node;
2056 StopLow = StopMiddle + 1;
2058 StopHigh = StopMiddle;
2060 if (StopLow >= StopHigh)
2106 strcpy(newword,
word);
2117 if (baselen && *baselen + strlen(Affix->
find) <= Affix->
replen)
2119 strcpy(newword, Affix->
find);
2140 newword_len = strlen(newword);
2161 if (forms ==
cur || strcmp(
word, *(
cur - 1)) != 0)
2178 int wrdlen = strlen(
word),
2211 for (
j = 0;
j < prefix->naff;
j++)
2220 pnode = prefix->node;
2236 for (
i = 0;
i < suffix->
naff;
i++)
2247 swrdlen = strlen(newword);
2253 for (
j = 0;
j < prefix->naff;
j++)
2255 if (
CheckAffix(newword, swrdlen, prefix->aff[
j],
flag, pnewword, &baselen))
2265 pnode = prefix->node;
2270 snode = suffix->
node;
2300 while ((*ptr)->affix)
2302 if (
len > (*ptr)->len && strncmp((*ptr)->affix,
word, (*ptr)->len) == 0)
2305 issuffix = (*ptr)->issuffix;
2307 return (issuffix) ?
len : 0;
2316 while ((*ptr)->affix)
2318 if (
len > (*ptr)->len && (affbegin = strstr(
word, (*ptr)->affix)) != NULL)
2320 len = (*ptr)->len + (affbegin -
word);
2321 issuffix = (*ptr)->issuffix;
2323 return (issuffix) ?
len : 0;
2377 int level = (snode) ? minpos :
startpos;
2382 int compoundflag = 0;
2387 notprobed = (
char *)
palloc(wordlen);
2388 memset(notprobed, 1, wordlen);
2391 while (level < wordlen)
2403 lenaff = level -
startpos + lenaff;
2405 if (!notprobed[
startpos + lenaff - 1])
2408 if (level + lenaff - 1 <= minpos)
2419 else if (level == wordlen - 1)
2429 char **sptr = subres;
2431 notprobed[
startpos + lenaff - 1] = 0;
2452 StopLow = node->
data;
2454 while (StopLow < StopHigh)
2456 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
2460 StopLow = StopMiddle + 1;
2462 StopHigh = StopMiddle;
2465 if (StopLow < StopHigh)
2469 else if (level == wordlen - 1)
2475 if (StopMiddle->
isword &&
2483 if (wordlen == level + 1)
2507 node = StopMiddle->
node;
2527 (*lcur)->lexeme =
word;
2528 (*lcur)->flags = flags;
2529 (*lcur)->nvariant = NVariant;
2531 (*lcur)->lexeme = NULL;
2549 while (*ptr && (lcur - lres) <
MAX_NORM)
2551 addNorm(&lres, &lcur, *ptr, 0, NVariant++);
2559 int wordlen = strlen(
word);
2572 char **subptr = subres;
2576 for (
i = 0;
i < var->
nstem - 1;
i++)
2581 addNorm(&lres, &lcur, *subptr, 0, NVariant);
2587 var->
stem[0] = NULL;
static void PGresult * res
elog(ERROR, "%s: %s", p2, msg)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void err(int eval, const char *fmt,...)
static const FormData_pg_attribute a1
static const FormData_pg_attribute a2
if(TABLE==NULL||TABLE_index==NULL)
Assert(fmt[strlen(fmt) - 1] !='\n')
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
int pg_mblen(const char *mbstr)
char * pnstrdup(const char *in, Size len)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurTransactionContext
void * repalloc(void *pointer, Size size)
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static XLogRecPtr startpos
#define qsort(a, b, c, d)
void check_stack_depth(void)
static void prefixes(struct vars *v)
int pg_regcomp(regex_t *re, const chr *string, size_t len, int flags, Oid collation)
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
size_t pg_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
static int find(struct vars *v, struct cnfa *cnfa, struct colormap *cm)
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)
void RS_compile(Regis *r, bool issuffix, const char *str)
bool RS_execute(Regis *r, char *str)
bool RS_isRegis(const char *str)
void NIStartBuild(IspellDict *Conf)
#define GETWCHAR(W, L, N, T)
static int strbcmp(const unsigned char *s1, const unsigned char *s2)
void NIFinishBuild(IspellDict *Conf)
void NIImportAffixes(IspellDict *Conf, const char *filename)
static char * findchar2(char *str, int c1, int c2)
static SplitVar * SplitToVariants(IspellDict *Conf, SPNode *snode, SplitVar *orig, char *word, int wordlen, int startpos, int minpos)
static int parse_ooaffentry(char *str, char *type, char *flag, char *find, char *repl, char *mask)
static int cmpspell(const void *s1, const void *s2)
static bool get_nextfield(char **str, char *next)
void NISortDictionary(IspellDict *Conf)
static int FindWord(IspellDict *Conf, const char *word, const char *affixflag, int flag)
static char * cpstrdup(IspellDict *Conf, const char *str)
static void NIAddSpell(IspellDict *Conf, const char *word, const char *flag)
static SPNode * mkSPNode(IspellDict *Conf, int low, int high, int level)
static char * lowerstr_ctx(IspellDict *Conf, const char *src)
static void NIImportOOAffixes(IspellDict *Conf, const char *filename)
#define COMPACT_ALLOC_CHUNK
static void addNorm(TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant)
static AffixNodeData * FindAffixes(AffixNode *node, const char *word, int wrdlen, int *level, int type)
static void NIAddAffix(IspellDict *Conf, const char *flag, char flagflags, const char *mask, const char *find, const char *repl, int type)
static AffixNode * mkANode(IspellDict *Conf, int low, int high, int level, int type)
static void getNextFlagFromString(IspellDict *Conf, char **sflagset, char *sflag)
void NISortAffixes(IspellDict *Conf)
static int cmpcmdflag(const void *f1, const void *f2)
static SplitVar * CopyVar(SplitVar *s, int makedup)
static void setCompoundAffixFlagValue(IspellDict *Conf, CompoundAffixFlag *entry, char *s, uint32 val)
static int CheckCompoundAffixes(CMPDAffix **ptr, char *word, int len, bool CheckInPlace)
void NIImportDictionary(IspellDict *Conf, const char *filename)
static bool IsAffixFlagInUse(IspellDict *Conf, int affix, const char *affixflag)
static bool parse_affentry(char *str, char *mask, char *find, char *repl)
static char * findchar(char *str, int c)
static bool isAffixInUse(IspellDict *Conf, char *affixflag)
static uint32 makeCompoundFlags(IspellDict *Conf, int affix)
static int cmpspellaffix(const void *s1, const void *s2)
TSLexeme * NINormalizeWord(IspellDict *Conf, char *word)
static int strbncmp(const unsigned char *s1, const unsigned char *s2, size_t count)
static char ** NormalizeSubWord(IspellDict *Conf, char *word, int flag)
static int getCompoundAffixFlagValue(IspellDict *Conf, char *s)
static int MergeAffix(IspellDict *Conf, int a1, int a2)
static char * getAffixFlagSet(IspellDict *Conf, char *s)
static void AddStem(SplitVar *v, char *word)
static void * compact_palloc0(IspellDict *Conf, size_t size)
static int addToResult(char **forms, char **cur, char *word)
static char * CheckAffix(const char *word, size_t len, AFFIX *Affix, int flagflags, char *newword, int *baselen)
static void mkVoidAffix(IspellDict *Conf, bool issuffix, int startsuffix)
static void addCompoundAffixFlagValue(IspellDict *Conf, char *s, uint32 val)
static int cmpaffix(const void *s1, const void *s2)
#define FF_COMPOUNDFLAGMASK
#define FF_COMPOUNDFORBIDFLAG
#define FF_COMPOUNDPERMITFLAG
#define FF_COMPOUNDMIDDLE
AffixNodeData data[FLEXIBLE_ARRAY_MEMBER]
union CompoundAffixFlag::@122 flag
CompoundAffixFlag * CompoundAffixFlags
CMPDAffix * CompoundAffix
SPNodeData data[FLEXIBLE_ARRAY_MEMBER]
union aff_struct::@121 reg
union spell_struct::@119 p
struct spell_struct::@119::@120 d
char word[FLEXIBLE_ARRAY_MEMBER]
bool tsearch_readline_begin(tsearch_readline_state *stp, const char *filename)
char * tsearch_readline(tsearch_readline_state *stp)
int t_isspace(const char *ptr)
int t_isdigit(const char *ptr)
int t_isalpha(const char *ptr)
int t_isprint(const char *ptr)
void tsearch_readline_end(tsearch_readline_state *stp)
char * lowerstr(const char *str)