Fri Nov 10 14:15:21 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>

* hurd/hurdsig.c (_hurd_internal_post_signal): For SIGNO == 0,
	skip straight to pending check.  When UNTRACED, resume process
	from suspension first.

	* intl/Makefile (headers): New variable, libintl.h.
	[gettext-srcdir]: New rules to copy source from $(gettext-srcdir)/intl.
	* configure.in: Check for --with-gettext arg.

Fri Nov 10 13:51:30 1995  Richard Stallman  <rms@gnu.ai.mit.edu>

	* malloc/malloc.c (get_contiguous_space): New function.
	(morecore): Rewrite allocating new malloc info table.
	(_malloc_internal): Use get_contiguous_space.

Fri Nov 10 13:03:40 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>

	* hurd/hurdexec.c (_hurd_exec): If exec'ing self, pass
	_hurd_msgport to be destroyed.

	* Makerules (installed-libcs): Filter out %_pic.a.

	* hurd/hurdinit.c (_hurd_proc_init): When traced, use msg_sig_post
	to our msgport to take SIGTRAP, instead of _hurd_raise_signal.

	* hurd/Makefile (user-interfaces): Add hurd/process_request.
This commit is contained in:
Roland McGrath 1995-11-10 20:38:31 +00:00
parent d7435cd836
commit 75914335da
16 changed files with 294 additions and 168 deletions

View File

@ -1,3 +1,31 @@
Fri Nov 10 14:15:21 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* hurd/hurdsig.c (_hurd_internal_post_signal): For SIGNO == 0,
skip straight to pending check. When UNTRACED, resume process
from suspension first.
* intl/Makefile (headers): New variable, libintl.h.
[gettext-srcdir]: New rules to copy source from $(gettext-srcdir)/intl.
* configure.in: Check for --with-gettext arg.
Fri Nov 10 13:51:30 1995 Richard Stallman <rms@gnu.ai.mit.edu>
* malloc/malloc.c (get_contiguous_space): New function.
(morecore): Rewrite allocating new malloc info table.
(_malloc_internal): Use get_contiguous_space.
Fri Nov 10 13:03:40 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* hurd/hurdexec.c (_hurd_exec): If exec'ing self, pass
_hurd_msgport to be destroyed.
* Makerules (installed-libcs): Filter out %_pic.a.
* hurd/hurdinit.c (_hurd_proc_init): When traced, use msg_sig_post
to our msgport to take SIGTRAP, instead of _hurd_raise_signal.
* hurd/Makefile (user-interfaces): Add hurd/process_request.
Wed Nov 8 16:31:25 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> Wed Nov 8 16:31:25 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* termios/Makefile (headers): Add sys/ttychars.h. * termios/Makefile (headers): Add sys/ttychars.h.

View File

@ -457,6 +457,7 @@ ifdef objects
installed-libcs := $(foreach o,$(object-suffixes),\ installed-libcs := $(foreach o,$(object-suffixes),\
$(libdir)/$(patsubst %,$(libtype$o),\ $(libdir)/$(patsubst %,$(libtype$o),\
$(libprefix)$(libc-name))) $(libprefix)$(libc-name)))
installed-libcs := $(filter-out %_pic.a,$(installed-libcs))
install: $(installed-libcs) install: $(installed-libcs)
$(installed-libcs): $(libdir)/lib$(libprefix)%: lib $(installed-libcs): $(libdir)/lib$(libprefix)%: lib
$(make-target-directory) $(make-target-directory)

27
configure vendored
View File

