/*
* Initialization requires a lot of memory that's not needed
- * after the initialization is done. In init function,
- * CurrentMemoryContext is a long lived memory context associated
- * with the dictionary cache entry, so we use a temporary context
- * for the short-lived stuff.
+ * after the initialization is done. During initialization,
+ * CurrentMemoryContext is the long-lived memory context associated
+ * with the dictionary cache entry. We keep the short-lived stuff
+ * in the Conf->buildCxt context.
*/
-static MemoryContext tmpCtx = NULL;
+#define tmpalloc(sz) MemoryContextAlloc(Conf->buildCxt, (sz))
+#define tmpalloc0(sz) MemoryContextAllocZero(Conf->buildCxt, (sz))
-#define tmpalloc(sz) MemoryContextAlloc(tmpCtx, (sz))
-#define tmpalloc0(sz) MemoryContextAllocZero(tmpCtx, (sz))
-
-static void
-checkTmpCtx(void)
+/*
+ * Prepare for constructing an ISpell dictionary.
+ *
+ * The IspellDict struct is assumed to be zeroed when allocated.
+ */
+void
+NIStartBuild(IspellDict *Conf)
{
/*
- * XXX: This assumes that CurrentMemoryContext doesn't have any children
- * other than the one we create here.
+ * The temp context is a child of CurTransactionContext, so that it will
+ * go away automatically on error.
*/
- if (CurrentMemoryContext->firstchild == NULL)
- {
- tmpCtx = AllocSetContextCreate(CurrentMemoryContext,
- "Ispell dictionary init context",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
- }
- else
- tmpCtx = CurrentMemoryContext->firstchild;
+ Conf->buildCxt = AllocSetContextCreate(CurTransactionContext,
+ "Ispell dictionary init context",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
}
+/*
+ * Clean up when dictionary construction is complete.
+ */
+void
+NIFinishBuild(IspellDict *Conf)
+{
+ /* Release no-longer-needed temp memory */
+ MemoryContextDelete(Conf->buildCxt);
+ /* Just for cleanliness, zero the now-dangling pointers */
+ Conf->buildCxt = NULL;
+ Conf->Spell = NULL;
+}
+
+
+/*
+ * Apply lowerstr(), producing a temporary result (in the buildCxt).
+ */
static char *
-lowerstr_ctx(char *src)
+lowerstr_ctx(IspellDict *Conf, const char *src)
{
MemoryContext saveCtx;
char *dst;
- saveCtx = MemoryContextSwitchTo(tmpCtx);
+ saveCtx = MemoryContextSwitchTo(Conf->buildCxt);
dst = lowerstr(src);
MemoryContextSwitchTo(saveCtx);
return 0;
}
+
static int
strbncmp(const unsigned char *s1, const unsigned char *s2, size_t count)
{
tsearch_readline_state trst;
char *line;
- checkTmpCtx();
-
if (!tsearch_readline_begin(&trst, filename))
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
}
s += pg_mblen(s);
}
- pstr = lowerstr_ctx(line);
+ pstr = lowerstr_ctx(Conf, line);
NIAddSpell(Conf, pstr, flag);
pfree(pstr);
char scanbuf[BUFSIZ];
char *recoded;
- checkTmpCtx();
-
/* read file to find any flag */
memset(Conf->flagval, 0, sizeof(Conf->flagval));
Conf->usecompound = false;
if (ptype)
pfree(ptype);
- ptype = lowerstr_ctx(type);
+ ptype = lowerstr_ctx(Conf, type);
if (scanread < 4 || (STRNCMP(ptype, "sfx") && STRNCMP(ptype, "pfx")))
goto nextline;
if (strlen(sflag) != 1 || flag != *sflag || flag == 0)
goto nextline;
- prepl = lowerstr_ctx(repl);
+ prepl = lowerstr_ctx(Conf, repl);
/* affix flag */
if ((ptr = strchr(prepl, '/')) != NULL)
{
ptr++;
}
}
- pfind = lowerstr_ctx(find);
- pmask = lowerstr_ctx(mask);
+ pfind = lowerstr_ctx(Conf, find);
+ pmask = lowerstr_ctx(Conf, mask);
if (t_iseq(find, '0'))
*pfind = '\0';
if (t_iseq(repl, '0'))
bool oldformat = false;
char *recoded = NULL;
- checkTmpCtx();
-
if (!tsearch_readline_begin(&trst, filename))
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
int naffix = 0;
int curaffix;
- checkTmpCtx();
-
/* compress affixes */
/* Count the number of different flags used in the dictionary */
qsort((void *) Conf->Spell, Conf->nspell, sizeof(SPELL *), cmpspell);
Conf->Dictionary = mkSPNode(Conf, 0, Conf->nspell, 0);
-
- Conf->Spell = NULL;
}
static AffixNode *
CMPDAffix *ptr;
int firstsuffix = Conf->naffixes;
- checkTmpCtx();
-
if (Conf->naffixes == 0)
return;
int naffixes;
AFFIX *Affix;
- /*
- * Temporary array of all words in the dict file. Only used during
- * initialization
- */
- SPELL **Spell;
- int nspell; /* number of valid entries in Spell array */
- int mspell; /* allocated length of Spell array */
-
AffixNode *Suffix;
AffixNode *Prefix;
unsigned char flagval[256];
bool usecompound;
+
+ /*
+ * Remaining fields are only used during dictionary construction;
+ * they are set up by NIStartBuild and cleared by NIFinishBuild.
+ */
+ MemoryContext buildCxt; /* temp context for construction */
+
+ /* Temporary array of all words in the dict file */
+ SPELL **Spell;
+ int nspell; /* number of valid entries in Spell array */
+ int mspell; /* allocated length of Spell array */
} IspellDict;
extern TSLexeme *NINormalizeWord(IspellDict *Conf, char *word);
+
+extern void NIStartBuild(IspellDict *Conf);
extern void NIImportAffixes(IspellDict *Conf, const char *filename);
extern void NIImportDictionary(IspellDict *Conf, const char *filename);
extern void NISortDictionary(IspellDict *Conf);
extern void NISortAffixes(IspellDict *Conf);
+extern void NIFinishBuild(IspellDict *Conf);
#endif