From c4563d2d668675c2d5083f6ad01c801d6ccbe013 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 28 Apr 1999 23:13:52 +0000 Subject: Update. 1999-04-28 Ulrich Drepper * argp/argp-ba.c (argp_program_bug_address): Don't initialize with 0. * argp/argp-parse.c (_argp_hang): Likewise. * argp/argp-pv.c (argp_program_version): Likewise. * argp/argp-pvh.c (argp_program_version_hook): Likewise. * inet/ether_hton.c (ether_hton, startp): Likewise. * inet/ether_ntoh.c (ether_ntoh, startp): Likewise. * inet/getnetgrent_r.c (setup, startp): Likewise. * intl/loadmsgcat.c (_nl_msg_cat_cntr): Likewise. * intl/localealias.c (string_space, string_space_act, string_space_max, nmap, maxmap): Likewise. * libio/iopopen.c (proc_file_chain): Likewise. * libio/oldiopopen.c (old_proc_file_chain): Likewise. * locale/lc-collate.c (__collate_table, __collate_extra, __collate_element_hash, __collate_element_strings, __collate_element_values): Likewise. * malloc/mcheck.c (mcheck_used): Likewise. * malloc/mtrace.c (added_atexit_handler): Likewise. * malloc/set-freeres.c (already_called): Likewise. * misc/getpass.c (getpass) [buf, bufsize]: Likewise. * misc/syslog.c (LogStat, LogTag): Likewise. * nss/XXX-lookup.c (DATABASE_NAME_SYMBOL): Likewise. * nss/getXXbyYY_r.c (startp): Likewise. * posix/getopt.c (optarg, __getopt_initialized): Likewise. * posix/regex.c (init_syntax_once) [done]: Likewise. (debug): Likewise. * string/strfry.c (init): Likewise. * sunrpc/svc_run.c (svc_top): Likewise. * posix/euidaccess.c (have_ids): Likewise. * sysdeps/unix/sysv/linux/poll.c (must_emulate): Likewise. * sysdeps/unix/sysv/linux/ttyname.c (__ttyname, namelen): Likewise. * time/getdate.c (getdate_err): Likewise. * time/tzfile.c (transitions, type_idxs, types, zone_names, leaps): Likewise. * time/tzset.c (old_tz, is_initialized): Likewise. * inet/getnameinfo.c (nrl_domainname): Rewrite to allow initialization of static data with zero. * signal/allocrtsig.c (init): Likewise. * string/Makefile (routines): Add strchrnul. * string/Versions [GLIBC_2.1.1]: Add strchrnul. * string/string.c: Add strchrnul prototype. * include/string.h: Add __strchrnul prototype. * sysdeps/generic/strchrnul.c: New file. * sysdeps/i386/strchrnul.S: New file. * sysdeps/i386/bits/string.c: Add strchrnul optimization. * sysdeps/i386/i486/bits/string.c: Likewise. * argp/argp-help.c (argp_args_usage): Use __strchrnul. * inet/ether_line.c (ether_line): Likewise. * nscd/nscd_conf.c (nscd_parse_file): Likewise. * nss/nsswitch.c (nss_parse_file): Likewise. * posix/execvp.c (execvp): Likewise. * posix/fnmatch.c (internal_fnmatch): Likewise. * resolv/res_hconf.c (_res_hconv_init): Likewise. * resolv/res_init.c (res_init): Likewise. * stdlib/fmtmsg.c (init): Likewise. * stdlib/getsubopt.c (getsubopt): Likewise. * catgets/catgets.c (catopen): Only allocate one memory block. (catclose): Only one free call necessary. * catgets/open_catalog.c (__open_catalog): Simplify handling of file descriptor. * ctype/ctype-extn.c: Make __toascii_l and __isascii_l alias instead of real functions. Simplify _tolower and _toupper. * grp/initgroups.c (compat_call): Remove unnecessary use of pointer variable. * iconv/gconv.h (struct gconv_info): Change data element from pointer to array of size 0. * iconv/gconv_open.c (__gconv_open): Allocate structures accordingly. * iconv/gconv_close.c (__gconv_close): Don't free data. * iconv/gconv_conf.c (add_alias): Avoid searching in tree twice to insert new alias. * iconv/gconv_db.c (add_derivation): More efficient copying. Check for error while inserting in tree. * include/time.h: Pretty print. * inet/ruserpass.c: Rewrite use of toktab to avoid string pointers in table and lots of relocations. * posix/regex.c (regerror): Rewrite use of re_error_msgid to avoid string pointers in table and lots of relocations. * intl/finddomain.c: Remove definition of strchr macro. * io/ftw.c (nftw_arr, ftw_arr): Make const. * locale/loadlocale.c (_nl_load_locale): Optimize string copying. * locale/localeinfo.h (_nl_category_names): Change into an array with fixed width char string elements. * locale/setlocale.c (_nl_category_names): Likewise. (_nl_current): Make global. * locale/nl_langinfo.c (nldata): Removed. Use _nl_current now. * malloc/Makefile (distribute): Add stackinfo.h. * sysdeps/generic/stackinfo.h: New file. * sysdeps/i386/stackinfo.h: New file. * posix/execl.c: Use stackinfo.h in optimizing alloca use. * posix/execle.c: Likewise. * posix/execlp.c: Likewise. * nis/nis_table.c (__create_ib_request): Always use realloc. * posix/execvp.c (execute): Rename to script_execute and keep only code to execute using shell. (execvp): Call execv directly and only fall back on script_execute. * resolv/inet_net_pton.c (inet_net_pton_ipv4): Remove digits define and always use xdigits instead. * resolv/res_init.c (res_init): Use rawmemchr instead of strchr where appropriate. * stdlib/fpioconst.h (__tens): New declaration. (struct mp_power): Remove array, add arrayoff element. * stdlib/fpioconst.c: Replace definitions of _ten_p* arrays by one __tens array and add in _fpioconst_pow10 offsets into __tens. * stdio-common/printf_fp.c: Rewrite to use new __tens array. * stdlib/strtod.c: Likewise. * stdlib/a64l.c (a64l_table): Avoid unnecessary elements. * stdlib/exit.c: Rewrite to use __exit_funcs being as sign for end of the list. * stdlib/atexit.c (__exit_funcs): Don't initialize. * stdlib/fmtmsg.c (keywords): Make name element fixed width array. * sunrpc/clnt_perr.c: Rewrite clnt_sperrno and auth_errmsg to use a single and an array with offsets. * sunrpc/des_soft.c (partab): Make it const. * sunrpc/key_call.c (trytimeout, tottimeout): Make const. (__key_encryptsession_pk_LOCAL): Don't initialize with 0. (__key_decryptsession_pk_LOCAL): Likewise. (__key_gendes_LOCAL): Likewise. (MESSENGER): Mark const. (key_call_private_main): Don't initialize with 0. (use_keyenvoy): Don't initialize with 0. (key_call): Rewrite to reverse logic of use_doors variable. * sunrpc/netname.c (OPSYS): Define as array, not pointer. (startp): Don't initialize with zero. * sunrpc/openchild.c (_openchild): Make first argument const. * sunrpc/pmap_rmt.c (timeout): Mark const. * sunrpc/xcrypt.c (hex): Likewise. * sysdeps/unix/sysv/linux/getcwd.c: Rewrite to allow omitting initialization of global variables. * sysdeps/unix/sysv/linux/getpt.c: Likewise. * sysdeps/unix/sysv/linux/if_index.c: Likewise. * termios/tcgetsid.c: Likewise. * sysdeps/unix/sysv/linux/i386/dl-procinfo.h (x86_cap_flags): Change fxsr to osfxsr. * time/tzfile.c (__tzfile_read): Rewrite to allocate only one memory block. Add function to free memory if wanted. * time/tzset.c (tzset_internal): Pass extra argument to __tzfile_read. * wcsmbs/wcsmbsload.c (to_wc, to_mb): Correct initializers. * wcsmbs/wmemset.c: Little code optimization. --- sysdeps/generic/stackinfo.h | 21 +++ sysdeps/generic/strchrnul.c | 166 +++++++++++++++++ sysdeps/i386/bits/string.h | 60 +++++++ sysdeps/i386/i486/bits/string.h | 60 +++++++ sysdeps/i386/stackinfo.h | 28 +++ sysdeps/i386/strchrnul.S | 275 +++++++++++++++++++++++++++++ sysdeps/posix/euidaccess.c | 4 +- sysdeps/unix/sysv/linux/getcwd.c | 17 +- sysdeps/unix/sysv/linux/getpt.c | 8 +- sysdeps/unix/sysv/linux/i386/dl-procinfo.h | 4 +- sysdeps/unix/sysv/linux/if_index.c | 16 +- sysdeps/unix/sysv/linux/poll.c | 4 +- sysdeps/unix/sysv/linux/ttyname.c | 6 +- 13 files changed, 640 insertions(+), 29 deletions(-) create mode 100644 sysdeps/generic/stackinfo.h create mode 100644 sysdeps/generic/strchrnul.c create mode 100644 sysdeps/i386/stackinfo.h create mode 100644 sysdeps/i386/strchrnul.S (limited to 'sysdeps') diff --git a/sysdeps/generic/stackinfo.h b/sysdeps/generic/stackinfo.h new file mode 100644 index 0000000000..5d6d8200bd --- /dev/null +++ b/sysdeps/generic/stackinfo.h @@ -0,0 +1,21 @@ +/* Copyright (C) 1999 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. */ + +/* This file contains a bit of information about the stack allocation + of the processor. Since there is no general truth we can't say + anything here. */ diff --git a/sysdeps/generic/strchrnul.c b/sysdeps/generic/strchrnul.c new file mode 100644 index 0000000000..1d6ece5332 --- /dev/null +++ b/sysdeps/generic/strchrnul.c @@ -0,0 +1,166 @@ +/* Copyright (C) 1991, 93, 94, 95, 96, 97, 99 Free Software Foundation, Inc. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + bug fix and commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + 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. */ + +#include + +#undef __strchrnul +#undef strchrnul + +/* Find the first occurrence of C in S or the final NUL byte. */ +char * +__strchrnul (s, c) + const char *s; + int c; +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + + c = (unsigned char) c; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = s; ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == c || *char_ptr == '\0') + return (void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + switch (sizeof (longword)) + { + case 4: magic_bits = 0x7efefeffL; break; + case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; + default: + abort (); + } + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; + if (sizeof (longword) > 4) + /* Do the shift in two steps to avoid a warning if long has 32 bits. */ + charmask |= (charmask << 16) << 16; + if (sizeof (longword) > 8) + abort (); + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + for (;;) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C as well as zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *longword_ptr++; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0 || + + /* That caught zeroes. Now test for C. */ + ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) + & ~magic_bits) != 0) + { + /* Which of the bytes was C or zero? + If none of them were, it was a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); + + if (*cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (sizeof (longword) > 4) + { + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + } + } + } + + /* This should never happen. */ + return NULL; +} + +weak_alias (__strchrnul, strchrnul) diff --git a/sysdeps/i386/bits/string.h b/sysdeps/i386/bits/string.h index 4bd65af7f1..5a67c1b4e1 100644 --- a/sysdeps/i386/bits/string.h +++ b/sysdeps/i386/bits/string.h @@ -517,6 +517,66 @@ __strchr_c (__const char *__s, int __c) } +/* Find the first occurrence of C in S or the final NUL byte. */ +#define _HAVE_STRING_ARCH_strchrnul 1 +#define __strchrnul(s, c) \ + (__extension__ (__builtin_constant_p (c) \ + ? ((c) == '\0' \ + ? (char *) __rawmemchr (s, c) \ + : __strchrnul_c (s, ((c) & 0xff) << 8)) \ + : __strchrnul_g (s, c))) + +__STRING_INLINE char *__strchrnul_g (__const char *__s, int __c); + +__STRING_INLINE char * +__strchrnul_g (__const char *__s, int __c) +{ + register unsigned long int __d0; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" + "movb %%al,%%ah\n" + "1:\n\t" + "lodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "2:\n\t" + "movl %1,%0" + : "=a" (__res), "=&S" (__d0) + : "0" (__c), "1" (__s) + : "cc"); + return __res - 1; +} + +__STRING_INLINE char *__strchrnul_c (__const char *__s, int __c); + +__STRING_INLINE char * +__strchrnul_c (__const char *__s, int __c) +{ + register unsigned long int __d0; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" + "1:\n\t" + "lodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "2:\n\t" + "movl %1,%0" + : "=a" (__res), "=&S" (__d0) + : "0" (__c), "1" (__s) + : "cc"); + return __res - 1; +} +#ifdef __USE_GNU +# define strchrnul(s, c) __strchrnul (s, c) +#endif + + /* Return the length of the initial segment of S which consists entirely of characters not in REJECT. */ #define _HAVE_STRING_ARCH_strcspn 1 diff --git a/sysdeps/i386/i486/bits/string.h b/sysdeps/i386/i486/bits/string.h index 6e5c3fed1f..cb0229b5cd 100644 --- a/sysdeps/i386/i486/bits/string.h +++ b/sysdeps/i386/i486/bits/string.h @@ -1056,6 +1056,66 @@ __strchr_g (__const char *__s, int __c) } +/* Find the first occurrence of C in S or the final NUL byte. */ +#define _HAVE_STRING_ARCH_strchrnul 1 +#define __strchrnul(s, c) \ + (__extension__ (__builtin_constant_p (c) \ + ? ((c) == '\0' \ + ? (char *) __rawmemchr (s, c) \ + : __strchrnul_c (s, ((c) & 0xff) << 8)) \ + : __strchrnul_g (s, c))) + +__STRING_INLINE char *__strchrnul_c (__const char *__s, int __c); + +__STRING_INLINE char * +__strchrnul_c (__const char *__s, int __c) +{ + register unsigned long int __d0; + register char *__res; + __asm__ __volatile__ + ("1:\n\t" + "movb (%0),%%al\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "leal 1(%0),%0\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "decl %0\n" + "2:" + : "=r" (__res), "=&a" (__d0) + : "0" (__s), "1" (__c) + : "cc"); + return __res; +} + +__STRING_INLINE char *__strchrnul_g (__const char *__s, int __c); + +__STRING_INLINE char * +__strchrnul_g (__const char *__s, int __c) +{ + register unsigned long int __d0; + register char *__res; + __asm__ __volatile__ + ("movb %%al,%%ah\n" + "1:\n\t" + "movb (%0),%%al\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "leal 1(%0),%0\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "decl %0\n" + "2:" + : "=r" (__res), "=&a" (__d0) + : "0" (__s), "1" (__c) + : "cc"); + return __res; +} +#ifdef __USE_GNU +# define strchrnul(s, c) __strchrnul (s, c) +#endif + + #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED /* Find the first occurrence of C in S. This is the BSD name. */ # define _HAVE_STRING_ARCH_index 1 diff --git a/sysdeps/i386/stackinfo.h b/sysdeps/i386/stackinfo.h new file mode 100644 index 0000000000..2fe865a364 --- /dev/null +++ b/sysdeps/i386/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 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. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On x86 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/sysdeps/i386/strchrnul.S b/sysdeps/i386/strchrnul.S new file mode 100644 index 0000000000..45950c3564 --- /dev/null +++ b/sysdeps/i386/strchrnul.S @@ -0,0 +1,275 @@ +/* strchrnul (str, ch) -- Return pointer to first occurrence of CH in STR + or the final NUL byte. + For Intel 80x86, x>=3. + Copyright (C) 1994, 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper + Some optimisations by Alan Modra + + 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. */ + +#include +#include "asm-syntax.h" + +/* + INPUT PARAMETERS: + str (sp + 4) + ch (sp + 8) +*/ + + .text +ENTRY (__strchrnul) + pushl %edi /* Save callee-safe registers used here. */ + + movl 8(%esp), %eax /* get string pointer */ + movl 12(%esp), %edx /* get character we are looking for */ + + /* At the moment %edx contains C. What we need for the + algorithm is C in all bytes of the dword. Avoid + operations on 16 bit words because these require an + prefix byte (and one more cycle). */ + movb %dl, %dh /* now it is 0|0|c|c */ + movl %edx, %ecx + shll $16, %edx /* now it is c|c|0|0 */ + movw %cx, %dx /* and finally c|c|c|c */ + + /* Before we start with the main loop we process single bytes + until the source pointer is aligned. This has two reasons: + 1. aligned 32-bit memory access is faster + and (more important) + 2. we process in the main loop 32 bit in one step although + we don't know the end of the string. But accessing at + 4-byte alignment guarantees that we never access illegal + memory if this would not also be done by the trivial + implementation (this is because all processor inherent + boundaries are multiples of 4. */ + + testb $3, %eax /* correctly aligned ? */ + jz L(11) /* yes => begin loop */ + movb (%eax), %cl /* load byte in question (we need it twice) */ + cmpb %cl, %dl /* compare byte */ + je L(6) /* target found => return */ + testb %cl, %cl /* is NUL? */ + jz L(6) /* yes => return NULL */ + incl %eax /* increment pointer */ + + testb $3, %eax /* correctly aligned ? */ + jz L(11) /* yes => begin loop */ + movb (%eax), %cl /* load byte in question (we need it twice) */ + cmpb %cl, %dl /* compare byte */ + je L(6) /* target found => return */ + testb %cl, %cl /* is NUL? */ + jz L(6) /* yes => return NULL */ + incl %eax /* increment pointer */ + + testb $3, %eax /* correctly aligned ? */ + jz L(11) /* yes => begin loop */ + movb (%eax), %cl /* load byte in question (we need it twice) */ + cmpb %cl, %dl /* compare byte */ + je L(6) /* target found => return */ + testb %cl, %cl /* is NUL? */ + jz L(6) /* yes => return NULL */ + incl %eax /* increment pointer */ + + /* No we have reached alignment. */ + jmp L(11) /* begin loop */ + + /* We exit the loop if adding MAGIC_BITS to LONGWORD fails to + change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-31 is set, there will be a carry + into bit 32 (=carry flag), so all of the hole bits will + be changed. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + /* Each round the main loop processes 16 bytes. */ + + ALIGN(4) + +L(1): addl $16, %eax /* adjust pointer for whole round */ + +L(11): movl (%eax), %ecx /* get word (= 4 bytes) in question */ + xorl %edx, %ecx /* XOR with word c|c|c|c => bytes of str == c + are now 0 */ + movl $0xfefefeff, %edi /* magic value */ + addl %ecx, %edi /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* C */ + + /* According to the algorithm we had to reverse the effect of the + XOR first and then test the overflow bits. But because the + following XOR would destroy the carry flag and it would (in a + representation with more than 32 bits) not alter then last + overflow, we can now test this condition. If no carry is signaled + no overflow must have occurred in the last byte => it was 0. */ + jnc L(7) + + /* We are only interested in carry bits that change due to the + previous add, so remove original bits */ + xorl %ecx, %edi /* ((word^charmask)+magic)^(word^charmask) */ + + /* Now test for the other three overflow bits. */ + orl $0xfefefeff, %edi /* set all non-carry bits */ + incl %edi /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + /* If at least one byte of the word is C we don't get 0 in %edi. */ + jnz L(7) /* found it => return pointer */ + + /* Now we made sure the dword does not contain the character we are + looking for. But because we deal with strings we have to check + for the end of string before testing the next dword. */ + + xorl %edx, %ecx /* restore original dword without reload */ + movl $0xfefefeff, %edi /* magic value */ + addl %ecx, %edi /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc L(71) /* highest byte is NUL => return NULL */ + xorl %ecx, %edi /* (word+magic)^word */ + orl $0xfefefeff, %edi /* set all non-carry bits */ + incl %edi /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz L(71) /* found NUL => return NULL */ + + movl 4(%eax), %ecx /* get word (= 4 bytes) in question */ + xorl %edx, %ecx /* XOR with word c|c|c|c => bytes of str == c + are now 0 */ + movl $0xfefefeff, %edi /* magic value */ + addl %ecx, %edi /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* C */ + jnc L(71) /* highest byte is C => return pointer */ + xorl %ecx, %edi /* ((word^charmask)+magic)^(word^charmask) */ + orl $0xfefefeff, %edi /* set all non-carry bits */ + incl %edi /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz L(71) /* found it => return pointer */ + xorl %edx, %ecx /* restore original dword without reload */ + movl $0xfefefeff, %edi /* magic value */ + addl %ecx, %edi /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc L(71) /* highest byte is NUL => return NULL */ + xorl %ecx, %edi /* (word+magic)^word */ + orl $0xfefefeff, %edi /* set all non-carry bits */ + incl %edi /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz L(71) /* found NUL => return NULL */ + + movl 8(%eax), %ecx /* get word (= 4 bytes) in question */ + xorl %edx, %ecx /* XOR with word c|c|c|c => bytes of str == c + are now 0 */ + movl $0xfefefeff, %edi /* magic value */ + addl %ecx, %edi /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* C */ + jnc L(72) /* highest byte is C => return pointer */ + xorl %ecx, %edi /* ((word^charmask)+magic)^(word^charmask) */ + orl $0xfefefeff, %edi /* set all non-carry bits */ + incl %edi /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz L(72) /* found it => return pointer */ + xorl %edx, %ecx /* restore original dword without reload */ + movl $0xfefefeff, %edi /* magic value */ + addl %ecx, %edi /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc L(72) /* highest byte is NUL => return NULL */ + xorl %ecx, %edi /* (word+magic)^word */ + orl $0xfefefeff, %edi /* set all non-carry bits */ + incl %edi /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz L(72) /* found NUL => return NULL */ + + movl 12(%eax), %ecx /* get word (= 4 bytes) in question */ + xorl %edx, %ecx /* XOR with word c|c|c|c => bytes of str == c + are now 0 */ + movl $0xfefefeff, %edi /* magic value */ + addl %ecx, %edi /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* C */ + jnc L(73) /* highest byte is C => return pointer */ + xorl %ecx, %edi /* ((word^charmask)+magic)^(word^charmask) */ + orl $0xfefefeff, %edi /* set all non-carry bits */ + incl %edi /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz L(73) /* found it => return pointer */ + xorl %edx, %ecx /* restore original dword without reload */ + movl $0xfefefeff, %edi /* magic value */ + addl %ecx, %edi /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc L(73) /* highest byte is NUL => return NULL */ + xorl %ecx, %edi /* (word+magic)^word */ + orl $0xfefefeff, %edi /* set all non-carry bits */ + incl %edi /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jz L(1) /* no NUL found => restart loop */ + +L(73): addl $4, %eax /* adjust pointer */ +L(72): addl $4, %eax +L(71): addl $4, %eax + + /* We now scan for the byte in which the character was matched. + But we have to take care of the case that a NUL char is + found before this in the dword. */ + +L(7): testb %cl, %cl /* is first byte C? */ + jz L(6) /* yes => return pointer */ + cmpb %dl, %cl /* is first byte NUL? */ + je L(6) /* yes => return NULL */ + incl %eax /* it's not in the first byte */ + + testb %ch, %ch /* is second byte C? */ + jz L(6) /* yes => return pointer */ + cmpb %dl, %ch /* is second byte NUL? */ + je L(6) /* yes => return NULL? */ + incl %eax /* it's not in the second byte */ + + shrl $16, %ecx /* make upper byte accessible */ + testb %cl, %cl /* is third byte C? */ + jz L(6) /* yes => return pointer */ + cmpb %dl, %cl /* is third byte NUL? */ + je L(6) /* yes => return NULL */ + + /* It must be in the fourth byte and it cannot be NUL. */ + incl %eax + +L(6): popl %edi /* restore saved register content */ + + ret +END (__strchrnul) + +weak_alias (__strchrnul, strchrnul) diff --git a/sysdeps/posix/euidaccess.c b/sysdeps/posix/euidaccess.c index d38e7cc71b..e2205861a8 100644 --- a/sysdeps/posix/euidaccess.c +++ b/sysdeps/posix/euidaccess.c @@ -1,5 +1,5 @@ /* Check if effective user id can access file - Copyright (C) 1990, 91, 95, 96, 97, 98 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 95, 96, 97, 98, 99 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 @@ -119,7 +119,7 @@ static uid_t euid; static gid_t egid; /* Nonzero if UID, GID, EUID, and EGID have valid values. */ -static int have_ids = 0; +static int have_ids; /* Return 0 if the user has permission of type MODE on file PATH; diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c index bbe21d627f..fe28e2d894 100644 --- a/sysdeps/unix/sysv/linux/getcwd.c +++ b/sysdeps/unix/sysv/linux/getcwd.c @@ -1,5 +1,5 @@ /* Determine current working directory. Linux version. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -40,10 +40,10 @@ static char *generic_getcwd (char *buf, size_t size) internal_function; compiling under 2.1.92+ the libc still runs under older kernels. */ extern int __syscall_getcwd (char *buf, unsigned long size); static int no_syscall_getcwd; -static int no_new_dcache = 1; +static int have_new_dcache; #else # define no_syscall_getcwd 1 -static int no_new_dcache; +static int have_new_dcache = 1; #endif char * @@ -55,7 +55,7 @@ __getcwd (char *buf, size_t size) char *result; size_t alloc_size = size; - if (no_syscall_getcwd && no_new_dcache) + if (no_syscall_getcwd && !have_new_dcache) return generic_getcwd (buf, size); if (size == 0) @@ -101,7 +101,7 @@ __getcwd (char *buf, size_t size) if (errno == ENOSYS) { no_syscall_getcwd = 1; - no_new_dcache = 0; /* Now we will try the /proc method. */ + have_new_dcache = 1; /* Now we will try the /proc method. */ } else if (errno != ERANGE || buf != NULL) { @@ -137,12 +137,13 @@ __getcwd (char *buf, size_t size) return buf; } else - no_new_dcache = 1; + have_new_dcache = 0; } - /* Set to no_new_dcache only if error indicates that proc doesn't exist. */ + /* Set to have_new_dcache only if error indicates that proc doesn't + exist. */ if (errno != EACCES && errno != ENAMETOOLONG) - no_new_dcache = 1; + have_new_dcache = 0; /* Something went wrong. Restore the error number and use the generic version. */ diff --git a/sysdeps/unix/sysv/linux/getpt.c b/sysdeps/unix/sysv/linux/getpt.c index 8165eccc1b..d2e0f1a7b8 100644 --- a/sysdeps/unix/sysv/linux/getpt.c +++ b/sysdeps/unix/sysv/linux/getpt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Zack Weinberg , 1998. @@ -31,10 +31,10 @@ int __bsd_getpt (void); int __getpt (void) { - static int have_dev_ptmx = 1; + static int have_no_dev_ptmx; int fd; - if (have_dev_ptmx) + if (!have_no_dev_ptmx) { fd = __open (_PATH_DEVPTMX, O_RDWR); if (fd != -1) @@ -42,7 +42,7 @@ __getpt (void) else { if (errno == ENOENT || errno == ENODEV) - have_dev_ptmx = 0; + have_no_dev_ptmx = 1; else return -1; } diff --git a/sysdeps/unix/sysv/linux/i386/dl-procinfo.h b/sysdeps/unix/sysv/linux/i386/dl-procinfo.h index 77c859ba53..7624cbc94e 100644 --- a/sysdeps/unix/sysv/linux/i386/dl-procinfo.h +++ b/sysdeps/unix/sysv/linux/i386/dl-procinfo.h @@ -1,5 +1,5 @@ /* Linux/i386 version of processor capability information handling macros. - Copyright (C) 1998 Free Software Foundation, Inc. + Copyright (C) 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998. @@ -28,7 +28,7 @@ static const char x86_cap_flags[][7] = "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov", "pat", "pse36", "18", "19", "20", "21", "22", "mmx", - "fxsr", "25", "26", "27", "28", "29", "30", "amd3d" + "osfxsr", "25", "26", "27", "28", "29", "30", "amd3d" }; static inline int diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c index aa89a38e69..9b3db6abfb 100644 --- a/sysdeps/unix/sysv/linux/if_index.c +++ b/sysdeps/unix/sysv/linux/if_index.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 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 @@ -120,7 +120,7 @@ if_nameindex (void) unsigned int nifs, i; int rq_len; struct if_nameindex *idx = NULL; - static int new_siocgifconf = 1; + static int old_siocgifconf; #define RQ_IFS 4 if (fd < 0) @@ -130,13 +130,13 @@ if_nameindex (void) /* We may be able to get the needed buffer size directly, rather than guessing. */ - if (new_siocgifconf) + if (! old_siocgifconf) { ifc.ifc_buf = NULL; ifc.ifc_len = 0; if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0) { - new_siocgifconf = 0; + old_siocgifconf = 1; rq_len = RQ_IFS * sizeof (struct ifreq); } else @@ -156,7 +156,7 @@ if_nameindex (void) } rq_len *= 2; } - while (ifc.ifc_len == rq_len && new_siocgifconf == 0); + while (ifc.ifc_len == rq_len && old_siocgifconf); nifs = ifc.ifc_len / sizeof (struct ifreq); @@ -212,9 +212,9 @@ if_indextoname (unsigned int ifindex, char *ifname) list. This ioctl is not present in kernels before version 2.1.50. */ struct ifreq ifr; int fd; - static int siogifname_works = 1; + static int siogifname_works_not; - if (siogifname_works) + if (!siogifname_works_not) { int serrno = errno; @@ -227,7 +227,7 @@ if_indextoname (unsigned int ifindex, char *ifname) if (__ioctl (fd, SIOGIFNAME, &ifr) < 0) { if (errno == EINVAL) - siogifname_works = 0; /* Don't make the same mistake twice. */ + siogifname_works_not = 1; /* Don't make the same mistake twice. */ } else { diff --git a/sysdeps/unix/sysv/linux/poll.c b/sysdeps/unix/sysv/linux/poll.c index 880eeb9aa8..e7df3b7774 100644 --- a/sysdeps/unix/sysv/linux/poll.c +++ b/sysdeps/unix/sysv/linux/poll.c @@ -1,5 +1,5 @@ /* Poll system call, with emulation if it is not available. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999 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 @@ -37,7 +37,7 @@ __poll (fds, nfds, timeout) unsigned long int nfds; int timeout; { - static int must_emulate = 0; + static int must_emulate; if (!must_emulate) { diff --git a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c index 0dd9c704af..cc8f9f0ee2 100644 --- a/sysdeps/unix/sysv/linux/ttyname.c +++ b/sysdeps/unix/sysv/linux/ttyname.c @@ -28,7 +28,7 @@ #include -char *__ttyname = NULL; +char *__ttyname; static char * getttyname __P ((const char *dev, dev_t mydev, ino_t myino, int save, int *dostat)) @@ -44,7 +44,7 @@ getttyname (dev, mydev, myino, save, dostat) int *dostat; { static char *name; - static size_t namelen = 0; + static size_t namelen; struct stat st; DIR *dirstream; struct dirent *d; @@ -106,7 +106,7 @@ ttyname (fd) int fd; { static char *buf; - static size_t buflen = 0; + static size_t buflen; char procname[30]; struct stat st, st1; int dostat = 0; -- cgit 1.4.1