1 /*
2 FUNCTION
3 	<<strstr>>---find string segment
4 
5 INDEX
6 	strstr
7 
8 ANSI_SYNOPSIS
9 	#include <string.h>
10 	char *strstr(const char *<[s1]>, const char *<[s2]>);
11 
12 TRAD_SYNOPSIS
13 	#include <string.h>
14 	char *strstr(<[s1]>, <[s2]>)
15 	char *<[s1]>;
16 	char *<[s2]>;
17 
18 DESCRIPTION
19 	Locates the first occurrence in the string pointed to by <[s1]> of
20 	the sequence of characters in the string pointed to by <[s2]>
21 	(excluding the terminating null character).
22 
23 RETURNS
24 	Returns a pointer to the located string segment, or a null
25 	pointer if the string <[s2]> is not found. If <[s2]> points to
26 	a string with zero length, <[s1]> is returned.
27 
28 PORTABILITY
29 <<strstr>> is ANSI C.
30 
31 <<strstr>> requires no supporting OS subroutines.
32 
33 QUICKREF
34 	strstr ansi pure
35 */
36 
37 #include <section_config.h>
38 #include <basic_types.h>
39 
40 #include <string.h>
41 
42 extern char * _strchr(const char *s1 , int i);
43 
44 #if !defined(PREFER_SIZE_OVER_SPEED)
45 # define RETURN_TYPE char *
46 # define AVAILABLE(h, h_l, j, n_l)			\
47   (! _memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l))	\
48    && ((h_l) = (j) + (n_l)))
49 # include "str-two-way.h"
50 #endif
51 
52 LIBC_ROM_TEXT_SECTION
53 _LONG_CALL_
_strstr(const char * searchee,const char * lookfor)54 char * _strstr(const char *searchee , const char *lookfor)
55 {
56 #if defined(PREFER_SIZE_OVER_SPEED)
57 
58   /* Less code size, but quadratic performance in the worst case.  */
59   if (*searchee == 0)
60     {
61       if (*lookfor)
62 	return (char *) NULL;
63       return (char *) searchee;
64     }
65 
66   while (*searchee)
67     {
68       size_t i;
69       i = 0;
70 
71       while (1)
72 	{
73 	  if (lookfor[i] == 0)
74 	    {
75 	      return (char *) searchee;
76 	    }
77 
78 	  if (lookfor[i] != searchee[i])
79 	    {
80 	      break;
81 	    }
82 	  i++;
83 	}
84       searchee++;
85     }
86 
87   return (char *) NULL;
88 
89 #else /* compilation for speed */
90 
91   /* Larger code size, but guaranteed linear performance.  */
92   const char *haystack = searchee;
93   const char *needle = lookfor;
94   size_t needle_len; /* Length of NEEDLE.  */
95   size_t haystack_len; /* Known minimum length of HAYSTACK.  */
96   int ok = 1; /* True if NEEDLE is prefix of HAYSTACK.  */
97 
98   /* Determine length of NEEDLE, and in the process, make sure
99      HAYSTACK is at least as long (no point processing all of a long
100      NEEDLE if HAYSTACK is too short).  */
101   while (*haystack && *needle)
102     ok &= *haystack++ == *needle++;
103   if (*needle)
104     return NULL;
105   if (ok)
106     return (char *) searchee;
107 
108   /* Reduce the size of haystack using strchr, since it has a smaller
109      linear coefficient than the Two-Way algorithm.  */
110   needle_len = needle - lookfor;
111   haystack = _strchr (searchee + 1, *lookfor);
112   if (!haystack || needle_len == 1)
113     return (char *) haystack;
114   haystack_len = (haystack > searchee + needle_len ? 1
115 		  : needle_len + searchee - haystack);
116 
117   /* Perform the search.  */
118   if (needle_len < LONG_NEEDLE_THRESHOLD)
119     return __rtl_two_way_short_needle ((const unsigned char *) haystack,
120 				 haystack_len,
121 				 (const unsigned char *) lookfor, needle_len);
122   return __rtl_two_way_long_needle ((const unsigned char *) haystack, haystack_len,
123 			      (const unsigned char *) lookfor, needle_len);
124 #endif /* compilation for speed */
125 }
126