home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume14 / strstr / part01 next >
Encoding:
Text File  |  1990-08-30  |  5.3 KB  |  207 lines

  1. Newsgroups: comp.sources.misc
  2. organization: U.S. Army Ballistic Research Laboratory (BRL), APG, MD.
  3. keywords: strstr C library source code
  4. subject: v14i074: strstr.c implementation
  5. From: gwyn@smoke.brl.mil (Doug Gwyn)
  6. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  7.  
  8. Posting-number: Volume 14, Issue 74
  9. Submitted-by: gwyn@smoke.brl.mil (Doug Gwyn)
  10. Archive-name: strstr/part01
  11.  
  12. #! /bin/sh
  13. # This file was wrapped with "dummyshar".  "sh" this file to extract.
  14. # Contents:  strstr.c
  15. echo extracting 'strstr.c'
  16. if test -f 'strstr.c' -a -z "$1"; then echo Not overwriting 'strstr.c'; else
  17. sed 's/^X//' << \EOF > 'strstr.c'
  18. X/*
  19. X    strstr - public-domain implementation of standard C library function
  20. X
  21. X    last edit:    24-Aug-1990    D A Gwyn
  22. X
  23. X    This is an original implementation based on an idea by D M Sunday,
  24. X    essentially the "quick search" algorithm described in CACM V33 N8.
  25. X    Unlike Sunday's implementation, this one does not wander past the
  26. X    ends of the strings (which can cause malfunctions under certain
  27. X    circumstances), nor does it require the length of the searched
  28. X    text to be determined in advance.  There are numerous other subtle
  29. X    improvements too.  The code is intended to be fully portable, but in
  30. X    environments that do not conform to the C standard, you should check
  31. X    the sections below marked "configure as required".  There are also
  32. X    a few compilation options, as follows:
  33. X
  34. X    #define ROBUST    to obtain sane behavior when invoked with a null
  35. X            pointer argument, at a miniscule cost in speed
  36. X    #define ZAP    to use memset() to zero the shift[] array; this may
  37. X            be faster in some implementations, but could fail on
  38. X            unusual architectures
  39. X    #define DEBUG    to enable assertions (bug detection)
  40. X    #define TEST    to enable the test program attached at the end
  41. X*/
  42. X#define ROBUST
  43. X#define    ZAP
  44. X
  45. X#ifdef __STDC__
  46. X
  47. X#include    <stddef.h>        /* defines size_t and NULL */
  48. X#include    <limits.h>        /* defines UCHAR_MAX */
  49. X
  50. X#ifdef ZAP
  51. Xtypedef void    *pointer;
  52. Xextern pointer    memset( pointer, int, size_t );
  53. X#endif
  54. X
  55. X#else    /* normal UNIX-like C environment assumed; configure as required: */
  56. X
  57. Xtypedef unsigned    size_t;     /* type of result of sizeof */
  58. X
  59. X#define    NULL        0        /* null pointer constant */
  60. X
  61. X#define    UCHAR_MAX    255        /* largest value of unsigned char */
  62. X                    /* 255 @ 8 bits, 65535 @ 16 bits */
  63. X
  64. X#ifdef ZAP
  65. Xtypedef char    *pointer;
  66. Xextern pointer    memset();
  67. X#endif
  68. X
  69. X#define const    /* nothing */
  70. X
  71. X#endif    /* __STDC__ */
  72. X
  73. X#ifndef DEBUG
  74. X#define    NDEBUG
  75. X#endif
  76. X#include    <assert.h>
  77. X
  78. Xtypedef const unsigned char    cuc;    /* char variety used in algorithm */
  79. X
  80. X#define EOS    '\0'            /* C string terminator */
  81. X
  82. Xchar *                    /* returns -> leftmost occurrence,
  83. X                       or null pointer if not present */
  84. Xstrstr( s1, s2 )
  85. X    const char    *s1;        /* -> string to be searched */
  86. X    const char    *s2;        /* -> search-pattern string */
  87. X    {
  88. X    register cuc    *t;        /* -> text character being tested */
  89. X    register cuc    *p;        /* -> pattern char being tested */
  90. X    register cuc    *tx;        /* -> possible start of match */
  91. X    register size_t    m;        /* length of pattern */
  92. X#if UCHAR_MAX > 255            /* too large for auto allocation */
  93. X    static                /* not malloc()ed; that can fail! */
  94. X#endif                    /* else allocate shift[] on stack */
  95. X        size_t    shift[UCHAR_MAX + 1];    /* pattern shift table */
  96. X
  97. X#ifdef ROBUST                /* not required by C standard */
  98. X    if ( s1 == NULL || s2 == NULL )
  99. X        return NULL;        /* certainly, no match is found! */
  100. X#endif
  101. X
  102. X    /* Precompute shift intervals based on the pattern;
  103. X       the length of the pattern is determined as a side effect: */
  104. X
  105. X#ifdef ZAP
  106. X    (void)memset( (pointer)&shift[1], 0, UCHAR_MAX * sizeof(size_t) );
  107. X#else
  108. X    {
  109. X    register unsigned char    c;
  110. X
  111. X    c = UCHAR_MAX;
  112. X    do
  113. X        shift[c] = 0;
  114. X    while ( --c > 0 );
  115. X    }
  116. X#endif
  117. X    /* Note: shift[0] is undefined at this point (fixed later). */
  118. X
  119. X    for ( m = 1, p = (cuc *)s2; *p != EOS; ++m, ++p )
  120. X        shift[(cuc)*p] = m;
  121. X
  122. X    assert(s2[m - 1] == EOS);
  123. X
  124. X    {
  125. X    register unsigned char    c;
  126. X
  127. X    c = UCHAR_MAX;
  128. X    do
  129. X        shift[c] = m - shift[c];
  130. X    while ( --c > 0 );
  131. X
  132. X    /* Note: shift[0] is still undefined at this point. */
  133. X    }
  134. X
  135. X    shift[0] = --m;         /* shift[EOS]; important details! */
  136. X
  137. X    assert(s2[m] == EOS);
  138. X
  139. X    /* Try to find the pattern in the text string: */
  140. X
  141. X    for ( tx = (cuc *)s1; ; tx += shift[*t] )
  142. X        {
  143. X        for ( t = tx, p = (cuc *)s2; ; ++t, ++p )
  144. X            {
  145. X            if ( *p == EOS )       /* entire pattern matched */
  146. X                return (char *)tx;
  147. X
  148. X            if ( *p != *t )
  149. X                break;
  150. X            }
  151. X
  152. X        do    {
  153. X            assert(m > 0);
  154. X            assert(t - tx < m);
  155. X
  156. X            if ( *t == EOS )
  157. X                return NULL;    /* no match */
  158. X            }
  159. X        while ( ++t - tx != m );    /* < */
  160. X        }
  161. X    }
  162. X
  163. X#ifdef TEST
  164. X
  165. X#ifdef __STDC__
  166. X
  167. X#include    <stdlib.h>        /* defines exit, EXIT_* */
  168. X
  169. X#else    /* normal UNIX-like C environment assumed; configure as required: */
  170. X
  171. Xextern void    exit();
  172. X#define    EXIT_SUCCESS    0
  173. X#define    EXIT_FAILURE    1
  174. X
  175. X#endif    /* __STDC__ */
  176. X
  177. X#include    <stdio.h>
  178. X
  179. Xint
  180. Xmain( argc, argv )
  181. X    int        argc;
  182. X    char        *argv[];
  183. X    {
  184. X    register char    *p;
  185. X
  186. X    if ( argc < 3 )
  187. X        {
  188. X        (void)fprintf( stderr, "usage: strstr text pattern\n" );
  189. X        exit( EXIT_FAILURE );
  190. X        }
  191. X
  192. X    if ( (p = strstr( argv[1], argv[2] )) == NULL )
  193. X        (void)printf( "pattern not found\n" );
  194. X    else
  195. X        (void)printf( "pattern start: %s\n", p );
  196. X
  197. X    return EXIT_SUCCESS;
  198. X    }
  199. X
  200. X#endif    /* TEST */
  201. EOF
  202. chars=`wc -c < 'strstr.c'`
  203. if test $chars !=     4462; then echo 'strstr.c' is $chars characters, should be     4462 characters!; fi
  204. fi
  205. exit 0
  206.  
  207.