Commit | Line | Data |
---|---|---|
a35f6d0c KB |
1 | /* |
2 | * Copyright (c) 1988 Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
50c7758a KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
a35f6d0c KB |
16 | */ |
17 | ||
50c7758a | 18 | #if defined(LIBC_SCCS) && !defined(lint) |
a856e8fc | 19 | .asciz "@(#)strchr.s 5.3 (Berkeley) %G%" |
50c7758a | 20 | #endif /* LIBC_SCCS and not lint */ |
a35f6d0c | 21 | |
a35f6d0c KB |
22 | /* |
23 | * Find the first occurence of c in the string cp. | |
24 | * Return pointer to match or null pointer. | |
25 | * | |
26 | * char * | |
a856e8fc | 27 | * strchr(cp, c) |
a35f6d0c KB |
28 | * char *cp, c; |
29 | */ | |
30 | #include "DEFS.h" | |
31 | ||
a856e8fc KB |
32 | .lcomm tbl,256 |
33 | ||
a35f6d0c | 34 | ENTRY(strchr, 0) |
a856e8fc KB |
35 | movzwl $65535,r4 /* handy constant */ |
36 | movq 4(ap),r1 /* r1 = cp; r2 = c */ | |
37 | movzbl r2,r2 | |
38 | beql Lzero /* special case for c == '\0' */ | |
39 | ||
40 | /* | |
41 | * Fancy scanc version. Alas, it is not reentrant. | |
42 | */ | |
43 | movab tbl,r3 /* r3 = base of table */ | |
44 | bbss $0,(r3),Lreent /* ensure not reentering */ | |
45 | movab (r3)[r2],r5 | |
46 | incb (r5) /* mark both '\0' and c */ | |
47 | 0: | |
48 | scanc r4,(r1),(r3),$1 /* look for c or '\0' */ | |
49 | beql 0b /* still looking */ | |
50 | movl r1,r0 /* return whatever we found */ | |
51 | tstb (r0) | |
52 | bneq 1f # unless it was '\0': | |
53 | clrl r0 # then return NULL | |
a35f6d0c | 54 | 1: |
a856e8fc | 55 | clrb (r5) /* clean up table */ |
a35f6d0c KB |
56 | clrb (r3) |
57 | ret | |
58 | ||
a856e8fc KB |
59 | /* |
60 | * Special case for \0. | |
61 | */ | |
62 | Lzero: | |
63 | locc r2,r4,(r1) /* just find end of string */ | |
64 | beql Lzero /* still looking */ | |
65 | movl r1,r0 /* found it */ | |
66 | ret | |
a35f6d0c KB |
67 | |
68 | /* | |
a856e8fc KB |
69 | * Slower reentrant version is two two-step searches. The first |
70 | * phase runs until we know where the string ends; it locates the | |
71 | * first occurrence of c within a 65535-byte block. If we find | |
72 | * the end of the string first, we switch to the second phase, | |
73 | * were we look only up to the known end of string. | |
a35f6d0c | 74 | */ |
a856e8fc KB |
75 | Lreent: |
76 | 0: /* first phase */ | |
a35f6d0c | 77 | movl r1,r3 |
a856e8fc KB |
78 | locc $0,r4,(r3) /* look for '\0' */ |
79 | bneq 1f | |
80 | locc r2,r4,(r3) /* look for c */ | |
81 | beql 0b /* not found: reset pointer and loop */ | |
82 | movl r1,r0 /* found: return it */ | |
a35f6d0c | 83 | ret |
a856e8fc KB |
84 | 1: /* second phase */ |
85 | subl3 r3,r1,r0 /* length of short block */ | |
86 | locc r2,r0,(r3) /* look for c */ | |
87 | beql 2f /* not found: return NULL */ | |
88 | movl r1,r0 | |
89 | 2: ret |