@ -14,6 +14,8 @@ ac_default_prefix=/usr/local
# Any additions from configure.in: # Any additions from configure.in:
ac_help="$ac_help ac_help="$ac_help
--with-gmp=DIRECTORY find GMP source code in DIRECTORY (not needed)" --with-gmp=DIRECTORY find GMP source code in DIRECTORY (not needed)"
ac_help="$ac_help
--with-gettext=DIR find GNU gettext source code in DIR (not needed)"
ac_help="$ac_help ac_help="$ac_help
--with-fp if using floating-point hardware" --with-fp if using floating-point hardware"
ac_help="$ac_help ac_help="$ac_help
@ -558,6 +560,21 @@ esac
fi fi
# Check for a --with-gettext argument and set gettext-srcdir in config.make.
# Check whether --with-gettext or --without-gettext was given.
if test "${with_gettext+set}" = set; then
withval="$with_gettext"
case "$with_gettext" in
yes)
{ echo "configure: error: --with-gettext requires an argument; use --with-gettext=DIR" 1>&2; exit 1; } ;;
''|no) ;;
*)
config_vars="$config_vars
gettext-srcdir = $withval" ;;
esac
fi
# Check whether --with-fp or --without-fp was given. # Check whether --with-fp or --without-fp was given.
if test "${with_fp+set}" = set; then if test "${with_fp+set}" = set; then
@ -768,7 +785,7 @@ ostry=$os
while o=`echo $tail | sed 's/\.[^.]*$//'`; test $o != $tail; do while o=`echo $tail | sed 's/\.[^.]*$//'`; test $o != $tail; do
ostry="$ostry /$o" ostry="$ostry /$o"
tail=$o tail=$o
done done
o=`echo $tail | sed 's/[0-9]*$//'` o=`echo $tail | sed 's/[0-9]*$//'`
if test $o != $tail; then if test $o != $tail; then
ostry="$ostry /$o" ostry="$ostry /$o"
@ -1133,7 +1150,7 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser, # On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. # not just through cpp.
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1137 "configure" #line 1154 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <assert.h> #include <assert.h>
Syntax Error Syntax Error
@ -1147,7 +1164,7 @@ else
rm -rf conftest* rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp" CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1151 "configure" #line 1168 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <assert.h> #include <assert.h>
Syntax Error Syntax Error
@ -1201,7 +1218,7 @@ if eval "test \"`echo '$''{'libc_cv_friendly_stddef'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4 echo $ac_n "(cached) $ac_c" 1>&4
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1205 "configure" #line 1222 "configure"
#include "confdefs.h" #include "confdefs.h"
#define __need_size_t #define __need_size_t
#define __need_wchar_t #define __need_wchar_t
@ -1324,7 +1341,7 @@ if eval "test \"`echo '$''{'libc_cv_have_initfini'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&4 echo $ac_n "(cached) $ac_c" 1>&4
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1328 "configure" #line 1345 "configure"
#include "confdefs.h" #include "confdefs.h"
int main() { return 0; } int main() { return 0; }

View File

