1/*-------------------------------------------------------------------------
2 *
3 * dict_ispell.c
4 * Ispell dictionary interface
5 *
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 *
8 *
9 * IDENTIFICATION
10 * src/backend/tsearch/dict_ispell.c
11 *
12 *-------------------------------------------------------------------------
13 */
14#include "postgres.h"
15
16#include "commands/defrem.h"
17#include "tsearch/dicts/spell.h"
18#include "tsearch/ts_locale.h"
19#include "tsearch/ts_utils.h"
20#include "utils/builtins.h"
21
22
23typedef struct
24{
25 StopList stoplist;
26 IspellDict obj;
27} DictISpell;
28
29Datum
30dispell_init(PG_FUNCTION_ARGS)
31{
32 List *dictoptions = (List *) PG_GETARG_POINTER(0);
33 DictISpell *d;
34 bool affloaded = false,
35 dictloaded = false,
36 stoploaded = false;
37 ListCell *l;
38
39 d = (DictISpell *) palloc0(sizeof(DictISpell));
40
41 NIStartBuild(&(d->obj));
42
43 foreach(l, dictoptions)
44 {
45 DefElem *defel = (DefElem *) lfirst(l);
46
47 if (strcmp(defel->defname, "dictfile") == 0)
48 {
49 if (dictloaded)
50 ereport(ERROR,
51 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
52 errmsg("multiple DictFile parameters")));
53 NIImportDictionary(&(d->obj),
54 get_tsearch_config_filename(defGetString(defel),
55 "dict"));
56 dictloaded = true;
57 }
58 else if (strcmp(defel->defname, "afffile") == 0)
59 {
60 if (affloaded)
61 ereport(ERROR,
62 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
63 errmsg("multiple AffFile parameters")));
64 NIImportAffixes(&(d->obj),
65 get_tsearch_config_filename(defGetString(defel),
66 "affix"));
67 affloaded = true;
68 }
69 else if (strcmp(defel->defname, "stopwords") == 0)
70 {
71 if (stoploaded)
72 ereport(ERROR,
73 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
74 errmsg("multiple StopWords parameters")));
75 readstoplist(defGetString(defel), &(d->stoplist), lowerstr);
76 stoploaded = true;
77 }
78 else
79 {
80 ereport(ERROR,
81 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
82 errmsg("unrecognized Ispell parameter: \"%s\"",
83 defel->defname)));
84 }
85 }
86
87 if (affloaded && dictloaded)
88 {
89 NISortDictionary(&(d->obj));
90 NISortAffixes(&(d->obj));
91 }
92 else if (!affloaded)
93 {
94 ereport(ERROR,
95 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
96 errmsg("missing AffFile parameter")));
97 }
98 else
99 {
100 ereport(ERROR,
101 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
102 errmsg("missing DictFile parameter")));
103 }
104
105 NIFinishBuild(&(d->obj));
106
107 PG_RETURN_POINTER(d);
108}
109
110Datum
111dispell_lexize(PG_FUNCTION_ARGS)
112{
113 DictISpell *d = (DictISpell *) PG_GETARG_POINTER(0);
114 char *in = (char *) PG_GETARG_POINTER(1);
115 int32 len = PG_GETARG_INT32(2);
116 char *txt;
117 TSLexeme *res;
118 TSLexeme *ptr,
119 *cptr;
120
121 if (len <= 0)
122 PG_RETURN_POINTER(NULL);
123
124 txt = lowerstr_with_len(in, len);
125 res = NINormalizeWord(&(d->obj), txt);
126
127 if (res == NULL)
128 PG_RETURN_POINTER(NULL);
129
130 cptr = res;
131 for (ptr = cptr; ptr->lexeme; ptr++)
132 {
133 if (searchstoplist(&(d->stoplist), ptr->lexeme))
134 {
135 pfree(ptr->lexeme);
136 ptr->lexeme = NULL;
137 }
138 else
139 {
140 if (cptr != ptr)
141 memcpy(cptr, ptr, sizeof(TSLexeme));
142 cptr++;
143 }
144 }
145 cptr->lexeme = NULL;
146
147 PG_RETURN_POINTER(res);
148}
149