Blame locale/programs/ld-messages.c

Packit Service 82fcde
/* Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
Packit Service 82fcde
Packit Service 82fcde
   This program is free software; you can redistribute it and/or modify
Packit Service 82fcde
   it under the terms of the GNU General Public License as published
Packit Service 82fcde
   by the Free Software Foundation; version 2 of the License, or
Packit Service 82fcde
   (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   This program is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 82fcde
   GNU General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU General Public License
Packit Service 82fcde
   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#ifdef HAVE_CONFIG_H
Packit Service 82fcde
# include <config.h>
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#include <langinfo.h>
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <regex.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <sys/uio.h>
Packit Service 82fcde
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
Packit Service 82fcde
#include "localedef.h"
Packit Service 82fcde
#include "linereader.h"
Packit Service 82fcde
#include "localeinfo.h"
Packit Service 82fcde
#include "locfile.h"
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* The real definition of the struct for the LC_MESSAGES locale.  */
Packit Service 82fcde
struct locale_messages_t
Packit Service 82fcde
{
Packit Service 82fcde
  const char *yesexpr;
Packit Service 82fcde
  const char *noexpr;
Packit Service 82fcde
  const char *yesstr;
Packit Service 82fcde
  const char *nostr;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
messages_startup (struct linereader *lr, struct localedef_t *locale,
Packit Service 82fcde
		  int ignore_content)
Packit Service 82fcde
{
Packit Service 82fcde
  if (!ignore_content)
Packit Service 82fcde
    locale->categories[LC_MESSAGES].messages =
Packit Service 82fcde
      (struct locale_messages_t *) xcalloc (1,
Packit Service 82fcde
					    sizeof (struct locale_messages_t));
Packit Service 82fcde
Packit Service 82fcde
  if (lr != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      lr->translate_strings = 1;
Packit Service 82fcde
      lr->return_widestr = 0;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
messages_finish (struct localedef_t *locale, const struct charmap_t *charmap)
Packit Service 82fcde
{
Packit Service 82fcde
  struct locale_messages_t *messages
Packit Service 82fcde
    = locale->categories[LC_MESSAGES].messages;
Packit Service 82fcde
  int nothing = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Now resolve copying and also handle completely missing definitions.  */
Packit Service 82fcde
  if (messages == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* First see whether we were supposed to copy.  If yes, find the
Packit Service 82fcde
	 actual definition.  */
Packit Service 82fcde
      if (locale->copy_name[LC_MESSAGES] != NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Find the copying locale.  This has to happen transitively since
Packit Service 82fcde
	     the locale we are copying from might also copying another one.  */
Packit Service 82fcde
	  struct localedef_t *from = locale;
Packit Service 82fcde
Packit Service 82fcde
	  do
Packit Service 82fcde
	    from = find_locale (LC_MESSAGES, from->copy_name[LC_MESSAGES],
Packit Service 82fcde
				from->repertoire_name, charmap);
Packit Service 82fcde
	  while (from->categories[LC_MESSAGES].messages == NULL
Packit Service 82fcde
		 && from->copy_name[LC_MESSAGES] != NULL);
Packit Service 82fcde
Packit Service 82fcde
	  messages = locale->categories[LC_MESSAGES].messages
Packit Service 82fcde
	    = from->categories[LC_MESSAGES].messages;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* If there is still no definition issue an warning and create an
Packit Service 82fcde
	 empty one.  */
Packit Service 82fcde
      if (messages == NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  record_warning (_("\
Packit Service 82fcde
No definition for %s category found"), "LC_MESSAGES");
Packit Service 82fcde
	  messages_startup (NULL, locale, 0);
Packit Service 82fcde
	  messages = locale->categories[LC_MESSAGES].messages;
Packit Service 82fcde
	  nothing = 1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* The fields YESSTR and NOSTR are optional.  */
Packit Service 82fcde
  if (messages->yesstr == NULL)
Packit Service 82fcde
    messages->yesstr = "";
Packit Service 82fcde
  if (messages->nostr == NULL)
Packit Service 82fcde
    messages->nostr = "";
Packit Service 82fcde
Packit Service 82fcde
  if (messages->yesexpr == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (! nothing)
Packit Service 82fcde
	record_error (0, 0, _("%s: field `%s' undefined"),
Packit Service 82fcde
		      "LC_MESSAGES", "yesexpr");
Packit Service 82fcde
      messages->yesexpr = "^[yY]";
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (messages->yesexpr[0] == '\0')
Packit Service 82fcde
    {
Packit Service 82fcde
      record_error (0, 0, _("\
Packit Service 82fcde
%s: value for field `%s' must not be an empty string"),
Packit Service 82fcde
		    "LC_MESSAGES", "yesexpr");
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      int result;
Packit Service 82fcde
      regex_t re;
Packit Service 82fcde
Packit Service 82fcde
      /* Test whether it are correct regular expressions.  */
Packit Service 82fcde
      result = regcomp (&re, messages->yesexpr, REG_EXTENDED);
Packit Service 82fcde
      if (result != 0 && !be_quiet)
Packit Service 82fcde
	{
Packit Service 82fcde
	  char errbuf[BUFSIZ];
Packit Service 82fcde
Packit Service 82fcde
	  (void) regerror (result, &re, errbuf, BUFSIZ);
Packit Service 82fcde
	  record_error (0, 0, _("\
Packit Service 82fcde
%s: no correct regular expression for field `%s': %s"),
Packit Service 82fcde
			"LC_MESSAGES", "yesexpr", errbuf);
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (result != 0)
Packit Service 82fcde
	regfree (&re);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (messages->noexpr == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (! nothing)
Packit Service 82fcde
	record_error (0, 0, _("%s: field `%s' undefined"),
Packit Service 82fcde
		      "LC_MESSAGES", "noexpr");
Packit Service 82fcde
      messages->noexpr = "^[nN]";
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (messages->noexpr[0] == '\0')
Packit Service 82fcde
    {
Packit Service 82fcde
      record_error (0, 0, _("\
Packit Service 82fcde
%s: value for field `%s' must not be an empty string"),
Packit Service 82fcde
		    "LC_MESSAGES", "noexpr");
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      int result;
Packit Service 82fcde
      regex_t re;
Packit Service 82fcde
Packit Service 82fcde
      /* Test whether it are correct regular expressions.  */
Packit Service 82fcde
      result = regcomp (&re, messages->noexpr, REG_EXTENDED);
Packit Service 82fcde
      if (result != 0 && !be_quiet)
Packit Service 82fcde
	{
Packit Service 82fcde
	  char errbuf[BUFSIZ];
Packit Service 82fcde
Packit Service 82fcde
	  (void) regerror (result, &re, errbuf, BUFSIZ);
Packit Service 82fcde
	  record_error (0, 0, _("\
Packit Service 82fcde
%s: no correct regular expression for field `%s': %s"),
Packit Service 82fcde
			"LC_MESSAGES", "noexpr", errbuf);
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (result != 0)
Packit Service 82fcde
	regfree (&re);
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
messages_output (struct localedef_t *locale, const struct charmap_t *charmap,
Packit Service 82fcde
		 const char *output_path)
Packit Service 82fcde
{
Packit Service 82fcde
  struct locale_messages_t *messages
Packit Service 82fcde
    = locale->categories[LC_MESSAGES].messages;
Packit Service 82fcde
  struct locale_file file;
Packit Service 82fcde
Packit Service 82fcde
  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES));
Packit Service 82fcde
  add_locale_string (&file, messages->yesexpr);
Packit Service 82fcde
  add_locale_string (&file, messages->noexpr);
Packit Service 82fcde
  add_locale_string (&file, messages->yesstr);
Packit Service 82fcde
  add_locale_string (&file, messages->nostr);
Packit Service 82fcde
  add_locale_string (&file, charmap->code_set_name);
Packit Service 82fcde
  write_locale_data (output_path, LC_MESSAGES, "LC_MESSAGES", &file;;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* The parser for the LC_MESSAGES section of the locale definition.  */
Packit Service 82fcde
void
Packit Service 82fcde
messages_read (struct linereader *ldfile, struct localedef_t *result,
Packit Service 82fcde
	       const struct charmap_t *charmap, const char *repertoire_name,
Packit Service 82fcde
	       int ignore_content)
Packit Service 82fcde
{
Packit Service 82fcde
  struct repertoire_t *repertoire = NULL;
Packit Service 82fcde
  struct locale_messages_t *messages;
Packit Service 82fcde
  struct token *now;
Packit Service 82fcde
  enum token_t nowtok;
Packit Service 82fcde
Packit Service 82fcde
  /* Get the repertoire we have to use.  */
Packit Service 82fcde
  if (repertoire_name != NULL)
Packit Service 82fcde
    repertoire = repertoire_read (repertoire_name);
Packit Service 82fcde
Packit Service 82fcde
  /* The rest of the line containing `LC_MESSAGES' must be free.  */
Packit Service 82fcde
  lr_ignore_rest (ldfile, 1);
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
  do
Packit Service 82fcde
    {
Packit Service 82fcde
      now = lr_token (ldfile, charmap, result, NULL, verbose);
Packit Service 82fcde
      nowtok = now->tok;
Packit Service 82fcde
    }
Packit Service 82fcde
  while (nowtok == tok_eol);
Packit Service 82fcde
Packit Service 82fcde
  /* If we see `copy' now we are almost done.  */
Packit Service 82fcde
  if (nowtok == tok_copy)
Packit Service 82fcde
    {
Packit Service 82fcde
      handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_messages,
Packit Service 82fcde
		   LC_MESSAGES, "LC_MESSAGES", ignore_content);
Packit Service 82fcde
      return;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Prepare the data structures.  */
Packit Service 82fcde
  messages_startup (ldfile, result, ignore_content);
Packit Service 82fcde
  messages = result->categories[LC_MESSAGES].messages;
Packit Service 82fcde
Packit Service 82fcde
  while (1)
Packit Service 82fcde
    {
Packit Service 82fcde
      struct token *arg;
Packit Service 82fcde
Packit Service 82fcde
      /* Of course we don't proceed beyond the end of file.  */
Packit Service 82fcde
      if (nowtok == tok_eof)
Packit Service 82fcde
	break;
Packit Service 82fcde
Packit Service 82fcde
      /* Ignore empty lines.  */
Packit Service 82fcde
      if (nowtok == tok_eol)
Packit Service 82fcde
	{
Packit Service 82fcde
	  now = lr_token (ldfile, charmap, result, NULL, verbose);
Packit Service 82fcde
	  nowtok = now->tok;
Packit Service 82fcde
	  continue;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      switch (nowtok)
Packit Service 82fcde
	{
Packit Service 82fcde
#define STR_ELEM(cat) \
Packit Service 82fcde
	case tok_##cat:							      \
Packit Service 82fcde
	  /* Ignore the rest of the line if we don't need the input of	      \
Packit Service 82fcde
	     this line.  */						      \
Packit Service 82fcde
	  if (ignore_content)						      \
Packit Service 82fcde
	    {								      \
Packit Service 82fcde
	      lr_ignore_rest (ldfile, 0);				      \
Packit Service 82fcde
	      break;							      \
Packit Service 82fcde
	    }								      \
Packit Service 82fcde
									      \
Packit Service 82fcde
	  if (messages->cat != NULL)					      \
Packit Service 82fcde
	    {								      \
Packit Service 82fcde
	      lr_error (ldfile, _("\
Packit Service 82fcde
%s: field `%s' declared more than once"), "LC_MESSAGES", #cat);		      \
Packit Service 82fcde
	      lr_ignore_rest (ldfile, 0);				      \
Packit Service 82fcde
	      break;							      \
Packit Service 82fcde
	    }								      \
Packit Service 82fcde
	  now = lr_token (ldfile, charmap, result, repertoire, verbose);      \
Packit Service 82fcde
	  if (now->tok != tok_string)					      \
Packit Service 82fcde
	    goto syntax_error;						      \
Packit Service 82fcde
	  else if (!ignore_content && now->val.str.startmb == NULL)	      \
Packit Service 82fcde
	    {								      \
Packit Service 82fcde
	      lr_error (ldfile, _("\
Packit Service 82fcde
%s: unknown character in field `%s'"), "LC_MESSAGES", #cat);		      \
Packit Service 82fcde
	      messages->cat = "";					      \
Packit Service 82fcde
	    }								      \
Packit Service 82fcde
	  else if (!ignore_content)					      \
Packit Service 82fcde
	    messages->cat = now->val.str.startmb;			      \
Packit Service 82fcde
	  break
Packit Service 82fcde
Packit Service 82fcde
	  STR_ELEM (yesexpr);
Packit Service 82fcde
	  STR_ELEM (noexpr);
Packit Service 82fcde
	  STR_ELEM (yesstr);
Packit Service 82fcde
	  STR_ELEM (nostr);
Packit Service 82fcde
Packit Service 82fcde
	case tok_end:
Packit Service 82fcde
	  /* Next we assume `LC_MESSAGES'.  */
Packit Service 82fcde
	  arg = lr_token (ldfile, charmap, result, NULL, verbose);
Packit Service 82fcde
	  if (arg->tok == tok_eof)
Packit Service 82fcde
	    break;
Packit Service 82fcde
	  if (arg->tok == tok_eol)
Packit Service 82fcde
	    lr_error (ldfile, _("%s: incomplete `END' line"), "LC_MESSAGES");
Packit Service 82fcde
	  else if (arg->tok != tok_lc_messages)
Packit Service 82fcde
	    lr_error (ldfile, _("\
Packit Service 82fcde
%1$s: definition does not end with `END %1$s'"), "LC_MESSAGES");
Packit Service 82fcde
	  lr_ignore_rest (ldfile, arg->tok == tok_lc_messages);
Packit Service 82fcde
	  return;
Packit Service 82fcde
Packit Service 82fcde
	default:
Packit Service 82fcde
	syntax_error:
Packit Service 82fcde
	  SYNTAX_ERROR (_("%s: syntax error"), "LC_MESSAGES");
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* Prepare for the next round.  */
Packit Service 82fcde
      now = lr_token (ldfile, charmap, result, NULL, verbose);
Packit Service 82fcde
      nowtok = now->tok;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* When we come here we reached the end of the file.  */
Packit Service 82fcde
  lr_error (ldfile, _("%s: premature end of file"), "LC_MESSAGES");
Packit Service 82fcde
}