@ -18,6 +18,19 @@ yes) AC_MSG_ERROR(--with-gmp requires an argument; use --with-gmp=DIRECTORY) ;;
gmp-srcdir = $withval" ;; gmp-srcdir = $withval" ;;
esac esac
]) ])
# Check for a --with-gettext argument and set gettext-srcdir in config.make.
AC_ARG_WITH(gettext, dnl
--with-gettext=DIR find GNU gettext source code in DIR (not needed),
[dnl
case "$with_gettext" in
yes)
AC_MSG_ERROR(--with-gettext requires an argument; use --with-gettext=DIR) ;;
''|no) ;;
*)
config_vars="$config_vars
gettext-srcdir = $withval" ;;
esac
])
dnl Arguments to specify presence of other packages/features. dnl Arguments to specify presence of other packages/features.
AC_ARG_WITH(fp, dnl AC_ARG_WITH(fp, dnl
@ -133,7 +146,7 @@ ostry=$os
while o=`echo $tail | sed 's/\.[^.]*$//'`; test $o != $tail; do while o=`echo $tail | sed 's/\.[^.]*$//'`; test $o != $tail; do
ostry="$ostry /$o" ostry="$ostry /$o"
tail=$o tail=$o
done done
o=`echo $tail | sed 's/[0-9]*$//'` o=`echo $tail | sed 's/[0-9]*$//'`
if test $o != $tail; then if test $o != $tail; then
ostry="$ostry /$o" ostry="$ostry /$o"

View File

@ -33,7 +33,8 @@ distribute := hurdstartup.h hurdfault.h intr-rpc.defs STATUS
# The RPC interfaces go in a separate library. # The RPC interfaces go in a separate library.
interface-library := libhurduser interface-library := libhurduser
user-interfaces := $(addprefix hurd/,\ user-interfaces := $(addprefix hurd/,\
auth process startup \ auth startup \
process process_request \
msg msg_reply msg_request \ msg msg_reply msg_request \
exec exec_startup crash interrupt \ exec exec_startup crash interrupt \
fs fsys io term socket ifsock) fs fsys io term socket ifsock)

View File

@ -30,7 +30,7 @@ Cambridge, MA 02139, USA. */
If TASK == mach_task_self (), some ports are dealloc'd by the exec server. If TASK == mach_task_self (), some ports are dealloc'd by the exec server.
ARGV and ENVP are terminated by NULL pointers. */ ARGV and ENVP are terminated by NULL pointers. */
error_t error_t
_hurd_exec (task_t task, file_t file, _hurd_exec (task_t task, file_t file,
char *const argv[], char *const envp[]) char *const argv[], char *const envp[])
{ {
error_t err; error_t err;
@ -129,7 +129,7 @@ _hurd_exec (task_t task, file_t file,
in the exec, or the signal will never be delivered. Setting the in the exec, or the signal will never be delivered. Setting the
critical section flag avoids anything we call trying to acquire the critical section flag avoids anything we call trying to acquire the
sigstate lock. */ sigstate lock. */
ss->critical_section = 1; ss->critical_section = 1;
__spin_unlock (&ss->lock); __spin_unlock (&ss->lock);
@ -224,7 +224,7 @@ _hurd_exec (task_t task, file_t file,
ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports, ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
ints, INIT_INT_MAX, ints, INIT_INT_MAX,
please_dealloc, pdp - please_dealloc, please_dealloc, pdp - please_dealloc,
NULL, 0); &_hurd_msgport, task == __mach_task_self () ? 1 : 0);
} }
/* Release references to the standard ports. */ /* Release references to the standard ports. */

View File

@ -151,7 +151,7 @@ _hurd_proc_init (char **argv)
/* This process is "traced", meaning it should stop on signals or exec. /* This process is "traced", meaning it should stop on signals or exec.
We are all set up now to handle signals. Stop ourselves, to inform We are all set up now to handle signals. Stop ourselves, to inform
our parent (presumably a debugger) that the exec has completed. */ our parent (presumably a debugger) that the exec has completed. */
_hurd_raise_signal (NULL, SIGTRAP, 0, 0); __msg_sig_post (_hurd_msgport, SIGTRAP, __mach_task_self ());
} }
/* Called when we get a message telling us to change our proc server port. */ /* Called when we get a message telling us to change our proc server port. */

View File

