Blame locale/programs/ld-identification.c

Packit Service 82fcde
/* Copyright (C) 1998-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@cygnus.com>, 1998.
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 <stdlib.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 "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_IDENTIFICATION locale.  */
Packit Service 82fcde
struct locale_identification_t
Packit Service 82fcde
{
Packit Service 82fcde
  const char *title;
Packit Service 82fcde
  const char *source;
Packit Service 82fcde
  const char *address;
Packit Service 82fcde
  const char *contact;
Packit Service 82fcde
  const char *email;
Packit Service 82fcde
  const char *tel;
Packit Service 82fcde
  const char *fax;
Packit Service 82fcde
  const char *language;
Packit Service 82fcde
  const char *territory;
Packit Service 82fcde
  const char *audience;
Packit Service 82fcde
  const char *application;
Packit Service 82fcde
  const char *abbreviation;
Packit Service 82fcde
  const char *revision;
Packit Service 82fcde
  const char *date;
Packit Service 82fcde
  const char *category[__LC_LAST];
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static const char *category_name[__LC_LAST] =
Packit Service 82fcde
{
Packit Service 82fcde
  [LC_CTYPE] = "LC_CTYPE",
Packit Service 82fcde
  [LC_NUMERIC] = "LC_NUMERIC",
Packit Service 82fcde
  [LC_TIME] = "LC_TIME",
Packit Service 82fcde
  [LC_COLLATE] = "LC_COLLATE",
Packit Service 82fcde
  [LC_MONETARY] = "LC_MONETARY",
Packit Service 82fcde
  [LC_MESSAGES] = "LC_MESSAGES",
Packit Service 82fcde
  [LC_ALL] = "LC_ALL",
Packit Service 82fcde
  [LC_PAPER] = "LC_PAPER",
Packit Service 82fcde
  [LC_NAME] = "LC_NAME",
Packit Service 82fcde
  [LC_ADDRESS] = "LC_ADDRESS",
Packit Service 82fcde
  [LC_TELEPHONE] = "LC_TELEPHONE",
Packit Service 82fcde
  [LC_MEASUREMENT] = "LC_MEASUREMENT",
Packit Service 82fcde
  [LC_IDENTIFICATION] = "LC_IDENTIFICATION"
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
identification_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
    {
Packit Service 82fcde
      locale->categories[LC_IDENTIFICATION].identification =
Packit Service 82fcde
	(struct locale_identification_t *)
Packit Service 82fcde
	xcalloc (1, sizeof (struct locale_identification_t));
Packit Service 82fcde
Packit Service 82fcde
      locale->categories[LC_IDENTIFICATION].identification->category[LC_ALL] =
Packit Service 82fcde
	"";
Packit Service 82fcde
    }
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
identification_finish (struct localedef_t *locale,
Packit Service 82fcde
		       const struct charmap_t *charmap)
Packit Service 82fcde
{
Packit Service 82fcde
  struct locale_identification_t *identification
Packit Service 82fcde
    = locale->categories[LC_IDENTIFICATION].identification;
Packit Service 82fcde
  int nothing = 0;
Packit Service 82fcde
  size_t num;
Packit Service 82fcde
Packit Service 82fcde
  /* Now resolve copying and also handle completely missing definitions.  */
Packit Service 82fcde
  if (identification == 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_IDENTIFICATION] != 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_IDENTIFICATION,
Packit Service 82fcde
				from->copy_name[LC_IDENTIFICATION],
Packit Service 82fcde
				from->repertoire_name, charmap);
Packit Service 82fcde
	  while (from->categories[LC_IDENTIFICATION].identification == NULL
Packit Service 82fcde
		 && from->copy_name[LC_IDENTIFICATION] != NULL);
Packit Service 82fcde
Packit Service 82fcde
	  identification = locale->categories[LC_IDENTIFICATION].identification
Packit Service 82fcde
	    = from->categories[LC_IDENTIFICATION].identification;
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 (identification == NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  record_warning (_("\
Packit Service 82fcde
No definition for %s category found"), "LC_IDENTIFICATION");
Packit Service 82fcde
	  identification_startup (NULL, locale, 0);
Packit Service 82fcde
	  identification
Packit Service 82fcde
	    = locale->categories[LC_IDENTIFICATION].identification;
Packit Service 82fcde
	  nothing = 1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
#define TEST_ELEM(cat) \
Packit Service 82fcde
  if (identification->cat == NULL)					      \
Packit Service 82fcde
    {									      \
Packit Service 82fcde
      if (verbose && ! nothing)						      \
Packit Service 82fcde
	record_warning (_("%s: field `%s' not defined"), "LC_IDENTIFICATION", \
Packit Service 82fcde
			#cat);						      \
Packit Service 82fcde
      identification->cat = "";						      \
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  TEST_ELEM (title);
Packit Service 82fcde
  TEST_ELEM (source);
Packit Service 82fcde
  TEST_ELEM (address);
Packit Service 82fcde
  TEST_ELEM (contact);
Packit Service 82fcde
  TEST_ELEM (email);
Packit Service 82fcde
  TEST_ELEM (tel);
Packit Service 82fcde
  TEST_ELEM (fax);
Packit Service 82fcde
  TEST_ELEM (language);
Packit Service 82fcde
  TEST_ELEM (territory);
Packit Service 82fcde
  TEST_ELEM (audience);
Packit Service 82fcde
  TEST_ELEM (application);
Packit Service 82fcde
  TEST_ELEM (abbreviation);
Packit Service 82fcde
  TEST_ELEM (revision);
Packit Service 82fcde
  TEST_ELEM (date);
Packit Service 82fcde
Packit Service 82fcde
  for (num = 0; num < __LC_LAST; ++num)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* We don't accept/parse this category, so skip it early.  */
Packit Service 82fcde
      if (num == LC_ALL)
Packit Service 82fcde
	continue;
Packit Service 82fcde
Packit Service 82fcde
      if (identification->category[num] == NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (verbose && ! nothing)
Packit Service 82fcde
	    record_warning (_("\
Packit Service 82fcde
%s: no identification for category `%s'"), "LC_IDENTIFICATION",
Packit Service 82fcde
			    category_name[num]);
Packit Service 82fcde
	  identification->category[num] = "";
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Only list the standards we care about.  This is based on the
Packit Service 82fcde
	     ISO 30112 WD10 [2014] standard which supersedes all previous
Packit Service 82fcde
	     revisions of the ISO 14652 standard.  */
Packit Service 82fcde
	  static const char * const standards[] =
Packit Service 82fcde
	    {
Packit Service 82fcde
	      "posix:1993",
Packit Service 82fcde
	      "i18n:2004",
Packit Service 82fcde
	      "i18n:2012",
Packit Service 82fcde
	    };
Packit Service 82fcde
	  size_t i;
Packit Service 82fcde
	  bool matched = false;
Packit Service 82fcde
Packit Service 82fcde
	  for (i = 0; i < sizeof (standards) / sizeof (standards[0]); ++i)
Packit Service 82fcde
	    if (strcmp (identification->category[num], standards[i]) == 0)
Packit Service 82fcde
	      matched = true;
Packit Service 82fcde
Packit Service 82fcde
	  if (matched != true)
Packit Service 82fcde
	    record_error (0, 0, _("\
Packit Service 82fcde
%s: unknown standard `%s' for category `%s'"),
Packit Service 82fcde
			  "LC_IDENTIFICATION",
Packit Service 82fcde
			  identification->category[num],
Packit Service 82fcde
			  category_name[num]);
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
identification_output (struct localedef_t *locale,
Packit Service 82fcde
		       const struct charmap_t *charmap,
Packit Service 82fcde
		       const char *output_path)
Packit Service 82fcde
{
Packit Service 82fcde
  struct locale_identification_t *identification
Packit Service 82fcde
    = locale->categories[LC_IDENTIFICATION].identification;
Packit Service 82fcde
  struct locale_file file;
Packit Service 82fcde
  size_t num;
Packit Service 82fcde
Packit Service 82fcde
  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION));
Packit Service 82fcde
  add_locale_string (&file, identification->title);
Packit Service 82fcde
  add_locale_string (&file, identification->source);
Packit Service 82fcde
  add_locale_string (&file, identification->address);
Packit Service 82fcde
  add_locale_string (&file, identification->contact);
Packit Service 82fcde
  add_locale_string (&file, identification->email);
Packit Service 82fcde
  add_locale_string (&file, identification->tel);
Packit Service 82fcde
  add_locale_string (&file, identification->fax);
Packit Service 82fcde
  add_locale_string (&file, identification->language);
Packit Service 82fcde
  add_locale_string (&file, identification->territory);
Packit Service 82fcde
  add_locale_string (&file, identification->audience);
Packit Service 82fcde
  add_locale_string (&file, identification->application);
Packit Service 82fcde
  add_locale_string (&file, identification->abbreviation);
Packit Service 82fcde
  add_locale_string (&file, identification->revision);
Packit Service 82fcde
  add_locale_string (&file, identification->date);
Packit Service 82fcde
  start_locale_structure (&file;;
Packit Service 82fcde
  for (num = 0; num < __LC_LAST; ++num)
Packit Service 82fcde
    if (num != LC_ALL)
Packit Service 82fcde
      add_locale_string (&file, identification->category[num]);
Packit Service 82fcde
  end_locale_structure (&file;;
Packit Service 82fcde
  add_locale_string (&file, charmap->code_set_name);
Packit Service 82fcde
  write_locale_data (output_path, LC_IDENTIFICATION, "LC_IDENTIFICATION",
Packit Service 82fcde
		     &file;;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* The parser for the LC_IDENTIFICATION section of the locale definition.  */
Packit Service 82fcde
void
Packit Service 82fcde
identification_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 locale_identification_t *identification;
Packit Service 82fcde
  struct token *now;
Packit Service 82fcde
  struct token *arg;
Packit Service 82fcde
  struct token *cattok;
Packit Service 82fcde
  int category;
Packit Service 82fcde
  enum token_t nowtok;
Packit Service 82fcde
Packit Service 82fcde
  /* The rest of the line containing `LC_IDENTIFICATION' must be free.  */
Packit Service 82fcde
  lr_ignore_rest (ldfile, 1);
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,
Packit Service 82fcde
		   tok_lc_identification, LC_IDENTIFICATION,
Packit Service 82fcde
		   "LC_IDENTIFICATION", ignore_content);
Packit Service 82fcde
      return;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Prepare the data structures.  */
Packit Service 82fcde
  identification_startup (ldfile, result, ignore_content);
Packit Service 82fcde
  identification = result->categories[LC_IDENTIFICATION].identification;
Packit Service 82fcde
Packit Service 82fcde
  while (1)
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
	  arg = lr_token (ldfile, charmap, result, NULL, verbose);	      \
Packit Service 82fcde
	  if (arg->tok != tok_string)					      \
Packit Service 82fcde
	    goto err_label;						      \
Packit Service 82fcde
	  if (identification->cat != NULL)				      \
Packit Service 82fcde
	    lr_error (ldfile, _("\
Packit Service 82fcde
%s: field `%s' declared more than once"), "LC_IDENTIFICATION", #cat);	      \
Packit Service 82fcde
	  else if (!ignore_content && arg->val.str.startmb == NULL)	      \
Packit Service 82fcde
	    {								      \
Packit Service 82fcde
	      lr_error (ldfile, _("\
Packit Service 82fcde
%s: unknown character in field `%s'"), "LC_IDENTIFICATION", #cat);	      \
Packit Service 82fcde
	      identification->cat = "";					      \
Packit Service 82fcde
	    }								      \
Packit Service 82fcde
	  else if (!ignore_content)					      \
Packit Service 82fcde
	    identification->cat = arg->val.str.startmb;			      \
Packit Service 82fcde
	  break
Packit Service 82fcde
Packit Service 82fcde
	  STR_ELEM (title);
Packit Service 82fcde
	  STR_ELEM (source);
Packit Service 82fcde
	  STR_ELEM (address);
Packit Service 82fcde
	  STR_ELEM (contact);
Packit Service 82fcde
	  STR_ELEM (email);
Packit Service 82fcde
	  STR_ELEM (tel);
Packit Service 82fcde
	  STR_ELEM (fax);
Packit Service 82fcde
	  STR_ELEM (language);
Packit Service 82fcde
	  STR_ELEM (territory);
Packit Service 82fcde
	  STR_ELEM (audience);
Packit Service 82fcde
	  STR_ELEM (application);
Packit Service 82fcde
	  STR_ELEM (abbreviation);
Packit Service 82fcde
	  STR_ELEM (revision);
Packit Service 82fcde
	  STR_ELEM (date);
Packit Service 82fcde
Packit Service 82fcde
	case tok_category:
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
	  /* We expect two operands.  */
Packit Service 82fcde
	  arg = lr_token (ldfile, charmap, result, NULL, verbose);
Packit Service 82fcde
	  if (arg->tok != tok_string && arg->tok != tok_ident)
Packit Service 82fcde
	    goto err_label;
Packit Service 82fcde
	  /* Next is a semicolon.  */
Packit Service 82fcde
	  cattok = lr_token (ldfile, charmap, result, NULL, verbose);
Packit Service 82fcde
	  if (cattok->tok != tok_semicolon)
Packit Service 82fcde
	    goto err_label;
Packit Service 82fcde
	  /* Now a LC_xxx identifier.  */
Packit Service 82fcde
	  cattok = lr_token (ldfile, charmap, result, NULL, verbose);
Packit Service 82fcde
	  switch (cattok->tok)
Packit Service 82fcde
	    {
Packit Service 82fcde
#define CATEGORY(lname, uname) \
Packit Service 82fcde
	    case tok_lc_##lname:					      \
Packit Service 82fcde
	      category = LC_##uname;					      \
Packit Service 82fcde
	      break
Packit Service 82fcde
Packit Service 82fcde
	      CATEGORY (identification, IDENTIFICATION);
Packit Service 82fcde
	      CATEGORY (ctype, CTYPE);
Packit Service 82fcde
	      CATEGORY (collate, COLLATE);
Packit Service 82fcde
	      CATEGORY (time, TIME);
Packit Service 82fcde
	      CATEGORY (numeric, NUMERIC);
Packit Service 82fcde
	      CATEGORY (monetary, MONETARY);
Packit Service 82fcde
	      CATEGORY (messages, MESSAGES);
Packit Service 82fcde
	      CATEGORY (paper, PAPER);
Packit Service 82fcde
	      CATEGORY (name, NAME);
Packit Service 82fcde
	      CATEGORY (address, ADDRESS);
Packit Service 82fcde
	      CATEGORY (telephone, TELEPHONE);
Packit Service 82fcde
	      CATEGORY (measurement, MEASUREMENT);
Packit Service 82fcde
Packit Service 82fcde
	    default:
Packit Service 82fcde
	      goto err_label;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  if (identification->category[category] != NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      lr_error (ldfile, _("\
Packit Service 82fcde
%s: duplicate category version definition"), "LC_IDENTIFICATION");
Packit Service 82fcde
	      free (arg->val.str.startmb);
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    identification->category[category] = arg->val.str.startmb;
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case tok_end:
Packit Service 82fcde
	  /* Next we assume `LC_IDENTIFICATION'.  */
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"),
Packit Service 82fcde
		      "LC_IDENTIFICATION");
Packit Service 82fcde
	  else if (arg->tok != tok_lc_identification)
Packit Service 82fcde
	    lr_error (ldfile, _("\
Packit Service 82fcde
%1$s: definition does not end with `END %1$s'"), "LC_IDENTIFICATION");
Packit Service 82fcde
	  lr_ignore_rest (ldfile, arg->tok == tok_lc_identification);
Packit Service 82fcde
	  return;
Packit Service 82fcde
Packit Service 82fcde
	default:
Packit Service 82fcde
	err_label:
Packit Service 82fcde
	  SYNTAX_ERROR (_("%s: syntax error"), "LC_IDENTIFICATION");
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_IDENTIFICATION");
Packit Service 82fcde
}