BSD 4_3_Reno release
[unix-history] / usr / src / lib / libc / vax / string / strchr.s
index 2900e81..f4e8db7 100644 (file)
@@ -3,85 +3,89 @@
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
  * from this software without specific prior written permission.
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * from this software without specific prior written permission.
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-       .asciz "@(#)strchr.s    5.2 (Berkeley) %G%"
+       .asciz "@(#)strchr.s    5.4 (Berkeley) 6/1/90"
 #endif /* LIBC_SCCS and not lint */
 
 #endif /* LIBC_SCCS and not lint */
 
-#ifdef notdef
-_sccsid:.asciz "@(#)index.s    5.4 (Berkeley) 5/25/88"
-#endif
-
 /*
  * Find the first occurence of c in the string cp.
  * Return pointer to match or null pointer.
  *
  * char *
 /*
  * Find the first occurence of c in the string cp.
  * Return pointer to match or null pointer.
  *
  * char *
- * index(cp, c)
+ * strchr(cp, c)
  *     char *cp, c;
  */
 #include "DEFS.h"
 
  *     char *cp, c;
  */
 #include "DEFS.h"
 
+       .lcomm  tbl,256
+
 ENTRY(strchr, 0)
 ENTRY(strchr, 0)
-       movq    4(ap),r1        # r1 = cp; r2 = c
-       tstl    r2              # check for special case c == '\0'
-       bneq    2f
+       movzwl  $65535,r4       /* handy constant */
+       movq    4(ap),r1        /* r1 = cp; r2 = c */
+       movzbl  r2,r2
+       beql    Lzero           /* special case for c == '\0' */
+
+/*
+ * Fancy scanc version.  Alas, it is not reentrant.
+ */
+       movab   tbl,r3          /* r3 = base of table */
+       bbss    $0,(r3),Lreent  /* ensure not reentering */
+       movab   (r3)[r2],r5     
+       incb    (r5)            /* mark both '\0' and c */
+0:
+       scanc   r4,(r1),(r3),$1 /* look for c or '\0' */
+       beql    0b              /* still looking */
+       movl    r1,r0           /* return whatever we found */
+       tstb    (r0)
+       bneq    1f              #       unless it was '\0':
+       clrl    r0              #       then return NULL
 1:
 1:
-       locc    $0,$65535,(r1)  # just find end of string
-       beql    1b              # still looking
-       movl    r1,r0           # found it
-       ret
-2:
-       moval   tbl,r3          # r3 = address of table
-       bbss    $0,(r3),5f      # insure not reentering
-       movab   (r3)[r2],r5     # table entry for c
-       incb    (r5)
-       movzwl  $65535,r4       # fast access
-3:
-       scanc   r4,(r1),(r3),$1 # look for c or '\0'
-       beql    3b              # still looking
-       movl    r1,r0           # return pointer to char
-       tstb    (r0)            #    if have found '\0'
-       bneq    4f
-       clrl    r0              # else return 0
-4:
-       clrb    (r5)            # clean up table
+       clrb    (r5)            /* clean up table */
        clrb    (r3)
        ret
 
        clrb    (r3)
        ret
 
-       .data
-tbl:   .space  256
-       .text
+/*
+ * Special case for \0.
+ */
+Lzero:
+       locc    r2,r4,(r1)      /* just find end of string */
+       beql    Lzero           /* still looking */
+       movl    r1,r0           /* found it */
+       ret
 
 /*
 
 /*
- * Reentrant, but slower version of index
+ * Slower reentrant version is two two-step searches.  The first
+ * phase runs until we know where the string ends; it locates the
+ * first occurrence of c within a 65535-byte block.  If we find
+ * the end of the string first, we switch to the second phase,
+ * were we look only up to the known end of string.
  */
  */
-5:
+Lreent:
+0:     /* first phase */
        movl    r1,r3
        movl    r1,r3
-6:
-       locc    $0,$65535,(r3)  # look for '\0'
-       bneq    7f
-       locc    r2,$65535,(r3)  # look for c
-       bneq    8f
-       movl    r1,r3           # reset pointer and ...
-       jbr     6b              # ... try again
-7:
-       subl3   r3,r1,r4        # length of short block
-       incl    r4              # +1 for '\0'
-       locc    r2,r4,(r3)      # look for c
-       bneq    8f
-       ret
-8:
-       movl    r1,r0           # return pointer to char
+       locc    $0,r4,(r3)      /* look for '\0' */
+       bneq    1f
+       locc    r2,r4,(r3)      /* look for c */
+       beql    0b              /* not found: reset pointer and loop */
+       movl    r1,r0           /* found: return it */
        ret
        ret
+1:     /* second phase */
+       subl3   r3,r1,r0        /* length of short block */
+       locc    r2,r0,(r3)      /* look for c */
+       beql    2f              /* not found: return NULL */
+       movl    r1,r0
+2:     ret