diff --git a/contrib/unaccent/unaccent.c b/contrib/unaccent/unaccent.c
new file mode 100644
index 4182376..8caa7c2
*** a/contrib/unaccent/unaccent.c
--- b/contrib/unaccent/unaccent.c
***************
*** 23,52 ****
  PG_MODULE_MAGIC;
  
  /*
!  * Unaccent dictionary uses uncompressed suffix tree to find a
!  * character to replace. Each node of tree is an array of
!  * SuffixChar struct with length = 256 (n-th element of array
   * corresponds to byte)
   */
! typedef struct SuffixChar
  {
! 	struct SuffixChar *nextChar;
  	char	   *replaceTo;
  	int			replacelen;
! } SuffixChar;
  
  /*
!  * placeChar - put str into tree's structure, byte by byte.
   */
! static SuffixChar *
! placeChar(SuffixChar *node, unsigned char *str, int lenstr, char *replaceTo, int replacelen)
  {
! 	SuffixChar *curnode;
  
  	if (!node)
  	{
! 		node = palloc(sizeof(SuffixChar) * 256);
! 		memset(node, 0, sizeof(SuffixChar) * 256);
  	}
  
  	curnode = node + *str;
--- 23,51 ----
  PG_MODULE_MAGIC;
  
  /*
!  * Unaccent dictionary uses trie to find a character to replace. Each node of
!  * trie is an array of TrieChar struct with length = 256 (n-th element of array
   * corresponds to byte)
   */
! typedef struct TrieChar
  {
! 	struct TrieChar *nextChar;
  	char	   *replaceTo;
  	int			replacelen;
! } TrieChar;
  
  /*
!  * placeChar - put str into trie's structure, byte by byte.
   */
! static TrieChar *
! placeChar(TrieChar *node, unsigned char *str, int lenstr, char *replaceTo, int replacelen)
  {
! 	TrieChar *curnode;
  
  	if (!node)
  	{
! 		node = palloc(sizeof(TrieChar) * 256);
! 		memset(node, 0, sizeof(TrieChar) * 256);
  	}
  
  	curnode = node + *str;
*************** placeChar(SuffixChar *node, unsigned cha
*** 71,83 ****
  }
  
  /*
!  * initSuffixTree  - create suffix tree from file. Function converts
   * UTF8-encoded file into current encoding.
   */
! static SuffixChar *
! initSuffixTree(char *filename)
  {
! 	SuffixChar *volatile rootSuffixTree = NULL;
  	MemoryContext ccxt = CurrentMemoryContext;
  	tsearch_readline_state trst;
  	volatile bool skip;
--- 70,82 ----
  }
  
  /*
!  * initTrie  - create trie from file. Function converts
   * UTF8-encoded file into current encoding.
   */
! static TrieChar *
! initTrie(char *filename)
  {
! 	TrieChar *volatile rootTrie = NULL;
  	MemoryContext ccxt = CurrentMemoryContext;
  	tsearch_readline_state trst;
  	volatile bool skip;
*************** initSuffixTree(char *filename)
*** 161,167 ****
  				}
  
  				if (state >= 3)
! 					rootSuffixTree = placeChar(rootSuffixTree,
  											   (unsigned char *) src, srclen,
  											   trg, trglen);
  
--- 160,166 ----
  				}
  
  				if (state >= 3)
! 					rootTrie = placeChar(rootTrie,
  											   (unsigned char *) src, srclen,
  											   trg, trglen);
  
*************** initSuffixTree(char *filename)
*** 192,205 ****
  
  	tsearch_readline_end(&trst);
  
! 	return rootSuffixTree;
  }
  
  /*
!  * findReplaceTo - find multibyte character in tree
   */
! static SuffixChar *
! findReplaceTo(SuffixChar *node, unsigned char *src, int srclen)
  {
  	while (node)
  	{
--- 191,204 ----
  
  	tsearch_readline_end(&trst);
  
! 	return rootTrie;
  }
  
  /*
!  * findReplaceTo - find multibyte character in trie
   */
! static TrieChar *
! findReplaceTo(TrieChar *node, unsigned char *src, int srclen)
  {
  	while (node)
  	{
*************** Datum
*** 221,227 ****
  unaccent_init(PG_FUNCTION_ARGS)
  {
  	List	   *dictoptions = (List *) PG_GETARG_POINTER(0);
! 	SuffixChar *rootSuffixTree = NULL;
  	bool		fileloaded = false;
  	ListCell   *l;
  
--- 220,226 ----
  unaccent_init(PG_FUNCTION_ARGS)
  {
  	List	   *dictoptions = (List *) PG_GETARG_POINTER(0);
! 	TrieChar   *rootTrie = NULL;
  	bool		fileloaded = false;
  	ListCell   *l;
  
*************** unaccent_init(PG_FUNCTION_ARGS)
*** 235,241 ****
  				ereport(ERROR,
  						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  						 errmsg("multiple Rules parameters")));
! 			rootSuffixTree = initSuffixTree(defGetString(defel));
  			fileloaded = true;
  		}
  		else
--- 234,240 ----
  				ereport(ERROR,
  						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  						 errmsg("multiple Rules parameters")));
! 			rootTrie = initTrie(defGetString(defel));
  			fileloaded = true;
  		}
  		else
*************** unaccent_init(PG_FUNCTION_ARGS)
*** 254,260 ****
  				 errmsg("missing Rules parameter")));
  	}
  
! 	PG_RETURN_POINTER(rootSuffixTree);
  }
  
  PG_FUNCTION_INFO_V1(unaccent_lexize);
--- 253,259 ----
  				 errmsg("missing Rules parameter")));
  	}
  
! 	PG_RETURN_POINTER(rootTrie);
  }
  
  PG_FUNCTION_INFO_V1(unaccent_lexize);
*************** Datum		unaccent_lexize(PG_FUNCTION_ARGS)
*** 262,282 ****
  Datum
  unaccent_lexize(PG_FUNCTION_ARGS)
  {
! 	SuffixChar *rootSuffixTree = (SuffixChar *) PG_GETARG_POINTER(0);
  	char	   *srcchar = (char *) PG_GETARG_POINTER(1);
  	int32		len = PG_GETARG_INT32(2);
  	char	   *srcstart,
  			   *trgchar = NULL;
  	int			charlen;
  	TSLexeme   *res = NULL;
! 	SuffixChar *node;
  
  	srcstart = srcchar;
  	while (srcchar - srcstart < len)
  	{
  		charlen = pg_mblen(srcchar);
  
! 		node = findReplaceTo(rootSuffixTree, (unsigned char *) srcchar, charlen);
  		if (node && node->replaceTo)
  		{
  			if (!res)
--- 261,281 ----
  Datum
  unaccent_lexize(PG_FUNCTION_ARGS)
  {
! 	TrieChar   *rootTrie = (TrieChar *) PG_GETARG_POINTER(0);
  	char	   *srcchar = (char *) PG_GETARG_POINTER(1);
  	int32		len = PG_GETARG_INT32(2);
  	char	   *srcstart,
  			   *trgchar = NULL;
  	int			charlen;
  	TSLexeme   *res = NULL;
! 	TrieChar   *node;
  
  	srcstart = srcchar;
  	while (srcchar - srcstart < len)
  	{
  		charlen = pg_mblen(srcchar);
  
! 		node = findReplaceTo(rootTrie, (unsigned char *) srcchar, charlen);
  		if (node && node->replaceTo)
  		{
  			if (!res)
