dict_ispell.c 3.85 KB
Newer Older
1 2
/* $PostgreSQL: pgsql/contrib/tsearch2/dict_ispell.c,v 1.10 2006/03/11 04:38:30 momjian Exp $ */

Bruce Momjian's avatar
Bruce Momjian committed
3
/*
Teodor Sigaev's avatar
Teodor Sigaev committed
4 5 6 7 8
 * ISpell interface
 * Teodor Sigaev <teodor@sigaev.ru>
 */
#include "postgres.h"

9 10
#include <ctype.h>

Teodor Sigaev's avatar
Teodor Sigaev committed
11 12 13
#include "dict.h"
#include "common.h"
#include "ispell/spell.h"
14
#include "ts_locale.h"
Teodor Sigaev's avatar
Teodor Sigaev committed
15

Bruce Momjian's avatar
Bruce Momjian committed
16 17
typedef struct
{
Teodor Sigaev's avatar
Teodor Sigaev committed
18 19
	StopList	stoplist;
	IspellDict	obj;
Bruce Momjian's avatar
Bruce Momjian committed
20
}	DictISpell;
Teodor Sigaev's avatar
Teodor Sigaev committed
21 22

PG_FUNCTION_INFO_V1(spell_init);
Bruce Momjian's avatar
Bruce Momjian committed
23 24
Datum		spell_init(PG_FUNCTION_ARGS);

Teodor Sigaev's avatar
Teodor Sigaev committed
25
PG_FUNCTION_INFO_V1(spell_lexize);
Bruce Momjian's avatar
Bruce Momjian committed
26
Datum		spell_lexize(PG_FUNCTION_ARGS);
Teodor Sigaev's avatar
Teodor Sigaev committed
27 28

static void
Bruce Momjian's avatar
Bruce Momjian committed
29 30
freeDictISpell(DictISpell * d)
{
31
	NIFree(&(d->obj));
Teodor Sigaev's avatar
Teodor Sigaev committed
32 33 34 35
	freestoplist(&(d->stoplist));
	free(d);
}

Bruce Momjian's avatar
Bruce Momjian committed
36 37 38 39 40 41 42 43 44 45 46 47
Datum
spell_init(PG_FUNCTION_ARGS)
{
	DictISpell *d;
	Map		   *cfg,
			   *pcfg;
	text	   *in;
	bool		affloaded = false,
				dictloaded = false,
				stoploaded = false;

	if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL)
48 49 50
		ereport(ERROR,
				(errcode(ERRCODE_CONFIG_FILE_ERROR),
				 errmsg("ISpell confguration error")));
Bruce Momjian's avatar
Bruce Momjian committed
51 52 53

	d = (DictISpell *) malloc(sizeof(DictISpell));
	if (!d)
54 55 56
		ereport(ERROR,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 errmsg("out of memory")));
Bruce Momjian's avatar
Bruce Momjian committed
57 58
	memset(d, 0, sizeof(DictISpell));
	d->stoplist.wordop = lowerstr;
Teodor Sigaev's avatar
Teodor Sigaev committed
59 60

	in = PG_GETARG_TEXT_P(0);
Bruce Momjian's avatar
Bruce Momjian committed
61
	parse_cfgdict(in, &cfg);
Teodor Sigaev's avatar
Teodor Sigaev committed
62
	PG_FREE_IF_COPY(in, 0);
Bruce Momjian's avatar
Bruce Momjian committed
63 64 65
	pcfg = cfg;
	while (pcfg->key)
	{
66
		if (pg_strcasecmp("DictFile", pcfg->key) == 0)
Bruce Momjian's avatar
Bruce Momjian committed
67 68 69
		{
			if (dictloaded)
			{
Teodor Sigaev's avatar
Teodor Sigaev committed
70
				freeDictISpell(d);
71
				ereport(ERROR,
72 73
						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
						 errmsg("dictionary already loaded")));
Teodor Sigaev's avatar
Teodor Sigaev committed
74
			}
75
			if (NIImportDictionary(&(d->obj), pcfg->value))
Bruce Momjian's avatar
Bruce Momjian committed
76
			{
Teodor Sigaev's avatar
Teodor Sigaev committed
77
				freeDictISpell(d);
78 79 80 81
				ereport(ERROR,
						(errcode(ERRCODE_CONFIG_FILE_ERROR),
						 errmsg("could not load dictionary file \"%s\"",
								pcfg->value)));
Teodor Sigaev's avatar
Teodor Sigaev committed
82
			}
Bruce Momjian's avatar
Bruce Momjian committed
83 84
			dictloaded = true;
		}
85
		else if (pg_strcasecmp("AffFile", pcfg->key) == 0)
Bruce Momjian's avatar
Bruce Momjian committed
86 87 88
		{
			if (affloaded)
			{
Teodor Sigaev's avatar
Teodor Sigaev committed
89
				freeDictISpell(d);
90
				ereport(ERROR,
91 92
						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
						 errmsg("affixes already loaded")));
Teodor Sigaev's avatar
Teodor Sigaev committed
93
			}
