diff options
Diffstat (limited to 'string')
-rw-r--r-- | string/Makefile | 2 | ||||
-rw-r--r-- | string/strsignal.c | 93 | ||||
-rw-r--r-- | string/tst-inlcall.c | 76 |
3 files changed, 163 insertions, 8 deletions
diff --git a/string/Makefile b/string/Makefile index 5b11a5885a..93d68a45be 100644 --- a/string/Makefile +++ b/string/Makefile @@ -42,7 +42,7 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \ strcoll_l strxfrm_l tests := tester inl-tester noinl-tester testcopy test-ffs \ - tst-strlen stratcliff tst-svc + tst-strlen stratcliff tst-svc tst-inlcall distribute := memcopy.h pagecopy.h tst-svc.expect diff --git a/string/strsignal.c b/string/strsignal.c index 69629b7855..41585dca00 100644 --- a/string/strsignal.c +++ b/string/strsignal.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 94, 95, 96, 97, 98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -18,7 +18,9 @@ #include <signal.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <bits/libc-lock.h> #ifndef HAVE_GNU_LD @@ -27,23 +29,100 @@ /* Defined in siglist.c. */ extern const char *const _sys_siglist[]; +static __libc_key_t key; + +/* If nonzero the key allocation failed and we should better use a + static buffer than fail. */ +#define BUFFERSIZ 100 +static char local_buf[BUFFERSIZ]; +static char *static_buf; + +/* Destructor for the thread-specific data. */ +static void init (void); +static void free_key_mem (void *mem); +static char *getbuffer (void); /* Return a string describing the meaning of the signal number SIGNUM. */ char * strsignal (int signum) { + __libc_once_define (static, once); const char *desc; - if (signum < 0 || signum > NSIG || (desc = _sys_siglist[signum]) == NULL) + /* If we have not yet initialized the buffer do it now. */ + __libc_once (once, init); + + if ( +#ifdef SIGRTMIN + (signum >= SIGRTMIN && signum <= SIGRTMAX) || +#endif + signum < 0 || signum > NSIG || (desc = _sys_siglist[signum]) == NULL) { - static char buf[512]; - int len = __snprintf (buf, sizeof buf, _("Unknown signal %d"), signum); + char *buffer = getbuffer (); + int len = __snprintf (buffer, BUFFERSIZ - 1, +#ifdef SIGRTMIN + signum >= SIGRTMIN && signum <= SIGRTMAX + ? _("Real-time signal %d") : +#endif + _("Unknown signal %d"), signum); if (len < 0) - return NULL; - buf[len - 1] = '\0'; - return buf; + buffer = NULL; + else + buffer[len] = '\0'; + + return buffer; } return (char *) _(desc); } + + +/* Initialize buffer. */ +static void +init (void) +{ + if (__libc_key_create (&key, free_key_mem)) + /* Creating the key failed. This means something really went + wrong. In any case use a static buffer which is better than + nothing. */ + static_buf = local_buf; +} + + +/* Free the thread specific data, this is done if a thread terminates. */ +static void +free_key_mem (void *mem) +{ + free (mem); + __libc_setspecific (key, NULL); +} + + +/* Return the buffer to be used. */ +static char * +getbuffer (void) +{ + char *result; + + if (static_buf != NULL) + result = static_buf; + else + { + /* We don't use the static buffer and so we have a key. Use it + to get the thread-specific buffer. */ + result = __libc_getspecific (key); + if (result == NULL) + { + /* No buffer allocated so far. */ + result = malloc (BUFFERSIZ); + if (result == NULL) + /* No more memory available. We use the static buffer. */ + result = local_buf; + else + __libc_setspecific (key, result); + } + } + + return result; +} diff --git a/string/tst-inlcall.c b/string/tst-inlcall.c new file mode 100644 index 0000000000..3682e88ff6 --- /dev/null +++ b/string/tst-inlcall.c @@ -0,0 +1,76 @@ +/* Tester for calling inline string functions. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +/* Make sure we test the optimized inline functions. */ +#define __USE_STRING_INLINES 1 + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <fcntl.h> + + +int +main (void) +{ + int status; + int errors = 0; + char buf1[1000]; + char *cp; + char ch; + + cp = strcpy (buf1, "hello world"); + if (strcmp ("hello world", cp++) != 0) + { + puts ("strcmp test 1 failed"); + ++errors; + } + + cp = buf1; + if (strcmp (cp++, "hello world") != 0) + { + puts ("strcmp test 2 failed"); + ++errors; + } + + ch = 'h'; + if (strchr ("hello world", ch++) == NULL) + { + puts ("strchr test 1 failed"); + ++errors; + } + + if (errors == 0) + { + status = EXIT_SUCCESS; + puts ("No errors."); + } + else + { + status = EXIT_FAILURE; + printf ("%Zd errors.\n", errors); + } + exit (status); +} |