@ -265,11 +265,14 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
incoming signal, returns the reply port to be received on. Otherwise incoming signal, returns the reply port to be received on. Otherwise
returns MACH_PORT_NULL. returns MACH_PORT_NULL.
SIGNO is used to find the applicable SA_RESTART bit. If SIGNO is zero,
the RPC fails with EINTR instead of restarting (thread_cancel).
*STATE_CHANGE is set nonzero if STATE->basic was modified and should *STATE_CHANGE is set nonzero if STATE->basic was modified and should
be applied back to the thread if it might ever run again, else zero. */ be applied back to the thread if it might ever run again, else zero. */
mach_port_t mach_port_t
_hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread, _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
struct machine_thread_all_state *state, int *state_change, struct machine_thread_all_state *state, int *state_change,
mach_port_t *reply_port, mach_port_t *reply_port,
mach_msg_type_name_t reply_port_type, mach_msg_type_name_t reply_port_type,
@ -480,6 +483,52 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
})); }));
_hurd_stopped = 1; _hurd_stopped = 1;
} }
/* Resume the process after a suspension. */
void resume (void)
{
/* Resume the process from being stopped. */
thread_t *threads;
mach_msg_type_number_t nthreads, i;
error_t err;
if (! _hurd_stopped)
return;
/* Tell the proc server we are continuing. */
__USEPORT (PROC, __proc_mark_cont (port));
/* Fetch ports to all our threads and resume them. */
err = __task_threads (__mach_task_self (), &threads, &nthreads);
assert_perror (err);
for (i = 0; i < nthreads; ++i)
{
if (threads[i] != _hurd_msgport_thread &&
(act != handle || threads[i] != ss->thread))
{
err = __thread_resume (threads[i]);
assert_perror (err);
}
err = __mach_port_deallocate (__mach_task_self (),
threads[i]);
assert_perror (err);
}
__vm_deallocate (__mach_task_self (),
(vm_address_t) threads,
nthreads * sizeof *threads);
_hurd_stopped = 0;
/* The thread that will run the handler is already suspended. */
ss_suspended = 1;
}
if (signo == 0)
{
if (untraced)
/* This is PTRACE_CONTINUE. */
resume ();
/* This call is just to check for pending signals. */
__spin_lock (&ss->lock);
goto check_pending_signals;
}
post_signal: post_signal:
@ -514,8 +563,6 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
__spin_lock (&ss->lock); __spin_lock (&ss->lock);
handler = ss->actions[signo].sa_handler;
if (!untraced && (_hurd_exec_flags & EXEC_TRACED)) if (!untraced && (_hurd_exec_flags & EXEC_TRACED))
{ {
/* We are being traced. Stop to tell the debugger of the signal. */ /* We are being traced. Stop to tell the debugger of the signal. */
@ -530,6 +577,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
return; return;
} }
handler = ss->actions[signo].sa_handler;
if (handler == SIG_DFL) if (handler == SIG_DFL)
/* Figure out the default action for this signal. */ /* Figure out the default action for this signal. */
switch (signo) switch (signo)
@ -604,35 +653,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
ss->pending &= ~STOPSIGS; ss->pending &= ~STOPSIGS;
if (_hurd_stopped && act != stop && (untraced || signo == SIGCONT)) if (_hurd_stopped && act != stop && (untraced || signo == SIGCONT))
{ resume ();
/* Resume the process from being stopped. */
thread_t *threads;
mach_msg_type_number_t nthreads, i;
error_t err;
/* Tell the proc server we are continuing. */
__USEPORT (PROC, __proc_mark_cont (port));
/* Fetch ports to all our threads and resume them. */
err = __task_threads (__mach_task_self (), &threads, &nthreads);
assert_perror (err);
for (i = 0; i < nthreads; ++i)
{
if (threads[i] != _hurd_msgport_thread &&
(act != handle || threads[i] != ss->thread))
{
err = __thread_resume (threads[i]);
assert_perror (err);
}
err = __mach_port_deallocate (__mach_task_self (),
threads[i]);
assert_perror (err);
}
__vm_deallocate (__mach_task_self (),
(vm_address_t) threads,
nthreads * sizeof *threads);
_hurd_stopped = 0;
/* The thread that will run the handler is already suspended. */
ss_suspended = 1;
}
} }
} }
@ -648,10 +669,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
act = term; act = term;
} }
/* Handle receipt of a blocked signal, or any signal while stopped. /* Handle receipt of a blocked signal, or any signal while stopped. */
It matters that we test ACT first here, because we must never pass if (__sigismember (&ss->blocked, signo) ||
SIGNO==0 to __sigismember. */
if ((act != ignore && __sigismember (&ss->blocked, signo)) ||
(signo != SIGKILL && _hurd_stopped)) (signo != SIGKILL && _hurd_stopped))
{ {
mark_pending (); mark_pending ();
@ -754,7 +773,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
ss->context = &ocontext; ss->context = &ocontext;
} }
_hurdsig_end_catch_fault (); _hurdsig_end_catch_fault ();
if (! machine_get_basic_state (ss->thread, &thread_state)) if (! machine_get_basic_state (ss->thread, &thread_state))
goto sigbomb; goto sigbomb;
loc = interrupted_reply_port_location (&thread_state, 1); loc = interrupted_reply_port_location (&thread_state, 1);
@ -772,7 +791,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
else else
{ {
wait_for_reply wait_for_reply
= (_hurdsig_abort_rpcs (ss, signo, 1, = (_hurdsig_abort_rpcs (ss, signo, 1,
&thread_state, &state_changed, &thread_state, &state_changed,
&reply_port, reply_port_type, untraced) &reply_port, reply_port_type, untraced)
!= MACH_PORT_NULL); != MACH_PORT_NULL);
@ -851,12 +870,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
} }
/* The signal has either been ignored or is now being handled. We can /* The signal has either been ignored or is now being handled. We can
consider it delivered and reply to the killer. The exception is consider it delivered and reply to the killer. */
signal 0, which can be sent by a user thread to make us check for reply ();
pending signals. In that case we want to deliver the pending signals
before replying. */
if (signo != 0)
reply ();
/* We get here unless the signal was fatal. We still hold SS->lock. /* We get here unless the signal was fatal. We still hold SS->lock.
Check for pending signals, and loop to post them. */ Check for pending signals, and loop to post them. */
@ -874,6 +889,9 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
return pending = ss->pending & ~ss->blocked; return pending = ss->pending & ~ss->blocked;
} }
check_pending_signals:
untraced = 0;
if (signals_pending ()) if (signals_pending ())
{ {
pending: pending:
@ -974,7 +992,7 @@ signal_allowed (int signo, mach_port_t refport)
/* A continue signal can be sent by anyone in the session. */ /* A continue signal can be sent by anyone in the session. */
mach_port_t sessport; mach_port_t sessport;
if (! __USEPORT (PROC, __proc_getsidport (port, &sessport))) if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
{ {
__mach_port_deallocate (__mach_task_self (), sessport); __mach_port_deallocate (__mach_task_self (), sessport);
if (refport == sessport) if (refport == sessport)
goto win; goto win;
@ -1099,7 +1117,7 @@ _hurdsig_init (void)
MACH_PORT_RIGHT_RECEIVE, MACH_PORT_RIGHT_RECEIVE,
&_hurd_msgport)) &_hurd_msgport))
__libc_fatal ("hurd: Can't create message port receive right\n"); __libc_fatal ("hurd: Can't create message port receive right\n");
/* Make a send right to the signal port. */ /* Make a send right to the signal port. */
if (err = __mach_port_insert_right (__mach_task_self (), if (err = __mach_port_insert_right (__mach_task_self (),
_hurd_msgport, _hurd_msgport,
@ -1135,7 +1153,7 @@ _hurdsig_init (void)
if (err = __thread_resume (_hurd_msgport_thread)) if (err = __thread_resume (_hurd_msgport_thread))
__libc_fatal ("hurd: Can't resume signal thread\n"); __libc_fatal ("hurd: Can't resume signal thread\n");
#if 0 /* Don't confuse poor gdb. */ #if 0 /* Don't confuse poor gdb. */
/* Receive exceptions on the signal port. */ /* Receive exceptions on the signal port. */
__task_set_special_port (__mach_task_self (), __task_set_special_port (__mach_task_self (),

View File

@ -19,6 +19,7 @@
# Cambridge, MA 02139, USA. # Cambridge, MA 02139, USA.
subdir = intl subdir = intl
headers = libintl.h
routines = bindtextdom dcgettext dgettext gettext \ routines = bindtextdom dcgettext dgettext gettext \
finddomain loadmsgcat localealias textdomain finddomain loadmsgcat localealias textdomain
distribute = gettext.h gettextP.h hash-string.h distribute = gettext.h gettextP.h hash-string.h
@ -27,3 +28,17 @@ include ../Rules
CPPFLAGS += -D'GNULOCALEDIR="$(localedir)"' \ CPPFLAGS += -D'GNULOCALEDIR="$(localedir)"' \
-D'LOCALE_ALIAS_PATH="$(localedir):$(nlsdir)"' -D'LOCALE_ALIAS_PATH="$(localedir):$(nlsdir)"'
ifdef gettext-srcdir
%:: $(gettext-srcdir)/intl/%.glibc; $(copysrc)
%:: $(gettext-srcdir)/intl/%; $(copysrc)
define copysrc
cp -f $< $@.new
chmod a-w $@.new
mv -f $@.new $@
test ! -d CVS || cvs commit -m'Updated from $<' $@
endef
endif

View File

@ -317,14 +317,13 @@ DCGETTEXT (domainname, msgid, category)
{ {
int cnt; int cnt;
for (cnt = 6; cnt >= 0 && retval == NULL; --cnt) for (cnt = 0; domain->successor[cnt] != NULL; --cnt)
if (domain->successor[cnt] != NULL) {
{ retval = find_msg (domain->successor[cnt], msgid);
retval = find_msg (domain->successor[cnt], msgid);
if (domain->successor[cnt]->data == NULL) if (retval != NULL)
domain->successor[cnt] = NULL; break;
} }
} }
if (retval != NULL) if (retval != NULL)

View File

@ -95,6 +95,11 @@ static struct loaded_domain *make_entry_rec __P ((const char *dirname,
const char *domainname, const char *domainname,
int do_allocate)); int do_allocate));
/* Substitution for systems lacking this function in their C library. */
#if !_LIBC && !HAVE_STPCPY
static char *stpcpy __P ((char *dest, const char *src));
#endif
/* Return a data structure describing the message catalog described by /* Return a data structure describing the message catalog described by
the DOMAINNAME and CATEGORY parameters with respect to the currently the DOMAINNAME and CATEGORY parameters with respect to the currently
@ -155,9 +160,9 @@ _nl_find_domain (dirname, locale, domainname)
if (retval->data != NULL) if (retval->data != NULL)
return retval; return retval;
for (cnt = 6; cnt >= 0; --cnt) for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
{ {
if (retval->successor[cnt] == 0) if (retval->successor[cnt]->decided == 0)
_nl_load_domain (retval->successor[cnt]); _nl_load_domain (retval->successor[cnt]);
if (retval->successor[cnt]->data != NULL) if (retval->successor[cnt]->data != NULL)
@ -279,13 +284,13 @@ _nl_find_domain (dirname, locale, domainname)
separator character in the file name, not for XPG syntax. */ separator character in the file name, not for XPG syntax. */
if (syntax == xpg) if (syntax == xpg)
{ {
if (territory[0] == '\0') if (territory != NULL && territory[0] == '\0')
mask &= ~TERRITORY; mask &= ~TERRITORY;
if (codeset[0] == '\0') if (codeset != NULL && codeset[0] == '\0')
mask &= ~XPG_CODESET; mask &= ~XPG_CODESET;
if (modifier[0] == '\0') if (modifier != NULL && modifier[0] == '\0')
mask &= ~XPG_MODIFIER; mask &= ~XPG_MODIFIER;
} }
@ -340,107 +345,110 @@ make_entry_rec (dirname, mask, language, territory, codeset, modifier,
const char *domain; const char *domain;
int do_allocate; int do_allocate;
{ {
struct loaded_domain *retval, *last; char *filename = NULL;
char *filename, *cp; struct loaded_domain *last = NULL;
struct loaded_domain *retval;
char *cp;
size_t entries; size_t entries;
int cnt; int cnt;
/* Allocate room for the full file name. */
filename = (char *) malloc (strlen (dirname) + 1
+ strlen (language)
+ ((mask & TERRITORY) != 0
? strlen (territory) : 0)
+ ((mask & XPG_CODESET) != 0
? strlen (codeset) : 0)
+ ((mask & XPG_MODIFIER) != 0 ?
strlen (modifier) : 0)
+ ((mask & CEN_SPECIAL) != 0
? strlen (special) : 0)
+ ((mask & CEN_SPONSOR) != 0
? strlen (sponsor) : 0)
+ ((mask & CEN_REVISION) != 0
? strlen (revision) : 0) + 1
+ strlen (domain) + 1);
if (filename == NULL) /* Process the current entry described by the MASK only when it is
return NULL; valid. Because the mask can have in the first call bits from
both syntaces set this is necessary to prevent constructing
illegal local names. */
/* FIXME: Rewrite because test is necessary only in first round. */
if ((mask & CEN_SPECIFIC) == 0 || (mask & XPG_SPECIFIC) == 0)
{
/* Allocate room for the full file name. */
filename = (char *) malloc (strlen (dirname) + 1
+ strlen (language)
+ ((mask & TERRITORY) != 0
? strlen (territory) : 0)
+ ((mask & XPG_CODESET) != 0
? strlen (codeset) : 0)
+ ((mask & XPG_MODIFIER) != 0 ?
strlen (modifier) : 0)
+ ((mask & CEN_SPECIAL) != 0
? strlen (special) : 0)
+ ((mask & CEN_SPONSOR) != 0
? strlen (sponsor) : 0)
+ ((mask & CEN_REVISION) != 0
? strlen (revision) : 0) + 1
+ strlen (domain) + 1);
retval = NULL; if (filename == NULL)
last = NULL; return NULL;
/* We don't want libintl.a to depend on any other library. So we retval = NULL;
avoid the non-standard function stpcpy. In GNU C Library this last = NULL;
function is available, though. Also allow the symbol HAVE_STPCPY
to be defined. */
#if !defined _LIBC && !defined HAVE_STPCPY
# define stpcpy(p, s) \
(strcpy (p, s), strchr (p, '\0'))
#endif
/* Construct file name. */ /* Construct file name. */
cp = stpcpy (filename, dirname); cp = stpcpy (filename, dirname);
*cp++ = '/'; *cp++ = '/';
cp = stpcpy (cp, language); cp = stpcpy (cp, language);
if ((mask & TERRITORY) != 0) if ((mask & TERRITORY) != 0)
{
*cp++ = '_';
cp = stpcpy (cp, territory);
}
if ((mask & XPG_CODESET) != 0)
{
*cp++ = '.';
cp = stpcpy (cp, codeset);
}
if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
{
/* This component can be part of both syntaces but has different
leading characters. For CEN we use `+', else `@'. */
*cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
cp = stpcpy (cp, modifier);
}
if ((mask & CEN_SPECIAL) != 0)
{
*cp++ = '+';
cp = stpcpy (cp, special);
}
if ((mask & CEN_SPONSOR) != 0)
{
*cp++ = ',';
cp = stpcpy (cp, sponsor);
}
if ((mask & CEN_REVISION) != 0)
{
*cp++ = '_';
cp = stpcpy (cp, revision);
}
*cp++ = '/';
stpcpy (cp, domain);
/* Look in list of already loaded domains whether it is already
available. */
last = NULL;
for (retval = _nl_loaded_domains; retval != NULL; retval = retval->next)
{
int compare = strcmp (retval->filename, filename);
if (compare == 0)
/* We found it! */
break;
if (compare < 0)
{ {
/* It's not in the list. */ *cp++ = '_';
retval = NULL; cp = stpcpy (cp, territory);
break; }
if ((mask & XPG_CODESET) != 0)
{
*cp++ = '.';
cp = stpcpy (cp, codeset);
}
if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
{
/* This component can be part of both syntaces but has different
leading characters. For CEN we use `+', else `@'. */
*cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
cp = stpcpy (cp, modifier);
}
if ((mask & CEN_SPECIAL) != 0)
{
*cp++ = '+';
cp = stpcpy (cp, special);
}
if ((mask & CEN_SPONSOR) != 0)
{
*cp++ = ',';
cp = stpcpy (cp, sponsor);
}
if ((mask & CEN_REVISION) != 0)
{
*cp++ = '_';
cp = stpcpy (cp, revision);
} }
last = retval; *cp++ = '/';
} stpcpy (cp, domain);
if (retval != NULL || do_allocate == 0) /* Look in list of already loaded domains whether it is already
{ available. */
free (filename); last = NULL;
return retval; for (retval = _nl_loaded_domains; retval != NULL; retval = retval->next)
if (retval->filename != NULL)
{
int compare = strcmp (retval->filename, filename);
if (compare == 0)
/* We found it! */
break;
if (compare < 0)
{
/* It's not in the list. */
retval = NULL;
break;
}
last = retval;
}
if (retval != NULL || do_allocate == 0)
{
free (filename);
return retval;
}
} }
retval = (struct loaded_domain *) malloc (sizeof (*retval)); retval = (struct loaded_domain *) malloc (sizeof (*retval));
@ -453,8 +461,8 @@ make_entry_rec (dirname, mask, language, territory, codeset, modifier,
if (last == NULL) if (last == NULL)
{ {
retval->next = _nl_loaded_domains; retval->next = _nl_loaded_domains;
_nl_loaded_domains = retval; _nl_loaded_domains = retval;
} }
else else
{ {
retval->next = last->next; retval->next = last->next;
@ -474,3 +482,22 @@ make_entry_rec (dirname, mask, language, territory, codeset, modifier,
return retval; return retval;
} }
/* @@ 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

View File

@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
# ifdef HAVE_STRING_H # ifdef HAVE_STRING_H
# include <string.h> # include <string.h>
# else # else
# define NULL 0 # define NULL ((void *) 0)
# endif # endif
# endif # endif
#endif #endif

View File

@ -75,6 +75,13 @@ _nl_load_domain (domain)
domain->decided = 1; domain->decided = 1;
domain->data = NULL; domain->data = NULL;
/* If the record does not represent a valid locale the FILENAME
might be NULL. This can happen when according to the given
specification the locale file name is different for XPG and CEN
syntax. */
if (domain->filename == NULL)
return;
/* Try to open the addressed file. */ /* Try to open the addressed file. */
fd = open (domain->filename, O_RDONLY); fd = open (domain->filename, O_RDONLY);
if (fd == -1) if (fd == -1)

View File

@ -1,5 +1,5 @@
/* localealias.c -- handle aliases for locale names /* localealias.c -- handle aliases for locale names
Copyright (C) 1995 Software Foundation, Inc. Copyright (C) 1995 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -125,7 +125,7 @@ _nl_expand_alias (name)
{ {
const char *start; const char *start;
while (locale_alias_path[0] != '\0' && locale_alias_path[0] == ':') while (locale_alias_path[0] == ':')
++locale_alias_path; ++locale_alias_path;
start = locale_alias_path; start = locale_alias_path;
@ -239,7 +239,7 @@ read_alias_file (fname, fname_len)
} }
} }
/* Possibily not the whole line fits into the buffer. Ignore /* Possibily not the whole line fitted into the buffer. Ignore
the rest of the line. */ the rest of the line. */
while (strchr (cp, '\n') == NULL) while (strchr (cp, '\n') == NULL)
{ {
@ -305,8 +305,8 @@ alias_compare (map1, map2)
{ {
/* I know this seems to be odd but the tolower() function in /* I know this seems to be odd but the tolower() function in
some systems libc cannot handle nonalpha characters. */ some systems libc cannot handle nonalpha characters. */
c1 = isalpha (*p1) ? tolower (*p1) : *p1; c1 = isupper (*p1) ? tolower (*p1) : *p1;
c2 = isalpha (*p2) ? tolower (*p2) : *p2; c2 = isupper (*p2) ? tolower (*p2) : *p2;
if (c1 == '\0') if (c1 == '\0')
break; break;
} }

View File

@ -1 +1 @@
#include <locale/libintl.h> #include <intl/libintl.h>