94
			if (NIImportAffixes(&(d->obj), pcfg->value))
Bruce Momjian's avatar
Bruce Momjian committed
95
			{
Teodor Sigaev's avatar
Teodor Sigaev committed
96
				freeDictISpell(d);
97 98 99 100
				ereport(ERROR,
						(errcode(ERRCODE_CONFIG_FILE_ERROR),
						 errmsg("could not load affix file \"%s\"",
								pcfg->value)));
Teodor Sigaev's avatar
Teodor Sigaev committed
101
			}
Bruce Momjian's avatar
Bruce Momjian committed
102 103
			affloaded = true;
		}
104
		else if (pg_strcasecmp("StopFile", pcfg->key) == 0)
Bruce Momjian's avatar
Bruce Momjian committed
105 106 107 108 109
		{
			text	   *tmp = char2text(pcfg->value);

			if (stoploaded)
			{
Teodor Sigaev's avatar
Teodor Sigaev committed
110
				freeDictISpell(d);
111
				ereport(ERROR,
112 113
						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
						 errmsg("stop words already loaded")));
Teodor Sigaev's avatar
Teodor Sigaev committed
114 115 116 117
			}
			readstoplist(tmp, &(d->stoplist));
			sortstoplist(&(d->stoplist));
			pfree(tmp);
Bruce Momjian's avatar
Bruce Momjian committed
118 119 120 121
			stoploaded = true;
		}
		else
		{
Teodor Sigaev's avatar
Teodor Sigaev committed
122
			freeDictISpell(d);
123 124 125
			ereport(ERROR,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("unrecognized option: %s => %s",
Bruce Momjian's avatar
Bruce Momjian committed
126
							pcfg->key, pcfg->value)));
Teodor Sigaev's avatar
Teodor Sigaev committed
127 128 129 130 131 132 133
		}
		pfree(pcfg->key);
		pfree(pcfg->value);
		pcfg++;
	}
	pfree(cfg);

Bruce Momjian's avatar
Bruce Momjian committed
134 135
	if (affloaded && dictloaded)
	{
136 137
		NISortDictionary(&(d->obj));
		NISortAffixes(&(d->obj));
Bruce Momjian's avatar
Bruce Momjian committed
138 139 140
	}
	else if (!affloaded)
	{
Teodor Sigaev's avatar
Teodor Sigaev committed
141
		freeDictISpell(d);
142 143 144
		ereport(ERROR,
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
				 errmsg("no affixes")));
Bruce Momjian's avatar
Bruce Momjian committed
145 146 147
	}
	else
	{
Teodor Sigaev's avatar
Teodor Sigaev committed
148
		freeDictISpell(d);
149 150 151
		ereport(ERROR,
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
				 errmsg("no dictionary")));
Teodor Sigaev's avatar
Teodor Sigaev committed
152 153 154 155 156 157
	}

	PG_RETURN_POINTER(d);
}

Datum
Bruce Momjian's avatar
Bruce Momjian committed
158 159 160 161 162
spell_lexize(PG_FUNCTION_ARGS)
{
	DictISpell *d = (DictISpell *) PG_GETARG_POINTER(0);
	char	   *in = (char *) PG_GETARG_POINTER(1);
	char	   *txt;
163 164 165
	TSLexeme   *res;
	TSLexeme   *ptr,
			   *cptr;
Bruce Momjian's avatar
Bruce Momjian committed
166 167

	if (!PG_GETARG_INT32(2))
Teodor Sigaev's avatar
Teodor Sigaev committed
168 169 170
		PG_RETURN_POINTER(NULL);

	txt = pnstrdup(in, PG_GETARG_INT32(2));
171
	res = NINormalizeWord(&(d->obj), txt);
Teodor Sigaev's avatar
Teodor Sigaev committed
172 173
	pfree(txt);

Bruce Momjian's avatar
Bruce Momjian committed
174
	if (res == NULL)
Teodor Sigaev's avatar
Teodor Sigaev committed
175 176
		PG_RETURN_POINTER(NULL);

Bruce Momjian's avatar
Bruce Momjian committed
177
	ptr = cptr = res;
178
	while (ptr->lexeme)
Bruce Momjian's avatar
Bruce Momjian committed
179
	{
180
		if (searchstoplist(&(d->stoplist), ptr->lexeme))
Bruce Momjian's avatar
Bruce Momjian committed
181
		{
182 183
			pfree(ptr->lexeme);
			ptr->lexeme = NULL;
Bruce Momjian's avatar
Bruce Momjian committed
184 185 186 187
			ptr++;
		}
		else
		{
188
			memcpy(cptr, ptr, sizeof(TSLexeme));
Bruce Momjian's avatar
Bruce Momjian committed
189
			cptr++;
Teodor Sigaev's avatar
Teodor Sigaev committed
190 191 192
			ptr++;
		}
	}
193
	cptr->lexeme = NULL;
Teodor Sigaev's avatar
Teodor Sigaev committed
194 195 196

	PG_RETURN_POINTER(res);
}