1 /* 2 * Copyright (c) 1994-2009 Red Hat, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its 16 * contributors may be used to endorse or promote products derived from this 17 * software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 FUNCTION 34 <<strchr>>---search for character in string 35 36 INDEX 37 strchr 38 39 ANSI_SYNOPSIS 40 #include <string.h> 41 char * strchr(const char *<[string]>, int <[c]>); 42 43 TRAD_SYNOPSIS 44 #include <string.h> 45 char * strchr(<[string]>, <[c]>); 46 const char *<[string]>; 47 int <[c]>; 48 49 DESCRIPTION 50 This function finds the first occurence of <[c]> (converted to 51 a char) in the string pointed to by <[string]> (including the 52 terminating null character). 53 54 RETURNS 55 Returns a pointer to the located character, or a null pointer 56 if <[c]> does not occur in <[string]>. 57 58 PORTABILITY 59 <<strchr>> is ANSI C. 60 61 <<strchr>> requires no supporting OS subroutines. 62 63 QUICKREF 64 strchr ansi pure 65 */ 66 67 #include <string.h> 68 #include <limits.h> 69 #include "_ansi.h" 70 71 /* Nonzero if X is not aligned on a "long" boundary. */ 72 #define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) 73 74 /* How many bytes are loaded each iteration of the word copy loop. */ 75 #define LBLOCKSIZE (sizeof (long)) 76 77 #if LONG_MAX == 2147483647L 78 #define DETECTNULL(X) (((X) - 0x01010101L) & ~(X) & 0x80808080UL) 79 #else 80 #if LONG_MAX == 9223372036854775807L 81 /* Nonzero if X (a long int) contains a NULL byte. */ 82 #define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ 83 0x8080808080808080UL) 84 #else 85 #error long int is not a 32bit or 64bit type. 86 #endif 87 #endif 88 89 /* DETECTCHAR returns nonzero if (long)X contains the byte used 90 to fill (long)MASK. */ 91 #define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) 92 93 char * 94 _DEFUN (strchr, (s1, i), 95 _CONST char *s1 _AND 96 int i) 97 { 98 _CONST unsigned char *s = (_CONST unsigned char *)s1; 99 unsigned char c = i; 100 101 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) 102 unsigned long mask,j; 103 unsigned long *aligned_addr; 104 105 /* Special case for finding 0. */ 106 if (!c) 107 { 108 while (UNALIGNED (s)) 109 { 110 if (!*s) 111 return (char *) s; 112 s++; 113 } 114 /* Operate a word at a time. */ 115 aligned_addr = (unsigned long *) s; 116 while (!DETECTNULL (*aligned_addr)) 117 aligned_addr++; 118 /* Found the end of string. */ 119 s = (const unsigned char *) aligned_addr; 120 while (*s) 121 s++; 122 return (char *) s; 123 } 124 125 /* All other bytes. Align the pointer, then search a long at a time. */ 126 while (UNALIGNED (s)) 127 { 128 if (!*s) 129 return NULL; 130 if (*s == c) 131 return (char *) s; 132 s++; 133 } 134 135 mask = c; 136 for (j = 8; j < LBLOCKSIZE * 8; j <<= 1) 137 mask = (mask << j) | mask; 138 139 aligned_addr = (unsigned long *) s; 140 while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask)) 141 aligned_addr++; 142 143 /* The block of bytes currently pointed to by aligned_addr 144 contains either a null or the target char, or both. We 145 catch it using the bytewise search. */ 146 147 s = (unsigned char *) aligned_addr; 148 149 #endif /* not PREFER_SIZE_OVER_SPEED */ 150 151 while (*s && *s != c) 152 s++; 153 if (*s == c) 154 return (char *)s; 155 return NULL; 156 } 157