summaryrefslogtreecommitdiff
path: root/locale/locfile-parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'locale/locfile-parse.c')
-rw-r--r--locale/locfile-parse.c838
1 files changed, 0 insertions, 838 deletions
diff --git a/locale/locfile-parse.c b/locale/locfile-parse.c
deleted file mode 100644
index daf56bcd45..0000000000
--- a/locale/locfile-parse.c
+++ /dev/null
@@ -1,838 +0,0 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
-
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA. */
-
-#include <errno.h>
-#include <assert.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <limits.h>
-#include <obstack.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
-
-#include "localedef.h"
-#include "localeinfo.h"
-#include "token.h"
-
-/* We don't have these constants defined because we don't use them. Give
- default values. */
-#define CTYPE_MB_CUR_MIN 0
-#define CTYPE_MB_CUR_MAX 0
-#define CTYPE_HASH_SIZE 0
-#define CTYPE_HASH_LAYERS 0
-#define CTYPE_CLASS 0
-#define CTYPE_TOUPPER_EB 0
-#define CTYPE_TOLOWER_EB 0
-#define CTYPE_TOUPPER_EL 0
-#define CTYPE_TOLOWER_EL 0
-
-
-/* We have all categories defined in `categories.def'. Now construct
- the description and data structure used for all categories. */
-#define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
- struct cat_item category##_desc[] = \
- { \
- NO_PAREN items \
- }; \
- \
- char *category##_values[NELEMS (category##_desc) - 1] = { NULL, };
-#include "categories.def"
-#undef DEFINE_CATEGORY
-
-struct category category[] =
- {
-#define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
- [category] = { _NL_NUM_##category, name, NELEMS (category##_desc) - 1, \
- category##_desc, category##_values, in, check, out },
-#include "categories.def"
-#undef DEFINE_CATEGORY
- };
-#define NCATEGORIES NELEMS (category)
-
-
-#define SYNTAX_ERROR \
- error (0, 0, gettext ("%s:%Zd: syntax error in locale definition file"), \
- locfile_data.filename, locfile_data.line_no)
-
-
-/* Prototypes for local functions. */
-static int get_byte (char *byte_ptr);
-static char *is_locale_name (int cat_no, const char *str, int len);
-
-
-/* Read a locale definition file FILE. The format is defined in
- POSIX.2 2.5.3. */
-void
-locfile_read (const char *fname)
-{
- /* Pointer to text of last token. */
- char *ptr;
- /* Length of last token (or if NUMBER the value itself). */
- int len;
- /* The last returned token. */
- int token;
- /* For error correction we remember whether the last token was correct. */
- int correct_token = 1;
-
- /* Open the desired input file on stdin. */
- locfile_open (fname);
-
- while ((token = locfile_lex (&ptr, &len)) != 0)
- {
- int cat_no;
-
- for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
- if (token == category[cat_no].cat_id)
- break;
-
- if (cat_no >= NCATEGORIES)
- /* A syntax error occured. No valid category defintion starts. */
- {
- if (correct_token != 0)
- error (0, 0, gettext ("%s:%Zd: locale category start expected"),
- locfile_data.filename, locfile_data.line_no);
-
- /* To prevent following errors mark as error case. */
- correct_token = 0;
-
- /* Synchronization point is the beginning of a new category.
- Overread all line upto this silently. */
- ignore_to_eol (0, 0);
- continue;
- }
-
- /* Rest of the line should be empty. */
- ignore_to_eol (0, 1);
-
- /* Perhaps these category is already specified. We simply give a
- warning and overwrite the values. */
- if (category[cat_no].filled != 0)
- error (0, 0, gettext ("%s:%Zd: multiple definition of locale "
- "category %s"), locfile_data.filename,
- locfile_data.line_no, category[cat_no].name);
-
- /* We read the first token because this could be the copy statement. */
- token = xlocfile_lex (&ptr, &len);
-
- if (token == TOK_COPY)
- /* Copying the definitions from an existing locale is requested. */
- {
- char *str;
-
- /* Get the name of the locale to copy from. */
- token = xlocfile_lex (&ptr, &len);
- if (token != TOK_IDENT && token != TOK_STRING)
- /* No name, then mark error and ignore everything upto next
- start of an category section. */
- {
- /* To prevent following errors mark as error case. */
- correct_token = 0;
-
- /* Synchronization point is the beginning of a new category.
- Overread all line upto this silently. */
- ignore_to_eol (0, 0);
- }
- else if ((str = is_locale_name (cat_no, ptr, len)) != NULL)
- /* Yes the name really names an existing locale file. We are
- returned the complete file name. Store it so that we can
- copy it in the output phase. */
- {
- category[cat_no].copy_locale = str;
- category[cat_no].filled = 1;
-
- ignore_to_eol (0, 1);
- }
- else
- /* No, the name does not address a valid locale file. Mark
- error case and ignore rest of category. */
- {
- char tmp[len + 1];
- memcpy (tmp, ptr, len);
- tmp[len] = '\0';
- error (0, 0, gettext ("%s:%Zd: invalid locale `%s' in copy "
- "statement"), locfile_data.filename,
- locfile_data.line_no, tmp);
- correct_token = 0;
- ignore_to_eol (0, 0);
- }
-
- /* This should END as the next token. */
- token = xlocfile_lex (&ptr, &len);
-
- if (token == TOK_END)
- /* This is the end of the category. */
- {
- token = xlocfile_lex (&ptr, &len);
-
- if (token != category[cat_no].cat_id)
- /* Wrong category name after END. */
- {
- error (0, 0, gettext ("%s:%Zd: category `%s' does not "
- "end with `END %s'"),
- locfile_data.filename, locfile_data.line_no,
- category[cat_no].name, category[cat_no].name);
- ignore_to_eol (0, 0);
- }
- else
- ignore_to_eol (0, 1);
-
- correct_token = 1;
- }
- else
- /* No END following copy. Give error while not in error case. */
- {
- if (correct_token != 0)
- error (0, 0, gettext ("%s:%Zd: `copy' must be sole rule"),
- locfile_data.filename, locfile_data.line_no);
- correct_token = 0;
- ignore_to_eol (0, 0);
- }
-
- continue;
- }
-
- /* Now it's time to mark as mentioned in the locale file. */
- category[cat_no].filled = 1;
-
- if (category[cat_no].infct != NULL)
- /* The category needs a special input handling. */
- {
- category[cat_no].infct(token);
- continue;
- }
-
- /* Now process the given items. */
- while (1)
- {
- int item_no;
-
- if (token == TOK_END)
- /* This is the end of the category. */
- {
- token = xlocfile_lex (&ptr, &len);
-
- if (token != category[cat_no].cat_id)
- {
- error (0, 0, gettext ("%s:%Zd: category `%s' does not end "
- "with `END %s'"),
- locfile_data.filename, locfile_data.line_no,
- category[cat_no].name, category[cat_no].name);
- ignore_to_eol (0, 0);
- }
- else
- ignore_to_eol (0, 1);
-
- /* Start next category. */
- break;
- }
-
- /* All other lines should describe valid items of the category. */
- for (item_no = 0; item_no < category[cat_no].number; ++item_no)
- if (category[cat_no].item_desc[item_no].item_id == token)
- break;
-
- if (item_no >= category[cat_no].number)
- /* This is not a valid item of the category. */
- {
- SYNTAX_ERROR;
- ignore_to_eol (0, 0);
-
- token = xlocfile_lex (&ptr, &len);
-
- /* And process next item. */
- continue;
- }
-
- /* Test whether already a value is defined. */
- if (category[cat_no].item_value[item_no] != NULL)
- error (0, 0, gettext ("%s:%Zd: category item `%s' already "
- "defined"),
- locfile_data.filename, locfile_data.line_no,
- category[cat_no].item_desc[item_no].name);
-
- switch (category[cat_no].item_desc[item_no].value_type)
- {
- case string:
- /* Get next token. This is the argument to the item. */
- token = xlocfile_lex (&ptr, &len);
-
- if (token != TOK_STRING)
- SYNTAX_ERROR;
- else
- category[cat_no].item_value[item_no] = strdup (ptr);
- ignore_to_eol (0, ptr != NULL);
- break;
- case stringarray:
- /* This is a difficult case. The number of strings in
- the array may vary. But for now its only necessary
- with ALT_DIGITS from LC_TIME. This item is the last
- so be can solve it by storing the number of string in
- the first place and the string indeces following
- that. */
- {
- int cnt;
- char **buffer;
- if (category[cat_no].item_value[item_no] != NULL)
- buffer = (char **) category[cat_no].item_value[item_no];
- else
- buffer = (char **) xmalloc (
- sizeof (char *) * category[cat_no].item_desc[item_no].max);
-
- category[cat_no].item_value[item_no] = (char *) buffer;
-
- /* As explained we may need a place to store the real number
- of strings. */
- if (category[cat_no].item_desc[item_no].min
- != category[cat_no].item_desc[item_no].max)
- ++buffer;
-
- cnt = 0;
- do
- {
- token = xlocfile_lex (&ptr, &len);
- if (token != TOK_STRING)
- {
- SYNTAX_ERROR;
- break;
- }
-
- if (cnt >= category[cat_no].item_desc[item_no].max)
- {
- error (0, 0, gettext ("%s:%Zd: too many elements "
- "for item `%s`"),
- locfile_data.filename, locfile_data.line_no,
- category[cat_no].item_desc[item_no].name);
- break;
- }
-
- buffer[cnt++] = strdup (ptr);
-
- token = locfile_lex (&ptr, &len);
- }
- while (token == TOK_CHAR && len == ';');
-
- ignore_to_eol (token, ptr != NULL);
-
- if (cnt < category[cat_no].item_desc[item_no].min)
- error (0, 0, gettext ("%s:%Zd: too few elements for item "
- "`%s'"),
- locfile_data.filename, locfile_data.line_no,
- category[cat_no].item_desc[item_no].name);
-
- if (category[cat_no].item_desc[item_no].min
- != category[cat_no].item_desc[item_no].max)
- *(int *) category[cat_no].item_value[item_no] = cnt;
- }
- break;
- case byte:
- {
- int ok;
- category[cat_no].item_value[item_no] = (char *) xmalloc (
- __alignof__ (char));
- ok = get_byte (category[cat_no].item_value[item_no]);
- ignore_to_eol (0, ok);
- }
- break;
- case bytearray:
- {
- char *buffer;
- int maxsize;
- int cnt;
- char byte;
- int ok;
-
- buffer = (char *) xmalloc ((maxsize = 30));
- cnt = 0;
-
- while ((ok = get_byte (&byte)))
- {
- if (cnt >= maxsize)
- buffer = (char *) xmalloc ((maxsize *= 2));
-
- buffer[cnt++] = byte;
-
- token = locfile_lex (&ptr, &len);
- if (token != TOK_CHAR || len != ';')
- break;
- }
-
- buffer[cnt] = '\0';
- category[cat_no].item_value[item_no] = buffer;
- ignore_to_eol (token, ok);
- }
- break;
- default:
- error (5, 0, gettext ("internal error in %s, line %u"),
- __FUNCTION__, __LINE__);
- /* NOTREACHED */
- }
-
- /* Get next token. */
- token = xlocfile_lex (&ptr, &len);
- } /* while (1) */
- }
-}
-
-
-/* Check given values for categories for consistency. */
-void
-categories_check (void)
-{
- int cat_no;
-
- for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
- if (category[cat_no].copy_locale == NULL)
- if (category[cat_no].filled != 0)
- if (category[cat_no].checkfct)
- category[cat_no].checkfct();
- else
- {
- int item_no;
-
- for (item_no = 0; item_no < category[cat_no].number; ++item_no)
- if (category[cat_no].item_value[item_no] == NULL)
- {
- int errcode;
-
- /* If the item is defined in the standard is it an error to
- have it not defined. */
- errcode = category[cat_no].item_desc[item_no].status == std
- ? 5 : 0;
-
- error (errcode, 0, gettext ("item `%s' of category `%s' "
- "undefined"),
- category[cat_no].item_desc[item_no].name,
- category[cat_no].name);
- }
- }
- else
- error (0, 0, gettext ("category `%s' not defined"),
- category[cat_no].name);
-}
-
-
-/* Write out the binary representation of the category data which can be
- loaded by setlocale(1). */
-void
-categories_write (void)
-{
- struct locale_file
- {
- int magic;
- int n;
- int idx[0];
- } *data;
- struct obstack obstk;
- int cat_no;
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
- obstack_init (&obstk);
-
- for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
- {
- int result = 0;
-
- if (category[cat_no].copy_locale != NULL)
- /* Simply copy the addressed locale file of the specified
- category. Please note that this is tried before the distinction
- between categories which need special handling is made. */
- {
- int source;
-
- /* Open source file. */
- source = open (category[cat_no].copy_locale, O_RDONLY);
- if (source < 0)
- error (0, 0, gettext ("cannot copy locale definition file `%s'"),
- category[cat_no].copy_locale);
- else
- {
- /* Construct file name of output file and open for writing. */
- char path[strlen (output_path)
- + strlen(category[cat_no].name) + 1];
- int dest;
- char *t;
-
- t = stpcpy (path, output_path);
- strcpy (t, category[cat_no].name);
-
- dest = creat (path, 0666);
- if (dest == -1)
- error (0, 0, gettext ("cannot open output file `%s': %m"),
- path);
- else
- {
- char buffer[BUFSIZ];
- int size;
-
- /* Copy the files. */
- do
- {
- size = read (source, buffer, BUFSIZ);
- write (dest, buffer, size);
- }
- while (size > 0);
-
- close (dest);
-
- /* Show success. */
- puts (category[cat_no].name);
- }
- close (source);
- }
-
- /* Next category. */
- continue;
- }
-
- if (category[cat_no].outfct)
- result = category[cat_no].outfct();
- else
- {
- char *path, *t;
- int fd;
- struct iovec *iov;
- int item_no, len, slen, cnt;
- int elems = 0;
-
- /* Count number of elements. */
- for (item_no = 0; item_no < category[cat_no].number; ++item_no)
- {
- switch (category[cat_no].item_desc[item_no].value_type)
- {
- case string:
- case byte:
- case bytearray:
- ++elems;
- break;
- case stringarray:
- elems += category[cat_no].item_desc[item_no].max;
- break;
- default:
- error (5, 0, gettext ("internal error in %s, line %u"),
- __FUNCTION__, __LINE__);
- /* NOTREACHED */
- }
- }
-
- /* We now have the number of elements. We build the structure
- and a helper structure for writing all out. */
- len = sizeof (struct locale_file) + elems * sizeof (int);
- data = obstack_alloc (&obstk, len);
- iov = obstack_alloc (&obstk, (elems + 1) * sizeof (struct iovec));
-
- data->magic = LIMAGIC (cat_no);
- data->n = elems;
- iov[0].iov_base = data;
- iov[0].iov_len = len;
-
- cnt = 0;
- for (item_no = 0; item_no < category[cat_no].number; ++item_no)
- if (category[cat_no].item_value[item_no] == NULL)
- {
- switch (category[cat_no].item_desc[item_no].value_type)
- {
- case string:
- case byte:
- case bytearray:
- data->idx[cnt] = len;
- ++len; /* We reserve one single byte for this entry. */
- iov[1 + cnt].iov_base = (char *) "";
- iov[1 + cnt].iov_len = 1;
- ++cnt;
- break;
- case stringarray:
- {
- int max;
- int nstr;
-
- max = category[cat_no].item_desc[item_no].max;
-
- for (nstr = 0; nstr < max; ++nstr)
- {
- data->idx[cnt] = len;
- ++len;
- iov[1 + cnt].iov_base = (char *) "";
- iov[1 + cnt].iov_len = 1;
- ++cnt;
- }
- }
- }
- }
- else
- switch (category[cat_no].item_desc[item_no].value_type)
- {
- case string:
- case bytearray:
- data->idx[cnt] = len;
- slen = strlen (category[cat_no].item_value[item_no]) + 1;
- len += slen;
- iov[1 + cnt].iov_base = category[cat_no].item_value[item_no];
- iov[1 + cnt].iov_len = slen;
- ++cnt;
- break;
- case byte:
- data->idx[cnt] = len;
- slen = 1;
- len += slen;
- iov[1 + cnt].iov_base = category[cat_no].item_value[item_no];
- iov[1 + cnt].iov_len = slen;
- ++cnt;
- break;
- case stringarray:
- {
- int nstr, nact;
- char **first;
-
- if (category[cat_no].item_desc[item_no].min
- == category[cat_no].item_desc[item_no].max)
- {
- nstr = category[cat_no].item_desc[item_no].min;
- first = (char **) category[cat_no].item_value[item_no];
- }
- else
- {
- nstr = *(int *) category[cat_no].item_value[item_no];
- first =
- ((char **) category[cat_no].item_value[item_no]) + 1;
- }
- nact = nstr;
- while (nstr > 0)
- {
- data->idx[cnt] = len;
- if (*first != NULL)
- {
- slen = strlen (*first) + 1;
- iov[1 + cnt].iov_base = *first;
- }
- else
- {
- slen = 1;
- iov[1 + cnt].iov_base = (char *) "";
- }
- len += slen;
- iov[1 + cnt].iov_len = slen;
- ++cnt;
- ++first;
- --nstr;
- }
- while (nact < category[cat_no].item_desc[item_no].max)
- {
- data->idx[cnt] = len;
- len += 1;
- iov[1 + cnt].iov_base = (char *) "";
- iov[1 + cnt].iov_len = 1;
- ++cnt;
- ++nact;
- }
- }
- break;
- default:
- /* Cannot happen. */
- break;
- }
- assert (cnt <= elems);
-
- /* Construct the output filename from the argument given to
- localedef on the command line. */
- path = (char *) obstack_alloc (&obstk, strlen (output_path) +
- 2 * strlen (category[cat_no].name) + 5);
- t = stpcpy (path, output_path);
- strcpy (t, category[cat_no].name);
-
- fd = creat (path, 0666);
-
- if (fd == -1)
- {
- /* Check whether it failed because the named file is a directory.
- In that case we use the file .../LC_xxx/SYS_LC_xxx, as the
- loading functions of the C Library do. */
- struct stat st;
-
- if (stat (path, &st) == 0 && S_ISDIR (st.st_mode))
- {
- stpcpy (stpcpy (strchr (path, '\0'), "/SYS_"),
- category[cat_no].name);
- fd = creat (path, 0666);
- }
- }
-
- if (fd == -1)
- {
- error (0, 0, gettext ("cannot open output file `%s': %m"),
- path);
- result = 1;
- }
- else
- {
- if (writev (fd, iov, cnt + 1) == -1)
- {
- error (0, 0, gettext ("cannot write output file `%s': %m"),
- path);
- result = 1;
- }
-
-if (elems==0) write(fd, &elems, 10);
-
- close (fd);
- }
- /* The old data is not needed anymore, but keep the obstack
- intact. */
- obstack_free (&obstk, data);
- }
-
- if (result == 0)
- puts (category[cat_no].name);
- }
- /* Now the whole obstack can be removed. */
- obstack_free (&obstk, NULL);
-}
-
-
-/* Get the representation of a number. This is a positive integer or
- the number -1 which is handled as a special symbol by the scanner. */
-static int
-get_byte (char *byte_ptr)
-{
- int token;
- char *ptr;
- int len;
-
- token = locfile_lex (&ptr, &len);
- if (token != TOK_NUMBER && token != TOK_MINUS1)
- /* None of the valid number format. */
- {
- error (0, 0, gettext ("%s:%Zd: number expected"),
- locfile_data.filename, locfile_data.line_no);
- *byte_ptr = 0;
- return 0;
- }
-
- if (token == TOK_MINUS1)
- {
- *byte_ptr = CHAR_MAX;
- return 1;
- }
-
- if (len > CHAR_MAX)
- /* The value of the numbers has to be less than CHAR_MAX. This is
- ok for the information they have to express. */
- {
- error (0, 0, gettext ("%s:%Zd: invalid number"),
- locfile_data.filename, locfile_data.line_no);
- *byte_ptr = 0;
- return 0;
- }
-
- *byte_ptr = len;
- return 1;
-}
-
-
-/* Test whether the string STR with length LEN is the name of an existing
- locale and whether a file for category CAT_NO is found in this directory.
- This categories are looked for in the system locale definition file
- directory.
- Return the complete file name for the category file. */
-static char *
-is_locale_name (int cat_no, const char *str, int len)
-{
- static char **locale_names = NULL;
- static int max_count = 0;
- static int locale_count = 0;
- int cnt, exist, fd;
- char *fname;
- struct stat st;
-
- if (locale_names == NULL)
- /* Read in the list of all available locales. */
- {
- DIR *dir;
- struct dirent *dirent;
-
- /* LOCALE_NAMES is not NULL anymore, but LOCALE_COUNT == 0. */
- ++locale_names;
-
- dir = opendir (LOCALE_PATH);
- if (dir == NULL)
- {
- error (1, errno, gettext ("cannot read locale directory `%s'"),
- LOCALE_PATH);
-
- return NULL;
- }
-
- /* Now we can look for all files in the directory. */
- while ((dirent = readdir (dir)) != NULL)
- if (strcmp (dirent->d_name, ".") != 0
- && strcmp (dirent->d_name, "..") != 0)
- {
- if (max_count == 0)
- locale_names = (char **) xmalloc ((max_count = 10)
- * sizeof (char *));
- else if (locale_count >= max_count)
- locale_names = (char **) xrealloc (locale_names,
- (max_count *= 2)
- * sizeof (char *));
- locale_names[locale_count++] = strdup (dirent->d_name);
- }
- closedir (dir);
- }
-
- for (cnt = 0; cnt < locale_count; ++cnt)
- if (strncmp (str, locale_names[cnt], len) == 0
- && locale_names[cnt][len] == '\0')
- break;
-
- if (cnt >= locale_count)
- return NULL;
-
- /* Now search for this specific locale file. */
- asprintf (&fname, "%s/%s/%s", LOCALE_PATH, locale_names[cnt],
- category[cat_no].name);
-
- fd = open (fname, O_RDONLY);
- if (fd < 0)
- {
- free (fname);
- return NULL;
- }
-
- exist = fstat (fd, &st);
- close (fd);
-
- if (exist < 0)
- {
- free (fname);
- return NULL;
- }
-
- return fname;
-}
-
-/*
- * Local Variables:
- * mode:c
- * c-basic-offset:2
- * End:
- */