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) - 0x01010101) & ~(X) & 0x80808080) 79 #else 80 #if LONG_MAX == 9223372036854775807L 81 /* Nonzero if X (a long int) contains a NULL byte. */ 82 #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) 83 #else 84 #error long int is not a 32bit or 64bit type. 85 #endif 86 #endif 87 88 /* DETECTCHAR returns nonzero if (long)X contains the byte used 89 to fill (long)MASK. */ 90 #define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) 91 92 char * 93 _DEFUN (strchr, (s1, i), 94 _CONST char *s1 _AND 95 int i) 96 { 97 _CONST unsigned char *s = (_CONST unsigned char *)s1; 98 unsigned char c = i; 99 100 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) 101 unsigned long mask,j; 102 unsigned long *aligned_addr; 103 104 /* Special case for finding 0. */ 105 if (!c) 106 { 107 while (UNALIGNED (s)) 108 { 109 if (!*s) 110 return (char *) s; 111 s++; 112 } 113 /* Operate a word at a time. */ 114 aligned_addr = (unsigned long *) s; 115 while (!DETECTNULL (*aligned_addr)) 116 aligned_addr++; 117 /* Found the end of string. */ 118 s = (const unsigned char *) aligned_addr; 119 while (*s) 120 s++; 121 return (char *) s; 122 } 123 124 /* All other bytes. Align the pointer, then search a long at a time. */ 125 while (UNALIGNED (s)) 126 { 127 if (!*s) 128 return NULL; 129 if (*s == c) 130 return (char *) s; 131 s++; 132 } 133 134 mask = c; 135 for (j = 8; j < LBLOCKSIZE * 8; j <<= 1) 136 mask = (mask << j) | mask; 137 138 aligned_addr = (unsigned long *) s; 139 while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask)) 140 aligned_addr++; 141 142 /* The block of bytes currently pointed to by aligned_addr 143 contains either a null or the target char, or both. We 144 catch it using the bytewise search. */ 145 146 s = (unsigned char *) aligned_addr; 147 148 #endif /* not PREFER_SIZE_OVER_SPEED */ 149 150 while (*s && *s != c) 151 s++; 152 if (*s == c) 153 return (char *)s; 154 return NULL; 155 } 156