/*
  * 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