Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
38163d9a
Commit
38163d9a
authored
Apr 27, 1998
by
Jeff Law
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial revision
From-SVN: r19445
parent
ee6d4817
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
624 additions
and
0 deletions
+624
-0
gcc/intl/dcgettext.c
+624
-0
No files found.
gcc/intl/dcgettext.c
0 → 100644
View file @
38163d9a
/* Implementation of the dcgettext(3) function.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#ifdef __GNUC__
# define alloca __builtin_alloca
# define HAVE_ALLOCA 1
#else
# if defined HAVE_ALLOCA_H || defined _LIBC
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca
char
*
alloca
();
# endif
# endif
# endif
#endif
#include <errno.h>
#ifndef errno
extern
int
errno
;
#endif
#ifndef __set_errno
# define __set_errno(val) errno = (val)
#endif
#if defined STDC_HEADERS || defined _LIBC
# include <stdlib.h>
#else
char
*
getenv
();
# ifdef HAVE_MALLOC_H
# include <malloc.h>
# else
void
free
();
# endif
#endif
#if defined HAVE_STRING_H || defined _LIBC
# ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
# endif
# include <string.h>
#else
# include <strings.h>
#endif
#if !HAVE_STRCHR && !defined _LIBC
# ifndef strchr
# define strchr index
# endif
#endif
#if defined HAVE_UNISTD_H || defined _LIBC
# include <unistd.h>
#endif
#include "gettext.h"
#include "gettextP.h"
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgettext.h"
#endif
#include "hash-string.h"
/* @@ end of prolog @@ */
#ifdef _LIBC
/* Rename the non ANSI C functions. This is required by the standard
because some ANSI C functions will require linking with this object
file and the name space must not be polluted. */
# define getcwd __getcwd
# ifndef stpcpy
# define stpcpy __stpcpy
# endif
#else
# if !defined HAVE_GETCWD
char
*
getwd
();
# define getcwd(buf, max) getwd (buf)
# else
char
*
getcwd
();
# endif
# ifndef HAVE_STPCPY
static
char
*
stpcpy
PARAMS
((
char
*
dest
,
const
char
*
src
));
# endif
#endif
/* Amount to increase buffer size by in each try. */
#define PATH_INCR 32
/* The following is from pathmax.h. */
/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
PATH_MAX but might cause redefinition warnings when sys/param.h is
later included (as on MORE/BSD 4.3). */
#if defined(_POSIX_VERSION) || (defined(HAVE_LIMITS_H) && !defined(__GNUC__))
# include <limits.h>
#endif
#ifndef _POSIX_PATH_MAX
# define _POSIX_PATH_MAX 255
#endif
#if !defined(PATH_MAX) && defined(_PC_PATH_MAX)
# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
#endif
/* Don't include sys/param.h if it already has been. */
#if defined(HAVE_SYS_PARAM_H) && !defined(PATH_MAX) && !defined(MAXPATHLEN)
# include <sys/param.h>
#endif
#if !defined(PATH_MAX) && defined(MAXPATHLEN)
# define PATH_MAX MAXPATHLEN
#endif
#ifndef PATH_MAX
# define PATH_MAX _POSIX_PATH_MAX
#endif
/* XPG3 defines the result of `setlocale (category, NULL)' as:
``Directs `setlocale()' to query `category' and return the current
setting of `local'.''
However it does not specify the exact format. And even worse: POSIX
defines this not at all. So we can use this feature only on selected
system (e.g. those using GNU C Library). */
#ifdef _LIBC
# define HAVE_LOCALE_NULL
#endif
/* Name of the default domain used for gettext(3) prior any call to
textdomain(3). The default value for this is "messages". */
const
char
_nl_default_default_domain
[]
=
"messages"
;
/* Value used as the default domain for gettext(3). */
const
char
*
_nl_current_default_domain
=
_nl_default_default_domain
;
/* Contains the default location of the message catalogs. */
const
char
_nl_default_dirname
[]
=
GNULOCALEDIR
;
/* List with bindings of specific domains created by bindtextdomain()
calls. */
struct
binding
*
_nl_domain_bindings
;
/* Prototypes for local functions. */
static
char
*
find_msg
PARAMS
((
struct
loaded_l10nfile
*
domain_file
,
const
char
*
msgid
))
internal_function
;
static
const
char
*
category_to_name
PARAMS
((
int
category
))
internal_function
;
static
const
char
*
guess_category_value
PARAMS
((
int
category
,
const
char
*
categoryname
))
internal_function
;
/* For those loosing systems which don't have `alloca' we have to add
some additional code emulating it. */
#ifdef HAVE_ALLOCA
/* Nothing has to be done. */
# define ADD_BLOCK(list, address)
/* nothing */
# define FREE_BLOCKS(list)
/* nothing */
#else
struct
block_list
{
void
*
address
;
struct
block_list
*
next
;
};
# define ADD_BLOCK(list, addr) \
do { \
struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
/* If we cannot get a free block we cannot add the new element to \
the list. */
\
if (newp != NULL) { \
newp->address = (addr); \
newp->next = (list); \
(list) = newp; \
} \
} while (0)
# define FREE_BLOCKS(list) \
do { \
while (list != NULL) { \
struct block_list *old = list; \
list = list->next; \
free (old); \
} \
} while (0)
# undef alloca
# define alloca(size) (malloc (size))
#endif
/* have alloca */
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define DCGETTEXT __dcgettext
#else
# define DCGETTEXT dcgettext__
#endif
/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
locale. */
char
*
DCGETTEXT
(
domainname
,
msgid
,
category
)
const
char
*
domainname
;
const
char
*
msgid
;
int
category
;
{
#ifndef HAVE_ALLOCA
struct
block_list
*
block_list
=
NULL
;
#endif
struct
loaded_l10nfile
*
domain
;
struct
binding
*
binding
;
const
char
*
categoryname
;
const
char
*
categoryvalue
;
char
*
dirname
,
*
xdomainname
;
char
*
single_locale
;
char
*
retval
;
int
saved_errno
=
errno
;
/* If no real MSGID is given return NULL. */
if
(
msgid
==
NULL
)
return
NULL
;
/* If DOMAINNAME is NULL, we are interested in the default domain. If
CATEGORY is not LC_MESSAGES this might not make much sense but the
defintion left this undefined. */
if
(
domainname
==
NULL
)
domainname
=
_nl_current_default_domain
;
/* First find matching binding. */
for
(
binding
=
_nl_domain_bindings
;
binding
!=
NULL
;
binding
=
binding
->
next
)
{
int
compare
=
strcmp
(
domainname
,
binding
->
domainname
);
if
(
compare
==
0
)
/* We found it! */
break
;
if
(
compare
<
0
)
{
/* It is not in the list. */
binding
=
NULL
;
break
;
}
}
if
(
binding
==
NULL
)
dirname
=
(
char
*
)
_nl_default_dirname
;
else
if
(
binding
->
dirname
[
0
]
==
'/'
)
dirname
=
binding
->
dirname
;
else
{
/* We have a relative path. Make it absolute now. */
size_t
dirname_len
=
strlen
(
binding
->
dirname
)
+
1
;
size_t
path_max
;
char
*
ret
;
path_max
=
(
unsigned
)
PATH_MAX
;
path_max
+=
2
;
/* The getcwd docs say to do this. */
dirname
=
(
char
*
)
alloca
(
path_max
+
dirname_len
);
ADD_BLOCK
(
block_list
,
dirname
);
__set_errno
(
0
);
while
((
ret
=
getcwd
(
dirname
,
path_max
))
==
NULL
&&
errno
==
ERANGE
)
{
path_max
+=
PATH_INCR
;
dirname
=
(
char
*
)
alloca
(
path_max
+
dirname_len
);
ADD_BLOCK
(
block_list
,
dirname
);
__set_errno
(
0
);
}
if
(
ret
==
NULL
)
{
/* We cannot get the current working directory. Don't signal an
error but simply return the default string. */
FREE_BLOCKS
(
block_list
);
__set_errno
(
saved_errno
);
return
(
char
*
)
msgid
;
}
stpcpy
(
stpcpy
(
strchr
(
dirname
,
'\0'
),
"/"
),
binding
->
dirname
);
}
/* Now determine the symbolic name of CATEGORY and its value. */
categoryname
=
category_to_name
(
category
);
categoryvalue
=
guess_category_value
(
category
,
categoryname
);
xdomainname
=
(
char
*
)
alloca
(
strlen
(
categoryname
)
+
strlen
(
domainname
)
+
5
);
ADD_BLOCK
(
block_list
,
xdomainname
);
stpcpy
(
stpcpy
(
stpcpy
(
stpcpy
(
xdomainname
,
categoryname
),
"/"
),
domainname
),
".mo"
);
/* Creating working area. */
single_locale
=
(
char
*
)
alloca
(
strlen
(
categoryvalue
)
+
1
);
ADD_BLOCK
(
block_list
,
single_locale
);
/* Search for the given string. This is a loop because we perhaps
got an ordered list of languages to consider for th translation. */
while
(
1
)
{
/* Make CATEGORYVALUE point to the next element of the list. */
while
(
categoryvalue
[
0
]
!=
'\0'
&&
categoryvalue
[
0
]
==
':'
)
++
categoryvalue
;
if
(
categoryvalue
[
0
]
==
'\0'
)
{
/* The whole contents of CATEGORYVALUE has been searched but
no valid entry has been found. We solve this situation
by implicitly appending a "C" entry, i.e. no translation
will take place. */
single_locale
[
0
]
=
'C'
;
single_locale
[
1
]
=
'\0'
;
}
else
{
char
*
cp
=
single_locale
;
while
(
categoryvalue
[
0
]
!=
'\0'
&&
categoryvalue
[
0
]
!=
':'
)
*
cp
++
=
*
categoryvalue
++
;
*
cp
=
'\0'
;
}
/* If the current locale value is C (or POSIX) we don't load a
domain. Return the MSGID. */
if
(
strcmp
(
single_locale
,
"C"
)
==
0
||
strcmp
(
single_locale
,
"POSIX"
)
==
0
)
{
FREE_BLOCKS
(
block_list
);
__set_errno
(
saved_errno
);
return
(
char
*
)
msgid
;
}
/* Find structure describing the message catalog matching the
DOMAINNAME and CATEGORY. */
domain
=
_nl_find_domain
(
dirname
,
single_locale
,
xdomainname
);
if
(
domain
!=
NULL
)
{
retval
=
find_msg
(
domain
,
msgid
);
if
(
retval
==
NULL
)
{
int
cnt
;
for
(
cnt
=
0
;
domain
->
successor
[
cnt
]
!=
NULL
;
++
cnt
)
{
retval
=
find_msg
(
domain
->
successor
[
cnt
],
msgid
);
if
(
retval
!=
NULL
)
break
;
}
}
if
(
retval
!=
NULL
)
{
FREE_BLOCKS
(
block_list
);
__set_errno
(
saved_errno
);
return
retval
;
}
}
}
/* NOTREACHED */
}
#ifdef _LIBC
/* Alias for function name in GNU C Library. */
weak_alias
(
__dcgettext
,
dcgettext
);
#endif
static
char
*
internal_function
find_msg
(
domain_file
,
msgid
)
struct
loaded_l10nfile
*
domain_file
;
const
char
*
msgid
;
{
size_t
top
,
act
,
bottom
;
struct
loaded_domain
*
domain
;
if
(
domain_file
->
decided
==
0
)
_nl_load_domain
(
domain_file
);
if
(
domain_file
->
data
==
NULL
)
return
NULL
;
domain
=
(
struct
loaded_domain
*
)
domain_file
->
data
;
/* Locate the MSGID and its translation. */
if
(
domain
->
hash_size
>
2
&&
domain
->
hash_tab
!=
NULL
)
{
/* Use the hashing table. */
nls_uint32
len
=
strlen
(
msgid
);
nls_uint32
hash_val
=
hash_string
(
msgid
);
nls_uint32
idx
=
hash_val
%
domain
->
hash_size
;
nls_uint32
incr
=
1
+
(
hash_val
%
(
domain
->
hash_size
-
2
));
nls_uint32
nstr
=
W
(
domain
->
must_swap
,
domain
->
hash_tab
[
idx
]);
if
(
nstr
==
0
)
/* Hash table entry is empty. */
return
NULL
;
if
(
W
(
domain
->
must_swap
,
domain
->
orig_tab
[
nstr
-
1
].
length
)
==
len
&&
strcmp
(
msgid
,
domain
->
data
+
W
(
domain
->
must_swap
,
domain
->
orig_tab
[
nstr
-
1
].
offset
))
==
0
)
return
(
char
*
)
domain
->
data
+
W
(
domain
->
must_swap
,
domain
->
trans_tab
[
nstr
-
1
].
offset
);
while
(
1
)
{
if
(
idx
>=
domain
->
hash_size
-
incr
)
idx
-=
domain
->
hash_size
-
incr
;
else
idx
+=
incr
;
nstr
=
W
(
domain
->
must_swap
,
domain
->
hash_tab
[
idx
]);
if
(
nstr
==
0
)
/* Hash table entry is empty. */
return
NULL
;
if
(
W
(
domain
->
must_swap
,
domain
->
orig_tab
[
nstr
-
1
].
length
)
==
len
&&
strcmp
(
msgid
,
domain
->
data
+
W
(
domain
->
must_swap
,
domain
->
orig_tab
[
nstr
-
1
].
offset
))
==
0
)
return
(
char
*
)
domain
->
data
+
W
(
domain
->
must_swap
,
domain
->
trans_tab
[
nstr
-
1
].
offset
);
}
/* NOTREACHED */
}
/* Now we try the default method: binary search in the sorted
array of messages. */
bottom
=
0
;
top
=
domain
->
nstrings
;
while
(
bottom
<
top
)
{
int
cmp_val
;
act
=
(
bottom
+
top
)
/
2
;
cmp_val
=
strcmp
(
msgid
,
domain
->
data
+
W
(
domain
->
must_swap
,
domain
->
orig_tab
[
act
].
offset
));
if
(
cmp_val
<
0
)
top
=
act
;
else
if
(
cmp_val
>
0
)
bottom
=
act
+
1
;
else
break
;
}
/* If an translation is found return this. */
return
bottom
>=
top
?
NULL
:
(
char
*
)
domain
->
data
+
W
(
domain
->
must_swap
,
domain
->
trans_tab
[
act
].
offset
);
}
/* Return string representation of locale CATEGORY. */
static
const
char
*
internal_function
category_to_name
(
category
)
int
category
;
{
const
char
*
retval
;
switch
(
category
)
{
#ifdef LC_COLLATE
case
LC_COLLATE
:
retval
=
"LC_COLLATE"
;
break
;
#endif
#ifdef LC_CTYPE
case
LC_CTYPE
:
retval
=
"LC_CTYPE"
;
break
;
#endif
#ifdef LC_MONETARY
case
LC_MONETARY
:
retval
=
"LC_MONETARY"
;
break
;
#endif
#ifdef LC_NUMERIC
case
LC_NUMERIC
:
retval
=
"LC_NUMERIC"
;
break
;
#endif
#ifdef LC_TIME
case
LC_TIME
:
retval
=
"LC_TIME"
;
break
;
#endif
#ifdef LC_MESSAGES
case
LC_MESSAGES
:
retval
=
"LC_MESSAGES"
;
break
;
#endif
#ifdef LC_RESPONSE
case
LC_RESPONSE
:
retval
=
"LC_RESPONSE"
;
break
;
#endif
#ifdef LC_ALL
case
LC_ALL
:
/* This might not make sense but is perhaps better than any other
value. */
retval
=
"LC_ALL"
;
break
;
#endif
default
:
/* If you have a better idea for a default value let me know. */
retval
=
"LC_XXX"
;
}
return
retval
;
}
/* Guess value of current locale from value of the environment variables. */
static
const
char
*
internal_function
guess_category_value
(
category
,
categoryname
)
int
category
;
const
char
*
categoryname
;
{
const
char
*
retval
;
/* The highest priority value is the `LANGUAGE' environment
variable. This is a GNU extension. */
retval
=
getenv
(
"LANGUAGE"
);
if
(
retval
!=
NULL
&&
retval
[
0
]
!=
'\0'
)
return
retval
;
/* `LANGUAGE' is not set. So we have to proceed with the POSIX
methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some
systems this can be done by the `setlocale' function itself. */
#if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
return
setlocale
(
category
,
NULL
);
#else
/* Setting of LC_ALL overwrites all other. */
retval
=
getenv
(
"LC_ALL"
);
if
(
retval
!=
NULL
&&
retval
[
0
]
!=
'\0'
)
return
retval
;
/* Next comes the name of the desired category. */
retval
=
getenv
(
categoryname
);
if
(
retval
!=
NULL
&&
retval
[
0
]
!=
'\0'
)
return
retval
;
/* Last possibility is the LANG environment variable. */
retval
=
getenv
(
"LANG"
);
if
(
retval
!=
NULL
&&
retval
[
0
]
!=
'\0'
)
return
retval
;
/* We use C as the default domain. POSIX says this is implementation
defined. */
return
"C"
;
#endif
}
/* @@ begin of epilog @@ */
/* We don't want libintl.a to depend on any other library. So we
avoid the non-standard function stpcpy. In GNU C Library this
function is available, though. Also allow the symbol HAVE_STPCPY
to be defined. */
#if !_LIBC && !HAVE_STPCPY
static
char
*
stpcpy
(
dest
,
src
)
char
*
dest
;
const
char
*
src
;
{
while
((
*
dest
++
=
*
src
++
)
!=
'\0'
)
/* Do nothing. */
;
return
dest
-
1
;
}
#endif
#ifdef _LIBC
/* If we want to free all resources we have to do some work at
program's end. */
static
void
__attribute__
((
unused
))
free_mem
(
void
)
{
struct
binding
*
runp
;
for
(
runp
=
_nl_domain_bindings
;
runp
!=
NULL
;
runp
=
runp
->
next
)
{
free
(
runp
->
domainname
);
if
(
runp
->
dirname
!=
_nl_default_dirname
)
/* Yes, this is a pointer comparison. */
free
(
runp
->
dirname
);
}
if
(
_nl_current_default_domain
!=
_nl_default_default_domain
)
/* Yes, again a pointer comparison. */
free
((
char
*
)
_nl_current_default_domain
);
}
text_set_element
(
__libc_subfreeres
,
free_mem
);
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment