diff options
Diffstat (limited to 'locale/locfile-parse.c')
-rw-r--r-- | locale/locfile-parse.c | 838 |
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: - */ |