80#define tmpalloc(sz) MemoryContextAlloc(Conf->buildCxt, (sz))
81#define tmpalloc0(sz) MemoryContextAllocZero(Conf->buildCxt, (sz))
96 "Ispell dictionary init context",
127#define COMPACT_ALLOC_CHUNK 8192
128#define COMPACT_MAX_REQ 1024
159#define cpalloc(size) compact_palloc0(Conf, size)
160#define cpalloc0(size) compact_palloc0(Conf, size)
182 dst =
str_tolower(src, strlen(src), DEFAULT_COLLATION_OID);
189#define MAXNORMLEN 256
191#define STRNCMP(s,p) strncmp( (s), (p), strlen(p) )
192#define GETWCHAR(W,L,N,T) ( ((const uint8*)(W))[ ((T)==FF_PREFIX) ? (N) : ( (L) - 1 - (N) ) ] )
193#define GETCHAR(A,N,T) GETWCHAR( (A)->repl, (A)->replen, N, T )
206 return strcmp((*(
SPELL *
const *)
s1)->p.flag,
207 (*(
SPELL *
const *)
s2)->p.flag);
220 if (fv1->
flag.
i == fv2->flag.i)
223 return (fv1->
flag.
i > fv2->flag.i) ? 1 : -1;
226 return strcmp(fv1->
flag.
s, fv2->flag.s);
260 int l1 = strlen((
const char *)
s1) - 1,
261 l2 = strlen((
const char *)
s2) - 1;
263 while (l1 >= 0 && l2 >= 0)
281strbncmp(
const unsigned char *
s1,
const unsigned char *
s2,
size_t count)
283 int l1 = strlen((
const char *)
s1) - 1,
284 l2 = strlen((
const char *)
s2) - 1,
287 while (l1 >= 0 && l2 >= 0 && l > 0)
317 if (
a1->type <
a2->type)
319 if (
a1->type >
a2->type)
322 return strcmp(
a1->repl,
a2->repl);
324 return strbcmp((
const unsigned char *)
a1->repl,
325 (
const unsigned char *)
a2->repl);
354 const char *sbuf = *sflagset;
357 bool met_comma =
false;
375 stop = (maxstep == 0);
378 s = strtol(*sflagset, &
next, 10);
379 if (*sflagset ==
next || errno == ERANGE)
381 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
382 errmsg(
"invalid affix flag \"%s\"", *sflagset)));
385 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
386 errmsg(
"affix flag \"%s\" is out of range",
388 sflag +=
sprintf(sflag,
"%0d", s);
394 if (isdigit((
unsigned char) **sflagset))
398 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
399 errmsg(
"invalid affix flag \"%s\"",
403 else if (
t_iseq(*sflagset,
','))
407 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
408 errmsg(
"invalid affix flag \"%s\"",
412 else if (!isspace((
unsigned char) **sflagset))
415 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
416 errmsg(
"invalid character in affix flag \"%s\"",
425 elog(
ERROR,
"unrecognized type of Conf->flagMode: %d",
435 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
436 errmsg(
"invalid affix flag \"%s\" with \"long\" flag value",
463 Assert(affix < Conf->nAffixData);
471 if (strcmp(
flag, affixflag) == 0)
525 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
526 errmsg(
"could not open dictionary file \"%s\": %m",
546 if (
pg_mblen(s) == 1 && isprint((
unsigned char) *s) && !isspace((
unsigned char) *s))
562 if (isspace((
unsigned char) *s))
615 StopLow = node->
data;
617 while (StopLow < StopHigh)
619 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
620 if (StopMiddle->
val == *ptr)
622 if (*(ptr + 1) ==
'\0' && StopMiddle->
isword)
644 node = StopMiddle->
node;
648 else if (StopMiddle->
val < *ptr)
649 StopLow = StopMiddle + 1;
651 StopHigh = StopMiddle;
653 if (StopLow >= StopHigh)
679 const char *
find,
const char *repl,
int type)
700 if (strcmp(mask,
".") == 0 || *mask ==
'\0')
724 tmask = (
char *)
tmpalloc(strlen(mask) + 3);
730 masklen = strlen(tmask);
742 DEFAULT_COLLATION_OID);
749 (
errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
750 errmsg(
"invalid regular expression: %s", errstr)));
764 if ((Affix->
replen = strlen(repl)) > 0)
772#define PAE_WAIT_MASK 0
774#define PAE_WAIT_FIND 2
776#define PAE_WAIT_REPL 4
778#define PAE_WAIT_TYPE 6
779#define PAE_WAIT_FLAG 7
803 else if (!isspace((
unsigned char) **
str))
818 if (isspace((
unsigned char) **
str))
859 char *repl,
char *mask)
892 elog(
ERROR,
"unrecognized state in parse_ooaffentry: %d",
921 *mask = *
find = *repl =
'\0';
929 else if (!isspace((
unsigned char) *
str))
943 else if (!isspace((
unsigned char) *
str))
961 else if (!isspace((
unsigned char) *
str))
963 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
978 else if (!isspace((
unsigned char) *
str))
980 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
995 else if (!isspace((
unsigned char) *
str))
997 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1012 else if (!isspace((
unsigned char) *
str))
1014 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1015 errmsg(
"syntax error")));
1023 *pmask = *pfind = *prepl =
'\0';
1025 return (*mask && (*
find || *repl));
1040 i = strtol(s, &
next, 10);
1041 if (s ==
next || errno == ERANGE)
1043 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1044 errmsg(
"invalid affix flag \"%s\"", s)));
1047 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1048 errmsg(
"affix flag \"%s\" is out of range", s)));
1074 while (*s && isspace((
unsigned char) *s))
1079 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1080 errmsg(
"syntax error")));
1084 while (*s && !isspace((
unsigned char) *s) && *s !=
'\n')
1130 const char *flagcur;
1167 curaffix = strtol(s, &end, 10);
1168 if (s == end || errno == ERANGE)
1170 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1171 errmsg(
"invalid affix alias \"%s\"", s)));
1173 if (curaffix > 0 && curaffix < Conf->nAffixData)
1182 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1183 errmsg(
"invalid affix alias \"%s\"", s)));
1208 bool isSuffix =
false;
1223 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1224 errmsg(
"could not open affix file \"%s\": %m",
1229 if (*recoded ==
'\0' || isspace((
unsigned char) *recoded) ||
t_iseq(recoded,
'#'))
1235 if (
STRNCMP(recoded,
"COMPOUNDFLAG") == 0)
1238 else if (
STRNCMP(recoded,
"COMPOUNDBEGIN") == 0)
1241 else if (
STRNCMP(recoded,
"COMPOUNDLAST") == 0)
1245 else if (
STRNCMP(recoded,
"COMPOUNDEND") == 0)
1248 else if (
STRNCMP(recoded,
"COMPOUNDMIDDLE") == 0)
1251 else if (
STRNCMP(recoded,
"ONLYINCOMPOUND") == 0)
1254 else if (
STRNCMP(recoded,
"COMPOUNDPERMITFLAG") == 0)
1256 recoded + strlen(
"COMPOUNDPERMITFLAG"),
1258 else if (
STRNCMP(recoded,
"COMPOUNDFORBIDFLAG") == 0)
1260 recoded + strlen(
"COMPOUNDFORBIDFLAG"),
1262 else if (
STRNCMP(recoded,
"FLAG") == 0)
1264 char *s = recoded + strlen(
"FLAG");
1266 while (*s && isspace((
unsigned char) *s))
1273 else if (
STRNCMP(s,
"num") == 0)
1275 else if (
STRNCMP(s,
"default") != 0)
1277 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1278 errmsg(
"Ispell dictionary supports only "
1279 "\"default\", \"long\", "
1280 "and \"num\" flag values")));
1294 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1295 errmsg(
"could not open affix file \"%s\": %m",
1302 if (*recoded ==
'\0' || isspace((
unsigned char) *recoded) ||
t_iseq(recoded,
'#'))
1312 if (
STRNCMP(ptype,
"af") == 0)
1318 naffix = atoi(sflag);
1321 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1322 errmsg(
"invalid number of flag vector aliases")));
1337 if (curaffix < naffix)
1344 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1345 errmsg(
"number of aliases exceeds specified number %d",
1351 if (fields_read < 4 ||
1355 sflaglen = strlen(sflag);
1366 if (fields_read == 4)
1368 isSuffix = (
STRNCMP(ptype,
"sfx") == 0);
1385 if ((ptr = strchr(repl,
'/')) != NULL)
1391 if ((ptr = strchr(prepl,
'/')) != NULL)
1400 NIAddAffix(Conf, sflag, flagflags | aflg, pmask, pfind, prepl,
1434 bool suffixes =
false;
1438 bool oldformat =
false;
1439 char *recoded = NULL;
1443 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1444 errmsg(
"could not open affix file \"%s\": %m",
1453 pstr =
str_tolower(recoded, strlen(recoded), DEFAULT_COLLATION_OID);
1456 if (*pstr ==
'#' || *pstr ==
'\n')
1459 if (
STRNCMP(pstr,
"compoundwords") == 0)
1465 while (*s && !isspace((
unsigned char) *s))
1467 while (*s && isspace((
unsigned char) *s))
1479 if (
STRNCMP(pstr,
"suffixes") == 0)
1486 if (
STRNCMP(pstr,
"prefixes") == 0)
1493 if (
STRNCMP(pstr,
"flag") == 0)
1498 while (*s && isspace((
unsigned char) *s))
1526 if (*s ==
'\0' || *s ==
'#' || *s ==
'\n' || *s ==
':' ||
1527 isspace((
unsigned char) *s))
1535 if (
STRNCMP(recoded,
"COMPOUNDFLAG") == 0 ||
1536 STRNCMP(recoded,
"COMPOUNDMIN") == 0 ||
1537 STRNCMP(recoded,
"PFX") == 0 ||
1559 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1560 errmsg(
"affix file contains both old-style and new-style commands")));
1577 Assert(a1 < Conf->nAffixData && a2 < Conf->nAffixData);
1626 Assert(affix < Conf->nAffixData);
1645 char lastchar =
'\0';
1650 for (
i = low;
i < high;
i++)
1665 for (
i = low;
i < high;
i++)
1682 bool clearCompoundOnly =
false;
1707 if (clearCompoundOnly)
1708 data->compoundflag &= ~FF_COMPOUNDONLY;
1743 curaffix = strtol(Conf->
Spell[
i]->
p.
flag, &end, 10);
1744 if (Conf->
Spell[
i]->
p.
flag == end || errno == ERANGE)
1746 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1747 errmsg(
"invalid affix alias \"%s\"",
1749 if (curaffix < 0 || curaffix >= Conf->
nAffixData)
1751 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1752 errmsg(
"invalid affix alias \"%s\"",
1754 if (*end !=
'\0' && !isdigit((
unsigned char) *end) && !isspace((
unsigned char) *end))
1756 (
errcode(ERRCODE_CONFIG_FILE_ERROR),
1757 errmsg(
"invalid affix alias \"%s\"",
1802 Assert(curaffix < naffix);
1835 uint8 lastchar =
'\0';
1842 for (
i = low;
i < high;
i++)
1860 for (
i = low;
i < high;
i++)
1873 memcpy(
data->aff, aff,
sizeof(
AFFIX *) * naff);
1884 aff[naff++] = Conf->
Affix +
i;
1894 memcpy(
data->aff, aff,
sizeof(
AFFIX *) * naff);
1912 int start = (issuffix) ? startsuffix : 0;
1913 int end = (issuffix) ? Conf->
naffixes : startsuffix;
1921 Affix->data->node = Conf->
Suffix;
1940 Affix->data->naff = (
uint32) cnt;
1946 Affix->data->aff[cnt] = Conf->
Affix +
i;
2006 strbncmp((
const unsigned char *) (ptr - 1)->affix,
2007 (
const unsigned char *) Affix->
repl,
2043 while (node && *level < wrdlen)
2045 StopLow = node->
data;
2047 while (StopLow < StopHigh)
2049 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
2055 if (StopMiddle->
naff)
2057 node = StopMiddle->
node;
2061 StopLow = StopMiddle + 1;
2063 StopHigh = StopMiddle;
2065 if (StopLow >= StopHigh)
2111 strcpy(newword,
word);
2122 if (baselen && *baselen + strlen(Affix->
find) <= Affix->
replen)
2124 strcpy(newword, Affix->
find);
2145 newword_len = strlen(newword);
2166 if (forms ==
cur || strcmp(
word, *(
cur - 1)) != 0)
2183 int wrdlen = strlen(
word),
2216 for (
j = 0;
j < prefix->naff;
j++)
2225 pnode = prefix->node;
2241 for (
i = 0;
i < suffix->
naff;
i++)
2252 swrdlen = strlen(newword);
2258 for (
j = 0;
j < prefix->naff;
j++)
2260 if (
CheckAffix(newword, swrdlen, prefix->aff[
j],
flag, pnewword, &baselen))
2270 pnode = prefix->node;
2275 snode = suffix->
node;
2305 while ((*ptr)->affix)
2307 if (
len > (*ptr)->len && strncmp((*ptr)->affix,
word, (*ptr)->len) == 0)
2310 issuffix = (*ptr)->issuffix;
2312 return (issuffix) ?
len : 0;
2321 while ((*ptr)->affix)
2323 if (
len > (*ptr)->len && (affbegin = strstr(
word, (*ptr)->affix)) != NULL)
2325 len = (*ptr)->len + (affbegin -
word);
2326 issuffix = (*ptr)->issuffix;
2328 return (issuffix) ?
len : 0;
2382 int level = (snode) ? minpos :
startpos;
2387 int compoundflag = 0;
2392 notprobed = (
char *)
palloc(wordlen);
2393 memset(notprobed, 1, wordlen);
2396 while (level < wordlen)
2408 lenaff = level -
startpos + lenaff;
2410 if (!notprobed[
startpos + lenaff - 1])
2413 if (level + lenaff - 1 <= minpos)
2424 else if (level == wordlen - 1)
2434 char **sptr = subres;
2436 notprobed[
startpos + lenaff - 1] = 0;
2457 StopLow = node->
data;
2459 while (StopLow < StopHigh)
2461 StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
2465 StopLow = StopMiddle + 1;
2467 StopHigh = StopMiddle;
2470 if (StopLow < StopHigh)
2474 else if (level == wordlen - 1)
2480 if (StopMiddle->
isword &&
2488 if (wordlen == level + 1)
2512 node = StopMiddle->
node;
2532 (*lcur)->lexeme =
word;
2533 (*lcur)->flags = flags;
2534 (*lcur)->nvariant = NVariant;
2536 (*lcur)->lexeme = NULL;
2554 while (*ptr && (lcur - lres) <
MAX_NORM)
2556 addNorm(&lres, &lcur, *ptr, 0, NVariant++);
2564 int wordlen = strlen(
word);
2577 char **subptr = subres;
2581 for (
i = 0;
i < var->
nstem - 1;
i++)
2586 addNorm(&lres, &lcur, *subptr, 0, NVariant);
2592 var->
stem[0] = NULL;
#define Assert(condition)
static void PGresult * res
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)
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
int pg_mblen(const char *mbstr)
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurTransactionContext
char * pnstrdup(const char *in, Size len)
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
static XLogRecPtr startpos
#define qsort(a, b, c, d)
MemoryContextSwitchTo(old_ctx)
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)
static pg_noinline void Size size
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 * cpstrdup(IspellDict *Conf, const char *str)
static int parse_ooaffentry(char *str, char *type, char *flag, char *find, char *repl, char *mask)
static const char * getAffixFlagSet(IspellDict *Conf, char *s)
static SPNode * mkSPNode(IspellDict *Conf, int low, int high, int level)
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 AffixNodeData * FindAffixes(AffixNode *node, const char *word, int wrdlen, int *level, int type)
static char * CheckAffix(const char *word, size_t len, AFFIX *Affix, int flagflags, char *newword, int *baselen)
static SplitVar * CopyVar(SplitVar *s, int makedup)
static void NIAddSpell(IspellDict *Conf, const char *word, const char *flag)
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 void NIAddAffix(IspellDict *Conf, const char *flag, char flagflags, const char *mask, const char *find, const char *repl, int type)
static char * findchar(char *str, int c)
static const char * VoidString
static char ** NormalizeSubWord(IspellDict *Conf, const char *word, int flag)
static int CheckCompoundAffixes(CMPDAffix **ptr, const char *word, int len, bool CheckInPlace)
static void getNextFlagFromString(IspellDict *Conf, const char **sflagset, char *sflag)
void NISortAffixes(IspellDict *Conf)
static int cmpcmdflag(const void *f1, const void *f2)
static char * findchar2(char *str, int c1, int c2)
static void setCompoundAffixFlagValue(IspellDict *Conf, CompoundAffixFlag *entry, char *s, uint32 val)
void NIImportDictionary(IspellDict *Conf, const char *filename)
static AffixNode * mkANode(IspellDict *Conf, int low, int high, int level, int type)
static bool IsAffixFlagInUse(IspellDict *Conf, int affix, const char *affixflag)
static bool parse_affentry(char *str, char *mask, char *find, char *repl)
static SplitVar * SplitToVariants(IspellDict *Conf, SPNode *snode, SplitVar *orig, const char *word, int wordlen, int startpos, int minpos)
static uint32 makeCompoundFlags(IspellDict *Conf, int affix)
static int cmpspellaffix(const void *s1, const void *s2)
static int strbncmp(const unsigned char *s1, const unsigned char *s2, size_t count)
TSLexeme * NINormalizeWord(IspellDict *Conf, const char *word)
static int MergeAffix(IspellDict *Conf, int a1, int a2)
static void * compact_palloc0(IspellDict *Conf, size_t size)
static int getCompoundAffixFlagValue(IspellDict *Conf, const char *s)
static void AddStem(SplitVar *v, char *word)
static int addToResult(char **forms, char **cur, char *word)
static void mkVoidAffix(IspellDict *Conf, bool issuffix, int startsuffix)
static bool isAffixInUse(IspellDict *Conf, const char *affixflag)
static void addCompoundAffixFlagValue(IspellDict *Conf, char *s, uint32 val)
static char * lowerstr_ctx(IspellDict *Conf, const char *src)
static int cmpaffix(const void *s1, const void *s2)
#define FF_COMPOUNDFLAGMASK
#define FF_COMPOUNDFORBIDFLAG
#define FF_COMPOUNDPERMITFLAG
#define FF_COMPOUNDMIDDLE
void check_stack_depth(void)
AffixNodeData data[FLEXIBLE_ARRAY_MEMBER]
union CompoundAffixFlag::@135 flag
CompoundAffixFlag * CompoundAffixFlags
CMPDAffix * CompoundAffix
SPNodeData data[FLEXIBLE_ARRAY_MEMBER]
union aff_struct::@134 reg
struct spell_struct::@132::@133 d
union spell_struct::@132 p
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_isalpha(const char *ptr)
void tsearch_readline_end(tsearch_readline_state *stp)