i18npath = strdupa (i18npath);
i18npath = memcpy (i18npathbuf, i18npath, pathlen + 1);
repertoire_read (const char *filename){  struct linereader *repfile;  struct repertoire_t *result;  struct repertoire_t **resultp;  struct repertoire_t search;  int state;  char *from_name = NULL;  char *to_name = NULL;  enum token_t ellipsis = tok_none;  search.name = filename;  resultp = tfind (&search, &known, &repertoire_compare);  if (resultp != NULL)    return *resultp;  /* Determine path.  */  repfile = lr_open (filename, repertoiremap_hash);  if (repfile == NULL)    {      if (strchr (filename, '/') == NULL)	{	  char *i18npath = getenv ("I18NPATH");	  if (i18npath != NULL && *i18npath != '\0')	    {	      char path[strlen (filename) + 1 + strlen (i18npath)		        + sizeof ("/repertoiremaps/") - 1];	      char *next;	      i18npath = strdupa (i18npath);	      while (repfile == NULL		     && (next = strsep (&i18npath, ":")) != NULL)		{		  stpcpy (stpcpy (stpcpy (path, next), "/repertoiremaps/"),			  filename);		  repfile = lr_open (path, repertoiremap_hash);		  if (repfile == NULL)		    {		      stpcpy (stpcpy (path, next), filename);		      repfile = lr_open (path, repertoiremap_hash);		    }		}	    }	  if (repfile == NULL)	    {	      /* Look in the systems charmap directory.  */	      char *buf = xmalloc (strlen (filename) + 1				   + sizeof (REPERTOIREMAP_PATH));	      stpcpy (stpcpy (stpcpy (buf, REPERTOIREMAP_PATH), "/"),		      filename);	      repfile = lr_open (buf, repertoiremap_hash);	      if (repfile == NULL)		free (buf);	    }	}      if (repfile == NULL)	return NULL;    }  /* We don't want symbolic names in string to be translated.  */  repfile->translate_strings = 0;  /* Allocate room for result.  */  result = (struct repertoire_t *) xmalloc (sizeof (struct repertoire_t));  memset (result, '\0', sizeof (struct repertoire_t));  result->name = xstrdup (filename);#define obstack_chunk_alloc malloc#define obstack_chunk_free free  obstack_init (&result->mem_pool);  if (init_hash (&result->char_table, 256)      || init_hash (&result->reverse_table, 256)      || init_hash (&result->seq_table, 256))    {      free (result);      return NULL;    }  /* We use a state machine to describe the charmap description file     format.  */  state = 1;  while (1)    {      /* What's on?  */      struct token *now = lr_token (repfile, NULL, NULL, NULL, verbose);      enum token_t nowtok = now->tok;      struct token *arg;      if (nowtok == tok_eof)	break;      switch (state)	{	case 1:	  /* We haven't yet read any character definition.  This is where	     we accept escape_char and comment_char definitions.  */	  if (nowtok == tok_eol)	    /* Ignore empty lines.  */	    continue;	  if (nowtok == tok_escape_char || nowtok == tok_comment_char)	    {	      /* We know that we need an argument.  */	      arg = lr_token (repfile, NULL, NULL, NULL, verbose);	      if (arg->tok != tok_ident)		{		  lr_error (repfile, _("syntax error in prolog: %s"),			    _("bad argument"));		  lr_ignore_rest (repfile, 0);		  continue;		}	      if (arg->val.str.lenmb != 1)		{		  lr_error (repfile, _("\argument to <%s> must be a single character"),			    nowtok == tok_escape_char ? "escape_char"						      : "comment_char");		  lr_ignore_rest (repfile, 0);		  continue;		}	      if (nowtok == tok_escape_char)		repfile->escape_char = *arg->val.str.startmb;	      else		repfile->comment_char = *arg->val.str.startmb;	      lr_ignore_rest (repfile, 1);	      continue;	    }	  if (nowtok == tok_charids)	    {	      lr_ignore_rest (repfile, 1);	      state = 2;	      continue;	    }	  /* Otherwise we start reading the character definitions.  */	  state = 2;	  /* FALLTHROUGH */	case 2:	  /* We are now are in the body.  Each line	     must have the format "%s %s %s\n" or "%s...%s %s %s\n".  */	  if (nowtok == tok_eol)	    /* Ignore empty lines.  */	    continue;	  if (nowtok == tok_end)	    {	      state = 90;	      continue;	    }	  if (nowtok != tok_bsymbol)	    {	      lr_error (repfile,			_("syntax error in repertoire map definition: %s"),			_("no symbolic name given"));	      lr_ignore_rest (repfile, 0);	      continue;	    }	  /* If the previous line was not completely correct free the	     used memory.  */	  if (from_name != NULL)	    obstack_free (&result->mem_pool, from_name);	  from_name = (char *) obstack_copy0 (&result->mem_pool,					      now->val.str.startmb,					      now->val.str.lenmb);	  to_name = NULL;	  state = 3;	  continue;	case 3:	  /* We have two possibilities: We can see an ellipsis or an	     encoding value.  */	  if (nowtok == tok_ellipsis3 || nowtok == tok_ellipsis4	      || nowtok == tok_ellipsis2)	    {	      ellipsis = nowtok;	      state = 4;	      continue;	    }	  /* FALLTHROUGH */	case 5:	  /* We expect a value of the form <Uxxxx> or <Uxxxxxxxx> where	     the xxx mean a hexadecimal value.  */	  state = 2;	  errno = 0;	  if (nowtok != tok_ucs4)	    {	      lr_error (repfile,			_("syntax error in repertoire map definition: %s"),			_("no <Uxxxx> or <Uxxxxxxxx> value given"));	      lr_ignore_rest (repfile, 0);	      continue;	    }	  /* We've found a new valid definition.  */	  repertoire_new_char (repfile, &result->char_table,			       &result->reverse_table, &result->mem_pool,			       now->val.ucs4, from_name, to_name,			       ellipsis != tok_ellipsis2);	  /* Ignore the rest of the line.  */	  lr_ignore_rest (repfile, 0);	  from_name = NULL;	  to_name = NULL;	  continue;	case 4:	  if (nowtok != tok_bsymbol)	    {	      lr_error (repfile,			_("syntax error in repertoire map definition: %s"),			_("no symbolic name given for end of range"));	      lr_ignore_rest (repfile, 0);	      state = 2;	      continue;	    }	  /* Copy the to-name in a safe place.  */	  to_name = (char *) obstack_copy0 (&result->mem_pool,					    repfile->token.val.str.startmb,					    repfile->token.val.str.lenmb);	  state = 5;	  continue;	case 90:	  if (nowtok != tok_charids)	    lr_error (repfile, _("\`%1$s' definition does not end with `END %1$s'"), "CHARIDS");	  lr_ignore_rest (repfile, nowtok == tok_charids);	  break;	}      break;    }  if (state != 2 && state != 90 && !be_quiet)    WITH_CUR_LOCALE (error (0, 0, _("%s: premature end of file"),			    repfile->fname));  lr_close (repfile);  if (tsearch (result, &known, &repertoire_compare) == NULL)    /* Something went wrong.  */    WITH_CUR_LOCALE (error (0, errno, _("cannot safe new repertoire map")));  return result;}